Subversion Repositories SvarDOS

Rev

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