Add 16-bit real-mode DOS target -- 127KB standalone, no extender
New Makefile.dos16 builds with OpenWatcom wcc (16-bit, MEDIUM model) producing a standard MZ executable that runs on any DOS without DOS/4GW. All 24 source files compile clean; tested on FreeDOS 1.4 via QEMU. Changes for 16-bit compatibility: - hal_dos.c: INTX macro selects int86() vs int386() based on _M_I86 - sound.c: reduce stack buffer from 8192 to 512 samples on 16-bit - tui.c: gracefully disable TUI if screen buffer allocation fails (near heap exhaustion common on 16-bit), batch mode still works - .gitignore: add .obj/.exe/.err/.lib for OpenWatcom build artifacts Size comparison: - 32-bit DOS/4GW: 175KB + 265KB extender = 440KB total - 16-bit real-mode: 127KB standalone The 32-bit build (Makefile.dos) and Linux build are unaffected. 72/72 interpreter tests pass.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,6 +2,10 @@ build/
|
||||
docs/_build/
|
||||
*.o
|
||||
*.d
|
||||
*.obj
|
||||
*.exe
|
||||
*.err
|
||||
*.lib
|
||||
gwbasic_*.txt
|
||||
gwbasic_*.dat
|
||||
gwbasic_*.bas
|
||||
|
||||
44
Makefile.dos16
Normal file
44
Makefile.dos16
Normal file
@@ -0,0 +1,44 @@
|
||||
# Makefile for building GW-BASIC 2026 with OpenWatcom for 16-bit DOS
|
||||
#
|
||||
# Usage:
|
||||
# wmake -f Makefile.dos16 (from OpenWatcom environment)
|
||||
# wmake -f Makefile.dos16 clean
|
||||
#
|
||||
# Requires: OpenWatcom 2.0+ targeting 16-bit real-mode DOS
|
||||
# Produces: GWBASIC.EXE (interpreter, standalone MZ executable — no DOS extender)
|
||||
#
|
||||
# The 16-bit build uses the MEDIUM memory model (-mm):
|
||||
# - Code: multiple segments (far calls), supports > 64KB total code
|
||||
# - Data: single segment (near pointers), must fit in 64KB
|
||||
#
|
||||
# The compiler (GWBASCOM.EXE) is not built in 16-bit mode because it uses
|
||||
# open_memstream() which is not available in 16-bit DOS. Use Makefile.dos
|
||||
# (32-bit) for the compiler.
|
||||
|
||||
CC = wcc
|
||||
CFLAGS = -bt=dos -mm -ox -w4 -zq -za99 -Iinclude -D__MSDOS__
|
||||
LINKER = wlink
|
||||
LIBRARIAN = wlib
|
||||
|
||||
# Interpreter sources (same as 32-bit minus compiler files)
|
||||
INTERP_OBJS = &
|
||||
src/main.obj src/tokens.obj src/tokenizer.obj src/error.obj &
|
||||
src/eval.obj src/interp.obj src/vars.obj src/arrays.obj &
|
||||
src/input.obj src/math_int.obj src/math_float.obj &
|
||||
src/math_transcend.obj src/strings.obj src/print.obj &
|
||||
src/fileio.obj src/program_io.obj src/print_using.obj &
|
||||
src/graphics.obj src/virmem.obj src/portio.obj src/strpool.obj &
|
||||
src/sound.obj src/tui.obj platform/hal_dos.obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -fo=$@ $<
|
||||
|
||||
all: gwbasic.exe
|
||||
|
||||
gwbasic.exe: $(INTERP_OBJS)
|
||||
$(LINKER) system dos option stack=8192 name $@ file { $< }
|
||||
|
||||
clean: .SYMBOLIC
|
||||
del src\*.obj
|
||||
del platform\*.obj
|
||||
del gwbasic.exe
|
||||
@@ -5,7 +5,8 @@
|
||||
* and screen control. Selected at compile time via __MSDOS__.
|
||||
* Linux HAL (hal_posix.c) is unchanged -- full backward compatibility.
|
||||
*
|
||||
* Build: wcc386 -bt=dos -mf -ox -za99 -D__MSDOS__ -Iinclude
|
||||
* Build: wcc386 -bt=dos -mf -ox -za99 -D__MSDOS__ -Iinclude (32-bit)
|
||||
* wcc -bt=dos -mm -ox -za99 -D__MSDOS__ -Iinclude (16-bit)
|
||||
*/
|
||||
|
||||
#ifdef __MSDOS__
|
||||
@@ -18,6 +19,13 @@
|
||||
#include <i86.h>
|
||||
#include <dos.h>
|
||||
|
||||
/* int86 (16-bit real mode) vs int386 (32-bit protected mode) */
|
||||
#ifdef _M_I86
|
||||
#define INTX(n, r_in, r_out) int86(n, r_in, r_out)
|
||||
#else
|
||||
#define INTX(n, r_in, r_out) int386(n, r_in, r_out)
|
||||
#endif
|
||||
|
||||
static int cursor_row = 0;
|
||||
static int cursor_col = 0;
|
||||
static int screen_cols = 80;
|
||||
@@ -33,7 +41,7 @@ static void bios_set_cursor(int row, int col)
|
||||
r.h.bh = 0;
|
||||
r.h.dh = (unsigned char)row;
|
||||
r.h.dl = (unsigned char)col;
|
||||
int386(0x10, &r, &r);
|
||||
INTX(0x10, &r, &r);
|
||||
cursor_row = row;
|
||||
cursor_col = col;
|
||||
}
|
||||
@@ -44,7 +52,7 @@ static void bios_get_cursor(int *row, int *col)
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.h.ah = 0x03;
|
||||
r.h.bh = 0;
|
||||
int386(0x10, &r, &r);
|
||||
INTX(0x10, &r, &r);
|
||||
*row = r.h.dh;
|
||||
*col = r.h.dl;
|
||||
}
|
||||
@@ -60,7 +68,7 @@ static void bios_scroll_up(int lines, int attr, int r1, int c1, int r2, int c2)
|
||||
r.h.cl = (unsigned char)c1;
|
||||
r.h.dh = (unsigned char)r2;
|
||||
r.h.dl = (unsigned char)c2;
|
||||
int386(0x10, &r, &r);
|
||||
INTX(0x10, &r, &r);
|
||||
}
|
||||
|
||||
static void bios_write_char(int ch, int attr)
|
||||
@@ -72,7 +80,7 @@ static void bios_write_char(int ch, int attr)
|
||||
r.h.bh = 0;
|
||||
r.h.bl = (unsigned char)attr;
|
||||
r.w.cx = 1;
|
||||
int386(0x10, &r, &r);
|
||||
INTX(0x10, &r, &r);
|
||||
}
|
||||
|
||||
/* --- Terminal I/O --- */
|
||||
@@ -118,7 +126,7 @@ static int dos_getch(void)
|
||||
union REGS r;
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.h.ah = 0x00;
|
||||
int386(0x16, &r, &r);
|
||||
INTX(0x16, &r, &r);
|
||||
return r.h.al ? r.h.al : (0x100 | r.h.ah);
|
||||
}
|
||||
|
||||
@@ -156,7 +164,7 @@ static void dos_init(void)
|
||||
union REGS r;
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.h.ah = 0x0F;
|
||||
int386(0x10, &r, &r);
|
||||
INTX(0x10, &r, &r);
|
||||
screen_cols = r.h.ah;
|
||||
screen_rows = 25; /* safe default; BIOS data area read needs far ptr */
|
||||
bios_get_cursor(&cursor_row, &cursor_col);
|
||||
|
||||
@@ -91,8 +91,13 @@ void snd_tone(int freq_hz, int duration_ticks)
|
||||
return;
|
||||
|
||||
/* Allocate buffer (or use stack for short tones) */
|
||||
#ifdef _M_I86
|
||||
int16_t stack_buf[512]; /* 1KB — 16-bit DOS has ~4-8KB stack */
|
||||
int16_t *buf = (total <= 512) ? stack_buf : malloc(total * sizeof(int16_t));
|
||||
#else
|
||||
int16_t stack_buf[8192];
|
||||
int16_t *buf = (total <= 8192) ? stack_buf : malloc(total * sizeof(int16_t));
|
||||
#endif
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
|
||||
@@ -665,8 +665,10 @@ void tui_init(bool fullscreen)
|
||||
/* Allocate screen buffer */
|
||||
tui.screen = calloc(tui.rows * tui.cols, sizeof(tui_cell_t));
|
||||
if (!tui.screen) {
|
||||
fprintf(stderr, "Out of memory for screen buffer\n");
|
||||
exit(1);
|
||||
/* Not enough near heap (common on 16-bit DOS).
|
||||
* Disable TUI — batch mode still works via HAL. */
|
||||
tui.active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set default F-key definitions */
|
||||
|
||||
Reference in New Issue
Block a user