settings.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // settings.cpp
  19. // Project: Nostril (aka Postal)
  20. //
  21. // This module impliments the CSettings class, which provides a standardized
  22. // method of working with all the various game settings.
  23. //
  24. // History:
  25. // 11/26/96 MJR Started.
  26. // 12/04/96 MJR Implimented all the static stuff.
  27. // 04/16/97 MJR Added test for read-only file when writing prefs, and
  28. // returned special error code to indicate such a thing.
  29. //
  30. // 05/08/97 JMI Added conditions for compiler versions' STL
  31. // differences.
  32. //
  33. // 06/09/97 MJR Fixed memory leak -- forgot to free the memory that was
  34. // allocated by PreDemo().
  35. //
  36. // 06/29/97 MJR Replaced STL vector with an RSP list. STL is an evil
  37. // entity that should be banished from the face of the earth.
  38. // Whoever suggested we use it should be shot. (Good thing
  39. // I'm the president -- it's against the rules to shoot me.)
  40. //
  41. // 07/10/97 MJR Removed use of non-ANSI "t" in mode string for file open.
  42. //
  43. ////////////////////////////////////////////////////////////////////////////////
  44. #define SETTINGS_CPP
  45. #include "RSPiX.h"
  46. #ifdef PATHS_IN_INCLUDES
  47. #include "WishPiX/Prefs/prefs.h"
  48. #else
  49. #include "prefs.h"
  50. #endif
  51. #include "main.h"
  52. #include "settings.h"
  53. ////////////////////////////////////////////////////////////////////////////////
  54. // Macros/types/etc.
  55. ////////////////////////////////////////////////////////////////////////////////
  56. ////////////////////////////////////////////////////////////////////////////////
  57. // Variables/data
  58. ////////////////////////////////////////////////////////////////////////////////
  59. // Pointer to container for all CSettings objects. This is a pointer to the
  60. // container for reasons explained in the constructor. I'm relying on what I
  61. // understand to be the defined C++ startup sequence: (1) initialize all static
  62. // data without explicit initializers to 0, then (2) initialize global static
  63. // objects in a translation unit (which gets into the whole order problem).
  64. // I take that to mean that this will be set to 0 before any code is executed.
  65. CSettings::SETTINGS* CSettings::ms_pSettings;
  66. // Pointer to memory used for memory file. While it isn't as critical as
  67. // the above pointer, this one isn't explicitly set to 0 for the same reasons.
  68. void* CSettings::ms_pMem;
  69. ////////////////////////////////////////////////////////////////////////////////
  70. // Function prototypes
  71. ////////////////////////////////////////////////////////////////////////////////
  72. ////////////////////////////////////////////////////////////////////////////////
  73. //
  74. // Default (and only) constructor
  75. //
  76. ////////////////////////////////////////////////////////////////////////////////
  77. CSettings::CSettings(void)
  78. {
  79. // If the container itself doesn't exist yet, create it now. This sucks
  80. // because we can't inform the caller if an error occurs. However, there
  81. // wasn't much choice, as the alternate (having this be the actual object
  82. // rather than a pointer to it) led to the typical C++ problem of not knowing
  83. // which would be initialized first -- the container or an object that wants
  84. // to use it. This way, the first object that tries to use the container
  85. // will create the container, so that problem goes away.
  86. if (ms_pSettings == 0)
  87. ms_pSettings = new SETTINGS;
  88. if (ms_pSettings != 0)
  89. {
  90. // Add this object to container
  91. m_pointer = ms_pSettings->InsertTail(this);
  92. }
  93. else
  94. TRACE("CSettings::CSettings(): Couldn't create new container!\n");
  95. }
  96. ////////////////////////////////////////////////////////////////////////////////
  97. //
  98. // Destructor
  99. //
  100. ////////////////////////////////////////////////////////////////////////////////
  101. CSettings::~CSettings()
  102. {
  103. // Make sure container exists
  104. if (ms_pSettings != 0)
  105. {
  106. // Remove this object from container
  107. ms_pSettings->Remove(m_pointer);
  108. // If there are no more objects, then delete the container itself
  109. if (ms_pSettings->GetHead() == 0)
  110. {
  111. delete ms_pSettings;
  112. ms_pSettings = 0;
  113. }
  114. // Make sure to delete memory if it wasn't already deleted
  115. if (ms_pMem)
  116. {
  117. free(ms_pMem);
  118. ms_pMem = 0;
  119. }
  120. }
  121. }
  122. ////////////////////////////////////////////////////////////////////////////////
  123. //
  124. // Load all settings from preference file
  125. //
  126. ////////////////////////////////////////////////////////////////////////////////
  127. short CSettings::LoadPrefs( // Returns 0 if successfull, non-zero otherwise
  128. char* pszFile) // In: Name of prefs file
  129. {
  130. short sResult = 0;
  131. // Make sure container exists
  132. if (ms_pSettings != 0)
  133. {
  134. // Open file for read access (text mode is default)
  135. RPrefs prefs;
  136. sResult = prefs.Open(pszFile, "r");
  137. if (sResult == 0)
  138. {
  139. // Do this for all CSettings objects
  140. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  141. {
  142. sResult = ms_pSettings->GetData(i)->LoadPrefs(&prefs);
  143. if (sResult)
  144. break;
  145. }
  146. // If no errors detected, double-check to be sure no I/O errors occurred
  147. if (!sResult && prefs.IsError())
  148. {
  149. sResult = -1;
  150. TRACE("CSettings::LoadPrefs(): Error reading prefs file!\n");
  151. }
  152. prefs.Close();
  153. }
  154. else
  155. {
  156. sResult = -1;
  157. TRACE("CSettings::LoadPrefs(): Couldn't open prefs file: %s !\n", pszFile);
  158. }
  159. }
  160. else
  161. {
  162. sResult = -1;
  163. TRACE("CSettings::LoadPrefs(): No container!\n");
  164. }
  165. return sResult;
  166. }
  167. ////////////////////////////////////////////////////////////////////////////////
  168. //
  169. // Save all settings to preference file
  170. //
  171. // Return values:
  172. // 0 = successfull
  173. // 1 = read-only file (couldn't save)
  174. // <0 = some other error
  175. //
  176. ////////////////////////////////////////////////////////////////////////////////
  177. short CSettings::SavePrefs( // Returns 0 if successfull, non-zero otherwise
  178. char* pszFile) // In: Name of prefs file
  179. {
  180. short sResult = 0;
  181. // Make sure container exists
  182. if (ms_pSettings != 0)
  183. {
  184. // First open file for read-only access. If this works, then at least
  185. // we know the file exists, although it might be a read-only file.
  186. RPrefs prefs;
  187. sResult = prefs.Open(pszFile, "r");
  188. if (sResult == 0)
  189. {
  190. prefs.Close();
  191. // Open file again, this time for read+ (read plus write/append) access.
  192. // If this doesn't work, the file is most likely a read-only file.
  193. sResult = prefs.Open(pszFile, "r+");
  194. if (sResult == 0)
  195. {
  196. // Do this for all CSettings objects
  197. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  198. {
  199. sResult = ms_pSettings->GetData(i)->SavePrefs(&prefs);
  200. if (sResult)
  201. break;
  202. }
  203. // If no errors detected, double-check to be sure no I/O errors occurred
  204. if (!sResult && prefs.IsError())
  205. {
  206. sResult = -1;
  207. TRACE("CSettings::SavePrefs(): Error writing prefs file!\n");
  208. }
  209. prefs.Close();
  210. }
  211. else
  212. {
  213. sResult = 1; // Special Read-Only error return!
  214. TRACE("CSettings::SavePrefs: Read-only prefs file: %s !\n", pszFile);
  215. }
  216. }
  217. else
  218. {
  219. sResult = -1;
  220. TRACE("CSettings::SavePrefs(): Couldn't open prefs file: %s !\n", pszFile);
  221. }
  222. }
  223. else
  224. {
  225. sResult = -1;
  226. TRACE("CSettings::SavePrefs(): No container!\n");
  227. }
  228. return sResult;
  229. }
  230. ////////////////////////////////////////////////////////////////////////////////
  231. //
  232. // Load all settings from game file
  233. //
  234. ////////////////////////////////////////////////////////////////////////////////
  235. short CSettings::LoadGame( // Returns 0 if successfull, non-zero otherwise
  236. char* pszFile) // In: Name of prefs file
  237. {
  238. short sResult = 0;
  239. // Make sure container exists
  240. if (ms_pSettings != 0)
  241. {
  242. // Open file for read access in binary mode
  243. RFile fileGame;
  244. sResult = fileGame.Open(pszFile, "rb", RFile::LittleEndian);
  245. if (sResult == 0)
  246. {
  247. // Do this for all CSettings objects
  248. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  249. {
  250. sResult = ms_pSettings->GetData(i)->LoadGame(&fileGame);
  251. if (sResult)
  252. break;
  253. }
  254. // If no errors detected, double-check to be sure no I/O errors occurred
  255. if (!sResult && fileGame.Error())
  256. {
  257. sResult = -1;
  258. TRACE("CSettings::LoadGame(): Error reading game file!\n");
  259. }
  260. fileGame.Close();
  261. }
  262. else
  263. {
  264. sResult = -1;
  265. TRACE("CSettings::LoadGame(): Couldn't open game file: %s !\n", pszFile);
  266. }
  267. }
  268. else
  269. {
  270. sResult = -1;
  271. TRACE("CSettings::LoadGame(): No container!\n");
  272. }
  273. return sResult;
  274. }
  275. ////////////////////////////////////////////////////////////////////////////////
  276. //
  277. // Save all settings to game file
  278. //
  279. ////////////////////////////////////////////////////////////////////////////////
  280. short CSettings::SaveGame( // Returns 0 if successfull, non-zero otherwise
  281. char* pszFile) // In: Name of prefs file
  282. {
  283. short sResult = 0;
  284. // Make sure container exists
  285. if (ms_pSettings != 0)
  286. {
  287. // Open file for write access in binary mode
  288. // Note: We don't care if the file already exists -- write mode will destroy it
  289. RFile fileGame;
  290. sResult = fileGame.Open(pszFile, "wb", RFile::LittleEndian);
  291. if (sResult == 0)
  292. {
  293. // Do this for all CSettings objects
  294. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  295. {
  296. sResult = ms_pSettings->GetData(i)->SaveGame(&fileGame);
  297. if (sResult)
  298. break;
  299. }
  300. // If no errors detected, double-check to be sure no I/O errors occurred
  301. if (!sResult && fileGame.Error())
  302. {
  303. sResult = -1;
  304. TRACE("CSettings::SaveGame(): Error writing game file!\n");
  305. }
  306. fileGame.Close();
  307. }
  308. else
  309. {
  310. sResult = -1;
  311. TRACE("CSettings::SaveGame(): Couldn't open game file: %s !\n", pszFile);
  312. }
  313. }
  314. else
  315. {
  316. sResult = -1;
  317. TRACE("CSettings::SaveGame(): No container!\n");
  318. }
  319. return sResult;
  320. }
  321. ////////////////////////////////////////////////////////////////////////////////
  322. //
  323. // Temporarily set settings for demo mode
  324. //
  325. ////////////////////////////////////////////////////////////////////////////////
  326. short CSettings::PreDemo( // Returns 0 if successfull, non-zero otherwise
  327. void)
  328. {
  329. short sResult = 0;
  330. // Make sure container exists
  331. if (ms_pSettings != 0)
  332. {
  333. // Allocate a chunk of memory for settings to be saved to
  334. ms_pMem = malloc(CSettings::MemFileSize);
  335. if (ms_pMem != 0)
  336. {
  337. // Open memory file
  338. RFile fileMem;
  339. sResult = fileMem.Open(ms_pMem, CSettings::MemFileSize, RFile::LittleEndian);
  340. if (sResult == 0)
  341. {
  342. // Do this for all CSettings objects
  343. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  344. {
  345. sResult = ms_pSettings->GetData(i)->PreDemo(&fileMem);
  346. if (sResult)
  347. break;
  348. }
  349. // If no errors detected, double-check to be sure no I/O errors occurred
  350. if (!sResult && fileMem.Error())
  351. {
  352. sResult = -1;
  353. TRACE("CSettings::PreDemo(): Error writing to mem file (probably too much data)!\n");
  354. }
  355. fileMem.Close();
  356. }
  357. else
  358. {
  359. sResult = -1;
  360. TRACE("CSettings::PreDemo(): Couldn't open mem file!\n");
  361. }
  362. }
  363. else
  364. {
  365. sResult = -1;
  366. TRACE("CSettings::PreDemo(): Couldn't allocate memory for mem file!\n");
  367. }
  368. }
  369. else
  370. {
  371. sResult = -1;
  372. TRACE("CSettings::PreDemo(): No container!\n");
  373. }
  374. return sResult;
  375. }
  376. ////////////////////////////////////////////////////////////////////////////////
  377. //
  378. // Restore settings to what they were prior to demo mode
  379. //
  380. ////////////////////////////////////////////////////////////////////////////////
  381. short CSettings::PostDemo( // Returns 0 if successfull, non-zero otherwise
  382. void)
  383. {
  384. short sResult = 0;
  385. // Make sure container exists
  386. if (ms_pSettings != 0)
  387. {
  388. // Make sure memory was allocated by PreDemo()
  389. if (ms_pMem != 0)
  390. {
  391. // Open previously allocated memory file
  392. RFile fileMem;
  393. sResult = fileMem.Open(ms_pMem, CSettings::MemFileSize, RFile::LittleEndian);
  394. if (sResult == 0)
  395. {
  396. // Do this for all CSettings objects
  397. for (SETTINGS::Pointer i = ms_pSettings->GetHead(); i != 0; i = ms_pSettings->GetNext(i))
  398. {
  399. sResult = ms_pSettings->GetData(i)->PostDemo(&fileMem);
  400. if (sResult)
  401. break;
  402. }
  403. // If no errors detected, double-check to be sure no I/O errors occurred
  404. if (!sResult && fileMem.Error())
  405. {
  406. sResult = -1;
  407. TRACE("CSettings::PostDemo(): Error reading from mem file!\n");
  408. }
  409. fileMem.Close();
  410. }
  411. else
  412. {
  413. sResult = -1;
  414. TRACE("CSettings::PostDemo(): Couldn't open mem file!\n");
  415. }
  416. // Free memory
  417. free(ms_pMem);
  418. ms_pMem = 0;
  419. }
  420. else
  421. {
  422. sResult = -1;
  423. TRACE("CSettings::PostDemo(): No memory file to read from! (did you forget to call CSettings::PreDemo?)\n");
  424. }
  425. }
  426. else
  427. {
  428. sResult = -1;
  429. TRACE("CSettings::PostDemo(): No container!\n");
  430. }
  431. return sResult;
  432. }
  433. ////////////////////////////////////////////////////////////////////////////////
  434. // EOF
  435. ////////////////////////////////////////////////////////////////////////////////