Subversion Repositories SvarDOS

Rev

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

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