//------------------------------------------------------------------------- /* Copyright (C) 2007 Jonathon Fowler This file is part of JFShadowWarrior Shadow Warrior is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- #import #include "compat.h" #include "types.h" #include "build.h" #include "baselayer.h" #include "grpscan.h" #include "gamedefs.h" #include "config.h" #import "GrpFile.game.h" #import "GameListSource.game.h" static struct { int fullscreen; int xdim3d, ydim3d, bpp3d; int forcesetup; char selectedgrp[BMAX_PATH+1]; int samplerate, bitspersample, channels; int usemouse, usejoystick; } settings; static struct soundQuality_t { int frequency; int samplesize; int channels; } * soundQualities = 0; @interface StartupWinController : NSWindowController { NSMutableArray *modeslist3d; GameListSource *gamelistsrc; IBOutlet NSButton *alwaysShowButton; IBOutlet NSButton *fullscreenButton; IBOutlet NSButton *useMouseButton; IBOutlet NSButton *useJoystickButton; IBOutlet NSTextView *messagesView; IBOutlet NSTabView *tabView; IBOutlet NSPopUpButton *videoMode3DPUButton; IBOutlet NSPopUpButton *soundQualityPUButton; IBOutlet NSScrollView *gameList; IBOutlet NSButton *cancelButton; IBOutlet NSButton *startButton; } - (void)dealloc; - (void)populateVideoModes:(BOOL)firstTime; - (void)populateSoundQuality:(BOOL)firstTime; - (IBAction)alwaysShowClicked:(id)sender; - (IBAction)fullscreenClicked:(id)sender; - (IBAction)cancel:(id)sender; - (IBAction)start:(id)sender; - (void)setupRunMode; - (void)setupMessagesMode; - (void)putsMessage:(NSString *)str; - (void)setTitle:(NSString *)str; @end @implementation StartupWinController - (void)dealloc { [gamelistsrc release]; [modeslist3d release]; [super dealloc]; } - (void)populateVideoModes:(BOOL)firstTime { int i, mode3d, fullscreen = ([fullscreenButton state] == NSOnState); int idx3d = -1; int xdim, ydim, bpp; if (firstTime) { xdim = settings.xdim3d; ydim = settings.ydim3d; bpp = settings.bpp3d; } else { mode3d = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue]; if (mode3d >= 0) { xdim = validmode[mode3d].xdim; ydim = validmode[mode3d].ydim; bpp = validmode[mode3d].bpp; } } mode3d = checkvideomode(&xdim, &ydim, bpp, fullscreen, 1); if (mode3d < 0) { int i, cd[] = { 32, 24, 16, 15, 8, 0 }; for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; } for ( ; cd[i]; i++) { mode3d = checkvideomode(&xdim, &ydim, cd[i], fullscreen, 1); if (mode3d < 0) continue; break; } } [modeslist3d release]; [videoMode3DPUButton removeAllItems]; modeslist3d = [[NSMutableArray alloc] init]; for (i = 0; i < validmodecnt; i++) { if (fullscreen == validmode[i].fs) { if (i == mode3d) idx3d = [modeslist3d count]; [modeslist3d addObject:[NSNumber numberWithInt:i]]; [videoMode3DPUButton addItemWithTitle:[NSString stringWithFormat:@"%d %C %d %d-bpp", validmode[i].xdim, 0xd7, validmode[i].ydim, validmode[i].bpp]]; } } if (idx3d >= 0) [videoMode3DPUButton selectItemAtIndex:idx3d]; } - (void)populateSoundQuality:(BOOL)firstTime { int i, curidx = -1; [soundQualityPUButton removeAllItems]; for (i = 0; soundQualities[i].frequency > 0; i++) { const char *ch; switch (soundQualities[i].channels) { case 1: ch = "Mono"; break; case 2: ch = "Stereo"; break; default: ch = "?"; break; } NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s", soundQualities[i].frequency / 1000, soundQualities[i].samplesize, ch ]; [soundQualityPUButton addItemWithTitle:s]; if (firstTime && soundQualities[i].frequency == settings.samplerate && soundQualities[i].samplesize == settings.bitspersample && soundQualities[i].channels == settings.channels) { curidx = i; } } if (firstTime && curidx < 0) { soundQualities[i].frequency = settings.samplerate; soundQualities[i].samplesize = settings.bitspersample; soundQualities[i].channels = settings.channels; const char *ch; switch (soundQualities[i].channels) { case 1: ch = "Mono"; break; case 2: ch = "Stereo"; break; default: ch = "?"; break; } NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s", soundQualities[i].frequency / 1000, soundQualities[i].samplesize, ch ]; [soundQualityPUButton addItemWithTitle:s]; curidx = i++; soundQualities[i].frequency = -1; } if (curidx >= 0) { [soundQualityPUButton selectItemAtIndex:curidx]; } } - (IBAction)alwaysShowClicked:(id)sender { } - (IBAction)fullscreenClicked:(id)sender { [self populateVideoModes:NO]; } - (IBAction)cancel:(id)sender { [NSApp abortModal]; } - (IBAction)start:(id)sender { int mode = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue]; if (mode >= 0) { settings.xdim3d = validmode[mode].xdim; settings.ydim3d = validmode[mode].ydim; settings.bpp3d = validmode[mode].bpp; settings.fullscreen = validmode[mode].fs; } int quality = [soundQualityPUButton indexOfSelectedItem]; if (quality >= 0) { settings.samplerate = soundQualities[quality].frequency; settings.bitspersample = soundQualities[quality].samplesize; settings.channels = soundQualities[quality].channels; } int row = [[gameList documentView] selectedRow]; if (row >= 0) { struct grpfile *p = [[gamelistsrc grpAtIndex:row] entryptr]; if (p) { strcpy(settings.selectedgrp, p->name); } } settings.usemouse = [useMouseButton state] == NSOnState; settings.usejoystick = [useJoystickButton state] == NSOnState; settings.forcesetup = [alwaysShowButton state] == NSOnState; [NSApp stopModal]; } - (void)setupRunMode { getvalidmodes(); [fullscreenButton setState: (settings.fullscreen ? NSOnState : NSOffState)]; [alwaysShowButton setState: (settings.forcesetup ? NSOnState : NSOffState)]; [useMouseButton setState: (settings.usemouse ? NSOnState : NSOffState)]; [useJoystickButton setState: (settings.usejoystick ? NSOnState : NSOffState)]; [self populateVideoModes:YES]; [self populateSoundQuality:YES]; // enable all the controls on the Configuration page NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator]; NSControl *control; while ((control = [enumerator nextObject])) { [control setEnabled:true]; } gamelistsrc = [[GameListSource alloc] init]; [[gameList documentView] setDataSource:gamelistsrc]; [[gameList documentView] deselectAll:nil]; int row = [gamelistsrc findIndexForGrpname:[NSString stringWithUTF8String:settings.selectedgrp]]; if (row >= 0) { [[gameList documentView] scrollRowToVisible:row]; [[gameList documentView] selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; } [cancelButton setEnabled:true]; [startButton setEnabled:true]; [tabView selectTabViewItemAtIndex:0]; [NSCursor unhide]; // Why should I need to do this? } - (void)setupMessagesMode { [tabView selectTabViewItemAtIndex:2]; // disable all the controls on the Configuration page except "always show", so the // user can enable it if they want to while waiting for something else to happen NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator]; NSControl *control; while ((control = [enumerator nextObject])) { if (control == alwaysShowButton) continue; [control setEnabled:false]; } [cancelButton setEnabled:false]; [startButton setEnabled:false]; } - (void)putsMessage:(NSString *)str { NSRange end; NSTextStorage *text = [messagesView textStorage]; BOOL shouldAutoScroll; shouldAutoScroll = ((int)NSMaxY([messagesView bounds]) == (int)NSMaxY([messagesView visibleRect])); end.location = [text length]; end.length = 0; [text beginEditing]; [messagesView replaceCharactersInRange:end withString:str]; [text endEditing]; if (shouldAutoScroll) { end.location = [text length]; end.length = 0; [messagesView scrollRangeToVisible:end]; } } - (void)setTitle:(NSString *)str { [[self window] setTitle:str]; } @end static StartupWinController *startwin = nil; int startwin_open(void) { if (startwin != nil) return 1; startwin = [[StartupWinController alloc] initWithWindowNibName:@"startwin.game"]; if (startwin == nil) return -1; { static unsigned soundQualityFrequencies[] = { 44100, 22050, 11025 }; static unsigned soundQualitySampleSizes[] = { 16, 8 }; static unsigned soundQualityChannels[] = { 2, 1 }; unsigned f, b, c, i; i = sizeof(soundQualityFrequencies) * sizeof(soundQualitySampleSizes) * sizeof(soundQualityChannels) / sizeof(int) + 2; // one for the terminator, one for a custom setting soundQualities = (struct soundQuality_t *) malloc(i * sizeof(struct soundQuality_t)); i = 0; for (c = 0; c < sizeof(soundQualityChannels) / sizeof(int); c++) { for (b = 0; b < sizeof(soundQualitySampleSizes) / sizeof(int); b++) { for (f = 0; f < sizeof(soundQualityFrequencies) / sizeof(int); f++) { soundQualities[i].frequency = soundQualityFrequencies[f]; soundQualities[i].samplesize = soundQualitySampleSizes[b]; soundQualities[i].channels = soundQualityChannels[c]; i++; } } } soundQualities[i].frequency = -1; } [startwin setupMessagesMode]; [startwin showWindow:nil]; return 0; } int startwin_close(void) { if (startwin == nil) return 1; [startwin close]; [startwin release]; startwin = nil; return 0; } int startwin_puts(const char *s) { NSString *ns; if (!s) return -1; if (startwin == nil) return 1; ns = [[NSString alloc] initWithCString:s]; [startwin putsMessage:ns]; [ns release]; return 0; } int startwin_settitle(const char *s) { NSString *ns; if (!s) return -1; if (startwin == nil) return 1; ns = [[NSString alloc] initWithCString:s]; [startwin setTitle:ns]; [ns release]; return 0; } int startwin_idle(void *v) { if (startwin) [[startwin window] displayIfNeeded]; return 0; } extern char* grpfile; extern int32 ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP, ForceSetup, UseMouse, UseJoystick; int startwin_run(void) { int retval; if (startwin == nil) return 0; ScanGroups(); settings.fullscreen = ScreenMode; settings.xdim3d = ScreenWidth; settings.ydim3d = ScreenHeight; settings.bpp3d = ScreenBPP; settings.samplerate = MixRate; settings.bitspersample = NumBits; settings.channels = NumChannels; settings.usemouse = UseMouse; settings.usejoystick = UseJoystick; settings.forcesetup = ForceSetup; strncpy(settings.selectedgrp, grpfile, BMAX_PATH); [startwin setupRunMode]; switch ([NSApp runModalForWindow:[startwin window]]) { #ifdef MAC_OS_X_VERSION_10_9 case NSModalResponseStop: retval = 1; break; case NSModalResponseAbort: retval = 0; break; #else case NSRunStoppedResponse: retval = 1; break; case NSRunAbortedResponse: retval = 0; break; #endif default: retval = -1; } [startwin setupMessagesMode]; if (retval) { ScreenMode = settings.fullscreen; ScreenWidth = settings.xdim3d; ScreenHeight = settings.ydim3d; ScreenBPP = settings.bpp3d; MixRate = settings.samplerate; NumBits = settings.bitspersample; NumChannels = settings.channels; UseMouse = settings.usemouse; UseJoystick = settings.usejoystick; ForceSetup = settings.forcesetup; grpfile = settings.selectedgrp; } return retval; }