2000-05-06 21:34:20 +02:00
|
|
|
/****************************************************************/
|
|
|
|
/* */
|
|
|
|
/* config.c */
|
|
|
|
/* DOS-C */
|
|
|
|
/* */
|
|
|
|
/* config.sys Processing Functions */
|
|
|
|
/* */
|
|
|
|
/* Copyright (c) 1996 */
|
|
|
|
/* Pasquale J. Villani */
|
|
|
|
/* All Rights Reserved */
|
|
|
|
/* */
|
|
|
|
/* This file is part of DOS-C. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is free software; you can redistribute it and/or */
|
|
|
|
/* modify it under the terms of the GNU General Public License */
|
|
|
|
/* as published by the Free Software Foundation; either version */
|
|
|
|
/* 2, or (at your option) any later version. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is distributed in the hope that it will be useful, but */
|
|
|
|
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
|
|
|
|
/* the GNU General Public License for more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public */
|
|
|
|
/* License along with DOS-C; see the file COPYING. If not, */
|
2003-06-30 20:50:38 +02:00
|
|
|
/* write to the Free Software Foundation, Inc., */
|
|
|
|
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */
|
2000-05-06 21:34:20 +02:00
|
|
|
/****************************************************************/
|
|
|
|
|
2001-04-22 00:32:53 +02:00
|
|
|
#include "portab.h"
|
2000-05-06 21:34:20 +02:00
|
|
|
#include "init-mod.h"
|
2001-07-10 00:19:33 +02:00
|
|
|
#include "dyndata.h"
|
|
|
|
|
2001-11-18 00:26:45 +01:00
|
|
|
#ifdef VERSION_STRINGS
|
2001-11-18 15:01:12 +01:00
|
|
|
static BYTE *RcsId =
|
|
|
|
"$Id$";
|
2001-11-18 00:26:45 +01:00
|
|
|
#endif
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
#define testbit(v,bit) ((UBYTE)((v) >> (UBYTE)(bit)) & 1)
|
|
|
|
|
2001-11-18 00:26:45 +01:00
|
|
|
#ifdef DEBUG
|
2001-11-18 15:01:12 +01:00
|
|
|
#define DebugPrintf(x) printf x
|
|
|
|
#else
|
|
|
|
#define DebugPrintf(x)
|
|
|
|
#endif
|
2001-07-10 00:19:33 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static UBYTE MenuColor BSS_INIT(0);
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static unsigned screenwidth(void)
|
|
|
|
{
|
|
|
|
return peek(0, 0x44a);
|
|
|
|
}
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static unsigned screenbottom(void)
|
|
|
|
{
|
|
|
|
UBYTE row = peekb(0, 0x484);
|
|
|
|
if (row == 0)
|
|
|
|
row = 24;
|
|
|
|
return row;
|
|
|
|
}
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static unsigned screeny(void)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
|
|
|
iregs r;
|
2004-07-09 04:16:31 +02:00
|
|
|
r.BH = peekb(0, 0x462); /* active video page */
|
|
|
|
r.AH = 0x03; /* get cursor pos */
|
|
|
|
init_call_intr(0x10, &r);
|
|
|
|
return r.DH;
|
|
|
|
}
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void gotoxy(unsigned x, unsigned y)
|
|
|
|
{
|
|
|
|
iregs r;
|
|
|
|
r.BH = peekb(0, 0x462); /* active video page */
|
|
|
|
r.DL = x;
|
|
|
|
r.DH = y;
|
|
|
|
r.AH = 0x02; /* set cursor pos */
|
2003-09-18 22:55:41 +02:00
|
|
|
init_call_intr(0x10, &r);
|
2004-07-09 04:16:31 +02:00
|
|
|
}
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void ClearScreenArea(UBYTE attr, unsigned x, unsigned y, unsigned w, unsigned h)
|
|
|
|
{
|
|
|
|
iregs r;
|
|
|
|
r.BH = attr;
|
|
|
|
r.CL = x; r.DL = x + w - 1;
|
|
|
|
r.CH = y; r.DH = y + h - 1;
|
|
|
|
r.AX = 0x0600; /* clear rectangle */
|
2003-09-18 22:55:41 +02:00
|
|
|
init_call_intr(0x10, &r);
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
gotoxy(x, y);
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void say(PCStr s)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
printf(s);
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void say2(PCStr f, PCStr s)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
printf(f, s);
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void clearrow(void)
|
|
|
|
{
|
|
|
|
unsigned width;
|
|
|
|
say("\r");
|
|
|
|
for (width = screenwidth(); --width;)
|
|
|
|
say(" ");
|
|
|
|
say("\r");
|
|
|
|
}
|
2002-11-09 20:10:11 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static seg_t umb_base_start BSS_INIT(0);
|
|
|
|
static size_t ebda_size BSS_INIT(0);
|
2003-10-05 18:22:57 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
struct config Config = {
|
2004-07-09 04:16:31 +02:00
|
|
|
/* UBYTE cfgDosDataUmb; */ 0,
|
|
|
|
/* BYTE cfgBuffers; */ NUMBUFF,
|
|
|
|
/* UBYTE cfgFiles; */ NFILES,
|
|
|
|
/* UBYTE cfgFilesHigh; */ 0,
|
|
|
|
/* UBYTE cfgFcbs; */ NFCBS,
|
|
|
|
/* UBYTE cfgProtFcbs; */ 0,
|
|
|
|
/* char cfgShell[256]; */ "command.com /P /E:256",
|
|
|
|
/* UBYTE cfgLastdrive; */ NLAST,
|
|
|
|
/* UBYTE cfgLastdriveHigh; */ 0,
|
|
|
|
/* BYTE cfgStacks; */ NSTACKS,
|
|
|
|
/* BYTE cfgStacksHigh; */ 0,
|
|
|
|
/* UWORD cfgStackSize; */ STACKSIZE,
|
|
|
|
/* UBYTE cfgP_0_startmode; */ 0, /* load command.com (low by default) */
|
|
|
|
/* unsigned ebda2move; */ 0, /* value for SWITCHES=/E:nnnn */
|
2001-11-18 15:01:12 +01:00
|
|
|
};
|
2004-04-13 13:54:09 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC seg_t base_seg BSS_INIT(0);
|
|
|
|
STATIC seg_t umb_base_seg BSS_INIT(0);
|
|
|
|
VFP lpTop BSS_INIT(0);
|
2004-04-14 01:46:25 +02:00
|
|
|
STATIC unsigned nCfgLine BSS_INIT(0);
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
static unsigned nPass BSS_INIT(0);
|
|
|
|
static char configfile [] = "FDCONFIG.SYS";
|
|
|
|
STATIC char szLine[256] BSS_INIT({0});
|
|
|
|
STATIC char szBuf[256] BSS_INIT({0});
|
|
|
|
|
|
|
|
UBYTE askCommand BSS_INIT(0);
|
|
|
|
|
|
|
|
static int MenuTimeout = -1;
|
|
|
|
static unsigned last_choice = 10; /* =non existing choice */
|
|
|
|
static unsigned line_choices BSS_INIT(0);
|
|
|
|
static unsigned all_choices BSS_INIT(0);
|
|
|
|
|
|
|
|
STATIC BOOL LoadDevice(PCStr, VFP top, int mode);
|
|
|
|
STATIC void CfgFailure(PCStr);
|
2003-06-15 21:26:49 +02:00
|
|
|
|
2002-01-23 23:29:41 +01:00
|
|
|
STATIC VOID DoMenu(void);
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC PCStr skipwh(PCStr);
|
|
|
|
STATIC PCStr scanword(PCStr, PStr);
|
|
|
|
STATIC PCStr scanverb(PCStr, PStr);
|
|
|
|
#define isdigit(ch) ((UBYTE)((ch) - '0') <= 9)
|
2004-05-23 18:21:14 +02:00
|
|
|
STATIC char toupper(char c);
|
2004-07-09 04:16:31 +02:00
|
|
|
static PStr strupr(PStr);
|
|
|
|
static PStr strcat(PStr d, PCStr s);
|
|
|
|
STATIC void mcb_init(seg_t, size_t, BYTE type);
|
|
|
|
STATIC void mumcb_init(seg_t, size_t);
|
|
|
|
#define mcb_next(seg) ((seg) + MK_SEG_PTR(mcb, seg)->m_size + 1)
|
|
|
|
|
|
|
|
STATIC PCStr GetNumArg(PCStr);
|
|
|
|
STATIC BOOL GetNumArg1(PCStr);
|
|
|
|
STATIC BOOL GetNumArg2(PCStr, int default2);
|
|
|
|
static void hintSkipAll(void);
|
|
|
|
static BOOL askSkipLine(void);
|
|
|
|
STATIC char strcasediff(PCStr, PCStr);
|
|
|
|
STATIC void LoadCountryInfoHardCoded(CStr filename, int ccode, int cpage);
|
2003-06-15 17:53:58 +02:00
|
|
|
STATIC void umb_init(void);
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-03-27 00:27:18 +01:00
|
|
|
STATIC void config_init_buffers(int anzBuffers); /* from BLOCKIO.C */
|
|
|
|
STATIC void config_init_fnodes(int f_nodes_cnt);
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
#define EOF 0x1a
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
typedef void config_sys_func_t(PCStr);
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC config_sys_func_t
|
|
|
|
CfgSwitches,
|
|
|
|
CfgMenuColor, CfgMenuDefault, CfgMenu, CfgMenuEsc,
|
|
|
|
CfgBreak, Config_Buffers, Country, Dosmem, DosData,
|
|
|
|
Fcbs, Files, FilesHigh, CfgLastdrive, CfgLastdriveHigh,
|
|
|
|
Numlock, CmdShell, CmdShellHigh,
|
|
|
|
Stacks, StacksHigh, CfgSwitchar,
|
|
|
|
sysScreenMode, sysVersion, SetAnyDos,
|
|
|
|
Device, DeviceHigh, CmdInstall, CmdInstallHigh, CmdSet;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC struct table {
|
|
|
|
PCStr const entry;
|
|
|
|
UBYTE pass;
|
|
|
|
config_sys_func_t *const func;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
} commands [] = {
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* this one is special since it checked for /N/F before F5/F8 and
|
|
|
|
asked for /K/E after menu; DoConfig() changes commands[0].pass */
|
|
|
|
{"SWITCHES", 0, CfgSwitches},
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
{"REM", 100, NULL},
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
{"MENUCOLOR", 0, CfgMenuColor},
|
2003-09-18 22:55:41 +02:00
|
|
|
{"MENUDEFAULT", 0, CfgMenuDefault},
|
2004-07-09 04:16:31 +02:00
|
|
|
{"MENU", 1, CfgMenu}, /* lines to print in pass 1 */
|
|
|
|
{"ECHO", 3, CfgMenu}, /* lines to print in pass 3 */
|
|
|
|
{"EECHO", 3, CfgMenuEsc}, /* modified ECHO (ea) */
|
|
|
|
|
|
|
|
{"BREAK", 2, CfgBreak},
|
|
|
|
{"BUFFERS", 2, Config_Buffers},
|
|
|
|
{"BUFFERSHIGH", 2, Config_Buffers}, /* currently dummy */
|
|
|
|
{"COUNTRY", 2, Country},
|
|
|
|
{"DOS", 2, Dosmem},
|
|
|
|
{"DOSDATA", 2, DosData},
|
|
|
|
{"FCBS", 2, Fcbs},
|
|
|
|
{"FILES", 2, Files},
|
|
|
|
{"FILESHIGH", 2, FilesHigh},
|
|
|
|
{"LASTDRIVE", 2, CfgLastdrive},
|
|
|
|
{"LASTDRIVEHIGH", 2, CfgLastdriveHigh},
|
|
|
|
{"NUMLOCK", 2, Numlock},
|
|
|
|
{"STACKS", 2, Stacks},
|
|
|
|
{"STACKSHIGH", 2, StacksHigh},
|
|
|
|
{"SWITCHAR", 2, CfgSwitchar},
|
|
|
|
{"SCREEN", 2, sysScreenMode}, /* JPP */
|
|
|
|
{"VERSION", 2, sysVersion}, /* JPP */
|
|
|
|
{"ANYDOS", 2, SetAnyDos}, /* tom */
|
|
|
|
|
|
|
|
{"DEVICE", 3, Device},
|
|
|
|
{"DEVICEHIGH", 3, DeviceHigh},
|
|
|
|
|
|
|
|
{"INSTALL", 4, CmdInstall},
|
|
|
|
{"INSTALLHIGH", 4, CmdInstallHigh},
|
|
|
|
{"SET", 4, CmdSet},
|
|
|
|
{"SHELL", 4, CmdShell},
|
|
|
|
{"SHELLHIGH", 4, CmdShellHigh},
|
2000-05-06 21:34:20 +02:00
|
|
|
};
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
enum { HMA_NONE, /* do nothing */
|
|
|
|
HMA_REQ, /* DOS=HIGH detected */
|
|
|
|
HMA_DONE, /* Moved kernel to HMA */
|
|
|
|
};
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
enum { UMB_NONE, /* do nothing */
|
|
|
|
UMB_DONE, /* UMB initialized */
|
|
|
|
UMB_REQ, /* DOS=UMB detected */
|
|
|
|
};
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static UBYTE HMAState BSS_INIT(HMA_NONE);
|
|
|
|
static UBYTE UmbState BSS_INIT(UMB_NONE);
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Do first time initialization. Store last so that we can reset it */
|
|
|
|
/* later. */
|
2002-01-23 23:29:41 +01:00
|
|
|
void PreConfig(void)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
/* Initialize the base memory pointers */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2000-05-08 06:30:00 +02:00
|
|
|
#ifdef DEBUG
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
|
|
|
printf("SDA located at 0x%p\n", internal_data);
|
|
|
|
}
|
2000-05-08 06:30:00 +02:00
|
|
|
#endif
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Begin by initializing our system buffers */
|
|
|
|
#ifdef DEBUG
|
2001-03-21 03:56:26 +01:00
|
|
|
/* printf("Preliminary %d buffers allocated at 0x%p\n", Config.cfgBuffers, buffers);*/
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
2003-06-20 21:54:18 +02:00
|
|
|
LoL->DPBp =
|
|
|
|
DynAlloc("DPBp", blk_dev.dh_name[0], sizeof(struct dpb));
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Initialize the file table */
|
2004-03-27 00:10:13 +01:00
|
|
|
config_init_fnodes(Config.cfgFiles);
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
LoL->sfthead = MK_PTR(struct sfttbl, FP_SEG(LoL), 0xcc); /* &(LoL->firstsftt) */
|
2003-06-15 17:53:58 +02:00
|
|
|
/* LoL->FCBp = (sfttbl FAR *)&FcbSft; */
|
|
|
|
/* LoL->FCBp = (sfttbl FAR *)
|
2001-11-18 15:01:12 +01:00
|
|
|
KernelAlloc(sizeof(sftheader)
|
|
|
|
+ Config.cfgFiles * sizeof(sft)); */
|
2001-07-28 20:13:06 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
config_init_buffers(Config.cfgBuffers);
|
2001-07-28 20:13:06 +02:00
|
|
|
|
2003-06-15 17:53:58 +02:00
|
|
|
LoL->CDSp = KernelAlloc(sizeof(struct cds) * LoL->lastdrive, 'L', 0);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2004-03-23 23:45:38 +01:00
|
|
|
printf("Preliminary:\n f_node 0x%p\n", LoL->f_nodes);
|
2003-06-15 17:53:58 +02:00
|
|
|
/* printf(" FCB table 0x%p\n",LoL->FCBp);*/
|
2003-06-20 21:54:18 +02:00
|
|
|
printf(" sft table 0x%p\n", LoL->sfthead);
|
2003-06-15 17:53:58 +02:00
|
|
|
printf(" CDS table 0x%p\n", LoL->CDSp);
|
|
|
|
printf(" DPB table 0x%p\n", LoL->DPBp);
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Done. Now initialize the MCB structure */
|
|
|
|
/* This next line is 8086 and 80x86 real mode specific */
|
|
|
|
#ifdef DEBUG
|
2004-07-09 04:16:31 +02:00
|
|
|
printf("Preliminary allocation completed: top at %p\n", lpTop);
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void KernelAllocSFT(sfttbl FAR *p, unsigned files, int high)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
p = p->sftt_next = (sfttbl FAR *)KernelAlloc(sizeof(sftheader) +
|
|
|
|
files * sizeof(sft), 'F', high);
|
|
|
|
p->sftt_count = files;
|
|
|
|
p->sftt_next = (sfttbl FAR *)-1l;
|
|
|
|
}
|
2003-09-04 21:14:16 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
#define EBDASEG 0x40e
|
|
|
|
#define RAMSIZE 0x413
|
|
|
|
#define RAM_size() peek(0, RAMSIZE)
|
2001-07-10 00:19:33 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Do pre-drivers initialization: near allocation and MCBs */
|
|
|
|
static void PreConfig3(void)
|
|
|
|
{
|
|
|
|
/* initialize NEAR allocated things */
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Initialize the base memory pointers from last time. */
|
2001-07-10 00:19:33 +02:00
|
|
|
/*
|
2003-09-04 21:14:16 +02:00
|
|
|
if the kernel could be moved to HMA, everything behind the dynamic
|
2001-11-18 15:01:12 +01:00
|
|
|
near data is free.
|
|
|
|
otherwise, the kernel is moved down - behind the dynamic allocated data,
|
|
|
|
and allocation starts after the kernel.
|
|
|
|
*/
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
size_t ram_top = RAM_size(); /* how much conventional RAM, kb */
|
|
|
|
seg_t ebdaseg = peek(0, EBDASEG);
|
|
|
|
size_t ebdasz = peekb(ebdaseg, 0);
|
|
|
|
if (Config.ebda2move && ram_top * 64 == ebdaseg && ebdasz <= 63)
|
2003-09-09 19:30:10 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
ram_top += ebdasz;
|
|
|
|
ebdasz *= 1024u;
|
|
|
|
if (ebdasz > Config.ebda2move)
|
|
|
|
ebdasz = (Config.ebda2move + 15) & -16;
|
|
|
|
ebda_size = ebdasz;
|
2003-09-09 19:30:10 +02:00
|
|
|
}
|
2003-09-04 21:14:16 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* We expect ram_top as Kbytes, so convert to paragraphs */
|
2004-07-09 04:16:31 +02:00
|
|
|
base_seg = LoL->first_mcb = FP_SEG(alignNextPara(DynLast()));
|
|
|
|
mcb_init(base_seg, ram_top * 64 - base_seg, MCB_LAST);
|
2003-06-20 21:54:18 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* allocate space in low memory for 3 file handles
|
|
|
|
(SFT) in addition to 5 handles, builtin into LOL */
|
|
|
|
KernelAllocSFT(LoL->sfthead, 3, 0);
|
2003-09-04 21:14:16 +02:00
|
|
|
|
|
|
|
if (ebda_size) /* move the Extended BIOS Data Area from top of RAM here */
|
2004-07-09 04:16:31 +02:00
|
|
|
{
|
|
|
|
seg_t new_seg = FP_SEG(KernelAlloc(ebda_size, 'I', 0));
|
|
|
|
fmemcpy(MK_SEG_PTR(BYTE, new_seg), MK_SEG_PTR(const BYTE, ebdaseg), ebda_size);
|
|
|
|
poke(0, EBDASEG, new_seg);
|
|
|
|
poke(0, RAMSIZE, ram_top);
|
|
|
|
}
|
2003-09-04 21:14:16 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
umb_init();
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Do last initialization. */
|
2003-06-15 15:24:53 +02:00
|
|
|
void PostConfig(void)
|
|
|
|
{
|
|
|
|
/* We could just have loaded FDXMS or HIMEM */
|
|
|
|
if (HMAState == HMA_REQ && MoveKernelToHMA())
|
|
|
|
HMAState = HMA_DONE;
|
2004-07-09 04:16:31 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
if (Config.cfgDosDataUmb)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
Config.cfgFilesHigh =
|
|
|
|
Config.cfgStacksHigh =
|
|
|
|
Config.cfgLastdriveHigh = 1;
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* compute lastdrive ... */
|
2004-07-09 04:16:31 +02:00
|
|
|
{
|
|
|
|
UBYTE drv = Config.cfgLastdrive;
|
|
|
|
if (drv < LoL->nblkdev)
|
|
|
|
drv = LoL->nblkdev;
|
|
|
|
LoL->lastdrive = drv;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
DebugPrintf(("starting FAR allocations at %x\n", base_seg));
|
2001-07-10 00:19:33 +02:00
|
|
|
|
2004-03-27 00:10:13 +01:00
|
|
|
/* Initialize the file table */
|
|
|
|
config_init_fnodes(Config.cfgFiles);
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Begin by initializing our system buffers */
|
2001-03-21 03:56:26 +01:00
|
|
|
/* dma_scratch = (BYTE FAR *) KernelAllocDma(BUFFERSIZE); */
|
2000-05-06 21:34:20 +02:00
|
|
|
#ifdef DEBUG
|
2001-03-21 03:56:26 +01:00
|
|
|
/* printf("DMA scratchpad allocated at 0x%p\n", dma_scratch); */
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2001-07-28 20:13:06 +02:00
|
|
|
config_init_buffers(Config.cfgBuffers);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2003-06-15 17:53:58 +02:00
|
|
|
/* LoL->sfthead = (sfttbl FAR *)&basesft; */
|
|
|
|
/* LoL->FCBp = (sfttbl FAR *)&FcbSft; */
|
|
|
|
/* LoL->FCBp = KernelAlloc(sizeof(sftheader)
|
2001-11-18 15:01:12 +01:00
|
|
|
+ Config.cfgFiles * sizeof(sft)); */
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
/* allocate space for remaining file handles (SFT); 5 are
|
|
|
|
already builtin and 3 are allocated in PreConfig3() */
|
|
|
|
KernelAllocSFT(LoL->sfthead->sftt_next,
|
|
|
|
Config.cfgFiles - 8, Config.cfgFilesHigh);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2003-06-15 17:53:58 +02:00
|
|
|
LoL->CDSp = KernelAlloc(sizeof(struct cds) * LoL->lastdrive, 'L', Config.cfgLastdriveHigh);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2004-03-27 00:10:13 +01:00
|
|
|
printf("Final: \n f_node 0x%p\n", LoL->f_nodes);
|
2003-06-15 17:53:58 +02:00
|
|
|
/* printf(" FCB table 0x%p\n",LoL->FCBp);*/
|
|
|
|
printf(" sft table 0x%p\n", LoL->sfthead->sftt_next);
|
|
|
|
printf(" CDS table 0x%p\n", LoL->CDSp);
|
|
|
|
printf(" DPB table 0x%p\n", LoL->DPBp);
|
2001-11-18 15:01:12 +01:00
|
|
|
#endif
|
2004-07-09 04:16:31 +02:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
if (Config.cfgStacks)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
void _seg *stackBase =
|
2003-06-15 15:24:53 +02:00
|
|
|
KernelAlloc(Config.cfgStacks * Config.cfgStackSize, 'S',
|
|
|
|
Config.cfgStacksHigh);
|
2000-05-06 21:34:20 +02:00
|
|
|
init_stacks(stackBase, Config.cfgStacks, Config.cfgStackSize);
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
DebugPrintf(("Stacks allocated at %p\n", stackBase));
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2003-06-15 15:24:53 +02:00
|
|
|
DebugPrintf(("Allocation completed: top at 0x%x\n", base_seg));
|
2000-06-21 20:16:46 +02:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This code must be executed after device drivers has been loaded */
|
2002-01-23 23:29:41 +01:00
|
|
|
VOID configDone(VOID)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (UmbState == UMB_DONE)
|
|
|
|
MK_SEG_PTR(mcb, base_seg)->m_type = MCB_LAST;
|
2003-06-15 15:24:53 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
if (HMAState != HMA_DONE)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
size_t hma_paras = (HMAFree + 15) / 16;
|
|
|
|
seg_t kernel_seg = allocmem(hma_paras);
|
|
|
|
#else
|
|
|
|
seg_t kernel_seg = allocmem((HMAFree + 15) / 16);
|
|
|
|
#endif
|
|
|
|
mcb _seg *p = MK_SEG_PTR(mcb, kernel_seg - 1);
|
2003-06-15 17:53:58 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
p->m_name[0] = 'S';
|
|
|
|
p->m_name[1] = 'C';
|
2003-06-30 20:50:38 +02:00
|
|
|
p->m_psp = 8;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
DebugPrintf(("HMA not available, moving text to %x\n", kernel_seg));
|
|
|
|
MoveKernel(kernel_seg);
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("kernel is low, start alloc at %x\n",
|
|
|
|
kernel_seg + hma_paras + 1));
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* The standard handles should be reopened here, because
|
|
|
|
we may have loaded new console or printer drivers in CONFIG.SYS */
|
|
|
|
}
|
2001-07-10 00:19:33 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
STATIC void umb_init(void)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
CVFP xms_addr;
|
|
|
|
seg_t umb_seg;
|
|
|
|
size_t umb_size;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (UmbState == UMB_REQ &&
|
|
|
|
(xms_addr = DetectXMSDriver()) != NULL &&
|
|
|
|
UMB_get_largest(xms_addr, &umb_seg, &umb_size))
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t umb_furthest = umb_seg;
|
|
|
|
|
|
|
|
/* SAFETY: new block may be too small or below memory top */
|
|
|
|
seg_t base_top = RAM_size() * 64 - 1;
|
|
|
|
if (umb_size < 2 || umb_furthest <= base_top)
|
|
|
|
return;
|
|
|
|
|
|
|
|
UmbState = UMB_DONE;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* reset root */
|
2004-07-09 04:16:31 +02:00
|
|
|
LoL->uppermem_root = base_top;
|
|
|
|
umb_base_seg = umb_furthest;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* create link mcb (below) */
|
2004-07-09 04:16:31 +02:00
|
|
|
/* (it prefixes hole between UMBs) */
|
|
|
|
MK_SEG_PTR(mcb, base_seg)->m_type = MCB_NORMAL;
|
|
|
|
MK_SEG_PTR(mcb, base_seg)->m_size--;
|
|
|
|
mumcb_init(base_top, umb_seg - base_top);
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* setup the real mcb for the devicehigh block */
|
2004-07-09 04:16:31 +02:00
|
|
|
mcb_init(umb_seg, umb_size, MCB_NORMAL);
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* there can be more UMBs !
|
|
|
|
this happens, if memory mapped devices are in between
|
2003-06-15 15:24:53 +02:00
|
|
|
like UMB memory c800..c8ff, d8ff..efff with device at d000..d7ff
|
|
|
|
However some of the xxxHIGH commands still only work with
|
|
|
|
the first UMB.
|
|
|
|
*/
|
2004-04-09 17:43:01 +02:00
|
|
|
while (UMB_get_largest(xms_addr, &umb_seg, &umb_size))
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (umb_furthest < umb_seg)
|
|
|
|
{
|
|
|
|
seg_t umb_hole = mcb_next(umb_furthest);
|
2001-07-22 03:58:58 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* SAFETY: new block may (1) be adjacent to old block,
|
|
|
|
(2) overlap it or (3) be inside. (2) and (3) are errors
|
|
|
|
and shouldn't happen, but handle them anyway. */
|
|
|
|
if (umb_hole >= umb_seg)
|
|
|
|
{
|
|
|
|
size_t overlap = umb_hole - umb_seg;
|
|
|
|
if (overlap < umb_size)
|
|
|
|
/* join adjacent/overlapped new block to prev block */
|
|
|
|
MK_SEG_PTR(mcb, umb_furthest)->m_size += umb_size - overlap;
|
|
|
|
continue;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* SAFETY: new block may be too small */
|
|
|
|
if (umb_size < 2)
|
|
|
|
continue;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* create link mcb (below) */
|
|
|
|
MK_SEG_PTR(mcb, umb_furthest)->m_size--;
|
|
|
|
umb_furthest = umb_seg;
|
|
|
|
umb_hole--;
|
|
|
|
mumcb_init(umb_hole, umb_seg - umb_hole);
|
|
|
|
}
|
|
|
|
else /* umb_seg <= umb_furthest */
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t umb_prev, umb_hole, umb_next, umb_cur_next;
|
|
|
|
|
|
|
|
/* SAFETY: umb_seg may point into base memory */
|
|
|
|
if (base_top >= umb_seg)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* find previous block */
|
|
|
|
for (umb_hole = base_top;;)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
umb_next = mcb_next(umb_hole);
|
|
|
|
/* ASSUME umb_hole->m_type == 'M' && umb_hole->m_psp == 8 &&
|
|
|
|
umb_next->m_type == 'M' && umb_next->m_psp != 8 &&
|
|
|
|
umb_hole < umb_next <= umb_furthest */
|
|
|
|
if (umb_seg <= umb_next)
|
|
|
|
break;
|
|
|
|
umb_prev = umb_next;
|
|
|
|
umb_hole = mcb_next(umb_next);
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
/* NOW base_top == umb_hole < umb_seg <= umb_next ||
|
|
|
|
base_top < umb_prev < umb_seg <= umb_next */
|
|
|
|
|
|
|
|
/* SAFETY: new block may be inside previous block */
|
|
|
|
umb_cur_next = umb_seg + umb_size;
|
|
|
|
if (umb_cur_next <= umb_hole)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* SAFETY: umb_seg may point below hole,
|
|
|
|
so, use ">=" instead "==" */
|
|
|
|
if (umb_hole + 1 >= umb_seg && umb_hole != base_top)
|
|
|
|
/* join adjacent/overlapped new block to prev block */
|
|
|
|
umb_size = umb_cur_next - (umb_seg = umb_prev);
|
2003-06-15 15:24:53 +02:00
|
|
|
else
|
2004-07-09 04:16:31 +02:00
|
|
|
{
|
|
|
|
/* SAFETY: new block may be too small */
|
|
|
|
if (umb_size < 2 && umb_cur_next < umb_next)
|
|
|
|
continue;
|
|
|
|
/* adjust link mcb below */
|
|
|
|
MK_SEG_PTR(mcb, umb_hole)->m_size = umb_seg - umb_hole - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SAFETY: new block may overlap next block,
|
|
|
|
so, use ">=" instead "==" */
|
|
|
|
if (umb_cur_next >= umb_next)
|
|
|
|
{
|
|
|
|
/* join adjacent/overlapped next block to new block */
|
|
|
|
if (umb_furthest == umb_next)
|
|
|
|
umb_furthest = umb_seg;
|
|
|
|
if (umb_base_seg == umb_next)
|
|
|
|
umb_base_seg = umb_seg;
|
|
|
|
umb_size = mcb_next(umb_next) - umb_seg;
|
|
|
|
}
|
|
|
|
else /* umb_cur_next < umb_next */
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
|
|
|
/* create link mcb (above) */
|
2004-07-09 04:16:31 +02:00
|
|
|
umb_size--, umb_cur_next--;
|
|
|
|
mumcb_init(umb_cur_next, umb_next - umb_cur_next);
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
} /* else */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* setup the real mcb for the devicehigh block */
|
|
|
|
mcb_init(umb_seg, umb_size, MCB_NORMAL);
|
|
|
|
} /* while */
|
|
|
|
|
|
|
|
MK_SEG_PTR(mcb, umb_furthest)->m_type = MCB_LAST;
|
|
|
|
umb_base_start = umb_base_seg;
|
2003-06-15 15:24:53 +02:00
|
|
|
|
|
|
|
DebugPrintf(("UMB Allocation completed: start at 0x%x\n", umb_base_seg));
|
2004-07-09 04:16:31 +02:00
|
|
|
} /* if */
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC const struct table * LookUp(CStr token)
|
|
|
|
{
|
|
|
|
const struct table *p = commands;
|
|
|
|
do
|
|
|
|
if (!strcasediff(p->entry, token))
|
|
|
|
return p;
|
|
|
|
while (++p < ENDOF(commands));
|
|
|
|
p = NULL;
|
|
|
|
return p;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void DoConfig_(void)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
int nFileDesc, done;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (askCommand & ASK_SKIPALL)
|
|
|
|
return;
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Check to see if we have a config.sys file. If not, just */
|
|
|
|
/* exit since we don't force the user to have one. */
|
2004-07-09 04:16:31 +02:00
|
|
|
/*strcpy (configfile, "FDCONFIG.SYS");*/
|
|
|
|
if ((nFileDesc = open(configfile, 0)) < 0)
|
2001-07-10 00:19:33 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("%s not found\n", configfile));
|
|
|
|
strcpy (configfile, "CONFIG.SYS");
|
|
|
|
if ((nFileDesc = open(configfile, 0)) < 0)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("%s not found\n", configfile));
|
2000-05-06 21:34:20 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("Reading %s...\n", configfile));
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Read each line into the buffer and then parse the line, */
|
|
|
|
/* do the table lookup and execute the handler for that */
|
|
|
|
/* function. */
|
2004-07-09 04:16:31 +02:00
|
|
|
done = nCfgLine = 0;
|
|
|
|
do
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
PStr q;
|
|
|
|
PCStr p;
|
|
|
|
const struct table *pEntry;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
/* read in a single line, \n or ^Z terminated */
|
2004-07-09 04:16:31 +02:00
|
|
|
nCfgLine++;
|
|
|
|
for (q = szLine;;)
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (read(nFileDesc, q, 1) <= 0 || *q == EOF)
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
done++;
|
2001-11-18 15:01:12 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*q == '\n') /* end of line */
|
2001-11-18 15:01:12 +01:00
|
|
|
break;
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*q != '\r') /* ignore CR */
|
|
|
|
{
|
|
|
|
q++;
|
|
|
|
if (q >= szLine + sizeof szLine - 1)
|
|
|
|
{
|
|
|
|
/* *q = 0; */ /* static memory already zeroed */
|
|
|
|
CfgFailure(q);
|
|
|
|
say("error - line overflow\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* for */
|
|
|
|
*q = 0; /* terminate line - make ASCIIZ */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
p = skipwh(szLine);
|
|
|
|
if (*p == '\0' || *p == ';')
|
|
|
|
continue; /* skip empty line and comment */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
p = scanverb(p, szBuf); /* extract verb */
|
|
|
|
pEntry = LookUp(szBuf);
|
|
|
|
if (pEntry == NULL)
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass == 2) /* only at pass 2 (after menu)... */
|
|
|
|
CfgFailure(p); /* ...say error for wrong verb */
|
2001-11-18 15:01:12 +01:00
|
|
|
continue;
|
2002-01-23 23:29:41 +01:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass != pEntry->pass ||
|
|
|
|
nPass > 1 && /* after menu: check "123?device=" */
|
|
|
|
!testbit(line_choices, last_choice))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pEntry->func != CfgMenu && pEntry->func != CfgMenuEsc)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p != ' ' && *p != '\t' && *p != '=')
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p = skipwh(p);
|
|
|
|
if (*p == '=') /* accept "device foo.sys" without '=' */
|
|
|
|
p = skipwh(p + 1);
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass > 1 && askSkipLine()) /* after menu: processing "?" */
|
|
|
|
continue;
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p == ' ' || *p == '\t')
|
|
|
|
p++;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2003-09-18 22:55:41 +02:00
|
|
|
/* YES. DO IT */
|
2004-07-09 04:16:31 +02:00
|
|
|
pEntry->func(p);
|
|
|
|
} while (!done && !(askCommand & ASK_SKIPALL));
|
2002-05-09 00:49:35 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
close(nFileDesc);
|
|
|
|
nPass++;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
void DoConfig()
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
DoConfig_(); /* switches=/f/n, menucolor= */
|
|
|
|
hintSkipAll();
|
|
|
|
if (!(askCommand & ASK_SKIPALL))
|
|
|
|
{
|
|
|
|
if (MenuColor) /* color defined? */
|
|
|
|
ClearScreenArea(MenuColor, 0, 0, screenwidth(), screenbottom() + 1);
|
|
|
|
DoConfig_(); /* show MENU, find choices */
|
|
|
|
if (all_choices)
|
|
|
|
{
|
|
|
|
if (!testbit(all_choices, last_choice))
|
|
|
|
{
|
|
|
|
unsigned ac;
|
|
|
|
last_choice = 0; /* find lowest existing choice */
|
|
|
|
for (ac = all_choices; !testbit(ac, 0); ac >>= 1)
|
|
|
|
last_choice++;
|
|
|
|
}
|
|
|
|
if ((all_choices - 1) & all_choices) /* more than one choice? */
|
|
|
|
DoMenu();
|
|
|
|
if (!(askCommand & ASK_SKIPALL))
|
|
|
|
{
|
|
|
|
static char choice[] = "CONFIG=0";
|
|
|
|
choice[7] = (UBYTE)'0' + last_choice;
|
|
|
|
CmdSet(choice); /* show choice in environment */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
commands[0].pass = 2; /* switches=/k/e at pass 2 */
|
|
|
|
DoConfig_(); /* break=, files=, etc. */
|
|
|
|
}
|
|
|
|
PreConfig3();
|
|
|
|
DoConfig_(); /* device= */
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2001-04-29 19:34:41 +02:00
|
|
|
/*
|
|
|
|
get BIOS key with timeout:
|
2004-07-09 04:16:31 +02:00
|
|
|
timeout < 0: no timeout, remove returned key from keyboard buffer
|
2001-04-29 19:34:41 +02:00
|
|
|
timeout = 0: poll only once
|
2004-07-09 04:16:31 +02:00
|
|
|
timeout > 0: timeout for poll in seconds
|
2001-04-29 19:34:41 +02:00
|
|
|
return
|
2004-07-09 04:16:31 +02:00
|
|
|
0 : no key hit (only for timeout >= 0)
|
2001-04-29 19:34:41 +02:00
|
|
|
0xHH.. : scancode in upper half
|
|
|
|
0x..LL : asciicode in lower half
|
|
|
|
*/
|
|
|
|
|
2004-05-24 20:39:49 +02:00
|
|
|
#define GetBiosTime() peekl(0, 0x46c)
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
#define ESC 27
|
|
|
|
#define K_F5 0x3F00
|
|
|
|
#define K_F8 0x4200
|
|
|
|
#define K_Left 0x4B00
|
|
|
|
#define K_Right 0x4D00
|
|
|
|
#define K_Up 0x4800
|
|
|
|
#define K_Down 0x5000
|
|
|
|
|
|
|
|
unsigned GetBiosKey(int timeout)
|
2001-04-29 19:34:41 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
iregs r;
|
2004-07-09 04:16:31 +02:00
|
|
|
if (timeout >= 0)
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
ULONG startTime = GetBiosTime();
|
|
|
|
do
|
|
|
|
{
|
|
|
|
r.AH = 0x01; /* are there keys available ? */
|
|
|
|
init_call_intr(0x16, &r);
|
|
|
|
if (!(r.flags & FLG_ZERO))
|
|
|
|
return r.AX;
|
|
|
|
} while ((unsigned)(GetBiosTime() - startTime) < timeout * 18u);
|
|
|
|
return 0;
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2004-05-24 20:39:49 +02:00
|
|
|
|
|
|
|
/* key available or blocking wait (timeout < 0): fetch it */
|
2004-07-09 04:16:31 +02:00
|
|
|
r.AH = 0x00;
|
2004-05-24 20:39:49 +02:00
|
|
|
init_call_intr(0x16, &r);
|
2004-07-09 04:16:31 +02:00
|
|
|
return r.AX;
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static void hintSkipAll(void)
|
2001-04-29 19:34:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
int timeout = InitKernelConfig.SkipConfigSeconds;
|
|
|
|
if (timeout >= 0)
|
2001-04-29 19:34:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
unsigned key;
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if ((all_choices - 1) & all_choices) /* more than one choice? */
|
|
|
|
timeout = 0;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (timeout > 0)
|
|
|
|
say2("Press F8 to trace or F5 to skip %s/AUTOEXEC.BAT", configfile);
|
|
|
|
key = GetBiosKey(timeout);
|
|
|
|
clearrow(); /* clear hint line */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (key == K_F8) /* F8 */
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
askCommand |= ASK_TRACE;
|
|
|
|
GetBiosKey(-1); /* remove key from buffer */
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
else if (key == K_F5) /* F5 */
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
askCommand |= ASK_SKIPALL;
|
|
|
|
say2("Bypassing %s and AUTOEXEC.BAT files.\n", configfile);
|
|
|
|
GetBiosKey(-1); /* remove key from buffer */
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static BOOL askSkipLine(void)
|
|
|
|
{
|
|
|
|
/* !device= never ask / ?device= always ask / device= ask if ASK_TRACE */
|
|
|
|
/* "!device?=" will not be asked... */
|
|
|
|
if ((askCommand & (ASK_NOASK | ASK_YESALL)) || /* "!" or Esc */
|
|
|
|
!(askCommand & (ASK_ASK | ASK_TRACE))) /* not ("?" or trace) */
|
|
|
|
return FALSE; /* do not skip, and do not ask either */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
say2("%s[Y,n]?", szLine);
|
2001-04-29 19:34:41 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
unsigned key = GetBiosKey(-1); /* wait keypress */
|
|
|
|
if (key == K_F5) /* YES, you may hit F5 here, too */
|
|
|
|
{
|
|
|
|
askCommand |= ASK_SKIPALL;
|
|
|
|
key = 'N';
|
|
|
|
}
|
|
|
|
if (key == K_F8) /* F8 */
|
|
|
|
key = ESC;
|
|
|
|
switch (toupper((UBYTE)key))
|
2001-04-29 19:34:41 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
case 'N':
|
2004-07-09 04:16:31 +02:00
|
|
|
say("N\n");
|
2001-11-18 15:01:12 +01:00
|
|
|
return TRUE;
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
case ESC: /* Esc answers all following questions YES */
|
|
|
|
askCommand &= ~ASK_TRACE;
|
|
|
|
askCommand |= ASK_YESALL;
|
|
|
|
/* and fall through */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
case 'Y':
|
2004-07-09 04:16:31 +02:00
|
|
|
say("Y\n");
|
2001-11-18 15:01:12 +01:00
|
|
|
return FALSE;
|
2001-04-29 19:34:41 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
} /* for */
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static int numarg BSS_INIT(0);
|
|
|
|
|
2004-05-23 18:21:14 +02:00
|
|
|
/* JPP - changed so will accept hex number. */
|
|
|
|
/* ea - changed to accept hex digits in hex numbers */
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC PCStr GetNumArg(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-05-23 18:21:14 +02:00
|
|
|
static char digits[] = "0123456789ABCDEF";
|
|
|
|
unsigned char base = 10;
|
|
|
|
int sign = 1;
|
|
|
|
int n = 0;
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* look for NUMBER */
|
2004-05-23 18:21:14 +02:00
|
|
|
p = skipwh(p);
|
2004-07-09 04:16:31 +02:00
|
|
|
if (!isdigit(*p))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p != '-')
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-05-23 18:21:14 +02:00
|
|
|
sign = -1;
|
2004-07-09 04:16:31 +02:00
|
|
|
p++;
|
2004-05-23 18:21:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for( ; *p; p++)
|
|
|
|
{
|
|
|
|
char ch = toupper(*p);
|
|
|
|
if (ch == 'X')
|
|
|
|
base = 16;
|
|
|
|
else
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
PCStr q = strchr(digits, ch);
|
2004-05-23 18:21:14 +02:00
|
|
|
if (q == NULL)
|
|
|
|
break;
|
|
|
|
n = n * base + (q - digits);
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
numarg = n * sign;
|
2004-05-23 18:21:14 +02:00
|
|
|
return p;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC BOOL isEOL(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p) /* garbage at line end? */
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: nnn EOL */
|
|
|
|
STATIC BOOL GetNumArg1(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
p = GetNumArg(p);
|
|
|
|
if (p == NULL)
|
|
|
|
return FALSE;
|
|
|
|
return isEOL(skipwh(p));
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static int numarg1 BSS_INIT(0);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: nnn [, nnn] EOL */
|
|
|
|
STATIC BOOL GetNumArg2(PCStr p, int default2)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
p = GetNumArg(p);
|
2004-04-07 00:48:12 +02:00
|
|
|
if (p == NULL)
|
2004-07-09 04:16:31 +02:00
|
|
|
return FALSE;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
numarg1 = numarg;
|
|
|
|
numarg = default2;
|
|
|
|
p = skipwh(p);
|
|
|
|
if (*p == ',')
|
|
|
|
return GetNumArg1(p + 1);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
return isEOL(p);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: BUFFERS [=] nnn [, nnn] */
|
|
|
|
STATIC void Config_Buffers(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg2(p, 0))
|
|
|
|
Config.cfgBuffers = (UBYTE)numarg1;
|
|
|
|
/* Second argument (0..8 buffers for read-ahead) not supported */
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Set screen mode - rewritten to use init_call_intr() by RE / ICD */
|
|
|
|
/* Format: SCREEN [=] nnn */
|
|
|
|
STATIC void sysScreenMode(PCStr p)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg1(p))
|
|
|
|
{
|
|
|
|
unsigned mode = numarg;
|
|
|
|
if (mode >= 0x10)
|
|
|
|
{
|
|
|
|
/* Modes
|
|
|
|
0x11 (17) 28 lines
|
|
|
|
0x12 (18) 43/50 lines
|
|
|
|
0x14 (20) 25 lines
|
|
|
|
*/
|
|
|
|
if (mode != 0x11 && mode != 0x12 && mode != 0x14)
|
|
|
|
return; /* do nothing; invalid screenmode */
|
|
|
|
mode |= 0x1100;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
iregs r;
|
|
|
|
r.BL = 0; /* block to load for AH=0x11 */
|
|
|
|
r.AX = mode; /* set videomode */
|
|
|
|
init_call_intr(0x10, &r);
|
|
|
|
}
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: VERSION [=] nn.nn */
|
|
|
|
STATIC void sysVersion(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
int major;
|
|
|
|
p = GetNumArg(p);
|
|
|
|
major = numarg;
|
|
|
|
if (p == NULL || *p != '.' || !GetNumArg1(p + 1))
|
|
|
|
return;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
printf("Changing reported version to %d.%d\n",
|
|
|
|
LoL->os_setver_major = (UBYTE)major,
|
|
|
|
LoL->os_setver_minor = (UBYTE)numarg);
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: FILES [=] nnn */
|
|
|
|
/* Format: FILESHIGH [=] nnn */
|
|
|
|
static void _Files(PCStr p, UBYTE high)
|
|
|
|
{
|
|
|
|
if (GetNumArg1(p))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE nFiles = (UBYTE)numarg;
|
|
|
|
if (Config.cfgFiles < nFiles)
|
|
|
|
Config.cfgFiles = nFiles;
|
|
|
|
Config.cfgFilesHigh = high;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void Files(PCStr p) { _Files(p, 0); }
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void FilesHigh(PCStr p) { _Files(p, 1); }
|
2000-08-06 07:50:17 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: LASTDRIVE [=] letter */
|
|
|
|
/* Format: LASTDRIVEHIGH [=] letter */
|
|
|
|
static void _CfgLastdrive(PCStr p, UBYTE high)
|
2000-06-21 20:16:46 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
BYTE drv = toupper(*p);
|
|
|
|
if (drv < 'A' || drv > 'Z' || p[1])
|
|
|
|
{
|
|
|
|
/* no or wrong character or garbage at line end? */
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
}
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
drv -= 'A' - 1; /* Make real number */
|
|
|
|
if (Config.cfgLastdrive < drv)
|
|
|
|
Config.cfgLastdrive = drv;
|
|
|
|
Config.cfgLastdriveHigh = high;
|
|
|
|
}
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void CfgLastdrive(PCStr p) { _CfgLastdrive(p, 0); }
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void CfgLastdriveHigh(PCStr p) { _CfgLastdrive(p, 1); }
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* UmbState of confidence, UMB_DONE is sure, UMB_REQ maybe, UMB_NONE no way.
|
|
|
|
Transitions: UMB_NONE -> UMB_NONE/UMB_REQ depending on DOS=UMB, try init
|
|
|
|
(UMB_REQ -> UMB_DONE) after each driver load, as it could have been the
|
|
|
|
UMB driver.
|
|
|
|
If UMB really found, state UMB_DONE is reached and MCBs are adjusted.
|
|
|
|
*/
|
|
|
|
/* opt = HIGH | UMB
|
|
|
|
Format: DOS [=] opt {, opt}
|
|
|
|
*/
|
|
|
|
STATIC void Dosmem(PCStr p)
|
|
|
|
{
|
|
|
|
UBYTE UMBwanted = UMB_NONE, HMAwanted = HMA_NONE;
|
|
|
|
for (;;)
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
PCStr q = scanword(p, szBuf);
|
|
|
|
if (!strcasediff(szBuf, "UMB"))
|
|
|
|
UMBwanted = UMB_REQ;
|
|
|
|
else if (!strcasediff(szBuf, "HIGH"))
|
|
|
|
HMAwanted = HMA_REQ;
|
|
|
|
/* else if (!strcasediff(szBuf, "CLAIMINIT"))
|
|
|
|
* INITDataSegmentClaimed = 0;
|
|
|
|
*/
|
|
|
|
else
|
2001-03-21 03:56:26 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
2001-03-21 03:56:26 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
p = skipwh(q);
|
|
|
|
if (*p != ',')
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p == '\0')
|
|
|
|
break;
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
2000-06-21 20:16:46 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
p++;
|
|
|
|
} /* for */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (UmbState == UMB_NONE)
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2003-06-15 17:53:58 +02:00
|
|
|
LoL->uppermem_link = 0;
|
|
|
|
LoL->uppermem_root = 0xffff;
|
2004-07-09 04:16:31 +02:00
|
|
|
UmbState = UMBwanted;
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
/* Check if HMA is available straight away */
|
2004-07-09 04:16:31 +02:00
|
|
|
if (HMAwanted == HMA_REQ)
|
|
|
|
HMAState = MoveKernelToHMA() ? HMA_DONE : HMA_REQ;
|
2000-06-21 20:16:46 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: DOSDATA [=] UMB */
|
|
|
|
STATIC void DosData(PCStr p)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (!strcasediff(p, "UMB"))
|
2003-06-15 15:24:53 +02:00
|
|
|
Config.cfgDosDataUmb = TRUE;
|
2004-07-09 04:16:31 +02:00
|
|
|
else
|
|
|
|
CfgFailure(p);
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: SWITCHAR [=] character */
|
|
|
|
STATIC void CfgSwitchar(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p == '\0' || p[1])
|
|
|
|
{
|
|
|
|
/* no character or garbage at line end */
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
init_switchar(*p);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: SWITCHES [=] { /K | /N | /F | /E[[:]nnn] } */
|
|
|
|
STATIC void CfgSwitches(PCStr p)
|
2003-06-17 13:53:37 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
do
|
2003-06-17 13:53:37 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p != '/')
|
|
|
|
{
|
|
|
|
if (nPass)
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch(toupper(*++p))
|
|
|
|
{
|
2003-06-17 13:53:37 +02:00
|
|
|
case 'K':
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass)
|
2003-06-17 13:53:37 +02:00
|
|
|
kbdType = 0; /* force conv keyb */
|
2004-07-09 04:16:31 +02:00
|
|
|
p++;
|
2003-06-17 13:53:37 +02:00
|
|
|
break;
|
|
|
|
case 'N':
|
|
|
|
InitKernelConfig.SkipConfigSeconds = -1;
|
2004-07-09 04:16:31 +02:00
|
|
|
p++;
|
2003-06-17 13:53:37 +02:00
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
InitKernelConfig.SkipConfigSeconds = 0;
|
2004-07-09 04:16:31 +02:00
|
|
|
p++;
|
2003-06-17 13:53:37 +02:00
|
|
|
break;
|
2003-09-04 21:14:16 +02:00
|
|
|
case 'E': /* /E[[:]nnnn] Set the desired EBDA amount to move in bytes */
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Note that if there is no EBDA, this will have no effect */
|
|
|
|
if (*++p == ':')
|
|
|
|
p++; /* skip optional separator */
|
|
|
|
if (isdigit(*p))
|
|
|
|
{
|
|
|
|
p = GetNumArg(p);
|
|
|
|
if (p == NULL)
|
|
|
|
return;
|
2003-09-09 19:30:10 +02:00
|
|
|
/* allowed values: [48..1024] bytes, multiples of 16
|
2003-09-04 21:14:16 +02:00
|
|
|
* e.g. AwardBIOS: 48, AMIBIOS: 1024
|
|
|
|
* (Phoenix, MRBIOS, Unicore = ????)
|
|
|
|
*/
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass)
|
|
|
|
Config.ebda2move = numarg;
|
2003-09-04 21:14:16 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
break;
|
2003-06-17 13:53:37 +02:00
|
|
|
default:
|
2004-07-09 04:16:31 +02:00
|
|
|
if (nPass)
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
} /* switch */
|
|
|
|
p = skipwh(p);
|
|
|
|
} while (*p);
|
2003-06-17 13:53:37 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: FCBS [=] totalFcbs [, protectedFcbs] */
|
|
|
|
STATIC void Fcbs(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg2(p, Config.cfgProtFcbs))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE fcbs = (UBYTE)numarg1, prot = (UBYTE)numarg;
|
|
|
|
Config.cfgFcbs = fcbs;
|
|
|
|
if (prot > fcbs)
|
|
|
|
prot = fcbs;
|
|
|
|
Config.cfgProtFcbs = prot;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-08 06:30:00 +02:00
|
|
|
/* LoadCountryInfo():
|
|
|
|
* Searches a file in the COUNTRY.SYS format for an entry
|
|
|
|
* matching the specified code page and country code, and loads
|
|
|
|
* the corresponding information into memory. If code page is 0,
|
|
|
|
* the default code page for the country will be used.
|
|
|
|
*/
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void LoadCountryInfo(CStr filename, int ccode, int cpage)
|
2000-05-08 06:30:00 +02:00
|
|
|
{
|
2004-09-03 11:26:53 +02:00
|
|
|
/* COUNTRY.SYS file data structures - see RBIL tables 2619-2622 */
|
|
|
|
|
|
|
|
struct { /* file header */
|
|
|
|
char name[8]; /* "\377COUNTRY.SYS" */
|
|
|
|
char reserved[11];
|
|
|
|
ULONG offset; /* offset of first entry in file */
|
|
|
|
} header;
|
|
|
|
struct { /* entry */
|
|
|
|
int length; /* length of entry, not counting this word, = 12 */
|
|
|
|
int country; /* country ID */
|
|
|
|
int codepage; /* codepage ID */
|
|
|
|
int reserved[2];
|
|
|
|
ULONG offset; /* offset of country-subfunction-header in file */
|
|
|
|
} entry;
|
|
|
|
struct { /* subfunction header */
|
|
|
|
int length; /* length of entry, not counting this word, = 6 */
|
|
|
|
int id; /* subfunction ID */
|
|
|
|
ULONG offset; /* offset within file of subfunction data entry */
|
|
|
|
} subf_hdr;
|
|
|
|
struct { /* subfunction data */
|
|
|
|
char signature[8]; /* \377CTYINFO|UCASE|LCASE|FUCASE|FCHAR|COLLATE|DBCS */
|
|
|
|
int length; /* length of following table in bytes */
|
|
|
|
} subf_data;
|
|
|
|
struct CountrySpecificInfo country;
|
|
|
|
int fd, entries, count, i, j;
|
|
|
|
|
|
|
|
if ((fd = open(filename, 0)) < 0)
|
|
|
|
{
|
|
|
|
printf("%s not found\n", filename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (read(fd, &header, sizeof(header)) < sizeof(header))
|
|
|
|
{
|
|
|
|
printf("Can't read %s\n", filename);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
if (memcmp(&header.name, "\377COUNTRY", 8))
|
|
|
|
{
|
|
|
|
err:printf("%s has invalid format\n", filename);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
if (lseek(fd, header.offset) == 0xffffffffL
|
|
|
|
|| read(fd, &entries, sizeof(entries)) < sizeof(entries))
|
|
|
|
goto err;
|
|
|
|
for (i = 0; i < entries; i++)
|
|
|
|
{
|
|
|
|
if (read(fd, &entry, sizeof(entry)) < sizeof(entry) || entry.length != 12)
|
|
|
|
goto err;
|
|
|
|
if (entry.country != ccode || entry.codepage != cpage && cpage)
|
|
|
|
continue;
|
|
|
|
if (lseek(fd, entry.offset) == 0xffffffffL
|
|
|
|
|| read(fd, &count, sizeof(count)) < sizeof(count))
|
|
|
|
goto err;
|
|
|
|
for (j = 0; j < count; j++)
|
|
|
|
{
|
|
|
|
if (read(fd, &subf_hdr, sizeof(subf_hdr)) < sizeof(subf_hdr)
|
|
|
|
|| subf_hdr.length != 6)
|
|
|
|
goto err;
|
|
|
|
if (subf_hdr.id != 1)
|
|
|
|
continue;
|
|
|
|
if (lseek(fd, subf_hdr.offset) == 0xffffffffL
|
|
|
|
|| read(fd, &subf_data, sizeof(subf_data)) < sizeof(subf_data)
|
|
|
|
|| memcmp(&subf_data.signature, "\377CTYINFO", 8))
|
|
|
|
goto err;
|
|
|
|
if (read(fd, &country, sizeof(country)) < sizeof(country))
|
|
|
|
goto err;
|
|
|
|
if (country.CountryID != entry.country
|
|
|
|
|| country.CodePage != entry.codepage && cpage)
|
|
|
|
continue;
|
|
|
|
i = nlsCountryInfoHardcoded.C.CodePage;
|
|
|
|
fmemcpy(&nlsCountryInfoHardcoded.C, &country,
|
|
|
|
min(sizeof(country), subf_data.length));
|
|
|
|
nlsCountryInfoHardcoded.C.CodePage = i;
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("couldn't find country info for country ID %u\n", ccode);
|
|
|
|
ret:
|
|
|
|
close(fd);
|
2004-07-09 04:16:31 +02:00
|
|
|
}
|
2000-05-08 06:30:00 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: COUNTRY [=] countryCode [, [codePage] [, filename]] */
|
|
|
|
STATIC void Country(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
int ccode;
|
2004-09-03 11:26:53 +02:00
|
|
|
PCStr filename = "\\COUNTRY.SYS";
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
p = GetNumArg(p);
|
|
|
|
if (p == NULL)
|
|
|
|
return;
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
ccode = numarg;
|
2004-09-03 11:26:53 +02:00
|
|
|
numarg = 0;
|
2004-07-09 04:16:31 +02:00
|
|
|
p = skipwh(p);
|
|
|
|
if (*p == ',')
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
p = skipwh(p + 1);
|
|
|
|
if (*p != ',')
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
p = GetNumArg(p);
|
|
|
|
if (p == NULL)
|
|
|
|
return;
|
|
|
|
p = skipwh(p);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p == ',')
|
|
|
|
filename = p + 1;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p && *p != ',') /* garbage at line end? */
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2003-06-15 15:24:53 +02:00
|
|
|
|
2004-09-03 11:26:53 +02:00
|
|
|
LoadCountryInfo(filename, ccode, numarg);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: STACKS [=] stacks [, stackSize] */
|
|
|
|
/* Format: STACKSHIGH [=] stacks [, stackSize] */
|
|
|
|
static void _Stacks(PCStr p, UBYTE high)
|
2001-03-30 21:30:06 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg2(p, Config.cfgStackSize))
|
|
|
|
{
|
|
|
|
UBYTE stacks = (UBYTE)numarg1;
|
|
|
|
UWORD sz = numarg;
|
|
|
|
if (stacks > 64)
|
|
|
|
stacks = 64;
|
|
|
|
if (sz < 32)
|
|
|
|
sz = 32;
|
|
|
|
if (sz > 512)
|
|
|
|
sz = 512;
|
|
|
|
Config.cfgStacks = stacks;
|
|
|
|
Config.cfgStackSize = sz;
|
|
|
|
Config.cfgStacksHigh = high;
|
|
|
|
}
|
2001-03-30 21:30:06 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void Stacks(PCStr p) { _Stacks(p, 0); }
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void StacksHigh(PCStr p) { _Stacks(p, 1); }
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: SHELL [=] command */
|
|
|
|
STATIC void CmdShell(PCStr p)
|
|
|
|
{
|
2001-03-30 21:30:06 +02:00
|
|
|
Config.cfgP_0_startmode = 0;
|
2004-07-09 04:16:31 +02:00
|
|
|
/* assume strlen(p)+1 <= sizeof Config.cfgShell */
|
|
|
|
strcpy(Config.cfgShell, p);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: SHELLHIGH [=] command */
|
|
|
|
STATIC void CmdShellHigh(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
Config.cfgP_0_startmode = 0x80;
|
|
|
|
/* assume strlen(p)+1 <= sizeof Config.cfgShell */
|
|
|
|
strcpy(Config.cfgShell, p);
|
2001-03-25 19:11:54 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: BREAK [=] (ON | OFF) */
|
|
|
|
STATIC void CfgBreak(PCStr p)
|
2001-03-25 19:11:54 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (!strcasediff(p, "ON"))
|
|
|
|
break_ena = 1;
|
|
|
|
else if (!strcasediff(p, "OFF"))
|
|
|
|
break_ena = 0;
|
|
|
|
else
|
|
|
|
CfgFailure(p);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: NUMLOCK [=] (ON | OFF) */
|
|
|
|
STATIC void Numlock(PCStr p)
|
2000-06-21 20:16:46 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE FAR *keyflags = MK_PTR(UBYTE, 0, 0x417);
|
|
|
|
if (!strcasediff(p, "ON"))
|
|
|
|
*keyflags |= 32;
|
|
|
|
else if (!strcasediff(p, "OFF"))
|
|
|
|
*keyflags &= ~32;
|
2001-11-18 15:01:12 +01:00
|
|
|
else
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
keycheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Format: DEVICEHIGH [=] command */
|
|
|
|
STATIC void DeviceHigh(PCStr p)
|
|
|
|
{
|
|
|
|
if (UmbState != UMB_DONE || /* UMB not initialized? */
|
|
|
|
LoadDevice(p, MK_SEG_PTR(void, mcb_next(umb_base_start)), TRUE) == DE_NOMEM)
|
|
|
|
Device(p);
|
2000-06-21 20:16:46 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: DEVICE [=] command */
|
|
|
|
STATIC void Device(PCStr p)
|
2000-06-21 20:16:46 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
LoadDevice(p, lpTop, FALSE);
|
2000-06-21 20:16:46 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC BOOL LoadDevice(PCStr p, VFP top, int mode)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
int ret;
|
2000-06-21 20:16:46 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t base = base_seg;
|
|
|
|
seg_t start = LoL->first_mcb;
|
2001-11-18 15:01:12 +01:00
|
|
|
if (mode)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
|
|
|
base = umb_base_seg;
|
2004-07-09 04:16:31 +02:00
|
|
|
start = umb_base_start;
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
if (base == start)
|
|
|
|
base++;
|
|
|
|
base++;
|
2004-07-09 04:16:31 +02:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Get the device driver name */
|
2004-07-09 04:16:31 +02:00
|
|
|
{
|
|
|
|
PStr d = szBuf;
|
|
|
|
PCStr s = p;
|
|
|
|
for (; (UBYTE)*s > ' '; d++, s++)
|
|
|
|
*d = *s;
|
|
|
|
*d = '\0';
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* The driver is loaded at the top of allocated memory. */
|
|
|
|
/* The device driver is paragraph aligned. */
|
2004-07-09 04:16:31 +02:00
|
|
|
{
|
|
|
|
exec_blk eb;
|
|
|
|
eb.load.reloc = eb.load.load_seg = base;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2004-07-09 04:16:31 +02:00
|
|
|
printf("Loading device driver %s at segment %04x\n", szBuf, base);
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
ret = init_DosExec(3, &eb, szBuf);
|
|
|
|
if (ret != SUCCESS)
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
return ret;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2001-04-16 16:28:32 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
strcpy(szBuf, p);
|
2003-06-17 13:53:37 +02:00
|
|
|
/* uppercase the device driver command */
|
2004-07-09 04:16:31 +02:00
|
|
|
/* add \r\n to the command line */
|
|
|
|
strcat(strupr(szBuf), " \r\n");
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
/* TE this fixes the loading of devices drivers with
|
|
|
|
multiple devices in it. NUMEGA's SoftIce is such a beast
|
|
|
|
*/
|
|
|
|
|
2003-10-30 13:22:06 +01:00
|
|
|
/* NOTE - Modification for multisegmented device drivers: */
|
|
|
|
/* In order to emulate the functionallity experienced with other */
|
|
|
|
/* DOS operating systems, the original 'top' end address is */
|
|
|
|
/* updated with the end address returned from the INIT request. */
|
|
|
|
/* The updated end address is then used when issuing the next */
|
|
|
|
/* INIT request for the following device driver within the file */
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
ofs_t next = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
struct dhdr FAR *dhp = MK_PTR(struct dhdr, base, next);
|
|
|
|
if ((ret = init_device(dhp, szBuf, mode, &top)) != SUCCESS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
next = FP_OFF(dhp->dh_next);
|
|
|
|
|
|
|
|
/* Link in device driver and save LoL->nul_dev pointer to next */
|
|
|
|
dhp->dh_next = LoL->nul_dev.dh_next;
|
|
|
|
LoL->nul_dev.dh_next = dhp;
|
|
|
|
} while (next != 0xffff);
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2003-06-15 15:24:53 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* might have been the UMB driver -> try UMB initialization */
|
|
|
|
umb_init();
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
return ret;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void CfgFailure(PCStr p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
printf("Error in %s line %d:\n"
|
|
|
|
"%s\n", configfile, nCfgLine, szLine);
|
|
|
|
gotoxy(p - szLine, screeny());
|
|
|
|
say("^\n");
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
struct submcb
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2003-06-15 15:24:53 +02:00
|
|
|
char type;
|
|
|
|
unsigned short start;
|
|
|
|
unsigned short size;
|
|
|
|
char unused[3];
|
|
|
|
char name[8];
|
|
|
|
};
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
void _seg * KernelAllocPara(size_t nPara, UBYTE type, CStr name, int mode)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t base, start;
|
|
|
|
struct submcb _seg *p;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (mode && UmbState == UMB_DONE)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
|
|
|
base = umb_base_seg;
|
2004-07-09 04:16:31 +02:00
|
|
|
start = umb_base_start;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
else
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
mode = 0;
|
2003-06-15 15:24:53 +02:00
|
|
|
base = base_seg;
|
2003-06-15 17:53:58 +02:00
|
|
|
start = LoL->first_mcb;
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
/* create the special DOS data MCB if it doesn't exist yet */
|
|
|
|
DebugPrintf(("kernelallocpara: %x %x %x %c %d\n", start, base, nPara, type, mode));
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2003-06-15 15:24:53 +02:00
|
|
|
if (base == start)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
mcb _seg *p = MK_SEG_PTR(mcb, base);
|
|
|
|
mcb_init(++base, p->m_size, p->m_type);
|
|
|
|
mumcb_init(FP_SEG(p), 1);
|
2003-06-30 20:50:38 +02:00
|
|
|
p->m_name[1] = 'D';
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2003-06-30 20:50:38 +02:00
|
|
|
nPara++;
|
2004-07-09 04:16:31 +02:00
|
|
|
mcb_init(base + nPara, MK_SEG_PTR(mcb, base)->m_size - nPara + 1,
|
|
|
|
MK_SEG_PTR(mcb, base)->m_type);
|
|
|
|
MK_SEG_PTR(mcb, start)->m_size += nPara;
|
2003-06-15 15:24:53 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
p = MK_SEG_PTR(struct submcb, base);
|
2003-06-15 15:24:53 +02:00
|
|
|
p->type = type;
|
|
|
|
p->start = FP_SEG(p)+1;
|
2004-07-09 04:16:31 +02:00
|
|
|
p->size = nPara - 1;
|
2003-06-15 15:24:53 +02:00
|
|
|
if (name)
|
|
|
|
fmemcpy(p->name, name, 8);
|
2003-06-30 20:50:38 +02:00
|
|
|
base += nPara;
|
2003-06-15 15:24:53 +02:00
|
|
|
if (mode)
|
|
|
|
umb_base_seg = base;
|
|
|
|
else
|
|
|
|
base_seg = base;
|
2004-07-09 04:16:31 +02:00
|
|
|
return MK_SEG_PTR(void, FP_SEG(p) + 1);
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
void _seg * KernelAlloc(size_t nBytes, UBYTE type, int mode)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
void _seg *p;
|
|
|
|
size_t nPara = (nBytes + 15) / 16;
|
2003-06-15 15:24:53 +02:00
|
|
|
|
2003-06-15 17:53:58 +02:00
|
|
|
if (LoL->first_mcb == 0)
|
2003-06-15 15:24:53 +02:00
|
|
|
{
|
|
|
|
/* prealloc */
|
2004-07-09 04:16:31 +02:00
|
|
|
/* note: lpTop is already para-aligned */
|
|
|
|
return alignNextPara(lpTop = MK_FP(FP_SEG(lpTop) - nPara, FP_OFF(lpTop)));
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
p = KernelAllocPara(nPara, type, NULL, mode);
|
2003-06-15 15:24:53 +02:00
|
|
|
fmemset(p, 0, nBytes);
|
|
|
|
return p;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef I86
|
2003-03-13 00:06:48 +01:00
|
|
|
#if 0
|
2003-06-15 15:24:53 +02:00
|
|
|
STATIC BYTE FAR * KernelAllocDma(WORD bytes, char type)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2003-06-15 15:24:53 +02:00
|
|
|
if ((base_seg & 0x0fff) + (bytes >> 4) > 0x1000) {
|
|
|
|
KernelAllocPara((base_seg + 0x0fff) & 0xf000 - base_seg, type, NULL, 0);
|
|
|
|
}
|
|
|
|
return KernelAlloc(bytes, type);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2003-03-13 00:06:48 +01:00
|
|
|
#endif
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
void _seg * alignNextPara(CVFP p)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
/* First, convert the segmented pointer to linear address */
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t seg = FP_OFF(p);
|
|
|
|
if (seg)
|
|
|
|
seg = (seg - 1) / 16 + 1;
|
|
|
|
seg += FP_SEG(p);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* return an address adjusted to the nearest paragraph boundary */
|
|
|
|
return MK_SEG_PTR(void, seg);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC PCStr skipwh(PCStr s)
|
2004-03-26 12:26:55 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
s--;
|
|
|
|
do
|
|
|
|
s++;
|
|
|
|
while (*s == ' ' || *s == '\t');
|
|
|
|
return s;
|
2004-03-26 12:26:55 +01:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC PCStr scanword(PCStr s, PStr d)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
s = skipwh(s);
|
|
|
|
while (*s >= 'a' && *s <= 'z' ||
|
|
|
|
*s >= 'A' && *s <= 'Z')
|
|
|
|
*d++ = *s++;
|
|
|
|
*d = '\0';
|
2000-05-06 21:34:20 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC PCStr scanverb(PCStr s, PStr d)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
askCommand &= ~(ASK_ASK | ASK_NOASK);
|
|
|
|
line_choices = 0xffff; /* statement in all menus */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
for (;; s++)
|
|
|
|
{
|
|
|
|
s = skipwh(s);
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*s == '!') /* "!dos" ? */
|
|
|
|
askCommand |= ASK_NOASK;
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
else if (*s == '?') /* "?device" ? */
|
|
|
|
askCommand |= ASK_ASK;
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
else
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE ch = *s - (UBYTE)'0';
|
|
|
|
if (ch <= 9) /* "123?device" ? */
|
|
|
|
{
|
|
|
|
PCStr p = s;
|
|
|
|
unsigned digits = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
digits |= 1 << ch;
|
|
|
|
ch = *++p - (UBYTE)'0';
|
|
|
|
} while (ch <= 9);
|
2002-05-09 00:49:35 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p != '?')
|
|
|
|
break;
|
|
|
|
|
|
|
|
s = p;
|
|
|
|
line_choices = digits;
|
|
|
|
all_choices |= digits;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
} /* else */
|
|
|
|
} /* for */
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
s = scanword(s, d);
|
|
|
|
|
|
|
|
if (*s == '?') /* "device?" ? */
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
askCommand |= ASK_ASK;
|
|
|
|
s++;
|
2001-11-14 00:36:45 +01:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Yet another change for true portability (PJV) */
|
2004-05-23 18:21:14 +02:00
|
|
|
STATIC char toupper(char c)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
if (c >= 'a' && c <= 'z')
|
2004-05-23 18:21:14 +02:00
|
|
|
c -= 'a' - 'A';
|
|
|
|
return c;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2003-10-05 18:22:57 +02:00
|
|
|
/* Convert string s to uppercase */
|
2004-07-09 04:16:31 +02:00
|
|
|
static PStr strupr(PStr s)
|
2003-10-05 18:22:57 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
PStr d = s;
|
|
|
|
for (;; d++)
|
|
|
|
{
|
|
|
|
char ch = *d;
|
|
|
|
if (ch == '\0')
|
|
|
|
break;
|
|
|
|
*d = toupper(ch);
|
2004-01-26 01:47:56 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
return s;
|
2003-10-05 18:22:57 +02:00
|
|
|
}
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* The following code is 8086 dependant */
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
#if 1 /* ifdef KERNEL */
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void mcb_init_copy(seg_t seg, size_t size, mcb *near_mcb)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
near_mcb->m_size = size - 1;
|
|
|
|
fmemcpy(MK_SEG_PTR(mcb, seg), near_mcb, sizeof(mcb));
|
2003-06-30 20:50:38 +02:00
|
|
|
}
|
2000-08-06 07:50:17 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void mcb_init(seg_t seg, size_t size, BYTE type)
|
2003-06-30 20:50:38 +02:00
|
|
|
{
|
2004-04-14 01:46:25 +02:00
|
|
|
static mcb near_mcb BSS_INIT({0});
|
2003-06-30 20:50:38 +02:00
|
|
|
near_mcb.m_type = type;
|
|
|
|
mcb_init_copy(seg, size, &near_mcb);
|
2000-06-21 20:16:46 +02:00
|
|
|
}
|
2000-08-06 07:50:17 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void mumcb_init(seg_t seg, size_t size)
|
2000-08-06 07:50:17 +02:00
|
|
|
{
|
2003-06-30 20:50:38 +02:00
|
|
|
static mcb near_mcb = {
|
|
|
|
MCB_NORMAL,
|
|
|
|
8, 0,
|
|
|
|
{0,0,0},
|
|
|
|
{"SC"}
|
|
|
|
};
|
|
|
|
mcb_init_copy(seg, size, &near_mcb);
|
2000-08-06 07:50:17 +02:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static PStr strcat(PStr d, PCStr s)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2003-10-05 18:22:57 +02:00
|
|
|
strcpy(d + strlen(d), s);
|
|
|
|
return d;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2001-03-25 19:11:54 +02:00
|
|
|
/* compare two ASCII strings ignoring case */
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC char strcasediff(PCStr d, PCStr s)
|
2001-03-25 19:11:54 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
while (toupper(*s) == toupper(*d))
|
|
|
|
{
|
|
|
|
if (*s == '\0')
|
|
|
|
return 0;
|
|
|
|
s++, d++;
|
|
|
|
}
|
|
|
|
return 1;
|
2001-03-25 19:11:54 +02:00
|
|
|
}
|
2001-03-21 03:56:26 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
moved from BLOCKIO.C here.
|
2004-07-09 04:16:31 +02:00
|
|
|
that saves some relocation problems
|
2001-03-21 03:56:26 +01:00
|
|
|
*/
|
|
|
|
|
2004-04-11 00:48:26 +02:00
|
|
|
STATIC void config_init_buffers(int wantedbuffers)
|
2001-03-21 03:56:26 +01:00
|
|
|
{
|
|
|
|
struct buffer FAR *pbuffer;
|
2004-04-11 00:48:26 +02:00
|
|
|
unsigned buffers = 0;
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* fill HMA with buffers if BUFFERS count >=0 and DOS in HMA */
|
2004-04-11 00:48:26 +02:00
|
|
|
if (wantedbuffers < 0)
|
|
|
|
wantedbuffers = -wantedbuffers;
|
2002-12-09 01:17:15 +01:00
|
|
|
else if (HMAState == HMA_DONE)
|
2004-04-11 00:48:26 +02:00
|
|
|
buffers = (0xfff0 - HMAFree) / sizeof(struct buffer);
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (wantedbuffers < 6) /* min 6 buffers */
|
2004-04-11 00:48:26 +02:00
|
|
|
wantedbuffers = 6;
|
2004-07-09 04:16:31 +02:00
|
|
|
if (wantedbuffers > 99) /* max 99 buffers */
|
2001-11-18 15:01:12 +01:00
|
|
|
{
|
2004-04-11 00:48:26 +02:00
|
|
|
printf("BUFFERS=%u not supported, reducing to 99\n", wantedbuffers);
|
|
|
|
wantedbuffers = 99;
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
if (buffers < wantedbuffers) /* not less than requested */
|
2004-04-11 00:48:26 +02:00
|
|
|
buffers = wantedbuffers;
|
2001-07-28 20:13:06 +02:00
|
|
|
|
2004-04-11 00:48:26 +02:00
|
|
|
LoL->nbuffers = buffers;
|
2003-06-15 17:53:58 +02:00
|
|
|
LoL->inforecptr = &LoL->firstbuf;
|
2003-07-12 22:56:11 +02:00
|
|
|
{
|
2004-04-11 00:48:26 +02:00
|
|
|
size_t bytes = sizeof(struct buffer) * buffers;
|
2004-07-09 04:16:31 +02:00
|
|
|
if ((pbuffer = HMAalloc(bytes)) == NULL)
|
2003-07-12 22:56:11 +02:00
|
|
|
{
|
|
|
|
pbuffer = KernelAlloc(bytes, 'B', 0);
|
2004-04-11 00:48:26 +02:00
|
|
|
if (HMAState == HMA_DONE)
|
|
|
|
firstAvailableBuf = MK_FP(0xffff, HMAFree);
|
2003-07-12 22:56:11 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LoL->bufloc = LOC_HMA;
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
/* space in HMA beyond requested buffers available as user space */
|
2004-04-11 00:48:26 +02:00
|
|
|
firstAvailableBuf = pbuffer + wantedbuffers;
|
2003-07-12 22:56:11 +02:00
|
|
|
}
|
|
|
|
}
|
2004-05-23 17:10:08 +02:00
|
|
|
LoL->deblock_buf = DiskTransferBuffer;
|
2003-07-12 22:56:11 +02:00
|
|
|
LoL->firstbuf = pbuffer;
|
2001-03-21 03:56:26 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("init_buffers (size %u) at (%p)",
|
|
|
|
sizeof(struct buffer), pbuffer));
|
2001-09-23 22:39:44 +02:00
|
|
|
|
2004-04-11 00:48:26 +02:00
|
|
|
buffers--;
|
|
|
|
pbuffer->b_prev = FP_OFF(pbuffer + buffers);
|
2001-03-21 03:56:26 +01:00
|
|
|
{
|
2004-04-11 00:48:26 +02:00
|
|
|
int i = buffers;
|
|
|
|
do
|
2002-12-09 01:17:15 +01:00
|
|
|
{
|
2004-04-11 00:48:26 +02:00
|
|
|
pbuffer->b_next = FP_OFF(pbuffer + 1);
|
|
|
|
pbuffer++;
|
|
|
|
pbuffer->b_prev = FP_OFF(pbuffer - 1);
|
2004-07-09 04:16:31 +02:00
|
|
|
} while (--i);
|
2002-12-09 01:17:15 +01:00
|
|
|
}
|
2004-04-11 00:48:26 +02:00
|
|
|
pbuffer->b_next = FP_OFF(pbuffer - buffers);
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2001-09-23 22:39:44 +02:00
|
|
|
DebugPrintf((" done\n"));
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (FP_SEG(pbuffer) == /*HMASEG*/0xFFFF)
|
2004-04-11 00:48:26 +02:00
|
|
|
{
|
|
|
|
buffers++;
|
2001-11-18 15:01:12 +01:00
|
|
|
printf("Kernel: allocated %d Diskbuffers = %u Bytes in HMA\n",
|
2004-04-11 00:48:26 +02:00
|
|
|
buffers, buffers * sizeof(struct buffer));
|
|
|
|
}
|
2001-03-21 03:56:26 +01:00
|
|
|
}
|
|
|
|
|
2004-03-27 00:27:18 +01:00
|
|
|
STATIC void config_init_fnodes(int f_nodes_cnt)
|
2004-03-27 00:10:13 +01:00
|
|
|
{
|
|
|
|
struct f_node FAR *p;
|
|
|
|
size_t bytes;
|
|
|
|
|
|
|
|
/* number of allocated files */
|
|
|
|
LoL->f_nodes_cnt = f_nodes_cnt;
|
|
|
|
bytes = f_nodes_cnt * sizeof(struct f_node);
|
|
|
|
|
|
|
|
p = HMAalloc(bytes);
|
|
|
|
if (p == NULL)
|
|
|
|
p = KernelAlloc(bytes, 'F', 0);
|
|
|
|
LoL->f_nodes = p;
|
|
|
|
}
|
|
|
|
|
2001-03-21 03:56:26 +01:00
|
|
|
/*
|
2004-07-09 04:16:31 +02:00
|
|
|
Undocumented feature:
|
|
|
|
Format: ANYDOS [=]
|
2001-03-21 03:56:26 +01:00
|
|
|
will report to MSDOS programs just the version number
|
|
|
|
they expect. be careful with it!
|
2001-11-18 15:01:12 +01:00
|
|
|
*/
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void SetAnyDos(PCStr p)
|
2001-03-21 03:56:26 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (*p) /* garbage at line end? */
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
ReturnAnyDosVersionExpected = TRUE;
|
2001-03-21 03:56:26 +01:00
|
|
|
}
|
2001-07-10 00:19:33 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: EECHO string */
|
|
|
|
STATIC void CfgMenuEsc(PCStr p)
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
char ch;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ch = *p; p++;
|
|
|
|
if (ch == '\0')
|
|
|
|
ch = '\n';
|
|
|
|
if (ch == '$') /* translate $ to ESC */
|
|
|
|
ch = ESC;
|
|
|
|
printf("%c", ch);
|
|
|
|
} while (ch != '\n');
|
2002-01-23 23:29:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-07-09 04:16:31 +02:00
|
|
|
'MENU'ing stuff
|
|
|
|
although it's worse then MSDOS's , its better then nothing
|
|
|
|
Menu selection bar struct:
|
|
|
|
x pos, y pos, string
|
2002-01-23 23:29:41 +01:00
|
|
|
*/
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static struct MenuSelector
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
unsigned x, y;
|
|
|
|
UBYTE len;
|
|
|
|
char text[80];
|
|
|
|
} MenuStruct[10] BSS_INIT({0});
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static unsigned nextMenuRow BSS_INIT(0);
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: MENU string */
|
|
|
|
/* Format: ECHO string */
|
|
|
|
STATIC void CfgMenu(PCStr p)
|
|
|
|
{
|
|
|
|
struct MenuSelector *menu;
|
|
|
|
UBYTE ch;
|
|
|
|
unsigned len;
|
|
|
|
int spaces;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
say2("%s\n", p);
|
|
|
|
nextMenuRow++;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* find digit */
|
|
|
|
for (len = 0;; p++, len++)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
ch = *p;
|
|
|
|
if (ch == '\0')
|
|
|
|
return;
|
|
|
|
ch -= (UBYTE)'0';
|
|
|
|
if (ch <= 9)
|
|
|
|
break;
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
menu = &MenuStruct[ch];
|
|
|
|
menu->x = len; /* start position of digit */
|
|
|
|
menu->y = nextMenuRow - 1;
|
|
|
|
|
|
|
|
/* copy menu text (up to null or 10+ spaces) */
|
|
|
|
len = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ch = *p;
|
|
|
|
if (ch == '\0')
|
|
|
|
break;
|
|
|
|
menu->text[len] = ch;
|
|
|
|
p++, len++;
|
|
|
|
if (ch > ' ')
|
|
|
|
{
|
|
|
|
menu->len = len;
|
|
|
|
spaces = 11;
|
|
|
|
}
|
|
|
|
} while (--spaces && len < sizeof menu->text - 1);
|
|
|
|
menu->text[menu->len] = '\0';
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2002-01-23 23:29:41 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void SelectLine(unsigned i)
|
2003-06-15 21:26:49 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
struct MenuSelector *menu = MenuStruct;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (menu->len)
|
|
|
|
{
|
|
|
|
UBYTE attr = MenuColor;
|
|
|
|
if (i == 0) /* selected line? */
|
|
|
|
/* swap colors and clear blinking attribute */
|
|
|
|
attr = ((attr << 4) | (attr >> 4)) & 0x7f;
|
|
|
|
|
|
|
|
/* redraw line */
|
|
|
|
ClearScreenArea(attr, menu->x, menu->y, menu->len, 1);
|
|
|
|
say2("%s", menu->text);
|
|
|
|
}
|
|
|
|
menu++, i--;
|
|
|
|
} while (menu < ENDOF(MenuStruct));
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2003-06-15 21:26:49 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
static unsigned show_choices(unsigned choicey)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
unsigned x;
|
|
|
|
UBYTE i;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
gotoxy(2, choicey);
|
|
|
|
say("Enter a choice: [");
|
|
|
|
x = 19; /* =strlen(" Enter a choice: [") */
|
|
|
|
i = 0;
|
|
|
|
do
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (testbit(all_choices, i))
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (i < last_choice)
|
|
|
|
x++;
|
|
|
|
printf("%c", (UBYTE)'0' + i);
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
i++;
|
|
|
|
} while (i <= 9);
|
|
|
|
say("]");
|
|
|
|
return x;
|
|
|
|
}
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC VOID DoMenu(void)
|
|
|
|
{
|
|
|
|
unsigned choicey;
|
|
|
|
say("\n\n\n"); /* make sure there are 3 free lines */
|
|
|
|
choicey = screeny() - 2;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
gotoxy(0, screenbottom());
|
|
|
|
say2("F5=Bypass startup files F8=Confirm each line of %s/AUTOEXEC.BAT",
|
|
|
|
configfile);
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
unsigned key;
|
|
|
|
UBYTE c;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
gotoxy(75, screenbottom());
|
|
|
|
say(askCommand & ASK_TRACE ? "[Y]" : "[N]");
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (MenuColor && nextMenuRow + 1 == choicey)
|
|
|
|
SelectLine(last_choice); /* invert color of selected line */
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (MenuTimeout >= 0)
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
show_choices(choicey);
|
|
|
|
printf(" Time remainig: %d ", MenuTimeout);
|
|
|
|
|
|
|
|
gotoxy(show_choices(choicey), choicey);
|
|
|
|
key = GetBiosKey(1); /* poll keyboard 1 second */
|
|
|
|
if (key == 0)
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (MenuTimeout == 0)
|
|
|
|
break; /* timeout, take default */
|
2003-03-13 00:06:48 +01:00
|
|
|
MenuTimeout--;
|
2004-07-09 04:16:31 +02:00
|
|
|
continue;
|
2003-03-13 00:06:48 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
2003-03-13 00:06:48 +01:00
|
|
|
MenuTimeout = -1;
|
2004-07-09 04:16:31 +02:00
|
|
|
clearrow(); /* clear "Time remaining" */
|
|
|
|
}
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
gotoxy(show_choices(choicey), choicey);
|
|
|
|
key = GetBiosKey(-1); /* remove key from buffer */
|
|
|
|
|
|
|
|
if (key == K_F5) /* F5 */
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
askCommand |= ASK_SKIPALL;
|
2002-01-23 23:29:41 +01:00
|
|
|
break;
|
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
if (key == K_F8) /* F8 */
|
|
|
|
askCommand ^= ASK_TRACE;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
c = last_choice;
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (key == K_Up || key == K_Left)
|
|
|
|
while (c > 0 && !testbit(all_choices, --c));
|
|
|
|
|
|
|
|
else if (key == K_Down || key == K_Right)
|
|
|
|
while (c < 9 && !testbit(all_choices, ++c));
|
2003-09-18 22:55:41 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
else
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
unsigned k = key; /* hint for compiler optimizer */
|
|
|
|
c = (UBYTE)k;
|
|
|
|
if (c == '\r') /* CR - use current choice */
|
|
|
|
break;
|
|
|
|
c -= (UBYTE)'0';
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (testbit(all_choices, c))
|
|
|
|
last_choice = c;
|
|
|
|
} /* for */
|
|
|
|
|
|
|
|
gotoxy(0, screenbottom());
|
|
|
|
clearrow(); /* clear hint line at bottom */
|
|
|
|
gotoxy(0, choicey + 2);
|
2002-01-23 23:29:41 +01:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: MENUDEFAULT [=] menu [, waitsecs] */
|
|
|
|
STATIC void CfgMenuDefault(PCStr p)
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg2(p, MenuTimeout))
|
2002-01-23 23:29:41 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
last_choice = numarg1;
|
|
|
|
/*if (last_choice > 10)
|
|
|
|
last_choice = 10;*/
|
|
|
|
MenuTimeout = numarg;
|
2002-01-23 23:29:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: MENUCOLOR [=] foreground [, background] */
|
|
|
|
STATIC void CfgMenuColor(PCStr p)
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
if (GetNumArg2(p, 0))
|
2003-09-18 22:55:41 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE attr = (UBYTE)((numarg << 4) | numarg1);
|
|
|
|
if (attr == 0)
|
|
|
|
attr = 0x07; /* white on black */
|
|
|
|
MenuColor = attr;
|
2003-09-18 22:55:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-13 00:06:48 +01:00
|
|
|
/* ****************************************************************
|
2004-07-09 04:16:31 +02:00
|
|
|
** implementation of INSTALL=NANSI.COM /P /X /BLA
|
2003-03-13 00:06:48 +01:00
|
|
|
*/
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void free(seg_t seg)
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
iregs r;
|
|
|
|
r.ES = seg;
|
|
|
|
r.AH = 0x49; /* free memory */
|
|
|
|
init_call_intr(0x21, &r);
|
2003-03-13 00:06:48 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
/* set memory allocation strategy */
|
|
|
|
STATIC void set_strategy(UBYTE strat)
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
iregs r;
|
|
|
|
r.BL = strat;
|
|
|
|
r.AX = 0x5801;
|
|
|
|
init_call_intr(0x21, &r);
|
2003-03-13 00:06:48 +01:00
|
|
|
}
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* Format: INSTALL [=] command */
|
|
|
|
/* Format: INSTALLHIGH [=] command */
|
|
|
|
STATIC void _CmdInstall(PCStr p, int mode)
|
|
|
|
{
|
|
|
|
CommandTail args;
|
|
|
|
PStr pf;
|
|
|
|
unsigned len;
|
2003-03-13 00:06:48 +01:00
|
|
|
exec_blk exb;
|
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
for (pf = szBuf;; p++, pf++)
|
2003-03-13 00:06:48 +01:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
UBYTE ch = *p;
|
|
|
|
if (ch <= ' ' || ch == '/')
|
2003-03-13 00:06:48 +01:00
|
|
|
break;
|
2004-07-09 04:16:31 +02:00
|
|
|
*pf = ch;
|
2003-03-13 00:06:48 +01:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
*pf = '\0';
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
len = strlen(p);
|
|
|
|
if (len > sizeof args.ctBuffer - 2)
|
|
|
|
len = sizeof args.ctBuffer - 2; /* trim too long line */
|
|
|
|
args.ctCount = (UBYTE)len;
|
|
|
|
args.ctBuffer[len] = '\r';
|
|
|
|
args.ctBuffer[len+1] = 0;
|
|
|
|
memcpy(args.ctBuffer, p, len);
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
set_strategy(mode);
|
|
|
|
exb.exec.env_seg = DOS_PSP + 8;
|
|
|
|
exb.exec.cmd_line = &args;
|
|
|
|
/*exb.exec.fcb_1 = exb.exec.fcb_2 = NULL;*/ /* unimportant */
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("cmd[%s] args [%u,%s]\n", szBuf, args.ctCount, args.ctBuffer));
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
if (init_DosExec(mode, &exb, szBuf) != SUCCESS)
|
|
|
|
CfgFailure(p);
|
2003-06-15 15:24:53 +02:00
|
|
|
}
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void CmdInstall(PCStr p) { _CmdInstall(p, 0); }
|
2004-05-10 03:36:09 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
STATIC void CmdInstallHigh(PCStr p) { _CmdInstall(p, 0x80); }
|
2004-05-10 03:36:09 +02:00
|
|
|
|
2003-03-13 00:06:48 +01:00
|
|
|
VOID DoInstall(void)
|
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
seg_t kernel;
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* grab memory for this install code:
|
|
|
|
we are executing somewhere at top of memory and need to protect
|
|
|
|
the INIT_CODE from other programs that will be executing soon
|
2003-03-13 00:06:48 +01:00
|
|
|
*/
|
|
|
|
|
2004-05-10 03:36:09 +02:00
|
|
|
set_strategy(LAST_FIT);
|
2004-07-09 04:16:31 +02:00
|
|
|
kernel = allocmem(((unsigned)_init_end + ebda_size + 15) / 16);
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
DebugPrintf(("Installing commands now (kernel at %X)\n", kernel));
|
|
|
|
|
|
|
|
DoConfig_();
|
2003-03-13 00:06:48 +01:00
|
|
|
|
2004-05-10 03:36:09 +02:00
|
|
|
set_strategy(FIRST_FIT);
|
2004-07-09 04:16:31 +02:00
|
|
|
free(kernel);
|
|
|
|
|
|
|
|
DebugPrintf(("Done with installing commands\n"));
|
2003-03-13 00:06:48 +01:00
|
|
|
}
|
2003-10-05 18:22:57 +02:00
|
|
|
|
2004-07-09 04:16:31 +02:00
|
|
|
/* master_env copied over command line area in
|
|
|
|
DOS_PSP, thus its size limited to 128 bytes */
|
|
|
|
static char master_env[128] BSS_INIT({0});
|
|
|
|
static PStr envp = master_env;
|
|
|
|
|
|
|
|
/* Format: SET var = string */
|
|
|
|
STATIC void CmdSet(PCStr p)
|
2003-10-05 18:22:57 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
PStr q;
|
|
|
|
p = skipwh(scanword(p, szBuf));
|
|
|
|
if (*p != '=') /* equal sign is required */
|
2003-10-05 18:22:57 +02:00
|
|
|
{
|
2004-07-09 04:16:31 +02:00
|
|
|
CfgFailure(p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* environment variables must be uppercase */
|
|
|
|
strcat(strupr(szBuf), "=");
|
|
|
|
|
|
|
|
{
|
|
|
|
PStr pm = master_env; /* find duplication */
|
|
|
|
for (q = pm; pm < envp; q = pm)
|
|
|
|
{
|
|
|
|
PCStr v = szBuf;
|
|
|
|
while (*v == *pm) /* compare variables */
|
|
|
|
v++, pm++;
|
|
|
|
while (*++pm); /* find end of definition */
|
|
|
|
pm++;
|
|
|
|
if (*v == '\0') /* variable found? */
|
|
|
|
{
|
|
|
|
while (pm < envp)
|
|
|
|
*q++ = *pm++; /* remove duplication */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} /* for */
|
|
|
|
}
|
|
|
|
|
|
|
|
p = skipwh(p + 1);
|
|
|
|
if (*p) /* add new definition? */
|
|
|
|
{
|
|
|
|
size_t sz = strlen(strcat(szBuf, p)) + 1;
|
|
|
|
|
|
|
|
/* environment ends by empty ASCIIZ (one null character) */
|
|
|
|
if (sz >= master_env + sizeof master_env - q)
|
|
|
|
{
|
|
|
|
CfgFailure(p);
|
|
|
|
say("Out of environment space\n");
|
|
|
|
return;
|
2003-10-05 18:22:57 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
strcpy(q, szBuf);
|
|
|
|
q += sz;
|
2003-10-05 18:22:57 +02:00
|
|
|
}
|
2004-07-09 04:16:31 +02:00
|
|
|
|
|
|
|
envp = q;
|
|
|
|
*q = '\0'; /* "add" empty ASCIIZ string */
|
|
|
|
fmemcpy(MK_PTR(char, DOS_PSP + 8, 0), master_env, q + 1 - master_env);
|
2003-10-05 18:22:57 +02:00
|
|
|
}
|