Subversion Repositories SvarDOS

Rev

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

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