Subversion Repositories SvarDOS

Rev

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

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