Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
8557 maxcodehac 1
// WL_MAIN.C
2
 
3
#ifdef _WIN32
4
    #include 
5
#else
6
    #include 
7
#endif
8
 
9
#include "wl_def.h"
10
#pragma hdrstop
11
#include "wl_atmos.h"
12
#include 
13
 
14
/*
15
=============================================================================
16
 
17
                             WOLFENSTEIN 3-D
18
 
19
                        An Id Software production
20
 
21
                             by John Carmack
22
 
23
=============================================================================
24
*/
25
 
26
extern byte signon[];
8596 turbocat 27
extern void kolibri_set_win_center();
8664 turbocat 28
extern char* dirname(char* path);
29
extern void setcwd(char* path);
9097 turbocat 30
extern "C"{
31
    extern void uSDL_StartTicks(void);
32
}
8557 maxcodehac 33
/*
34
=============================================================================
35
 
36
                             LOCAL CONSTANTS
37
 
38
=============================================================================
39
*/
40
 
41
 
42
#define FOCALLENGTH     (0x5700l)               // in global coordinates
43
#define VIEWGLOBAL      0x10000                 // globals visable flush to wall
44
 
45
#define VIEWWIDTH       256                     // size of view window
46
#define VIEWHEIGHT      144
47
 
48
/*
49
=============================================================================
50
 
51
                            GLOBAL VARIABLES
52
 
53
=============================================================================
54
*/
55
 
56
char    str[80];
57
int     dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8,
58
                       5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES};
59
 
60
//
61
// proejection variables
62
//
63
fixed    focallength;
64
unsigned screenofs;
65
int      viewscreenx, viewscreeny;
66
int      viewwidth;
67
int      viewheight;
68
short    centerx;
69
int      shootdelta;           // pixels away from centerx a target can be
70
fixed    scale;
71
int32_t  heightnumerator;
72
 
73
 
74
void    Quit (const char *error,...);
75
 
76
boolean startgame;
77
boolean loadedgame;
78
int     mouseadjustment;
79
 
80
char    configdir[256] = "";
81
char    configname[13] = "config.";
82
 
83
//
84
// Command line parameter variables
85
//
86
boolean param_debugmode = false;
87
boolean param_nowait = false;
88
int     param_difficulty = 1;           // default is "normal"
89
int     param_tedlevel = -1;            // default is not to start a level
90
int     param_joystickindex = 0;
91
 
92
#if defined(_arch_dreamcast)
93
int     param_joystickhat = 0;
94
int     param_samplerate = 11025;       // higher samplerates result in "out of memory"
95
int     param_audiobuffer = 4096 / (44100 / param_samplerate);
96
#elif defined(GP2X_940)
97
int     param_joystickhat = -1;
98
int     param_samplerate = 11025;       // higher samplerates result in "out of memory"
99
int     param_audiobuffer = 128;
100
#else
101
int     param_joystickhat = -1;
102
int     param_samplerate = 44100;
103
int     param_audiobuffer = 2048 / (44100 / param_samplerate);
104
#endif
105
 
106
int     param_mission = 0;
107
boolean param_goodtimes = false;
108
boolean param_ignorenumchunks = false;
109
 
110
/*
111
=============================================================================
112
 
113
                            LOCAL VARIABLES
114
 
115
=============================================================================
116
*/
117
 
118
 
119
/*
120
====================
121
=
122
= ReadConfig
123
=
124
====================
125
*/
126
 
127
void ReadConfig(void)
128
{
129
    SDMode  sd;
130
    SMMode  sm;
131
    SDSMode sds;
132
 
133
    char configpath[300];
134
 
135
#ifdef _arch_dreamcast
136
    DC_LoadFromVMU(configname);
137
#endif
138
 
139
    if(configdir[0])
140
        snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
141
    else
142
        strcpy(configpath, configname);
143
 
144
    const int file = open(configpath, O_RDONLY | O_BINARY);
145
    if (file != -1)
146
    {
147
        //
148
        // valid config file
149
        //
150
        word tmp;
151
        read(file,&tmp,sizeof(tmp));
152
        if(tmp!=0xfefa)
153
        {
154
            close(file);
155
            goto noconfig;
156
        }
157
        read(file,Scores,sizeof(HighScore) * MaxScores);
158
 
159
        read(file,&sd,sizeof(sd));
160
        read(file,&sm,sizeof(sm));
161
        read(file,&sds,sizeof(sds));
162
 
163
        read(file,&mouseenabled,sizeof(mouseenabled));
164
        read(file,&joystickenabled,sizeof(joystickenabled));
165
        boolean dummyJoypadEnabled;
166
        read(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
167
        boolean dummyJoystickProgressive;
168
        read(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
169
        int dummyJoystickPort = 0;
170
        read(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
171
 
172
        read(file,dirscan,sizeof(dirscan));
173
        read(file,buttonscan,sizeof(buttonscan));
174
        read(file,buttonmouse,sizeof(buttonmouse));
175
        read(file,buttonjoy,sizeof(buttonjoy));
176
 
177
        read(file,&viewsize,sizeof(viewsize));
178
        read(file,&mouseadjustment,sizeof(mouseadjustment));
179
 
180
        close(file);
181
 
182
        if ((sd == sdm_AdLib || sm == smm_AdLib) && !AdLibPresent
183
                && !SoundBlasterPresent)
184
        {
185
            sd = sdm_PC;
186
            sm = smm_Off;
187
        }
188
 
189
        if ((sds == sds_SoundBlaster && !SoundBlasterPresent))
190
            sds = sds_Off;
191
 
192
        // make sure values are correct
193
 
194
        if(mouseenabled) mouseenabled=true;
195
        if(joystickenabled) joystickenabled=true;
196
 
197
        if (!MousePresent)
198
            mouseenabled = false;
199
        if (!IN_JoyPresent())
200
            joystickenabled = false;
201
 
202
        if(mouseadjustment<0) mouseadjustment=0;
203
        else if(mouseadjustment>9) mouseadjustment=9;
204
 
205
        if(viewsize<4) viewsize=4;
206
        else if(viewsize>21) viewsize=21;
207
 
208
        MainMenu[6].active=1;
209
        MainItems.curpos=0;
210
    }
211
    else
212
    {
213
        //
214
        // no config file, so select by hardware
215
        //
216
noconfig:
217
        if (SoundBlasterPresent || AdLibPresent)
218
        {
219
            sd = sdm_AdLib;
220
            sm = smm_AdLib;
221
        }
222
        else
223
        {
224
            sd = sdm_PC;
225
            sm = smm_Off;
226
        }
227
 
228
        if (SoundBlasterPresent)
229
            sds = sds_SoundBlaster;
230
        else
231
            sds = sds_Off;
232
 
233
        if (MousePresent)
234
            mouseenabled = true;
235
 
236
        if (IN_JoyPresent())
237
            joystickenabled = true;
238
 
239
        viewsize = 19;                          // start with a good size
240
        mouseadjustment=5;
241
    }
242
 
243
    SD_SetMusicMode (sm);
244
    SD_SetSoundMode (sd);
245
    SD_SetDigiDevice (sds);
246
}
247
 
248
/*
249
====================
250
=
251
= WriteConfig
252
=
253
====================
254
*/
255
 
256
void WriteConfig(void)
257
{
258
    char configpath[300];
259
 
260
#ifdef _arch_dreamcast
261
    fs_unlink(configname);
262
#endif
263
 
264
    if(configdir[0])
265
        snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
266
    else
267
        strcpy(configpath, configname);
268
 
269
    const int file = open(configpath, O_CREAT | O_WRONLY | O_BINARY, 0644);
270
    if (file != -1)
271
    {
272
        word tmp=0xfefa;
273
        write(file,&tmp,sizeof(tmp));
274
        write(file,Scores,sizeof(HighScore) * MaxScores);
275
 
276
        write(file,&SoundMode,sizeof(SoundMode));
277
        write(file,&MusicMode,sizeof(MusicMode));
278
        write(file,&DigiMode,sizeof(DigiMode));
279
 
280
        write(file,&mouseenabled,sizeof(mouseenabled));
281
        write(file,&joystickenabled,sizeof(joystickenabled));
282
        boolean dummyJoypadEnabled = false;
283
        write(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
284
        boolean dummyJoystickProgressive = false;
285
        write(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
286
        int dummyJoystickPort = 0;
287
        write(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
288
 
289
        write(file,dirscan,sizeof(dirscan));
290
        write(file,buttonscan,sizeof(buttonscan));
291
        write(file,buttonmouse,sizeof(buttonmouse));
292
        write(file,buttonjoy,sizeof(buttonjoy));
293
 
294
        write(file,&viewsize,sizeof(viewsize));
295
        write(file,&mouseadjustment,sizeof(mouseadjustment));
296
 
297
        close(file);
298
    }
299
#ifdef _arch_dreamcast
300
    DC_SaveToVMU(configname, NULL);
301
#endif
302
}
303
 
304
 
305
//===========================================================================
306
 
307
/*
308
=====================
309
=
310
= NewGame
311
=
312
= Set up new game to start from the beginning
313
=
314
=====================
315
*/
316
 
317
void NewGame (int difficulty,int episode)
318
{
319
    memset (&gamestate,0,sizeof(gamestate));
320
    gamestate.difficulty = difficulty;
321
    gamestate.weapon = gamestate.bestweapon
322
            = gamestate.chosenweapon = wp_pistol;
323
    gamestate.health = 100;
324
    gamestate.ammo = STARTAMMO;
325
    gamestate.lives = 3;
326
    gamestate.nextextra = EXTRAPOINTS;
327
    gamestate.episode=episode;
328
 
329
    startgame = true;
330
}
331
 
332
//===========================================================================
333
 
334
void DiskFlopAnim(int x,int y)
335
{
336
    static int8_t which=0;
337
    if (!x && !y)
338
        return;
339
    VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);
340
    VW_UpdateScreen();
341
    which^=1;
342
}
343
 
344
 
345
int32_t DoChecksum(byte *source,unsigned size,int32_t checksum)
346
{
347
    unsigned i;
348
 
349
    for (i=0;i
350
    checksum += source[i]^source[i+1];
351
 
352
    return checksum;
353
}
354
 
355
 
356
/*
357
==================
358
=
359
= SaveTheGame
360
=
361
==================
362
*/
363
 
364
extern statetype s_grdstand;
365
extern statetype s_player;
366
 
367
boolean SaveTheGame(FILE *file,int x,int y)
368
{
369
//    struct diskfree_t dfree;
370
//    int32_t avail,size,checksum;
371
    int checksum;
372
    objtype *ob;
373
    objtype nullobj;
374
    statobj_t nullstat;
375
 
376
/*    if (_dos_getdiskfree(0,&dfree))
377
        Quit("Error in _dos_getdiskfree call");
378
 
379
    avail = (int32_t)dfree.avail_clusters *
380
                  dfree.bytes_per_sector *
381
                  dfree.sectors_per_cluster;
382
 
383
    size = 0;
384
    for (ob = player; ob ; ob=ob->next)
385
        size += sizeof(*ob);
386
    size += sizeof(nullobj);
387
 
388
    size += sizeof(gamestate) +
389
            sizeof(LRstruct)*LRpack +
390
            sizeof(tilemap) +
391
            sizeof(actorat) +
392
            sizeof(laststatobj) +
393
            sizeof(statobjlist) +
394
            sizeof(doorposition) +
395
            sizeof(pwallstate) +
396
            sizeof(pwalltile) +
397
            sizeof(pwallx) +
398
            sizeof(pwally) +
399
            sizeof(pwalldir) +
400
            sizeof(pwallpos);
401
 
402
    if (avail < size)
403
    {
404
        Message(STR_NOSPACE1"\n"STR_NOSPACE2);
405
        return false;
406
    }*/
407
 
408
    checksum = 0;
409
 
410
    DiskFlopAnim(x,y);
411
    fwrite(&gamestate,sizeof(gamestate),1,file);
412
    checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
413
 
414
    DiskFlopAnim(x,y);
415
    fwrite(&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
416
    checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
417
 
418
    DiskFlopAnim(x,y);
419
    fwrite(tilemap,sizeof(tilemap),1,file);
420
    checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
421
    DiskFlopAnim(x,y);
422
 
423
    int i;
424
    for(i=0;i
425
    {
426
        for(int j=0;j
427
        {
428
            word actnum;
429
            objtype *objptr=actorat[i][j];
430
            if(ISPOINTER(objptr))
431
                actnum=0x8000 | (word)(objptr-objlist);
432
            else
433
                actnum=(word)(uintptr_t)objptr;
434
            fwrite(&actnum,sizeof(actnum),1,file);
435
            checksum = DoChecksum((byte *)&actnum,sizeof(actnum),checksum);
436
        }
437
    }
438
 
439
    fwrite (areaconnect,sizeof(areaconnect),1,file);
440
    fwrite (areabyplayer,sizeof(areabyplayer),1,file);
441
 
442
    // player object needs special treatment as it's in WL_AGENT.CPP and not in
443
    // WL_ACT2.CPP which could cause problems for the relative addressing
444
 
445
    ob = player;
446
    DiskFlopAnim(x,y);
447
    memcpy(&nullobj,ob,sizeof(nullobj));
448
    nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_player);
449
    fwrite(&nullobj,sizeof(nullobj),1,file);
450
    ob = ob->next;
451
 
452
    DiskFlopAnim(x,y);
453
    for (; ob ; ob=ob->next)
454
    {
455
        memcpy(&nullobj,ob,sizeof(nullobj));
456
        nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_grdstand);
457
        fwrite(&nullobj,sizeof(nullobj),1,file);
458
    }
459
    nullobj.active = ac_badobject;          // end of file marker
460
    DiskFlopAnim(x,y);
461
    fwrite(&nullobj,sizeof(nullobj),1,file);
462
 
463
    DiskFlopAnim(x,y);
464
    word laststatobjnum=(word) (laststatobj-statobjlist);
465
    fwrite(&laststatobjnum,sizeof(laststatobjnum),1,file);
466
    checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
467
 
468
    DiskFlopAnim(x,y);
469
    for(i=0;i
470
    {
471
        memcpy(&nullstat,statobjlist+i,sizeof(nullstat));
472
        nullstat.visspot=(byte *) ((uintptr_t) nullstat.visspot-(uintptr_t)spotvis);
473
        fwrite(&nullstat,sizeof(nullstat),1,file);
474
        checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
475
    }
476
 
477
    DiskFlopAnim(x,y);
478
    fwrite (doorposition,sizeof(doorposition),1,file);
479
    checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
480
    DiskFlopAnim(x,y);
481
    fwrite (doorobjlist,sizeof(doorobjlist),1,file);
482
    checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
483
 
484
    DiskFlopAnim(x,y);
485
    fwrite (&pwallstate,sizeof(pwallstate),1,file);
486
    checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
487
    fwrite (&pwalltile,sizeof(pwalltile),1,file);
488
    checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
489
    fwrite (&pwallx,sizeof(pwallx),1,file);
490
    checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
491
    fwrite (&pwally,sizeof(pwally),1,file);
492
    checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
493
    fwrite (&pwalldir,sizeof(pwalldir),1,file);
494
    checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
495
    fwrite (&pwallpos,sizeof(pwallpos),1,file);
496
    checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
497
 
498
    //
499
    // WRITE OUT CHECKSUM
500
    //
501
    fwrite (&checksum,sizeof(checksum),1,file);
502
 
503
    fwrite (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
504
 
505
    return(true);
506
}
507
 
508
//===========================================================================
509
 
510
/*
511
==================
512
=
513
= LoadTheGame
514
=
515
==================
516
*/
517
 
518
boolean LoadTheGame(FILE *file,int x,int y)
519
{
520
    int32_t checksum,oldchecksum;
521
    objtype nullobj;
522
    statobj_t nullstat;
523
 
524
    checksum = 0;
525
 
526
    DiskFlopAnim(x,y);
527
    fread (&gamestate,sizeof(gamestate),1,file);
528
    checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
529
 
530
    DiskFlopAnim(x,y);
531
    fread (&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
532
    checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
533
 
534
    DiskFlopAnim(x,y);
535
    SetupGameLevel ();
536
 
537
    DiskFlopAnim(x,y);
538
    fread (tilemap,sizeof(tilemap),1,file);
539
    checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
540
 
541
    DiskFlopAnim(x,y);
542
 
543
    int actnum=0, i;
544
    for(i=0;i
545
    {
546
        for(int j=0;j
547
        {
548
            fread (&actnum,sizeof(word),1,file);
549
            checksum = DoChecksum((byte *) &actnum,sizeof(word),checksum);
550
            if(actnum&0x8000)
551
                actorat[i][j]=objlist+(actnum&0x7fff);
552
            else
553
                actorat[i][j]=(objtype *)(uintptr_t) actnum;
554
        }
555
    }
556
 
557
    fread (areaconnect,sizeof(areaconnect),1,file);
558
    fread (areabyplayer,sizeof(areabyplayer),1,file);
559
 
560
    InitActorList ();
561
    DiskFlopAnim(x,y);
562
    fread (player,sizeof(*player),1,file);
563
    player->state=(statetype *) ((uintptr_t)player->state+(uintptr_t)&s_player);
564
 
565
    while (1)
566
    {
567
        DiskFlopAnim(x,y);
568
        fread (&nullobj,sizeof(nullobj),1,file);
569
        if (nullobj.active == ac_badobject)
570
            break;
571
        GetNewActor ();
572
        nullobj.state=(statetype *) ((uintptr_t)nullobj.state+(uintptr_t)&s_grdstand);
573
        // don't copy over the links
574
        memcpy (newobj,&nullobj,sizeof(nullobj)-8);
575
    }
576
 
577
    DiskFlopAnim(x,y);
578
    word laststatobjnum;
579
    fread (&laststatobjnum,sizeof(laststatobjnum),1,file);
580
    laststatobj=statobjlist+laststatobjnum;
581
    checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
582
 
583
    DiskFlopAnim(x,y);
584
    for(i=0;i
585
    {
586
        fread(&nullstat,sizeof(nullstat),1,file);
587
        checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
588
        nullstat.visspot=(byte *) ((uintptr_t)nullstat.visspot+(uintptr_t)spotvis);
589
        memcpy(statobjlist+i,&nullstat,sizeof(nullstat));
590
    }
591
 
592
    DiskFlopAnim(x,y);
593
    fread (doorposition,sizeof(doorposition),1,file);
594
    checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
595
    DiskFlopAnim(x,y);
596
    fread (doorobjlist,sizeof(doorobjlist),1,file);
597
    checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
598
 
599
    DiskFlopAnim(x,y);
600
    fread (&pwallstate,sizeof(pwallstate),1,file);
601
    checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
602
    fread (&pwalltile,sizeof(pwalltile),1,file);
603
    checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
604
    fread (&pwallx,sizeof(pwallx),1,file);
605
    checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
606
    fread (&pwally,sizeof(pwally),1,file);
607
    checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
608
    fread (&pwalldir,sizeof(pwalldir),1,file);
609
    checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
610
    fread (&pwallpos,sizeof(pwallpos),1,file);
611
    checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
612
 
613
    if (gamestate.secretcount)      // assign valid floorcodes under moved pushwalls
614
    {
615
        word *map, *obj; word tile, sprite;
616
        map = mapsegs[0]; obj = mapsegs[1];
617
        for (y=0;y
618
            for (x=0;x
619
            {
620
                tile = *map++; sprite = *obj++;
621
                if (sprite == PUSHABLETILE && !tilemap[x][y]
622
                    && (tile < AREATILE || tile >= (AREATILE+NUMMAPS)))
623
                {
624
                    if (*map >= AREATILE)
625
                        tile = *map;
626
                    if (*(map-1-mapwidth) >= AREATILE)
627
                        tile = *(map-1-mapwidth);
628
                    if (*(map-1+mapwidth) >= AREATILE)
629
                        tile = *(map-1+mapwidth);
630
                    if ( *(map-2) >= AREATILE)
631
                        tile = *(map-2);
632
 
633
                    *(map-1) = tile; *(obj-1) = 0;
634
                }
635
            }
636
    }
637
 
638
    Thrust(0,0);    // set player->areanumber to the floortile you're standing on
639
 
640
    fread (&oldchecksum,sizeof(oldchecksum),1,file);
641
 
642
    fread (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
643
    if(lastgamemusicoffset<0) lastgamemusicoffset=0;
644
 
645
 
646
    if (oldchecksum != checksum)
647
    {
648
        Message(STR_SAVECHT1"\n"
649
                STR_SAVECHT2"\n"
650
                STR_SAVECHT3"\n"
651
                STR_SAVECHT4);
652
 
653
        IN_ClearKeysDown();
654
        IN_Ack();
655
 
656
        gamestate.oldscore = gamestate.score = 0;
657
        gamestate.lives = 1;
658
        gamestate.weapon =
659
            gamestate.chosenweapon =
660
            gamestate.bestweapon = wp_pistol;
661
        gamestate.ammo = 8;
662
    }
663
 
664
    return true;
665
}
666
 
667
//===========================================================================
668
 
669
/*
670
==========================
671
=
672
= ShutdownId
673
=
674
= Shuts down all ID_?? managers
675
=
676
==========================
677
*/
678
 
679
void ShutdownId (void)
680
{
681
    US_Shutdown ();         // This line is completely useless...
682
    SD_Shutdown ();
683
    PM_Shutdown ();
684
    IN_Shutdown ();
685
    VW_Shutdown ();
686
    CA_Shutdown ();
687
#if defined(GP2X_940)
688
    GP2X_Shutdown();
689
#endif
690
}
691
 
692
 
693
//===========================================================================
694
 
695
/*
696
==================
697
=
698
= BuildTables
699
=
700
= Calculates:
701
=
702
= scale                 projection constant
703
= sintable/costable     overlapping fractional tables
704
=
705
==================
706
*/
707
 
708
const float radtoint = (float)(FINEANGLES/2/PI);
709
 
710
void BuildTables (void)
711
{
712
    //
713
    // calculate fine tangents
714
    //
715
 
716
    int i;
717
    for(i=0;i
718
    {
719
        double tang=tan((i+0.5)/radtoint);
720
        finetangent[i]=(int32_t)(tang*GLOBAL1);
721
        finetangent[FINEANGLES/4-1-i]=(int32_t)((1/tang)*GLOBAL1);
722
    }
723
 
724
    //
725
    // costable overlays sintable with a quarter phase shift
726
    // ANGLES is assumed to be divisable by four
727
    //
728
 
729
    float angle=0;
730
    float anglestep=(float)(PI/2/ANGLEQUAD);
731
    for(i=0; i
732
    {
733
        fixed value=(int32_t)(GLOBAL1*sin(angle));
734
        sintable[i]=sintable[i+ANGLES]=sintable[ANGLES/2-i]=value;
735
        sintable[ANGLES-i]=sintable[ANGLES/2+i]=-value;
736
        angle+=anglestep;
737
    }
738
    sintable[ANGLEQUAD] = 65536;
739
    sintable[3*ANGLEQUAD] = -65536;
740
 
741
#if defined(USE_STARSKY) || defined(USE_RAIN) || defined(USE_SNOW)
742
    Init3DPoints();
743
#endif
744
}
745
 
746
//===========================================================================
747
 
748
 
749
/*
750
====================
751
=
752
= CalcProjection
753
=
754
= Uses focallength
755
=
756
====================
757
*/
758
 
759
void CalcProjection (int32_t focal)
760
{
761
    int     i;
762
    int    intang;
763
    float   angle;
764
    double  tang;
765
    int     halfview;
766
    double  facedist;
767
 
768
    focallength = focal;
769
    facedist = focal+MINDIST;
770
    halfview = viewwidth/2;                                 // half view in pixels
771
 
772
    //
773
    // calculate scale value for vertical height calculations
774
    // and sprite x calculations
775
    //
776
    scale = (fixed) (halfview*facedist/(VIEWGLOBAL/2));
777
 
778
    //
779
    // divide heightnumerator by a posts distance to get the posts height for
780
    // the heightbuffer.  The pixel height is height>>2
781
    //
782
    heightnumerator = (TILEGLOBAL*scale)>>6;
783
 
784
    //
785
    // calculate the angle offset from view angle of each pixel's ray
786
    //
787
 
788
    for (i=0;i
789
    {
790
        // start 1/2 pixel over, so viewangle bisects two middle pixels
791
        tang = (int32_t)i*VIEWGLOBAL/viewwidth/facedist;
792
        angle = (float) atan(tang);
793
        intang = (int) (angle*radtoint);
794
        pixelangle[halfview-1-i] = intang;
795
        pixelangle[halfview+i] = -intang;
796
    }
797
}
798
 
799
 
800
 
801
//===========================================================================
802
 
803
/*
804
===================
805
=
806
= SetupWalls
807
=
808
= Map tile values to scaled pics
809
=
810
===================
811
*/
812
 
813
void SetupWalls (void)
814
{
815
    int     i;
816
 
817
    horizwall[0]=0;
818
    vertwall[0]=0;
819
 
820
    for (i=1;i
821
    {
822
        horizwall[i]=(i-1)*2;
823
        vertwall[i]=(i-1)*2+1;
824
    }
825
}
826
 
827
//===========================================================================
828
 
829
/*
830
==========================
831
=
832
= SignonScreen
833
=
834
==========================
835
*/
836
 
837
void SignonScreen (void)                        // VGA version
838
{
839
    VL_SetVGAPlaneMode ();
840
 
841
    VL_MungePic (signon,320,200);
842
    VL_MemToScreen (signon,320,200,0,0);
843
}
844
 
845
 
846
/*
847
==========================
848
=
849
= FinishSignon
850
=
851
==========================
852
*/
853
 
854
void FinishSignon (void)
855
{
856
#ifndef SPEAR
857
    VW_Bar (0,189,300,11,VL_GetPixel(0,0));
858
    WindowX = 0;
859
    WindowW = 320;
860
    PrintY = 190;
861
 
862
    #ifndef JAPAN
863
    SETFONTCOLOR(14,4);
864
 
865
    #ifdef SPANISH
866
    US_CPrint ("Oprima una tecla");
867
    #else
868
    US_CPrint ("Press a key");
869
    #endif
870
 
871
    #endif
872
 
873
    VH_UpdateScreen();
874
 
875
    if (!param_nowait)
876
        IN_Ack ();
877
 
878
    #ifndef JAPAN
879
    VW_Bar (0,189,300,11,VL_GetPixel(0,0));
880
 
881
    PrintY = 190;
882
    SETFONTCOLOR(10,4);
883
 
884
    #ifdef SPANISH
885
    US_CPrint ("pensando...");
886
    #else
887
    US_CPrint ("Working...");
888
    #endif
889
 
890
    VH_UpdateScreen();
891
    #endif
892
 
893
    SETFONTCOLOR(0,15);
894
#else
895
    VH_UpdateScreen();
896
 
897
    if (!param_nowait)
898
        VW_WaitVBL(3*70);
899
#endif
900
}
901
 
902
//===========================================================================
903
 
904
/*
905
=====================
906
=
907
= InitDigiMap
908
=
909
=====================
910
*/
911
 
912
// channel mapping:
913
//  -1: any non reserved channel
914
//   0: player weapons
915
//   1: boss weapons
916
 
917
static int wolfdigimap[] =
918
    {
919
        // These first sounds are in the upload version
920
#ifndef SPEAR
921
        HALTSND,                0,  -1,
922
        DOGBARKSND,             1,  -1,
923
        CLOSEDOORSND,           2,  -1,
924
        OPENDOORSND,            3,  -1,
925
        ATKMACHINEGUNSND,       4,   0,
926
        ATKPISTOLSND,           5,   0,
927
        ATKGATLINGSND,          6,   0,
928
        SCHUTZADSND,            7,  -1,
929
        GUTENTAGSND,            8,  -1,
930
        MUTTISND,               9,  -1,
931
        BOSSFIRESND,            10,  1,
932
        SSFIRESND,              11, -1,
933
        DEATHSCREAM1SND,        12, -1,
934
        DEATHSCREAM2SND,        13, -1,
935
        DEATHSCREAM3SND,        13, -1,
936
        TAKEDAMAGESND,          14, -1,
937
        PUSHWALLSND,            15, -1,
938
 
939
        LEBENSND,               20, -1,
940
        NAZIFIRESND,            21, -1,
941
        SLURPIESND,             22, -1,
942
 
943
        YEAHSND,                32, -1,
944
 
945
#ifndef UPLOAD
946
        // These are in all other episodes
947
        DOGDEATHSND,            16, -1,
948
        AHHHGSND,               17, -1,
949
        DIESND,                 18, -1,
950
        EVASND,                 19, -1,
951
 
952
        TOT_HUNDSND,            23, -1,
953
        MEINGOTTSND,            24, -1,
954
        SCHABBSHASND,           25, -1,
955
        HITLERHASND,            26, -1,
956
        SPIONSND,               27, -1,
957
        NEINSOVASSND,           28, -1,
958
        DOGATTACKSND,           29, -1,
959
        LEVELDONESND,           30, -1,
960
        MECHSTEPSND,            31, -1,
961
 
962
        SCHEISTSND,             33, -1,
963
        DEATHSCREAM4SND,        34, -1,         // AIIEEE
964
        DEATHSCREAM5SND,        35, -1,         // DEE-DEE
965
        DONNERSND,              36, -1,         // EPISODE 4 BOSS DIE
966
        EINESND,                37, -1,         // EPISODE 4 BOSS SIGHTING
967
        ERLAUBENSND,            38, -1,         // EPISODE 6 BOSS SIGHTING
968
        DEATHSCREAM6SND,        39, -1,         // FART
969
        DEATHSCREAM7SND,        40, -1,         // GASP
970
        DEATHSCREAM8SND,        41, -1,         // GUH-BOY!
971
        DEATHSCREAM9SND,        42, -1,         // AH GEEZ!
972
        KEINSND,                43, -1,         // EPISODE 5 BOSS SIGHTING
973
        MEINSND,                44, -1,         // EPISODE 6 BOSS DIE
974
        ROSESND,                45, -1,         // EPISODE 5 BOSS DIE
975
 
976
#endif
977
#else
978
//
979
// SPEAR OF DESTINY DIGISOUNDS
980
//
981
        HALTSND,                0,  -1,
982
        CLOSEDOORSND,           2,  -1,
983
        OPENDOORSND,            3,  -1,
984
        ATKMACHINEGUNSND,       4,   0,
985
        ATKPISTOLSND,           5,   0,
986
        ATKGATLINGSND,          6,   0,
987
        SCHUTZADSND,            7,  -1,
988
        BOSSFIRESND,            8,   1,
989
        SSFIRESND,              9,  -1,
990
        DEATHSCREAM1SND,        10, -1,
991
        DEATHSCREAM2SND,        11, -1,
992
        TAKEDAMAGESND,          12, -1,
993
        PUSHWALLSND,            13, -1,
994
        AHHHGSND,               15, -1,
995
        LEBENSND,               16, -1,
996
        NAZIFIRESND,            17, -1,
997
        SLURPIESND,             18, -1,
998
        LEVELDONESND,           22, -1,
999
        DEATHSCREAM4SND,        23, -1,         // AIIEEE
1000
        DEATHSCREAM3SND,        23, -1,         // DOUBLY-MAPPED!!!
1001
        DEATHSCREAM5SND,        24, -1,         // DEE-DEE
1002
        DEATHSCREAM6SND,        25, -1,         // FART
1003
        DEATHSCREAM7SND,        26, -1,         // GASP
1004
        DEATHSCREAM8SND,        27, -1,         // GUH-BOY!
1005
        DEATHSCREAM9SND,        28, -1,         // AH GEEZ!
1006
        GETGATLINGSND,          38, -1,         // Got Gat replacement
1007
 
1008
#ifndef SPEARDEMO
1009
        DOGBARKSND,             1,  -1,
1010
        DOGDEATHSND,            14, -1,
1011
        SPIONSND,               19, -1,
1012
        NEINSOVASSND,           20, -1,
1013
        DOGATTACKSND,           21, -1,
1014
        TRANSSIGHTSND,          29, -1,         // Trans Sight
1015
        TRANSDEATHSND,          30, -1,         // Trans Death
1016
        WILHELMSIGHTSND,        31, -1,         // Wilhelm Sight
1017
        WILHELMDEATHSND,        32, -1,         // Wilhelm Death
1018
        UBERDEATHSND,           33, -1,         // Uber Death
1019
        KNIGHTSIGHTSND,         34, -1,         // Death Knight Sight
1020
        KNIGHTDEATHSND,         35, -1,         // Death Knight Death
1021
        ANGELSIGHTSND,          36, -1,         // Angel Sight
1022
        ANGELDEATHSND,          37, -1,         // Angel Death
1023
        GETSPEARSND,            39, -1,         // Got Spear replacement
1024
#endif
1025
#endif
1026
        LASTSOUND
1027
    };
1028
 
1029
 
1030
void InitDigiMap (void)
1031
{
1032
    int *map;
1033
 
1034
    for (map = wolfdigimap; *map != LASTSOUND; map += 3)
1035
    {
1036
        DigiMap[map[0]] = map[1];
1037
        DigiChannel[map[1]] = map[2];
1038
        SD_PrepareSound(map[1]);
1039
    }
1040
}
1041
 
1042
#ifndef SPEAR
1043
CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32};
1044
CP_itemtype MusicMenu[]=
1045
    {
1046
        {1,"Get Them!",0},
1047
        {1,"Searching",0},
1048
        {1,"P.O.W.",0},
1049
        {1,"Suspense",0},
1050
        {1,"War March",0},
1051
        {1,"Around The Corner!",0},
1052
 
1053
        {1,"Nazi Anthem",0},
1054
        {1,"Lurking...",0},
1055
        {1,"Going After Hitler",0},
1056
        {1,"Pounding Headache",0},
1057
        {1,"Into the Dungeons",0},
1058
        {1,"Ultimate Conquest",0},
1059
 
1060
        {1,"Kill the S.O.B.",0},
1061
        {1,"The Nazi Rap",0},
1062
        {1,"Twelfth Hour",0},
1063
        {1,"Zero Hour",0},
1064
        {1,"Ultimate Conquest",0},
1065
        {1,"Wolfpack",0}
1066
    };
1067
#else
1068
CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32};
1069
CP_itemtype MusicMenu[]=
1070
    {
1071
        {1,"Funky Colonel Bill",0},
1072
        {1,"Death To The Nazis",0},
1073
        {1,"Tiptoeing Around",0},
1074
        {1,"Is This THE END?",0},
1075
        {1,"Evil Incarnate",0},
1076
        {1,"Jazzin' Them Nazis",0},
1077
        {1,"Puttin' It To The Enemy",0},
1078
        {1,"The SS Gonna Get You",0},
1079
        {1,"Towering Above",0}
1080
    };
1081
#endif
1082
 
1083
#ifndef SPEARDEMO
1084
void DoJukebox(void)
1085
{
1086
    int which,lastsong=-1;
1087
    unsigned start;
1088
    unsigned songs[]=
1089
        {
1090
#ifndef SPEAR
1091
            GETTHEM_MUS,
1092
            SEARCHN_MUS,
1093
            POW_MUS,
1094
            SUSPENSE_MUS,
1095
            WARMARCH_MUS,
1096
            CORNER_MUS,
1097
 
1098
            NAZI_OMI_MUS,
1099
            PREGNANT_MUS,
1100
            GOINGAFT_MUS,
1101
            HEADACHE_MUS,
1102
            DUNGEON_MUS,
1103
            ULTIMATE_MUS,
1104
 
1105
            INTROCW3_MUS,
1106
            NAZI_RAP_MUS,
1107
            TWELFTH_MUS,
1108
            ZEROHOUR_MUS,
1109
            ULTIMATE_MUS,
1110
            PACMAN_MUS
1111
#else
1112
            XFUNKIE_MUS,             // 0
1113
            XDEATH_MUS,              // 2
1114
            XTIPTOE_MUS,             // 4
1115
            XTHEEND_MUS,             // 7
1116
            XEVIL_MUS,               // 17
1117
            XJAZNAZI_MUS,            // 18
1118
            XPUTIT_MUS,              // 21
1119
            XGETYOU_MUS,             // 22
1120
            XTOWER2_MUS              // 23
1121
#endif
1122
        };
1123
 
1124
    IN_ClearKeysDown();
1125
    if (!AdLibPresent && !SoundBlasterPresent)
1126
        return;
1127
 
1128
    MenuFadeOut();
1129
 
1130
#ifndef SPEAR
1131
#ifndef UPLOAD
9097 turbocat 1132
    start = (( uSDL_GetTicks()/10)%3)*6;
8557 maxcodehac 1133
#else
1134
    start = 0;
1135
#endif
1136
#else
1137
    start = 0;
1138
#endif
1139
 
1140
    CA_CacheGrChunk (STARTFONT+1);
1141
#ifdef SPEAR
1142
    CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
1143
#else
1144
    CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
1145
#endif
1146
    CA_LoadAllSounds ();
1147
 
1148
    fontnumber=1;
1149
    ClearMScreen ();
1150
    VWB_DrawPic(112,184,C_MOUSELBACKPIC);
1151
    DrawStripes (10);
1152
    SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
1153
 
1154
#ifndef SPEAR
1155
    DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR);
1156
#else
1157
    DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR);
1158
#endif
1159
 
1160
    DrawMenu (&MusicItems,&MusicMenu[start]);
1161
 
1162
    SETFONTCOLOR (READHCOLOR,BKGDCOLOR);
1163
    PrintY=15;
1164
    WindowX = 0;
1165
    WindowY = 320;
1166
    US_CPrint ("Robert's Jukebox");
1167
 
1168
    SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
1169
    VW_UpdateScreen();
1170
    MenuFadeIn();
1171
 
1172
    do
1173
    {
1174
        which = HandleMenu(&MusicItems,&MusicMenu[start],NULL);
1175
        if (which>=0)
1176
        {
1177
            if (lastsong >= 0)
1178
                MusicMenu[start+lastsong].active = 1;
1179
 
1180
            StartCPMusic(songs[start + which]);
1181
            MusicMenu[start+which].active = 2;
1182
            DrawMenu (&MusicItems,&MusicMenu[start]);
1183
            VW_UpdateScreen();
1184
            lastsong = which;
1185
        }
1186
    } while(which>=0);
1187
 
1188
    MenuFadeOut();
1189
    IN_ClearKeysDown();
1190
#ifdef SPEAR
1191
    UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
1192
#else
1193
    UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
1194
#endif
1195
}
1196
#endif
1197
 
1198
/*
1199
==========================
1200
=
1201
= InitGame
1202
=
1203
= Load a few things right away
1204
=
1205
==========================
1206
*/
1207
 
1208
static void InitGame()
1209
{
1210
#ifndef SPEARDEMO
1211
    boolean didjukebox=false;
1212
#endif
1213
 
1214
    // initialize SDL
1215
#if defined _WIN32
1216
    putenv("SDL_VIDEODRIVER=directx");
1217
#endif
8645 turbocat 1218
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
8557 maxcodehac 1219
    {
1220
        printf("Unable to init SDL: %s\n", SDL_GetError());
1221
        exit(1);
1222
    }
9097 turbocat 1223
#ifdef _KOLIBRI
1224
    uSDL_StartTicks();
1225
#endif
8645 turbocat 1226
    SDL_AudioInit(NULL);
8557 maxcodehac 1227
    atexit(SDL_Quit);
1228
 
1229
    int numJoysticks = SDL_NumJoysticks();
1230
    if(param_joystickindex && (param_joystickindex < -1 || param_joystickindex >= numJoysticks))
1231
    {
1232
        if(!numJoysticks)
1233
            printf("No joysticks are available to SDL!\n");
1234
        else
1235
            printf("The joystick index must be between -1 and %i!\n", numJoysticks - 1);
1236
        exit(1);
1237
    }
1238
 
1239
#if defined(GP2X_940)
1240
    GP2X_MemoryInit();
1241
#endif
8596 turbocat 1242
 
8557 maxcodehac 1243
    SignonScreen ();
8645 turbocat 1244
#ifdef _KOLIBRI
8596 turbocat 1245
    kolibri_set_win_center();
8645 turbocat 1246
#endif
1247
 
8557 maxcodehac 1248
#if defined _WIN32
1249
    if(!fullscreen)
1250
    {
1251
        struct SDL_SysWMinfo wmInfo;
1252
        SDL_VERSION(&wmInfo.version);
1253
 
1254
        if(SDL_GetWMInfo(&wmInfo) != -1)
1255
        {
1256
            HWND hwndSDL = wmInfo.window;
1257
            DWORD style = GetWindowLong(hwndSDL, GWL_STYLE) & ~WS_SYSMENU;
1258
            SetWindowLong(hwndSDL, GWL_STYLE, style);
1259
            SetWindowPos(hwndSDL, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
1260
        }
1261
    }
1262
#endif
1263
	VW_UpdateScreen();
1264
 
1265
    VH_Startup ();
1266
    IN_Startup ();
1267
    PM_Startup ();
1268
    SD_Startup ();
1269
    CA_Startup ();
1270
    US_Startup ();
1271
 
1272
    // TODO: Will any memory checking be needed someday??
1273
#ifdef NOTYET
1274
#ifndef SPEAR
1275
    if (mminfo.mainmem < 235000L)
1276
#else
1277
    if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))
1278
#endif
1279
    {
1280
        byte *screen;
1281
 
1282
        CA_CacheGrChunk (ERRORSCREEN);
1283
        screen = grsegs[ERRORSCREEN];
1284
        ShutdownId();
1285
/*        memcpy((byte *)0xb8000,screen+7+7*160,17*160);
1286
        gotoxy (1,23);*/
1287
        exit(1);
1288
    }
1289
#endif
1290
 
1291
 
1292
//
1293
// build some tables
1294
//
1295
    InitDigiMap ();
1296
 
1297
    ReadConfig ();
1298
 
1299
    SetupSaveGames();
1300
 
1301
//
1302
// HOLDING DOWN 'M' KEY?
1303
//
1304
	IN_ProcessEvents();
1305
 
1306
#ifndef SPEARDEMO
1307
    if (Keyboard[sc_M])
1308
    {
1309
        DoJukebox();
1310
        didjukebox=true;
1311
    }
1312
    else
1313
#endif
1314
 
1315
//
1316
// draw intro screen stuff
1317
//
1318
    IntroScreen ();
1319
 
1320
#ifdef _arch_dreamcast
1321
    //TODO: VMU Selection Screen
1322
#endif
1323
 
1324
//
1325
// load in and lock down some basic chunks
1326
//
1327
 
1328
    CA_CacheGrChunk(STARTFONT);
1329
    CA_CacheGrChunk(STATUSBARPIC);
1330
 
1331
    LoadLatchMem ();
1332
    BuildTables ();          // trig tables
1333
    SetupWalls ();
1334
 
1335
    NewViewSize (viewsize);
1336
 
1337
//
1338
// initialize variables
1339
//
1340
    InitRedShifts ();
1341
#ifndef SPEARDEMO
1342
    if(!didjukebox)
1343
#endif
1344
        FinishSignon();
1345
 
1346
#ifdef NOTYET
1347
    vdisp = (byte *) (0xa0000+PAGE1START);
1348
    vbuf = (byte *) (0xa0000+PAGE2START);
1349
#endif
1350
}
1351
 
1352
//===========================================================================
1353
 
1354
/*
1355
==========================
1356
=
1357
= SetViewSize
1358
=
1359
==========================
1360
*/
1361
 
1362
boolean SetViewSize (unsigned width, unsigned height)
1363
{
1364
    viewwidth = width&~15;                  // must be divisable by 16
1365
    viewheight = height&~1;                 // must be even
1366
    centerx = viewwidth/2-1;
1367
    shootdelta = viewwidth/10;
1368
    if((unsigned) viewheight == screenHeight)
1369
        viewscreenx = viewscreeny = screenofs = 0;
1370
    else
1371
    {
1372
        viewscreenx = (screenWidth-viewwidth) / 2;
1373
        viewscreeny = (screenHeight-scaleFactor*STATUSLINES-viewheight)/2;
1374
        screenofs = viewscreeny*screenWidth+viewscreenx;
1375
    }
1376
 
1377
//
1378
// calculate trace angles and projection constants
1379
//
1380
    CalcProjection (FOCALLENGTH);
1381
 
1382
    return true;
1383
}
1384
 
1385
 
1386
void ShowViewSize (int width)
1387
{
1388
    int oldwidth,oldheight;
1389
 
1390
    oldwidth = viewwidth;
1391
    oldheight = viewheight;
1392
 
1393
    if(width == 21)
1394
    {
1395
        viewwidth = screenWidth;
1396
        viewheight = screenHeight;
1397
        VWB_BarScaledCoord (0, 0, screenWidth, screenHeight, 0);
1398
    }
1399
    else if(width == 20)
1400
    {
1401
        viewwidth = screenWidth;
1402
        viewheight = screenHeight - scaleFactor*STATUSLINES;
1403
        DrawPlayBorder ();
1404
    }
1405
    else
1406
    {
1407
        viewwidth = width*16*screenWidth/320;
1408
        viewheight = (int) (width*16*HEIGHTRATIO*screenHeight/200);
1409
        DrawPlayBorder ();
1410
    }
1411
 
1412
    viewwidth = oldwidth;
1413
    viewheight = oldheight;
1414
}
1415
 
1416
 
1417
void NewViewSize (int width)
1418
{
1419
    viewsize = width;
1420
    if(viewsize == 21)
1421
        SetViewSize(screenWidth, screenHeight);
1422
    else if(viewsize == 20)
1423
        SetViewSize(screenWidth, screenHeight - scaleFactor * STATUSLINES);
1424
    else
1425
        SetViewSize(width*16*screenWidth/320, (unsigned) (width*16*HEIGHTRATIO*screenHeight/200));
1426
}
1427
 
1428
 
1429
 
1430
//===========================================================================
1431
 
1432
/*
1433
==========================
1434
=
1435
= Quit
1436
=
1437
==========================
1438
*/
1439
 
1440
void Quit (const char *errorStr, ...)
1441
{
1442
#ifdef NOTYET
1443
    byte *screen;
1444
#endif
1445
    char error[256];
1446
    if(errorStr != NULL)
1447
    {
1448
        va_list vlist;
1449
        va_start(vlist, errorStr);
1450
        vsprintf(error, errorStr, vlist);
1451
        va_end(vlist);
1452
    }
1453
    else error[0] = 0;
1454
 
1455
    if (!pictable)  // don't try to display the red box before it's loaded
1456
    {
1457
        ShutdownId();
1458
        if (error && *error)
1459
        {
1460
#ifdef NOTYET
1461
            SetTextCursor(0,0);
1462
#endif
1463
            puts(error);
1464
#ifdef NOTYET
1465
            SetTextCursor(0,2);
1466
#endif
1467
            VW_WaitVBL(100);
1468
        }
1469
        exit(1);
1470
    }
1471
 
1472
    if (!error || !*error)
1473
    {
1474
#ifdef NOTYET
1475
        #ifndef JAPAN
1476
        CA_CacheGrChunk (ORDERSCREEN);
1477
        screen = grsegs[ORDERSCREEN];
1478
        #endif
1479
#endif
1480
        WriteConfig ();
1481
    }
1482
#ifdef NOTYET
1483
    else
1484
    {
1485
        CA_CacheGrChunk (ERRORSCREEN);
1486
        screen = grsegs[ERRORSCREEN];
1487
    }
1488
#endif
1489
 
1490
    ShutdownId ();
1491
 
1492
    if (error && *error)
1493
    {
1494
#ifdef NOTYET
1495
        memcpy((byte *)0xb8000,screen+7,7*160);
1496
        SetTextCursor(9,3);
1497
#endif
1498
        puts(error);
1499
#ifdef NOTYET
1500
        SetTextCursor(0,7);
1501
#endif
1502
        VW_WaitVBL(200);
1503
        exit(1);
1504
    }
1505
    else
1506
    if (!error || !(*error))
1507
    {
1508
#ifdef NOTYET
1509
        #ifndef JAPAN
1510
        memcpy((byte *)0xb8000,screen+7,24*160); // 24 for SPEAR/UPLOAD compatibility
1511
        #endif
1512
        SetTextCursor(0,23);
1513
#endif
1514
    }
1515
 
1516
    exit(0);
1517
}
1518
 
1519
//===========================================================================
1520
 
1521
 
1522
 
1523
/*
1524
=====================
1525
=
1526
= DemoLoop
1527
=
1528
=====================
1529
*/
1530
 
1531
 
1532
static void DemoLoop()
1533
{
1534
    int LastDemo = 0;
1535
 
1536
//
1537
// check for launch from ted
1538
//
1539
    if (param_tedlevel != -1)
1540
    {
1541
        param_nowait = true;
1542
        EnableEndGameMenuItem();
1543
        NewGame(param_difficulty,0);
1544
 
1545
#ifndef SPEAR
1546
        gamestate.episode = param_tedlevel/10;
1547
        gamestate.mapon = param_tedlevel%10;
1548
#else
1549
        gamestate.episode = 0;
1550
        gamestate.mapon = param_tedlevel;
1551
#endif
1552
        GameLoop();
1553
        Quit (NULL);
1554
    }
1555
 
1556
 
1557
//
1558
// main game cycle
1559
//
1560
 
1561
#ifndef DEMOTEST
1562
 
1563
    #ifndef UPLOAD
1564
 
1565
        #ifndef GOODTIMES
1566
        #ifndef SPEAR
1567
        #ifndef JAPAN
1568
        if (!param_nowait)
1569
            NonShareware();
1570
        #endif
1571
        #else
1572
            #ifndef GOODTIMES
1573
            #ifndef SPEARDEMO
1574
            extern void CopyProtection(void);
1575
            if(!param_goodtimes)
1576
                CopyProtection();
1577
            #endif
1578
            #endif
1579
        #endif
1580
        #endif
1581
    #endif
1582
 
1583
    StartCPMusic(INTROSONG);
1584
 
1585
#ifndef JAPAN
1586
    if (!param_nowait)
1587
        PG13 ();
1588
#endif
1589
 
1590
#endif
1591
 
1592
    while (1)
1593
    {
1594
        while (!param_nowait)
1595
        {
1596
//
1597
// title page
1598
//
1599
#ifndef DEMOTEST
1600
 
1601
#ifdef SPEAR
1602
            SDL_Color pal[256];
1603
            CA_CacheGrChunk (TITLEPALETTE);
1604
            VL_ConvertPalette(grsegs[TITLEPALETTE], pal, 256);
1605
 
1606
            CA_CacheGrChunk (TITLE1PIC);
1607
            VWB_DrawPic (0,0,TITLE1PIC);
1608
            UNCACHEGRCHUNK (TITLE1PIC);
1609
 
1610
            CA_CacheGrChunk (TITLE2PIC);
1611
            VWB_DrawPic (0,80,TITLE2PIC);
1612
            UNCACHEGRCHUNK (TITLE2PIC);
1613
            VW_UpdateScreen ();
1614
            VL_FadeIn(0,255,pal,30);
1615
 
1616
            UNCACHEGRCHUNK (TITLEPALETTE);
1617
#else
1618
            CA_CacheScreen (TITLEPIC);
1619
            VW_UpdateScreen ();
1620
            VW_FadeIn();
1621
#endif
1622
            if (IN_UserInput(TickBase*15))
1623
                break;
1624
            VW_FadeOut();
1625
//
1626
// credits page
1627
//
1628
            CA_CacheScreen (CREDITSPIC);
1629
            VW_UpdateScreen();
1630
            VW_FadeIn ();
1631
            if (IN_UserInput(TickBase*10))
1632
                break;
1633
            VW_FadeOut ();
1634
//
1635
// high scores
1636
//
1637
            DrawHighScores ();
1638
            VW_UpdateScreen ();
1639
            VW_FadeIn ();
1640
 
1641
            if (IN_UserInput(TickBase*10))
1642
                break;
1643
#endif
1644
//
1645
// demo
1646
//
1647
 
1648
            #ifndef SPEARDEMO
1649
            PlayDemo (LastDemo++%4);
1650
            #else
1651
            PlayDemo (0);
1652
            #endif
1653
 
1654
            if (playstate == ex_abort)
1655
                break;
1656
            VW_FadeOut();
1657
            if(screenHeight % 200 != 0)
1658
                VL_ClearScreen(0);
1659
            StartCPMusic(INTROSONG);
1660
        }
1661
 
1662
        VW_FadeOut ();
1663
 
1664
#ifdef DEBUGKEYS
1665
        if (Keyboard[sc_Tab] && param_debugmode)
1666
            RecordDemo ();
1667
        else
1668
            US_ControlPanel (0);
1669
#else
1670
        US_ControlPanel (0);
1671
#endif
1672
 
1673
        if (startgame || loadedgame)
1674
        {
1675
            GameLoop ();
1676
            if(!param_nowait)
1677
            {
1678
                VW_FadeOut();
1679
                StartCPMusic(INTROSONG);
1680
            }
1681
        }
1682
    }
1683
}
1684
 
1685
 
1686
//===========================================================================
1687
 
1688
#define IFARG(str) if(!strcmp(arg, (str)))
1689
 
1690
void CheckParameters(int argc, char *argv[])
1691
{
1692
    bool hasError = false, showHelp = false;
1693
    bool sampleRateGiven = false, audioBufferGiven = false;
1694
    int defaultSampleRate = param_samplerate;
1695
 
1696
    for(int i = 1; i < argc; i++)
1697
    {
1698
        char *arg = argv[i];
1699
#ifndef SPEAR
1700
        IFARG("--goobers")
1701
#else
1702
        IFARG("--debugmode")
1703
#endif
1704
            param_debugmode = true;
1705
        else IFARG("--baby")
1706
            param_difficulty = 0;
1707
        else IFARG("--easy")
1708
            param_difficulty = 1;
1709
        else IFARG("--normal")
1710
            param_difficulty = 2;
1711
        else IFARG("--hard")
1712
            param_difficulty = 3;
1713
        else IFARG("--nowait")
1714
            param_nowait = true;
1715
        else IFARG("--tedlevel")
1716
        {
1717
            if(++i >= argc)
1718
            {
1719
                printf("The tedlevel option is missing the level argument!\n");
1720
                hasError = true;
1721
            }
1722
            else param_tedlevel = atoi(argv[i]);
1723
        }
1724
        else IFARG("--windowed")
1725
            fullscreen = false;
1726
        else IFARG("--windowed-mouse")
1727
        {
1728
            fullscreen = false;
1729
            forcegrabmouse = true;
1730
        }
1731
        else IFARG("--res")
1732
        {
1733
            if(i + 2 >= argc)
1734
            {
1735
                printf("The res option needs the width and/or the height argument!\n");
1736
                hasError = true;
1737
            }
1738
            else
1739
            {
1740
                screenWidth = atoi(argv[++i]);
1741
                screenHeight = atoi(argv[++i]);
1742
                unsigned factor = screenWidth / 320;
1743
                if(screenWidth % 320 || screenHeight != 200 * factor && screenHeight != 240 * factor)
1744
                    printf("Screen size must be a multiple of 320x200 or 320x240!\n"), hasError = true;
1745
            }
1746
        }
1747
        else IFARG("--resf")
1748
        {
1749
            if(i + 2 >= argc)
1750
            {
1751
                printf("The resf option needs the width and/or the height argument!\n");
1752
                hasError = true;
1753
            }
1754
            else
1755
            {
1756
                screenWidth = atoi(argv[++i]);
1757
                screenHeight = atoi(argv[++i]);
1758
                if(screenWidth < 320)
1759
                    printf("Screen width must be at least 320!\n"), hasError = true;
1760
                if(screenHeight < 200)
1761
                    printf("Screen height must be at least 200!\n"), hasError = true;
1762
            }
1763
        }
1764
        else IFARG("--bits")
1765
        {
1766
            if(++i >= argc)
1767
            {
1768
                printf("The bits option is missing the color depth argument!\n");
1769
                hasError = true;
1770
            }
1771
            else
1772
            {
1773
                screenBits = atoi(argv[i]);
1774
                switch(screenBits)
1775
                {
1776
                    case 8:
1777
                    case 16:
1778
                    case 24:
1779
                    case 32:
1780
                        break;
1781
 
1782
                    default:
1783
                        printf("Screen color depth must be 8, 16, 24, or 32!\n");
1784
                        hasError = true;
1785
                        break;
1786
                }
1787
            }
1788
        }
1789
        else IFARG("--nodblbuf")
1790
            usedoublebuffering = false;
1791
        else IFARG("--extravbls")
1792
        {
1793
            if(++i >= argc)
1794
            {
1795
                printf("The extravbls option is missing the vbls argument!\n");
1796
                hasError = true;
1797
            }
1798
            else
1799
            {
1800
                extravbls = atoi(argv[i]);
1801
                if(extravbls < 0)
1802
                {
1803
                    printf("Extravbls must be positive!\n");
1804
                    hasError = true;
1805
                }
1806
            }
1807
        }
1808
        else IFARG("--joystick")
1809
        {
1810
            if(++i >= argc)
1811
            {
1812
                printf("The joystick option is missing the index argument!\n");
1813
                hasError = true;
1814
            }
1815
            else param_joystickindex = atoi(argv[i]);   // index is checked in InitGame
1816
        }
1817
        else IFARG("--joystickhat")
1818
        {
1819
            if(++i >= argc)
1820
            {
1821
                printf("The joystickhat option is missing the index argument!\n");
1822
                hasError = true;
1823
            }
1824
            else param_joystickhat = atoi(argv[i]);
1825
        }
1826
        else IFARG("--samplerate")
1827
        {
1828
            if(++i >= argc)
1829
            {
1830
                printf("The samplerate option is missing the rate argument!\n");
1831
                hasError = true;
1832
            }
1833
            else param_samplerate = atoi(argv[i]);
1834
            sampleRateGiven = true;
1835
        }
1836
        else IFARG("--audiobuffer")
1837
        {
1838
            if(++i >= argc)
1839
            {
1840
                printf("The audiobuffer option is missing the size argument!\n");
1841
                hasError = true;
1842
            }
1843
            else param_audiobuffer = atoi(argv[i]);
1844
            audioBufferGiven = true;
1845
        }
1846
        else IFARG("--mission")
1847
        {
1848
            if(++i >= argc)
1849
            {
1850
                printf("The mission option is missing the mission argument!\n");
1851
                hasError = true;
1852
            }
1853
            else
1854
            {
1855
                param_mission = atoi(argv[i]);
1856
                if(param_mission < 0 || param_mission > 3)
1857
                {
1858
                    printf("The mission option must be between 0 and 3!\n");
1859
                    hasError = true;
1860
                }
1861
            }
1862
        }
1863
        else IFARG("--configdir")
1864
        {
1865
            if(++i >= argc)
1866
            {
1867
                printf("The configdir option is missing the dir argument!\n");
1868
                hasError = true;
1869
            }
1870
            else
1871
            {
1872
                size_t len = strlen(argv[i]);
1873
                if(len + 2 > sizeof(configdir))
1874
                {
1875
                    printf("The config directory is too long!\n");
1876
                    hasError = true;
1877
                }
1878
                else
1879
                {
1880
                    strcpy(configdir, argv[i]);
1881
                    if(argv[i][len] != '/' && argv[i][len] != '\\')
1882
                        strcat(configdir, "/");
1883
                }
1884
            }
1885
        }
1886
        else IFARG("--goodtimes")
1887
            param_goodtimes = true;
1888
        else IFARG("--ignorenumchunks")
1889
            param_ignorenumchunks = true;
1890
        else IFARG("--help")
1891
            showHelp = true;
1892
        else hasError = true;
1893
    }
1894
    if(hasError || showHelp)
1895
    {
1896
        if(hasError) printf("\n");
1897
        printf(
8655 turbocat 1898
            "Wolf4SDL v1.7\n"
8557 maxcodehac 1899
            "Ported by Chaos-Software (http://www.chaos-software.de.vu)\n"
8645 turbocat 1900
        #ifdef _KOLIBRI
1901
            "Ported for KolibriOS by 'turbocat2001' and 'maxcodehack'\n"
1902
        #endif
8557 maxcodehac 1903
            "Original Wolfenstein 3D by id Software\n\n"
1904
            "Usage: Wolf4SDL [options]\n"
1905
            "Options:\n"
1906
            " --help                 This help page\n"
1907
            " --tedlevel      Starts the game in the given level\n"
1908
            " --baby                 Sets the difficulty to baby for tedlevel\n"
1909
            " --easy                 Sets the difficulty to easy for tedlevel\n"
1910
            " --normal               Sets the difficulty to normal for tedlevel\n"
1911
            " --hard                 Sets the difficulty to hard for tedlevel\n"
1912
            " --nowait               Skips intro screens\n"
8655 turbocat 1913
        #ifndef _KOLIBRI
8557 maxcodehac 1914
            " --windowed[-mouse]     Starts the game in a window [and grabs mouse]\n"
9097 turbocat 1915
        #endif
8557 maxcodehac 1916
            " --res   Sets the screen resolution\n"
1917
            "                        (must be multiple of 320x200 or 320x240)\n"
1918
            " --resf           Sets any screen resolution >= 320x200\n"
1919
            "                        (which may result in graphic errors)\n"
1920
            " --bits              Sets the screen color depth\n"
1921
            "                        (use this when you have palette/fading problems\n"
1922
            "                        allowed: 8, 16, 24, 32, default: \"best\" depth)\n"
1923
            " --nodblbuf             Don't use SDL's double buffering\n"
1924
            " --extravbls      Sets a delay after each frame, which may help to\n"
9097 turbocat 1925
            "                        reduce flickering (unit is currently 8 ms, default: 2)\n"
8655 turbocat 1926
        #ifndef _KOLIBRI
8557 maxcodehac 1927
            " --joystick      Use the index-th joystick if available\n"
1928
            "                        (-1 to disable joystick, default: 0)\n"
1929
            " --joystickhat   Enables movement with the given coolie hat\n"
8655 turbocat 1930
        #endif
8557 maxcodehac 1931
            " --samplerate     Sets the sound sample rate (given in Hz, default: %i)\n"
1932
            " --audiobuffer    Sets the size of the audio buffer (-> sound latency)\n"
1933
            "                        (given in bytes, default: 2048 / (44100 / samplerate))\n"
1934
            " --ignorenumchunks      Ignores the number of chunks in VGAHEAD.*\n"
1935
            "                        (may be useful for some broken mods)\n"
1936
            " --configdir       Directory where config file and save games are stored\n"
1937
#if defined(_arch_dreamcast) || defined(_WIN32)
1938
            "                        (default: current directory)\n"
8655 turbocat 1939
#endif
1940
 
1941
#ifdef _KOLIBRI
1942
            "                        (default: /tmp0/1/wolf4sdl)\n"
8557 maxcodehac 1943
#else
1944
            "                        (default: $HOME/.wolf4sdl)\n"
1945
#endif
1946
#if defined(SPEAR) && !defined(SPEARDEMO)
1947
            " --mission     Mission number to play (0-3)\n"
1948
            "                        (default: 0 -> .sod, 1-3 -> .sd*)\n"
1949
            " --goodtimes            Disable copy protection quiz\n"
1950
#endif
1951
            , defaultSampleRate
1952
        );
1953
        exit(1);
1954
    }
1955
 
1956
    if(sampleRateGiven && !audioBufferGiven)
1957
        param_audiobuffer = 2048 / (44100 / param_samplerate);
1958
}
1959
 
1960
/*
1961
==========================
1962
=
1963
= main
1964
=
1965
==========================
1966
*/
1967
 
1968
int main (int argc, char *argv[])
1969
{
8664 turbocat 1970
#ifdef _KOLIBRI
1971
    setcwd(dirname(argv[0]));
1972
#endif
1973
 
8557 maxcodehac 1974
#if defined(_arch_dreamcast)
1975
    DC_Init();
1976
#else
1977
    CheckParameters(argc, argv);
1978
#endif
1979
    CheckForEpisodes();
1980
    InitGame();
1981
    DemoLoop();
1982
    Quit("Demo loop exited???");
1983
    return 1;
1984
}