diff options
author | Simon Howard | 2008-09-04 23:15:36 +0000 |
---|---|---|
committer | Simon Howard | 2008-09-04 23:15:36 +0000 |
commit | 0df2cb80cf03d7259746834220d209b306a8c503 (patch) | |
tree | fdc5037429c91dcbc8207c3e75fc787ef96e207a /src/heretic/d_main.c | |
parent | 6a294daa7859eaf0250aa4a77484dd11550e5c5e (diff) | |
download | chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.gz chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.bz2 chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.zip |
Add GPLed Heretic/Hexen source.
Subversion-branch: /branches/raven-branch
Subversion-revision: 1195
Diffstat (limited to 'src/heretic/d_main.c')
-rw-r--r-- | src/heretic/d_main.c | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c new file mode 100644 index 00000000..59205997 --- /dev/null +++ b/src/heretic/d_main.c @@ -0,0 +1,1040 @@ + +// D_main.c + +#ifdef __WATCOMC__ +#include <dos.h> +#include <graph.h> +#include <sys\types.h> +#include <direct.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include "DoomDef.h" +#include "P_local.h" +#include "soundst.h" + +boolean shareware = false; // true if only episode 1 present +boolean ExtendedWAD = false; // true if episodes 4 and 5 present + +boolean nomonsters; // checkparm of -nomonsters +boolean respawnparm; // checkparm of -respawn +boolean debugmode; // checkparm of -debug +boolean ravpic; // checkparm of -ravpic +boolean cdrom; // true if cd-rom mode active +boolean singletics; // debug flag to cancel adaptiveness +boolean noartiskip; // whether shift-enter skips an artifact + +skill_t startskill; +int startepisode; +int startmap; +boolean autostart; +extern boolean automapactive; + +boolean advancedemo; + +FILE *debugfile; + +void D_CheckNetGame(void); +void D_ProcessEvents(void); +void G_BuildTiccmd(ticcmd_t *cmd); +void D_DoAdvanceDemo(void); +void D_PageDrawer (void); +void D_AdvanceDemo (void); +void F_Drawer(void); +boolean F_Responder(event_t *ev); + +//--------------------------------------------------------------------------- +// +// FUNC 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)); +} + +/* +=============================================================================== + + EVENT HANDLING + +Events are asyncronous inputs generally generated by the game user. + +Events can be discarded if no responder claims them + +=============================================================================== +*/ + +event_t events[MAXEVENTS]; +int eventhead; +int eventtail; + +//--------------------------------------------------------------------------- +// +// PROC D_PostEvent +// +// Called by the I/O functions when input is detected. +// +//--------------------------------------------------------------------------- + +void D_PostEvent(event_t *ev) +{ + events[eventhead] = *ev; + eventhead = (++eventhead)&(MAXEVENTS-1); +} + +//--------------------------------------------------------------------------- +// +// PROC D_ProcessEvents +// +// Send all the events of the given timestamp down the responder chain. +// +//--------------------------------------------------------------------------- + +void D_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); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMessage +// +//--------------------------------------------------------------------------- + +void DrawMessage(void) +{ + player_t *player; + + player = &players[consoleplayer]; + if(player->messageTics <= 0 || !player->message) + { // No message + return; + } + MN_DrTextA(player->message, 160-MN_TextAWidth(player->message)/2, 1); +} + +//--------------------------------------------------------------------------- +// +// PROC D_Display +// +// Draw current display, possibly wiping it from the previous. +// +//--------------------------------------------------------------------------- + +void R_ExecuteSetViewSize(void); + +extern boolean finalestage; + +void D_Display(void) +{ + extern boolean MenuActive; + extern boolean askforquit; + + // 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: + D_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)); + } + } + // Handle player messages + DrawMessage(); + + // Menu drawing + MN_Drawer(); + + // Send out any new accumulation + NetUpdate(); + + // Flush buffered stuff to screen + I_Update(); +} + +//--------------------------------------------------------------------------- +// +// PROC D_DoomLoop +// +//--------------------------------------------------------------------------- + +void D_DoomLoop(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(); + D_ProcessEvents(); + G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]); + if (advancedemo) + D_DoAdvanceDemo (); + G_Ticker(); + gametic++; + maketic++; + } + else + { + // Will run at least one tic + TryRunTics(); + } + + // Move positional sounds + S_UpdateSounds(players[consoleplayer].mo); + D_Display(); + } +} + +/* +=============================================================================== + + DEMO LOOP + +=============================================================================== +*/ + +int demosequence; +int pagetic; +char *pagename; + + +/* +================ += += D_PageTicker += += Handles timing for warped projection += +================ +*/ + +void D_PageTicker (void) +{ + if (--pagetic < 0) + D_AdvanceDemo (); +} + + +/* +================ += += D_PageDrawer += +================ +*/ + +extern boolean MenuActive; + +void D_PageDrawer(void) +{ + V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE)); + if(demosequence == 1) + { + V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE)); + } + UpdateState |= I_FULLSCRN; +} + +/* +================= += += D_AdvanceDemo += += Called after each demo or intro demosequence finishes +================= +*/ + +void D_AdvanceDemo (void) +{ + advancedemo = true; +} + +void D_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 = 210; + gamestate = GS_DEMOSCREEN; + pagename = "TITLE"; + S_StartSong(mus_titl, false); + break; + case 1: + pagetic = 140; + 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; + if(shareware) + { + pagename = "ORDER"; + } + else + { + pagename = "CREDIT"; + } + break; + case 6: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo ("demo3"); + break; + } +} + + +/* +================= += += D_StartTitle += +================= +*/ + +void D_StartTitle (void) +{ + gameaction = ga_nothing; + demosequence = -1; + D_AdvanceDemo (); +} + + +/* +============== += += D_CheckRecordFrom += += -recordfrom <savegame num> <demoname> +============== +*/ + +void D_CheckRecordFrom (void) +{ + int p; + char file[256]; + + p = M_CheckParm ("-recordfrom"); + if (!p || p > myargc-2) + return; + + if(cdrom) + { + sprintf(file, SAVEGAMENAMECD"%c.hsg",myargv[p+1][0]); + } + else + { + sprintf(file, SAVEGAMENAME"%c.hsg",myargv[p+1][0]); + } + G_LoadGame (file); + G_DoLoadGame (); // load the gameskill etc info from savegame + + G_RecordDemo (gameskill, 1, gameepisode, gamemap, myargv[p+2]); + D_DoomLoop (); // never returns +} + +/* +=============== += += D_AddFile += +=============== +*/ + +#define MAXWADFILES 20 + +// MAPDIR should be defined as the directory that holds development maps +// for the -wart # # command + +#ifdef __NeXT__ + +#define MAPDIR "/Novell/Heretic/data/" + +#define SHAREWAREWADNAME "/Novell/Heretic/source/heretic1.wad" + +char *wadfiles[MAXWADFILES] = +{ + "/Novell/Heretic/source/heretic.wad", + "/Novell/Heretic/data/texture1.lmp", + "/Novell/Heretic/data/texture2.lmp", + "/Novell/Heretic/data/pnames.lmp" +}; + +#else + +#define MAPDIR "\\data\\" + +#define SHAREWAREWADNAME "heretic1.wad" + +char *wadfiles[MAXWADFILES] = +{ + "heretic.wad", + "texture1.lmp", + "texture2.lmp", + "pnames.lmp" +}; + +#endif + +char *basedefault = "heretic.cfg"; + +char exrnwads[80]; +char exrnwads2[80]; + +void wadprintf(void) +{ + if(debugmode) + { + return; + } + #ifdef __WATCOMC__ + _settextposition(23, 2); + _setbkcolor(1); + _settextcolor(0); + _outtext(exrnwads); + _settextposition(24, 2); + _outtext(exrnwads2); + #endif +} + +void D_AddFile(char *file) +{ + int numwadfiles; + char *new; +// char text[256]; + + for(numwadfiles = 0; wadfiles[numwadfiles]; numwadfiles++); + new = malloc(strlen(file)+1); + strcpy(new, file); + if(strlen(exrnwads)+strlen(file) < 78) + { + if(strlen(exrnwads)) + { + strcat(exrnwads, ", "); + } + else + { + strcpy(exrnwads, "External Wadfiles: "); + } + strcat(exrnwads, file); + } + else if(strlen(exrnwads2)+strlen(file) < 79) + { + if(strlen(exrnwads2)) + { + strcat(exrnwads2, ", "); + } + else + { + strcpy(exrnwads2, " "); + strcat(exrnwads, ","); + } + strcat(exrnwads2, file); + } + wadfiles[numwadfiles] = new; +} + +//========================================================== +// +// Startup Thermo code +// +//========================================================== +#define MSG_Y 9 +//#define THERM_X 15 +//#define THERM_Y 16 +//#define THERMCOLOR 3 +#define THERM_X 14 +#define THERM_Y 14 + +int thermMax; +int thermCurrent; +char *startup; // * to text screen +char smsg[80]; // status bar line + +// +// Heretic startup screen shit +// + +byte *hscreen; + +void hgotoxy(int x,int y) +{ + hscreen = (byte *)(0xb8000 + y*160 + x*2); +} + +void hput(unsigned char c, unsigned char a) +{ + *hscreen++ = c; + *hscreen++ = a; +} + +void hprintf(char *string, unsigned char a) +{ +#ifdef __WATCOMC__ + int i; + + if(debugmode) + { + puts(string); + return; + } + for(i = 0; i < strlen(string); i++) + { + hput(string[i], a); + } +#endif +} + +void drawstatus(void) +{ + if(debugmode) + { + return; + } + #ifdef __WATCOMC__ + _settextposition(25, 2); + _setbkcolor(1); + _settextcolor(15); + _outtext(smsg); + _settextposition(25, 1); + #endif +} + +void status(char *string) +{ + strcat(smsg,string); + drawstatus(); +} + +void DrawThermo(void) +{ + #ifdef __WATCOMC__ + unsigned char *screen; + int progress; + int i; + + if(debugmode) + { + return; + } +#if 0 + progress = (98*thermCurrent)/thermMax; + screen = (char *)0xb8000 + (THERM_Y*160 + THERM_X*2); + for (i = 0;i < progress/2; i++) + { + switch(i) + { + case 4: + case 9: + case 14: + case 19: + case 29: + case 34: + case 39: + case 44: + *screen++ = 0xb3; + *screen++ = (THERMCOLOR<<4)+15; + break; + case 24: + *screen++ = 0xba; + *screen++ = (THERMCOLOR<<4)+15; + break; + default: + *screen++ = 0xdb; + *screen++ = 0x40 + THERMCOLOR; + break; + } + } + if (progress&1) + { + *screen++ = 0xdd; + *screen++ = 0x40 + THERMCOLOR; + } +#else + progress = (50*thermCurrent)/thermMax+2; +// screen = (char *)0xb8000 + (THERM_Y*160 + THERM_X*2); + hgotoxy(THERM_X,THERM_Y); + for (i = 0; i < progress; i++) + { +// *screen++ = 0xdb; +// *screen++ = 0x2a; + hput(0xdb,0x2a); + } +#endif + #endif +} + +#ifdef __WATCOMC__ +void blitStartup(void) +{ + byte *textScreen; + + if(debugmode) + { + return; + } + + // Blit main screen + textScreen = (byte *)0xb8000; + memcpy(textScreen, startup, 4000); + + // Print version string + _setbkcolor(4); // Red + _settextcolor(14); // Yellow + _settextposition(3, 47); + _outtext(VERSION_TEXT); + + // Hide cursor + _settextcursor(0x2000); +} +#endif + +char tmsg[300]; +void tprintf(char *msg,int initflag) +{ +#if 0 + #ifdef __WATCOMC__ + char temp[80]; + int start; + int add; + int i; + #endif + + if(debugmode) + { + printf(msg); + return; + } + #ifdef __WATCOMC__ + if (initflag) + tmsg[0] = 0; + strcat(tmsg,msg); + blitStartup(); + DrawThermo(); + _setbkcolor(4); + _settextcolor(15); + for (add = start = i = 0; i <= strlen(tmsg); i++) + if ((tmsg[i] == '\n') || (!tmsg[i])) + { + memset(temp,0,80); + strncpy(temp,tmsg+start,i-start); + _settextposition(MSG_Y+add,40-strlen(temp)/2); + _outtext(temp); + start = i+1; + add++; + } + _settextposition(25,1); + drawstatus(); + #else + printf(msg); + #endif +#endif +} + +void CheckAbortStartup(void) +{ +#ifdef __WATCOMC__ + extern int lastpress; + + if(lastpress == 1) + { // Abort if escape pressed + CleanExit(); + } +#endif +} + +void IncThermo(void) +{ + thermCurrent++; + DrawThermo(); + CheckAbortStartup(); +} + +void InitThermo(int max) +{ + thermMax = max; + thermCurrent = 0; +} + +#ifdef __WATCOMC__ +void CleanExit(void) +{ + union REGS regs; + + I_ShutdownKeyboard(); + regs.x.eax = 0x3; + int386(0x10, ®s, ®s); + printf("Exited from HERETIC.\n"); + exit(1); +} +#endif + +//--------------------------------------------------------------------------- +// +// PROC D_DoomMain +// +//--------------------------------------------------------------------------- + +void D_DoomMain(void) +{ + int p; + int e; + int m; + char file[256]; + FILE *fp; + boolean devMap; + //char *screen; + + M_FindResponseFile(); + setbuf(stdout, NULL); + nomonsters = M_CheckParm("-nomonsters"); + respawnparm = M_CheckParm("-respawn"); + ravpic = M_CheckParm("-ravpic"); + noartiskip = M_CheckParm("-noartiskip"); + debugmode = M_CheckParm("-debug"); + startskill = sk_medium; + startepisode = 1; + startmap = 1; + autostart = false; + + // wadfiles[0] is a char * to the main wad + fp = fopen(wadfiles[0], "rb"); + if(fp) + { + fclose(fp); + } + else + { // Change to look for shareware wad + wadfiles[0] = SHAREWAREWADNAME; + } + + // Check for -CDROM + cdrom = false; +#ifdef __WATCOMC__ + if(M_CheckParm("-cdrom")) + { + cdrom = true; + mkdir("c:\\heretic.cd"); + } +#endif + + // -FILE [filename] [filename] ... + // Add files to the wad list. + p = M_CheckParm("-file"); + if(p) + { // the parms after p are wadfile/lump names, until end of parms + // or another - preceded parm + while(++p != myargc && myargv[p][0] != '-') + { + D_AddFile(myargv[p]); + } + } + + // -DEVMAP <episode> <map> + // Adds a map wad from the development directory to the wad list, + // and sets the start episode and the start map. + devMap = false; + p = M_CheckParm("-devmap"); + if(p && p < myargc-2) + { + e = myargv[p+1][0]; + m = myargv[p+2][0]; + sprintf(file, MAPDIR"E%cM%c.wad", e, m); + D_AddFile(file); + printf("DEVMAP: Episode %c, Map %c.\n", e, m); + startepisode = e-'0'; + startmap = m-'0'; + autostart = true; + devMap = true; + } + + p = M_CheckParm("-playdemo"); + if(!p) + { + p = M_CheckParm("-timedemo"); + } + if (p && p < myargc-1) + { + sprintf(file, "%s.lmp", myargv[p+1]); + D_AddFile(file); + printf("Playing demo %s.lmp.\n", myargv[p+1]); + } + +// +// get skill / episode / map from parms +// + if(M_CheckParm("-deathmatch")) + { + deathmatch = true; + } + + p = M_CheckParm("-skill"); + if(p && p < myargc-1) + { + startskill = myargv[p+1][0]-'1'; + autostart = true; + } + + p = M_CheckParm("-episode"); + if(p && p < myargc-1) + { + startepisode = myargv[p+1][0]-'0'; + startmap = 1; + autostart = true; + } + + p = M_CheckParm("-warp"); + if(p && p < myargc-2) + { + startepisode = myargv[p+1][0]-'0'; + startmap = myargv[p+2][0]-'0'; + autostart = true; + } + +// +// init subsystems +// + printf("V_Init: allocate screens.\n"); + V_Init(); + + // Load defaults before initing other systems + printf("M_LoadDefaults: Load system defaults.\n"); + M_LoadDefaults(); + + printf("Z_Init: Init zone memory allocation daemon.\n"); + Z_Init(); + + printf("W_Init: Init WADfiles.\n"); + W_InitMultipleFiles(wadfiles); + + if(W_CheckNumForName("E2M1") == -1) + { // Can't find episode 2 maps, must be the shareware WAD + shareware = true; + } + else if(W_CheckNumForName("EXTENDED") != -1) + { // Found extended lump, must be the extended WAD + ExtendedWAD = true; + } + +#ifdef __WATCOMC__ + I_StartupKeyboard(); + I_StartupJoystick(); +#endif + startup = W_CacheLumpName("LOADING", PU_CACHE); + #ifdef __WATCOMC__ + blitStartup(); + #endif + + // + // Build status bar line! + // + smsg[0] = 0; + if (deathmatch) + status("DeathMatch..."); + if (nomonsters) + status("No Monsters..."); + if (respawnparm) + status("Respawning..."); + if (autostart) + { + char temp[64]; + sprintf(temp, "Warp to Episode %d, Map %d, Skill %d ", + startepisode, startmap, startskill+1); + status(temp); + } + wadprintf(); // print the added wadfiles + + tprintf("MN_Init: Init menu system.\n",1); + MN_Init(); + + CT_Init(); + + tprintf("R_Init: Init Heretic refresh daemon.",1); + hgotoxy(17,7); + hprintf("Loading graphics",0x3f); + R_Init(); + + tprintf("P_Init: Init Playloop state.",1); + hgotoxy(17,8); + hprintf("Init game engine.",0x3f); + P_Init(); + IncThermo(); + + tprintf("I_Init: Setting up machine state.\n",1); + I_Init(); + IncThermo(); + + tprintf("D_CheckNetGame: Checking network game status.\n",1); + hgotoxy(17,9); + hprintf("Checking network game status.", 0x3f); + D_CheckNetGame(); + IncThermo(); + +#ifdef __WATCOMC__ + I_CheckExternDriver(); // Check for an external device driver +#endif + + tprintf("SB_Init: Loading patches.\n",1); + SB_Init(); + IncThermo(); + +// +// start the apropriate game based on parms +// + + D_CheckRecordFrom(); + + p = M_CheckParm("-record"); + if(p && p < myargc-1) + { + G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p+1]); + D_DoomLoop(); // Never returns + } + + p = M_CheckParm("-playdemo"); + if(p && p < myargc-1) + { + singledemo = true; // Quit after one demo + G_DeferedPlayDemo(myargv[p+1]); + D_DoomLoop(); // Never returns + } + + p = M_CheckParm("-timedemo"); + if(p && p < myargc-1) + { + G_TimeDemo(myargv[p+1]); + D_DoomLoop(); // Never returns + } + + p = M_CheckParm("-loadgame"); + if(p && p < myargc-1) + { + if(cdrom) + { + sprintf(file, SAVEGAMENAMECD"%c.hsg", myargv[p+1][0]); + } + else + { + sprintf(file, SAVEGAMENAME"%c.hsg", myargv[p+1][0]); + } + G_LoadGame(file); + } + + // Check valid episode and map + if((autostart || netgame) && (devMap == false)) + { + if(M_ValidEpisodeMap(startepisode, startmap) == false) + { + startepisode = 1; + startmap = 1; + } + } + + if(gameaction != ga_loadgame) + { + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + if(autostart || netgame) + { + G_InitNew(startskill, startepisode, startmap); + } + else + { + D_StartTitle(); + } + } +#ifdef __WATCOMC__ + _settextcursor(0x0607); // bring the cursor back +#endif + D_DoomLoop(); // Never returns +} |