Subversion Repositories SvarDOS

Rev

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

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