Subversion Repositories SvarDOS

Rev

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