Subversion Repositories SvarDOS

Rev

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

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