Subversion Repositories SvarDOS

Rev

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

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