Subversion Repositories SvarDOS

Rev

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

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