Subversion Repositories SvarDOS

Rev

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

Rev 554 Rev 555
1
/*
1
/*
2
 * SVARDOS INSTALL PROGRAM
2
 * SVARDOS INSTALL PROGRAM
3
 * Copyright (C) 2021 Mateusz Viste
3
 * Copyright (C) 2021 Mateusz Viste
4
 *
4
 *
5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
6
 *
6
 *
7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
8
 *
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
15
 *
16
 * The above copyright notice and this permission notice shall be included in
16
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
17
 * all copies or substantial portions of the Software.
18
 *
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
25
 * DEALINGS IN THE SOFTWARE.
26
 *
26
 *
27
 * http://svardos.osdn.io
27
 * http://svardos.osdn.io
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 "input.h"
39
#include "input.h"
40
#include "video.h"
40
#include "video.h"
41
 
41
 
42
/* keyboard layouts and locales */
42
/* keyboard layouts and locales */
43
#include "keylay.h"
43
#include "keylay.h"
44
#include "keyoff.h"
44
#include "keyoff.h"
45
 
45
 
46
/* color scheme (color, mono) */
46
/* color scheme (color, mono) */
47
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
47
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
48
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
48
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
49
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
49
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
50
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
50
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
51
 
51
 
52
/* mono flag */
52
/* mono flag */
53
static int mono = 0;
53
static int mono = 0;
54
 
54
 
55
/* how much disk space does SvarDOS require (in MiB) */
55
/* how much disk space does SvarDOS require (in MiB) */
56
#define SVARDOS_DISK_REQ 8
56
#define SVARDOS_DISK_REQ 8
57
 
57
 
58
/* menu screens can output only one of these: */
58
/* menu screens can output only one of these: */
59
#define MENUNEXT 0
59
#define MENUNEXT 0
60
#define MENUPREV -1
60
#define MENUPREV -1
61
#define MENUQUIT -2
61
#define MENUQUIT -2
62
 
62
 
63
/* a convenience 'function' used for debugging */
63
/* a convenience 'function' used for debugging */
64
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
64
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
65
 
65
 
66
struct slocales {
66
struct slocales {
67
  char lang[4];
67
  char lang[4];
68
  char *keybcode;
68
  char *keybcode;
69
  unsigned int codepage;
69
  unsigned int codepage;
70
  int egafile;
70
  int egafile;
71
  int keybfile;
71
  int keybfile;
72
  int keyboff;
72
  int keyboff;
73
  int keyblen;
73
  int keyblen;
74
  unsigned int keybid;
74
  unsigned int keybid;
75
};
75
};
76
 
76
 
77
 
77
 
78
/* reboot the computer */
78
/* reboot the computer */
79
static void reboot(void) {
79
static void reboot(void) {
80
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
80
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
81
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
81
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
82
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
82
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
83
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
83
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
84
}
84
}
85
 
85
 
86
 
86
 
87
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
87
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
88
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
88
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
89
  int linew, lincount;
89
  int linew, lincount;
90
  linew = 80;
90
  linew = 80;
91
  if (x >= 0) linew -= (x << 1);
91
  if (x >= 0) linew -= (x << 1);
92
 
92
 
93
  for (lincount = 1; y+lincount < 25; lincount++) {
93
  for (lincount = 1; y+lincount < 25; lincount++) {
94
    int i, len = linew;
94
    int i, len = linew;
95
    for (i = 0; i <= linew; i++) {
95
    for (i = 0; i <= linew; i++) {
96
      if (s[i] == ' ') len = i;
96
      if (s[i] == ' ') len = i;
97
      if (s[i] == '\n') {
97
      if (s[i] == '\n') {
98
        len = i;
98
        len = i;
99
        break;
99
        break;
100
      }
100
      }
101
      if (s[i] == 0) {
101
      if (s[i] == 0) {
102
        len = i;
102
        len = i;
103
        break;
103
        break;
104
      }
104
      }
105
    }
105
    }
106
    video_putstring(y++, x, attr, s, len);
106
    video_putstring(y++, x, attr, s, len);
107
    s += len;
107
    s += len;
108
    if (*s == 0) break;
108
    if (*s == 0) break;
109
    s += 1; /* skip the whitespace char */
109
    s += 1; /* skip the whitespace char */
110
  }
110
  }
111
  return(lincount);
111
  return(lincount);
112
}
112
}
113
 
113
 
114
 
114
 
115
/* an NLS wrapper around video_putstring(), also performs line wrapping when
115
/* an NLS wrapper around video_putstring(), also performs line wrapping when
116
 * needed. returns the amount of lines that were output */
116
 * needed. returns the amount of lines that were output */
117
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
117
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
118
  s = kittengets(nlsmaj, nlsmin, s);
118
  s = kittengets(nlsmaj, nlsmin, s);
119
  return(putstringwrap(y, x, attr, s));
119
  return(putstringwrap(y, x, attr, s));
120
}
120
}
121
 
121
 
122
 
122
 
123
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
123
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
124
 * exists already! returns 0 on success. */
124
 * exists already! returns 0 on success. */
125
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
125
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
126
  FILE *fd1, *fd2;
126
  FILE *fd1, *fd2;
127
  size_t sz;
127
  size_t sz;
128
  int res = -1; /* assume failure */
128
  int res = -1; /* assume failure */
129
 
129
 
130
  /* open files */
130
  /* open files */
131
  fd1 = fopen(f1, "rb");
131
  fd1 = fopen(f1, "rb");
132
  fd2 = fopen(f2, "wb");
132
  fd2 = fopen(f2, "wb");
133
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
133
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
134
 
134
 
135
  /* copy data */
135
  /* copy data */
136
  for (;;) {
136
  for (;;) {
137
    sz = fread(buff, 1, buffsz, fd1);
137
    sz = fread(buff, 1, buffsz, fd1);
138
    if (sz == 0) {
138
    if (sz == 0) {
139
      if (feof(fd1) != 0) break;
139
      if (feof(fd1) != 0) break;
140
      goto QUIT;
140
      goto QUIT;
141
    }
141
    }
142
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
142
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
143
  }
143
  }
144
 
144
 
145
  res = 0; /* success */
145
  res = 0; /* success */
146
 
146
 
147
  QUIT:
147
  QUIT:
148
  if (fd1 != NULL) fclose(fd1);
148
  if (fd1 != NULL) fclose(fd1);
149
  if (fd2 != NULL) fclose(fd2);
149
  if (fd2 != NULL) fclose(fd2);
150
  return(res);
150
  return(res);
151
}
151
}
152
 
152
 
153
 
153
 
154
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
154
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
155
  int i, offset = 0, res = 0, count, width = 0;
155
  int i, offset = 0, res = 0, count, width = 0;
156
  /* count how many positions there is, and check their width */
156
  /* count how many positions there is, and check their width */
157
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
157
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
158
    int len = strlen(list[count]);
158
    int len = strlen(list[count]);
159
    if (len > width) width = len;
159
    if (len > width) width = len;
160
  }
160
  }
161
 
161
 
162
  /* if xpos negative, means 'center out' */
162
  /* if xpos negative, means 'center out' */
163
  if (xpos < 0) xpos = 39 - (width >> 1);
163
  if (xpos < 0) xpos = 39 - (width >> 1);
164
 
164
 
165
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
165
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
166
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
166
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
167
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
167
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
168
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
168
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
169
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
169
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
170
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
170
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
171
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
171
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
172
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
172
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
173
 
173
 
174
  for (;;) {
174
  for (;;) {
175
    int key;
175
    int key;
176
    /* list of selectable items */
176
    /* list of selectable items */
177
    for (i = 0; i < height - 2; i++) {
177
    for (i = 0; i < height - 2; i++) {
178
      if (i + offset == res) {
178
      if (i + offset == res) {
179
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
179
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
180
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
180
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
181
        video_movecursor(ypos + 1 + i, xpos);
181
        video_movecursor(ypos + 1 + i, xpos);
182
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
182
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
183
      } else if (i + offset < count) {
183
      } else if (i + offset < count) {
184
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
184
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
185
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
185
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
186
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
186
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
187
      } else {
187
      } else {
188
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
188
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
189
      }
189
      }
190
    }
190
    }
191
    key = input_getkey();
191
    key = input_getkey();
192
    if (key == 0x0D) { /* ENTER */
192
    if (key == 0x0D) { /* ENTER */
193
      return(res);
193
      return(res);
194
    } else if (key == 0x148) { /* up */
194
    } else if (key == 0x148) { /* up */
195
      if (res > 0) {
195
      if (res > 0) {
196
        res--;
196
        res--;
197
        if (res < offset) offset = res;
197
        if (res < offset) offset = res;
198
      }
198
      }
199
    } else if (key == 0x150) { /* down */
199
    } else if (key == 0x150) { /* down */
200
      if (res+1 < count) {
200
      if (res+1 < count) {
201
        res++;
201
        res++;
202
        if (res > offset + height - 3) offset = res - (height - 3);
202
        if (res > offset + height - 3) offset = res - (height - 3);
203
      }
203
      }
204
    } else if (key == 0x147) { /* home */
204
    } else if (key == 0x147) { /* home */
205
      res = 0;
205
      res = 0;
206
      offset = 0;
206
      offset = 0;
207
    } else if (key == 0x14F) { /* end */
207
    } else if (key == 0x14F) { /* end */
208
      res = count - 1;
208
      res = count - 1;
209
      if (res > offset + height - 3) offset = res - (height - 3);
209
      if (res > offset + height - 3) offset = res - (height - 3);
210
    } else if (key == 0x1B) {  /* ESC */
210
    } else if (key == 0x1B) {  /* ESC */
211
      return(-1);
211
      return(-1);
212
    }/* else {
212
    }/* else {
213
      char buf[8];
213
      char buf[8];
214
      snprintf(buf, sizeof(buf), "0x%02X ", key);
214
      snprintf(buf, sizeof(buf), "0x%02X ", key);
215
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
215
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
216
    }*/
216
    }*/
217
  }
217
  }
218
}
218
}
219
 
219
 
220
static void newscreen(int statusbartype) {
220
static void newscreen(int statusbartype) {
221
  char *msg;
221
  char *msg;
222
  msg = kittengets(0, 0, "SVARDOS INSTALLATION");
222
  msg = kittengets(0, 0, "SVARDOS INSTALLATION");
223
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
223
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
224
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
224
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
225
  video_clear(COLOR_BODY[mono], 80, -80);
225
  video_clear(COLOR_BODY[mono], 80, -80);
226
  switch (statusbartype) {
226
  switch (statusbartype) {
227
    case 1:
227
    case 1:
228
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
228
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
229
      break;
229
      break;
230
    case 2:
230
    case 2:
231
      msg = kittengets(0, 5, "Press any key...");
231
      msg = kittengets(0, 5, "Press any key...");
232
      break;
232
      break;
233
    case 3:
233
    case 3:
234
      msg = "";
234
      msg = "";
235
      break;
235
      break;
236
    default:
236
    default:
237
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
237
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
238
      break;
238
      break;
239
  }
239
  }
240
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
240
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
241
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
241
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
242
  video_movecursor(25,0);
242
  video_movecursor(25,0);
243
}
243
}
244
 
244
 
245
/* fills a slocales struct accordingly to the value of its keyboff member */
245
/* fills a slocales struct accordingly to the value of its keyboff member */
246
static void kblay2slocal(struct slocales *locales) {
246
static void kblay2slocal(struct slocales *locales) {
247
  char *m;
247
  char *m;
248
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
248
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
249
  m++;
249
  m++;
250
  /* skip keyb code and copy it to locales.keybcode */
250
  /* skip keyb code and copy it to locales.keybcode */
251
  locales->keybcode = m;
251
  locales->keybcode = m;
252
  for (; *m != 0; m++);
252
  for (; *m != 0; m++);
253
  /* */
253
  /* */
254
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
254
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
255
  locales->egafile = m[3];
255
  locales->egafile = m[3];
256
  locales->keybfile = m[4];
256
  locales->keybfile = m[4];
257
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
257
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
258
}
258
}
259
 
259
 
260
static int selectlang(struct slocales *locales) {
260
static int selectlang(struct slocales *locales) {
261
  int choice, x;
261
  int choice, x;
262
  char *msg;
262
  char *msg;
263
  char *langlist[] = {
263
  char *langlist[] = {
264
    "English",
264
    "English",
265
    "French",
265
    "French",
266
    "German",
266
    "German",
267
    "Italian",
267
    "Italian",
268
    "Polish",
268
    "Polish",
269
    "Russian",
269
    "Russian",
270
    "Slovene",
270
    "Slovene",
271
    "Swedish",
271
    "Swedish",
272
    "Turkish",
272
    "Turkish",
273
    NULL
273
    NULL
274
  };
274
  };
275
 
275
 
276
  newscreen(1);
276
  newscreen(1);
277
  msg = kittengets(1, 0, "Welcome to SvarDOS");
277
  msg = kittengets(1, 0, "Welcome to SvarDOS");
278
  x = 40 - (strlen(msg) >> 1);
278
  x = 40 - (strlen(msg) >> 1);
279
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
279
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
280
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
280
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
281
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
281
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
282
  choice = menuselect(11, -1, 11, langlist, -1);
282
  choice = menuselect(11, -1, 11, langlist, -1);
283
  if (choice < 0) return(MENUPREV);
283
  if (choice < 0) return(MENUPREV);
284
  /* populate locales with default values */
284
  /* populate locales with default values */
285
  memset(locales, 0, sizeof(struct slocales));
285
  memset(locales, 0, sizeof(struct slocales));
286
  switch (choice) {
286
  switch (choice) {
287
    case 1:
287
    case 1:
288
      strcpy(locales->lang, "FR");
288
      strcpy(locales->lang, "FR");
289
      locales->keyboff = OFFLOC_FR;
289
      locales->keyboff = OFFLOC_FR;
290
      locales->keyblen = OFFLEN_FR;
290
      locales->keyblen = OFFLEN_FR;
291
      break;
291
      break;
292
    case 2:
292
    case 2:
293
      strcpy(locales->lang, "DE");
293
      strcpy(locales->lang, "DE");
294
      locales->keyboff = OFFLOC_DE;
294
      locales->keyboff = OFFLOC_DE;
295
      locales->keyblen = OFFLEN_DE;
295
      locales->keyblen = OFFLEN_DE;
296
      break;
296
      break;
297
    case 3:
297
    case 3:
298
      strcpy(locales->lang, "IT");
298
      strcpy(locales->lang, "IT");
299
      locales->keyboff = OFFLOC_IT;
299
      locales->keyboff = OFFLOC_IT;
300
      locales->keyblen = OFFLEN_IT;
300
      locales->keyblen = OFFLEN_IT;
301
      break;
301
      break;
302
    case 4:
302
    case 4:
303
      strcpy(locales->lang, "PL");
303
      strcpy(locales->lang, "PL");
304
      locales->keyboff = OFFLOC_PL;
304
      locales->keyboff = OFFLOC_PL;
305
      locales->keyblen = OFFLEN_PL;
305
      locales->keyblen = OFFLEN_PL;
306
      break;
306
      break;
307
    case 5:
307
    case 5:
308
      strcpy(locales->lang, "RU");
308
      strcpy(locales->lang, "RU");
309
      locales->keyboff = OFFLOC_RU;
309
      locales->keyboff = OFFLOC_RU;
310
      locales->keyblen = OFFLEN_RU;
310
      locales->keyblen = OFFLEN_RU;
311
      break;
311
      break;
312
    case 6:
312
    case 6:
313
      strcpy(locales->lang, "SI");
313
      strcpy(locales->lang, "SI");
314
      locales->keyboff = OFFLOC_SI;
314
      locales->keyboff = OFFLOC_SI;
315
      locales->keyblen = OFFLEN_SI;
315
      locales->keyblen = OFFLEN_SI;
316
      break;
316
      break;
317
    case 7:
317
    case 7:
318
      strcpy(locales->lang, "SV");
318
      strcpy(locales->lang, "SV");
319
      locales->keyboff = OFFLOC_SV;
319
      locales->keyboff = OFFLOC_SV;
320
      locales->keyblen = OFFLEN_SV;
320
      locales->keyblen = OFFLEN_SV;
321
      break;
321
      break;
322
    case 8:
322
    case 8:
323
      strcpy(locales->lang, "TR");
323
      strcpy(locales->lang, "TR");
324
      locales->keyboff = OFFLOC_TR;
324
      locales->keyboff = OFFLOC_TR;
325
      locales->keyblen = OFFLEN_TR;
325
      locales->keyblen = OFFLEN_TR;
326
      break;
326
      break;
327
    default:
327
    default:
328
      strcpy(locales->lang, "EN");
328
      strcpy(locales->lang, "EN");
329
      locales->keyboff = 0;
329
      locales->keyboff = 0;
330
      locales->keyblen = OFFCOUNT;
330
      locales->keyblen = OFFCOUNT;
331
      break;
331
      break;
332
  }
332
  }
333
  /* populate the slocales struct accordingly to the keyboff member */
333
  /* populate the slocales struct accordingly to the keyboff member */
334
  kblay2slocal(locales);
334
  kblay2slocal(locales);
335
  /* */
335
  /* */
336
  return(MENUNEXT);
336
  return(MENUNEXT);
337
}
337
}
338
 
338
 
339
 
339
 
340
static int selectkeyb(struct slocales *locales) {
340
static int selectkeyb(struct slocales *locales) {
341
  int menuheight, choice;
341
  int menuheight, choice;
342
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
342
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
343
  newscreen(0);
343
  newscreen(0);
344
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
344
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
345
  menuheight = locales->keyblen + 2;
345
  menuheight = locales->keyblen + 2;
346
  if (menuheight > 13) menuheight = 13;
346
  if (menuheight > 13) menuheight = 13;
347
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
347
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
348
  if (choice < 0) return(MENUPREV);
348
  if (choice < 0) return(MENUPREV);
349
  /* (re)load the keyboard layout & codepage setup */
349
  /* (re)load the keyboard layout & codepage setup */
350
  locales->keyboff += choice;
350
  locales->keyboff += choice;
351
  kblay2slocal(locales);
351
  kblay2slocal(locales);
352
  return(MENUNEXT);
352
  return(MENUNEXT);
353
}
353
}
354
 
354
 
355
 
355
 
356
/* returns 0 if installation must proceed, non-zero otherwise */
356
/* returns 0 if installation must proceed, non-zero otherwise */
357
static int welcomescreen(void) {
357
static int welcomescreen(void) {
358
  int c;
358
  int c;
359
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
359
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
360
  choice[0] = kittengets(0, 1, choice[0]);
360
  choice[0] = kittengets(0, 1, choice[0]);
361
  choice[1] = kittengets(0, 2, choice[1]);
361
  choice[1] = kittengets(0, 2, choice[1]);
362
  newscreen(0);
362
  newscreen(0);
363
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install SvarDOS: a free, MSDOS-compatible operating system based on the FreeDOS kernel. SvarDOS 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 SvarDOS is installed.");
363
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install SvarDOS: a free, MSDOS-compatible operating system based on the FreeDOS kernel. SvarDOS 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 SvarDOS is installed.");
364
  c = menuselect(13, -1, 4, choice, -1);
364
  c = menuselect(13, -1, 4, choice, -1);
365
  if (c < 0) return(MENUPREV);
365
  if (c < 0) return(MENUPREV);
366
  if (c == 0) return(MENUNEXT);
366
  if (c == 0) return(MENUNEXT);
367
  return(MENUQUIT);
367
  return(MENUQUIT);
368
}
368
}
369
 
369
 
370
 
370
 
371
/* returns 1 if drive is removable, 0 if not, -1 on error */
371
/* returns 1 if drive is removable, 0 if not, -1 on error */
372
static int isdriveremovable(int drv) {
372
static int isdriveremovable(int drv) {
373
  union REGS r;
373
  union REGS r;
374
  r.x.ax = 0x4408;
374
  r.x.ax = 0x4408;
375
  r.h.bl = drv;
375
  r.h.bl = drv;
376
  int86(0x21, &r, &r);
376
  int86(0x21, &r, &r);
377
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
377
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
378
  if (r.x.cflag != 0) return(-1);
378
  if (r.x.cflag != 0) return(-1);
379
  if (r.x.ax == 0) return(1);
379
  if (r.x.ax == 0) return(1);
380
  return(0);
380
  return(0);
381
}
381
}
382
 
382
 
383
 
383
 
384
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
384
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
385
static int disksize(int drv) {
385
static int disksize(int drv) {
386
  long res;
386
  long res;
387
  union REGS r;
387
  union REGS r;
388
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
388
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
389
  r.h.dl = drv;  /* A=1, B=2, etc */
389
  r.h.dl = drv;  /* A=1, B=2, etc */
390
  int86(0x21, &r, &r);
390
  int86(0x21, &r, &r);
391
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
391
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
392
  res = r.x.ax;  /* sectors per cluster */
392
  res = r.x.ax;  /* sectors per cluster */
393
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
393
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
394
  res *= r.x.cx; /* bytes per sector */
394
  res *= r.x.cx; /* bytes per sector */
395
  res >>= 20;    /* convert bytes to MiB */
395
  res >>= 20;    /* convert bytes to MiB */
396
  return(res);
396
  return(res);
397
}
397
}
398
 
398
 
399
 
399
 
400
/* returns 0 if disk is empty, non-zero otherwise */
400
/* returns 0 if disk is empty, non-zero otherwise */
401
static int diskempty(int drv) {
401
static int diskempty(int drv) {
402
  unsigned int rc;
402
  unsigned int rc;
403
  int res;
403
  int res;
404
  char buff[8];
404
  char buff[8];
405
  struct find_t fileinfo;
405
  struct find_t fileinfo;
406
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
406
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
407
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
407
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
408
  if (rc == 0) {
408
  if (rc == 0) {
409
    res = 1; /* call successfull means disk is not empty */
409
    res = 1; /* call successfull means disk is not empty */
410
  } else {
410
  } else {
411
    res = 0;
411
    res = 0;
412
  }
412
  }
413
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
413
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
414
  return(res);
414
  return(res);
415
}
415
}
416
 
416
 
417
#ifdef DEADCODE
417
#ifdef DEADCODE
418
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
418
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
419
static int set_cur_drive(char drv) {
419
static int set_cur_drive(char drv) {
420
  union REGS r;
420
  union REGS r;
421
  if ((drv < 'A') || (drv > 'Z')) return(-1);
421
  if ((drv < 'A') || (drv > 'Z')) return(-1);
422
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
422
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
423
  r.h.dl = drv - 'A';
423
  r.h.dl = drv - 'A';
424
  int86(0x21, &r, &r);
424
  int86(0x21, &r, &r);
425
  if (r.h.al < drv - 'A') return(-1);
425
  if (r.h.al < drv - 'A') return(-1);
426
  return(0);
426
  return(0);
427
}
427
}
428
#endif
428
#endif
429
 
429
 
430
 
430
 
431
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
431
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
432
static int get_cur_drive(void) {
432
static int get_cur_drive(void) {
433
  union REGS r;
433
  union REGS r;
434
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
434
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
435
  int86(0x21, &r, &r);
435
  int86(0x21, &r, &r);
436
  return(r.h.al);
436
  return(r.h.al);
437
}
437
}
438
 
438
 
439
 
439
 
440
/* returns 0 if file exists, non-zero otherwise */
440
/* returns 0 if file exists, non-zero otherwise */
441
static int fileexists(const char *fname) {
441
static int fileexists(const char *fname) {
442
  FILE *fd;
442
  FILE *fd;
443
  fd = fopen(fname, "rb");
443
  fd = fopen(fname, "rb");
444
  if (fd == NULL) return(-1);
444
  if (fd == NULL) return(-1);
445
  fclose(fd);
445
  fclose(fd);
446
  return(0);
446
  return(0);
447
}
447
}
448
 
448
 
449
 
449
 
450
static int preparedrive(char sourcedrv) {
450
static int preparedrive(char sourcedrv) {
451
  int driveremovable;
451
  int driveremovable;
452
  int selecteddrive = 3; /* default to 'C:' */
452
  int selecteddrive = 3; /* default to 'C:' */
453
  int cselecteddrive;
453
  int cselecteddrive;
454
  int ds;
454
  int ds;
455
  int choice;
455
  int choice;
456
  char buff[1024];
456
  char buff[1024];
457
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
457
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
458
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
458
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
459
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
459
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
460
    driveid = 2; /* primary drive is the emulated USB storage */
460
    driveid = 2; /* primary drive is the emulated USB storage */
461
  }
461
  }
462
  cselecteddrive = 'A' + selecteddrive - 1;
462
  cselecteddrive = 'A' + selecteddrive - 1;
463
  for (;;) {
463
  for (;;) {
464
    driveremovable = isdriveremovable(selecteddrive);
464
    driveremovable = isdriveremovable(selecteddrive);
465
    if (driveremovable < 0) {
465
    if (driveremovable < 0) {
466
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
466
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
467
      newscreen(0);
467
      newscreen(0);
468
      list[0] = kittengets(0, 3, list[0]);
468
      list[0] = kittengets(0, 3, list[0]);
469
      list[1] = kittengets(0, 4, list[1]);
469
      list[1] = kittengets(0, 4, list[1]);
470
      list[2] = kittengets(0, 2, list[2]);
470
      list[2] = kittengets(0, 2, list[2]);
471
      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 SvarDOS can be installed on it. Note, that SvarDOS 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, SVARDOS_DISK_REQ);
471
      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 SvarDOS can be installed on it. Note, that SvarDOS 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, SVARDOS_DISK_REQ);
472
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
472
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY[mono], buff), -1, 5, list, -1)) {
473
      switch (menuselect(14, -1, 5, list, -1)) {
-
 
474
        case 0:
473
        case 0:
475
          sprintf(buff, "FDISK /AUTO %d", driveid);
474
          sprintf(buff, "FDISK /AUTO %d", driveid);
476
          system(buff);
475
          system(buff);
477
          break;
476
          break;
478
        case 1:
477
        case 1:
479
          video_clear(0x0700, 0, 0);
478
          video_clear(0x0700, 0, 0);
480
          video_movecursor(0, 0);
479
          video_movecursor(0, 0);
481
          sprintf(buff, "FDISK %d", driveid);
480
          sprintf(buff, "FDISK %d", driveid);
482
          system(buff);
481
          system(buff);
483
          break;
482
          break;
484
        case 2:
483
        case 2:
485
          return(MENUQUIT);
484
          return(MENUQUIT);
486
        default:
485
        default:
487
          return(-1);
486
          return(-1);
488
      }
487
      }
489
      /* write a temporary MBR which only skips the drive (in case BIOS would
488
      /* write a temporary MBR which only skips the drive (in case BIOS would
490
       * try to boot off the not-yet-ready C: disk) */
489
       * try to boot off the not-yet-ready C: disk) */
491
      sprintf(buff, "FDISK /AMBR %d", driveid);
490
      sprintf(buff, "FDISK /AMBR %d", driveid);
492
      system(buff); /* writes BOOT.MBR into actual MBR */
491
      system(buff); /* writes BOOT.MBR into actual MBR */
493
      newscreen(2);
492
      newscreen(2);
494
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
493
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
495
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
494
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
496
      input_getkey();
495
      input_getkey();
497
      reboot();
496
      reboot();
498
      return(MENUQUIT);
497
      return(MENUQUIT);
499
    } else if (driveremovable > 0) {
498
    } else if (driveremovable > 0) {
500
      newscreen(2);
499
      newscreen(2);
501
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
500
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
502
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
501
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
503
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
502
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
504
      return(MENUQUIT);
503
      return(MENUQUIT);
505
    }
504
    }
506
    /* if not formatted, propose to format it right away (try to create a directory) */
505
    /* if not formatted, propose to format it right away (try to create a directory) */
507
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
506
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
508
    if (mkdir(buff) == 0) {
507
    if (mkdir(buff) == 0) {
509
      rmdir(buff);
508
      rmdir(buff);
510
    } else {
509
    } else {
511
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
510
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
512
      newscreen(0);
511
      newscreen(0);
513
      list[0] = kittengets(0, 6, list[0]);
512
      list[0] = kittengets(0, 6, list[0]);
514
      list[1] = kittengets(0, 2, list[1]);
513
      list[1] = kittengets(0, 2, list[1]);
515
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
514
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
516
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
515
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
517
      choice = menuselect(12, -1, 4, list, -1);
516
      choice = menuselect(12, -1, 4, list, -1);
518
      if (choice < 0) return(MENUPREV);
517
      if (choice < 0) return(MENUPREV);
519
      if (choice == 1) return(MENUQUIT);
518
      if (choice == 1) return(MENUQUIT);
520
      video_clear(0x0700, 0, 0);
519
      video_clear(0x0700, 0, 0);
521
      video_movecursor(0, 0);
520
      video_movecursor(0, 0);
522
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
521
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
523
      system(buff);
522
      system(buff);
524
      continue;
523
      continue;
525
    }
524
    }
526
    /* check total disk space */
525
    /* check total disk space */
527
    ds = disksize(selecteddrive);
526
    ds = disksize(selecteddrive);
528
    if (ds < SVARDOS_DISK_REQ) {
527
    if (ds < SVARDOS_DISK_REQ) {
529
      int y = 9;
528
      int y = 9;
530
      newscreen(2);
529
      newscreen(2);
531
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB."), cselecteddrive, SVARDOS_DISK_REQ);
530
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB."), cselecteddrive, SVARDOS_DISK_REQ);
532
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
531
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
533
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
532
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
534
      input_getkey();
533
      input_getkey();
535
      return(MENUQUIT);
534
      return(MENUQUIT);
536
    }
535
    }
537
    /* is the disk empty? */
536
    /* is the disk empty? */
538
    newscreen(0);
537
    newscreen(0);
539
    if (diskempty(selecteddrive) != 0) {
538
    if (diskempty(selecteddrive) != 0) {
540
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
539
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
541
      int y = 6;
540
      int y = 6;
542
      list[0] = kittengets(0, 6, list[0]);
541
      list[0] = kittengets(0, 6, list[0]);
543
      list[1] = kittengets(0, 2, list[1]);
542
      list[1] = kittengets(0, 2, list[1]);
544
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. SvarDOS 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);
543
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. SvarDOS 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);
545
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
544
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
546
      choice = menuselect(++y, -1, 4, list, -1);
545
      choice = menuselect(++y, -1, 4, list, -1);
547
      if (choice < 0) return(MENUPREV);
546
      if (choice < 0) return(MENUPREV);
548
      if (choice == 1) return(MENUQUIT);
547
      if (choice == 1) return(MENUQUIT);
549
      video_clear(0x0700, 0, 0);
548
      video_clear(0x0700, 0, 0);
550
      video_movecursor(0, 0);
549
      video_movecursor(0, 0);
551
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
550
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
552
      system(buff);
551
      system(buff);
553
      continue;
552
      continue;
554
    } else {
553
    } else {
555
      /* final confirmation */
554
      /* final confirmation */
556
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
555
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
557
      list[0] = kittengets(0, 1, list[0]);
556
      list[0] = kittengets(0, 1, list[0]);
558
      list[1] = kittengets(0, 2, list[1]);
557
      list[1] = kittengets(0, 2, list[1]);
559
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
558
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
560
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
559
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
561
      choice = menuselect(10, -1, 4, list, -1);
560
      choice = menuselect(10, -1, 4, list, -1);
562
      if (choice < 0) return(MENUPREV);
561
      if (choice < 0) return(MENUPREV);
563
      if (choice == 1) return(MENUQUIT);
562
      if (choice == 1) return(MENUQUIT);
564
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
563
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
565
      system(buff);
564
      system(buff);
566
      sprintf(buff, "FDISK /MBR %d", driveid);
565
      sprintf(buff, "FDISK /MBR %d", driveid);
567
      system(buff);
566
      system(buff);
568
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
567
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
569
      mkdir(buff);
568
      mkdir(buff);
570
      return(cselecteddrive);
569
      return(cselecteddrive);
571
    }
570
    }
572
  }
571
  }
573
}
572
}
574
 
573
 
575
 
574
 
576
/* generates locales-related configurations and writes them to file (this
575
/* generates locales-related configurations and writes them to file (this
577
 * is used to compute autoexec.bat content) */
576
 * is used to compute autoexec.bat content) */
578
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
577
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
579
  if (locales == NULL) return;
578
  if (locales == NULL) return;
580
 
579
 
581
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
580
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
582
 
581
 
583
  if (locales->egafile > 0) {
582
  if (locales->egafile > 0) {
584
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
583
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
585
    if (locales->egafile == 1) {
584
    if (locales->egafile == 1) {
586
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
585
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
587
    } else {
586
    } else {
588
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
587
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
589
    }
588
    }
590
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
589
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
591
  }
590
  }
592
 
591
 
593
  if (locales->keybfile > 0) {
592
  if (locales->keybfile > 0) {
594
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
593
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
595
    if (locales->keybfile == 1) {
594
    if (locales->keybfile == 1) {
596
      fprintf(fd, "KEYBOARD.SYS");
595
      fprintf(fd, "KEYBOARD.SYS");
597
    } else {
596
    } else {
598
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
597
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
599
    }
598
    }
600
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
599
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
601
    fprintf(fd, "\r\n");
600
    fprintf(fd, "\r\n");
602
  }
601
  }
603
}
602
}
604
 
603
 
605
 
604
 
606
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
605
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
607
  char buff[128];
606
  char buff[128];
608
  FILE *fd;
607
  FILE *fd;
609
  /*** CONFIG.SYS ***/
608
  /*** CONFIG.SYS ***/
610
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
609
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
611
  fd = fopen(buff, "wb");
610
  fd = fopen(buff, "wb");
612
  if (fd == NULL) return;
611
  if (fd == NULL) return;
613
  fprintf(fd, "DOS=UMB,HIGH\r\n"
612
  fprintf(fd, "DOS=UMB,HIGH\r\n"
614
              "LASTDRIVE=Z\r\n"
613
              "LASTDRIVE=Z\r\n"
615
              "FILES=50\r\n");
614
              "FILES=50\r\n");
616
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
615
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
617
  if (strcmp(locales->lang, "EN") == 0) {
616
  if (strcmp(locales->lang, "EN") == 0) {
618
    strcpy(buff, "COMMAND");
617
    strcpy(buff, "COMMAND");
619
  } else {
618
  } else {
620
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
619
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
621
  }
620
  }
622
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
621
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
623
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
622
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
624
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
623
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
625
  fclose(fd);
624
  fclose(fd);
626
  /*** AUTOEXEC.BAT ***/
625
  /*** AUTOEXEC.BAT ***/
627
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
626
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
628
  fd = fopen(buff, "wb");
627
  fd = fopen(buff, "wb");
629
  if (fd == NULL) return;
628
  if (fd == NULL) return;
630
  fprintf(fd, "@ECHO OFF\r\n");
629
  fprintf(fd, "@ECHO OFF\r\n");
631
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
630
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
632
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
631
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
633
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
632
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
634
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
633
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
635
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
634
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
636
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
635
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
637
  fprintf(fd, "PROMPT $P$G\r\n");
636
  fprintf(fd, "PROMPT $P$G\r\n");
638
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
637
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
639
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
638
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
640
  fprintf(fd, "FDAPM APMDOS\r\n");
639
  fprintf(fd, "FDAPM APMDOS\r\n");
641
  fprintf(fd, "\r\n");
640
  fprintf(fd, "\r\n");
642
  genlocalesconf(fd, locales);
641
  genlocalesconf(fd, locales);
643
  fprintf(fd, "\r\n");
642
  fprintf(fd, "\r\n");
644
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
643
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
645
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
644
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
646
  fprintf(fd, "\r\n");
645
  fprintf(fd, "\r\n");
647
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
646
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
648
  fprintf(fd, "REM CTMOUSE\r\n");
647
  fprintf(fd, "REM CTMOUSE\r\n");
649
  fprintf(fd, "\r\n");
648
  fprintf(fd, "\r\n");
650
  fprintf(fd, "ECHO.\r\n");
649
  fprintf(fd, "ECHO.\r\n");
651
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
650
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
652
  fclose(fd);
651
  fclose(fd);
653
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
652
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
654
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
653
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
655
  mkdir(buff);
654
  mkdir(buff);
656
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
655
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
657
  mkdir(buff);
656
  mkdir(buff);
658
  /*** PKG.CFG ***/
657
  /*** PKG.CFG ***/
659
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
658
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
660
  fd = fopen(buff, "wb");
659
  fd = fopen(buff, "wb");
661
  if (fd == NULL) return;
660
  if (fd == NULL) return;
662
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
661
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
663
              "\r\n"
662
              "\r\n"
664
              "# Programs\r\n"
663
              "# Programs\r\n"
665
              "DIR PROGS C:\\\r\n"
664
              "DIR PROGS C:\\\r\n"
666
              "\r\n"
665
              "\r\n"
667
              "# Games \r\n"
666
              "# Games \r\n"
668
              "DIR GAMES C:\\\r\n"
667
              "DIR GAMES C:\\\r\n"
669
              "\r\n"
668
              "\r\n"
670
              "# Drivers\r\n"
669
              "# Drivers\r\n"
671
              "DIR DRIVERS C:\\DRIVERS\r\n"
670
              "DIR DRIVERS C:\\DRIVERS\r\n"
672
              "\r\n"
671
              "\r\n"
673
              "# Development tools\r\n"
672
              "# Development tools\r\n"
674
              "DIR DEVEL C:\\DEVEL\r\n");
673
              "DIR DEVEL C:\\DEVEL\r\n");
675
  fclose(fd);
674
  fclose(fd);
676
  /*** COUNTRY.SYS ***/
675
  /*** COUNTRY.SYS ***/
677
  /*** PICOTCP ***/
676
  /*** PICOTCP ***/
678
  /*** WATTCP ***/
677
  /*** WATTCP ***/
679
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
678
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
680
  fd = fopen(buff, "wb");
679
  fd = fopen(buff, "wb");
681
  if (fd == NULL) return;
680
  if (fd == NULL) return;
682
  fprintf(fd, "my_ip = dhcp\r\n"
681
  fprintf(fd, "my_ip = dhcp\r\n"
683
              "#my_ip = 192.168.0.7\r\n"
682
              "#my_ip = 192.168.0.7\r\n"
684
              "#netmask = 255.255.255.0\r\n"
683
              "#netmask = 255.255.255.0\r\n"
685
              "#nameserver = 192.168.0.1\r\n"
684
              "#nameserver = 192.168.0.1\r\n"
686
              "#nameserver = 192.168.0.2\r\n"
685
              "#nameserver = 192.168.0.2\r\n"
687
              "#gateway = 192.168.0.1\r\n");
686
              "#gateway = 192.168.0.1\r\n");
688
  fclose(fd);
687
  fclose(fd);
689
}
688
}
690
 
689
 
691
 
690
 
692
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
691
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
693
  char pkglist[512];
692
  char pkglist[512];
694
  int i, pkglistlen;
693
  int i, pkglistlen;
695
  size_t pkglistflen;
694
  size_t pkglistflen;
696
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
695
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
697
  FILE *fd = NULL;
696
  FILE *fd = NULL;
698
  char *pkgptr;
697
  char *pkgptr;
699
  newscreen(3);
698
  newscreen(3);
700
  /* load pkg list */
699
  /* load pkg list */
701
  fd = fopen("install.lst", "rb");
700
  fd = fopen("install.lst", "rb");
702
  if (fd == NULL) {
701
  if (fd == NULL) {
703
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
702
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
704
    input_getkey();
703
    input_getkey();
705
    return(-1);
704
    return(-1);
706
  }
705
  }
707
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
706
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
708
  fclose(fd);
707
  fclose(fd);
709
  if (pkglistflen == sizeof(pkglist)) {
708
  if (pkglistflen == sizeof(pkglist)) {
710
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
709
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
711
    input_getkey();
710
    input_getkey();
712
    return(-1);
711
    return(-1);
713
  }
712
  }
714
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
713
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
715
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
714
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
716
  pkglistlen = 0;
715
  pkglistlen = 0;
717
  for (i = 0; i < pkglistflen; i++) {
716
  for (i = 0; i < pkglistflen; i++) {
718
    switch (pkglist[i]) {
717
    switch (pkglist[i]) {
719
      case '\n':
718
      case '\n':
720
        pkglistlen++;
719
        pkglistlen++;
721
        /* FALLTHRU */
720
        /* FALLTHRU */
722
      case '\r':
721
      case '\r':
723
        pkglist[i] = 0;
722
        pkglist[i] = 0;
724
        break;
723
        break;
725
    }
724
    }
726
  }
725
  }
727
  /* copy pkg.exe to the new drive, along with all packages */
726
  /* copy pkg.exe to the new drive, along with all packages */
728
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
727
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
729
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
728
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
730
  fcopy(buff, buff + 64, buff, sizeof(buff));
729
  fcopy(buff, buff + 64, buff, sizeof(buff));
731
 
730
 
732
  /* open the post-install autoexec.bat and prepare initial instructions */
731
  /* open the post-install autoexec.bat and prepare initial instructions */
733
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
732
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
734
  fd = fopen(buff, "wb");
733
  fd = fopen(buff, "wb");
735
  if (fd == NULL) return(-1);
734
  if (fd == NULL) return(-1);
736
  fprintf(fd, "@ECHO OFF\r\n");
735
  fprintf(fd, "@ECHO OFF\r\n");
737
 
736
 
738
  /* copy packages */
737
  /* copy packages */
739
  pkgptr = pkglist;
738
  pkgptr = pkglist;
740
  for (i = 0;; i++) {
739
  for (i = 0;; i++) {
741
    /* move forward to nearest entry or end of list */
740
    /* move forward to nearest entry or end of list */
742
    while (*pkgptr == 0) pkgptr++;
741
    while (*pkgptr == 0) pkgptr++;
743
    if (*pkgptr == 0xff) break;
742
    if (*pkgptr == 0xff) break;
744
    /* install the package */
743
    /* install the package */
745
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
744
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
746
    strcat(buff, "       ");
745
    strcat(buff, "       ");
747
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
746
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
748
    /* wait for new diskette if package not found */
747
    /* wait for new diskette if package not found */
749
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
748
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
750
    while (fileexists(buff) != 0) {
749
    while (fileexists(buff) != 0) {
751
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
750
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
752
      input_getkey();
751
      input_getkey();
753
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
752
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
754
    }
753
    }
755
    /* proceed with package copy (buff contains the src filename already) */
754
    /* proceed with package copy (buff contains the src filename already) */
756
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
755
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
757
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
756
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
758
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
757
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
759
      input_getkey();
758
      input_getkey();
760
      fclose(fd);
759
      fclose(fd);
761
      return(-1);
760
      return(-1);
762
    }
761
    }
763
    /* write install instruction to post-install script */
762
    /* write install instruction to post-install script */
764
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
763
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
765
    /* jump to next entry or end of list */
764
    /* jump to next entry or end of list */
766
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
765
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
767
    if (*pkgptr == 0xff) break;
766
    if (*pkgptr == 0xff) break;
768
  }
767
  }
769
  /* set up locales so the "installation over" message is nicely displayed */
768
  /* set up locales so the "installation over" message is nicely displayed */
770
  genlocalesconf(fd, locales);
769
  genlocalesconf(fd, locales);
771
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
770
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
772
  fprintf(fd, "DEL pkg.exe\r\n"
771
  fprintf(fd, "DEL pkg.exe\r\n"
773
              "COPY CONFIG.SYS C:\\\r\n"
772
              "COPY CONFIG.SYS C:\\\r\n"
774
              "DEL CONFIG.SYS\r\n"
773
              "DEL CONFIG.SYS\r\n"
775
              "DEL C:\\AUTOEXEC.BAT\r\n"
774
              "DEL C:\\AUTOEXEC.BAT\r\n"
776
              "COPY AUTOEXEC.BAT C:\\\r\n"
775
              "COPY AUTOEXEC.BAT C:\\\r\n"
777
              "DEL AUTOEXEC.BAT\r\n");
776
              "DEL AUTOEXEC.BAT\r\n");
778
  /* print out the "installation over" message */
777
  /* print out the "installation over" message */
779
  fprintf(fd, "ECHO.\r\n"
778
  fprintf(fd, "ECHO.\r\n"
780
              "ECHO %s\r\n"
779
              "ECHO %s\r\n"
781
              "ECHO.\r\n", kittengets(5, 1, "SvarDOS installation is over. Please restart your computer now."));
780
              "ECHO.\r\n", kittengets(5, 1, "SvarDOS installation is over. Please restart your computer now."));
782
  fclose(fd);
781
  fclose(fd);
783
 
782
 
784
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
783
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
785
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
784
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
786
  fd = fopen(buff, "wb");
785
  fd = fopen(buff, "wb");
787
  if (fd == NULL) return(-1);
786
  if (fd == NULL) return(-1);
788
  fprintf(fd, "@ECHO OFF\r\n"
787
  fprintf(fd, "@ECHO OFF\r\n"
789
              "SET DOSDIR=C:\\SVARDOS\r\n"
788
              "SET DOSDIR=C:\\SVARDOS\r\n"
790
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
789
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
791
              "PATH %%DOSDIR%%\\BIN\r\n");
790
              "PATH %%DOSDIR%%\\BIN\r\n");
792
  fprintf(fd, "CD TEMP\r\n"
791
  fprintf(fd, "CD TEMP\r\n"
793
              "postinst.bat\r\n");
792
              "postinst.bat\r\n");
794
  fclose(fd);
793
  fclose(fd);
795
 
794
 
796
  return(0);
795
  return(0);
797
}
796
}
798
 
797
 
799
 
798
 
800
static void finalreboot(void) {
799
static void finalreboot(void) {
801
  int y = 9;
800
  int y = 9;
802
  newscreen(2);
801
  newscreen(2);
803
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Your computer will reboot now.\nPlease remove the installation disk from your drive.");
802
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Your computer will reboot now.\nPlease remove the installation disk from your drive.");
804
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
803
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
805
  input_getkey();
804
  input_getkey();
806
  reboot();
805
  reboot();
807
}
806
}
808
 
807
 
809
 
808
 
810
static void loadcp(const struct slocales *locales) {
809
static void loadcp(const struct slocales *locales) {
811
  char buff[64];
810
  char buff[64];
812
  if (locales->codepage == 437) return;
811
  if (locales->codepage == 437) return;
813
  video_movecursor(1, 0);
812
  video_movecursor(1, 0);
814
  if (locales->egafile == 1) {
813
  if (locales->egafile == 1) {
815
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
814
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
816
  } else {
815
  } else {
817
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
816
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
818
  }
817
  }
819
  system(buff);
818
  system(buff);
820
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
819
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
821
  system(buff);
820
  system(buff);
822
  /* below I re-init the video controller - apparently this is required if
821
  /* below I re-init the video controller - apparently this is required if
823
   * I want the new glyph symbols to be actually applied, at least some
822
   * I want the new glyph symbols to be actually applied, at least some
824
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
823
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
825
  {
824
  {
826
  union REGS r;
825
  union REGS r;
827
  r.h.ah = 0x0F; /* get current video mode */
826
  r.h.ah = 0x0F; /* get current video mode */
828
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
827
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
829
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
828
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
830
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
829
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
831
  int86(0x10, &r, &r);
830
  int86(0x10, &r, &r);
832
  }
831
  }
833
}
832
}
834
 
833
 
835
 
834
 
836
#ifdef DEADCODE
835
#ifdef DEADCODE
837
/* checks that drive drv contains SvarDOS packages
836
/* checks that drive drv contains SvarDOS packages
838
 * returns 0 if found, non-zero otherwise */
837
 * returns 0 if found, non-zero otherwise */
839
static int checkinstsrc(char drv) {
838
static int checkinstsrc(char drv) {
840
  char fname[16];
839
  char fname[16];
841
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
840
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
842
  return(fileexists(fname));
841
  return(fileexists(fname));
843
}
842
}
844
#endif
843
#endif
845
 
844
 
846
 
845
 
847
int main(void) {
846
int main(void) {
848
  struct slocales locales;
847
  struct slocales locales;
849
  int targetdrv;
848
  int targetdrv;
850
  int sourcedrv;
849
  int sourcedrv;
851
  int action;
850
  int action;
852
 
851
 
853
  sourcedrv = get_cur_drive() + 'A';
852
  sourcedrv = get_cur_drive() + 'A';
854
 
853
 
855
  /* init screen and detect mono status */
854
  /* init screen and detect mono status */
856
  mono = video_init();
855
  mono = video_init();
857
 
856
 
858
  kittenopen("INSTALL"); /* load initial NLS support */
857
  kittenopen("INSTALL"); /* load initial NLS support */
859
 
858
 
860
 SelectLang:
859
 SelectLang:
861
  action = selectlang(&locales); /* welcome to svardos, select your language */
860
  action = selectlang(&locales); /* welcome to svardos, select your language */
862
  if (action != MENUNEXT) goto Quit;
861
  if (action != MENUNEXT) goto Quit;
863
  setenv("LANG", locales.lang, 1);
862
  setenv("LANG", locales.lang, 1);
864
  loadcp(&locales);
863
  loadcp(&locales);
865
  kittenclose(); /* reload NLS with new language */
864
  kittenclose(); /* reload NLS with new language */
866
  kittenopen("INSTALL"); /* NLS support */
865
  kittenopen("INSTALL"); /* NLS support */
867
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
866
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
868
  if (action == MENUQUIT) goto Quit;
867
  if (action == MENUQUIT) goto Quit;
869
  if (action == MENUPREV) goto SelectLang;
868
  if (action == MENUPREV) goto SelectLang;
870
 
869
 
871
 WelcomeScreen:
870
 WelcomeScreen:
872
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
871
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
873
  if (action == MENUQUIT) goto Quit;
872
  if (action == MENUQUIT) goto Quit;
874
  if (action == MENUPREV) goto SelectLang;
873
  if (action == MENUPREV) goto SelectLang;
875
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
874
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
876
  if (targetdrv == MENUQUIT) goto Quit;
875
  if (targetdrv == MENUQUIT) goto Quit;
877
  if (targetdrv == MENUPREV) goto WelcomeScreen;
876
  if (targetdrv == MENUPREV) goto WelcomeScreen;
878
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
877
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
879
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
878
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
880
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
879
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
881
  /*netcfg();*/ /* basic networking config */
880
  /*netcfg();*/ /* basic networking config */
882
  finalreboot(); /* remove the CD and reboot */
881
  finalreboot(); /* remove the CD and reboot */
883
 
882
 
884
 Quit:
883
 Quit:
885
  kittenclose(); /* close NLS support */
884
  kittenclose(); /* close NLS support */
886
  video_clear(0x0700, 0, 0);
885
  video_clear(0x0700, 0, 0);
887
  video_movecursor(0, 0);
886
  video_movecursor(0, 0);
888
  return(0);
887
  return(0);
889
}
888
}
890
 
889