Subversion Repositories SvarDOS

Rev

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

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