SettingsTableViewController.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //
  2. // Settings.m
  3. // SDLPal
  4. //
  5. // Created by palxex on 2017/5/18.
  6. // Copyright © 2017年 SDLPAL team. All rights reserved.
  7. //
  8. #import "SettingsTableViewController.h"
  9. #import "SDLPal_AppDelegate.h"
  10. #import <ActionSheetPicker-3.0/ActionSheetStringPicker.h>
  11. #include "palcfg.h"
  12. #define UIKitLocalizedString(key) [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] localizedStringForKey:key value:@"" table:nil]
  13. @implementation SettingsTableViewController {
  14. NSArray *AudioSampleRates;
  15. NSArray *AudioBufferSizes;
  16. NSArray *OPLSampleRates;
  17. NSArray *CDFormats;
  18. NSArray *MusicFormats;
  19. NSArray *OPLFormats;
  20. NSArray *LogLevels;
  21. NSArray *AspectRatios;
  22. NSArray *allFiles;
  23. NSMutableArray *AvailFiles;
  24. BOOL checkAllFilesIncluded;
  25. NSString *resourceStatus;
  26. AbstractActionSheetPicker *picker;
  27. IBOutlet UIView *transitionView;
  28. IBOutlet UILabel *lblResourceStatus;
  29. IBOutlet UILabel *lblLanguageFile;
  30. IBOutlet UILabel *lblFontFile;
  31. IBOutlet UISwitch *toggleTouchScreenOverlay;
  32. IBOutlet UISwitch *toggleKeepAspect;
  33. IBOutlet UILabel *lblAspectRatio;
  34. IBOutlet UISwitch *toggleSmoothScaling;
  35. IBOutlet UILabel *lblMusicType;
  36. IBOutlet UILabel *lblOPLType;
  37. IBOutlet UILabel *lblOPLRate;
  38. IBOutlet UILabel *lblCDAudioSource;
  39. IBOutlet UISwitch *toggleStereo;
  40. IBOutlet UISwitch *toggleSurroundOPL;
  41. IBOutlet UILabel *lblResampleRate;
  42. IBOutlet UILabel *lblAudioBufferSize;
  43. IBOutlet UISlider *sliderResampleQuality;
  44. IBOutlet UISlider *sliderMusicVolume;
  45. IBOutlet UISlider *sliderSFXVolume;
  46. IBOutlet UILabel *lblLogLevel;
  47. IBOutlet UITextField *textLogFile;
  48. }
  49. - (BOOL)includedInList:(NSArray*)array name:(NSString *)filename {
  50. for( NSString *item in array ) {
  51. if( [filename caseInsensitiveCompare:item] == NSOrderedSame )
  52. return YES;
  53. }
  54. return NO;
  55. }
  56. - (void)viewDidLoad {
  57. [super viewDidLoad];
  58. [transitionView setFrame:self.view.frame];
  59. UILabel* tlabel=[[UILabel alloc] initWithFrame:CGRectMake(0,0, 300, 40)];
  60. tlabel.text=[NSString stringWithUTF8String:PAL_GIT_REVISION];
  61. tlabel.backgroundColor =[UIColor clearColor];
  62. tlabel.adjustsFontSizeToFitWidth=YES;
  63. self.navigationItem.titleView=tlabel;
  64. AudioSampleRates = @[ @"11025", @"22050", @"44100", @"49716" ];
  65. AudioBufferSizes = @[ @"512", @"1024", @"2048", @"4096", @"8192" ];
  66. OPLSampleRates = @[ @"12429", @"24858", @"49716", @"11025", @"22050", @"44100" ];
  67. CDFormats = @[ @"MP3", @"OGG" ];
  68. MusicFormats = @[ @"MIDI", @"RIX", @"MP3", @"OGG" ];
  69. OPLFormats = @[ @"DOSBOX", @"MAME", @"DOSBOXNEW" ];
  70. LogLevels = @[ @"VERBOSE", @"DEBUG", @"INFO", @"WARNING", @"ERROR", @"FATAL" ];
  71. AspectRatios = @[ @"16:10", @"4:3" ];
  72. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
  73. tap.cancelsTouchesInView = NO;
  74. [self.view addGestureRecognizer:tap];
  75. UIRefreshControl *refreshController = [[UIRefreshControl alloc] init];
  76. [refreshController addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
  77. [self.tableView addSubview:refreshController];
  78. [self recheckSharingFolder];
  79. [self readConfigs];
  80. }
  81. -(void)dismissKeyboard
  82. {
  83. [self.view endEditing:YES];
  84. }
  85. -(void)handleRefresh : (id)sender
  86. {
  87. UIRefreshControl *refreshController = sender;
  88. [self recheckSharingFolder];
  89. [refreshController endRefreshing];
  90. }
  91. - (void)recheckSharingFolder {
  92. AvailFiles = [NSMutableArray new];
  93. NSArray *builtinList = @[ @"wor16.fon", @"wor16.asc", @"m.msg"];
  94. NSArray *builtinExtensionList = @[@"exe",@"drv",@"dll",@"rpg",@"mkf",@"avi",@"dat",@"cfg",@"ini"];
  95. allFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSString stringWithUTF8String:UTIL_BasePath()] error:nil];
  96. for( NSString *filename in allFiles ) {
  97. if( ![self includedInList:builtinExtensionList name:filename.pathExtension] &&
  98. ![self includedInList:builtinList name:filename] ) {
  99. [AvailFiles addObject:filename];
  100. }
  101. }
  102. checkAllFilesIncluded = YES;
  103. for( NSString *checkFile in @[@"abc.mkf", @"ball.mkf", @"data.mkf", @"f.mkf", @"fbp.mkf", @"fire.mkf", @"gop.mkf", @"m.msg", @"map.mkf", @"mgo.mkf", @"rgm.mkf", @"rng.mkf", @"sss.mkf", @"word.dat"] ) {
  104. if( ![self includedInList:allFiles name:checkFile] ) {
  105. checkAllFilesIncluded = NO;
  106. break;
  107. }
  108. }
  109. if(!resourceStatus) resourceStatus = lblResourceStatus.text;
  110. lblResourceStatus.text = [NSString stringWithFormat:@"%@%@", resourceStatus, checkAllFilesIncluded ? @"✅" : @"❌" ];
  111. }
  112. typedef void(^SelectedBlock)(NSString *selected);
  113. - (void)showPickerWithTitle:(NSString *)title toLabel:(UILabel*)label inArray:(NSArray*)array {
  114. [self showPickerWithTitle:title toLabel:label inArray:array origin:self.navigationController.navigationBar allowEmpty:NO];
  115. }
  116. - (void)showPickerWithTitle:(NSString *)title toLabel:(UILabel*)label inArray:(NSArray*)array origin:(UIView*)origin {
  117. [self showPickerWithTitle:title toLabel:label inArray:array origin:origin allowEmpty:NO];
  118. }
  119. - (void)showPickerWithTitle:(NSString *)title toLabel:(UILabel*)label inArray:(NSArray*)array origin:(UIView*)origin allowEmpty:(BOOL)allowEmpty {
  120. [self showPickerWithTitle:title toLabel:label inArray:array origin:origin allowEmpty:allowEmpty doneBlock:nil];
  121. }
  122. - (void)showPickerWithTitle:(NSString *)title toLabel:(UILabel*)label inArray:(NSArray*)array origin:(UIView*)origin allowEmpty:(BOOL)allowEmpty doneBlock:(SelectedBlock)doneBlock {
  123. array = allowEmpty ? [array arrayByAddingObject:@""] : array;
  124. picker = [ActionSheetStringPicker showPickerWithTitle:nil
  125. rows:array
  126. initialSelection:[array containsObject:label.text] ? [array indexOfObject:label.text] : 0
  127. doneBlock:^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) {
  128. label.text = array[selectedIndex];
  129. if(doneBlock) doneBlock(label.text);
  130. }
  131. cancelBlock:nil
  132. origin:origin];
  133. }
  134. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  135. //need manually sync with storyboard...
  136. int rows = 1;
  137. switch(section) {
  138. case 0:
  139. rows = 1;
  140. break;
  141. case 1:
  142. rows = 2;
  143. break;
  144. case 2:
  145. rows = 4;
  146. break;
  147. case 3:
  148. rows = [lblMusicType.text isEqualToString:@"RIX"] ? 11 : 4;
  149. break;
  150. case 4:
  151. rows = 2;
  152. break;
  153. default:
  154. break;
  155. }
  156. return rows;
  157. }
  158. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  159. UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
  160. if( indexPath.section == 1 && indexPath.row == 0 ) { //language file
  161. [self showPickerWithTitle:nil toLabel:lblLanguageFile inArray:AvailFiles origin:cell allowEmpty:YES];
  162. }else if( indexPath.section == 1 && indexPath.row == 1 ) { //font file
  163. [self showPickerWithTitle:nil toLabel:lblFontFile inArray:AvailFiles origin:cell allowEmpty:YES];
  164. }else if( indexPath.section == 2 && indexPath.row == 0 ) { //touch overlay
  165. toggleTouchScreenOverlay.on = !toggleTouchScreenOverlay.isOn;
  166. }else if( indexPath.section == 2 && indexPath.row == 1 ) { //keep aspect
  167. toggleKeepAspect.on = !toggleKeepAspect.isOn;
  168. }else if( indexPath.section == 2 && indexPath.row == 2 ) { //aspect ratio
  169. [self showPickerWithTitle:nil toLabel:lblAspectRatio inArray:AspectRatios origin:cell allowEmpty:NO];
  170. }else if( indexPath.section == 2 && indexPath.row == 3 ) { //smooth scaling
  171. toggleSmoothScaling.on = !toggleSmoothScaling.isOn;
  172. }else if( indexPath.section == 3 && indexPath.row == 0 ) { //BGM
  173. [self showPickerWithTitle:nil toLabel:lblMusicType inArray:MusicFormats origin:cell allowEmpty:NO doneBlock:^(NSString *selected) {
  174. [self.tableView reloadData];
  175. }];
  176. }else if( indexPath.section == 3 && indexPath.row == 4 ) { //OPL Type
  177. [self showPickerWithTitle:nil toLabel:lblOPLType inArray:OPLFormats origin:cell];
  178. }else if( indexPath.section == 3 && indexPath.row == 5 ) { //OPL Rate
  179. [self showPickerWithTitle:nil toLabel:lblOPLRate inArray:OPLSampleRates origin:cell];
  180. }else if( indexPath.section == 3 && indexPath.row == 1 ) { //CD Source
  181. [self showPickerWithTitle:nil toLabel:lblCDAudioSource inArray:CDFormats origin:cell];
  182. }else if( indexPath.section == 3 && indexPath.row == 8 ) { //Stereo
  183. toggleStereo.on = !toggleStereo.isOn;
  184. }else if( indexPath.section == 3 && indexPath.row == 9 ) { //Surround
  185. toggleSurroundOPL.on = !toggleSurroundOPL.isOn;
  186. }else if( indexPath.section == 3 && indexPath.row == 6 ) { //SampleRate
  187. [self showPickerWithTitle:nil toLabel:lblResampleRate inArray:AudioSampleRates origin:cell];
  188. }else if( indexPath.section == 3 && indexPath.row == 7 ) { //Buffer size
  189. [self showPickerWithTitle:nil toLabel:lblAudioBufferSize inArray:AudioBufferSizes origin:cell];
  190. }else if( indexPath.section == 4 && indexPath.row == 0 ) { //Log Level
  191. [self showPickerWithTitle:nil toLabel:lblLogLevel inArray:LogLevels origin:cell];
  192. }
  193. }
  194. - (IBAction)btnDefaultClicked:(id)sender {
  195. PAL_LoadConfig(NO);
  196. [self readConfigs];
  197. }
  198. - (IBAction)btnConfirmClicked:(id)sender {
  199. if(!checkAllFilesIncluded){
  200. UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Cannot find data file in the iTunes File Sharing directory",nil)
  201. message:NSLocalizedString(@"NOTE: For copyright reasons data files required to run the game are NOT included.",nil)
  202. preferredStyle:UIAlertControllerStyleAlert];
  203. UIAlertAction *cacelAction = [UIAlertAction actionWithTitle:UIKitLocalizedString(@"OK") style:UIAlertActionStyleDefault handler:nil];
  204. [alert addAction:cacelAction];
  205. [self presentViewController:alert animated:YES completion:nil];
  206. return;
  207. }
  208. [UIView animateWithDuration:0.65
  209. delay:0.0
  210. usingSpringWithDamping:1.0
  211. initialSpringVelocity:0.0
  212. options:UIViewAnimationOptionCurveEaseInOut
  213. animations:^{
  214. CGPoint point = self.navigationController.view.center;
  215. point.y += self.navigationController.view.frame.size.height;
  216. [self.navigationController.view setCenter:point];
  217. } completion:^(BOOL finished) {
  218. [self saveConfigs];
  219. gConfig.fLaunchSetting = NO;
  220. PAL_SaveConfig();
  221. [[SDLPalAppDelegate sharedAppDelegate] launchGame];
  222. }];
  223. }
  224. - (void)readConfigs {
  225. gConfig.fFullScreen = YES; //iOS specific; need this to make sure statusbar hidden in game completely
  226. lblLanguageFile.text = [NSString stringWithUTF8String:gConfig.pszMsgFile ? gConfig.pszMsgFile : ""];
  227. lblFontFile.text = [NSString stringWithUTF8String:gConfig.pszFontFile ? gConfig.pszFontFile : ""];
  228. textLogFile.text = [NSString stringWithUTF8String:gConfig.pszLogFile ? gConfig.pszLogFile : ""];
  229. toggleStereo.on = gConfig.iAudioChannels == 2;
  230. toggleSurroundOPL.on = gConfig.fUseSurroundOPL;
  231. toggleTouchScreenOverlay.on = gConfig.fUseTouchOverlay;
  232. toggleKeepAspect.on = gConfig.fKeepAspectRatio;
  233. lblAspectRatio.text = [NSString stringWithFormat:@"%d:%d",gConfig.dwAspectX,gConfig.dwAspectY];
  234. toggleSmoothScaling.on = gConfig.pszScaleQuality ? strncmp(gConfig.pszScaleQuality, "0", sizeof(char)) != 0 : NO;
  235. lblMusicType.text = MusicFormats[gConfig.eMusicType];
  236. lblOPLType.text = OPLFormats[gConfig.eOPLType];
  237. lblOPLRate.text = [NSString stringWithFormat:@"%d",gConfig.iOPLSampleRate];
  238. lblCDAudioSource.text = CDFormats[gConfig.eCDType-MUSIC_OGG];
  239. lblResampleRate.text = [NSString stringWithFormat:@"%d",gConfig.iSampleRate];
  240. lblAudioBufferSize.text = [NSString stringWithFormat:@"%d",gConfig.wAudioBufferSize];
  241. sliderMusicVolume.value = gConfig.iMusicVolume;
  242. sliderSFXVolume.value = gConfig.iSoundVolume;
  243. sliderResampleQuality.value = gConfig.iResampleQuality;
  244. lblLogLevel.text = LogLevels[gConfig.iLogLevel];
  245. [self.tableView reloadData];
  246. }
  247. - (void)saveConfigs {
  248. gConfig.pszMsgFile = [lblLanguageFile.text length] == 0 ? NULL : strdup([[lblLanguageFile text] UTF8String]);
  249. gConfig.pszFontFile = [lblLanguageFile.text length] == 0 ? NULL : strdup([[lblFontFile text] UTF8String]);
  250. gConfig.pszLogFile = [lblLanguageFile.text length] == 0 ? NULL : strdup([[textLogFile text] UTF8String]);
  251. gConfig.iAudioChannels = toggleStereo.isOn ? 2 : 1;
  252. gConfig.fUseSurroundOPL = toggleSurroundOPL.isOn;
  253. gConfig.fKeepAspectRatio = toggleKeepAspect.isOn;
  254. gConfig.dwAspectX = [[lblAspectRatio.text componentsSeparatedByString:@":"][0] intValue];
  255. gConfig.dwAspectY = [[lblAspectRatio.text componentsSeparatedByString:@":"][1] intValue];
  256. gConfig.fUseTouchOverlay = toggleTouchScreenOverlay.isOn;
  257. gConfig.pszScaleQuality = strdup(toggleSmoothScaling.on ? "1" : "0");
  258. gConfig.eMusicType = (MUSICTYPE)[MusicFormats indexOfObject:lblMusicType.text];
  259. gConfig.eOPLType = (OPLTYPE )[OPLFormats indexOfObject:lblOPLType.text];
  260. gConfig.iOPLSampleRate = [lblOPLRate.text intValue];
  261. gConfig.eCDType = (MUSICTYPE)[CDFormats indexOfObject:lblCDAudioSource.text]+MUSIC_OGG;
  262. gConfig.iSampleRate = [lblResampleRate.text intValue];
  263. gConfig.wAudioBufferSize = [lblAudioBufferSize.text intValue];
  264. gConfig.iMusicVolume = sliderMusicVolume.value;
  265. gConfig.iSoundVolume = sliderSFXVolume.value;
  266. gConfig.iResampleQuality = sliderResampleQuality.value;
  267. gConfig.iLogLevel = (LOGLEVEL)[LogLevels indexOfObject:lblLogLevel.text];
  268. }
  269. @end