Subversion Repositories SvarDOS

Rev

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

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