Subversion Repositories SvarDOS

Rev

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

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