Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.[Ee][Xx][Ee]
*.[Oo][Bb][Jj]
*.[Cc][Oo][Mm]
*.[Mm][Aa][Pp]
*.[Ll][Ss][Tt]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ It is written in C to compile with Borland Turbo C++ 3.0.

You can probably get it to work with other MS-DOS C compilers without too much trouble.

It also contains an assembly language component compiled with NASM (LAUNCHER.COM). This attempts to reduce memory consumption to maximise the amount of conventional memory available to programs run from the menu. Without LAUNCHER.COM, DOSMENU.COM will consume 66KB of conventional memory, whereas using LAUNCHER.COM the consumption is reduced to only 4KB. Note that LAUNCHER.COM is optional, and DOSMENU.COM will still work without it being present, just at the cost of more memory consumption.

![Screenshot](./screenshot.png?raw=true "Screenshot")
3 changes: 2 additions & 1 deletion compile.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@echo off
cls
tcc -mt -lt dosmenu.c
nasm -fbin -o launcher.com -l launcher.lst launcher.asm
tcc -mt -lt -M dosmenu.c
97 changes: 92 additions & 5 deletions dosmenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#define true 1
#define false 0

#define LAUNCHER_VECTOR 0x88

void abortMsg(char *msg);

void * xmalloc(size_t size) {
Expand All @@ -18,6 +20,71 @@ void * xmalloc(size_t size) {
return r;
}

char * xstrdup(char *str) {
char *copy = xmalloc(strlen(str)+1);
strcpy(copy,str);
return copy;
}

char * xstrcat(char *a, char *b) {
int na, nb;
char *r;

na = strlen(a);
nb = strlen(b);
r = xmalloc(na+nb+1);
r[0] = 0;
strcat(r, a);
strcat(r, b);
return r;
}

int fileExistenceCheck(char *fname) {
FILE *fh = fopen(fname,"r");
if (fh == NULL)
return false;
fclose(fh);
return true;
}

int checkLauncherInstalled() {
return getvect(LAUNCHER_VECTOR) != 0;
}

int callLauncher(char *exec, char *args, int pause) {
union REGS in;
memset(&in,0,sizeof(union REGS));
in.x.ax = 0x1369;
in.x.bx = (int)exec;
in.x.cx = pause;
in.x.si = (int)args;
return int86(LAUNCHER_VECTOR, &in, &in);
}

// Split cmd into command line and argument
void launcherSystem(char *line, int pause) {
char *comspec, *arg;
int rc;

comspec = getenv("COMSPEC");
if (comspec == NULL || strlen(comspec) == 0)
abortMsg("COMSPEC not set");
if (!fileExistenceCheck(comspec))
abortMsg("Command interpreter (COMSPEC) not found");

arg = xstrcat("/C ",line);
if (strlen(arg) > 126) {
free(arg);
abortMsg("Command line too long");
}

rc = callLauncher(comspec,arg,pause);
free(arg);
if (rc != 0)
abortMsg("Launcher invocation failed");
exit(0);
}

void resetVideo(void) {
textmode(C80);
textcolor(LIGHTGRAY);
Expand Down Expand Up @@ -46,17 +113,16 @@ struct section {

struct section * newSection(char *name) {
struct section * s = (struct section*) xmalloc(sizeof(struct section));
s->name = strdup(name);
s->name = xstrdup(name);
s->settings = NULL;
s->next = NULL;
return s;
}


struct setting * newSetting(char *name, char* value) {
struct setting * s = (struct setting*) xmalloc(sizeof(struct setting));
s->name = strdup(name);
s->value = strdup(value);
s->name = xstrdup(name);
s->value = xstrdup(value);
s->next = NULL;
return s;
}
Expand Down Expand Up @@ -329,6 +395,16 @@ int main(int argc, char**argv) {
saveCWD = xmalloc(256);
getcwd(saveCWD, 256);

// The launcher is an assembly language program used to reduce
// memory consumption. If we find it run it instead of ourselves.
if (fileExistenceCheck("DOSMENU.COM") &&
!checkLauncherInstalled() &&
fileExistenceCheck("LAUNCHER.COM")) {
execl("LAUNCHER.COM","LAUNCHER.COM",NULL);
// If we get to here, launcher failed
}

drainInput();
resetVideo();
_setcursortype(_NOCURSOR);
sections = loadConfig();
Expand Down Expand Up @@ -392,9 +468,20 @@ int main(int argc, char**argv) {
struct section * nth = getSectionByIndex(sections, selected);
char *dir = getSettingInSection(nth, "dir");
char *run = getSettingInSection(nth, "run");
char *pause = getSettingInSection(nth, "pause");

if (dir != NULL)
chdir(dir);
system(run);
if (checkLauncherInstalled())
launcherSystem(run, strcmp(pause,"1")==0);
else
system(run);
if (strcmp(pause,"1")==0) {
drainInput();
printf("Press any key to continue...");
readScanCode();
printf("\n");
}
chdir(saveCWD);
resetVideo();
_setcursortype(_NOCURSOR);
Expand Down
10 changes: 10 additions & 0 deletions dosmenu.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ run=KEEN2.EXE
[Keen 3]
dir=C:\GAMES\KEEN3
run=KEEN3.EXE
[TEST]
run=Z:\COMMAND.COM
[TEST2]
run=c:\zutl\dumpargs.com foo
pause=1
[DEBUG]
run=c:\debug.exe
[MEM]
run=c:\dos\mem.exe
pause=1
Loading