Subversion Repositories SvarDOS

Rev

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

Rev 303 Rev 310
1
/*
1
/*
2
 * SVARDOS INSTALL PROGRAM
2
 * SVARDOS INSTALL PROGRAM
3
 * Copyright (C) 2021 Mateusz Viste
3
 * Copyright (C) 2021 Mateusz Viste
4
 *
4
 *
5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
6
 *
6
 *
7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
8
 *
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
15
 *
16
 * The above copyright notice and this permission notice shall be included in
16
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
17
 * all copies or substantial portions of the Software.
18
 *
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
25
 * DEALINGS IN THE SOFTWARE.
26
 *
26
 *
27
 * http://svardos.osdn.io
27
 * http://svardos.osdn.io
28
 */
28
 */
29
 
29
 
30
#include <dos.h>
30
#include <dos.h>
31
#include <direct.h>  /* mkdir() */
31
#include <direct.h>  /* mkdir() */
32
#include <stdio.h>   /* printf() and friends */
32
#include <stdio.h>   /* printf() and friends */
33
#include <stdlib.h>  /* system() */
33
#include <stdlib.h>  /* system() */
34
#include <string.h>  /* memcpy() */
34
#include <string.h>  /* memcpy() */
35
#include <unistd.h>
35
#include <unistd.h>
36
 
36
 
37
#include "kitten\kitten.h"
37
#include "kitten\kitten.h"
38
 
38
 
39
#include "cdrom.h"
-
 
40
#include "input.h"
39
#include "input.h"
41
#include "video.h"
40
#include "video.h"
42
 
41
 
43
/* keyboard layouts and locales */
42
/* keyboard layouts and locales */
44
#include "keylay.h"
43
#include "keylay.h"
45
#include "keyoff.h"
44
#include "keyoff.h"
46
 
45
 
47
/* color scheme (color, mono) */
46
/* color scheme (color, mono) */
48
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
47
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
49
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
48
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
50
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
49
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
51
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
50
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
52
 
51
 
53
/* mono flag */
52
/* mono flag */
54
static int mono = 0;
53
static int mono = 0;
55
 
54
 
56
/* how much disk space does SvarDOS require (in MiB) */
55
/* how much disk space does SvarDOS require (in MiB) */
57
#define SVARDOS_DISK_REQ 8
56
#define SVARDOS_DISK_REQ 8
58
 
57
 
59
/* menu screens can output only one of these: */
58
/* menu screens can output only one of these: */
60
#define MENUNEXT 0
59
#define MENUNEXT 0
61
#define MENUPREV -1
60
#define MENUPREV -1
62
#define MENUQUIT -2
61
#define MENUQUIT -2
63
 
62
 
64
/* a convenience 'function' used for debugging */
63
/* a convenience 'function' used for debugging */
65
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
64
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
66
 
65
 
67
struct slocales {
66
struct slocales {
68
  char lang[4];
67
  char lang[4];
69
  char *keybcode;
68
  char *keybcode;
70
  unsigned int codepage;
69
  unsigned int codepage;
71
  int egafile;
70
  int egafile;
72
  int keybfile;
71
  int keybfile;
73
  int keyboff;
72
  int keyboff;
74
  int keyblen;
73
  int keyblen;
75
  unsigned int keybid;
74
  unsigned int keybid;
76
};
75
};
77
 
76
 
78
 
77
 
79
/* reboot the computer */
78
/* reboot the computer */
80
static void reboot(void) {
79
static void reboot(void) {
81
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
80
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
82
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
81
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
83
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
82
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
84
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
83
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
85
}
84
}
86
 
85
 
87
 
86
 
88
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
87
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
89
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
88
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
90
  int linew, lincount;
89
  int linew, lincount;
91
  linew = 80;
90
  linew = 80;
92
  if (x >= 0) linew -= (x << 1);
91
  if (x >= 0) linew -= (x << 1);
93
 
92
 
94
  for (lincount = 1; y+lincount < 25; lincount++) {
93
  for (lincount = 1; y+lincount < 25; lincount++) {
95
    int i, len = linew;
94
    int i, len = linew;
96
    for (i = 0; i <= linew; i++) {
95
    for (i = 0; i <= linew; i++) {
97
      if (s[i] == ' ') len = i;
96
      if (s[i] == ' ') len = i;
98
      if (s[i] == '\n') {
97
      if (s[i] == '\n') {
99
        len = i;
98
        len = i;
100
        break;
99
        break;
101
      }
100
      }
102
      if (s[i] == 0) {
101
      if (s[i] == 0) {
103
        len = i;
102
        len = i;
104
        break;
103
        break;
105
      }
104
      }
106
    }
105
    }
107
    video_putstring(y++, x, attr, s, len);
106
    video_putstring(y++, x, attr, s, len);
108
    s += len;
107
    s += len;
109
    if (*s == 0) break;
108
    if (*s == 0) break;
110
    s += 1; /* skip the whitespace char */
109
    s += 1; /* skip the whitespace char */
111
  }
110
  }
112
  return(lincount);
111
  return(lincount);
113
}
112
}
114
 
113
 
115
 
114
 
116
/* an NLS wrapper around video_putstring(), also performs line wrapping when
115
/* an NLS wrapper around video_putstring(), also performs line wrapping when
117
 * needed. returns the amount of lines that were output */
116
 * needed. returns the amount of lines that were output */
118
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
117
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
119
  s = kittengets(nlsmaj, nlsmin, s);
118
  s = kittengets(nlsmaj, nlsmin, s);
120
  return(putstringwrap(y, x, attr, s));
119
  return(putstringwrap(y, x, attr, s));
121
}
120
}
122
 
121
 
123
 
122
 
124
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
123
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
125
 * exists already! returns 0 on success. */
124
 * exists already! returns 0 on success. */
126
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
125
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
127
  FILE *fd1, *fd2;
126
  FILE *fd1, *fd2;
128
  size_t sz;
127
  size_t sz;
129
  int res = -1; /* assume failure */
128
  int res = -1; /* assume failure */
130
 
129
 
131
  /* open files */
130
  /* open files */
132
  fd1 = fopen(f1, "rb");
131
  fd1 = fopen(f1, "rb");
133
  fd2 = fopen(f2, "wb");
132
  fd2 = fopen(f2, "wb");
134
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
133
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
135
 
134
 
136
  /* copy data */
135
  /* copy data */
137
  for (;;) {
136
  for (;;) {
138
    sz = fread(buff, 1, buffsz, fd1);
137
    sz = fread(buff, 1, buffsz, fd1);
139
    if (sz == 0) {
138
    if (sz == 0) {
140
      if (feof(fd1) != 0) break;
139
      if (feof(fd1) != 0) break;
141
      goto QUIT;
140
      goto QUIT;
142
    }
141
    }
143
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
142
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
144
  }
143
  }
145
 
144
 
146
  res = 0; /* success */
145
  res = 0; /* success */
147
 
146
 
148
  QUIT:
147
  QUIT:
149
  if (fd1 != NULL) fclose(fd1);
148
  if (fd1 != NULL) fclose(fd1);
150
  if (fd2 != NULL) fclose(fd2);
149
  if (fd2 != NULL) fclose(fd2);
151
  return(res);
150
  return(res);
152
}
151
}
153
 
152
 
154
 
153
 
155
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
154
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
156
  int i, offset = 0, res = 0, count, width = 0;
155
  int i, offset = 0, res = 0, count, width = 0;
157
  /* count how many positions there is, and check their width */
156
  /* count how many positions there is, and check their width */
158
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
157
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
159
    int len = strlen(list[count]);
158
    int len = strlen(list[count]);
160
    if (len > width) width = len;
159
    if (len > width) width = len;
161
  }
160
  }
162
 
161
 
163
  /* if xpos negative, means 'center out' */
162
  /* if xpos negative, means 'center out' */
164
  if (xpos < 0) xpos = 39 - (width >> 1);
163
  if (xpos < 0) xpos = 39 - (width >> 1);
165
 
164
 
166
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
165
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
167
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
166
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
168
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
167
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
169
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
168
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
170
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
169
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
171
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
170
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
172
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
171
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
173
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
172
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
174
 
173
 
175
  for (;;) {
174
  for (;;) {
176
    int key;
175
    int key;
177
    /* list of selectable items */
176
    /* list of selectable items */
178
    for (i = 0; i < height - 2; i++) {
177
    for (i = 0; i < height - 2; i++) {
179
      if (i + offset == res) {
178
      if (i + offset == res) {
180
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
179
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
181
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
180
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
182
        video_movecursor(ypos + 1 + i, xpos);
181
        video_movecursor(ypos + 1 + i, xpos);
183
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
182
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
184
      } else if (i + offset < count) {
183
      } else if (i + offset < count) {
185
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
184
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
186
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
185
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
187
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
186
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
188
      } else {
187
      } else {
189
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
188
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
190
      }
189
      }
191
    }
190
    }
192
    key = input_getkey();
191
    key = input_getkey();
193
    if (key == 0x0D) { /* ENTER */
192
    if (key == 0x0D) { /* ENTER */
194
      return(res);
193
      return(res);
195
    } else if (key == 0x148) { /* up */
194
    } else if (key == 0x148) { /* up */
196
      if (res > 0) {
195
      if (res > 0) {
197
        res--;
196
        res--;
198
        if (res < offset) offset = res;
197
        if (res < offset) offset = res;
199
      }
198
      }
200
    } else if (key == 0x150) { /* down */
199
    } else if (key == 0x150) { /* down */
201
      if (res+1 < count) {
200
      if (res+1 < count) {
202
        res++;
201
        res++;
203
        if (res > offset + height - 3) offset = res - (height - 3);
202
        if (res > offset + height - 3) offset = res - (height - 3);
204
      }
203
      }
205
    } else if (key == 0x147) { /* home */
204
    } else if (key == 0x147) { /* home */
206
      res = 0;
205
      res = 0;
207
      offset = 0;
206
      offset = 0;
208
    } else if (key == 0x14F) { /* end */
207
    } else if (key == 0x14F) { /* end */
209
      res = count - 1;
208
      res = count - 1;
210
      if (res > offset + height - 3) offset = res - (height - 3);
209
      if (res > offset + height - 3) offset = res - (height - 3);
211
    } else if (key == 0x1B) {  /* ESC */
210
    } else if (key == 0x1B) {  /* ESC */
212
      return(-1);
211
      return(-1);
213
    }/* else {
212
    }/* else {
214
      char buf[8];
213
      char buf[8];
215
      snprintf(buf, sizeof(buf), "0x%02X ", key);
214
      snprintf(buf, sizeof(buf), "0x%02X ", key);
216
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
215
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
217
    }*/
216
    }*/
218
  }
217
  }
219
}
218
}
220
 
219
 
221
static void newscreen(int statusbartype) {
220
static void newscreen(int statusbartype) {
222
  char *msg;
221
  char *msg;
223
  msg = kittengets(0, 0, "SVARDOS INSTALLATION");
222
  msg = kittengets(0, 0, "SVARDOS INSTALLATION");
224
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
223
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
225
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
224
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
226
  video_clear(COLOR_BODY[mono], 80, -80);
225
  video_clear(COLOR_BODY[mono], 80, -80);
227
  switch (statusbartype) {
226
  switch (statusbartype) {
228
    case 1:
227
    case 1:
229
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
228
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
230
      break;
229
      break;
231
    case 2:
230
    case 2:
232
      msg = kittengets(0, 5, "Press any key...");
231
      msg = kittengets(0, 5, "Press any key...");
233
      break;
232
      break;
234
    case 3:
233
    case 3:
235
      msg = "";
234
      msg = "";
236
      break;
235
      break;
237
    default:
236
    default:
238
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
237
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
239
      break;
238
      break;
240
  }
239
  }
241
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
240
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
242
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
241
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
243
  video_movecursor(25,0);
242
  video_movecursor(25,0);
244
}
243
}
245
 
244
 
246
/* fills a slocales struct accordingly to the value of its keyboff member */
245
/* fills a slocales struct accordingly to the value of its keyboff member */
247
static void kblay2slocal(struct slocales *locales) {
246
static void kblay2slocal(struct slocales *locales) {
248
  char *m;
247
  char *m;
249
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
248
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
250
  m++;
249
  m++;
251
  /* skip keyb code and copy it to locales.keybcode */
250
  /* skip keyb code and copy it to locales.keybcode */
252
  locales->keybcode = m;
251
  locales->keybcode = m;
253
  for (; *m != 0; m++);
252
  for (; *m != 0; m++);
254
  /* */
253
  /* */
255
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
254
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
256
  locales->egafile = m[3];
255
  locales->egafile = m[3];
257
  locales->keybfile = m[4];
256
  locales->keybfile = m[4];
258
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
257
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
259
}
258
}
260
 
259
 
261
static int selectlang(struct slocales *locales) {
260
static int selectlang(struct slocales *locales) {
262
  int choice, x;
261
  int choice, x;
263
  char *msg;
262
  char *msg;
264
  char *langlist[] = {
263
  char *langlist[] = {
265
    "English",
264
    "English",
266
    "French",
265
    "French",
267
    "German",
266
    "German",
268
    "Italian",
267
    "Italian",
269
    "Polish",
268
    "Polish",
270
    "Russian",
269
    "Russian",
271
    "Slovene",
270
    "Slovene",
272
    "Swedish",
271
    "Swedish",
273
    "Turkish",
272
    "Turkish",
274
    NULL
273
    NULL
275
  };
274
  };
276
 
275
 
277
  newscreen(1);
276
  newscreen(1);
278
  msg = kittengets(1, 0, "Welcome to SvarDOS");
277
  msg = kittengets(1, 0, "Welcome to SvarDOS");
279
  x = 40 - (strlen(msg) >> 1);
278
  x = 40 - (strlen(msg) >> 1);
280
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
279
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
281
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
280
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
282
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
281
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
283
  choice = menuselect(11, -1, 11, langlist, -1);
282
  choice = menuselect(11, -1, 11, langlist, -1);
284
  if (choice < 0) return(MENUPREV);
283
  if (choice < 0) return(MENUPREV);
285
  /* populate locales with default values */
284
  /* populate locales with default values */
286
  memset(locales, 0, sizeof(struct slocales));
285
  memset(locales, 0, sizeof(struct slocales));
287
  switch (choice) {
286
  switch (choice) {
288
    case 1:
287
    case 1:
289
      strcpy(locales->lang, "FR");
288
      strcpy(locales->lang, "FR");
290
      locales->keyboff = OFFLOC_FR;
289
      locales->keyboff = OFFLOC_FR;
291
      locales->keyblen = OFFLEN_FR;
290
      locales->keyblen = OFFLEN_FR;
292
      break;
291
      break;
293
    case 2:
292
    case 2:
294
      strcpy(locales->lang, "DE");
293
      strcpy(locales->lang, "DE");
295
      locales->keyboff = OFFLOC_DE;
294
      locales->keyboff = OFFLOC_DE;
296
      locales->keyblen = OFFLEN_DE;
295
      locales->keyblen = OFFLEN_DE;
297
      break;
296
      break;
298
    case 3:
297
    case 3:
299
      strcpy(locales->lang, "IT");
298
      strcpy(locales->lang, "IT");
300
      locales->keyboff = OFFLOC_IT;
299
      locales->keyboff = OFFLOC_IT;
301
      locales->keyblen = OFFLEN_IT;
300
      locales->keyblen = OFFLEN_IT;
302
      break;
301
      break;
303
    case 4:
302
    case 4:
304
      strcpy(locales->lang, "PL");
303
      strcpy(locales->lang, "PL");
305
      locales->keyboff = OFFLOC_PL;
304
      locales->keyboff = OFFLOC_PL;
306
      locales->keyblen = OFFLEN_PL;
305
      locales->keyblen = OFFLEN_PL;
307
      break;
306
      break;
308
    case 5:
307
    case 5:
309
      strcpy(locales->lang, "RU");
308
      strcpy(locales->lang, "RU");
310
      locales->keyboff = OFFLOC_RU;
309
      locales->keyboff = OFFLOC_RU;
311
      locales->keyblen = OFFLEN_RU;
310
      locales->keyblen = OFFLEN_RU;
312
      break;
311
      break;
313
    case 6:
312
    case 6:
314
      strcpy(locales->lang, "SI");
313
      strcpy(locales->lang, "SI");
315
      locales->keyboff = OFFLOC_SI;
314
      locales->keyboff = OFFLOC_SI;
316
      locales->keyblen = OFFLEN_SI;
315
      locales->keyblen = OFFLEN_SI;
317
      break;
316
      break;
318
    case 7:
317
    case 7:
319
      strcpy(locales->lang, "SV");
318
      strcpy(locales->lang, "SV");
320
      locales->keyboff = OFFLOC_SV;
319
      locales->keyboff = OFFLOC_SV;
321
      locales->keyblen = OFFLEN_SV;
320
      locales->keyblen = OFFLEN_SV;
322
      break;
321
      break;
323
    case 8:
322
    case 8:
324
      strcpy(locales->lang, "TR");
323
      strcpy(locales->lang, "TR");
325
      locales->keyboff = OFFLOC_TR;
324
      locales->keyboff = OFFLOC_TR;
326
      locales->keyblen = OFFLEN_TR;
325
      locales->keyblen = OFFLEN_TR;
327
      break;
326
      break;
328
    default:
327
    default:
329
      strcpy(locales->lang, "EN");
328
      strcpy(locales->lang, "EN");
330
      locales->keyboff = 0;
329
      locales->keyboff = 0;
331
      locales->keyblen = OFFCOUNT;
330
      locales->keyblen = OFFCOUNT;
332
      break;
331
      break;
333
  }
332
  }
334
  /* populate the slocales struct accordingly to the keyboff member */
333
  /* populate the slocales struct accordingly to the keyboff member */
335
  kblay2slocal(locales);
334
  kblay2slocal(locales);
336
  /* */
335
  /* */
337
  return(MENUNEXT);
336
  return(MENUNEXT);
338
}
337
}
339
 
338
 
340
 
339
 
341
static int selectkeyb(struct slocales *locales) {
340
static int selectkeyb(struct slocales *locales) {
342
  int menuheight, choice;
341
  int menuheight, choice;
343
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
342
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
344
  newscreen(0);
343
  newscreen(0);
345
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
344
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
346
  menuheight = locales->keyblen + 2;
345
  menuheight = locales->keyblen + 2;
347
  if (menuheight > 13) menuheight = 13;
346
  if (menuheight > 13) menuheight = 13;
348
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
347
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
349
  if (choice < 0) return(MENUPREV);
348
  if (choice < 0) return(MENUPREV);
350
  /* (re)load the keyboard layout & codepage setup */
349
  /* (re)load the keyboard layout & codepage setup */
351
  locales->keyboff += choice;
350
  locales->keyboff += choice;
352
  kblay2slocal(locales);
351
  kblay2slocal(locales);
353
  return(MENUNEXT);
352
  return(MENUNEXT);
354
}
353
}
355
 
354
 
356
 
355
 
357
/* returns 0 if installation must proceed, non-zero otherwise */
356
/* returns 0 if installation must proceed, non-zero otherwise */
358
static int welcomescreen(void) {
357
static int welcomescreen(void) {
359
  int c;
358
  int c;
360
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
359
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
361
  choice[0] = kittengets(0, 1, choice[0]);
360
  choice[0] = kittengets(0, 1, choice[0]);
362
  choice[1] = kittengets(0, 2, choice[1]);
361
  choice[1] = kittengets(0, 2, choice[1]);
363
  newscreen(0);
362
  newscreen(0);
364
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install SvarDOS: a free, MSDOS-compatible operating system based on the FreeDOS kernel. SvarDOS targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once SvarDOS is installed.");
363
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install SvarDOS: a free, MSDOS-compatible operating system based on the FreeDOS kernel. SvarDOS targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once SvarDOS is installed.");
365
  c = menuselect(13, -1, 4, choice, -1);
364
  c = menuselect(13, -1, 4, choice, -1);
366
  if (c < 0) return(MENUPREV);
365
  if (c < 0) return(MENUPREV);
367
  if (c == 0) return(MENUNEXT);
366
  if (c == 0) return(MENUNEXT);
368
  return(MENUQUIT);
367
  return(MENUQUIT);
369
}
368
}
370
 
369
 
371
 
370
 
372
/* returns 1 if drive is removable, 0 if not, -1 on error */
371
/* returns 1 if drive is removable, 0 if not, -1 on error */
373
static int isdriveremovable(int drv) {
372
static int isdriveremovable(int drv) {
374
  union REGS r;
373
  union REGS r;
375
  r.x.ax = 0x4408;
374
  r.x.ax = 0x4408;
376
  r.h.bl = drv;
375
  r.h.bl = drv;
377
  int86(0x21, &r, &r);
376
  int86(0x21, &r, &r);
378
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
377
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
379
  if (r.x.cflag != 0) return(-1);
378
  if (r.x.cflag != 0) return(-1);
380
  if (r.x.ax == 0) return(1);
379
  if (r.x.ax == 0) return(1);
381
  return(0);
380
  return(0);
382
}
381
}
383
 
382
 
384
 
383
 
385
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
384
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
386
static int disksize(int drv) {
385
static int disksize(int drv) {
387
  long res;
386
  long res;
388
  union REGS r;
387
  union REGS r;
389
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
388
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
390
  r.h.dl = drv;
389
  r.h.dl = drv;
391
  int86(0x21, &r, &r);
390
  int86(0x21, &r, &r);
392
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
391
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
393
  res = r.x.ax;  /* sectors per cluster */
392
  res = r.x.ax;  /* sectors per cluster */
394
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
393
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
395
  res *= r.x.cx; /* bytes per sector */
394
  res *= r.x.cx; /* bytes per sector */
396
  res >>= 20;    /* convert bytes to MiB */
395
  res >>= 20;    /* convert bytes to MiB */
397
  return(res);
396
  return(res);
398
}
397
}
399
 
398
 
400
 
399
 
401
/* returns 0 if disk is empty, non-zero otherwise */
400
/* returns 0 if disk is empty, non-zero otherwise */
402
static int diskempty(int drv) {
401
static int diskempty(int drv) {
403
  unsigned int rc;
402
  unsigned int rc;
404
  int res;
403
  int res;
405
  char buff[8];
404
  char buff[8];
406
  struct find_t fileinfo;
405
  struct find_t fileinfo;
407
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
406
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
408
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
407
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
409
  if (rc == 0) {
408
  if (rc == 0) {
410
    res = 1; /* call successfull means disk is not empty */
409
    res = 1; /* call successfull means disk is not empty */
411
  } else {
410
  } else {
412
    res = 0;
411
    res = 0;
413
  }
412
  }
414
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
413
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
415
  return(res);
414
  return(res);
416
}
415
}
417
 
416
 
418
#ifdef DEADCODE
417
#ifdef DEADCODE
419
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
418
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
420
static int set_cur_drive(char drv) {
419
static int set_cur_drive(char drv) {
421
  union REGS r;
420
  union REGS r;
422
  if ((drv < 'A') || (drv > 'Z')) return(-1);
421
  if ((drv < 'A') || (drv > 'Z')) return(-1);
423
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
422
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
424
  r.h.dl = drv - 'A';
423
  r.h.dl = drv - 'A';
425
  int86(0x21, &r, &r);
424
  int86(0x21, &r, &r);
426
  if (r.h.al < drv - 'A') return(-1);
425
  if (r.h.al < drv - 'A') return(-1);
427
  return(0);
426
  return(0);
428
}
427
}
429
#endif
428
#endif
430
 
429
 
-
 
430
 
-
 
431
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
-
 
432
static int get_cur_drive(void) {
-
 
433
  union REGS r;
-
 
434
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
-
 
435
  int86(0x21, &r, &r);
-
 
436
  return(r.h.al);
-
 
437
}
-
 
438
 
-
 
439
 
431
/* returns 0 if file exists, non-zero otherwise */
440
/* returns 0 if file exists, non-zero otherwise */
432
static int fileexists(const char *fname) {
441
static int fileexists(const char *fname) {
433
  FILE *fd;
442
  FILE *fd;
434
  fd = fopen(fname, "rb");
443
  fd = fopen(fname, "rb");
435
  if (fd == NULL) return(-1);
444
  if (fd == NULL) return(-1);
436
  fclose(fd);
445
  fclose(fd);
437
  return(0);
446
  return(0);
438
}
447
}
439
 
448
 
440
 
449
 
441
static int preparedrive(void) {
450
static int preparedrive(char sourcedrv) {
442
  int driveremovable;
451
  int driveremovable;
443
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
452
  int selecteddrive = 3; /* default to 'C:' */
444
  int cselecteddrive;
453
  int cselecteddrive;
445
  int ds;
454
  int ds;
446
  int choice;
455
  int choice;
447
  char buff[1024];
456
  char buff[1024];
-
 
457
  if (selecteddrive == get_cur_drive()) selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
448
  cselecteddrive = 'A' + selecteddrive - 1;
458
  cselecteddrive = 'A' + selecteddrive - 1;
449
  for (;;) {
459
  for (;;) {
450
    driveremovable = isdriveremovable(selecteddrive);
460
    driveremovable = isdriveremovable(selecteddrive);
451
    if (driveremovable < 0) {
461
    if (driveremovable < 0) {
452
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
462
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
453
      newscreen(0);
463
      newscreen(0);
454
      list[0] = kittengets(0, 3, list[0]);
464
      list[0] = kittengets(0, 3, list[0]);
455
      list[1] = kittengets(0, 4, list[1]);
465
      list[1] = kittengets(0, 4, list[1]);
456
      list[2] = kittengets(0, 2, list[2]);
466
      list[2] = kittengets(0, 2, list[2]);
457
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so SvarDOS can be installed on it. Note, that SvarDOS requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVARDOS_DISK_REQ);
467
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so SvarDOS can be installed on it. Note, that SvarDOS requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVARDOS_DISK_REQ);
458
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
468
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
459
      switch (menuselect(14, -1, 5, list, -1)) {
469
      switch (menuselect(14, -1, 5, list, -1)) {
460
        case 0:
470
        case 0:
461
          system("FDISK /AUTO");
471
          system("FDISK /AUTO"); /* TODO DRIVE SHOULD BE SPECIFIED FOR MULTI-DRIVE SYSTEMS ! */
462
          break;
472
          break;
463
        case 1:
473
        case 1:
464
          video_clear(0x0700, 0, 0);
474
          video_clear(0x0700, 0, 0);
465
          video_movecursor(0, 0);
475
          video_movecursor(0, 0);
466
          system("FDISK");
476
          system("FDISK");  /* TODO DRIVE SHOULD BE SPECIFIED FOR MULTI-DRIVE SYSTEMS ! */
467
          break;
477
          break;
468
        case 2:
478
        case 2:
469
          return(MENUQUIT);
479
          return(MENUQUIT);
470
        default:
480
        default:
471
          return(-1);
481
          return(-1);
472
      }
482
      }
473
      /* write a temporary MBR which only skips the drive (in case BIOS would
483
      /* write a temporary MBR which only skips the drive (in case BIOS would
474
       * try to boot off the not-yet-ready C: disk) */
484
       * try to boot off the not-yet-ready C: disk) */
475
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */
485
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */  /* TODO DRIVE SHOULD BE SPECIFIED FOR MULTI-DRIVE SYSTEMS ! */
476
      newscreen(2);
486
      newscreen(2);
477
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
487
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
478
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
488
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
479
      input_getkey();
489
      input_getkey();
480
      reboot();
490
      reboot();
481
      return(MENUQUIT);
491
      return(MENUQUIT);
482
    } else if (driveremovable > 0) {
492
    } else if (driveremovable > 0) {
483
      newscreen(2);
493
      newscreen(2);
484
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
494
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
485
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
495
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
486
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
496
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
487
      return(MENUQUIT);
497
      return(MENUQUIT);
488
    }
498
    }
489
    /* if not formatted, propose to format it right away (try to create a directory) */
499
    /* if not formatted, propose to format it right away (try to create a directory) */
490
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
500
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
491
    if (mkdir(buff) == 0) {
501
    if (mkdir(buff) == 0) {
492
      rmdir(buff);
502
      rmdir(buff);
493
    } else {
503
    } else {
494
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
504
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
495
      newscreen(0);
505
      newscreen(0);
496
      list[0] = kittengets(0, 6, list[0]);
506
      list[0] = kittengets(0, 6, list[0]);
497
      list[1] = kittengets(0, 2, list[1]);
507
      list[1] = kittengets(0, 2, list[1]);
498
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
508
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
499
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
509
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
500
      choice = menuselect(12, -1, 4, list, -1);
510
      choice = menuselect(12, -1, 4, list, -1);
501
      if (choice < 0) return(MENUPREV);
511
      if (choice < 0) return(MENUPREV);
502
      if (choice == 1) return(MENUQUIT);
512
      if (choice == 1) return(MENUQUIT);
503
      video_clear(0x0700, 0, 0);
513
      video_clear(0x0700, 0, 0);
504
      video_movecursor(0, 0);
514
      video_movecursor(0, 0);
505
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
515
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
506
      system(buff);
516
      system(buff);
507
      continue;
517
      continue;
508
    }
518
    }
509
    /* check total disk space */
519
    /* check total disk space */
510
    ds = disksize(selecteddrive);
520
    ds = disksize(selecteddrive);
511
    if (ds < SVARDOS_DISK_REQ) {
521
    if (ds < SVARDOS_DISK_REQ) {
512
      int y = 9;
522
      int y = 9;
513
      newscreen(2);
523
      newscreen(2);
514
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB."), cselecteddrive);
524
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB."), cselecteddrive);
515
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
525
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
516
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
526
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
517
      input_getkey();
527
      input_getkey();
518
      return(MENUQUIT);
528
      return(MENUQUIT);
519
    }
529
    }
520
    /* is the disk empty? */
530
    /* is the disk empty? */
521
    newscreen(0);
531
    newscreen(0);
522
    if (diskempty(selecteddrive) != 0) {
532
    if (diskempty(selecteddrive) != 0) {
523
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
533
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
524
      int y = 6;
534
      int y = 6;
525
      list[0] = kittengets(0, 6, list[0]);
535
      list[0] = kittengets(0, 6, list[0]);
526
      list[1] = kittengets(0, 2, list[1]);
536
      list[1] = kittengets(0, 2, list[1]);
527
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. SvarDOS must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
537
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. SvarDOS must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
528
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
538
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
529
      choice = menuselect(++y, -1, 4, list, -1);
539
      choice = menuselect(++y, -1, 4, list, -1);
530
      if (choice < 0) return(MENUPREV);
540
      if (choice < 0) return(MENUPREV);
531
      if (choice == 1) return(MENUQUIT);
541
      if (choice == 1) return(MENUQUIT);
532
      video_clear(0x0700, 0, 0);
542
      video_clear(0x0700, 0, 0);
533
      video_movecursor(0, 0);
543
      video_movecursor(0, 0);
534
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
544
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
535
      system(buff);
545
      system(buff);
536
      continue;
546
      continue;
537
    } else {
547
    } else {
538
      /* final confirmation */
548
      /* final confirmation */
539
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
549
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
540
      list[0] = kittengets(0, 1, list[0]);
550
      list[0] = kittengets(0, 1, list[0]);
541
      list[1] = kittengets(0, 2, list[1]);
551
      list[1] = kittengets(0, 2, list[1]);
542
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
552
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
543
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
553
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
544
      choice = menuselect(10, -1, 4, list, -1);
554
      choice = menuselect(10, -1, 4, list, -1);
545
      if (choice < 0) return(MENUPREV);
555
      if (choice < 0) return(MENUPREV);
546
      if (choice == 1) return(MENUQUIT);
556
      if (choice == 1) return(MENUQUIT);
547
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
557
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
548
      system(buff);
558
      system(buff);
549
      system("FDISK /MBR");
559
      system("FDISK /MBR"); /* TODO DRIVE SHOULD BE SPECIFIED FOR MULTI-DRIVE SYSTEMS ! */
550
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
560
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
551
      mkdir(buff);
561
      mkdir(buff);
552
      return(cselecteddrive);
562
      return(cselecteddrive);
553
    }
563
    }
554
  }
564
  }
555
}
565
}
556
 
566
 
557
 
567
 
558
/* generates locales-related configurations and writes them to file (this
568
/* generates locales-related configurations and writes them to file (this
559
 * is used to compute autoexec.bat content) */
569
 * is used to compute autoexec.bat content) */
560
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
570
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
561
  if (locales == NULL) return;
571
  if (locales == NULL) return;
562
 
572
 
563
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
573
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
564
 
574
 
565
  if (locales->egafile > 0) {
575
  if (locales->egafile > 0) {
566
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
576
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
567
    if (locales->egafile == 1) {
577
    if (locales->egafile == 1) {
568
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
578
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
569
    } else {
579
    } else {
570
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
580
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
571
    }
581
    }
572
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
582
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
573
  }
583
  }
574
 
584
 
575
  if (locales->keybfile > 0) {
585
  if (locales->keybfile > 0) {
576
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
586
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\BIN\\", locales->keybcode, locales->codepage);
577
    if (locales->keybfile == 1) {
587
    if (locales->keybfile == 1) {
578
      fprintf(fd, "KEYBOARD.SYS");
588
      fprintf(fd, "KEYBOARD.SYS");
579
    } else {
589
    } else {
580
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
590
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
581
    }
591
    }
582
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
592
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
583
    fprintf(fd, "\r\n");
593
    fprintf(fd, "\r\n");
584
  }
594
  }
585
}
595
}
586
 
596
 
587
 
597
 
588
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
598
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
589
  char buff[128];
599
  char buff[128];
590
  FILE *fd;
600
  FILE *fd;
591
  /*** CONFIG.SYS ***/
601
  /*** CONFIG.SYS ***/
592
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
602
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
593
  fd = fopen(buff, "wb");
603
  fd = fopen(buff, "wb");
594
  if (fd == NULL) return;
604
  if (fd == NULL) return;
595
  fprintf(fd, "DOS=UMB,HIGH\r\n"
605
  fprintf(fd, "DOS=UMB,HIGH\r\n"
596
              "LASTDRIVE=Z\r\n"
606
              "LASTDRIVE=Z\r\n"
597
              "FILES=50\r\n");
607
              "FILES=50\r\n");
598
  fprintf(fd, "DEVICE=%c:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n", targetdrv);
608
  fprintf(fd, "DEVICE=%c:\\SVARDOS\\BIN\\HIMEMX.EXE\r\n", targetdrv);
599
  if (strcmp(locales->lang, "EN") == 0) {
609
  if (strcmp(locales->lang, "EN") == 0) {
600
    strcpy(buff, "COMMAND");
610
    strcpy(buff, "COMMAND");
601
  } else {
611
  } else {
602
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
612
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
603
  }
613
  }
604
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
614
  fprintf(fd, "SHELLHIGH=C:\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", buff);
605
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
615
  fprintf(fd, "REM COUNTRY=001,437,C:\\SVARDOS\\CONF\\COUNTRY.SYS\r\n");
606
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
616
  fprintf(fd, "REM DEVICE=C:\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n");
607
  fclose(fd);
617
  fclose(fd);
608
  /*** AUTOEXEC.BAT ***/
618
  /*** AUTOEXEC.BAT ***/
609
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
619
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
610
  fd = fopen(buff, "wb");
620
  fd = fopen(buff, "wb");
611
  if (fd == NULL) return;
621
  if (fd == NULL) return;
612
  fprintf(fd, "@ECHO OFF\r\n");
622
  fprintf(fd, "@ECHO OFF\r\n");
613
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
623
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
614
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
624
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
615
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
625
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
616
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
626
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
617
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
627
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
618
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
628
  fprintf(fd, "PATH %%DOSDIR%%\\BIN\r\n");
619
  fprintf(fd, "PROMPT $P$G\r\n");
629
  fprintf(fd, "PROMPT $P$G\r\n");
620
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
630
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
621
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
631
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
622
  fprintf(fd, "FDAPM APMDOS\r\n");
632
  fprintf(fd, "FDAPM APMDOS\r\n");
623
  fprintf(fd, "\r\n");
633
  fprintf(fd, "\r\n");
624
  genlocalesconf(fd, locales);
634
  genlocalesconf(fd, locales);
625
  fprintf(fd, "\r\n");
635
  fprintf(fd, "\r\n");
626
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
636
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
627
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
637
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
628
  fprintf(fd, "\r\n");
638
  fprintf(fd, "\r\n");
629
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
639
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
630
  fprintf(fd, "REM CTMOUSE\r\n");
640
  fprintf(fd, "REM CTMOUSE\r\n");
631
  fprintf(fd, "\r\n");
641
  fprintf(fd, "\r\n");
632
  fprintf(fd, "ECHO.\r\n");
642
  fprintf(fd, "ECHO.\r\n");
633
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
643
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
634
  fclose(fd);
644
  fclose(fd);
635
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
645
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
636
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
646
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
637
  mkdir(buff);
647
  mkdir(buff);
638
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
648
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
639
  mkdir(buff);
649
  mkdir(buff);
640
  /*** PKG.CFG ***/
650
  /*** PKG.CFG ***/
641
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
651
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
642
  fd = fopen(buff, "wb");
652
  fd = fopen(buff, "wb");
643
  if (fd == NULL) return;
653
  if (fd == NULL) return;
644
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
654
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
645
              "\r\n"
655
              "\r\n"
646
              "# Programs\r\n"
656
              "# Programs\r\n"
647
              "DIR PROGS C:\\\r\n"
657
              "DIR PROGS C:\\\r\n"
648
              "\r\n"
658
              "\r\n"
649
              "# Games \r\n"
659
              "# Games \r\n"
650
              "DIR GAMES C:\\\r\n"
660
              "DIR GAMES C:\\\r\n"
651
              "\r\n"
661
              "\r\n"
652
              "# Drivers\r\n"
662
              "# Drivers\r\n"
653
              "DIR DRIVERS C:\\DRIVERS\r\n"
663
              "DIR DRIVERS C:\\DRIVERS\r\n"
654
              "\r\n"
664
              "\r\n"
655
              "# Development tools\r\n"
665
              "# Development tools\r\n"
656
              "DIR DEVEL C:\\DEVEL\r\n");
666
              "DIR DEVEL C:\\DEVEL\r\n");
657
  fclose(fd);
667
  fclose(fd);
658
  /*** COUNTRY.SYS ***/
668
  /*** COUNTRY.SYS ***/
659
  /*** PICOTCP ***/
669
  /*** PICOTCP ***/
660
  /*** WATTCP ***/
670
  /*** WATTCP ***/
661
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
671
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
662
  fd = fopen(buff, "wb");
672
  fd = fopen(buff, "wb");
663
  if (fd == NULL) return;
673
  if (fd == NULL) return;
664
  fprintf(fd, "my_ip = dhcp\r\n"
674
  fprintf(fd, "my_ip = dhcp\r\n"
665
              "#my_ip = 192.168.0.7\r\n"
675
              "#my_ip = 192.168.0.7\r\n"
666
              "#netmask = 255.255.255.0\r\n"
676
              "#netmask = 255.255.255.0\r\n"
667
              "#nameserver = 192.168.0.1\r\n"
677
              "#nameserver = 192.168.0.1\r\n"
668
              "#nameserver = 192.168.0.2\r\n"
678
              "#nameserver = 192.168.0.2\r\n"
669
              "#gateway = 192.168.1.1\r\n");
679
              "#gateway = 192.168.1.1\r\n");
670
  fclose(fd);
680
  fclose(fd);
671
}
681
}
672
 
682
 
673
 
683
 
674
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
684
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
675
  char pkglist[512];
685
  char pkglist[512];
676
  int i, pkglistlen;
686
  int i, pkglistlen;
677
  size_t pkglistflen;
687
  size_t pkglistflen;
678
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
688
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
679
  FILE *fd = NULL;
689
  FILE *fd = NULL;
680
  char *pkgptr;
690
  char *pkgptr;
681
  newscreen(3);
691
  newscreen(3);
682
  /* load pkg list */
692
  /* load pkg list */
683
  fd = fopen("install.lst", "rb");
693
  fd = fopen("install.lst", "rb");
684
  if (fd == NULL) {
694
  if (fd == NULL) {
685
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
695
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
686
    input_getkey();
696
    input_getkey();
687
    return(-1);
697
    return(-1);
688
  }
698
  }
689
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
699
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
690
  fclose(fd);
700
  fclose(fd);
691
  if (pkglistflen == sizeof(pkglist)) {
701
  if (pkglistflen == sizeof(pkglist)) {
692
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
702
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
693
    input_getkey();
703
    input_getkey();
694
    return(-1);
704
    return(-1);
695
  }
705
  }
696
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
706
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
697
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
707
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
698
  pkglistlen = 0;
708
  pkglistlen = 0;
699
  for (i = 0; i < pkglistflen; i++) {
709
  for (i = 0; i < pkglistflen; i++) {
700
    switch (pkglist[i]) {
710
    switch (pkglist[i]) {
701
      case '\n':
711
      case '\n':
702
        pkglistlen++;
712
        pkglistlen++;
703
        /* FALLTHRU */
713
        /* FALLTHRU */
704
      case '\r':
714
      case '\r':
705
        pkglist[i] = 0;
715
        pkglist[i] = 0;
706
        break;
716
        break;
707
    }
717
    }
708
  }
718
  }
709
  /* copy pkg.exe to the new drive, along with all packages */
719
  /* copy pkg.exe to the new drive, along with all packages */
710
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
720
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
711
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
721
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
712
  fcopy(buff, buff + 64, buff, sizeof(buff));
722
  fcopy(buff, buff + 64, buff, sizeof(buff));
713
 
723
 
714
  /* open the post-install autoexec.bat and prepare initial instructions */
724
  /* open the post-install autoexec.bat and prepare initial instructions */
715
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
725
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
716
  fd = fopen(buff, "wb");
726
  fd = fopen(buff, "wb");
717
  if (fd == NULL) return(-1);
727
  if (fd == NULL) return(-1);
718
  fprintf(fd, "@ECHO OFF\r\n");
728
  fprintf(fd, "@ECHO OFF\r\n");
719
 
729
 
720
  /* copy packages */
730
  /* copy packages */
721
  pkgptr = pkglist;
731
  pkgptr = pkglist;
722
  for (i = 0;; i++) {
732
  for (i = 0;; i++) {
723
    /* move forward to nearest entry or end of list */
733
    /* move forward to nearest entry or end of list */
724
    while (*pkgptr == 0) pkgptr++;
734
    while (*pkgptr == 0) pkgptr++;
725
    if (*pkgptr == 0xff) break;
735
    if (*pkgptr == 0xff) break;
726
    /* install the package */
736
    /* install the package */
727
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
737
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
728
    strcat(buff, "       ");
738
    strcat(buff, "       ");
729
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
739
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
730
    /* wait for new diskette if package not found */
740
    /* wait for new diskette if package not found */
731
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
741
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", srcdrv, pkgptr);
732
    while (fileexists(buff) != 0) {
742
    while (fileexists(buff) != 0) {
733
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
743
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
734
      input_getkey();
744
      input_getkey();
735
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
745
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
736
    }
746
    }
737
    /* proceed with package copy (buff contains the src filename already) */
747
    /* proceed with package copy (buff contains the src filename already) */
738
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
748
    snprintf(buff + 32, sizeof(buff) - 32, "%c:\\temp\\%s.zip", targetdrv, pkgptr);
739
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
749
    if (fcopy(buff + 32, buff, buff, sizeof(buff)) != 0) {
740
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
750
      video_putstring(10, 30, COLOR_BODY[mono], "READ ERROR", -1);
741
      input_getkey();
751
      input_getkey();
742
      fclose(fd);
752
      fclose(fd);
743
      return(-1);
753
      return(-1);
744
    }
754
    }
745
    /* write install instruction to post-install script */
755
    /* write install instruction to post-install script */
746
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
756
    fprintf(fd, "pkg install %s.zip\r\ndel %s.zip\r\n", pkgptr, pkgptr);
747
    /* jump to next entry or end of list */
757
    /* jump to next entry or end of list */
748
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
758
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
749
    if (*pkgptr == 0xff) break;
759
    if (*pkgptr == 0xff) break;
750
  }
760
  }
751
  /* set up locales so the "installation over" message is nicely displayed */
761
  /* set up locales so the "installation over" message is nicely displayed */
752
  genlocalesconf(fd, locales);
762
  genlocalesconf(fd, locales);
753
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
763
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
754
  fprintf(fd, "DEL pkg.exe\r\n"
764
  fprintf(fd, "DEL pkg.exe\r\n"
755
              "COPY CONFIG.SYS C:\\\r\n"
765
              "COPY CONFIG.SYS C:\\\r\n"
756
              "DEL CONFIG.SYS\r\n"
766
              "DEL CONFIG.SYS\r\n"
757
              "DEL C:\\AUTOEXEC.BAT\r\n"
767
              "DEL C:\\AUTOEXEC.BAT\r\n"
758
              "COPY AUTOEXEC.BAT C:\\\r\n"
768
              "COPY AUTOEXEC.BAT C:\\\r\n"
759
              "DEL AUTOEXEC.BAT\r\n");
769
              "DEL AUTOEXEC.BAT\r\n");
760
  /* print out the "installation over" message */
770
  /* print out the "installation over" message */
761
  fprintf(fd, "ECHO.\r\n"
771
  fprintf(fd, "ECHO.\r\n"
762
              "ECHO %s\r\n"
772
              "ECHO %s\r\n"
763
              "ECHO.\r\n", kittengets(5, 1, "SvarDOS installation is over. Please restart your computer now."));
773
              "ECHO.\r\n", kittengets(5, 1, "SvarDOS installation is over. Please restart your computer now."));
764
  fclose(fd);
774
  fclose(fd);
765
 
775
 
766
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
776
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
767
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
777
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
768
  fd = fopen(buff, "wb");
778
  fd = fopen(buff, "wb");
769
  if (fd == NULL) return(-1);
779
  if (fd == NULL) return(-1);
770
  fprintf(fd, "@ECHO OFF\r\n"
780
  fprintf(fd, "@ECHO OFF\r\n"
771
              "SET DOSDIR=C:\\SVARDOS\r\n"
781
              "SET DOSDIR=C:\\SVARDOS\r\n"
772
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
782
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
773
              "PATH %%DOSDIR%%\\BIN\r\n");
783
              "PATH %%DOSDIR%%\\BIN\r\n");
774
  fprintf(fd, "CD TEMP\r\n"
784
  fprintf(fd, "CD TEMP\r\n"
775
              "postinst.bat\r\n");
785
              "postinst.bat\r\n");
776
  fclose(fd);
786
  fclose(fd);
777
 
787
 
778
  return(0);
788
  return(0);
779
}
789
}
780
 
790
 
781
 
791
 
782
static void finalreboot(void) {
792
static void finalreboot(void) {
783
  int y = 9;
793
  int y = 9;
784
  newscreen(2);
794
  newscreen(2);
785
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Your computer will reboot now.\nPlease remove the installation disk from your drive.");
795
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Your computer will reboot now.\nPlease remove the installation disk from your drive.");
786
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
796
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
787
  input_getkey();
797
  input_getkey();
788
  reboot();
798
  reboot();
789
}
799
}
790
 
800
 
791
 
801
 
792
static void loadcp(const struct slocales *locales) {
802
static void loadcp(const struct slocales *locales) {
793
  char buff[64];
803
  char buff[64];
794
  if (locales->codepage == 437) return;
804
  if (locales->codepage == 437) return;
795
  video_movecursor(1, 0);
805
  video_movecursor(1, 0);
796
  if (locales->egafile == 1) {
806
  if (locales->egafile == 1) {
797
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
807
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
798
  } else {
808
  } else {
799
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
809
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
800
  }
810
  }
801
  system(buff);
811
  system(buff);
802
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
812
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
803
  system(buff);
813
  system(buff);
804
  /* below I re-init the video controller - apparently this is required if
814
  /* below I re-init the video controller - apparently this is required if
805
   * I want the new glyph symbols to be actually applied, at least some
815
   * I want the new glyph symbols to be actually applied, at least some
806
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
816
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
807
  {
817
  {
808
  union REGS r;
818
  union REGS r;
809
  r.h.ah = 0x0F; /* get current video mode */
819
  r.h.ah = 0x0F; /* get current video mode */
810
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
820
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
811
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
821
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
812
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
822
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
813
  int86(0x10, &r, &r);
823
  int86(0x10, &r, &r);
814
  }
824
  }
815
}
825
}
816
 
826
 
817
 
827
 
-
 
828
#ifdef DEADCODE
818
/* checks that drive drv contains SvarDOS packages
829
/* checks that drive drv contains SvarDOS packages
819
 * returns 0 if found, non-zero otherwise */
830
 * returns 0 if found, non-zero otherwise */
820
static int checkinstsrc(char drv) {
831
static int checkinstsrc(char drv) {
821
  char fname[16];
832
  char fname[16];
822
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
833
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
823
  return(fileexists(fname));
834
  return(fileexists(fname));
824
}
835
}
-
 
836
#endif
825
 
837
 
826
 
838
 
827
int main(void) {
839
int main(void) {
828
  struct slocales locales;
840
  struct slocales locales;
829
  int targetdrv;
841
  int targetdrv;
830
  int sourcedrv;
842
  int sourcedrv;
831
  int action;
843
  int action;
832
 
844
 
833
  /* am I running in install-from-floppy mode? */
-
 
834
  if (checkinstsrc('A') == 0) {
-
 
835
    sourcedrv = 'A';
-
 
836
  } else { /* otherwise find where the cdrom drive is */
-
 
837
    sourcedrv = cdrom_findfirst();
845
  sourcedrv = get_cur_drive() + 'A';
838
    if (sourcedrv < 0) {
-
 
839
      printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
-
 
840
      return(1);
-
 
841
    }
-
 
842
    sourcedrv += 'A'; /* convert the source drive 'id' (A=0) to an actual drive letter */
-
 
843
    if (checkinstsrc(sourcedrv) != 0) {
-
 
844
      printf("ERROR: SVARDOS INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
-
 
845
      return(1);
-
 
846
    }
-
 
847
  }
-
 
848
 
846
 
849
  /* init screen and detect mono status */
847
  /* init screen and detect mono status */
850
  mono = video_init();
848
  mono = video_init();
851
 
849
 
852
  kittenopen("INSTALL"); /* load initial NLS support */
850
  kittenopen("INSTALL"); /* load initial NLS support */
853
 
851
 
854
 SelectLang:
852
 SelectLang:
855
  action = selectlang(&locales); /* welcome to svardos, select your language */
853
  action = selectlang(&locales); /* welcome to svardos, select your language */
856
  if (action != MENUNEXT) goto Quit;
854
  if (action != MENUNEXT) goto Quit;
857
  setenv("LANG", locales.lang, 1);
855
  setenv("LANG", locales.lang, 1);
858
  loadcp(&locales);
856
  loadcp(&locales);
859
  kittenclose(); /* reload NLS with new language */
857
  kittenclose(); /* reload NLS with new language */
860
  kittenopen("INSTALL"); /* NLS support */
858
  kittenopen("INSTALL"); /* NLS support */
861
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
859
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
862
  if (action == MENUQUIT) goto Quit;
860
  if (action == MENUQUIT) goto Quit;
863
  if (action == MENUPREV) goto SelectLang;
861
  if (action == MENUPREV) goto SelectLang;
864
 
862
 
865
 WelcomeScreen:
863
 WelcomeScreen:
866
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
864
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
867
  if (action == MENUQUIT) goto Quit;
865
  if (action == MENUQUIT) goto Quit;
868
  if (action == MENUPREV) goto SelectLang;
866
  if (action == MENUPREV) goto SelectLang;
869
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
867
  targetdrv = preparedrive(sourcedrv); /* what drive should we install to? check avail. space */
870
  if (targetdrv == MENUQUIT) goto Quit;
868
  if (targetdrv == MENUQUIT) goto Quit;
871
  if (targetdrv == MENUPREV) goto WelcomeScreen;
869
  if (targetdrv == MENUPREV) goto WelcomeScreen;
872
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
870
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
873
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
871
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
874
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
872
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
875
  /*netcfg();*/ /* basic networking config */
873
  /*netcfg();*/ /* basic networking config */
876
  finalreboot(); /* remove the CD and reboot */
874
  finalreboot(); /* remove the CD and reboot */
877
 
875
 
878
 Quit:
876
 Quit:
879
  kittenclose(); /* close NLS support */
877
  kittenclose(); /* close NLS support */
880
  video_clear(0x0700, 0, 0);
878
  video_clear(0x0700, 0, 0);
881
  video_movecursor(0, 0);
879
  video_movecursor(0, 0);
882
  return(0);
880
  return(0);
883
}
881
}
884
 
882