Subversion Repositories SvarDOS

Rev

Rev 67 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 67 Rev 69
1
/*
1
/*
2
 * SVAROG386 INSTALL
2
 * SVAROG386 INSTALL
3
 * COPYRIGHT (C) 2016 MATEUSZ VISTE
3
 * COPYRIGHT (C) 2016 MATEUSZ VISTE
4
 *
4
 *
5
 * http://svarog386.sf.net
5
 * http://svarog386.sf.net
6
 */
6
 */
7
 
7
 
8
#include <dos.h>
8
#include <dos.h>
9
#include <direct.h>  /* mkdir() */
9
#include <direct.h>  /* mkdir() */
10
#include <stdio.h>   /* printf() and friends */
10
#include <stdio.h>   /* printf() and friends */
11
#include <stdlib.h>  /* system() */
11
#include <stdlib.h>  /* system() */
12
#include <string.h>  /* memcpy() */
12
#include <string.h>  /* memcpy() */
13
#include <unistd.h>
13
#include <unistd.h>
14
 
14
 
15
#include "kitten\kitten.h"
15
#include "kitten\kitten.h"
16
 
16
 
17
#include "cdrom.h"
17
#include "cdrom.h"
18
#include "input.h"
18
#include "input.h"
19
#include "video.h"
19
#include "video.h"
20
 
20
 
21
/* keyboard layouts and locales */
21
/* keyboard layouts and locales */
22
#include "keylay.h"
22
#include "keylay.h"
23
#include "keyoff.h"
23
#include "keyoff.h"
24
 
24
 
25
/* color scheme (color, mono) */
25
/* color scheme (color, mono) */
26
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
26
static unsigned short COLOR_TITLEBAR[2] = {0x7000,0x7000};
27
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
27
static unsigned short COLOR_BODY[2] = {0x1700,0x0700};
28
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
28
static unsigned short COLOR_SELECT[2] = {0x7000,0x7000};
29
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
29
static unsigned short COLOR_SELECTCUR[2] = {0x1F00,0x0700};
30
 
30
 
31
/* mono flag */
31
/* mono flag */
32
static int mono = 0;
32
static int mono = 0;
33
 
33
 
34
/* how much disk space does Svarog386 require (in MiB) */
34
/* how much disk space does Svarog386 require (in MiB) */
35
#define SVAROG_DISK_REQ 8
35
#define SVAROG_DISK_REQ 8
36
 
36
 
37
/* a convenience 'function' used for debugging */
37
/* a convenience 'function' used for debugging */
38
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
38
#define DBG(x) { video_putstringfix(24, 0, 0x4F00u, x, 80); }
39
 
39
 
40
struct slocales {
40
struct slocales {
41
  char lang[4];
41
  char lang[4];
42
  char *keybcode;
42
  char *keybcode;
43
  unsigned int codepage;
43
  unsigned int codepage;
44
  int egafile;
44
  int egafile;
45
  int keybfile;
45
  int keybfile;
46
  int keyboff;
46
  int keyboff;
47
  int keyblen;
47
  int keyblen;
48
};
48
};
49
 
49
 
50
 
50
 
51
/* reboot the computer */
51
/* reboot the computer */
52
static void reboot(void) {
52
static void reboot(void) {
53
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
53
  void ((far *bootroutine)()) = (void (far *)()) 0xFFFF0000L;
54
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
54
  int far *rstaddr = (int far *)0x00400072L; /* BIOS boot flag is at 0040:0072 */
55
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
55
  *rstaddr = 0x1234; /* 0x1234 = warm boot, 0 = cold boot */
56
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
56
  (*bootroutine)(); /* jump to the BIOS reboot routine at FFFF:0000 */
57
}
57
}
58
 
58
 
59
 
59
 
60
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
60
/* outputs a string to screen with taking care of word wrapping. returns amount of lines. */
61
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
61
static int putstringwrap(int y, int x, unsigned short attr, char *s) {
62
  int linew, lincount;
62
  int linew, lincount;
63
  linew = 80;
63
  linew = 80;
64
  if (x >= 0) linew -= (x << 1);
64
  if (x >= 0) linew -= (x << 1);
65
 
65
 
66
  for (lincount = 1; y+lincount < 25; lincount++) {
66
  for (lincount = 1; y+lincount < 25; lincount++) {
67
    int i, len = linew;
67
    int i, len = linew;
68
    for (i = 0; i <= linew; i++) {
68
    for (i = 0; i <= linew; i++) {
69
      if (s[i] == ' ') len = i;
69
      if (s[i] == ' ') len = i;
70
      if (s[i] == '\n') {
70
      if (s[i] == '\n') {
71
        len = i;
71
        len = i;
72
        break;
72
        break;
73
      }
73
      }
74
      if (s[i] == 0) {
74
      if (s[i] == 0) {
75
        len = i;
75
        len = i;
76
        break;
76
        break;
77
      }
77
      }
78
    }
78
    }
79
    video_putstring(y++, x, attr, s, len);
79
    video_putstring(y++, x, attr, s, len);
80
    s += len;
80
    s += len;
81
    if (*s == 0) break;
81
    if (*s == 0) break;
82
    s += 1; /* skip the whitespace char */
82
    s += 1; /* skip the whitespace char */
83
  }
83
  }
84
  return(lincount);
84
  return(lincount);
85
}
85
}
86
 
86
 
87
 
87
 
88
/* an NLS wrapper around video_putstring(), also performs line wrapping when
88
/* an NLS wrapper around video_putstring(), also performs line wrapping when
89
 * needed. returns the amount of lines that were output */
89
 * needed. returns the amount of lines that were output */
90
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
90
static int putstringnls(int y, int x, unsigned short attr, int nlsmaj, int nlsmin, char *s) {
91
  s = kittengets(nlsmaj, nlsmin, s);
91
  s = kittengets(nlsmaj, nlsmin, s);
92
  return(putstringwrap(y, x, attr, s));
92
  return(putstringwrap(y, x, attr, s));
93
}
93
}
94
 
94
 
95
 
95
 
96
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
96
static int menuselect(int ypos, int xpos, int height, char **list, int listlen) {
97
  int i, offset = 0, res = 0, count, width = 0;
97
  int i, offset = 0, res = 0, count, width = 0;
98
  /* count how many positions there is, and check their width */
98
  /* count how many positions there is, and check their width */
99
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
99
  for (count = 0; (list[count] != NULL) && (count != listlen); count++) {
100
    int len = strlen(list[count]);
100
    int len = strlen(list[count]);
101
    if (len > width) width = len;
101
    if (len > width) width = len;
102
  }
102
  }
103
 
103
 
104
  /* if xpos negative, means 'center out' */
104
  /* if xpos negative, means 'center out' */
105
  if (xpos < 0) xpos = 39 - (width >> 1);
105
  if (xpos < 0) xpos = 39 - (width >> 1);
106
 
106
 
107
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
107
  video_putchar(ypos, xpos+width+2, COLOR_SELECT[mono], 0xBF);         /*       \ */
108
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
108
  video_putchar(ypos, xpos-1, COLOR_SELECT[mono], 0xDA);               /*  /      */
109
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
109
  video_putchar(ypos+height-1, xpos-1, COLOR_SELECT[mono], 0xC0);      /*  \      */
110
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
110
  video_putchar(ypos+height-1, xpos+width+2, COLOR_SELECT[mono], 0xD9);/*      /  */
111
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
111
  video_putcharmulti(ypos, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
112
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
112
  video_putcharmulti(ypos+height-1, xpos, COLOR_SELECT[mono], 0xC4, width + 2, 1);
113
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
113
  video_putcharmulti(ypos+1, xpos-1, COLOR_SELECT[mono], 0xB3, height - 2, 80);
114
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
114
  video_putcharmulti(ypos+1, xpos+width+2, COLOR_SELECT[mono], 0xB3, height - 2, 80);
115
 
115
 
116
  for (;;) {
116
  for (;;) {
117
    int key;
117
    int key;
118
    /* list of selectable items */
118
    /* list of selectable items */
119
    for (i = 0; i < height - 2; i++) {
119
    for (i = 0; i < height - 2; i++) {
120
      if (i + offset == res) {
120
      if (i + offset == res) {
121
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
121
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECTCUR[mono], 16);
122
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
122
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECTCUR[mono], 17);
123
        video_movecursor(ypos + 1 + i, xpos);
123
        video_movecursor(ypos + 1 + i, xpos);
124
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
124
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECTCUR[mono], list[i + offset], width);
125
      } else if (i + offset < count) {
125
      } else if (i + offset < count) {
126
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
126
        video_putchar(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ');
127
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
127
        video_putchar(ypos + 1 + i, xpos+width+1, COLOR_SELECT[mono], ' ');
128
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
128
        video_putstringfix(ypos + 1 + i, xpos+1, COLOR_SELECT[mono], list[i + offset], width);
129
      } else {
129
      } else {
130
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
130
        video_putcharmulti(ypos + 1 + i, xpos, COLOR_SELECT[mono], ' ', width+2, 1);
131
      }
131
      }
132
    }
132
    }
133
    key = input_getkey();
133
    key = input_getkey();
134
    if (key == 0x0D) { /* ENTER */
134
    if (key == 0x0D) { /* ENTER */
135
      return(res);
135
      return(res);
136
    } else if (key == 0x148) { /* up */
136
    } else if (key == 0x148) { /* up */
137
      if (res > 0) {
137
      if (res > 0) {
138
        res--;
138
        res--;
139
        if (res < offset) offset = res;
139
        if (res < offset) offset = res;
140
      }
140
      }
141
    } else if (key == 0x150) { /* down */
141
    } else if (key == 0x150) { /* down */
142
      if (res+1 < count) {
142
      if (res+1 < count) {
143
        res++;
143
        res++;
144
        if (res > offset + height - 3) offset = res - (height - 3);
144
        if (res > offset + height - 3) offset = res - (height - 3);
145
      }
145
      }
146
    } else if (key == 0x147) { /* home */
146
    } else if (key == 0x147) { /* home */
147
      res = 0;
147
      res = 0;
148
      offset = 0;
148
      offset = 0;
149
    } else if (key == 0x14F) { /* end */
149
    } else if (key == 0x14F) { /* end */
150
      res = count - 1;
150
      res = count - 1;
151
      if (res > offset + height - 3) offset = res - (height - 3);
151
      if (res > offset + height - 3) offset = res - (height - 3);
152
    } else if (key == 0x1B) {  /* ESC */
152
    } else if (key == 0x1B) {  /* ESC */
153
      return(-1);
153
      return(-1);
154
    } else {
154
    } else {
155
      char buf[8];
155
      char buf[8];
156
      snprintf(buf, sizeof(buf), "0x%02X ", key);
156
      snprintf(buf, sizeof(buf), "0x%02X ", key);
157
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
157
      video_putstring(1, 0, COLOR_BODY[mono], buf, -1);
158
    }
158
    }
159
  }
159
  }
160
}
160
}
161
 
161
 
162
static void newscreen(void) {
162
static void newscreen(void) {
163
  int x;
163
  int x;
164
  char *title;
164
  char *title;
165
  title = kittengets(0, 0, "SVAROG386 INSTALLATION");
165
  title = kittengets(0, 0, "SVAROG386 INSTALLATION");
166
  for (x = 0; x < 80; x++) video_putchar(0, x, COLOR_TITLEBAR[mono], ' ');
166
  for (x = 0; x < 80; x++) video_putchar(0, x, COLOR_TITLEBAR[mono], ' ');
167
  video_putstring(0, 40 - (strlen(title) >> 1), COLOR_TITLEBAR[mono], title, -1);
167
  video_putstring(0, 40 - (strlen(title) >> 1), COLOR_TITLEBAR[mono], title, -1);
168
  video_clear(COLOR_BODY[mono], 80);
168
  video_clear(COLOR_BODY[mono], 80);
169
  video_movecursor(25,0);
169
  video_movecursor(25,0);
170
}
170
}
171
 
171
 
172
static int selectlang(struct slocales *locales) {
172
static int selectlang(struct slocales *locales) {
173
  int choice, x;
173
  int choice, x;
174
  char *msg;
174
  char *msg;
175
  char *langlist[] = {
175
  char *langlist[] = {
176
    "English",
176
    "English",
177
    "French",
177
    "French",
178
    "Polish",
178
    "Polish",
179
    "Turkish",
179
    "Turkish",
180
    NULL
180
    NULL
181
  };
181
  };
182
 
182
 
183
  newscreen();
183
  newscreen();
184
  msg = kittengets(1, 0, "Welcome to Svarog386");
184
  msg = kittengets(1, 0, "Welcome to Svarog386");
185
  x = 40 - (strlen(msg) >> 1);
185
  x = 40 - (strlen(msg) >> 1);
186
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
186
  video_putstring(4, x, COLOR_BODY[mono], msg, -1);
187
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
187
  video_putcharmulti(5, x, COLOR_BODY[mono], '=', strlen(msg), 1);
188
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
188
  putstringnls(8, -1, COLOR_BODY[mono], 1, 1, "Please select your language from the list below:");
189
  choice = menuselect(11, -1, 6, langlist, -1);
189
  choice = menuselect(11, -1, 6, langlist, -1);
190
  if (choice < 0) return(-1);
190
  if (choice < 0) return(-1);
191
  /* populate locales with default values */
191
  /* populate locales with default values */
192
  memset(locales, 0, sizeof(struct slocales));
192
  memset(locales, 0, sizeof(struct slocales));
193
  switch (choice) {
193
  switch (choice) {
194
    case 1:
194
    case 1:
195
      strcpy(locales->lang, "FR");
195
      strcpy(locales->lang, "FR");
196
      locales->keyboff = OFFLOC_FR;
196
      locales->keyboff = OFFLOC_FR;
197
      locales->keyblen = OFFLEN_FR;
197
      locales->keyblen = OFFLEN_FR;
198
      break;
198
      break;
199
    case 2:
199
    case 2:
200
      strcpy(locales->lang, "PL");
200
      strcpy(locales->lang, "PL");
201
      locales->keyboff = OFFLOC_PL;
201
      locales->keyboff = OFFLOC_PL;
202
      locales->keyblen = OFFLEN_PL;
202
      locales->keyblen = OFFLEN_PL;
203
      break;
203
      break;
204
    case 3:
204
    case 3:
205
      strcpy(locales->lang, "TR");
205
      strcpy(locales->lang, "TR");
206
      locales->keyboff = OFFLOC_TR;
206
      locales->keyboff = OFFLOC_TR;
207
      locales->keyblen = OFFLEN_TR;
207
      locales->keyblen = OFFLEN_TR;
208
      break;
208
      break;
209
    default:
209
    default:
210
      strcpy(locales->lang, "EN");
210
      strcpy(locales->lang, "EN");
211
      locales->keyboff = 0;
211
      locales->keyboff = 0;
212
      locales->keyblen = OFFCOUNT;
212
      locales->keyblen = OFFCOUNT;
213
      break;
213
      break;
214
  }
214
  }
215
  /* populate the slocales struct */
215
  /* populate the slocales struct */
216
  for (msg = kblayouts[locales->keyboff]; *msg != 0; msg++); /* skip layout name */
216
  for (msg = kblayouts[locales->keyboff]; *msg != 0; msg++); /* skip layout name */
217
  msg++;
217
  msg++;
218
  /* skip keyb code and copy it to locales.keybcode */
218
  /* skip keyb code and copy it to locales.keybcode */
219
  locales->keybcode = msg;
219
  locales->keybcode = msg;
220
  for (; *msg != 0; msg++);
220
  for (; *msg != 0; msg++);
221
  /* */
221
  /* */
222
  locales->codepage = ((unsigned short)msg[1] << 8) | msg[2];
222
  locales->codepage = ((unsigned short)msg[1] << 8) | msg[2];
223
  locales->egafile = msg[3];
223
  locales->egafile = msg[3];
224
  locales->keybfile = msg[4];
224
  locales->keybfile = msg[4];
225
  /* */
225
  /* */
226
  return(0);
226
  return(0);
227
}
227
}
228
 
228
 
229
 
229
 
230
#define LTODEC(x, y) ((unsigned short)(x << 8) | (y))
230
#define LTODEC(x, y) ((unsigned short)(x << 8) | (y))
231
static int selectkeyb(struct slocales *locales) {
231
static int selectkeyb(struct slocales *locales) {
232
  int keyboff, keyblen, menuheight;
232
  int keyboff, keyblen, menuheight;
233
  unsigned short lang;
233
  unsigned short lang;
234
  lang = LTODEC(locales->lang[0], locales->lang[1]);
234
  lang = LTODEC(locales->lang[0], locales->lang[1]);
235
 
235
 
236
  switch (lang) {
236
  switch (lang) {
237
    case LTODEC('F', 'R'):
237
    case LTODEC('F', 'R'):
238
      keyboff = OFFLOC_FR;
238
      keyboff = OFFLOC_FR;
239
      keyblen = OFFLEN_FR;
239
      keyblen = OFFLEN_FR;
240
      break;
240
      break;
241
    case LTODEC('P', 'L'):
241
    case LTODEC('P', 'L'):
242
      keyboff = OFFLOC_PL;
242
      keyboff = OFFLOC_PL;
243
      keyblen = OFFLEN_PL;
243
      keyblen = OFFLEN_PL;
244
      break;
244
      break;
245
    case LTODEC('T', 'R'):
245
    case LTODEC('T', 'R'):
246
      keyboff = OFFLOC_TR;
246
      keyboff = OFFLOC_TR;
247
      keyblen = OFFLEN_TR;
247
      keyblen = OFFLEN_TR;
248
      break;
248
      break;
249
    default: /* otherwise propose all possible keyoard layouts */
249
    default: /* otherwise propose all possible keyoard layouts */
250
      keyboff = 0;
250
      keyboff = 0;
251
      keyblen = OFFCOUNT;
251
      keyblen = OFFCOUNT;
252
      break;
252
      break;
253
  }
253
  }
254
  if (keyblen == 1) return(0); /* do not ask for keyboard layout if only one is available for given language */
254
  if (keyblen == 1) return(0); /* do not ask for keyboard layout if only one is available for given language */
255
  newscreen();
255
  newscreen();
256
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "Svarog386 supports the keyboard layouts used in different countries. Choose the keyboard layout you want.");
256
  putstringnls(5, 1, COLOR_BODY[mono], 1, 5, "Svarog386 supports the keyboard layouts used in different countries. Choose the keyboard layout you want.");
257
  menuheight = keyblen + 2;
257
  menuheight = keyblen + 2;
258
  if (menuheight > 13) menuheight = 13;
258
  if (menuheight > 13) menuheight = 13;
259
  if (menuselect(10, -1, menuheight, &(kblayouts[keyboff]), keyblen) < 0) return(-1);
259
  if (menuselect(10, -1, menuheight, &(kblayouts[keyboff]), keyblen) < 0) return(-1);
260
  return(0);
260
  return(0);
261
}
261
}
262
 
262
 
263
 
263
 
264
/* returns 0 if installation must proceed, non-zero otherwise */
264
/* returns 0 if installation must proceed, non-zero otherwise */
265
static int welcomescreen(void) {
265
static int welcomescreen(void) {
266
  char *choice[] = {"Install Svarog386 to disk", "Quit to DOS", NULL};
266
  char *choice[] = {"Install Svarog386 to disk", "Quit to DOS", NULL};
267
  choice[0] = kittengets(0, 1, choice[0]);
267
  choice[0] = kittengets(0, 1, choice[0]);
268
  choice[1] = kittengets(0, 2, choice[1]);
268
  choice[1] = kittengets(0, 2, choice[1]);
269
  newscreen();
269
  newscreen();
270
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install Svarog386: a free, MSDOS-compatible operating system based on the FreeDOS kernel. Svarog386 targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once Svarog386 is installed.");
270
  putstringnls(4, 1, COLOR_BODY[mono], 2, 0, "You are about to install Svarog386: a free, MSDOS-compatible operating system based on the FreeDOS kernel. Svarog386 targets 386+ computers and comes with a variety of third-party applications.\n\nWARNING: If your PC has another operating system installed, this other system might be unable to boot once Svarog386 is installed.");
271
  return(menuselect(13, -1, 4, choice, -1));
271
  return(menuselect(13, -1, 4, choice, -1));
272
}
272
}
273
 
273
 
274
 
274
 
275
/* returns 1 if drive is removable, 0 if not, -1 on error */
275
/* returns 1 if drive is removable, 0 if not, -1 on error */
276
static int isdriveremovable(int drv) {
276
static int isdriveremovable(int drv) {
277
  union REGS r;
277
  union REGS r;
278
  r.x.ax = 0x4408;
278
  r.x.ax = 0x4408;
279
  r.h.bl = drv;
279
  r.h.bl = drv;
280
  int86(0x21, &r, &r);
280
  int86(0x21, &r, &r);
281
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
281
  /* CF set on error, AX set to 0 if removable, 1 if fixed */
282
  if (r.x.cflag != 0) return(-1);
282
  if (r.x.cflag != 0) return(-1);
283
  if (r.x.ax == 0) return(1);
283
  if (r.x.ax == 0) return(1);
284
  return(0);
284
  return(0);
285
}
285
}
286
 
286
 
287
 
287
 
288
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
288
/* returns total disk space of drive drv (in MiB, max 2048), or -1 if drive invalid */
289
static int disksize(int drv) {
289
static int disksize(int drv) {
290
  long res;
290
  long res;
291
  union REGS r;
291
  union REGS r;
292
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
292
  r.h.ah = 0x36; /* DOS 2+ get free disk space */
293
  r.h.dl = drv;
293
  r.h.dl = drv;
294
  int86(0x21, &r, &r);
294
  int86(0x21, &r, &r);
295
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
295
  if (r.x.ax == 0xffffu) return(-1); /* AX set to FFFFh if drive invalid */
296
  res = r.x.ax;  /* sectors per cluster */
296
  res = r.x.ax;  /* sectors per cluster */
297
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
297
  res *= r.x.dx; /* dx contains total clusters, bx contains free clusters */
298
  res *= r.x.cx; /* bytes per sector */
298
  res *= r.x.cx; /* bytes per sector */
299
  res >>= 20;    /* convert bytes to MiB */
299
  res >>= 20;    /* convert bytes to MiB */
300
  return(res);
300
  return(res);
301
}
301
}
302
 
302
 
303
 
303
 
304
/* returns 0 if disk is empty, non-zero otherwise */
304
/* returns 0 if disk is empty, non-zero otherwise */
305
static int diskempty(int drv) {
305
static int diskempty(int drv) {
306
  unsigned int rc;
306
  unsigned int rc;
307
  int res;
307
  int res;
308
  char buff[8];
308
  char buff[8];
309
  struct find_t fileinfo;
309
  struct find_t fileinfo;
310
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
310
  snprintf(buff, sizeof(buff), "%c:\\*.*", 'A' + drv - 1);
311
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
311
  rc = _dos_findfirst(buff, _A_NORMAL | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM, &fileinfo);
312
  if (rc == 0) {
312
  if (rc == 0) {
313
    res = 1; /* call successfull means disk is not empty */
313
    res = 1; /* call successfull means disk is not empty */
314
  } else {
314
  } else {
315
    res = 0;
315
    res = 0;
316
  }
316
  }
317
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
317
  /* _dos_findclose(&fileinfo); */ /* apparently required only on OS/2 */
318
  return(res);
318
  return(res);
319
}
319
}
320
 
320
 
321
 
321
 
322
static int preparedrive(void) {
322
static int preparedrive(void) {
323
  int driveremovable;
323
  int driveremovable;
324
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
324
  int selecteddrive = 3; /* hardcoded to 'C:' for now */
325
  int cselecteddrive;
325
  int cselecteddrive;
326
  int ds;
326
  int ds;
327
  char buff[1024];
327
  char buff[1024];
328
  cselecteddrive = 'A' + selecteddrive - 1;
328
  cselecteddrive = 'A' + selecteddrive - 1;
329
  for (;;) {
329
  for (;;) {
330
    newscreen();
330
    newscreen();
331
    driveremovable = isdriveremovable(selecteddrive);
331
    driveremovable = isdriveremovable(selecteddrive);
332
    if (driveremovable < 0) {
332
    if (driveremovable < 0) {
333
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
333
      char *list[] = { "Create a partition automatically", "Run the FDISK partitioning tool", "Quit to DOS", NULL};
334
      list[0] = kittengets(0, 3, list[0]);
334
      list[0] = kittengets(0, 3, list[0]);
335
      list[1] = kittengets(0, 4, list[1]);
335
      list[1] = kittengets(0, 4, list[1]);
336
      list[2] = kittengets(0, 2, list[2]);
336
      list[2] = kittengets(0, 2, list[2]);
337
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so Svarog386 can be installed on it. Note, that Svarog386 requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVAROG_DISK_REQ);
337
      snprintf(buff, sizeof(buff), kittengets(3, 0, "ERROR: Drive %c: could not be found. Perhaps your hard disk needs to be partitioned first. Please create at least one partition on your hard disk, so Svarog386 can be installed on it. Note, that Svarog386 requires at least %d MiB of available disk space.\n\nYou can use the FDISK partitioning tool for creating the required partition manually, or you can let the installer partitioning your disk automatically. You can also abort the installation to use any other partition manager of your choice."), cselecteddrive, SVAROG_DISK_REQ);
338
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
338
      putstringwrap(4, 1, COLOR_BODY[mono], buff);
339
      switch (menuselect(14, -1, 5, list, -1)) {
339
      switch (menuselect(14, -1, 5, list, -1)) {
340
        case 0:
340
        case 0:
341
          system("FDISK /AUTO");
341
          system("FDISK /AUTO");
342
          break;
342
          break;
343
        case 1:
343
        case 1:
344
          video_clear(0x0700, 0);
344
          video_clear(0x0700, 0);
345
          video_movecursor(0, 0);
345
          video_movecursor(0, 0);
346
          system("FDISK");
346
          system("FDISK");
347
          break;
347
          break;
348
        default:
348
        default:
349
          return(-1);
349
          return(-1);
350
      }
350
      }
351
      newscreen();
351
      newscreen();
352
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
352
      putstringnls(10, 10, COLOR_BODY[mono], 3, 1, "Your computer will reboot now.");
353
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
353
      putstringnls(12, 10, COLOR_BODY[mono], 0, 5, "Press any key...");
354
      input_getkey();
354
      input_getkey();
355
      reboot();
355
      reboot();
356
      return(-1);
356
      return(-1);
357
    } else if (driveremovable > 0) {
357
    } else if (driveremovable > 0) {
358
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
358
      snprintf(buff, sizeof(buff), kittengets(3, 2, "ERROR: Drive %c: is a removable device. Installation aborted."), cselecteddrive);
359
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
359
      video_putstring(9, 1, COLOR_BODY[mono], buff, -1);
360
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
360
      putstringnls(11, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
361
      return(-1);
361
      return(-1);
362
    }
362
    }
363
    /* if not formatted, propose to format it right away (try to create a directory) */
363
    /* if not formatted, propose to format it right away (try to create a directory) */
364
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
364
    snprintf(buff, sizeof(buff), "%c:\\SVWRTEST.123", cselecteddrive);
365
    if (mkdir(buff) == 0) {
365
    if (mkdir(buff) == 0) {
366
      rmdir(buff);
366
      rmdir(buff);
367
    } else {
367
    } else {
368
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
368
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
369
      list[0] = kittengets(0, 6, list[0]);
369
      list[0] = kittengets(0, 6, list[0]);
370
      list[1] = kittengets(0, 2, list[1]);
370
      list[1] = kittengets(0, 2, list[1]);
371
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
371
      snprintf(buff, sizeof(buff), kittengets(3, 3, "ERROR: Drive %c: seems to be unformated. Do you wish to format it?"), cselecteddrive);
372
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
372
      video_putstring(7, 1, COLOR_BODY[mono], buff, -1);
373
      if (menuselect(12, -1, 4, list, -1) != 0) return(-1);
373
      if (menuselect(12, -1, 4, list, -1) != 0) return(-1);
374
      video_clear(0x0700, 0);
374
      video_clear(0x0700, 0);
375
      video_movecursor(0, 0);
375
      video_movecursor(0, 0);
376
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
376
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
377
      system(buff);
377
      system(buff);
378
      continue;
378
      continue;
379
    }
379
    }
380
    /* check total disk space */
380
    /* check total disk space */
381
    ds = disksize(selecteddrive);
381
    ds = disksize(selecteddrive);
382
    if (ds < SVAROG_DISK_REQ) {
382
    if (ds < SVAROG_DISK_REQ) {
383
      int y = 9;
383
      int y = 9;
384
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! Svarog386 requires a disk of at least %d MiB."), cselecteddrive);
384
      snprintf(buff, sizeof(buff), kittengets(3, 4, "ERROR: Drive %c: is not big enough! Svarog386 requires a disk of at least %d MiB."), cselecteddrive);
385
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
385
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
386
      putstringnls(++y, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
386
      putstringnls(++y, 2, COLOR_BODY[mono], 0, 5, "Press any key...");
387
      input_getkey();
387
      input_getkey();
388
      return(-1);
388
      return(-1);
389
    }
389
    }
390
    /* is the disk empty? */
390
    /* is the disk empty? */
391
    if (diskempty(selecteddrive) != 0) {
391
    if (diskempty(selecteddrive) != 0) {
392
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
392
      char *list[] = { "Proceed with formatting", "Quit to DOS", NULL};
393
      int y = 6;
393
      int y = 6;
394
      list[0] = kittengets(0, 6, list[0]);
394
      list[0] = kittengets(0, 6, list[0]);
395
      list[1] = kittengets(0, 2, list[1]);
395
      list[1] = kittengets(0, 2, list[1]);
396
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. Svarog386 must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
396
      snprintf(buff, sizeof(buff), kittengets(3, 5, "ERROR: Drive %c: is not empty. Svarog386 must be installed on an empty disk.\n\nYou can format the disk now, to make it empty. Note however, that this will ERASE ALL CURRENT DATA on your disk."), cselecteddrive);
397
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
397
      y += putstringwrap(y, 1, COLOR_BODY[mono], buff);
398
      if (menuselect(++y, -1, 4, list, -1) != 0) return(-1);
398
      if (menuselect(++y, -1, 4, list, -1) != 0) return(-1);
399
      video_clear(0x0700, 0);
399
      video_clear(0x0700, 0);
400
      video_movecursor(0, 0);
400
      video_movecursor(0, 0);
401
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
401
      snprintf(buff, sizeof(buff), "FORMAT %c: /Q /U /Z:seriously /V:SVAROG386", cselecteddrive);
402
      system(buff);
402
      system(buff);
403
      continue;
403
      continue;
404
    } else {
404
    } else {
405
      /* final confirmation */
405
      /* final confirmation */
406
      char *list[] = { "Install Svarog386", "Quit to DOS", NULL};
406
      char *list[] = { "Install Svarog386", "Quit to DOS", NULL};
407
      list[0] = kittengets(0, 1, list[0]);
407
      list[0] = kittengets(0, 1, list[0]);
408
      list[1] = kittengets(0, 2, list[1]);
408
      list[1] = kittengets(0, 2, list[1]);
409
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of Svarog386 to %c: is about to begin."), cselecteddrive);
409
      snprintf(buff, sizeof(buff), kittengets(3, 6, "The installation of Svarog386 to %c: is about to begin."), cselecteddrive);
410
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
410
      video_putstring(7, -1, COLOR_BODY[mono], buff, -1);
411
      if (menuselect(10, -1, 4, list, -1) != 0) return(-1);
411
      if (menuselect(10, -1, 4, list, -1) != 0) return(-1);
412
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
412
      snprintf(buff, sizeof(buff), "SYS A: %c: > NUL", cselecteddrive);
413
      system(buff);
413
      system(buff);
414
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
414
      snprintf(buff, sizeof(buff), "%c:\\TEMP", cselecteddrive);
415
      mkdir(buff);
415
      mkdir(buff);
416
      return(cselecteddrive);
416
      return(cselecteddrive);
417
    }
417
    }
418
  }
418
  }
419
}
419
}
420
 
420
 
421
 
421
 
422
/* copy file src into dst, substituting all characters c1 by c2 */
422
/* copy file src into dst, substituting all characters c1 by c2 */
423
static void fcopysub(char *dst, char *src, char c1, char c2) {
423
static void fcopysub(char *dst, char *src, char c1, char c2) {
424
  FILE *fdd, *fds;
424
  FILE *fdd, *fds;
425
  int buff;
425
  int buff;
426
  fds = fopen(src, "rb");
426
  fds = fopen(src, "rb");
427
  if (fds == NULL) return;
427
  if (fds == NULL) return;
428
  fdd = fopen(dst, "wb");
428
  fdd = fopen(dst, "wb");
429
  if (fdd == NULL) {
429
  if (fdd == NULL) {
430
    fclose(fds);
430
    fclose(fds);
431
    return;
431
    return;
432
  }
432
  }
433
  /* */
433
  /* */
434
  for (;;) {
434
  for (;;) {
435
    buff = fgetc(fds);
435
    buff = fgetc(fds);
436
    if (buff == EOF) break;
436
    if (buff == EOF) break;
437
    if (buff == c1) buff = c2;
437
    if (buff == c1) buff = c2;
438
    fprintf(fdd, "%c", buff);
438
    fprintf(fdd, "%c", buff);
439
  }
439
  }
440
  /* close files and return */
440
  /* close files and return */
441
  fclose(fdd);
441
  fclose(fdd);
442
  fclose(fds);
442
  fclose(fds);
443
}
443
}
444
 
444
 
445
 
445
 
446
static void bootfilesgen(int targetdrv, struct slocales *locales, int cdromdrv) {
446
static void bootfilesgen(int targetdrv, struct slocales *locales, int cdromdrv) {
447
  char buff[128];
447
  char buff[128];
448
  FILE *fd;
448
  FILE *fd;
449
  /*** CONFIG.SYS ***/
449
  /*** CONFIG.SYS ***/
450
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
450
  snprintf(buff, sizeof(buff), "%c:\\CONFIG.SYS", targetdrv);
451
  fd = fopen(buff, "wb");
451
  fd = fopen(buff, "wb");
452
  if (fd == NULL) return;
452
  if (fd == NULL) return;
453
  fprintf(fd, "DOS=UMB,HIGH\r\n");
453
  fprintf(fd, "DOS=UMB,HIGH\r\n");
454
  fprintf(fd, "FILES=50\r\n");
454
  fprintf(fd, "FILES=50\r\n");
455
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVAROG.386\\BIN\\HIMEMX.EXE\r\n", targetdrv);
455
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\SVAROG.386\\BIN\\HIMEMX.EXE\r\n", targetdrv);
456
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVAROG.386\\BIN\\COMMAND.COM /E:512 /P\r\n", targetdrv);
456
  fprintf(fd, "SHELLHIGH=%c:\\SYSTEM\\SVAROG.386\\BIN\\COMMAND.COM /E:512 /P\r\n", targetdrv);
457
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
457
  fprintf(fd, "REM COUNTRY=001,437,%c:\\SYSTEM\\CONF\\COUNTRY.SYS\r\n", targetdrv);
458
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
458
  fprintf(fd, "DEVICE=%c:\\SYSTEM\\DRIVERS\\UDVD2\\UDVD2.SYS /D:SVCD0001 /H\r\n", targetdrv);
459
  fclose(fd);
459
  fclose(fd);
460
  /*** AUTOEXEC.BAT ***/
460
  /*** AUTOEXEC.BAT ***/
461
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
461
  snprintf(buff, sizeof(buff), "%c:\\AUTOEXEC.BAT", targetdrv);
462
  fd = fopen(buff, "wb");
462
  fd = fopen(buff, "wb");
463
  if (fd == NULL) return;
463
  if (fd == NULL) return;
464
  fprintf(fd, "@ECHO OFF\r\n");
464
  fprintf(fd, "@ECHO OFF\r\n");
465
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
465
  fprintf(fd, "SET TEMP=%c:\\TEMP\r\n", targetdrv);
466
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVAROG.386\r\n", targetdrv);
466
  fprintf(fd, "SET DOSDIR=%c:\\SYSTEM\\SVAROG.386\r\n", targetdrv);
467
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
467
  fprintf(fd, "SET NLSPATH=%%DOSDIR%%\\NLS\r\n");
468
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
468
  fprintf(fd, "SET LANG=%s\r\n", locales->lang);
469
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
469
  fprintf(fd, "SET DIRCMD=/OGNE/P/4\r\n");
470
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
470
  fprintf(fd, "SET FDNPKG.CFG=%c:\\SYSTEM\\CFG\\FDNPKG.CFG\r\n", targetdrv);
471
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
471
  fprintf(fd, "SET WATTCP.CFG=%c:\\SYSTEM\\CFG\\WATTCP.CFG\r\n", targetdrv);
472
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
472
  fprintf(fd, "PATH %%DOSDIR%%\\BIN;%c:\\SYSTEM\\LINKS\r\n", targetdrv);
473
  fprintf(fd, "PROMPT $P$G\r\n");
473
  fprintf(fd, "PROMPT $P$G\r\n");
474
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
474
  fprintf(fd, "ALIAS REBOOT=FDAPM COLDBOOT\r\n");
475
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
475
  fprintf(fd, "ALIAS HALT=FDAPM POWEROFF\r\n");
476
  fprintf(fd, "FDAPM APMDOS\r\n");
476
  fprintf(fd, "FDAPM APMDOS\r\n");
477
  fprintf(fd, "\r\n");
477
  fprintf(fd, "\r\n");
478
  if (locales->egafile > 0) {
478
  if (locales->egafile > 0) {
479
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
479
    fprintf(fd, "DISPLAY CON=(EGA,,1)\r\n");
480
    if (locales->egafile == 1) {
480
    if (locales->egafile == 1) {
481
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
481
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA.CPX)\r\n", locales->codepage, targetdrv);
482
    } else {
482
    } else {
483
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
483
      fprintf(fd, "MODE CON CP PREPARE=((%u) %c:\\SYSTEM\\SVAROG.386\\CPI\\EGA%d.CPX)\r\n", locales->codepage, targetdrv, locales->egafile);
484
    }
484
    }
485
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
485
    fprintf(fd, "MODE CON CP SELECT=%u\r\n", locales->codepage);
486
    if (locales->keybfile == 1) {
486
    if (locales->keybfile == 1) {
487
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBOARD.SYS\r\n", locales->keybcode, locales->codepage, targetdrv);
487
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBOARD.SYS\r\n", locales->keybcode, locales->codepage, targetdrv);
488
    } else {
488
    } else {
489
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBRD%d.SYS\r\n", locales->keybcode, locales->codepage, targetdrv, locales->keybfile);
489
      fprintf(fd, "KEYB %s,%d,%c:\\SYSTEM\\SVAROG.386\\BIN\\KEYBRD%d.SYS\r\n", locales->keybcode, locales->codepage, targetdrv, locales->keybfile);
490
    }
490
    }
491
    fprintf(fd, "\r\n");
491
    fprintf(fd, "\r\n");
492
  }
492
  }
493
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
493
  fprintf(fd, "SHSUCDX /d:SVCD0001\r\n");
494
  fprintf(fd, "\r\n");
494
  fprintf(fd, "\r\n");
495
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
495
  fprintf(fd, "REM Uncomment the line below for automatic mouse support\r\n");
496
  fprintf(fd, "REM CTMOUSE\r\n");
496
  fprintf(fd, "REM CTMOUSE\r\n");
497
  fprintf(fd, "\r\n");
497
  fprintf(fd, "\r\n");
498
  fprintf(fd, "ECHO.\r\n");
498
  fprintf(fd, "ECHO.\r\n");
499
  fprintf(fd, "ECHO Welcome to Svarog386! Type 'HELP' if you need help.\r\n");
499
  fprintf(fd, "ECHO Welcome to Svarog386! Type 'HELP' if you need help.\r\n");
500
  fclose(fd);
500
  fclose(fd);
501
  /*** CREATE DIRECTORY FOR OTHER CONFIGURATION FILES ***/
501
  /*** CREATE DIRECTORY FOR OTHER CONFIGURATION FILES ***/
502
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
502
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG", targetdrv);
503
  mkdir(buff);
503
  mkdir(buff);
504
  /*** FDNPKG.CFG ***/
504
  /*** FDNPKG.CFG ***/
505
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
505
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\CFG\\FDNPKG.CFG", targetdrv);
506
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
506
  fcopysub(buff, "A:\\DAT\\FDNPKG.CFG", '$', cdromdrv);
507
  /*** COUNTRY.SYS ***/
507
  /*** COUNTRY.SYS ***/
508
  /*** PICOTCP ***/
508
  /*** PICOTCP ***/
509
  /*** WATTCP ***/
509
  /*** WATTCP ***/
510
}
510
}
511
 
511
 
512
 
512
 
513
static void installpackages(int targetdrv, int cdromdrv) {
513
static void installpackages(int targetdrv, int cdromdrv) {
514
  char *pkglist[] = {
514
  char *pkglist[] = {
515
    "A:\\UDVD2", /* this one's not part of CORE, hence it's stored right on the floppy */
515
    "A:\\UDVD2", /* this one's not part of CORE, hence it's stored right on the floppy */
516
    "APPEND",
516
    "APPEND",
517
    "ASSIGN",
517
    "ASSIGN",
518
    "ATTRIB",
518
    "ATTRIB",
519
    "CHKDSK",
519
    "CHKDSK",
520
    "CHOICE",
520
    "CHOICE",
521
    "COMMAND",
521
    "COMMAND",
522
    "COMP",
522
    "COMP",
523
    "CPIDOS",
523
    "CPIDOS",
524
    "CTMOUSE",
524
    "CTMOUSE",
525
    "DEBUG",
525
    "DEBUG",
526
    "DEFRAG",
526
    "DEFRAG",
527
    "DELTREE",
527
    "DELTREE",
528
    "DEVLOAD",
528
    "DEVLOAD",
529
    "DISKCOMP",
529
    "DISKCOMP",
530
    "DISKCOPY",
530
    "DISKCOPY",
531
    "DISPLAY",
531
    "DISPLAY",
532
    "DOSFSCK",
532
    "DOSFSCK",
533
    "EDIT",
533
    "EDIT",
534
    "EDLIN",
534
    "EDLIN",
535
    "EXE2BIN",
535
    "EXE2BIN",
536
    "FC",
536
    "FC",
537
    "FDAPM",
537
    "FDAPM",
538
    "FDISK",
538
    "FDISK",
539
    "FDNPKG",
539
    "FDNPKG",
540
    "FIND",
540
    "FIND",
541
    "FORMAT",
541
    "FORMAT",
542
    "HELP",
542
    "HELP",
543
    "HIMEMX",
543
    "HIMEMX",
544
    "KERNEL",
544
    "KERNEL",
545
    "KEYB",
545
    "KEYB",
546
    "KEYB_LAY",
546
    "KEYB_LAY",
547
    "LABEL",
547
    "LABEL",
548
    "LBACACHE",
548
    "LBACACHE",
549
    "MEM",
549
    "MEM",
550
    "MIRROR",
550
    "MIRROR",
551
    "MODE",
551
    "MODE",
552
    "MORE",
552
    "MORE",
553
    "MOVE",
553
    "MOVE",
554
    "NANSI",
554
    "NANSI",
555
    "NLSFUNC",
555
    "NLSFUNC",
556
    "PRINT",
556
    "PRINT",
557
    "RDISK",
557
    "RDISK",
558
    "RECOVER",
558
    "RECOVER",
559
    "REPLACE",
559
    "REPLACE",
560
    "SHARE",
560
    "SHARE",
561
    "SHSUCDX",
561
    "SHSUCDX",
562
    "SORT",
562
    "SORT",
563
    "SWSUBST",
563
    "SWSUBST",
564
    "TREE",
564
    "TREE",
565
    "UNDELETE",
565
    "UNDELETE",
566
    "XCOPY",
566
    "XCOPY",
567
    NULL
567
    NULL
568
  };
568
  };
569
  int i, pkglistlen;
569
  int i, pkglistlen;
570
  char buff[64];
570
  char buff[64];
571
  newscreen();
571
  newscreen();
572
  /* count how long the pkg list is */
572
  /* count how long the pkg list is */
573
  for (pkglistlen = 0; pkglist[pkglistlen] != NULL; pkglistlen++);
573
  for (pkglistlen = 0; pkglist[pkglistlen] != NULL; pkglistlen++);
574
  /* set DOSDIR and friends */
574
  /* set DOSDIR and friends */
575
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVAROG.386", targetdrv);
575
  snprintf(buff, sizeof(buff), "%c:\\SYSTEM\\SVAROG.386", targetdrv);
576
  setenv("DOSDIR", buff, 1);
576
  setenv("DOSDIR", buff, 1);
577
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
577
  snprintf(buff, sizeof(buff), "%c:\\TEMP", targetdrv);
578
  setenv("TEMP", buff, 1);
578
  setenv("TEMP", buff, 1);
579
  /* install packages */
579
  /* install packages */
580
  for (i = 0; pkglist[i] != NULL; i++) {
580
  for (i = 0; pkglist[i] != NULL; i++) {
581
    char buff[128];
581
    char buff[128];
582
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkglist[i]);
582
    snprintf(buff, sizeof(buff), kittengets(4, 0, "Installing package %d/%d: %s"), i+1, pkglistlen, pkglist[i]);
583
    strcat(buff, "       ");
583
    strcat(buff, "       ");
584
    video_putstring(10, 1, COLOR_BODY[mono], buff, -1);
584
    video_putstring(10, 1, COLOR_BODY[mono], buff, -1);
585
    if (pkglist[i][1] == ':') {
585
    if (pkglist[i][1] == ':') {
586
      snprintf(buff, sizeof(buff), "FDINST INSTALL %s.ZIP > NUL", pkglist[i]);
586
      snprintf(buff, sizeof(buff), "FDINST INSTALL %s.ZIP > NUL", pkglist[i]);
587
    } else {
587
    } else {
588
      snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\CORE\\%s.ZIP > NUL", cdromdrv, pkglist[i]);
588
      snprintf(buff, sizeof(buff), "FDINST INSTALL %c:\\CORE\\%s.ZIP > NUL", cdromdrv, pkglist[i]);
589
    }
589
    }
590
    system(buff);
590
    system(buff);
591
  }
591
  }
592
}
592
}
593
 
593
 
594
 
594
 
595
static void finalreboot(void) {
595
static void finalreboot(void) {
596
  int y = 9;
596
  int y = 9;
597
  newscreen();
597
  newscreen();
598
  y += putstringnls(y, 2, COLOR_BODY[mono], 5, 0, "Svarog386 installation is over. Your computer will reboot now.\nPlease remove the installation disk from your drive.");
598
  y += putstringnls(y, 2, COLOR_BODY[mono], 5, 0, "Svarog386 installation is over. Your computer will reboot now.\nPlease remove the installation disk from your drive.");
599
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
599
  putstringnls(++y, 1, COLOR_BODY[mono], 0, 5, "Press any key...");
600
  input_getkey();
600
  input_getkey();
601
  reboot();
601
  reboot();
602
}
602
}
603
 
603
 
604
 
604
 
605
static void loadcp(struct slocales *locales) {
605
static void loadcp(struct slocales *locales) {
606
  char buff[64];
606
  char buff[64];
607
  if (locales->codepage == 437) return;
607
  if (locales->codepage == 437) return;
608
  video_movecursor(1, 0);
608
  video_movecursor(1, 0);
609
  if (locales->egafile == 1) {
609
  if (locales->egafile == 1) {
610
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
610
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA.CPX) > NUL", locales->codepage);
611
  } else {
611
  } else {
612
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
612
    snprintf(buff, sizeof(buff), "MODE CON CP PREP=((%u) A:\\EGA%d.CPX) > NUL", locales->codepage, locales->egafile);
613
  }
613
  }
614
  system(buff);
614
  system(buff);
615
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
615
  snprintf(buff, sizeof(buff), "MODE CON CP SEL=%u > NUL", locales->codepage);
616
  system(buff);
616
  system(buff);
617
  /* below I re-init the video controller - apparently this is required if
617
  /* below I re-init the video controller - apparently this is required if
618
   * I want the new glyph symbols to be actually applied, at least some
618
   * I want the new glyph symbols to be actually applied, at least some
619
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
619
   * (broken?) BIOSes, like VBox, apply glyphs only at next video mode change */
620
  {
620
  {
621
  union REGS r;
621
  union REGS r;
622
  r.h.ah = 0x0F; /* get current video mode */
622
  r.h.ah = 0x0F; /* get current video mode */
623
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
623
  int86(0x10, &r, &r); /* r.h.al contains the current video mode now */
624
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
624
  r.h.al |= 128; /* set the high bit of AL to instruct BIOS not to flush VRAM's content (EGA+) */
625
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
625
  r.h.ah = 0; /* re-set video mode (to whatever is set in AL) */
626
  int86(0x10, &r, &r);
626
  int86(0x10, &r, &r);
627
  }
627
  }
628
}
628
}
629
 
629
 
630
 
-
 
631
/* checks CD drive drv for the presence of the Svarog386 install CD
630
/* checks CD drive drv for the presence of the Svarog386 install CD
632
 * returns 0 if found, non-zero otherwise */
631
 * returns 0 if found, non-zero otherwise */
633
/*static int checkcd(char drv) {
632
static int checkcd(char drv) {
634
  FILE *fd;
633
  FILE *fd;
635
  char fname[32];
634
  char fname[32];
636
  snprintf(fname, sizeof(fname), "%c:\\CORE\\MEM.ZIP", drv);
635
  snprintf(fname, sizeof(fname), "%c:\\CORE\\MEM.ZIP", drv);
637
  fd = fopen(fname, "rb");
636
  fd = fopen(fname, "rb");
638
  if (fd == NULL) return(-1);
637
  if (fd == NULL) return(-1);
639
  fclose(fd);
638
  fclose(fd);
640
  return(0);
639
  return(0);
641
}*/
640
}
642
 
641
 
643
 
642
 
644
int main(void) {
643
int main(void) {
645
  struct slocales locales;
644
  struct slocales locales;
646
  int targetdrv;
645
  int targetdrv;
647
  int cdromdrv;
646
  int cdromdrv;
648
 
647
 
649
  /* find where the cdrom drive is */
648
  /* find where the cdrom drive is */
650
  cdromdrv = cdrom_findfirst();
649
  cdromdrv = cdrom_findfirst();
651
  if (cdromdrv < 0) {
650
  if (cdromdrv < 0) {
652
    printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
651
    printf("ERROR: CD-ROM DRIVE NOT FOUND\r\n");
653
    return(1);
652
    return(1);
654
  }
653
  }
655
  cdromdrv += 'A'; /* convert the cdrom 'id' (A=0) to an actual drive letter */
654
  cdromdrv += 'A'; /* convert the cdrom 'id' (A=0) to an actual drive letter */
656
  /*if (checkcd(cdromdrv) != 0) {
655
  if (checkcd(cdromdrv) != 0) {
657
    printf("ERROR: SVAROG386 INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
656
    printf("ERROR: SVAROG386 INSTALLATION CD NOT FOUND IN THE DRIVE.\r\n");
658
    return(1);
657
    return(1);
659
  }*/
658
  }
660
 
659
 
661
  /* init screen and detect mono status */
660
  /* init screen and detect mono status */
662
  mono = video_init();
661
  mono = video_init();
663
 
662
 
664
  for (;;) { /* fake loop, it's here just to break out easily */
663
  for (;;) { /* fake loop, it's here just to break out easily */
665
    kittenopen("INSTALL"); /* NLS support */
664
    kittenopen("INSTALL"); /* NLS support */
666
    if (selectlang(&locales) < 0) break; /* welcome to svarog, select your language */
665
    if (selectlang(&locales) < 0) break; /* welcome to svarog, select your language */
667
    setenv("LANG", locales.lang, 1);
666
    setenv("LANG", locales.lang, 1);
668
    loadcp(&locales);
667
    loadcp(&locales);
669
    kittenclose(); /* reload NLS with new language */
668
    kittenclose(); /* reload NLS with new language */
670
    kittenopen("INSTALL"); /* NLS support */
669
    kittenopen("INSTALL"); /* NLS support */
671
    if (selectkeyb(&locales) != 0) break;  /* what keyb layout should we use? */
670
    if (selectkeyb(&locales) != 0) break;  /* what keyb layout should we use? */
672
    if (welcomescreen() != 0) break; /* what svarog386 is, ask whether to run live dos or install */
671
    if (welcomescreen() != 0) break; /* what svarog386 is, ask whether to run live dos or install */
673
    targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
672
    targetdrv = preparedrive(); /* what drive should we install to? check avail. space */
674
    if (targetdrv < 0) break;
673
    if (targetdrv < 0) break;
675
    /*askaboutsources();*/ /* IF sources are available, ask if installing with them */
674
    /*askaboutsources();*/ /* IF sources are available, ask if installing with them */
676
    installpackages(targetdrv, cdromdrv);    /* install packages */
675
    installpackages(targetdrv, cdromdrv);    /* install packages */
677
    bootfilesgen(targetdrv, &locales, cdromdrv); /* generate boot files and other configurations */
676
    bootfilesgen(targetdrv, &locales, cdromdrv); /* generate boot files and other configurations */
678
    /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
677
    /*localcfg();*/ /* show local params (currency, etc), and propose to change them (based on localcfg) */
679
    /*netcfg();*/ /* basic networking config */
678
    /*netcfg();*/ /* basic networking config */
680
    finalreboot(); /* remove the CD and reboot */
679
    finalreboot(); /* remove the CD and reboot */
681
    break;
680
    break;
682
  }
681
  }
683
  kittenclose(); /* close NLS support */
682
  kittenclose(); /* close NLS support */
684
  video_clear(0x0700, 0);
683
  video_clear(0x0700, 0);
685
  video_movecursor(0, 0);
684
  video_movecursor(0, 0);
686
  return(0);
685
  return(0);
687
}
686
}
688
 
687