Subversion Repositories SvarDOS

Rev

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

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