Subversion Repositories eduke32

Rev

Rev 4644 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2396 hendricks2 1
// Objective-C programmers shall recoil in fear at this mess
2
 
3
#import <Cocoa/Cocoa.h>
4
 
5
#include "duke3d.h"
2430 helixhorne 6
#include "game.h"
2726 hendricks2 7
#include "common.h"
8
#include "common_game.h"
2396 hendricks2 9
#include "build.h"
10
#include "compat.h"
11
#include "baselayer.h"
12
#include "grpscan.h"
13
 
14
#import "GrpFile.game.h"
15
#import "GameListSource.game.h"
16
 
2429 helixhorne 17
static id nsapp;
18
 
2396 hendricks2 19
static struct {
20
    int fullscreen;
21
    int xdim3d, ydim3d, bpp3d;
22
    int forcesetup;
23
    char selectedgrp[BMAX_PATH+1];
24
    int game;
25
    int samplerate, bitspersample, channels;
26
} settings;
27
 
28
static struct soundQuality_t {
29
    int frequency;
30
    int samplesize;
31
    int channels;
32
} * soundQualities = 0;
33
 
34
 
35
@interface StartupWinController : NSWindowController
36
{
37
    NSMutableArray *modeslist3d;
38
    GameListSource *gamelistsrc;
2431 helixhorne 39
 
2396 hendricks2 40
    IBOutlet NSButton *alwaysShowButton;
41
    IBOutlet NSButton *fullscreenButton;
42
    IBOutlet NSTextView *messagesView;
43
    IBOutlet NSTabView *tabView;
44
    IBOutlet NSPopUpButton *videoMode3DPUButton;
45
    IBOutlet NSPopUpButton *soundQualityPUButton;
46
    IBOutlet NSScrollView *gameList;
2431 helixhorne 47
 
2396 hendricks2 48
    IBOutlet NSButton *cancelButton;
49
    IBOutlet NSButton *startButton;
50
}
51
 
52
- (void)dealloc;
53
- (void)populateVideoModes:(BOOL)firstTime;
54
- (void)populateSoundQuality:(BOOL)firstTime;
55
 
56
- (IBAction)alwaysShowClicked:(id)sender;
57
- (IBAction)fullscreenClicked:(id)sender;
58
 
59
- (IBAction)cancel:(id)sender;
60
- (IBAction)start:(id)sender;
61
 
62
- (void)setupRunMode;
63
- (void)setupMessagesMode;
64
- (void)putsMessage:(NSString *)str;
65
- (void)setTitle:(NSString *)str;
66
 
67
@end
68
 
69
@implementation StartupWinController
70
 
71
- (void)dealloc
72
{
73
    [gamelistsrc release];
74
    [modeslist3d release];
75
    [super dealloc];
76
}
77
 
78
- (void)populateVideoModes:(BOOL)firstTime
79
{
80
    int i, mode3d, fullscreen = ([fullscreenButton state] == NSOnState);
81
    int idx3d = -1;
4644 hendricks2 82
    int xdim = 0, ydim = 0, bpp = 0;
2431 helixhorne 83
 
2396 hendricks2 84
    if (firstTime) {
85
        xdim = settings.xdim3d;
86
        ydim = settings.ydim3d;
87
        bpp  = settings.bpp3d;
88
    } else {
89
        mode3d = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
90
        if (mode3d >= 0) {
91
            xdim = validmode[mode3d].xdim;
92
            ydim = validmode[mode3d].ydim;
93
            bpp = validmode[mode3d].bpp;
94
        }
2431 helixhorne 95
 
2396 hendricks2 96
    }
97
    mode3d = checkvideomode(&xdim, &ydim, bpp, fullscreen, 1);
98
    if (mode3d < 0) {
99
        int i, cd[] = { 32, 24, 16, 15, 8, 0 };
100
        for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; }
101
        for ( ; cd[i]; i++) {
102
            mode3d = checkvideomode(&xdim, &ydim, cd[i], fullscreen, 1);
103
            if (mode3d < 0) continue;
104
            break;
105
        }
106
    }
2431 helixhorne 107
 
2396 hendricks2 108
    [modeslist3d release];
109
    [videoMode3DPUButton removeAllItems];
2431 helixhorne 110
 
2396 hendricks2 111
    modeslist3d = [[NSMutableArray alloc] init];
2431 helixhorne 112
 
2396 hendricks2 113
    for (i = 0; i < validmodecnt; i++) {
114
        if (fullscreen == validmode[i].fs) {
115
            if (i == mode3d) idx3d = [modeslist3d count];
116
            [modeslist3d addObject:[NSNumber numberWithInt:i]];
117
            [videoMode3DPUButton addItemWithTitle:[NSString stringWithFormat:@"%d %C %d %d-bpp",
118
                                                   validmode[i].xdim, 0xd7, validmode[i].ydim, validmode[i].bpp]];
119
        }
120
    }
2431 helixhorne 121
 
2396 hendricks2 122
    if (idx3d >= 0) [videoMode3DPUButton selectItemAtIndex:idx3d];
123
}
124
 
125
- (void)populateSoundQuality:(BOOL)firstTime
126
{
127
    int i, curidx = -1;
2431 helixhorne 128
 
2396 hendricks2 129
    [soundQualityPUButton removeAllItems];
2431 helixhorne 130
 
2396 hendricks2 131
    for (i = 0; soundQualities[i].frequency > 0; i++) {
132
        const char *ch;
133
        switch (soundQualities[i].channels) {
134
            case 1: ch = "Mono"; break;
135
            case 2: ch = "Stereo"; break;
136
            default: ch = "?"; break;
137
        }
2431 helixhorne 138
 
2396 hendricks2 139
        NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s",
140
                            soundQualities[i].frequency / 1000,
141
                            soundQualities[i].samplesize,
142
                            ch
143
                     ];
144
        [soundQualityPUButton addItemWithTitle:s];
2431 helixhorne 145
 
2396 hendricks2 146
        if (firstTime &&
147
            soundQualities[i].frequency == settings.samplerate &&
148
            soundQualities[i].samplesize == settings.bitspersample &&
149
            soundQualities[i].channels == settings.channels) {
150
            curidx = i;
151
        }
152
    }
2431 helixhorne 153
 
2396 hendricks2 154
    if (firstTime && curidx < 0) {
155
        soundQualities[i].frequency = settings.samplerate;
156
        soundQualities[i].samplesize = settings.bitspersample;
157
        soundQualities[i].channels = settings.channels;
2431 helixhorne 158
 
2396 hendricks2 159
        const char *ch;
160
        switch (soundQualities[i].channels) {
161
            case 1: ch = "Mono"; break;
162
            case 2: ch = "Stereo"; break;
163
            default: ch = "?"; break;
164
        }
165
        NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s",
166
                       soundQualities[i].frequency / 1000,
167
                       soundQualities[i].samplesize,
168
                       ch
169
                       ];
170
        [soundQualityPUButton addItemWithTitle:s];
2431 helixhorne 171
 
2396 hendricks2 172
        curidx = i++;
173
        soundQualities[i].frequency = -1;
174
    }
2431 helixhorne 175
 
2396 hendricks2 176
    if (curidx >= 0) {
177
        [soundQualityPUButton selectItemAtIndex:curidx];
178
    }
179
}
180
 
181
- (IBAction)alwaysShowClicked:(id)sender
182
{
4647 hendricks2 183
    UNREFERENCED_PARAMETER(sender);
2396 hendricks2 184
}
185
 
186
- (IBAction)fullscreenClicked:(id)sender
187
{
4647 hendricks2 188
    UNREFERENCED_PARAMETER(sender);
4644 hendricks2 189
 
2396 hendricks2 190
    [self populateVideoModes:NO];
191
}
192
 
193
- (IBAction)cancel:(id)sender
194
{
4647 hendricks2 195
    UNREFERENCED_PARAMETER(sender);
4644 hendricks2 196
 
2429 helixhorne 197
    [nsapp abortModal];
2396 hendricks2 198
}
199
 
200
- (IBAction)start:(id)sender
201
{
4647 hendricks2 202
    UNREFERENCED_PARAMETER(sender);
4644 hendricks2 203
 
2396 hendricks2 204
    int mode = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
205
    if (mode >= 0) {
206
        settings.xdim3d = validmode[mode].xdim;
207
        settings.ydim3d = validmode[mode].ydim;
208
        settings.bpp3d = validmode[mode].bpp;
209
        settings.fullscreen = validmode[mode].fs;
210
    }
2431 helixhorne 211
 
2396 hendricks2 212
    int quality = [soundQualityPUButton indexOfSelectedItem];
213
    if (quality >= 0) {
214
        settings.samplerate = soundQualities[quality].frequency;
215
        settings.bitspersample = soundQualities[quality].samplesize;
216
        settings.channels = soundQualities[quality].channels;
217
    }
2431 helixhorne 218
 
2396 hendricks2 219
    int row = [[gameList documentView] selectedRow];
220
    if (row >= 0) {
221
        struct grpfile *p = [[gamelistsrc grpAtIndex:row] entryptr];
222
        if (p) {
223
            strcpy(settings.selectedgrp, p->name);
224
            settings.game = p->game;
225
        }
226
    }
2431 helixhorne 227
 
2396 hendricks2 228
    settings.forcesetup = [alwaysShowButton state] == NSOnState;
2431 helixhorne 229
 
2429 helixhorne 230
    [nsapp stopModal];
2396 hendricks2 231
}
232
 
233
- (void)setupRunMode
234
{
235
    getvalidmodes();
2431 helixhorne 236
 
2396 hendricks2 237
    [fullscreenButton setState: (settings.fullscreen ? NSOnState : NSOffState)];
238
    [alwaysShowButton setState: (settings.forcesetup ? NSOnState : NSOffState)];
239
    [self populateVideoModes:YES];
240
    [self populateSoundQuality:YES];
2431 helixhorne 241
 
2396 hendricks2 242
    // enable all the controls on the Configuration page
243
    NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
244
    NSControl *control;
2537 hendricks2 245
    while ((control = [enumerator nextObject])) [control setEnabled:true];
2431 helixhorne 246
 
2396 hendricks2 247
    gamelistsrc = [[GameListSource alloc] init];
248
    [[gameList documentView] setDataSource:gamelistsrc];
249
    [[gameList documentView] deselectAll:nil];
2431 helixhorne 250
 
4644 hendricks2 251
    int row = [gamelistsrc findIndexForGrpname:[NSString stringWithCString:settings.selectedgrp encoding:NSUTF8StringEncoding]];
2396 hendricks2 252
    if (row >= 0) {
253
        [[gameList documentView] scrollRowToVisible:row];
254
#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
255
        [[gameList documentView] selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
256
#else
257
        [[gameList documentView] selectRow:row byExtendingSelection:NO];
258
#endif
259
    }
2431 helixhorne 260
 
2396 hendricks2 261
    [cancelButton setEnabled:true];
262
    [startButton setEnabled:true];
2431 helixhorne 263
 
2396 hendricks2 264
    [tabView selectTabViewItemAtIndex:0];
4647 hendricks2 265
    [NSCursor unhide]; // Why should I need to do this?
2396 hendricks2 266
}
267
 
268
- (void)setupMessagesMode
269
{
270
    [tabView selectTabViewItemAtIndex:2];
2431 helixhorne 271
 
2396 hendricks2 272
    // disable all the controls on the Configuration page except "always show", so the
273
    // user can enable it if they want to while waiting for something else to happen
274
    NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
275
    NSControl *control;
2537 hendricks2 276
    while ((control = [enumerator nextObject])) {
2396 hendricks2 277
        if (control == alwaysShowButton) continue;
278
        [control setEnabled:false];
279
    }
2431 helixhorne 280
 
2396 hendricks2 281
    [cancelButton setEnabled:false];
282
    [startButton setEnabled:false];
283
}
284
 
285
- (void)putsMessage:(NSString *)str
286
{
287
    NSRange end;
288
    NSTextStorage *text = [messagesView textStorage];
289
    BOOL shouldAutoScroll;
2431 helixhorne 290
 
2396 hendricks2 291
    shouldAutoScroll = ((int)NSMaxY([messagesView bounds]) == (int)NSMaxY([messagesView visibleRect]));
2431 helixhorne 292
 
2396 hendricks2 293
    end.location = [text length];
294
    end.length = 0;
2431 helixhorne 295
 
2396 hendricks2 296
    [text beginEditing];
297
    [messagesView replaceCharactersInRange:end withString:str];
298
    [text endEditing];
2431 helixhorne 299
 
2396 hendricks2 300
    if (shouldAutoScroll) {
301
        end.location = [text length];
302
        end.length = 0;
303
        [messagesView scrollRangeToVisible:end];
304
    }
305
}
306
 
307
- (void)setTitle:(NSString *)str
308
{
309
    [[self window] setTitle:str];
310
}
311
 
312
@end
313
 
314
static StartupWinController *startwin = nil;
315
 
316
int startwin_open(void)
317
{
2429 helixhorne 318
    // fix for "ld: absolute address to symbol _NSApp in a different linkage unit not supported"
319
    // (OS X 10.6) when building for PPC
320
    nsapp = [NSApplication sharedApplication];
321
 
2396 hendricks2 322
    if (startwin != nil) return 1;
2431 helixhorne 323
 
2396 hendricks2 324
    startwin = [[StartupWinController alloc] initWithWindowNibName:@"startwin.game"];
325
    if (startwin == nil) return -1;
2431 helixhorne 326
 
2396 hendricks2 327
    {
328
        static int soundQualityFrequencies[] = { 48000, 44100, 32000, 24000, 22050 };
329
        static int soundQualitySampleSizes[] = { 16, 8 };
330
        static int soundQualityChannels[]    = { 2, 1 };
4644 hendricks2 331
        size_t f, b, c, i;
2431 helixhorne 332
 
2396 hendricks2 333
        i = sizeof(soundQualityFrequencies) *
334
            sizeof(soundQualitySampleSizes) *
335
            sizeof(soundQualityChannels) /
336
            sizeof(int) + 2;    // one for the terminator, one for a custom setting
337
        soundQualities = (struct soundQuality_t *) malloc(i * sizeof(struct soundQuality_t));
2431 helixhorne 338
 
2396 hendricks2 339
        i = 0;
340
        for (c = 0; c < sizeof(soundQualityChannels) / sizeof(int); c++) {
341
            for (b = 0; b < sizeof(soundQualitySampleSizes) / sizeof(int); b++) {
342
                for (f = 0; f < sizeof(soundQualityFrequencies) / sizeof(int); f++) {
343
                    soundQualities[i].frequency = soundQualityFrequencies[f];
344
                    soundQualities[i].samplesize = soundQualitySampleSizes[b];
345
                    soundQualities[i].channels = soundQualityChannels[c];
2431 helixhorne 346
 
2396 hendricks2 347
                    i++;
348
                }
349
            }
350
        }
2431 helixhorne 351
 
2396 hendricks2 352
        soundQualities[i].frequency = -1;
353
    }
2431 helixhorne 354
 
2396 hendricks2 355
    [startwin setupMessagesMode];
356
    [startwin showWindow:nil];
2431 helixhorne 357
 
2396 hendricks2 358
    return 0;
359
}
360
 
361
int startwin_close(void)
362
{
363
    if (startwin == nil) return 1;
2431 helixhorne 364
 
2396 hendricks2 365
    [startwin close];
366
    [startwin release];
367
    startwin = nil;
2431 helixhorne 368
 
2396 hendricks2 369
    free(soundQualities);
2431 helixhorne 370
 
2396 hendricks2 371
    return 0;
372
}
373
 
374
int startwin_puts(const char *s)
375
{
376
    NSString *ns;
2431 helixhorne 377
 
2396 hendricks2 378
    if (!s) return -1;
379
    if (startwin == nil) return 1;
2431 helixhorne 380
 
4644 hendricks2 381
    ns = [[NSString alloc] initWithUTF8String:s];
2396 hendricks2 382
    [startwin putsMessage:ns];
383
    [ns release];
2431 helixhorne 384
 
2396 hendricks2 385
    return 0;
386
}
387
 
388
int startwin_settitle(const char *s)
389
{
390
    NSString *ns;
2431 helixhorne 391
 
2396 hendricks2 392
    if (!s) return -1;
393
    if (startwin == nil) return 1;
2431 helixhorne 394
 
4644 hendricks2 395
    ns = [[NSString alloc] initWithUTF8String:s];
2396 hendricks2 396
    [startwin setTitle:ns];
397
    [ns release];
2431 helixhorne 398
 
2396 hendricks2 399
    return 0;
400
}
401
 
402
int startwin_idle(void *v)
403
{
4647 hendricks2 404
    UNREFERENCED_PARAMETER(v);
405
 
2396 hendricks2 406
    if (startwin) [[startwin window] displayIfNeeded];
407
    return 0;
408
}
409
 
410
 
411
int startwin_run(void)
412
{
413
    int retval;
2431 helixhorne 414
 
2396 hendricks2 415
    if (startwin == nil) return 0;
2431 helixhorne 416
 
2430 helixhorne 417
    settings.fullscreen = ud.config.ScreenMode;
418
    settings.xdim3d = ud.config.ScreenWidth;
419
    settings.ydim3d = ud.config.ScreenHeight;
420
    settings.bpp3d = ud.config.ScreenBPP;
421
    settings.samplerate = ud.config.MixRate;
422
    settings.bitspersample = ud.config.NumBits;
423
    settings.channels = ud.config.NumChannels;
424
    settings.forcesetup = ud.config.ForceSetup;
425
//    settings.game = gametype;
2726 hendricks2 426
    strncpy(settings.selectedgrp, G_GrpFile(), BMAX_PATH);
2431 helixhorne 427
 
2396 hendricks2 428
    [startwin setupRunMode];
2431 helixhorne 429
 
2429 helixhorne 430
    switch ([nsapp runModalForWindow:[startwin window]]) {
2396 hendricks2 431
        case NSRunStoppedResponse: retval = 1; break;
432
        case NSRunAbortedResponse: retval = 0; break;
433
        default: retval = -1;
434
    }
2431 helixhorne 435
 
2396 hendricks2 436
    [startwin setupMessagesMode];
2431 helixhorne 437
 
2396 hendricks2 438
    if (retval) {
2430 helixhorne 439
        ud.config.ScreenMode = settings.fullscreen;
440
        ud.config.ScreenWidth = settings.xdim3d;
441
        ud.config.ScreenHeight = settings.ydim3d;
442
        ud.config.ScreenBPP = settings.bpp3d;
443
        ud.config.MixRate = settings.samplerate;
444
        ud.config.NumBits = settings.bitspersample;
2431 helixhorne 445
        ud.config.NumChannels = settings.channels;
2430 helixhorne 446
        ud.config.ForceSetup = settings.forcesetup;
2726 hendricks2 447
        clearGrpNamePtr();
448
        g_grpNamePtr = dup_filename(settings.selectedgrp);
2430 helixhorne 449
//        gametype = settings.game;
2396 hendricks2 450
    }
2431 helixhorne 451
 
2396 hendricks2 452
    return retval;
453
}