Subversion Repositories SvarDOS

Rev

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