#ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #include "Credits.h" #include "Encrypted File.h" #include "Language Defines.h" #else #include "Types.h" #include "Credits.h" #include "Language Defines.h" #include "vsurface.h" #include "mousesystem.h" #include "Text.h" #include "wordwrap.h" #include "Video.h" #include "render dirty.h" #include "local.h" #include "utilities.h" #include "WCheck.h" #include "screenids.h" #include "Font Control.h" #include "cursors.h" #include "font.h" #include "wordwrap.h" #include "sysutil.h" #include "Input.h" #include "english.h" #include "encrypted file.h" #include "Random.h" #endif //externals extern HVSURFACE ghFrameBuffer; //local Defines enum { CRDT_RENDER_NONE, CRDT_RENDER_ALL, }; //nnn typedef struct _CRDT_NODE { UINT32 uiType; //the type of node CHAR16 *pString; //string for the node if the node contains a string UINT32 uiFlags; //various flags INT16 sPosX; //position of the node on the screen if the node is displaying stuff INT16 sPosY; INT16 sOldPosX; //position of the node on the screen if the node is displaying stuff INT16 sOldPosY; INT16 sHeightOfString; //The height of the displayed string BOOLEAN fDelete; //Delete this loop UINT32 uiLastTime; // The last time the node was udated UINT32 uiVideoSurfaceImage; struct _CRDT_NODE *pPrev; struct _CRDT_NODE *pNext; } CRDT_NODE; //type of credits enum { CRDT_NODE_NONE, CRDT_NODE_DEFAULT, // scrolls up and off the screen }; //flags for the credits //Flags: #define CRDT_FLAG__TITLE 0x00000001 #define CRDT_FLAG__START_SECTION 0x00000002 #define CRDT_FLAG__END_SECTION 0x00000004 #define CRDT_NAME_OF_CREDIT_FILE "BINARYDATA\\Credits.edt" #define CRDT_NAME_OF_MOD_CREDIT_FILE "BINARYDATA\\Credits_Mod.edt" #define CREDITS_LINESIZE (80 * 2) // // Code tokens // //new codes: #define CRDT_START_CODE '@' #define CRDT_SEPARATION_CODE L"," #define CRDT_END_CODE L";" #define CRDT_DELAY_BN_STRINGS_CODE 'D' #define CRDT_DELAY_BN_SECTIONS_CODE 'B' #define CRDT_SCROLL_SPEED 'S' #define CRDT_FONT_JUSTIFICATION 'J' #define CRDT_TITLE_FONT_COLOR 'C' #define CRDT_ACTIVE_FONT_COLOR 'R' //Flags: #define CRDT_TITLE 'T' #define CRDT_START_OF_SECTION '{' #define CRDT_END_OF_SECTION '}' #define CRDT_NAME_FONT FONT12ARIAL #define CRDT_LINE_NODE_DISAPPEARS_AT 0 #define CRDT_WIDTH_OF_TEXT_AREA 210 #define CRDT_SCROLL_PIXEL_AMOUNT 1 #define CRDT_NODE_DELAY_AMOUNT 25 #define CRDT_DELAY_BN_NODES 750 #define CRDT_DELAY_BN_SECTIONS 2500 #define CRDT_SPACE_BN_SECTIONS 50 #define CRDT_SPACE_BN_NODES 12 #define CRDT_START_POS_Y (SCREEN_HEIGHT - 1) #define CRDT_EYE_WIDTH 30 #define CRDT_EYE_HEIGHT 12 #define CRDT_EYES_CLOSED_TIME 150 //ddd typedef struct { INT16 sX; INT16 sY; INT16 sWidth; INT16 sHeight; INT16 sEyeX; INT16 sEyeY; INT16 sMouthX; INT16 sMouthY; INT16 sBlinkFreq; UINT32 uiLastBlinkTime; UINT32 uiEyesClosedTime; } CDRT_FACE; CDRT_FACE gCreditFaces[] = { // x y w h 298, 137, 37, 49, 310, 157, 304, 170, 2500, 0, 0, //Camfield 348, 137, 43, 47, 354, 153, 354, 153, 3700, 0, 0, //Shawn 407, 132, 30, 50, 408, 151, 410, 164, 3000, 0, 0, //Kris 443, 131, 30, 50, 447, 151, 446, 161, 4000, 0, 0, //Ian 487, 136, 43, 50, 493, 155, 493, 155, 3500, 0, 0, //Linda 529, 145, 43, 50, 536, 164, 536, 164, 4000, 0, 0, //Eric 581, 132, 43, 48, 584, 150, 583, 161, 3500, 0, 0, //Lynn 278, 211, 36, 51, 283, 232, 283, 241, 3700, 0, 0, //Norm 319, 210, 34, 49, 323, 227, 320, 339, 4000, 0, 0, //George 358, 211, 38, 49, 364, 226, 361, 239, 3600, 0, 0, //Andrew Stacey 396, 200, 42, 50, 406, 220, 403, 230, 4600, 0, 0, //Scott 444, 202, 43, 51, 452, 220, 452, 231, 2800, 0, 0, //Emmons 493, 188, 36, 51, 501, 207, 499, 217, 4500, 0, 0, //Dave 531, 199, 47, 56, 541, 221, 540, 232, 4000, 0, 0, //Alex 585, 196, 39, 49, 593, 218, 593, 228, 3500, 0, 0, //Joey }; //Global Variables MOUSE_REGION gCrdtMouseRegions[ NUM_PEOPLE_IN_CREDITS ]; void SelectCreditFaceRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); void SelectCreditFaceMovementRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); UINT32 guiCreditBackGroundImage; UINT32 guiCreditFaces; BOOLEAN gfCreditsScreenEntry = TRUE; BOOLEAN gfCreditsScreenExit = FALSE; UINT32 guiCreditsExitScreen; UINT8 gubCreditScreenRenderFlags = CRDT_RENDER_ALL; CRDT_NODE *gCrdtRootNode=NULL; CRDT_NODE *gCrdtLastAddedNode=NULL; BOOLEAN gfCrdtHaveRenderedFirstFrameToSaveBuffer; // need to render background image to save buffer once INT32 giCurrentlySelectedFace = -1; // //VAriables needed for processing of the nodes: // UINT32 guiCreditScreenActiveFont; // the font that is used UINT32 guiCreditScreenTitleFont; // the font that is used UINT8 gubCreditScreenActiveColor; // color of the font UINT8 gubCreditScreenTitleColor; // color of a Title node UINT32 guiCrdtNodeScrollSpeed = CRDT_NODE_DELAY_AMOUNT; //speed credits go up at UINT32 guiCrdtLastTimeUpdatingNode=0; // the last time a node was read from the file UINT8 gubCrdtJustification = CENTER_JUSTIFIED; // the current justification UINT32 guiGapBetweenCreditSections = CRDT_SPACE_BN_SECTIONS; UINT32 guiGapBetweenCreditNodes = CRDT_SPACE_BN_NODES; UINT32 guiGapTillReadNextCredit = CRDT_SPACE_BN_NODES; UINT32 guiCurrentCreditRecord = 0; BOOLEAN gfPauseCreditScreen = FALSE; BOOLEAN gfModCredits = TRUE; HWFILE ghFile; //Function Prototypes BOOLEAN EnterCreditsScreen(); BOOLEAN ExitCreditScreen(); void HandleCreditScreen(); BOOLEAN RenderCreditScreen(); void GetCreditScreenUserInput(); void SetCreditsExitScreen( UINT32 uiScreenToGoTo ); BOOLEAN ShutDownCreditList(); BOOLEAN AddCreditNode( UINT32 uiType, UINT32 uiFlags, STR16 pString ); BOOLEAN InitCreditNode( ); BOOLEAN DisplayCreditNode( CRDT_NODE *pCurrent ); void HandleCreditNodes(); void HandleNode_Default( CRDT_NODE *pCurrent ); void HandleCurrentCreditNode( CRDT_NODE *pCurrent ); BOOLEAN DeleteNode( CRDT_NODE *pNodeToDelete ); UINT32 GetAndHandleCreditCodeFromCodeString( STR16 pzCode ); BOOLEAN GetNextCreditFromTextFile(); UINT32 CountNumberOfCreditNodes(); STR16 GetNextCreditCode( STR16 pString, UINT32 *pSizeOfCode ); void HandleCreditFlags( UINT32 uiFlags ); void HandleCreditEyeBlinking(); void InitCreditEyeBlinking(); UINT32 CreditScreenInit( void ) { gfCreditsScreenEntry = TRUE; return( 1 ); } UINT32 CreditScreenHandle( void ) { StartFrameBufferRender(); if( gfCreditsScreenEntry ) { if( !EnterCreditsScreen() ) { gfCreditsScreenEntry = FALSE; gfCreditsScreenExit = TRUE; } else { gfCreditsScreenEntry = FALSE; gfCreditsScreenExit = FALSE; } gubCreditScreenRenderFlags = CRDT_RENDER_ALL; } GetCreditScreenUserInput(); HandleCreditScreen(); ExecuteBaseDirtyRectQueue(); EndFrameBufferRender(); if( gfCreditsScreenExit ) { ExitCreditScreen(); gfCreditsScreenEntry = TRUE; gfCreditsScreenExit = FALSE; } return( guiCreditsExitScreen ); } UINT32 CreditScreenShutdown( void ) { return( 1 ); } BOOLEAN EnterCreditsScreen() { UINT32 uiCnt; VOBJECT_DESC VObjectDesc; gfModCredits = TRUE; ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0 ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; if (iResolution >= _640x480 && iResolution < _800x600) { FilenameForBPP("INTERFACE\\Credits.sti", VObjectDesc.ImageFile); } else if (iResolution < _1024x768) { FilenameForBPP("INTERFACE\\Credits_800x600.sti", VObjectDesc.ImageFile); } else { FilenameForBPP("INTERFACE\\Credits_1024x768.sti", VObjectDesc.ImageFile); } CHECKF(AddVideoObject(&VObjectDesc, &guiCreditBackGroundImage )); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Credit Faces.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiCreditFaces )); //Initialize the root credit node InitCreditNode( ); guiCreditsExitScreen = CREDIT_SCREEN; gfCrdtHaveRenderedFirstFrameToSaveBuffer = FALSE; guiCreditScreenActiveFont = FONT12ARIAL; gubCreditScreenActiveColor = FONT_MCOLOR_DKWHITE; guiCreditScreenTitleFont = FONT14ARIAL; gubCreditScreenTitleColor = FONT_MCOLOR_RED; guiCrdtNodeScrollSpeed = CRDT_NODE_DELAY_AMOUNT; gubCrdtJustification = CENTER_JUSTIFIED; guiCurrentCreditRecord = 0; guiCrdtLastTimeUpdatingNode = GetJA2Clock(); guiGapBetweenCreditSections = CRDT_SPACE_BN_SECTIONS; guiGapBetweenCreditNodes = CRDT_SPACE_BN_NODES; guiGapTillReadNextCredit = CRDT_SPACE_BN_NODES; for( uiCnt=0; uiCnt < NUM_PEOPLE_IN_CREDITS; uiCnt++) { // Make a mouse region MSYS_DefineRegion( &gCrdtMouseRegions[uiCnt], gCreditFaces[uiCnt].sX + xResOffset, gCreditFaces[uiCnt].sY + yResOffset, (INT16)(gCreditFaces[uiCnt].sX + gCreditFaces[uiCnt].sWidth + xResOffset), (INT16)(gCreditFaces[uiCnt].sY + gCreditFaces[uiCnt].sHeight + yResOffset), MSYS_PRIORITY_NORMAL, CURSOR_WWW, SelectCreditFaceMovementRegionCallBack, SelectCreditFaceRegionCallBack ); // Add region MSYS_AddRegion( &gCrdtMouseRegions[uiCnt] ); MSYS_SetRegionUserData( &gCrdtMouseRegions[uiCnt], 0, uiCnt ); } giCurrentlySelectedFace = -1; gfPauseCreditScreen = FALSE; InitCreditEyeBlinking(); return( TRUE ); } BOOLEAN ExitCreditScreen() { UINT32 uiCnt; DeleteVideoObjectFromIndex( guiCreditBackGroundImage ); DeleteVideoObjectFromIndex( guiCreditFaces ); //ShutDown Credit link list ShutDownCreditList(); for( uiCnt=0; uiCnt < NUM_PEOPLE_IN_CREDITS; uiCnt++) { MSYS_RemoveRegion( &gCrdtMouseRegions[uiCnt] ); } return( TRUE ); } //hhh void HandleCreditScreen() { UINT16 CRDT_NAME_LOC_X = 375 + xResOffset; UINT16 CRDT_NAME_LOC_Y = 420 + yResOffset; UINT16 CRDT_NAME_TITLE_LOC_Y = 435 + yResOffset; UINT16 CRDT_NAME_FUNNY_LOC_Y = 450 + yResOffset; UINT16 CRDT_NAME_LOC_WIDTH = 260; UINT16 CRDT_NAME_LOC_HEIGHT = ( CRDT_NAME_FUNNY_LOC_Y - CRDT_NAME_LOC_Y + GetFontHeight( CRDT_NAME_FONT ) ); if( gubCreditScreenRenderFlags == CRDT_RENDER_ALL ) { RenderCreditScreen(); gubCreditScreenRenderFlags = CRDT_RENDER_NONE; } //Handle the Credit linked list HandleCreditNodes(); //Handle the blinkng eyes HandleCreditEyeBlinking(); //is it time to get a new node if( gCrdtLastAddedNode == NULL || ( CRDT_START_POS_Y - ( gCrdtLastAddedNode->sPosY + gCrdtLastAddedNode->sHeightOfString - 16 ) ) >= (INT16)guiGapTillReadNextCredit ) { //if there are no more credits in the file if( !GetNextCreditFromTextFile() && gCrdtLastAddedNode == NULL ) { SetCreditsExitScreen( MAINMENU_SCREEN ); } } RestoreExternBackgroundRect( CRDT_NAME_LOC_X, CRDT_NAME_LOC_Y, CRDT_NAME_LOC_WIDTH, (INT16)CRDT_NAME_LOC_HEIGHT ); if( giCurrentlySelectedFace != -1 ) { DrawTextToScreen( gzCreditNames[giCurrentlySelectedFace], CRDT_NAME_LOC_X, CRDT_NAME_LOC_Y, CRDT_NAME_LOC_WIDTH, CRDT_NAME_FONT, FONT_MCOLOR_WHITE, 0, FALSE, INVALIDATE_TEXT | CENTER_JUSTIFIED ); DrawTextToScreen( gzCreditNameTitle[giCurrentlySelectedFace], CRDT_NAME_LOC_X, CRDT_NAME_TITLE_LOC_Y, CRDT_NAME_LOC_WIDTH, CRDT_NAME_FONT, FONT_MCOLOR_WHITE, 0, FALSE, INVALIDATE_TEXT | CENTER_JUSTIFIED ); DrawTextToScreen( gzCreditNameFunny[giCurrentlySelectedFace], CRDT_NAME_LOC_X, CRDT_NAME_FUNNY_LOC_Y, CRDT_NAME_LOC_WIDTH, CRDT_NAME_FONT, FONT_MCOLOR_WHITE, 0, FALSE, INVALIDATE_TEXT | CENTER_JUSTIFIED ); } } //rrr BOOLEAN RenderCreditScreen() { HVOBJECT hPixHandle; GetVideoObject(&hPixHandle, guiCreditBackGroundImage ); BltVideoObject( FRAME_BUFFER, hPixHandle, 0, xResOffset, yResOffset, VO_BLT_SRCTRANSPARENCY, NULL); if( !gfCrdtHaveRenderedFirstFrameToSaveBuffer ) { gfCrdtHaveRenderedFirstFrameToSaveBuffer = TRUE; //blit everything to the save buffer ( cause the save buffer can bleed through ) BlitBufferToBuffer(guiRENDERBUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); UnmarkButtonsDirty( ); } InvalidateScreen( ); return( TRUE ); } void GetCreditScreenUserInput() { InputAtom Event; while (DequeueSpecificEvent(&Event, KEY_DOWN|KEY_UP|KEY_REPEAT)) { if( Event.usEvent == KEY_DOWN ) { switch( Event.usParam ) { case ESC: //Exit out of the screen SetCreditsExitScreen( MAINMENU_SCREEN ); break; case 'r': gubCreditScreenRenderFlags = CRDT_RENDER_ALL; break; case 'i': InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); break; case UPARROW: guiCrdtNodeScrollSpeed+=5; break; case DNARROW: if( guiCrdtNodeScrollSpeed > 5 ) guiCrdtNodeScrollSpeed-=5; break; case PAUSE: case SPACE: if( gfPauseCreditScreen ) gfPauseCreditScreen = FALSE; else gfPauseCreditScreen = TRUE; break; } } } } void SetCreditsExitScreen( UINT32 uiScreenToGoTo ) { gfCreditsScreenExit = TRUE; guiCreditsExitScreen = uiScreenToGoTo; } BOOLEAN InitCreditNode( ) { if( gCrdtRootNode != NULL ) Assert( 0 ); gCrdtRootNode = NULL; return( TRUE ); } BOOLEAN ShutDownCreditList() { CRDT_NODE *pNodeToDelete=NULL; CRDT_NODE *pTemp=NULL; pNodeToDelete = gCrdtRootNode; while( pNodeToDelete!= NULL ) { pTemp = pNodeToDelete; pNodeToDelete = pNodeToDelete->pNext; //Delete the current node DeleteNode( pTemp ); } return( TRUE ); } BOOLEAN DeleteNode( CRDT_NODE *pNodeToDelete ) { CRDT_NODE *pTempNode; pTempNode = pNodeToDelete; if( gCrdtLastAddedNode == pNodeToDelete ) { gCrdtLastAddedNode = NULL; } //if its Not the first node if( pNodeToDelete->pPrev != NULL ) pNodeToDelete->pPrev = pNodeToDelete->pNext; else { if( gCrdtRootNode->pNext != NULL ) { gCrdtRootNode = gCrdtRootNode->pNext; gCrdtRootNode->pPrev = NULL; } } //if its the last node in the list if( pNodeToDelete->pNext == NULL && pNodeToDelete->pPrev != NULL ) pNodeToDelete->pPrev->pNext = NULL; //iof the node that is being deleted is the first node if( pTempNode == gCrdtRootNode ) gCrdtRootNode = NULL; //Free the string if( pTempNode->pString != NULL ) { MemFree( pTempNode->pString ); pTempNode->pString = NULL; } //if the node had something to display, delete a surface for it if( pTempNode->uiType == CRDT_NODE_DEFAULT ) { DeleteVideoSurfaceFromIndex( pTempNode->uiVideoSurfaceImage ); pTempNode->uiVideoSurfaceImage = 0; } //Free the node MemFree( pTempNode ); pTempNode = NULL; return( TRUE ); } //aaa BOOLEAN AddCreditNode( UINT32 uiType, UINT32 uiFlags, STR16 pString ) { CRDT_NODE *pNodeToAdd=NULL; CRDT_NODE *pTemp=NULL; UINT32 uiSizeOfString = ( wcslen( pString ) + 2 ) * 2; UINT32 uiFontToUse; UINT8 uiColorToUse; UINT16 CRDT_TEXT_START_LOC = xResOffset + 10; //if if( uiType == CRDT_NODE_NONE) { Assert( 0 ); return( TRUE ); } pNodeToAdd = (CRDT_NODE *) MemAlloc( sizeof( CRDT_NODE) ); if( pNodeToAdd == NULL ) { return( FALSE ); } memset( pNodeToAdd, 0, sizeof( CRDT_NODE) ); //Determine the font and the color to use if( uiFlags & CRDT_FLAG__TITLE ) { uiFontToUse = guiCreditScreenTitleFont; uiColorToUse = gubCreditScreenTitleColor; } else { uiFontToUse = guiCreditScreenActiveFont; uiColorToUse = gubCreditScreenActiveColor; } // // Set some default data // //the type of the node pNodeToAdd->uiType = uiType; //any flags that are added pNodeToAdd->uiFlags = uiFlags; //the starting left position for the it pNodeToAdd->sPosX = CRDT_TEXT_START_LOC; //Allocate memory for the string pNodeToAdd->pString = (CHAR16 *) MemAlloc( uiSizeOfString ); if( pNodeToAdd->pString == NULL ) return( FALSE ); //copy the string into the node wcscpy( pNodeToAdd->pString, pString ); //Calculate the height of the string pNodeToAdd->sHeightOfString = DisplayWrappedString( 0, 0, CRDT_WIDTH_OF_TEXT_AREA, 2, uiFontToUse, uiColorToUse, pNodeToAdd->pString, 0, FALSE, DONT_DISPLAY_TEXT ) + 1; //starting y position on the screen pNodeToAdd->sPosY = CRDT_START_POS_Y; // pNodeToAdd->uiLastTime = GetJA2Clock(); //if the node can have something to display, Create a surface for it if( pNodeToAdd->uiType == CRDT_NODE_DEFAULT ) { VSURFACE_DESC vs_desc; // Create a background video surface to blt the face onto vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE; vs_desc.usWidth = CRDT_WIDTH_OF_TEXT_AREA; vs_desc.usHeight = pNodeToAdd->sHeightOfString; vs_desc.ubBitDepth = 16; if( AddVideoSurface( &vs_desc, &pNodeToAdd->uiVideoSurfaceImage) == 0 ) { return( FALSE ); } //Set transparency SetVideoSurfaceTransparency( pNodeToAdd->uiVideoSurfaceImage, 0 ); //fill the surface with a transparent color ColorFillVideoSurfaceArea(pNodeToAdd->uiVideoSurfaceImage, 0, 0, CRDT_WIDTH_OF_TEXT_AREA, pNodeToAdd->sHeightOfString, 0 ); //set the font dest buffer to be the surface SetFontDestBuffer( pNodeToAdd->uiVideoSurfaceImage, 0, 0, CRDT_WIDTH_OF_TEXT_AREA, pNodeToAdd->sHeightOfString, FALSE ); //write the string onto the surface DisplayWrappedString( 0, 1, CRDT_WIDTH_OF_TEXT_AREA, 2, uiFontToUse, uiColorToUse, pNodeToAdd->pString, 0, FALSE, gubCrdtJustification ); //reset the font dest buffer SetFontDestBuffer(FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE); } // // Insert the node into the list // //if its the first node to add if( gCrdtRootNode == NULL ) { //make the new node the root node gCrdtRootNode = pNodeToAdd; gCrdtRootNode->pNext = NULL; gCrdtRootNode->pPrev = NULL; } else { pTemp = gCrdtRootNode; while( pTemp->pNext != NULL ) { pTemp = pTemp->pNext; } //Add the new node to the list pTemp->pNext = pNodeToAdd; //Assign the prev node pNodeToAdd->pPrev = pTemp; } gCrdtLastAddedNode = pNodeToAdd; return( TRUE ); } void HandleCreditNodes() { CRDT_NODE *pCurrent=NULL; CRDT_NODE *pTemp=NULL; if( gCrdtRootNode == NULL ) return; //if the screen is paused, exit if( gfPauseCreditScreen ) return; pCurrent = gCrdtRootNode; if( !( GetJA2Clock() - guiCrdtLastTimeUpdatingNode > guiCrdtNodeScrollSpeed ) ) return; //loop through all the nodes while( pCurrent != NULL ) { pTemp = pCurrent; pCurrent = pCurrent->pNext; //Handle the current node HandleCurrentCreditNode( pTemp ); //if the node is to be deleted if( pTemp->fDelete ) { //delete the node DeleteNode( pTemp ); } } guiCrdtLastTimeUpdatingNode = GetJA2Clock(); } void HandleCurrentCreditNode( CRDT_NODE *pCurrent ) { //switch on the type of node switch( pCurrent->uiType ) { case CRDT_NODE_DEFAULT: HandleNode_Default( pCurrent ); break; default: Assert( 0 ); break; } } void HandleNode_Default( CRDT_NODE *pCurrent ) { //Display the Current Node DisplayCreditNode( pCurrent ); //Save the old position pCurrent->sOldPosX = pCurrent->sPosX; pCurrent->sOldPosY = pCurrent->sPosY; //Move the current node up pCurrent->sPosY -= CRDT_SCROLL_PIXEL_AMOUNT; //if the node is entirely off the screen if( ( pCurrent->sPosY + pCurrent->sHeightOfString ) < CRDT_LINE_NODE_DISAPPEARS_AT ) { //mark the node to be deleted this frame pCurrent->fDelete = TRUE; } pCurrent->uiLastTime = GetJA2Clock(); } BOOLEAN DisplayCreditNode( CRDT_NODE *pCurrent ) { HVSURFACE hVSurface; //Currently, we have no need to display a node that doesnt have a string if( pCurrent->pString == NULL ) return( FALSE ); //if the node is new and we havent displayed it yet if( pCurrent->uiLastTime == 0 ) { } //else we have to restore were the string was else { // //Restore the background before blitting the text back on // //if the surface is at the bottom of the screen if( pCurrent->sOldPosY + pCurrent->sHeightOfString > CRDT_START_POS_Y ) { INT16 sHeight = SCREEN_HEIGHT - pCurrent->sOldPosY; //INT16 sHeight = 480 - pCurrent->sOldPosY; RestoreExternBackgroundRect( pCurrent->sOldPosX, pCurrent->sOldPosY, CRDT_WIDTH_OF_TEXT_AREA, sHeight ); } else if( pCurrent->sOldPosY > CRDT_LINE_NODE_DISAPPEARS_AT ) { RestoreExternBackgroundRect( pCurrent->sOldPosX, pCurrent->sOldPosY, CRDT_WIDTH_OF_TEXT_AREA, pCurrent->sHeightOfString ); } //if the surface is at the top of the screen else { INT16 sHeight = pCurrent->sOldPosY + pCurrent->sHeightOfString; RestoreExternBackgroundRect( pCurrent->sOldPosX, CRDT_LINE_NODE_DISAPPEARS_AT, CRDT_WIDTH_OF_TEXT_AREA, sHeight ); } } GetVideoSurface( &hVSurface, pCurrent->uiVideoSurfaceImage ); BltVideoSurfaceToVideoSurface( ghFrameBuffer, hVSurface, 0, pCurrent->sPosX, pCurrent->sPosY, VS_BLT_CLIPPED | VS_BLT_USECOLORKEY, NULL ); return( TRUE ); } //return false from this function when there are no more items in the text file BOOLEAN GetNextCreditFromTextFile() { CHAR16 zOriginalString[512]; CHAR16 zString[512]; CHAR16 zCodes[512]; STR16 pzNewCode=NULL; UINT32 uiNodeType = 0; UINT32 uiStartLoc = 0; UINT32 uiFlags=0; // 1.) MOD Credits if (gfModCredits == TRUE) { if (FileExists(CRDT_NAME_OF_MOD_CREDIT_FILE)) { uiStartLoc = CREDITS_LINESIZE * (guiCurrentCreditRecord); if( !LoadEncryptedDataFromFile( CRDT_NAME_OF_MOD_CREDIT_FILE, zOriginalString, uiStartLoc, CREDITS_LINESIZE ) ) { //there are no more credits gfModCredits = FALSE; guiCurrentCreditRecord = 0; } // We have ended the mod credits list if (strcmp((char *)zOriginalString, "") == 0) { gfModCredits = FALSE; guiCurrentCreditRecord = 0; } } else { gfModCredits = FALSE; guiCurrentCreditRecord = 0; } } if (gfModCredits == FALSE) { switch(guiCurrentCreditRecord) { // 2.) 1.13 Credits case 0: wcscpy(zOriginalString, L"@T,C208,R134,D16,B40,S10,J1,};"); break; case 1: wcscpy(zOriginalString, pCreditsJA2113[0]); break; case 2: wcscpy(zOriginalString, L"@};"); break; case 3: wcscpy(zOriginalString, pCreditsJA2113[1]); break; case 4: wcscpy(zOriginalString, L"anv"); break; case 5: wcscpy(zOriginalString, L"BirdFlu"); break; case 6: wcscpy(zOriginalString, L"Buggler"); break; case 7: wcscpy(zOriginalString, L"Bugmonster"); break; case 8: wcscpy(zOriginalString, L"ChrisL"); break; case 9: wcscpy(zOriginalString, L"Flugente"); break; case 10: wcscpy(zOriginalString, L"haydent"); break; case 11: wcscpy(zOriginalString, L"Jazz"); break; case 12: wcscpy(zOriginalString, L"Kaiden"); break; case 13: wcscpy(zOriginalString, L"Kriplo"); break; case 14: wcscpy(zOriginalString, L"Lesh"); break; case 15: wcscpy(zOriginalString, L"Little Alien"); break; case 16: wcscpy(zOriginalString, L"Madd Mugsy"); break; case 17: wcscpy(zOriginalString, L"Overhaul"); break; case 18: wcscpy(zOriginalString, L"RoWa21 aka Wanne"); break; case 19: wcscpy(zOriginalString, L"Sandro"); break; case 20: wcscpy(zOriginalString, L"silversurfer"); break; case 21: wcscpy(zOriginalString, L"Space Viking"); break; case 22: wcscpy(zOriginalString, L"@};Zathras"); break; case 23: wcscpy(zOriginalString, pCreditsJA2113[2]); break; case 24: wcscpy(zOriginalString, L"BulletSix"); break; case 25: wcscpy(zOriginalString, L"coolberg"); break; case 26: wcscpy(zOriginalString, L"Corpse"); break; case 27: wcscpy(zOriginalString, L"John Wright"); break; case 28: wcscpy(zOriginalString, L"Kaerar"); break; case 29: wcscpy(zOriginalString, L"Kazuya"); break; case 30: wcscpy(zOriginalString, L"Khor"); break; case 31: wcscpy(zOriginalString, L"Lisac"); break; case 32: wcscpy(zOriginalString, L"Madd Mugsy"); break; case 33: wcscpy(zOriginalString, L"Marlboro Man"); break; case 34: wcscpy(zOriginalString, L"PasHancock"); break; case 35: wcscpy(zOriginalString, L"Scorpion"); break; case 36: wcscpy(zOriginalString, L"smeagol"); break; case 37: wcscpy(zOriginalString, L"Starwalker"); break; case 38: wcscpy(zOriginalString, L"Tbird94lx"); break; case 39: wcscpy(zOriginalString, L"Terry Thorne"); break; case 40: wcscpy(zOriginalString, pCreditsJA2113[3]); break; case 41: wcscpy(zOriginalString, pCreditsJA2113[4]); break; case 42: wcscpy(zOriginalString, L"Madd Mugsy"); break; case 43: wcscpy(zOriginalString, L"Starwalker"); break; case 44: wcscpy(zOriginalString, L"@};Lisac"); break; case 45: wcscpy(zOriginalString, pCreditsJA2113[5]); break; case 46: wcscpy(zOriginalString, L"BearPit"); break; case 47: wcscpy(zOriginalString, L"Captain J"); break; case 48: wcscpy(zOriginalString, L"DeFrog"); break; case 49: wcscpy(zOriginalString, L"DepressivesBrot"); break; case 50: wcscpy(zOriginalString, L"Dimitri"); break; case 51: wcscpy(zOriginalString, L"Farmer Toby"); break; case 52: wcscpy(zOriginalString, L"Headrock"); break; case 53: wcscpy(zOriginalString, L"inshy"); break; case 54: wcscpy(zOriginalString, L"JAPH"); break; case 55: wcscpy(zOriginalString, L"JMich"); break; case 56: wcscpy(zOriginalString, L"Jones"); break; case 57: wcscpy(zOriginalString, L"Judge"); break; case 58: wcscpy(zOriginalString, L"Kermi"); break; case 59: wcscpy(zOriginalString, L"Miro"); break; case 60: wcscpy(zOriginalString, L"Pulmu"); break; case 61: wcscpy(zOriginalString, L"Scheinworld"); break; case 62: wcscpy(zOriginalString, L"Scorpion"); break; case 63: wcscpy(zOriginalString, L"Sergeant Kolja"); break; case 64: wcscpy(zOriginalString, L"ShadoWarrior"); break; case 65: wcscpy(zOriginalString, L"Shanga"); break; case 66: wcscpy(zOriginalString, L"Snap"); break; case 67: wcscpy(zOriginalString, L"TheDrill"); break; case 68: wcscpy(zOriginalString, L"WarmSteel"); break; case 69: wcscpy(zOriginalString, L"Wil473"); break; case 70: wcscpy(zOriginalString, pCreditsJA2113[6]); break; // Additonal lines for free space case 71: wcscpy(zOriginalString, L"@T,B40,C208,{; "); break; case 72: wcscpy(zOriginalString, L"@}; "); break; // 3.) Sir-Tech Credits default: //Get the current Credit record uiStartLoc = CREDITS_LINESIZE * (guiCurrentCreditRecord-(72+1)); if( !LoadEncryptedDataFromFile( CRDT_NAME_OF_CREDIT_FILE, zOriginalString, uiStartLoc, CREDITS_LINESIZE ) ) { //there are no more credits return( FALSE ); } } } //Increment to the next crdit record guiCurrentCreditRecord++; //if there are no codes in the string if( zOriginalString[0] != CRDT_START_CODE ) { //copy the string wcscpy( zString, zOriginalString ); uiNodeType = CRDT_NODE_DEFAULT; } else { UINT32 uiSizeOfCodes = 0; UINT32 uiSizeOfSubCode = 0; STR16 pzEndCode = NULL; UINT32 uiDistanceIntoCodes = 0; //Retrive all the codes from the string pzEndCode = wcsstr( zOriginalString, CRDT_END_CODE ); //Make a string for the codes wcscpy( zCodes, zOriginalString ); //end the setence after the codes zCodes[ pzEndCode - zOriginalString + 1 ] = '\0'; //Get the size of the codes uiSizeOfCodes = pzEndCode - zOriginalString + 1; // //check to see if there is a string, or just codes // //if the string is the same size as the codes if( wcslen( zOriginalString ) == uiSizeOfCodes ) { //there is no string, just codes uiNodeType = CRDT_NODE_NONE; } //else there is a string aswell else { //copy the main string wcscpy( zString, &zOriginalString[ uiSizeOfCodes ] ); uiNodeType = CRDT_NODE_DEFAULT; } //get rid of the start code delimeter uiDistanceIntoCodes = 1; uiFlags = 0; //loop through the string of codes to get all the control codes out while( uiDistanceIntoCodes < uiSizeOfCodes ) { //Determine what kind of code it is, and handle it uiFlags |= GetAndHandleCreditCodeFromCodeString( &zCodes[ uiDistanceIntoCodes ] ); //get the next code from the string of codes, returns NULL when done pzNewCode = GetNextCreditCode( &zCodes[ uiDistanceIntoCodes ], &uiSizeOfSubCode ); //if we are done getting the sub codes if( pzNewCode == NULL ) { uiDistanceIntoCodes = uiSizeOfCodes; } else { //else increment by the size of the code uiDistanceIntoCodes += uiSizeOfSubCode; } } } if( uiNodeType != CRDT_NODE_NONE ) { //add the node to the list AddCreditNode( uiNodeType, uiFlags, zString ); } //if any processing of the flags need to be done HandleCreditFlags( uiFlags ); return( TRUE ); } //return any flags that need to be set in the node UINT32 GetAndHandleCreditCodeFromCodeString( STR16 pzCode ) { //if the code is to change the delay between strings if( pzCode[0] == CRDT_DELAY_BN_STRINGS_CODE ) { UINT32 uiNewDelay=0; //Get the delay from the string swscanf( &pzCode[1], L"%d%*s", &uiNewDelay ); guiGapBetweenCreditNodes = uiNewDelay; return( CRDT_NODE_NONE ); } //if the code is to change the delay between sections strings else if( pzCode[0] == CRDT_DELAY_BN_SECTIONS_CODE ) { UINT32 uiNewDelay=0; //Get the delay from the string swscanf( &pzCode[1], L"%d%*s", &uiNewDelay ); guiGapBetweenCreditSections = uiNewDelay; return( CRDT_NODE_NONE ); } else if( pzCode[0] == CRDT_SCROLL_SPEED ) { UINT32 uiScrollSpeed=0; //Get the delay from the string swscanf( &pzCode[1], L"%d%*s", &uiScrollSpeed ); guiCrdtNodeScrollSpeed = uiScrollSpeed; return( CRDT_NODE_NONE ); } else if( pzCode[0] == CRDT_FONT_JUSTIFICATION ) { UINT32 uiJustification=0; //Get the delay from the string swscanf( &pzCode[1], L"%d%*s", &uiJustification ); //get the justification switch( uiJustification ) { case 0: gubCrdtJustification = LEFT_JUSTIFIED; break; case 1: gubCrdtJustification = CENTER_JUSTIFIED; break; case 2: gubCrdtJustification = RIGHT_JUSTIFIED; break; default: Assert( 0 ); } return( CRDT_NODE_NONE ); } else if( pzCode[0] == CRDT_TITLE_FONT_COLOR ) { UINT uiBuffer = 0; swscanf( &pzCode[1], L"%d%*s", &uiBuffer ); gubCreditScreenTitleColor = (UINT8)uiBuffer; return( CRDT_NODE_NONE ); } else if( pzCode[0] == CRDT_ACTIVE_FONT_COLOR ) { UINT uiBuffer = 0; swscanf( &pzCode[1], L"%d%*s", &uiBuffer ); gubCreditScreenActiveColor = (UINT8)uiBuffer; return( CRDT_NODE_NONE ); } else if( pzCode[0] == CRDT_TITLE ) { return( CRDT_FLAG__TITLE ); } else if( pzCode[0] == CRDT_START_OF_SECTION ) { return( CRDT_FLAG__START_SECTION ); } else if( pzCode[0] == CRDT_END_OF_SECTION ) { return( CRDT_FLAG__END_SECTION ); } return( CRDT_NODE_NONE ); } UINT32 CountNumberOfCreditNodes() { UINT32 uiNumNodes = 0; CRDT_NODE *pTempNode = gCrdtRootNode; while( pTempNode ) { uiNumNodes++; pTempNode = pTempNode->pNext; } return( uiNumNodes ); } STR16 GetNextCreditCode( STR16 pString, UINT32 *pSizeOfCode ) { STR16 pzNewCode=NULL; UINT32 uiSizeOfCode = 0; //get the new subcode out pzNewCode = wcsstr( pString, CRDT_SEPARATION_CODE ); //if there is no separation code, then there must be an end code if( pzNewCode == NULL ) { //we are done pzNewCode = NULL; } else { //get rid of separeation code pzNewCode++; //calc size of sub string uiSizeOfCode = pzNewCode - pString; } *pSizeOfCode = uiSizeOfCode; return( pzNewCode ); } //Flags: void HandleCreditFlags( UINT32 uiFlags ) { if( uiFlags & CRDT_FLAG__TITLE ) { } if( uiFlags & CRDT_FLAG__START_SECTION ) { guiGapTillReadNextCredit = guiGapBetweenCreditNodes; } if( uiFlags & CRDT_FLAG__END_SECTION ) { guiGapTillReadNextCredit = guiGapBetweenCreditSections; } } void SelectCreditFaceRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ) { if (iReason & MSYS_CALLBACK_REASON_INIT) { } else if(iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { } else if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { } } void SelectCreditFaceMovementRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ) { if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { giCurrentlySelectedFace = -1; } else if( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) { giCurrentlySelectedFace = MSYS_GetRegionUserData( pRegion,0 ); } else if( iReason & MSYS_CALLBACK_REASON_MOVE ) { } } void InitCreditEyeBlinking() { UINT8 ubCnt; for( ubCnt=0; ubCnt (UINT32)gCreditFaces[ubCnt].sBlinkFreq ) { BltVideoObject( FRAME_BUFFER, hPixHandle, (UINT8)(ubCnt*3), gCreditFaces[ubCnt].sEyeX + xResOffset, gCreditFaces[ubCnt].sEyeY + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL); InvalidateRegion( gCreditFaces[ubCnt].sEyeX + xResOffset, gCreditFaces[ubCnt].sEyeY + yResOffset, gCreditFaces[ubCnt].sEyeX + CRDT_EYE_WIDTH + xResOffset, gCreditFaces[ubCnt].sEyeY + CRDT_EYE_HEIGHT + yResOffset ); gCreditFaces[ubCnt].uiLastBlinkTime = GetJA2Clock(); gCreditFaces[ubCnt].uiEyesClosedTime = GetJA2Clock() + CRDT_EYES_CLOSED_TIME + Random( CRDT_EYES_CLOSED_TIME ); } else if( GetJA2Clock() > gCreditFaces[ubCnt].uiEyesClosedTime ) { gCreditFaces[ubCnt].uiEyesClosedTime = 0; RestoreExternBackgroundRect( gCreditFaces[ubCnt].sEyeX + xResOffset, gCreditFaces[ubCnt].sEyeY + yResOffset, CRDT_EYE_WIDTH, CRDT_EYE_HEIGHT ); } } }