Subversion Repositories SvarDOS

Rev

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