Subversion Repositories SvarDOS

Rev

Rev 81 | Rev 95 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
28 mv_fox 1
/*
2
 * SVAROG386 INSTALL
94 mv_fox 3
 * COPYRIGHT (C) 2016 MATEUSZ VISTE, ALL RIGHTS RESERVED.
42 mv_fox 4
 *
94 mv_fox 5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 * this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 * notice, this list of conditions and the following disclaimer in the
13
 * documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
 * POSSIBILITY OF SUCH DAMAGE.
26
 *
42 mv_fox 27
 * http://svarog386.sf.net
28 mv_fox 28
 */
29
 
30
#include <dos.h>
30 mv_fox 31
#include <direct.h>  /* mkdir() */
28 mv_fox 32
#include <stdio.h>   /* printf() and friends */
33
#include <stdlib.h>  /* system() */
34
#include <string.h>  /* memcpy() */
35
#include <unistd.h>
42 mv_fox 36
 
37
#include "kitten\kitten.h"
38
 
53 mv_fox 39
#include "cdrom.h"
28 mv_fox 40
#include "input.h"
41
#include "video.h"
42
 
67 mv_fox 43
/* keyboard layouts and locales */
44
#include "keylay.h"
45
#include "keyoff.h"
42 mv_fox 46
 
29 mv_fox 47
/* color scheme (color, mono) */
48
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
49
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
50
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
51
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
28 mv_fox 52
 
29 mv_fox 53
/* mono flag */
54
static int mono = 0;
28 mv_fox 55
 
47 mv_fox 56
/* how much disk space does Svarog386 require (in MiB) */
57
#define SVAROG_DISK_REQ 8
28 mv_fox 58
 
73 mv_fox 59
/* menu screens can output only one of these: */
60
#define MENUNEXT 0
61
#define MENUPREV -1
62
#define MENUQUIT -2
63
 
67 mv_fox 64
/* a convenience 'function' used for debugging */
65
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
47 mv_fox 66
 
67 mv_fox 67
struct slocales {
68
  char lang[4];
69
  char *keybcode;
70
  unsigned int codepage;
71
  int egafile;
72
  int keybfile;
73
  int keyboff;
74
  int keyblen;
75
};
76
 
77
 
28 mv_fox 78
/* reboot the computer */
79
static void reboot(void) {
80
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
81
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
82
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
83
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
84
}
85
 
42 mv_fox 86
 
56 mv_fox 87
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
88
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
89
  int linew, lincount;
90
  linew = 80;
91
  if (x >= 0) linew -= (x << 1);
92
 
93
  for (lincount = 1; y+lincount < 25; lincount++) {
94
    int i, len = linew;
95
    for (i = 0; i <= linew; i++) {
96
      if (s[i] == ' ') len = i;
97
      if (s[i] == '\n') {
98
        len = i;
99
        break;
100
      }
101
      if (s[i] == 0) {
102
        len = i;
103
        break;
104
      }
105
    }
106
    video_putstring(y++, x, attr, s, len);
107
    s += len;
108
    if (*s == 0) break;
109
    s += 1; /* skip the whitespace char */
110
  }
111
  return(lincount);
112
}
113
 
114
 
115
/* an NLS wrapper around video_putstring(), also performs line wrapping when
116
 * needed. returns the amount of lines that were output */
117
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
42 mv_fox 118
  s = kittengets(nlsmaj, nlsmin, s);
56 mv_fox 119
  return(putstringwrap(y, x, attr, s));
42 mv_fox 120
}
121
 
122
 
67 mv_fox 123
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
28 mv_fox 124
  int i, offset = 0, res = 0, count, width = 0;
67 mv_fox 125
  /* count how many positions there is, and check their width */
126
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
28 mv_fox 127
    int len = strlen(list[count]);
128
    if (len > width) width = len;
129
  }
130
 
131
  /* if xpos negative, means 'center out' */
132
  if (xpos < 0) xpos = 39 - (width >> 1);
133
 
29 mv_fox 134
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
135
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
136
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
137
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
138
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
139
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
140
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
141
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
28 mv_fox 142
 
143
  for (;;) {
144
    int key;
145
    /* list of selectable items */
146
    for (i = 0; i < height - 2; i++) {
147
      if (i + offset == res) {
29 mv_fox 148
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
149
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
28 mv_fox 150
        video_movecursor(ypos + 1 + i, xpos);
29 mv_fox 151
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
28 mv_fox 152
      } else if (i + offset < count) {
29 mv_fox 153
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
154
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
155
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
28 mv_fox 156
      } else {
29 mv_fox 157
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
28 mv_fox 158
      }
159
    }
160
    key = input_getkey();
161
    if (key == 0x0D) { /* ENTER */
162
      return(res);
163
    } else if (key == 0x148) { /* up */
33 mv_fox 164
      if (res > 0) {
165
        res--;
166
        if (res < offset) offset = res;
167
      }
28 mv_fox 168
    } else if (key == 0x150) { /* down */
33 mv_fox 169
      if (res+1 < count) {
170
        res++;
171
        if (res > offset + height - 3) offset = res - (height - 3);
172
      }
173
    } else if (key == 0x147) { /* home */
174
      res = 0;
175
      offset = 0;
176
    } else if (key == 0x14F) { /* end */
177
      res = count - 1;
178
      if (res > offset + height - 3) offset = res - (height - 3);
28 mv_fox 179
    } else if (key == 0x1B) {  /* ESC */
180
      return(-1);
78 mv_fox 181
    }/* else {
33 mv_fox 182
      char buf[8];
55 mv_fox 183
      snprintf(buf, sizeof(buf), "0x%02X ", key);
56 mv_fox 184
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
78 mv_fox 185
    }*/
28 mv_fox 186
  }
187
}
188
 
79 mv_fox 189
static void newscreen(int statusbartype) {
190
  char *msg;
191
  msg = kittengets(0, 0, "SVAROG386 INSTALLATION");
81 mv_fox 192
  video_putcharmulti(0, 0, COLOR_TITLEBAR[mono], ' ', 80, 1);
79 mv_fox 193
  video_putstring(0, 40 - (strlen(msg) >> 1), COLOR_TITLEBAR[mono], msg, -1);
81 mv_fox 194
  video_clear(COLOR_BODY[mono], 80, -80);
79 mv_fox 195
  switch (statusbartype) {
196
    case 1:
197
      msg = kittengets(0, 11, "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS");
198
      break;
199
    case 2:
200
      msg = kittengets(0, 5, "Press any key...");
201
      break;
202
    case 3:
203
      msg = "";
204
      break;
205
    default:
206
      msg = kittengets(0, 10, "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen");
207
      break;
208
  }
209
  video_putchar(24, 0, COLOR_TITLEBAR[mono], ' ');
210
  video_putstringfix(24, 1, COLOR_TITLEBAR[mono], msg, 79);
36 mv_fox 211
  video_movecursor(25,0);
28 mv_fox 212
}
213
 
67 mv_fox 214
static int selectlang(struct slocales *locales) {
215
  int choice, x;
42 mv_fox 216
  char *msg;
28 mv_fox 217
  char *langlist[] = {
67 mv_fox 218
    "English",
219
    "French",
220
    "Polish",
221
    "Turkish",
28 mv_fox 222
    NULL
223
  };
224
 
79 mv_fox 225
  newscreen(1);
42 mv_fox 226
  msg = kittengets(1, 0, "Welcome to Svarog386");
227
  x = 40 - (strlen(msg) >> 1);
56 mv_fox 228
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
42 mv_fox 229
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
49 mv_fox 230
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
67 mv_fox 231
  choice = menuselect(11, -1, 6, langlist, -1);
73 mv_fox 232
  if (choice < 0) return(MENUPREV);
67 mv_fox 233
  /* populate locales with default values */
234
  memset(locales, 0, sizeof(struct slocales));
235
  switch (choice) {
236
    case 1:
237
      strcpy(locales->lang, "FR");
238
      locales->keyboff = OFFLOC_FR;
239
      locales->keyblen = OFFLEN_FR;
240
      break;
241
    case 2:
242
      strcpy(locales->lang, "PL");
243
      locales->keyboff = OFFLOC_PL;
244
      locales->keyblen = OFFLEN_PL;
245
      break;
246
    case 3:
247
      strcpy(locales->lang, "TR");
248
      locales->keyboff = OFFLOC_TR;
249
      locales->keyblen = OFFLEN_TR;
250
      break;
251
    default:
252
      strcpy(locales->lang, "EN");
253
      locales->keyboff = 0;
254
      locales->keyblen = OFFCOUNT;
255
      break;
256
  }
257
  /* populate the slocales struct */
258
  for (msg = kblayouts[locales->keyboff]; *msg != 0; msg++); /* skip layout name */
259
  msg++;
260
  /* skip keyb code and copy it to locales.keybcode */
261
  locales->keybcode = msg;
262
  for (; *msg != 0; msg++);
263
  /* */
264
  locales->codepage = ((unsigned short)msg[1] << 8) | msg[2];
265
  locales->egafile = msg[3];
266
  locales->keybfile = msg[4];
267
  /* */
73 mv_fox 268
  return(MENUNEXT);
28 mv_fox 269
}
270
 
271
 
67 mv_fox 272
#define LTODEC(x, y) ((unsigned short)(x << 8) | (y))
273
static int selectkeyb(struct slocales *locales) {
274
  int keyboff, keyblen, menuheight;
275
  unsigned short lang;
276
  lang = LTODEC(locales->lang[0], locales->lang[1]);
277
 
278
  switch (lang) {
279
    case LTODEC('F', 'R'):
280
      keyboff = OFFLOC_FR;
281
      keyblen = OFFLEN_FR;
282
      break;
283
    case LTODEC('P', 'L'):
284
      keyboff = OFFLOC_PL;
285
      keyblen = OFFLEN_PL;
286
      break;
287
    case LTODEC('T', 'R'):
288
      keyboff = OFFLOC_TR;
289
      keyblen = OFFLEN_TR;
290
      break;
291
    default: /* otherwise propose all possible keyoard layouts */
292
      keyboff = 0;
293
      keyblen = OFFCOUNT;
294
      break;
295
  }
73 mv_fox 296
  if (keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
79 mv_fox 297
  newscreen(0);
67 mv_fox 298
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "Svarog386 supports the keyboard layouts used in different countries. Choose the keyboard layout you want.");
299
  menuheight = keyblen + 2;
300
  if (menuheight > 13) menuheight = 13;
73 mv_fox 301
  if (menuselect(10, -1, menuheight, &(kblayouts[keyboff]), keyblen) < 0) return(MENUPREV);
302
  return(MENUNEXT);
67 mv_fox 303
}
304
 
305
 
28 mv_fox 306
/* returns 0 if installation must proceed, non-zero otherwise */
307
static int welcomescreen(void) {
73 mv_fox 308
  int c;
28 mv_fox 309
  char *choice[] = {"Install Svarog386 to disk", "Quit to DOS", NULL};
42 mv_fox 310
  choice[0] = kittengets(0, 1, choice[0]);
311
  choice[1] = kittengets(0, 2, choice[1]);
79 mv_fox 312
  newscreen(0);
56 mv_fox 313
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install Svarog386: a free, MSDOS-compatible operating system based on the FreeDOS kernel. Svarog386 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 Svarog386 is installed.");
73 mv_fox 314
  c = menuselect(13, -1, 4, choice, -1);
315
  if (c < 0) return(MENUPREV);
316
  if (c == 0) return(MENUNEXT);
317
  return(MENUQUIT);
28 mv_fox 318
}
319
 
320
 
33 mv_fox 321
/* returns 1 if drive is removable, 0 if not, -1 on error */
322
static int isdriveremovable(int drv) {
28 mv_fox 323
  union REGS r;
33 mv_fox 324
  r.x.ax = 0x4408;
325
  r.h.bl = drv;
28 mv_fox 326
  int86(0x21, &r, &r);
33 mv_fox 327
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
328
  if (r.x.cflag != 0) return(-1);
329
  if (r.x.ax == 0) return(1);
330
  return(0);
28 mv_fox 331
}
332
 
333
 
35 mv_fox 334
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
335
static int disksize(int drv) {
28 mv_fox 336
  long res;
337
  union REGS r;
338
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
339
  r.h.dl = drv;
340
  int86(0x21, &r, &r);
341
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
49 mv_fox 342
  res = r.x.ax;  /* sectors per cluster */
343
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
344
  res *= r.x.cx; /* bytes per sector */
345
  res >>= 20;    /* convert bytes to MiB */
346
  return(res);
35 mv_fox 347
}
348
 
349
 
350
/* returns 0 if disk is empty, non-zero otherwise */
351
static int diskempty(int drv) {
352
  unsigned int rc;
353
  int res;
354
  char buff[8];
355
  struct find_t fileinfo;
55 mv_fox 356
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
35 mv_fox 357
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
358
  if (rc == 0) {
359
    res = 1; /* call successfull means disk is not empty */
28 mv_fox 360
  } else {
35 mv_fox 361
    res = 0;
28 mv_fox 362
  }
35 mv_fox 363
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
28 mv_fox 364
  return(res);
365
}
366
 
367
 
368
static int preparedrive(void) {
33 mv_fox 369
  int driveremovable;
36 mv_fox 370
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
371
  int cselecteddrive;
35 mv_fox 372
  int ds;
73 mv_fox 373
  int choice;
56 mv_fox 374
  char buff[1024];
36 mv_fox 375
  cselecteddrive = 'A' + selecteddrive - 1;
28 mv_fox 376
  for (;;) {
33 mv_fox 377
    driveremovable = isdriveremovable(selecteddrive);
378
    if (driveremovable < 0) {
49 mv_fox 379
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
79 mv_fox 380
      newscreen(0);
42 mv_fox 381
      list[0] = kittengets(0, 3, list[0]);
382
      list[1] = kittengets(0, 4, list[1]);
383
      list[2] = kittengets(0, 2, list[2]);
56 mv_fox 384
      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 Svarog386 can be installed on it. Note, that Svarog386 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, SVAROG_DISK_REQ);
61 mv_fox 385
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
67 mv_fox 386
      switch (menuselect(14, -1, 5, list, -1)) {
33 mv_fox 387
        case 0:
388
          system("FDISK /AUTO");
389
          break;
390
        case 1:
81 mv_fox 391
          video_clear(0x0700, 0, 0);
33 mv_fox 392
          video_movecursor(0, 0);
393
          system("FDISK");
394
          break;
73 mv_fox 395
        case 2:
396
          return(MENUQUIT);
56 mv_fox 397
        default:
33 mv_fox 398
          return(-1);
399
      }
79 mv_fox 400
      newscreen(2);
61 mv_fox 401
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
42 mv_fox 402
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
33 mv_fox 403
      input_getkey();
28 mv_fox 404
      reboot();
73 mv_fox 405
      return(MENUQUIT);
33 mv_fox 406
    } else if (driveremovable > 0) {
79 mv_fox 407
      newscreen(2);
56 mv_fox 408
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
61 mv_fox 409
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
42 mv_fox 410
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
73 mv_fox 411
      return(MENUQUIT);
28 mv_fox 412
    }
33 mv_fox 413
    /* if not formatted, propose to format it right away (try to create a directory) */
55 mv_fox 414
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
53 mv_fox 415
    if (mkdir(buff) == 0) {
416
      rmdir(buff);
417
    } else {
28 mv_fox 418
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
79 mv_fox 419
      newscreen(0);
42 mv_fox 420
      list[0] = kittengets(0, 6, list[0]);
421
      list[1] = kittengets(0, 2, list[1]);
56 mv_fox 422
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
61 mv_fox 423
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
73 mv_fox 424
      choice = menuselect(12, -1, 4, list, -1);
425
      if (choice < 0) return(MENUPREV);
426
      if (choice == 1) return(MENUQUIT);
81 mv_fox 427
      video_clear(0x0700, 0, 0);
28 mv_fox 428
      video_movecursor(0, 0);
55 mv_fox 429
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
36 mv_fox 430
      system(buff);
28 mv_fox 431
      continue;
432
    }
33 mv_fox 433
    /* check total disk space */
35 mv_fox 434
    ds = disksize(selecteddrive);
47 mv_fox 435
    if (ds < SVAROG_DISK_REQ) {
56 mv_fox 436
      int y = 9;
79 mv_fox 437
      newscreen(2);
56 mv_fox 438
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! Svarog386 requires a disk of at least %d MiB."), cselecteddrive);
61 mv_fox 439
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 440
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
28 mv_fox 441
      input_getkey();
73 mv_fox 442
      return(MENUQUIT);
28 mv_fox 443
    }
444
    /* is the disk empty? */
79 mv_fox 445
    newscreen(0);
35 mv_fox 446
    if (diskempty(selecteddrive) != 0) {
28 mv_fox 447
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
65 mv_fox 448
      int y = 6;
42 mv_fox 449
      list[0] = kittengets(0, 6, list[0]);
450
      list[1] = kittengets(0, 2, list[1]);
56 mv_fox 451
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. Svarog386 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);
65 mv_fox 452
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 453
      choice = menuselect(++y, -1, 4, list, -1);
454
      if (choice < 0) return(MENUPREV);
455
      if (choice == 1) return(MENUQUIT);
81 mv_fox 456
      video_clear(0x0700, 0, 0);
28 mv_fox 457
      video_movecursor(0, 0);
55 mv_fox 458
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
42 mv_fox 459
      system(buff);
28 mv_fox 460
      continue;
461
    } else {
462
      /* final confirmation */
463
      char *list[] = { "Install Svarog386", "Quit to DOS", NULL};
42 mv_fox 464
      list[0] = kittengets(0, 1, list[0]);
465
      list[1] = kittengets(0, 2, list[1]);
56 mv_fox 466
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of Svarog386 to %c: is about to begin."), cselecteddrive);
467
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
73 mv_fox 468
      choice = menuselect(10, -1, 4, list, -1);
469
      if (choice < 0) return(MENUPREV);
470
      if (choice == 1) return(MENUQUIT);
62 mv_fox 471
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
36 mv_fox 472
      system(buff);
55 mv_fox 473
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
36 mv_fox 474
      mkdir(buff);
475
      return(cselecteddrive);
28 mv_fox 476
    }
477
  }
478
}
479
 
480
 
53 mv_fox 481
/* copy file src into dst, substituting all characters c1 by c2 */
482
static void fcopysub(char *dst, char *src, char c1, char c2) {
483
  FILE *fdd, *fds;
484
  int buff;
485
  fds = fopen(src, "rb");
486
  if (fds == NULL) return;
487
  fdd = fopen(dst, "wb");
488
  if (fdd == NULL) {
489
    fclose(fds);
490
    return;
491
  }
492
  /* */
493
  for (;;) {
494
    buff = fgetc(fds);
495
    if (buff == EOF) break;
496
    if (buff == c1) buff = c2;
497
    fprintf(fdd, "%c", buff);
498
  }
499
  /* close files and return */
500
  fclose(fdd);
501
  fclose(fds);
502
}
503
 
504
 
67 mv_fox 505
static void bootfilesgen(int targetdrv, struct slocales *locales, int cdromdrv) {
28 mv_fox 506
  char buff[128];
507
  FILE *fd;
53 mv_fox 508
  /*** CONFIG.SYS ***/
55 mv_fox 509
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
53 mv_fox 510
  fd = fopen(buff, "wb");
511
  if (fd == NULL) return;
512
  fprintf(fd, "DOS=UMB,HIGH\r\n");
513
  fprintf(fd, "FILES=50\r\n");
514
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVAROG.386\\BIN\\HIMEMX.EXE\r\n", targetdrv);
77 mv_fox 515
  if (strcmp(locales->lang, "EN") == 0) {
516
    strcpy(buff, "command");
517
  } else {
518
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
519
  }
520
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVAROG.386\\BIN\\%s.COM /E:512 /P\r\n", targetdrv, buff);
53 mv_fox 521
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
522
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
523
  fclose(fd);
28 mv_fox 524
  /*** AUTOEXEC.BAT ***/
55 mv_fox 525
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
28 mv_fox 526
  fd = fopen(buff, "wb");
527
  if (fd == NULL) return;
528
  fprintf(fd, "@ECHO OFF\r\n");
36 mv_fox 529
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
530
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVAROG.386\r\n", targetdrv);
49 mv_fox 531
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
67 mv_fox 532
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
53 mv_fox 533
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
534
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
535
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
536
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
28 mv_fox 537
  fprintf(fd, "PROMPT $P$G\r\n");
30 mv_fox 538
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
539
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
56 mv_fox 540
  fprintf(fd, "FDAPM APMDOS\r\n");
28 mv_fox 541
  fprintf(fd, "\r\n");
67 mv_fox 542
  if (locales->egafile > 0) {
55 mv_fox 543
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
67 mv_fox 544
    if (locales->egafile == 1) {
545
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
49 mv_fox 546
    } else {
67 mv_fox 547
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
49 mv_fox 548
    }
67 mv_fox 549
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
74 mv_fox 550
  }
551
  if (locales->keybfile > 0) {
67 mv_fox 552
    if (locales->keybfile == 1) {
553
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBOARD.SYS\r\n", locales->keybcode, locales->codepage, targetdrv);
554
    } else {
555
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBRD%d.SYS\r\n", locales->keybcode, locales->codepage, targetdrv, locales->keybfile);
556
    }
49 mv_fox 557
    fprintf(fd, "\r\n");
558
  }
559
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
560
  fprintf(fd, "\r\n");
561
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
562
  fprintf(fd, "REM CTMOUSE\r\n");
563
  fprintf(fd, "\r\n");
53 mv_fox 564
  fprintf(fd, "ECHO.\r\n");
74 mv_fox 565
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to Svarog386! Type 'HELP' if you need help."));
28 mv_fox 566
  fclose(fd);
53 mv_fox 567
  /*** CREATE DIRECTORY FOR OTHER CONFIGURATION FILES ***/
568
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
569
  mkdir(buff);
570
  /*** FDNPKG.CFG ***/
571
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
572
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
573
  /*** COUNTRY.SYS ***/
574
  /*** PICOTCP ***/
575
  /*** WATTCP ***/
28 mv_fox 576
}
577
 
578
 
53 mv_fox 579
static void installpackages(int targetdrv, int cdromdrv) {
28 mv_fox 580
  char *pkglist[] = {
55 mv_fox 581
    "A:\\UDVD2", /* this one's not part of CORE, hence it's stored right on the floppy */
28 mv_fox 582
    "APPEND",
583
    "ASSIGN",
584
    "ATTRIB",
585
    "CHKDSK",
586
    "CHOICE",
587
    "COMMAND",
588
    "COMP",
589
    "CPIDOS",
590
    "CTMOUSE",
591
    "DEBUG",
592
    "DEFRAG",
593
    "DELTREE",
594
    "DEVLOAD",
595
    "DISKCOMP",
596
    "DISKCOPY",
597
    "DISPLAY",
598
    "DOSFSCK",
599
    "EDIT",
600
    "EDLIN",
601
    "EXE2BIN",
602
    "FC",
603
    "FDAPM",
604
    "FDISK",
605
    "FDNPKG",
606
    "FIND",
607
    "FORMAT",
608
    "HELP",
609
    "HIMEMX",
610
    "KERNEL",
611
    "KEYB",
65 mv_fox 612
    "KEYB_LAY",
28 mv_fox 613
    "LABEL",
614
    "LBACACHE",
615
    "MEM",
616
    "MIRROR",
617
    "MODE",
618
    "MORE",
619
    "MOVE",
620
    "NANSI",
621
    "NLSFUNC",
622
    "PRINT",
623
    "RDISK",
624
    "RECOVER",
625
    "REPLACE",
626
    "SHARE",
627
    "SHSUCDX",
628
    "SORT",
629
    "SWSUBST",
630
    "TREE",
631
    "UNDELETE",
632
    "XCOPY",
633
    NULL
634
  };
30 mv_fox 635
  int i, pkglistlen;
46 mv_fox 636
  char buff[64];
79 mv_fox 637
  newscreen(3);
30 mv_fox 638
  /* count how long the pkg list is */
639
  for (pkglistlen = 0; pkglist[pkglistlen] != NULL; pkglistlen++);
46 mv_fox 640
  /* set DOSDIR and friends */
641
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVAROG.386", targetdrv);
642
  setenv("DOSDIR", buff, 1);
643
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
644
  setenv("TEMP", buff, 1);
30 mv_fox 645
  /* install packages */
28 mv_fox 646
  for (i = 0; pkglist[i] != NULL; i++) {
36 mv_fox 647
    char buff[128];
42 mv_fox 648
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkglist[i]);
36 mv_fox 649
    strcat(buff, "       ");
61 mv_fox 650
    video_putstring(10, 1, COLOR_BODY[mono], buff, -1);
55 mv_fox 651
    if (pkglist[i][1] == ':') {
652
      snprintf(buff, sizeof(buff), "FDINST INSTALL %s.ZIP > NUL", pkglist[i]);
653
    } else {
654
      snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\CORE\\%s.ZIP > NUL", cdromdrv, pkglist[i]);
655
    }
28 mv_fox 656
    system(buff);
657
  }
658
}
659
 
660
 
42 mv_fox 661
static void finalreboot(void) {
56 mv_fox 662
  int y = 9;
79 mv_fox 663
  newscreen(2);
73 mv_fox 664
  y += putstringnls(y, 1, COLOR_BODY[mono], 5, 0, "Svarog386 installation is over. Your computer will reboot now.\nPlease remove the installation disk from your drive.");
61 mv_fox 665
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
42 mv_fox 666
  input_getkey();
667
  reboot();
668
}
669
 
670
 
67 mv_fox 671
static void loadcp(struct slocales *locales) {
42 mv_fox 672
  char buff[64];
67 mv_fox 673
  if (locales->codepage == 437) return;
42 mv_fox 674
  video_movecursor(1, 0);
67 mv_fox 675
  if (locales->egafile == 1) {
676
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
42 mv_fox 677
  } else {
67 mv_fox 678
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
42 mv_fox 679
  }
680
  system(buff);
67 mv_fox 681
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
42 mv_fox 682
  system(buff);
683
  /* below I re-init the video controller - apparently this is required if
65 mv_fox 684
   * I want the new glyph symbols to be actually applied, at least some
685
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
42 mv_fox 686
  {
687
  union REGS r;
688
  r.h.ah = 0x0F; /* get current video mode */
689
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
56 mv_fox 690
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
691
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
42 mv_fox 692
  int86(0x10, &r, &r);
693
  }
694
}
695
 
65 mv_fox 696
/* checks CD drive drv for the presence of the Svarog386 install CD
697
 * returns 0 if found, non-zero otherwise */
69 mv_fox 698
static int checkcd(char drv) {
65 mv_fox 699
  FILE *fd;
700
  char fname[32];
701
  snprintf(fname, sizeof(fname), "%c:\\CORE\\MEM.ZIP", drv);
702
  fd = fopen(fname, "rb");
703
  if (fd == NULL) return(-1);
704
  fclose(fd);
705
  return(0);
69 mv_fox 706
}
65 mv_fox 707
 
708
 
28 mv_fox 709
int main(void) {
67 mv_fox 710
  struct slocales locales;
28 mv_fox 711
  int targetdrv;
53 mv_fox 712
  int cdromdrv;
73 mv_fox 713
  int action;
28 mv_fox 714
 
53 mv_fox 715
  /* find where the cdrom drive is */
716
  cdromdrv = cdrom_findfirst();
717
  if (cdromdrv < 0) {
718
    printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
719
    return(1);
720
  }
721
  cdromdrv += 'A'; /* convert the cdrom 'id' (A=0) to an actual drive letter */
69 mv_fox 722
  if (checkcd(cdromdrv) != 0) {
65 mv_fox 723
    printf("ERROR: SVAROG386 INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
724
    return(1);
69 mv_fox 725
  }
53 mv_fox 726
 
29 mv_fox 727
  /* init screen and detect mono status */
728
  mono = video_init();
729
 
73 mv_fox 730
  kittenopen("INSTALL"); /* load initial NLS support */
731
 
732
 SelectLang:
733
  action = selectlang(&locales); /* welcome to svarog, select your language */
734
  if (action != MENUNEXT) goto Quit;
735
  setenv("LANG", locales.lang, 1);
736
  loadcp(&locales);
737
  kittenclose(); /* reload NLS with new language */
738
  kittenopen("INSTALL"); /* NLS support */
739
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
740
  if (action == MENUQUIT) goto Quit;
741
  if (action == MENUPREV) goto SelectLang;
742
 
743
 WelcomeScreen:
744
  action = welcomescreen(); /* what svarog386 is, ask whether to run live dos or install */
745
  if (action == MENUQUIT) goto Quit;
746
  if (action == MENUPREV) goto SelectLang;
747
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
748
  if (targetdrv == MENUQUIT) goto Quit;
749
  if (targetdrv == MENUPREV) goto WelcomeScreen;
750
  /*askaboutsources();*/ /* IF sources are available, ask if installing with them */
751
  installpackages(targetdrv, cdromdrv);    /* install packages */
752
  bootfilesgen(targetdrv, &locales, cdromdrv); /* generate boot files and other configurations */
753
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
754
  /*netcfg();*/ /* basic networking config */
755
  finalreboot(); /* remove the CD and reboot */
756
 
757
 Quit:
42 mv_fox 758
  kittenclose(); /* close NLS support */
81 mv_fox 759
  video_clear(0x0700, 0, 0);
28 mv_fox 760
  video_movecursor(0, 0);
761
  return(0);
762
}