Subversion Repositories SvarDOS

Rev

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

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