Subversion Repositories SvarDOS

Rev

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

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