Subversion Repositories SvarDOS

Rev

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

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