Subversion Repositories SvarDOS

Rev

Rev 1179 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1179 Rev 1180
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-2023 MATEUSZ VISTE, ALL RIGHTS RESERVED.
6
 * COPYRIGHT (C) 2016-2023 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
    "Brazilian",
269
    "Brazilian",
270
    "French",
270
    "French",
271
    "German",
271
    "German",
272
    "Italian",
272
    "Italian",
273
    "Polish",
273
    "Polish",
274
    "Russian",
274
    "Russian",
275
    "Slovene",
275
    "Slovene",
276
    "Swedish",
276
    "Swedish",
277
    "Turkish",
277
    "Turkish",
278
    NULL
278
    NULL
279
  };
279
  };
280
 
280
 
281
  newscreen(1);
281
  newscreen(1);
282
  msg = svarlang_strid(0x0100); /* "Welcome to SvarDOS" */
282
  msg = svarlang_strid(0x0100); /* "Welcome to SvarDOS" */
283
  x = 40 - (strlen(msg) >> 1);
283
  x = 40 - (strlen(msg) >> 1);
284
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
284
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
285
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
285
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
286
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1); /* "Please select your language from the list below:" */
286
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1); /* "Please select your language from the list below:" */
287
  choice = menuselect(11, -1, 11, langlist, -1);
287
  choice = menuselect(11, -1, 11, langlist, -1);
288
  if (choice < 0) return(MENUPREV);
288
  if (choice < 0) return(MENUPREV);
289
  /* populate locales with default values */
289
  /* populate locales with default values */
290
  memset(locales, 0, sizeof(struct slocales));
290
  memset(locales, 0, sizeof(struct slocales));
291
  switch (choice) {
291
  switch (choice) {
292
    case 1:
292
    case 1:
293
      strcpy(locales->lang, "BR");
293
      strcpy(locales->lang, "BR");
294
      locales->keyboff = OFFLOC_BR;
294
      locales->keyboff = OFFLOC_BR;
295
      locales->keyblen = OFFLEN_BR;
295
      locales->keyblen = OFFLEN_BR;
296
      break;
296
      break;
297
    case 2:
297
    case 2:
298
      strcpy(locales->lang, "FR");
298
      strcpy(locales->lang, "FR");
299
      locales->keyboff = OFFLOC_FR;
299
      locales->keyboff = OFFLOC_FR;
300
      locales->keyblen = OFFLEN_FR;
300
      locales->keyblen = OFFLEN_FR;
301
      break;
301
      break;
302
    case 3:
302
    case 3:
303
      strcpy(locales->lang, "DE");
303
      strcpy(locales->lang, "DE");
304
      locales->keyboff = OFFLOC_DE;
304
      locales->keyboff = OFFLOC_DE;
305
      locales->keyblen = OFFLEN_DE;
305
      locales->keyblen = OFFLEN_DE;
306
      break;
306
      break;
307
    case 4:
307
    case 4:
308
      strcpy(locales->lang, "IT");
308
      strcpy(locales->lang, "IT");
309
      locales->keyboff = OFFLOC_IT;
309
      locales->keyboff = OFFLOC_IT;
310
      locales->keyblen = OFFLEN_IT;
310
      locales->keyblen = OFFLEN_IT;
311
      break;
311
      break;
312
    case 5:
312
    case 5:
313
      strcpy(locales->lang, "PL");
313
      strcpy(locales->lang, "PL");
314
      locales->keyboff = OFFLOC_PL;
314
      locales->keyboff = OFFLOC_PL;
315
      locales->keyblen = OFFLEN_PL;
315
      locales->keyblen = OFFLEN_PL;
316
      break;
316
      break;
317
    case 6:
317
    case 6:
318
      strcpy(locales->lang, "RU");
318
      strcpy(locales->lang, "RU");
319
      locales->keyboff = OFFLOC_RU;
319
      locales->keyboff = OFFLOC_RU;
320
      locales->keyblen = OFFLEN_RU;
320
      locales->keyblen = OFFLEN_RU;
321
      break;
321
      break;
322
    case 7:
322
    case 7:
323
      strcpy(locales->lang, "SI");
323
      strcpy(locales->lang, "SI");
324
      locales->keyboff = OFFLOC_SI;
324
      locales->keyboff = OFFLOC_SI;
325
      locales->keyblen = OFFLEN_SI;
325
      locales->keyblen = OFFLEN_SI;
326
      break;
326
      break;
327
    case 8:
327
    case 8:
328
      strcpy(locales->lang, "SV");
328
      strcpy(locales->lang, "SV");
329
      locales->keyboff = OFFLOC_SV;
329
      locales->keyboff = OFFLOC_SV;
330
      locales->keyblen = OFFLEN_SV;
330
      locales->keyblen = OFFLEN_SV;
331
      break;
331
      break;
332
    case 9:
332
    case 9:
333
      strcpy(locales->lang, "TR");
333
      strcpy(locales->lang, "TR");
334
      locales->keyboff = OFFLOC_TR;
334
      locales->keyboff = OFFLOC_TR;
335
      locales->keyblen = OFFLEN_TR;
335
      locales->keyblen = OFFLEN_TR;
336
      break;
336
      break;
337
    default:
337
    default:
338
      strcpy(locales->lang, "EN");
338
      strcpy(locales->lang, "EN");
339
      locales->keyboff = 0;
339
      locales->keyboff = 0;
340
      locales->keyblen = OFFCOUNT;
340
      locales->keyblen = OFFCOUNT;
341
      break;
341
      break;
342
  }
342
  }
343
  /* populate the slocales struct accordingly to the keyboff member */
343
  /* populate the slocales struct accordingly to the keyboff member */
344
  kblay2slocal(locales);
344
  kblay2slocal(locales);
345
  /* */
345
  /* */
346
  return(MENUNEXT);
346
  return(MENUNEXT);
347
}
347
}
348
 
348
 
349
 
349
 
350
static int selectkeyb(struct slocales *locales) {
350
static int selectkeyb(struct slocales *locales) {
351
  int menuheight, choice;
351
  int menuheight, choice;
352
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
352
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
353
  newscreen(0);
353
  newscreen(0);
354
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5); /* "SvarDOS supports different keyboard layouts */
354
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5); /* "SvarDOS supports different keyboard layouts */
355
  menuheight = locales->keyblen + 2;
355
  menuheight = locales->keyblen + 2;
356
  if (menuheight > 13) menuheight = 13;
356
  if (menuheight > 13) menuheight = 13;
357
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
357
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
358
  if (choice < 0) return(MENUPREV);
358
  if (choice < 0) return(MENUPREV);
359
  /* (re)load the keyboard layout & codepage setup */
359
  /* (re)load the keyboard layout & codepage setup */
360
  locales->keyboff += choice;
360
  locales->keyboff += choice;
361
  kblay2slocal(locales);
361
  kblay2slocal(locales);
362
  return(MENUNEXT);
362
  return(MENUNEXT);
363
}
363
}
364
 
364
 
365
 
365
 
366
/* returns 0 if installation must proceed, non-zero otherwise */
366
/* returns 0 if installation must proceed, non-zero otherwise */
367
static int welcomescreen(void) {
367
static int welcomescreen(void) {
368
  int c;
368
  int c;
369
  const char *choice[3];
369
  const char *choice[3];
370
  choice[0] = svarlang_strid(0x0001);
370
  choice[0] = svarlang_strid(0x0001);
371
  choice[1] = svarlang_strid(0x0002);
371
  choice[1] = svarlang_strid(0x0002);
372
  choice[2] = NULL;
372
  choice[2] = NULL;
373
  newscreen(0);
373
  newscreen(0);
374
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0); /* "You are about to install SvarDOS */
374
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0); /* "You are about to install SvarDOS */
375
  c = menuselect(13, -1, 4, choice, -1);
375
  c = menuselect(13, -1, 4, choice, -1);
376
  if (c < 0) return(MENUPREV);
376
  if (c < 0) return(MENUPREV);
377
  if (c == 0) return(MENUNEXT);
377
  if (c == 0) return(MENUNEXT);
378
  return(MENUQUIT);
378
  return(MENUQUIT);
379
}
379
}
380
 
380
 
381
 
381
 
382
/* returns 1 if drive is removable, 0 if not, -1 on error */
382
/* returns 1 if drive is removable, 0 if not, -1 on error */
383
static int isdriveremovable(int drv) {
383
static int isdriveremovable(int drv) {
384
  union REGS r;
384
  union REGS r;
385
  r.x.ax = 0x4408;
385
  r.x.ax = 0x4408;
386
  r.h.bl = drv;
386
  r.h.bl = drv;
387
  int86(0x21, &r, &r);
387
  int86(0x21, &r, &r);
388
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
388
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
389
  if (r.x.cflag != 0) return(-1);
389
  if (r.x.cflag != 0) return(-1);
390
  if (r.x.ax == 0) return(1);
390
  if (r.x.ax == 0) return(1);
391
  return(0);
391
  return(0);
392
}
392
}
393
 
393
 
394
 
394
 
395
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
395
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
396
static int disksize(int drv) {
396
static int disksize(int drv) {
397
  long res;
397
  long res;
398
  union REGS r;
398
  union REGS r;
399
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
399
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
400
  r.h.dl = drv;  /* A=1, B=2, etc */
400
  r.h.dl = drv;  /* A=1, B=2, etc */
401
  int86(0x21, &r, &r);
401
  int86(0x21, &r, &r);
402
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
402
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
403
  res = r.x.ax;  /* sectors per cluster */
403
  res = r.x.ax;  /* sectors per cluster */
404
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
404
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
405
  res *= r.x.cx; /* bytes per sector */
405
  res *= r.x.cx; /* bytes per sector */
406
  res >>= 20;    /* convert bytes to MiB */
406
  res >>= 20;    /* convert bytes to MiB */
407
  return(res);
407
  return(res);
408
}
408
}
409
 
409
 
410
 
410
 
411
/* returns 0 if disk is empty, non-zero otherwise */
411
/* returns 0 if disk is empty, non-zero otherwise */
412
static int diskempty(int drv) {
412
static int diskempty(int drv) {
413
  unsigned int rc;
413
  unsigned int rc;
414
  int res;
414
  int res;
415
  char buff[8];
415
  char buff[8];
416
  struct find_t fileinfo;
416
  struct find_t fileinfo;
417
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
417
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
418
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
418
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
419
  if (rc == 0) {
419
  if (rc == 0) {
420
    res = 1; /* call successfull means disk is not empty */
420
    res = 1; /* call successfull means disk is not empty */
421
  } else {
421
  } else {
422
    res = 0;
422
    res = 0;
423
  }
423
  }
424
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
424
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
425
  return(res);
425
  return(res);
426
}
426
}
427
 
427
 
428
#ifdef DEADCODE
428
#ifdef DEADCODE
429
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
429
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
430
static int set_cur_drive(char drv) {
430
static int set_cur_drive(char drv) {
431
  union REGS r;
431
  union REGS r;
432
  if ((drv < 'A') || (drv > 'Z')) return(-1);
432
  if ((drv < 'A') || (drv > 'Z')) return(-1);
433
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
433
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
434
  r.h.dl = drv - 'A';
434
  r.h.dl = drv - 'A';
435
  int86(0x21, &r, &r);
435
  int86(0x21, &r, &r);
436
  if (r.h.al < drv - 'A') return(-1);
436
  if (r.h.al < drv - 'A') return(-1);
437
  return(0);
437
  return(0);
438
}
438
}
439
#endif
439
#endif
440
 
440
 
441
 
441
 
442
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
442
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
443
static int get_cur_drive(void) {
443
static int get_cur_drive(void) {
444
  union REGS r;
444
  union REGS r;
445
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
445
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
446
  int86(0x21, &r, &r);
446
  int86(0x21, &r, &r);
447
  return(r.h.al);
447
  return(r.h.al);
448
}
448
}
449
 
449
 
450
 
450
 
451
/* returns 0 if file exists, non-zero otherwise */
451
/* returns 0 if file exists, non-zero otherwise */
452
static int fileexists(const char *fname) {
452
static int fileexists(const char *fname) {
453
  FILE *fd;
453
  FILE *fd;
454
  fd = fopen(fname, "rb");
454
  fd = fopen(fname, "rb");
455
  if (fd == NULL) return(-1);
455
  if (fd == NULL) return(-1);
456
  fclose(fd);
456
  fclose(fd);
457
  return(0);
457
  return(0);
458
}
458
}
459
 
459
 
460
 
460
 
461
/* tries to write an empty file to drive.
461
/* tries to write an empty file to drive.
462
 * asks DOS to inhibit the int 24h handler for this job, so erros are
462
 * asks DOS to inhibit the int 24h handler for this job, so erros are
463
 * gracefully reported - unfortunately this does not work under FreeDOS because
463
 * gracefully reported - unfortunately this does not work under FreeDOS because
464
 * the DOS-C kernel does not implement the required flag.
464
 * the DOS-C kernel does not implement the required flag.
465
 * returns 0 on success (ie. "disk exists and is writeable"). */
465
 * returns 0 on success (ie. "disk exists and is writeable"). */
466
static unsigned short test_drive_write(char drive, char *buff) {
466
static unsigned short test_drive_write(char drive, char *buff) {
467
  unsigned short result = 0;
467
  unsigned short result = 0;
468
  sprintf(buff, "%c:\\SVWRTEST.123", drive);
468
  sprintf(buff, "%c:\\SVWRTEST.123", drive);
469
  _asm {
469
  _asm {
470
    push ax
470
    push ax
471
    push bx
471
    push bx
472
    push cx
472
    push cx
473
    push dx
473
    push dx
474
 
474
 
475
    mov ah, 0x6c   /* extended open/create file */
475
    mov ah, 0x6c   /* extended open/create file */
476
    mov bx, 0x2001 /* open for write + inhibit int 24h handler */
476
    mov bx, 0x2001 /* open for write + inhibit int 24h handler */
477
    xor cx, cx     /* file attributes on the created file */
477
    xor cx, cx     /* file attributes on the created file */
478
    mov dx, 0x0010 /* create file if does not exist, fail if it exists */
478
    mov dx, 0x0010 /* create file if does not exist, fail if it exists */
479
    mov si, buff   /* filename to create */
479
    mov si, buff   /* filename to create */
480
    int 0x21
480
    int 0x21
481
    jc FAILURE
481
    jc FAILURE
482
    /* close the file (handle in AX) */
482
    /* close the file (handle in AX) */
483
    mov bx, ax
483
    mov bx, ax
484
    mov ah, 0x3e /* close file */
484
    mov ah, 0x3e /* close file */
485
    int 0x21
485
    int 0x21
486
    jc FAILURE
486
    jc FAILURE
487
    /* delete the file */
487
    /* delete the file */
488
    mov ah, 0x41 /* delete file pointed out by DS:DX */
488
    mov ah, 0x41 /* delete file pointed out by DS:DX */
489
    mov dx, buff
489
    mov dx, buff
490
    int 0x21
490
    int 0x21
491
    jnc DONE
491
    jnc DONE
492
 
492
 
493
    FAILURE:
493
    FAILURE:
494
    mov result, ax
494
    mov result, ax
495
    DONE:
495
    DONE:
496
 
496
 
497
    pop dx
497
    pop dx
498
    pop cx
498
    pop cx
499
    pop bx
499
    pop bx
500
    pop ax
500
    pop ax
501
  }
501
  }
502
  return(result);
502
  return(result);
503
}
503
}
504
 
504
 
505
 
505
 
506
static int preparedrive(char sourcedrv) {
506
static int preparedrive(char sourcedrv) {
507
  int driveremovable;
507
  int driveremovable;
508
  int selecteddrive = 3; /* default to 'C:' */
508
  int selecteddrive = 3; /* default to 'C:' */
509
  int cselecteddrive;
509
  int cselecteddrive;
510
  int ds;
510
  int ds;
511
  int choice;
511
  int choice;
512
  char buff[1024];
512
  char buff[1024];
513
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
513
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
514
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
514
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
515
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
515
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
516
    driveid = 2; /* primary drive is the emulated USB storage */
516
    driveid = 2; /* primary drive is the emulated USB storage */
517
  }
517
  }
518
  cselecteddrive = 'A' + selecteddrive - 1;
518
  cselecteddrive = 'A' + selecteddrive - 1;
519
  for (;;) {
519
  for (;;) {
520
    driveremovable = isdriveremovable(selecteddrive);
520
    driveremovable = isdriveremovable(selecteddrive);
521
    if (driveremovable < 0) {
521
    if (driveremovable < 0) {
522
      const char *list[4];
522
      const char *list[4];
523
      newscreen(0);
523
      newscreen(0);
524
      list[0] = svarlang_str(0, 3); /* Create a partition automatically */
524
      list[0] = svarlang_str(0, 3); /* Create a partition automatically */
525
      list[1] = svarlang_str(0, 4); /* Run the FDISK tool */
525
      list[1] = svarlang_str(0, 4); /* Run the FDISK tool */
526
      list[2] = svarlang_str(0, 2); /* Quit to DOS */
526
      list[2] = svarlang_str(0, 2); /* Quit to DOS */
527
      list[3] = NULL;
527
      list[3] = NULL;
528
      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 */
528
      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 */
529
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY[mono], buff), -1, 5, list, -1)) {
529
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY[mono], buff), -1, 5, list, -1)) {
530
        case 0:
530
        case 0:
531
          sprintf(buff, "FDISK /AUTO %d", driveid);
531
          sprintf(buff, "FDISK /AUTO %d", driveid);
532
          system(buff);
532
          system(buff);
533
          break;
533
          break;
534
        case 1:
534
        case 1:
535
          video_clear(0x0700, 0, 0);
535
          video_clear(0x0700, 0, 0);
536
          video_movecursor(0, 0);
536
          video_movecursor(0, 0);
537
          sprintf(buff, "FDISK %d", driveid);
537
          sprintf(buff, "FDISK %d", driveid);
538
          system(buff);
538
          system(buff);
539
          break;
539
          break;
540
        case 2:
540
        case 2:
541
          return(MENUQUIT);
541
          return(MENUQUIT);
542
        default:
542
        default:
543
          return(-1);
543
          return(-1);
544
      }
544
      }
545
      /* write a temporary MBR which only skips the drive (in case BIOS would
545
      /* write a temporary MBR which only skips the drive (in case BIOS would
546
       * try to boot off the not-yet-ready C: disk) */
546
       * try to boot off the not-yet-ready C: disk) */
547
      sprintf(buff, "FDISK /AMBR %d", driveid);
547
      sprintf(buff, "FDISK /AMBR %d", driveid);
548
      system(buff); /* writes BOOT.MBR into actual MBR */
548
      system(buff); /* writes BOOT.MBR into actual MBR */
549
      newscreen(2);
549
      newscreen(2);
550
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1); /* "Your computer will reboot now." */
550
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1); /* "Your computer will reboot now." */
551
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
551
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
552
      input_getkey();
552
      input_getkey();
553
      reboot();
553
      reboot();
554
      return(MENUQUIT);
554
      return(MENUQUIT);
555
    } else if (driveremovable > 0) {
555
    } else if (driveremovable > 0) {
556
      newscreen(2);
556
      newscreen(2);
557
      snprintf(buff, sizeof(buff), svarlang_strid(0x0302), cselecteddrive); /* "ERROR: Drive %c: is a removable device */
557
      snprintf(buff, sizeof(buff), svarlang_strid(0x0302), cselecteddrive); /* "ERROR: Drive %c: is a removable device */
558
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
558
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
559
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
559
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
560
      return(MENUQUIT);
560
      return(MENUQUIT);
561
    }
561
    }
562
    /* if not formatted, propose to format it right away (try to create a directory) */
562
    /* if not formatted, propose to format it right away (try to create a directory) */
563
    if (test_drive_write(cselecteddrive, buff) != 0) {
563
    if (test_drive_write(cselecteddrive, buff) != 0) {
564
      const char *list[3];
564
      const char *list[3];
565
      newscreen(0);
565
      newscreen(0);
566
      snprintf(buff, sizeof(buff), svarlang_str(3, 3), cselecteddrive); /* "ERROR: Drive %c: seems to be unformated. Do you wish to format it?") */
566
      snprintf(buff, sizeof(buff), svarlang_str(3, 3), cselecteddrive); /* "ERROR: Drive %c: seems to be unformated. Do you wish to format it?") */
567
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
567
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
568
 
568
 
569
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
569
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
570
      list[0] = buff;
570
      list[0] = buff;
571
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
571
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
572
      list[2] = NULL;
572
      list[2] = NULL;
573
 
573
 
574
      choice = menuselect(12, -1, 4, list, -1);
574
      choice = menuselect(12, -1, 4, list, -1);
575
      if (choice < 0) return(MENUPREV);
575
      if (choice < 0) return(MENUPREV);
576
      if (choice == 1) return(MENUQUIT);
576
      if (choice == 1) return(MENUQUIT);
577
      video_clear(0x0700, 0, 0);
577
      video_clear(0x0700, 0, 0);
578
      video_movecursor(0, 0);
578
      video_movecursor(0, 0);
579
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
579
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
580
      system(buff);
580
      system(buff);
581
      continue;
581
      continue;
582
    }
582
    }
583
    /* check total disk space */
583
    /* check total disk space */
584
    ds = disksize(selecteddrive);
584
    ds = disksize(selecteddrive);
585
    if (ds < SVARDOS_DISK_REQ) {
585
    if (ds < SVARDOS_DISK_REQ) {
586
      int y = 9;
586
      int y = 9;
587
      newscreen(2);
587
      newscreen(2);
588
      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." */
588
      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." */
589
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
589
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
590
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
590
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
591
      input_getkey();
591
      input_getkey();
592
      return(MENUQUIT);
592
      return(MENUQUIT);
593
    }
593
    }
594
    /* is the disk empty? */
594
    /* is the disk empty? */
595
    newscreen(0);
595
    newscreen(0);
596
    if (diskempty(selecteddrive) != 0) {
596
    if (diskempty(selecteddrive) != 0) {
597
      const char *list[3];
597
      const char *list[3];
598
      int y = 6;
598
      int y = 6;
599
      snprintf(buff, sizeof(buff), svarlang_strid(0x0305), cselecteddrive); /* "ERROR: Drive %c: not empty" */
599
      snprintf(buff, sizeof(buff), svarlang_strid(0x0305), cselecteddrive); /* "ERROR: Drive %c: not empty" */
600
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
600
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
601
 
601
 
602
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
602
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
603
      list[0] = buff;
603
      list[0] = buff;
604
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
604
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
605
      list[2] = NULL;
605
      list[2] = NULL;
606
 
606
 
607
      choice = menuselect(++y, -1, 4, list, -1);
607
      choice = menuselect(++y, -1, 4, list, -1);
608
      if (choice < 0) return(MENUPREV);
608
      if (choice < 0) return(MENUPREV);
609
      if (choice == 1) return(MENUQUIT);
609
      if (choice == 1) return(MENUQUIT);
610
      video_clear(0x0700, 0, 0);
610
      video_clear(0x0700, 0, 0);
611
      video_movecursor(0, 0);
611
      video_movecursor(0, 0);
612
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
612
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
613
      system(buff);
613
      system(buff);
614
      continue;
614
      continue;
615
    } else {
615
    } else {
616
      /* final confirmation */
616
      /* final confirmation */
617
      const char *list[3];
617
      const char *list[3];
618
      list[0] = svarlang_strid(0x0001); /* Install SvarDOS */
618
      list[0] = svarlang_strid(0x0001); /* Install SvarDOS */
619
      list[1] = svarlang_strid(0x0002); /* Quit to DOS */
619
      list[1] = svarlang_strid(0x0002); /* Quit to DOS */
620
      list[2] = NULL;
620
      list[2] = NULL;
621
      snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
621
      snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
622
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
622
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
623
      choice = menuselect(10, -1, 4, list, -1);
623
      choice = menuselect(10, -1, 4, list, -1);
624
      if (choice < 0) return(MENUPREV);
624
      if (choice < 0) return(MENUPREV);
625
      if (choice == 1) return(MENUQUIT);
625
      if (choice == 1) return(MENUQUIT);
626
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
626
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
627
      system(buff);
627
      system(buff);
628
      sprintf(buff, "FDISK /MBR %d", driveid);
628
      sprintf(buff, "FDISK /MBR %d", driveid);
629
      system(buff);
629
      system(buff);
630
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
630
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
631
      mkdir(buff);
631
      mkdir(buff);
632
      return(cselecteddrive);
632
      return(cselecteddrive);
633
    }
633
    }
634
  }
634
  }
635
}
635
}
636
 
636
 
637
 
637
 
638
/* generates locales-related configurations and writes them to file (this
638
/* generates locales-related configurations and writes them to file (this
639
 * is used to compute autoexec.bat content) */
639
 * is used to compute autoexec.bat content) */
640
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
640
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
641
  if (locales == NULL) return;
641
  if (locales == NULL) return;
642
 
642
 
643
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
643
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
644
 
644
 
645
  if (locales->egafile > 0) {
645
  if (locales->egafile > 0) {
646
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
646
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
647
    if (locales->egafile == 1) {
647
    if (locales->egafile == 1) {
648
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
648
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
649
    } else {
649
    } else {
650
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
650
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
651
    }
651
    }
652
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
652
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
653
  }
653
  }
654
 
654
 
655
  if (locales->keybfile > 0) {
655
  if (locales->keybfile > 0) {
656
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
656
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
657
    if (locales->keybfile == 1) {
657
    if (locales->keybfile == 1) {
658
      fprintf(fd, "KEYBOARD.SYS");
658
      fprintf(fd, "KEYBOARD.SYS");
659
    } else {
659
    } else {
660
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
660
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
661
    }
661
    }
662
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
662
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
663
    fprintf(fd, "\r\n");
663
    fprintf(fd, "\r\n");
664
  }
664
  }
665
}
665
}
666
 
666
 
667
 
667
 
668
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
668
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
669
  char buff[128];
669
  char buff[128];
670
  FILE *fd;
670
  FILE *fd;
671
  /*** CONFIG.SYS ***/
671
  /*** CONFIG.SYS ***/
672
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
672
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
673
  fd = fopen(buff, "wb");
673
  fd = fopen(buff, "wb");
674
  if (fd == NULL) return;
674
  if (fd == NULL) return;
675
  fprintf(fd, "DOS=UMB,HIGH\r\n"
675
  fprintf(fd, "DOS=UMB,HIGH\r\n"
676
              "LASTDRIVE=Z\r\n"
676
              "LASTDRIVE=Z\r\n"
677
              "FILES=50\r\n");
677
              "FILES=50\r\n");
678
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
678
  fprintf(fd, "DEVICE=C:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n");
679
  fprintf(fd, "SHELL=C:\\COMMAND.COM /E:512 /P\r\n");
679
  fprintf(fd, "SHELL=C:\\COMMAND.COM /E:512 /P\r\n");
680
  fprintf(fd, "REM COUNTRY=001,%u,C:\\SVARDOS\\CFG\\COUNTRY.SYS\r\n", locales->codepage);
680
  fprintf(fd, "REM COUNTRY=001,%u,C:\\SVARDOS\\CFG\\COUNTRY.SYS\r\n", locales->codepage);
681
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
681
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
682
  fclose(fd);
682
  fclose(fd);
683
  /*** AUTOEXEC.BAT ***/
683
  /*** AUTOEXEC.BAT ***/
684
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
684
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
685
  fd = fopen(buff, "wb");
685
  fd = fopen(buff, "wb");
686
  if (fd == NULL) return;
686
  if (fd == NULL) return;
687
  fprintf(fd, "@ECHO OFF\r\n");
687
  fprintf(fd, "@ECHO OFF\r\n");
688
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
688
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
689
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
689
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
690
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS;.\r\n");
690
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS;.\r\n");
691
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
691
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
692
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
692
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
693
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
693
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
694
  fprintf(fd, "PROMPT $P$G\r\n");
694
  fprintf(fd, "PROMPT $P$G\r\n");
695
  fprintf(fd, "FDAPM APMDOS\r\n");
695
  fprintf(fd, "FDAPM APMDOS\r\n");
696
  fprintf(fd, "\r\n");
696
  fprintf(fd, "\r\n");
697
  genlocalesconf(fd, locales);
697
  genlocalesconf(fd, locales);
698
  fprintf(fd, "\r\n");
698
  fprintf(fd, "\r\n");
699
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
699
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
700
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
700
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
701
  fprintf(fd, "\r\n");
701
  fprintf(fd, "\r\n");
702
  fprintf(fd, "ECHO.\r\n");
702
  fprintf(fd, "ECHO.\r\n");
703
  fprintf(fd, "ECHO %s\r\n", svarlang_strid(0x0600)); /* "Welcome to SvarDOS!" */
703
  fprintf(fd, "ECHO %s\r\n", svarlang_strid(0x0600)); /* "Welcome to SvarDOS!" */
704
  fclose(fd);
704
  fclose(fd);
705
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
705
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
706
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
706
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
707
  mkdir(buff);
707
  mkdir(buff);
708
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
708
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
709
  mkdir(buff);
709
  mkdir(buff);
710
  /*** PKG.CFG ***/
710
  /*** PKG.CFG ***/
711
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
711
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
712
  fd = fopen(buff, "wb");
712
  fd = fopen(buff, "wb");
713
  if (fd == NULL) return;
713
  if (fd == NULL) return;
714
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
714
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
715
              "\r\n"
715
              "\r\n"
716
              "# Programs\r\n"
716
              "# Programs\r\n"
717
              "DIR PROGS C:\\\r\n"
717
              "DIR PROGS C:\\\r\n"
718
              "\r\n"
718
              "\r\n"
719
              "# Games \r\n"
719
              "# Games \r\n"
720
              "DIR GAMES C:\\\r\n"
720
              "DIR GAMES C:\\\r\n"
721
              "\r\n"
721
              "\r\n"
722
              "# Drivers\r\n"
722
              "# Drivers\r\n"
723
              "DIR DRIVERS C:\\DRIVERS\r\n"
723
              "DIR DRIVERS C:\\DRIVERS\r\n"
724
              "\r\n"
724
              "\r\n"
725
              "# Development tools\r\n"
725
              "# Development tools\r\n"
726
              "DIR DEVEL C:\\DEVEL\r\n");
726
              "DIR DEVEL C:\\DEVEL\r\n");
727
  fclose(fd);
727
  fclose(fd);
728
  /*** COUNTRY.SYS ***/
728
  /*** COUNTRY.SYS ***/
729
  /*** PICOTCP ***/
729
  /*** PICOTCP ***/
730
  /*** WATTCP ***/
730
  /*** WATTCP ***/
731
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
731
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
732
  fd = fopen(buff, "wb");
732
  fd = fopen(buff, "wb");
733
  if (fd == NULL) return;
733
  if (fd == NULL) return;
734
  fprintf(fd, "my_ip = dhcp\r\n"
734
  fprintf(fd, "my_ip = dhcp\r\n"
735
              "#my_ip = 192.168.0.7\r\n"
735
              "#my_ip = 192.168.0.7\r\n"
736
              "#netmask = 255.255.255.0\r\n"
736
              "#netmask = 255.255.255.0\r\n"
737
              "#nameserver = 192.168.0.1\r\n"
737
              "#nameserver = 192.168.0.1\r\n"
738
              "#nameserver = 192.168.0.2\r\n"
738
              "#nameserver = 192.168.0.2\r\n"
739
              "#gateway = 192.168.0.1\r\n");
739
              "#gateway = 192.168.0.1\r\n");
740
  fclose(fd);
740
  fclose(fd);
741
}
741
}
742
 
742
 
743
 
743
 
744
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales, const char *buildstring) {
744
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales, const char *buildstring) {
745
  char pkglist[512];
745
  char pkglist[512];
746
  int i, pkglistlen;
746
  int i, pkglistlen;
747
  size_t pkglistflen;
747
  size_t pkglistflen;
748
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
748
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
749
  FILE *fd = NULL;
749
  FILE *fd = NULL;
750
  char *pkgptr;
750
  char *pkgptr;
751
  newscreen(3);
751
  newscreen(3);
752
  /* load pkg list */
752
  /* load pkg list */
753
  fd = fopen("install.lst", "rb");
753
  fd = fopen("install.lst", "rb");
754
  if (fd == NULL) {
754
  if (fd == NULL) {
755
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
755
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
756
    input_getkey();
756
    input_getkey();
757
    return(-1);
757
    return(-1);
758
  }
758
  }
759
  pkglistflen = fread(pkglist, 1, sizeof(pkglist) - 2, fd);
759
  pkglistflen = fread(pkglist, 1, sizeof(pkglist) - 2, fd);
760
  fclose(fd);
760
  fclose(fd);
761
  if (pkglistflen == sizeof(pkglist) - 2) {
761
  if (pkglistflen == sizeof(pkglist) - 2) {
762
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
762
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
763
    input_getkey();
763
    input_getkey();
764
    return(-1);
764
    return(-1);
765
  }
765
  }
766
  /* mark the end of list */
766
  /* mark the end of list */
767
  pkglist[pkglistflen] = 0;
767
  pkglist[pkglistflen] = 0;
768
  pkglist[pkglistflen + 1] = 0xff;
768
  pkglist[pkglistflen + 1] = 0xff;
769
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
769
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
770
  pkglistlen = 0;
770
  pkglistlen = 0;
771
  for (i = 0; i < pkglistflen; i++) {
771
  for (i = 0; i < pkglistflen; i++) {
772
    switch (pkglist[i]) {
772
    switch (pkglist[i]) {
773
      case '\n':
773
      case '\n':
774
        pkglistlen++;
774
        pkglistlen++;
775
        /* FALLTHRU */
775
        /* FALLTHRU */
776
      case '\r':
776
      case '\r':
777
        pkglist[i] = 0;
777
        pkglist[i] = 0;
778
        break;
778
        break;
779
    }
779
    }
780
  }
780
  }
781
  /* copy pkg.exe to the new drive, along with all packages */
781
  /* copy pkg.exe to the new drive, along with all packages */
782
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
782
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
783
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
783
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
784
  fcopy(buff, buff + 64, buff, sizeof(buff));
784
  fcopy(buff, buff + 64, buff, sizeof(buff));
785
 
785
 
786
  /* open the post-install autoexec.bat and prepare initial instructions */
786
  /* open the post-install autoexec.bat and prepare initial instructions */
787
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
787
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
788
  fd = fopen(buff, "wb");
788
  fd = fopen(buff, "wb");
789
  if (fd == NULL) return(-1);
789
  if (fd == NULL) return(-1);
790
  fprintf(fd, "@ECHO OFF\r\nECHO INSTALLING SVARDOS BUILD %s\r\n", buildstring);
790
  fprintf(fd, "@ECHO OFF\r\nECHO INSTALLING SVARDOS BUILD %s\r\n", buildstring);
791
 
791
 
792
  /* move COMMAND.COM so it does not clashes with the installation of the SVARCOM package */
792
  /* move COMMAND.COM so it does not clashes with the installation of the SVARCOM package */
793
  fprintf(fd, "COPY \\COMMAND.COM \\CMD.COM\r\n");
793
  fprintf(fd, "COPY \\COMMAND.COM \\CMD.COM\r\n");
794
  fprintf(fd, "SET COMSPEC=%c:\\CMD.COM\r\n", targetdrv);
794
  fprintf(fd, "SET COMSPEC=%c:\\CMD.COM\r\n", targetdrv);
795
  fprintf(fd, "DEL \\COMMAND.COM\r\n");
795
  fprintf(fd, "DEL \\COMMAND.COM\r\n");
796
 
796
 
797
  /* copy packages */
797
  /* copy packages */
798
  for (i = 0;; i++) {
798
  for (i = 0;; i++) {
799
    RETRY_ENTIRE_LIST:
799
    RETRY_ENTIRE_LIST:
800
 
800
 
801
    /* move forward to nearest entry or end of list */
801
    /* move forward to nearest entry or end of list */
802
    for (pkgptr = pkglist; *pkgptr == 0; pkgptr++);
802
    for (pkgptr = pkglist; *pkgptr == 0; pkgptr++);
803
    if (*pkgptr == 0xff) break; /* end of list: means all packages have been processed */
803
    if (*pkgptr == 0xff) break; /* end of list: means all packages have been processed */
804
 
804
 
805
    /* is this package present on the floppy disk? */
805
    /* is this package present on the floppy disk? */
806
    TRY_NEXTPKG:
806
    TRY_NEXTPKG:
807
    sprintf(buff, "%s.svp", pkgptr);
807
    sprintf(buff, "%s.svp", pkgptr);
808
    if (fileexists(buff) != 0) {
808
    if (fileexists(buff) != 0) {
809
      while (*pkgptr != 0) pkgptr++;
809
      while (*pkgptr != 0) pkgptr++;
810
      while (*pkgptr == 0) pkgptr++;
810
      while (*pkgptr == 0) pkgptr++;
811
      /* end of list? ask for next floppy, there's nothing interesting left on this one */
811
      /* end of list? ask for next floppy, there's nothing interesting left on this one */
812
      if (*pkgptr == 0xff) {
812
      if (*pkgptr == 0xff) {
813
        putstringnls(12, 1, COLOR_BODY[mono], 4, 1); /* "INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY" */
813
        putstringnls(12, 1, COLOR_BODY[mono], 4, 1); /* "INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY" */
814
        input_getkey();
814
        input_getkey();
815
        video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
815
        video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
816
        goto RETRY_ENTIRE_LIST;
816
        goto RETRY_ENTIRE_LIST;
817
      }
817
      }
818
      goto TRY_NEXTPKG;
818
      goto TRY_NEXTPKG;
819
    }
819
    }
820
 
820
 
821
    /* install the package */
821
    /* install the package */
822
    snprintf(buff, sizeof(buff), svarlang_strid(0x0400), i+1, pkglistlen, pkgptr); /* "Installing package %d/%d: %s" */
822
    snprintf(buff, sizeof(buff), svarlang_strid(0x0400), i+1, pkglistlen, pkgptr); /* "Installing package %d/%d: %s" */
823
    strcat(buff, "       ");
823
    strcat(buff, "       ");
824
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
824
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
825
 
825
 
826
    /* proceed with package copy */
826
    /* proceed with package copy */
827
    sprintf(buff, "%c:\\temp\\%s.svp", targetdrv, pkgptr);
827
    sprintf(buff, "%c:\\temp\\%s.svp", targetdrv, pkgptr);
828
    if (fcopy(buff, buff + 7, buff, sizeof(buff)) != 0) {
828
    if (fcopy(buff, buff + 7, buff, sizeof(buff)) != 0) {
829
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
829
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
830
      input_getkey();
830
      input_getkey();
831
      fclose(fd);
831
      fclose(fd);
832
      return(-1);
832
      return(-1);
833
    }
833
    }
834
    /* write install instruction to post-install script */
834
    /* write install instruction to post-install script */
835
    fprintf(fd, "pkg install %s.svp\r\ndel %s.svp\r\n", pkgptr, pkgptr);
835
    fprintf(fd, "pkg install %s.svp\r\ndel %s.svp\r\n", pkgptr, pkgptr);
836
    /* jump to next entry or end of list and zero out the pkg name in the process */
836
    /* jump to next entry or end of list and zero out the pkg name in the process */
837
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) {
837
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) {
838
      *pkgptr = 0;
838
      *pkgptr = 0;
839
      pkgptr++;
839
      pkgptr++;
840
    }
840
    }
841
  }
841
  }
842
  /* set up locales so the "installation over" message is nicely displayed */
842
  /* set up locales so the "installation over" message is nicely displayed */
843
  genlocalesconf(fd, locales);
843
  genlocalesconf(fd, locales);
844
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
844
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
845
  fprintf(fd, "DEL pkg.exe\r\n"
845
  fprintf(fd, "DEL pkg.exe\r\n"
846
              "COPY CONFIG.SYS C:\\\r\n"
846
              "COPY CONFIG.SYS C:\\\r\n"
847
              "DEL CONFIG.SYS\r\n"
847
              "DEL CONFIG.SYS\r\n"
848
              "DEL C:\\AUTOEXEC.BAT\r\n"
848
              "DEL C:\\AUTOEXEC.BAT\r\n"
849
              "COPY AUTOEXEC.BAT C:\\\r\n"
849
              "COPY AUTOEXEC.BAT C:\\\r\n"
850
              "DEL AUTOEXEC.BAT\r\n"
850
              "DEL AUTOEXEC.BAT\r\n"
851
              "SET COMSPEC=C:\\COMMAND.COM\r\n"
851
              "SET COMSPEC=C:\\COMMAND.COM\r\n"
852
              "DEL \\CMD.COM\r\n");
852
              "DEL \\CMD.COM\r\n");
853
  /* print out the "installation over" message */
853
  /* print out the "installation over" message */
854
  fprintf(fd, "ECHO.\r\n"
854
  fprintf(fd, "ECHO.\r\n"
855
              "ECHO ");
855
              "ECHO ");
856
  fprintf(fd, svarlang_strid(0x0501), buildstring); /* "SvarDOS installation is over. Please restart your computer now" */
856
  fprintf(fd, svarlang_strid(0x0501), buildstring); /* "SvarDOS installation is over. Please restart your computer now" */
857
  fprintf(fd, "\r\n"
857
  fprintf(fd, "\r\n"
858
              "ECHO.\r\n");
858
              "ECHO.\r\n");
859
  fclose(fd);
859
  fclose(fd);
860
 
860
 
861
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
861
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
862
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
862
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
863
  fd = fopen(buff, "wb");
863
  fd = fopen(buff, "wb");
864
  if (fd == NULL) return(-1);
864
  if (fd == NULL) return(-1);
865
  fprintf(fd, "@ECHO OFF\r\n"
865
  fprintf(fd, "@ECHO OFF\r\n"
866
              "SET DOSDIR=C:\\SVARDOS\r\n"
866
              "SET DOSDIR=C:\\SVARDOS\r\n"
867
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
867
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
868
              "PATH %%DOSDIR%%\\BIN\r\n");
868
              "PATH %%DOSDIR%%\\BIN\r\n");
869
  fprintf(fd, "CD TEMP\r\n"
869
  fprintf(fd, "CD TEMP\r\n"
870
              "postinst.bat\r\n");
870
              "postinst.bat\r\n");
871
  fclose(fd);
871
  fclose(fd);
872
 
872
 
873
  return(0);
873
  return(0);
874
}
874
}
875
 
875
 
876
 
876
 
877
static void finalreboot(void) {
877
static void finalreboot(void) {
878
  int y = 9;
878
  int y = 9;
879
  newscreen(2);
879
  newscreen(2);
880
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0); /* "Your computer will reboot now.\nPlease remove the installation disk from your drive" */
880
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0); /* "Your computer will reboot now.\nPlease remove the installation disk from your drive" */
881
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
881
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5); /* "Press any key..." */
882
  input_getkey();
882
  input_getkey();
883
  reboot();
883
  reboot();
884
}
884
}
885
 
885
 
886
 
886
 
887
static void loadcp(const struct slocales *locales) {
887
static void loadcp(const struct slocales *locales) {
888
  char buff[64];
888
  char buff[64];
889
  if (locales->codepage == 437) return;
889
  if (locales->codepage == 437) return;
890
  video_movecursor(1, 0);
890
  video_movecursor(1, 0);
891
  if (locales->egafile == 1) {
891
  if (locales->egafile == 1) {
892
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
892
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
893
  } else {
893
  } else {
894
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
894
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
895
  }
895
  }
896
  system(buff);
896
  system(buff);
897
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
897
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
898
  system(buff);
898
  system(buff);
899
  /* below I re-init the video controller - apparently this is required if
899
  /* below I re-init the video controller - apparently this is required if
900
   * I want the new glyph symbols to be actually applied, at least some
900
   * I want the new glyph symbols to be actually applied, at least some
901
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
901
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
902
  {
902
  {
903
  union REGS r;
903
  union REGS r;
904
  r.h.ah = 0x0F; /* get current video mode */
904
  r.h.ah = 0x0F; /* get current video mode */
905
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
905
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
906
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
906
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
907
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
907
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
908
  int86(0x10, &r, &r);
908
  int86(0x10, &r, &r);
909
  }
909
  }
910
}
910
}
911
 
911
 
912
 
912
 
913
#ifdef DEADCODE
913
#ifdef DEADCODE
914
/* checks that drive drv contains SvarDOS packages
914
/* checks that drive drv contains SvarDOS packages
915
 * returns 0 if found, non-zero otherwise */
915
 * returns 0 if found, non-zero otherwise */
916
static int checkinstsrc(char drv) {
916
static int checkinstsrc(char drv) {
917
  char fname[16];
917
  char fname[16];
918
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.SVP", drv);
918
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.SVP", drv);
919
  return(fileexists(fname));
919
  return(fileexists(fname));
920
}
920
}
921
#endif
921
#endif
922
 
922
 
923
 
923
 
924
int main(int argc, char **argv) {
924
int main(int argc, char **argv) {
925
  struct slocales locales;
925
  struct slocales locales;
926
  int targetdrv;
926
  int targetdrv;
927
  int sourcedrv;
927
  int sourcedrv;
928
  int action;
928
  int action;
929
  const char *buildstring = "###";
929
  const char *buildstring = "###";
930
 
930
 
931
  /* setup the internal int 24h handler ("always fail") */
931
  /* setup the internal int 24h handler ("always fail") */
932
  int24hdl();
932
  int24hdl();
933
 
933
 
934
  if (argc != 1) buildstring = argv[1];
934
  if (argc != 1) buildstring = argv[1];
935
 
935
 
936
  sourcedrv = get_cur_drive() + 'A';
936
  sourcedrv = get_cur_drive() + 'A';
937
 
937
 
938
  /* init screen and detect mono status */
938
  /* init screen and detect mono status */
939
  mono = video_init();
939
  mono = video_init();
940
 
940
 
941
 SelectLang:
941
 SelectLang:
942
  action = selectlang(&locales); /* welcome to svardos, select your language */
942
  action = selectlang(&locales); /* welcome to svardos, select your language */
943
  if (action != MENUNEXT) goto Quit;
943
  if (action != MENUNEXT) goto Quit;
944
  loadcp(&locales);
944
  loadcp(&locales);
945
  svarlang_load("INSTALL", locales.lang, NULL); /* NLS support */
945
  svarlang_load("INSTALL", locales.lang, NULL); /* NLS support */
946
 
946
 
947
 SelectKeyb:
947
 SelectKeyb:
948
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
948
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
949
  if (action == MENUQUIT) goto Quit;
949
  if (action == MENUQUIT) goto Quit;
950
  if (action == MENUPREV) goto SelectLang;
950
  if (action == MENUPREV) goto SelectLang;
951
 
951
 
952
 WelcomeScreen:
952
 WelcomeScreen:
953
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
953
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
954
  if (action == MENUQUIT) goto Quit;
954
  if (action == MENUQUIT) goto Quit;
955
  if (action == MENUPREV) {
955
  if (action == MENUPREV) {
956
    if (locales.keyblen > 1) goto SelectKeyb; /* if there is a choice of more than 1 layout, ask for it */
956
    if (locales.keyblen > 1) goto SelectKeyb; /* if there is a choice of more than 1 layout, ask for it */
957
    goto SelectLang;
957
    goto SelectLang;
958
  }
958
  }
959
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
959
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
960
  if (targetdrv == MENUQUIT) goto Quit;
960
  if (targetdrv == MENUQUIT) goto Quit;
961
  if (targetdrv == MENUPREV) goto WelcomeScreen;
961
  if (targetdrv == MENUPREV) goto WelcomeScreen;
962
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
962
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
963
  if (installpackages(targetdrv, sourcedrv, &locales, buildstring) != 0) goto Quit;    /* install packages */
963
  if (installpackages(targetdrv, sourcedrv, &locales, buildstring) != 0) goto Quit;    /* install packages */
964
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
964
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
965
  /*netcfg();*/ /* basic networking config */
965
  /*netcfg();*/ /* basic networking config */
966
  finalreboot(); /* remove the CD and reboot */
966
  finalreboot(); /* remove the CD and reboot */
967
 
967
 
968
 Quit:
968
 Quit:
969
  video_clear(0x0700, 0, 0);
969
  video_clear(0x0700, 0, 0);
970
  video_movecursor(0, 0);
970
  video_movecursor(0, 0);
971
  return(0);
971
  return(0);
972
}
972
}
973
 
973