Subversion Repositories SvarDOS

Rev

Rev 1805 | Rev 1831 | 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
 *
190 mateuszvis 4
 * PUBLISHED UNDER THE TERMS OF THE MIT LICENSE
42 mv_fox 5
 *
1624 mateusz.vi 6
 * COPYRIGHT (C) 2016-2024 MATEUSZ VISTE, ALL RIGHTS RESERVED.
94 mv_fox 7
 *
190 mateuszvis 8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the "Software"),
10
 * to deal in the Software without restriction, including without limitation
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * Software is furnished to do so, subject to the following conditions:
94 mv_fox 14
 *
190 mateuszvis 15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
94 mv_fox 17
 *
190 mateuszvis 18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
 * DEALINGS IN THE SOFTWARE.
94 mv_fox 25
 *
868 mateusz.vi 26
 * http://svardos.org
28 mv_fox 27
 */
28
 
29
#include <dos.h>
30 mv_fox 30
#include <direct.h>  /* mkdir() */
28 mv_fox 31
#include <stdio.h>   /* printf() and friends */
32
#include <stdlib.h>  /* system() */
33
#include <string.h>  /* memcpy() */
34
#include <unistd.h>
42 mv_fox 35
 
1662 mateusz.vi 36
#include "mdr\cout.h"
1661 mateusz.vi 37
#include "mdr\dos.h"
624 mateuszvis 38
#include "svarlang.lib\svarlang.h"
42 mv_fox 39
 
67 mv_fox 40
/* keyboard layouts and locales */
41
#include "keylay.h"
42
#include "keyoff.h"
42 mv_fox 43
 
908 mateusz.vi 44
/* prototype of the int24hdl() function defined in int24hdl.asm */
45
void int24hdl(void);
46
 
47
 
1664 mateusz.vi 48
/* color scheme (preset for color) */
49
static unsigned char COLOR_TITLEBAR  = 0x70;
1671 mateusz.vi 50
static unsigned char COLOR_TITLEVER  = 0x78;
1664 mateusz.vi 51
static unsigned char COLOR_BODY      = 0x17;
1673 mateusz.vi 52
static unsigned char COLOR_BODYWARN  = 0x1F;
1664 mateusz.vi 53
static unsigned char COLOR_SELECT    = 0x70;
54
static unsigned char COLOR_SELECTCUR = 0x1F;
28 mv_fox 55
 
1671 mateusz.vi 56
/* build release string, populated at startup by reading floppy's label */
57
static char BUILDSTRING[13];
28 mv_fox 58
 
190 mateuszvis 59
/* how much disk space does SvarDOS require (in MiB) */
60
#define SVARDOS_DISK_REQ 8
28 mv_fox 61
 
73 mv_fox 62
/* menu screens can output only one of these: */
63
#define MENUNEXT 0
64
#define MENUPREV -1
65
#define MENUQUIT -2
66
 
67 mv_fox 67
/* a convenience 'function' used for debugging */
68
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
47 mv_fox 69
 
67 mv_fox 70
struct slocales {
71
  char lang[4];
624 mateuszvis 72
  const char *keybcode;
67 mv_fox 73
  unsigned int codepage;
74
  int egafile;
75
  int keybfile;
76
  int keyboff;
77
  int keyblen;
96 mv_fox 78
  unsigned int keybid;
67 mv_fox 79
};
80
 
81
 
1662 mateusz.vi 82
/* put a string on screen and fill it until w chars with whilte space */
83
static void video_putstringfix(unsigned char y, unsigned char x, unsigned char attr, const char *s, unsigned char w) {
84
  unsigned char i;
85
 
86
  /* print the string up to w characters */
87
  i = mdr_cout_str(y, x, s, attr, w);
88
 
89
  /* fill in left space (if any) with blanks */
90
  mdr_cout_char_rep(y, x + i, ' ', attr, w - i);
91
}
92
 
93
 
28 mv_fox 94
/* reboot the computer */
95
static void reboot(void) {
96
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
97
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
98
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
99
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
100
}
101
 
42 mv_fox 102
 
1669 mateusz.vi 103
/* returns 1 if file exists, zero otherwise */
104
static int fileexists(const char *fname) {
105
  FILE *fd;
106
  fd = fopen(fname, "rb");
107
  if (fd == NULL) return(0);
108
  fclose(fd);
109
  return(1);
110
}
111
 
112
 
56 mv_fox 113
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
1662 mateusz.vi 114
static unsigned char putstringwrap(unsigned char y, unsigned char x, unsigned char attr, const char *s) {
115
  unsigned char linew, lincount;
116
  linew = 80 - (x << 1);
56 mv_fox 117
 
118
  for (lincount = 1; y+lincount < 25; lincount++) {
119
    int i, len = linew;
120
    for (i = 0; i <= linew; i++) {
121
      if (s[i] == ' ') len = i;
122
      if (s[i] == '\n') {
123
        len = i;
124
        break;
125
      }
126
      if (s[i] == 0) {
127
        len = i;
128
        break;
129
      }
130
    }
1662 mateusz.vi 131
    mdr_cout_str(y++, x, s, attr, len);
56 mv_fox 132
    s += len;
133
    if (*s == 0) break;
134
    s += 1; /* skip the whitespace char */
135
  }
136
  return(lincount);
137
}
138
 
139
 
140
/* an NLS wrapper around video_putstring(), also performs line wrapping when
141
 * needed. returns the amount of lines that were output */
1662 mateusz.vi 142
static unsigned char putstringnls(unsigned char y, unsigned char x, unsigned char attr, unsigned char nlsmaj, unsigned char nlsmin) {
624 mateuszvis 143
  const char *s = svarlang_str(nlsmaj, nlsmin);
144
  if (s == NULL) s = "";
56 mv_fox 145
  return(putstringwrap(y, x, attr, s));
42 mv_fox 146
}
147
 
148
 
280 mateuszvis 149
/* copy file f1 to f2 using buff as a buffer of buffsz bytes. f2 will be overwritten if it
150
 * exists already! returns 0 on success. */
151
static int fcopy(const char *f2, const char *f1, void *buff, size_t buffsz) {
152
  FILE *fd1, *fd2;
153
  size_t sz;
154
  int res = -1; /* assume failure */
155
 
156
  /* open files */
157
  fd1 = fopen(f1, "rb");
158
  fd2 = fopen(f2, "wb");
159
  if ((fd1 == NULL) || (fd2 == NULL)) goto QUIT;
160
 
161
  /* copy data */
162
  for (;;) {
163
    sz = fread(buff, 1, buffsz, fd1);
164
    if (sz == 0) {
165
      if (feof(fd1) != 0) break;
166
      goto QUIT;
167
    }
168
    if (fwrite(buff, 1, sz, fd2) != sz) goto QUIT;
169
  }
170
 
171
  res = 0; /* success */
172
 
173
  QUIT:
174
  if (fd1 != NULL) fclose(fd1);
175
  if (fd2 != NULL) fclose(fd2);
176
  return(res);
177
}
178
 
179
 
1666 mateusz.vi 180
/* display a menu with items and return user's choice.
181
 * ypos: starting line where the menu is drawn
182
 * height: number of items to display inside the menu
183
 * list: NULL-terminated list of items
184
 * maxlistlen: limit list to this many items tops */
1665 mateusz.vi 185
static int menuselect(unsigned char ypos, unsigned char height, const char **list, int maxlistlen) {
186
  int i, offset = 0, res = 0, count;
187
  unsigned char y, xpos, width = 0;
1662 mateusz.vi 188
 
1666 mateusz.vi 189
  /* count how many positions there are, and check their width */
1665 mateusz.vi 190
  for (count = 0; (list[count] != NULL) && (count != maxlistlen); count++) {
28 mv_fox 191
    int len = strlen(list[count]);
192
    if (len > width) width = len;
193
  }
1666 mateusz.vi 194
  width++; /* it's nice to have a small margin to the right of the widest item */
28 mv_fox 195
 
196
  /* if xpos negative, means 'center out' */
1665 mateusz.vi 197
  xpos = 39 - (width >> 1);
28 mv_fox 198
 
1666 mateusz.vi 199
  mdr_cout_char_rep(ypos, xpos, 0xC4, COLOR_SELECT, width + 2);  /* top line */
1664 mateusz.vi 200
  mdr_cout_char(ypos, xpos+width+2, 0xBF, COLOR_SELECT);         /*       \ */
201
  mdr_cout_char(ypos, xpos-1, 0xDA, COLOR_SELECT);               /*  /      */
1666 mateusz.vi 202
  ypos++; /* from now on ypos relates to the position of the content */
203
  mdr_cout_char(ypos+height, xpos-1, 0xC0, COLOR_SELECT);      /*  \      */
204
  mdr_cout_char(ypos+height, xpos+width+2, 0xD9, COLOR_SELECT);/*      /  */
205
  mdr_cout_char_rep(ypos+height, xpos, 0xC4, COLOR_SELECT, width + 2);
28 mv_fox 206
 
207
  for (;;) {
208
    int key;
1666 mateusz.vi 209
 
210
    /* draw side borders of the menu + the cursor */
211
    if (count <= height) { /* no need for a cursor, all fits on one page */
212
      i = 255;
213
    } else {
214
      i = offset * (height - 1) / (count - height);
215
    }
216
 
217
    for (y = ypos; y < (ypos + height); y++) {
218
      mdr_cout_char(y, xpos-1, 0xB3, COLOR_SELECT); /* left side */
219
      if (y - ypos == i) {
1667 mateusz.vi 220
        mdr_cout_char(y, xpos+width+2, '=', COLOR_SELECT); /* cursor */
1666 mateusz.vi 221
      } else {
222
        mdr_cout_char(y, xpos+width+2, 0xB3, COLOR_SELECT); /* right side */
223
      }
224
    }
225
 
28 mv_fox 226
    /* list of selectable items */
1666 mateusz.vi 227
    for (i = 0; i < height; i++) {
28 mv_fox 228
      if (i + offset == res) {
1666 mateusz.vi 229
        mdr_cout_char(ypos + i, xpos, 16, COLOR_SELECTCUR);
230
        mdr_cout_char(ypos + i, xpos+width+1, 17, COLOR_SELECTCUR);
231
        mdr_cout_locate(ypos + i, xpos);
232
        video_putstringfix(ypos + i, xpos+1, COLOR_SELECTCUR, list[i + offset], width);
28 mv_fox 233
      } else if (i + offset < count) {
1666 mateusz.vi 234
        mdr_cout_char(ypos + i, xpos, ' ', COLOR_SELECT);
235
        mdr_cout_char(ypos + i, xpos+width+1, ' ', COLOR_SELECT);
236
        video_putstringfix(ypos + i, xpos+1, COLOR_SELECT, list[i + offset], width);
28 mv_fox 237
      } else {
1666 mateusz.vi 238
        mdr_cout_char_rep(ypos + i, xpos, ' ', COLOR_SELECT, width+2);
28 mv_fox 239
      }
240
    }
1661 mateusz.vi 241
    key = mdr_dos_getkey();
28 mv_fox 242
    if (key == 0x0D) { /* ENTER */
243
      return(res);
244
    } else if (key == 0x148) { /* up */
33 mv_fox 245
      if (res > 0) {
246
        res--;
247
        if (res < offset) offset = res;
248
      }
28 mv_fox 249
    } else if (key == 0x150) { /* down */
33 mv_fox 250
      if (res+1 < count) {
251
        res++;
1666 mateusz.vi 252
        if (res > offset + height - 1) offset = res - (height - 1);
33 mv_fox 253
      }
254
    } else if (key == 0x147) { /* home */
255
      res = 0;
256
      offset = 0;
257
    } else if (key == 0x14F) { /* end */
258
      res = count - 1;
1666 mateusz.vi 259
      if (res > offset + height - 1) offset = res - (height - 1);
28 mv_fox 260
    } else if (key == 0x1B) {  /* ESC */
261
      return(-1);
78 mv_fox 262
    }/* else {
33 mv_fox 263
      char buf[8];
55 mv_fox 264
      snprintf(buf, sizeof(buf), "0x%02X ", key);
1664 mateusz.vi 265
      video_putstring(1, 0, COLOR_BODY, buf, -1);
78 mv_fox 266
    }*/
28 mv_fox 267
  }
268
}
269
 
1662 mateusz.vi 270
static void newscreen(unsigned char statusbartype) {
624 mateuszvis 271
  const char *msg;
1664 mateusz.vi 272
  mdr_cout_cls(COLOR_BODY);
624 mateuszvis 273
  msg = svarlang_strid(0x00); /* "SVARDOS INSTALLATION" */
1664 mateusz.vi 274
  mdr_cout_char_rep(0, 0, ' ', COLOR_TITLEBAR, 80);
275
  mdr_cout_str(0, 40 - (strlen(msg) >> 1), msg, COLOR_TITLEBAR, 80);
1671 mateusz.vi 276
  mdr_cout_str(0, 80 - strlen(BUILDSTRING), BUILDSTRING, COLOR_TITLEVER, 12);
277
 
79 mv_fox 278
  switch (statusbartype) {
279
    case 1:
624 mateuszvis 280
      msg = svarlang_strid(0x000B); /* "Up/Down = Select entry | Enter = Validate your choice | ESC = Quit to DOS" */
79 mv_fox 281
      break;
282
    case 2:
624 mateuszvis 283
      msg = svarlang_strid(0x0005); /* "Press any key..." */
79 mv_fox 284
      break;
285
    case 3:
286
      msg = "";
287
      break;
288
    default:
624 mateuszvis 289
      msg = svarlang_strid(0x000A); /* "Up/Down = Select entry | Enter = Validate your choice | ESC = Previous screen" */
79 mv_fox 290
      break;
291
  }
1664 mateusz.vi 292
  mdr_cout_char(24, 0, ' ', COLOR_TITLEBAR);
293
  video_putstringfix(24, 1, COLOR_TITLEBAR, msg, 79);
1662 mateusz.vi 294
  mdr_cout_locate(25,0);
28 mv_fox 295
}
296
 
96 mv_fox 297
/* fills a slocales struct accordingly to the value of its keyboff member */
298
static void kblay2slocal(struct slocales *locales) {
624 mateuszvis 299
  const char *m;
96 mv_fox 300
  for (m = kblayouts[locales->keyboff]; *m != 0; m++); /* skip layout name */
301
  m++;
302
  /* skip keyb code and copy it to locales.keybcode */
303
  locales->keybcode = m;
304
  for (; *m != 0; m++);
305
  /* */
306
  locales->codepage = ((unsigned short)m[1] << 8) | m[2];
307
  locales->egafile = m[3];
308
  locales->keybfile = m[4];
309
  locales->keybid = ((unsigned short)m[5] << 8) | m[6];
310
}
311
 
67 mv_fox 312
static int selectlang(struct slocales *locales) {
313
  int choice, x;
624 mateuszvis 314
  const char *msg;
315
  const char *langlist[] = {
67 mv_fox 316
    "English",
1177 mateusz.vi 317
    "Brazilian",
67 mv_fox 318
    "French",
133 mv_fox 319
    "German",
119 mv_fox 320
    "Italian",
67 mv_fox 321
    "Polish",
116 mv_fox 322
    "Russian",
123 mv_fox 323
    "Slovene",
128 mv_fox 324
    "Swedish",
67 mv_fox 325
    "Turkish",
28 mv_fox 326
    NULL
327
  };
328
 
1669 mateusz.vi 329
  /* do not ask for language on non-multilang setups */
330
  if (!fileexists("INSTALL.LNG")) {
331
    choice = 0;
332
    goto SkipLangSelect;
333
  }
334
 
79 mv_fox 335
  newscreen(1);
624 mateuszvis 336
  msg = svarlang_strid(0x0100); /* "Welcome to SvarDOS" */
42 mv_fox 337
  x = 40 - (strlen(msg) >> 1);
1664 mateusz.vi 338
  mdr_cout_str(4, x, msg, COLOR_BODY, 80);
339
  mdr_cout_char_rep(5, x, '=', COLOR_BODY, strlen(msg));
1662 mateusz.vi 340
 
341
  /* center out the string "Please select your language..." */
342
  msg = svarlang_str(1, 1); /* "Please select your language from the list below:" */
343
  if (strlen(msg) > 74) {
1664 mateusz.vi 344
    putstringwrap(8, 1, COLOR_BODY, msg);
1662 mateusz.vi 345
  } else {
1664 mateusz.vi 346
    mdr_cout_str(8, 40 - (strlen(msg) / 2), msg, COLOR_BODY, 80);
1662 mateusz.vi 347
  }
348
 
1666 mateusz.vi 349
  choice = menuselect(11, 9, langlist, -1);
73 mv_fox 350
  if (choice < 0) return(MENUPREV);
1669 mateusz.vi 351
 
352
  SkipLangSelect:
353
 
67 mv_fox 354
  /* populate locales with default values */
355
  memset(locales, 0, sizeof(struct slocales));
356
  switch (choice) {
357
    case 1:
1179 mateusz.vi 358
      strcpy(locales->lang, "BR");
359
      locales->keyboff = OFFLOC_BR;
360
      locales->keyblen = OFFLEN_BR;
361
      break;
362
    case 2:
67 mv_fox 363
      strcpy(locales->lang, "FR");
364
      locales->keyboff = OFFLOC_FR;
365
      locales->keyblen = OFFLEN_FR;
366
      break;
1177 mateusz.vi 367
    case 3:
133 mv_fox 368
      strcpy(locales->lang, "DE");
369
      locales->keyboff = OFFLOC_DE;
370
      locales->keyblen = OFFLEN_DE;
371
      break;
1177 mateusz.vi 372
    case 4:
119 mv_fox 373
      strcpy(locales->lang, "IT");
374
      locales->keyboff = OFFLOC_IT;
375
      locales->keyblen = OFFLEN_IT;
376
      break;
1177 mateusz.vi 377
    case 5:
67 mv_fox 378
      strcpy(locales->lang, "PL");
379
      locales->keyboff = OFFLOC_PL;
380
      locales->keyblen = OFFLEN_PL;
381
      break;
1177 mateusz.vi 382
    case 6:
116 mv_fox 383
      strcpy(locales->lang, "RU");
384
      locales->keyboff = OFFLOC_RU;
385
      locales->keyblen = OFFLEN_RU;
386
      break;
1177 mateusz.vi 387
    case 7:
123 mv_fox 388
      strcpy(locales->lang, "SI");
389
      locales->keyboff = OFFLOC_SI;
390
      locales->keyblen = OFFLEN_SI;
391
      break;
1177 mateusz.vi 392
    case 8:
128 mv_fox 393
      strcpy(locales->lang, "SV");
394
      locales->keyboff = OFFLOC_SV;
395
      locales->keyblen = OFFLEN_SV;
396
      break;
1177 mateusz.vi 397
    case 9:
67 mv_fox 398
      strcpy(locales->lang, "TR");
399
      locales->keyboff = OFFLOC_TR;
400
      locales->keyblen = OFFLEN_TR;
401
      break;
402
    default:
403
      strcpy(locales->lang, "EN");
404
      locales->keyboff = 0;
405
      locales->keyblen = OFFCOUNT;
406
      break;
407
  }
96 mv_fox 408
  /* populate the slocales struct accordingly to the keyboff member */
409
  kblay2slocal(locales);
67 mv_fox 410
  /* */
73 mv_fox 411
  return(MENUNEXT);
28 mv_fox 412
}
413
 
414
 
67 mv_fox 415
static int selectkeyb(struct slocales *locales) {
96 mv_fox 416
  int menuheight, choice;
417
  if (locales->keyblen == 1) return(MENUNEXT); /* do not ask for keyboard layout if only one is available for given language */
79 mv_fox 418
  newscreen(0);
1664 mateusz.vi 419
  putstringnls(5, 1, COLOR_BODY, 1, 5); /* "SvarDOS supports different keyboard layouts */
1666 mateusz.vi 420
  menuheight = locales->keyblen;
421
  if (menuheight > 11) menuheight = 11;
1665 mateusz.vi 422
  choice = menuselect(10, menuheight, &(kblayouts[locales->keyboff]), locales->keyblen);
96 mv_fox 423
  if (choice < 0) return(MENUPREV);
424
  /* (re)load the keyboard layout & codepage setup */
425
  locales->keyboff += choice;
426
  kblay2slocal(locales);
73 mv_fox 427
  return(MENUNEXT);
67 mv_fox 428
}
429
 
430
 
28 mv_fox 431
/* returns 0 if installation must proceed, non-zero otherwise */
432
static int welcomescreen(void) {
73 mv_fox 433
  int c;
624 mateuszvis 434
  const char *choice[3];
435
  choice[0] = svarlang_strid(0x0001);
436
  choice[1] = svarlang_strid(0x0002);
437
  choice[2] = NULL;
79 mv_fox 438
  newscreen(0);
1664 mateusz.vi 439
  putstringnls(4, 1, COLOR_BODY, 2, 0); /* "You are about to install SvarDOS */
1666 mateusz.vi 440
  c = menuselect(13, 2, choice, -1);
73 mv_fox 441
  if (c < 0) return(MENUPREV);
442
  if (c == 0) return(MENUNEXT);
443
  return(MENUQUIT);
28 mv_fox 444
}
445
 
446
 
33 mv_fox 447
/* returns 1 if drive is removable, 0 if not, -1 on error */
448
static int isdriveremovable(int drv) {
28 mv_fox 449
  union REGS r;
33 mv_fox 450
  r.x.ax = 0x4408;
451
  r.h.bl = drv;
28 mv_fox 452
  int86(0x21, &r, &r);
33 mv_fox 453
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
454
  if (r.x.cflag != 0) return(-1);
455
  if (r.x.ax == 0) return(1);
456
  return(0);
28 mv_fox 457
}
458
 
459
 
35 mv_fox 460
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
461
static int disksize(int drv) {
28 mv_fox 462
  long res;
463
  union REGS r;
464
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
312 mateuszvis 465
  r.h.dl = drv;  /* A=1, B=2, etc */
28 mv_fox 466
  int86(0x21, &r, &r);
467
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
49 mv_fox 468
  res = r.x.ax;  /* sectors per cluster */
469
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
470
  res *= r.x.cx; /* bytes per sector */
471
  res >>= 20;    /* convert bytes to MiB */
472
  return(res);
35 mv_fox 473
}
474
 
475
 
476
/* returns 0 if disk is empty, non-zero otherwise */
477
static int diskempty(int drv) {
478
  unsigned int rc;
479
  int res;
480
  char buff[8];
481
  struct find_t fileinfo;
55 mv_fox 482
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
35 mv_fox 483
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
484
  if (rc == 0) {
485
    res = 1; /* call successfull means disk is not empty */
28 mv_fox 486
  } else {
35 mv_fox 487
    res = 0;
28 mv_fox 488
  }
35 mv_fox 489
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
28 mv_fox 490
  return(res);
491
}
492
 
280 mateuszvis 493
#ifdef DEADCODE
200 mateuszvis 494
/* set new DOS "current drive" to drv ('A', 'B', etc). returns 0 on success */
495
static int set_cur_drive(char drv) {
496
  union REGS r;
497
  if ((drv < 'A') || (drv > 'Z')) return(-1);
498
  r.h.ah = 0x0E; /* DOS 1+ SELECT DEFAULT DRIVE */
499
  r.h.dl = drv - 'A';
500
  int86(0x21, &r, &r);
501
  if (r.h.al < drv - 'A') return(-1);
502
  return(0);
503
}
280 mateuszvis 504
#endif
200 mateuszvis 505
 
310 mateuszvis 506
 
507
/* get the DOS "current drive" (0=A:, 1=B:, etc) */
508
static int get_cur_drive(void) {
509
  union REGS r;
510
  r.h.ah = 0x19; /* DOS 1+ GET CURRENT DEFAULT DRIVE */
511
  int86(0x21, &r, &r);
512
  return(r.h.al);
513
}
514
 
515
 
898 mateusz.vi 516
/* tries to write an empty file to drive.
517
 * asks DOS to inhibit the int 24h handler for this job, so erros are
518
 * gracefully reported - unfortunately this does not work under FreeDOS because
519
 * the DOS-C kernel does not implement the required flag.
520
 * returns 0 on success (ie. "disk exists and is writeable"). */
521
static unsigned short test_drive_write(char drive, char *buff) {
522
  unsigned short result = 0;
523
  sprintf(buff, "%c:\\SVWRTEST.123", drive);
524
  _asm {
525
    push ax
526
    push bx
527
    push cx
528
    push dx
529
 
530
    mov ah, 0x6c   /* extended open/create file */
531
    mov bx, 0x2001 /* open for write + inhibit int 24h handler */
532
    xor cx, cx     /* file attributes on the created file */
533
    mov dx, 0x0010 /* create file if does not exist, fail if it exists */
534
    mov si, buff   /* filename to create */
535
    int 0x21
536
    jc FAILURE
537
    /* close the file (handle in AX) */
538
    mov bx, ax
539
    mov ah, 0x3e /* close file */
540
    int 0x21
541
    jc FAILURE
542
    /* delete the file */
543
    mov ah, 0x41 /* delete file pointed out by DS:DX */
544
    mov dx, buff
545
    int 0x21
546
    jnc DONE
547
 
548
    FAILURE:
549
    mov result, ax
550
    DONE:
551
 
552
    pop dx
553
    pop cx
554
    pop bx
555
    pop ax
556
  }
557
  return(result);
558
}
559
 
560
 
310 mateuszvis 561
static int preparedrive(char sourcedrv) {
33 mv_fox 562
  int driveremovable;
310 mateuszvis 563
  int selecteddrive = 3; /* default to 'C:' */
36 mv_fox 564
  int cselecteddrive;
35 mv_fox 565
  int ds;
73 mv_fox 566
  int choice;
56 mv_fox 567
  char buff[1024];
312 mateuszvis 568
  int driveid = 1; /* fdisk runs on first drive (unless USB boot) */
569
  if (selecteddrive == get_cur_drive() + 1) { /* get_cur_drive() returns 0-based values (A=0) while selecteddrive is 1-based (A=1) */
570
    selecteddrive = 4; /* use D: if install is run from C: (typically because it was booted from USB?) */
571
    driveid = 2; /* primary drive is the emulated USB storage */
572
  }
36 mv_fox 573
  cselecteddrive = 'A' + selecteddrive - 1;
28 mv_fox 574
  for (;;) {
33 mv_fox 575
    driveremovable = isdriveremovable(selecteddrive);
576
    if (driveremovable < 0) {
624 mateuszvis 577
      const char *list[4];
79 mv_fox 578
      newscreen(0);
624 mateuszvis 579
      list[0] = svarlang_str(0, 3); /* Create a partition automatically */
580
      list[1] = svarlang_str(0, 4); /* Run the FDISK tool */
581
      list[2] = svarlang_str(0, 2); /* Quit to DOS */
582
      list[3] = NULL;
583
      snprintf(buff, sizeof(buff), svarlang_strid(0x0300), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: could not be found. Note, that SvarDOS requires at least %d MiB of available disk space */
1666 mateusz.vi 584
      switch (menuselect(6 + putstringwrap(4, 1, COLOR_BODY, buff), 3, list, -1)) {
33 mv_fox 585
        case 0:
1239 mateusz.vi 586
          sprintf(buff, "FDISK /PRI:MAX %d", driveid);
312 mateuszvis 587
          system(buff);
33 mv_fox 588
          break;
589
        case 1:
1662 mateusz.vi 590
          mdr_cout_cls(0x07);
591
          mdr_cout_locate(0, 0);
312 mateuszvis 592
          sprintf(buff, "FDISK %d", driveid);
593
          system(buff);
33 mv_fox 594
          break;
73 mv_fox 595
        case 2:
596
          return(MENUQUIT);
56 mv_fox 597
        default:
33 mv_fox 598
          return(-1);
599
      }
113 mv_fox 600
      /* write a temporary MBR which only skips the drive (in case BIOS would
601
       * try to boot off the not-yet-ready C: disk) */
1239 mateusz.vi 602
      sprintf(buff, "FDISK /LOADIPL %d", driveid);
312 mateuszvis 603
      system(buff); /* writes BOOT.MBR into actual MBR */
79 mv_fox 604
      newscreen(2);
1664 mateusz.vi 605
      putstringnls(10, 10, COLOR_BODY, 3, 1); /* "Your computer will reboot now." */
606
      putstringnls(12, 10, COLOR_BODY, 0, 5); /* "Press any key..." */
1661 mateusz.vi 607
      mdr_dos_getkey();
28 mv_fox 608
      reboot();
73 mv_fox 609
      return(MENUQUIT);
33 mv_fox 610
    } else if (driveremovable > 0) {
79 mv_fox 611
      newscreen(2);
624 mateuszvis 612
      snprintf(buff, sizeof(buff), svarlang_strid(0x0302), cselecteddrive); /* "ERROR: Drive %c: is a removable device */
1664 mateusz.vi 613
      mdr_cout_str(9, 1, buff, COLOR_BODY, 80);
614
      putstringnls(11, 2, COLOR_BODY, 0, 5); /* "Press any key..." */
73 mv_fox 615
      return(MENUQUIT);
28 mv_fox 616
    }
33 mv_fox 617
    /* if not formatted, propose to format it right away (try to create a directory) */
898 mateusz.vi 618
    if (test_drive_write(cselecteddrive, buff) != 0) {
624 mateuszvis 619
      const char *list[3];
79 mv_fox 620
      newscreen(0);
624 mateuszvis 621
      snprintf(buff, sizeof(buff), svarlang_str(3, 3), cselecteddrive); /* "ERROR: Drive %c: seems to be unformated. Do you wish to format it?") */
1664 mateusz.vi 622
      mdr_cout_str(7, 1, buff, COLOR_BODY, 80);
556 mateuszvis 623
 
624 mateuszvis 624
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
556 mateuszvis 625
      list[0] = buff;
624 mateuszvis 626
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
556 mateuszvis 627
      list[2] = NULL;
628
 
1666 mateusz.vi 629
      choice = menuselect(12, 2, list, -1);
73 mv_fox 630
      if (choice < 0) return(MENUPREV);
631
      if (choice == 1) return(MENUQUIT);
1662 mateusz.vi 632
      mdr_cout_cls(0x07);
633
      mdr_cout_locate(0, 0);
190 mateuszvis 634
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
36 mv_fox 635
      system(buff);
28 mv_fox 636
      continue;
637
    }
33 mv_fox 638
    /* check total disk space */
35 mv_fox 639
    ds = disksize(selecteddrive);
190 mateuszvis 640
    if (ds < SVARDOS_DISK_REQ) {
56 mv_fox 641
      int y = 9;
79 mv_fox 642
      newscreen(2);
624 mateuszvis 643
      snprintf(buff, sizeof(buff), svarlang_strid(0x0304), cselecteddrive, SVARDOS_DISK_REQ); /* "ERROR: Drive %c: is not big enough! SvarDOS requires a disk of at least %d MiB." */
1664 mateusz.vi 644
      y += putstringwrap(y, 1, COLOR_BODY, buff);
645
      putstringnls(++y, 1, COLOR_BODY, 0, 5); /* "Press any key..." */
1661 mateusz.vi 646
      mdr_dos_getkey();
73 mv_fox 647
      return(MENUQUIT);
28 mv_fox 648
    }
649
    /* is the disk empty? */
79 mv_fox 650
    newscreen(0);
35 mv_fox 651
    if (diskempty(selecteddrive) != 0) {
624 mateuszvis 652
      const char *list[3];
65 mv_fox 653
      int y = 6;
624 mateuszvis 654
      snprintf(buff, sizeof(buff), svarlang_strid(0x0305), cselecteddrive); /* "ERROR: Drive %c: not empty" */
1664 mateusz.vi 655
      y += putstringwrap(y, 1, COLOR_BODY, buff);
556 mateuszvis 656
 
624 mateuszvis 657
      snprintf(buff, sizeof(buff), svarlang_strid(0x0007), cselecteddrive); /* "Format drive %c:" */
556 mateuszvis 658
      list[0] = buff;
624 mateuszvis 659
      list[1] = svarlang_strid(0x0002); /* "Quit to DOS" */
556 mateuszvis 660
      list[2] = NULL;
661
 
1666 mateusz.vi 662
      choice = menuselect(++y, 2, list, -1);
73 mv_fox 663
      if (choice < 0) return(MENUPREV);
664
      if (choice == 1) return(MENUQUIT);
1662 mateusz.vi 665
      mdr_cout_cls(0x07);
666
      mdr_cout_locate(0, 0);
190 mateuszvis 667
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVARDOS", cselecteddrive);
42 mv_fox 668
      system(buff);
28 mv_fox 669
      continue;
670
    } else {
671
      /* final confirmation */
624 mateuszvis 672
      const char *list[3];
673
      list[0] = svarlang_strid(0x0001); /* Install SvarDOS */
674
      list[1] = svarlang_strid(0x0002); /* Quit to DOS */
675
      list[2] = NULL;
676
      snprintf(buff, sizeof(buff), svarlang_strid(0x0306), cselecteddrive); /* "The installation of SvarDOS to %c: is about to begin." */
1672 mateusz.vi 677
      mdr_cout_str(7, 40 - (strlen(buff) / 2), buff, COLOR_BODY, 80);
1666 mateusz.vi 678
      choice = menuselect(10, 2, list, -1);
73 mv_fox 679
      if (choice < 0) return(MENUPREV);
680
      if (choice == 1) return(MENUQUIT);
310 mateuszvis 681
      snprintf(buff, sizeof(buff), "SYS %c: %c: > NUL", sourcedrv, cselecteddrive);
36 mv_fox 682
      system(buff);
312 mateuszvis 683
      sprintf(buff, "FDISK /MBR %d", driveid);
684
      system(buff);
55 mv_fox 685
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
36 mv_fox 686
      mkdir(buff);
687
      return(cselecteddrive);
28 mv_fox 688
    }
689
  }
690
}
691
 
692
 
280 mateuszvis 693
/* generates locales-related configurations and writes them to file (this
694
 * is used to compute autoexec.bat content) */
695
static void genlocalesconf(FILE *fd, const struct slocales *locales) {
696
  if (locales == NULL) return;
697
 
698
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
699
 
700
  if (locales->egafile > 0) {
701
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
702
    if (locales->egafile == 1) {
703
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA.CPX)\r\n", locales->codepage);
704
    } else {
705
      fprintf(fd, "MODE CON CP PREPARE=((%u) %%DOSDIR%%\\CPI\\EGA%d.CPX)\r\n", locales->codepage, locales->egafile);
706
    }
707
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
708
  }
709
 
710
  if (locales->keybfile > 0) {
1659 bttr 711
    fprintf(fd, "KEYB %s,%d,%%DOSDIR%%\\", locales->keybcode, locales->codepage);
280 mateuszvis 712
    if (locales->keybfile == 1) {
713
      fprintf(fd, "KEYBOARD.SYS");
714
    } else {
715
      fprintf(fd, "KEYBRD%d.SYS", locales->keybfile);
716
    }
717
    if (locales->keybid != 0) fprintf(fd, " /ID:%d", locales->keybid);
718
    fprintf(fd, "\r\n");
719
  }
720
}
721
 
722
 
723
static void bootfilesgen(char targetdrv, const struct slocales *locales) {
28 mv_fox 724
  char buff[128];
725
  FILE *fd;
53 mv_fox 726
  /*** CONFIG.SYS ***/
280 mateuszvis 727
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\CONFIG.SYS", targetdrv);
53 mv_fox 728
  fd = fopen(buff, "wb");
729
  if (fd == NULL) return;
1751 mateusz.vi 730
  fprintf(fd, "; SvarDOS kernel configuration\r\n"
731
              "\r\n"
732
              "; highest allowed drive letter\r\n"
733
              "LASTDRIVE=Z\r\n"
734
              "\r\n"
735
              "; max. number of files that programs are allowed to open simultaneously\r\n"
736
              "FILES=25\r\n");
737
  fprintf(fd, "\r\n"
738
              "; XMS memory driver\r\n"
739
              "DEVICE=C:\\SVARDOS\\HIMEMX.EXE\r\n");
740
  fprintf(fd, "\r\n"
741
              "; try moving DOS to upper memory, then to high memory\r\n"
742
              "DOS=UMB,HIGH\r\n");
743
  fprintf(fd, "\r\n"
744
              "; command interpreter (shell) location and default environment size\r\n"
745
              "SHELL=C:\\COMMAND.COM /E:512 /P\r\n");
746
  fprintf(fd, "\r\n"
747
              "; NLS configuration\r\n"
748
              ";COUNTRY=001,%u,C:\\SVARDOS\\CFG\\COUNTRY.SYS\r\n", locales->codepage);
749
  fprintf(fd, "\r\n"
750
              "; CD-ROM driver initialization\r\n"
751
              ";DEVICE=C:\\DRIVERS\\VIDECDD\\VIDE-CDD.SYS /D:SVCD0001\r\n");
53 mv_fox 752
  fclose(fd);
28 mv_fox 753
  /*** AUTOEXEC.BAT ***/
280 mateuszvis 754
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\AUTOEXEC.BAT", targetdrv);
28 mv_fox 755
  fd = fopen(buff, "wb");
756
  if (fd == NULL) return;
757
  fprintf(fd, "@ECHO OFF\r\n");
280 mateuszvis 758
  fprintf(fd, "SET TEMP=C:\\TEMP\r\n");
759
  fprintf(fd, "SET DOSDIR=C:\\SVARDOS\r\n");
817 mateusz.vi 760
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS;.\r\n");
1757 mateusz.vi 761
  fprintf(fd, "SET DIRCMD=/O/P\r\n");
303 mateuszvis 762
  fprintf(fd, "SET WATTCP.CFG=%%DOSDIR%%\\CFG\r\n");
1637 mateusz.vi 763
  fprintf(fd, "PATH %%DOSDIR%%\r\n");
28 mv_fox 764
  fprintf(fd, "PROMPT $P$G\r\n");
1757 mateusz.vi 765
  fprintf(fd, "\r\n"
766
              "REM enable CPU power saving\r\n"
767
              "FDAPM APMDOS\r\n");
28 mv_fox 768
  fprintf(fd, "\r\n");
280 mateuszvis 769
  genlocalesconf(fd, locales);
49 mv_fox 770
  fprintf(fd, "\r\n");
280 mateuszvis 771
  fprintf(fd, "REM Uncomment the line below for CDROM support\r\n");
772
  fprintf(fd, "REM SHSUCDX /d:SVCD0001\r\n");
773
  fprintf(fd, "\r\n");
53 mv_fox 774
  fprintf(fd, "ECHO.\r\n");
624 mateuszvis 775
  fprintf(fd, "ECHO %s\r\n", svarlang_strid(0x0600)); /* "Welcome to SvarDOS!" */
28 mv_fox 776
  fclose(fd);
200 mateuszvis 777
  /*** CREATE DIRECTORY FOR CONFIGURATION FILES ***/
277 mateuszvis 778
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS", targetdrv);
200 mateuszvis 779
  mkdir(buff);
277 mateuszvis 780
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG", targetdrv);
53 mv_fox 781
  mkdir(buff);
277 mateuszvis 782
  /*** PKG.CFG ***/
783
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\PKG.CFG", targetdrv);
784
  fd = fopen(buff, "wb");
785
  if (fd == NULL) return;
786
  fprintf(fd, "# pkg config file - specifies locations where packages should be installed\r\n"
787
              "\r\n"
1637 mateusz.vi 788
              "# DOS core binaries\r\n"
789
              "DIR BIN C:\\SVARDOS\r\n"
790
              "\r\n"
277 mateuszvis 791
              "# Programs\r\n"
792
              "DIR PROGS C:\\\r\n"
793
              "\r\n"
794
              "# Games \r\n"
795
              "DIR GAMES C:\\\r\n"
796
              "\r\n"
797
              "# Drivers\r\n"
798
              "DIR DRIVERS C:\\DRIVERS\r\n"
799
              "\r\n"
800
              "# Development tools\r\n"
801
              "DIR DEVEL C:\\DEVEL\r\n");
802
  fclose(fd);
53 mv_fox 803
  /*** COUNTRY.SYS ***/
804
  /*** PICOTCP ***/
805
  /*** WATTCP ***/
303 mateuszvis 806
  snprintf(buff, sizeof(buff), "%c:\\SVARDOS\\CFG\\WATTCP.CFG", targetdrv);
807
  fd = fopen(buff, "wb");
808
  if (fd == NULL) return;
809
  fprintf(fd, "my_ip = dhcp\r\n"
810
              "#my_ip = 192.168.0.7\r\n"
811
              "#netmask = 255.255.255.0\r\n"
812
              "#nameserver = 192.168.0.1\r\n"
813
              "#nameserver = 192.168.0.2\r\n"
554 mateuszvis 814
              "#gateway = 192.168.0.1\r\n");
303 mateuszvis 815
  fclose(fd);
28 mv_fox 816
}
817
 
818
 
1671 mateusz.vi 819
static int installpackages(char targetdrv, char srcdrv, const struct slocales *locales) {
192 mateuszvis 820
  char pkglist[512];
30 mv_fox 821
  int i, pkglistlen;
192 mateuszvis 822
  size_t pkglistflen;
280 mateuszvis 823
  char buff[1024]; /* must be *at least* 1 sector big for efficient file copying */
824
  FILE *fd = NULL;
192 mateuszvis 825
  char *pkgptr;
79 mv_fox 826
  newscreen(3);
192 mateuszvis 827
  /* load pkg list */
828
  fd = fopen("install.lst", "rb");
829
  if (fd == NULL) {
1664 mateusz.vi 830
    mdr_cout_str(10, 30, "ERROR: INSTALL.LST NOT FOUND", COLOR_BODY, 80);
1661 mateusz.vi 831
    mdr_dos_getkey();
192 mateuszvis 832
    return(-1);
833
  }
1125 mateusz.vi 834
  pkglistflen = fread(pkglist, 1, sizeof(pkglist) - 2, fd);
192 mateuszvis 835
  fclose(fd);
1125 mateusz.vi 836
  if (pkglistflen == sizeof(pkglist) - 2) {
1664 mateusz.vi 837
    mdr_cout_str(10, 30, "ERROR: INSTALL.LST TOO LARGE", COLOR_BODY, 80);
1661 mateusz.vi 838
    mdr_dos_getkey();
192 mateuszvis 839
    return(-1);
840
  }
1125 mateusz.vi 841
  /* mark the end of list */
842
  pkglist[pkglistflen] = 0;
843
  pkglist[pkglistflen + 1] = 0xff;
192 mateuszvis 844
  /* replace all \r and \n chars by 0 bytes, and count the number of packages */
845
  pkglistlen = 0;
846
  for (i = 0; i < pkglistflen; i++) {
847
    switch (pkglist[i]) {
848
      case '\n':
849
        pkglistlen++;
850
        /* FALLTHRU */
851
      case '\r':
852
        pkglist[i] = 0;
853
        break;
854
    }
855
  }
280 mateuszvis 856
  /* copy pkg.exe to the new drive, along with all packages */
857
  snprintf(buff, sizeof(buff), "%c:\\TEMP\\pkg.exe", targetdrv);
858
  snprintf(buff + 64, sizeof(buff) - 64, "%c:\\pkg.exe", srcdrv);
859
  fcopy(buff, buff + 64, buff, sizeof(buff));
860
 
861
  /* open the post-install autoexec.bat and prepare initial instructions */
862
  snprintf(buff, sizeof(buff), "%c:\\temp\\postinst.bat", targetdrv);
863
  fd = fopen(buff, "wb");
864
  if (fd == NULL) return(-1);
1671 mateusz.vi 865
  fprintf(fd, "@ECHO OFF\r\nECHO INSTALLING SVARDOS BUILD %s\r\n", BUILDSTRING);
280 mateuszvis 866
 
1104 mateusz.vi 867
  /* move COMMAND.COM so it does not clashes with the installation of the SVARCOM package */
868
  fprintf(fd, "COPY \\COMMAND.COM \\CMD.COM\r\n");
1805 mateusz.vi 869
  fprintf(fd, "SET COMSPEC=C:\\CMD.COM\r\n"); /* POSTINST.BAT is executed after system is rebooted, so the system drive is always C: */
1104 mateusz.vi 870
  fprintf(fd, "DEL \\COMMAND.COM\r\n");
871
 
280 mateuszvis 872
  /* copy packages */
192 mateuszvis 873
  for (i = 0;; i++) {
1125 mateusz.vi 874
    RETRY_ENTIRE_LIST:
875
 
192 mateuszvis 876
    /* move forward to nearest entry or end of list */
1125 mateusz.vi 877
    for (pkgptr = pkglist; *pkgptr == 0; pkgptr++);
878
    if (*pkgptr == 0xff) break; /* end of list: means all packages have been processed */
879
 
880
    /* is this package present on the floppy disk? */
881
    TRY_NEXTPKG:
882
    sprintf(buff, "%s.svp", pkgptr);
1669 mateusz.vi 883
    if (!fileexists(buff)) {
1125 mateusz.vi 884
      while (*pkgptr != 0) pkgptr++;
885
      while (*pkgptr == 0) pkgptr++;
886
      /* end of list? ask for next floppy, there's nothing interesting left on this one */
887
      if (*pkgptr == 0xff) {
1664 mateusz.vi 888
        putstringnls(12, 1, COLOR_BODY, 4, 1); /* "INSERT THE DISK THAT CONTAINS THE REQUIRED FILE AND PRESS ANY KEY" */
1661 mateusz.vi 889
        mdr_dos_getkey();
1664 mateusz.vi 890
        video_putstringfix(12, 1, COLOR_BODY, "", 80); /* erase the 'insert disk' message */
1125 mateusz.vi 891
        goto RETRY_ENTIRE_LIST;
892
      }
893
      goto TRY_NEXTPKG;
894
    }
895
 
192 mateuszvis 896
    /* install the package */
624 mateuszvis 897
    snprintf(buff, sizeof(buff), svarlang_strid(0x0400), i+1, pkglistlen, pkgptr); /* "Installing package %d/%d: %s" */
36 mv_fox 898
    strcat(buff, "       ");
1664 mateusz.vi 899
    mdr_cout_str(10, 1, buff, COLOR_BODY, 40);
1125 mateusz.vi 900
 
901
    /* proceed with package copy */
902
    sprintf(buff, "%c:\\temp\\%s.svp", targetdrv, pkgptr);
903
    if (fcopy(buff, buff + 7, buff, sizeof(buff)) != 0) {
1664 mateusz.vi 904
      mdr_cout_str(10, 30, "READ ERROR", COLOR_BODY, 80);
1661 mateusz.vi 905
      mdr_dos_getkey();
280 mateuszvis 906
      fclose(fd);
192 mateuszvis 907
      return(-1);
55 mv_fox 908
    }
280 mateuszvis 909
    /* write install instruction to post-install script */
700 mateusz.vi 910
    fprintf(fd, "pkg install %s.svp\r\ndel %s.svp\r\n", pkgptr, pkgptr);
1125 mateusz.vi 911
    /* jump to next entry or end of list and zero out the pkg name in the process */
912
    while ((*pkgptr != 0) && (*pkgptr != 0xff)) {
913
      *pkgptr = 0;
914
      pkgptr++;
915
    }
28 mv_fox 916
  }
280 mateuszvis 917
  /* set up locales so the "installation over" message is nicely displayed */
918
  genlocalesconf(fd, locales);
919
  /* replace autoexec.bat and config.sys now and write some nice message on screen */
920
  fprintf(fd, "DEL pkg.exe\r\n"
1828 mateusz.vi 921
              "DEL C:\\CONFIG.SYS\r\n"
280 mateuszvis 922
              "COPY CONFIG.SYS C:\\\r\n"
923
              "DEL CONFIG.SYS\r\n"
924
              "DEL C:\\AUTOEXEC.BAT\r\n"
925
              "COPY AUTOEXEC.BAT C:\\\r\n"
1104 mateusz.vi 926
              "DEL AUTOEXEC.BAT\r\n"
1109 bttr 927
              "SET COMSPEC=C:\\COMMAND.COM\r\n"
1104 mateusz.vi 928
              "DEL \\CMD.COM\r\n");
280 mateuszvis 929
  /* print out the "installation over" message */
930
  fprintf(fd, "ECHO.\r\n"
868 mateusz.vi 931
              "ECHO ");
1673 mateusz.vi 932
  fprintf(fd, svarlang_strid(0x0502), BUILDSTRING); /* "SvarDOS installation is over. Please restart your computer now" */
868 mateusz.vi 933
  fprintf(fd, "\r\n"
934
              "ECHO.\r\n");
280 mateuszvis 935
  fclose(fd);
936
 
1828 mateusz.vi 937
  /* dummy config.sys with a SHELL directive, EDR does not call command.com
938
   * with /P otherwise, see https://github.com/SvarDOS/edrdos/issues/74 */
939
  snprintf(buff, sizeof(buff), "%c:\\config.sys", targetdrv);
940
  fd = fopen(buff, "wb");
941
  if (fd == NULL) return(-1);
942
  fprintf(fd, "SHELL=C:\\COMMAND.COM /P\r\n");
943
  fclose(fd);
944
 
280 mateuszvis 945
  /* prepare a dummy autoexec.bat that will call temp\postinst.bat */
946
  snprintf(buff, sizeof(buff), "%c:\\autoexec.bat", targetdrv);
947
  fd = fopen(buff, "wb");
948
  if (fd == NULL) return(-1);
949
  fprintf(fd, "@ECHO OFF\r\n"
950
              "SET DOSDIR=C:\\SVARDOS\r\n"
951
              "SET NLSPATH=%%DOSDIR%%\\NLS\r\n"
1659 bttr 952
              "PATH %%DOSDIR%%\r\n");
280 mateuszvis 953
  fprintf(fd, "CD TEMP\r\n"
954
              "postinst.bat\r\n");
955
  fclose(fd);
956
 
192 mateuszvis 957
  return(0);
28 mv_fox 958
}
959
 
960
 
42 mv_fox 961
static void finalreboot(void) {
56 mv_fox 962
  int y = 9;
79 mv_fox 963
  newscreen(2);
1673 mateusz.vi 964
  y += putstringnls(y, 1, COLOR_BODY, 5, 0); /* "Your computer will reboot now." */
965
  y += putstringnls(y, 1, COLOR_BODYWARN, 5, 1); /* Please remove the installation disk from your drive" */
1664 mateusz.vi 966
  putstringnls(++y, 1, COLOR_BODY, 0, 5); /* "Press any key..." */
1661 mateusz.vi 967
  mdr_dos_getkey();
42 mv_fox 968
  reboot();
969
}
970
 
971
 
192 mateuszvis 972
static void loadcp(const struct slocales *locales) {
42 mv_fox 973
  char buff[64];
67 mv_fox 974
  if (locales->codepage == 437) return;
1662 mateusz.vi 975
  mdr_cout_locate(1, 0);
67 mv_fox 976
  if (locales->egafile == 1) {
310 mateuszvis 977
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA.CPX) > NUL", locales->codepage);
42 mv_fox 978
  } else {
310 mateuszvis 979
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
42 mv_fox 980
  }
981
  system(buff);
67 mv_fox 982
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
42 mv_fox 983
  system(buff);
984
  /* below I re-init the video controller - apparently this is required if
65 mv_fox 985
   * I want the new glyph symbols to be actually applied, at least some
986
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
42 mv_fox 987
  {
988
  union REGS r;
989
  r.h.ah = 0x0F; /* get current video mode */
990
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
56 mv_fox 991
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
992
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
42 mv_fox 993
  int86(0x10, &r, &r);
994
  }
995
}
996
 
200 mateuszvis 997
 
310 mateuszvis 998
#ifdef DEADCODE
193 mateuszvis 999
/* checks that drive drv contains SvarDOS packages
65 mv_fox 1000
 * returns 0 if found, non-zero otherwise */
193 mateuszvis 1001
static int checkinstsrc(char drv) {
1002
  char fname[16];
700 mateusz.vi 1003
  snprintf(fname, sizeof(fname), "%c:\\ATTRIB.SVP", drv);
1669 mateusz.vi 1004
  return(!fileexists(fname));
69 mv_fox 1005
}
310 mateuszvis 1006
#endif
65 mv_fox 1007
 
1008
 
1671 mateusz.vi 1009
int main(void) {
67 mv_fox 1010
  struct slocales locales;
28 mv_fox 1011
  int targetdrv;
193 mateuszvis 1012
  int sourcedrv;
73 mv_fox 1013
  int action;
28 mv_fox 1014
 
908 mateusz.vi 1015
  /* setup the internal int 24h handler ("always fail") */
1016
  int24hdl();
1017
 
1671 mateusz.vi 1018
  /* read the svardos build revision (from floppy label) */
1019
  {
1020
    const char *fspec = "*.*";
1021
    const char *res = (void*)0x9E; /* default DTA is at PSP:80h, field 1Eh of DTA is the ASCIZ file name */
868 mateusz.vi 1022
 
1671 mateusz.vi 1023
    _asm {
1024
      push cx
1025
      push dx
1026
 
1027
      mov ax, 0x4e00  /* findfirst */
1028
      mov cx, 0x08    /* file attr mask, 0x08 = volume label */
1029
      mov dx, fspec
1030
      int 0x21
1031
      jnc good
1672 mateusz.vi 1032
      mov bx, res
1033
      mov [bx], byte ptr 0
1671 mateusz.vi 1034
      good:
1035
 
1036
      pop dx
1037
      pop cx
1038
    }
1039
 
1040
    memcpy(BUILDSTRING, res, 12);
1041
  }
1042
 
310 mateuszvis 1043
  sourcedrv = get_cur_drive() + 'A';
53 mv_fox 1044
 
1664 mateusz.vi 1045
  /* init screen and detect mono adapters */
1046
  if (mdr_cout_init(NULL, NULL) == 0) {
1047
    /* overload color scheme with mono settings */
1048
    COLOR_TITLEBAR = 0x70;
1671 mateusz.vi 1049
    COLOR_TITLEVER = 0x70;
1664 mateusz.vi 1050
    COLOR_BODY = 0x07;
1673 mateusz.vi 1051
    COLOR_BODYWARN = 0x07;
1664 mateusz.vi 1052
    COLOR_SELECT = 0x70;
1053
    COLOR_SELECTCUR = 0x07;
1054
  }
29 mv_fox 1055
 
73 mv_fox 1056
 SelectLang:
190 mateuszvis 1057
  action = selectlang(&locales); /* welcome to svardos, select your language */
73 mv_fox 1058
  if (action != MENUNEXT) goto Quit;
1059
  loadcp(&locales);
1462 mateusz.vi 1060
  svarlang_load("INSTALL.LNG", locales.lang); /* NLS support */
865 mateusz.vi 1061
 
73 mv_fox 1062
  action = selectkeyb(&locales);  /* what keyb layout should we use? */
1063
  if (action == MENUQUIT) goto Quit;
1669 mateusz.vi 1064
  if (action == MENUPREV) {
1065
    if (!fileexists("INSTALL.LNG")) goto Quit;
1066
    goto SelectLang;
1067
  }
73 mv_fox 1068
 
1069
 WelcomeScreen:
190 mateuszvis 1070
  action = welcomescreen(); /* what svardos is, ask whether to run live dos or install */
73 mv_fox 1071
  if (action == MENUQUIT) goto Quit;
1669 mateusz.vi 1072
  if (action == MENUPREV) goto SelectLang;
1073
 
312 mateuszvis 1074
  targetdrv = preparedrive(sourcedrv); /* what drive should we install from? check avail. space */
73 mv_fox 1075
  if (targetdrv == MENUQUIT) goto Quit;
1076
  if (targetdrv == MENUPREV) goto WelcomeScreen;
280 mateuszvis 1077
  bootfilesgen(targetdrv, &locales); /* generate boot files and other configurations */
1671 mateusz.vi 1078
  if (installpackages(targetdrv, sourcedrv, &locales) != 0) goto Quit;    /* install packages */
73 mv_fox 1079
  /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
1080
  /*netcfg();*/ /* basic networking config */
1081
  finalreboot(); /* remove the CD and reboot */
1082
 
1083
 Quit:
1662 mateusz.vi 1084
  mdr_cout_locate(0, 0);
1085
  mdr_cout_close();
28 mv_fox 1086
  return(0);
1087
}