Subversion Repositories SvarDOS

Rev

Rev 113 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 113 Rev 116
1
/*
1
/*
2
 * SVAROG386 INSTALL
2
 * SVAROG386 INSTALL
3
 * COPYRIGHT (C) 2016 MATEUSZ VISTE, ALL RIGHTS RESERVED.
3
 * COPYRIGHT (C) 2016 MATEUSZ VISTE, ALL RIGHTS RESERVED.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
6
 * modification, are permitted provided that the following conditions are met:
7
 *
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 * this list of conditions and the following disclaimer.
9
 * this list of conditions and the following disclaimer.
10
 *
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 * notice, this list of conditions and the following disclaimer in the
12
 * notice, this list of conditions and the following disclaimer in the
13
 * documentation and/or other materials provided with the distribution.
13
 * documentation and/or other materials provided with the distribution.
14
 *
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
 * POSSIBILITY OF SUCH DAMAGE.
25
 * POSSIBILITY OF SUCH DAMAGE.
26
 *
26
 *
27
 * http://svarog386.sf.net
27
 * http://svarog386.sf.net
28
 */
28
 */
29
 
29
 
30
#include <dos.h>
30
#include <dos.h>
31
#include <direct.h>  /* mkdir() */
31
#include <direct.h>  /* mkdir() */
32
#include <stdio.h>   /* printf() and friends */
32
#include <stdio.h>   /* printf() and friends */
33
#include <stdlib.h>  /* system() */
33
#include <stdlib.h>  /* system() */
34
#include <string.h>  /* memcpy() */
34
#include <string.h>  /* memcpy() */
35
#include <unistd.h>
35
#include <unistd.h>
36
 
36
 
37
#include "kitten\kitten.h"
37
#include "kitten\kitten.h"
38
 
38
 
39
#include "cdrom.h"
39
#include "cdrom.h"
40
#include "input.h"
40
#include "input.h"
41
#include "video.h"
41
#include "video.h"
42
 
42
 
43
/* keyboard layouts and locales */
43
/* keyboard layouts and locales */
44
#include "keylay.h"
44
#include "keylay.h"
45
#include "keyoff.h"
45
#include "keyoff.h"
46
 
46
 
47
/* color scheme (color, mono) */
47
/* color scheme (color, mono) */
48
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
48
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
49
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
49
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
50
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
50
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
51
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
51
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
52
 
52
 
53
/* mono flag */
53
/* mono flag */
54
static int mono = 0;
54
static int mono = 0;
55
 
55
 
56
/* how much disk space does Svarog386 require (in MiB) */
56
/* how much disk space does Svarog386 require (in MiB) */
57
#define SVAROG_DISK_REQ 8
57
#define SVAROG_DISK_REQ 8
58
 
58
 
59
/* menu screens can output only one of these: */
59
/* menu screens can output only one of these: */
60
#define MENUNEXT 0
60
#define MENUNEXT 0
61
#define MENUPREV -1
61
#define MENUPREV -1
62
#define MENUQUIT -2
62
#define MENUQUIT -2
63
 
63
 
64
/* a convenience 'function' used for debugging */
64
/* a convenience 'function' used for debugging */
65
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
65
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
66
 
66
 
67
struct slocales {
67
struct slocales {
68
  char lang[4];
68
  char lang[4];
69
  char *keybcode;
69
  char *keybcode;
70
  unsigned int codepage;
70
  unsigned int codepage;
71
  int egafile;
71
  int egafile;
72
  int keybfile;
72
  int keybfile;
73
  int keyboff;
73
  int keyboff;
74
  int keyblen;
74
  int keyblen;
75
  unsigned int keybid;
75
  unsigned int keybid;
76
};
76
};
77
 
77
 
78
 
78
 
79
/* reboot the computer */
79
/* reboot the computer */
80
static void reboot(void) {
80
static void reboot(void) {
81
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
81
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
82
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
82
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
83
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
83
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
84
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
84
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
85
}
85
}
86
 
86
 
87
 
87
 
88
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
88
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
89
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
89
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
90
  int linew, lincount;
90
  int linew, lincount;
91
  linew = 80;
91
  linew = 80;
92
  if (x >= 0) linew -= (x << 1);
92
  if (x >= 0) linew -= (x << 1);
93
 
93
 
94
  for (lincount = 1; y+lincount < 25; lincount++) {
94
  for (lincount = 1; y+lincount < 25; lincount++) {
95
    int i, len = linew;
95
    int i, len = linew;
96
    for (i = 0; i <= linew; i++) {
96
    for (i = 0; i <= linew; i++) {
97
      if (s[i] == ' ') len = i;
97
      if (s[i] == ' ') len = i;
98
      if (s[i] == '\n') {
98
      if (s[i] == '\n') {
99
        len = i;
99
        len = i;
100
        break;
100
        break;
101
      }
101
      }
102
      if (s[i] == 0) {
102
      if (s[i] == 0) {
103
        len = i;
103
        len = i;
104
        break;
104
        break;
105
      }
105
      }
106
    }
106
    }
107
    video_putstring(y++, x, attr, s, len);
107
    video_putstring(y++, x, attr, s, len);
108
    s += len;
108
    s += len;
109
    if (*s == 0) break;
109
    if (*s == 0) break;
110
    s += 1; /* skip the whitespace char */
110
    s += 1; /* skip the whitespace char */
111
  }
111
  }
112
  return(lincount);
112
  return(lincount);
113
}
113
}
114
 
114
 
115
 
115
 
116
/* an NLS wrapper around video_putstring(), also performs line wrapping when
116
/* an NLS wrapper around video_putstring(), also performs line wrapping when
117
 * needed. returns the amount of lines that were output */
117
 * needed. returns the amount of lines that were output */
118
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
118
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
119
  s = kittengets(nlsmaj, nlsmin, s);
119
  s = kittengets(nlsmaj, nlsmin, s);
120
  return(putstringwrap(y, x, attr, s));
120
  return(putstringwrap(y, x, attr, s));
121
}
121
}
122
 
122
 
123
 
123
 
124
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
124
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
125
  int i, offset = 0, res = 0, count, width = 0;
125
  int i, offset = 0, res = 0, count, width = 0;
126
  /* count how many positions there is, and check their width */
126
  /* count how many positions there is, and check their width */
127
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
127
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
128
    int len = strlen(list[count]);
128
    int len = strlen(list[count]);
129
    if (len > width) width = len;
129
    if (len > width) width = len;
130
  }
130
  }
131
 
131
 
132
  /* if xpos negative, means 'center out' */
132
  /* if xpos negative, means 'center out' */
133
  if (xpos < 0) xpos = 39 - (width >> 1);
133
  if (xpos < 0) xpos = 39 - (width >> 1);
134
 
134
 
135
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
135
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
136
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
136
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
137
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
137
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
138
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
138
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
139
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
139
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
140
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
140
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
141
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
141
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
142
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
142
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
143
 
143
 
144
  for (;;) {
144
  for (;;) {
145
    int key;
145
    int key;
146
    /* list of selectable items */
146
    /* list of selectable items */
147
    for (i = 0; i < height - 2; i++) {
147
    for (i = 0; i < height - 2; i++) {
148
      if (i + offset == res) {
148
      if (i + offset == res) {
149
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
149
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
150
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
150
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
151
        video_movecursor(ypos + 1 + i, xpos);
151
        video_movecursor(ypos + 1 + i, xpos);
152
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
152
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
153
      } else if (i + offset < count) {
153
      } else if (i + offset < count) {
154
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
154
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
155
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
155
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
156
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
156
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
157
      } else {
157
      } else {
158
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
158
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
159
      }
159
      }
160
    }
160
    }
161
    key = input_getkey();
161
    key = input_getkey();
162
    if (key == 0x0D) { /* ENTER */
162
    if (key == 0x0D) { /* ENTER */
163
      return(res);
163
      return(res);
164
    } else if (key == 0x148) { /* up */
164
    } else if (key == 0x148) { /* up */
165
      if (res > 0) {
165
      if (res > 0) {
166
        res--;
166
        res--;
167
        if (res < offset) offset = res;
167
        if (res < offset) offset = res;
168
      }
168
      }
169
    } else if (key == 0x150) { /* down */
169
    } else if (key == 0x150) { /* down */
170
      if (res+1 < count) {
170
      if (res+1 < count) {
171
        res++;
171
        res++;
172
        if (res > offset + height - 3) offset = res - (height - 3);
172
        if (res > offset + height - 3) offset = res - (height - 3);
173
      }
173
      }
174
    } else if (key == 0x147) { /* home */
174
    } else if (key == 0x147) { /* home */
175
      res = 0;
175
      res = 0;
176
      offset = 0;
176
      offset = 0;
177
    } else if (key == 0x14F) { /* end */
177
    } else if (key == 0x14F) { /* end */
178
      res = count - 1;
178
      res = count - 1;
179
      if (res > offset + height - 3) offset = res - (height - 3);
179
      if (res > offset + height - 3) offset = res - (height - 3);
180
    } else if (key == 0x1B) {  /* ESC */
180
    } else if (key == 0x1B) {  /* ESC */
181
      return(-1);
181
      return(-1);
182
    }/* else {
182
    }/* else {
183
      char buf[8];
183
      char buf[8];
184
      snprintf(buf, sizeof(buf), "0x%02X ", key);
184
      snprintf(buf, sizeof(buf), "0x%02X ", key);
185
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
185
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
186
    }*/
186
    }*/
187
  }
187
  }
188
}
188
}
189
 
189
 
190
static void newscreen(int statusbartype) {
190
static void newscreen(int statusbartype) {
191
  char *msg;
191
  char *msg;
192
  msg = kittengets(0, 0, "SVAROG386 INSTALLATION");
192
  msg = kittengets(0, 0, "SVAROG386 INSTALLATION");
193
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
193
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
194
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
194
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
195
  video_clear(COLOR_BODY[mono], 80, -80);
195
  video_clear(COLOR_BODY[mono], 80, -80);
196
  switch (statusbartype) {
196
  switch (statusbartype) {
197
    case 1:
197
    case 1:
198
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
198
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
199
      break;
199
      break;
200
    case 2:
200
    case 2:
201
      msg = kittengets(0, 5, "Press any key...");
201
      msg = kittengets(0, 5, "Press any key...");
202
      break;
202
      break;
203
    case 3:
203
    case 3:
204
      msg = "";
204
      msg = "";
205
      break;
205
      break;
206
    default:
206
    default:
207
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
207
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
208
      break;
208
      break;
209
  }
209
  }
210
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
210
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
211
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
211
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
212
  video_movecursor(25,0);
212
  video_movecursor(25,0);
213
}
213
}
214
 
214
 
215
/* fills a slocales struct accordingly to the value of its keyboff member */
215
/* fills a slocales struct accordingly to the value of its keyboff member */
216
static void kblay2slocal(struct slocales *locales) {
216
static void kblay2slocal(struct slocales *locales) {
217
  char *m;
217
  char *m;
218
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
218
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
219
  m++;
219
  m++;
220
  /* skip keyb code and copy it to locales.keybcode */
220
  /* skip keyb code and copy it to locales.keybcode */
221
  locales->keybcode = m;
221
  locales->keybcode = m;
222
  for (; *m != 0; m++);
222
  for (; *m != 0; m++);
223
  /* */
223
  /* */
224
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
224
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
225
  locales->egafile = m[3];
225
  locales->egafile = m[3];
226
  locales->keybfile = m[4];
226
  locales->keybfile = m[4];
227
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
227
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
228
}
228
}
229
 
229
 
230
static int selectlang(struct slocales *locales) {
230
static int selectlang(struct slocales *locales) {
231
  int choice, x;
231
  int choice, x;
232
  char *msg;
232
  char *msg;
233
  char *langlist[] = {
233
  char *langlist[] = {
234
    "English",
234
    "English",
235
    "French",
235
    "French",
236
    "Polish",
236
    "Polish",
-
 
237
    "Russian",
237
    "Turkish",
238
    "Turkish",
238
    NULL
239
    NULL
239
  };
240
  };
240
 
241
 
241
  newscreen(1);
242
  newscreen(1);
242
  msg = kittengets(1, 0, "Welcome to Svarog386");
243
  msg = kittengets(1, 0, "Welcome to Svarog386");
243
  x = 40 - (strlen(msg) >> 1);
244
  x = 40 - (strlen(msg) >> 1);
244
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
245
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
245
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
246
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
246
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
247
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
247
  choice = menuselect(11, -1, 6, langlist, -1);
248
  choice = menuselect(11, -1, 7, langlist, -1);
248
  if (choice < 0) return(MENUPREV);
249
  if (choice < 0) return(MENUPREV);
249
  /* populate locales with default values */
250
  /* populate locales with default values */
250
  memset(locales, 0, sizeof(struct slocales));
251
  memset(locales, 0, sizeof(struct slocales));
251
  switch (choice) {
252
  switch (choice) {
252
    case 1:
253
    case 1:
253
      strcpy(locales->lang, "FR");
254
      strcpy(locales->lang, "FR");
254
      locales->keyboff = OFFLOC_FR;
255
      locales->keyboff = OFFLOC_FR;
255
      locales->keyblen = OFFLEN_FR;
256
      locales->keyblen = OFFLEN_FR;
256
      break;
257
      break;
257
    case 2:
258
    case 2:
258
      strcpy(locales->lang, "PL");
259
      strcpy(locales->lang, "PL");
259
      locales->keyboff = OFFLOC_PL;
260
      locales->keyboff = OFFLOC_PL;
260
      locales->keyblen = OFFLEN_PL;
261
      locales->keyblen = OFFLEN_PL;
261
      break;
262
      break;
262
    case 3:
263
    case 3:
-
 
264
      strcpy(locales->lang, "RU");
-
 
265
      locales->keyboff = OFFLOC_RU;
-
 
266
      locales->keyblen = OFFLEN_RU;
-
 
267
      break;
-
 
268
    case 4:
263
      strcpy(locales->lang, "TR");
269
      strcpy(locales->lang, "TR");
264
      locales->keyboff = OFFLOC_TR;
270
      locales->keyboff = OFFLOC_TR;
265
      locales->keyblen = OFFLEN_TR;
271
      locales->keyblen = OFFLEN_TR;
266
      break;
272
      break;
267
    default:
273
    default:
268
      strcpy(locales->lang, "EN");
274
      strcpy(locales->lang, "EN");
269
      locales->keyboff = 0;
275
      locales->keyboff = 0;
270
      locales->keyblen = OFFCOUNT;
276
      locales->keyblen = OFFCOUNT;
271
      break;
277
      break;
272
  }
278
  }
273
  /* populate the slocales struct accordingly to the keyboff member */
279
  /* populate the slocales struct accordingly to the keyboff member */
274
  kblay2slocal(locales);
280
  kblay2slocal(locales);
275
  /* */
281
  /* */
276
  return(MENUNEXT);
282
  return(MENUNEXT);
277
}
283
}
278
 
284
 
279
 
285
 
280
static int selectkeyb(struct slocales *locales) {
286
static int selectkeyb(struct slocales *locales) {
281
  int menuheight, choice;
287
  int menuheight, choice;
282
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
288
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
283
  newscreen(0);
289
  newscreen(0);
284
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "Svarog386 supports the keyboard layouts used in different countries. Choose the keyboard layout you want.");
290
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "Svarog386 supports the keyboard layouts used in different countries. Choose the keyboard layout you want.");
285
  menuheight = locales->keyblen + 2;
291
  menuheight = locales->keyblen + 2;
286
  if (menuheight > 13) menuheight = 13;
292
  if (menuheight > 13) menuheight = 13;
287
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
293
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
288
  if (choice < 0) return(MENUPREV);
294
  if (choice < 0) return(MENUPREV);
289
  /* (re)load the keyboard layout & codepage setup */
295
  /* (re)load the keyboard layout & codepage setup */
290
  locales->keyboff += choice;
296
  locales->keyboff += choice;
291
  kblay2slocal(locales);
297
  kblay2slocal(locales);
292
  return(MENUNEXT);
298
  return(MENUNEXT);
293
}
299
}
294
 
300
 
295
 
301
 
296
/* returns 0 if installation must proceed, non-zero otherwise */
302
/* returns 0 if installation must proceed, non-zero otherwise */
297
static int welcomescreen(void) {
303
static int welcomescreen(void) {
298
  int c;
304
  int c;
299
  char *choice[] = {"Install Svarog386 to disk", "Quit to DOS", NULL};
305
  char *choice[] = {"Install Svarog386 to disk", "Quit to DOS", NULL};
300
  choice[0] = kittengets(0, 1, choice[0]);
306
  choice[0] = kittengets(0, 1, choice[0]);
301
  choice[1] = kittengets(0, 2, choice[1]);
307
  choice[1] = kittengets(0, 2, choice[1]);
302
  newscreen(0);
308
  newscreen(0);
303
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install Svarog386: a free, MSDOS-compatible operating system based on the FreeDOS kernel. Svarog386 targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once Svarog386 is installed.");
309
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install Svarog386: a free, MSDOS-compatible operating system based on the FreeDOS kernel. Svarog386 targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once Svarog386 is installed.");
304
  c = menuselect(13, -1, 4, choice, -1);
310
  c = menuselect(13, -1, 4, choice, -1);
305
  if (c < 0) return(MENUPREV);
311
  if (c < 0) return(MENUPREV);
306
  if (c == 0) return(MENUNEXT);
312
  if (c == 0) return(MENUNEXT);
307
  return(MENUQUIT);
313
  return(MENUQUIT);
308
}
314
}
309
 
315
 
310
 
316
 
311
/* returns 1 if drive is removable, 0 if not, -1 on error */
317
/* returns 1 if drive is removable, 0 if not, -1 on error */
312
static int isdriveremovable(int drv) {
318
static int isdriveremovable(int drv) {
313
  union REGS r;
319
  union REGS r;
314
  r.x.ax = 0x4408;
320
  r.x.ax = 0x4408;
315
  r.h.bl = drv;
321
  r.h.bl = drv;
316
  int86(0x21, &r, &r);
322
  int86(0x21, &r, &r);
317
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
323
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
318
  if (r.x.cflag != 0) return(-1);
324
  if (r.x.cflag != 0) return(-1);
319
  if (r.x.ax == 0) return(1);
325
  if (r.x.ax == 0) return(1);
320
  return(0);
326
  return(0);
321
}
327
}
322
 
328
 
323
 
329
 
324
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
330
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
325
static int disksize(int drv) {
331
static int disksize(int drv) {
326
  long res;
332
  long res;
327
  union REGS r;
333
  union REGS r;
328
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
334
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
329
  r.h.dl = drv;
335
  r.h.dl = drv;
330
  int86(0x21, &r, &r);
336
  int86(0x21, &r, &r);
331
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
337
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
332
  res = r.x.ax;  /* sectors per cluster */
338
  res = r.x.ax;  /* sectors per cluster */
333
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
339
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
334
  res *= r.x.cx; /* bytes per sector */
340
  res *= r.x.cx; /* bytes per sector */
335
  res >>= 20;    /* convert bytes to MiB */
341
  res >>= 20;    /* convert bytes to MiB */
336
  return(res);
342
  return(res);
337
}
343
}
338
 
344
 
339
 
345
 
340
/* returns 0 if disk is empty, non-zero otherwise */
346
/* returns 0 if disk is empty, non-zero otherwise */
341
static int diskempty(int drv) {
347
static int diskempty(int drv) {
342
  unsigned int rc;
348
  unsigned int rc;
343
  int res;
349
  int res;
344
  char buff[8];
350
  char buff[8];
345
  struct find_t fileinfo;
351
  struct find_t fileinfo;
346
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
352
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
347
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
353
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
348
  if (rc == 0) {
354
  if (rc == 0) {
349
    res = 1; /* call successfull means disk is not empty */
355
    res = 1; /* call successfull means disk is not empty */
350
  } else {
356
  } else {
351
    res = 0;
357
    res = 0;
352
  }
358
  }
353
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
359
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
354
  return(res);
360
  return(res);
355
}
361
}
356
 
362
 
357
 
363
 
358
static int preparedrive(void) {
364
static int preparedrive(void) {
359
  int driveremovable;
365
  int driveremovable;
360
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
366
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
361
  int cselecteddrive;
367
  int cselecteddrive;
362
  int ds;
368
  int ds;
363
  int choice;
369
  int choice;
364
  char buff[1024];
370
  char buff[1024];
365
  cselecteddrive = 'A' + selecteddrive - 1;
371
  cselecteddrive = 'A' + selecteddrive - 1;
366
  for (;;) {
372
  for (;;) {
367
    driveremovable = isdriveremovable(selecteddrive);
373
    driveremovable = isdriveremovable(selecteddrive);
368
    if (driveremovable < 0) {
374
    if (driveremovable < 0) {
369
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
375
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
370
      newscreen(0);
376
      newscreen(0);
371
      list[0] = kittengets(0, 3, list[0]);
377
      list[0] = kittengets(0, 3, list[0]);
372
      list[1] = kittengets(0, 4, list[1]);
378
      list[1] = kittengets(0, 4, list[1]);
373
      list[2] = kittengets(0, 2, list[2]);
379
      list[2] = kittengets(0, 2, list[2]);
374
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so Svarog386 can be installed on it. Note, that Svarog386 requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVAROG_DISK_REQ);
380
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so Svarog386 can be installed on it. Note, that Svarog386 requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVAROG_DISK_REQ);
375
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
381
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
376
      switch (menuselect(14, -1, 5, list, -1)) {
382
      switch (menuselect(14, -1, 5, list, -1)) {
377
        case 0:
383
        case 0:
378
          system("FDISK /AUTO");
384
          system("FDISK /AUTO");
379
          break;
385
          break;
380
        case 1:
386
        case 1:
381
          video_clear(0x0700, 0, 0);
387
          video_clear(0x0700, 0, 0);
382
          video_movecursor(0, 0);
388
          video_movecursor(0, 0);
383
          system("FDISK");
389
          system("FDISK");
384
          break;
390
          break;
385
        case 2:
391
        case 2:
386
          return(MENUQUIT);
392
          return(MENUQUIT);
387
        default:
393
        default:
388
          return(-1);
394
          return(-1);
389
      }
395
      }
390
      /* write a temporary MBR which only skips the drive (in case BIOS would
396
      /* write a temporary MBR which only skips the drive (in case BIOS would
391
       * try to boot off the not-yet-ready C: disk) */
397
       * try to boot off the not-yet-ready C: disk) */
392
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */
398
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */
393
      newscreen(2);
399
      newscreen(2);
394
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
400
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
395
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
401
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
396
      input_getkey();
402
      input_getkey();
397
      reboot();
403
      reboot();
398
      return(MENUQUIT);
404
      return(MENUQUIT);
399
    } else if (driveremovable > 0) {
405
    } else if (driveremovable > 0) {
400
      newscreen(2);
406
      newscreen(2);
401
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
407
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
402
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
408
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
403
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
409
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
404
      return(MENUQUIT);
410
      return(MENUQUIT);
405
    }
411
    }
406
    /* if not formatted, propose to format it right away (try to create a directory) */
412
    /* if not formatted, propose to format it right away (try to create a directory) */
407
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
413
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
408
    if (mkdir(buff) == 0) {
414
    if (mkdir(buff) == 0) {
409
      rmdir(buff);
415
      rmdir(buff);
410
    } else {
416
    } else {
411
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
417
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
412
      newscreen(0);
418
      newscreen(0);
413
      list[0] = kittengets(0, 6, list[0]);
419
      list[0] = kittengets(0, 6, list[0]);
414
      list[1] = kittengets(0, 2, list[1]);
420
      list[1] = kittengets(0, 2, list[1]);
415
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
421
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
416
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
422
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
417
      choice = menuselect(12, -1, 4, list, -1);
423
      choice = menuselect(12, -1, 4, list, -1);
418
      if (choice < 0) return(MENUPREV);
424
      if (choice < 0) return(MENUPREV);
419
      if (choice == 1) return(MENUQUIT);
425
      if (choice == 1) return(MENUQUIT);
420
      video_clear(0x0700, 0, 0);
426
      video_clear(0x0700, 0, 0);
421
      video_movecursor(0, 0);
427
      video_movecursor(0, 0);
422
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
428
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
423
      system(buff);
429
      system(buff);
424
      continue;
430
      continue;
425
    }
431
    }
426
    /* check total disk space */
432
    /* check total disk space */
427
    ds = disksize(selecteddrive);
433
    ds = disksize(selecteddrive);
428
    if (ds < SVAROG_DISK_REQ) {
434
    if (ds < SVAROG_DISK_REQ) {
429
      int y = 9;
435
      int y = 9;
430
      newscreen(2);
436
      newscreen(2);
431
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! Svarog386 requires a disk of at least %d MiB."), cselecteddrive);
437
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! Svarog386 requires a disk of at least %d MiB."), cselecteddrive);
432
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
438
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
433
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
439
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
434
      input_getkey();
440
      input_getkey();
435
      return(MENUQUIT);
441
      return(MENUQUIT);
436
    }
442
    }
437
    /* is the disk empty? */
443
    /* is the disk empty? */
438
    newscreen(0);
444
    newscreen(0);
439
    if (diskempty(selecteddrive) != 0) {
445
    if (diskempty(selecteddrive) != 0) {
440
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
446
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
441
      int y = 6;
447
      int y = 6;
442
      list[0] = kittengets(0, 6, list[0]);
448
      list[0] = kittengets(0, 6, list[0]);
443
      list[1] = kittengets(0, 2, list[1]);
449
      list[1] = kittengets(0, 2, list[1]);
444
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. Svarog386 must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
450
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. Svarog386 must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
445
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
451
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
446
      choice = menuselect(++y, -1, 4, list, -1);
452
      choice = menuselect(++y, -1, 4, list, -1);
447
      if (choice < 0) return(MENUPREV);
453
      if (choice < 0) return(MENUPREV);
448
      if (choice == 1) return(MENUQUIT);
454
      if (choice == 1) return(MENUQUIT);
449
      video_clear(0x0700, 0, 0);
455
      video_clear(0x0700, 0, 0);
450
      video_movecursor(0, 0);
456
      video_movecursor(0, 0);
451
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
457
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
452
      system(buff);
458
      system(buff);
453
      continue;
459
      continue;
454
    } else {
460
    } else {
455
      /* final confirmation */
461
      /* final confirmation */
456
      char *list[] = { "Install Svarog386", "Quit to DOS", NULL};
462
      char *list[] = { "Install Svarog386", "Quit to DOS", NULL};
457
      list[0] = kittengets(0, 1, list[0]);
463
      list[0] = kittengets(0, 1, list[0]);
458
      list[1] = kittengets(0, 2, list[1]);
464
      list[1] = kittengets(0, 2, list[1]);
459
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of Svarog386 to %c: is about to begin."), cselecteddrive);
465
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of Svarog386 to %c: is about to begin."), cselecteddrive);
460
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
466
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
461
      choice = menuselect(10, -1, 4, list, -1);
467
      choice = menuselect(10, -1, 4, list, -1);
462
      if (choice < 0) return(MENUPREV);
468
      if (choice < 0) return(MENUPREV);
463
      if (choice == 1) return(MENUQUIT);
469
      if (choice == 1) return(MENUQUIT);
464
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
470
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
465
      system(buff);
471
      system(buff);
466
      system("FDISK /MBR");
472
      system("FDISK /MBR");
467
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
473
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
468
      mkdir(buff);
474
      mkdir(buff);
469
      return(cselecteddrive);
475
      return(cselecteddrive);
470
    }
476
    }
471
  }
477
  }
472
}
478
}
473
 
479
 
474
 
480
 
475
/* copy file src into dst, substituting all characters c1 by c2 */
481
/* copy file src into dst, substituting all characters c1 by c2 */
476
static void fcopysub(char *dst, char *src, char c1, char c2) {
482
static void fcopysub(char *dst, char *src, char c1, char c2) {
477
  FILE *fdd, *fds;
483
  FILE *fdd, *fds;
478
  int buff;
484
  int buff;
479
  fds = fopen(src, "rb");
485
  fds = fopen(src, "rb");
480
  if (fds == NULL) return;
486
  if (fds == NULL) return;
481
  fdd = fopen(dst, "wb");
487
  fdd = fopen(dst, "wb");
482
  if (fdd == NULL) {
488
  if (fdd == NULL) {
483
    fclose(fds);
489
    fclose(fds);
484
    return;
490
    return;
485
  }
491
  }
486
  /* */
492
  /* */
487
  for (;;) {
493
  for (;;) {
488
    buff = fgetc(fds);
494
    buff = fgetc(fds);
489
    if (buff == EOF) break;
495
    if (buff == EOF) break;
490
    if (buff == c1) buff = c2;
496
    if (buff == c1) buff = c2;
491
    fprintf(fdd, "%c", buff);
497
    fprintf(fdd, "%c", buff);
492
  }
498
  }
493
  /* close files and return */
499
  /* close files and return */
494
  fclose(fdd);
500
  fclose(fdd);
495
  fclose(fds);
501
  fclose(fds);
496
}
502
}
497
 
503
 
498
 
504
 
499
static void bootfilesgen(int targetdrv, struct slocales *locales, int cdromdrv) {
505
static void bootfilesgen(int targetdrv, struct slocales *locales, int cdromdrv) {
500
  char buff[128];
506
  char buff[128];
501
  char buff2[16];
507
  char buff2[16];
502
  char buff3[16];
508
  char buff3[16];
503
  FILE *fd;
509
  FILE *fd;
504
  /*** CONFIG.SYS ***/
510
  /*** CONFIG.SYS ***/
505
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
511
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
506
  fd = fopen(buff, "wb");
512
  fd = fopen(buff, "wb");
507
  if (fd == NULL) return;
513
  if (fd == NULL) return;
508
  fprintf(fd, "DOS=UMB,HIGH\r\n"
514
  fprintf(fd, "DOS=UMB,HIGH\r\n"
509
              "LASTDRIVE=Z\r\n"
515
              "LASTDRIVE=Z\r\n"
510
              "FILES=50\r\n");
516
              "FILES=50\r\n");
511
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVAROG.386\\BIN\\HIMEMX.EXE\r\n", targetdrv);
517
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVAROG.386\\BIN\\HIMEMX.EXE\r\n", targetdrv);
512
  if (strcmp(locales->lang, "EN") == 0) {
518
  if (strcmp(locales->lang, "EN") == 0) {
513
    strcpy(buff, "COMMAND");
519
    strcpy(buff, "COMMAND");
514
  } else {
520
  } else {
515
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
521
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
516
  }
522
  }
517
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVAROG.386\\BIN\\%s.COM /E:512 /P\r\n", targetdrv, buff);
523
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVAROG.386\\BIN\\%s.COM /E:512 /P\r\n", targetdrv, buff);
518
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
524
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
519
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
525
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
520
  fclose(fd);
526
  fclose(fd);
521
  /*** AUTOEXEC.BAT ***/
527
  /*** AUTOEXEC.BAT ***/
522
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
528
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
523
  fd = fopen(buff, "wb");
529
  fd = fopen(buff, "wb");
524
  if (fd == NULL) return;
530
  if (fd == NULL) return;
525
  fprintf(fd, "@ECHO OFF\r\n");
531
  fprintf(fd, "@ECHO OFF\r\n");
526
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
532
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
527
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVAROG.386\r\n", targetdrv);
533
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVAROG.386\r\n", targetdrv);
528
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
534
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
529
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
535
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
530
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
536
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
531
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
537
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
532
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
538
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
533
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
539
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
534
  fprintf(fd, "PROMPT $P$G\r\n");
540
  fprintf(fd, "PROMPT $P$G\r\n");
535
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
541
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
536
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
542
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
537
  fprintf(fd, "FDAPM APMDOS\r\n");
543
  fprintf(fd, "FDAPM APMDOS\r\n");
538
  fprintf(fd, "\r\n");
544
  fprintf(fd, "\r\n");
539
  if (locales->egafile > 0) {
545
  if (locales->egafile > 0) {
540
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
546
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
541
    if (locales->egafile == 1) {
547
    if (locales->egafile == 1) {
542
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
548
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
543
    } else {
549
    } else {
544
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
550
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
545
    }
551
    }
546
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
552
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
547
  }
553
  }
548
  if (locales->keybfile > 0) {
554
  if (locales->keybfile > 0) {
549
    if (locales->keybfile == 1) {
555
    if (locales->keybfile == 1) {
550
      snprintf(buff2, sizeof(buff2), "KEYBOARD.SYS");
556
      snprintf(buff2, sizeof(buff2), "KEYBOARD.SYS");
551
    } else {
557
    } else {
552
      snprintf(buff2, sizeof(buff2), "KEYBRD%d.SYS", locales->keybfile);
558
      snprintf(buff2, sizeof(buff2), "KEYBRD%d.SYS", locales->keybfile);
553
    }
559
    }
554
    if (locales->keybid == 0) {
560
    if (locales->keybid == 0) {
555
      buff3[0] = 0;
561
      buff3[0] = 0;
556
    } else {
562
    } else {
557
      snprintf(buff3, sizeof(buff3), " /ID:%d", locales->keybid);
563
      snprintf(buff3, sizeof(buff3), " /ID:%d", locales->keybid);
558
    }
564
    }
559
    fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\%s%s\r\n", locales->keybcode, locales->codepage, targetdrv, buff2, buff3);
565
    fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\%s%s\r\n", locales->keybcode, locales->codepage, targetdrv, buff2, buff3);
560
    fprintf(fd, "\r\n");
566
    fprintf(fd, "\r\n");
561
  }
567
  }
562
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
568
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
563
  fprintf(fd, "\r\n");
569
  fprintf(fd, "\r\n");
564
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
570
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
565
  fprintf(fd, "REM CTMOUSE\r\n");
571
  fprintf(fd, "REM CTMOUSE\r\n");
566
  fprintf(fd, "\r\n");
572
  fprintf(fd, "\r\n");
567
  fprintf(fd, "ECHO.\r\n");
573
  fprintf(fd, "ECHO.\r\n");
568
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to Svarog386! Type 'HELP' if you need help."));
574
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to Svarog386! Type 'HELP' if you need help."));
569
  fclose(fd);
575
  fclose(fd);
570
  /*** CREATE DIRECTORY FOR OTHER CONFIGURATION FILES ***/
576
  /*** CREATE DIRECTORY FOR OTHER CONFIGURATION FILES ***/
571
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
577
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
572
  mkdir(buff);
578
  mkdir(buff);
573
  /*** FDNPKG.CFG ***/
579
  /*** FDNPKG.CFG ***/
574
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
580
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
575
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
581
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
576
  /*** COUNTRY.SYS ***/
582
  /*** COUNTRY.SYS ***/
577
  /*** PICOTCP ***/
583
  /*** PICOTCP ***/
578
  /*** WATTCP ***/
584
  /*** WATTCP ***/
579
}
585
}
580
 
586
 
581
 
587
 
582
static void installpackages(int targetdrv, int cdromdrv) {
588
static void installpackages(int targetdrv, int cdromdrv) {
583
  char *pkglist[] = {
589
  char *pkglist[] = {
584
    "A:\\UDVD2", /* this one's not part of CORE, hence it's stored right on the floppy */
590
    "A:\\UDVD2", /* this one's not part of CORE, hence it's stored right on the floppy */
585
    "APPEND",
591
    "APPEND",
586
    "ASSIGN",
592
    "ASSIGN",
587
    "ATTRIB",
593
    "ATTRIB",
588
    "CHKDSK",
594
    "CHKDSK",
589
    "CHOICE",
595
    "CHOICE",
590
    "COMMAND",
596
    "COMMAND",
591
    "COMP",
597
    "COMP",
592
    "CPIDOS",
598
    "CPIDOS",
593
    "CTMOUSE",
599
    "CTMOUSE",
594
    "DEBUG",
600
    "DEBUG",
595
    "DEFRAG",
601
    "DEFRAG",
596
    "DELTREE",
602
    "DELTREE",
597
    "DEVLOAD",
603
    "DEVLOAD",
598
    "DISKCOMP",
604
    "DISKCOMP",
599
    "DISKCOPY",
605
    "DISKCOPY",
600
    "DISPLAY",
606
    "DISPLAY",
601
    "DOSFSCK",
607
    "DOSFSCK",
602
    "EDIT",
608
    "EDIT",
603
    "EDLIN",
609
    "EDLIN",
604
    "EXE2BIN",
610
    "EXE2BIN",
605
    "FC",
611
    "FC",
606
    "FDAPM",
612
    "FDAPM",
607
    "FDISK",
613
    "FDISK",
608
    "FDNPKG",
614
    "FDNPKG",
609
    "FIND",
615
    "FIND",
610
    "FORMAT",
616
    "FORMAT",
611
    "HELP",
617
    "HELP",
612
    "HIMEMX",
618
    "HIMEMX",
613
    "KERNEL",
619
    "KERNEL",
614
    "KEYB",
620
    "KEYB",
615
    "KEYB_LAY",
621
    "KEYB_LAY",
616
    "LABEL",
622
    "LABEL",
617
    "LBACACHE",
623
    "LBACACHE",
618
    "MEM",
624
    "MEM",
619
    "MIRROR",
625
    "MIRROR",
620
    "MODE",
626
    "MODE",
621
    "MORE",
627
    "MORE",
622
    "MOVE",
628
    "MOVE",
623
    "NANSI",
629
    "NANSI",
624
    "NLSFUNC",
630
    "NLSFUNC",
625
    "PRINT",
631
    "PRINT",
626
    "RDISK",
632
    "RDISK",
627
    "RECOVER",
633
    "RECOVER",
628
    "REPLACE",
634
    "REPLACE",
629
    "SHARE",
635
    "SHARE",
630
    "SHSUCDX",
636
    "SHSUCDX",
631
    "SORT",
637
    "SORT",
632
    "SWSUBST",
638
    "SWSUBST",
633
    "TREE",
639
    "TREE",
634
    "UNDELETE",
640
    "UNDELETE",
635
    "XCOPY",
641
    "XCOPY",
636
    NULL
642
    NULL
637
  };
643
  };
638
  int i, pkglistlen;
644
  int i, pkglistlen;
639
  char buff[64];
645
  char buff[64];
640
  newscreen(3);
646
  newscreen(3);
641
  /* count how long the pkg list is */
647
  /* count how long the pkg list is */
642
  for (pkglistlen = 0; pkglist[pkglistlen] != NULL; pkglistlen++);
648
  for (pkglistlen = 0; pkglist[pkglistlen] != NULL; pkglistlen++);
643
  /* set DOSDIR and friends */
649
  /* set DOSDIR and friends */
644
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVAROG.386", targetdrv);
650
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVAROG.386", targetdrv);
645
  setenv("DOSDIR", buff, 1);
651
  setenv("DOSDIR", buff, 1);
646
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
652
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
647
  setenv("TEMP", buff, 1);
653
  setenv("TEMP", buff, 1);
648
  /* install packages */
654
  /* install packages */
649
  for (i = 0; pkglist[i] != NULL; i++) {
655
  for (i = 0; pkglist[i] != NULL; i++) {
650
    char buff[128];
656
    char buff[128];
651
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkglist[i]);
657
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkglist[i]);
652
    strcat(buff, "       ");
658
    strcat(buff, "       ");
653
    video_putstring(10, 1, COLOR_BODY[mono], buff, -1);
659
    video_putstring(10, 1, COLOR_BODY[mono], buff, -1);
654
    if (pkglist[i][1] == ':') {
660
    if (pkglist[i][1] == ':') {
655
      snprintf(buff, sizeof(buff), "FDINST INSTALL %s.ZIP > NUL", pkglist[i]);
661
      snprintf(buff, sizeof(buff), "FDINST INSTALL %s.ZIP > NUL", pkglist[i]);
656
    } else {
662
    } else {
657
      snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\CORE\\%s.ZIP > NUL", cdromdrv, pkglist[i]);
663
      snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\CORE\\%s.ZIP > NUL", cdromdrv, pkglist[i]);
658
    }
664
    }
659
    system(buff);
665
    system(buff);
660
  }
666
  }
661
}
667
}
662
 
668
 
663
 
669
 
664
static void finalreboot(void) {
670
static void finalreboot(void) {
665
  int y = 9;
671
  int y = 9;
666
  newscreen(2);
672
  newscreen(2);
667
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Svarog386 installation is over. Your computer will reboot now.\nPlease remove the installation disk from your drive.");
673
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Svarog386 installation is over. Your computer will reboot now.\nPlease remove the installation disk from your drive.");
668
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
674
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
669
  input_getkey();
675
  input_getkey();
670
  reboot();
676
  reboot();
671
}
677
}
672
 
678
 
673
 
679
 
674
static void loadcp(struct slocales *locales) {
680
static void loadcp(struct slocales *locales) {
675
  char buff[64];
681
  char buff[64];
676
  if (locales->codepage == 437) return;
682
  if (locales->codepage == 437) return;
677
  video_movecursor(1, 0);
683
  video_movecursor(1, 0);
678
  if (locales->egafile == 1) {
684
  if (locales->egafile == 1) {
679
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
685
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
680
  } else {
686
  } else {
681
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
687
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
682
  }
688
  }
683
  system(buff);
689
  system(buff);
684
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
690
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
685
  system(buff);
691
  system(buff);
686
  /* below I re-init the video controller - apparently this is required if
692
  /* below I re-init the video controller - apparently this is required if
687
   * I want the new glyph symbols to be actually applied, at least some
693
   * I want the new glyph symbols to be actually applied, at least some
688
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
694
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
689
  {
695
  {
690
  union REGS r;
696
  union REGS r;
691
  r.h.ah = 0x0F; /* get current video mode */
697
  r.h.ah = 0x0F; /* get current video mode */
692
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
698
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
693
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
699
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
694
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
700
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
695
  int86(0x10, &r, &r);
701
  int86(0x10, &r, &r);
696
  }
702
  }
697
}
703
}
698
 
704
 
699
/* checks CD drive drv for the presence of the Svarog386 install CD
705
/* checks CD drive drv for the presence of the Svarog386 install CD
700
 * returns 0 if found, non-zero otherwise */
706
 * returns 0 if found, non-zero otherwise */
701
static int checkcd(char drv) {
707
static int checkcd(char drv) {
702
  FILE *fd;
708
  FILE *fd;
703
  char fname[32];
709
  char fname[32];
704
  snprintf(fname, sizeof(fname), "%c:\\CORE\\MEM.ZIP", drv);
710
  snprintf(fname, sizeof(fname), "%c:\\CORE\\MEM.ZIP", drv);
705
  fd = fopen(fname, "rb");
711
  fd = fopen(fname, "rb");
706
  if (fd == NULL) return(-1);
712
  if (fd == NULL) return(-1);
707
  fclose(fd);
713
  fclose(fd);
708
  return(0);
714
  return(0);
709
}
715
}
710
 
716
 
711
 
717
 
712
int main(void) {
718
int main(void) {
713
  struct slocales locales;
719
  struct slocales locales;
714
  int targetdrv;
720
  int targetdrv;
715
  int cdromdrv;
721
  int cdromdrv;
716
  int action;
722
  int action;
717
 
723
 
718
  /* find where the cdrom drive is */
724
  /* find where the cdrom drive is */
719
  cdromdrv = cdrom_findfirst();
725
  cdromdrv = cdrom_findfirst();
720
  if (cdromdrv < 0) {
726
  if (cdromdrv < 0) {
721
    printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
727
    printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
722
    return(1);
728
    return(1);
723
  }
729
  }
724
  cdromdrv += 'A'; /* convert the cdrom 'id' (A=0) to an actual drive letter */
730
  cdromdrv += 'A'; /* convert the cdrom 'id' (A=0) to an actual drive letter */
725
  if (checkcd(cdromdrv) != 0) {
731
  if (checkcd(cdromdrv) != 0) {
726
    printf("ERROR: SVAROG386 INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
732
    printf("ERROR: SVAROG386 INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
727
    return(1);
733
    return(1);
728
  }
734
  }
729
 
735
 
730
  /* init screen and detect mono status */
736
  /* init screen and detect mono status */
731
  mono = video_init();
737
  mono = video_init();
732
 
738
 
733
  kittenopen("INSTALL"); /* load initial NLS support */
739
  kittenopen("INSTALL"); /* load initial NLS support */
734
 
740
 
735
 SelectLang:
741
 SelectLang:
736
  action = selectlang(&locales); /* welcome to svarog, select your language */
742
  action = selectlang(&locales); /* welcome to svarog, select your language */
737
  if (action != MENUNEXT) goto Quit;
743
  if (action != MENUNEXT) goto Quit;
738
  setenv("LANG", locales.lang, 1);
744
  setenv("LANG", locales.lang, 1);
739
  loadcp(&locales);
745
  loadcp(&locales);
740
  kittenclose(); /* reload NLS with new language */
746
  kittenclose(); /* reload NLS with new language */
741
  kittenopen("INSTALL"); /* NLS support */
747
  kittenopen("INSTALL"); /* NLS support */
742
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
748
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
743
  if (action == MENUQUIT) goto Quit;
749
  if (action == MENUQUIT) goto Quit;
744
  if (action == MENUPREV) goto SelectLang;
750
  if (action == MENUPREV) goto SelectLang;
745
 
751
 
746
 WelcomeScreen:
752
 WelcomeScreen:
747
  action = welcomescreen(); /* what svarog386 is, ask whether to run live dos or install */
753
  action = welcomescreen(); /* what svarog386 is, ask whether to run live dos or install */
748
  if (action == MENUQUIT) goto Quit;
754
  if (action == MENUQUIT) goto Quit;
749
  if (action == MENUPREV) goto SelectLang;
755
  if (action == MENUPREV) goto SelectLang;
750
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
756
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
751
  if (targetdrv == MENUQUIT) goto Quit;
757
  if (targetdrv == MENUQUIT) goto Quit;
752
  if (targetdrv == MENUPREV) goto WelcomeScreen;
758
  if (targetdrv == MENUPREV) goto WelcomeScreen;
753
  /*askaboutsources();*/ /* IF sources are available, ask if installing with them */
759
  /*askaboutsources();*/ /* IF sources are available, ask if installing with them */
754
  installpackages(targetdrv, cdromdrv);    /* install packages */
760
  installpackages(targetdrv, cdromdrv);    /* install packages */
755
  bootfilesgen(targetdrv, &locales, cdromdrv); /* generate boot files and other configurations */
761
  bootfilesgen(targetdrv, &locales, cdromdrv); /* generate boot files and other configurations */
756
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
762
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
757
  /*netcfg();*/ /* basic networking config */
763
  /*netcfg();*/ /* basic networking config */
758
  finalreboot(); /* remove the CD and reboot */
764
  finalreboot(); /* remove the CD and reboot */
759
 
765
 
760
 Quit:
766
 Quit:
761
  kittenclose(); /* close NLS support */
767
  kittenclose(); /* close NLS support */
762
  video_clear(0x0700, 0, 0);
768
  video_clear(0x0700, 0, 0);
763
  video_movecursor(0, 0);
769
  video_movecursor(0, 0);
764
  return(0);
770
  return(0);
765
}
771
}
766
 
772