2020-05-27 12:16:20 -07:00
//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
// software: you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
/* $Header: F:\projects\c&c\vcs\code\startup.cpv 2.17 16 Oct 1995 16:48:12 JOE_BOSTIC $ */
/***********************************************************************************************
* * * C O N F I D E N T I A L - - - W E S T W O O D S T U D I O S * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Project Name : Command & Conquer *
* *
* File Name : STARTUP . CPP *
* *
* Programmer : Joe L . Bostic *
* *
* Start Date : October 3 , 1994 *
* *
* Last Update : August 27 , 1995 [ JLB ] *
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* Functions : *
* Delete_Swap_Files - - Deletes previously existing swap files . *
* Prog_End - - Cleans up library systems in prep for game exit . *
* main - - Initial startup routine ( preps library systems ) . *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# include "function.h"
# include <conio.h>
# include <io.h>
# include "ccdde.h"
bool Read_Private_Config_Struct ( char * profile , NewConfigType * config ) ;
void Delete_Swap_Files ( void ) ;
void Print_Error_End_Exit ( char * string ) ;
void Print_Error_Exit ( char * string ) ;
WinTimerClass * WinTimer ;
extern void Create_Main_Window ( HANDLE instance , int command_show , int width , int height ) ;
extern bool ReadyToQuit ;
void Read_Setup_Options ( RawFileClass * config_file ) ;
bool VideoBackBufferAllowed = true ;
void Check_From_WChat ( char * wchat_name ) ;
bool SpawnedFromWChat = false ;
bool ProgEndCalled = false ;
extern " C " {
bool __cdecl Detect_MMX_Availability ( void ) ;
void __cdecl Init_MMX ( void ) ;
}
# if (0)
char WibbleBuffer [ 1024 * 1024 ] ;
void CD_Test ( void )
{
HANDLE handle ;
DWORD size ;
handle = CreateFile ( " e: \\ scores.mix " , GENERIC_READ , FILE_SHARE_READ ,
NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ) ;
if ( handle = = INVALID_HANDLE_VALUE ) {
return ;
}
unsigned bytes_read ;
do {
bytes_read = ReadFile ( handle , WibbleBuffer , 1024 * 1024 , & size , NULL ) ;
} while ( size = = 1024 * 1024 ) ;
CloseHandle ( handle ) ;
}
# endif //(0)
/***********************************************************************************************
* main - - Initial startup routine ( preps library systems ) . *
* *
* This is the routine that is first called when the program starts up . It basically *
* handles the command line parsing and setting up library systems . *
* *
* INPUT : argc - - Number of command line arguments . *
* *
* argv - - Pointer to array of comman line argument strings . *
* *
* OUTPUT : Returns with execution failure code ( if any ) . *
* *
* WARNINGS : none *
* *
* HISTORY : *
* 03 / 20 / 1995 JLB : Created . *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
HINSTANCE ProgramInstance ;
extern BOOL CC95AlreadyRunning ;
void Move_Point ( short & x , short & y , register DirType dir , unsigned short distance ) ;
void Check_Use_Compressed_Shapes ( void ) ;
extern void DLL_Shutdown ( void ) ;
BOOL WINAPI DllMain ( HINSTANCE instance , unsigned int fdwReason , void * lpvReserved )
{
lpvReserved ;
switch ( fdwReason ) {
case DLL_PROCESS_ATTACH :
ProgramInstance = instance ;
break ;
case DLL_PROCESS_DETACH :
if ( WindowsTimer ) {
delete WindowsTimer ;
WindowsTimer = NULL ;
}
DLL_Shutdown ( ) ;
MixFileClass : : Free_All ( ) ;
Uninit_Game ( ) ;
break ;
case DLL_THREAD_ATTACH :
case DLL_THREAD_DETACH :
break ;
}
return true ;
}
//int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int command_show )
//{
// Heap_Dump_Check( "first thing in main" );
// malloc(1);
int DLL_Startup ( const char * command_line_in )
{
RunningAsDLL = true ;
int command_show = SW_HIDE ;
HINSTANCE instance = ProgramInstance ;
char command_line [ 1024 ] ;
strcpy ( command_line , command_line_in ) ;
CCDebugString ( " C&C95 - Starting up. \n " ) ;
//WindowsTimer = new WinTimerClass(60,FALSE);
//CD_Test();
/*
* * These values return 0x47 if code is working correctly
*/
// int temp = Desired_Facing256 (1070, 5419, 1408, 5504);
/*
* * If we are already running then switch to the existing process and exit
*/
SpawnedFromWChat = false ;
if ( CC95AlreadyRunning ) { //Set in the DDEServer constructor
//MessageBox (NULL, "Error - attempt to restart C&C95 when already running.", "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
HWND ccwindow ;
ccwindow = FindWindow ( " Command & Conquer " , " Command & Conquer " ) ;
if ( ccwindow ) {
SetForegroundWindow ( ccwindow ) ;
ShowWindow ( ccwindow , SW_RESTORE ) ;
}
return ( EXIT_SUCCESS ) ;
}
// ST - 3/6/2019 1:36PM
//DDSCAPS surface_capabilities;
if ( Ram_Free ( MEM_NORMAL ) < 5000000 ) {
# ifdef GERMAN
printf ( " Zuwenig Hauptspeicher verf<72> gbar. \n " ) ;
# else
# ifdef FRENCH
printf ( " M<EFBFBD> moire vive (RAM) insuffisante. \n " ) ;
# else
printf ( " Insufficient RAM available. \n " ) ;
# endif
# endif
return ( EXIT_FAILURE ) ;
}
//void *test_buffer = Alloc(20,MEM_NORMAL);
//memset ((char*)test_buffer, 0, 21);
//Free(test_buffer);
int argc ; //Command line argument count
unsigned command_scan ;
char command_char ;
char * argv [ 20 ] ; //Pointers to command line arguments
char path_to_exe [ 280 ] ;
ProgramInstance = instance ;
/*
* * Get the full path to the . EXE
*/
GetModuleFileName ( instance , & path_to_exe [ 0 ] , 280 ) ;
/*
* * First argument is supposed to be a pointer to the . EXE that is running
* *
*/
argc = 1 ; //Set argument count to 1
argv [ 0 ] = & path_to_exe [ 0 ] ; //Set 1st command line argument to point to full path
/*
* * Get pointers to command line arguments just like if we were in DOS
* *
* * The command line we get is cr / zero ? terminated .
* *
*/
command_scan = 0 ;
do {
/*
* * Scan for non - space character on command line
*/
do {
command_char = * ( command_line + command_scan + + ) ;
} while ( command_char = = ' ' ) ;
if ( command_char ! = 0 & & command_char ! = 13 ) {
argv [ argc + + ] = command_line + command_scan - 1 ;
/*
* * Scan for space character on command line
*/
bool in_quotes = false ;
do {
command_char = * ( command_line + command_scan + + ) ;
if ( command_char = = ' " ' ) {
in_quotes = ! in_quotes ;
}
} while ( ( in_quotes | | command_char ! = ' ' ) & & command_char ! = 0 & & command_char ! = 13 ) ;
* ( command_line + command_scan - 1 ) = 0 ;
}
} while ( command_char ! = 0 & & command_char ! = 13 & & argc < 20 ) ;
/*
* * Remember the current working directory and drive .
*/
# if (0) //PG_TO_FIX
unsigned olddrive ;
char oldpath [ MAX_PATH ] ;
getcwd ( oldpath , sizeof ( oldpath ) ) ;
_dos_getdrive ( & olddrive ) ;
/*
* * Change directory to the where the executable is located . Handle the
* * case where there is no path attached to argv [ 0 ] .
*/
char drive [ _MAX_DRIVE ] ;
char path [ _MAX_PATH ] ;
unsigned drivecount ;
_splitpath ( argv [ 0 ] , drive , path , NULL , NULL ) ;
if ( ! drive [ 0 ] ) {
drive [ 0 ] = ( ' A ' + olddrive ) - 1 ;
}
if ( ! path [ 0 ] ) {
strcpy ( path , " . " ) ;
}
_dos_setdrive ( toupper ( ( drive [ 0 ] ) - ' A ' ) + 1 , & drivecount ) ;
if ( path [ strlen ( path ) - 1 ] = = ' \\ ' ) {
path [ strlen ( path ) - 1 ] = ' \0 ' ;
}
chdir ( path ) ;
# endif
# ifdef JAPANESE
ForceEnglish = false ;
# endif
if ( Parse_Command_Line ( argc , argv ) ) {
WindowsTimer = new WinTimerClass ( 60 , FALSE ) ;
2020-09-16 10:03:04 -07:00
# if (0)
2020-05-27 12:16:20 -07:00
int time_test = WindowsTimer - > Get_System_Tick_Count ( ) ;
Sleep ( 1000 ) ;
if ( WindowsTimer - > Get_System_Tick_Count ( ) = = time_test ) {
# ifdef FRENCH
MessageBox ( 0 , " Error - L'horloge syst<73> me n'a pas pu s'initialiser en raison de l'instabilit<69> du syt<79> me. Vous devez red<65> marrer Windows. " , " Command & Conquer " , MB_OK | MB_ICONSTOP ) ;
# else
# ifdef GERMAN
MessageBox ( 0 , " Fehler - das Timer-System konnte aufgrund einer Instabilit<69> t des Systems nicht initialisiert werden. Bitte starten Sie Windows neu. " , " Command & Conquer " , MB_OK | MB_ICONSTOP ) ;
# else
MessageBox ( 0 , " Error - Timer system failed to start due to system instability. You need to restart Windows. " , " Command & Conquer " , MB_OK | MB_ICONSTOP ) ;
# endif //GERMAN
# endif //FRENCH
return ( EXIT_FAILURE ) ;
}
2020-09-16 10:03:04 -07:00
# endif
2020-05-27 12:16:20 -07:00
RawFileClass cfile ( " CONQUER.INI " ) ;
# ifdef JAPANESE
//////////////////////////////////////if(!ForceEnglish) KBLanguage = 1;
# endif
/*
* * Check for existance of MMX support on the processor
*/
if ( Detect_MMX_Availability ( ) ) {
//MessageBox(NULL, "MMX extensions detected - enabling MMX support.", "Command & Conquer",MB_ICONEXCLAMATION|MB_OK);
MMXAvailable = true ;
}
/*
* * If there is loads of memory then use uncompressed shapes
*/
Check_Use_Compressed_Shapes ( ) ;
/*
* * If there is not enough disk space free , dont allow the product to run .
*/
if ( Disk_Space_Available ( ) < INIT_FREE_DISK_SPACE ) {
# ifdef GERMAN
char disk_space_message [ 512 ] ;
sprintf ( disk_space_message , " Nicht genug Festplattenplatz f<> r Command & Conquer. \n Sie brauchen %d MByte freien Platz auf der Festplatte. " , ( INIT_FREE_DISK_SPACE ) / ( 1024 * 1024 ) ) ;
MessageBox ( NULL , disk_space_message , " Command & Conquer " , MB_ICONEXCLAMATION | MB_OK ) ;
if ( WindowsTimer )
delete WindowsTimer ;
return ( EXIT_FAILURE ) ;
# endif
# ifdef FRENCH
char disk_space_message [ 512 ] ;
sprintf ( disk_space_message , " Espace disque insuffisant pour lancer Command & Conquer. \n Vous devez disposer de %d Mo d'espace disponsible sur disque dur. " , ( INIT_FREE_DISK_SPACE ) / ( 1024 * 1024 ) ) ;
MessageBox ( NULL , disk_space_message , " Command & Conquer " , MB_ICONEXCLAMATION | MB_OK ) ;
if ( WindowsTimer )
delete WindowsTimer ;
return ( EXIT_FAILURE ) ;
# endif
# if !(FRENCH | GERMAN)
int reply = MessageBox ( NULL , " Warning - you are critically low on free disk space for virtual memory and save games. Do you want to play C&C anyway? " , " Command & Conquer " , MB_ICONQUESTION | MB_YESNO ) ;
if ( reply = = IDNO ) {
if ( WindowsTimer )
delete WindowsTimer ;
return ( EXIT_FAILURE ) ;
}
# endif
}
# if (0) // ST - 1/2/2019 5:50PM
CDFileClass : : Set_CD_Drive ( CDList . Get_First_CD_Drive ( ) ) ;
# endif
if ( cfile . Is_Available ( ) ) {
# ifndef NOMEMCHECK
char * cdata = ( char * ) Load_Alloc_Data ( cfile ) ;
Read_Private_Config_Struct ( cdata , & NewConfig ) ;
delete [ ] cdata ;
# else
Read_Private_Config_Struct ( ( char * ) Load_Alloc_Data ( cfile ) , & NewConfig ) ;
# endif
Read_Setup_Options ( & cfile ) ;
CCDebugString ( " C&C95 - Creating main window. \n " ) ;
Create_Main_Window ( instance , command_show , ScreenWidth , ScreenHeight ) ;
CCDebugString ( " C&C95 - Initialising audio. \n " ) ;
SoundOn = Audio_Init ( MainWindow , 16 , false , 11025 * 2 , 0 ) ;
Palette = new ( MEM_CLEAR ) unsigned char [ 768 ] ;
BOOL video_success = FALSE ;
CCDebugString ( " C&C95 - Setting video mode. \n " ) ;
/*
* * Set 640 x400 video mode . If its not available then try for 640 x480
*/
if ( ScreenHeight = = 400 ) {
if ( Set_Video_Mode ( MainWindow , ScreenWidth , ScreenHeight , 8 ) ) {
video_success = TRUE ;
} else {
if ( Set_Video_Mode ( MainWindow , ScreenWidth , 480 , 8 ) ) {
video_success = TRUE ;
ScreenHeight = 480 ;
}
}
} else {
if ( Set_Video_Mode ( MainWindow , ScreenWidth , ScreenHeight , 8 ) ) {
video_success = TRUE ;
}
}
if ( ! video_success ) {
CCDebugString ( " C&C95 - Failed to set video mode. \n " ) ;
MessageBox ( MainWindow , Text_String ( TXT_UNABLE_TO_SET_VIDEO_MODE ) , " Command & Conquer " , MB_ICONEXCLAMATION | MB_OK ) ;
if ( WindowsTimer ) delete WindowsTimer ;
if ( Palette ) delete [ ] Palette ;
return ( EXIT_FAILURE ) ;
}
CCDebugString ( " C&C95 - Initialising video surfaces. \n " ) ;
if ( ScreenWidth = = 320 ) {
VisiblePage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) 0 ) ;
ModeXBuff . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) ( GBC_VISIBLE | GBC_VIDEOMEM ) ) ;
} else {
# if (1) //ST - 1/3/2019 2:11PM
VisiblePage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) 0 ) ;
HiddenPage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) 0 ) ;
# else
VisiblePage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) ( GBC_VISIBLE | GBC_VIDEOMEM ) ) ;
/*
* * Check that we really got a video memory page . Failure is fatal .
*/
memset ( & surface_capabilities , 0 , sizeof ( surface_capabilities ) ) ;
VisiblePage . Get_DD_Surface ( ) - > GetCaps ( & surface_capabilities ) ;
if ( surface_capabilities . dwCaps & DDSCAPS_SYSTEMMEMORY ) {
/*
* * Aaaarrgghh !
*/
CCDebugString ( " C&C95 - Unable to allocate primary surface. \n " ) ;
MessageBox ( MainWindow , Text_String ( TXT_UNABLE_TO_ALLOCATE_PRIMARY_VIDEO_BUFFER ) , " Command & Conquer " , MB_ICONEXCLAMATION | MB_OK ) ;
if ( WindowsTimer ) delete WindowsTimer ;
if ( Palette ) delete [ ] Palette ;
return ( EXIT_FAILURE ) ;
}
/*
* * If we have enough left then put the hidpage in video memory unless . . .
* *
* * If there is no blitter then we will get better performance with a system
* * memory hidpage
* *
* * Use a system memory page if the user has specified it via the ccsetup program .
*/
CCDebugString ( " C&C95 - Allocating back buffer " ) ;
long video_memory = Get_Free_Video_Memory ( ) ;
unsigned video_capabilities = Get_Video_Hardware_Capabilities ( ) ;
if ( video_memory < ScreenWidth * ScreenHeight | |
( ! ( video_capabilities & VIDEO_BLITTER ) ) | |
( video_capabilities & VIDEO_NO_HARDWARE_ASSIST ) | |
! VideoBackBufferAllowed ) {
CCDebugString ( " in system memory. \n " ) ;
HiddenPage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) 0 ) ;
} else {
//HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
CCDebugString ( " in video memory. \n " ) ;
HiddenPage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) GBC_VIDEOMEM ) ;
/*
* * Make sure we really got a video memory hid page . If we didnt then things
* * will run very slowly .
*/
memset ( & surface_capabilities , 0 , sizeof ( surface_capabilities ) ) ;
HiddenPage . Get_DD_Surface ( ) - > GetCaps ( & surface_capabilities ) ;
if ( surface_capabilities . dwCaps & DDSCAPS_SYSTEMMEMORY ) {
/*
* * Oh dear , big trub . This must be an IBM Aptiva or something similarly cruddy .
* * We must redo the Hidden Page as system memory .
*/
AllSurfaces . Remove_DD_Surface ( HiddenPage . Get_DD_Surface ( ) ) ; // Remove the old surface from the AllSurfaces list
HiddenPage . Get_DD_Surface ( ) - > Release ( ) ;
HiddenPage . Init ( ScreenWidth , ScreenHeight , NULL , 0 , ( GBC_Enum ) 0 ) ;
} else {
VisiblePage . Attach_DD_Surface ( & HiddenPage ) ;
}
}
# endif
}
ScreenHeight = 1536 ;
if ( VisiblePage . Get_Height ( ) = = 480 ) {
SeenBuff . Attach ( & VisiblePage , 0 , 40 , 1536 , 1536 ) ;
HidPage . Attach ( & HiddenPage , 0 , 40 , 1536 , 1536 ) ;
} else {
SeenBuff . Attach ( & VisiblePage , 0 , 0 , 1536 , 1536 ) ;
HidPage . Attach ( & HiddenPage , 0 , 0 , 1536 , 1536 ) ;
}
CCDebugString ( " C&C95 - Adjusting variables for resolution. \n " ) ;
Options . Adjust_Variables_For_Resolution ( ) ;
CCDebugString ( " C&C95 - Setting palette. \n " ) ;
/////////Set_Palette(Palette);
WindowList [ 0 ] [ WINDOWWIDTH ] = SeenBuff . Get_Width ( ) > > 3 ;
WindowList [ 0 ] [ WINDOWHEIGHT ] = SeenBuff . Get_Height ( ) ;
/*
* * Install the memory error handler
*/
Memory_Error = & Memory_Error_Handler ;
/*
* * Initialise MMX support if its available
*/
CCDebugString ( " C&C95 - Entering MMX detection. \n " ) ;
if ( MMXAvailable ) {
Init_MMX ( ) ;
}
CCDebugString ( " C&C95 - Creating mouse class. \n " ) ;
WWMouse = new WWMouseClass ( & SeenBuff , 32 , 32 ) ;
// MouseInstalled = Install_Mouse(32,24,320,200);
MouseInstalled = TRUE ;
/*
* * See if we should run the intro
*/
CCDebugString ( " C&C95 - Reading CONQUER.INI. \n " ) ;
char * buffer = ( char * ) Alloc ( 64000 , MEM_NORMAL ) ; //(char *)HidPage.Get_Buffer();
cfile . Read ( buffer , cfile . Size ( ) ) ;
buffer [ cfile . Size ( ) ] = ' \0 ' ;
/*
* * Check for forced intro movie run disabling . If the conquer
* * configuration file says " no " , then don ' t run the intro .
*/
char tempbuff [ 5 ] ;
WWGetPrivateProfileString ( " Intro " , " PlayIntro " , " Yes " , tempbuff , 4 , buffer ) ;
if ( ( stricmp ( tempbuff , " No " ) = = 0 ) | | SpawnedFromWChat ) {
Special . IsFromInstall = false ;
} else {
Special . IsFromInstall = true ;
}
SlowPalette = WWGetPrivateProfileInt ( " Options " , " SlowPalette " , 1 , buffer ) ;
# ifdef DEMO
/*
* * Check for override directory path for CD searches .
*/
WWGetPrivateProfileString ( " CD " , " Path " , " . " , OverridePath , sizeof ( OverridePath ) , buffer ) ;
# endif
/*
* * Regardless of whether we should run it or not , here we ' re
* * gonna change it to say " no " in the future .
*/
WWWritePrivateProfileString ( " Intro " , " PlayIntro " , " No " , buffer ) ;
cfile . Write ( buffer , strlen ( buffer ) ) ;
Free ( buffer ) ;
CCDebugString ( " C&C95 - Checking availability of C&CSPAWN.INI packet from WChat. \n " ) ;
if ( DDEServer . Get_MPlayer_Game_Info ( ) ) {
CCDebugString ( " C&C95 - C&CSPAWN.INI packet available. \n " ) ;
Check_From_WChat ( NULL ) ;
} else {
CCDebugString ( " C&C95 - C&CSPAWN.INI packet not arrived yet. \n " ) ;
//Check_From_WChat("C&CSPAWN.INI");
//if (Special.IsFromWChat){
// DDEServer.Disable();
//}
}
/*
* * If the intro is being run for the first time , then don ' t
* * allow breaking out of it with the < ESC > key .
*/
if ( Special . IsFromInstall ) {
BreakoutAllowed = false ;
}
Memory_Error_Exit = Print_Error_End_Exit ;
CCDebugString ( " C&C95 - Entering main game. \n " ) ;
Main_Game ( argc , argv ) ;
if ( RunningAsDLL ) {
return ( EXIT_SUCCESS ) ;
}
VisiblePage . Clear ( ) ;
HiddenPage . Clear ( ) ;
// Set_Video_Mode(RESET_MODE);
Memory_Error_Exit = Print_Error_Exit ;
CCDebugString ( " C&C95 - About to exit. \n " ) ;
ReadyToQuit = 1 ;
PostMessage ( MainWindow , WM_DESTROY , 0 , 0 ) ;
do
{
Keyboard : : Check ( ) ;
} while ( ReadyToQuit = = 1 ) ;
CCDebugString ( " C&C95 - Returned from final message loop. \n " ) ;
//Prog_End();
//Invalidate_Cached_Icons();
//VisiblePage.Un_Init();
//HiddenPage.Un_Init();
//AllSurfaces.Release();
//Reset_Video_Mode();
//Stop_Profiler();
return ( EXIT_SUCCESS ) ;
} else {
# ifdef GERMAN
puts ( " Bitte erst das SETUP-Programm starten. \n " ) ;
# else
# ifdef FRENCH
puts ( " Lancez d'abord le programme de configuration SETUP. \n " ) ;
# else
puts ( " Run SETUP program first. " ) ;
puts ( " \n " ) ;
# endif
Kbd . Get ( ) ;
# endif
}
// Remove_Keyboard_Interrupt();
if ( WindowsTimer ) {
delete WindowsTimer ;
WindowsTimer = NULL ;
}
if ( Palette ) {
delete [ ] Palette ;
Palette = NULL ;
}
}
/*
* * Restore the current drive and directory .
*/
# ifdef NOT_FOR_WIN95
_dos_setdrive ( olddrive , & drivecount ) ;
chdir ( oldpath ) ;
# endif //NOT_FOR_WIN95
return ( EXIT_SUCCESS ) ;
}
/***********************************************************************************************
* Prog_End - - Cleans up library systems in prep for game exit . *
* *
* This routine should be called before the game terminates . It handles cleaning up *
* library systems so that a graceful return to the host operating system is achieved . *
* *
* INPUT : none *
* *
* OUTPUT : none *
* *
* WARNINGS : none *
* *
* HISTORY : *
* 03 / 20 / 1995 JLB : Created . *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
void __cdecl Prog_End ( const char * why , bool fatal ) // Added why and fatal parameters. ST - 6/27/2019 10:10PM
{
GlyphX_Debug_Print ( " Prog_End() " ) ;
if ( why ) {
GlyphX_Debug_Print ( why ) ;
}
if ( fatal ) {
* ( ( int * ) 0 ) = 0 ;
}
# ifndef DEMO
if ( GameToPlay = = GAME_MODEM | | GameToPlay = = GAME_NULL_MODEM ) {
// NullModem.Change_IRQ_Priority(0);
}
# endif
CCDebugString ( " C&C95 - About to call Sound_End. \n " ) ;
Sound_End ( ) ;
CCDebugString ( " C&C95 - Returned from Sound_End. \n " ) ;
if ( WWMouse ) {
CCDebugString ( " C&C95 - Deleting mouse object. \n " ) ;
delete WWMouse ;
WWMouse = NULL ;
}
if ( WindowsTimer ) {
CCDebugString ( " C&C95 - Deleting windows timer. \n " ) ;
delete WindowsTimer ;
WindowsTimer = NULL ;
}
if ( Palette ) {
CCDebugString ( " C&C95 - Deleting palette object. \n " ) ;
delete [ ] Palette ;
Palette = NULL ;
}
ProgEndCalled = true ;
}
/***********************************************************************************************
* Delete_Swap_Files - - Deletes previously existing swap files . *
* *
* This routine will scan through the current directory and delete any swap files it may *
* find . This is used to clear out any left over swap files from previous runs ( crashes ) *
* of the game . This routine presumes that it cannot delete the swap file that is created *
* by the current run of the game . *
* *
* INPUT : none *
* *
* OUTPUT : none *
* *
* WARNINGS : none *
* *
* HISTORY : *
* 08 / 27 / 1995 JLB : Created . *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
void Delete_Swap_Files ( void )
{
# if (0)
struct find_t ff ; // for _dos_findfirst
if ( ! _dos_findfirst ( " *.SWP " , _A_NORMAL , & ff ) ) {
do {
unlink ( ff . name ) ;
} while ( ! _dos_findnext ( & ff ) ) ;
}
# endif
}
void Print_Error_End_Exit ( char * string )
{
printf ( " %s \n " , string ) ;
Get_Key ( ) ;
Prog_End ( ) ;
printf ( " %s \n " , string ) ;
if ( ! RunningAsDLL ) {
exit ( 1 ) ;
}
}
void Print_Error_Exit ( char * string )
{
printf ( " %s \n " , string ) ;
if ( ! RunningAsDLL ) {
exit ( 1 ) ;
}
}
/***********************************************************************************************
* Read_Setup_Options - - Read stuff in from the INI file that we need to know sooner *
* *
* *
* *
* INPUT : Nothing *
* *
* OUTPUT : Nothing *
* *
* WARNINGS : None *
* *
* HISTORY : *
* 6 / 7 / 96 4 : 09 PM ST : Created *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
void Read_Setup_Options ( RawFileClass * config_file )
{
char * buffer = new char [ config_file - > Size ( ) ] ;
if ( config_file - > Is_Available ( ) ) {
config_file - > Read ( buffer , config_file - > Size ( ) ) ;
VideoBackBufferAllowed = WWGetPrivateProfileInt ( " Options " , " VideoBackBuffer " , 1 , buffer ) ;
AllowHardwareBlitFills = WWGetPrivateProfileInt ( " Options " , " HardwareFills " , 1 , buffer ) ;
ScreenHeight = WWGetPrivateProfileInt ( " Options " , " Resolution " , 0 , buffer ) ? 1536 : 1536 ;
IsV107 = WWGetPrivateProfileInt ( " Options " , " Compatibility " , 0 , buffer ) ;
/*
* * See if an alternative socket number has been specified
*/
int socket = WWGetPrivateProfileInt ( " Options " , " Socket " , 0 , buffer ) ;
if ( socket > 0 ) {
socket + = 0x4000 ;
if ( socket > = 0x4000 & & socket < 0x8000 ) {
Ipx . Set_Socket ( socket ) ;
}
}
/*
* * See if a destination network has been specified
*/
char netbuf [ 512 ] ;
memset ( netbuf , 0 , sizeof ( netbuf ) ) ;
char * netptr = WWGetPrivateProfileString ( " Options " , " DestNet " , NULL , netbuf , sizeof ( netbuf ) , buffer ) ;
if ( netptr & & strlen ( netbuf ) ) {
NetNumType net ;
NetNodeType node ;
/*
* * Scan the string , pulling off each address piece
*/
int i = 0 ;
char * p = strtok ( netbuf , " . " ) ;
int x ;
while ( p ) {
sscanf ( p , " %x " , & x ) ; // convert from hex string to int
if ( i < 4 ) {
net [ i ] = ( char ) x ; // fill NetNum
} else {
node [ i - 4 ] = ( char ) x ; // fill NetNode
}
i + + ;
p = strtok ( NULL , " . " ) ;
}
/*
* * If all the address components were successfully read , fill in the
* * BridgeNet with a broadcast address to the network across the bridge .
*/
if ( i > = 4 ) {
IsBridge = 1 ;
memset ( node , 0xff , 6 ) ;
BridgeNet = IPXAddressClass ( net , node ) ;
}
}
}
delete [ ] buffer ;
}