Subversion Repositories Kolibri OS

Rev

Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:
20
//	DOOM selection menu, options, episode etc.
21
//	Sliders and icons. Kinda widget stuff.
22
//
23
//-----------------------------------------------------------------------------
24
 
25
static const char
26
rcsid[] = "$Id: m_menu.c,v 1.7 1997/02/03 22:45:10 b1 Exp $";
27
 
28
#include 
29
#include 
30
 
31
#include "m_swap.h"
32
#include "doomdef.h"
33
#include "dstrings.h"
34
 
35
#include "d_main.h"
36
 
37
#include "i_system.h"
38
#include "i_video.h"
39
#include "z_zone.h"
40
#include "v_video.h"
41
#include "w_wad.h"
42
 
43
#include "r_local.h"
44
 
45
 
46
#include "hu_stuff.h"
47
 
48
#include "g_game.h"
49
 
50
#include "m_argv.h"
51
 
52
#include "s_sound.h"
53
 
54
#include "doomstat.h"
55
 
56
// Data.
57
#include "sounds.h"
58
 
59
#include "m_menu.h"
60
 
61
 
62
 
63
extern patch_t*		hu_font[HU_FONTSIZE];
64
extern boolean		message_dontfuckwithme;
65
 
66
extern boolean		chat_on;		// in heads-up code
67
 
68
//
69
// defaulted values
70
//
71
int			mouseSensitivity;       // has default
72
 
73
// Show messages has default, 0 = off, 1 = on
74
int			showMessages;
75
 
76
 
77
// Blocky mode, has default, 0 = high, 1 = normal
78
int			detailLevel;
79
int			screenblocks;		// has default
80
 
81
// temp for screenblocks (0-9)
82
int			screenSize;
83
 
84
// -1 = no quicksave slot picked!
85
int			quickSaveSlot;
86
 
87
 // 1 = message to be printed
88
int			messageToPrint;
89
// ...and here is the message string!
90
char*			messageString;
91
 
92
// message x & y
93
int			messx;
94
int			messy;
95
int			messageLastMenuActive;
96
 
97
// timed message = no input from user
98
boolean			messageNeedsInput;
99
 
100
void    (*messageRoutine)(int response);
101
 
102
#define SAVESTRINGSIZE 	24
103
 
104
char gammamsg[5][26] =
105
{
106
    GAMMALVL0,
107
    GAMMALVL1,
108
    GAMMALVL2,
109
    GAMMALVL3,
110
    GAMMALVL4
111
};
112
 
113
// we are going to be entering a savegame string
114
int			saveStringEnter;
115
int             	saveSlot;	// which slot to save in
116
int			saveCharIndex;	// which char we're editing
117
// old save description before edit
118
char			saveOldString[SAVESTRINGSIZE];
119
 
120
boolean			inhelpscreens;
121
boolean			menuactive;
122
 
123
#define SKULLXOFF		-32
124
#define LINEHEIGHT		16
125
 
126
extern boolean		sendpause;
127
char			savegamestrings[10][SAVESTRINGSIZE];
128
 
129
char	endstring[160];
130
 
131
 
132
//
133
// MENU TYPEDEFS
134
//
135
typedef struct
136
{
137
    // 0 = no cursor here, 1 = ok, 2 = arrows ok
138
    short	status;
139
 
140
    char	name[10];
141
 
142
    // choice = menu item #.
143
    // if status = 2,
144
    //   choice=0:leftarrow,1:rightarrow
145
    void	(*routine)(int choice);
146
 
147
    // hotkey in menu
148
    char	alphaKey;
149
} menuitem_t;
150
 
151
 
152
 
153
typedef struct menu_s
154
{
155
    short		numitems;	// # of menu items
156
    struct menu_s*	prevMenu;	// previous menu
157
    menuitem_t*		menuitems;	// menu items
158
    void		(*routine)();	// draw routine
159
    short		x;
160
    short		y;		// x,y of menu
161
    short		lastOn;		// last item user was on in menu
162
} menu_t;
163
 
164
short		itemOn;			// menu item skull is on
165
short		skullAnimCounter;	// skull animation counter
166
short		whichSkull;		// which skull to draw
167
 
168
// graphic name of skulls
169
// warning: initializer-string for array of chars is too long
170
char    skullName[2][/*8*/9] = {"M_SKULL1","M_SKULL2"};
171
 
172
// current menudef
173
menu_t*	currentMenu;
174
 
175
//
176
// PROTOTYPES
177
//
178
void M_NewGame(int choice);
179
void M_Episode(int choice);
180
void M_ChooseSkill(int choice);
181
void M_LoadGame(int choice);
182
void M_SaveGame(int choice);
183
void M_Options(int choice);
184
void M_EndGame(int choice);
185
void M_ReadThis(int choice);
186
void M_ReadThis2(int choice);
187
void M_QuitDOOM(int choice);
188
 
189
void M_ChangeMessages(int choice);
190
void M_ChangeSensitivity(int choice);
191
void M_SfxVol(int choice);
192
void M_MusicVol(int choice);
193
void M_ChangeDetail(int choice);
194
void M_SizeDisplay(int choice);
195
void M_StartGame(int choice);
196
void M_Sound(int choice);
197
 
198
void M_FinishReadThis(int choice);
199
void M_LoadSelect(int choice);
200
void M_SaveSelect(int choice);
201
void M_ReadSaveStrings(void);
202
void M_QuickSave(void);
203
void M_QuickLoad(void);
204
 
205
void M_DrawMainMenu(void);
206
void M_DrawReadThis1(void);
207
void M_DrawReadThis2(void);
208
void M_DrawNewGame(void);
209
void M_DrawEpisode(void);
210
void M_DrawOptions(void);
211
void M_DrawSound(void);
212
void M_DrawLoad(void);
213
void M_DrawSave(void);
214
 
215
void M_DrawSaveLoadBorder(int x,int y);
216
void M_SetupNextMenu(menu_t *menudef);
217
void M_DrawThermo(int x,int y,int thermWidth,int thermDot);
218
void M_DrawEmptyCell(menu_t *menu,int item);
219
void M_DrawSelCell(menu_t *menu,int item);
220
void M_WriteText(int x, int y, char *string);
221
int  M_StringWidth(char *string);
222
int  M_StringHeight(char *string);
223
void M_StartControlPanel(void);
224
void M_StartMessage(char *string,void *routine,boolean input);
225
void M_StopMessage(void);
226
void M_ClearMenus (void);
227
 
228
 
229
 
230
 
231
//
232
// DOOM MENU
233
//
234
enum
235
{
236
    newgame = 0,
237
    options,
238
    loadgame,
239
    savegame,
240
    readthis,
241
    quitdoom,
242
    main_end
243
} main_e;
244
 
245
menuitem_t MainMenu[]=
246
{
247
    {1,"M_NGAME",M_NewGame,'n'},
248
    {1,"M_OPTION",M_Options,'o'},
249
    {1,"M_LOADG",M_LoadGame,'l'},
250
    {1,"M_SAVEG",M_SaveGame,'s'},
251
    // Another hickup with Special edition.
252
    {1,"M_RDTHIS",M_ReadThis,'r'},
253
    {1,"M_QUITG",M_QuitDOOM,'q'}
254
};
255
 
256
menu_t  MainDef =
257
{
258
    main_end,
259
    NULL,
260
    MainMenu,
261
    M_DrawMainMenu,
262
    97,64,
263
 
264
};
265
 
266
 
267
//
268
// EPISODE SELECT
269
//
270
enum
271
{
272
    ep1,
273
    ep2,
274
    ep3,
275
    ep4,
276
    ep_end
277
} episodes_e;
278
 
279
menuitem_t EpisodeMenu[]=
280
{
281
    {1,"M_EPI1", M_Episode,'k'},
282
    {1,"M_EPI2", M_Episode,'t'},
283
    {1,"M_EPI3", M_Episode,'i'},
284
    {1,"M_EPI4", M_Episode,'t'}
285
};
286
 
287
menu_t  EpiDef =
288
{
289
    ep_end,		// # of menu items
290
    &MainDef,		// previous menu
291
    EpisodeMenu,	// menuitem_t ->
292
    M_DrawEpisode,	// drawing routine ->
293
    48,63,              // x,y
294
    ep1			// lastOn
295
};
296
 
297
//
298
// NEW GAME
299
//
300
enum
301
{
302
    killthings,
303
    toorough,
304
    hurtme,
305
    violence,
306
    nightmare,
307
    newg_end
308
} newgame_e;
309
 
310
menuitem_t NewGameMenu[]=
311
{
312
    {1,"M_JKILL",	M_ChooseSkill, 'i'},
313
    {1,"M_ROUGH",	M_ChooseSkill, 'h'},
314
    {1,"M_HURT",	M_ChooseSkill, 'h'},
315
    {1,"M_ULTRA",	M_ChooseSkill, 'u'},
316
    {1,"M_NMARE",	M_ChooseSkill, 'n'}
317
};
318
 
319
menu_t  NewDef =
320
{
321
    newg_end,		// # of menu items
322
    &EpiDef,		// previous menu
323
    NewGameMenu,	// menuitem_t ->
324
    M_DrawNewGame,	// drawing routine ->
325
    48,63,              // x,y
326
    hurtme		// lastOn
327
};
328
 
329
 
330
 
331
//
332
// OPTIONS MENU
333
//
334
enum
335
{
336
    endgame,
337
    messages,
338
    detail,
339
    scrnsize,
340
    option_empty1,
341
    mousesens,
342
    option_empty2,
343
    soundvol,
344
    opt_end
345
} options_e;
346
 
347
menuitem_t OptionsMenu[]=
348
{
349
    {1,"M_ENDGAM",	M_EndGame,'e'},
350
    {1,"M_MESSG",	M_ChangeMessages,'m'},
351
    {1,"M_DETAIL",	M_ChangeDetail,'g'},
352
    {2,"M_SCRNSZ",	M_SizeDisplay,'s'},
353
    {-1,"",0},
354
    {2,"M_MSENS",	M_ChangeSensitivity,'m'},
355
    {-1,"",0},
356
    {1,"M_SVOL",	M_Sound,'s'}
357
};
358
 
359
menu_t  OptionsDef =
360
{
361
    opt_end,
362
    &MainDef,
363
    OptionsMenu,
364
    M_DrawOptions,
365
    60,37,
366
 
367
};
368
 
369
//
370
// Read This! MENU 1 & 2
371
//
372
enum
373
{
374
    rdthsempty1,
375
    read1_end
376
} read_e;
377
 
378
menuitem_t ReadMenu1[] =
379
{
380
    {1,"",M_ReadThis2,0}
381
};
382
 
383
menu_t  ReadDef1 =
384
{
385
    read1_end,
386
    &MainDef,
387
    ReadMenu1,
388
    M_DrawReadThis1,
389
    280,185,
390
 
391
};
392
 
393
enum
394
{
395
    rdthsempty2,
396
    read2_end
397
} read_e2;
398
 
399
menuitem_t ReadMenu2[]=
400
{
401
    {1,"",M_FinishReadThis,0}
402
};
403
 
404
menu_t  ReadDef2 =
405
{
406
    read2_end,
407
    &ReadDef1,
408
    ReadMenu2,
409
    M_DrawReadThis2,
410
    330,175,
411
 
412
};
413
 
414
//
415
// SOUND VOLUME MENU
416
//
417
enum
418
{
419
    sfx_vol,
420
    sfx_empty1,
421
    music_vol,
422
    sfx_empty2,
423
    sound_end
424
} sound_e;
425
 
426
menuitem_t SoundMenu[]=
427
{
428
    {2,"M_SFXVOL",M_SfxVol,'s'},
429
    {-1,"",0},
430
    {2,"M_MUSVOL",M_MusicVol,'m'},
431
    {-1,"",0}
432
};
433
 
434
menu_t  SoundDef =
435
{
436
    sound_end,
437
    &OptionsDef,
438
    SoundMenu,
439
    M_DrawSound,
440
    80,64,
441
 
442
};
443
 
444
//
445
// LOAD GAME MENU
446
//
447
enum
448
{
449
    load1,
450
    load2,
451
    load3,
452
    load4,
453
    load5,
454
    load6,
455
    load_end
456
} load_e;
457
 
458
menuitem_t LoadMenu[]=
459
{
460
    {1,"", M_LoadSelect,'1'},
461
    {1,"", M_LoadSelect,'2'},
462
    {1,"", M_LoadSelect,'3'},
463
    {1,"", M_LoadSelect,'4'},
464
    {1,"", M_LoadSelect,'5'},
465
    {1,"", M_LoadSelect,'6'}
466
};
467
 
468
menu_t  LoadDef =
469
{
470
    load_end,
471
    &MainDef,
472
    LoadMenu,
473
    M_DrawLoad,
474
    80,54,
475
 
476
};
477
 
478
//
479
// SAVE GAME MENU
480
//
481
menuitem_t SaveMenu[]=
482
{
483
    {1,"", M_SaveSelect,'1'},
484
    {1,"", M_SaveSelect,'2'},
485
    {1,"", M_SaveSelect,'3'},
486
    {1,"", M_SaveSelect,'4'},
487
    {1,"", M_SaveSelect,'5'},
488
    {1,"", M_SaveSelect,'6'}
489
};
490
 
491
menu_t  SaveDef =
492
{
493
    load_end,
494
    &MainDef,
495
    SaveMenu,
496
    M_DrawSave,
497
    80,54,
498
 
499
};
500
 
501
 
502
//
503
// M_ReadSaveStrings
504
//  read the strings from the savegame files
505
//
506
void M_ReadSaveStrings(void)
507
{
508
    FILE           *handle;
509
    int             count;
510
    int             i;
511
    char    name[256];
512
 
513
    for (i = 0;i < load_end;i++)
514
    {
515
	sprintf(name,SAVEGAMENAME"%d.dsg",i);
516
 
517
	handle = fopen (name, "r");
518
	if (handle == NULL)
519
	{
520
	    strcpy(&savegamestrings[i][0],EMPTYSTRING);
521
	    LoadMenu[i].status = 0;
522
	    continue;
523
	}
524
	count = fread (&savegamestrings[i], 1, SAVESTRINGSIZE, handle);
525
	fclose (handle);
526
	LoadMenu[i].status = 1;
527
    }
528
}
529
 
530
 
531
//
532
// M_LoadGame & Cie.
533
//
534
void M_DrawLoad(void)
535
{
536
    int             i;
537
 
538
    V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_LOADG",PU_CACHE));
539
    for (i = 0;i < load_end; i++)
540
    {
541
	M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
542
	M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
543
    }
544
}
545
 
546
 
547
 
548
//
549
// Draw border for the savegame description
550
//
551
void M_DrawSaveLoadBorder(int x,int y)
552
{
553
    int             i;
554
 
555
    V_DrawPatchDirect (x-8,y+7,0,W_CacheLumpName("M_LSLEFT",PU_CACHE));
556
 
557
    for (i = 0;i < 24;i++)
558
    {
559
	V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSCNTR",PU_CACHE));
560
	x += 8;
561
    }
562
 
563
    V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSRGHT",PU_CACHE));
564
}
565
 
566
 
567
 
568
//
569
// User wants to load this game
570
//
571
void M_LoadSelect(int choice)
572
{
573
    char    name[256];
574
 
575
    if (M_CheckParm("-cdrom"))
576
	sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",choice);
577
    else
578
	sprintf(name,SAVEGAMENAME"%d.dsg",choice);
579
    G_LoadGame (name);
580
    M_ClearMenus ();
581
}
582
 
583
//
584
// Selected from DOOM menu
585
//
586
void M_LoadGame (int choice)
587
{
588
    if (netgame)
589
    {
590
	M_StartMessage(LOADNET,NULL,false);
591
	return;
592
    }
593
 
594
    M_SetupNextMenu(&LoadDef);
595
    M_ReadSaveStrings();
596
}
597
 
598
 
599
//
600
//  M_SaveGame & Cie.
601
//
602
void M_DrawSave(void)
603
{
604
    int             i;
605
 
606
    V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_SAVEG",PU_CACHE));
607
    for (i = 0;i < load_end; i++)
608
    {
609
	M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
610
	M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
611
    }
612
 
613
    if (saveStringEnter)
614
    {
615
	i = M_StringWidth(savegamestrings[saveSlot]);
616
	M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_");
617
    }
618
}
619
 
620
//
621
// M_Responder calls this when user is finished
622
//
623
void M_DoSave(int slot)
624
{
625
    G_SaveGame (slot,savegamestrings[slot]);
626
    M_ClearMenus ();
627
 
628
    // PICK QUICKSAVE SLOT YET?
629
    if (quickSaveSlot == -2)
630
	quickSaveSlot = slot;
631
}
632
 
633
//
634
// User wants to save. Start string input for M_Responder
635
//
636
void M_SaveSelect(int choice)
637
{
638
    // we are going to be intercepting all chars
639
    saveStringEnter = 1;
640
 
641
    saveSlot = choice;
642
    strcpy(saveOldString,savegamestrings[choice]);
643
    if (!strcmp(savegamestrings[choice],EMPTYSTRING))
644
	savegamestrings[choice][0] = 0;
645
    saveCharIndex = strlen(savegamestrings[choice]);
646
}
647
 
648
//
649
// Selected from DOOM menu
650
//
651
void M_SaveGame (int choice)
652
{
653
    if (!usergame)
654
    {
655
	M_StartMessage(SAVEDEAD,NULL,false);
656
	return;
657
    }
658
 
659
    if (gamestate != GS_LEVEL)
660
	return;
661
 
662
    M_SetupNextMenu(&SaveDef);
663
    M_ReadSaveStrings();
664
}
665
 
666
 
667
 
668
//
669
//      M_QuickSave
670
//
671
char    tempstring[80];
672
 
673
void M_QuickSaveResponse(int ch)
674
{
675
    if (ch == 'y')
676
    {
677
	M_DoSave(quickSaveSlot);
678
	S_StartSound(NULL,sfx_swtchx);
679
    }
680
}
681
 
682
void M_QuickSave(void)
683
{
684
    if (!usergame)
685
    {
686
	S_StartSound(NULL,sfx_oof);
687
	return;
688
    }
689
 
690
    if (gamestate != GS_LEVEL)
691
	return;
692
 
693
    if (quickSaveSlot < 0)
694
    {
695
	M_StartControlPanel();
696
	M_ReadSaveStrings();
697
	M_SetupNextMenu(&SaveDef);
698
	quickSaveSlot = -2;	// means to pick a slot now
699
	return;
700
    }
701
    sprintf(tempstring,QSPROMPT,savegamestrings[quickSaveSlot]);
702
    M_StartMessage(tempstring,M_QuickSaveResponse,true);
703
}
704
 
705
 
706
 
707
//
708
// M_QuickLoad
709
//
710
void M_QuickLoadResponse(int ch)
711
{
712
    if (ch == 'y')
713
    {
714
	M_LoadSelect(quickSaveSlot);
715
	S_StartSound(NULL,sfx_swtchx);
716
    }
717
}
718
 
719
 
720
void M_QuickLoad(void)
721
{
722
    if (netgame)
723
    {
724
	M_StartMessage(QLOADNET,NULL,false);
725
	return;
726
    }
727
 
728
    if (quickSaveSlot < 0)
729
    {
730
	M_StartMessage(QSAVESPOT,NULL,false);
731
	return;
732
    }
733
    sprintf(tempstring,QLPROMPT,savegamestrings[quickSaveSlot]);
734
    M_StartMessage(tempstring,M_QuickLoadResponse,true);
735
}
736
 
737
 
738
 
739
 
740
//
741
// Read This Menus
742
// Had a "quick hack to fix romero bug"
743
//
744
void M_DrawReadThis1(void)
745
{
746
    inhelpscreens = true;
747
    switch ( gamemode )
748
    {
749
      case commercial:
750
	V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP",PU_CACHE));
751
	break;
752
      case shareware:
753
      case registered:
754
      case retail:
755
	V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP1",PU_CACHE));
756
	break;
757
      default:
758
	break;
759
    }
760
    return;
761
}
762
 
763
 
764
 
765
//
766
// Read This Menus - optional second page.
767
//
768
void M_DrawReadThis2(void)
769
{
770
    inhelpscreens = true;
771
    switch ( gamemode )
772
    {
773
      case retail:
774
      case commercial:
775
	// This hack keeps us from having to change menus.
776
	V_DrawPatchDirect (0,0,0,W_CacheLumpName("CREDIT",PU_CACHE));
777
	break;
778
      case shareware:
779
      case registered:
780
	V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP2",PU_CACHE));
781
	break;
782
      default:
783
	break;
784
    }
785
    return;
786
}
787
 
788
 
789
//
790
// Change Sfx & Music volumes
791
//
792
void M_DrawSound(void)
793
{
794
    V_DrawPatchDirect (60,38,0,W_CacheLumpName("M_SVOL",PU_CACHE));
795
 
796
    M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1),
797
		 16,snd_SfxVolume);
798
 
799
    M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1),
800
		 16,snd_MusicVolume);
801
}
802
 
803
void M_Sound(int choice)
804
{
805
    M_SetupNextMenu(&SoundDef);
806
}
807
 
808
void M_SfxVol(int choice)
809
{
810
    switch(choice)
811
    {
812
      case 0:
813
	if (snd_SfxVolume)
814
	    snd_SfxVolume--;
815
	break;
816
      case 1:
817
	if (snd_SfxVolume < 15)
818
	    snd_SfxVolume++;
819
	break;
820
    }
821
 
822
    S_SetSfxVolume(snd_SfxVolume /* *8 */);
823
}
824
 
825
void M_MusicVol(int choice)
826
{
827
    switch(choice)
828
    {
829
      case 0:
830
	if (snd_MusicVolume)
831
	    snd_MusicVolume--;
832
	break;
833
      case 1:
834
	if (snd_MusicVolume < 15)
835
	    snd_MusicVolume++;
836
	break;
837
    }
838
 
839
    S_SetMusicVolume(snd_MusicVolume /* *8 */);
840
}
841
 
842
 
843
 
844
 
845
//
846
// M_DrawMainMenu
847
//
848
void M_DrawMainMenu(void)
849
{
850
    V_DrawPatchDirect (94,2,0,W_CacheLumpName("M_DOOM",PU_CACHE));
851
}
852
 
853
 
854
 
855
 
856
//
857
// M_NewGame
858
//
859
void M_DrawNewGame(void)
860
{
861
    V_DrawPatchDirect (96,14,0,W_CacheLumpName("M_NEWG",PU_CACHE));
862
    V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_SKILL",PU_CACHE));
863
}
864
 
865
void M_NewGame(int choice)
866
{
867
    if (netgame && !demoplayback)
868
    {
869
	M_StartMessage(NEWGAME,NULL,false);
870
	return;
871
    }
872
 
873
    if ( gamemode == commercial )
874
	M_SetupNextMenu(&NewDef);
875
    else
876
	M_SetupNextMenu(&EpiDef);
877
}
878
 
879
 
880
//
881
//      M_Episode
882
//
883
int     epi;
884
 
885
void M_DrawEpisode(void)
886
{
887
    V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_EPISOD",PU_CACHE));
888
}
889
 
890
void M_VerifyNightmare(int ch)
891
{
892
    if (ch != 'y')
893
	return;
894
 
895
    G_DeferedInitNew(nightmare,epi+1,1);
896
    M_ClearMenus ();
897
}
898
 
899
void M_ChooseSkill(int choice)
900
{
901
    if (choice == nightmare)
902
    {
903
	M_StartMessage(NIGHTMARE,M_VerifyNightmare,true);
904
	return;
905
    }
906
 
907
    G_DeferedInitNew(choice,epi+1,1);
908
    M_ClearMenus ();
909
}
910
 
911
void M_Episode(int choice)
912
{
913
    if ( (gamemode == shareware)
914
	 && choice)
915
    {
916
	M_StartMessage(SWSTRING,NULL,false);
917
	M_SetupNextMenu(&ReadDef1);
918
	return;
919
    }
920
 
921
    // Yet another hack...
922
    if ( (gamemode == registered)
923
	 && (choice > 2))
924
    {
925
 //     __libclog_printf("M_Episode: 4th episode requires UltimateDOOM\n");
926
      choice = 0;
927
    }
928
 
929
    epi = choice;
930
    M_SetupNextMenu(&NewDef);
931
}
932
 
933
 
934
 
935
//
936
// M_Options
937
//
938
char    detailNames[2][9]	= {"M_GDHIGH","M_GDLOW"};
939
char	msgNames[2][9]		= {"M_MSGOFF","M_MSGON"};
940
 
941
 
942
void M_DrawOptions(void)
943
{
944
    V_DrawPatchDirect (108,15,0,W_CacheLumpName("M_OPTTTL",PU_CACHE));
945
 
946
    V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0,
947
		       W_CacheLumpName(detailNames[detailLevel],PU_CACHE));
948
 
949
    V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0,
950
		       W_CacheLumpName(msgNames[showMessages],PU_CACHE));
951
 
952
    M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(mousesens+1),
953
		 10,mouseSensitivity);
954
 
955
    M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1),
956
		 9,screenSize);
957
}
958
 
959
void M_Options(int choice)
960
{
961
    M_SetupNextMenu(&OptionsDef);
962
}
963
 
964
 
965
 
966
//
967
//      Toggle messages on/off
968
//
969
void M_ChangeMessages(int choice)
970
{
971
    // warning: unused parameter `int choice'
972
    choice = 0;
973
    showMessages = 1 - showMessages;
974
 
975
    if (!showMessages)
976
	players[consoleplayer].message = MSGOFF;
977
    else
978
	players[consoleplayer].message = MSGON ;
979
 
980
    message_dontfuckwithme = true;
981
}
982
 
983
 
984
//
985
// M_EndGame
986
//
987
void M_EndGameResponse(int ch)
988
{
989
    if (ch != 'y')
990
	return;
991
 
992
    currentMenu->lastOn = itemOn;
993
    M_ClearMenus ();
994
    D_StartTitle ();
995
}
996
 
997
void M_EndGame(int choice)
998
{
999
    choice = 0;
1000
    if (!usergame)
1001
    {
1002
	S_StartSound(NULL,sfx_oof);
1003
	return;
1004
    }
1005
 
1006
    if (netgame)
1007
    {
1008
	M_StartMessage(NETEND,NULL,false);
1009
	return;
1010
    }
1011
 
1012
    M_StartMessage(ENDGAME,M_EndGameResponse,true);
1013
}
1014
 
1015
 
1016
 
1017
 
1018
//
1019
// M_ReadThis
1020
//
1021
void M_ReadThis(int choice)
1022
{
1023
    choice = 0;
1024
    M_SetupNextMenu(&ReadDef1);
1025
}
1026
 
1027
void M_ReadThis2(int choice)
1028
{
1029
    choice = 0;
1030
    M_SetupNextMenu(&ReadDef2);
1031
}
1032
 
1033
void M_FinishReadThis(int choice)
1034
{
1035
    choice = 0;
1036
    M_SetupNextMenu(&MainDef);
1037
}
1038
 
1039
 
1040
 
1041
 
1042
//
1043
// M_QuitDOOM
1044
//
1045
int     quitsounds[8] =
1046
{
1047
    sfx_pldeth,
1048
    sfx_dmpain,
1049
    sfx_popain,
1050
    sfx_slop,
1051
    sfx_telept,
1052
    sfx_posit1,
1053
    sfx_posit3,
1054
    sfx_sgtatk
1055
};
1056
 
1057
int     quitsounds2[8] =
1058
{
1059
    sfx_vilact,
1060
    sfx_getpow,
1061
    sfx_boscub,
1062
    sfx_slop,
1063
    sfx_skeswg,
1064
    sfx_kntdth,
1065
    sfx_bspact,
1066
    sfx_sgtatk
1067
};
1068
 
1069
 
1070
 
1071
void M_QuitResponse(int ch)
1072
{
1073
    if (ch != 'y')
1074
	return;
1075
    if (!netgame)
1076
    {
1077
	if (gamemode == commercial)
1078
	    S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
1079
	else
1080
	    S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
1081
	I_WaitVBL(105);
1082
    }
1083
    I_Quit ();
1084
}
1085
 
1086
 
1087
 
1088
 
1089
void M_QuitDOOM(int choice)
1090
{
1091
  // We pick index 0 which is language sensitive,
1092
  //  or one at random, between 1 and maximum number.
1093
  if (language != english )
1094
    sprintf(endstring,"%s\n\n"DOSY, endmsg[0] );
1095
  else
1096
    sprintf(endstring,"%s\n\n"DOSY, endmsg[ (gametic%(NUM_QUITMESSAGES-2))+1 ]);
1097
 
1098
  M_StartMessage(endstring,M_QuitResponse,true);
1099
}
1100
 
1101
 
1102
 
1103
void M_ChangeSensitivity(int choice)
1104
{
1105
    switch(choice)
1106
    {
1107
      case 0:
1108
	if (mouseSensitivity)
1109
	    mouseSensitivity--;
1110
	break;
1111
      case 1:
1112
	if (mouseSensitivity < 9)
1113
	    mouseSensitivity++;
1114
	break;
1115
    }
1116
}
1117
 
1118
 
1119
 
1120
 
1121
void M_ChangeDetail(int choice)
1122
{
1123
    choice = 0;
1124
    detailLevel = 1 - detailLevel;
1125
 
1126
    // FIXME - does not work. Remove anyway?
1127
//    __libclog_printf("M_ChangeDetail: low detail mode n.a.\n");
1128
 
1129
    return;
1130
 
1131
    /*R_SetViewSize (screenblocks, detailLevel);
1132
 
1133
    if (!detailLevel)
1134
	players[consoleplayer].message = DETAILHI;
1135
    else
1136
	players[consoleplayer].message = DETAILLO;*/
1137
}
1138
 
1139
 
1140
 
1141
 
1142
void M_SizeDisplay(int choice)
1143
{
1144
    switch(choice)
1145
    {
1146
      case 0:
1147
	if (screenSize > 0)
1148
	{
1149
	    screenblocks--;
1150
	    screenSize--;
1151
	}
1152
	break;
1153
      case 1:
1154
	if (screenSize < 8)
1155
	{
1156
	    screenblocks++;
1157
	    screenSize++;
1158
	}
1159
	break;
1160
    }
1161
 
1162
 
1163
    R_SetViewSize (screenblocks, detailLevel);
1164
}
1165
 
1166
 
1167
 
1168
 
1169
//
1170
//      Menu Functions
1171
//
1172
void
1173
M_DrawThermo
1174
( int	x,
1175
  int	y,
1176
  int	thermWidth,
1177
  int	thermDot )
1178
{
1179
    int		xx;
1180
    int		i;
1181
 
1182
    xx = x;
1183
    V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERML",PU_CACHE));
1184
    xx += 8;
1185
    for (i=0;i
1186
    {
1187
	V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMM",PU_CACHE));
1188
	xx += 8;
1189
    }
1190
    V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERMR",PU_CACHE));
1191
 
1192
    V_DrawPatchDirect ((x+8) + thermDot*8,y,
1193
		       0,W_CacheLumpName("M_THERMO",PU_CACHE));
1194
}
1195
 
1196
 
1197
 
1198
void
1199
M_DrawEmptyCell
1200
( menu_t*	menu,
1201
  int		item )
1202
{
1203
    V_DrawPatchDirect (menu->x - 10,        menu->y+item*LINEHEIGHT - 1, 0,
1204
		       W_CacheLumpName("M_CELL1",PU_CACHE));
1205
}
1206
 
1207
void
1208
M_DrawSelCell
1209
( menu_t*	menu,
1210
  int		item )
1211
{
1212
    V_DrawPatchDirect (menu->x - 10,        menu->y+item*LINEHEIGHT - 1, 0,
1213
		       W_CacheLumpName("M_CELL2",PU_CACHE));
1214
}
1215
 
1216
 
1217
void
1218
M_StartMessage
1219
( char*		string,
1220
  void*		routine,
1221
  boolean	input )
1222
{
1223
    messageLastMenuActive = menuactive;
1224
    messageToPrint = 1;
1225
    messageString = string;
1226
    messageRoutine = routine;
1227
    messageNeedsInput = input;
1228
    menuactive = true;
1229
    return;
1230
}
1231
 
1232
 
1233
 
1234
void M_StopMessage(void)
1235
{
1236
    menuactive = messageLastMenuActive;
1237
    messageToPrint = 0;
1238
}
1239
 
1240
 
1241
 
1242
//
1243
// Find string width from hu_font chars
1244
//
1245
int M_StringWidth(char* string)
1246
{
1247
    int             i;
1248
    int             w = 0;
1249
    int             c;
1250
 
1251
    for (i = 0;i < strlen(string);i++)
1252
    {
1253
	c = toupper(string[i]) - HU_FONTSTART;
1254
	if (c < 0 || c >= HU_FONTSIZE)
1255
	    w += 4;
1256
	else
1257
	    w += SHORT (hu_font[c]->width);
1258
    }
1259
 
1260
    return w;
1261
}
1262
 
1263
 
1264
 
1265
//
1266
//      Find string height from hu_font chars
1267
//
1268
int M_StringHeight(char* string)
1269
{
1270
    int             i;
1271
    int             h;
1272
    int             height = SHORT(hu_font[0]->height);
1273
 
1274
    h = height;
1275
    for (i = 0;i < strlen(string);i++)
1276
	if (string[i] == '\n')
1277
	    h += height;
1278
 
1279
    return h;
1280
}
1281
 
1282
 
1283
//
1284
//      Write a string using the hu_font
1285
//
1286
void
1287
M_WriteText
1288
( int		x,
1289
  int		y,
1290
  char*		string)
1291
{
1292
    int		w;
1293
    char*	ch;
1294
    int		c;
1295
    int		cx;
1296
    int		cy;
1297
 
1298
 
1299
    ch = string;
1300
    cx = x;
1301
    cy = y;
1302
 
1303
    while(1)
1304
    {
1305
	c = *ch++;
1306
	if (!c)
1307
	    break;
1308
	if (c == '\n')
1309
	{
1310
	    cx = x;
1311
	    cy += 12;
1312
	    continue;
1313
	}
1314
 
1315
	c = toupper(c) - HU_FONTSTART;
1316
	if (c < 0 || c>= HU_FONTSIZE)
1317
	{
1318
	    cx += 4;
1319
	    continue;
1320
	}
1321
 
1322
	w = SHORT (hu_font[c]->width);
1323
	if (cx+w > SCREENWIDTH)
1324
	    break;
1325
	V_DrawPatchDirect(cx, cy, 0, hu_font[c]);
1326
	cx+=w;
1327
    }
1328
}
1329
 
1330
 
1331
 
1332
//
1333
// CONTROL PANEL
1334
//
1335
 
1336
//
1337
// M_Responder
1338
//
1339
boolean M_Responder (event_t* ev)
1340
{
1341
    int             ch;
1342
    int             i;
1343
    static  int     joywait = 0;
1344
    static  int     mousewait = 0;
1345
    static  int     mousey = 0;
1346
    static  int     lasty = 0;
1347
    static  int     mousex = 0;
1348
    static  int     lastx = 0;
1349
 
1350
    ch = -1;
1351
 
1352
    if (ev->type == ev_joystick && joywait < I_GetTime())
1353
    {
1354
	if (ev->data3 == -1)
1355
	{
1356
	    ch = KEY_UPARROW;
1357
	    joywait = I_GetTime() + 5;
1358
	}
1359
	else if (ev->data3 == 1)
1360
	{
1361
	    ch = KEY_DOWNARROW;
1362
	    joywait = I_GetTime() + 5;
1363
	}
1364
 
1365
	if (ev->data2 == -1)
1366
	{
1367
	    ch = KEY_LEFTARROW;
1368
	    joywait = I_GetTime() + 2;
1369
	}
1370
	else if (ev->data2 == 1)
1371
	{
1372
	    ch = KEY_RIGHTARROW;
1373
	    joywait = I_GetTime() + 2;
1374
	}
1375
 
1376
	if (ev->data1&1)
1377
	{
1378
	    ch = KEY_ENTER;
1379
	    joywait = I_GetTime() + 5;
1380
	}
1381
	if (ev->data1&2)
1382
	{
1383
	    ch = KEY_BACKSPACE;
1384
	    joywait = I_GetTime() + 5;
1385
	}
1386
    }
1387
    else
1388
    {
1389
	if (ev->type == ev_mouse && mousewait < I_GetTime())
1390
	{
1391
	    mousey += ev->data3;
1392
	    if (mousey < lasty-30)
1393
	    {
1394
		ch = KEY_DOWNARROW;
1395
		mousewait = I_GetTime() + 5;
1396
		mousey = lasty -= 30;
1397
	    }
1398
	    else if (mousey > lasty+30)
1399
	    {
1400
		ch = KEY_UPARROW;
1401
		mousewait = I_GetTime() + 5;
1402
		mousey = lasty += 30;
1403
	    }
1404
 
1405
	    mousex += ev->data2;
1406
	    if (mousex < lastx-30)
1407
	    {
1408
		ch = KEY_LEFTARROW;
1409
		mousewait = I_GetTime() + 5;
1410
		mousex = lastx -= 30;
1411
	    }
1412
	    else if (mousex > lastx+30)
1413
	    {
1414
		ch = KEY_RIGHTARROW;
1415
		mousewait = I_GetTime() + 5;
1416
		mousex = lastx += 30;
1417
	    }
1418
 
1419
	    if (ev->data1&1)
1420
	    {
1421
		ch = KEY_ENTER;
1422
		mousewait = I_GetTime() + 15;
1423
	    }
1424
 
1425
	    if (ev->data1&2)
1426
	    {
1427
		ch = KEY_BACKSPACE;
1428
		mousewait = I_GetTime() + 15;
1429
	    }
1430
	}
1431
	else
1432
	    if (ev->type == ev_keydown)
1433
	    {
1434
		ch = ev->data1;
1435
	    }
1436
    }
1437
 
1438
    if (ch == -1)
1439
	return false;
1440
 
1441
 
1442
    // Save Game string input
1443
    if (saveStringEnter)
1444
    {
1445
	switch(ch)
1446
	{
1447
	  case KEY_BACKSPACE:
1448
	    if (saveCharIndex > 0)
1449
	    {
1450
		saveCharIndex--;
1451
		savegamestrings[saveSlot][saveCharIndex] = 0;
1452
	    }
1453
	    break;
1454
 
1455
	  case KEY_ESCAPE:
1456
	    saveStringEnter = 0;
1457
	    strcpy(&savegamestrings[saveSlot][0],saveOldString);
1458
	    break;
1459
 
1460
	  case KEY_ENTER:
1461
	    saveStringEnter = 0;
1462
	    if (savegamestrings[saveSlot][0])
1463
		M_DoSave(saveSlot);
1464
	    break;
1465
 
1466
	  default:
1467
	    ch = toupper(ch);
1468
	    if (ch != 32)
1469
		if (ch-HU_FONTSTART < 0 || ch-HU_FONTSTART >= HU_FONTSIZE)
1470
		    break;
1471
	    if (ch >= 32 && ch <= 127 &&
1472
		saveCharIndex < SAVESTRINGSIZE-1 &&
1473
		M_StringWidth(savegamestrings[saveSlot]) <
1474
		(SAVESTRINGSIZE-2)*8)
1475
	    {
1476
		savegamestrings[saveSlot][saveCharIndex++] = ch;
1477
		savegamestrings[saveSlot][saveCharIndex] = 0;
1478
	    }
1479
	    break;
1480
	}
1481
	return true;
1482
    }
1483
 
1484
    // Take care of any messages that need input
1485
    if (messageToPrint)
1486
    {
1487
	if (messageNeedsInput == true &&
1488
	    !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE))
1489
	    return false;
1490
 
1491
	menuactive = messageLastMenuActive;
1492
	messageToPrint = 0;
1493
	if (messageRoutine)
1494
	    messageRoutine(ch);
1495
 
1496
	menuactive = false;
1497
	S_StartSound(NULL,sfx_swtchx);
1498
	return true;
1499
    }
1500
 
1501
    if (devparm && ch == KEY_F1)
1502
    {
1503
	G_ScreenShot ();
1504
	return true;
1505
    }
1506
 
1507
 
1508
    // F-Keys
1509
    if (!menuactive)
1510
	switch(ch)
1511
	{
1512
	  case KEY_MINUS:         // Screen size down
1513
	    if (automapactive || chat_on)
1514
		return false;
1515
	    M_SizeDisplay(0);
1516
	    S_StartSound(NULL,sfx_stnmov);
1517
	    return true;
1518
 
1519
	  case KEY_EQUALS:        // Screen size up
1520
	    if (automapactive || chat_on)
1521
		return false;
1522
	    M_SizeDisplay(1);
1523
	    S_StartSound(NULL,sfx_stnmov);
1524
	    return true;
1525
 
1526
	  case KEY_F1:            // Help key
1527
	    M_StartControlPanel ();
1528
 
1529
	    if ( gamemode == retail )
1530
	      currentMenu = &ReadDef2;
1531
	    else
1532
	      currentMenu = &ReadDef1;
1533
 
1534
	    itemOn = 0;
1535
	    S_StartSound(NULL,sfx_swtchn);
1536
	    return true;
1537
 
1538
	  case KEY_F2:            // Save
1539
	    M_StartControlPanel();
1540
	    S_StartSound(NULL,sfx_swtchn);
1541
	    M_SaveGame(0);
1542
	    return true;
1543
 
1544
	  case KEY_F3:            // Load
1545
	    M_StartControlPanel();
1546
	    S_StartSound(NULL,sfx_swtchn);
1547
	    M_LoadGame(0);
1548
	    return true;
1549
 
1550
	  case KEY_F4:            // Sound Volume
1551
	    M_StartControlPanel ();
1552
	    currentMenu = &SoundDef;
1553
	    itemOn = sfx_vol;
1554
	    S_StartSound(NULL,sfx_swtchn);
1555
	    return true;
1556
 
1557
	  case KEY_F5:            // Detail toggle
1558
	    M_ChangeDetail(0);
1559
	    S_StartSound(NULL,sfx_swtchn);
1560
	    return true;
1561
 
1562
	  case KEY_F6:            // Quicksave
1563
	    S_StartSound(NULL,sfx_swtchn);
1564
	    M_QuickSave();
1565
	    return true;
1566
 
1567
	  case KEY_F7:            // End game
1568
	    S_StartSound(NULL,sfx_swtchn);
1569
	    M_EndGame(0);
1570
	    return true;
1571
 
1572
	  case KEY_F8:            // Toggle messages
1573
	    M_ChangeMessages(0);
1574
	    S_StartSound(NULL,sfx_swtchn);
1575
	    return true;
1576
 
1577
	  case KEY_F9:            // Quickload
1578
	    S_StartSound(NULL,sfx_swtchn);
1579
	    M_QuickLoad();
1580
	    return true;
1581
 
1582
	  case KEY_F10:           // Quit DOOM
1583
	    S_StartSound(NULL,sfx_swtchn);
1584
	    M_QuitDOOM(0);
1585
	    return true;
1586
 
1587
	  case KEY_F11:           // gamma toggle
1588
	    usegamma++;
1589
	    if (usegamma > 4)
1590
		usegamma = 0;
1591
	    players[consoleplayer].message = gammamsg[usegamma];
1592
	    I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE));
1593
	    return true;
1594
 
1595
	}
1596
 
1597
 
1598
    // Pop-up menu?
1599
    if (!menuactive)
1600
    {
1601
	if (ch == KEY_ESCAPE)
1602
	{
1603
	    M_StartControlPanel ();
1604
	    S_StartSound(NULL,sfx_swtchn);
1605
	    return true;
1606
	}
1607
	return false;
1608
    }
1609
 
1610
 
1611
    // Keys usable within menu
1612
    switch (ch)
1613
    {
1614
      case KEY_DOWNARROW:
1615
	do
1616
	{
1617
	    if (itemOn+1 > currentMenu->numitems-1)
1618
		itemOn = 0;
1619
	    else itemOn++;
1620
	    S_StartSound(NULL,sfx_pstop);
1621
	} while(currentMenu->menuitems[itemOn].status==-1);
1622
	return true;
1623
 
1624
      case KEY_UPARROW:
1625
	do
1626
	{
1627
	    if (!itemOn)
1628
		itemOn = currentMenu->numitems-1;
1629
	    else itemOn--;
1630
	    S_StartSound(NULL,sfx_pstop);
1631
	} while(currentMenu->menuitems[itemOn].status==-1);
1632
	return true;
1633
 
1634
      case KEY_LEFTARROW:
1635
	if (currentMenu->menuitems[itemOn].routine &&
1636
	    currentMenu->menuitems[itemOn].status == 2)
1637
	{
1638
	    S_StartSound(NULL,sfx_stnmov);
1639
	    currentMenu->menuitems[itemOn].routine(0);
1640
	}
1641
	return true;
1642
 
1643
      case KEY_RIGHTARROW:
1644
	if (currentMenu->menuitems[itemOn].routine &&
1645
	    currentMenu->menuitems[itemOn].status == 2)
1646
	{
1647
	    S_StartSound(NULL,sfx_stnmov);
1648
	    currentMenu->menuitems[itemOn].routine(1);
1649
	}
1650
	return true;
1651
 
1652
      case KEY_ENTER:
1653
	if (currentMenu->menuitems[itemOn].routine &&
1654
	    currentMenu->menuitems[itemOn].status)
1655
	{
1656
	    currentMenu->lastOn = itemOn;
1657
	    if (currentMenu->menuitems[itemOn].status == 2)
1658
	    {
1659
		currentMenu->menuitems[itemOn].routine(1);      // right arrow
1660
		S_StartSound(NULL,sfx_stnmov);
1661
	    }
1662
	    else
1663
	    {
1664
		currentMenu->menuitems[itemOn].routine(itemOn);
1665
		S_StartSound(NULL,sfx_pistol);
1666
	    }
1667
	}
1668
	return true;
1669
 
1670
      case KEY_ESCAPE:
1671
	currentMenu->lastOn = itemOn;
1672
	M_ClearMenus ();
1673
	S_StartSound(NULL,sfx_swtchx);
1674
	return true;
1675
 
1676
      case KEY_BACKSPACE:
1677
	currentMenu->lastOn = itemOn;
1678
	if (currentMenu->prevMenu)
1679
	{
1680
	    currentMenu = currentMenu->prevMenu;
1681
	    itemOn = currentMenu->lastOn;
1682
	    S_StartSound(NULL,sfx_swtchn);
1683
	}
1684
	return true;
1685
 
1686
      default:
1687
	for (i = itemOn+1;i < currentMenu->numitems;i++)
1688
	    if (currentMenu->menuitems[i].alphaKey == ch)
1689
	    {
1690
		itemOn = i;
1691
		S_StartSound(NULL,sfx_pstop);
1692
		return true;
1693
	    }
1694
	for (i = 0;i <= itemOn;i++)
1695
	    if (currentMenu->menuitems[i].alphaKey == ch)
1696
	    {
1697
		itemOn = i;
1698
		S_StartSound(NULL,sfx_pstop);
1699
		return true;
1700
	    }
1701
	break;
1702
 
1703
    }
1704
 
1705
    return false;
1706
}
1707
 
1708
 
1709
 
1710
//
1711
// M_StartControlPanel
1712
//
1713
void M_StartControlPanel (void)
1714
{
1715
    // intro might call this repeatedly
1716
    if (menuactive)
1717
	return;
1718
 
1719
    menuactive = 1;
1720
    currentMenu = &MainDef;         // JDC
1721
    itemOn = currentMenu->lastOn;   // JDC
1722
}
1723
 
1724
 
1725
//
1726
// M_Drawer
1727
// Called after the view has been rendered,
1728
// but before it has been blitted.
1729
//
1730
void M_Drawer (void)
1731
{
1732
    static short	x;
1733
    static short	y;
1734
    short		i;
1735
    short		max;
300 serge 1736
    char *p;
1737
    int len;
298 serge 1738
    char		string[40];
1739
    int			start;
1740
 
1741
    inhelpscreens = false;
1742
 
1743
    // Horiz. & Vertically center string and print it.
1744
    if (messageToPrint)
1745
    {
300 serge 1746
	  y = 100 - M_StringHeight(messageString)/2;
1747
	  p = messageString;
1748
	  len = strlen(p);
1749
	  while(*p)
1750
	  {
1751
        for (i = 0;len;i++,len--)
1752
        {
1753
 	      if (*(p+i) == '\n')
1754
		  { memset(string,0,40);
1755
		    strncpy(string,p,i);
1756
		    p+= i+1;
1757
		    len-= 1;
298 serge 1758
		    break;
300 serge 1759
		  };
1760
	    };
1761
 
1762
        if (len == 0)
1763
        { strncpy(string,p,i);
1764
          p+=i;
1765
        };
1766
        x = 160 - M_StringWidth(string)/2;
1767
        M_WriteText(x,y,string);
1768
        y += SHORT(hu_font[0]->height);
1769
	  };
1770
	  return;
1771
    };
298 serge 1772
 
1773
    if (!menuactive)
1774
	return;
1775
 
1776
    if (currentMenu->routine)
1777
	currentMenu->routine();         // call Draw routine
1778
 
1779
    // DRAW MENU
1780
    x = currentMenu->x;
1781
    y = currentMenu->y;
1782
    max = currentMenu->numitems;
1783
 
1784
    for (i=0;i
1785
    {
1786
	if (currentMenu->menuitems[i].name[0])
1787
	    V_DrawPatchDirect (x,y,0,
1788
			       W_CacheLumpName(currentMenu->menuitems[i].name ,PU_CACHE));
1789
	y += LINEHEIGHT;
1790
    }
1791
 
1792
 
1793
    // DRAW SKULL
1794
    V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0,
1795
		      W_CacheLumpName(skullName[whichSkull],PU_CACHE));
1796
 
1797
}
1798
 
1799
 
1800
//
1801
// M_ClearMenus
1802
//
1803
void M_ClearMenus (void)
1804
{
1805
    menuactive = 0;
1806
    // if (!netgame && usergame && paused)
1807
    //       sendpause = true;
1808
}
1809
 
1810
 
1811
 
1812
 
1813
//
1814
// M_SetupNextMenu
1815
//
1816
void M_SetupNextMenu(menu_t *menudef)
1817
{
1818
    currentMenu = menudef;
1819
    itemOn = currentMenu->lastOn;
1820
}
1821
 
1822
 
1823
//
1824
// M_Ticker
1825
//
1826
void M_Ticker (void)
1827
{
1828
    if (--skullAnimCounter <= 0)
1829
    {
1830
	whichSkull ^= 1;
1831
	skullAnimCounter = 8;
1832
    }
1833
}
1834
 
1835
 
1836
//
1837
// M_Init
1838
//
1839
void M_Init (void)
1840
{
1841
    currentMenu = &MainDef;
1842
    menuactive = 0;
1843
    itemOn = currentMenu->lastOn;
1844
    whichSkull = 0;
1845
    skullAnimCounter = 10;
1846
    screenSize = screenblocks - 3;
1847
    messageToPrint = 0;
1848
    messageString = NULL;
1849
    messageLastMenuActive = menuactive;
1850
    quickSaveSlot = -1;
1851
 
1852
    // Here we could catch other version dependencies,
1853
    //  like HELP1/2, and four episodes.
1854
 
1855
 
1856
    switch ( gamemode )
1857
    {
1858
      case commercial:
1859
	// This is used because DOOM 2 had only one HELP
1860
        //  page. I use CREDIT as second page now, but
1861
	//  kept this hack for educational purposes.
1862
	MainMenu[readthis] = MainMenu[quitdoom];
1863
	MainDef.numitems--;
1864
	MainDef.y += 8;
1865
	NewDef.prevMenu = &MainDef;
1866
	ReadDef1.routine = M_DrawReadThis1;
1867
	ReadDef1.x = 330;
1868
	ReadDef1.y = 165;
1869
	ReadMenu1[0].routine = M_FinishReadThis;
1870
	break;
1871
      case shareware:
1872
	// Episode 2 and 3 are handled,
1873
	//  branching to an ad screen.
1874
      case registered:
1875
	// We need to remove the fourth episode.
1876
	EpiDef.numitems--;
1877
	break;
1878
      case retail:
1879
	// We are fine.
1880
      default:
1881
	break;
1882
    }
1883
 
1884
}
1885