[list -]
%if 0

lDebug general set up and macros

Copyright (C) 1995-2003 Paul Vojta
Copyright (C) 2008-2025 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif

TOLOWER		equ 32
TOUPPER		equ ~32
TOUPPER_W	equ ~(32<<8|32)
MNEMONOFS	equ 28		; offset in disassembler output line
				;  where mnemonics start
MNEMONOFS_40	equ 20
MNEMONOFS_MS	equ 24

%include "lmacros3.mac"
[list -]
%include "AMIS.MAC"
[list -]

%if __NASM_VERSION_ID__ >= 2000000h + 17 * 10000h
	numdef HAVE_NASM_NOTE, 1
%else
	numdef HAVE_NASM_NOTE, 0
%endif
%imacro hiddenusesection 1.nolist
%if _HAVE_NASM_NOTE
 %note usesection %1
%endif
 usesection %1
%endmacro

	numdef BUILDINGHELPONLY, 0	; must be 0 for regular build, 1 for help
	defaulting 1			; enable defaulting
	numdef SYMBOLIC, 0

%if _SYMBOLIC
	defaulting 0			; disable defaulting
%include "symbols.mac"
[list -]
		; symbolic branch defines *without* defaulting!
	numdef ZZ_INSERT_TEMP, 1
	numdef XMS_SYMBOL_TABLE, 1
	numdef BUFFER_86MM_SLICE, 0
	numdef SECOND_SLICE, 0

	defaulting 1			; re-enable defaulting

		; symbolic branch defines
	numdef 86MM_SYMBOL_TABLE_MAX, 256, 256
%endif

	numdef INIT_MAX, 0
	numdef EXTENSIONS, 1
	numdef ELDTRAILER, 1
	numdef EXT_CODE_SIZE, 64 * 1024 - 16
	numdef EXT_CODE_DEFAULT_SIZE, 16 * 1024
	numdef EXT_CODE_INIT_SIZE, 8 * 1024
	numdef EXT_CODE_BOOT_SIZE, 16 * 1024
	; numdef EXT_DATA_MAX_SIZE, 24 * 1024
	numdef EXT_DATA_DEFAULT_SIZE, 16 * 1024
	numdef EXT_DATA_INIT_SIZE, 16 * 1024
	numdef EXT_DATA_BOOT_SIZE, 16 * 1024
	numdef EXT_VARIABLES, 16
	numdef EXT_PUTS_GETLINE, 1
	numdef RECLAIM, 1
	numdef LINK, 0
	incdef _EXTENSIONS, LINK
	numdef LINKHASH, 1
%if _BUILDINGHELPONLY
	; placeholder, fix external assembling of help pages
 ext_data_max_size_equate equ _EXT_DATA_DEFAULT_SIZE
%endif
ext_data_max_size_equate_early equ ext_data_max_size_equate
%if _INIT_MAX
 %assign _EXT_CODE_INIT_SIZE _EXT_CODE_SIZE
 %assign _EXT_DATA_INIT_SIZE ext_data_max_size_equate_early
%endif
%if _EXTENSIONS
 extsegment_size equ (_EXT_CODE_INIT_SIZE + 15) & ~15
 extsegment_boot_size equ (_EXT_CODE_BOOT_SIZE + 15) & ~15
%else
 extsegment_size equ 0
 extsegment_boot_size equ 0
%endif

	numdef APP_ENV_SIZE, 2048
	numdef DEV_ENV_SIZE, 2048
	numdef BOOT_ENV_SIZE, 2048
app_env_size equ (_APP_ENV_SIZE + 15) & ~15
dev_env_size equ (_DEV_ENV_SIZE + 15) & ~15
boot_env_size equ (_BOOT_ENV_SIZE + 15) & ~15

		; serialp defines
	numdef USE_TX_FIFO, 1		; fill 16-byte UART TX FIFO when THRE
	numdef ECHO_RX_TO_TX, 0		; echo received text to the other side
	numdef RX_TO_TX_ADD_LF, 1

	numdef UART_PORT, 2
%if _UART_PORT == 1
	numdef INTNUM, 0Ch
	numdef OFFMASK, 0001_0000b
_ONMASK      equ ~ _OFFMASK
	numdef UART_BASE, 3F8h
%elif _UART_PORT == 2
	numdef INTNUM, 0Bh
	numdef OFFMASK, 0000_1000b
_ONMASK      equ ~ _OFFMASK
	numdef UART_BASE, 2F8h
%else
 %fatal Invalid UART_PORT value: _UART_PORT
%endif
	numdef UART_RATE, 12		; 9600 bps, see table in this file
	numdef UART_PARAMS, 0000_0011b	; 8n1, see tables
	numdef UART_FIFO, 0
		; 20h = (sometimes) use 64-byte FIFOs
		; 30h = (sometimes) mask of tx FIFO trigger level
		; C0h = mask of rx FIFO trigger level:
		;	00h = 1 byte
		;	40h = 4 bytes
		;	80h = 8 bytes
		;	C0h = 14 bytes
		; (may differ for some chips)
		; refer to https://github.com/spotify/linux/blob/6eb782fc88d11b9f40f3d1d714531f22c57b39f9/include/linux/serial_reg.h#L48
	numdef RXFIFOSIZE, 128	; set this to your needs
	numdef TXFIFOSIZE, 128	; dito.
		; the fifos must be large on slow computers
		; and can be small on fast ones
		; These have nothing to do with the 16550A's
		; built-in FIFOs!
	numdef BI_TX_FIFO_SIZE, 16
		; This refers to the 16550A's built-in TX FIFO.
		;  Set to 15 (instead of 16) here or in variable DSF if
		;  using dosemu before revision gc7f5a828 2019-01-22,
		;  see https://github.com/stsp/dosemu2/issues/748

%macro rx_checkwrap 0
  cmp  si, rxfifo+_RXFIFOSIZE
  jb  %%rx_nowrap
  mov  si, rxfifo
%%rx_nowrap:
%endmacro

%macro tx_checkwrap 0
  cmp  si, txfifo+_TXFIFOSIZE
  jb  %%tx_nowrap
  mov  si, txfifo
%%tx_nowrap:
%endmacro


			; Options. The defaults can be configured here.
			; All options can be set on NASM's command line too.
strdef FILENAME,	"DEBUG"	; max 6 characters!
strdef BOOTSCRIPTPREFIX,""
strdef BOOTSCRIPTNAME,	"LDEBUG.SLD"
strdef BOOTSCRIPTLABEL,	"bootstartup"
strdef DEVSCRIPTPREFIX,""
strdef DEVSCRIPTNAME,	"LDEBUG.SLD"
strdef DEVSCRIPTLABEL,	"devicestartup"
strdef APPSCRIPTPREFIX,""
strdef APPSCRIPTNAME,	"LDEBUG.SLD"
strdef APPSCRIPTLABEL,	"applicationstartup"
strdef PROGNAME,	"lDebug"
strdef VERSION,		{" (",__DATE__,")"}	; immediately follows _PROGNAME
numdef HELP_EXTERNAL,	0	; use externally-built help page files
numdef HELP_COMPRESSED,	0	; compress externally-built help pages
 excdef !_HELP_EXTERNAL, HELP_COMPRESSED
numdef HELP_COMPRESSED_LARGEST,	3 * 1024
 excdef !_HELP_COMPRESSED, HELP_COMPRESSED_LARGEST
hshrink_message_buffer_size equ _HELP_COMPRESSED_LARGEST
numdef TEST_HELP_FILE,	0	; include TESTHELP command
 excdef !_HELP_COMPRESSED, TEST_HELP_FILE
strdef REVISIONID,	""
strdef REVISIONID_LMACROS,	""
strdef REVISIONID_SYMSNIP,	""
strdef REVISIONID_SCANPTAB,	""
strdef REVISIONID_INICOMP,	""
strdef REVISIONID_INICHECK,	""
strdef REVISIONID_LDOSBOOT,	""
numdef XTNAME,		0
numdef PM,		0	; create DEBUGX
numdef PM_ENTRY_SECTION,1	; leave DPMI entry code in entry section
 excdef !_PM, PM_ENTRY_SECTION
numdef DEBUG_PM_ENTRY,	0	; debug esph/ss B bit in exc32
numdef RUN_ENTRY_SECTION,1	; put some run.asm entrypoint code to entry section
numdef RUN2_ENTRY_SECTION,1	; put some run.asm run code to entry section
numdef DEBUG,		0	; debug lDebug with itself, support BU command
numdef DEBUG_COND,	0	; add debug mode (conditionally debuggable)
numdef DEBUG_COND_DEFAULT_ON,1	; enable debug mode by default
numdef DEBUG0
numdef DEBUG1
numdef DEBUG2
numdef DEBUG3
numdef DEBUG4
numdef DEBUG5
%idefine d5 _d 5,
numdef TTEST,		1	; include ttest command (parseql + RE)
numdef SLEEP_NEW,	1
numdef DOUBLEDOLLAR,	0	; accept double dollar for setting a high limit
				;  for dollar-prefixed segments in PM
numdef IMMASM,		1	; include . (dot) command for immediate assembler
numdef IMMASM_AUXBUFF,	0
numdef REGSHIGHLIGHT,	1	; support RHIGHLIGHT flag, highlight differences
numdef GETLINEHIGHLIGHT,1	; support opt3_getline_highlight
numdef DHIGHLIGHT,	0	; this defaults to off, not yet ready
numdef REGSLINEBREAK,	1	; allow opt6_r_linebreak to prepend linebreak to R
numdef REGSREADABLEFLAGS,1	; allow different flags state display styles
numdef MS_N_COMPAT,	1	; include N command mode compatible to MS Debug
numdef MS_0RANGE_COMPAT,1	; include compatibility mode for explicit 0 length
numdef MS_PROMPT_COMPAT,1	; include compatibility mode for R prompts
numdef MS_MNEMON_COMPAT,1	; include option for MS Debug style mnemonofs
numdef PASSTF,		0	; do not clear TF early in intr1 unconditionally
numdef VXCHG,		1	; support video swap so outputs remain separated
numdef VXCHG_DEFAULT_ON,0	; enable video swap by default
numdef VXCHGBIOS,	0	; use ROM-BIOS page swap to do video swap
numdef FORCETEXT,	0	; force setting text mode upon run return
numdef ALTVID,		1	; support alternate video adapter
numdef MCLOPT,		0	; accept /M command line option
numdef MCLOPT_DEFAULT,	8	; default for /M (8 = /M-, 20h = /M+)
numdef INDOS_PROMPT,	1	; prepend '!' to prompt while InDOS
numdef INDOS_PROMPT_NOBOOT, 1	; -... except while booted
numdef INDOS_PROMPT_NOFLAG, 1	; -... except while only DCO flag set
numdef EMS,		0	; support X commands
numdef INT,		1	; support DI command
numdef MCB,		1	; support DM command
numdef MCBPOSITION,	0	; support position display in DM command
numdef MCBLIMIT,	0	; support upper limit in DM command
numdef SDSUB,		0	; support SD sub-MCBs in DM command
numdef DX,		0	; support DX command (386-only)
numdef RN,		0	; support RN command
numdef RM,		0	; support RM command (only if _MMXSUPP=1)
numdef RN_AUX,		0	; use auxiliary buffer for RN command
numdef RM_AUX,		0	; use auxiliary buffer for RM command
numdef MMXSUPP,		1	; support MMX specific commands
numdef MMX_REDETECT,	1	; redetect MMX support (86 Mode / PM)
numdef DT,		1	; support DT command (ASCII table)
numdef DSTRINGS,	1	; support DZ, D$, D#, DW# commands
numdef DNUM,		1	; support DB, DW, DD commands
numdef DQ,		0	; support DQ command
numdef DTOP,		1	; support TOP keyword for D, DB, DW, DD, DX
numdef RH,		1	; support RH commands
numdef SWHILEBUFFER,	1	; allow S command to use the WHILE buffer
numdef RECMDWHILEBUFFER,1	; allow RE commands to use the WHILE buffer
numdef STRNUM,		1	; support AS SIZE keywords for strings (E, F, S)
numdef COUNT,		1	; support COUNT command and variable
numdef SCOUNT,		1	; set COUNT variable for S pattern
numdef CLEAR,		1	; support CLEAR command (clear screen)
numdef HHDIVREMAIN,	1	; display remainder if H runs a division
numdef RSEPARATE,	1	; support R variable dword/3byte separator
numdef SDUMP,		1	; dump 16 bytes at found location for S command
numdef SDUMPDISPLACEMENT, 1	; in S dump list search pattern length displacement
numdef SREVERSE,	1	; support S REVERSE mode
numdef ESTRINGS,	1	; support EZ, E$, E#, EW# commands
; numdef ENUM,		1	; support EB, EW, ED, EP, ES, EO commands
numdef USESDA,		1	; use SDA to get/set PSP in RM
numdef SYSREQINT,	09h	; if _CATCHSYSREQ, defines the method (int 09h or 15h)
numdef SYSREQ_DISABLE_INT2F_HOOK,	0
				; if _CATCHSYSREQ and _PM disable int 2Fh hook
%if _SYSREQINT != 09h && _SYSREQINT != 15h
 %error Invalid SysReq interrupt number
%endif
numdef VDD,		1	; try to load DEBXXVDD.DLL to use it for L and W sector commands
numdef EXPRESSIONS,	1	; support expression evaluator for any numeric value
				; disabling this also uses the simple H command
numdef EXPRESSION_PRECEDENCE_STACK_CHECK,	128	; see usage
numdef EXPRESSION_PARENS_STACK_CHECK,		128	; see usage
numdef EXPRESSION_INDIRECTION_STACK_CHECK,	128	; see usage
numdef EXPRESSION_VALUE_IN_STACK_CHECK,		128	; see usage
numdef EXPRESSION_LINEAR_STACK_CHECK,		128	; see usage
numdef EXPRESSION_DESCTYPE_STACK_CHECK,		128	; see usage
numdef EXPRESSION_COND_STACK_CHECK,		128	; see usage
numdef EXPRESSION_DEBUG,0	; output debugging trace of expression

numdef INDIRECTION,	1	; support memory access inside expressions
numdef VARIABLES,	1	; support V00 to VFF calculation variables
numdef OPTIONS,		1	; support DCO, DCS, DIF, DAO, DAS option variables
numdef MESSAGESEGMENT,	1	; separate message segment (for help and links)

numdef COND,		1	; disassemble short conditional jumps with notice on the condition
numdef COND_RDUMP_ONLY,	1	;  but only in the register dump single-line disassembler (R)
 excdef !_COND,COND_RDUMP_ONLY
numdef EXTHELP,		1
numdef EXTHELPBOOT,	_EXTHELP

numdef MCP,		0
numdef LOADER,		0	; build loader, not the full debugger
 incdef _LOADER, BOOTLDR
 excdef _LOADER, APPLICATION, DEVICE, PM, CATCHINTFAULT, CATCHINT0C, CATCHINT0D
 excdef _LOADER, CATCHINT00, CATCHINT01, CATCHINT03, CATCHINT06
 excdef _LOADER, CATCHINT08, CATCHINT07, CATCHINT18, CATCHINT19, CATCHSYSREQ
 excdef _LOADER, RH, VXCHG, ALTVID, DSTRINGS, DX, REGSHIGHLIGHT, IMMASM
 excdef _LOADER, TEST_HELP_FILE, EXTHELP, EMS, RN, RM, SYMBOLIC, BREAKPOINTS
 excdef _LOADER, NUM_B_BP, NUM_G_BP, ACCESS_VARIABLES_AMOUNT, REGSLINEBREAK
 excdef _LOADER, 40COLUMNS, DELAY_BEFORE_BP, MCB, DUALCODE, TSR
%if !_LOADER
%ixdefine repeatdw dw
%else
%imacro repeatdw 1-*.nolist
 %rep %0
	dw %1
  %rotate 1
 %endrep
%endmacro
%endif

numdef APPLICATION,	1	; support loading as an application
numdef DEVICE,		1	; support loading as device driver
numdef DEVICE_SET_2324,	1	; set up debugger's own int 23h/24h for device mode
numdef TSR,		1	; support resident operation from application load
numdef ATTACH,		1	; support attaching from TSR/device mode
 excdef !(_APPLICATION && _TSR || _DEVICE), ATTACH
numdef CONFIG,		1	; detect and store configuration directory
numdef EXECUTABLE,	1	; store pathname in init_executable_pathname
numdef BOOTLDR,		1	; support loading instead of DOS
numdef BOOTLDR_DISCARD,	1	; discard boot.asm code if unused
 excdef !_BOOTLDR, BOOTLDR_DISCARD
 excdef !(_APPLICATION || _DEVICE), BOOTLDR_DISCARD
numdef BOOTLDR_DISCARD_HELP, 1	; discard boot help if unused
 excdef !_BOOTLDR, BOOTLDR_DISCARD_HELP
 excdef !(_APPLICATION || _DEVICE), BOOTLDR_DISCARD_HELP
 excdef !_MESSAGESEGMENT, BOOTLDR_DISCARD_HELP
 excdef !_EXTHELPBOOT, BOOTLDR_DISCARD_HELP
numdef CHECKSUM,	0	; include inicheck revision ID if true
numdef CHECKSUM_NEW,	0	; like _CHECKSUM but for all modes (not only boot)
numdef INPUT_FILE_BOOT,	4	; number of boot input file levels to allow
 excdef !_BOOTLDR, INPUT_FILE_BOOT
				; (if no bootldr, force number to zero)

numdef INPUT_FILE_HANDLES, 16	; number of input file levels to allow
 excdef !(_APPLICATION || _DEVICE), INPUT_FILE_HANDLES
numdef RE_BUFFER_SIZE, 2048, -	; size of RE commands buffer
numdef RC_BUFFER_SIZE, 256, -	; size of RC commands buffer
numdef ACCESS_VARIABLES_AMOUNT, 4, 4
numdef MEMREF_AMOUNT, 4, 4
 excdef !_MEMREF_AMOUNT, ACCESS_VARIABLES_AMOUNT

numdef BREAKPOINTS,	1	; support B commands
numdef NUM_B_BP,	16,-	; number of breakpoints for B
numdef NUM_SYM_BP,	16,-	; number of symbol breakpoints
numdef NUM_G_BP,	16,-	; number of breakpoints for G
 excdef !_SYMBOLIC,NUM_SYM_BP	; no symbol breakpoints if not symbolic
 excdef !_BREAKPOINTS,NUM_B_BP,NUM_SYM_BP
				; (if no support, force number to zero)
 excdef !(_NUM_B_BP + _NUM_SYM_BP),BREAKPOINTS
				; (if number zero, no support)
numdef BREAKPOINTS_STICKY, 0	; support sticky breakpoints for B (unsupported)
numdef NUM_B_ID_BYTES, 384, -	; size of shared bb ID buffer space
numdef NUM_B_WHEN_BYTES, 1024, -; size of shared bb condition buffer space

%if _NUM_G_BP > 128
 %errror Number of G breakpoints must not be higher than 128
				; more don't fit on the command line anyway.
				; also insures our byte count is large enough.
%endif

%if (_NUM_B_BP + _NUM_SYM_BP) > 255
 %error Number of B breakpoints must not be higher than 255
				; insure that they work with a byte count
%endif

%if _NUM_B_ID_BYTES > 1024
 %error Size of bb ID buffer must not be higher than 1024 bytes
				; we use 10 bits for our offsets into this buffer
%endif

numdef DETECT,		0	; (not yet) detect DPMI mode changes
numdef GUARD_86M_INT2F,	1	; check before calling 86 Mode int 2Fh
				; (it is assumed to be valid if we entered PM)
numdef DELAY_BEFORE_BP,	1	; allow option to delay before writing breakpoints
numdef HISTORY,		1	; command history for rawinput
numdef HISTORY_SIZE,	1024	; size of history buffer
numdef HISTORY_SEPARATE_FIXED, 1; use fixed-size separate history segment
%if _HISTORY
 %if _HISTORY_SEPARATE_FIXED
numdef HISTORY_SIZE,	8192	; different default size
  historysegment_boot_size equ (_HISTORY_SIZE + 15) & ~15
  %assign _HISTORY_WANT_SIZE _HISTORY_SIZE
  %if _INIT_MAX
   %assign _HISTORY_SIZE 65520
  %endif
 historysegment_size equ (_HISTORY_SIZE + 15) & ~15
 %imacro gethistorysegment 1
	mov %1, word [ss:history.segorsel]
 %endmacro
 %imacro gethistoryoffset 1
	mov %1, 0
 %endmacro
 %else
 historysegment_size equ 0
 historysegment_boot_size equ 0
 %imacro gethistorysegment 1
	push ss
	pop %1
 %endmacro
 %imacro gethistoryoffset 1
	mov %1, historybuffer
 %endmacro
 %endif
%else
 historysegment_size equ 0
 historysegment_boot_size equ 0
%endif
numdef NEWFULLHANDLING, 1	; fillbuf related hackery (ee/getline)
numdef DEFAULTSHOWSIZE,	0	; show size of various parts by default
numdef 40COLUMNS,	1

numdef CATCHINT00,	1	; catch Int00 (divide error)
numdef CATCHINT01,	1	; catch Int01 (single-step)
numdef CATCHINT03,	1	; catch Int03 (breakpoint)
	; The debugger only works properly with Int01 and Int03 hooked.
	;  However, the same as FreeDOS Debug we offer the option to
	;  not hook them. This is intended as an alternative to using
	;  the _DEBUG option (DDebug); if the inner debugger does not
	;  hook the breakpoint interrupts then it can be debugged.
numdef CATCHINT06,	1	; catch Int06 (invalid opcode)
numdef CATCHINT07,	0	; catch Int07 (no x87 present on 286+)
numdef CATCHINTFAULT,	1
numdef CATCHINT0C,	_CATCHINTFAULT
				; catch Int0C (stack fault in R86M, or IRQ)
numdef CATCHINT0D,	_CATCHINTFAULT
				; catch Int0D (general protection fault in R86M, or IRQ)
numdef CATCHINTFAULTCOND,1
numdef DETECT95LX,	1	; do not catch Int06 on HP 95LX
numdef CATCHINT18,	1	; catch Int18 (diskless boot hook)
numdef CATCHINT19,	1	; catch Int19 (boot load)
numdef CATCHSYSREQ,	0	; catch Int15 or Int09 (sysreq)
%assign CATCHINTAMOUNT (!!_CATCHINT00 \
			 + !!_CATCHINT01 \
			 + !!_CATCHINT03 \
			 + !!_CATCHINT06 \
			 + !!_CATCHINT07 \
			 + !!_CATCHINT0C \
			 + !!_CATCHINT0D \
			 + !!_CATCHINT18 \
			 + !!_CATCHINT19 \
			 + !!_CATCHSYSREQ \
			 )
numdef CATCHINT08,	1	; catch Int08 (timer IRQ, special)
numdef CATCHINT2D,	1	; catch Int2D (AMIS, special)
numdef DEBUGUPDATESAVE,	1
%assign _DEBUGUPDATESAVE 1	; (must be on now that unused downlinks equal -1)
numdef STACKSIZE,	512
%if _STACKSIZE < 128
 %error Too low stack size set
%endif
numdef AUXBUFFSIZE,	8192 + 16
numdef AUXBUFFMAXSIZE,	24 * 1024
%ifn _APPLICATION || _DEVICE
 %assign _AUXBUFFMAXSIZE _AUXBUFFSIZE
%endif
numdef WHILEBUFFSIZE,	264
numdef PSPVARIABLES,	1	; support PSP, PPI, PPR variables
numdef DOSEMU,		1	; detect dosemu (eg to avoid DPMI entry hook)
numdef DOSEMU_PRESTROKES_HELP,1	; call DOS_HELPER_PRESTROKES_START on dosemu2

numdef DISASM_32BIT,	1
		; these options ain't working yet:
numdef INSTSET,		6	; set general instruction set (0..6 for 8086..686)
numdef MMXINSTSET,	0	; (not yet) MMX instruction set
numdef FPUINSTSET,	1	; FPU instruction set
;numdef 386REGS,	1	; support 32-bit registers, as well as the FS and GS segment registers
numdef ONLYNON386,	0	; only support non-386 operation. no
				; 386-related patching is used.
				; additionally, 386 registers ain't
				; managed by lDebug. displays a warning.
numdef ONLY386,		0	; only 386+ operation. no 386-related
				; patching is used, and loading is
				; aborted on non-386 CPUs.
%if _ONLY386 && _ONLYNON386
 %error Cannot set both only 386 and only non-386
%endif
%if _MCP
%strcat _PROGNAME "Condtnl. Debuggable ",_PROGNAME
%strcat _FILENAME "C",_FILENAME
strdef BOOTSCRIPTNAME,	"LDOSMCP.SLD"
strdef DEVSCRIPTNAME,	"LDOSMCP.SLD"
strdef APPSCRIPTNAME,	"LDOSMCP.SLD"
%elif _LOADER
%define _PROGNAME "lDOS pre-boot loader"
%define _FILENAME "LOADER"
strdef BOOTSCRIPTNAME,	"LOADER.SLD"
%elif _DEBUG && _DEBUG_COND
%strcat _PROGNAME "Condtnl. Debuggable ",_PROGNAME
%strcat _FILENAME "C",_FILENAME
strdef BOOTSCRIPTNAME,	"LCDEBUG.SLD"
strdef DEVSCRIPTNAME,	"LCDEBUG.SLD"
strdef APPSCRIPTNAME,	"LCDEBUG.SLD"
%elif _DEBUG
%strcat _PROGNAME "Debuggable ",_PROGNAME
%strcat _FILENAME "D",_FILENAME
strdef BOOTSCRIPTNAME,	"LDDEBUG.SLD"
strdef DEVSCRIPTNAME,	"LDDEBUG.SLD"
strdef APPSCRIPTNAME,	"LDDEBUG.SLD"
%endif


			; Option sets. Selecting one of these
			; special options sets the default values
			; for other options. Because of defaulting,
			; the option sets have to be defined after
			; all the defaults for these options. (The
			; default that occurs last is used.)
numdef XT,		0
%if _XT
numdef INSTSET,		1	; restrict instruction set to 8086/88, 80186/88 (NEC V30/V20)
numdef PM,		0	; disable DPMI support
numdef VDD,		0	; disable VDD support
numdef MMXINSTSET,	0	; disable MMX instructions
numdef MMXSUPP,		0	; disable RM command
numdef ONLYNON386,	1	; disable 386-specific code
numdef ONLY386,		0	; disable 386-specific code
numdef XTNAME,		1
%endif


%if _XTNAME
%strcat _PROGNAME _PROGNAME,"XT"; lDebugXT
%strcat _FILENAME _FILENAME,"XT"; DEBUGXT
%endif

		; Following only take effect if _PM is true
numdef NOEXTENDER,	1	; don't assume DPMI host includes a DOS extender
numdef WIN9XSUPP,	1	; avoid to hook DPMI entry when running in Win9x
numdef CATCHEXC00,	1
numdef CATCHEXC01,	1
numdef CATCHEXC03,	1
	; As for the interrupts (refer to CATCHINT defines above), we
	;  allow building without the hooks for breakpoint exceptions.
numdef CATCHEXC06,	1	; catch exception 06h in PM
numdef CATCHEXC0C,	1	; catch exception 0Ch in PM
numdef CATCHEXC0D,	1
numdef CATCHEXC0E,	1
%assign CATCHEXCAMOUNT (!!_CATCHEXC00 \
			 + !!_CATCHEXC01 \
			 + !!_CATCHEXC03 \
			 + !!_CATCHEXC06 \
			 + !!_CATCHEXC0C \
			 + !!_CATCHEXC0D \
			 + !!_CATCHEXC0E \
			 )
numdef CATCHPMINT214C,	1	; catch interrupt 21h function 4Ch in PM
numdef CATCHPMINT41,	0	; catch interrupt 41h (function 004Fh handled)
%assign CATCHPMINTAMOUNT (!!_CATCHPMINT214C \
			   + !!_CATCHPMINT41)
numdef BREAK_INSTALLDPMI, 1	; allow to break on entering PM
numdef DISPHOOK,	1	; display "DPMI entry hooked..."
 excdef !_PM,NOEXTENDER,WIN9XSUPP,CATCHEXC06,CATCHEXC0C,DISPHOOK
 excdef !(_PM || _CATCHINT07 || _CATCHINT0C || _CATCHINT0D),EXCCSIP
%if _PM
%strcat _PROGNAME _PROGNAME,"X"
%strcat _FILENAME _FILENAME,"X"
%endif

	numdef BP_OFFSET, 1	; store preferred offsets in breakpoints
				;  (only displayed by BL and G LIST)
%if _BP_OFFSET
 %if _PM
  %assign BPSIZE	9	; 4 byte for 32-bit address,
				;  4 byte for 32-bit offset,
				;  1 byte storing original data
 %else
  %assign BPSIZE	6	; 3 byte for 21-bit address,
				;  2 byte for 16-bit offset,
				;  1 byte storing original data
 %endif
%else
 %if _PM
  %assign BPSIZE	5	; 4 byte for 32-bit address,
				;  1 byte storing original data
 %else
  %assign BPSIZE	4	; 3 byte for 21-bit address,
				;  1 byte storing original data
 %endif
%endif

numdef EXCCSIP,		1	; display CS:IP where exception occured
numdef AREAS_HOOK_CLIENT, _PM && _DEBUG
				; allow to install our areas into another debugger
				;  (this indicates to *use* AMIS function 33h)
numdef AREAS_HOOK_SERVER, _PM	; allow others to install areas into us
				;  (this indicates to *provide* AMIS function 33h)
excdef !_CATCHINT2D, AREAS_HOOK_SERVER
numdef AREAS, \
	_AREAS_HOOK_CLIENT || _PM || \
	_CATCHINT07 || _CATCHINT0C || _CATCHINT0D
				; display message indicating area of fault

excdef _ONLYNON386, DX


LINE_IN_LEN equ	257		; length of line_in (including header stuff)

		; PSP offsets
ALASAP	equ 02h			; Address of LAst Segment Allocated to Program
				;  => behind process's allocation
CPMCALL	equ 05h			; CP/M CALL 5 compatibility entrypoint
TPIV	equ 0Ah			; Terminate Program Interrupt Vector (Int22)
CCIV	equ 0Eh			; Control-C Interrupt Vector (Int23)
CEIV	equ 12h			; Critical Error Interrupt Vector (Int24)
SPSAV	equ 2Eh			; Save the stack pointer here
DTA	equ 80h			; Program arguments; also used to store file name (N cmd)


%include "eld.mac"

%include "install.mac"

	struc SEGADR
saOffset:	resd 1
saSegSel:	resw 1
%if _PM
saSegment:	resw 1
saSelector:	resw 1
%endif
	endstruc

	%macro segmentedaddress 0.nolist
	istruc SEGADR
	iend
	%endmacro

	struc SEGOFS16ADR
so16aOffset:	resw 1
so16aSegSel:	resw 1
%if _PM
so16aSegment:	resw 1
so16aSelector:	resw 1
%endif
	endstruc

	%macro segofs16address 0-1.nolist zero
	istruc SEGOFS16ADR
%ifidni %1,zero
%elifidni %1,minusone
at so16aOffset,		dw -1
at so16aSegSel,		dw -1
 %if _PM
at so16aSegment,	dw -1
at so16aSelector,	dw -1
 %endif
%else
 %error Unexpected initialiser keyword
%endif
	iend
	%endmacro

	struc SEGONLYADR
soaSegSel:	resw 1
%if _PM
soaSegment:	resw 1
soaSelector:	resw 1
%endif
	endstruc

	%macro segonlyaddress 0.nolist
	istruc SEGONLYADR
	iend
	%endmacro


%if _BOOTLDR
 %include "iniload.mac"

	struc LOADSETTINGS
lsKernelName:	resw 1	; -> kernel file default name
lsAddName:	resw 1	; -> additional file default name, may be empty string
lsMinPara:	resw 1	; how much to load at least, fail if file smaller
lsMaxPara:	resw 1	; how much to load at most (will round up to sector size)
lsOptions:	resw 1	; option flags
lsSegment:	resw 1	; => where to load file
lsEntry:	resd 1	; relative segment for CS, value for IP
lsBPB:		resd 1	; segment for BPB (-1 auto-BPB), offset for BPB
lsCheckOffset:	resw 1	; offset in file segment of word to check
lsCheckValue:	resw 1	; value to check for word, 0 if unused
lsName:		resq 1	; ASCIZ load protocol name
	endstruc

		numdef LUF_DEFAULT_DISKETTE, 0
		numdef LUF_DEFAULT_HARDDISK, 0
%endif


%include "mzheader.mac"


	struc INPUTFILEHANDLE
ifhHandle:	resw 1
ifhFlags:	resw 1
ifhParentSeek:	resd 1
	endstruc

ifhfIsDup:		equ  100h	; before closing, seek it back
	; same value as LBA flag for boot load input files
ifhfTestReserved1:	equ 1000h
ifhfTestReserved2:	equ 2000h
ifhfQuietInput:		equ 4000h	; do not display prompt and input
ifhfQuietOutput:	equ 8000h	; do not display normal output
	; these four are valid for both input file handles and
	;  boot load input files.


	struc AREASTRUC
areastrucEntry:		resb 24
areastrucNext:		resd 1
areastrucPrev:		resd 1
areastrucSubAmount:	resw 1
areastrucSubOffset:	resw 1
areastrucFunAmount:	resw 1
areastrucFunOffset:	resw 1
	endstruc

	struc AREASTRUCSUB
areastrucsubLinear:	resd 1
areastrucsubLinearEnd:	resd 1
areastrucsubListOffset:	resw 1
areastrucsubListAmount:	resw 1
	endstruc

	struc AREASTRUCFUN
areastrucfunLinear:	resd 1
areastrucfunLinearEnd:	resd 1
areastrucfunListOffset:	resw 1
areastrucfunListAmount:	resw 1
	endstruc

	struc AREA
areastart:		resw 1
areaend:		resw 1
areamessage:		resw 1
			resw 1
	endstruc


%include "isvariab.mac"


%include "386.mac"


%if _VDD
; standard BOPs for communication with DEBXXVDD on NT platforms
%macro RegisterModule 0.nolist
	db 0C4h, 0C4h, 58h, 0
	nop
%endmacro
%macro UnRegisterModule 0.nolist
	db 0C4h, 0C4h, 58h, 1
	nop
%endmacro
%macro DispatchCall 0.nolist
	db 0C4h, 0C4h, 58h, 2
	nop
%endmacro
%endif

%assign CODE_INSURE_COUNT 0

		; The entry_to_code_seg/_sel dispatcher in lDEBUG_DATA_ENTRY
		;  detects mistaken debugger breakpoints in its
		;  in-code-parameter by checking for a low-byte
		;  value equal to 0CCh (one-byte int3 opcode).
		; Therefore, we insure that all destinations jumped to
		;  via that dispatcher do not happen to be located
		;  on an offset that gives 0CCh in the low byte.
	%imacro code_insure_low_byte_not_0CCh 0.nolist
 %if (($ - _CURRENT_SECTION %+ _start) & 0FFh) == 0CCh
	nop
  %assign CODE_INSURE_COUNT 1 + CODE_INSURE_COUNT
 %endif
	%endmacro


		; dual code segments
	numdef DUALCODE, (_SYMBOLIC || _IMMASM) && _PM
	numdef DUALCODENEARDUAL, 1
	numdef EXPRDUALCODE, 1
	numdef SYMBOLICDUALCODE, 1
	numdef SYMBOLASMDUALCODE, 0
%if _DUALCODE && _PM

%if _DEBUG
%idefine dualfunction comment
%else
%idefine dualfunction code_insure_low_byte_not_0CCh
%endif

%idefine dualreturn call _CURRENT_SECTION %+ _dualret_helper
%idefine dualdistance far
	%imacro dualcall 1.nolist
%ifndef SECTION_OF_%1
 %error Unknown target section for symbol %1
%endif
	call _CURRENT_SECTION %+ _to_ %+ %[SECTION_OF_%1] %+ _dualcall_helper
 %if _DEBUG
	jmp strict short %%skipdata
 %endif
	dw %1
%%skipdata:
	%endmacro
	%imacro nearcall 1.nolist
%ifndef SECTION_OF_%1
 %error Unknown target section for symbol %1
%endif
%ifidni %[SECTION_OF_%1], _CURRENT_SECTION
	call %1
%else
	call _CURRENT_SECTION %+ _to_ %+ %[SECTION_OF_%1] %+ _nearcall_helper
 %if _DEBUG
	jmp strict short %%skipdata
 %endif
	dw %1
%%skipdata:
%endif
	%endmacro

%elif _DUALCODE && ! _PM

%idefine dualfunction comment
%idefine dualreturn
%idefine dualdistance far
%define PATCH_RELOCATE_FROM_lDEBUG_CODE ""
%define PATCH_RELOCATE_FROM_lDEBUG_CODE2 ""
	%imacro dualcall 1.nolist
%ifndef SECTION_OF_%1
 %error Unknown target section for symbol %1
%endif
%ifidni %[SECTION_OF_%1], _CURRENT_SECTION
	push cs
	call %1
%else
	call relocatedzero:%1
%push
%assign %$entry ($ + _CURRENT_SECTION %+ FIXUP) - 2
	relocatelist _CURRENT_SECTION, %$entry
%pop
%endif
	%endmacro
	%imacro relocatelist 2.nolist
 %define PATCH_RELOCATE_FROM_%1 %[PATCH_RELOCATE_FROM_%1],%2
	%endmacro
 %if _DUALCODENEARDUAL
	%imacro nearcall 1
%ifndef SECTION_OF_%1
 %error Unknown target section for symbol %1
%endif
%ifidni %[SECTION_OF_%1], _CURRENT_SECTION
	call %1
%else
 %push
 %xdefine %$originalsection _CURRENT_SECTION
 %xdefine %$targetsection SECTION_OF_%1
  %ifndef NEARCALL_THUNK_TO_%1
	hiddenusesection %$targetsection
%define NEARCALL_THUNK_TO_%1 %%nearcall_thunk_to_%1
section_of %%nearcall_thunk_to_%1
dualfunction
%%nearcall_thunk_to_%1:
	call %1
	dualreturn
	retf

	hiddenusesection %$originalsection
  %endif
 %pop
	dualcall NEARCALL_THUNK_TO_%1
%endif
	%endmacro
 %else
	%imacro nearcall 1.nolist
%ifndef SECTION_OF_%1
 %error Unknown target section for symbol %1
%endif
%ifidni %[SECTION_OF_%1], _CURRENT_SECTION
	call %1
%else
	call _CURRENT_SECTION %+ _to_ %+ %[SECTION_OF_%1] %+ _nearcall_helper
 %if _DEBUG
	jmp strict short %%skipdata
 %endif
	dw %1
%%skipdata:
%endif
	%endmacro
 %endif
%elif ! _DUALCODE

%idefine dualfunction comment
%idefine dualreturn
%idefine dualdistance near
	%imacro dualcall 1.nolist
	call %1
	%endmacro
	%imacro nearcall 1.nolist
	call %1
	%endmacro
%assign _SYMBOLICDUALCODE 0
%assign _SYMBOLASMDUALCODE 0

%else
 %error Unexpected defines
%endif

%ifn _SYMBOLICDUALCODE
 %assign _SYMBOLASMDUALCODE 0
%endif

 %if _SYMBOLIC && _DUALCODE && _SYMBOLASMDUALCODE
%idefine dual2function	dualfunction
%idefine dual2return	dualreturn
%idefine dual2distance	dualdistance
%idefine dual2call	dualcall
 %else
%idefine dual2function comment
%idefine dual2return
%idefine dual2distance near
	%imacro dual2call 1.nolist
	call %1
	%endmacro
 %endif

	%imacro section_of 1-*.nolist
%rep %0
%xdefine SECTION_OF_%1 _CURRENT_SECTION
%rotate 1
%endrep
	%endmacro

	%imacro check_section_of 1.nolist
%ifndef SECTION_OF_%1
 %error No section specified for symbol %1
%elifnidni SECTION_OF_%1, _CURRENT_SECTION
 %error Wrong section for symbol %1: section_of=SECTION_OF_%1, current=_CURRENT_SECTION
%endif
	%endmacro

	%imacro section_of_function 0-1.nolist
check_section_of %1%00
%00:
	%endmacro


	numdef CHECKSECTION, 0
	numdef CHECKCALLSECTION, _CHECKSECTION
	numdef CHECKJMPSECTION, _CHECKSECTION
	numdef CHECKJCCSECTION, _CHECKSECTION

%if _CHECKCALLSECTION
	%imacro call 1.nolist
	%? %1
checksection %1, %?, call
	%endmacro
%endif
%if _CHECKJMPSECTION
	%imacro jmp 1.nolist
	%? %1
checksection %1, %?, jmp
	%endmacro
%endif
%if _CHECKJCCSECTION
	%imacro je 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jne 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro

	%imacro jb 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnb 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jbe 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnbe 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jc 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnc 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro ja 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jna 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jae 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnae 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro

	%imacro jl 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnl 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jle 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnle 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jg 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jng 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jge 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnge 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro

	%imacro jo 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jno 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jp 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnp 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jpe 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnpe 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jpo 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jnpo 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro js 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jns 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro

	%imacro jcxz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro jecxz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro loop 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro loopz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro loopnz 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro loope 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
	%imacro loopne 1.nolist
	%? %1
checksection %1, %?, jcc
	%endmacro
%endif

	%imacro checksection 3.nolist
%push
 %defstr %$string %1
 %substr %$shortword %$string 1, 5
 %substr %$shortsep %$string 6, 1
 %substr %$nearword %$string 1, 4
 %substr %$nearsep %$string 5, 1
 %substr %$farword %$string 1, 3
 %substr %$farsep %$string 4, 1
 %assign %$isshort 0
 %ifidni %$shortword, "short"
  %if %$shortsep == 32 || %$shortsep == 9
   %assign %$isshort 1
   %substr %$string %$string 7, -1
  %elif %$shortsep == '['
   %assign %$isshort 1
   %substr %$string %$string 6, -1
  %endif
 %endif
 %assign %$isnear 0
 %ifidni %$nearword, "near"
  %if %$nearsep == 32 || %$nearsep == 9
   %assign %$isnear 1
   %substr %$string %$string 6, -1
  %elif %$nearsep == '['
   %assign %$isnear 1
   %substr %$string %$string 5, -1
  %endif
 %endif
 %assign %$isfar 0
 %ifidni %$farword, "far"
  %if %$farsep == 32 || %$farsep == 9
   %assign %$isfar 1
   %substr %$string %$string 5, -1
  %elif %$farsep == '['
   %assign %$isfar 1
   %substr %$string %$string 4, -1
  %endif
 %endif

 %deftok %$token %$string

 %assign %$size 2
 %assign %$isreg 0
 %assign %$exit 0
 %rep 2
  %ifn %$exit
   %if %$size == 2
    %define %$regnames "ax  cx  dx  bx  sp  bp  si  di  "
   %elif %$size == 4
    %define %$regnames "eax ecx edx ebx esp ebp esi edi "
   %endif
   %assign %$index 0
   %rep 8
    %ifn %$exit
     %substr %$reg %$regnames %$index * 4 + 1, 4
     %deftok %$reg %$reg
     %ifnempty %$reg
      %ifidni %$reg, %$token
       %assign %$isreg %$size
       %assign %$exit 1
       %exitrep
      %endif
     %endif
    %endif
    %assign %$index %$index + 1
   %endrep
   %if %$exit
    %exitrep
   %endif
   %assign %$size %$size * 2
  %endif
 %endrep

 %assign %$ismulti 0
 %assign %$ismem 0
 %strlen %$length %$string
 %assign %$ii 0
 %rep %$length
  %substr %$point %$string %$ii + 1, 1
  %if %$point == 32 || %$point == 9
   %assign %$ismulti 1
  %endif
  %ifidn %$point, '['
   %assign %$ismem 1
  %endif
  %assign %$ii %$ii + 1
 %endrep

 %assign %$islocal 0
 %substr %$point %$string 1, 1
 %substr %$prefix %$string 1, 3
 %ifidn %$point, '.'
  %ifnidn %$prefix, '..@'
   %assign %$islocal 1
  %endif
 %endif

 %if %$isreg
  %if %$isreg == 4
   %warning 32-bit reg %3: %2 %1
  %else
   %warning 16-bit reg %3: %2 %1
  %endif
 %elif %$ismulti || %$ismem
  %warning not single %3: %2 %1
 %elif %$islocal
  %ifidni %3, call
   %warning local %3: %2 %1
  %endif
 %elifdef SECTION_OF_%[%$token]
  %ifnidni SECTION_OF_%[%$token], _CURRENT_SECTION
   %error Symbol %$token called wrongly: section_of=SECTION_OF_%[%$token], current=_CURRENT_SECTION
  %endif
 %endif
%pop
	%endmacro


	struc MEMREF
mrLinear:		resd 1
mrOffset:		resd 1
mrSegmentSelector:	resw 1
mrFlags:		resw 1
mrLength:		resd 1
	endstruc

		; Currently only direct branches are allowed when
		;  disassembling from the U command. (That is,
		;  [disflags] & DIS_F_SHOW is clear.) All other
		;  types of references depend on segment registers
		;  and sometimes base and index registers, which are
		;  not known ahead of time. They are only known for
		;  the R command's disassembly. (DIS_F_SHOW set.)
		; (When a mov ss or pop to ss will change ss, a
		;  subsequent instruction using ss will not be
		;  disassembled with the correct ss value.
		;  This should be rare though. We may at a later
		;  point detect this condition and not display
		;  references with ss then.)
mrfBranchDirect:	equ    1
mrfMem:			equ    2
mrfMemSource:		equ    4
mrfMemDest:		equ    8
mrfA32:			equ   10h
mrfString:		equ   20h
mrfStringSource:	equ   40h
mrfStringDest:		equ   80h
mrfUsesSS:		equ  100h
mrfBranchIndirect:	equ  200h


%if _VXCHG && ! _VXCHGBIOS
	struc XMSM
.size_:		resd 1
.srchdl:	resw 1
.srcadr:	resd 1
.dsthdl:	resw 1
.dstadr:	resd 1
	endstruc
%endif


[list +]
