Subversion Repositories SvarDOS

Rev

Rev 197 | Rev 203 | 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);
197 mateuszvis 312
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that 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
 
200 mateuszvis 386
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
387
static int set_cur_drive(char drv) {
388
  union REGS r;
389
  if ((drv < 'A') || (drv > 'Z')) return(-1);
390
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
391
  r.h.dl = drv - 'A';
392
  int86(0x21, &r, &r);
393
  if (r.h.al < drv - 'A') return(-1);
394
  return(0);
395
}
396
 
397
 
398
/* returns 0 if file exists, non-zero otherwise */
399
static int fileexists(const char *fname) {
400
  FILE *fd;
401
  fd = fopen(fname, "rb");
402
  if (fd == NULL) return(-1);
403
  fclose(fd);
404
  return(0);
405
}
406
 
407
 
28 mv_fox 408
static int preparedrive(void) {
33 mv_fox 409
  int driveremovable;
36 mv_fox 410
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
411
  int cselecteddrive;
35 mv_fox 412
  int ds;
73 mv_fox 413
  int choice;
56 mv_fox 414
  char buff[1024];
36 mv_fox 415
  cselecteddrive = 'A' + selecteddrive - 1;
28 mv_fox 416
  for (;;) {
33 mv_fox 417
    driveremovable = isdriveremovable(selecteddrive);
418
    if (driveremovable < 0) {
49 mv_fox 419
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
79 mv_fox 420
      newscreen(0);
42 mv_fox 421
      list[0] = kittengets(0, 3, list[0]);
422
      list[1] = kittengets(0, 4, list[1]);
423
      list[2] = kittengets(0, 2, list[2]);
190 mateuszvis 424
      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 425
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
67 mv_fox 426
      switch (menuselect(14, -1, 5, list, -1)) {
33 mv_fox 427
        case 0:
428
          system("FDISK /AUTO");
429
          break;
430
        case 1:
81 mv_fox 431
          video_clear(0x0700, 0, 0);
33 mv_fox 432
          video_movecursor(0, 0);
433
          system("FDISK");
434
          break;
73 mv_fox 435
        case 2:
436
          return(MENUQUIT);
56 mv_fox 437
        default:
33 mv_fox 438
          return(-1);
439
      }
113 mv_fox 440
      /* write a temporary MBR which only skips the drive (in case BIOS would
441
       * try to boot off the not-yet-ready C: disk) */
442
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */
79 mv_fox 443
      newscreen(2);
61 mv_fox 444
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
42 mv_fox 445
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
33 mv_fox 446
      input_getkey();
28 mv_fox 447
      reboot();
73 mv_fox 448
      return(MENUQUIT);
33 mv_fox 449
    } else if (driveremovable > 0) {
79 mv_fox 450
      newscreen(2);
56 mv_fox 451
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
61 mv_fox 452
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
42 mv_fox 453
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
73 mv_fox 454
      return(MENUQUIT);
28 mv_fox 455
    }
33 mv_fox 456
    /* if not formatted, propose to format it right away (try to create a directory) */
55 mv_fox 457
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
53 mv_fox 458
    if (mkdir(buff) == 0) {
459
      rmdir(buff);
460
    } else {
28 mv_fox 461
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
79 mv_fox 462
      newscreen(0);
42 mv_fox 463
      list[0] = kittengets(0, 6, list[0]);
464
      list[1] = kittengets(0, 2, list[1]);
56 mv_fox 465
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
61 mv_fox 466
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
73 mv_fox 467
      choice = menuselect(12, -1, 4, list, -1);
468
      if (choice < 0) return(MENUPREV);
469
      if (choice == 1) return(MENUQUIT);
81 mv_fox 470
      video_clear(0x0700, 0, 0);
28 mv_fox 471
      video_movecursor(0, 0);
190 mateuszvis 472
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
36 mv_fox 473
      system(buff);
28 mv_fox 474
      continue;
475
    }
33 mv_fox 476
    /* check total disk space */
35 mv_fox 477
    ds = disksize(selecteddrive);
190 mateuszvis 478
    if (ds < SVARDOS_DISK_REQ) {
56 mv_fox 479
      int y = 9;
79 mv_fox 480
      newscreen(2);
190 mateuszvis 481
      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 482
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 483
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
28 mv_fox 484
      input_getkey();
73 mv_fox 485
      return(MENUQUIT);
28 mv_fox 486
    }
487
    /* is the disk empty? */
79 mv_fox 488
    newscreen(0);
35 mv_fox 489
    if (diskempty(selecteddrive) != 0) {
28 mv_fox 490
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
65 mv_fox 491
      int y = 6;
42 mv_fox 492
      list[0] = kittengets(0, 6, list[0]);
493
      list[1] = kittengets(0, 2, list[1]);
190 mateuszvis 494
      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 495
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 496
      choice = menuselect(++y, -1, 4, list, -1);
497
      if (choice < 0) return(MENUPREV);
498
      if (choice == 1) return(MENUQUIT);
81 mv_fox 499
      video_clear(0x0700, 0, 0);
28 mv_fox 500
      video_movecursor(0, 0);
190 mateuszvis 501
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
42 mv_fox 502
      system(buff);
28 mv_fox 503
      continue;
504
    } else {
505
      /* final confirmation */
190 mateuszvis 506
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
42 mv_fox 507
      list[0] = kittengets(0, 1, list[0]);
508
      list[1] = kittengets(0, 2, list[1]);
190 mateuszvis 509
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
56 mv_fox 510
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
73 mv_fox 511
      choice = menuselect(10, -1, 4, list, -1);
512
      if (choice < 0) return(MENUPREV);
513
      if (choice == 1) return(MENUQUIT);
62 mv_fox 514
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
36 mv_fox 515
      system(buff);
111 mv_fox 516
      system("FDISK /MBR");
55 mv_fox 517
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
36 mv_fox 518
      mkdir(buff);
519
      return(cselecteddrive);
28 mv_fox 520
    }
521
  }
522
}
523
 
524
 
53 mv_fox 525
/* copy file src into dst, substituting all characters c1 by c2 */
192 mateuszvis 526
static void fcopysub(const char *dst, const char *src, char c1, char c2) {
53 mv_fox 527
  FILE *fdd, *fds;
528
  int buff;
529
  fds = fopen(src, "rb");
530
  if (fds == NULL) return;
531
  fdd = fopen(dst, "wb");
532
  if (fdd == NULL) {
533
    fclose(fds);
534
    return;
535
  }
536
  /* */
537
  for (;;) {
538
    buff = fgetc(fds);
539
    if (buff == EOF) break;
540
    if (buff == c1) buff = c2;
541
    fprintf(fdd, "%c", buff);
542
  }
543
  /* close files and return */
544
  fclose(fdd);
545
  fclose(fds);
546
}
547
 
548
 
192 mateuszvis 549
static void bootfilesgen(char targetdrv, const struct slocales *locales, char cdromdrv) {
28 mv_fox 550
  char buff[128];
96 mv_fox 551
  char buff2[16];
552
  char buff3[16];
28 mv_fox 553
  FILE *fd;
53 mv_fox 554
  /*** CONFIG.SYS ***/
55 mv_fox 555
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
53 mv_fox 556
  fd = fopen(buff, "wb");
557
  if (fd == NULL) return;
101 mv_fox 558
  fprintf(fd, "DOS=UMB,HIGH\r\n"
559
              "LASTDRIVE=Z\r\n"
560
              "FILES=50\r\n");
190 mateuszvis 561
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVARDOS\\BIN\\HIMEMX.EXE\r\n", targetdrv);
77 mv_fox 562
  if (strcmp(locales->lang, "EN") == 0) {
95 mv_fox 563
    strcpy(buff, "COMMAND");
77 mv_fox 564
  } else {
565
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
566
  }
190 mateuszvis 567
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", targetdrv, buff);
53 mv_fox 568
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
569
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
570
  fclose(fd);
28 mv_fox 571
  /*** AUTOEXEC.BAT ***/
55 mv_fox 572
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
28 mv_fox 573
  fd = fopen(buff, "wb");
574
  if (fd == NULL) return;
575
  fprintf(fd, "@ECHO OFF\r\n");
36 mv_fox 576
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
190 mateuszvis 577
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVARDOS\r\n", targetdrv);
49 mv_fox 578
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
67 mv_fox 579
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
53 mv_fox 580
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
581
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
582
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
583
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
28 mv_fox 584
  fprintf(fd, "PROMPT $P$G\r\n");
30 mv_fox 585
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
586
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
56 mv_fox 587
  fprintf(fd, "FDAPM APMDOS\r\n");
28 mv_fox 588
  fprintf(fd, "\r\n");
67 mv_fox 589
  if (locales->egafile > 0) {
55 mv_fox 590
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
67 mv_fox 591
    if (locales->egafile == 1) {
190 mateuszvis 592
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVARDOS\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
49 mv_fox 593
    } else {
190 mateuszvis 594
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVARDOS\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
49 mv_fox 595
    }
67 mv_fox 596
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
74 mv_fox 597
  }
598
  if (locales->keybfile > 0) {
67 mv_fox 599
    if (locales->keybfile == 1) {
96 mv_fox 600
      snprintf(buff2, sizeof(buff2), "KEYBOARD.SYS");
67 mv_fox 601
    } else {
96 mv_fox 602
      snprintf(buff2, sizeof(buff2), "KEYBRD%d.SYS", locales->keybfile);
67 mv_fox 603
    }
98 mv_fox 604
    if (locales->keybid == 0) {
96 mv_fox 605
      buff3[0] = 0;
606
    } else {
607
      snprintf(buff3, sizeof(buff3), " /ID:%d", locales->keybid);
608
    }
190 mateuszvis 609
    fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVARDOS\\BIN\\%s%s\r\n", locales->keybcode, locales->codepage, targetdrv, buff2, buff3);
49 mv_fox 610
    fprintf(fd, "\r\n");
611
  }
612
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
613
  fprintf(fd, "\r\n");
614
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
615
  fprintf(fd, "REM CTMOUSE\r\n");
616
  fprintf(fd, "\r\n");
53 mv_fox 617
  fprintf(fd, "ECHO.\r\n");
190 mateuszvis 618
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
28 mv_fox 619
  fclose(fd);
200 mateuszvis 620
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
621
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM", targetdrv);
622
  mkdir(buff);
53 mv_fox 623
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
624
  mkdir(buff);
625
  /*** FDNPKG.CFG ***/
626
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
627
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
628
  /*** COUNTRY.SYS ***/
629
  /*** PICOTCP ***/
630
  /*** WATTCP ***/
28 mv_fox 631
}
632
 
633
 
192 mateuszvis 634
static int installpackages(char targetdrv, char cdromdrv) {
635
  char pkglist[512];
30 mv_fox 636
  int i, pkglistlen;
192 mateuszvis 637
  size_t pkglistflen;
46 mv_fox 638
  char buff[64];
192 mateuszvis 639
  FILE *fd;
640
  char *pkgptr;
79 mv_fox 641
  newscreen(3);
192 mateuszvis 642
  /* load pkg list */
643
  fd = fopen("install.lst", "rb");
644
  if (fd == NULL) {
645
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
646
    input_getkey();
647
    return(-1);
648
  }
649
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
650
  fclose(fd);
651
  if (pkglistflen == sizeof(pkglist)) {
652
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
653
    input_getkey();
654
    return(-1);
655
  }
656
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
657
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
658
  pkglistlen = 0;
659
  for (i = 0; i < pkglistflen; i++) {
660
    switch (pkglist[i]) {
661
      case '\n':
662
        pkglistlen++;
663
        /* FALLTHRU */
664
      case '\r':
665
        pkglist[i] = 0;
666
        break;
667
    }
668
  }
200 mateuszvis 669
  /* set DOSDIR, TEMP, COMSPEC and FDNPKG.CFG */
190 mateuszvis 670
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVARDOS", targetdrv);
46 mv_fox 671
  setenv("DOSDIR", buff, 1);
672
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
673
  setenv("TEMP", buff, 1);
200 mateuszvis 674
  snprintf(buff, sizeof(buff), "%c:\\COMMAND.COM", targetdrv);
675
  setenv("COMSPEC", buff, 1);
676
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
677
  setenv("FDNPKG.CFG", buff, 1);
678
  /* copy pkginst to the new drive so it is not read from floppy each time I need it */
679
  snprintf(buff, sizeof(buff), "COPY %c:\\FDINST.EXE %c:\\ > NUL", cdromdrv, targetdrv);
680
  system(buff);
681
  /* change current drive to target so I use the on-hdd fdinst from now on */
682
  if (set_cur_drive(targetdrv) != 0) {
683
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: CHANGING DRIVE TO TARGET FAILED", -1);
684
    input_getkey();
685
    return(-1);
686
  }
30 mv_fox 687
  /* install packages */
192 mateuszvis 688
  pkgptr = pkglist;
689
  for (i = 0;; i++) {
690
    char buff[64];
691
    /* move forward to nearest entry or end of list */
692
    while (*pkgptr == 0) pkgptr++;
693
    if (*pkgptr == 0xff) break;
694
    /* install the package */
695
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
36 mv_fox 696
    strcat(buff, "       ");
192 mateuszvis 697
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
200 mateuszvis 698
    /* wait for new diskette if package not found */
699
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", cdromdrv, pkgptr);
700
    while (fileexists(buff) != 0) {
701
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
702
      input_getkey();
703
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
704
    }
705
    /* proceed with package install */
192 mateuszvis 706
    snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\%s.ZIP > NUL", cdromdrv, pkgptr);
707
    if (system(buff) != 0) {
200 mateuszvis 708
      video_putstring(12, 30, COLOR_BODY[mono], "ERROR: PKG INSTALL FAILED", -1);
192 mateuszvis 709
      input_getkey();
710
      return(-1);
55 mv_fox 711
    }
192 mateuszvis 712
    /* jump to next entry or end of list */
713
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
714
    if (*pkgptr == 0xff) break;
28 mv_fox 715
  }
192 mateuszvis 716
  return(0);
28 mv_fox 717
}
718
 
719
 
42 mv_fox 720
static void finalreboot(void) {
56 mv_fox 721
  int y = 9;
79 mv_fox 722
  newscreen(2);
190 mateuszvis 723
  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 724
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
42 mv_fox 725
  input_getkey();
726
  reboot();
727
}
728
 
729
 
192 mateuszvis 730
static void loadcp(const struct slocales *locales) {
42 mv_fox 731
  char buff[64];
67 mv_fox 732
  if (locales->codepage == 437) return;
42 mv_fox 733
  video_movecursor(1, 0);
67 mv_fox 734
  if (locales->egafile == 1) {
735
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
42 mv_fox 736
  } else {
67 mv_fox 737
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
42 mv_fox 738
  }
739
  system(buff);
67 mv_fox 740
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
42 mv_fox 741
  system(buff);
742
  /* below I re-init the video controller - apparently this is required if
65 mv_fox 743
   * I want the new glyph symbols to be actually applied, at least some
744
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
42 mv_fox 745
  {
746
  union REGS r;
747
  r.h.ah = 0x0F; /* get current video mode */
748
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
56 mv_fox 749
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
750
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
42 mv_fox 751
  int86(0x10, &r, &r);
752
  }
753
}
754
 
200 mateuszvis 755
 
193 mateuszvis 756
/* checks that drive drv contains SvarDOS packages
65 mv_fox 757
 * returns 0 if found, non-zero otherwise */
193 mateuszvis 758
static int checkinstsrc(char drv) {
759
  char fname[16];
760
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
200 mateuszvis 761
  return(fileexists(fname));
69 mv_fox 762
}
65 mv_fox 763
 
764
 
28 mv_fox 765
int main(void) {
67 mv_fox 766
  struct slocales locales;
28 mv_fox 767
  int targetdrv;
193 mateuszvis 768
  int sourcedrv;
73 mv_fox 769
  int action;
28 mv_fox 770
 
193 mateuszvis 771
  /* am I running in install-from-floppy mode? */
772
  if (checkinstsrc('A') == 0) {
773
    sourcedrv = 'A';
774
  } else { /* otherwise find where the cdrom drive is */
775
    sourcedrv = cdrom_findfirst();
776
    if (sourcedrv < 0) {
777
      printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
778
      return(1);
779
    }
780
    sourcedrv += 'A'; /* convert the source drive 'id' (A=0) to an actual drive letter */
781
    if (checkinstsrc(sourcedrv) != 0) {
782
      printf("ERROR: SVARDOS INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
783
      return(1);
784
    }
53 mv_fox 785
  }
786
 
29 mv_fox 787
  /* init screen and detect mono status */
788
  mono = video_init();
789
 
73 mv_fox 790
  kittenopen("INSTALL"); /* load initial NLS support */
791
 
792
 SelectLang:
190 mateuszvis 793
  action = selectlang(&locales); /* welcome to svardos, select your language */
73 mv_fox 794
  if (action != MENUNEXT) goto Quit;
795
  setenv("LANG", locales.lang, 1);
796
  loadcp(&locales);
797
  kittenclose(); /* reload NLS with new language */
798
  kittenopen("INSTALL"); /* NLS support */
799
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
800
  if (action == MENUQUIT) goto Quit;
801
  if (action == MENUPREV) goto SelectLang;
802
 
803
 WelcomeScreen:
190 mateuszvis 804
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
73 mv_fox 805
  if (action == MENUQUIT) goto Quit;
806
  if (action == MENUPREV) goto SelectLang;
807
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
808
  if (targetdrv == MENUQUIT) goto Quit;
809
  if (targetdrv == MENUPREV) goto WelcomeScreen;
200 mateuszvis 810
  bootfilesgen(targetdrv, &locales, sourcedrv); /* generate boot files and other configurations */
193 mateuszvis 811
  if (installpackages(targetdrv, sourcedrv) != 0) goto Quit;    /* install packages */
73 mv_fox 812
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
813
  /*netcfg();*/ /* basic networking config */
814
  finalreboot(); /* remove the CD and reboot */
815
 
816
 Quit:
42 mv_fox 817
  kittenclose(); /* close NLS support */
81 mv_fox 818
  video_clear(0x0700, 0, 0);
28 mv_fox 819
  video_movecursor(0, 0);
820
  return(0);
821
}