123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935 |
- //**************************************************************************
- //**
- //** h2_main.c : Heretic 2 : Raven Software, Corp.
- //**
- //** $RCSfile: h2_main.c,v $
- //** $Revision: 1.50 $
- //** $Date: 96/01/16 13:02:28 $
- //** $Author: bgokey $
- //**
- //**************************************************************************
- // HEADER FILES ------------------------------------------------------------
- #ifdef __WATCOMC__
- #include <dos.h>
- #include <sys\types.h>
- #include <direct.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "h2def.h"
- #include "p_local.h"
- #include "soundst.h"
- // MACROS ------------------------------------------------------------------
- #define CONFIG_FILE_NAME "hexen.cfg"
- #define MAXWADFILES 20
- // TYPES -------------------------------------------------------------------
- typedef struct
- {
- char *name;
- void (*func)(char **args, int tag);
- int requiredArgs;
- int tag;
- } execOpt_t;
- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
- void R_ExecuteSetViewSize(void);
- void D_CheckNetGame(void);
- void G_BuildTiccmd(ticcmd_t *cmd);
- void F_Drawer(void);
- boolean F_Responder(event_t *ev);
- void I_StartupKeyboard(void);
- void I_StartupJoystick(void);
- void I_ShutdownKeyboard(void);
- void S_InitScript(void);
- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
- void H2_ProcessEvents(void);
- void H2_DoAdvanceDemo(void);
- void H2_AdvanceDemo(void);
- void H2_StartTitle(void);
- void H2_PageTicker(void);
- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
- static void DrawMessage(void);
- static void PageDrawer(void);
- static void HandleArgs(void);
- static void CheckRecordFrom(void);
- static void AddWADFile(char *file);
- static void DrawAndBlit(void);
- static void ExecOptionFILE(char **args, int tag);
- static void ExecOptionSCRIPTS(char **args, int tag);
- static void ExecOptionDEVMAPS(char **args, int tag);
- static void ExecOptionSKILL(char **args, int tag);
- static void ExecOptionPLAYDEMO(char **args, int tag);
- static void ExecOptionMAXZONE(char **args, int tag);
- static void CreateSavePath(void);
- static void WarpCheck(void);
- #ifdef TIMEBOMB
- static void DoTimeBomb(void);
- #endif
- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
- extern boolean automapactive;
- extern boolean MenuActive;
- extern boolean askforquit;
- extern char *SavePath;
- // PUBLIC DATA DEFINITIONS -------------------------------------------------
- boolean DevMaps; // true = Map development mode
- char *DevMapsDir = ""; // development maps directory
- boolean shareware; // true if only episode 1 present
- boolean nomonsters; // checkparm of -nomonsters
- boolean respawnparm; // checkparm of -respawn
- boolean randomclass; // checkparm of -randclass
- boolean debugmode; // checkparm of -debug
- boolean ravpic; // checkparm of -ravpic
- boolean cdrom; // true if cd-rom mode active
- boolean cmdfrag; // true if a CMD_FRAG packet should be sent out
- boolean singletics; // debug flag to cancel adaptiveness
- boolean artiskip; // whether shift-enter skips an artifact
- int maxzone = 0x800000; // Maximum allocated for zone heap (8meg default)
- skill_t startskill;
- int startepisode;
- int startmap;
- boolean autostart;
- boolean advancedemo;
- FILE *debugfile;
- event_t events[MAXEVENTS];
- int eventhead;
- int eventtail;
- // PRIVATE DATA DEFINITIONS ------------------------------------------------
- static int WarpMap;
- static int demosequence;
- static int pagetic;
- static char *pagename;
- #ifdef __NeXT__
- static char *wadfiles[MAXWADFILES] =
- {
- "/Novell/H2/source/hexen.wad"
- };
- #else
- static char *wadfiles[MAXWADFILES] =
- {
- "hexen.wad"
- };
- #endif
- static execOpt_t ExecOptions[] =
- {
- { "-file", ExecOptionFILE, 1, 0 },
- { "-scripts", ExecOptionSCRIPTS, 1, 0 },
- { "-devmaps", ExecOptionDEVMAPS, 1, 0 },
- { "-skill", ExecOptionSKILL, 1, 0 },
- { "-playdemo", ExecOptionPLAYDEMO, 1, 0 },
- { "-timedemo", ExecOptionPLAYDEMO, 1, 0 },
- { "-maxzone", ExecOptionMAXZONE, 1, 0 },
- { NULL, NULL, 0, 0 } // Terminator
- };
- // CODE --------------------------------------------------------------------
- //==========================================================================
- //
- // H2_Main
- //
- //==========================================================================
- void InitMapMusicInfo(void);
- void H2_Main(void)
- {
- int p;
- M_FindResponseFile();
- setbuf(stdout, NULL);
- startepisode = 1;
- autostart = false;
- startskill = sk_medium;
- startmap = 1;
- shareware = false; // Always false for Hexen
- HandleArgs();
- // Initialize subsystems
- ST_Message("V_Init: allocate screens.\n");
- V_Init();
- // Load defaults before initing other systems
- ST_Message("M_LoadDefaults: Load system defaults.\n");
- M_LoadDefaults(CONFIG_FILE_NAME);
- // Now that the savedir is loaded from .CFG, make sure it exists
- CreateSavePath();
- // HEXEN MODIFICATION:
- // There is a realloc() in W_AddFile() that might fail if the zone
- // heap has been previously allocated, so we need to initialize the
- // WAD files BEFORE the zone memory initialization.
- ST_Message("W_Init: Init WADfiles.\n");
- W_InitMultipleFiles(wadfiles);
- #ifdef TIMEBOMB
- DoTimeBomb();
- #endif
- ST_Message("Z_Init: Init zone memory allocation daemon.\n");
- Z_Init();
- #ifdef __WATCOMC__
- I_StartupKeyboard();
- I_StartupJoystick();
- #endif
- ST_Message("MN_Init: Init menu system.\n");
- MN_Init();
- ST_Message("CT_Init: Init chat mode data.\n");
- CT_Init();
- InitMapMusicInfo(); // Init music fields in mapinfo
- #ifdef __WATCOMC__
- ST_Message("S_InitScript\n");
- S_InitScript();
- #endif
- ST_Message("SN_InitSequenceScript: Registering sound sequences.\n");
- SN_InitSequenceScript();
- ST_Message("I_Init: Setting up machine state.\n");
- I_Init();
- ST_Message("ST_Init: Init startup screen.\n");
- ST_Init();
- S_StartSongName("orb", true);
- // Show version message now, so it's visible during R_Init()
- ST_Message("Executable: "VERSIONTEXT".\n");
- ST_Message("R_Init: Init Hexen refresh daemon");
- R_Init();
- ST_Message("\n");
- if (M_CheckParm("-net")) ST_NetProgress(); // Console player found
- ST_Message("P_Init: Init Playloop state.\n");
- P_Init();
- // Check for command line warping. Follows P_Init() because the
- // MAPINFO.TXT script must be already processed.
- WarpCheck();
- if(autostart)
- {
- ST_Message("Warp to Map %d (\"%s\":%d), Skill %d\n",
- WarpMap, P_GetMapName(startmap), startmap, startskill+1);
- }
- ST_Message("D_CheckNetGame: Checking network game status.\n");
- D_CheckNetGame();
- ST_Message("SB_Init: Loading patches.\n");
- SB_Init();
-
- CheckRecordFrom();
- p = M_CheckParm("-record");
- if(p && p < myargc-1)
- {
- G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p+1]);
- H2_GameLoop(); // Never returns
- }
- p = M_CheckParm("-playdemo");
- if(p && p < myargc-1)
- {
- singledemo = true; // Quit after one demo
- G_DeferedPlayDemo(myargv[p+1]);
- H2_GameLoop(); // Never returns
- }
- p = M_CheckParm("-timedemo");
- if(p && p < myargc-1)
- {
- G_TimeDemo(myargv[p+1]);
- H2_GameLoop(); // Never returns
- }
- p = M_CheckParm("-loadgame");
- if(p && p < myargc-1)
- {
- G_LoadGame(atoi(myargv[p+1]));
- }
- if(gameaction != ga_loadgame)
- {
- UpdateState |= I_FULLSCRN;
- BorderNeedRefresh = true;
- if(autostart || netgame)
- {
- G_StartNewInit();
- G_InitNew(startskill, startepisode, startmap);
- }
- else
- {
- H2_StartTitle();
- }
- }
- H2_GameLoop(); // Never returns
- }
- //==========================================================================
- //
- // HandleArgs
- //
- //==========================================================================
- static void HandleArgs(void)
- {
- int p;
- execOpt_t *opt;
- nomonsters = M_ParmExists("-nomonsters");
- respawnparm = M_ParmExists("-respawn");
- randomclass = M_ParmExists("-randclass");
- ravpic = M_ParmExists("-ravpic");
- artiskip = M_ParmExists("-artiskip");
- debugmode = M_ParmExists("-debug");
- deathmatch = M_ParmExists("-deathmatch");
- cdrom = M_ParmExists("-cdrom");
- cmdfrag = M_ParmExists("-cmdfrag");
- // Process command line options
- for(opt = ExecOptions; opt->name != NULL; opt++)
- {
- p = M_CheckParm(opt->name);
- if(p && p < myargc-opt->requiredArgs)
- {
- opt->func(&myargv[p], opt->tag);
- }
- }
- // Look for an external device driver
- I_CheckExternDriver();
- }
- //==========================================================================
- //
- // WarpCheck
- //
- //==========================================================================
- static void WarpCheck(void)
- {
- int p;
- int map;
- p = M_CheckParm("-warp");
- if(p && p < myargc-1)
- {
- WarpMap = atoi(myargv[p+1]);
- map = P_TranslateMap(WarpMap);
- if(map == -1)
- { // Couldn't find real map number
- startmap = 1;
- ST_Message("-WARP: Invalid map number.\n");
- }
- else
- { // Found a valid startmap
- startmap = map;
- autostart = true;
- }
- }
- else
- {
- WarpMap = 1;
- startmap = P_TranslateMap(1);
- if(startmap == -1)
- {
- startmap = 1;
- }
- }
- }
- //==========================================================================
- //
- // ExecOptionSKILL
- //
- //==========================================================================
- static void ExecOptionSKILL(char **args, int tag)
- {
- startskill = args[1][0]-'1';
- autostart = true;
- }
- //==========================================================================
- //
- // ExecOptionFILE
- //
- //==========================================================================
- static void ExecOptionFILE(char **args, int tag)
- {
- int p;
- p = M_CheckParm("-file");
- while(++p != myargc && myargv[p][0] != '-')
- {
- AddWADFile(myargv[p]);
- }
- }
- //==========================================================================
- //
- // ExecOptionPLAYDEMO
- //
- //==========================================================================
- static void ExecOptionPLAYDEMO(char **args, int tag)
- {
- char file[256];
- sprintf(file, "%s.lmp", args[1]);
- AddWADFile(file);
- ST_Message("Playing demo %s.lmp.\n", args[1]);
- }
- //==========================================================================
- //
- // ExecOptionSCRIPTS
- //
- //==========================================================================
- static void ExecOptionSCRIPTS(char **args, int tag)
- {
- sc_FileScripts = true;
- sc_ScriptsDir = args[1];
- }
- //==========================================================================
- //
- // ExecOptionDEVMAPS
- //
- //==========================================================================
- static void ExecOptionDEVMAPS(char **args, int tag)
- {
- DevMaps = true;
- ST_Message("Map development mode enabled:\n");
- ST_Message("[config ] = %s\n", args[1]);
- SC_OpenFileCLib(args[1]);
- SC_MustGetStringName("mapsdir");
- SC_MustGetString();
- ST_Message("[mapsdir ] = %s\n", sc_String);
- DevMapsDir = malloc(strlen(sc_String)+1);
- strcpy(DevMapsDir, sc_String);
- SC_MustGetStringName("scriptsdir");
- SC_MustGetString();
- ST_Message("[scriptsdir] = %s\n", sc_String);
- sc_FileScripts = true;
- sc_ScriptsDir = malloc(strlen(sc_String)+1);
- strcpy(sc_ScriptsDir, sc_String);
- while(SC_GetString())
- {
- if(SC_Compare("file"))
- {
- SC_MustGetString();
- AddWADFile(sc_String);
- }
- else
- {
- SC_ScriptError(NULL);
- }
- }
- SC_Close();
- }
- long superatol(char *s)
- {
- long int n=0, r=10, x, mul=1;
- char *c=s;
- for (; *c; c++)
- {
- x = (*c & 223) - 16;
- if (x == -3)
- {
- mul = -mul;
- }
- else if (x == 72 && r == 10)
- {
- n -= (r=n);
- if (!r) r=16;
- if (r<2 || r>36) return -1;
- }
- else
- {
- if (x>10) x-=39;
- if (x >= r) return -1;
- n = (n*r) + x;
- }
- }
- return(mul*n);
- }
- static void ExecOptionMAXZONE(char **args, int tag)
- {
- int size;
-
- size = superatol(args[1]);
- if (size < MINIMUM_HEAP_SIZE) size = MINIMUM_HEAP_SIZE;
- if (size > MAXIMUM_HEAP_SIZE) size = MAXIMUM_HEAP_SIZE;
- maxzone = size;
- }
- //==========================================================================
- //
- // H2_GameLoop
- //
- //==========================================================================
- void H2_GameLoop(void)
- {
- if(M_CheckParm("-debugfile"))
- {
- char filename[20];
- sprintf(filename, "debug%i.txt", consoleplayer);
- debugfile = fopen(filename,"w");
- }
- I_InitGraphics();
- while(1)
- {
- // Frame syncronous IO operations
- I_StartFrame();
- // Process one or more tics
- if(singletics)
- {
- I_StartTic();
- H2_ProcessEvents();
- G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]);
- if(advancedemo)
- {
- H2_DoAdvanceDemo();
- }
- G_Ticker();
- gametic++;
- maketic++;
- }
- else
- {
- // Will run at least one tic
- TryRunTics();
- }
- // Move positional sounds
- S_UpdateSounds(players[displayplayer].mo);
- DrawAndBlit();
- }
- }
- //==========================================================================
- //
- // H2_ProcessEvents
- //
- // Send all the events of the given timestamp down the responder chain.
- //
- //==========================================================================
- void H2_ProcessEvents(void)
- {
- event_t *ev;
- for(; eventtail != eventhead; eventtail = (++eventtail)&(MAXEVENTS-1))
- {
- ev = &events[eventtail];
- if(F_Responder(ev))
- {
- continue;
- }
- if(MN_Responder(ev))
- {
- continue;
- }
- G_Responder(ev);
- }
- }
- //==========================================================================
- //
- // H2_PostEvent
- //
- // Called by the I/O functions when input is detected.
- //
- //==========================================================================
- void H2_PostEvent(event_t *ev)
- {
- events[eventhead] = *ev;
- eventhead = (++eventhead)&(MAXEVENTS-1);
- }
- //==========================================================================
- //
- // DrawAndBlit
- //
- //==========================================================================
- static void DrawAndBlit(void)
- {
- // Change the view size if needed
- if(setsizeneeded)
- {
- R_ExecuteSetViewSize();
- }
- // Do buffered drawing
- switch(gamestate)
- {
- case GS_LEVEL:
- if(!gametic)
- {
- break;
- }
- if(automapactive)
- {
- AM_Drawer();
- }
- else
- {
- R_RenderPlayerView(&players[displayplayer]);
- }
- CT_Drawer();
- UpdateState |= I_FULLVIEW;
- SB_Drawer();
- break;
- case GS_INTERMISSION:
- IN_Drawer();
- break;
- case GS_FINALE:
- F_Drawer();
- break;
- case GS_DEMOSCREEN:
- PageDrawer();
- break;
- }
- if(paused && !MenuActive && !askforquit)
- {
- if(!netgame)
- {
- V_DrawPatch(160, viewwindowy+5, W_CacheLumpName("PAUSED",
- PU_CACHE));
- }
- else
- {
- V_DrawPatch(160, 70, W_CacheLumpName("PAUSED",
- PU_CACHE));
- }
- }
- // Draw current message
- DrawMessage();
- // Draw Menu
- MN_Drawer();
- // Send out any new accumulation
- NetUpdate();
- // Flush buffered stuff to screen
- I_Update();
- }
- //==========================================================================
- //
- // DrawMessage
- //
- //==========================================================================
- static void DrawMessage(void)
- {
- player_t *player;
- player = &players[consoleplayer];
- if(player->messageTics <= 0 || !player->message)
- { // No message
- return;
- }
- if(player->yellowMessage)
- {
- MN_DrTextAYellow(player->message,
- 160-MN_TextAWidth(player->message)/2, 1);
- }
- else
- {
- MN_DrTextA(player->message, 160-MN_TextAWidth(player->message)/2, 1);
- }
- }
- //==========================================================================
- //
- // H2_PageTicker
- //
- //==========================================================================
- void H2_PageTicker(void)
- {
- if(--pagetic < 0)
- {
- H2_AdvanceDemo();
- }
- }
- //==========================================================================
- //
- // PageDrawer
- //
- //==========================================================================
- static void PageDrawer(void)
- {
- V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE));
- if(demosequence == 1)
- {
- V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE));
- }
- UpdateState |= I_FULLSCRN;
- }
- //==========================================================================
- //
- // H2_AdvanceDemo
- //
- // Called after each demo or intro demosequence finishes.
- //
- //==========================================================================
- void H2_AdvanceDemo(void)
- {
- advancedemo = true;
- }
- //==========================================================================
- //
- // H2_DoAdvanceDemo
- //
- //==========================================================================
- void H2_DoAdvanceDemo(void)
- {
- players[consoleplayer].playerstate = PST_LIVE; // don't reborn
- advancedemo = false;
- usergame = false; // can't save/end game here
- paused = false;
- gameaction = ga_nothing;
- demosequence = (demosequence+1)%7;
- switch(demosequence)
- {
- case 0:
- pagetic = 280;
- gamestate = GS_DEMOSCREEN;
- pagename = "TITLE";
- S_StartSongName("hexen", true);
- break;
- case 1:
- pagetic = 210;
- gamestate = GS_DEMOSCREEN;
- pagename = "TITLE";
- break;
- case 2:
- BorderNeedRefresh = true;
- UpdateState |= I_FULLSCRN;
- G_DeferedPlayDemo("demo1");
- break;
- case 3:
- pagetic = 200;
- gamestate = GS_DEMOSCREEN;
- pagename = "CREDIT";
- break;
- case 4:
- BorderNeedRefresh = true;
- UpdateState |= I_FULLSCRN;
- G_DeferedPlayDemo("demo2");
- break;
- case 5:
- pagetic = 200;
- gamestate = GS_DEMOSCREEN;
- pagename = "CREDIT";
- break;
- case 6:
- BorderNeedRefresh = true;
- UpdateState |= I_FULLSCRN;
- G_DeferedPlayDemo("demo3");
- break;
- }
- }
- //==========================================================================
- //
- // H2_StartTitle
- //
- //==========================================================================
- void H2_StartTitle(void)
- {
- gameaction = ga_nothing;
- demosequence = -1;
- H2_AdvanceDemo();
- }
- //==========================================================================
- //
- // CheckRecordFrom
- //
- // -recordfrom <savegame num> <demoname>
- //
- //==========================================================================
- static void CheckRecordFrom(void)
- {
- int p;
- p = M_CheckParm("-recordfrom");
- if(!p || p > myargc-2)
- { // Bad args
- return;
- }
- G_LoadGame(atoi(myargv[p+1]));
- G_DoLoadGame(); // Load the gameskill etc info from savegame
- G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p+2]);
- H2_GameLoop(); // Never returns
- }
- //==========================================================================
- //
- // AddWADFile
- //
- //==========================================================================
- static void AddWADFile(char *file)
- {
- int i;
- char *new;
- ST_Message("Adding external file: %s\n", file);
- i = 0;
- while(wadfiles[i])
- {
- i++;
- }
- new = malloc(strlen(file)+1);
- strcpy(new, file);
- wadfiles[i] = new;
- }
- #ifdef __WATCOMC__
- /*
- void CleanExit(void)
- {
- union REGS regs;
- I_ShutdownKeyboard();
- regs.x.eax = 0x3;
- int386(0x10, ®s, ®s);
- printf("Exited from HEXEN: Beyond Heretic.\n");
- exit(1);
- }
- */
- #endif
- //==========================================================================
- //
- // FixedDiv
- //
- //==========================================================================
- fixed_t FixedDiv(fixed_t a, fixed_t b)
- {
- if((abs(a)>>14) >= abs(b))
- {
- return((a^b)<0 ? MININT : MAXINT);
- }
- return(FixedDiv2(a, b));
- }
- //==========================================================================
- //
- // CreateSavePath
- //
- //==========================================================================
- static void CreateSavePath(void)
- {
- char creationPath[121];
- int len;
- if(cdrom == true)
- {
- SavePath = "c:\\hexndata\\";
- }
- len = strlen(SavePath);
- if (len >= 120) I_Error("Save path too long\n");
- strcpy(creationPath, SavePath);
- #ifdef __WATCOMC__
- creationPath[len-1] = 0;
- mkdir(creationPath);
- #endif
- }
- #ifdef TIMEBOMB
- //==========================================================================
- //
- // DoTimeBomb
- //
- //==========================================================================
- static void DoTimeBomb(void)
- {
- #ifdef __WATCOMC__
- time_t timeOfDay;
- struct tm timeBuffer;
- timeOfDay = time(NULL);
- _localtime(&timeOfDay, &timeBuffer);
- if(timeBuffer.tm_year != TIMEBOMB_YEAR
- || timeBuffer.tm_yday < TIMEBOMB_STARTDATE
- || timeBuffer.tm_yday > TIMEBOMB_ENDDATE)
- {
- I_Error("W_InitWadfiles: Wad file doesn't have IWAD or PWAD id\n");
- }
-
- printf("\n===============================================================================\n");
- printf(" Hexen: Beyond Heretic\n\n");
- printf(" Beta -- Do Not Distribute!\n");
- printf(" Press any key to continue.\n");
- printf("===============================================================================\n");
-
- getch();
- printf("\n");
- #endif
- }
- #endif
|