Subversion Repositories SvarDOS

Rev

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

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