Subversion Repositories SvarDOS

Rev

Rev 203 | Rev 277 | 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
206 mateuszvis 3
 * Copyright (C) 2021 Mateusz Viste
4
 *
190 mateuszvis 5
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
42 mv_fox 6
 *
190 mateuszvis 7
 * COPYRIGHT (C) 2016-2021 MATEUSZ VISTE, ALL RIGHTS RESERVED.
94 mv_fox 8
 *
190 mateuszvis 9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
94 mv_fox 15
 *
190 mateuszvis 16
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
94 mv_fox 18
 *
190 mateuszvis 19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
94 mv_fox 26
 *
190 mateuszvis 27
 * http://svardos.osdn.io
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
 
190 mateuszvis 56
/* how much disk space does SvarDOS require (in MiB) */
57
#define SVARDOS_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;
190 mateuszvis 192
  msg = kittengets(0, 0, "SVARDOS 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",
133 mv_fox 236
    "German",
119 mv_fox 237
    "Italian",
67 mv_fox 238
    "Polish",
116 mv_fox 239
    "Russian",
123 mv_fox 240
    "Slovene",
128 mv_fox 241
    "Swedish",
67 mv_fox 242
    "Turkish",
28 mv_fox 243
    NULL
244
  };
245
 
79 mv_fox 246
  newscreen(1);
190 mateuszvis 247
  msg = kittengets(1, 0, "Welcome to SvarDOS");
42 mv_fox 248
  x = 40 - (strlen(msg) >> 1);
56 mv_fox 249
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
42 mv_fox 250
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
49 mv_fox 251
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
133 mv_fox 252
  choice = menuselect(11, -1, 11, langlist, -1);
73 mv_fox 253
  if (choice < 0) return(MENUPREV);
67 mv_fox 254
  /* populate locales with default values */
255
  memset(locales, 0, sizeof(struct slocales));
256
  switch (choice) {
257
    case 1:
258
      strcpy(locales->lang, "FR");
259
      locales->keyboff = OFFLOC_FR;
260
      locales->keyblen = OFFLEN_FR;
261
      break;
262
    case 2:
133 mv_fox 263
      strcpy(locales->lang, "DE");
264
      locales->keyboff = OFFLOC_DE;
265
      locales->keyblen = OFFLEN_DE;
266
      break;
267
    case 3:
119 mv_fox 268
      strcpy(locales->lang, "IT");
269
      locales->keyboff = OFFLOC_IT;
270
      locales->keyblen = OFFLEN_IT;
271
      break;
133 mv_fox 272
    case 4:
67 mv_fox 273
      strcpy(locales->lang, "PL");
274
      locales->keyboff = OFFLOC_PL;
275
      locales->keyblen = OFFLEN_PL;
276
      break;
133 mv_fox 277
    case 5:
116 mv_fox 278
      strcpy(locales->lang, "RU");
279
      locales->keyboff = OFFLOC_RU;
280
      locales->keyblen = OFFLEN_RU;
281
      break;
133 mv_fox 282
    case 6:
123 mv_fox 283
      strcpy(locales->lang, "SI");
284
      locales->keyboff = OFFLOC_SI;
285
      locales->keyblen = OFFLEN_SI;
286
      break;
133 mv_fox 287
    case 7:
128 mv_fox 288
      strcpy(locales->lang, "SV");
289
      locales->keyboff = OFFLOC_SV;
290
      locales->keyblen = OFFLEN_SV;
291
      break;
133 mv_fox 292
    case 8:
67 mv_fox 293
      strcpy(locales->lang, "TR");
294
      locales->keyboff = OFFLOC_TR;
295
      locales->keyblen = OFFLEN_TR;
296
      break;
297
    default:
298
      strcpy(locales->lang, "EN");
299
      locales->keyboff = 0;
300
      locales->keyblen = OFFCOUNT;
301
      break;
302
  }
96 mv_fox 303
  /* populate the slocales struct accordingly to the keyboff member */
304
  kblay2slocal(locales);
67 mv_fox 305
  /* */
73 mv_fox 306
  return(MENUNEXT);
28 mv_fox 307
}
308
 
309
 
67 mv_fox 310
static int selectkeyb(struct slocales *locales) {
96 mv_fox 311
  int menuheight, choice;
312
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
79 mv_fox 313
  newscreen(0);
197 mateuszvis 314
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "SvarDOS supports different keyboard layouts. Choose the keyboard layout that you want.");
96 mv_fox 315
  menuheight = locales->keyblen + 2;
67 mv_fox 316
  if (menuheight > 13) menuheight = 13;
96 mv_fox 317
  choice = menuselect(10, -1, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
318
  if (choice < 0) return(MENUPREV);
319
  /* (re)load the keyboard layout & codepage setup */
320
  locales->keyboff += choice;
321
  kblay2slocal(locales);
73 mv_fox 322
  return(MENUNEXT);
67 mv_fox 323
}
324
 
325
 
28 mv_fox 326
/* returns 0 if installation must proceed, non-zero otherwise */
327
static int welcomescreen(void) {
73 mv_fox 328
  int c;
190 mateuszvis 329
  char *choice[] = {"Install SvarDOS to disk", "Quit to DOS", NULL};
42 mv_fox 330
  choice[0] = kittengets(0, 1, choice[0]);
331
  choice[1] = kittengets(0, 2, choice[1]);
79 mv_fox 332
  newscreen(0);
190 mateuszvis 333
  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 334
  c = menuselect(13, -1, 4, choice, -1);
335
  if (c < 0) return(MENUPREV);
336
  if (c == 0) return(MENUNEXT);
337
  return(MENUQUIT);
28 mv_fox 338
}
339
 
340
 
33 mv_fox 341
/* returns 1 if drive is removable, 0 if not, -1 on error */
342
static int isdriveremovable(int drv) {
28 mv_fox 343
  union REGS r;
33 mv_fox 344
  r.x.ax = 0x4408;
345
  r.h.bl = drv;
28 mv_fox 346
  int86(0x21, &r, &r);
33 mv_fox 347
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
348
  if (r.x.cflag != 0) return(-1);
349
  if (r.x.ax == 0) return(1);
350
  return(0);
28 mv_fox 351
}
352
 
353
 
35 mv_fox 354
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
355
static int disksize(int drv) {
28 mv_fox 356
  long res;
357
  union REGS r;
358
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
359
  r.h.dl = drv;
360
  int86(0x21, &r, &r);
361
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
49 mv_fox 362
  res = r.x.ax;  /* sectors per cluster */
363
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
364
  res *= r.x.cx; /* bytes per sector */
365
  res >>= 20;    /* convert bytes to MiB */
366
  return(res);
35 mv_fox 367
}
368
 
369
 
370
/* returns 0 if disk is empty, non-zero otherwise */
371
static int diskempty(int drv) {
372
  unsigned int rc;
373
  int res;
374
  char buff[8];
375
  struct find_t fileinfo;
55 mv_fox 376
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
35 mv_fox 377
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
378
  if (rc == 0) {
379
    res = 1; /* call successfull means disk is not empty */
28 mv_fox 380
  } else {
35 mv_fox 381
    res = 0;
28 mv_fox 382
  }
35 mv_fox 383
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
28 mv_fox 384
  return(res);
385
}
386
 
387
 
200 mateuszvis 388
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
389
static int set_cur_drive(char drv) {
390
  union REGS r;
391
  if ((drv < 'A') || (drv > 'Z')) return(-1);
392
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
393
  r.h.dl = drv - 'A';
394
  int86(0x21, &r, &r);
395
  if (r.h.al < drv - 'A') return(-1);
396
  return(0);
397
}
398
 
399
 
400
/* returns 0 if file exists, non-zero otherwise */
401
static int fileexists(const char *fname) {
402
  FILE *fd;
403
  fd = fopen(fname, "rb");
404
  if (fd == NULL) return(-1);
405
  fclose(fd);
406
  return(0);
407
}
408
 
409
 
28 mv_fox 410
static int preparedrive(void) {
33 mv_fox 411
  int driveremovable;
36 mv_fox 412
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
413
  int cselecteddrive;
35 mv_fox 414
  int ds;
73 mv_fox 415
  int choice;
56 mv_fox 416
  char buff[1024];
36 mv_fox 417
  cselecteddrive = 'A' + selecteddrive - 1;
28 mv_fox 418
  for (;;) {
33 mv_fox 419
    driveremovable = isdriveremovable(selecteddrive);
420
    if (driveremovable < 0) {
49 mv_fox 421
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
79 mv_fox 422
      newscreen(0);
42 mv_fox 423
      list[0] = kittengets(0, 3, list[0]);
424
      list[1] = kittengets(0, 4, list[1]);
425
      list[2] = kittengets(0, 2, list[2]);
190 mateuszvis 426
      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 427
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
67 mv_fox 428
      switch (menuselect(14, -1, 5, list, -1)) {
33 mv_fox 429
        case 0:
430
          system("FDISK /AUTO");
431
          break;
432
        case 1:
81 mv_fox 433
          video_clear(0x0700, 0, 0);
33 mv_fox 434
          video_movecursor(0, 0);
435
          system("FDISK");
436
          break;
73 mv_fox 437
        case 2:
438
          return(MENUQUIT);
56 mv_fox 439
        default:
33 mv_fox 440
          return(-1);
441
      }
113 mv_fox 442
      /* write a temporary MBR which only skips the drive (in case BIOS would
443
       * try to boot off the not-yet-ready C: disk) */
444
      system("FDISK /AMBR"); /* writes BOOT.MBR into actual MBR */
79 mv_fox 445
      newscreen(2);
61 mv_fox 446
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
42 mv_fox 447
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
33 mv_fox 448
      input_getkey();
28 mv_fox 449
      reboot();
73 mv_fox 450
      return(MENUQUIT);
33 mv_fox 451
    } else if (driveremovable > 0) {
79 mv_fox 452
      newscreen(2);
56 mv_fox 453
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
61 mv_fox 454
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
42 mv_fox 455
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
73 mv_fox 456
      return(MENUQUIT);
28 mv_fox 457
    }
33 mv_fox 458
    /* if not formatted, propose to format it right away (try to create a directory) */
55 mv_fox 459
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
53 mv_fox 460
    if (mkdir(buff) == 0) {
461
      rmdir(buff);
462
    } else {
28 mv_fox 463
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
79 mv_fox 464
      newscreen(0);
42 mv_fox 465
      list[0] = kittengets(0, 6, list[0]);
466
      list[1] = kittengets(0, 2, list[1]);
56 mv_fox 467
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
61 mv_fox 468
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
73 mv_fox 469
      choice = menuselect(12, -1, 4, list, -1);
470
      if (choice < 0) return(MENUPREV);
471
      if (choice == 1) return(MENUQUIT);
81 mv_fox 472
      video_clear(0x0700, 0, 0);
28 mv_fox 473
      video_movecursor(0, 0);
190 mateuszvis 474
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
36 mv_fox 475
      system(buff);
28 mv_fox 476
      continue;
477
    }
33 mv_fox 478
    /* check total disk space */
35 mv_fox 479
    ds = disksize(selecteddrive);
190 mateuszvis 480
    if (ds < SVARDOS_DISK_REQ) {
56 mv_fox 481
      int y = 9;
79 mv_fox 482
      newscreen(2);
190 mateuszvis 483
      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 484
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 485
      putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
28 mv_fox 486
      input_getkey();
73 mv_fox 487
      return(MENUQUIT);
28 mv_fox 488
    }
489
    /* is the disk empty? */
79 mv_fox 490
    newscreen(0);
35 mv_fox 491
    if (diskempty(selecteddrive) != 0) {
28 mv_fox 492
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
65 mv_fox 493
      int y = 6;
42 mv_fox 494
      list[0] = kittengets(0, 6, list[0]);
495
      list[1] = kittengets(0, 2, list[1]);
190 mateuszvis 496
      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 497
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
73 mv_fox 498
      choice = menuselect(++y, -1, 4, list, -1);
499
      if (choice < 0) return(MENUPREV);
500
      if (choice == 1) return(MENUQUIT);
81 mv_fox 501
      video_clear(0x0700, 0, 0);
28 mv_fox 502
      video_movecursor(0, 0);
190 mateuszvis 503
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
42 mv_fox 504
      system(buff);
28 mv_fox 505
      continue;
506
    } else {
507
      /* final confirmation */
190 mateuszvis 508
      char *list[] = { "Install SvarDOS", "Quit to DOS", NULL};
42 mv_fox 509
      list[0] = kittengets(0, 1, list[0]);
510
      list[1] = kittengets(0, 2, list[1]);
190 mateuszvis 511
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of SvarDOS to %c: is about to begin."), cselecteddrive);
56 mv_fox 512
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
73 mv_fox 513
      choice = menuselect(10, -1, 4, list, -1);
514
      if (choice < 0) return(MENUPREV);
515
      if (choice == 1) return(MENUQUIT);
62 mv_fox 516
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
36 mv_fox 517
      system(buff);
111 mv_fox 518
      system("FDISK /MBR");
55 mv_fox 519
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
36 mv_fox 520
      mkdir(buff);
521
      return(cselecteddrive);
28 mv_fox 522
    }
523
  }
524
}
525
 
526
 
53 mv_fox 527
/* copy file src into dst, substituting all characters c1 by c2 */
192 mateuszvis 528
static void fcopysub(const char *dst, const char *src, char c1, char c2) {
53 mv_fox 529
  FILE *fdd, *fds;
530
  int buff;
531
  fds = fopen(src, "rb");
532
  if (fds == NULL) return;
533
  fdd = fopen(dst, "wb");
534
  if (fdd == NULL) {
535
    fclose(fds);
536
    return;
537
  }
538
  /* */
539
  for (;;) {
540
    buff = fgetc(fds);
541
    if (buff == EOF) break;
542
    if (buff == c1) buff = c2;
543
    fprintf(fdd, "%c", buff);
544
  }
545
  /* close files and return */
546
  fclose(fdd);
547
  fclose(fds);
548
}
549
 
550
 
192 mateuszvis 551
static void bootfilesgen(char targetdrv, const struct slocales *locales, char cdromdrv) {
28 mv_fox 552
  char buff[128];
96 mv_fox 553
  char buff2[16];
554
  char buff3[16];
28 mv_fox 555
  FILE *fd;
53 mv_fox 556
  /*** CONFIG.SYS ***/
55 mv_fox 557
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
53 mv_fox 558
  fd = fopen(buff, "wb");
559
  if (fd == NULL) return;
101 mv_fox 560
  fprintf(fd, "DOS=UMB,HIGH\r\n"
561
              "LASTDRIVE=Z\r\n"
562
              "FILES=50\r\n");
190 mateuszvis 563
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVARDOS\\BIN\\HIMEMX.EXE\r\n", targetdrv);
77 mv_fox 564
  if (strcmp(locales->lang, "EN") == 0) {
95 mv_fox 565
    strcpy(buff, "COMMAND");
77 mv_fox 566
  } else {
567
    snprintf(buff, sizeof(buff), "CMD-%s", locales->lang);
568
  }
190 mateuszvis 569
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVARDOS\\BIN\\%s.COM /E:512 /P\r\n", targetdrv, buff);
53 mv_fox 570
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
571
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
572
  fclose(fd);
28 mv_fox 573
  /*** AUTOEXEC.BAT ***/
55 mv_fox 574
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
28 mv_fox 575
  fd = fopen(buff, "wb");
576
  if (fd == NULL) return;
577
  fprintf(fd, "@ECHO OFF\r\n");
36 mv_fox 578
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
190 mateuszvis 579
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVARDOS\r\n", targetdrv);
49 mv_fox 580
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
67 mv_fox 581
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
53 mv_fox 582
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
583
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
584
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
585
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
28 mv_fox 586
  fprintf(fd, "PROMPT $P$G\r\n");
30 mv_fox 587
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
588
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
56 mv_fox 589
  fprintf(fd, "FDAPM APMDOS\r\n");
28 mv_fox 590
  fprintf(fd, "\r\n");
67 mv_fox 591
  if (locales->egafile > 0) {
55 mv_fox 592
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
67 mv_fox 593
    if (locales->egafile == 1) {
190 mateuszvis 594
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVARDOS\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
49 mv_fox 595
    } else {
190 mateuszvis 596
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVARDOS\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
49 mv_fox 597
    }
67 mv_fox 598
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
74 mv_fox 599
  }
600
  if (locales->keybfile > 0) {
67 mv_fox 601
    if (locales->keybfile == 1) {
96 mv_fox 602
      snprintf(buff2, sizeof(buff2), "KEYBOARD.SYS");
67 mv_fox 603
    } else {
96 mv_fox 604
      snprintf(buff2, sizeof(buff2), "KEYBRD%d.SYS", locales->keybfile);
67 mv_fox 605
    }
98 mv_fox 606
    if (locales->keybid == 0) {
96 mv_fox 607
      buff3[0] = 0;
608
    } else {
609
      snprintf(buff3, sizeof(buff3), " /ID:%d", locales->keybid);
610
    }
190 mateuszvis 611
    fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVARDOS\\BIN\\%s%s\r\n", locales->keybcode, locales->codepage, targetdrv, buff2, buff3);
49 mv_fox 612
    fprintf(fd, "\r\n");
613
  }
614
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
615
  fprintf(fd, "\r\n");
616
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
617
  fprintf(fd, "REM CTMOUSE\r\n");
618
  fprintf(fd, "\r\n");
53 mv_fox 619
  fprintf(fd, "ECHO.\r\n");
190 mateuszvis 620
  fprintf(fd, "ECHO %s\r\n", kittengets(6, 0, "Welcome to SvarDOS! Type 'HELP' if you need help."));
28 mv_fox 621
  fclose(fd);
200 mateuszvis 622
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
623
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM", targetdrv);
624
  mkdir(buff);
53 mv_fox 625
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
626
  mkdir(buff);
627
  /*** FDNPKG.CFG ***/
628
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
629
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
630
  /*** COUNTRY.SYS ***/
631
  /*** PICOTCP ***/
632
  /*** WATTCP ***/
28 mv_fox 633
}
634
 
635
 
192 mateuszvis 636
static int installpackages(char targetdrv, char cdromdrv) {
637
  char pkglist[512];
30 mv_fox 638
  int i, pkglistlen;
192 mateuszvis 639
  size_t pkglistflen;
46 mv_fox 640
  char buff[64];
192 mateuszvis 641
  FILE *fd;
642
  char *pkgptr;
79 mv_fox 643
  newscreen(3);
192 mateuszvis 644
  /* load pkg list */
645
  fd = fopen("install.lst", "rb");
646
  if (fd == NULL) {
647
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST NOT FOUND", -1);
648
    input_getkey();
649
    return(-1);
650
  }
651
  pkglistflen = fread(pkglist, 1, sizeof(pkglist), fd);
652
  fclose(fd);
653
  if (pkglistflen == sizeof(pkglist)) {
654
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: INSTALL.LST TOO LARGE", -1);
655
    input_getkey();
656
    return(-1);
657
  }
658
  pkglist[pkglistflen] = 0xff; /* mark the end of list */
659
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
660
  pkglistlen = 0;
661
  for (i = 0; i < pkglistflen; i++) {
662
    switch (pkglist[i]) {
663
      case '\n':
664
        pkglistlen++;
665
        /* FALLTHRU */
666
      case '\r':
667
        pkglist[i] = 0;
668
        break;
669
    }
670
  }
200 mateuszvis 671
  /* set DOSDIR, TEMP, COMSPEC and FDNPKG.CFG */
190 mateuszvis 672
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVARDOS", targetdrv);
46 mv_fox 673
  setenv("DOSDIR", buff, 1);
674
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
675
  setenv("TEMP", buff, 1);
200 mateuszvis 676
  snprintf(buff, sizeof(buff), "%c:\\COMMAND.COM", targetdrv);
677
  setenv("COMSPEC", buff, 1);
678
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
679
  setenv("FDNPKG.CFG", buff, 1);
203 mateuszvis 680
  /* copy pkginst to the new drive so it is not read from the floppy each time */
681
  snprintf(buff, sizeof(buff), "COPY A:\\FDINST.EXE %c:\\ > NUL", targetdrv);
200 mateuszvis 682
  system(buff);
683
  /* change current drive to target so I use the on-hdd fdinst from now on */
684
  if (set_cur_drive(targetdrv) != 0) {
685
    video_putstring(10, 30, COLOR_BODY[mono], "ERROR: CHANGING DRIVE TO TARGET FAILED", -1);
686
    input_getkey();
687
    return(-1);
688
  }
30 mv_fox 689
  /* install packages */
192 mateuszvis 690
  pkgptr = pkglist;
691
  for (i = 0;; i++) {
692
    char buff[64];
693
    /* move forward to nearest entry or end of list */
694
    while (*pkgptr == 0) pkgptr++;
695
    if (*pkgptr == 0xff) break;
696
    /* install the package */
697
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkgptr);
36 mv_fox 698
    strcat(buff, "       ");
192 mateuszvis 699
    video_putstringfix(10, 1, COLOR_BODY[mono], buff, sizeof(buff));
200 mateuszvis 700
    /* wait for new diskette if package not found */
701
    snprintf(buff, sizeof(buff), "%c:\\%s.zip", cdromdrv, pkgptr);
702
    while (fileexists(buff) != 0) {
703
      putstringnls(12, 1, COLOR_BODY[mono], 4, 1, "*** INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY ***");
704
      input_getkey();
705
      video_putstringfix(12, 1, COLOR_BODY[mono], "", 80); /* erase the 'insert disk' message */
706
    }
707
    /* proceed with package install */
192 mateuszvis 708
    snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\%s.ZIP > NUL", cdromdrv, pkgptr);
709
    if (system(buff) != 0) {
200 mateuszvis 710
      video_putstring(12, 30, COLOR_BODY[mono], "ERROR: PKG INSTALL FAILED", -1);
192 mateuszvis 711
      input_getkey();
712
      return(-1);
55 mv_fox 713
    }
192 mateuszvis 714
    /* jump to next entry or end of list */
715
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) pkgptr++;
716
    if (*pkgptr == 0xff) break;
28 mv_fox 717
  }
192 mateuszvis 718
  return(0);
28 mv_fox 719
}
720
 
721
 
42 mv_fox 722
static void finalreboot(void) {
56 mv_fox 723
  int y = 9;
79 mv_fox 724
  newscreen(2);
190 mateuszvis 725
  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 726
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
42 mv_fox 727
  input_getkey();
728
  reboot();
729
}
730
 
731
 
192 mateuszvis 732
static void loadcp(const struct slocales *locales) {
42 mv_fox 733
  char buff[64];
67 mv_fox 734
  if (locales->codepage == 437) return;
42 mv_fox 735
  video_movecursor(1, 0);
67 mv_fox 736
  if (locales->egafile == 1) {
737
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
42 mv_fox 738
  } else {
67 mv_fox 739
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
42 mv_fox 740
  }
741
  system(buff);
67 mv_fox 742
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
42 mv_fox 743
  system(buff);
744
  /* below I re-init the video controller - apparently this is required if
65 mv_fox 745
   * I want the new glyph symbols to be actually applied, at least some
746
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
42 mv_fox 747
  {
748
  union REGS r;
749
  r.h.ah = 0x0F; /* get current video mode */
750
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
56 mv_fox 751
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
752
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
42 mv_fox 753
  int86(0x10, &r, &r);
754
  }
755
}
756
 
200 mateuszvis 757
 
193 mateuszvis 758
/* checks that drive drv contains SvarDOS packages
65 mv_fox 759
 * returns 0 if found, non-zero otherwise */
193 mateuszvis 760
static int checkinstsrc(char drv) {
761
  char fname[16];
762
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.ZIP", drv);
200 mateuszvis 763
  return(fileexists(fname));
69 mv_fox 764
}
65 mv_fox 765
 
766
 
28 mv_fox 767
int main(void) {
67 mv_fox 768
  struct slocales locales;
28 mv_fox 769
  int targetdrv;
193 mateuszvis 770
  int sourcedrv;
73 mv_fox 771
  int action;
28 mv_fox 772
 
193 mateuszvis 773
  /* am I running in install-from-floppy mode? */
774
  if (checkinstsrc('A') == 0) {
775
    sourcedrv = 'A';
776
  } else { /* otherwise find where the cdrom drive is */
777
    sourcedrv = cdrom_findfirst();
778
    if (sourcedrv < 0) {
779
      printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
780
      return(1);
781
    }
782
    sourcedrv += 'A'; /* convert the source drive 'id' (A=0) to an actual drive letter */
783
    if (checkinstsrc(sourcedrv) != 0) {
784
      printf("ERROR: SVARDOS INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
785
      return(1);
786
    }
53 mv_fox 787
  }
788
 
29 mv_fox 789
  /* init screen and detect mono status */
790
  mono = video_init();
791
 
73 mv_fox 792
  kittenopen("INSTALL"); /* load initial NLS support */
793
 
794
 SelectLang:
190 mateuszvis 795
  action = selectlang(&locales); /* welcome to svardos, select your language */
73 mv_fox 796
  if (action != MENUNEXT) goto Quit;
797
  setenv("LANG", locales.lang, 1);
798
  loadcp(&locales);
799
  kittenclose(); /* reload NLS with new language */
800
  kittenopen("INSTALL"); /* NLS support */
801
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
802
  if (action == MENUQUIT) goto Quit;
803
  if (action == MENUPREV) goto SelectLang;
804
 
805
 WelcomeScreen:
190 mateuszvis 806
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
73 mv_fox 807
  if (action == MENUQUIT) goto Quit;
808
  if (action == MENUPREV) goto SelectLang;
809
  targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
810
  if (targetdrv == MENUQUIT) goto Quit;
811
  if (targetdrv == MENUPREV) goto WelcomeScreen;
200 mateuszvis 812
  bootfilesgen(targetdrv, &locales, sourcedrv); /* generate boot files and other configurations */
193 mateuszvis 813
  if (installpackages(targetdrv, sourcedrv) != 0) goto Quit;    /* install packages */
73 mv_fox 814
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
815
  /*netcfg();*/ /* basic networking config */
816
  finalreboot(); /* remove the CD and reboot */
817
 
818
 Quit:
42 mv_fox 819
  kittenclose(); /* close NLS support */
81 mv_fox 820
  video_clear(0x0700, 0, 0);
28 mv_fox 821
  video_movecursor(0, 0);
822
  return(0);
823
}