Subversion Repositories SvarDOS

Rev

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

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