Subversion Repositories SvarDOS

Rev

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

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