home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / prefs.cpp < prev    next >
C/C++ Source or Header  |  1999-10-28  |  10KB  |  411 lines

  1. /*
  2.  *  prefs.cpp - Preferences handling
  3.  *
  4.  *  Basilisk II (C) 1997-1999 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25.  
  26. #include "sysdeps.h"
  27. #include "sys.h"
  28. #include "prefs.h"
  29.  
  30.  
  31. // Common preferences items (those which exist on all platforms)
  32. // Except for "disk", "floppy", "cdrom", "scsiX", "screen", "rom" and "ether",
  33. // these are guaranteed to be in the prefs; "disk", "floppy" and "cdrom" can
  34. // occur multiple times
  35. prefs_desc common_prefs_items[] = {
  36.     {"disk", TYPE_STRING, true},        // Device/file names of Mac volumes (disk.cpp)
  37.     {"floppy", TYPE_STRING, true},        // Device/file names of Mac floppy drives (sony.cpp)
  38.     {"cdrom", TYPE_STRING, true},        // Device/file names of Mac CD-ROM drives (cdrom.cpp)
  39.     {"extfs", TYPE_STRING, false},        // Root path of ExtFS (extfs.cpp)
  40.     {"scsi0", TYPE_STRING, false},        // SCSI targets for Mac SCSI ID 0..6 (scsi_*.cpp)
  41.     {"scsi1", TYPE_STRING, false},
  42.     {"scsi2", TYPE_STRING, false},
  43.     {"scsi3", TYPE_STRING, false},
  44.     {"scsi4", TYPE_STRING, false},
  45.     {"scsi5", TYPE_STRING, false},
  46.     {"scsi6", TYPE_STRING, false},
  47.     {"screen", TYPE_STRING, false},        // Video mode (video.cpp)
  48.     {"seriala", TYPE_STRING, false},    // Device name of Mac serial port A (serial_*.cpp)
  49.     {"serialb", TYPE_STRING, false},    // Device name of Mac serial port B (serial_*.cpp)
  50.     {"ether", TYPE_STRING, false},        // Device name of Mac ethernet adapter (ether_*.cpp)
  51.     {"rom", TYPE_STRING, false},        // Path of ROM file (main_*.cpp)
  52.     {"bootdrive", TYPE_INT16, false},    // Boot drive number (main.cpp)
  53.     {"bootdriver", TYPE_INT16, false},    // Boot driver number (main.cpp)
  54.     {"ramsize", TYPE_INT32, false},        // Size of Mac RAM in bytes (main_*.cpp)
  55.     {"frameskip", TYPE_INT32, false},    // Number of frames to skip in refreshed video modes (video_*.cpp)
  56.     {"modelid", TYPE_INT32, false},        // Mac Model ID (Gestalt Model ID minus 6) (rom_patches.cpp)
  57.     {"cpu", TYPE_INT32, false},            // CPU type (0 = 68000, 1 = 68010 etc.) (main.cpp)
  58.     {"fpu", TYPE_BOOLEAN, false},        // Enable FPU emulation (main.cpp)
  59.     {"nocdrom", TYPE_BOOLEAN, false},    // Don't install CD-ROM driver (cdrom.cpp/rom_patches.cpp)
  60.     {"nosound", TYPE_BOOLEAN, false},    // Don't enable sound output (audio_*.cpp)
  61.     {"nogui", TYPE_BOOLEAN, false},        // Disable GUI (main_*.cpp)
  62.     {NULL, TYPE_END, false}    // End of list
  63. };
  64.  
  65.  
  66. // Prefs item are stored in a linked list of these nodes
  67. struct prefs_node {
  68.     prefs_node *next;
  69.     const char *name;
  70.     prefs_type type;
  71.     void *data;
  72. };
  73.  
  74. // List of prefs nodes
  75. static prefs_node *the_prefs;
  76.  
  77.  
  78. /*
  79.  *  Initialize preferences
  80.  */
  81.  
  82. void PrefsInit(void)
  83. {
  84.     // Start with empty list
  85.     the_prefs = NULL;
  86.  
  87.     // Set defaults
  88.     SysAddSerialPrefs();
  89.     PrefsAddInt16("bootdriver", 0);
  90.     PrefsAddInt16("bootdrive", 0);
  91.     PrefsAddInt32("ramsize", 8 * 1024 * 1024);
  92.     PrefsAddInt32("frameskip", 6);
  93.     PrefsAddInt32("modelid", 5);    // Mac IIci
  94.     PrefsAddInt32("cpu", 3);        // 68030
  95.     PrefsAddBool("fpu", false);
  96.     PrefsAddBool("nocdrom", false);
  97.     PrefsAddBool("nosound", false);
  98.     PrefsAddBool("nogui", false);
  99.     AddPlatformPrefsDefaults();
  100.  
  101.     // Load preferences from settings file
  102.     LoadPrefs();
  103. }
  104.  
  105.  
  106. /*
  107.  *  Deinitialize preferences
  108.  */
  109.  
  110. void PrefsExit(void)
  111. {
  112.     // Free prefs list
  113.     prefs_node *p = the_prefs, *next;
  114.     while (p) {
  115.         next = p->next;
  116.         free((void *)p->name);
  117.         free(p->data);
  118.         delete p;
  119.         p = next;
  120.     }
  121. }
  122.  
  123.  
  124. /*
  125.  *  Find preferences descriptor by keyword
  126.  */
  127.  
  128. static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
  129. {
  130.     while (list->type != TYPE_ANY) {
  131.         if (strcmp(list->name, name) == 0)
  132.             return list;
  133.         list++;
  134.     }
  135.     return NULL;
  136. }
  137.  
  138.  
  139. /*
  140.  *  Set prefs items
  141.  */
  142.  
  143. static void add_data(const char *name, prefs_type type, void *data, int size)
  144. {
  145.     void *d = malloc(size);
  146.     if (d == NULL)
  147.         return;
  148.     memcpy(d, data, size);
  149.     prefs_node *p = new prefs_node;
  150.     p->next = 0;
  151.     p->name = strdup(name);
  152.     p->type = type;
  153.     p->data = d;
  154.     if (the_prefs) {
  155.         prefs_node *prev = the_prefs;
  156.         while (prev->next)
  157.             prev = prev->next;
  158.         prev->next = p;
  159.     } else
  160.         the_prefs = p;
  161. }
  162.  
  163. void PrefsAddString(const char *name, const char *s)
  164. {
  165.     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
  166. }
  167.  
  168. void PrefsAddBool(const char *name, bool b)
  169. {
  170.     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
  171. }
  172.  
  173. void PrefsAddInt16(const char *name, int16 val)
  174. {
  175.     add_data(name, TYPE_INT16, &val, sizeof(int16));
  176. }
  177.  
  178. void PrefsAddInt32(const char *name, int32 val)
  179. {
  180.     add_data(name, TYPE_INT32, &val, sizeof(int32));
  181. }
  182.  
  183.  
  184. /*
  185.  *  Replace prefs items
  186.  */
  187.  
  188. static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
  189. {
  190.     prefs_node *p = the_prefs;
  191.     int i = 0;
  192.     while (p) {
  193.         if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
  194.             if (i == index)
  195.                 return p;
  196.             else
  197.                 i++;
  198.         }
  199.         p = p->next;
  200.     }
  201.     return NULL;
  202. }
  203.  
  204. void PrefsReplaceString(const char *name, const char *s, int index)
  205. {
  206.     prefs_node *p = find_node(name, TYPE_STRING, index);
  207.     if (p) {
  208.         free(p->data);
  209.         p->data = strdup(s);
  210.     } else
  211.         add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
  212. }
  213.  
  214. void PrefsReplaceBool(const char *name, bool b)
  215. {
  216.     prefs_node *p = find_node(name, TYPE_BOOLEAN);
  217.     if (p)
  218.         *(bool *)(p->data) = b;
  219.     else
  220.         add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
  221. }
  222.  
  223. void PrefsReplaceInt16(const char *name, int16 val)
  224. {
  225.     prefs_node *p = find_node(name, TYPE_INT16);
  226.     if (p)
  227.         *(int16 *)(p->data) = val;
  228.     else
  229.         add_data(name, TYPE_INT16, &val, sizeof(int16));
  230. }
  231.  
  232. void PrefsReplaceInt32(const char *name, int32 val)
  233. {
  234.     prefs_node *p = find_node(name, TYPE_INT32);
  235.     if (p)
  236.         *(int32 *)(p->data) = val;
  237.     else
  238.         add_data(name, TYPE_INT32, &val, sizeof(int32));
  239. }
  240.  
  241.  
  242. /*
  243.  *  Get prefs items
  244.  */
  245.  
  246. const char *PrefsFindString(const char *name, int index)
  247. {
  248.     prefs_node *p = find_node(name, TYPE_STRING, index);
  249.     if (p)
  250.         return (char *)(p->data);
  251.     else
  252.         return NULL;
  253. }
  254.  
  255. bool PrefsFindBool(const char *name)
  256. {
  257.     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
  258.     if (p)
  259.         return *(bool *)(p->data);
  260.     else
  261.         return false;
  262. }
  263.  
  264. int16 PrefsFindInt16(const char *name)
  265. {
  266.     prefs_node *p = find_node(name, TYPE_INT16, 0);
  267.     if (p)
  268.         return *(int16 *)(p->data);
  269.     else
  270.         return 0;
  271. }
  272.  
  273. int32 PrefsFindInt32(const char *name)
  274. {
  275.     prefs_node *p = find_node(name, TYPE_INT32, 0);
  276.     if (p)
  277.         return *(int32 *)(p->data);
  278.     else
  279.         return 0;
  280. }
  281.  
  282.  
  283. /*
  284.  *  Remove prefs items
  285.  */
  286.  
  287. void PrefsRemoveItem(const char *name, int index)
  288. {
  289.     prefs_node *p = find_node(name, TYPE_ANY, index);
  290.     if (p) {
  291.         free((void *)p->name);
  292.         free(p->data);
  293.         prefs_node *q = the_prefs;
  294.         if (q == p) {
  295.             the_prefs = NULL;
  296.             delete p;
  297.             return;
  298.         }
  299.         while (q) {
  300.             if (q->next == p) {
  301.                 q->next = p->next;
  302.                 delete p;
  303.                 return;
  304.             }
  305.             q = q->next;
  306.         }
  307.     }
  308. }
  309.  
  310.  
  311. /*
  312.  *  Load prefs from stream (utility function for LoadPrefs() implementation)
  313.  */
  314.  
  315. void LoadPrefsFromStream(FILE *f)
  316. {
  317.     char line[256];
  318.     while(fgets(line, 255, f)) {
  319.         // Read line
  320.         int len = strlen(line);
  321.         if (len == 0)
  322.             continue;
  323.         line[len-1] = 0;
  324.  
  325.         // Comments begin with "#" or ";"
  326.         if (line[0] == '#' || line[0] == ';')
  327.             continue;
  328.  
  329.         // Terminate string after keyword
  330.         char *p = line;
  331.         while (!isspace(*p)) p++;
  332.         *p++ = 0;
  333.  
  334.         // Skip whitespace until value
  335.         while (isspace(*p)) p++;
  336.         if (*p == 0)
  337.             continue;
  338.         char *keyword = line;
  339.         char *value = p;
  340.         int32 i = atol(value);
  341.  
  342.         // Look for keyword first in common item list, then in platform specific list
  343.         const prefs_desc *desc = find_prefs_desc(keyword, common_prefs_items);
  344.         if (desc == NULL)
  345.             desc = find_prefs_desc(keyword, platform_prefs_items);
  346.         if (desc == NULL) {
  347.             printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
  348.             continue;
  349.         }
  350.  
  351.         // Add item to prefs
  352.         switch (desc->type) {
  353.             case TYPE_STRING:
  354.                 if (desc->multiple)
  355.                     PrefsAddString(keyword, value);
  356.                 else
  357.                     PrefsReplaceString(keyword, value);
  358.                 break;
  359.             case TYPE_BOOLEAN:
  360.                 PrefsReplaceBool(keyword, !strcmp(value, "true"));
  361.                 break;
  362.             case TYPE_INT16:
  363.                 PrefsReplaceInt16(keyword, i);
  364.                 break;
  365.             case TYPE_INT32:
  366.                 PrefsReplaceInt32(keyword, i);
  367.                 break;
  368.             default:
  369.                 break;
  370.         }
  371.     }
  372. }
  373.  
  374.  
  375. /*
  376.  *  Save settings to stream (utility function for SavePrefs() implementation)
  377.  */
  378.  
  379. static void write_prefs(FILE *f, const prefs_desc *list)
  380. {
  381.     while (list->type != TYPE_ANY) {
  382.         switch (list->type) {
  383.             case TYPE_STRING: {
  384.                 int index = 0;
  385.                 const char *str;
  386.                 while ((str = PrefsFindString(list->name, index++)) != NULL)
  387.                     fprintf(f, "%s %s\n", list->name, str);
  388.                 break;
  389.             }
  390.             case TYPE_BOOLEAN:
  391.                 fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
  392.                 break;
  393.             case TYPE_INT16:
  394.                 fprintf(f, "%s %d\n", list->name, PrefsFindInt16(list->name));
  395.                 break;
  396.             case TYPE_INT32:
  397.                 fprintf(f, "%s %ld\n", list->name, PrefsFindInt32(list->name));
  398.                 break;
  399.             default:
  400.                 break;
  401.         }
  402.         list++;
  403.     }
  404. }
  405.  
  406. void SavePrefsToStream(FILE *f)
  407. {
  408.     write_prefs(f, common_prefs_items);
  409.     write_prefs(f, platform_prefs_items);
  410. }
  411.