Subversion Repositories SvarDOS

Rev

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