diff -uNr a/dos32a/ChangeLog b/dos32a/ChangeLog
--- a/dos32a/ChangeLog false
+++ b/dos32a/ChangeLog 805dfe2f1e4e5b312178e659424e80835770e13bdf2e958ae6d7a22e2434579ddde0f93ef162314aa8ffa5beaefba2ebe5a833d7d60c9bda34952eacf599f37e
@@ -0,0 +1,769 @@
+ *****************************************
+ *** DOS/32A DOS Extender -- ChangeLog ***
+ *****************************************
+
+
+[2006-04-20]
+DOS/32 Advanced DOS Extender, version 9.1.2
+===========================================
+
+DOS Extender (DOS32A.EXE):
+--------------------------
++ Bugfix: Int 21h function 3Fh refused to return when reading from STDIN
+ (reported by Gianni Gallucci)
+
++ Bugfix: in irq_fail fn, hardware exception #9 doesn't have exception code
+ (reported by Charles Hyde)
+
++ applied mode.asm patch (also by Charles Hyde from Infineon) with minor
+ formatting changes; I'm rather ambivalent about implementing the others
+ into the mainstream builds (in particular the PAE one), will make those
+ available from the development (beta) page...
+
+
+
+
+
+[2005-12-12]
+DOS/32 Advanced DOS Extender, version 9.1.1
+===========================================
+
+DOS Extender (DOS32A.EXE):
+--------------------------
++ improved memory allocation under Clean system: INT 15h, AX=0E801h is used
+ if AX=0E820h fails (based on patch provided by Arthur Kalliokoski)
+
+
+
+
+
+[2005-11-08]
+DOS/32 Advanced DOS Extender, version 9.1.0
+===========================================
+
+DOS Extender (DOS32A.EXE):
+--------------------------
++ added support for SSE/SSE2/SSE3 capable processors
+
++ added preliminary support for PE file format (recognized but not yet implemented)
+
++ with verbose mode turned on the DOS Extender will pause prompting to press a key;
+ this gives a chance to read loader info before the app kicks in
+
++ internal debugger has been dropped, CLIENT/debug.asm has been heavily rewritten
+
++ INT 1 and INT 3 op-codes are now treated by DOS/32A as no-ops, this works around
+ some lame anti-debugging protections (Null-pointer protection works as expected)
+
++ "VCPI/DPMI Detection Order" option has been removed, DOS/32A unconditionally
+ favours VCPI over DPMI, if and when possible
+
++ "Internal Exception Control" option has been removed, DOS/32A is always in control
+ of the exception handling
+
++ "Trap and Report Emulated IRQs" option has been removed, this simplifies IRQ
+ handling
+
++ "Extended Memory Blocks Checking" option has been removed, DOS/32A unconditionally
+ checks EMB integrity
+
++ DPMITST environment option is no longer supported; it is still recognized but is
+ now a no-op
+
++ whenever possible, DOS/32A will favour INT 15h/XMS systems over VCPI/DPMI,
+ (thanks wd)
+
++ INT 31h DPMI last function entry is cached so that subsequent calls with the same
+ function number do no search the lookup table
+
++ INT 31h DPMI functions 0E00h & 0E01h no longer virtualize FPU EM & MP flags
+
++ additional PIC constraint: slave PIC may not be mapped onto INT 8
+
++ slightly reduced run-time complexity of the IRQ handling code
+
++ exception handlers are now invoked with the correct stack frame (as mandated
+ by DPMI v0.9 spec)
+
++ all the exception vectors are now hooked under external DPMI (symmetric with
+ built-in DPMI and using the same exception handlers)
+
+
+SUNSYS Setup Utility (SS.EXE):
+------------------------------
++ the following options in the Kernel menu have been deprecated:
+
+ "VCPI/DPMI Detection Order"
+ "Internal Exception Control"
+ "Trap and Report Emulated IRQs"
+ "Extended Memory Blocks Checking"
+
+ it is still possible to toggle the state of these options, but the changes have
+ no effect on the DOS Extender
+
+
+SUNSYS Debugger (SD.EXE):
+-------------------------
++ R.I.P.
+
+
+
+
+
+[2005-05-19]
+DOS/32 Advanced DOS Extender, version 7.35
+==========================================
+
+DOS Extender (DOS32A.EXE):
+--------------------------
++ mouse callback code cleanup
++ allocation of up to 2Gig under Clean system (Int 15h, AX=E820h)
++ with verbose mode active and not under external DPMI the entry point
+ of application will trap to internal debugger
+
+
+
+
+
+[2005-01-12]
+DOS/32 Advanced DOS Extender version 7.33
+=========================================
+
+DOS Extender (DOS32A.EXE):
+--------------------------
++ Bugfix: exec loader could crash the DOS Extender during startup in rare situations
++ Bugfix: DPMI function 0301h can not transfer data on stack to real mode procedure
++ Int 21h functions 4402h, 4403h, 4404h, 4405h, (DOS IOCTL) have been extended
++ Int 21h functions 3Fh & 40h (DOS IO) have been rewritten
++ mouse callback can now handle non-standard stack frames
+
+
+SUNSYS Bind Utility (SB.EXE):
+-----------------------------
++ Bugfix: minor binding problems with unbound LE/LX execs
++ removed check for DOS32A environment string
+
+
+SUNSYS Compress Utility (SC.EXE):
+---------------------------------
++ removed check for DOS32A environment string
+
+
+SUNSYS Setup Utility (SS.EXE):
+------------------------------
++ removed Lock and Version checks
+
+
+
+
+
+*******************************************************************************
+Release 8
+DOS/32 Advanced DOS Extender version 7.1
+========================================
+
+News:
+-----
++ This release of DOS/32A is distributed under a new license. See "license.txt"
+ for more information.
+
++ The complete source code of the DOS Extender and its tools is included with
+ this release.
+
+DOS Extender:
+-------------
++ Fixed bug in DPMI function 0503h when in certain cases the contents of the
+ memory block being reallocated was not copied to the new location.
+
++ Minor fix: DOS/32A environment configuration option /NOWARN can now accept
+ several warnings separated by a comma (eg /NOWARN:9003,9004).
+
+Other:
+------
++ Minor updates to the documentation manuals, mainly to reflect the new
+ licensing issues.
+
+
+
+
+
+*******************************************************************************
+Service Pack 1 (Revision [C])
+DOS/32 Advanced DOS Extender version 7.0
+========================================
+
+News:
+-----
++ SVER Utility program. This utility can be used to find out the version
+ of DOS/32A, STUB/32A or STUB/32C and to display the OEM Information
+ appended to the LC-style executables by Original Equipment Vendors.
+
+DOS Extender:
+-------------
++ Fixed problem in DOS/32A DPMI kernel causing the DOS Extender not being
+ able to properly callback the IRQs of the second PIC to the protected mode
+ handlers.
+
+SUNSYS Setup Utility:
+---------------------
++ Fixed minor problem when in Kernel Config window setting VCPI PhysTables
+ to 0 and switching to Hex mode caused the number to flash red incorrectly
+ indicating an errorneously enered value.
+
+
+
+
+
+*******************************************************************************
+Release 7
+DOS/32 Advanced DOS Extender version 7.0
+========================================
+
+News
+----
++ A new high performance D32A C/C++ Run-Time Library is now included with
+ DOS/32 Advanced DOS Extender. The Library is located in .\L32 directory
+ and its C/C++ header in .\H32 directory.
+
++ The documentation manuals supplied with DOS/32 Advanced DOS Extender are
+ now in the HTML format. The plain-text based manuals have been dropped. To
+ view the new HTML based manuals use an internet browser (Netscape Navigator
+ is highly recommended although Explorer will also do fine), select "File ->
+ Open File" from the browser's menu and open "manual.htm" file located in the
+ .\DOCS directory.
+
+DOS Extender
+------------
++ Year 2000 compliance has been added for DOS/32 Advanced DOS Extender and
+ all of the utilities accompanying it.
+
++ When running under _external_ DPMI host, DOS/32A will remove its own DPMI
+ Kernel from memory, thus freeing up up to 10KB of conventional DOS memory.
+
++ Added exception handling under _external_ DPMI, DOS/32A will trap exceptions
+ #0, #6, #13 and #14 (ie the most common) and report the complete machine
+ state; DOS/32A will now also report where the exception came from by
+ specifying "KERNEL" for ADPMI Kernel, "CLIENT" for DOS/32A Client, "APP/32"
+ for the currently running application and "APP/??" if exception's origin is
+ unknown.
+
++ Added support for "Performance Counters" which monitor the number of mode
+ switches for INTs, IRQs, and Callbacks; a new Extended DPMI API function
+ (AX=0A00h, then AL=09h) provides access to these.
+
++ Added support for protected mode TSRs installed with INT 21h, AH=31h
+ function; contents of DX register passed to this function are ignored
+ when called from protected mode.
+
++ Added new warning (9006): "incompatible version of DOS/32A already running"
+ issued when the parent and the child applications are running under
+ different versions of DOS/32A (when spawn() programs).
+
++ Added new environment option "/NOWARN:xxxx" to disable particular warnings,
+ ie /NOWARN:9003.
+
++ Added new environment option "/NOC" to disable explictly the copyright
+ banner. The warnings are still displayed on the screen.
+
++ Increased the maximum of loadable Objects from 32 to 64 per application.
+
++ Improved CTRL-C and CTRL-Break handling in the DOS Extender's Client code,
+ which solves problems with these key combinations not properly detected when
+ running under some external DPMI hosts (in particular Windows).
+
++ Improved Interrupt switching algorithm in DOS/32A DPMI Kernel, also improved
+ algorithm enabling A20 gate when running in Clean system.
+
++ Improved error checking in Extended DOS functions 0FF95h and 0FF97h: they
+ will now fail calls that allocate 0 bytes or >1MB.
+
++ Improved support for VCPI system software; fixed bug in VCPI initialization
+ code which caused the DOS Extender's kernel to fail to free all the
+ allocated PageTables on exit in some situations. You are now also allowed to
+ set VCPI PhysTables value to zero to save some conventional memory if not
+ using physical memory mapping DPMI functions 0800h and 0801h.
+
++ Minor fix: DPMI function 0001h (Free Selector) will now fail any calls that
+ try to free the current CS (Kernel) or SS (App. stack) selectors.
+
++ Minor fix: Extended DOS function 4Ch (Terminate) will release ZERO selector
+ before exiting to DOS.
+
++ Minor improvements in the LC-style file format loader: uncompressed Objects
+ are loaded slightly faster.
+
++ Fixed bug in Extended DOS function AH=40h (Write to file) when DOS/32A would
+ crash when running under external DPMI and writing to disk with no free
+ space left.
+
++ Fixed bug in DOS/32 Advanced environment configuration reading functions,
+ when the DOS Extender would sometimes at startup take off into "hyperspace"
+ reading the whole environment, instead of just one line (DOS32A=...).
+
++ Removed check for invalid limits in DPMI function 0008h; DOS/32A will now
+ unconditionally perform auto-correction of selector's limit if it is out
+ of range.
+
++ Removed support for bottom-up allocation scheme when running under Clean
+ (INT 15h) system software. Instead improved support for top-down allocation
+ scheme which yields better performance and more extended memory.
+
++ Reduced the default number of Page Tables reserved for physical memory
+ mapping from 4 down to 2 (eq 8MB).
+
++ Reduced the default size of DOS Transfer Buffer from 16KB down to 8KB, does
+ not affect disk I/O performance but brings the memory requirements down.
+
+SUNSYS Bind Utility:
+--------------------
++ Fixed all known problems.
+
++ Added support for OEM title information for LC-style execs.
+
++ Otherwise no major changes visible to the user.
+
+SUNSYS Compress Utility:
+------------------------
++ Fixed all known problems.
+
++ Improved (rewritten) "Advanced Preprocessing" algorithm.
+
++ Added support for OEM title information for LC-style execs.
+
++ Otherwise no major changes visible to the user.
+
+SUNSYS Setup Utility:
+---------------------
++ Removed "Selector Invalid Limit Check" option.
+
++ Otherwise no major changes visible to the user.
+
+SUNSYS Debugger:
+----------------
++ No major changes.
+
+
+
+
+
+*******************************************************************************
+Release 6
+DOS/32 Advanced DOS Extender version 6.00
+=========================================
+
+News
+----
++ New SUNSYS Compress Utility program which allows compression of LE- and
+ LX-style Linear Executables into the new LC-style Linear Compressed file
+ format (see "sc.txt" help file located in .\DOCS directory).
+
++ Configurable stub file STUB/32C which can be configured by SUNSYS Setup
+ Utility program, located in .\BINW directory and named "stub32c.exe".
+
+DOS Extender
+------------
++ Removed fatal error (0008): "configuration header corrupted", which was never
+ used unless the DOS Extender was linked incorrectly.
+
++ Upon a crash (exception) in protected mode application the DOS Extender will
+ report the unrelocated crash address for _any_ Object, not the only one that
+ had entry point in it as it did before.
+
++ DOS/32 Advanced now supports allocation of more than 64MB of memory without
+ using Virtual Memory. The maximum amount of memory the DOS Extender can
+ allocate is limited to 2GB when running under XMS and to 256MB under VCPI.
+
++ Fixed problem with Verbose Mode when the DOS Extender would report the
+ incorrect size of DPMI memory when allocated >64MB. The DPMI memory size is
+ now reported in KB when below 64MB, and in MB when above.
+
++ Added support for LC-style Linear Compressed protected mode executables. By
+ using SUNSYS Compress Utility the users can compress LE and LX applications
+ into the new LC file format.
+
++ Added new run-time error (4007): "not enough DOS Transfer Buffer space to
+ load LC-exec" which is reported when loading Linear Compressed executables
+ and the size of DOS Transfer Buffer is set below 8KB.
+
++ The Loader will skip allocation of selectors for subsequently loaded 32bit
+ Objects, and will make the application happy with only one 32bit CODE and
+ one 32bit DATA selectors respective. This will prevent wasting of selectors
+ in applications which contain more than two 32bit Objects.
+
++ DPMI functions 0602h and 0603h are supported and will return with CF clear
+ without actually doing anything good.
+
+SUNSYS Bind Utility:
+--------------------
++ Added new commands and options "/BC", "/RC", "/BN", "/UN", "/Q", "/S" and
+ "/H" (or "/?"). Refer to "sb.txt" help file for more information.
+
+SUNSYS Compress Utility:
+------------------------
++ This one is new for this release. See "sc.txt" for help.
+
+SUNSYS Setup Utility:
+---------------------
++ Added support for configurable stubs, STUB/32C files.
+
++ Added (actually documented) options "/INFO", "/LOCK", "/UNLOCK", "/QUIET",
+ "/SILENT" and "/H" (or "/?"). See "ss.txt" help file.
+
+SUNSYS Debugger:
+----------------
++ Minor changes, fixed mouse problem with some mouse drivers when the cursor
+ would disappear when moving it below the bottom of the screen.
+
+
+
+
+
+*******************************************************************************
+Release 5
+DOS/32 Advanced DOS Extender version 5.00
+=========================================
+
+DOS Extender
+------------
++ Resolved problem with WATCOM Linker v11.0(a) when the DOS Extender was not
+ able to correctly recognize and load the LX-style executables.
+
++ The DOS Extender now supports, and will correctly load Objects with the size
+ of zero. However, as such Objects will in most cases indicate an error in
+ the protected mode application (wlink dead code elimination should kill'em),
+ the DOS Extender will issue a new warning (9005) to inform the user about
+ this situation.
+
++ The default size of the DOS Transfer Buffer is now 16KB instead of 64KB.
+ This not only reduced the DOS memory requirements, but also improved the
+ DOS Extender's disk I/O throughoutput.
+
++ When showing information about Selectors in the exception report listing
+ the DOS Extender will no longer list the DPL of a Selector as it always
+ was equal to 0. Instead, DOS/32 Advanced will show a better explanation
+ of Selector's attributes (CODE/DATA and 16/32 bit).
+
++ DPMI function 0008h, Set Segment Limit, will now report invalid limits as a
+ new run-time error (6006), which will result in application termination. You
+ can always turn off this feature, by using the SUNSYS Setup Utility.
+
++ Fatal error (3005) will now report message "error in app exec" which means
+ that the application was corrupted or an error occurred at link time.
+
++ With VERBOSE mode turned on the DOS Extender will now list the PSP_Sel,
+ Env_Sel and Env_Seg to provide additional information about PSP Selector,
+ Environment Selector and Environment real mode Segment allocated by the
+ DOS Extender for application. In addition, the DOS Extender will report
+ Process_ID and Module Name in the exception listing which can be useful
+ when spawning applications.
+
++ Added new feature: "Start Full-Screen under Windows". DOS/32 Advanced will
+ switch the application to the full-screen mode when running under Windows in
+ a DOS-box window. Can be turned off (the default is off).
+
++ Another new option in the DOS Extender: "Ignore DOS/4G API Extension Calls".
+ Documented in the "ss.txt" help file. Certain programs which otherwise use
+ DOS/4G API extensions can now be run under DOS/32 Advanced.
+
++ The DOS Extender will now automatically deinstall the possibly installed
+ mouse ISR by issuing INT 33h with AX=000Ch and ES:EDI=0 on exit to DOS.
+
++ New extended DOS functions 0FF94h..0FF97h are now supported for allocation
+ of DOS memory. These functions work in exactly the same way as functions
+ 0FF90h..0FF93h. Look into "Programmer's Reference" ("prog_ref.doc" file)
+ documentation for more information about those.
+
++ The spawning techniques of DOS/32 Advanced have been greatly improved. The
+ required size of the "DOS Transfer Buffer" is now 1KB instead of 4KB when
+ using extended DOS function AH=4Bh to spawn. Read more about this in the
+ "Technical Reference" ("rech_ref.doc" file) documentation.
+
++ Memory management ADPMI functions have been rewritten and now offer improved
+ performance and security. Allocated Extended Memory Blocks are now aligned
+ on Paragraph (16-byte) boundary and protection against EMB overwriting is
+ now 99% safe.
+
++ Once again, DOS/32 Advanced DOS Extender requires no extended memory to load
+ and execute a protected mode program. The relocations are now loaded into
+ DOS memory first, only when not enough DOS memory, will they be loaded into
+ extended memory (a very rare situation).
+
++ Fixed minor problem in DPMI functions 0800h/0801h when the last mapped page
+ was not marked as last.
+
++ Fixed bug in extended DOS function AH=40h, Write to File, when truncation
+ of files (using ECX = 0) did not work as expected.
+
++ Corrected DPMI function 050Ah, Get Base and Size of Memory Block. The base
+ reported now points to the actual address of memory block instead of block
+ header.
+
++ Fixed problem with IRQ 7 which was not processed by DOS/32 Advanced built-in
+ DPMI correctly.
+
++ Fixed a small problem when the DOS Extender could not load and execute the
+ "raw" LE/LX programs, ie applications not bound to any stub.
+
++ The ADPMI function 0EEFFh now returns EAX with "D32A" ID-string instead of
+ "PMDW". This function has been pretty much standardized and can be used
+ for effective detection of the currently running DOS Extender.
+
++ The Free Package version now supports DPMI functions 0800h and 0801h for
+ mapping of linear memory.
+
++ Support for Win95 Long File Names has been included into this version of
+ DOS/32 Advanced. Look for information on these functions (INT 21h, AX=71xxh)
+ in the "Programmer's Reference" documentation ("prog_ref.doc" file).
+
+SUNSYS Setup Utility:
+---------------------
++ Two new options have been added: "Ignore DOS/4G API Extension Calls" in the
+ "Configure DOS/32A DPMI Kernel" menu, and "Start Full-Screen under Windows"
+ in the "Configure DOS/32A DOS Extender" menu.
+
++ Several options have been renamed, and placed in a more proper (logical)
+ order. You really should not have problems with recognizing them though.
+
+SUNSYS Bind Utility:
+--------------------
++ Unbinding of LE/LX executables is now supported in the Free Package version.
+
+SUNSYS Debugger:
+----------------
++ Fully functional, except for the "System Interrupt History" which is
+ supported in the Pro version only. Otherwise no major changes.
+
+
+
+
+
+*******************************************************************************
+Release 4
+DOS/32 Advanced DOS Extender version 4.30
+=========================================
+
+Install Program:
+----------------
++ The Install program will now automatically copy file "dos32a.lnk" into
+ WATCOM's BINW or BIN directory (depending on which version of WATCOM C/C++
+ you have) if you select auto-system-update (which is strongly recommended).
+
++ You can now install DOS/32 Advanced in any directory, not just "DRV:\DIR" as
+ it was before. You can install it for example in "C:\WATCOM\DOS32A" or
+ anything like that.
+
++ File "dos4gw.exe" which was located in .\PCTEST directory has been removed
+ to reduce the size of Compressed Data File.
+
+DOS Extender:
+-------------
++ Bug fixed in DPMI function 0500h when the reported information was written
+ to DS instead of ES selector (I know, I know...).
+
++ The DOS Extender will now correctly recognize and execute all types of
+ DOS/4G(W) Professional bound applications.
+
++ Mode switching routines have been optimized for Pentium MMX/II and AMD K6
+ processors (or any CPU with multiple execution units supporting RISC86).
+ This does not really improve mode switching speed though.
+
++ Bug fixed: the DOS Extender can now display decimal numbers greater than
+ 0x7FFF within strings containing "%d" option.
+
++ DOS/32 Advanced now supports the "Verbose Mode". This one can be useful when
+ you need to know exactly what is going on while the DOS Extender is loading
+ your application, amount of allocated memory and so on.
+
++ New environment option: /VERBOSE[:ON|OFF]. Refer to the "User's Reference"
+ ("user_ref.doc" file) documentation for more information.
+
++ New "undocumented" DOS API function AX=Magic. This function is mentioned
+ somewhere in this package, but you will have to discover it yourself!
+
+SUNSYS Setup Utility:
+---------------------
++ The Setup Utility now supports new option: "Verbose Mode".
+
+SUNSYS Bind Utility:
+--------------------
++ The Bind Utility will now correctly recognize and process all types of
+ DOS/4G(W) Professional bound applications.
+
++ Two new commands: "-BS", bind STUB/32A to a file, and "-RS" replace existing
+ stub with STUB/32A, now supported.
+
+SUNSYS Debugger:
+----------------
++ The Debugger will now correctly recognize and load all types of
+ DOS/4G(W) Professional bound applications.
+
++ The Debugger shipped with the Free Package version of the DOS Extender now
+ supports all commands except "Here" (F4-key) and "Run" (F9-key).
+
+
+
+
+
+*******************************************************************************
+Release 3
+DOS/32 Advanced DOS Extender version 4.00
+=========================================
+
+News:
+-----
++ Installation program that installs DOS/32 Advanced DOS Extender on your
+ computer.
+
++ New stub file, 538 bytes in size!
+
+DOS Extender:
+-------------
++ DOS/32 Advanced DOS Extender does not check for 8086 anymore. This should not
+ be a problem since PC/XTs are quite dead nowdays.
+
++ DOS API function AH=0Ah is no longer supported and has been removed. It is
+ not used in WATCOM libraries and nobody uses it anyway.
+
++ Support for Slow Object Loading Scheme has been dropped. The DOS Extender
+ now requires some Extended memory in order to load application fixups, even
+ if the application itself is loaded in DOS memory.
+
++ Error code (4004) has been changed: not enough extended memory to load
+ application fixups.
+
++ Page Offset Shifts other than 0 are now supported by the loader for LX-style
+ executables.
+
++ Fixed bug in startup code causing no errors being reported when protected
+ mode was not entered successfully.
+
++ Fixed bug in exteded VBE API AX=4F00h when the CX register was not passed
+ down to the real mode.
+
++ VBE API is now truly extended: function AX=4F00h now translates the pointers
+ returned in the VBE structure to protected mode values.
+
++ New extended VBE functions have been added: AX=4F09h and AX=4F0Ah.
+
++ Bug fixed: options /QUIET and /PRINT:OFF defined in the environment now
+ disable the copyright string (Pro version only) as well as warnings.
+
++ Bug fixed: on exit under "Clean" system the DOS Extender will not disable
+ the A20 gate. This will solve problems when spawning programs with no
+ memory manager installed, but this will also produce a problem with A20 line
+ enabled after you run DOS/32 Advanced under "Clean" system. I guess we will
+ have to live with that, since there ain't many programs that rely on memory
+ wraparound under 1MB today, and you probably use a memory manager anyway.
+
++ Fixed a little bug in DPMI API function AX=0300h when parameters pushed on
+ stack that were to be copied to the real mode stack were not being copied
+ properly.
+
++ Bug fixed: extended DOS function AH=34h, get InDOS flag, will now work as
+ expected (no GPEs or crashes no more).
+
++ Bug fixed: the loader was not able to correctly load the last object of the
+ protected mode application, especially when the application was linked with
+ debug info which was placed directly after the last object's data. An
+ incorrect amount of bytes was read causing the _BSS segment being trashed
+ while it should contain zeroes only (by default, WATCOM startup code will
+ clear only the first 4K of _BSS segment if it thinks it runs under DOS/4GW).
+
++ Extended DOS API function AH=4Ch (terminate program), now will not restore
+ real mode environment segment in PSP at offset 002Ch to be compatible with
+ external DPMIs since they might need the protected mode selector at that
+ offset to perform their cleanup on the way to DOS,.. or some place else.
+
++ Extended DOS API now supports new functions: AX=0FF8Ah, AX=0FF90h, AX=0FF91h,
+ ... and so on (see "prog_ref.doc" file).
+
+SUNSYS Setup Utility:
+---------------------
++ Option Use Fast Loading Object Scheme is no longer supported.
+
+SUNSYS Bind Utility:
+--------------------
++ No major changes.
+
+SUNSYS Debugger:
+----------------
++ No major changes.
+
+
+
+
+
+*******************************************************************************
+Release 2
+DOS/32 Advanced DOS Extender version 3.00
+=========================================
+
+DOS Extender:
+-------------
++ When a file name is specified at the command line, the DOS Extender will now
+ apply an ".exe" extension to it, if it could not open the original file. This
+ will solve some compatibility problems when replacing DOS/4GW DOS Extenders
+ with DOS/32 Advanced.
+
++ The loader now supports Fast Object Loading Scheme. This feature allows the
+ DOS Extender to load protected mode applications much faster (as fast as
+ DOS/4GW does). Though it requires some extended memory to be allocated. Note
+ that if no extended memory was allocated by the DOS Extender at startup,
+ this feature will not be used, and the DOS Extender will automatically use
+ the old, slow Object Loading Scheme, rather than reporting an error.
+
++ The loader now supports Paragraph (16 byte) alignment along with Page
+ alignment (4096 byte) for objects that are loaded into extended memory.
+ If a program has a large number of objects, this feature will greatly
+ increase the amount of free extended memory available after the application
+ was loaded.
+
++ Invented new DOS function in the DOS Extender: AX=0FF89h - DOS/32 Advanced
+ Get Configuration Info (see "prog_ref.doc" file).
+
++ Invented new DPMI API function (AX=0A00h): AL=06h - Get DOS/32 Advanced
+ Kernel Selectors (see "prog_ref.doc" file).
+
++ When spawning DOS/32 Advanced from another (incompatible) DOS Extender
+ under VCPI, DOS/32 Advanced startup code will no longer cause the system
+ to crash.
+
++ DPMI function 0500h will no longer return error 8013h when no extended
+ memory was allocated at startup. Instead it will simply fill all the
+ fields in the structure with zeroes.
+
++ DPMI function 0500h will no longer return the incorrect size of the largest
+ available extended memory block as it did before in rare cases.
+
+SUNSYS Setup Utility:
+---------------------
++ Option Console Output has been replaced with two new options: Show Warnings
+ and Show Copyright Banner at Startup.
+
++ New option in DOS Extender Configuration window: Use Fast Loading Object
+ Scheme.
+
++ New option in DOS Extender Configuration window: Object Alignment when
+ Loaded High.
+
++ New option in DOS Extender Configuration window: Show Copyright Banner at
+ Startup. This function replaces the old Console Output option, and allows
+ the user to separately disable warnings (with Show Warnings option) and
+ the copyright banner.
+
+SUNSYS Debugger:
+----------------
++ The Debugger now supports WATCOM-style assembly text screen along with
+ Borland's Turbo Debugger-style. Use key '1' to switch between TD and WD
+ text screens.
+
+
+
+
+
+*******************************************************************************
+Release 1
+DOS/32 Advanced DOS Extender version 2.25
+=========================================
+
++ The first publicly available version of DOS/32 Advanced DOS Extender.
diff -uNr a/dos32a/LICENSE b/dos32a/LICENSE
--- a/dos32a/LICENSE false
+++ b/dos32a/LICENSE d82eaf75c9cf68f866ff7b565f4a4a6d74bd70299cf506cc2a79412ce6f0cf4f2ac72a9626a92db8b87d1132da2398e6dd17eecd4e2ed97f77e52601ab35b8b6
@@ -0,0 +1,39 @@
+DOS/32 Advanced DOS Extender Software License
+=============================================
+
+Copyright (C) 1996-2006 by Narech K. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. The end-user documentation included with the redistribution, if any,
+must include the following acknowledgment:
+
+"This product uses DOS/32 Advanced DOS Extender technology."
+
+Alternately, this acknowledgment may appear in the software itself, if
+and wherever such third-party acknowledgments normally appear.
+
+4. Products derived from this software may not be called "DOS/32A" or
+"DOS/32 Advanced".
+
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff -uNr a/dos32a/MANIFEST b/dos32a/MANIFEST
--- a/dos32a/MANIFEST false
+++ b/dos32a/MANIFEST 02d632e991f6d9f98083a9464c5078faa330d6ae45c483c27cd04ae9ac752237a9409dfa59ce131f61c824521d877fd551a6eb2c7924fb0ef22ebf6b31648ebe
@@ -0,0 +1 @@
+ 828710 dos32a-src "DOS/32 Advanced DOS Extender, version 9.1.2."
diff -uNr a/dos32a/README b/dos32a/README
--- a/dos32a/README false
+++ b/dos32a/README d8eba3544618167de4e6c502efd69643db9b47fb96c9733e8f11ab03cf6634396d0b02e3784b1e3c449630a4516abf048d9e25f1bec3e347fd3a9c354f5b4dea
@@ -0,0 +1,55 @@
+[2006-04-20]
+DOS/32 Advanced DOS Extender, version 9.1.2
+Illis quorum meruere labores.
+
+
+Contents:
+ 1.0 - Synopsis
+ 2.0 - System Requirements
+ 3.0 - Release Notes
+ 4.0 - FAQ
+
+
+
+
+1.0 - Synopsis
+==============
+This is a DOS (Dead Operating System) Extender. It extends DOS. By how much
+or for how long still remains a mystery. It lives in a refrigerator. It has
+a wonderful ability to piss off one's dearest neighbors by sporadically
+electrocuting their cats. Incidentally it also makes the farm sheep go bäää.
+
+
+
+2.0 - System Requirements
+=========================
+A puter and a pint of Guiness... Actually, you can replace puter with women.
+Guiness, however, is mandatory.
+
+
+
+3.0 - Release Notes
+===================
+Avril Lavigne rocks! Kent - ni är så j:a bra! Vitja Tsoy (Kino) - s ponikshej
+golovoj, v tvoju pamjat'...
+
+
+
+4.0 - FAQ
+=========
+Q: What's new?!
+A: Oh, not much. Just the same old shit wrapped up nicely in a new package.
+
+Q: I've found a bug, yippie! Now what?
+A: Pin it on a wall. Alternatively send it in, I collect them!
+
+Q: WTF?! I can't build from your sources.
+A: RTFM! Twice! Dumbass. Then download and install v7.1 SDK.
+
+Q: Eeeek!
+A: Exactly! Ya said it, mate.
+
+
+- his infinite evilness Narech "den livsfarlige" K. Over n' out! :=)
+
+[EOFF]
diff -uNr a/dos32a/src/dos32a/dos32a.asm b/dos32a/src/dos32a/dos32a.asm
--- a/dos32a/src/dos32a/dos32a.asm false
+++ b/dos32a/src/dos32a/dos32a.asm a0373e242747f5cd54b18587f47445fdd236e769ea7be365307850e55e903622625c1375d0ceb763784f68f3554fd3682737c72e94e768d576d1c8552bf0444d
@@ -0,0 +1,477 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+BUILDING_KERNEL = 0
+BUILDING_CLIENT = 1
+
+;*****************************************************************************
+; DOS/32 Advanced DOS Extender master Client file, implements program entry
+; point and includes the necessary client files from .\TEXT\CLIENT\.
+;
+;*****************************************************************************
+
+STACKSIZE = 0080h ; size of stack (in para)
+INTTABSIZE = 0040h ; size of copy of interrupt table (in para)
+
+_ID32 segment para public use16 'CODE0'
+_ID32 ends
+_KERNEL segment para public use16 'CODE1'
+_KERNEL ends
+_TEXT16 segment para public use16 'CODE2'
+_TEXT16 ends
+_STACK segment para stack use16 'STACK'
+_STACK ends
+
+extrn pm32_info :far
+extrn pm32_init :far
+extrn pm32_data :byte
+
+include TEXT\include.asm
+
+
+ .386p
+ LOCALS
+ NOJUMPS
+;=============================================================================
+_ID32 segment para public use16 'CODE0'
+_ID32_SIZE=16 ; size excluding 'ID32' signature
+;-----------------------------------------------------------------------------
+db 'ID32' ; ID signature
+db 00111111b ; KERNEL misc. bits:
+ ; bit 0: **deprecated**
+ ; bit 1: **deprecated**
+ ; bit 2: 0=VCPI smart page alloc off, 1=on /1=def
+ ; bit 3: 0=VCPI+XMS alloc scheme off, 1=on /1=def
+ ; bit 4: **deprecated**
+ ; bit 5: **deprecated**
+ ; bit 6: reserved /0=def
+ ; bit 7: 0=ignore 4G extensions off, 1=on /0=def
+db 64 ; Max. number of page tables under VCPI /256MB
+db 2 ; Max. number of page tables mem_mapping /4MB
+db 16 ; Max. number of real mode callbacks /16
+dw 256 ; Max. number of Selectors under VCPI/XMS/raw /256
+db 8 ; Real mode Stack nesting
+db 8 ; Protected mode Stack nesting
+dw 20h ; Real mode Stack length, (in para)
+dw 20h ; Protected mode Stack length, (in para)
+dd 0FFFFFFFFh ; Max. extended memory to allocate in bytes
+;-----------------------------------------------------------------------------
+db 00111111b ; DOS/32A misc. bits:
+ ; bit 0: 0=console output off, 1=on /1=def
+ ; bit 1: 0=sound generation off, 1=on /1=def
+ ; bit 2: 0=restore INT table off, 1=on /1=def
+ ; bit 3: 0=report modified INTs off, 1=on /1=def
+ ; bit 4: 0=load 16 in lowmem off, 1=on /1=def
+ ; bit 5: 0=force load 16 low off, 1=on /1=def
+ ; bit 6: 0=cls on exception off, 1=on /0=def
+ ; bit 7: 0=null-ptr protect off, 1=on /0=def
+If EXEC_TYPE eq 0
+db 00001001b ; DOS/32A Pro second misc. bits
+Else
+db 10001001b ; DOS/32A Beta second misc. bits
+Endif
+ ; bit 0: 0=config by enironment off, 1=on /1=def
+ ; bit 1: 0=focus on this VM off, 1=on /0=def
+ ; bit 2: 0=align objects on PARA, 1=PAGE /0=def
+ ; bit 3: 0=show copyright off, 1=on /1=def
+ ; bit 4: 0=verbose mode off, 1=on /0=def
+ ; bit 5: reserved /0=def
+ ; bit 6: 0=lock configuration off, 1=on /*
+ ; bit 7: 0=Professional, 1=Beta /*
+dw 0200h ; DOS INT 21h buffer in low memory (in para) /8 KB
+dw 090Ch ; Internal Version of DOS/32A: db low,high
+dw 0000h ; Reserved (v7.0+)
+;-----------------------------------------------------------------------------
+include TEXT\oemtitle.asm
+_ID32 ends
+
+
+
+
+
+
+
+
+
+;=============================================================================
+_TEXT16 segment para public use16 'CODE2'
+ assume cs:_TEXT16, ds:_TEXT16
+ org 0
+
+@text16_beg label byte
+
+include TEXT\CLIENT\config.asm
+include TEXT\CLIENT\strings.asm
+include TEXT\CLIENT\misc.asm
+include TEXT\CLIENT\debug.asm
+include TEXT\CLIENT\int10h.asm
+include TEXT\CLIENT\int21h.asm
+include TEXT\CLIENT\int33h.asm
+include loader.asm
+include loadlc.asm
+include loadpe.asm
+
+
+ .8086
+ Align 4
+
+start: push cs ; DS = CS
+ pop ds
+ mov _seg_ds,ds ; save SEG regs
+ mov _seg_es,es
+ mov _seg_ss,ss
+ mov ax,es:[002Ch]
+ mov _seg_env,ax
+ sti
+ cld
+
+ call get_default_config ; configure using defaults
+ call get_environ_config ; configure using environment
+ call copyright ; show copyright message
+ mov ax,ss ; get end of program
+ mov si,es:[0002h] ; get free DOS memory (in para)
+ add ax,STACKSIZE+INTTABSIZE ; stacksize+inttable (in para)
+ mov _seg_buf,ax ; set base of INT 21h buffer segment
+ add ax,_lowmembuf ; +lowbuf (in para)
+ mov _membase,ax ; set base of memory for PMbuf
+ sub si,ax ; check if enough mem
+ jnc @@1
+@@err1: neg si
+ mov cl,6
+ shr si,cl ; convert para to KB
+ mov ax,1001h
+ jmp report_error
+@@err2: mov ax,1002h
+ jmp report_error
+
+@@1: sub ax,_seg_es ; (SS+STK+INT+DOS)-ES *NOTE*: no BUF
+ mov bx,ax ; resize DOS memory
+ mov ah,4Ah
+ int 21h
+ jc @@err2
+ call far ptr pm32_info ; prepare and check for errors
+ jnc @@2 ; if error had occured, AX=error code
+ jmp report_error ; exit with error message
+;
+; No errors had occured, initialize kernel
+;
+ .386p
+@@2: mov wptr _buf_size,bx
+ mov wptr _cpu_type,cx
+
+ call remove_kernel
+
+ mov ax,_membase ; do second check for available memory
+ mov si,es:[0002h] ; (not really needed)
+ add ax,bx ; AX=base of free mem after PMbuf
+ sub si,ax
+ jc @@err1
+ add bx,_membase ; resize DOS memory
+ sub bx,_seg_es ; (SS+STK+INT+DOS+BUF)-ES
+ mov ah,4Ah
+ int 21h
+ jc @@err2
+ movzx eax,_seg_buf
+ mov edx,eax
+ sub ax,_seg_ds ; adjust for CS(sel):0000(offs)
+ shl edx,4
+ shl eax,4
+ mov _lobufbase,eax ; set INT 21h buf base relative to CS:
+ mov _lobufzero,edx ; set INT 21h buf base relative to 0
+ movzx eax,_seg_ds
+ shl eax,4
+ mov _seg_ds_base,eax ; set 32bit base of CS and DS segment
+ movzx eax,_lowmembuf
+ shl eax,4
+ mov _lobufsize,eax ; set INT 21h buffer size in bytes
+ mov es,_membase
+ mov bx,_version
+ mov dx,offs critical_handler
+ call far ptr pm32_init ; enter Protected Mode
+ jc report_error
+
+ cli
+ mov _sel_cs,cs ; save PM selectors
+ mov _sel_ds,ds
+ mov _sel_es,es
+ mov _sel_ss,ss
+ mov _sel_esp,esp
+ mov ax,es:[002Ch]
+ mov _sel_env,ax
+ mov _process_id,si
+ push di ecx
+ call init_system ; setup PM interrupts/buffers
+ call save_inttab ; now we can safely save inttab
+ call verbose_showsys
+ pop ecx di
+ sti
+
+ call check_system ; check for, and issue any warnings
+ mov fs,_sel_ss ; FS: = selector of buffer (and stack)
+ mov gs,_sel_zero ; GS: = zero selector
+ call open_exec ; open executable file
+ call load_exec_header ; load exec header into memory
+ call check_command_line ; get command line info
+ cmp dx,0040h ; check if reloc-tab starts at 0040h
+ jnz @@6 ; if not, check command line for fname
+ mov edx,_exec_start ; get start of exec
+ test dx,dx ; check if application is bound
+ jnz load_bound_app ; if bound, load BOUND Application
+@@6: test si,si ; check if command line is not empty
+ jnz load_extrn_app ; if cmd != 0, load EXTRN Application
+ call close_exec ; display help message
+ mov ax,8001h
+ jmp report_error
+
+load_extrn_app:
+ call close_exec
+ call open_extrn_exec
+ call load_extrn_exec_header
+ call update_environment
+ call remove_name_from_cmd
+ mov edx,_exec_start
+
+load_bound_app:
+ mov _err_code,3002h ; "error in app file"
+ call seek_from_start ; move file ptr to 32bit application
+ mov ecx,4 ; load 4 bytes (app signature)
+ xor edx,edx ; offset is zero
+ call load_fs_block ; load
+ mov ax,fs:[0000h] ; get file signature
+ mov bx,fs:[0002h]
+ test bx,bx
+ jnz @@1
+ cmp ax,'EL' ; 'LE' type
+ jz load_le_app
+ cmp ax,'XL' ; 'LX' type
+ jz load_lx_app
+ cmp ax,'CL' ; 'LC' type (Linear Compressed)
+ jz load_lc_app
+ cmp ax,'EP' ; 'PE' type
+ jz load_pe_app
+@@1: call close_exec
+ mov ax,3004h ; "app exec format not supported"
+ jmp file_error
+
+
+;=============================================================================
+; Jump to loaded 32-bit code
+;
+enter_32bit_code:
+ test cs:_misc_byte2,00010000b
+ jz @@0
+
+ sti
+ mov al,'>' ; "press any key to continue..."
+ call printc
+ xor ax,ax ; wait for a keypress
+ int 16h
+ call printcr
+
+@@0: cli ; disable interrupts
+ cld
+ call install_nullptr_protect ; install Null-Ptr Protection
+ mov ss,_sel32_ss ; SS = app 32bit data sel
+ mov esp,_app_esp ; ESP = application stack
+
+ mov es,_sel_es ; ES = environment sel
+ mov fs,_sel_zero ; FS = 32bit zero sel
+ mov ds,_sel32_ss ; DS = app 32bit data sel
+ xor eax,eax ; clear registers
+ xor ebx,ebx
+ xor ecx,ecx
+ xor edx,edx
+ xor esi,esi
+ xor edi,edi
+ xor ebp,ebp
+ mov gs,ax
+
+ pushfd ; push flags
+ push dptr cs:_sel32_cs ; push 32bit destination selector
+ push dptr cs:_app_eip ; push 32bit destination offset
+ or bptr ss:[esp+9],2 ; enable interrupts
+ sti
+ iretd
+
+
+
+
+
+;=============================================================================
+init_system:
+ xor eax,eax ; reset temp variables to zero
+ mov _app_esp,eax
+ mov _app_num_objects,eax
+ mov _app_off_datapages,eax
+ call setup_selectors ; setup system selectors
+ call setup_dta_buffer ; allocate buffer for DTA and Mouse
+ call initialize_mouse ; initialize mouse
+
+ mov ax,0204h ; get default PM interrupt handlers
+ mov bl,10h
+ int 31h
+ mov wptr _int10_cs,cx
+ mov dptr _int10_ip,edx
+
+ mov bl,21h
+ int 31h
+ mov wptr _int21_cs,cx
+ mov dptr _int21_ip,edx
+
+ mov bl,23h
+ int 31h
+ mov wptr _int23_cs,cx
+ mov dptr _int23_ip,edx
+
+ mov bl,33h
+ int 31h
+ mov wptr _int33_cs,cx
+ mov dptr _int33_ip,edx
+
+ mov ax,0202h ; get default PM exception handlers
+ xor ebx,ebx
+@@0: int 31h
+ mov wptr _exc_tab[ebx*8+4],cx
+ mov dptr _exc_tab[ebx*8+0],edx
+ inc bl
+ cmp bl,15
+ jb @@0
+
+ call install_client_ints ; install client PM interrupts
+ jc dpmi_error
+
+ call win_focus_vm ; switch to full-screen under Windows
+
+ cmp _sys_type,3
+ jz @@done
+ cmp _process_id,0 ; do not reset PIT if we've been
+ jnz @@done ; spawned to avoid timing problems
+
+ call restore_pit
+
+@@done: ret
+
+
+;=============================================================================
+check_system:
+ test di,di ; if no prev. DOS/32A in system
+ jz @@1 ; then jump
+ cmp di,_version ; check DOS/32A versions
+ jz @@1 ; if the same then jump
+ mov ax,9006h ; "incompatible version of DOS/32A"
+ call report_error
+@@1: cmp _sys_type,3 ; if running under an external DPMI
+ jz @@2 ; then jump
+ test ecx,ecx ; if extended memory has been alloced
+ jnz @@2 ; then jump
+ mov ax,9001h ; "no ext mem has been allocated"
+ call report_error
+@@2: mov ax,0400h ; get DPMI info
+ int 31h
+ cmp dh,08h ; warn if PICs have been remapped
+ jnz @@3
+ cmp dl,70h
+ jz @@4
+@@3: movzx si,dh
+ movzx di,dl
+ mov ax,9002h ; "PICs have been relocated"
+ call report_error
+@@4: ret
+
+
+;=============================================================================
+remove_kernel:
+ cmp _sys_type,3
+ jnz @@done
+
+ cli
+ pop bp
+ push es
+ mov es,_seg_kernel
+ mov si,offs @text16_beg
+ mov cx,(offs @text16_end - @text16_beg) / 2
+ rep movsw
+ pop es
+ mov ax,dx
+ shr ax,4
+ mov dx,ss
+ sub dx,ax
+ mov ss,dx
+ mov dx,ds
+ sub dx,ax
+ mov ds,dx
+ sub _seg_ds,ax
+ sub _seg_ss,ax
+ sub _seg_buf,ax
+ sub _membase,ax
+ push dx
+ push bp
+ sti
+ retf
+@@done: ret
+
+
+
+
+
+;=============================================================================
+; DATA
+
+include TEXT\CLIENT\data.asm
+
+
+;=============================================================================
+; BETA test code
+
+If EXEC_TYPE eq 2
+include TEXT\testbeta.asm
+Endif
+
+ Align 16
+@text16_end label byte
+_TEXT16 ends
+
+
+
+;=============================================================================
+; STACK
+_STACK segment para stack use16 'STACK'
+ db STACKSIZE*16 dup(?)
+_STACK ends
+end start
diff -uNr a/dos32a/src/dos32a/kernel.asm b/dos32a/src/dos32a/kernel.asm
--- a/dos32a/src/dos32a/kernel.asm false
+++ b/dos32a/src/dos32a/kernel.asm 0b15f492012406be562ee802d7cb6ea411687333661e1adf3fc0e9a9d95a9e2a6dc967df30ff884a966e2ca66a8a4857d2981ceccae8d77949b3fa88c572c41e
@@ -0,0 +1,279 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+BUILDING_KERNEL = 1
+BUILDING_CLIENT = 0
+
+;*****************************************************************************
+; DOS/32 Advanced DOS Extender master Kernel file, includes kernel definitions
+; data structures, and files from .\TEXT\KERNEL\ implementing the kernel.
+;
+; Created on: Oct-30-1996
+;
+;*****************************************************************************
+
+ .386p
+ .387
+ LOCALS
+ NOJUMPS
+
+SELCODE = 08h ; KERNEL code selector
+SELDATA = 10h ; KERNEL data selector
+SELZERO = 18h ; ZERO data selector
+SELVCPITSS = 20h ; TSS selector for VCPI
+SELVCPICODE = 28h ; VCPI call code selector
+SELVCPICOD2 = 30h ; VCPI internal selector #2
+SELVCPICOD3 = 38h ; VCPI internal selector #3
+SELBIOSDATA = 40h ; BIOS DATA Area 40h selector
+SELCALLBACK = 48h ; Callback DS selector
+
+SYSSELECTORS = 10 ; number of system selectors in GDT
+
+INCLUDE TEXT\include.asm
+PUBLIC pm32_info
+PUBLIC pm32_init
+PUBLIC pm32_data
+PUBLIC @kernel_beg
+PUBLIC @kernel_end
+
+
+_KERNEL segment para public use16 'CODE1'
+ assume cs:_KERNEL, ds:_KERNEL
+;=============================================================================
+pm32_data label byte ; data area 12 bytes
+pm32_mode db -1 ; mode bits:
+ ; bit0: 0=test DPMI/VCPI, 1=VCPI/DPMI
+ ; bit1: 0=exception control off, 1=on
+ ; bit2: 0=VCPI smart alloc pages off, 1=on
+ ; bit3: 0=VCPI+XMS alloc sheme off, 1=on
+ ; bit4: 0=trap software INTs off, 1=on
+ ; bit5: 0=check ext blocks off, 1=on
+ ; bit6: 0=invalid limit check off, 1=on
+ ; bit7: reserved
+pm32_maxpages db -1 ; maximum number of VCPI page tables
+pm32_maxfpages db -1 ; max. of physical mem. map pages
+pm32_callbacks db -1 ; number of real mode callbacks
+pm32_selectors dw -1 ; max selectors under VCPI/XMS/raw
+pm32_rmstacks db -1 ; real mode stack nesting
+pm32_pmstacks db -1 ; protected mode stack nesting
+pm32_rmstacklen dw -1 ; real mode stack length, in para
+pm32_pmstacklen dw -1 ; protected mode stack length, in para
+pm32_maxextmem dd -1 ; maximum extended memory to allocate
+
+
+
+;=============================================================================
+; GLOBAL DATA:
+;=============================================================================
+
+;=============================================================================
+;*** MEMORY DATA ***
+mem_ptr equ @area1_dd+00h ;dd 0; pointer to next free mem block
+mem_free equ @area1_dd+04h ;dd 0; size of largest free mem block
+mem_top equ @area1_dd+08h ;dd 0
+mem_used equ @area1_dw+0Ch ;dw 0
+segmentbases equ @area1_dw+0Eh ;dw 16*2 dup(0); for function 0002h
+
+
+;=============================================================================
+;*** Interrupt Redirection DATA ***
+temp_int equ @area1_db+4Fh ;db 0
+irqset_rm equ @area1_dw+50h ;dw 0 ; installed Real Mode IRQ Vectors
+irqset_pm equ @area1_dw+52h ;dw 0 ; installed Prot. Mode IRQ Vectors
+irqtab_rm equ @area1_dd+56h ;dd 16 dup(0) ; 16 Real Mode IRQ Vectors
+irqtab_pm equ @area1_dd+96h ;dd 32 dup(0) ; 16 Prot. Mode IRQ Vectors
+exctab_pm equ @area1_dd+116h ;dd 32 dup(0) ; 16 Exception Vectors
+
+
+;=============================================================================
+;*** Misc. ***
+tempw0 equ @area1_dw+198h ;dw 0
+tempw1 equ @area1_dw+19Ah ;dw 0
+tempd1 equ @area1_dd+19Ch ;label dword
+tempw2 equ @area1_dw+19Ch ;dw 0
+tempw3 equ @area1_dw+19Eh ;dw 0
+
+oldcr0 equ @area1_dd+1A0h ;dd 0 ; preserved CR0
+oldint15h equ @area1_dd+1A4h ;dd 0 ; preserved INT 15h vector
+oldint1Bh equ @area1_dd+1A8h ;dd 0
+oldint1Ch equ @area1_dd+1ACh ;dd 0
+oldint21h equ @area1_dd+1B0h ;dd 0
+oldint23h equ @area1_dd+1B4h ;dd 0
+oldint24h equ @area1_dd+1B8h ;dd 0
+oldint2Fh equ @area1_dd+1BCh ;dd 0
+newint1Bh equ @area1_dd+1C0h ;dd 0
+newint1Ch equ @area1_dd+1C4h ;dd 0
+newint23h equ @area1_dd+1C8h ;dd 0
+newint24h equ @area1_dd+1CCh ;dd 0
+id32_mem_free equ @area1_dd+1D0h
+id32_mem_ptr equ @area1_dd+1D4h
+id32_mem_vcpi equ @area1_dd+1D8h
+id32_process_id equ @area1_dw+1DCh ; current process id when spawn
+id32_spawned_id equ @area1_db+1E0h ; spawn mode flag (1=spawned)
+id32_tsrmode_id equ @area1_db+1E2h ; TSR mode flag (1=TSR)
+pagetablebase equ @area1_dd+1E4h ;dd 0; base of page table area
+pagetabletop equ @area1_dd+1E8h ;dd 0; top of page table area
+pagetablefree equ @area1_dd+1ECh ;dd 0; base of available pagetab area
+phystablebase equ @area1_dd+1F0h ;dd 0
+phystabletop equ @area1_dd+1F4h ;dd 0
+
+;=============================================================================
+; *** Performance Counters ***
+_pc_base equ @area1_db+200h
+_pc_intrmtopm equ @area1_dd+200h ;dd 0; INT RM->PM switch counter
+_pc_intpmtorm equ @area1_dd+204h ;dd 0; INT PM->RM switch counter
+_pc_irqrmtopm equ @area1_dd+208h ;dd 0; IRQ RM->PM switch counter
+_pc_irqpmtorm equ @area1_dd+20Ch ;dd 0; IRQ PM->RM switch counter
+_pc_irqcbrmtopm equ @area1_dd+210h ;dd 0; IRQ Callback RM->PM counter
+_pc_irqcbpmtorm equ @area1_dd+214h ;dd 0; IRQ Callback PM->RM counter
+_pc_cbrmtopm equ @area1_dd+218h ;dd 0; Callback RM->PM counter
+_pc_cbpmtorm equ @area1_dd+21Ch ;dd 0; Callback PM->RM counter
+pmstacklen equ @area1_dd+220h ;dd 0; prot mode stack length in bytes
+pmstackbase equ @area1_dd+224h ;dd 0; bottom of prot mode stack area
+pmstacktop equ @area1_dd+228h ;dd 0; top of prot mode stack area
+pmstacktop2 equ @area1_dd+22Ch ;dd 0
+rmstacklen equ @area1_dw+230h ;dw 0; real mode stack size in para
+rmstackbase equ @area1_dw+232h ;dw 0; bottom of real mode stack area
+rmstacktop equ @area1_dw+234h ;dw 0; top of real mode stack area
+rmstacktop2 equ @area1_dw+236h ;dw 0
+rmstackesp equ @area1_dd+240h ;dd 0; for functions 0300h,0301h,0302h
+rmstackss equ @area1_dw+244h ;dw 0
+callbackbase equ @area1_dd+248h ;dd 0; base of real mode callbacks
+callbackseg equ @area1_dw+24Ch ;dw 0; segment of callbacks
+irqcallbackptr equ @area1_dw+250h ;dw 0; ptr to IRQ callback ESP buffer
+
+ evendata
+client_call dw 0,0 ; client's critical handler offset
+client_version dw 0 ; extender version
+kernel_code dw 0 ; kernel CS: segment
+cputype db 0 ; CPU type
+fputype db 0 ; FPU type
+pmodetype db 0 ; protected mode type
+pagetables db 0 ; number of page tables under VCPI
+picslave db 0 ; PIC slave base interrupt
+picmaster db 0 ; PIC master base interrupt
+__reserved_1 db 0 ; reserved
+A20_state db 0 ; old A20 gate state
+cpuidlvl dd 0 ; CPUID level
+
+ evendata
+codebase dd 0 ; _KERNEL linear address
+dpmiepmode dd 0 ; DPMI enter pmode addx
+
+selzero dw SELZERO ; for immediate segreg loading
+seldata dw SELDATA ; for immediate segreg loading
+selcallback dw SELCALLBACK ; for immediate segreg loading
+gdtseg dw 0 ; segment of GDT
+gdtlimit dw 0 ; GDT limit
+gdtbase dd 0 ; GDT base
+idtseg dw 0 ; segment of IDT
+idtlimit dw 7FFh ; IDT limit
+idtbase dd 0 ; IDT base
+rmidtlimit dw 3FFh ; real mode IDT limit
+rmidtbase dd 0 ; real mode IDT base
+rmtopmswrout dw offs v_rmtopmsw ; addx of real to protected routine
+pmtormswrout dd offs v_pmtormsw ; addx of protected to real routine
+
+
+;=============================================================================
+;*** XMS DATA ***
+ evendata
+xms_call dw 0,0 ; XMS driver offset, segment
+xms_data dd 0 ; XMS 3.0 available memory
+xms_handle dw 0 ; memory handle
+
+
+;=============================================================================
+;*** VCPI DATA ***
+ evendata ; VCPI structure, DO NOT MODIFY
+vcpi_cr3 dd 0 ; VCPI CR3 value for protected mode
+vcpi_gdtaddx dd offs gdtlimit ; linear addx of GDT limit and base
+vcpi_idtaddx dd offs idtlimit ; linear addx of IDT limit and base
+vcpi_selldt dw 0 ; LDT selector for protected mode
+vcpi_seltss dw SELVCPITSS ; TSS selector for protected mode
+vcpi_eip dd offs v_rmtopmswpm; destination EIP in protected mode
+vcpi_cs dw SELCODE ; destination CS in protected mode
+
+vcpi_calleip dd 0 ; VCPI protected mode call offset
+vcpi_callcs dw SELVCPICODE ; VCPI protected mode call selector
+vcpi_allocmem dw 0 ; VCPI number of allocated pages
+vcpistrucaddx dd offs vcpi_cr3 ; VCPI switch structure linear address
+vcpiswitchstack dd 0 ; VCPI temporary mode switch stack
+
+
+;=============================================================================
+;*** DPMI DATA ***
+ evendata
+int31h_cache label word
+ dw 0EEFFh ; last DPMI function #
+ dw int31h_EEFF ; last DPMI function target addr
+
+
+
+
+
+;=============================================================================
+; PROTECTED MODE INIT/EXIT CODE
+
+include TEXT\KERNEL\detect.asm
+include TEXT\KERNEL\init.asm
+include TEXT\KERNEL\exit.asm
+include TEXT\KERNEL\misc.asm
+
+
+;=============================================================================
+; PROTECTED MODE KERNEL CODE
+
+include TEXT\KERNEL\mode.asm
+include TEXT\KERNEL\intr.asm
+include TEXT\KERNEL\int31h.asm
+
+
+;=============================================================================
+; BETA test code
+
+If EXEC_TYPE eq 2
+include TEXT\testbeta.asm
+Endif
+
+ Align 16
+@kernel_end label byte
+
+_KERNEL ends
+end
diff -uNr a/dos32a/src/dos32a/loader.asm b/dos32a/src/dos32a/loader.asm
--- a/dos32a/src/dos32a/loader.asm false
+++ b/dos32a/src/dos32a/loader.asm 8da138308286a12155a21b6bdb313ced8d8daec83d7445340dee376cdc3baf18312072b818e0381dcac6a8d3f1b31c97881f720878e1aac2bd45f9e5278826d7
@@ -0,0 +1,670 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;*****************************************************************************
+; DOS/32A 32-bit application loader (LE/LX style file formats)
+;
+;*****************************************************************************
+
+PushState
+
+APP_MAXOBJECTS = 64
+
+
+.386p
+;=============================================================================
+load_le_app:
+ mov _app_type,0
+ jmp load_application
+
+load_lx_app:
+ mov _app_type,1
+ jmp load_application
+
+load_lc_app:
+ mov _app_type,2
+
+
+;=============================================================================
+load_application:
+ call load_header ; load 'LE'/'LX' exec header
+ call verbose_showloadhdr
+ mov ecx,1 ; start with Object #1
+@@1: call load_object ; load object
+ call create_selector ; allocate selector for loaded object
+ call verbose_showloadobj
+ push edx ; save Object Selector/Object Flags
+ push edi ; save Address of loaded Object
+ push esi ; save Page Table Index
+ push ebx ; save # Page Table Entries
+ inc cx ; increment Current_Object#
+ cmp cx,word ptr _app_num_objects
+ jbe @@1 ; loop until all objects are loaded
+ call preload_fixups ; preload fixup tables and records
+ mov ebp,esp ; base pointer to last loaded Object
+ mov ebx,_app_num_objects ; number of Objects
+ dec bx
+ shl bx,4
+ mov _app_tmp_addr1,ebx
+@@4: call relocate_object
+ sub bx,10h
+ jnc @@4
+ call unload_fixups ; free allocated memory for fixups
+ call close_exec ; close file
+ mov esp,_sel_esp
+ call verbose_showstartup
+ jmp enter_32bit_code
+
+
+
+;-----------------------------------------------------------------------------
+load_header:
+ mov ecx,0A8h ; load 'LE' header
+ mov edx,04h
+ mov _err_code,3002h ; "error in app file"
+ cmp _app_type,2
+ jz load_lc_header
+
+ call load_fs_block
+ mov edx,_exec_start
+
+ mov ax,fs:[0010h] ; get Module Flags
+ and ax,2000h ; check if not-loadable;/no-fixups
+ mov ax,3005h
+ jnz file_error
+ mov ax,fs:[0044h] ; get # Objects
+ mov cx,ax
+ cmp ax,APP_MAXOBJECTS
+ mov ax,4001h ; "too many objects"
+ ja file_error
+ mov _app_num_objects,ecx
+
+ mov eax,fs:[0040h] ; get Object Table Offset
+ add eax,edx
+ mov _app_off_objects,eax
+ mov eax,fs:[0048h] ; get Object PageTable Offset
+ add eax,edx
+ mov _app_off_objpagetab,eax
+ mov eax,fs:[0068h] ; get Fixup PageTable Offset
+ add eax,edx
+ mov _app_off_fixpagetab,eax
+ mov eax,fs:[006Ch] ; get Fixup Record Table Offset
+ add eax,edx
+ mov _app_off_fixrectab,eax
+ mov eax,fs:[0080h] ; get Data Pages Offset
+ add _app_off_datapages,eax
+
+ mov eax,fs:[0018h] ; get EIP Object #
+ mov _app_eip_object,eax
+ mov eax,fs:[0020h] ; get ESP Object #
+ mov _app_esp_object,eax
+ mov eax,fs:[001Ch] ; get EIP
+ mov _app_eip,eax
+ mov eax,fs:[0024h] ; get ESP
+ mov _app_esp,eax
+ mov eax,fs:[0030h] ; get Fixup Records Size
+ mov _app_siz_fixrecstab,eax
+ mov eax,fs:[002Ch] ; get Bytes on Last Page (LE-only)
+ mov _app_siz_lastpage,eax
+
+ mov eax,0FFFh
+ cmp _app_type,0
+ jz @@done
+ mov ax,1
+ mov cx,fs:[002Ch] ; get Page Offset Shift for LX-type
+ shl ax,cl ; max shift is 15 (8000h-1)
+ dec ax
+
+@@done: mov _app_off_pageshift,eax
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+load_object:
+ push ecx
+ cmp _app_type,2
+ jz load_lc_object
+
+ mov _err_code,3002h ; "error in app file"
+ mov edx,_app_off_objects
+ call seek_from_start ; move to object header
+ mov ecx,18h
+ xor edx,edx
+ call load_fs_block ; load object header
+ add _app_off_objects,eax
+
+ mov edx,_app_off_datapages ; get Data_Pages_Offset
+ call seek_from_start ; move to object data
+ mov eax,fs:[0000h] ; get Virtual_Size[Object]
+ mov ebx,fs:[0010h] ; get # Page Table Entries
+ mov ecx,fs:[0008h] ; get Flags[Object]
+ mov esi,fs:[000Ch] ; get Page Table Index
+
+ push ecx ; save Object Flags
+ call alloc_block ; allocate EAX memory block to EDI
+ mov ecx,eax ; ECX = bytes to read
+ mov ebp,eax ; EBP = preserve Virtual Size
+ mov edx,edi ; EDX = addres to read to
+ call fill_zero_pages ; fill allocated memory with zeroes
+
+ mov eax,ebx
+ test eax,eax ; check if # Page Table Entries = 0
+ jz @@5 ; if yes, skip loading
+ shl eax,12 ; convert # Page Table Entries to bytes
+ cmp eax,ecx ; check if # bytes >= bytes to load
+ jae @@1 ; if yes, jump
+ mov ecx,eax ; else adjust number of bytes to read
+
+@@1: mov ax,[esp+4] ; get Object #
+ cmp ax,word ptr _app_num_objects
+ jnz @@3
+ cmp _app_type,0
+ jnz @@2
+ lea ecx,[ebx-1] ; load LE-style Last Object (BSS)
+ shl ecx,12
+ add ecx,_app_siz_lastpage
+ jmp @@3
+@@2: mov ecx,ebx ; load LX-style Last Object (BSS)
+ shl ecx,12
+
+@@3: mov _err_code,3002h ; "error in app file"
+ call load_gs_block ; load object data
+ mov eax,ecx
+ mov edx,_app_off_pageshift
+ test eax,edx
+ jz @@4
+ mov ecx,edx
+ not edx
+ and eax,edx
+ lea eax,[eax+ecx+1]
+@@4: add _app_off_datapages,eax
+
+@@5: pop edx ; restore Object Flags
+@@done: pop ecx
+ ret
+
+
+
+
+;=============================================================================
+relocate_object:
+ xor eax,eax
+ cmp eax,[ebp+ebx+0] ; get # Page Table Entries[Object]
+ jnz @@0 ; if zero, done
+ ret
+@@0: cmp _app_type,0
+ jnz relocate_lx_object
+
+relocate_le_object:
+ mov ecx,[ebp+ebx+4] ; get Page Table Index
+ mov edx,_app_off_objpagetab ; get Object Page Table Offset in exec
+ lea edx,[ecx*4+edx-4]
+ mov _err_code,3002h ; "error in app file"
+ call seek_from_start ; *1) move file ptr
+@@1: push eax ; EAX = counter
+ mov ecx,4
+ xor edx,edx
+ mov _err_code,3002h ; "error in app file"
+ call load_fs_block ; load block
+ xor ecx,ecx ; get index into FixupPageTab
+ mov ch,fs:[0001h]
+ mov cl,fs:[0002h]
+ jcxz @@2
+ mov eax,_app_off_fixpagetab ; get Fixup Page Table Offset
+ lea eax,[ecx*4+eax-4]
+ mov esi,gs:[eax+00h] ; get offset of 1st fixup table
+ mov ecx,gs:[eax+04h] ; get offset of 2nd fixup table
+ sub ecx,esi ; calculate size of 1st tab
+ jz @@2 ; if 1st == 2nd, no fixups
+ add esi,_app_off_fixrectab ; get Fixup Record Table Offset
+ mov edi,[esp] ; get current page number
+ shl edi,12
+ add edi,[ebp+ebx+8] ; address of page target to fix in mem
+ add ecx,esi
+ call apply_fixups ; patch target with fixup data
+@@2: pop eax
+ inc ax
+ cmp ax,word ptr [ebp+ebx+0]
+ jb @@1
+ ret
+
+relocate_lx_object:
+ mov ecx,[ebp+ebx+4] ; get Page Table Index
+ mov edx,_app_off_fixpagetab ; get Fixup Page Table Offset
+ lea edx,[ecx*4+edx-4]
+@@1: push eax edx ; EAX = counter
+ mov esi,gs:[edx+00h] ; get offset of 1st fixup table
+ mov ecx,gs:[edx+04h] ; get offset of 2nd fixup table
+ sub ecx,esi ; calculate size of 1st tab
+ jz @@2 ; if 1st == 2nd, no fixups
+ add esi,_app_off_fixrectab ; get Fixup Record Table Offset
+ mov edi,[esp+4] ; get current page number
+ shl edi,12
+ add edi,[ebp+ebx+8] ; address of page target to fix in mem
+ add ecx,esi
+ call apply_fixups ; patch target with fixup data
+@@2: pop edx eax
+ add edx,4
+ inc ax
+ cmp ax,word ptr [ebp+ebx+0]
+ jb @@1
+ ret
+
+
+
+;=============================================================================
+apply_fixups:
+@@0: push ecx edi
+ mov _err_code,4005h ; "unrecognized fixup data"
+ mov cx,gs:[esi+0] ; get SRC/FLAGS
+ movsx edx,word ptr gs:[esi+2] ; get SRCOFF
+ movzx eax,word ptr gs:[esi+4] ; get OBJNUM
+ add edi,edx ; calculate dest addr to be fixed
+ test cx,0F20h ; SrcLists/Imports not supported
+ jnz file_errorm ; jump if one of these
+ test cx,4000h ; test if 16bit object number
+ jnz @@1 ; if yes, jump
+ mov ah,0
+ dec esi
+@@1: add esi,6
+ dec eax ; Object Number - 1
+ shl eax,4
+ mov edx,_app_tmp_addr1
+ sub edx,eax
+ jc file_errorm
+ mov _app_tmp_addr2,edx
+ mov edx,[ebp+edx+8] ; EDX = Destination Object Address
+ mov al,cl
+ and al,0Fh
+ cmp al,02h ; check if 16bit Selector
+ jz @@3 ; if yes, jump
+ cmp al,08h
+ ja file_errorm
+ mov eax,gs:[esi]
+ test cx,1000h ; check for Alias flag
+ jnz @@2 ; if not, jump
+ movzx eax,ax
+ sub esi,2
+@@2: add esi,4
+@@3: cmp cl,07h
+ jnz @@4
+ add eax,edx
+ mov gs:[edi+0],eax
+@@5: pop edi ecx
+ cmp esi,ecx
+ jb @@0
+ ret
+@@4: push si
+ mov si,cx
+ and si,0Fh
+ add si,si
+ mov _err_code,4006h ; "16bit fixup overflow"
+ call fix_tab[si]
+ pop si
+ jmp @@5
+
+;
+; EAX = Data
+; EDX = Address of Object
+; EDI = Address to Fixup
+; EBP:EBX = Ptr to Current Object Table
+;-----------------------------------------------------------------------------
+fix_byte:
+ mov gs:[edi+0],al
+ ret
+fix_16off:
+ mov gs:[edi+0],ax
+ ret
+fix_32off:
+ add eax,edx
+ mov gs:[edi+0],eax
+ ret
+fix_32selfrel:
+ add eax,edx
+ lea ecx,[edi+4]
+ sub eax,ecx
+ test word ptr [ebp+ebx+12],2000h
+ jnz @@1
+ lea ecx,[eax+8002h]
+ shr ecx,16
+ jnz file_errorm
+ mov gs:[edi+0],ax
+ ret
+@@1: mov gs:[edi+0],eax
+ ret
+fix_16sel:
+ call check_range
+ mov gs:[edi+0],dx
+ ret
+fix_1616ptr:
+ call check_range
+ mov gs:[edi+0],ax
+ mov gs:[edi+2],dx
+ ret
+fix_1632ptr:
+ add eax,edx
+ mov gs:[edi+0],eax
+ call check_range
+ mov gs:[edi+4],dx
+ ret
+fix_invalid:
+ mov ax,4005h ; "unrecognized fixup data"
+ jmp file_error
+
+check_range:
+ test word ptr [ebp+ebx+12],1000h ; check if 16:16 alias requird
+ jnz @@1 ; if yes, jump
+ test cl,10h
+ jnz @@1
+@@0: mov ecx,_app_tmp_addr2
+ mov dx,[ebp+ecx+14] ; get selector
+ ret
+@@1: test cl,10h
+ jz @@0
+ mov ecx,_app_tmp_addr2
+ mov dx,[ebp+ecx+14] ; get selector
+ test eax,0FFFF0000h ; check 64K range
+ jnz file_errorm
+ ret
+
+
+ evendata
+fix_tab label word
+ dw fix_byte ; 00h
+ dw fix_invalid ; 01h
+ dw fix_16sel ; 02h
+ dw fix_1616ptr ; 03h
+ dw fix_invalid ; 04h
+ dw fix_16off ; 05h
+ dw fix_1632ptr ; 06h
+ dw fix_32off ; 07h
+ dw fix_32selfrel ; 08h
+
+
+
+
+
+
+
+
+;-----------------------------------------------------------------------------
+; In: ECX = size
+; Out: EDI = address
+;
+fill_zero_pages:
+ push es dx eax ecx edi
+ push gs
+ pop es
+ mov dl,cl
+ shr ecx,2
+ xor eax,eax
+ rep stos dword ptr es:[edi]
+ mov cl,dl
+ and cl,3
+ rep stos byte ptr es:[edi]
+ pop edi ecx eax dx es
+ ret
+
+
+;-----------------------------------------------------------------------------
+; In: EAX = size
+; Out: EDI = address
+;
+alloc_block:
+ push dx
+ test eax,eax ; if size of Object is zero
+ jz @@null ; then report a warning 9005
+ mov dl,_misc_byte ; get misc byte
+ shr dx,4 ; get memory alloc bits in bit1,0
+ and dx,3 ; mask them
+ jz @@00 ; if 00b alloc scheme, jump
+ dec dx
+ jz @@01
+ dec dx
+ jz @@10
+ dec dx
+ jz @@11
+@@done: pop dx
+ ret
+@@null: push ax si
+ mov si,[esp+0Ch]
+ mov ax,9005h
+ call report_error
+ pop si ax dx
+ xor edi,edi
+ ret
+
+;
+; load 16bit/32bit -> low, then high, then error
+;---------------------------------------
+@@00: call alloc_dos_mem ; try to allocate DOS memory block
+ jnc @@done ; if allocated, jump
+ mov _err_code,4003h ; "not enough DPMI mem"
+ call alloc_dpmi_mem ; try to allocate DPMI memory block
+ jnc @@done ; if allocated, jump
+ jmp file_errorm ; if failed, error
+;
+; load 16bit -> low, then high, then error
+; load 32bit -> high only, then error
+;---------------------------------------
+@@01: test cx,2000h ; check if 32bit Object
+ jnz @@01_1 ; if yes, jump
+ mov _err_code,4002h ; "not enough DOS mem"
+ call alloc_dos_mem
+ jnc @@done ; if allocated, jump
+@@01_1: mov _err_code,4003h ; "not enough DPMI mem"
+ call alloc_dpmi_mem
+ jnc @@done ; if allocated, jump
+ jmp file_errorm ; if failed, error
+;
+; load 16bit/32bit low, then error
+;---------------------------------------
+@@10: mov _err_code,4002h ; "not enough DOS mem"
+ call alloc_dos_mem
+ jnc @@done
+ jmp file_errorm ; if failed, error
+;
+; load 16bit/32bit high, then error
+;---------------------------------------
+@@11: mov _err_code,4003h ; "not enough DPMI mem"
+ call alloc_dpmi_mem
+ jnc @@done
+ jmp file_errorm ; if failed, error
+
+
+
+
+;-----------------------------------------------------------------------------
+alloc_dos_mem:
+ push eax ebp ; EAX = size to allocate
+ add eax,0Fh ; align size on para
+ shr eax,4
+ test eax,0FFFF0000h ; check high word of EAX
+ stc
+ jnz @@done
+ sub esp,32h
+ mov ebp,esp
+ mov byte ptr [ebp+1Dh],48h ; DOS func: AH=48h
+ mov word ptr [ebp+10h],ax ; DOS BX=size
+ call int21h
+ movzx edi,word ptr [ebp+1Ch] ; get returned value in EAX
+ shl edi,4 ; NOTE: addres is relative to 0
+ bt word ptr [ebp+20h],0 ; check for errors
+ lea esp,[esp+32h]
+@@done: pop ebp eax
+ ret
+
+;-----------------------------------------------------------------------------
+alloc_dpmi_mem:
+ push esi ebx ecx edx eax
+ mov ebx,eax
+ mov ax,0FF91h ; allocate DPMI memory
+ int 21h
+ jc @@done
+ mov eax,ebx
+ xor edx,edx
+ test _misc_byte2,00000100b ; check if para or page alignment
+ jnz @@l1
+ test al,0Fh
+ jz @@1
+ jmp @@l2
+@@l1: test ax,0FFFh ; check if returned addr aligned
+ jz @@1 ; on PAGE boundary, if yes, jump
+@@l2: test _misc_byte2,00000100b
+ jnz @@l3
+ add ebx,0Fh
+ and bl,0F0h
+ jmp @@l4
+@@l3: add ebx,0FFFh
+ and bx,0F000h ; align linear addr on PAGE boundary
+@@l4: sub ebx,eax ; calculate difference
+ mov edx,ebx
+ add ebx,[esp]
+ mov ax,0FF93h ; resize DPMI memory block
+ int 21h
+ jc @@done
+@@1: lea edi,[ebx+edx] ; adjust linear address
+ test _misc_byte2,00000100b
+ jnz @@l5
+ test di,000Fh
+ jmp @@l6
+@@l5: test di,0FFFh
+@@l6: stc
+ jnz @@done
+ clc
+@@done: pop eax edx ecx ebx esi
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+create_selector:
+ push ebx ecx edx esi edi
+ mov ax,dx
+ mov ecx,ebp ; ECX = Virtual Size[Object]
+ mov dx,_acc_rights ; default: PAGE, USE32, DATA
+ test al,0004h ; check if object is executable
+ jz @@1 ; if not, jump
+ or dl,0008h ; set selector to Code
+@@1: test ax,2000h ; check if object is 32bit
+ jz @@2 ; if not, jump
+ xor edi,edi ; set base to Zero
+ or ecx,-1 ; set limit to 4Gb
+
+ test al,0004h ; check if code or data Object
+ mov ax,_sel32_cs ; AX = 32bit code selector
+ jnz @@0 ; if code, then jump
+ mov ax,_sel32_ss ; AX = 32bit data selector
+@@0: test ax,ax ; check if already allocated
+ jnz @@4 ; if yes, use this selector
+ jmp @@3
+
+@@2: and dx,0BFFFh ; set selector to 16bit
+@@3: call set_descriptor ; allocate selector
+ jc dpmi_error
+@@4: pop edi esi
+ mov [esp+2],ax ; store selector in high word of EDX
+ pop edx ecx ebx
+ mov _app_buf_allocsel[ecx*2],ax
+ mov _app_buf_allocbase[ecx*4],edi
+
+ cmp cx,word ptr _app_eip_object; is Current_Object# == EIP_Object#
+ jnz @@l1 ; if not, jump
+ mov _sel32_cs,ax
+ mov _unreloc_eip,edi
+ test dx,2000h ; check if Object is 32bit
+ jz @@l1 ; if not, leave _APP_EIP as is
+ add _app_eip,edi
+
+@@l1: cmp cx,word ptr _app_esp_object; is Current_Object# == ESP_Object#
+ jnz @@l2 ; if not, jump
+ mov _sel32_ss,ax
+ mov _unreloc_esp,edi
+ add _app_esp,edi ; adjust ESP
+@@l2: ret
+
+
+preload_fixups:
+ cmp _app_type,2
+ jz preload_lc_fixups
+
+ mov ebx,_app_siz_fixrecstab ; allocate memory for fixups
+ mov _app_load,0 ; default load fixups low
+ mov ax,0FF95h
+ int 21h
+ jnc @@1
+ mov _app_load,1 ; try load fixups hi
+ mov al,91h
+ int 21h
+ mov ax,4004h
+ jc file_error ; if not enough memory, error
+@@1: mov _app_buf_fixrecstab,esi
+
+ mov _err_code,3002h ; "error in app file"
+ mov edx,_app_off_fixpagetab ; move file ptr to fixups
+ call seek_from_start
+ mov edx,ebx
+ mov ecx,_app_siz_fixrecstab
+ call load_gs_block
+
+ mov eax,_app_off_fixrectab
+ mov ebx,_app_off_fixpagetab
+ sub eax,ebx
+ add eax,edx
+ mov _app_off_fixpagetab,edx
+ mov _app_off_fixrectab,eax
+ ret
+
+
+unload_fixups:
+ cmp _app_type,2
+ jz unload_lc_fixups
+
+ mov esi,_app_buf_fixrecstab
+ mov ax,0FF96h
+ cmp _app_load,0
+ jz @@1
+ mov al,92h
+@@1: int 21h
+ ret
+
+
+PopState
+
diff -uNr a/dos32a/src/dos32a/loadlc.asm b/dos32a/src/dos32a/loadlc.asm
--- a/dos32a/src/dos32a/loadlc.asm false
+++ b/dos32a/src/dos32a/loadlc.asm 3979a8df8c14218bd961e99f311e4449a00cc89ada60f8216334493104b91e43ac57eb46cc133b09964f9e2c9dc34af6b857f464cf1a8d8d6a42446d9f01faab
@@ -0,0 +1,283 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;*****************************************************************************
+; DOS/32A LC-style 32-bit (compressed) application loader
+;
+;*****************************************************************************
+
+;-----------------------------------------------------------------------------
+; LC Header Format
+;
+; 0000 DD "LC" \0\0
+; 0004 DB # of Objects
+; 0005 DB LC-flags
+; bit0..3: LC implementation version
+; bit4..7: reserved
+; 0006 DB EIP Object #
+; 0007 DB ESP Object #
+; 0008 DD EIP Offset
+; 000C DD ESP Offset
+; 0010 ... ...Object #1 Header follows...
+;
+;-----------------------------------------------------------------------------
+; Object Header Format
+;
+; 0000 DD Virtual Size (Uncompressed Size)
+; bit31: 0=encoded, 1=not encoded
+; 0004 DD Compressed Size
+; 0008 DW Object Flags
+; 000A DW Extended Object Flags
+; 000C DW Page Table Index
+; 000E DW # of Page Table Entries
+; 0010 ... ...Object Data follows...
+;
+;-----------------------------------------------------------------------------
+;
+; Fixups Header Format
+;
+; 0000 DD Uncompresed Size
+; bit31: 0=encoded, 1=not encoded
+; 0004 DD Compressed Size
+; 0008 DD Fixup Record Table Offset
+; 000C ... ...Fixup Page Table Data ...
+; 000C+[0008] ... ...Fixup Record Table Data ...
+;
+
+LC_SPECVER equ 04h
+
+;=============================================================================
+load_lc_header:
+ mov cl,0Ch ; load 'LC' header
+ call load_fs_block
+ xor eax,eax
+ mov al,fs:[0004h] ; get # Objects
+ mov _app_num_objects,eax
+ mov al,fs:[0006h] ; get EIP Object #
+ mov _app_eip_object,eax
+ mov al,fs:[0007h] ; get ESP Object #
+ mov _app_esp_object,eax
+ mov eax,fs:[0008h] ; get EIP
+ mov _app_eip,eax
+ mov eax,fs:[000Ch] ; get ESP
+ mov _app_esp,eax
+ mov al,fs:[0005h]
+ and al,0Fh
+ cmp al,LC_SPECVER ; check LC implementation version
+ mov ax,3006h ; "exec not supported"
+ jnz file_error
+ mov ax,4007h ; "not enough DOS Transfer Buffer"
+ cmp _lobufsize,2000h ; must be at least 8KB
+ jb file_error
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+load_lc_object:
+ mov ecx,10h
+ xor edx,edx
+ mov _err_code,3002h ; "error in app file"
+ call load_fs_block ; load object header
+ mov eax,fs:[0000h] ; get Virtual_Size[Object]
+ btr eax,31 ; check if encoded and clear bit "31"
+ setc _ic_byte ; if not encoded, set _ic_byte to "1"
+ push eax
+ call alloc_block ; allocate EAX memory block to EDI
+ mov ecx,eax ; ECX = bytes to read
+ mov edx,edi ; EDX = address to read to
+ call fill_zero_pages ; fill allocated memory with zeroes
+ mov _err_code,3002h ; "error in app file"
+ mov ebx,fs:[0004h] ; EBX = compressed data size
+ mov ecx,ebx
+ jecxz @@done ; skip null-size Objects
+ cmp _ic_byte,0
+ jnz @@1
+ mov ax,0FF91h
+ int 21h
+ mov ax,4003h ; "not enough extended memory"
+ jc file_error
+ mov _app_buf_fixrecstab,esi ; preserve memory block handle
+ mov edx,ebx
+ call decompress_data
+ mov ax,0FF92h
+ mov esi,_app_buf_fixrecstab
+ int 21h
+ jmp @@done
+@@1: call load_gs_block
+@@done: pop ebp ; get Virtual_Size[Object]
+ movzx ebx,word ptr fs:[000Eh] ; get # Page Table Entries
+ movzx edx,word ptr fs:[0008h] ; get Flags[Object]
+ movzx esi,word ptr fs:[000Ch] ; get Page Table Index
+ pop ecx
+ ret
+
+
+
+preload_lc_fixups:
+ mov ecx,0Ch
+ xor edx,edx
+ mov _err_code,3002h ; "error in app file"
+ call load_fs_block ; load LC Fixup Header
+ mov ax,0FF91h ; alloc memory for Decoded fixups
+ mov ebx,fs:[0000h]
+ btr ebx,31 ; check if encoded and clear bit "31"
+ setc _ic_byte ; if not encoded, set _ic_byte to "1"
+ mov ecx,ebx
+ inc ebx ; prevent error when EBX = 0
+ int 21h
+ mov ax,4003h
+ jc file_error
+ mov edx,ebx
+ mov edi,ebx
+ mov _app_buf_fixrecstab,esi
+ call fill_zero_pages ; fill allocated memory with zeroes
+ mov ebx,fs:[0004h]
+ mov ecx,ebx
+ cmp _ic_byte,0
+ jnz @@1
+ mov ax,0FF91h ; alloc memory for Encoded fixups
+ inc ebx ; prevent error when EBX = 0
+ int 21h
+ mov ax,4003h
+ jc file_error
+ mov edx,ebx
+ call decompress_data
+ mov ax,0FF92h
+ int 21h
+ jmp @@done
+@@1: call load_gs_block
+@@done: mov _app_off_fixpagetab,edi
+ add edi,fs:[0008h]
+ mov _app_off_fixrectab,edi
+ ret
+
+unload_lc_fixups:
+ mov ax,0FF92h
+ mov esi,_app_buf_fixrecstab
+ int 21h
+ ret
+
+
+
+;=============================================================================
+; EBX = source address
+; EDI = destination address
+; ECX = size of source
+;
+decompress_data:
+ call load_gs_block
+
+decompress:
+ pushad
+ mov _xc_byte,0
+ mov _srcaddr,ebx
+ mov _codesize,ecx
+ push edi
+ mov ecx,_lobufsize
+ mov esi,_lobufbase
+ mov edi,_lobufzero
+ call fill_zero_pages
+ pop edi
+ xor bx,bx
+ mov edx,0FEEh
+@@3: shr bx,1
+ and dx,0FFFh
+ test bh,01h
+ je @@6
+@@4: test bl,01h
+ je @@8
+ call getbyte
+ js @@5
+ mov [esi+edx],al
+ mov gs:[edi],al
+ inc dx
+ inc edi
+ jmp @@3
+@@5: mov _codesize,edi ; for INT 21h / AX=0FF8Dh function
+ popad
+ ret
+@@6: call getbyte
+ js @@5
+ or ah,-1
+ mov bx,ax
+ jmp @@4
+@@8: call getbyte
+ js @@5
+ mov cl,al
+ call getbyte
+ js @@5
+ mov ch,al
+ shr ch,4
+ and ax,0Fh
+ add al,02h
+ mov bp,ax
+ test ax,ax
+ jl @@3
+@@9: and cx,0FFFh
+ and dx,0FFFh
+ mov al,[esi+ecx]
+ mov [esi+edx],al
+ mov gs:[edi],al
+ inc cx
+ inc dx
+ inc edi
+ dec bp
+ jns @@9
+ jmp @@3
+
+
+;-----------------------------------------------------------------------------
+getbyte:mov eax,_srcaddr
+ mov al,gs:[eax]
+ xor al,_xc_byte
+ inc _srcaddr
+ mov _xc_byte,al
+ dec _codesize
+ ret
+
+
+
+
+;-----------------------------------------------------------------------------
+_ic_byte equ _int_number ;db 0
+_xc_byte equ _app_load ;db 0
+_srcaddr equ _app_tmp_addr1 ;dd 0
+_codesize equ _app_tmp_addr2 ;dd 0
+
diff -uNr a/dos32a/src/dos32a/loadpe.asm b/dos32a/src/dos32a/loadpe.asm
--- a/dos32a/src/dos32a/loadpe.asm false
+++ b/dos32a/src/dos32a/loadpe.asm bf2d8275ddac10274d45bd45de2ffb7afb22062c51c20f70d3952ad0f1338b7b4e1369938fd82914559d224d250f17f985fab9c8dacade68b95bcd5414b3cd50
@@ -0,0 +1,56 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.386p
+;=============================================================================
+load_pe_app:
+ mov _app_type,3
+;
+; Insert PE loader implementation here
+;
+ mov ax,3004h ; "exec format not supported"
+ jmp file_error
+
+
+
+PopState
+
diff -uNr a/dos32a/src/dos32a/text/client/config.asm b/dos32a/src/dos32a/text/client/config.asm
--- a/dos32a/src/dos32a/text/client/config.asm false
+++ b/dos32a/src/dos32a/text/client/config.asm ae2cc92c2e1991a17b7f819da9cf16349de6bd01a82553d4c5795f59810040e313bfaf7258445bbd66280ed7ea639dba599fc9d39f1e41b0a8688a0dc437072e
@@ -0,0 +1,433 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.8086
+;=============================================================================
+; Get default configuration from _ID32 segment (buried in the program)
+; and configure the both KERNEL and CLIENT
+;
+get_default_config:
+ push ds es
+ mov ax,_ID32
+ mov dx,_KERNEL
+ mov _seg_id32,ax
+ mov _seg_kernel,dx
+
+ push ax dx ; STUB/32C configuration code
+ mov ax,0FF87h
+ int 21h
+ cmp dx,'ID'
+ jnz @@1
+ cmp ax,'32'
+ jnz @@1
+ mov es,cs:_seg_id32
+ xor di,di
+ mov cx,12
+ rep movsw
+ mov ds,cs:_seg_ds
+ or _sys_misc,0001h ; indicate STUB/32C configuration
+@@1: pop dx ax
+
+ mov ds,ax
+ mov es,dx
+ xor si,si ; DS:SI=_ID32:0000
+ mov di,offs pm32_data ; ES:DI=_KERNEL:PM32_DATA
+ lodsw ; check for 'ID32' signature
+ cmp ax,'DI' ; if not present, skip confuguration
+ jnz @@err
+ lodsw
+ cmp ax,'23'
+ jnz @@err
+ mov cx,_ID32_SIZE
+ rep movsb ; copy default config to KERNEL
+ mov es,cs:_seg_ds
+If EXEC_TYPE eq 0
+ and wptr ds:[si],7FFFh
+Else
+ or wptr ds:[si],8800h
+Endif
+ lodsw ; get DOS/32A config byte
+ mov wptr es:_misc_byte,ax
+ lodsw ; get DOS buffer size
+ mov wptr es:_lowmembuf,ax
+ lodsw ; get version
+ mov wptr es:_version,ax
+ clc
+ jmp @@done
+@@err: stc
+@@done: pop es ds
+ ret
+
+
+ evendata
+@area2_db label byte
+@area2_dw label word
+@area2_dd label dword
+
+;=============================================================================
+; Get environment configuration from the environment segment (at PSP:002C)
+; and configure both KERNEL and DOS/32A
+;
+get_environ_config:
+ push ds es
+ jc @@done
+ test _misc_byte2,00000001b
+ jz @@done
+ mov es,_seg_env
+ xor di,di ; ES:DI=envirment
+ mov cx,-1 ; environment size, unlimited
+ xor ax,ax
+@@0: push cx
+ mov cx,7 ; CX =length of 'DOS32A=' string
+ mov si,offs dos_str ; DS:SI=offset of 'DOS32A=' string
+ repe cmpsb
+ pop cx
+ jz @@1 ; quit loop if found
+ repne scasb
+ cmp al,es:[di] ; check for end of environment
+ jnz @@0 ; loop until found or end of environ.
+ jmp @@done ; no string found, exit
+@@1: call skip_env_spaces ; skip any leading spaces
+ cmp bptr es:[di],0 ; if at the end of the line, exit
+ jz @@done ; (actually, just in case)
+ call get_env_word ; get word and configure
+ call skip_env_nonspaces ; skip anything else until space or 0
+ cmp bptr es:[di],0
+ jnz @@1
+@@done: pop es ds
+ ret
+
+get_env_word:
+ xor bx,bx ; BX=pointer to next argument in tab
+@@0: mov si,dfn_tab[bx] ; DS:SI=string offset
+ cmp si,-1 ; check if at end of arg. list
+ jz @@1 ; if yes, terminate search
+ mov cx,dfn_tab[bx+2] ; CX=get string length
+ push di
+ repe cmpsb ; compare strings
+ pop di
+ jz @@2 ; if equ, process argument
+ add bx,6 ; loop until done
+ jmp @@0
+@@1: ret
+@@2: add di,dfn_tab[bx+2] ; adjust env pointer by string length
+ jmp cs:dfn_tab[bx-2+6] ; goto appropriate argument handler
+
+skip_env_spaces:
+@@1: mov al,es:[di]
+ test al,al
+ jz @@3
+ cmp al,'/'
+ jz @@2
+ cmp al,20h
+ jnz @@3
+ inc di
+ jmp @@1
+@@2: inc di
+@@3: ret
+
+skip_env_nonspaces:
+@@1: mov al,es:[di]
+ test al,al
+ jz @@3
+ cmp al,'/'
+ jz @@2
+ cmp al,20h
+ jz @@3
+ inc di
+ jmp @@1
+@@2: inc di
+@@3: ret
+
+
+
+;=============================================================================
+; Get switch in AX: 0, 1, ON, OFF (CF=1 if not found)
+;
+get_env_swc:
+ cmp bptr es:[di],':' ; skip ':' if present
+ jne @@1
+ inc di
+@@1: xor ax,ax ; if '0', return(0)
+ cmp bptr es:[di],'0' ; check for '0'=OFF
+ jz @@x1
+ inc ax ; if '1', return(1)
+ cmp bptr es:[di],'1' ; check for '1'=ON
+ jz @@x1
+ cmp wptr es:[di],'NO' ; check for 'ON'
+ jz @@x2
+ dec ax
+ cmp wptr es:[di],'FO' ; check for 'OF'(F)
+ jnz @@x0
+ cmp bptr es:[di+2],'F' ; check for (OF)'F'
+ jz @@x3
+@@x0: stc
+ ret
+@@x3: inc di
+@@x2: inc di
+@@x1: inc di
+ test al,al
+ ret
+
+
+
+;=============================================================================
+; Get number in AX: 0<=N(dec)<=65535 (CF=1 if not found)
+;
+get_env_num:
+ cmp bptr es:[di],':' ; skip ':' if present
+ jne @@1
+ inc di
+@@1: xor ax,ax
+ xor bx,bx
+ mov cx,10
+ mov al,es:[di]
+ sub al,'0'
+ jb @@exit
+ cmp al,9
+ ja @@exit
+ xchg bx,ax
+ mul cx
+ xchg bx,ax
+ add bx,ax
+@@2: inc di
+ xor ax,ax
+ mov al,es:[di]
+ sub al,'0'
+ jb @@done
+ cmp al,9
+ ja @@done
+ xchg bx,ax
+ mul cx
+ xchg bx,ax
+ add bx,ax
+ jmp @@2
+@@done: mov ax,bx
+ clc
+ ret
+@@exit: stc
+ ret
+
+
+
+
+
+;=============================================================================
+; /QUIET
+;
+cfg_env_quiet:
+If EXEC_TYPE eq 0
+ and wptr _misc_byte,1111011111111100b
+Else
+ and wptr _misc_byte,1111111111111100b
+Endif
+ ret
+
+
+
+;=============================================================================
+; /PRINT:ON|OFF
+;
+cfg_env_print:
+ call get_env_swc
+ jc @@0
+ jz @@1
+ or wptr _misc_byte,0000100000000001b
+ ret
+@@1: and wptr _misc_byte,1111011111111110b
+@@0: ret
+
+
+
+;=============================================================================
+; SOUND:ON|OFF
+;
+cfg_env_sound:
+ call get_env_swc
+ jc @@0
+ jz @@1
+ or _misc_byte,00000010b
+ ret
+@@1: and _misc_byte,11111101b
+@@0: ret
+
+
+
+;=============================================================================
+; /EXTMEM:nnnn (KB)
+;
+cfg_env_extmem:
+ call get_env_num
+ jc @@0
+ push ds
+ mov ds,_seg_kernel
+ assume ds:_KERNEL
+ push ax
+ mov bx,1024 ; make AX (Kb)-> DX:AX (bytes)
+ mul bx ; DX:AX= bytes
+ mov wptr ds:[pm32_data+12],ax ; set ext mem requirements
+ mov wptr ds:[pm32_data+14],dx
+ pop ax
+ add ax,00FFFh
+ and ax,0F000h
+ xor dx,dx
+ mov bx,1000h ; BX=Page size in KB
+ div bx ; MEM KB / Page Size KB
+ test al,al
+ jnz @@1 ; must alloc at least one
+ inc al
+@@1: mov bptr ds:[pm32_data+1],al ; set max allowed pagetables
+ assume ds:_TEXT16
+ pop ds
+@@0: ret
+
+
+
+;=============================================================================
+; /DOSBUF:nnnn (KB)
+;
+cfg_env_dosbuf:
+ call get_env_num
+ cmp ax,1 ; 1KB < ax < 64KB
+ jb @@0
+ cmp ax,64
+ ja @@0
+ jnz @@2
+ mov ax,0FFFh
+ jmp @@1
+@@2: mov cl,6
+ shl ax,cl ; convert KB to para
+@@1: mov _lowmembuf,ax
+@@0: ret
+
+
+
+;=============================================================================
+; /DPMITST:ON|OFF
+;
+cfg_env_test:
+ call get_env_swc
+; jc @@0
+; push ds
+; mov ds,_seg_kernel
+; assume ds:_KERNEL
+; jz @@1
+; or bptr ds:pm32_data[0],00000001b
+; pop ds
+; ret
+;@@1: and bptr ds:pm32_data[0],11111110b
+; assume ds:_TEXT16
+; pop ds
+@@0: ret
+
+
+
+;=============================================================================
+; /RESTORE:ON|OFF
+;
+cfg_env_restore:
+ call get_env_swc
+ jc @@0
+ jz @@1
+ or _misc_byte,00000100b
+ ret
+@@1: and _misc_byte,11111011b
+@@0: ret
+
+
+
+;=============================================================================
+; /NULLP[:ON|OFF]
+;
+cfg_env_nullp:
+ call get_env_swc
+ jc @@0
+ jz @@1
+@@0: or _misc_byte,10000000b
+ ret
+@@1: and _misc_byte,01111111b
+ ret
+
+
+
+;=============================================================================
+; /VERBOSE[:ON:OFF]
+;
+cfg_env_verbose:
+ call get_env_swc
+ jc @@0
+ jz @@1
+@@0: or _misc_byte2,00010000b
+ ret
+@@1: and _misc_byte2,11101111b
+ ret
+
+
+
+;=============================================================================
+; /NOWARN:nnnn
+;
+cfg_env_nowarn:
+ call get_env_num
+ sub ax,9000
+ jb @@0
+ cmp al,6
+ ja @@0
+ add ax,ax
+ mov bx,ax
+ mov wptr errtab_90xx[bx],0
+ cmp bptr es:[di],','
+ jnz @@0
+ inc di
+ jmp cfg_env_nowarn
+@@0: ret
+
+
+
+;=============================================================================
+; /NOC
+;
+cfg_env_noc:
+ and bptr _misc_byte2,11110111b
+ ret
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/client/data.asm b/dos32a/src/dos32a/text/client/data.asm
--- a/dos32a/src/dos32a/text/client/data.asm false
+++ b/dos32a/src/dos32a/text/client/data.asm 0cbd28472bf26fceae6e938ab39c52fa4825d619f76fba4e7d1011e17aec2d5d152371d84e5cbdd127764348141b8179c77b22778b16760b83c5ffac1cd34cef
@@ -0,0 +1,397 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+
+; table string /len/subroutine
+;-----------------------------------------------
+ Align 2
+dfn_tab dw df1_str, 5, cfg_env_quiet
+ dw df2_str, 5, cfg_env_print
+ dw df3_str, 5, cfg_env_sound
+ dw df4_str, 6, cfg_env_extmem
+ dw df5_str, 6, cfg_env_dosbuf
+ dw df6_str, 7, cfg_env_test
+ dw df8_str, 7, cfg_env_restore
+ dw df9_str, 5, cfg_env_nullp
+ dw dfA_str, 7, cfg_env_verbose
+ dw dfB_str, 6, cfg_env_nowarn
+ dw dfC_str, 3, cfg_env_noc
+ dw -1
+
+
+; table errcode, errstatus, errtab
+;------------------------------------------
+ Align 2
+g_errtab db 00h, 0
+ dw errtab_00xx
+ db 10h, 0
+ dw errtab_10xx
+ db 20h, 0
+ dw errtab_20xx
+ db 30h, 0
+ dw errtab_30xx
+ db 40h, 0
+ dw errtab_40xx
+ db 60h, 2
+ dw errtab_60xx
+ db 80h, 0
+ dw errtab_80xx
+ db 90h, 1
+ dw errtab_90xx
+ dw -1
+
+h_errtab dw errmsg1, errmsg2, errmsg3
+
+errtab_00xx dw d_err0, d_err1, d_err2, d_err3, d_err4
+ dw d_err5, d_err6, d_err7
+errtab_10xx dw n_msg, m_err1, m_err2
+errtab_20xx dw e_err0, e_err1, e_err2
+errtab_30xx dw n_msg, a_err1, a_err2, a_err3, a_err4, a_err2, a_err4
+errtab_40xx dw n_msg, l_err1, l_err2, l_err3, l_err4, l_err5, l_err6, l_err7
+errtab_60xx dw r_msg80,n_msg, r_msg81,r_msg82,r_msg83,r_msg84
+errtab_80xx dw n_msg, x_err1, x_err2, x_err3
+errtab_90xx dw n_msg, w_msg1, w_msg2, w_msg3, w_msg4, w_msg5, w_msg6
+
+i_msg dw i_msg00, i_msg01, i_msg02, i_msg03
+ dw i_msg04, i_msg05, i_msg06, i_msg07
+ dw i_msg08, i_msg09, i_msg0A, i_msg0B
+ dw i_msg0C, i_msg0D, i_msg0E, n_msg
+
+
+
+
+
+
+;=============================================================================
+ Align 4
+_misc_byte db 3 ; DOS/32A misc. bits ; +00
+_misc_byte2 db 7 ; +01
+_version dw 0 ; version ; +02
+_cpu_type db 0 ; CPU type: 80x86 ; +04
+_sys_type db 0 ; system type: raw/XMS/VCPI/DPMI ; +05
+_sys_misc dw 0 ; system misc. bits ; +06
+_buf_size dw 0 ; protected mode buffer size ; +08
+
+; _sys_misc map:
+;----------------
+; bit 0: 0=no stub32c present, 1=program started from stub32c
+; bit 8: 0=no CTRL-C, 1=CTRL-C detected (run-time)
+
+
+_pic_mask dw 0 ; PIC mask
+_err_code dw 0
+_acc_rights dw 0
+_mus_size dd 0
+_mus_backoff dw 0
+_mus_backseg dw 0
+_mus_off dd 0
+_mus_sel dd 0
+_mus_data db 0,0
+
+_seg_ds dw 0 ; real mode segment storage
+_seg_es dw 0
+_seg_ss dw 0
+_seg_env dw 0
+_seg_buf dw 0
+_seg_dta dw 0
+_seg_mus dw 0
+_seg_id32 dw 0
+_seg_kernel dw 0
+
+_sel_cs dw 0 ; protected mode selector storage
+_sel_ds dw 0
+_sel_es dw 0
+_sel_esp dd 0
+_sel_ss dw 0
+_sel_zero dw 0 ; ZERO_32 Data selector
+_sel_env dw 0 ; default environment selector
+_process_id dw 0
+
+_sel32_cs dw 0,0 ; CODE_32 Code selector
+_sel32_ss dw 0,0 ; DATA_32 Data selector
+
+_membase dw 0 ; memory base after stk+int+buf
+_lowmembuf dw 0 ; size of DOS INT 21h buffer
+_lobufzero dd 0
+_lobufbase dd 0
+_lobufsize dd 0
+_seg_ds_base dd 0 ; 32bit base of DS (CS) segment
+_dta_sel dw 0
+_dta_off dd 0
+_app_dta_sel dw 0
+_app_dta_off dd 0
+
+;-----------------------------------------------------------------------------
+_int10_ip dd 0 ; default INT 10h handler
+_int10_cs dd 0
+_int21_ip dd 0 ; default INT 21h handler
+_int21_cs dd 0
+_int23_ip dd 0 ; default INT 23h handler
+_int23_cs dd 0
+_int33_ip dd 0 ; default INT 33h handler
+_int33_cs dd 0
+_exc_tab dd 16 * 2 dup(0)
+
+
+;-----------------------------------------------------------------------------
+_exec_handle equ @area1_dw+00h ;dw 0
+_exec_start equ @area1_dd+04h ;dd 0
+_app_tmp_addr1 equ @area1_dd+08h ;dd 0
+_app_tmp_addr2 equ @area1_dd+0Ch ;dd 0
+
+_app_num_objects equ @area1_dd+10h ;dd 0
+_app_off_objects equ @area1_dd+14h ;dd 0
+
+_app_off_objpagetab equ @area1_dd+18h ;dd 0
+_app_off_fixpagetab equ @area1_dd+1Ch ;dd 0
+_app_off_fixrectab equ @area1_dd+20h ;dd 0
+_app_off_datapages equ @area1_dd+24h ;dd 0
+_app_off_pageshift equ @area1_dd+28h ;dd 0
+
+_app_eip_object equ @area1_dd+2Ch ;dd 0
+_app_esp_object equ @area1_dd+30h ;dd 0
+_app_eip equ @area1_dd+34h ;dd 0
+_app_esp equ @area1_dd+38h ;dd 0
+_unreloc_eip equ @area1_dd+3Ch ;dd 0
+_unreloc_esp equ @area1_dd+40h ;dd 0
+_app_siz_fixrecstab equ @area1_dd+44h ;dd 0
+_app_buf_fixrecstab equ @area1_dd+48h ;dd 0
+_app_siz_lastpage equ @area1_dd+4Ch ;dd 0
+
+_int_number equ @area1_db+50h ;db 0,0
+_int_temp equ @area1_dw+52h ;dw 0
+_int_errcode equ @area1_dd+54h ;dd 0
+_int_esp equ @area1_dd+58h ;dd 0
+_int_ss equ @area1_dd+5Ch ;dw 0
+_int_erravail equ @area1_db+5Eh ;db 0
+
+_app_type equ @area1_db+60h ;db 0
+_app_load equ @area1_db+61h ;db 0
+
+_mus_esp equ @area1_dd+64h ;dd 0
+_mus_ss equ @area1_dw+68h ;dw 0
+
+; machine state
+ms_reg_cr0 equ @area1_dd+ 80h ;dd 0
+ms_reg_cr2 equ @area1_dd+ 84h ;dd 0
+ms_reg_cr3 equ @area1_dd+ 88h ;dd 0
+ms_reg_dr6 equ @area1_dd+ 8Ch ;dd 0
+ms_eflags equ @area1_dd+ 90h ;dd 0
+ms_ec equ @area1_dd+ 94h ;dd 0
+ms_frame_esp equ @area1_dd+0A0h ;dd 0 ; exception handler's stack frame: ESP
+ms_frame_ss equ @area1_dw+0A4h ;dw 0 ; exception handler's stack frame: SS
+ms_reg_ds equ @area1_dw+0A8h ;dw 0
+ms_int equ @area1_dw+0ACh ;dw 0 ; INT #
+
+_app_buf_allocsel equ @area2_dw+00h ;dw 0
+_app_buf_allocbase equ @area2_dd+APP_MAXOBJECTS*2 ;dd APP_MAXOBJECTS*2 dup(00h)
+
+
+;-----------------------------------------------------------------------------
+n_msg db 0
+cpr_msg db 'DOS/32A -- DOS Extender '
+If EXEC_TYPE eq 2
+ db 'BETA '
+EndIf
+ db 'version '
+ver_msg db 'x.x.x',cr
+ db 'Copyright (C) 1996-2006 by Narech K.',cr
+cpr_end label byte
+
+errmsg1 db 'DOS/32A fatal (%w): ',0
+errmsg2 db 'DOS/32A warning (%w): ',0
+errmsg3 db 'DOS/32A run-time (%w): ',0
+
+;-----------------------------------------------------------------------------
+dos_str db 'DOS32A='
+df1_str db 'QUIET' ; print =OFF, sound =OFF --
+df2_str db 'PRINT' ; print (off=only errors reported) on/off
+df3_str db 'SOUND' ; sound on error on/off
+df4_str db 'EXTMEM' ; max Extended memory to alloc (KB)
+df5_str db 'DOSBUF' ; lowmembuf, DOS INT 21h buffer (KB)
+df6_str db 'DPMITST' ; test DPMI/VCPI or VCPI/DPMI on/off
+df8_str db 'RESTORE' ; restore int vector table on exit on/off
+df9_str db 'NULLP' ; install Null-Pointer protection on/off
+dfA_str db 'VERBOSE' ; use verbose mode on/off
+dfB_str db 'NOWARN' ; disable particular warning (NUM)
+dfC_str db 'NOC' ; disable copyright banner --
+
+ Align 4
+@area1_db label byte
+@area1_dw label word
+@area1_dd label dword
+
+
+; INIT errors 00xx
+;=============================================================================
+d_err0 db 'this program requires DOS 4.0 or higher' ,0
+d_err1 db '80386 processor or better required to run protected mode' ,0
+d_err2 db 'system software does not follow VCPI/DPMI specifications' ,0
+d_err3 db 'present DPMI host does not support 32bit applications' ,0
+d_err4 db 'incompatible VCPI PIC mappings' ,0
+d_err5 db 'could not enter 32bit protected mode' ,0
+d_err6 db 'could not allocate system selectors' ,0
+d_err7 db 'could not enable A20 line' ,0
+
+
+; MEMORY errors 10xx
+;=============================================================================
+m_err1 db 'not enough DOS memory, additional %dKB needed' ,0
+m_err2 db 'DOS reported insufficient memory' ,0
+
+
+; EXEC errors 20xx
+;=============================================================================
+e_err0 db 'invalid environment' ,0
+e_err1 db 'could not open exec file "%s"' ,0
+e_err2 db 'error in exec file "%s"' ,0
+
+
+; APPLICATION errors 30xx
+;=============================================================================
+a_err1 db 'could not open application file "%s"' ,0
+a_err2 db 'error in application file "%s"' ,0
+a_err3 db 'file "%s" does not contain any valid exec format' ,0
+a_err4 db 'exec format not supported in file "%s"' ,0
+
+
+; LOADER errors 40xx
+;=============================================================================
+l_err1 db 'too many objects in application exec "%s"' ,0
+l_err2 db 'not enough DOS memory to load application exec "%s"' ,0
+l_err3 db 'not enough extended memory to load application exec "%s"' ,0
+l_err4 db 'not enough extended memory to load fixups for exec "%s"' ,0
+l_err5 db 'unrecognized fixup data in application exec "%s"' ,0
+l_err6 db '16bit fixup overflow in application exec "%s"' ,0
+l_err7 db 'not enough DOS Transfer Buffer space to load LC-exec "%s"' ,0
+
+
+; MISC. errors 80xx
+;=============================================================================
+x_err1 db 'syntax is DOS32A ' ,0
+x_err2 db 'DOS reported an error (#%wh)' ,0
+x_err3 db 'DPMI host reported an error (#%wh)' ,0
+
+
+; WARNINGS 90xx
+;=============================================================================
+w_msg1 db 'no extended memory has been allocated' ,0
+w_msg2 db 'PICs have been relocated to INT %bh, INT %bh' ,0
+w_msg3 db 'real mode interrupt vector has been modified: INT %bh' ,0
+w_msg4 db 'mouse initialization failed' ,0
+w_msg5 db 'object #%d contains no data or code' ,0
+w_msg6 db 'incompatible version of DOS/32A already running' ,0
+
+
+; RUN-TIME errors 60xx
+;=============================================================================
+r_msg80 db 'unknown error code (#%bh)' ,0
+r_msg81 db 'out of real-mode virtual stacks' ,0
+r_msg82 db 'out of protected-mode virtual stacks' ,0
+r_msg83 db 'extended memory blocks have been corrupted (#%l)' ,0
+r_msg84 db 'DOS/4G API calls not supported' ,0
+
+
+
+; Verbose messages
+;=============================================================================
+v_msg01 db 'Processor: %d, System: %s, Memory: DOS=%dKB, DPMI=%d%s',cre
+v_msg02 db 'NONE',0, 'XMS',0,0, 'VCPI',0, 'DPMI',0
+v_msg03 db 'LE',0,'LX',0,'LC',0,'PE',0
+v_msg04 db 'KB',0
+v_msg05 db 'MB',0
+v_msg10 db 'Loading program "%s", %s-style',cre
+v_msg11 db 'Object #%d loaded at %l, V/Psize: %l/%l, Flags=%w, Sel=%w',cre
+v_msg12 db 'Startup CS:EIP=%w:%l, SS:ESP=%w:%l, %s EIP=%d:%l',cr
+ db 'Memory left: DOS=%dKB, DPMI=%d%s. PSP_Sel=%w, Env_Sel=%w, Env_Seg=%w',cre
+
+
+;=============================================================================
+excmsgE db 'exception',0
+excmsgI db 'unexpected interrupt',0
+excmsg1 db '%s %bh',cr
+ db 'Identity: %s at %w:%l',cre
+excmsg2 db '%s crash address %d:%l',0
+excmsg4 db ', error code pushed on stack %l',0
+
+excmsgA db 'Linear',0
+excmsgB db 'Unrelocated',0
+excmsgC db 'Module name: "%s", ProcessId=%w',cre
+
+nulmsg0 db 'Null-pointer protection at %w:%l',cre
+
+dbgmsg1 db 'EFLAGS = %l [%l.%l] ',0
+dbgmsg2 db 'CS:[EIP] = %b %b %b %b %b %b %b %b %b %b',0
+dbgmsg4 db 'EAX = %l ESI = %l DR6 = %l SS:[ESP+00] = %l',cre
+dbgmsg5 db 'EBX = %l EDI = %l CR0 = %l SS:[ESP+04] = %l',cre
+dbgmsg6 db 'ECX = %l EBP = %l CR2 = %l SS:[ESP+08] = %l',cre
+dbgmsg7 db 'EDX = %l ESP = %l CR3 = %l SS:[ESP+0C] = %l',cre
+dbgmsgA db 'Invalid selector',0
+dbgmsgB db 'NULL selector',0
+
+selmsg1 db 'CS: = %w ',0
+selmsg2 db 'DS: = %w ',0
+selmsg3 db 'ES: = %w ',0
+selmsg4 db 'SS: = %w ',0
+selmsg5 db 'FS: = %w ',0
+selmsg6 db 'GS: = %w ',0
+selmsg0 db 'Base=%l Limit=%l Gr=%s Seg=%s/%dbit Type=%d Acc=%w',cre
+selmsg9 db 'BYTE',0,'PAGE',0
+selmsg8 db 'DATA',0,'CODE',0
+selmsgX db 'KERNEL=',0
+selmsgY db 'CLIENT=',0
+selmsgZ db 'APP/32=',0
+selmsgW db 'APP/??=',0
+
+i_msg00 db 'integer division by zero' ,0
+i_msg01 db 'hardware breakpoint' ,0
+i_msg02 db 'NMI' ,0
+i_msg03 db 'software breakpoint' ,0
+i_msg04 db 'overflow check fault' ,0
+i_msg05 db 'bounds check fault' ,0
+i_msg06 db 'invalid opcode fault' ,0
+i_msg07 db 'coprocessor not available' ,0
+i_msg08 db 'double fault' ,0
+i_msg09 db 'coprocessor segment overrun' ,0
+i_msg0A db 'invalid TSS fault' ,0
+i_msg0B db 'segment not present fault' ,0
+i_msg0C db 'stack fault' ,0
+i_msg0D db 'general protection fault' ,0
+i_msg0E db 'page fault' ,0
+
diff -uNr a/dos32a/src/dos32a/text/client/debug.asm b/dos32a/src/dos32a/text/client/debug.asm
--- a/dos32a/src/dos32a/text/client/debug.asm false
+++ b/dos32a/src/dos32a/text/client/debug.asm 30b81317062b8362a8ea90927449f26088a98fb429ee5a931e0677e6a96d0fb4fe2489497d072015295a03b66cc78594fd1a98d197f00ee1c17b3757b58b4453
@@ -0,0 +1,767 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.386p
+;=============================================================================
+; IN: AL = interrupt number (if applicable)
+; AH = kernel error code:
+;
+; 81h = unhandled interrupt/exception
+; 82h = out of real-mode virtual stacks
+; 83h = out of protected-mode virtual stacks
+; 84h = extended memory blocks have been corrupted
+; 85h = DOS/4G API calls not supported
+;
+;=============================================================================
+critical_handler:
+ cli ; immediately disable interrupts
+ cld ; clear direction flag
+ mov ds,cs:_sel_ds ; restore client DS
+ lss esp,fptr _sel_esp ; restore client SS:ESP
+
+ push ax ; push error code
+ mov al,20h ; send EOI codes to PICs
+ out 0A0h,al
+ out 020h,al
+
+ mov ax,_pic_mask ; restore PIC masks
+ out 0A1h,al
+ mov al,ah
+ out 021h,al
+
+ call restore_pit
+ call restore_inttab
+ call tone
+ call scr_on
+ pop dx ; DH = code, DL = int number
+
+ mov ax,6001h ; error 6001: "unexpected interrupt"
+ cmp dh,81h
+ jz @@arg_dl
+
+ mov al,02h ; error 6002: "out of real-mode virtual stacks"
+ cmp dh,82h
+ jz @@report
+
+ mov al,03h ; error 6003: "out of protected-mode virtual stacks"
+ cmp dh,83h
+ jz @@report
+
+ mov al,04h ; error 6004: "extended memory blocks have been corrupted"
+ cmp dh,84h
+ jz @@arg_esi
+
+ mov al,05h ; error 6005: "DOS/4G API calls not supported"
+ cmp dh,85h
+ jz @@report
+
+ mov al,00h ; error 6000: "unknown error code"
+
+@@arg_dl:
+ movzx si,dl ; load SI with DL
+ jmp @@report
+
+@@arg_esi:
+ rol esi,16 ; convert ESI to DI:SI
+ mov di,si
+ shr esi,16
+
+@@report:
+ call report_error
+ mov al,0FFh ; exit with error code 0FFh
+ jmp exit386
+
+
+
+
+;=============================================================================
+eh00: push 00h
+ jmp eh_common
+eh01: push 01h
+ jmp eh_debug
+eh02: push 02h
+ jmp eh_common
+eh03: push 03h
+ jmp eh_debug
+eh04: push 04h
+ jmp eh_common
+eh05: push 05h
+ jmp eh_common
+eh06: push 06h
+ jmp eh_common
+eh07: push 07h
+ jmp eh_common
+eh08: push 08h
+ jmp eh_common
+eh09: push 09h
+ jmp eh_common
+eh0A: push 0Ah
+ jmp eh_common
+eh0B: push 0Bh
+ jmp eh_common
+eh0C: push 0Ch
+ jmp eh_common
+eh0D: push 0Dh
+ jmp eh_common
+eh0E: push 0Eh
+ jmp eh_common
+
+
+;=============================================================================
+; Machine state at the point of exception:
+;
+;
+; Stack Frame relative to ms_frame_ ss:esp
+;
+; 00:SS +1Ch
+; ESP +18h
+; EFL +14h
+; 00:CS +10h
+; EIP +0Ch
+; ec +08h
+; Ret: 00:CS +04h
+; Ret: EIP +00h
+;
+;--------------------
+; Stack Frame relative to ss:esp at the point of eh_reporter
+;
+; DS +26h
+; ES +24h
+; FS +22h
+; GS +20h
+; EAX +1Ch
+; ECX +18h
+; EDX +14h
+; EBX +10h
+; ESP +0Ch
+; EBP +08h
+; ESI +04h
+; EDI +00h
+;
+eh_debug:
+ cmp cs:_sys_type,3
+ jz @@0
+
+ push eax
+ mov eax,dr6 ; check if breakpoint on one of DRs
+ and al,0Fh
+ pop eax
+ jnz eh_common ; if yes, jump
+
+@@0: add esp,2 ; pop INT #
+ and bptr [esp+15h],0FEh ; reset trap flag
+ db 66h ; do 32bit far ret
+ retf
+
+
+;=============================================================================
+;eh_debug_continue:
+; popad
+; pop gs fs es ds
+; lss esp,fptr cs:ms_frame_esp ; restore app's SS:ESP
+; and bptr [esp+15h],0FEh ; reset trap flag
+; db 66h ; do 32bit far ret
+; retf
+
+;=============================================================================
+;eh_debug_trap:
+; popad
+; pop gs fs es ds
+; lss esp,fptr cs:ms_frame_esp ; restore app's SS:ESP
+; or bptr [esp+15h],01h ; set trap flag
+; db 66h ; do 32bit far ret
+; retf
+
+
+;=============================================================================
+eh_common:
+ cli
+ cld
+
+ push ax ; save AX
+ mov ax,ds ; AX = app's DS
+ mov ds,cs:_sel_ds ; load DS with client's data selector
+ mov ms_reg_ds,ax ; machine state: save DS
+ pop ax ; restore AX
+
+ pop ms_int ; machine state: save INT #
+
+ mov ms_frame_ss,ss ; machine state: save eh frame SS
+ mov ms_frame_esp,esp ; machine state: save eh frame ESP
+
+ lss esp,fptr _sel_esp ; switch to internal stack
+
+ push ms_reg_ds
+ push es
+ push fs
+ push gs
+ pushad
+
+ mov es,ms_frame_ss
+ mov ebp,ms_frame_esp
+
+ mov eax,es:[ebp+08h]
+ mov ms_ec,eax ; machine state: save error code
+ mov eax,es:[ebp+14h]
+ mov ms_eflags,eax ; machine state: save EFLAGS
+;
+; make FS:ESI = app's CS:EIP
+; make GS:EDI = app's SS:ESP
+;
+ mov ax,es:[ebp+10h] ; load app CS
+ call check_selector ; validate app's CS
+ mov fs,ax ; FS = app CS
+
+ mov ax,es:[ebp+1Ch] ; load app SS
+ call check_selector ; validate app's SS
+ mov gs,ax ; GS = app SS
+
+ mov esi,es:[ebp+0Ch] ; load app EIP
+ mov edi,es:[ebp+18h] ; load app ESP
+;
+; copy CRx regs
+;
+ xor eax,eax
+ mov ms_reg_cr0,eax ; machine state: reset CR0
+ mov ms_reg_cr2,eax ; machine state: reset CR2
+ mov ms_reg_cr3,eax ; machine state: reset CR3
+ mov ms_reg_dr6,eax ; machine state: reset DR6
+
+ cmp _sys_type,3
+ jz @@1
+ mov eax,cr0
+ mov ms_reg_cr0,eax ; machine state: save CR0
+ mov eax,cr2
+ mov ms_reg_cr2,eax ; machine state: save CR2
+ mov eax,cr3
+ mov ms_reg_cr3,eax ; machine state: save CR3
+ mov eax,dr6
+ mov ms_reg_dr6,eax ; machine state: save DR6
+
+@@1: mov ebp,esp
+
+ mov al,20h ; send EOI to PICs
+ out 0A0h,al
+ out 020h,al
+
+ mov ax,_pic_mask ; restore PIC masks
+ out 0A1h,al
+ mov al,ah
+ out 021h,al
+
+eh_reporter:
+ call restore_pit
+ call restore_inttab
+ call tone
+ call scr_on
+
+ call dump_description
+ call dump_description2
+
+ push _process_id
+ push offs start
+ mov dx,offs excmsgC
+ call prints
+ add sp,4
+
+ call dump_origin ; dump origin of exception
+ call dump_eflags ; dump EFLAGS
+ call dump_opcodes ; dump op-codes @ CS:EIP
+
+ call dump_regs ; dump regs, CRs, stack
+ call dump_selectors ; dump selectors
+
+ mov al,-1
+ jmp exit386
+
+
+
+
+
+;=============================================================================
+dump_description:
+ mov eax,ms_reg_dr6 ; check if this is a breakpoint on one of DRs
+ and al,0Fh
+ jz @@0 ; if not, jump
+
+ call check_faultsel ; check if CS is known code selector
+ push esi ; show EIP
+ push fs ; show CS
+ mov dx,offs nulmsg0 ; "Null-pointer protection..."
+ call prints
+ add sp,6
+ ret
+
+@@0: push 6001h ; manually push error code
+ mov dx,offs errmsg3 ; 'DOS/32A run-time:'
+ call prints
+ pop ax ; remove arg from stack
+
+ mov ebx,-2 ; FIXME: can crash
+ call loadl_cs_eip ; load 4 bytes at CS:[EIP-2]
+
+ mov bl,0CDh ; check for INT # opcode
+ mov bh,bptr ms_int
+ cmp ax,bx
+
+ mov cx,offs excmsgE ; "exception"
+ jnz @@1
+ mov cx,offs excmsgI ; "unexpected interrupt"
+
+@@1: mov ax,ms_int ; machine state: get INT #
+ mov bx,ax
+ add bx,bx
+
+ push esi ; show EIP
+ push fs ; show CS
+ push wptr i_msg[bx] ; int name
+ push ax ; int number
+ push cx ; "exception"
+ mov dx,offs excmsg1 ; main string
+ call prints
+ add sp,12
+
+ ret
+
+
+;=============================================================================
+dump_description2:
+ call check_faultsel ; check if CS is known code selector
+ push eax ; addr
+ push cx ; object #
+ mov ax,offs excmsgA ; "Linear"
+ jc @@1
+ mov ax,offs excmsgB ; "Unrelocated"
+@@1: push ax
+ mov dx,offs excmsg2 ; "...crash address..."
+ call prints
+ add sp,8
+
+ mov ax,ms_int
+ cmp al,08h ; if error code present, show it
+ jb @@3
+ cmp al,09h
+ je @@2
+ cmp al,0Eh
+ ja @@3
+
+@@2: push ms_ec ; display error code
+ mov dx,offs excmsg4
+ call prints
+ add sp,4
+
+@@3: call printcr
+
+ ret
+
+
+;=============================================================================
+; In: FS = app's CS
+;
+dump_origin:
+ mov al,'='
+ mov cx,72
+@@0: call printc
+ loop @@0
+
+ mov ax,fs
+ cmp ax,0008h ; note: kernel selector hardcoded!
+ mov dx,offs selmsgX ; exception came from "KERNEL"
+ jz @@1
+ cmp ax,_sel_cs
+ mov dx,offs selmsgY ; exception came from "CLIENT"
+ jz @@1
+ cmp ax,_sel32_cs
+ mov dx,offs selmsgZ ; exception came from "APP/32"
+ jz @@1
+ mov dx,offs selmsgW ; where do all they come from?
+@@1: call prints
+ jmp printcr
+
+
+;=============================================================================
+dump_eflags:
+ mov cl,8
+ mov ebx,ms_eflags
+ xor eax,eax
+ xor edx,edx
+@@0: shr bl,1
+ rcr eax,4
+ shr bh,1
+ rcr edx,4
+ loop @@0
+ push eax
+ push edx
+ push ms_eflags
+ mov dx,offs dbgmsg1
+ call prints
+ add sp,12
+ ret
+
+
+;=============================================================================
+; In: FS:ESI = app's CS:EIP
+;
+dump_opcodes:
+ mov cl,10
+ mov ebx,9
+@@0: call loadb_cs_eip
+ push ax
+ dec ebx
+ loop @@0
+ mov dx,offs dbgmsg2
+ call prints
+ add sp,10*2
+ jmp printcr
+
+
+;=============================================================================
+; In: SS:EBP = local stack frame
+; FS:ESI = app's CS:EIP
+; GS:EDI = app's SS:ESP
+;
+dump_regs:
+ xor ebx,ebx
+ call loadl_ss_esp
+ push eax ; STK[0]
+ push ms_reg_dr6 ; DR6
+ push dptr [ebp+04h] ; ESI
+ push dptr [ebp+1Ch] ; EAX
+ mov dx,offs dbgmsg4
+ call prints
+ add sp,16
+
+ add bx,4
+ call loadl_ss_esp
+ push eax ; STK[4]
+ push ms_reg_cr0 ; CR0
+ push dptr [ebp+00h] ; EDI
+ push dptr [ebp+10h] ; EBX
+ mov dx,offs dbgmsg5
+ call prints
+ add sp,16
+
+ add bx,4
+ call loadl_ss_esp
+ push eax ; STK[8]
+ push ms_reg_cr2 ; CR2
+ push dptr [ebp+08h] ; EBP
+ push dptr [ebp+18h] ; ECX
+ mov dx,offs dbgmsg6
+ call prints
+ add sp,16
+
+ add bx,4
+ call loadl_ss_esp
+ push eax ; STK[12]
+ push ms_reg_cr3 ; CR3
+ push edi ; ESP
+ push dptr [ebp+14h] ; EDX
+ mov dx,offs dbgmsg7
+ call prints
+ add sp,16
+
+ ret
+
+
+;=============================================================================
+; In: SS:EBP = local stack frame
+; FS:ESI = app's CS:EIP
+; GS:EDI = app's SS:ESP
+;
+dump_selectors:
+ mov dx,offs selmsg1
+ mov ax,fs ; CS selector
+ call describe_selector
+
+ mov dx,offs selmsg2
+ mov ax,[ebp+26h] ; DS selector
+ call describe_selector
+
+ mov dx,offs selmsg3
+ mov ax,[ebp+24h] ; ES selector
+ call describe_selector
+
+ mov dx,offs selmsg4
+ mov ax,gs ; SS selector
+ call describe_selector
+
+ mov dx,offs selmsg5
+ mov ax,[ebp+22h] ; FS selector
+ call describe_selector
+
+ mov dx,offs selmsg6
+ mov ax,[ebp+20h] ; GS selector
+ call describe_selector
+
+ ret
+
+
+
+
+
+;=============================================================================
+; In: AX = selector
+;
+describe_selector:
+ push ax
+ call prints
+ pop ax
+ test ax,ax ; check if NULL selector
+ jnz @@1
+ mov dx,offs dbgmsgB
+ call prints
+ jmp printcr
+
+@@1: mov bx,ax
+ sub sp,8 ; get selector info
+ push ss
+ pop es
+ mov edi,esp
+ mov ax,000Bh
+ int 31h
+ jnc @@2 ; branch if selector is OK
+ add sp,8 ; invalid selector
+ mov dx,offs dbgmsgA
+ call prints
+ jmp printcr
+
+@@2: mov ax,wptr es:[edi+5] ; describe selector
+ mov dx,ax
+ push ax ; Acc
+
+ shr al,1
+ and ax,07h
+ push ax ; Type
+
+ mov cl,dh
+ shr cl,6
+ and cl,1
+ mov ax,16
+ shl ax,cl
+ push ax ; Seg: USE16/USE32
+
+ mov al,dl
+ shr al,3
+ and eax,01h
+ lea eax,selmsg8[eax*4+eax]
+ push ax ; Seg: DATA/CODE
+
+ mov al,dh
+ shr al,7
+ and eax,01h
+ lea eax,selmsg9[eax+eax*4]
+ push ax ; Granularity
+
+ mov al,dh
+ and eax,0Fh
+ shl eax,16
+ mov ax,wptr es:[edi+0]
+ push eax ; Limit
+ mov ah,bptr es:[edi+7]
+ mov al,bptr es:[edi+4]
+ shl eax,16
+ mov ax,wptr es:[edi+2]
+ push eax ; Base
+ mov dx,offs selmsg0
+ call prints
+ add sp,26
+ ret
+
+
+;=============================================================================
+; In: FS:ESI = app CS:EIP
+;
+; Out: if FS = known selector:
+; CF clear
+; CX:EAX = N:unrelocated_addr
+; else
+; CF set
+; CX:EAX = 0:linear_addr
+check_faultsel:
+ mov ax,6 ; get base of app's CS
+ mov bx,fs
+ int 31h
+ shl ecx,16
+ mov cx,dx ; ECX = base of app's CS
+ lea eax,[ecx+esi] ; EAX = linear addr (eg CS.base + EIP)
+ mov ecx,_app_num_objects
+ jcxz @@err
+@@0: cmp bx,_app_buf_allocsel[ecx*2]
+ jz @@ok
+ loop @@0
+@@err: stc
+ ret
+@@ok: sub eax,_app_buf_allocbase[ecx*4] ; EAX = unrelocated addr
+ clc
+ ret
+
+
+;=============================================================================
+; In: AX = selector
+;
+; Out: if valid selector AX.out == AX.in
+; else AX = 0 (Null selector)
+;
+check_selector:
+ lar bx,ax ; get access rights
+ jnz @@0 ; if sel not a valid selector, jump
+ verr ax ; verify selector read access
+ jnz @@0 ; if non-readable, jump
+ not bx ; invert Present bit
+ test bh,80h ; test Present bit
+ jnz @@0 ; if segment not present, jump
+ ret
+@@0: xor ax,ax ; return Null selector
+ ret
+
+
+;=============================================================================
+; In: FS:ESI = app's CS:EIP
+; EBX = offset
+;
+; Out: AL
+;
+loadb_cs_eip:
+ mov ax,fs
+ test ax,ax
+ jnz @@0
+ xor eax,eax
+ ret
+@@0: movzx eax,bptr fs:[esi+ebx]
+ ret
+
+;=============================================================================
+; In: FS:ESI = app's CS:EIP
+; EBX = offset
+;
+; Out: EAX
+;
+loadl_cs_eip:
+ mov ax,fs
+ test ax,ax
+ jnz @@0
+ xor eax,eax
+ ret
+@@0: mov eax,fs:[esi+ebx]
+ ret
+
+;=============================================================================
+; In: GS:EDI = app's SS:ESP
+; EBX = offset
+;
+; Out: EAX
+;
+loadl_ss_esp:
+ mov ax,gs
+ test ax,ax
+ jnz @@0
+ xor eax,eax
+ ret
+@@0: mov eax,gs:[edi+ebx]
+ ret
+
+
+
+
+
+.8086
+;=============================================================================
+tone: push ax cx
+ mov ax,0500h
+ mov cx,0110h
+ call beep
+ mov ax,0300h
+ call beep
+ pop cx ax
+ ret
+
+;=============================================================================
+beep: test cs:_misc_byte,00000010b
+ jnz @@0
+ ret
+
+@@0: push cx dx ax ; AX=frequency, CX=time
+ mov al,0B6h ; set frequency
+ out 43h,al
+ pop ax
+ out 42h,al ; fLow
+ mov al,ah
+ out 42h,al ; fHigh
+ in al,61h ; beep on
+ or al,03h
+ out 61h,al
+@@loop: in al,40h
+ in al,40h
+ mov ah,al
+@@1: in al,40h
+ in al,40h
+ cmp ah,al
+ je @@1
+ loop @@loop
+ in al,61h ; beep off
+ and al,not 03h
+ out 61h,al
+ pop dx cx
+ ret
+
+;=============================================================================
+scr_on: push ax bx cx dx
+ test cs:_misc_byte,01000000b
+ jz @@0
+
+ mov ax,0003h
+ int 10h ; set default videomode
+
+@@0: mov dx,03C4h ; turn on VGA screen
+ mov al,01
+ out dx,al
+ inc dx
+ in al,dx
+ and al,0DFh
+ out dx,al
+ pop dx cx bx ax
+ ret
+
+
+PopState
+
diff -uNr a/dos32a/src/dos32a/text/client/int10h.asm b/dos32a/src/dos32a/text/client/int10h.asm
--- a/dos32a/src/dos32a/text/client/int10h.asm false
+++ b/dos32a/src/dos32a/text/client/int10h.asm 0b05fb9f373a0aca408114f975bc50f6e833e25b564e43b3fe14ce7a8d832e4ea6a9dd40b77a4bc9a2f847f6d986d1782fc4657933bf95afc50fd9984b92c021
@@ -0,0 +1,377 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.386p
+;=============================================================================
+_int10: cld
+ push ds es
+ pushad
+
+ cmp ah,1Bh
+ jz @v_1Bh
+ cmp ah,1Ch
+ jz @v_1Ch
+ cmp ax,4F00h
+ jz @v_4F00h
+ cmp ax,4F01h
+ jz @v_4F01h
+ cmp ax,4F04h
+ jz @v_4F04h
+ cmp ax,4F09h
+ jz @v_4F09h
+ cmp ax,4F0Ah
+ jz @v_4F0Ah
+
+ popad
+ pop es ds
+ db 66h
+ jmp cs:_int10_ip
+
+
+
+;=============================================================================
+; VGA: Read Functionality Information
+; In: BX = implementation type
+; ES:EDI = 64 byte buffer
+; Out: AL = 1Bh if function supported by VGA BIOS
+; BX = implementation type
+; ES:EDI = 64 byte buffer
+;
+@v_1Bh: sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax ; store AX
+ mov [ebp+10h],bx ; store BX
+ mov ds,cs:_sel_ds
+ mov ax,_seg_buf
+ mov wptr [ebp+22h],ax ; store ES
+ mov wptr [ebp+00h],0 ; store DI
+ call int10h
+ mov ecx,16
+ mov esi,_lobufbase
+ rep movs dword ptr es:[edi],[esi]
+ movzx eax,wptr [ebp+1Ch] ; get AX
+ movzx ebx,wptr [ebp+10h] ; get BX
+ add esp,32h
+ mov [esp+1Ch],eax ; return EAX
+ mov [esp+10h],ebx ; return EBX
+ jmp @__ok
+
+
+;=============================================================================
+; VGA: Save/Restore VGA Video State
+; In: AL = subfunction:
+; 00h - get state buffer size
+; Return: EBX = number of 64-byte blocks needed
+; 01h - save video states
+; 02h - restore video states
+; ECX = states to save/restore
+; ES:EBX = pointer to save/restore buffer
+; Out: AL = 1Ch if function supported by VGA BIOS
+;
+@v_1Ch: test al,al
+ jz @v_1Ch_00
+ cmp al,01h
+ jz @v_1Ch_01
+ cmp al,02h
+ jz @v_1Ch_02
+ jmp @v_err
+
+@v_1Ch_00:
+ pushfd
+ db 66h
+ call cs:_int10_ip
+ movzx eax,ax
+ movzx ebx,bx
+ mov [esp+1Ch],eax
+ mov [esp+10h],ebx
+ jmp @__ok
+
+@v_1Ch_01:
+ sub esp,32h
+ mov ebp,esp
+ call @v_std
+ call int10h
+ mov esi,_lobufbase
+ mov edi,ebx
+ mov ax,1C00h
+ xor bx,bx
+ int 10h
+ mov ecx,ebx
+ shl ecx,4
+ rep movs dptr es:[edi],[esi]
+ jmp @v_ok
+
+@v_1Ch_02:
+ sub esp,32h
+ mov ebp,esp
+ call @v_std
+ mov esi,ebx
+ mov edi,_lobufbase
+ mov ax,1C00h
+ xor bx,bx
+ int 10h
+ mov ecx,ebx
+ shl ecx,4
+ push ds es
+ pop ds es
+ rep movs dptr es:[edi],[esi]
+ call int10h
+ jmp @v_ok
+
+
+;=============================================================================
+; VESA: Get SuperVGA Information
+; In: ES:EDI = 512 byte buffer
+; Out: AL = 4Fh if function supported by VESA BIOS
+; AH = 00h if function was successful
+; ES:EDI = 512 byte buffer
+;
+;=============================================================================
+; VESA: Get SuperVGA Mode Information
+; In: CX = VideoMode
+; ES:EDI = 256 byte buffer
+; Out: AL = 4Fh if function supported by VESA BIOS
+; AH = 00h if function was successful
+; ES:EDI = 256 byte buffer
+;
+@v_4F00h:
+@v_4F01h:
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax ; store AX
+ mov [ebp+18h],cx ; store CX
+ mov dx,ax
+ mov ds,cs:_sel_ds
+ mov ax,_seg_buf
+ mov wptr [ebp+22h],ax ; store ES
+ mov wptr [ebp+00h],0 ; store DI
+ call int10h
+ mov esi,_lobufbase
+ test dl,dl
+ mov ecx,64
+ jnz @@1
+
+ lea ebx,[esi+06h] ; offset of OEM Str
+ call @@mod
+ lea ebx,[esi+0Eh] ; offset of VideoMode Ptr
+ call @@mod
+ lea ebx,[esi+16h] ; offset of OEM Version Ptr
+ call @@mod
+ lea ebx,[esi+1Ah] ; offset of OEM Name Ptr
+ call @@mod
+ lea ebx,[esi+1Eh] ; offset of OEM Revision Ptr
+ call @@mod
+ mov ecx,128
+@@1: rep movs dptr es:[edi],[esi]
+ jmp @v_ok
+
+@@mod: movzx edx,wptr [ebx+00h] ; get low word (offset)
+ movzx eax,wptr [ebx+02h] ; get high word (segment)
+ shl eax,4 ; convert real mode seg:off
+ add eax,edx ; to linear ptr relative to zero
+ mov dx,[ebx+02h]
+ cmp dx,_seg_buf
+ jnz @@ok
+ sub eax,_lobufzero ; since the structure will be moved
+ add eax,edi ; from buffer, we must adjust ptr
+@@ok: mov [ebx+00h],eax
+ ret
+
+
+;=============================================================================
+; VESA: Save/Restore SuperVGA Video State
+; In: DL = subfunction:
+; 00h - get state buffer size
+; Return: BX = number of 64-byte blocks needed
+; 01h - save video states
+; 02h - restore video states
+; ECX = states to save/restore
+; ES:EBX = pointer to save/restore buffer
+; Out: AL = 4Fh if function supported by VESA BIOS
+; AH = 00h if function was successful
+;
+@v_4F04h:
+ test dl,dl
+ jz @v_1Ch_00
+ cmp dl,01h
+ jz @v_4F04h_01
+ cmp dl,02h
+ jz @v_4F04h_02
+ jmp @v_err
+
+@v_4F04h_01:
+ sub esp,32h
+ mov ebp,esp
+ call @v_std
+ call int10h
+ mov esi,_lobufbase
+ mov edi,ebx
+ mov ax,4F04h
+ xor dl,dl
+ xor bx,bx
+ int 10h
+ mov ecx,ebx
+ shl ecx,4
+ rep movs dptr es:[edi],[esi]
+ jmp @v_ok
+
+@v_4F04h_02:
+ sub esp,32h
+ mov ebp,esp
+ call @v_std
+ mov esi,ebx
+ mov edi,_lobufbase
+ mov ax,4F04h
+ xor dl,dl
+ xor bx,bx
+ int 10h
+ mov ecx,ebx
+ shl ecx,4
+ push ds es
+ pop ds es
+ rep movs dptr es:[edi],[esi]
+ call int10h
+ jmp @v_ok
+
+
+;=============================================================================
+; VESA: Load/Unload Palette Data
+; In: BL = subfunction:
+; 00h - set palette data
+; 01h - get palette data
+; 02h - set 2nd palette data
+; 03h - get 2nd palette data
+; 80h - set palette data during VR
+; ECX = number of palette registers to update
+; EDX = first palette register to update
+; ES:EDI = pointer to buffer
+; Out: AL = 4Fh if function supported by VESA BIOS
+; AH = 00h if function was successful
+;
+@v_4F09h:
+ cmp bl,03h
+ jbe @@0
+ cmp bl,80h
+ jnz @v_err
+@@0: sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov [ebp+18h],cx
+ mov [ebp+14h],dx
+ mov [ebp+10h],bx
+ mov ds,cs:_sel_ds
+ mov ax,_seg_buf
+ mov wptr [ebp+22h],ax
+ mov wptr [ebp+00h],0
+ test bl,bl
+ jz @@1
+ dec bl
+ jz @@2
+ dec bl
+ jz @@1
+ dec bl
+ jz @@2
+@@1: mov esi,edi
+ mov edi,_lobufbase
+ push ds es
+ pop ds es
+ rep movs dptr es:[edi],[esi]
+ call int10h
+ jmp @v_ok
+@@2: call int10h
+ mov esi,_lobufbase
+ rep movs dptr es:[edi],[esi]
+ jmp @v_ok
+
+
+;=============================================================================
+; VESA: Get Protected Mode Interface
+; In: BL = 00h - return protected mode table
+; Out: AL = 4Fh if function supported by VESA BIOS
+; AH = 00h if function was successful
+; ES = protected mode selector of table
+; EDI = offset of table
+; ECX = length of table
+;
+@v_4F0Ah:
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov [ebp+10h],bx
+ call int10h
+ movzx eax,wptr [ebp+1Ch] ; get AX
+ movzx ecx,wptr [ebp+18h] ; get CX
+ movzx edx,wptr [ebp+22h] ; get ES segment
+ movzx edi,wptr [ebp+00h] ; get DI pointer
+ cmp ax,004Fh ; check that there was no error
+ jnz @v_ok
+ shl edx,4
+ add edi,edx ; convert seg:off to linear addr
+ add esp,32h
+ mov [esp+1Ch],eax ; set EAX
+ mov [esp+18h],ecx ; set ECX
+ mov [esp+00h],edi ; set EDI
+ mov ax,cs:_sel_zero
+ mov [esp+20h],ax ; set ES
+ jmp @__ok
+
+
+
+
+;-----------------------------------------------------------------------------
+@v_std: mov [ebp+1Ch],ax ; store AX
+ mov [ebp+18h],cx ; store CX
+ mov [ebp+14h],dx ; store DX
+ mov ds,cs:_sel_ds
+ mov ax,_seg_buf
+ mov wptr [ebp+22h],ax ; store ES
+ mov wptr [ebp+10h],0 ; store BX
+ ret
+@v_ok: movzx eax,wptr [ebp+1Ch]
+ add esp,32h
+ mov [esp+1Ch],eax
+ jmp @__ok
+@v_err: mov dptr [esp+1Ch],-1
+ jmp @__ok
+
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/client/int21h.asm b/dos32a/src/dos32a/text/client/int21h.asm
--- a/dos32a/src/dos32a/text/client/int21h.asm false
+++ b/dos32a/src/dos32a/text/client/int21h.asm df7fa6c8d493b3af578b3fa23121b5f17ec4c7382afc2347f993bebeba50fdfa75769761174b7b892a61d95c351b5a654c8ed93cb5347973c43fe6961ecca592
@@ -0,0 +1,1493 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.386p
+;=============================================================================
+_int21: cld
+ test cs:_sys_misc,0100h ; check for CTRL-C flag
+ jnz _ctrl_c
+
+ push ds es
+ pushad
+
+ cmp ah,09h ; Print string: DS:EDX
+ jz @__09h
+
+ cmp ah,1Ah ; Set DTA buffer: DS:EDX
+ jz @__1Ah
+ cmp ah,1Bh ; Get DefDrive Info: -> AL, DS:EBX, ECX EDX
+ jz @__1Bh
+ cmp ah,1Ch ; Get Drive Info: AL, (-> ---//---)
+ jz @__1Ch
+ cmp ah,1Fh ; Get DefDrive PB: -> AL, DS:EBX
+ jz @__1Fh
+
+ cmp ah,25h ; Set INT vector: AL, DS:EDX
+ jz @__25h
+
+ cmp ah,2Fh ; Get DTA buffer: -> ES:EBX
+ jz @__2Fh
+ cmp ah,31h ; Go TSR AL
+ jz @__31h
+ cmp ah,32h ; Get Drive PB: AL, (-> DS:EBX)
+ jz @__32h
+ cmp ah,34h ; Get InDOS flag: -> ES:EBX
+ jz @__34h
+
+ cmp ah,35h ; Get INT vector: AL, ES:EBX
+ jz @__35h
+
+ cmp ah,39h ; Create DIR: DS:EDX
+ jz @__39h
+ cmp ah,3Ah ; Remove DIR: DS:EDX
+ jz @__3Ah
+ cmp ah,3Bh ; Change DIR: DS:EDX
+ jz @__3Bh
+
+ cmp ah,3Ch ; Create file: CX, DS:EDX
+ jz @__3Ch
+ cmp ah,3Dh ; Open file: AL, DS:EDX
+ jz @__3Dh
+ cmp ah,3Fh ; Read file: BX, ECX, DS:EDX
+ jz @__3Fh
+ cmp ah,40h ; Write file: BX, ECX, DS:EDX
+ jz @__40h
+ cmp ah,41h ; Delete file: DS:EDX
+ jz @__41h
+ cmp ah,42h ; Move file ptr: AL, BX, EDX, (->EAX)
+ jz @__42h
+ cmp ah,43h ; Change file attr: CX, DS:EDX
+ jz @__43h
+
+ cmp ax,4402h ; IOCTL Read: BX, ECX, DS:EDX
+ jz @__4402h
+ cmp ax,4403h ; IOCTL Write: BX, ECX, DS:EDX
+ jz @__4403h
+ cmp ax,4404h ; IOCTL Read: BX, ECX, DS:EDX
+ jz @__4404h
+ cmp ax,4405h ; IOCTL Write: BX, ECX, DS:EDX
+ jz @__4405h
+
+ cmp ah,47h ; Get DIR: DL, DS:ESI
+ jz @__47h
+
+ cmp ah,48h ; Alloc mem: BX (->AX)
+ jz @__48h
+ cmp ah,49h ; Dealloc mem: ES
+ jz @__49h
+ cmp ah,4Ah ; Realloc mem: BX
+ jz @__4Ah
+
+ cmp ah,4Bh ; Execute Prog: AL, DS:EDX, ES:EBX
+ jz @__4Bh
+ cmp ah,4Ch ; Terminate Prog: AL
+ jz @__4Ch
+
+ cmp ah,4Eh ; Find file: CX, DS:EDX
+ jz @__4Eh
+ cmp ah,4Fh ; Find next file: -
+ jz @__4Fh
+ cmp ah,51h ; Get PSP segment: (->BX)
+ jz @__51h
+ cmp ah,56h ; Rename file: DS:EDX, ES:EDI
+ jz @__56h
+ cmp ah,5Ah ; Create temp file: CX, DS:EDX
+ jz @__5Ah
+ cmp ah,5Bh ; Create new file: CX, DS:EDX
+ jz @__5Bh
+ cmp ah,62h ; Get PSP selector: (->BX)
+ jz @__62h
+
+ cmp ah,0FFh ; Rational DOS/4G call
+ jz @__FFh
+
+ cmp ah,71h ; Windows 95 long filename extensions
+ jnz @__go21
+ cmp al,39h ; Win95 Create DIR: DS:EDX
+ jz @__39h
+ cmp al,3Ah ; Win95 Remove DIR: DS:EDX
+ jz @__3Ah
+ cmp al,3Bh ; Win95 Change DIR: DS:EDX
+ jz @__3Bh
+ cmp al,41h ; Win95 Delete file: DS:EDX, CX, SI
+ jz @__41h
+ cmp al,43h ; Win95 Change attr: DS:EDX, BL, CX
+ jz @__43h
+ cmp al,47h ; Win95 Get curr DIR: DS:ESI, DL
+ jz @__47h
+ cmp al,56h ; Win95 Rename file: DS:EDX, ES:EDI
+ jz @__56h
+ cmp al,60h ; Win95 True name:
+ jz @_7160
+ cmp al,6Ch ; Win95 C/Open file:
+ jz @_716C
+
+@__go21:popad
+ pop es ds
+ db 66h
+ jmp cs:_int21_ip
+
+
+_ctrl_c:mov ax,4CFFh ; exit on CTRL-C with code 255
+ jmp @__4Ch
+
+
+
+
+;=============================================================================
+; Print String
+; In: DS:EDX = offset of string
+; Out: -
+;
+@__09h: push ds
+ pop es
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov esi,edx
+ mov edi,edx
+ mov al,'$'
+ or ecx,-1
+ repne scas bptr es:[edi]
+ not ecx
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ rep movs bptr es:[edi],[esi]
+ stos bptr es:[edi]
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+14h],00h
+ call int21h
+ add esp,32h
+ jmp @__ok
+
+
+
+;=============================================================================
+; Set DTA buffer
+; In: DS:EDX = sel:offs
+; Out: -
+;
+@__1Ah: mov es,cs:_sel_ds
+ mov es:_app_dta_sel,ds
+ mov es:_app_dta_off,edx
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov ax,cs:_seg_dta
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+14h],0
+ call int21h
+ add esp,32h
+ jmp @__ok
+
+
+
+;=============================================================================
+; Get Default Drive Info
+; In: -
+; Out: AL = sectors per cluster
+; DS:EBX = addr of FAT
+; ECX = bytes per sector
+; EDX = number of clusters on drive
+;
+@__1Bh:
+@__1Ch: call @__all
+ mov [esp+1Ch],al
+ cmp al,0FFh
+ jz @@done
+ mov [esp+14h],edx
+ mov [esp+18h],ecx
+ shl esi,4
+ add ebx,esi
+ mov [esp+10h],ebx
+ mov ax,cs:_sel_zero
+ mov [esp+22h],ax
+@@done: jmp @__ok
+
+
+
+;=============================================================================
+; Get Drive Info
+; In: DL = Drive number
+; Out: AL = sectors per cluster
+; DS:EBX = addr of FAT
+; ECX = bytes per sector
+; EDX = number of clusters on drive
+;
+;@__1Ch: jmp @__1Bh
+
+
+
+;=============================================================================
+; Get DefDrive Parameter Block
+; In: -
+; Out: AL = status
+; DS:EBX = addr of DPB
+;
+@__1Fh:
+@__32h: call @__all
+ mov [esp+1Ch],al
+ cmp al,0FFh
+ jz @@done
+ shl esi,4
+ add ebx,esi
+ mov [esp+10h],ebx
+ mov ax,cs:_sel_zero
+ mov [esp+22h],ax
+@@done: jmp @__ok
+
+
+
+;=============================================================================
+; Set INT vector
+; In: AL = INT vector, DS:EDX = sel:offs
+; Out: -
+;
+@__25h: mov bl,al
+ mov cx,ds
+ mov ax,0205h
+ int 31h
+ jc @__err
+ jmp @__ok
+
+
+
+;=============================================================================
+; Get DTA buffer
+; In: -
+; Out: ES:EBX = addr of DTA
+;
+@__2Fh: mov ax,cs:_app_dta_sel
+ mov [esp+20h],ax
+ mov eax,cs:_app_dta_off
+ mov [esp+10h],eax
+ jmp @__ok
+
+
+
+;=============================================================================
+; Go TSR
+; In: AL = exit code
+; Out: -
+;
+@__31h: sub esp,32h
+ mov ebp,esp
+
+ mov bx,cs:_membase
+ add bx,cs:_buf_size
+ sub bx,cs:_seg_es
+ mov [ebp+1Ch],ax
+ mov [ebp+14h],bx
+ call int21h
+
+ add esp,32h
+ jmp @__ok
+
+
+
+;=============================================================================
+; Get Drive Parameter Block
+; In: DL = drive number
+; Out: AL = status
+; DS:EBX = addr of DPB
+;
+;@__32h: jmp @__1Fh
+
+
+
+;=============================================================================
+; Get InDOS flag address
+; In: -
+; Out: ES:EBX = addr of InDOS flag
+;
+@__34h: call @__all
+ shl edi,4
+ add ebx,edi
+ mov [esp+10h],ebx
+ mov ax,cs:_sel_zero
+ mov [esp+20h],ax
+ jmp @__ok
+
+
+
+;=============================================================================
+; Get INT vector
+; In: AL = INT vector
+; Out: ES:EBX = sel:offs
+;
+@__35h: mov bl,al
+ mov ax,0204h
+ int 31h
+ mov [esp+20h],cx
+ mov [esp+10h],edx
+ jmp @__ok
+
+
+
+;=============================================================================
+; Create Directory
+; In: DS:EDX = directory name
+; Out: -
+;
+@__39h:
+@__3Ah:
+@__3Bh:
+@__41h:
+@__5Ah:
+@__5Bh:
+ call @__std
+ jz @__ok
+ mov [esp+1Ch],eax
+ jmp @__err
+
+
+
+;=============================================================================
+; Remove Directory
+; In: DS:EDX = directory name
+; Out: -
+;
+;@__3Ah: jmp @__39h
+
+
+
+;=============================================================================
+; Change Directory
+; In: DS:EDX = directory name
+; Out: -
+;
+;@__3Bh: jmp @__39h
+
+
+
+;=============================================================================
+; Create File
+; In: DS:EDX = file name, ECX = attributes
+; Out: EAX = file handle
+;
+@__3Ch:
+@__3Dh: call @__std
+ mov [esp+1Ch],eax
+ jz @__ok
+ jmp @__err
+
+
+
+;=============================================================================
+; Open File
+; In: DS:EDX = file name, AL = access mode
+; Out: EAX = file handle
+;
+;@__3Dh: jmp @__3Ch
+
+
+
+;=============================================================================
+; Read from File
+; In: DS:EDX = addr, ECX = size, EBX = handle
+; Out: EAX = bytes read
+;
+@__4402h:
+@__4404h:
+@__3Fh:
+ push ds
+ pop es
+ mov ds,cs:_sel_ds ; DS=_TEXT16
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+10h],bx ; store handle in structure
+
+ mov edi,edx ; ES:EDI=destination
+ mov ebx,ecx ; EBX=bytes to read
+ xor edx,edx ; EDX=counter bytes read
+
+@@loop: mov [ebp+1Ch],ax ; store AX in structure
+ mov ax,_seg_buf
+ mov [ebp+24h],ax ; store DS in structure
+ mov wptr [ebp+14h],0 ; store DX in structure
+
+ mov eax,ebx
+ cmp eax,_lobufsize
+ jbe @@1
+ mov eax,_lobufsize
+@@1: mov [ebp+18h],ax ; store CX in structure
+
+ call int21h ; DOS read
+ movzx eax,wptr [ebp+1Ch] ; EAX=bytes read
+ test bptr [ebp+20h],1 ; check for error
+ jnz @@err
+
+ test ax,ax ; if read 0 bytes
+ jz @@done ; then we're done
+
+ mov esi,_lobufbase ; DS:ESI=source
+ call @__cp2 ; copy buffer to destination
+
+ add edx,eax ; adjust bytes read
+
+ cmp wptr [ebp+10h],0 ; if was reading from stdin
+ jz @@done ; then we're done
+
+ sub ebx,eax ; adjust bytes to read
+ mov ax,[ebp+1Ch+32h]
+ ja @@loop
+
+@@done: add esp,32h
+ mov [esp+1Ch],edx ; store bytes count
+ jmp @__ok
+@@err: add esp,32h
+ mov [esp+1Ch],eax ; error reading, store errcode
+ jmp @__err
+
+
+
+;=============================================================================
+; Write to File
+; In: DS:EDX = addr, ECX = size, EBX = handle
+; Out: EAX = bytes written
+;
+@__4403h:
+@__4405h:
+@__40h: mov es,cs:_sel_ds
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+10h],bx ; store handle in structure
+
+ mov esi,edx ; DS:ESI=source
+ mov ebx,ecx ; EBX=bytes to write
+ xor edx,edx ; EDX=counter bytes written
+
+@@loop: mov [ebp+1Ch],ax ; store AX in structure
+ mov ax,cs:_seg_buf
+ mov [ebp+24h],ax ; store DS in structure
+ mov wptr [ebp+14h],0 ; store DX in structure
+
+ mov eax,ebx
+ cmp eax,cs:_lobufsize
+ jbe @@1
+ mov eax,cs:_lobufsize
+@@1: mov [ebp+18h],ax ; store CX in structure
+
+ mov edi,cs:_lobufbase
+ call @__cp2 ; copy source into buffer
+
+ call int21h ; DOS write to file
+ movzx eax,wptr [ebp+1Ch] ; EAX=bytes written
+ test bptr [ebp+20h],1 ; check for error
+ jnz @@err
+
+ test ax,ax
+ jz @@done ; if 0 bytes written, we're done
+
+ add edx,eax ; adjust bytes written
+ sub ebx,eax ; adjust bytes to write
+ mov ax,[ebp+1Ch+32h]
+ ja @@loop ; loop until done
+
+@@done: add esp,32h
+ mov [esp+1Ch],edx ; store bytes count
+ jmp @__ok
+@@err: add esp,32h
+ mov [esp+1Ch],eax ; error writing, store errcode
+ jmp @__err
+
+
+
+;=============================================================================
+; Delete File
+; In: DS:EDX = file name
+; Out: -
+;
+;@__41h: jmp @__39h
+
+
+
+;=============================================================================
+; Move File Ptr
+; In: ECX:EDX = ptr, AL = mode
+; Out: EDX:EAX = ptr
+;
+@__42h: call @__all
+ mov [esp+1Ch],eax
+ jnz @__err
+ mov [esp+14h],edx
+ jmp @__ok
+
+
+
+;=============================================================================
+; Change File Attributes
+; In: DS:EDX = file name
+; Out: -
+;
+@__43h: call @__std
+ jz @@1
+ mov [esp+1Ch],eax
+ jmp @__err
+@@1: mov [esp+18h],ecx
+ jmp @__ok
+
+
+
+;=============================================================================
+; Get Directory
+; In: DL = drive
+; DS:ESI = buffer
+; Out: -
+;
+@__47h: sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov [ebp+14h],dx
+ mov ax,cs:_seg_buf
+ mov [ebp+24h],ax
+ mov wptr [ebp+04h],0
+ call int21h
+ test bptr [ebp+20h],1
+ jnz @@err
+ push ds
+ pop es
+ mov edi,esi
+ mov ds,cs:_sel_ds
+ mov esi,_lobufbase
+@@1: lods bptr ds:[esi]
+ stos bptr es:[edi]
+ test al,al
+ jnz @@1
+ add esp,32h
+ jmp @__ok
+@@err: movzx eax,wptr [ebp+1Ch]
+ add esp,32h
+ mov [esp+1Ch],eax
+ jmp @__err
+
+
+
+;=============================================================================
+; Allocate DOS Memory
+; In: EBX = bytes to allocate
+; Out: EAX = selector
+;
+@__48h: mov ax,0100h
+ int 31h
+ jc @@1
+ movzx edx,dx
+ mov [esp+1Ch],edx
+ jmp @__ok
+@@1: movzx eax,ax
+ movzx ebx,bx
+ mov [esp+1Ch],eax
+ mov [esp+10h],ebx
+ jmp @__err
+
+
+
+;=============================================================================
+; Deallocate DOS Memory
+; In: ES = selector
+; Out: -
+;
+@__49h: mov ax,0101h
+ mov dx,es
+ int 31h
+ jnc @@0
+ movzx eax,ax
+ mov [esp+1Ch],eax
+ jmp @__err
+@@0: mov wptr [esp+20h],0
+ jmp @__ok
+
+
+
+;=============================================================================
+; Resize DOS Memory
+; In: ES = selector, EBX = new size
+; Out: -
+;
+@__4Ah: mov ax,0102h
+ mov dx,es
+ int 31h
+ jnc @__ok
+ movzx eax,ax
+ movzx ebx,bx
+ mov [esp+1Ch],eax
+ mov [esp+10h],ebx
+ jmp @__err
+
+
+
+;=============================================================================
+; Execute Program (sub-func AL=00h)
+; In: AL = 00h
+; DS:EDX = path name
+; ES:EBX = parameter block
+; Out: -
+;
+@__4Bh: test al,al ; only subfunction AL=00h supported
+ jnz @__err
+ cmp cs:_lobufsize,0400h ; buffer size must be at least 1Kb
+ jb @__err ; if less, return -1
+
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax ; put AX in structure
+
+ push es
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ mov esi,edx
+ add edi,100h
+@@1: lods bptr ds:[esi] ; copy Path\Name into buffer
+ stos bptr es:[edi]
+ test al,al
+ jnz @@1
+ pop es
+
+ push ds es
+ mov esi,es:[ebx+06h]
+ mov edi,cs:_lobufbase
+ mov ds,es:[ebx+0Ah]
+ mov es,cs:_sel_ds
+ add edi,180h
+ movzx ecx,bptr ds:[esi]
+ inc cx
+ inc cx
+ rep movs bptr es:[edi],[esi] ; copy command line
+ pop es ds
+
+ push ds es
+ mov edi,es:[ebx+00h] ; get environment
+ mov ax,es:[ebx+04h]
+ test ax,ax ; check env selector is 0
+ jz @@3 ; if yes, jump
+ mov es,ax
+ xor ax,ax
+ mov esi,edi
+ or ecx,-1
+@@2: repne scas bptr es:[edi]
+ dec ecx
+ scas bptr es:[edi]
+ jnz @@2
+ not ecx
+ mov ax,0100h ; allocate mem for environment
+ mov bx,cx
+ shr bx,4
+ inc bx
+ int 31h
+ jc @@4
+ push es
+ pop ds
+ mov es,dx
+ xor edi,edi
+ rep movs bptr es:[edi],[esi] ; copy environment
+@@3: mov ds,cs:_sel_ds
+ mov edi,_lobufbase
+ mov wptr [edi+00h],ax
+ mov ax,_seg_buf
+ mov wptr [edi+02h],180h
+ mov wptr [edi+04h],ax
+ mov ax,_seg_es
+ mov wptr [edi+06h],5Ch
+ mov wptr [edi+08h],ax
+ mov wptr [edi+0Ah],6Ch
+ mov wptr [edi+0Ch],ax
+@@4: pop es ds
+ jc @@err
+
+ push dx ; save env selector
+ mov ds,cs:_sel_ds
+ mov ax,_seg_buf
+ mov wptr [ebp+22h],ax
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+10h],0000h
+ mov wptr [ebp+14h],0100h
+
+ cmp _sys_type,3
+ jz @@5
+ mov eax,cr0
+ mov edi,eax
+ and al,0FBh
+ mov cr0,eax
+@@5: call uninstall_client_ints
+ call int21h
+ call install_client_ints
+ cmp _sys_type,3
+ jz @@6
+ mov cr0,edi
+
+@@6: pop dx ; restore env sel
+ mov ax,0101h
+ int 31h
+
+ movzx eax,wptr [ebp+1Ch] ; get return code
+ test bptr [ebp+20h],01h ; check carry flag
+ lea esp,[esp+32h]
+ mov [esp+1Ch],eax ; put return code in AX
+ jnz @__err ; if error, set carry on ret
+ jmp @__ok
+
+@@err: add esp,32h
+ mov dptr [esp+1Ch],-1
+ jmp @__err
+
+
+
+;=============================================================================
+; Terminate Program
+; In: AL = error code
+; Out: -
+;
+@__4Ch: cli ; disable interrupts
+ cld
+ mov ds,cs:_sel_ds ; restore SEG registers
+ mov es,_sel_es
+ lss esp,fptr _sel_esp ; set default stack
+ push ax
+ mov ax,_sel_env
+ mov es:[002Ch],ax ; restore default environment
+
+ cmp _sys_type,3 ; if under DPMI, do not clear DRx
+ jz @@1
+ xor eax,eax
+ mov dr7,eax
+
+@@1: push es ; undefine Mouse ISR
+ mov ax,000Ch
+ xor edx,edx
+ mov cx,dx
+ mov es,dx
+ int 33h
+ pop es
+
+ mov dx,_mus_backoff ; free mouse callback
+ mov cx,_mus_backseg
+ mov ax,cx
+ or ax,dx
+ jz @@2
+ mov ax,0304h
+ int 31h
+
+@@2: mov ecx,_app_num_objects ; deallocate selectors
+ jcxz @@4
+@@3: mov ax,0001h
+ mov bx,_app_buf_allocsel[ecx*2]
+ int 31h
+ loop @@3
+
+@@4: call check_inttab
+ call restore_inttab
+ call uninstall_client_ints
+
+@@5: mov ax,0001h ; free ZERO selector
+ mov bx,cs:_sel_zero
+ int 31h
+
+ xor ax,ax
+ mov fs,ax
+ mov gs,ax
+ pop ax
+ db 66h ; 32-bit jump
+ jmp cs:_int21_ip ; exit with errorcode in AL
+
+
+
+;=============================================================================
+; Find First File
+; In: CX = file attributes
+; DS:EDX = file name
+; Out: -
+;
+@__4Eh: call @__std
+ jnz @@err
+ mov ds,cs:_dta_sel
+ mov esi,cs:_dta_off
+ mov es,cs:_app_dta_sel
+ mov edi,cs:_app_dta_off
+ mov ecx,2Bh
+ rep movs bptr es:[edi],[esi]
+ jmp @__ok
+@@err: mov [esp+1Ch],eax
+ jmp @__err
+
+
+
+;=============================================================================
+; Find Next File
+; In: -
+; Out: -
+;
+@__4Fh: mov ds,cs:_app_dta_sel
+ mov esi,cs:_app_dta_off
+ mov es,cs:_dta_sel
+ mov edi,cs:_dta_off
+ mov ecx,2Bh
+ rep movs bptr es:[edi],[esi]
+ call @__all
+ jnz @@err
+ mov ds,cs:_dta_sel
+ mov esi,cs:_dta_off
+ mov es,cs:_app_dta_sel
+ mov edi,cs:_app_dta_off
+ mov ecx,2Bh
+ rep movs bptr es:[edi],[esi]
+ jmp @__ok
+@@err: mov [esp+1Ch],eax
+ jmp @__err
+
+
+
+;=============================================================================
+; Get PSP Segment
+; In: -
+; Out: EBX = PSP segment
+;
+@__51h: movzx eax,cs:_seg_es
+ mov [esp+10h],eax
+ jmp @__ok
+
+
+
+;=============================================================================
+; Rename File
+; In: DS:EDX = old filename
+; ES:EDI = new filename
+; Out: -
+;
+@__56h: sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ or ecx,-1
+ xor al,al
+ repne scas bptr es:[edi]
+ not ecx
+ sub edi,ecx
+ mov esi,edi
+ push ds
+ push es
+ pop ds
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ rep movs bptr es:[edi],[esi]
+ pop ds
+ mov ecx,edi
+ mov ebx,cs:_lobufbase
+ sub ecx,ebx
+ xchg ecx,ebx
+ push ds
+ pop es
+ mov esi,edx
+ xchg esi,edi
+ or ecx,-1
+ xor al,al
+ repne scas bptr es:[edi]
+ not ecx
+ sub edi,ecx
+ xchg esi,edi
+ mov es,cs:_sel_ds
+ rep movs bptr es:[edi],[esi]
+ mov ax,cs:_seg_buf
+ mov [ebp+24h],ax
+ mov [ebp+22h],ax
+ mov wptr [ebp+00h],0
+ mov [ebp+14h],bx
+ call int21h
+ jmp @__tst
+
+
+
+;=============================================================================
+; Create Temp File
+; In: DS:EDX = file name
+; Out: -
+;
+;@__5Ah: jmp @__39h
+
+
+
+;=============================================================================
+; Create New File
+; In: CX = attributes
+; DS:EDX = file name
+; Out: -
+;
+;@__5Bh: jmp @__39h
+
+
+
+;=============================================================================
+; Get PSP Selector
+; In: -
+; Out: BX = PSP selector
+;
+@__62h: movzx eax,cs:_sel_es
+ mov [esp+10h],eax
+ jmp @__ok
+
+
+
+;=============================================================================
+; Win95 Get Short (8.3) filename
+; In: CL = 00/01/02h
+; CH = SUBST expansion flag
+; DS:ESI = ASCIIZ long filename or path
+; ES:EDI = 261/128/261-byte buffer for short name
+; Out: -
+;
+@_7160: sub esp,32h
+ mov ebp,esp
+ push es edi
+ mov [ebp+1Ch],ax
+ mov [ebp+18h],cx
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ add edi,0200h
+@@1: lods bptr ds:[esi]
+ stos bptr es:[edi]
+ test al,al
+ jnz @@1
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+22h],ax
+ mov wptr [ebp+04h],0200h
+ mov wptr [ebp+00h],0000h
+ call int21h
+ push es
+ pop ds
+ mov esi,cs:_lobufbase
+ pop edi es
+ test bptr [ebp+20h],1
+ jnz @@err
+@@2: lods bptr ds:[esi]
+ stos bptr es:[edi]
+ test al,al
+ jnz @@2
+ add esp,32h
+ jmp @__ok
+@@err: movzx eax,wptr [ebp+1Ch]
+ add esp,32h
+ mov [esp+1Ch],eax
+ jmp @__err
+
+
+
+;=============================================================================
+; Win95 Create or Open File
+; In: BX = access mode
+; CX = attributes
+; DX = action
+; DI = alias hint
+; DS:ESI = ASCIIZ long filename
+; Out: AX = file handle
+; CX = action taken
+;
+@_716C: sub esp,32h
+ mov ebp,esp
+ mov [ebp+00h],di
+ mov [ebp+10h],bx
+ mov [ebp+14h],dx
+ mov [ebp+18h],cx
+ mov [ebp+1Ch],ax
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+04h],0
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+@@0: lods bptr ds:[esi]
+ stos bptr es:[edi]
+ test al,al
+ jnz @@0
+ call int21h
+ movzx eax,wptr [ebp+1Ch]
+ movzx ecx,wptr [ebp+18h]
+ test bptr [ebp+20h],1
+ lea esp,[esp+32h]
+ mov [esp+1Ch],eax
+ jnz @__err
+ mov [esp+18h],ecx
+ jmp @__ok
+
+
+
+
+
+;=============================================================================
+; DOS/4G Identification call
+; In: AX = 0FF00h, DX = 0078h
+; Out: EAX = 0FFFF3447h '..4G'
+;
+@__FFh: cmp al,88h ; AX=0FF88h - DOS/32A functional call
+ jz @_FF88
+ cmp al,89h ; AX=0FF89h - DOS/32A get config
+ jz @_FF89
+ cmp al,8Ah ; AX=0FF8Ah - DOS/32A get info
+ jz @_FF8A
+ cmp al,8Dh ; AX=0FF8Dh - DOS/32A decompress data
+ jz @_FF8D
+ cmp al,8Eh ; AX=0FF8Eh - DOS/32A get Client ptrs
+ jz @_FF8E
+ cmp al,8Fh ; AX=0FF8Fh - DOS/32A resize DOS buf
+ jz @_FF8F
+
+ cmp al,80h ; AX=0FF80h - DOS/32A prints (magic)
+ jz @_FF80
+ cmp al,90h ; AX=0FF90h - DOS/32A get hi mem
+ jz @_FF90
+ cmp al,91h ; AX=0FF91h - DOS/32A alloc hi mem
+ jz @_FF91
+ cmp al,92h ; AX=0FF92h - DOS/32A free hi mem
+ jz @_FF92
+ cmp al,93h ; AX=0FF93h - DOS/32A resize hi mem
+ jz @_FF93
+
+ cmp al,94h ; AX=0FF94h - DOS/32A get lo mem
+ jz @_FF94
+ cmp al,95h ; AX=0FF95h - DOS/32A alloc lo mem
+ jz @_FF95
+ cmp al,96h ; AX=0FF96h - DOS/32A free lo mem
+ jz @_FF96
+ cmp al,97h ; AX=0FF97h - DOS/32A resize lo mem
+ jz @_FF97
+
+ cmp al,98h ; AX=0FF98h - DOS/32A map phys mem
+ jz @_FF98
+ cmp al,99h ; AX=0FF99h - DOS/32A free phys mem
+ jz @_FF99
+ cmp al,9Ah ; AX=0FF9Ah - DOS/32A alloc selector
+ jz @_FF9A
+
+ cmp dx,0078h ; DX=0078h - DOS/4G detection
+ jnz @__go21
+ mov gs,cs:_sel_ds
+ mov dptr [esp+1Ch],4734FFFFh
+ jmp @__ok
+
+
+;=============================================================================
+; DOS/32A Identification call
+; In: AX = 0FF88h
+; Out: EAX = 'ID32'
+; EBX = DOS Extender version
+;
+@_FF88: sub esp,32h ; DOS/32A internal function
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ call int21h
+ mov eax,'ID32'
+ movzx ebx,cs:_version
+ mov ecx,[ebp+18h]
+ mov edx,[ebp+14h]
+ mov esi,[ebp+04h]
+ mov edi,[ebp+00h]
+ mov ebp,[esp+3Ah]
+ add esp,52h
+ jmp @__exi
+
+;=============================================================================
+; DOS/32A Get Client Configuration
+; In: AX = 0FF89h
+; Out: EAX = 'ID32'
+; EBX = DOS Extender version
+; ECX = size of low buffer
+; EDX = configuration bits
+; ESI = pointer to ID32 config header
+; FS = zero selector
+;
+@_FF89: mov eax,'ID32'
+ movzx esi,cs:_seg_id32
+ shl esi,4
+ mov fs,cs:_sel_zero
+ movzx ebx,cs:_version
+ mov ecx,cs:_lobufsize
+ movzx edx,wptr cs:_misc_byte
+ add esp,20h
+ jmp @__exi
+
+;=============================================================================
+; DOS/32A Get Kernel Configuration
+; In: AX = 0FF8Ah
+; Out: EAX = 'ID32'
+; EBX = DOS Extender version
+; CL = CPU type
+; CH = System software
+; DL = Kernel configuration bits
+; ESI = pointer to Kernel config header
+; FS = zero selector
+;
+@_FF8A: mov eax,'ID32'
+ movzx esi,cs:_seg_kernel
+ shl esi,4
+ add esi,offs pm32_data
+ mov fs,cs:_sel_zero
+ movzx ebx,cs:_version
+ mov cl,cs:_cpu_type
+ mov ch,cs:_sys_type
+ mov dl,fs:[esi+00h]
+ add esp,20h
+ jmp @__exi
+
+;=============================================================================
+; DOS/32A Decompress data
+; In: AX = 0FF8Dh
+; DS:EBX = source address
+; DS:EDI = destination address
+; ECX = source size
+; Out: EAX = destination size
+;
+@_FF8D: push gs ds
+ pop gs
+ mov ds,cs:_sel_ds
+ call decompress
+ mov eax,_codesize
+ sub eax,edi
+ pop gs
+ mov [esp+1Ch],eax
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Return pointers to Client variables
+; In: AX = 0FF8Eh
+; Out: GS = Client data selector
+; EDX = pointer to "start" == module file name
+; ESI = pointer to loaded application sel/base table
+; EDI = pointer to Client variables structure
+;
+@_FF8E: mov gs,cs:_sel_ds
+ mov edx,offs start
+ mov esi,offs _app_buf_allocsel
+ mov edi,offs _misc_byte
+ add esp,20h
+ jmp @__exi
+
+;=============================================================================
+; DOS/32A Resize DOS transfer buffer
+; In: AX = 0FF8Fh
+; EBX = new size of DOS transfer buffer in bytes
+; Out: EBX = old size of DOS transfer buffer in bytes
+;
+@_FF8F: mov ds,cs:_sel_ds
+ xchg _lobufsize,ebx
+ mov [esp+10h],ebx
+ jmp @__ok
+
+
+;=============================================================================
+; DOS/32A Print String (Magic)
+; In: AX = 0FF80h
+; EBX = value
+; DS:EDX = pointer to string
+; Out: -
+;
+@_FF80: mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ mov esi,edx
+ mov dx,di
+@@1: lods bptr ds:[esi]
+ stosb
+ test al,al
+ jnz @@1
+ push es
+ pop ds
+ mov _int_ss,ss
+ mov _int_esp,esp
+ lss esp,fptr _sel_esp
+ push ecx
+ push ebx
+ call prints
+ lss esp,fptr _int_esp
+ jmp @__ok
+
+
+;=============================================================================
+; DOS/32A Get Free Extended Memory Information
+; In: AX = 0FF90h
+; Out: EAX = largest free memory block
+;
+@_FF90: push ss
+ pop es
+ sub esp,30h
+ mov edi,esp
+ mov ax,0500h
+ int 31h
+ mov eax,[esp]
+ add esp,30h
+ mov [esp+1Ch],eax
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Allocate Extended Memory
+; In: AX = 0FF91h
+; EBX = size of block
+; Out: EBX = linear address of block
+; ESI = handle of block
+;
+@_FF91: call @_FF9x1
+ mov ax,0501h
+ int 31h
+ jmp @_FF9x2
+
+;=============================================================================
+; DOS/32A Free Extended Memory
+; In: AX = 0FF92h
+; ESI = handle of block
+; Out: -
+;
+@_FF92: call @_FF9x1
+ mov ax,0502h
+ int 31h
+ jc @__err
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Resize Extended Memory
+; In: AX = 0FF93h
+; EBX = new size of block
+; ESI = handle of block
+; Out: EBX = new linear address of block
+; ESI = new handle of block
+;
+@_FF93: call @_FF9x1
+ mov ax,0503h
+ int 31h
+ jmp @_FF9x2
+
+;=============================================================================
+; DOS/32A Get Free DOS Memory Information
+; In: AX = 0FF94h
+; Out: EAX = largest free memory block
+;
+@_FF94: mov ah,48h
+ mov bx,-1
+ call @__all
+ shl ebx,4
+ mov [esp+1Ch],ebx
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Allocate DOS Memory
+; In: AX = 0FF94h
+; EBX = size of block
+; Out: EBX = linear address of block
+; ESI = handle of block
+;
+@_FF95: add ebx,0Fh
+ shr ebx,4
+ test ebx,0FFFF0000h
+ jnz @__err
+ test bx,bx
+ jz @__err
+ mov ah,48h
+ call @__all
+ jnz @__err
+ mov [esp+04h],eax
+ shl eax,4
+ mov [esp+10h],eax
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Free DOS Memory
+; In: AX = 0FF96h
+; ESI = handle of block
+; Out: -
+;
+@_FF96: sub esp,32h
+ mov ebp,esp
+ mov bptr [ebp+1Dh],49h
+ mov wptr [ebp+22h],si
+ call int21h
+ test bptr [ebp+20h],1
+ lea esp,[esp+32h]
+ jnz @__err
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Resize DOS Memory
+; In: AX = 0FF97h
+; EBX = new size of block
+; ESI = handle of block
+; Out: EBX = new linear address of block
+; ESI = new handle of block
+;
+@_FF97: add ebx,0Fh
+ shr ebx,4
+ test ebx,0FFFF0000h
+ jnz @__err
+ test bx,bx
+ jz @__err
+ sub esp,32h
+ mov ebp,esp
+ mov bptr [ebp+1Dh],4Ah
+ mov wptr [ebp+10h],bx
+ mov wptr [ebp+22h],si
+ call int21h
+ test bptr [ebp+20h],1
+ lea esp,[esp+32h]
+ jnz @__err
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Map Physical Memory
+; In: AX = 0FF98h
+; EBX = base of physical memory
+; ESI = size of region
+; Out: EBX = linear address of memory
+;
+@_FF98: call @_FF9x1
+ mov ax,0800h
+ int 31h
+ jc @__err
+ jmp @_FF9x3
+
+;=============================================================================
+; DOS/32A Unmap Physical Memory
+; In: AX = 0FF99h
+; EBX = linear address of memory
+; Out: -
+;
+@_FF99: call @_FF9x1
+ mov ax,0801h
+ int 31h
+ jc @__err
+ jmp @__ok
+
+;=============================================================================
+; DOS/32A Allocate Selector
+; In: AX = 0FF94h
+; EBX = selector base
+; ECX = selector limit
+; DX = selector access rights
+; Out: AX = selector
+;
+@_FF9A: mov edi,ebx
+ call set_descriptor
+ jc @__err
+ mov [esp+1Ch],ax
+ jmp @__ok
+
+
+
+
+;-----------------------------------------------------------------------------
+@_FF9x1:mov cx,bx ; convert BX:CX to EBX
+ shr ebx,16
+ mov di,si ; convert SI:DI to EDI
+ shr esi,16
+ ret
+@_FF9x2:jc @__err
+ shl esi,16
+ mov si,di
+ mov [esp+04h],esi
+@_FF9x3:shl ebx,16
+ mov bx,cx
+ mov [esp+10h],ebx
+ jmp @__ok
+
+
+
+
+;*****************************************************************************
+@__cpy: push ds ; copy NULL-terminated string to buffer
+ pop es
+ xor ax,ax
+ mov esi,edx
+ mov edi,edx
+ or ecx,-1
+ repne scas bptr es:[edi]
+ not ecx
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ rep movs bptr es:[edi],[esi]
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+24h],ax
+ mov wptr [ebp+14h],0
+ jmp int21h
+@__cp2: mov ecx,eax ; copy buffer
+ shr cx,2
+ rep movs dptr es:[edi],[esi]
+ mov cl,al
+ and cl,03h
+ rep movs bptr es:[edi],[esi]
+ ret
+@__std: sub esp,32h
+ mov ebp,esp
+ mov [ebp+04h],si ; these two pass-downs are
+ mov [ebp+10h],bx ; for Win95 longfilenames
+ mov [ebp+18h],cx
+ mov [ebp+1Ch],ax
+ call @__cpy
+ movzx eax,wptr [ebp+1Ch]
+ movzx ecx,wptr [ebp+18h]
+ test bptr [ebp+20h],1
+ lea esp,[esp+32h] ; restore stack
+ ret
+@__all: sub esp,32h
+ mov ebp,esp
+ mov [ebp+10h],bx
+ mov [ebp+14h],dx
+ mov [ebp+18h],cx
+ mov [ebp+1Ch],ax
+ call int21h
+ movzx eax,wptr [ebp+1Ch]
+ movzx ecx,wptr [ebp+18h]
+ movzx edx,wptr [ebp+14h]
+ movzx ebx,wptr [ebp+10h]
+ movzx edi,wptr [ebp+22h] ; ES
+ movzx esi,wptr [ebp+24h] ; DS
+ test bptr [ebp+20h],1
+ lea esp,[esp+32h] ; restore stack
+ ret
+@__tst: movzx eax,wptr [ebp+1Ch] ; get error number
+ test bptr [ebp+20h],1 ; check if CF is set
+ lea esp,[esp+32h] ; restore stack
+ mov [esp+1Ch],eax ; put EAX (error) on stack
+ jnz @__err
+@__ok: popad ; return ok
+@__exi: pop es ds
+ and bptr [esp+8],0FEh
+ iretd
+@__err: popad ; return with error
+ pop es ds
+ or bptr [esp+8],01h
+ iretd
+
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/client/int33h.asm b/dos32a/src/dos32a/text/client/int33h.asm
--- a/dos32a/src/dos32a/text/client/int33h.asm false
+++ b/dos32a/src/dos32a/text/client/int33h.asm e2e31c006ffe4d231b2e02177072205f810923779ead9bd8a618345596f7b1f7915a1519c93eadfac862649fda724b46840c26c6fb1e4bce1664fb6ee45eac75
@@ -0,0 +1,285 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.386p
+;=============================================================================
+_int33: cld
+ push ds es
+ pushad
+
+ cmp ax,0009h
+ jz @__0009h
+ cmp ax,000Ch
+ jz @__000Ch
+ cmp ax,0014h
+ jz @__0014h
+ cmp ax,0016h
+ jz @__0016h
+ cmp ax,0017h
+ jz @__0017h
+ cmp ax,0018h
+ jz @__0018h
+ cmp ax,0019h
+ jz @__0019h
+ cmp ax,0020h
+ jz @__0020h
+
+ popad
+ pop es ds
+ db 66h
+ jmp cs:_int33_ip
+
+
+
+
+;=============================================================================
+; Define Graphics Cursor
+; In: BX = column of cursor hotspot in bitmap
+; CX = row of cursor hotspot in bitmap
+; ES:EDX = mask bitmap
+;
+@__0009h:
+ push es
+ pop ds
+ sub esp,32h
+ mov ebp,esp
+ mov esi,edx
+ mov es,cs:_sel_zero
+ movzx edi,cs:_seg_mus
+ mov wptr [ebp+1Ch],ax
+ mov wptr [ebp+18h],cx
+ mov wptr [ebp+10h],bx
+ mov wptr [ebp+22h],di
+ mov wptr [ebp+14h],0
+ shl edi,4
+ mov ecx,10h
+ rep movs dptr es:[edi],[esi]
+ call int33h
+ add esp,32h
+ jmp @__ok
+
+
+
+;=============================================================================
+; Define Interrupt Subroutine
+; In: CX = call mask
+; ES:EDX = far pointer to routine
+;
+@__000Ch:
+ call _mus_int_def
+ jmp @__ok
+
+
+;=============================================================================
+; Exchange Defined Interrupt Subroutine
+; In: CX = call mask
+; ES:EDX = far pointer to routine
+; Out: CX = call mask
+; ES:EDX = far pointer to routine
+;
+@__0014h:
+ mov si,wptr cs:_mus_sel
+ mov edi,dptr cs:_mus_off
+ call _mus_int_def
+ mov [esp+14h],edi
+ mov [esp+20h],si
+ jmp @__ok
+
+
+;=============================================================================
+; Define Interrupt Subroutine
+; In: CX = call mask
+; ES:EDX = far pointer to routine
+;
+@__0018h:
+ call _mus_int_def
+ mov [esp+1Ch],eax
+ jmp @__ok
+
+
+;=============================================================================
+; Return Defined Interrupt Subroutine
+; In: CX = call mask
+; Out: BX:EDX = far pointer to routine
+;
+@__0019h:
+ mov ax,wptr cs:_mus_sel
+ mov edx,dptr cs:_mus_off
+ mov [esp+14h],edx
+ mov [esp+10h],ax
+ jmp @__ok
+
+
+
+;-----------------------------------------------------------------------------
+_mus_int_def:
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov [ebp+18h],cx
+ mov ds,cs:_sel_ds
+ xor eax,eax
+ mov _mus_off,edx
+ mov _mus_sel,es
+ mov ax,es
+ or eax,edx
+ jz @@1
+ mov ax,_seg_ds
+ mov dx,offs _mus_int_rm
+@@1: mov wptr [ebp+14h],dx
+ mov wptr [ebp+22h],ax
+ cli
+ call int33h
+ movzx eax,wptr [ebp+1Ch]
+ add esp,32h
+ sti
+ ret
+
+_mus_int_rm:
+ cmp cs:_mus_data,0
+ mov cs:_mus_data,1
+ jnz @@1
+ jmp dword ptr cs:_mus_backoff
+@@1: retf
+
+_mus_int_pm:
+ cld
+ pushad
+ push ds es fs gs
+ xor eax,eax
+
+ mov ax,ds
+ mov ds,cs:_sel_ds
+ mov ds:_mus_esp,esp
+ mov ds:_mus_ss,ss
+ mov ds,ax
+
+ mov ax,ss
+ lar eax,eax
+ shr eax,23
+ jc @@1
+ movzx esp,sp
+
+@@1: mov ax,cs:_seg_ds
+ mov wptr es:[edi+2Ch],ax
+ mov wptr es:[edi+2Ah],offs @@done
+
+ movzx eax,wptr es:[edi+1Ch]
+ movzx ecx,wptr es:[edi+18h]
+ movzx edx,wptr es:[edi+14h]
+ movzx ebx,wptr es:[edi+10h]
+ movzx esi,wptr es:[edi+04h]
+ movzx edi,wptr es:[edi+00h]
+ pushfd
+ call fword ptr cs:_mus_off
+
+ lss esp,fword ptr cs:_mus_esp
+
+ pop gs fs es ds
+ popad
+ iretd
+@@done: mov cs:_mus_data,0
+ retf
+
+
+
+;=============================================================================
+; Save Driver State
+; In: BX = size of buffer
+; ES:EDX = buffer for driver state
+;
+@__0016h:
+ sub esp,32h
+ mov ebp,esp
+ mov edi,edx
+ mov [ebp+1Ch],ax
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+22h],ax
+ mov wptr [ebp+14h],0
+ call int33h
+ mov ds,cs:_sel_ds
+ mov esi,_lobufbase
+ mov ecx,_mus_size
+ rep movs bptr es:[edi],[esi]
+ add esp,32h
+ jmp @__ok
+
+
+;=============================================================================
+; Restore Driver State
+; In: BX = size of buffer
+; ES:EDX = buffer containing saved state
+;
+@__0017h:
+ push es
+ pop ds
+ sub esp,32h
+ mov ebp,esp
+ mov esi,edx
+ mov [ebp+1Ch],ax
+ mov ax,cs:_seg_buf
+ mov wptr [ebp+22h],ax
+ mov wptr [ebp+14h],0
+ mov es,cs:_sel_ds
+ mov edi,cs:_lobufbase
+ mov ecx,cs:_mus_size
+ rep movs bptr es:[edi],[esi]
+ call int33h
+ add esp,32h
+ jmp @__ok
+
+
+;=============================================================================
+; Enable Mouse Driver
+; In: -
+;
+@__0020h:
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ call int33h
+ add esp,32h
+ mov wptr [esp+1Ch],-1
+ jmp @__ok
+
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/client/misc.asm b/dos32a/src/dos32a/text/client/misc.asm
--- a/dos32a/src/dos32a/text/client/misc.asm false
+++ b/dos32a/src/dos32a/text/client/misc.asm 96d599e5fc3078fec775f2f42f73df63de1632aedeec54fc496edaf561c64d6dc4fedd361d2b4eae35ff102c8074cb1b652c2b4127cc911fd9e1fadc368ca067
@@ -0,0 +1,975 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.8086
+;=============================================================================
+; Real mode exit routine, using 8086 instructions
+;
+exit86: cli
+ cld
+ mov ds,cs:_seg_ds ; restore SEG regs
+ mov es,_seg_es
+ mov ss,_seg_ss
+ mov sp,STACKSIZE*16 ; set stack to default size
+ mov ax,_seg_env
+ mov es:[002Ch],ax
+ mov ax,4CFFh ; exit with error code -1
+ int 21h ; NOTE: DOS 1.0 will hang
+
+.386p
+;=============================================================================
+; Protected mode exit routine, using 80386 instructions
+;
+exit386:cli
+ cld
+ mov ds,cs:_sel_ds ; restore SEG regs
+ mov es,_sel_es
+ lss esp,fptr _sel_esp ; set stack to default size
+ xor dx,dx
+ mov fs,dx
+ mov gs,dx
+ mov ah,4Ch ; exit with error code in AL
+ int 21h
+
+;=============================================================================
+save_inttab: ; save real mode interrupts
+ push cx si di ds es
+ xor si,si
+ mov di,STACKSIZE*16
+ mov ds,cs:_sel_zero
+ mov es,cs:_sel_ss
+ mov cx,0200h
+ cld
+ rep movsw
+ in al,21h ; save PIC mask
+ mov ah,al
+ in al,0A1h
+ pop es ds di si cx
+ mov _pic_mask,ax
+ ret
+
+;=============================================================================
+restore_inttab: ; restore real mode interrupts
+ test cs:_misc_byte,00000100b
+ jz @@done
+ cmp cs:_sys_type,3
+ jz @@1
+ xor eax,eax ; reset Null-Pointer protection
+ mov dr7,eax
+@@1: pushf
+ cli
+ push si di ds es
+ xor di,di
+ mov si,STACKSIZE*16
+ mov es,cs:_sel_zero
+ mov ds,cs:_sel_ss
+ mov cx,0200h
+ cld
+ rep movsw
+ mov ax,cs:_pic_mask ; restore PIC mask
+ out 0A1h,al
+ mov al,ah
+ out 21h,al
+ pop es ds di si
+ popf
+@@done: ret
+
+;=============================================================================
+check_inttab:
+ test cs:_misc_byte,00001000b
+ jz @@done
+ pushad
+ push ds es
+ xor bx,bx
+ mov ds,cs:_sel_ss
+ mov es,cs:_sel_zero
+ mov esi,STACKSIZE*16
+ xor edi,edi
+ cld
+@@1: cmps dptr ds:[esi],[edi]
+ jnz @@2
+@@3: inc bx
+ cmp bx,256
+ jb @@1
+ pop es ds
+ popad
+@@done: ret
+@@2: mov ax,9003h
+ push bx si
+ mov si,bx
+ call report_error
+ pop si bx
+ jmp @@3
+
+;=============================================================================
+restore_pit:
+ push ax
+ mov al,36h ; reprogram PIT to DOS freq
+ out 43h,al
+ mov al,00h
+ out 40h,al
+ out 40h,al
+ pop ax
+ ret
+
+;=============================================================================
+set_descriptor: ; EDI=base, ECX=limit, DX=access
+ push ebx ecx edx ebp
+ mov ebp,ecx
+ xor ax,ax ; allocate descriptor
+ mov cx,1
+ int 31h
+ jc @@err
+ mov bx,ax
+ mov ax,0009h ; set access rights
+ mov cx,dx
+ int 31h
+ jc @@err
+ dec ax ; set limit
+ mov ecx,ebp
+ mov dx,cx
+ shr ecx,16
+ int 31h
+ jc @@err
+ dec ax ; set base
+ mov ecx,edi
+ mov dx,cx
+ shr ecx,16
+ int 31h
+ jc @@err
+ mov ax,bx
+@@err: pop ebp edx ecx ebx
+ ret
+
+;=============================================================================
+_int23: push ds ; handle CTRL-C INT 23h
+ mov ds,cs:_sel_ds
+ or _sys_misc,0100h
+ pop ds
+ iretd
+
+;=============================================================================
+int10h: push bx ; simulate INT 10h (VGA API)
+ mov bx,10h
+ jmp intxxh
+
+int33h: push bx ; simulate INT 33h (Mouse API)
+ mov bx,33h
+ jmp intxxh
+
+int21h: push bx ; simulate INT 21h (DOS API)
+ mov bx,21h
+
+intxxh: push cx edi es
+ xor eax,eax
+ mov [ebp+20h],ax ; clear Flags
+ mov [ebp+2Eh],eax ; clear SS:SP
+ xor cx,cx
+ push ss
+ pop es
+ mov edi,ebp
+ mov ax,0300h
+ int 31h
+ pop es edi cx bx
+ jc dpmi_error
+ ret
+
+
+;=============================================================================
+setup_dta_buffer:
+ sub esp,32h
+ mov ebp,esp
+ mov ax,_seg_ss
+ add ax,0010h
+ mov _seg_dta,ax ; DTA at offset STK_TOP + 0100h
+ mov wptr [ebp+24h],ax
+ add ax,0008h
+ mov _seg_mus,ax ; MOUSE at offset STK_TOP + 0180h
+ mov ax,ss
+ mov _dta_sel,ax
+ mov _app_dta_sel,ax
+ mov eax,0100h
+ mov _dta_off,eax
+ mov _app_dta_off,eax
+ mov bptr [ebp+1Dh],1Ah
+ mov wptr [ebp+14h],0
+ call int21h ; set up new DTA buffer
+ add esp,32h
+ ret
+
+;=============================================================================
+initialize_mouse:
+ push ds
+ mov ds,_sel_zero
+ cmp dptr ds:[4*33h],0 ; check if mouse INT 33h is installed
+ pop ds
+ jz @@err ; if not, report warning
+ mov ax,0021h ; software reset mouse handler
+ int 33h
+ cmp ax,0021h ; check if function supported
+ jnz @@1 ; if yes, go on
+ xor ax,ax ; try hardware reset
+ int 33h
+ inc ax ; if failed, report warning
+ jnz @@err
+@@1: mov ax,0015h ; get mouse buffer size
+ int 33h
+ movzx eax,bx
+ cmp eax,_lobufsize
+ jae @@err
+ mov _mus_size,eax
+ push ds es
+ push cs
+ pop ds
+ push ss
+ pop es
+ mov esi,offs _mus_int_pm
+ mov edi,STACKSIZE*16-40h
+ mov ax,0303h
+ int 31h
+ pop es ds
+ jc dpmi_error
+ mov _mus_backoff,dx
+ mov _mus_backseg,cx
+ ret
+@@err: mov wptr _int33,0CF66h
+ mov ax,9004h
+ jmp report_error ; "mouse init failed"
+
+;=============================================================================
+install_client_ints:
+ mov ax,0205h
+ mov cx,cs
+
+ mov bl,10h
+ mov edx,offs _int10
+ int 31h
+ jc @@err
+
+ mov bl,21h
+ mov dx,offs _int21
+ int 31h
+ jc @@err
+
+ mov bl,23h
+ mov dx,offs _int23
+ int 31h
+ jc @@err
+
+ mov bl,33h
+ mov dx,offs _int33
+ int 31h
+ jc @@err
+
+
+ mov ax,0203h
+
+ mov bl,00h
+ mov dx,offs eh00
+ int 31h
+ jc @@err
+
+ mov bl,01h
+ mov dx,offs eh01
+ int 31h
+ jc @@err
+
+ mov bl,02h
+ mov dx,offs eh02
+ int 31h
+ jc @@err
+
+ mov bl,03h
+ mov dx,offs eh03
+ int 31h
+ jc @@err
+
+ mov bl,04h
+ mov dx,offs eh04
+ int 31h
+ jc @@err
+
+ mov bl,05h
+ mov dx,offs eh05
+ int 31h
+ jc @@err
+
+ mov bl,06h
+ mov dx,offs eh06
+ int 31h
+ jc @@err
+
+ mov bl,07h
+ mov dx,offs eh07
+ int 31h
+ jc @@err
+
+ mov bl,08h
+ mov dx,offs eh08
+ int 31h
+ jc @@err
+
+ mov bl,09h
+ mov dx,offs eh09
+ int 31h
+ jc @@err
+
+ mov bl,0Ah
+ mov dx,offs eh0A
+ int 31h
+ jc @@err
+
+ mov bl,0Bh
+ mov dx,offs eh0B
+ int 31h
+ jc @@err
+
+ mov bl,0Ch
+ mov dx,offs eh0C
+ int 31h
+ jc @@err
+
+ mov bl,0Dh
+ mov dx,offs eh0D
+ int 31h
+ jc @@err
+
+ mov bl,0Eh
+ mov dx,offs eh0E
+ int 31h
+
+ clc
+@@err: ret
+
+
+;=============================================================================
+uninstall_client_ints:
+ mov ax,0205h
+
+ mov bl,10h
+ mov cx, wptr cs:_int10_cs
+ mov edx,dptr cs:_int10_ip
+ int 31h
+
+ mov bl,21h
+ mov cx, wptr cs:_int21_cs
+ mov edx,dptr cs:_int21_ip
+ int 31h
+
+ mov bl,23h
+ mov cx, wptr cs:_int23_cs
+ mov edx,dptr cs:_int23_ip
+ int 31h
+
+ mov bl,33h
+ mov cx, wptr cs:_int33_cs
+ mov edx,dptr cs:_int33_ip
+ int 31h
+
+ mov ax,0203h ; restore default PM exception handlers
+ xor ebx,ebx
+@@0: mov cx,wptr cs:_exc_tab[ebx*8+4]
+ mov edx,dptr cs:_exc_tab[ebx*8+0]
+ int 31h
+ inc bl
+ cmp bl,15
+ jb @@0
+
+ clc
+@@done: ret
+
+;=============================================================================
+install_nullptr_protect:
+ cmp _sys_type,3
+ jz @@done
+ test _misc_byte,10000000b
+ jz @@done
+
+ xor eax,eax ; install null-pointer protection
+ mov dr6,eax
+ mov dr0,eax
+ add al,04h
+ mov dr1,eax
+ add al,04h
+ mov dr2,eax
+ add al,04h
+ mov dr3,eax
+ mov eax,0DDDD03FFh
+ mov dr7,eax
+@@done: ret
+
+;=============================================================================
+setup_selectors:
+ xor edi,edi ; base = 0
+ or ecx,-1 ; limit = 4GB
+ mov ax,cs ; get CS selector
+ lar dx,ax
+ mov dl,0C0h
+ xchg dh,dl
+ and dl,60h
+ or dl,92h
+ mov _acc_rights,dx ; set std selector access rights
+ call set_descriptor ; allocate descriptor
+ jc @@err
+ mov _sel_zero,ax
+ mov ax,0008h ; resize DS limit to 4GB
+ mov bx,ds ; this might be needed to access
+ mov cx,0FFFFh ; DOS buffer which is it self 64KB
+ mov dx,cx
+ int 31h
+ jc @@err
+ ret
+@@err: mov ax,4CFFh
+ int 21h
+
+
+
+
+
+;=============================================================================
+check_command_line:
+ mov di,80h
+ movzx cx,es:[di] ; get length of command line
+ jcxz @@err ; if zero, error
+ inc di ; offset to start of command line
+ mov al,20h
+ repe scasb ; look for non-space character
+ jz @@err ; if not found, error
+ dec di
+ inc cx
+ mov bx,di
+@@1: mov al,es:[di]
+ cmp al,09h ; look for TAB character
+ jz @@2
+ cmp al,0Dh ; look for CR character
+ jz @@2
+ cmp al,20h ; look for ' ' character
+ jz @@2
+ inc di
+ loop @@1
+@@2: mov cx,di
+ mov si,bx ; SI = pointer to file name
+ mov di,bx ; DI = pointer to file name
+ sub cx,bx ; CX = file name length
+@@done: ret
+@@err: xor si,si
+ ret
+
+;=============================================================================
+remove_name_from_cmd:
+ call check_command_line
+ jz @@done
+ mov al,20h
+ rep stosb
+@@done: ret
+
+;=============================================================================
+check_if_fullname:
+ push ds es
+ call check_command_line
+ jz @@done
+ mov al,'\'
+ mov bx,cx
+ repne scasb
+ jcxz @@done
+ push ds es
+ pop ds es
+ mov cx,bx
+ mov di,offs start+40h
+ rep movsb
+ xor al,al
+ stosb
+@@full: pop es ds
+ stc
+ ret
+@@done: pop es ds
+ clc
+ ret
+
+;=============================================================================
+update_environment:
+ push ds es
+ call check_if_fullname ; check if full path provided
+ jc @@skip ; if yes, skip copying
+ mov ah,19h
+ int 21h ; get drive letter
+ mov dl,al
+ add al,'A'
+ mov bptr [start+40h],al ; set drive
+ mov wptr [start+41h],'\:'
+ inc dx
+ mov ah,47h
+ mov esi,offs start+43h
+ int 21h ; get current directory
+ push ds
+ pop es
+ xor al,al
+ mov di,si
+ mov cx,64
+ repne scasb ; get length of dir string
+ cmp bptr [di-2],'\'
+ jnz @@0
+ dec di
+@@0: mov bptr [di-1],'\'
+ mov si,offs start
+ mov cx,64
+@@1: lodsb
+ stosb
+ test al,al
+ loopne @@1
+@@skip: push ds
+ pop es
+ xor al,al
+ mov cx,-1
+ mov di,offs start+40h
+ repne scasb
+ not cx
+ mov bx,cx
+ pop es
+ push es
+ mov ax,es:[002Ch] ; get environment selector
+ test ax,ax ; check if selector is NULL
+ jz @@err ; if yes, jump to error
+ lar cx,ax
+ jnz @@err
+ mov es,ax
+ xor al,al
+ xor di,di
+ mov cx,-1
+@@2: repne scasb
+ scasb
+ jnz @@2
+ inc di
+ inc di
+ mov cx,-1
+ mov dx,di
+ repne scasb
+ not cx
+ cmp bx,cx
+ ja create_new_environment
+ mov cx,bx
+ mov di,dx
+ mov si,offs start+40h
+ rep movsb
+ pop es ds
+ ret
+@@err: mov ax,2000h
+ jmp report_error
+
+create_new_environment:
+ push bx
+ mov cx,-1
+ xor di,di
+@@1: repne scasb ; get size of environment
+ dec cx
+ scasb
+ jnz @@1
+ not cx
+ inc cx
+ inc cx
+ push cx
+ add bx,cx
+ shr bx,4
+ inc bx
+ mov ax,0100h
+ int 31h
+ pop cx
+ jc @@err
+ push es
+ pop ds
+ mov es,dx
+ xor si,si
+ xor di,di
+ rep movsb
+ pop cx
+ mov si,offs start+40h
+ push cs
+ pop ds
+ rep movsb
+ pop es ds
+ mov es:[002Ch],dx
+ ret
+@@err: mov ax,2000h
+ jmp report_error
+
+
+;=============================================================================
+open_exec:
+ push ds es
+ mov ax,es:[002Ch] ; get environment selector
+ test ax,ax ; check if selector is NULL
+ jz @@err ; if yes, jump to error
+ lar cx,ax
+ jnz @@err
+ mov es,ax
+ xor ax,ax
+ xor di,di
+ mov cx,0FFFFh
+@@1: repne scasb ; look for end of environment
+ scasb
+ jcxz @@err ; reached end of environment
+ jnz @@1
+ inc di
+ inc di
+ push ds es
+ pop ds es
+ push di
+ mov si,di
+ mov di,offs start
+@@2: lodsb
+ stosb
+ test al,al
+ jnz @@2
+ pop di
+ movzx edx,di ; DS:EDX = pointer to exec name
+ mov ax,3DC0h ; open file
+ int 21h
+ pop es ds
+ mov _exec_handle,ax ; store file handle
+ mov ax,2001h
+ jc file_error ; if error, jump
+ ret
+@@err: mov ax,2000h
+ jmp report_error
+
+
+
+
+;=============================================================================
+load_exec_header:
+ xor edx,edx ; DS:EDX = ptr
+ mov ecx,64 ; ECX = 64 bytes to load
+ mov _err_code,2002h ; "error in exec file"
+ call load_fs_block
+ cmp wptr fs:[0000h],'ZM' ; exec must be 'MZ' file type
+ jnz file_errorm
+ mov eax,fs:[003Ch] ; get start of 32-bit code
+ mov edx,fs:[0018h] ; get start of MZ reloc-table
+ mov _exec_start,eax
+ ret
+
+
+
+
+;=============================================================================
+open_extrn_exec:
+ push ds es
+ push ds es ; swap DS and ES
+ pop ds es
+ mov di,offs start ; copy application exec name
+ rep movsb
+ push es
+ pop ds
+ mov bptr [di],0
+ mov edx,offs start
+ mov ax,3DC0h
+ int 21h
+ jc @@1 ; if error opening, try ".EXE"
+ pop es ds
+ mov _exec_handle,ax
+ ret
+
+@@1: mov bx,offs start
+@@2: cmp bptr [bx],2Eh
+ stc
+ jz @@err
+ inc bx
+ cmp bx,di
+ jb @@2
+ mov eax,4558452Eh
+ cmp eax,[di-4]
+ stc
+ jz @@err
+ mov eax,6578652Eh
+ cmp eax,[di-4]
+ stc
+ jz @@err
+ mov [di],eax
+ mov bptr [di+4],0
+ mov ax,3DC0h
+ int 21h
+@@err: pop es ds
+ mov _exec_handle,ax
+ mov ax,3001h
+ jc file_error
+ ret
+
+
+;=============================================================================
+load_extrn_exec_header:
+ xor edx,edx ; DS:EDX = ptr
+ mov ecx,64 ; ECX = 64 bytes to load
+ mov _err_code,3002h ; "error in app file"
+ call load_fs_block
+ call seek_from_start ; move to file start
+
+ xor ebp,ebp
+ mov _exec_start,ebp ; default start of exec offset and
+ mov _app_off_datapages,ebp ; LE/LX data offset in file
+ cmp wptr fs:[0000h],'ZM' ; is exec 'MZ' file type
+ jnz search_for_le ; if not, search for known exec type
+ mov eax,fs:[0018h] ; MZ reloc-tab must be at offset 0040h
+ cmp ax,40h
+ jnz search_for_mz
+ mov eax,fs:[003Ch] ; if yes, get start of 32-bit code
+ test ax,ax ; check if it is bound
+ jz search_for_mz ; if not, search
+ mov _exec_start,eax
+ ret
+
+
+search_for_mz:
+ xor esi,esi
+@@0: movzx eax,wptr fs:[0004h] ; get pages in file
+ shl eax,9 ; *512
+ movzx ebx,wptr fs:[0002h] ; get bytes on last page
+ add eax,ebx
+ mov bx,fs:[0000h]
+ cmp bx,'ZM'
+ jz @@1
+ cmp bx,'WB'
+ jz @@2
+ jmp @@3
+@@1: sub eax,0200h
+@@2: mov esi,ebp
+ add ebp,eax
+ mov edx,ebp
+ call seek_from_start
+ mov ecx,64
+ xor edx,edx
+ call load_fs_block
+ test eax,eax
+ jnz @@0
+ mov ax,3003h
+ jmp file_error ; if zero, no app in file
+@@3: mov bx,fs:[0000h]
+ cmp bx,'EL'
+ jz @@4
+ cmp bx,'XL'
+ jz @@4
+ cmp bx,'CL'
+ jz @@4
+ cmp bx,'EP'
+ jz @@4
+ mov edx,ebp
+ call seek_from_start
+ call search_for_le
+@@4: cmp eax,esi
+ jz @@5
+ mov edx,esi
+ add eax,10h
+ add edx,10h
+ and al,0F0h
+ and dl,0F0h
+ cmp eax,edx
+ jz @@5
+ mov _exec_start,ebp
+ mov _app_off_datapages,esi
+@@5: ret
+
+search_for_le:
+@@1: mov edx,_lobufzero ; DS:EDX = current ptr
+ mov ecx,_lobufsize ; ECX = bytes to load
+ call load_gs_block
+ test ax,ax ; check if no bytes read
+ mov ax,3003h
+ jz file_error ; if true, no app in file
+ shr cx,1
+@@2: mov ax,gs:[edx+0]
+ mov bx,gs:[edx+2]
+ test bx,bx
+ jnz @@4
+ cmp ax,'EL' ; 'LE' type
+ jz @@3
+ cmp ax,'XL' ; 'LX' type
+ jz @@3
+ cmp ax,'CL' ; 'LC' type
+ jz @@3
+ cmp ax,'PE' ; 'PE' type
+ jz @@3
+@@4: add edx,2
+ add ebp,2 ; increment pointer in file
+ loop @@2
+ jmp @@1
+@@3: ret
+
+
+
+
+
+;=============================================================================
+close_exec:
+ mov bx,cs:_exec_handle
+ mov ah,3Eh
+ int 21h
+ ret
+
+
+;=============================================================================
+seek_from_start:
+ push bx ecx edx eax
+ mov ecx,edx
+ shr ecx,16
+ mov bx,cs:_exec_handle
+ mov ax,4200h
+ int 21h
+ pop eax edx ecx bx
+ jc file_errorm
+ ret
+
+
+;=============================================================================
+load_fs_block:
+ push bx ds fs
+ pop ds
+ jmp @load_block
+load_gs_block:
+ push bx ds gs
+ pop ds
+@load_block:
+ mov bx,cs:_exec_handle
+ mov ah,3Fh
+ int 21h
+ pop ds bx
+ jc file_errorm
+ ret
+
+
+;=============================================================================
+verbose_getmem:
+ pop bp
+ mov ax,0FF90h
+ int 21h
+ shr eax,10
+ test eax,0FFFF0000h
+ mov dx,offs v_msg04
+ jz @@1
+ mov dx,offs v_msg05
+ shr eax,10
+@@1: push dx
+ push ax
+ mov ah,48h
+ mov bx,-1
+ int 21h
+ shr bx,6
+ push bx
+ jmp bp
+
+verbose_showsys:
+ test _misc_byte2,00010000b
+ jz @@done
+ call verbose_getmem
+ movzx eax,_sys_type
+ lea eax,v_msg02[eax*4+eax]
+ push ax
+ movzx ax,_cpu_type
+ imul ax,100
+ add ax,86
+ push ax
+ mov dx,offs v_msg01
+ call prints
+ add sp,10
+@@done: ret
+
+verbose_showloadhdr:
+ test _misc_byte2,00010000b
+ jz @@done
+ movzx eax,_app_type
+ lea eax,v_msg03[eax*2+eax]
+ push ax
+ push offs start
+ mov dx,offs v_msg10
+ call prints
+ add sp,4
+@@done: ret
+
+verbose_showloadobj:
+ test _misc_byte2,00010000b
+ jz @@done
+ pushad
+ mov ax,dx
+ shr edx,16
+ shl ebx,12
+ push dx
+ push ax
+ push ebp
+ push ebx
+ push edi
+ push cx
+ mov dx,offs v_msg11
+ call prints
+ add sp,18
+ popad
+@@done: ret
+
+verbose_showstartup:
+ test _misc_byte2,00010000b
+ jz @@done
+ push wptr _seg_env
+ push wptr es:[002Ch]
+ push wptr _sel_es
+ call verbose_getmem
+ mov eax,_app_eip
+ sub eax,_unreloc_eip
+ push eax
+ push wptr _app_eip_object
+ push offs excmsgB
+ push dptr _app_esp
+ push wptr _sel32_ss
+ push dptr _app_eip
+ push wptr _sel32_cs
+ mov dx,offs v_msg12
+ call prints
+ add sp,32
+@@done: ret
+
+
+win_focus_vm: ; Windows 9x - set focus on specified VM
+ test _misc_byte2,00000010b
+ jz @@done
+ xor bx,bx
+ mov ax,168Bh
+ int 2Fh
+@@done: ret
+
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/client/strings.asm b/dos32a/src/dos32a/text/client/strings.asm
--- a/dos32a/src/dos32a/text/client/strings.asm false
+++ b/dos32a/src/dos32a/text/client/strings.asm bd8829fe63241db333e5d3a39488ea8a7fa5f07c02e5e93372b034749f7ab05c5aee575fba19757fa645f78418216c7f763b084f3f6c360d6944b60ec300d126
@@ -0,0 +1,339 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+PushState
+
+
+.8086
+;=============================================================================
+; report_error: displays error code(AX) and error message
+; report_errorm: retreives error code from memory
+;
+report_errorm:
+ mov ax,cs:_err_code
+;
+; note: this function may autimatically terminate the client
+;
+report_error:
+ push bx ds
+ cmp cs:_sel_ds,0
+ jnz @@1
+ mov ds,cs:_seg_ds
+ jmp @@2
+@@1: mov ds,cs:_sel_ds
+@@2: xor bx,bx
+@@3: cmp ah,g_errtab[bx] ; check Global error #
+ jz @@4 ; if found, jump
+ cmp bptr [bx],0FFh
+ jz @@done
+ add bx,4
+ jmp @@3
+
+@@4: cmp g_errtab[bx+1],1 ; check if warning
+ jnz @@5 ; if not, jump
+ test _misc_byte,00000001b ; check if report warnings on
+ jz @@done ; if not, done
+@@5: push ax cx dx
+ push bx
+ mov bl,g_errtab[bx+1]
+ mov bh,0
+ mov cx,bx
+ add bx,bx ; BX = error header #
+ mov dx,h_errtab[bx] ; DX = Header error string
+ pop bx
+
+ push di si ; SI, DI = event. parameters
+ mov si,wptr g_errtab[bx+2] ; SI = Local error offset
+ mov bl,al
+ mov bh,0
+ add bx,bx ; BX = Local error #
+ mov di,[bx+si] ; DX = Local error string
+ test di,di
+ jz @@6
+ push ax
+ call prints
+ pop ax
+ mov dx,di
+ call prints
+ call printcr
+@@6: pop si di
+ cmp cl,1
+ jnz @@exit
+ pop dx cx ax
+@@done: pop ds bx
+ ret
+
+@@exit: mov al,-1
+ cmp _sel_cs,0
+ jnz @@0
+ jmp exit86
+@@0: jmp exit386
+
+
+
+
+.8086
+;=============================================================================
+; display copyright message and version number
+;
+copyright:
+ test _misc_byte2,00001000b
+ jz @@done
+ mov ax,_version
+ mov bx,offs ver_msg
+ mov si,offs cpr_msg
+ push ax
+ mov al,ah
+ aam
+ add al,30h
+ mov [bx+0],al
+ pop ax
+ aam
+ add ax,3030h
+ mov [bx+2],ah
+ mov [bx+4],al
+ mov cx,offs cpr_end - offs cpr_msg
+@@1: lodsb
+ push cx
+ xor bx,bx
+ mov ah,0Eh
+ int 10h
+ pop cx
+ loop @@1
+@@done: ret
+
+
+
+.8086
+;=============================================================================
+; Console I/O Routines (a la printf...)
+;=============================================================================
+STRSIZE = 0100h
+
+@char db 0,0
+@crlf db cre
+
+;=============================================================================
+; Print character in AL
+;
+printc:
+ push dx
+ mov @char,al
+ mov dx,offs @char
+ jmp @prnt
+
+;=============================================================================
+; Print NewLine (CR,LF)
+;
+printcr:
+ push dx
+ mov dx,offs @crlf
+@prnt: call prints
+ pop dx
+ ret
+
+;=============================================================================
+; Print string
+; DX = offset
+; ... = arguments pushed on stack
+;
+prints:
+ push ax bx cx dx si di bp ds es
+ push ss
+ pop es
+ mov bp,sp
+ sub sp,STRSIZE
+ add bp,2*10 ; BP -> argument list
+ mov si,dx ; DS:SI -> string
+ mov di,sp ; ES:DI -> space for formatted string
+ push di
+@@loop: lodsb
+ cmp al,'%'
+ jz @@args
+ cmp al,'$'
+ jnz @@next
+ mov al,'?'
+@@next: stosb
+ test al,al
+ jnz @@loop
+ pop di
+ call writes
+ add sp,STRSIZE
+ pop es ds bp di si dx cx bx ax
+ ret
+@@args: lodsb
+ cmp al,'%'
+ jz @@next
+ cmp al,'c' ; char
+ jz @@c
+ cmp al,'s' ; string
+ jz @@s
+ cmp al,'b' ; byte
+ jz @@b
+ cmp al,'w' ; word
+ jz @@w
+ cmp al,'l' ; long
+ jz @@l
+ cmp al,'d' ; decimal
+ jz @@d
+ jmp @@next ; unrecognized
+@@c: mov al,[bp]
+ add bp,2
+ jmp @@next
+@@s: mov bx,[bp]
+ add bp,2
+@@s0: mov al,[bx]
+ inc bx
+ test al,al
+ jz @@loop
+ cmp al,'$'
+ jnz @@s1
+ mov al,'?'
+@@s1: stosb
+ jmp @@s0
+@@b: mov ah,[bp]
+ add bp,2
+ mov cx,2
+ call @@hex
+ jmp @@loop
+@@w: mov ax,[bp]
+ add bp,2
+ mov cx,4
+ call @@hex
+ jmp @@loop
+@@l: mov ax,[bp+2]
+ mov cx,4
+ call @@hex
+ mov ax,[bp]
+ add bp,4
+ mov cx,4
+ call @@hex
+ jmp @@loop
+@@d: mov ax,[bp]
+ add bp,2
+ xor cx,cx
+ call @@dec
+ jmp @@loop
+@@hex: rol ax,4
+ mov bl,al
+ and bl,0Fh
+ add bl,30h
+ cmp bl,39h
+ jbe @@hex0
+ add bl,07h
+@@hex0: xchg ax,bx
+ stosb
+ xchg ax,bx
+ loop @@hex
+ ret
+@@dec: mov bx,10000
+ call @@dec0
+ mov bx,1000
+ call @@dec0
+ mov bx,100
+ call @@dec0
+ mov bx,10
+ call @@dec0
+ jmp @@dec2
+@@dec0: xor dx,dx
+ div bx
+ test ax,ax
+ jz @@dec1
+ inc cx
+@@dec1: test cx,cx
+ jz @@dec3
+@@dec2: add al,30h
+ stosb
+@@dec3: mov ax,dx
+ ret
+
+;=============================================================================
+writes: xor al,al
+ mov dx,di
+ mov cx,-1
+ repne scasb
+ dec di
+ push es
+ pop ds
+ mov ax,0924h
+ mov [di],al
+ cmp cs:_sel_cs,0
+ jnz @@0
+ int 21h
+ ret
+
+.386p
+;-----------------------------------------------------------------------------
+@@0: push ebp
+ sub esp,32h
+ mov ebp,esp
+ mov [ebp+1Ch],ax
+ mov [ebp+14h],dx
+ mov ax,cs:_seg_ss
+ mov [ebp+24h],ax
+ call int21h
+ add esp,32h
+ pop ebp
+ ret
+
+
+
+
+.386p
+;=============================================================================
+file_error:
+ mov si,offs start
+ jmp report_error
+file_errorm:
+ mov si,offs start
+ jmp report_errorm
+dos_error:
+ mov si,ax
+ mov ax,8002h
+ jmp common_error
+dpmi_error:
+ mov si,ax
+ mov ax,8003h
+common_error:
+ cli
+ lss esp,fptr cs:_sel_esp
+ jmp report_error
+
+
+PopState
diff -uNr a/dos32a/src/dos32a/text/include.asm b/dos32a/src/dos32a/text/include.asm
--- a/dos32a/src/dos32a/text/include.asm false
+++ b/dos32a/src/dos32a/text/include.asm 5cd2dc61279847939808d44479cbec8974139d712642af7418805cf5c4e559a2f92da743a33e02f2324c1817dbbb1a140ee01aeb1ca926beed23ec1b57172317
@@ -0,0 +1,46 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+cr equ 0Dh, 0Ah
+cre equ 0Dh, 0Ah ,0
+offs equ offset
+bptr equ byte ptr
+wptr equ word ptr
+dptr equ dword ptr
+fptr equ fword ptr
diff -uNr a/dos32a/src/dos32a/text/kernel/detect.asm b/dos32a/src/dos32a/text/kernel/detect.asm
--- a/dos32a/src/dos32a/text/kernel/detect.asm false
+++ b/dos32a/src/dos32a/text/kernel/detect.asm 36e0e6789ede354c5b348b6336d89a0b543d5fbf60e689cad9e37851bf8598dae139dcc8bc08e59fd3ebfae9033d24698820c41046b2bc51cf9cf0f1dc6db380
@@ -0,0 +1,424 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; Get Protected Mode Info
+;=========================
+; In: Nothing
+; Out: AX = return code:
+; 0000h = DOS version below 4.00
+; 0001h = no 80386+ detected
+; 0002h = system already in protected mode and no VCPI or DPMI found
+; 0003h = DPMI - host is not 32bit
+; 0004h = VCPI - incompatible PIC mappings
+; CF = set on error, if no error:
+; BX = number of paragraphs needed for protected mode data (may be 0)
+; CL = processor type
+; CH = protected mode type:
+; 00h = raw
+; 01h = XMS
+; 02h = VCPI
+; 03h = DPMI
+; DX = size of removable Kernel body (in bytes)
+; DI = base of removable Kernel body
+;=============================================================================
+ Align 4
+@area1_db label byte
+@area1_dw label word
+@area1_dd label dword
+
+pm32_info:
+ cld
+ push ds es ; preserve registers
+ push cs cs ; DS = CS (_KERNEL)
+ pop ds es
+
+ call cpu_detect ; get processor type
+ cmp al,3 ; check if processor is 80386+
+ mov ax,1 ; error in case no 80386+
+ jae @@0
+ jmp @@fail
+
+@@0: call fpu_detect ; detect/initialize FPU
+
+ mov ah,30h ; get DOS version
+ int 21h
+ cmp al,4 ; if DOS version is below 4.0
+ mov ax,0 ; return with error code 0
+ jb @@fail
+
+ mov ax,4300h ; check for XMS
+ int 2Fh
+ cmp al,80h
+ jnz @@1 ; jump if XMS not found
+
+ push es
+ mov ax,4310h
+ int 2Fh
+ mov xms_call[0],bx ; store XMS driver address
+ mov xms_call[2],es
+ mov ah,30h
+ int 21h ; HIMEM.SYS bug fix
+ mov ah,88h
+ xor bx,bx
+ call dptr xms_call ; get XMS v3 free mem in KB
+ test bl,bl ; if no XMS v3, use v2
+ jz @@xms1
+ mov ah,08h
+ call dptr xms_call ; get XMS v2 free mem in KB
+ movzx eax,ax
+@@xms1: mov xms_data,eax
+ pop es
+
+ pushf
+ pop ax ; AX = flags
+ and ah,0CFh ; reset IOPL to 0
+ push ax ; (can only be done at CPL 0)
+ popf ; reload flags with new IOPL
+ pushf
+ pop ax ; AX = flags
+ test ah,30h ; is IOPL still 0?
+ jz @@4 ; if yes, omit VCPI/DPMI tests
+
+@@1: call @@detect_VCPI ; check for VCPI first
+ call @@detect_DPMI ; check for DPMI second
+
+ smsw ax ; AX = machine status word
+ and al,1 ; is system in protected mode?
+ mov ax,2 ; error code in case in protected mode
+ jnz @@fail ; if in protected mode, fail
+
+@@4: cmp xms_data,0 ; check if XMS_mem is present
+ setnz ch ; if yes, pmode type is XMS
+ mov bx,80h ; BX = memory requirement (IDT)
+
+@@vcpi: movzx ax,pm32_rmstacks ; size of real mode stack area
+ imul ax,pm32_rmstacklen
+ add bx,ax
+
+ movzx ax,pm32_pmstacks ; size of protected mode stack area
+ imul ax,pm32_pmstacklen
+ add bx,ax
+
+ movzx ax,pm32_callbacks ; size of callbacks
+ imul ax,25
+ add ax,0Fh
+ shr ax,4
+ add bx,ax
+
+ mov ax,pm32_selectors ; size of GDT
+ add ax,SYSSELECTORS+1
+ shr ax,1
+ add bx,ax
+
+@@done: xor ax,ax ; success code, also clear carry flag
+ mov cl,cputype
+ mov pmodetype,ch ; store pmode type
+
+ mov dx,offs @kernel_end - offs @kernel_beg
+ mov di,offs @kernel_beg
+
+@@exit: pop es ds ; restore other registers
+ retf ; return
+
+@@fail: stc ; carry set, failed
+ jmp @@exit
+
+
+
+
+;=============================================================================
+@@detect_DPMI: ; detect a DPMI host
+ pop bp
+
+ mov ax,1687h ; check for DPMI
+ int 2Fh
+ test ax,ax ; DPMI present?
+ jnz @@d0 ; if no, exit routine
+
+ mov ax,1 ; error code in case no processor 386+
+ cmp cl,3 ; is processor 386+? (redundant)
+ jb @@fail ; if no, fail
+
+ mov al,3 ; error code in case DPMI not 32bit
+ test bl,1 ; is DPMI 32bit?
+ jz @@fail ; if no, fail
+
+ mov wptr dpmiepmode[0],di ; store DPMI initial mode switch addx
+ mov wptr dpmiepmode[2],es
+ mov bx,si ; BX = number of paragraphs needed
+ mov ch,3 ; pmode type is 3 (DPMI)
+ jmp @@done ; go to done ok
+@@d0: jmp bp ; return to calling routine
+
+
+;=============================================================================
+@@detect_VCPI: ; detect a VCPI server
+ pop bp
+
+ xor ax,ax ; get INT 67h vector
+ mov es,ax
+ mov ax,es:[67h*4]
+ or ax,es:[67h*4+2] ; is vector NULL
+ jz @@d0 ; if yes, no VCPI
+
+ mov ax,0DE00h ; call VCPI installation check
+ int 67h
+ test ah,ah ; AH returned as 0?
+ jnz @@d0 ; if no, no VCPI
+
+ mov ax,0DE0Ah ; get PIC mappings
+ int 67h
+ mov picmaster,bl
+ mov picslave,cl
+ mov ax,0004h ; error code 4 in case of exit
+ cmp bl,cl ; BL=CL, only one PIC available
+ je @@fail
+ cmp bl,30h ; PICs mapped on system vectors?
+ je @@fail
+ cmp cl,30h
+ je @@fail
+ cmp cl,08h ; slave PIC shouldn't be mapped onto INT 08h
+ je @@fail
+ test bl,bl ; should not be mapped on INT 00h
+ je @@fail
+ test cl,cl
+ je @@fail
+
+ mov edx,xms_data ; EDX=get free XMS memory
+ mov ecx,edx ; ECX=free XMS memory in KB
+ jecxz @@v1 ; skip if none
+
+ test pm32_mode,00001000b ; check if VCPI+XMS alloc scheme
+ jz @@vA ; if not, jump (save some DOS memory)
+ call xms_allocmem ; alloc XMS memory in EDX
+ mov di,dx ; DI=handle
+ dec ax ; if AX=0001, no error occured
+ jz @@v1
+@@vA: xor ecx,ecx ; if error, XMS memory in ECX = 0
+
+@@v1: mov ax,0DE03h
+ int 67h ; EDX=free VCPI pages
+
+ push es ecx edx di
+ test pm32_mode,00000100b ; check if VCPI smart pagetable alloc
+ jz @@v1a ; no, use standard detection
+
+ mov ah,48h ; allocate 4K block of memory
+ mov bx,0100h ; for VCPI pagetable
+ int 21h
+ jc @@v1a ; INT 21h failed, use standard alloc
+
+ mov es,ax ; ES=returned segment
+ xor di,di ; DI=zero pointer
+ sub sp,8*3 ; DS:SI=pointer to structure
+ mov si,sp
+ push ds
+ push ss
+ pop ds
+ mov ax,0DE01h ; get PM interface
+ int 67h
+ pop ds
+ add sp,8*3 ; discard structure on stack
+ mov ah,49h ; discard pagetable and free DOS mem
+ int 21h
+ mov eax,1000h ; pagetable limit 4K
+ sub ax,di ; minus used part
+ shr ax,2 ; convert to 4K pages
+ jmp @@v1b
+
+@@v1a: xor eax,eax
+@@v1b: pop di edx ecx es
+
+ mov esi,ecx ; ECX=XMS free mem,EDX=VCPI free pages
+ shr esi,2 ; ESI=XMS_freemem/4 (to match 4Kpages)
+ lea esi,[edx+esi+3FFh] ; ESI=XMS_4Kmem+VCPI_4Kpages+4M_align
+ sub esi,eax ; minus free 0th pagetable space
+ jnc @@v1c ; just in case...
+ adc esi,eax
+@@v1c: shr esi,10 ; ESI=ESI/1024
+ jecxz @@v2
+
+ mov dx,di
+ mov ah,0Ah ; free what was allocated
+ call dptr xms_call
+@@v2: movzx ax,pm32_maxpages
+ cmp ax,si
+ jbe @@v3
+ mov ax,si
+
+@@v3: test ax,ax ; if no pages, check for DOS/32A
+ jnz @@v5
+ pushad
+ mov bp,sp
+ mov ax,0FF88h ; check if running under DOS/32A
+ int 21h
+ cmp eax,'ID32' ; if present, use the already alloc'ed pagetables
+ jnz @@v4
+ mov [bp+1Ch],si ; store pagetables in AX
+@@v4: popad
+
+@@v5: cmp al,64 ; limit the number of pagetables to
+ jbe @@v6 ; maximum 64, = 256MB
+ mov al,64
+@@v6: mov pagetables,al ; BX = VCPI page tables needed
+ add al,pm32_maxfpages ; + physical memory mappable pages
+ shl ax,8 ; 100h paragraphs per page table
+ add ax,100h+100h+0FFh+7+80h ; +page_dir+0th_page+align_buf+TSS+IDT
+ mov bx,ax
+ mov ch,2 ; pmode type is 2 (VCPI)
+ jmp @@vcpi ; go to figure other memory needed
+@@v0: jmp bp ; return to calling routine
+
+
+
+
+
+;=============================================================================
+cpu_detect: ; detect: 286, 386, 486, 586 etc
+ cli
+ mov cl,2 ; CL: cputype=2 (80286)
+ pushf
+ pop ax
+ or ax,0F000h
+ push ax
+ popf
+ pushf
+ pop ax
+ and ax,0F000h
+ jne @@1
+ jmp @@x1
+@@1: inc cl ; CPU = 80386
+ pushfd
+ pop eax
+ mov edx,eax
+ xor eax,00040000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ xor eax,edx
+ jne @@2
+ jmp @@x1
+@@2: inc cl ; CPU = 80486
+ push edx
+ popfd
+ pushfd
+ pushfd
+ pop eax
+ mov edx,eax
+ xor eax,00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ xor eax,edx
+ jne @@3
+ jmp @@x2
+@@3: xor eax,eax
+ db 0Fh, 0A2h ; CPUID
+ mov cpuidlvl,eax ; set CPUID level
+ mov eax,1
+ db 0Fh, 0A2h ; CPUID
+ and ah,0Fh
+ mov cl,ah
+@@x2: popfd
+ xor eax,eax
+ xor edx,edx
+@@x1: mov al,cl
+ mov cputype,al ; store processor type
+ sti
+ ret
+
+fpu_detect: ; detect 8087, 287, 387, 487 etc
+ push large 0
+ mov bp,sp
+ fninit
+ fnstcw wptr [bp+2]
+ mov ax,wptr [bp+2]
+ cmp ah,03h
+ jnz @@done ; done: no FPU present
+ mov wptr [bp],1
+ and wptr [bp+2],0FF7Fh
+ wait
+ fldcw wptr [bp+2]
+ fdisi
+ fstcw wptr [bp+2]
+ wait
+ test wptr [bp+2],0080h
+ jnz @@done ; done: 8087 is present
+ mov wptr [bp],2
+ fninit
+ wait
+ fld1
+ wait
+ fldz
+ wait
+ fdivp st(1),st
+ wait
+ fld st(0)
+ wait
+ fchs
+ wait
+ fcompp
+ wait
+ fnstsw ax
+ wait
+ fnclex
+ wait
+ sahf
+ jz @@done ; done: 80287 is present
+ mov wptr [bp],3
+ mov al,cputype
+ cmp al,4
+ jb @@done ; done: 80387 is present
+ mov bptr [bp],al ; done: 80487+ (build-in)
+@@done: pop eax
+ and eax,7
+ jz @@exit
+ mov cx,8
+@@loop: fldz ; set ST(0) to ST(7) to +ZERO
+ loop @@loop
+ finit ; reinitialize FPU
+@@exit: mov fputype,al
+ ret
+
+ Align 4
+@area1_end label byte
+
diff -uNr a/dos32a/src/dos32a/text/kernel/exit.asm b/dos32a/src/dos32a/text/kernel/exit.asm
--- a/dos32a/src/dos32a/text/kernel/exit.asm false
+++ b/dos32a/src/dos32a/text/kernel/exit.asm 17d172764e9b940676e174ec57a1e9f06646e5fd581215eb887be9332be29b62ea93255c0fcd9f99b21860708a63ab130c17c9d95d1c98efcc85ee107dbe282f
@@ -0,0 +1,173 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; Exit Protected Mode
+;=============================================================================
+
+int21h_pm:
+ cmp ah,4Ch ; watch for INT 21h AH=4Ch
+ jne @@done
+
+ cli
+ cld
+ push ax ; save error code in AL
+
+ mov ds,cs:seldata
+ mov es,selzero
+
+ mov eax,oldcr0 ; restore CR0
+ mov cr0,eax
+
+ mov eax,oldint1Bh ; restore critical INTs
+ mov es:[4*1Bh],eax
+ mov eax,oldint1Ch
+ mov es:[4*1Ch],eax
+ mov eax,oldint21h
+ mov es:[4*21h],eax
+ mov eax,oldint23h
+ mov es:[4*23h],eax
+ mov eax,oldint24h
+ mov es:[4*24h],eax
+ mov eax,oldint2Fh
+ mov es:[4*2Fh],eax
+
+ call mem_dealloc ; dealloc memory for current process
+ movzx bx,pmodetype ; appropriate exit routine
+ add bx,bx
+ call @@exit[bx] ; call cleanup routine on exit
+
+ pop ax ; restore AX
+@@done: jmp int_matrix+4*21h ; go to INT 21h redirection
+
+@@exit dw r_exit
+ dw x_exit
+ dw v_exit
+ dw d_exit
+
+
+; deallocate memory for this process (eg all blocks matching id32_process_id)
+;=============================================================================
+mem_dealloc:
+ cmp id32_process_id,0 ; no need in freeing memory when
+ jz @@done ; only one process is running
+
+ mov esi,mem_ptr
+ mov eax,mem_free
+ or eax,esi ; check if memory was allocated
+ jz @@done ; if not, we are done
+
+@@1: mov eax,es:[esi+04h]
+ mov edx,es:[esi+08h]
+ btr eax,31
+ cmp edx,dptr id32_process_id ; block allocated from this process
+ jnz @@2 ; if not, jump
+ mov es:[esi+04h],eax ; otherwise set this block as free
+@@2: lea esi,[esi+eax+10h] ; get ptr to next memory block
+ cmp esi,mem_top ; check if at top of memory
+ jb @@1 ; if not, loop
+ push ds es
+ pop ds
+ call int31_linkfreeblocks
+ pop ds
+@@done: ret
+
+
+; RAW exit prologue
+;=============================================================================
+r_exit: mov eax,oldint15h ; put back old INT 15h handler
+ mov es:[4*15h],eax
+ ret
+
+; XMS exit prologue
+;=============================================================================
+x_exit: call xms_dealloc
+ mov ah,A20_state ; reset A20 gate to initial state
+ and ah,1
+ xor ah,1 ; calculate appropriate function num
+ add ah,3
+ jmp xms_call_pm
+
+; VCPI exit prologue
+;=============================================================================
+v_exit: mov cx,vcpi_allocmem ; check if memory was allocated
+ mov esi,pagetablefree
+ jcxz xms_dealloc ; if no VCPI memory was allocated, try XMS
+
+@@0: mov edx,es:[esi]
+ add esi,4
+ and dx,0F000h
+ mov ax,0DE05h
+ call fptr vcpi_calleip
+ loop @@0
+
+ mov eax,vcpi_cr3 ; reload CR3 to flush page cache
+ mov cr3,eax
+
+;-----------------------------------------------------------------------------
+xms_dealloc: ; XMS deallocate memory
+ mov dx,xms_handle ; check if memory was allocated
+ test dx,dx
+ jz d_exit ; if not, done
+
+@@0: mov ah,0Dh ; unlock XMS memory
+ call xms_call_pm
+ mov ah,0Ah ; free XMS memory
+xms_call_pm:
+ push ss
+ pop es
+ sub esp,32h
+ mov edi,esp
+ xor ecx,ecx
+ mov [esp+14h],dx ; DX
+ mov [esp+1Ch],ax ; AX
+ mov eax,dptr xms_call ; real mode CS:IP
+ mov [esp+20h],cx ; clear flags
+ mov [esp+2Eh],ecx ; clear SS:SP
+ mov [esp+2Ah],eax ; put in structure
+ xor bx,bx
+ mov ax,0301h
+ int 31h
+ add esp,32h
+
+; DPMI exit prologue (actually there is no such thing)
+;=============================================================================
+d_exit: ret
+
+
diff -uNr a/dos32a/src/dos32a/text/kernel/init.asm b/dos32a/src/dos32a/text/kernel/init.asm
--- a/dos32a/src/dos32a/text/kernel/init.asm false
+++ b/dos32a/src/dos32a/text/kernel/init.asm f1e2a860c622bee6310eb184f72e802a660975dd37269a71387e7e06a43b71bd8d8b9e501873eacb1701b155e8955bd9d18ef46f5751e120e283ebbccd9567ba
@@ -0,0 +1,1072 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; Initialize Protected Mode
+;===========================
+; In: BX = client version
+; DX = offset of Client's Safe Exit Routine (used by exception handler)
+; ES = real mode segment for protected mode data (ignored if not needed)
+;
+; Out: AX = return code:
+; 0005h = DPMI - could not enter 32bit protected mode
+; 0006h = DPMI - could not allocate needed selectors
+; 0007h = could not enable A20 gate
+; BX = kernel code selector
+; ECX = amount of allocated memory (in bytes)
+; EDX = pointer to allocated memory (from 0)
+; SI = current process ID (when spawned)
+; DI = version of the previously installed DOS/32A (0 if none)
+; CF = set on error, if no error:
+; ESP = high word clear
+; CS = 16bit selector for real mode CS with limit of 64k
+; SS = selector for real mode SS with limit of 64k
+; DS = selector for real mode DS with limit of 64k
+; ES = selector for PSP with limit of 100h
+; FS = 0 (NULL selector)
+; GS = 0 (NULL selector)
+;=============================================================================
+
+pm32_init:
+ cld
+ pushad
+ push ds
+ push cs ; DS = _KERNEL
+ pop ds
+
+ xor eax,eax
+ mov kernel_code,cs
+ mov client_version,bx
+ mov client_call[0],dx
+ mov ax,cs ; set base addx of _KERNEL
+ shl eax,4
+ mov codebase,eax
+ add vcpi_gdtaddx,eax ; adjust addresses for VCPI structure
+ add vcpi_idtaddx,eax
+ add vcpistrucaddx,eax
+ btr pm32_maxextmem,31 ; limit extended memory to 2GB
+
+ push es ; clear @area1 memory block
+ push cs
+ pop es
+ mov di,offs @area1_db
+ mov cx,(offs @area1_end - offs @area1_db) /2
+ xor ax,ax
+ rep stosw
+ pop es
+
+ mov bp,sp
+ mov [bp+02h],ax ; set DI to 0 (prev D32A version)
+ mov ax,0FF88h ; detect if DOS/32A is present
+ int 21h
+ cmp eax,'ID32' ; check if we were spawned
+ jnz @@1 ; if not, jump
+
+ mov [bp+02h],bx ; set DI to prev. version of D32A
+ cmp bx,client_version ; check versions
+ jnz @@1 ; if not equal, jump
+ mov id32_mem_free,ecx
+ mov id32_mem_ptr,edx
+ mov id32_mem_vcpi,edi
+ shr esi,16 ; get previous process id
+ inc si ; increment (make it this process id)
+ mov id32_process_id,si ; store the new, current process id
+ mov pm32_maxextmem,0 ; use already allocated memory
+
+@@1: movzx bx,pmodetype ; jump to appropriate init code
+ add bx,bx
+ jmp @@init[bx]
+
+@@init dw r_init
+ dw x_init
+ dw v_init
+ dw d_init
+
+
+;=============================================================================
+dvxr_init: ; DPMI/VCPI/XMS/raw common init tail
+ xor ax,ax ; allocate selector for return code
+ mov cx,1
+ int 31h
+ jnc @@0
+@@err: mov ax,4CFFh ; could not allocate selector
+ int 21h ; terminate immediately
+
+@@0: mov bp,sp
+ mov bx,ax ; new code descriptor for return
+ mov ax,0007h ; set base address of calling segment
+ mov dx,[bp+36]
+ mov cx,dx
+ shl dx,4
+ shr cx,12
+ int 31h
+ jc @@err
+
+ inc ax ; set selector limit to 64k
+ xor cx,cx
+ mov dx,0FFFFh
+ int 31h
+ jc @@err
+
+ inc ax ; set selector type and access rights
+ mov dx,cs ; get DPL from current CPL, and access
+ lar cx,dx ; rights and type from current CS
+ shr cx,8 ; type is already 16bit code segment
+ int 31h
+ jc @@err
+
+ mov [bp+36],bx ; store selector in return address
+
+ cmp cs:pmodetype,3 ; if DPMI, no need in client_call
+ jz @@1 ; DPMI will handle all the exceptions
+ push ds ; store client's code selector
+ mov ds,cs:seldata
+ mov client_call[2],bx
+ pop ds
+
+@@1: xor bx,bx ; init successful, carry clear
+
+;-----------------------------------------------------------------------------
+init_done: ; return with return code
+ mov [bp+1Eh],bx ; set AX=return code
+ jc @@1
+ mov eax,cs:mem_free
+ mov edx,cs:mem_ptr
+ mov [bp+1Ah],eax ; set ECX=amount of allocated memory
+ mov [bp+16h],edx ; set EDX=pointer to allocated memory
+ or eax,edx ; if allocated some memory, exit
+ jnz @@1
+ call init_done_id32
+@@1: pop ds
+ popad
+ mov bx,cs ; return BX=kernel code selector
+ mov si,cs:id32_process_id ; return SI=current process ID
+ cld
+ retf
+
+init_done_id32:
+ cmp cs:pmodetype,3 ; if under DPMI, exit
+ jz @@done
+ mov ds,cs:seldata
+ cmp id32_process_id,0 ; if this is the first process (mom)
+ jz @@done ; then we're done
+
+ mov eax,id32_mem_free
+ mov edx,id32_mem_ptr
+ mov [bp+1Ah],eax ; set ECX=amount of allocated memory
+ mov [bp+16h],edx ; set EDX=pointer to allocated memory
+ mov mem_free,eax
+ mov mem_ptr,edx
+ lea ecx,[eax+10h] ; size of memory + 16 bytes
+ lea eax,[ecx+edx] ; top of memory
+ mov mem_top,eax
+
+ mov al,pmodetype ; now check if running under VCPI
+ cmp al,0
+ jz @@done
+ cmp al,1
+ jz @@done
+ push es
+ mov esi,id32_mem_vcpi ; import pagetables from prev process
+ mov edi,pagetablefree
+ mov es,selzero
+ mov ds,selzero
+ shr ecx,12
+ rep movs dptr es:[edi],[esi]
+ pop es
+@@done: ret
+
+
+
+
+
+;=============================================================================
+;****** NOTE: DPMI host will provide all INT 31h functions and
+; will be responsible for any memory allocation.
+
+d_init: pop ds ; get original caller DS from stack
+ mov ax,1 ; enter DPMI protected mode
+ call cs:dpmiepmode
+ push ds ; put DS back onto stack
+ jnc dvxr_init ; error? if not, go on with init
+ mov bx,6 ; error entering protected mode, set
+ cmp ax,8011h ; error code and abort
+ stc
+ jz init_done
+ dec bx ; error code 5, not 6
+ jmp init_done
+
+
+
+
+
+ Align 16
+@kernel_beg label byte ;** Begin of kernel code
+@callback_data label byte ;** CALLBACK DATA Structure
+
+;=============================================================================
+v_init: xor eax,eax
+ mov ax,es ; align data area on page boundary
+ add ax,00FFh
+ xor al,al
+ mov es,ax
+ mov dx,ax ; set base and top of page table area
+
+ shl eax,4
+ add eax,1000h ; skip Page Directory
+ mov pagetablebase,eax ; 0th PageTable linear address
+ add eax,1000h ; skip 0th PageTable
+ movzx ecx,pagetables
+ shl ecx,12
+ add eax,ecx
+ mov pagetabletop,eax ; Nth PageTable linear adress
+ mov phystablebase,eax ; set base and top of physical pages
+ movzx ecx,pm32_maxfpages
+ shl ecx,12
+ add eax,ecx
+ mov phystabletop,eax
+
+ xor di,di
+ xor eax,eax ; clear PageDir and 0th PageTable
+ mov cx,0800h
+ rep stos dptr es:[di]
+
+ mov gs,dx ; GS = segment of Page Directory
+ mov ax,dx
+ add ax,0100h
+ mov es,ax ; ES = segment of 0th Page Table
+ mov fs,ax ; FS = segment of 0th Page Table
+
+ sub sp,8*3 ;***NOTE: stack will be restored later
+ mov si,sp ; DS:SI = ptr to VCPI structure
+ xor di,di ; ES:DI = ptr to imported 0th PageTab
+ push ds
+ push ss
+ pop ds
+ mov ax,0DE01h ; get VCPI protected mode interface
+ int 67h
+ pop ds
+
+ push di ;** store DI = ptr to free entry
+ mov vcpi_calleip,ebx ; store protected mode VCPI call EIP
+@@1: and bptr es:[di+1],0F1h ; clear bits 9-11 in imported PageTab
+ sub di,4
+ jnc @@1
+
+ mov cx,dx ; get physical address of PageDir
+ shr cx,8
+ mov ax,0DE06h
+ int 67h
+ and dx,0F000h
+ mov vcpi_cr3,edx ; set VCPI CR3 register
+;
+; Map VCPI 0th PageTable into our PageDir
+;
+ mov cx,es ; CX = 0th PageTable addr
+ shr cx,8 ; convert to PageTable number
+ mov ax,0DE06h ; VCPI get pagetable Physical Addr
+ int 67h
+ and dh,0F0h
+ mov dl,07h
+ mov gs:[0000h],edx ; store address in PageDir
+;
+; Map the rest of our custom PageTables into our PageDir
+;
+ mov ax,es ; advance to the 1st PageTable
+ add ax,0100h
+ mov es,ax
+
+ mov si,ax ; SI = segment of 1st PageTable
+ mov al,pagetables ; AL = PageTables to alloc
+ mov ebx,1 ; EBX = index ptr into PageDir
+ call vcpi_setup_pagetables ; initialize VCPI PageDir and PageTabs
+;
+; Map PageTables for phys. mapping into PageDir
+;
+ mov ax,gs ; advance PageDir to 8000_0000h addr
+ add ax,80h
+ mov gs,ax
+
+ mov al,pm32_maxfpages ; phystables to allocate
+ xor ebx,ebx ; EBX = index ptr into PageDir
+ call vcpi_setup_pagetables ; initialize VCPI PageDir and PageTabs
+ pop di ;** restore DI = ptr to free entry
+
+ xor eax,eax
+ test pm32_mode,00000100b ; if smart pagetables is off
+ jnz @@2 ; then align pagetablefree to
+ mov di,1000h ; first allocated free pagetable
+@@2: mov ax,di ; set base of usable page table area
+ add eax,pagetablebase
+ mov pagetablefree,eax
+
+ push si es
+ call vcpi_alloc_ems ; allocate VCPI memory
+ pop es si
+
+ push si ; SI = segment of TSS (for later use)
+ xor di,di ; clear TSS with all 0, not really
+ mov cx,34h ; needed, but just to be safe
+ xor ax,ax
+ rep stos word ptr es:[di]
+ mov eax,vcpi_cr3 ; set CR3 in TSS
+ mov es:[1Ch],eax
+ mov dword ptr es:[64h],680000h ; set offset of I/O permission bitmap and clear T bit
+ add si,7 ; increment next data area ptr
+ mov es,si
+ mov rmtopmswrout,offs v_rmtopmsw ; set VCPI mode switch addresses
+ mov pmtormswrout,offs v_pmtormsw
+ jmp vxr_init ; go to VCPI/XMS/raw continue init
+
+
+vcpi_setup_pagetables:
+ push bp
+ movzx bp,al ; BP = PageTables to alloc
+ test bp,bp
+ jz @@done
+@@1: mov cx,si ; CX = PageTable segment
+ shr cx,8 ; convert to PageTable number
+ mov ax,0DE06h ; VCPI get PageTable Physical Addr
+ int 67h
+ and dh,0F0h
+ mov dl,07h
+ mov gs:[ebx*4],edx ; store address in PageDir
+ add si,0100h ; increment pagetable segment (4K)
+ mov es,si
+ xor di,di ; clear PageTable
+ xor eax,eax
+ mov cx,0400h
+ rep stos dptr es:[di]
+ inc bx ; increment index in PageDir
+ dec bp ; decrement PageTable counter
+ jnz @@1 ; if no, loop
+@@done: pop bp
+ ret
+
+vcpi_alloc_ems:
+ push fs
+ pop es ; ES:DI ptr to free entry in 0th page
+ movzx eax,pagetables ; calculate free linear space
+ shl eax,22 ; convert PageTables to bytes (*4M)
+ mov ecx,1000h
+ sub cx,di ; ECX = unused space in 0th PageTable
+ and cl,0FCh
+ shl ecx,10 ; convert 4K pages to bytes
+ add eax,ecx ; EAX = available linear space (bytes)
+ mov ecx,pm32_maxextmem ; ECX = memory to allocate (bytes)
+ cmp ecx,eax ; choose smallest value
+ jbe @@0
+ mov ecx,eax
+@@0: xor ebx,ebx ; EBX = counter of allocated pages
+ jecxz @@done ; if no memory to be allocated, done
+
+@@1: cmp di,1000h ; if NOT overflowing page (DX>4096)
+ jb @@2 ; then jump
+ mov ax,es ; else adjust ES:DI pointer to next PG
+ add ax,0100h
+ mov es,ax
+ xor di,di
+
+@@2: mov ax,0DE04h ; allocate 4K VCPI page
+ int 67h
+ test ah,ah ; check if error
+ jnz @@3 ; if yes, then we are done
+ and dh,0F0h ; clear avail bits
+ mov dl,07h ; set page as user/writeable/present
+ mov es:[di],edx ; store page addr in PageTable
+ add di,4 ; increment ptr into PageTable
+ inc bx ; increment allocated page counter
+ sub ecx,4096
+ ja @@1 ; loop until no more pages to allocate
+
+@@3: mov vcpi_allocmem,bx ; store alloc pages for deallocation
+ cmp ecx,4096 ; is there memory left to allocate
+ jb @@4 ; no, then done
+ test pm32_mode,00001000b ; check if VCPI+XMS allocation scheme
+ jz @@4 ; enabled, if not jump
+ call vcpi_alloc_xms ; try XMS memory allocation
+
+@@4: shl ebx,12 ; convert allocated pages to bytes
+ jz @@done ; allocated any memory? if no, jump
+ mov mem_free,ebx ; store amount of allocated memory
+ mov eax,pagetablefree ; figure out address of memory
+ sub eax,pagetablebase
+ shl eax,10
+ mov mem_ptr,eax
+@@done: ret
+
+vcpi_alloc_xms:
+ push ebx ; save EBX counter
+ shr ecx,10 ; convert bytes to KB
+ and cl,0FCh ; mask ECX to match 4KB pages
+
+@@1: mov edx,ecx
+ jecxz @@done ; if EDX=0, no mem to be allocated
+ call xms_allocmem ; XMS allocate extended memory
+ dec ax
+ jz @@2 ; if got memory, jump
+ sub ecx,4 ; try less memory, subtract 4K page
+ jnc @@1 ; loop til there is no memory to alloc
+ jmp @@done ; no memory allocated, done
+
+@@2: mov xms_handle,dx ; store handle
+ mov ah,0Ch ; XMS lock extended memory
+ call dptr xms_call
+ dec ax
+ jz @@3 ; if locked memory, jump
+ xor dx,dx
+ xchg dx,xms_handle ; reset xms_handle: no mem allocated
+ mov ah,0Ah ; free allocated XMS memory
+ call dptr xms_call
+ jmp @@done
+
+@@3: shl edx,16 ; convert DX:BX to EDX pointer
+ mov dx,bx
+ shr ecx,2 ; ECX=memory allocated in 4K blocks
+ movzx eax,cx
+ pop ebx
+ add ebx,eax ; adjust allocated page number
+ push ebx
+
+@@4: cmp di,1000h ; if NOT overflowing page (DX>4096)
+ jb @@5 ; then jump
+ mov ax,es ; else adjust ES:DI pointer to next PG
+ add ax,0100h
+ mov es,ax
+ xor di,di
+
+@@5: and dh,0F0h ; clear avail bits
+ mov dl,07h ; set page as user/writeable/present
+ mov es:[di],edx ; set linear memory addr
+ add di,4 ; increment pointer
+ add edx,4096 ; increment address
+ loop @@4
+
+@@done: pop ebx ; restore EBX counter
+ ret
+
+
+
+
+
+;=============================================================================
+x_init: mov ah,07h ; query A20
+ call dptr xms_call
+ mov A20_state,al
+ mov ah,03h ; global enable A20
+ call dptr xms_call
+ mov bx,0007h ; error code 0007h in case of error
+ dec ax ; error enabling A20?
+ stc
+ jnz init_done ; if yes, exit with error 0007h
+
+ mov eax,xms_data ; get KB of free XMS memory
+ mov edx,pm32_maxextmem ; get requested amount of memory
+ shr edx,10 ; convert to KB
+ cmp edx,eax
+ jbe @@1
+ mov edx,eax
+
+@@1: mov esi,edx
+ test edx,edx ; check if no extended memory is to
+ jz @@done ; be allocated, if so, then jump
+
+ call xms_allocmem ; allocate EDX KB memory
+ dec ax
+ jnz @@done ; no memory has been allocated
+ mov xms_handle,dx ; store handle
+
+ mov ah,0Ch ; lock extended memory
+ call dptr xms_call
+ dec ax
+ jz @@2 ; if no error, jump
+ xor dx,dx
+ xchg dx,xms_handle ; reset handle: no mem allocated
+ mov ah,0Ah ; free allocated extended memory
+ call dptr xms_call
+ jmp @@done
+
+@@2: mov wptr mem_ptr[0],bx ; store linear pointer to memory
+ mov wptr mem_ptr[2],dx
+ shl esi,10 ; convert to bytes
+ mov dptr mem_free,esi ; store amount of memory allocated
+@@done: jmp xr_init ; go to XMS/raw continue init
+
+
+
+
+
+;=============================================================================
+r_init: call enable_A20 ; enable A20
+ mov bx,0007h ; error code 0007h
+ jc init_done ; exit if error enabling A20
+
+ push es
+
+ push ss
+ pop es
+ xor eax,eax
+ mov ebx,eax
+ mov ecx,eax
+ mov edi,eax
+
+ sub sp,32
+ mov di,sp
+
+@@0: mov cl,20
+ mov eax,0000E820h ; try INT 15h, AX=0E820h allocation scheme
+ mov edx,534D4150h ; "SMAP"
+ int 15h
+ jc @@noE820 ; cover all the possible
+ jcxz @@noE820 ; exit paths
+ cmp eax,534D4150h ; "SMAP"
+ jnz @@noE820
+
+ xor eax,eax
+ cmp eax,es:[di+04h] ; hiword: base address (must be 0)
+ jnz @@0
+ cmp eax,es:[di+0Ch] ; hiword: length in bytes (must be 0)
+ jnz @@0
+ inc ax
+ cmp eax,es:[di+10h] ; type: memory, available to OS (must be 1)
+ jnz @@0
+
+ mov edx,es:[di+00h] ; loword: base address
+ cmp edx,00100000h
+ jnz @@0
+ mov eax,es:[di+08h] ; loword: length in bytes
+ add edx,eax
+
+ add sp,32
+ pop es
+ jmp @@temper
+
+@@noE820:
+ add sp,32
+ pop es
+
+ xor bx,bx
+ xor cx,cx
+ xor dx,dx
+ mov ax,0E801h ; try INT 15h, AX=0E801h allocation scheme
+ stc
+ int 15h
+ jc @@noE801
+
+ mov di,cx ; test if configured memory is > 0
+ or di,dx
+ jz @@useE801 ; if not, use extended memory (AX,BX)
+
+ mov ax,cx ; use configured memory (CX,DX)
+ mov bx,dx
+
+@@useE801:
+ mov di,ax ; test if extended memory is > 0
+ or di,bx
+ jz @@noE801 ; if not, skip E801
+
+ movzx eax,ax ; EBX holds extended/configured memory above 16M in 64K blocks
+ movzx ebx,bx ; EAX holds extended/configured memory in range 1..16M in 1K blocks
+ shl ebx,6
+ add eax,ebx ; compute total memory as 1K blocks
+ jmp @@calcmem
+
+@@noE801:
+ xor eax,eax ; try INT 15h, AX=88h allocation scheme
+ mov ah,88h ; how much extended memory free
+ int 15h
+ test ax,ax ; if none, done with raw init
+ jz xr_init
+
+@@calcmem:
+ shl eax,10 ; EAX = size of memory (bytes)
+ lea edx,[eax+100000h] ; EDX = base of memory
+
+@@temper:
+ cmp eax,pm32_maxextmem ; check how much memory to alloc
+ jbe @@1 ; pick lowest value
+ mov eax,pm32_maxextmem
+
+@@1: add eax, 000003FFh ; align memory to KB
+ and eax,0FFFFFC00h
+ sub edx,eax
+ mov mem_ptr,edx ; store extended memory base
+ mov mem_free,eax ; store size of extended memory
+ shr eax,10 ; convert to KB
+ test eax,0ffff0000h
+ jz @@2
+ or ax,0ffffh
+@@2: mov mem_used,ax ; set used memory
+
+xr_init: ; XMS/raw common init tail
+ mov wptr picslave,0870h
+ mov rmtopmswrout,offs xr_rmtopmsw ; set XMS/raw mode switch addresses
+ mov pmtormswrout,offs xr_pmtormsw
+
+
+
+
+;=============================================================================
+vxr_init: ; VCPI/XMS/raw common init tail
+ call install_ints ; install interrupts and except handl.
+
+ xor eax,eax
+ mov ax,es
+ mov idtseg,ax ; set IDT segment base address
+ mov ebx,eax
+ shl ebx,4
+ mov idtbase,ebx ; set IDT linear base address
+
+ add ax,80h ; size of IDT
+ mov rmstackbase,ax
+
+ movzx bx,pm32_rmstacks ; set top and base of real mode stack
+ mov cx,pm32_rmstacklen
+ mov rmstacklen,cx
+ imul bx,cx ; area for interrupt redirection
+ add ax,bx
+ mov rmstacktop,ax
+ mov rmstacktop2,ax
+
+ shl eax,4
+ mov pmstackbase,eax ; set next data area to end of RM stk
+
+ movzx ebx,pm32_pmstacks ; set protected mode stack area top
+ movzx ecx,pm32_pmstacklen ; for callbacks
+ shl ecx,4
+ mov pmstacklen,ecx ; protected mode stack size in bytes
+ imul ebx,ecx
+ add eax,ebx
+ mov pmstacktop,eax ; protected mode stack area top
+ mov pmstacktop2,eax
+
+ mov callbackbase,eax ; top of stacks is base of callbacks
+ shr eax,4 ; BX = seg of callback area
+ mov callbackseg,ax
+ mov es,ax ; ES = seg of callback area
+
+ call allocate_callbacks ; allocate callbacks
+
+ xor eax,eax
+ mov ax,es ; set GDT base address
+ mov gdtseg,ax ; store segment of GDT
+ shl eax,4
+ mov gdtbase,eax
+ movzx ecx,pm32_selectors ; set GDT limit
+ lea ecx,[8*ecx+8*SYSSELECTORS-1]
+ mov gdtlimit,cx
+ xor di,di ; clear GDT with all 0
+ inc cx
+ shr cx,1
+ xor eax,eax
+ rep stos wptr es:[di]
+
+ cmp pmodetype,2 ; if under VCPI, do VCPI GDT set up
+ jne @@f0
+ pop ax ; restore TSS seg from stack
+ shl eax,4 ; set up TSS selector in GDT
+ mov es:[SELVCPITSS+2],eax
+ mov bptr es:[SELVCPITSS],67h ; limit
+ mov bptr es:[SELVCPITSS+5],89h ; access rights
+ add eax,64h-4*9 ; unused part of TSS is also
+ mov vcpiswitchstack,eax ; temporary switch stack
+ mov di,SELVCPICODE ; copy 3 VCPI descriptors from stack
+ mov si,sp ; to GDT
+ mov cl,4*3
+ rep movs wptr es:[di],ss:[si]
+ add sp,8*3 ;***NOTE: (VCPI) adjust stack
+
+@@f0: mov ax,0FFFFh
+ mov wptr es:[SELZERO],ax ; set SELZERO limit
+ mov wptr es:[SELCALLBACK],ax ; set callback DS limit
+ mov ax,0DF92h
+ mov wptr es:[SELZERO+5],ax ; set SELZERO rights
+ mov wptr es:[SELCALLBACK+5],ax ; set callback DS rights
+
+ mov ax,cs ; AX = base
+ mov bx,SELCODE ; BX = index to SELCODE descriptor
+ mov cx,0FFFFh ; CX = limit (64k)
+ mov dx,109Ah ; DX = access rights
+ call vxr_initsetdsc
+ mov bx,SELDATA ; BX = index to SELDATA descriptor
+ mov dx,1092h ; DX = access rights
+ call vxr_initsetdsc
+ mov ax,0040h
+ mov bx,SELBIOSDATA
+ call vxr_initsetdsc
+
+ mov bx,8*SYSSELECTORS ; BX = base of free descriptors
+ push bx ; store selector
+ mov ax,ss ; set caller SS descriptor
+ mov dx,5092h
+ call vxr_initsetdsc
+ mov ax,[bp] ; set caller DS descriptor
+ mov [bp],bx ; put DS selector on stack for exit
+ call vxr_initsetdsc
+
+ push bx ; get PSP segment
+ mov ah,51h
+ int 21h
+ mov si,bx ; SI = PSP segment
+ pop bx
+
+ push ds
+ mov ds,si ; set caller environment descriptor
+ mov ax,ds:[002Ch]
+ test ax,ax ; is environment seg 0?
+ jz @@f1 ; if yes, dont convert to descriptor
+ mov ds:[002Ch],bx ; store selector value in PSP
+ call vxr_initsetdsc
+ mov ax,si ; set caller PSP descriptor
+@@f1: mov cx,0FFh ; limit is 100h bytes
+ call vxr_initsetdsc
+ pop ds
+
+ sub bx,8
+ mov cx,bx ; CX = ES descriptor, PSP
+ pop dx ; DX = SS descriptor, from stack
+ mov ax,SELZERO ; AX = DS descriptor, SELZERO
+ movzx ebx,sp ; EBX = SP, current SP - same stack
+ mov si,SELCODE ; target CS is SELCODE, same segment
+ mov edi,offs @@swpm ; target EIP
+ jmp rmtopmswrout ; jump to mode switch routine
+;
+; now we are in protected mode
+;
+@@swpm: cli
+ mov edi,cs:codebase ; EDI = offset of _KERNEL from 0
+
+ mov eax,cs:vcpi_cr3 ; EAX = CR3
+ mov cr3,eax ; reload CR3 register to flush TLB
+
+ mov eax,cr0
+ mov oldcr0[edi],eax ; preserve original CR0
+
+ xor eax,eax
+ mov cr2,eax ; reset CR2 page fault addr register
+
+ cmp eax,cs:cpuidlvl ; check CPUID level
+ jz @@0 ; if not available, jump
+ mov al,1
+ db 0Fh, 0A2h ; CPUID
+ test edx,01000000h ; test if FXSAVE/FXRSTOR available (FXSR bit)
+ jz @@0 ; if not, jump
+ mov eax,cr4 ; load CR4 into EAX
+ or ax,0200h ; set OSFXFR bit
+ mov cr4,eax ; reload CR4 (note: OSXMMEXCPT is left unchanged)
+ mov eax,cr0 ; load CR0 in EAX
+ and al,0F9h ; clear EM & MP bits
+ mov cr0,eax ; reload CR0
+
+@@0: clts
+
+ mov eax,ds:[4*15h] ; preserve INT 15h
+ mov oldint15h[edi],eax
+ mov eax,ds:[4*1Bh] ; preserve INT 1Bh - (CTRL-Break)
+ mov oldint1Bh[edi],eax
+ mov eax,ds:[4*1Ch] ; preserve INT 1Ch - (timer ticks)
+ mov oldint1Ch[edi],eax
+ mov eax,ds:[4*21h] ; preserve INT 21h - (DOS API)
+ mov oldint21h[edi],eax
+ mov eax,ds:[4*23h] ; preserve INT 23h - (DOS CTRL-C)
+ mov oldint23h[edi],eax
+ mov eax,ds:[4*24h] ; preserve INT 24h - (DOS Critical handler)
+ mov oldint24h[edi],eax
+ mov eax,ds:[4*2Fh] ; preserve INT 2Fh - (Multiplex)
+ mov oldint2Fh[edi],eax
+
+ mov ax,cs:kernel_code ; install real mode INT 21h handler
+ shl eax,16
+ mov ax,offs int21h_rm
+ mov ds:[4*21h],eax
+
+ cmp cs:pmodetype,0 ; is system raw?
+ jnz @@1 ; if not, we are done
+ cmp cs:id32_process_id,0 ; is this the only instance?
+ jnz @@1 ; if not, we are done
+
+ mov ax,offs int15h_rm
+ mov ds:[4*15h],eax ; install real mode INT 15h handler
+
+@@1: push ds es edi
+ push cs
+ pop ds ; DS = code base (executable)
+ mov es,seldata ; ES = code base (writeable)
+ mov ax,0303h
+ mov esi,offs int1Bh ;** NOTE: EDI points to init_code
+ mov edi,offs @callback_data+00h ;** EDI = callback data structure
+ int 31h ;** which will be used only once
+ push cx dx ;** at startup.
+ mov si,offs int1Ch
+ mov di,offs @callback_data+32h
+ int 31h
+ push cx dx
+ mov si,offs int23h
+ mov di,offs @callback_data+64h
+ int 31h
+ push cx dx
+ mov si,offs int24h
+ mov di,offs @callback_data+96h
+ int 31h
+ push cx dx
+ mov ds,seldata ; DS = data selector
+ pop newint24h ; set allocated callbacks
+ pop newint23h
+ pop newint1Ch
+ pop newint1Bh
+ pop edi es ds
+
+ xor eax,eax
+ mov ebx,cs:mem_ptr ; EBX = base of extended memory
+ mov ecx,cs:mem_free ; ECX = size of extended memory
+ mov edx,ebx ; align ptr to memory on para boundary
+ add ebx,0Fh
+ and bl,0F0h
+ mov esi,ebx
+ sub esi,edx ; get the difference
+ add esi,10h ; plus 16 bytes for 1st block header
+ sub ecx,esi ; reduce size of free memory
+ ja @@2 ; if no error, jump
+ mov mem_ptr[edi],eax ; not enough memory even for one
+ mov mem_free[edi],eax ; memory block header, done now
+ jmp @@done
+
+@@2: mov eax,12345678h ; header id
+ mov [ebx+00h],eax ; set header id
+ mov [ebx+0Ch],eax ; set header id
+ movzx eax,id32_process_id ; load current process id
+ mov [ebx+08h],eax ; set current process id
+ mov [ebx+04h],ecx ; set first block unused/currentsize
+ lea edx,[ebx+ecx+10h] ; get pointer to next block (mem_top)
+ mov mem_top[edi],edx ; set top of memory
+ mov mem_ptr[edi],ebx ; set base of memory
+ mov mem_free[edi],ecx ; set size of memory
+
+@@done: sti
+ jmp dvxr_init ; go to DPMI/VCPI/XMS/raw init tail
+
+
+
+
+
+
+
+;=============================================================================
+; Initialize interrupt tables
+;
+; The setup is performed once at startup. The goal is to reduce
+; run-time complexity of the interrupt handling code by collecting
+; as much info as possible about system config and doing init here.
+;
+install_ints:
+ xor di,di ; set up IDT
+ xor ecx,ecx
+ mov dx,wptr picslave
+;
+; initialize IDT, point all INTs into int_matrix call table
+;
+@@1: lea eax,[ecx*4 + SELCODE*10000h + offs int_matrix]
+ stos dptr es:[di]
+ mov eax,8E00h ; interrupt gate type (IF=0)
+ mov bl,cl ; isolate high 5 bits of int num
+ and bl,0F8h
+ test cl,0F0h ; one of the low 16 interrupts?
+ jz @@2 ; if yes, store as interrupt gate
+ cmp bl,dl ; one of the high IRQs?
+ je @@2 ; if yes, store as interrupt gate
+ cmp bl,dh ; one of the low IRQs?
+ je @@2 ; if yes, store as interrupt gate
+ mov ax,8F00h ; set to trap gate type (IF=unchanged)
+@@2: stos dptr es:[di]
+ inc cl ; increment interrupt number
+ jnz @@1 ; loop if more interrupts to go
+;
+; initialize IDT, redirect INT 21h and INT 31h
+;
+ mov wptr es:[8*21h],offs int21h_pm ; protected mode INT 21h
+ mov wptr es:[8*31h],offs int31h_pm ; protected mode INT 31h
+
+ push ds es
+ push ds
+ pop es ; ES = DS
+;
+; initialize real-mode IRQ table, copy vectors from real-mode Interrupt table
+;
+ xor ax,ax
+ mov ds,ax
+ mov di,offs irqtab_rm
+ movzx si,dh
+ shl si,2
+ mov cx,8
+ rep movs dptr es:[di],ds:[si]
+ movzx si,dl
+ shl si,2
+ mov cl,8
+ rep movs dptr es:[di],ds:[si]
+;
+; initialize protected-mode Exception table, point exctab_pm entries into exc_matrix call table
+;
+ mov cl,16
+ mov di,offs exctab_pm
+ mov ax,offs exc_matrix
+@@3: stos wptr es:[di]
+ mov wptr es:[di+2],SELCODE
+ add di,6
+ add ax,4
+ loop @@3
+
+ pop es ds
+;
+; install INTs 00..0Eh (exceptions),
+; modify call targets in int_matrix call table such that they point to irq_fail
+;
+ mov ax,offs irq_fail ; offset of fail routine
+ sub ax,offs int_matrix+4 ; calculate offset displacement
+ mov di,offs int_matrix+2 ; DI = pointer into CALL matrix
+ mov cl,15
+@@l1: mov ds:[di],ax ; modify CALL address
+ sub ax,4 ; PUSH + CALL = 4 bytes
+ add di,4
+ loop @@l1
+;
+; install IRQs 0..15 (PIC dependent),
+; modify call targets in int_matrix call table such that they point to either irq_normal or irq_tester
+;
+ movzx dx,picmaster ; install IRQ 0-7 (INT 08-0Fh)
+ call setup_irqs
+ movzx dx,picslave ; install IRQ 8-15 (INT 70-77h)
+ call setup_irqs
+;
+; install INT 2 (special setup to handle co-proc)
+; modify call target of INT 02h in int_matrix call table such that it points to int_main
+;
+; mov ax,(offs int_main) - (offs int_matrix+4) - 02h*4
+; mov wptr int_matrix[02h*4+2],ax ; install INT 02h (NMI)
+
+;
+; install IRQ 7 (special setup to handle supurious signals)
+; modify call target of INT 0Fh in int_matrix call table such that it points to irq_normal
+;
+ cmp picmaster,10h ; setup IRQ 7, damn it!
+ jae @@done
+ mov ax,(offs irq_normal) - (offs int_matrix+4) - 0Fh*4
+ mov wptr int_matrix[0Fh*4+2],ax ; install INT 0Fh (IRQ 7)
+
+@@done: ret
+
+
+;-----------------------------------------------------------------------------
+setup_irqs:
+ cmp dl,0Fh
+ mov ax,offs irq_tester ; if DX is in range INT 00..0Fh
+ jbe @@0 ; install as IRQ check handler
+ mov ax,offs irq_normal ; else no IRQ check is needed
+@@0: shl dx,2
+ sub ax,offs int_matrix+4
+ sub ax,dx
+ mov di,offs int_matrix+2
+ add di,dx
+ mov cl,8 ; 8 IRQs to go
+@@loop: mov ds:[di],ax
+ sub ax,4 ; PUSH + CALL is 4 bytes
+ add di,4 ; next entry in int_matrix call table
+ loop @@loop
+ ret
+
+
+;-----------------------------------------------------------------------------
+allocate_callbacks:
+ movzx cx,pm32_callbacks ; CL = number of callbacks
+ jcxz @@done ; if no, done with this part
+ xor di,di ; location within callback seg
+ mov ax,6866h
+ mov dx,kernel_code
+
+ push ds
+ push es
+ pop ds
+@@1: mov wptr ds:[di],6066h ; PUSHAD instruction
+ mov bptr ds:[di+2],ah ; PUSH WORD instruction
+ mov wptr ds:[di+3],0 ; immediate 0 used as free flag
+ mov wptr ds:[di+5],ax ; PUSH DWORD instruction
+ mov bptr ds:[di+11],0B9h ; MOV CX,? instruction
+ mov wptr ds:[di+14],ax ; PUSH DWORD instruction
+ mov bptr ds:[di+20],0EAh ; JMP FAR PTR ?:? intruction
+ mov wptr ds:[di+21],offs callback
+ mov wptr ds:[di+23],dx
+ add di,25 ; increment ptr to callback
+ loop @@1 ; if more callbacks to do, loop
+ pop ds
+
+ add di,0Fh ; align next data area on paragraph
+ shr di,4
+ mov ax,es
+ add ax,di
+ mov es,ax ; set ES to base of next data area
+@@done: ret
+
+
+;-----------------------------------------------------------------------------
+vxr_initsetdsc: ; set descriptor for VCPI/XMS/raw init
+ push ax
+ movzx eax,ax ; EAX = base of segment
+ shl eax,4
+ mov wptr es:[bx],cx ; limit = CX
+ mov dptr es:[bx+2],eax ; base address = EAX
+ mov wptr es:[bx+5],dx ; access rights = DX
+ add bx,8 ; increment descriptor index
+ pop ax
+ ret
+
+
+;-----------------------------------------------------------------------------
+xms_allocmem:
+ push edi
+ mov edi,edx
+ mov ah,89h
+ call dptr xms_call
+ cmp ax,0001h
+ jz @@ok
+ mov dx,di
+ mov ah,09h
+ call dptr xms_call
+@@ok: pop edi
+ ret
+
+
diff -uNr a/dos32a/src/dos32a/text/kernel/int31h.asm b/dos32a/src/dos32a/text/kernel/int31h.asm
--- a/dos32a/src/dos32a/text/kernel/int31h.asm false
+++ b/dos32a/src/dos32a/text/kernel/int31h.asm d52f90a508196384327f644b88c734078e61942dd930c95f1f8934b1eb2f8102d826725a5838274568920e21f7ff5d90f87c5927a7a61baa305546e43b01b05f
@@ -0,0 +1,1923 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; INT 31h INTERFACE
+;=============================================================================
+
+ evendata
+;=============================================================================
+int31h_tab label word
+ dw 0300h ; simulate real mode int
+ dw int31h_0300
+ dw 0301h ; call rm proc RETF
+ dw int31h_0301
+ dw 0302h ; call rm proc IRET
+ dw int31h_0302
+;---------------------------------------------------------------------
+ dw 0000h ; allocate descriptor
+ dw int31h_0000
+ dw 0001h ; free descriptor
+ dw int31h_0001
+ dw 0002h ; map seg to sel
+ dw int31h_0002
+ dw 0003h ; get sel increment value
+ dw int31h_0003
+ dw 0006h ; get sel base addr
+ dw int31h_0006
+ dw 0007h ; set sel base addr
+ dw int31h_0007
+ dw 0008h ; set sel limit
+ dw int31h_0008
+ dw 0009h ; set sel access rights
+ dw int31h_0009
+ dw 000Ah ; create alias sel
+ dw int31h_000A
+ dw 000Bh ; get descriptor
+ dw int31h_000B
+ dw 000Ch ; set descriptor
+ dw int31h_000C
+ dw 000Eh ; get multi descriptors
+ dw int31h_000E
+ dw 000Fh ; set multi descriptors
+ dw int31h_000F
+;---------------------------------------------------------------------
+ dw 0100h ; alloc DOS memory
+ dw int31h_0100
+ dw 0101h ; free DOS memory
+ dw int31h_0101
+ dw 0102h ; resize DOS memory
+ dw int31h_0102
+;---------------------------------------------------------------------
+ dw 0200h ; get real mode int
+ dw int31h_0200
+ dw 0201h ; set real mode int
+ dw int31h_0201
+ dw 0202h ; get pm exception vector
+ dw int31h_0202
+ dw 0203h ; set pm exception vector
+ dw int31h_0203
+ dw 0204h ; get pm int
+ dw int31h_0204
+ dw 0205h ; set pm int
+ dw int31h_0205
+;---------------------------------------------------------------------
+ dw 0303h ; alloc callback
+ dw int31h_0303
+ dw 0304h ; free callback
+ dw int31h_0304
+ dw 0305h ; get state save/restore addr
+ dw int31h_0305
+ dw 0306h ; get raw mode switch addr
+ dw int31h_0306
+;---------------------------------------------------------------------
+ dw 0400h ; get DPMI version
+ dw int31h_0400
+;---------------------------------------------------------------------
+ dw 0500h ; get free mem info
+ dw int31h_0500
+ dw 0501h ; alloc mem
+ dw int31h_0501
+ dw 0502h ; free mem
+ dw int31h_0502
+ dw 0503h ; resize mem
+ dw int31h_0503
+ dw 050Ah ; get linear mem block and size
+ dw int31h_050A
+;---------------------------------------------------------------------
+ dw 0600h ; lock linear region *VM*
+ dw int31h_0600
+ dw 0601h ; unlock linear region *VM*
+ dw int31h_0601
+ dw 0602h ; Mark Real Mode Region as Pageable *VM*
+ dw int31h_0602
+ dw 0603h ; Relock Real Mode Region *VM*
+ dw int31h_0603
+ dw 0604h ; get page size *VM*
+ dw int31h_0604
+;---------------------------------------------------------------------
+ dw 0702h ; mark page *VM*
+ dw int31h_0702
+ dw 0703h ; discard page *VM*
+ dw int31h_0703
+;---------------------------------------------------------------------
+ dw 0800h ; physical mem mapping *VM*
+ dw int31h_0800
+ dw 0801h ; free mapped mem *VM*
+ dw int31h_0801
+;---------------------------------------------------------------------
+ dw 0900h ; get/disable VIS
+ dw int31h_0900
+ dw 0901h ; get/enable VIS
+ dw int31h_0901
+ dw 0902h ; get VIS
+ dw int31h_0902
+;---------------------------------------------------------------------
+ dw 0A00h ; vendor specific
+ dw int31h_0A00
+;---------------------------------------------------------------------
+; dw 0B00h ; Set Debug Watchpoint
+; dw int31h_0B00
+; dw 0B01h ; Clear Debug Watchpoint
+; dw int31h_0B01
+; dw 0B02h ; Get State of Debug Watchpoint
+; dw int31h_0B02
+; dw 0B03h ; Reset Debug Watchpoint
+; dw int31h_0B03
+;---------------------------------------------------------------------
+ dw 0E00h ; get FPU status
+ dw int31h_0E00
+ dw 0E01h ; set FPU emulation
+ dw int31h_0E01
+;---------------------------------------------------------------------
+ dw 0EEFFh ; PMODE/W compatible call
+ dw int31h_EEFF
+;---------------------------------------------------------------------
+int31h_end label word
+
+
+
+
+;=============================================================================
+int31h_pm:
+ cli
+ cld
+ push ds es fs gs ; push registers on stack
+ pushad
+
+ push bx
+ mov ds,cs:seldata ; DS -> KERNEL
+
+ cmp ax,int31h_cache[0] ; check if function # is in cache
+ mov bx,int31h_cache[2] ; retrieve cached target addr
+ je @@2 ; if cached, jump
+
+ xor bx,bx ; do a linear search
+@@0: cmp ax,int31h_tab[bx] ; found function # ?
+ je @@1 ; if yes, jump
+
+ add bx,4 ; advance to next entry
+ cmp bx,(offs int31h_end - offs int31h_tab) ; end of table?
+ jb @@0 ; loop until end of table
+
+ pop bx ; no function found
+ jmp int31fail8001 ; exit with error 8001h
+
+@@1: mov bx,int31h_tab[bx+2] ; get address of the appropriate handler
+ mov int31h_cache[0],ax ; store function # in cache
+ mov int31h_cache[2],bx ; store function addr in cache
+
+@@2: mov ds,selzero ; DS -> 0 (beginning of memory)
+ xchg bx,[esp] ; store target addr & restore BX
+ ret
+
+
+;-----------------------------------------------------------------------------
+int31fail8001: ; INT 31h return fail with error 8001h
+ mov al,01h
+ jmp int31failx
+int31fail8010: ; INT 31h return fail with error 8010h
+ mov al,10h
+ jmp int31failx
+int31fail8011: ; INT 31h return fail with error 8011h
+ mov al,11h
+ jmp int31failx
+int31fail8012: ; INT 31h return fail with error 8012h
+ mov al,12h
+ jmp int31failx
+int31fail8013: ; INT 31h return fail with error 8013h
+ mov al,13h
+ jmp int31failx
+int31fail8015: ; INT 31h return fail with error 8015h
+ mov al,15h
+ jmp int31failx
+int31fail8016: ; INT 31h return fail with error 8016h
+ mov al,16h
+ jmp int31failx
+int31fail8021: ; INT 31h return fail with error 8021h
+ mov al,21h
+ jmp int31failx
+int31fail8022: ; INT 31h return fail with error 8022h
+ mov al,22h
+ jmp int31failx
+int31fail8023: ; INT 31h return fail with error 8023h
+ mov al,23h
+ jmp int31failx
+int31fail8024: ; INT 31h return fail with error 8024h
+ mov al,24h
+ jmp int31failx
+int31fail8025: ; INT 31h return fail with error 8025h
+ mov al,25h
+
+int31failx:
+ mov ah,80h
+ mov [esp+28],ax ; set AX on stack to 8010h for POPAD
+ jmp int31fail
+
+
+
+;-----------------------------------------------------------------------------
+int31failbx: ; INT 31h return fail with BX,AX
+ mov wptr [esp+16],bx ; put BX onto stack for POPAD
+ jmp int31failax
+int31failcx: ; INT 31h return fail with CX,AX
+ mov wptr [esp+24],cx ; put CX onto stack for POPAD
+int31failax: ; INT 31h return fail with AX
+ mov wptr [esp+28],ax ; put AX onto stack for POPAD
+
+
+;-----------------------------------------------------------------------------
+int31fail: ; INT 31h return fail, pop all regs
+ popad
+ pop gs fs es ds
+int31failnopop: ; INT 31h return fail with carry set
+ or bptr [esp+8],01h ; set carry in EFLAGS on stack
+ iretd
+
+
+;-----------------------------------------------------------------------------
+int31okedx: ; INT 31h return ok with EDX,CX,AX
+ mov [esp+20],edx ; put EDX onto stack for POPAD
+ jmp int31okcx
+int31okdx: ; INT 31h return ok with DX,CX,AX
+ mov [esp+20],dx ; put DX onto stack for POPAD
+ jmp int31okcx
+int31oksinoax: ; INT 31h return ok SI,DI,BX,CX
+ mov ax,[esp+28] ; get old value of AX for restore
+int31oksi: ; INT 31h return ok SI,DI,BX,CX,AX
+ mov [esp+4],si ; put SI onto stack for POPAD
+ mov [esp+0],di ; put DI onto stack for POPAD
+int31okbx:
+ mov [esp+16],bx ; put BX onto stack for POPAD
+int31okcx: ; INT 31h return ok with CX,AX
+ mov [esp+24],cx ; put CX onto stack for POPAD
+int31okax: ; INT 31h return ok with AX
+ mov [esp+28],ax ; put AX onto stack for POPAD
+
+
+;-----------------------------------------------------------------------------
+int31ok: ; INT 31h return ok, pop all regs
+ popad
+ pop gs fs es ds
+int31oknopop: ; INT 31h return ok with carry clear
+ and bptr [esp+8],0FEh ; clear carry in EFLAGS on stack
+ iretd
+
+
+
+
+
+;=============================================================================
+; Helper functions
+;=============================================================================
+
+;-----------------------------------------------------------------------------
+int31testsel: ; test for valid selector BX
+ pop bp ; pop return address
+ cmp bx,cs:gdtlimit ; selector BX out of range?
+ ja int31fail8022 ; if yes, fail with error 8022h
+ mov edi,cs:gdtbase ; get base of GDT
+ and ebx,0FFF8h ; mask offset table index and RPL
+ test bptr ds:[edi+ebx+6],10h ; is descriptor used?
+ jz int31fail8022 ; if descriptor not used, fail 8022h
+ jmp bp ; return ok
+
+;-----------------------------------------------------------------------------
+int31testaccess: ; test access bits in CX
+ pop bp ; pop return address
+ test ch,20h ; test MUST BE 0 bit in CH
+ jnz int31fail8021 ; if not 0, error 8021h
+ test cl,90h ; test present and MUST BE 1 bits
+ jz int31fail8021 ; if both 0, error 8021h
+ jpo int31fail8021 ; if unequal, error 8021h
+ test cl,60h ; test DPL
+ jnz int31fail8021 ; if not 0, error 8021h
+ test cl,8 ; if code, more tests needed
+ jz @@0 ; if data, skip code tests
+ test cl,2 ; readable?
+ jz int31fail8021
+ test cl,4 ; non-conform?
+ jnz int31fail8021
+@@0: jmp bp ; return ok
+
+;-----------------------------------------------------------------------------
+int31testint:
+ movzx ebx,bl ; EBX = interrupt number
+ mov al,bl
+ mov ah,bl
+ and ax,0F807h
+ movzx esi,al
+ cmp ah,picmaster ; if 1st PIC, offset = buffer + 0
+ jz @@done
+ add si,8
+ cmp ah,picslave ; if 2nd PIC, offset = buffer + 8
+ jz @@done
+ or si,-1
+@@done: ret ; return: ZF = 0 if BL is IRQ, otherwise ZF = 1
+
+
+
+
+
+;=============================================================================
+; DESCRIPTOR FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Allocate Descriptors
+;
+int31h_0000:
+ test cx,cx ; if CX = 0, error 8021h
+ jz int31fail8021
+
+ mov edx,cs:gdtbase ; get base of GDT
+ movzx eax,cs:gdtlimit ; EAX = last selector index
+ and al,0F8h
+
+ mov bx,cx ; BX = number of selectors to find
+@@l0: test bptr [edx+eax+6],10h ; is descriptor used?
+ jnz @@f0
+ dec bx ; found free descriptor, dec counter
+ jnz @@f1 ; continue if need to find more
+
+ mov ebx,eax ; found all descriptors requested
+@@l1: mov dptr [edx+ebx],0 ; set entire new descriptor
+ mov dptr [edx+ebx+4],109200h
+ add bx,8 ; increment selector index
+ loop @@l1 ; dec counter of descriptors to mark
+ jmp int31okax ; return ok, with AX
+
+@@f0: mov bx,cx ; reset number of selectors to find
+@@f1: sub ax,8 ; dec current selector counter
+ cmp ax,8*SYSSELECTORS ; more descriptors to go?
+ jae @@l0 ; if yes, loop
+ jmp int31fail8011 ; did not find descriptors
+
+
+;=============================================================================
+; Free Descriptor
+;
+int31h_0001:
+ mov ax,cs
+ cmp ax,bx
+ jz int31fail8022 ; cannot free CS selector
+ mov ax,ss
+ cmp ax,bx
+ jz int31fail8022 ; cannot free SS selector
+ call int31testsel ; test for valid selector BX
+ xor eax,eax
+ mov [edi+ebx+0],eax ; mark descriptor as free
+ mov [edi+ebx+4],eax
+
+ mov cx,4 ; zero any segregs loaded with BX
+ lea ebp,[esp+32] ; EBP -> selectors on stack
+@@l0: cmp wptr [ebp],bx ; selector = BX?
+ jne @@f0 ; if no, continue loop
+
+ mov [ebp],ax ; zero selector on stack
+
+@@f0: add ebp,2 ; increment selector ptr
+ loop @@l0 ; loop
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Map Real-Mode Segment to Descriptor
+;
+int31h_0002:
+ mov ds,cs:seldata
+
+ mov cx,16 ; max 16 selectors
+ mov si,offs segmentbases ; check, if segment already mapped
+@@0: mov ax,[si+0] ; is selector zero (free entry)
+ test ax,ax
+ jz @@1 ; if yes, loop
+ cmp bx,[si+2] ; compare segment values
+ jz int31okax ; if already mapped, done
+@@1: add si,4
+ loop @@0
+
+ mov cl,16
+ mov si,offs segmentbases ; search for a free entry
+@@2: cmp wptr [si],0 ; this field free?
+ jz @@3 ; if yes, use it
+ add si,4
+ loop @@2
+ jmp int31fail8010 ; no entry free
+
+@@3: mov [si+2],bx ; store segment
+ movzx edi,bx ; convert to linear address
+ shl edi,4
+ mov cl,1
+ xor ax,ax
+ int 31h ; allocate selector
+ jc int31failax
+ mov [si+0],ax ; store selector
+
+ mov bx,ax
+ xor cx,cx
+ mov dx,-1
+ mov ax,8
+ int 31h ; set descriptor limit 64k
+
+ mov dx,di
+ shr edi,16
+ mov cx,di
+ mov ax,7
+ int 31h ; set descriptor base
+
+ mov cx,0092h
+ mov ax,9
+ int 31h ; set access rights
+
+ mov ax,bx ; return selector
+ jmp int31okax
+
+
+;=============================================================================
+; Get Selector Increment Value
+;
+int31h_0003:
+ mov ax,8 ; selector increment value is 8
+ jmp int31okax ; return ok, with AX
+
+
+;=============================================================================
+; Get Segment Base Address
+;
+int31h_0006:
+ call int31testsel ; test for valid selector BX
+
+ mov dx,wptr ds:[edi+ebx+2] ; low word of 32bit linear address
+ mov cl,bptr ds:[edi+ebx+4] ; high word of 32bit linear address
+ mov ch,bptr ds:[edi+ebx+7]
+ jmp int31okdx ; return ok, with DX, CX, AX
+
+
+;=============================================================================
+; Set Segment Base Address
+;
+int31h_0007:
+ call int31testsel ; test for valid selector BX
+
+ mov wptr ds:[edi+ebx+2],dx ; low word of 32bit linear address
+ mov bptr ds:[edi+ebx+4],cl ; high word of 32bit linear address
+ mov bptr ds:[edi+ebx+7],ch
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Set Segment Limit
+;
+int31h_0008:
+ call int31testsel ; test for valid selector BX
+ cmp cx,0Fh ; is limit greater than 1M?
+ jbe @@1 ; if not, jump
+
+ or dx,0FFFh ; auto-adjust limit
+ shrd dx,cx,12 ; DX = low 16 bits of page limit
+ shr cx,12 ; CL = high 4 bits of page limit
+ or cl,80h ; set granularity bit in CL
+
+@@1: mov wptr ds:[edi+ebx],dx ; put low word of limit
+ and bptr ds:[edi+ebx+6],50h ; mask off G and high nibble of limit
+ or bptr ds:[edi+ebx+6],cl ; put high nibble of limit
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Set Descriptor Access Rights
+;
+int31h_0009:
+ call int31testsel ; test for valid selector BX
+ call int31testaccess ; test access bits in CX
+
+ or ch, 10h ; set AVL bit, descriptor used
+ and ch,0D0h ; mask off low nibble of CH
+ and bptr ds:[edi+ebx+6],0Fh ; mask off high nibble access rights
+ or bptr ds:[edi+ebx+6],ch ; or in high access rights byte
+ mov bptr ds:[edi+ebx+5],cl ; put low access rights byte
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Create Alias Descriptor
+;
+int31h_000A:
+ call int31testsel ; test for valid selector BX
+
+ xor ax,ax ; allocate descriptor
+ mov cx,1
+ int 31h
+ jc int31fail8011 ; if failed, descriptor unavailable
+
+ push ax ; preserve allocated selector
+ push ds ; copy descriptor and set type data
+ pop es
+ movzx edi,ax ; EDI = target selector
+ mov esi,cs:gdtbase ; ESI -> GDT
+ add edi,esi ; adjust to target descriptor in GDT
+ add esi,ebx ; adjust to source descriptor in GDT
+
+ movs dptr es:[edi],ds:[esi] ; copy descriptor
+ lods dptr ds:[esi]
+ mov ah,92h ; set descriptor type - R/W up data
+ stos dptr es:[edi]
+ pop ax ; restore allocated selector
+ jmp int31okax ; return ok, with AX
+
+
+;=============================================================================
+; Get Descriptor
+;
+int31h_000B:
+ call int31testsel ; test for valid selector BX
+ lea esi,[edi+ebx] ; ESI -> descriptor in GDT
+ mov edi,[esp] ; get EDI buffer ptr from stack
+ movs dptr es:[edi],ds:[esi] ; copy descriptor
+ movs dptr es:[edi],ds:[esi]
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Set Descriptor
+;
+int31h_000C:
+ call int31testsel ; test for valid selector BX
+ mov esi,[esp] ; ESI = EDI buffer ptr from stack
+ mov cx,es:[esi+5] ; get access rights from descriptor
+ call int31testaccess ; test access bits in CX
+
+ push ds es ; swap DS and ES, target and source
+ pop ds es
+
+ add edi,ebx ; adjust EDI to descriptor in GDT
+ movs dptr es:[edi],ds:[esi] ; copy descriptor
+ lods dptr ds:[esi]
+ or al,10h ; set descriptor AVL bit
+ stos wptr es:[edi]
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Get Multiple Descriptors
+;
+int31h_000E:
+ mov ax,000Bh ; function 000Bh, get descriptor
+ jmp int31h_000EF ; go to common function
+
+
+;=============================================================================
+; Set Multiple Descriptors
+;
+int31h_000F:
+ mov ax,000Ch ; function 000Ch, set descriptor
+
+int31h_000EF: ; common to functions 000Eh and 000Fh
+ test cx,cx ; if CX = 0, return ok immediately
+ jz int31ok
+
+ mov dx,cx ; DX = number of descriptors
+ xor cx,cx ; CX = successful counter
+@@l0: mov bx,es:[edi] ; BX = selector to get
+ add edi,2
+ int 31h ; get/set descriptor
+ jc int31failcx ; if error, fail with AX and CX
+
+ add edi,8 ; increment descriptor ptr
+ inc cx ; increment successful copy counter
+ dec dx ; decrement loop counter
+ jnz @@l0 ; if more descriptors to go, loop
+ jmp int31ok ; return ok
+
+
+
+
+
+
+;=============================================================================
+; DOS MEMORY FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Allocate DOS Memory Block
+;
+int31h_0100:
+ mov ah,48h ; DOS alloc memory function
+ call int31010x_f2 ; allocate memory
+ jc int31failbx ; if fail, exit with AX=err, BX=maxmem
+
+ mov dx,ax ; DX=segment of DOS memory block
+ xor ax,ax ; allocate descriptor
+ mov cx,1
+ int 31h
+ jnc @@1
+ mov ah,49h ; if error allocating descriptor
+ call int31010x_f2 ; free what was allocated
+ jmp int31fail8011 ; and exit with error 8011h
+
+@@1: mov [esp+14h],ax ; set selector in DX
+ mov [esp+1Ch],dx ; set base address in AX
+ mov bx,ax
+ mov cx,dx
+ shl dx,4
+ shr cx,12
+ mov ax,0007h ; set selector base
+ int 31h
+
+ mov cx,0092h ; set access rights
+ mov al,09h
+ int 31h
+ jmp int31010x ; set selector size
+
+
+;=============================================================================
+; Free DOS Memory Block
+;
+int31h_0101:
+ mov ah,49h
+ mov si,dx ; preserve DX = selector
+ call int31010x_f1
+ jc int31failax
+ mov bx,si ; restore selector in BX
+ jmp int31h_0001
+
+
+;=============================================================================
+; Resize DOS Memory Block
+;
+int31h_0102:
+ mov ah,4Ah
+ mov si,dx ; preserve DX = selector
+ call int31010x_f1
+ jc int31failbx
+ mov bx,si ; restore selector in BX
+
+int31010x:
+ movzx edx,wptr [esp+10h] ; get original size
+ shl edx,4 ; convert para to bytes
+ dec edx ; limit=size-1
+ shld ecx,edx,16
+ mov ax,0008h ; set limit
+ int 31h
+ jmp int31ok
+
+
+;-----------------------------------------------------------------------------
+int31010x_f1:
+ pop bp
+ push ax bx
+ mov bx,dx ; BX = selector
+ mov ax,0006h ; get base
+ int 31h
+ pop bx ax
+ jc int31failax
+ shrd dx,cx,4 ; adjust CX:DX to segment value
+ push bp
+
+int31010x_f2:
+ xor cx,cx
+ push cx ; set real mode SS:SP
+ push cx
+ sub esp,10
+ push dx ; set real mode ES
+ push cx ; set real mode flags
+ pushad ; set real mode registers
+ push ss
+ pop es
+ mov edi,esp
+ mov bl,21h
+ mov ax,0300h
+ int 31h
+ mov bx,[esp+10h] ; get BX from structure
+ mov ax,[esp+1Ch] ; get AX from structure
+ lea esp,[esp+32h]
+ pop bp
+ jc int31failax ; if error, fail
+ bt wptr [esp-14h],0
+ jmp bp
+
+
+
+
+
+
+;=============================================================================
+; INTERRUPT FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Get Real Mode Interrupt Vector
+;
+int31h_0200:
+ movzx ebx,bl ; EBX = BL (interrupt number)
+ mov dx,[ebx*4+0] ; load real mode vector offset
+ mov cx,[ebx*4+2] ; load real mode vector segment
+ jmp int31okdx ; return ok, with AX, CX, DX
+
+
+;=============================================================================
+; Set Real Mode Interrupt Vector
+;
+int31h_0201:
+ mov ebp,dr7
+ xor eax,eax ; temporarily disable null-ptr protection
+ mov dr7,eax
+
+ movzx ebx,bl ; EBX = BL (interrupt number)
+ mov [ebx*4+0],dx ; set real mode vector offset
+ mov [ebx*4+2],cx ; set real mode vector segment
+
+ mov dr7,ebp
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Get Processor Exception Handler Vector
+;
+int31h_0202:
+ mov ds,cs:seldata
+ cmp bl,20h ; must be in range 00..1Fh
+ jae int31fail8021 ; invalid value
+
+ xor cx,cx
+ xor edx,edx
+ cmp bl,10h ; if not in range 00..0Fh
+ jae @@done ; return 0:0
+
+ movzx ebx,bl
+ mov cx,wptr exctab_pm[ebx*8+4] ; get user-defined exception handler CS
+ mov edx,dptr exctab_pm[ebx*8+0] ; get user-defined exception handler EIP
+
+@@done: mov ax,[esp+28]
+ jmp int31okedx ; return ok, with AX, CX, EDX
+
+
+;=============================================================================
+; Set Processor Exception Handler Vector
+;
+int31h_0203:
+ xchg bx,cx ; swap INT number with INT selector
+ call int31testsel ; test for valid selector BX
+ xchg bx,cx
+
+ mov ds,cs:seldata
+ cmp bl,20h ; must be in range 00..1Fh
+ jae int31fail8021 ; invalid value
+
+ cmp bl,10h ; if not in range 00..0Fh
+ jae @@done ; then done
+
+ movzx ebx,bl
+ mov wptr exctab_pm[ebx*8+4],cx ; set user-defined exception handler CS
+ mov dptr exctab_pm[ebx*8+0],edx ; set user-defined exception handler EIP
+
+@@done: jmp int31ok ; return ok
+
+
+;=============================================================================
+; Get Protected Mode Interrupt Vector
+;
+int31h_0204:
+ mov ds,cs:seldata
+ call int31testint ; check if one of IRQs
+ jz @@1 ; if yes, read from buffer
+
+@@0: shl ebx,3 ; adjust for location in IDT
+ add ebx,idtbase ; add base of IDT
+ mov ds,selzero
+ mov edx,dptr [ebx+4] ; get high word of offset
+ mov dx,wptr [ebx+0] ; get low word of offset
+ mov cx,wptr [ebx+2] ; get selector
+ jmp @@done
+
+@@1: bt irqset_pm,si ; check if IRQ is installed
+ jnc @@2 ; if not, return built-in handler
+ test bl,0F0h ; check if IRQ is above INT 0Fh
+ jnz @@0 ; if yes, don't buffer: read from IDT
+
+ mov cx,wptr irqtab_pm[esi*8+4] ; get user-defined IRQ handler CS
+ mov edx,dptr irqtab_pm[esi*8+0] ; get user-defined IRQ handler EIP
+ jmp @@done
+
+@@2: mov cx,SELCODE ; load built-in IRQ handler CS
+ lea edx,std_matrix[esi*4] ; load built-in IRQ handler EIP
+
+@@done: mov ax,[esp+28]
+ jmp int31okedx ; return ok, with AX, CX, EDX
+
+
+;=============================================================================
+; Set Protected Mode Interrupt Vector
+;
+int31h_0205:
+ xchg bx,cx ; swap int number with int selector
+ call int31testsel ; test for valid selector BX
+ xchg bx,cx
+
+ mov ds,cs:seldata
+ mov es,selzero
+ movzx ecx,cx ; ECX = CX (selector)
+
+ call int31testint ; check if one of IRQs
+ jz @@1 ; if yes, install in buffer
+ cmp bl,1Bh ; process special interrupts
+ jz @@1Bh
+ cmp bl,1Ch
+ jz @@1Ch
+ cmp bl,23h
+ jz @@23h
+ cmp bl,24h
+ jz @@24h
+
+@@0: shl ebx,3 ; adjust for location in IDT
+ add ebx,idtbase ; add base of IDT
+ mov wptr es:[ebx+0],dx ; set low word of offset
+ shr edx,16
+ mov wptr es:[ebx+6],dx ; set high word of offset
+ mov wptr es:[ebx+2],cx ; set selector
+ jmp @@done
+
+@@1: cmp cx,SELCODE ; check if restoring IRQ
+ jnz @@2 ; if not, jump
+
+ btr irqset_rm,si ; reset IRQ installed bit (RM)
+ btr irqset_pm,si ; reset IRQ installed bit (PM)
+ mov eax,irqtab_rm[esi*4] ; restore real mode interrupt
+ mov es:[ebx*4],eax
+ cmp bl,10h ; check if INT vector is above INT 0Fh
+ jae @@0 ; if yes, install into IDT
+
+ jmp @@done
+
+@@2: bts irqset_rm,si ; set IRQ installed bit (RM)
+ bts irqset_pm,si ; set IRQ installed bit (PM)
+ mov eax,es:[ebx*4] ; get CS:IP of real mode INT vector
+ mov irqtab_rm[esi*4],eax ; save CS:IP of real mode INT vector
+ lea eax,back_matrix[esi*4] ; get address of real mode IRQ callback
+ mov wptr es:[ebx*4+0],ax ; set real mode IRQ callback IP
+ mov wptr es:[ebx*4+2],_KERNEL ; set real mode IRQ callback CS
+ cmp bl,10h ; check if INT vector is above INT 0Fh
+ jae @@0 ; if yes, install into IDT
+
+ mov wptr irqtab_pm[esi*8+4],cx ; install CS into IRQ buffer
+ mov dptr irqtab_pm[esi*8+0],edx ; install EIP into IRQ buffer
+
+@@done: jmp int31ok ; return ok
+
+@@1Bh: cmp cx,SELCODE ; install real mode INT 1Bh callback
+ mov eax,newint1Bh
+ jnz @@1Bh0
+ mov eax,oldint1Bh
+@@1Bh0: mov es:[4*1Bh],eax
+ jmp @@0
+
+@@1Ch: cmp cx,SELCODE ; install real mode INT 1Ch callback
+ mov eax,newint1Ch
+ jnz @@1Ch0
+ mov eax,oldint1Ch
+@@1Ch0: mov es:[4*1Ch],eax
+ jmp @@0
+
+@@23h: cmp cx,SELCODE ; install real mode INT 23h callback
+ mov eax,newint23h
+ jnz @@23h0
+ mov eax,oldint23h
+@@23h0: mov es:[4*23h],eax
+ jmp @@0
+
+@@24h: cmp cx,SELCODE ; install real mode INT 24h callback
+ mov eax,newint24h
+ jnz @@24h0
+ mov eax,oldint24h
+@@24h0: mov es:[4*24h],eax
+ jmp @@0
+
+
+;=============================================================================
+; Get and Disable Virtual Interrupt State
+;
+int31h_0900:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ btr wptr [esp+8],9 ; test and clear IF bit in EFLAGS
+ setc al ; set AL = carry (IF flag from EFLAGS)
+ jmp int31oknopop ; return ok, dont pop registers
+
+
+;=============================================================================
+; Get and Enable Virtual Interrupt State
+;
+int31h_0901:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ bts wptr [esp+8],9 ; test and set IF bit in EFLAGS
+ setc al ; set AL = carry (IF flag from EFLAGS)
+ jmp int31oknopop ; return ok, dont pop registers
+
+
+;=============================================================================
+; Get Virtual Interrupt State
+;
+int31h_0902:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ bt wptr [esp+8],9 ; just test IF bit in EFLAGS
+ setc al ; set AL = carry (IF flag from EFLAGS)
+ jmp int31oknopop ; return ok, dont pop registers
+
+
+
+
+
+
+;=============================================================================
+; REAL/PROTECTED MODE TRANSLATION FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Call Real Mode Procedure with Far Return Frame
+; Call Real Mode Procedure with Interrupt Return Frame
+;
+int31h_0301:
+int31h_0302:
+ mov ebp,dptr es:[edi+2Ah] ; get target CS:IP from structure
+ jmp int3103 ; go to common code
+
+
+;=============================================================================
+; Simulate Real Mode Interrupt
+;
+int31h_0300:
+ movzx ebx,bl ; get real mode INT CS:IP
+ mov ebp,dptr ds:[ebx*4] ; read from real mode interrupt table
+
+int3103: ; common to 0300h, 0301h, and 0302h
+ mov gs,cs:seldata
+ movzx ebx,wptr es:[edi+2Eh] ; EBX = SP from register structure
+ movzx edx,wptr es:[edi+30h] ; EDX = SS from register structure
+ mov ax,bx ; check if caller provided stack
+ or ax,dx
+ jnz @@f3 ; if yes, go on to setup stack
+
+ mov dx,cs:rmstacktop ; DX = SS for real mode redirection
+ mov bx,cs:rmstacklen ; get size of real mode stack
+ sub dx,bx ; adjust DX to next stack location
+ cmp dx,cs:rmstackbase ; exceeded real mode stack space?
+ jb int31fail8012 ; if yes, error 8012h
+ mov gs:rmstacktop,dx ; update ptr for possible reenterancy
+ shl bx,4 ; adjust BX from paragraphs to bytes
+
+@@f3: lea edi,[edx*4] ; EDI -> top of real mode stack
+ lea edi,[edi*4+ebx]
+
+ mov ax,ss
+ xchg ax,gs:rmstackss ; preserve and set new top of stack
+ push ax ; parms for possible reenterancy
+ lea eax,[esp-4]
+ xchg eax,gs:rmstackesp
+ push eax
+
+ movzx ecx,cx
+ mov ax,cx ; EAX = length of stack parms
+ add ax,ax ; convert words to bytes
+ sub bx,2Eh ; adjust real mode SP for needed vars
+ sub bx,ax ; adjust real mode SP for stack parms
+
+ push ds es ; swap DS and ES
+ pop ds es
+
+ std ; string copy backwards
+ sub edi,2 ; copy stack parms from protected mode
+ lea esi,[ecx*2+esp+38h] ; stack to real mode stack
+ rep movs wptr es:[edi],ss:[esi]
+
+ mov esi,[esp+06h] ; ESI = offset of structure from stack
+ mov ax,ds:[esi+20h] ; AX = FLAGS from register structure
+ cmp bptr [esp+22h],1 ; check AL on stack for function code
+ jz @@f4 ; if function 0301h, go on
+ and ah,0FCh ; 0300h or 0302h, clear IF and TF flag
+ stos wptr es:[edi] ; put flags on real mode stack
+ sub bx,2
+
+@@f4: cld ; string copy forward
+ lea edi,[edx*4] ; EDI -> bottom of stack
+ lea edi,[edi*4+ebx]
+ mov cl,8 ; copy general regs to real mode stack
+ rep movs dptr es:[edi],ds:[esi]
+ add esi,6 ; copy FS and GS to real mode stack
+ movs dptr es:[edi],ds:[esi]
+
+ mov wptr es:[edi+8],_KERNEL ; return address from call
+ mov wptr es:[edi+6],offs @@f1
+ mov wptr es:[edi+4],ax ; store FLAGS for real mode IRET maybe
+ mov dptr es:[edi],ebp ; put call address to real mode stack
+ mov ax,[esi-6] ; real mode DS from register structure
+ mov cx,[esi-8] ; real mode ES from register structure
+ mov si,_KERNEL ; real mode target CS:IP
+ mov di,offs @@f0
+ db 66h ; JMP DWORD PTR, as in 32bit offset,
+ jmp wptr cs:pmtormswrout ; not seg:16bit offset
+
+@@f0: popad ; load regs with call values
+ pop fs gs
+ iret ; go to call address
+
+@@f1: push gs fs ds es ; store registers on stack
+ pushf ; store flags on stack
+ cli
+ pushad
+
+ xor eax,eax
+ mov ax,ss ; EAX = linear ptr to SS
+ xor ebp,ebp
+ shl eax,4
+ mov bp,sp ; EBP = SP
+ add ebp,eax ; EBP -> stored regs on stack
+
+ mov dx,cs:rmstackss ; get protected mode SS:ESP from stack
+ mov ebx,cs:rmstackesp
+ mov ax,SELZERO ; DS selector value for protected mode
+ mov cx,SELDATA ; ES selector value for protected mode
+ mov si,SELCODE ; target CS:EIP in protected mode
+ mov edi,offs @@f2
+ jmp cs:rmtopmswrout ; go back to protected mode
+
+@@f2: push es
+ pop gs
+ pop es:rmstackesp
+ pop es:rmstackss
+ mov esi,ebp ; copy return regs from real mode
+ mov edi,[esp] ; get structure offset from stack
+ mov es,[esp+24h]
+ mov ecx,15h ; stack to register structure
+ cld
+ rep movs wptr es:[edi],ds:[esi]
+
+ cmp dptr es:[edi+4],0 ; stack provided by caller?
+ jne int31ok ; if yes, done now
+ mov ax,cs:rmstacklen ; restore top of real mode stack
+ add gs:rmstacktop,ax
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Allocate Real Mode Callback Address
+;
+int31h_0303:
+ mov bl,cs:pm32_callbacks ; CL = total number of callbacks
+ test bl,bl ; are there any?
+ jz int31fail8015 ; if no, error 8015h
+
+ mov edx,cs:callbackbase ; EDX -> base of callbacks
+ mov ecx,edx ; for later use
+
+@@l0: cmp wptr [edx+3],0 ; is this callback free?
+ jz @@f0 ; if yes, allocate
+ add edx,25 ; increment ptr to callback
+ dec bl ; decrement loop counter
+ jnz @@l0 ; if more callbacks to check, loop
+ jmp int31fail8015 ; no free callback, error 8015h
+
+@@f0: mov bx,[esp+38] ; BX = caller DS from stack
+ mov [edx+3],bx ; store callback parms in callback
+ mov [edx+7],esi
+ mov [edx+12],es
+ mov [edx+16],edi
+ sub edx,ecx ; DX = offset of callback
+ shr ecx,4 ; CX = segment of callback
+ jmp int31okdx ; return ok, with DX, CX, AX
+
+
+;=============================================================================
+; Free Real Mode Callback Address
+;
+int31h_0304:
+ cmp cx,cs:callbackseg ; valid callback segment?
+ jne int31fail8024 ; if no, error 8024h
+
+ movzx ebx,dx ; EBX = offset of callback
+ xor ax,ax ; check if valid offset
+ xchg dx,ax
+ mov cx,25
+ div cx
+ test dx,dx ; is there a remainder
+ jnz int31fail8024 ; if yes, not valid, error 8024h
+ test ah,ah ; callback index too big?
+ jnz int31fail8024 ; if yes, not valid, error 8024h
+ cmp al,cs:pm32_callbacks ; callback index out of range?
+ jae int31fail8024 ; if yes, not valid, error 8024h
+
+ add ebx,cs:callbackbase ; EBX -> callback
+ mov wptr [ebx+3],0 ; set callback as free
+ jmp int31ok ; return ok
+
+
+;=============================================================================
+; Get State Save/Restore Addresses
+;
+int31h_0305: ; get state save/restore addresses
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ xor ax,ax ; size needed is none
+ mov bx,cs:kernel_code ; real mode seg of same RETF
+ mov cx,offs vxr_saverestorerm ; same offset of 16bit RETF
+ mov si,cs ; selector of routine is this one
+ mov edi,offs vxr_saverestorepm ; offset of simple 32bit RETF
+ jmp int31oknopop ; return ok, dont pop registers
+
+
+;=============================================================================
+; Get Raw CPU Mode Switch Addresses
+;
+int31h_0306: ; get raw mode switch addresses
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ mov si,cs ; selector of pmtorm rout is this one
+ mov edi,cs:pmtormswrout ; offset in this seg of rout
+ mov bx,cs:kernel_code ; real mode seg of rmtopm rout
+ mov cx,cs:rmtopmswrout ; offset of rout in real mode
+ jmp int31oknopop ; return ok, dont pop registers
+
+
+
+
+
+
+;=============================================================================
+; MISC FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Get DPMI Version
+;
+int31h_0400:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ mov ax,005Ah ; return version 0.9
+ mov bx,0003h ; capabilities
+ cmp cs:pmodetype,2
+ jnz @@1
+ mov bl,1
+@@1: mov cl,cs:cputype ; processor type
+ mov dx,wptr cs:picslave ; master and slave PIC values
+ jmp int31oknopop ; return ok, don't pop registers
+
+
+;=============================================================================
+; Get Vendor-Specific API Entry Point
+;
+int31h_0A00:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+
+ push es edi ecx esi ; save regs that will be modified
+ push cs ; ES = CS
+ pop es
+
+ mov ecx,15 ; search for vendor1 string
+ mov edi,offs @@str1
+ push esi
+ repe cmps bptr ds:[esi],es:[edi]
+ pop esi
+ mov edi,offs @@ent1 ; ES:EDI = sel:offset of entry SUNSYS
+ jz @@0 ; if found, jump
+ test cs:pm32_mode,10000000b ; check if to ignore DOS/4G extensions
+ jnz @@err ; if not, we are done
+ mov cl,16 ; search for vendor2 string
+ mov edi,offs @@str2
+ repe cmps bptr ds:[esi],es:[edi]
+ jnz @@err ; if not found, done
+ mov edi,offs @@ent2 ; ES:EDI = sel:offset of entry DOS/4G
+ pop esi ecx
+ add esp,6
+ jmp int31oknopop
+
+@@0: add esp,14
+ xor eax,eax ; clear high words
+ mov ebx,eax
+ mov ecx,eax
+ mov edx,eax
+ mov ax,cs:client_version ; AX = DOS Extender Version Number
+ mov bl,cs:pm32_mode ; BL = kernel configuration
+ mov bh,cs:pmodetype ; BH = system software type
+ mov cl,cs:cputype ; CL = processor type
+ mov ch,cs:fputype ; CH = FPU type
+ mov dx,wptr cs:picslave ; DX = PIC values (unremapped)
+ jmp int31oknopop
+
+@@err: pop esi ecx edi es ; if none of the strings were idetified
+ mov ax,8001h ; return with AX=8001h
+ jmp int31failnopop
+
+@@str1 db 'SUNSYS DOS/32A',0 ; vendor1 API ID-string (DOS/32A)
+@@str2 db 'RATIONAL DOS/4G',0 ; vendor2 API ID-string (DOS/4G)
+
+@@ent2: mov ax,8500h ; vendor2 API entry point (DOS/4G)
+ jmp dptr cs:client_call
+
+@@ent1: test al,al ; vendor1 API entry point (DOS/32A)
+ jz API_func00
+ cmp al,01h
+ jz API_func01
+ cmp al,02h
+ jz API_func02
+ cmp al,03h
+ jz API_func03
+ cmp al,04h
+ jz API_func04
+ cmp al,05h
+ jz API_func05
+ cmp al,06h
+ jz API_func06
+ cmp al,07h
+ jz API_func07
+ cmp al,08h
+ jz API_func08
+ cmp al,09h
+ jz API_func09
+ stc
+ db 66h
+ retf
+
+;---------------------------------------------------------------------
+API_func00: ; API function 00h: get access to IDT & GDT
+ mov bx,SELZERO
+ movzx ecx,cs:gdtlimit ; ECX = GDT limit
+ movzx edx,cs:idtlimit ; EDX = IDT limit
+ mov esi,cs:gdtbase ; BX:ESI = pointer to GDT
+ mov edi,cs:idtbase ; BX:EDI = pointer to IDT
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func01: ; API function 01h: get access to PageTables
+ mov bx,SELZERO
+ movzx ecx,cs:pagetables ; ECX = number of allocated pagetables
+ movzx edx,cs:pm32_maxfpages ; EDX = number of allocated phystables
+ mov esi,cs:pagetablebase ; BX:ESI = pointer to 0th pagetable
+ mov edi,cs:phystablebase ; BX:EDI = pointer to phystable
+ inc cx
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func02: ; API function 02: get access to INT tables
+ mov bx,SELDATA
+ mov esi,offs irqset_rm ; BX:ESI = pointer to INT switches
+ mov edi,offs irqtab_rm ; BX:EDI = pointer to INT tables
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func03: ; API function 03: get access to EXT memory
+ mov bx,SELZERO
+ mov ecx,cs:mem_free ; ECX = size of allocated memory
+ mov edx,cs:mem_ptr ; EDX = pointer to allocated memory
+ mov esi,cs:mem_top ; ESI = top of allocated memory
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func04: ; API function 04: get access to rm-stacks
+ mov bx,SELZERO
+ movzx ecx,cs:rmstacklen ; ECX = size of one stack
+ movzx edx,cs:rmstacktop ; EDX = pointer to top of stack
+ movzx esi,cs:rmstackbase ; ESI = base of stack area
+ movzx edi,cs:rmstacktop2 ; EDI = default top of stack
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func05: ; API function 05: get access to pm-stacks
+ mov bx,SELZERO
+ mov ecx,cs:pmstacklen ; ECX = size of one stack
+ mov edx,cs:pmstacktop ; EDX = pointer to top of stack
+ mov esi,cs:pmstackbase ; ESI = base of stack area
+ mov edi,cs:pmstacktop2 ; EDI = default top of stack
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func06: ; API function 06: get kernel selectors
+ mov bx,SELCODE ; BX = Kernel code selector
+ mov cx,SELDATA ; CX = Kernel data selector
+ mov dx,SELZERO ; DX = Kernel zero selector
+ movzx esi,wptr cs:kernel_code ; ESI = Kernel code segment
+ mov di,wptr cs:client_call[2] ; DI = Client code selector
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func07: ; API function 07: get critical handler entry
+ mov cx,cs:client_call[2] ; CX = default 16bit selector
+ mov dx,cs:client_call[0] ; DX = default 16bit offset
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func08: ; API function 08: set critical handler entry
+ push ds
+ mov ds,cs:seldata
+ mov client_call[2],cx ; CX = custom 16bit selector
+ mov client_call[0],dx ; DX = custom 16bit offset
+ pop ds
+ jmp API_funcok
+
+;---------------------------------------------------------------------
+API_func09: ; API function 09: get access to p. counters
+ mov cx,SELDATA ; CX = Kernel data selector
+ mov edx,offs _pc_base ; EDX = base of performance counters
+
+;---------------------------------------------------------------------
+API_funcok:
+ clc
+ db 66h
+ retf
+
+
+
+
+
+
+;=============================================================================
+; MEMORY FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Get Free Memory Information
+;
+int31h_0500:
+ or eax,-1
+ mov ecx,0Ch
+ push edi
+ rep stos dptr es:[edi]
+ pop edi
+ mov eax,cs:mem_ptr
+ or eax,cs:mem_free
+ jz @@1
+ call int31_checkblocks
+ call int31_getfreemem
+
+@@1: mov ebx,eax
+ mov edx,eax ; EDX = largest free block
+ mov eax,cs:mem_free
+ shr eax,12 ; EAX = total memory pages
+ shr ebx,12 ; EBX = free pages left
+ shr ecx,12 ; ECX = total allocated memory
+ push es
+ pop ds
+ mov [edi+00h],edx ; 00h - largest free block
+ mov [edi+04h],ebx ; 04h - max unlocked pages
+ mov [edi+08h],ebx ; 08h - max locked pages
+ mov [edi+0Ch],eax ; 0Ch - total linear space
+ mov [edi+10h],ebx ; 10h -
+ mov [edi+14h],ecx ; 14h -
+ mov [edi+18h],eax ; 18h - total pages
+ mov [edi+1Ch],ecx ; 1Ch - total free mem in pages
+ jmp int31ok
+
+
+;=============================================================================
+; Allocate Memory Block
+;
+int31h_0501:
+ call int31_checkifmemavail
+ call int31_testbxcxtoebx ; convert BX:CX to EBX
+ call int31_checkblocks
+ mov esi,cs:mem_ptr ; get pointer to memory
+@@1: mov eax,[esi+04h] ; get block size
+ btr eax,31 ; check if memory block is used
+ jc @@2 ; if yes, jump
+ cmp eax,ebx ; check if block is large enough
+ jae int31_allocblock ; if yes, allocate block
+@@2: lea esi,[esi+eax+10h] ; load address of next memory block
+ cmp esi,cs:mem_top ; check if at top of memory
+ jb @@1 ; if not, loop
+ jmp int31fail8013 ; fail: not enough memory
+
+
+;=============================================================================
+; Free Memory Block
+;
+int31h_0502:
+ shl esi,16 ; convert SI:DI to ESI
+ mov si,di
+ call int31_checkifmemavail
+ call int31_checkblocks
+ call int31_checkhandle
+ btr dptr [esi+04h],31 ; set block as free
+ call int31_linkfreeblocks
+ jmp int31ok
+
+
+;=============================================================================
+; Resize Memory Block
+;
+int31h_0503:
+ shl esi,16 ; convert SI:DI to ESI
+ mov si,di
+ call int31_checkifmemavail
+ call int31_testbxcxtoebx ; convert BX:CX to EBX
+ call int31_checkblocks
+ call int31_checkhandle
+
+ mov eax,[esi+04h] ; get size of this block
+ btr eax,31 ; check if block is used
+ jnc int31fail8023 ; if block is free, fail
+ cmp eax,ebx ; check if enough memory
+ jae int31_allocblock ; if yes, reallocate block
+ mov [esi+04h],eax ; set this block as free
+ lea edi,[esi+eax+10h] ; get address of next block
+ cmp edi,cs:mem_top ; check if at top of memory
+ jae @@0
+ mov edx,[edi+04h] ; get size of next block
+ btr edx,31 ; check if block next to us is free
+ jc @@0 ; if not, jump
+ lea edx,[eax+edx+10h] ; calculate total size (this+hdr+next)
+ cmp edx,ebx ; check if enough
+ jb @@0 ; if not, jump
+ mov eax,edx ; set this size = (this + next)
+ mov [esi+04h],eax ; link this and next blocks
+ jmp int31_allocblock ; and go to the allocation routine
+
+@@0: mov edi,cs:mem_ptr ; get pointer to memory
+@@1: mov edx,[edi+04h] ; get block size
+ btr edx,31 ; check if memory block is used
+ jc @@2 ; if yes, jump
+ cmp edx,ebx ; check if block is large enough
+ jae @@3 ; if yes, allocate block
+@@2: lea edi,[edi+edx+10h] ; load address of next memory block
+ cmp edi,cs:mem_top ; check if at top of memory
+ jb @@1 ; if not, loop
+ bts eax,31 ; set this block as used
+ mov [esi+04h],eax ; restore state of this block
+ jmp int31fail8013 ; fail: not enough memory
+
+@@3: push esi edi
+ mov ecx,eax
+ shr ecx,2
+ add esi,10h
+ add edi,10h
+ rep movs dptr es:[edi],ds:[esi]
+ mov cl,al
+ and cl,3
+ rep movs bptr es:[edi],ds:[esi]
+ pop edi esi
+ call int31_linkfreeblocks
+ mov esi,edi
+ mov eax,edx
+ jmp int31_allocblock ; and go to the allocation routine
+
+
+;=============================================================================
+; Get Memory Block Size and Base
+;
+int31h_050A:
+ shl esi,16 ; convert SI:DI to ESI
+ mov si,di
+ call int31_checkifmemavail
+ call int31_checkblocks
+ call int31_checkhandle
+ mov ebx,[esi+04h] ; check if block is used
+ btr ebx,31
+ jnc int31fail8023
+ add esi,10h
+ xchg ebx,esi
+ mov cx,bx
+ shr ebx,16
+ mov di,si
+ shr esi,16
+ jmp int31oksinoax
+
+
+
+;-----------------------------------------------------------------------------
+int31_checkifmemavail: ; check if memory had been allocated
+ pop bp
+ push eax
+ mov eax,cs:mem_ptr
+ or eax,cs:mem_free
+ pop eax
+ jz int31fail8013
+ jmp bp
+
+;-----------------------------------------------------------------------------
+int31_checkblocks: ; check if memory had been overwritten
+ push eax esi
+ mov esi,cs:mem_ptr
+@@1: test si,000Fh ; blocks must be para aligned
+ jnz @@err
+ mov eax,12345678h ; header id
+ cmp eax,[esi+00h] ; if no header_id at block start
+ jnz @@err ; then signal error
+ cmp eax,[esi+0Ch] ; if no header_id at block end
+ jnz @@err ; then signal error
+ mov eax,[esi+04h] ; get block size
+ btr eax,31 ; reset the used flag
+ lea esi,[esi+eax+10h] ; load address of next memory block
+ cmp esi,cs:mem_ptr
+ jb @@err
+ cmp esi,cs:mem_top ; check if at top of memory
+ ja @@err
+ jb @@1 ; if not, loop
+ pop esi eax
+@@done: ret
+
+@@err: mov ds,cs:seldata
+ xor eax,eax
+ mov mem_ptr,eax ; set to zero to prevent looping error
+ mov mem_free,eax ; when exiting
+ mov ax,8400h
+ jmp dptr client_call
+
+;-----------------------------------------------------------------------------
+int31_checkhandle:
+ pop bp ; check for valid handle in ESI
+ cmp esi,cs:mem_ptr
+ jb @@1
+ cmp esi,cs:mem_top
+ ja @@1
+ mov eax,12345678h
+ cmp eax,[esi+00h]
+ jnz @@1
+ cmp eax,[esi+0Ch]
+ jnz @@1
+ jmp bp
+@@1: jmp int31fail8023 ; fail: invalid handle
+
+;-----------------------------------------------------------------------------
+int31_testbxcxtoebx: ; convert BX:CX to EBX
+ pop bp
+ shl ebx,16
+ mov bx,cx
+ test ebx,ebx
+ jz int31fail8021 ; BX:CX cannot be zero
+ add ebx,0Fh ; align EBX on para boundary
+ and bl,0F0h
+ bt ebx,31
+ jc int31fail8021 ; cannot allocate that much memory
+ jmp bp
+
+;-----------------------------------------------------------------------------
+int31_getfreemem:
+ xor eax,eax ; reset free memory size
+ xor ecx,ecx
+ mov esi,cs:mem_ptr ; get pointer to memory
+@@1: mov edx,[esi+04h] ; get block size
+ btr edx,31 ; check if memory block is used
+ jc @@2 ; if yes, jump
+ add ecx,edx
+ cmp eax,edx ; pick largest value
+ ja @@2
+ mov eax,edx
+@@2: lea esi,[esi+edx+10h] ; load addres of next memory block
+ cmp esi,cs:mem_top ; check if at top of memory
+ jb @@1 ; if not, loop
+ ret
+
+;-----------------------------------------------------------------------------
+int31_allocblock:
+ mov ecx,12345678h
+ movzx edx,cs:id32_process_id
+ sub eax,ebx ; nextsize=actualsize-allocsize
+ sub eax,10h ; is nextsize<16 (header size)
+ jb @@1 ; if yes, do not create next block
+ lea edi,[esi+ebx+10h] ; EDI = ptr to next block
+ mov [edi+00h],ecx ; header ID1
+ mov [edi+04h],eax ; set next block as free/size
+ mov [edi+08h],edx ; process_ID
+ mov [edi+0Ch],ecx ; header ID2
+
+@@1: bts ebx,31 ; set this block as used
+ mov [esi+00h],ecx ; header ID1
+ mov [esi+04h],ebx ; store this block size in header
+ mov [esi+08h],edx ; process_ID
+ mov [esi+0Ch],ecx ; header ID2
+ call int31_linkfreeblocks
+
+ lea ebx,[esi+10h] ; EBX = ptr to memory block (-header)
+ mov cx,bx
+ shr ebx,16
+ mov di,si
+ shr esi,16
+ jmp int31oksinoax
+
+;-----------------------------------------------------------------------------
+int31_linkfreeblocks:
+ pushad
+ mov edi,cs:mem_ptr ; EDI = ptr to 1st block handle
+ mov ebp,cs:mem_top
+
+ mov eax,[edi+04h] ; get 1st block size
+ btr eax,31
+ lea esi,[edi+eax+10h] ; ESI = ptr to 2nd block handle
+ cmp esi,ebp ; check if at top of memory
+ jae @@done ; if yes, done
+ mov esi,edi ; ESI=EDI = ptr to 1st block
+
+@@1: mov eax,[esi+04h] ; get block size
+ btr eax,31 ; check if block is used
+ jc @@4 ; if yes, jump
+
+ xor ebx,ebx ; reset amount of free block memory
+ xor ecx,ecx ; reset number of free blocks in raw
+ mov edi,esi ; remember addr of first free block
+ jmp @@3
+
+@@2: add ecx,10h ; increment number of free blocks
+ mov eax,[esi+04h] ; get block size
+ btr eax,31 ; check if block is free
+ lea ebx,[eax+ebx] ; amount of free memory encountered
+ jnc @@3 ; if yes, jump
+ sub ebx,eax
+ sub ecx,10h
+ add ebx,ecx
+ add [edi+04h],ebx
+ jmp @@4
+
+@@3: lea esi,[esi+eax+10h] ; calculate address of next block
+ cmp esi,ebp ; check if at top of memory
+ jb @@2 ; if not, loop
+ add ebx,ecx
+ add [edi+04h],ebx
+ jmp @@done
+
+@@4: lea esi,[esi+eax+10h] ; calculate address of next block
+ cmp esi,ebp ; check if at top of memory
+ jb @@1 ; if not, loop
+
+@@done: popad
+ ret
+
+
+
+
+
+
+;=============================================================================
+; VIRTUAL MEMORY FUNCTIONS (not supported)
+;=============================================================================
+
+;=============================================================================
+; Lock Linear Region
+; Unlock Linear Region
+; Mark Real Mode Region as Pageable
+; Relock Real Mode Region
+; Mark Page as Demand Paging Candidate
+; Discard Page Contents
+;
+int31h_0600:
+int31h_0601:
+int31h_0602:
+int31h_0603:
+int31h_0702:
+int31h_0703:
+ jmp int31ok
+
+
+;=============================================================================
+; Get Page Size
+;
+int31h_0604:
+ xor bx,bx
+ mov cx,1000h
+ jmp int31okbx
+
+
+
+
+
+;=============================================================================
+; PHYSICAL MEMORY MAPPING FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Physical Address Mapping
+;
+int31h_0800:
+ shl ebx,16 ; convert BX:CX to EBX
+ shl esi,16 ; convert SI:DI to ESI
+ mov bx,cx
+ mov si,di
+ cmp ebx,100000h ; check if mapping under 1MB limit
+ jb int31fail8021 ; if yes, error
+ test esi,esi ; check if size is zero
+ jz int31fail8021 ; if yes, error
+ cmp cs:pmodetype,2 ; check if system is VCPI
+ jz @@vcpi ; if yes, do VCPI memory mapping
+ jmp int31ok ; if under raw/XMS, do nothing
+
+@@vcpi: cmp cs:pm32_maxfpages,0 ; check if any linear memory avail.
+ jz int31fail8012 ; if not, signal error 8012h
+
+ push ds
+ pop es
+ mov edi,cs:phystablebase ; get base of pagetables
+@@0: mov eax,ebx ; EAX = physical address
+ lea ecx,[esi+0FFFh] ; ECX = size of memory to map
+ and ax,0F000h
+ shr ecx,12
+ mov edx,edi
+@@1: cmp edi,cs:phystabletop ; are there any pages mapped left
+ jae @@3 ; no, go on with mapping
+
+ mov ebp,[edi]
+ and bp,0F000h
+ cmp eax,ebp ; check if page already mapped
+ jz @@2 ; if yes, go to check next page
+ add edi,4 ; increment pointer into pagetables
+ jmp @@0 ; loop
+
+@@2: add edi,4 ; increment pointer into pagetables
+ add eax,4096
+ dec ecx ; decrement amount of pages checked
+ jnz @@1 ; if there are more left, loop
+ mov eax,ebx
+ and ax,0F000h
+ sub ebx,eax
+ jmp @@done ; region already mapped, we are done
+
+@@3: mov edi,cs:phystablebase ; get base of pagetables
+ mov ecx,cs:phystabletop ; get number of available pagetables
+ sub ecx,edi
+ shr ecx,2 ; convert to 4KB pages
+ mov eax,ebx
+ and ax,0F000h
+ lea ebp,[ebx+esi+0FFFh] ; EBP = number of required 4KB pages
+ sub ebp,eax
+ shr ebp,12
+
+@@4: test ecx,ecx ; check if no linear space left
+ jz int31fail8021 ; if yes, error
+ xor eax,eax
+ repne scas dptr es:[edi] ; scan for first free page
+ lea edx,[edi-4] ; EDX = first free page address
+ repe scas dptr es:[edi] ; scan for amount of free pages
+ mov eax,edi
+ sub eax,edx
+ shr eax,2 ; EAX = free pages available
+ cmp eax,ebp ; check if enough free pages
+ jb @@4 ; no, must loop
+
+ mov eax,ebx ; EAX = physical address
+ and ax,0F000h
+ sub ebx,eax
+ mov edi,edx ; EDI = address of first free page
+ mov ecx,ebp
+ mov al,07h ; set page as user/writeable/present
+ cmp cs:cputype,3 ; check if CPU is 486+
+ jbe @@loop ; if not, jump
+ mov al,1Fh ; set PCD and PWT bits (no page cache)
+
+@@loop: stos dptr es:[edi] ; map one 4KB page
+ add eax,4096 ; go for next page
+ loop @@loop ; loop until no pages left
+ or bptr [edx+1],2 ; mark start of mapped block
+ or bptr [edi-3],4 ; mark end of mapped block
+
+@@done: sub edx,cs:phystablebase
+ shl edx,10
+ add edx,ebx
+
+ mov [esp+18h],dx
+ shr edx,16
+ or dx,8000h
+ mov [esp+10h],dx
+
+ mov eax,cs:vcpi_cr3
+ mov cr3,eax
+ xor eax,eax
+ mov cr2,eax
+ jmp int31ok
+
+
+;=============================================================================
+; Free Physical Address Mapping
+;
+int31h_0801:
+ cmp cs:pmodetype,2
+ jz @@vcpi
+ jmp int31ok ; if under raw/XMS, do nothing
+
+@@vcpi: cmp cs:pm32_maxfpages,0 ; check if any linear memory avail.
+ jz int31fail8012 ; if not, signal error 8012h
+
+ and bx,7FFFh
+ shl ebx,16
+ mov bx,cx
+ shr ebx,10
+ and bl,0FCh
+
+ add ebx,cs:phystablebase
+ cmp ebx,cs:phystablebase ; check if addr is in range
+ jb int31fail8025
+ cmp ebx,cs:phystabletop
+ jae int31fail8025
+ test bptr [ebx+1],2
+ jz int31fail8025
+
+@@loop: xor eax,eax ; clear page table entries
+ xchg eax,[ebx]
+ add ebx,04h
+ test ah,04h
+ jz @@loop
+
+@@1: mov eax,cs:vcpi_cr3
+ mov cr3,eax
+ xor eax,eax
+ mov cr2,eax
+ jmp int31ok
+
+
+
+
+
+
+;=============================================================================
+; FPU RELATED FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; Get Coprocessor Status
+;
+int31h_0E00:
+ movzx ax,cs:fputype ; get FPU type
+ shl ax,4 ; put FPU type in bits 4..7
+
+ smsw dx ; get MSW in DX
+ and dl,06h ; mask MP & EM bits
+ shr dl,1 ; map MP & EM bits to MPv & EMv bits
+ or al,dl ; put MPv & EMv bits into AL
+ shl dl,2 ; map MP & EM bits to MPr & EMr bits
+ or al,dl ; put MPr & EMr bits into AL
+
+ jmp int31okax
+
+
+;=============================================================================
+; Set Coprocessor Emulation
+;
+int31h_0E01:
+ mov ds,cs:seldata
+ and bl,00000011b ; mask MPv & EMv bits
+ shl bl,1 ; map MPv & EMv bits to MP & EM bits
+
+ smsw ax ; get MSW in AX
+ or al,bl ; set MP & EM bits
+ lmsw ax ; reload MSW
+
+ jmp int31ok
+
+
+
+
+
+
+;=============================================================================
+; NON-STANDARD FUNCTIONS
+;=============================================================================
+
+;=============================================================================
+; PMODE/W id function
+;
+int31h_EEFF:
+ add esp,26h ; adjust stack
+ pop ds ; restore DS
+ push cs
+ pop es ; ES = CS
+ mov eax,'D32A' ; load id-string
+ mov ebx,offs $+2 ; ES:EBX points to itself ('\0' within opcode)
+ mov ch,cs:pmodetype
+ mov cl,cs:cputype
+ mov dx,cs:client_version
+ jmp int31oknopop
+
diff -uNr a/dos32a/src/dos32a/text/kernel/intr.asm b/dos32a/src/dos32a/text/kernel/intr.asm
--- a/dos32a/src/dos32a/text/kernel/intr.asm false
+++ b/dos32a/src/dos32a/text/kernel/intr.asm bab1bb5a6d9129aae18a2c2b6091d3cd25d3441a42437476f424062021d17ca473f9369452d2695def5d54d3e97f4e1fa28848f7f109ed939d3c3ec5f0898f40
@@ -0,0 +1,676 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+; interrupt tables
+;=============================================================================
+ Align 16
+int_matrix: ; INT redirectors
+ rept 256 ; 256 INTs
+ push ax
+ call near ptr int_main
+ endm
+;=============================================================================
+std_matrix: ; Standard IRQ redirectors
+ rept 16 ; 16 IRQs
+ push ax
+ call near ptr irq_standard
+ endm
+;=============================================================================
+back_matrix: ; Real mode IRQ callbacks
+ rept 16 ; 16 IRQs
+ push ax
+ call near ptr irq_callback
+ endm
+;=============================================================================
+exc_matrix: ; Exceptions
+ rept 16 ; 16 EXCs
+ push ax
+ call near ptr exc_handler
+ endm
+
+
+
+
+
+;=============================================================================
+; Out of Real-Mode virtual stack space handler: handles virtual stack
+; overflows which may occur during a switch from PM to RM.
+;
+critical_error_rm:
+ cli
+ mov ds,cs:seldata ; DS points to kernel
+ mov es,selzero ; ES points to zero
+
+ mov eax,oldint1Ch ; restore INT 1Ch
+ mov es:[4*1Ch],eax
+
+ mov ax,rmstacktop2 ; restore RM virtual stack
+ mov rmstacktop,ax ; to a safe value
+
+ mov ax,8200h ; AX = kernel error code
+ jmp dptr client_call ; enter client's run-time error handler
+
+;=============================================================================
+; Out of Protected-Mode virtual stack space handler: handles virtual stack
+; overflows which may occur during a switch from RM to PM.
+;
+critical_error_pm:
+ cli
+ xor ax,ax
+ mov ds,cs:kernel_code ; DS points to kernel
+ mov es,ax ; ES points to zero
+
+ mov eax,oldint1Ch ; restore INT 1Ch
+ mov es:[4*1Ch],eax
+
+ mov eax,pmstacktop2 ; restore PM virtual stack
+ mov pmstacktop,eax ; to a safe value
+
+ mov ebx,eax ; EBX = ESP for protected mode
+ mov ax,SELDATA ; DS selector for protected mode
+ mov cx,ax
+ mov dx,SELZERO ; SS selector = zero selector
+ mov si,SELCODE ; target protected mode CS:EIP
+ mov edi,offs @@0
+ jmp rmtopmswrout ; switch to protected mode
+
+@@0: mov ax,8300h ; AX = kernel error code
+ jmp dptr client_call ; enter client's run-time error handler
+
+
+
+
+
+;=============================================================================
+; INT Redirector
+;
+; Default interrupt handler: reflects interrupts issued in protected mode
+; (and for which no user-defined handler is installed) to real-mode.
+;
+int_main:
+ cli ; disable interrupts
+
+ pop ax ; get caller address in AX
+ sub ax,offs int_matrix+1 ; calculate INT number
+ shr ax,2 ; now AX = INT ##h
+
+ pushad
+ push ds es fs gs
+ mov ds,cs:seldata
+
+ inc _pc_intpmtorm ; increment INT PM->RM counter
+ mov @@N,al ; modify code with interrupt number
+
+ mov dx,rmstacktop ; DX = SS for real mode redirection
+ mov bx,rmstacklen ; get size of real mode stack
+ movzx esi,dx ; EBP -> top of real mode stack
+ sub dx,bx ; adjust DX to next stack location
+ shl esi,4
+ cmp dx,rmstackbase ; exceeded real mode stack space?
+ jb critical_error_rm ; if yes, critical error
+ mov rmstacktop,dx ; update ptr for possible reenterancy
+ shl bx,4 ; set real mode SP to top of stack
+
+ mov es,selzero ; copy registers from protected mode
+ mov ds,selzero ; DS -> 0 (beginning of memory)
+ lea edi,[esi-26h]
+ mov ecx,8
+ mov [esi-2],ss ; store SS:ESP on real mode stack
+ mov [esi-6],esp
+ lea esi,[esp+8]
+ cld
+ rep movs dptr es:[edi],ss:[esi]
+ mov ax,[esp+28h] ; move AX to real mode stack frame
+ mov [edi-04h],ax
+ mov si,_KERNEL ; real mode target CS:IP
+ mov di,offs @@0
+ sub bx,26h ; adjust real mode SP for stored vars
+ db 66h ; JMP DWORD PTR, as in 32bit offset,
+ jmp wptr cs:pmtormswrout ; not seg:16bit offset
+
+@@0: popad ; load regs with int call values
+ db 0CDh ; issue INT ##h in real-mode
+@@N db 000h
+
+ pushad ; store registers on stack
+ pushf ; store flags on stack
+ cli ; disable interrupts
+ xor eax,eax ; EAX = linear ptr to SS
+ mov ebp,eax
+ mov ax,ss
+ shl eax,4
+ mov bp,sp ; EBP = SP
+ mov ebx,[bp+22h] ; get protected mode SS:ESP from stack
+ mov dx,[bp+26h]
+ add ebp,eax ; EBP -> stored regs on stack
+ mov ax,SELZERO ; DS selector value for protected mode
+ mov cx,SELDATA ; ES selector value for protected mode
+ mov si,SELCODE ; target CS:EIP in protected mode
+ mov edi,offs @@1
+ jmp cs:rmtopmswrout ; go back to protected mode
+
+@@1: inc es:_pc_intrmtopm ; increment INT RM->PM counter
+
+ mov ax,es:rmstacklen ; restore top of real mode stack
+ add es:rmstacktop,ax
+
+ mov ax,ds:[ebp] ; move return FLAGS from real mode
+ and ax,08D5h ; stack to protected mode stack
+ mov dx,[esp+32h]
+ and dx,not 08D5h
+ or ax,dx
+ mov [esp+32h],ax
+ mov eax,ebp
+ mov edi,[eax+2] ; restore return registers from real
+ mov esi,[eax+6] ; mode stack
+ mov ebp,[eax+10]
+ mov ebx,[eax+18]
+ mov edx,[eax+22]
+ mov ecx,[eax+26]
+ mov eax,[eax+30]
+
+ pop gs fs es ds ; restore segment regs
+ add esp,22h ; skip old registers
+ iretd ;**no pop AX
+
+
+
+
+
+;=============================================================================
+; irq_tester is called only for interrupts INT 08..0Fh, only when
+; master PIC is mapped onto those INTs
+;
+irq_tester: ; redirection for IRQs mapped on INT 08..0Fh
+ mov al,0Bh ; query master interrupt controller
+ out 20h,al
+ in al,20h
+ test al,al
+ jz irq_fail ; if no pending IRQ, jump
+
+ mov ax,[esp] ; get caller address from stack
+ sub ax,offs int_matrix+1 ; calculate INT number
+ shr ax,2 ; AX = INT number
+ mov [esp],ax ; save INT number
+
+ and al,07h ; AX = IRQ number
+ bt cs:irqset_pm,ax ; check if user handler is installed
+ pop ax ; restore INT number
+ jnc irq_down ; if not, proceed
+
+ and al,07h ; AX = IRQ number
+ shl ax,3
+ xchg ax,bx
+ sub esp,6 ; alloc 6 bytes on stack
+ mov [esp+4],ax ; put BX on stack
+ mov ax,wptr cs:irqtab_pm[bx+0] ; get target offset loword(EIP)
+ mov [esp+0],ax
+ mov ax,wptr cs:irqtab_pm[bx+2] ; get target offset hiword(EIP)
+ mov [esp+2],ax
+ mov bx,wptr cs:irqtab_pm[bx+4] ; get target selector CS
+ xchg bx,[esp+4] ; put CS and restore BX
+ mov ax,[esp+6] ; restore AX
+ db 66h ; do 32bit far ret to the
+ retf ; appropriate interrupt handler
+
+
+;=============================================================================
+; irq_normal is called for IRQs that do not need to be tested against
+; CPU exceptions
+;
+irq_normal: ; Standard IRQ handler that will send
+ pop ax ; all the IRQs that have not been
+ sub ax,offs int_matrix+1 ; hooked in protected mode to real
+ shr ax,2 ; mode
+
+;-----------------------------------------------------------------------------
+; reflects an IRQ to the real-mode handler
+;
+irq_down:
+ pushad
+ push ds es fs gs
+ mov ds,cs:seldata
+
+ inc _pc_irqpmtorm ; increment IRQ PM->RM counter
+
+ movzx eax,al ; EAX = interrupt number
+
+ mov dx,rmstacktop ; DX = SS for real mode redirection
+ mov bx,rmstacklen ; get size of real mode stack
+ movzx esi,dx ; ESI -> top of real mode stack
+ sub dx,bx ; adjust DX to next stack location
+ shl esi,4
+ cmp dx,rmstackbase ; exceeded real mode stack space?
+ jb critical_error_rm ; if yes, critical error
+ mov rmstacktop,dx ; update ptr for possible reenterancy
+ shl bx,4 ; set real mode SP to top of stack
+
+ mov ds,selzero ; DS -> 0 (beginning of memory)
+ mov edi,[eax*4] ; get real mode interrupt CS:IP
+ mov [esi-2],ss ; store SS: on real mode stack
+ mov [esi-6],esp ; store ESP on real mode stack
+ mov dptr [esi-10],_KERNEL ; set target FLAGS and CS on RM stack
+ mov wptr [esi-12],offs @irq ; set target IP on RM stack
+ shld esi,edi,16
+ sub bx,12 ; adjust real mode SP for stored vars
+ db 66h ; JMP DWORD PTR, as in 32bit offset,
+ jmp wptr cs:pmtormswrout ; not seg:16bit offset
+
+
+
+
+
+;=============================================================================
+; Exception Handler
+;
+; We get here when:
+; + an interrupt in range INT 00..0Fh occurs
+; + irq_tester function determines that there is no pending IRQ
+; in the interrupt controller
+;
+irq_fail:
+ pop ax ; get call address
+ sub ax,offs int_matrix+1 ; calculate INT ##
+ shr ax,2
+;
+; invoke a user-defined exception handler
+;
+ cmp al,08h ; exceptions 08h, 0A..0Eh push error codes
+ jb @@2
+ cmp al,09h
+ je @@2
+ cmp al,0Eh
+ ja @@2
+;
+; rearrange stack frame: have exception code
+;
+@@1: sub esp,16h
+ mov [esp+08h],eax ; save hiword(EAX)
+
+ movzx eax,ax
+ mov eax,cs:exctab_pm[eax*8+0]
+ mov [esp+00h],eax ; target EIP
+
+ movzx eax,wptr [esp+08h]
+ mov eax,cs:exctab_pm[eax*8+4]
+ mov [esp+04h],eax ; target CS
+
+ mov ax,[esp+16h] ; restore AX
+ mov [esp+08h],ax ; save loword(EAX)
+
+ mov ax,cs
+ mov [esp+0Ch],eax ; ret CS
+
+ mov eax,[esp+18h]
+ mov [esp+10h],eax ; EC
+ mov eax,[esp+1Ch]
+ mov [esp+14h],eax ; EIP
+ mov eax,[esp+20h]
+ mov [esp+18h],eax ; CS
+ mov eax,[esp+24h]
+ mov [esp+1Ch],eax ; EFL
+
+ jmp @@run
+;
+; rearrange stack frame: no exception code
+;
+@@2: sub esp,1Ah
+ mov [esp+08h],eax ; save hiword(EAX)
+
+ movzx eax,ax
+ mov eax,cs:exctab_pm[eax*8+0]
+ mov [esp+00h],eax ; target EIP
+
+ movzx eax,wptr [esp+08h]
+ mov eax,cs:exctab_pm[eax*8+4]
+ mov [esp+04h],eax ; target CS
+
+ mov ax,[esp+1Ah] ; restore AX
+ mov [esp+08h],ax ; save loword(EAX)
+
+ mov ax,cs
+ mov [esp+0Ch],eax ; ret CS
+
+ xor eax,eax
+ mov [esp+10h],eax ; EC
+ mov eax,[esp+1Ch]
+ mov [esp+14h],eax ; EIP
+ mov eax,[esp+20h]
+ mov [esp+18h],eax ; CS
+ mov eax,[esp+24h]
+ mov [esp+1Ch],eax ; EFL
+
+@@run: lea eax,[esp+28h]
+ mov [esp+20h],eax ; ESP
+
+ mov ax,ss
+ movzx eax,ax
+ mov [esp+24h],eax ; SS
+
+ mov ax,offs @@ret ; ret EIP
+ xchg eax,[esp+08h] ; restore EAX
+
+ db 66h ; do 32bit far ret to the
+ retf ; appropriate exception handler
+
+
+; exception handler epilogue
+; note: we don't reload the stack but simply ignore SS:ESP values on eh's stack frame
+@@ret: mov [esp],eax
+ mov eax,[esp+0Ch]
+ mov [esp+14h],eax
+ mov eax,[esp+08h]
+ mov [esp+10h],eax
+ mov eax,[esp+04h]
+ mov [esp+0Ch],eax
+ mov eax,[esp]
+ add esp,0Ch
+ iretd
+
+
+;=============================================================================
+; Invoke built-in exception handler
+;
+exc_handler:
+ pop ax
+ sub ax,offs exc_matrix+1
+ shr ax,2
+
+ mov ah,81h ; kernel run-time error 81h
+ jmp dptr cs:client_call ; jump to built-in exception handler
+
+
+
+
+
+
+;=============================================================================
+; Standard IRQ Handler
+;
+; This is a built-in IRQ handler. It is returned by INT 31h, AX=0204h
+; for BL values identifying IRQs for which no user-defined handler had been
+; installed. When a user-defined IRQ handler chains, the call goes here.
+;
+irq_standard: ; Standard IRQ handler that will send
+ cli
+ pop ax ; by default all the IRQs from
+ sub ax,offs std_matrix+1 ; protected mode to real mode
+ shr ax,2
+
+ pushad
+ push ds es fs gs
+ mov ds,cs:seldata
+
+ inc _pc_irqpmtorm ; increment IRQ PM->RM counter
+
+ movzx eax,al ; EAX = IRQ number
+
+ mov dx,rmstacktop ; DX = SS for real mode redirection
+ mov bx,rmstacklen ; get size of real mode stack
+ movzx esi,dx ; ESI -> top of real mode stack
+ sub dx,bx ; adjust DX to next stack location
+ shl esi,4
+ cmp dx,rmstackbase ; exceeded real mode stack space?
+ jb critical_error_rm ; if yes, critical error
+ mov rmstacktop,dx ; update ptr for possible reenterancy
+ shl bx,4 ; set real mode SP to top of stack
+
+ mov edi,irqtab_rm[eax*4] ; get real mode interrupt CS:IP
+ mov ds,selzero ; DS -> 0 (beginning of memory)
+ mov [esi-2],ss ; store SS: on real mode stack
+ mov [esi-6],esp ; store ESP on real mode stack
+ mov dptr [esi-10],_KERNEL ; set target FLAGS and CS on RM stack
+ mov wptr [esi-12],offs @irq ; set target IP on RM stack
+ shld esi,edi,16
+ sub bx,12 ; adjust real mode SP for stored vars
+ db 66h ; JMP DWORD PTR, as in 32bit offset,
+ jmp wptr cs:pmtormswrout ; not seg:16bit offset
+
+@irq: cli
+ mov ax,SELDATA ; DS selector value for protected mode
+ mov cx,ax ; ES selector value for protected mode
+ pop ebx ; get protected mode SS:ESP from stack
+ pop dx
+ mov si,SELCODE ; target CS:EIP in protected mode
+ mov edi,offs @@2
+ jmp cs:rmtopmswrout ; go back to protected mode
+
+@@2: inc _pc_irqrmtopm ; increment IRQ RM->PM counter
+
+ mov ax,rmstacklen ; restore top of real mode stack
+ add rmstacktop,ax
+
+ pop gs fs es ds ; restore all registers
+ popad
+ pop ax ; restore original AX
+ iretd
+
+
+
+
+
+
+
+
+; IRQ Callback
+;
+; Used by IRQs in real mode to process protected mode IRQ handlers.
+;
+;=============================================================================
+irq_callback:
+ cli
+ pop ax
+ sub ax,offs back_matrix+1
+ shr ax,2 ; AX = IRQ number
+
+ pushad
+ push ds es fs gs
+ mov ds,cs:kernel_code
+
+ inc _pc_irqcbrmtopm ; increment IRQCallback RM->PM counter
+ mov temp_int,al
+
+ mov edx,pmstacktop ; EDX = ESP for protected mode
+ mov ebx,edx
+ sub edx,pmstacklen
+ cmp edx,pmstackbase ; exceeded protected mode stack space?
+ jb critical_error_pm ; if yes, critical error
+ mov pmstacktop,edx ; update ptr for possible reenterancy
+
+ mov bp,ss ; save real mode SS:SP in EBP
+ shl ebp,16
+ mov bp,sp
+ mov si,irqcallbackptr ; save ESP across mode switches
+ mov dptr @callback_data[si+100h],esp
+ add irqcallbackptr,4
+
+ mov ax,SELCODE ; prot. mode DS
+ mov cx,SELZERO ; prot. mode ES
+ mov dx,cx ; prot. mode SS
+ mov si,ax ; prot. mode CS
+ mov edi,offs @@0 ; prot. mode EIP
+ jmp rmtopmswrout ; switch to protected mode
+
+@@0: movzx bx,temp_int
+ shl bx,3 ; BX = pointer to interrupt ##h
+ pushfd ; set return eflags
+ push large SELCODE ; set return CS on PM stack
+ push large offs @@1 ; set return EIP on PM stack
+ db 66h
+ jmp dptr irqtab_pm[bx] ; go to prot. mode interrupt handler
+
+@@1: mov ax,_KERNEL ; AX = real mode DS
+ mov si,ax ; SI = real mode CS
+ mov di,offs @@2 ; DI = real mode IP
+ mov bx,bp ; BX = real mode SP
+ shr ebp,16
+ mov dx,bp ; DX = real mode SS
+ db 66h
+ jmp wptr cs:pmtormswrout ; switch to real mode
+
+@@2: inc _pc_irqcbpmtorm ; increment IRQCallback PM->RM counter
+
+ mov eax,pmstacklen
+ add pmstacktop,eax
+
+ sub irqcallbackptr,4 ; restore original ESP
+ mov si,irqcallbackptr
+ mov esp,dptr @callback_data[si+100h]
+
+ pop gs fs es ds
+ popad
+ pop ax
+ iret ; return from IRQ callback
+
+
+
+
+
+
+
+
+;=============================================================================
+; Real mode callback actual code:
+;
+;## pushad
+;## push 0 ; if 0, callback is free
+;## push large 0
+;## mov cx,0 ; load CX with callers ES
+;## push large
+;## jmp far ptr ?:?
+;
+callback: ; real mode callback handler
+ mov ax,sp ; preserve SS:SP for callback
+ push ss
+ push ax
+ push gs fs ds es ; preserve real mode regs for callback
+ pushf ; preserve FLAGS for callback
+ cli
+ push cs
+ pop ds
+
+ inc _pc_cbrmtopm ; increment Callback RM->PM counter
+
+ mov ebp,pmstacktop ; EBP = ESP for protected mode
+ mov ebx,ebp ; set EBX to next stack location
+ sub ebx,pmstacklen
+ mov pmstacktop,ebx ; update ptr for possible reenterancy
+ cmp ebx,pmstackbase ; exceeded protected mode stack space?
+ jb critical_error_pm ; if yes, critical error
+
+ xor eax,eax ; EAX = base address of SS
+ mov ebx,eax
+ mov ax,ss
+ shl eax,4
+ mov bx,sp ; EBX = current linear SS:SP
+ add ebx,eax
+
+ mov es,ds:gdtseg ; set for protected mode callback DS
+ or eax,92000000h ; base address in GDT
+ mov es:[SELCALLBACK+2],eax
+ mov ax,SELZERO ; DS selector for protected mode
+ mov dx,ax ; SS selector = DS selector
+ mov si,SELCODE ; target protected mode CS:EIP
+ mov edi,offs @@0
+ jmp rmtopmswrout ; go to protected mode
+
+@@0: mov edi,[esp+14] ; EDI -> register structure from stack
+ lea esi,[esp+24] ; copy general registers from stack
+ mov ecx,8 ; to register structure
+ cld
+ rep movs dptr es:[edi],ds:[esi]
+
+ mov esi,esp ; copy FLAGS, ES, DS, FG, and GS
+ movs wptr es:[edi],ds:[esi]
+ movs dptr es:[edi],ds:[esi]
+ movs dptr es:[edi],ds:[esi]
+ lods dptr ds:[esi] ; EAX = real mode SS:SP from stack
+ add ax,42 ; adjust SP for stuff on stack
+ mov es:[edi+4],eax ; put in register structure
+ mov ds,cs:selcallback ; DS = callback DS selector
+ sub edi,42 ; EDI -> register structure
+ movzx esi,ax ; ESI = old real mode SP
+ xchg esp,ebp ; ESP = protected mode stack
+ pushfd ; push flags for IRETD from callback
+ push large cs ; push 32bit CS for IRETD
+ push large offs @@1 ; push 32bit EIP for IRETD
+ movzx eax,wptr [ebp+22] ; EAX = target CS of callback
+ push eax ; push 32bit CS for RETF to callback
+ push dptr [ebp+18] ; push 32bit EIP for retf
+ db 66h ; 32bit RETF to callback
+ retf
+
+@@1: cli
+ push es ; DS:ESI = register structure
+ pop ds
+ mov esi,edi
+ mov es,cs:selzero ; ES -> 0 (beginning of memory)
+ movzx ebx,wptr [esi+2Eh] ; EBX = real mode SP from structure
+ movzx edx,wptr [esi+30h] ; EDX = real mode SS from structure
+ sub bx,42 ; subtract size of vars to be put
+ mov ebp,[esi+0Ch] ; EBP = pushed ESP from real mode
+ mov bp,bx ; EBP = old high & new low word of ESP
+ lea edi,[edx*4] ; EDI -> real mode base of stack
+ lea edi,[edi*4+ebx] ; of vars to be stored
+ mov ecx,8 ; copy general registers to stack
+ cld
+ rep movs dptr es:[edi],ds:[esi]
+ mov eax,[esi+6] ; EAX = return FS and GS for real mode
+ mov es:[edi],eax ; store on real mode stack for return
+ mov eax,[esi+10] ; EAX = return CS:IP for real mode
+ mov es:[edi+4],eax ; store on real mode stack for return
+ mov ax,[esi] ; AX = return FLAGS for real mode
+ mov es:[edi+8],ax ; store on real mode stack for return
+ mov ax,[esi+4] ; AX = return DS for real mode
+ mov cx,[esi+2] ; CX = return ES for real mode
+ mov si,_KERNEL ; real mode target CS:IP
+ mov di,offs @@2
+ db 66h ; JMP DWORD PTR, as in 32bit offset,
+ jmp wptr cs:pmtormswrout ; not seg:16bit offset
+
+@@2: inc cs:_pc_cbpmtorm ; increment Callback PM->RM counter
+
+ mov esp,ebp ; restore total ESP, old high word
+ mov eax,cs:pmstacklen ; restore top of protected mode stack
+ add cs:pmstacktop,eax
+
+ popad ; get callback return general regs
+ pop fs gs ; get callback return FS and GS values
+ iret ; go to callback return CS:IP
+
diff -uNr a/dos32a/src/dos32a/text/kernel/misc.asm b/dos32a/src/dos32a/text/kernel/misc.asm
--- a/dos32a/src/dos32a/text/kernel/misc.asm false
+++ b/dos32a/src/dos32a/text/kernel/misc.asm 78db6faa3e49482cb71408bd5ecfcb1edd8f545e7c001583d085a9030605c72c7c07fa9741f71df400a68ce75aaf89fc23420c73ffee3074424e9942ad3bd70f
@@ -0,0 +1,295 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+; Real mode INT 15h
+;=============================================================================
+int15h_rm:
+ cmp ah,88h ; if function 88h, need to process
+ jz @@1
+ cmp ax,0E801h ; if function 0E801h, not supported
+ jz @@err
+ cmp ax,0E820h ; if function 0E820h, not supported
+ jz @@err
+ jmp cs:oldint15h ; chain to the old INT 15h handler
+
+@@1: pushf ; call old INT 15h handler
+ call cs:oldint15h
+ sub ax,cs:mem_used ; adjust AX by extended memory used
+ jnc @@ok
+ xor ax,ax ; reset on overflow
+
+@@ok: push bp
+ mov bp,sp
+ and bptr [bp+6],0FEh ; clear carry flag on stack for IRET
+ pop bp
+ iret
+
+@@err: push bp
+ mov bp,sp
+ or bptr [bp+6],01h ; set carry flag on stack for IRET
+ pop bp
+ iret
+
+
+
+; Real mode INT 21h
+;=============================================================================
+int21h_rm:
+ cmp cs:id32_tsrmode_id,0 ; if we are TSR, ignore 0FF88h calls
+ jnz @@1
+
+ cmp ax,0FF88h ; DOS/32A id call
+ jz int21h_call
+
+ cmp cs:id32_spawned_id,0 ; check if we're in spawn mode
+ jnz @@1 ; if yes, chain to the previous handler
+
+ cmp ah,4Ch ; Real mode INT 21h
+ jz int21h_exit
+ cmp ah,4Bh
+ jz int21h_spawn
+ cmp ah,31h
+ jz int21h_tsr
+@@1: jmp cs:oldint21h ; go to original real mode INT 21h
+
+
+;-----------------------------------------------------------------------------
+int21h_exit:
+ cli
+ mov bp,ax ; preserve AX=exit code
+ mov ax,SELDATA ; DS selector for protected mode
+ mov cx,ax
+ mov dx,SELZERO ; SS selector = zero selector
+ mov ebx,cs:pmstacktop ; EBX = ESP for protected mode
+ mov si,SELCODE ; target protected mode CS:EIP
+ mov edi,offs @@1
+ jmp cs:rmtopmswrout ; switch to protected mode
+@@1: mov ax,bp ; restore AX=exit code
+ jmp int21h_pm
+
+;-----------------------------------------------------------------------------
+int21h_spawn:
+ mov cs:id32_spawned_id,1 ; disable memory deallocation
+ pushf
+ call cs:oldint21h
+ mov cs:id32_spawned_id,0
+ pop bx cx dx ; pop IP, CS, FLG
+ push cx bx ; push CS, IP
+ retf
+
+;-----------------------------------------------------------------------------
+int21h_call: ; DOS/32A functional call (real mode)
+ mov eax,'ID32' ; EAX = "ID32"
+ movzx ebx,cs:client_version ; EBX = client version
+ mov ecx,cs:mem_free ; ECX = size of free memory
+ mov edx,cs:mem_ptr ; EDX = base of free memory
+ mov si,cs:id32_process_id ; SI(hi) = previous process id
+ shl esi,16
+ movzx si,cs:pagetables ; SI(lo) = pagetables allocated
+ mov edi,cs:pagetablefree ; EDI = base of free pagetable space
+ iret
+
+;-----------------------------------------------------------------------------
+int21h_tsr:
+ mov cs:id32_tsrmode_id,1 ; indicate that we are going TSR
+ jmp cs:oldint21h
+
+
+
+; Protected mode INT 1Bh callback handler
+;=============================================================================
+int1Bh: call intold_save
+ int 1Bh ; call protected mode INT 1Bh
+ mov ax,6
+ jmp intold_restore
+
+
+; Protected mode INT 1Ch callback handler
+;=============================================================================
+int1Ch: call intold_save
+ push ds
+ mov ds,cs:selzero ; restore default INT 1Ch
+ mov eax,cs:oldint1Ch
+ mov ds:[4*1Ch],eax
+ pop ds
+ int 1Ch ; call protected mode INT 1Ch
+ push ds
+ mov ds,cs:selzero ; restore callback INT 1Ch
+ mov eax,cs:newint1Ch
+ mov ds:[4*1Ch],eax
+ pop ds
+ mov ax,6
+ jmp intold_restore
+
+
+; Protected mode INT 23h callback handler
+;=============================================================================
+int23h: call intold_save
+ clc
+ mov ebp,esp
+ int 23h ; call protected mode INT 23h
+ mov esp,ebp
+ setc ah
+ mov al,es:[edi+20h]
+ and al,0FEh
+ add al,ah
+ mov es:[edi+20h],al
+ mov ax,4
+ jmp intold_restore
+
+
+; Protected mode INT 24h callback handler
+;=============================================================================
+int24h: call intold_save
+ push edi
+ push dptr ds:[esi+1Ah] ; CS, FLG
+ push dptr ds:[esi+16h] ; ES, IP
+ push dptr ds:[esi+12h] ; BP, DS
+ push dptr ds:[esi+0Eh] ; SI, DI
+ push dptr ds:[esi+0Ah] ; CX, DX
+ push dptr ds:[esi+06h] ; AX, BX
+ mov ax,wptr es:[edi+1Ch] ; get register AX
+ mov bp,wptr es:[edi+08h] ; get register BP
+ mov si,wptr es:[edi+04h] ; get register SI
+ mov di,wptr es:[edi+00h] ; get register DI
+ int 24h ; call protected mode INT 24h
+ add esp,18h
+ pop edi
+ mov es:[edi+1Ch],al
+ mov ax,6
+ jmp intold_restore
+
+
+;-----------------------------------------------------------------------------
+intold_save:
+ pop bp
+ mov ax,ds:[esi+04h] ; update FLAGS in structure
+ mov es:[edi+20h],ax
+ mov eax,ds:[esi+00h] ; update CS:IP in structure
+ mov es:[edi+2Ah],eax
+ push es edi
+ jmp bp
+
+;-----------------------------------------------------------------------------
+intold_restore:
+ pop edi es
+ add es:[edi+2Eh],ax
+ iretd
+
+
+
+
+;=============================================================================
+; Enable/Disable A20 Line
+;=============================================================================
+enable_A20: ; hardware enable gate A20
+ pushf
+ cli
+ call enablea20test ; is A20 already enabled?
+ setz al ; AL = 00h (OFF), AL = 01h (ON)
+ mov A20_state,al
+ jz @@done ; if yes, done
+ in al,92h ; PS/2 A20 enable
+ or al,02h
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+ out 92h,al
+ call enablea20test
+ jz @@done
+ call enablea20kbwait ; AT A20 enable
+ jnz @@f0
+ mov al,0D1h
+ out 64h,al
+ call enablea20kbwait
+ jnz @@f0
+ mov al,0DFh
+ out 60h,al
+ call enablea20kbwait
+@@f0: mov cx,0800h ; wait for A20 to enable do 800h tries
+@@l0: call enablea20test ; is A20 enabled?
+ jz @@done ; if yes, done
+ in al,40h ; get current tick counter
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+ in al,40h
+ mov ah,al
+@@l1: in al,40h ; wait a single tick
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+ in al,40h
+ cmp al,ah
+ je @@l1
+ loop @@l0 ; loop for another try
+ popf
+ stc ; error: set carry flag
+ ret
+@@done: popf
+ clc ; success: clear carry
+ ret
+
+;-----------------------------------------------------------------------------
+enablea20kbwait: ; wait for safe to write to 8042
+ xor cx,cx
+@@0: jmp short $+2
+ jmp short $+2
+ jmp short $+2
+ in al,64h ; read 8042 status
+ test al,2 ; buffer full?
+ loopnz @@0 ; if yes, loop
+ ret
+
+;-----------------------------------------------------------------------------
+enablea20test: ; test for enabled A20
+ push fs gs
+ xor ax,ax ; set A20 test segments 0 and 0ffffh
+ mov fs,ax
+ dec ax
+ mov gs,ax
+ mov al,fs:[0000h] ; get byte from 0:0
+ mov ah,al ; preserve old byte
+ not al ; modify byte
+ xchg al,gs:[0010h] ; put modified byte to 0ffffh:10h
+ cmp ah,fs:[0000h] ; set zero if byte at 0:0 not modified
+ mov gs:[0010h],al ; put back old byte at 0ffffh:10h
+ pop gs fs
+ ret ; return, zero if A20 enabled
+
diff -uNr a/dos32a/src/dos32a/text/kernel/mode.asm b/dos32a/src/dos32a/text/kernel/mode.asm
--- a/dos32a/src/dos32a/text/kernel/mode.asm false
+++ b/dos32a/src/dos32a/text/kernel/mode.asm e9591a4ffd6987f8195684ec71f0ffeb3d4d7313cbd3a4aaebd33a918de186baf6fbbc9ebd062753cf29db992a4b9c9ce3a7384a45d09f9a464ff61ffeda4f8a
@@ -0,0 +1,207 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; Mode Switching Routines
+;=============================================================================
+
+;=============================================================================
+; VCPI real mode to protected mode switch
+;
+; AX = protected mode DS
+; CX = protected mode ES
+; DX = protected mode SS
+; EBX = protected mode stack pointer
+; ESI = protected mode target CS
+; EDI = protected mode target IP
+;
+ Align 4
+v_rmtopmsw:
+ pushf ; store FLAGS
+ cli
+ mov ds,cs:kernel_code ; DS = _KERNEL
+ pop tempw0 ; move FLAGS from stack to temp
+ mov tempw1,ax ; store AX (protected mode DS)
+ mov tempw2,si ; store SI (protected mode CS)
+ mov esi,vcpistrucaddx ; ESI = linear addx of VCPI structure
+ mov ax,0DE0Ch ; VCPI switch to protected mode
+ int 67h
+v_rmtopmswpm:
+ mov ss,dx ; load protected mode SS:ESP
+ mov esp,ebx
+ mov ds,cs:tempw1 ; load protected mode DS
+ mov es,cx ; load protected mode ES
+ xor ax,ax
+ mov fs,ax ; load protected mode FS with NULL
+ mov gs,ax ; load protected mode GS with NULL
+ pushfd ; store EFLAGS
+ mov ax,cs:tempw0 ; move bits 0-11 of old FLAGS onto
+ and ah,0Fh ; stack for IRETD
+ mov [esp],ax
+ push cs:tempd1 ; store protected mode target CS
+ push edi ; store protected mode target EIP
+ iretd ; go to targed addx in protected mode
+
+;=============================================================================
+; VCPI protected mode to real mode switch
+;
+; AX = real mode DS
+; CX = real mode ES
+; DX = real mode SS
+; BX = real mode stack pointer
+; SI = real mode target CS
+; DI = real mode target IP
+;
+ Align 4
+v_pmtormsw:
+ pushf ; store FLAGS
+ cli
+ push ax ; store AX (real mode DS)
+ mov ds,cs:selzero ; DS -> 0 (beginning of memory)
+ movzx ebx,bx ; clear high word of EBX, real mode SP
+ mov eax,cs:vcpiswitchstack ; EAX -> top of temporary switch stack
+ movzx edx,dx ; clear high word of EDX, real mode SS
+ mov dptr ds:[eax+32],0 ; store real mode GS
+ movzx ecx,cx ; clear high word of ECX, real mode ES
+ mov dptr ds:[eax+28],0 ; store real mode FS
+ mov ds:[eax+20],ecx ; store real mode ES
+ pop cx ; move real mode DS from protected
+ mov ds:[eax+24],ecx ; mode stack to VCPI call stack
+ mov ds:[eax+16],edx ; store real mode SS
+ mov ds:[eax+12],ebx ; store real mode SP
+ mov dptr ds:[eax+4],_KERNEL ; store real mode CS
+ mov dptr ds:[eax],offs @@0 ; store real mode IP
+ pop bx ; restore FLAGS from stack
+ mov ss,cs:selzero ; SS -> 0 (beginning of memory)
+ mov esp,eax ; ESP = stack ptr for VCPI call
+ mov ax,0DE0Ch ; VCPI switch to real mode (V86)
+ call fptr cs:vcpi_calleip
+@@0: push bx ; store old FLAGS
+ push si ; store target CS in real mode
+ push di ; store target IP in real mode
+ iret ; go to target addx in real mode
+
+
+;=============================================================================
+; XMS/RAW real mode to protected mode switch
+;
+; AX = protected mode DS
+; CX = protected mode ES
+; DX = protected mode SS
+; EBX = protected mode stack pointer
+; ESI = protected mode target CS
+; EDI = protected mode target IP
+;
+ Align 4
+xr_rmtopmsw:
+ pushfd ; store EFLAGS
+ cli
+ push ax ; store AX (protected mode DS)
+ lidt fptr cs:idtlimit ; load protected mode IDT
+ lgdt fptr cs:gdtlimit ; load protected mode GDT
+ mov eax,cr0 ; switch to protected mode
+ or al,01h
+ mov cr0,eax
+ db 0EAh ; JMP FAR PTR SELCODE:$+4
+ dw $+4,SELCODE ; (clear prefetch que)
+ pop ds ; load protected mode DS
+ mov es,cx ; load protected mode ES
+ xor ax,ax
+ mov fs,ax ; load protected mode FS with NULL
+ mov gs,ax ; load protected mode GS with NULL
+ pop eax
+ mov ss,dx ; load protected mode SS:ESP
+ mov esp,ebx
+ and ah,0BFh ; set NT=0 in old EFLAGS
+ push ax ; set current FLAGS
+ popf
+ push eax ; store old EFLAGS
+ push esi ; store protected mode target CS
+ push edi ; store protected mode target EIP
+ iretd ; go to target addx in protected mode
+
+;=============================================================================
+; XMS/RAW protected mode to real mode switch
+;
+; AX = real mode DS
+; CX = real mode ES
+; DX = real mode SS
+; BX = real mode stack pointer
+; SI = real mode target CS
+; DI = real mode target IP
+;
+ Align 4
+xr_pmtormsw:
+ pushf ; store FLAGS
+ cli
+ push ax ; store AX (real mode DS)
+ mov ds,cs:seldata ; DS -> 0 (beginning of memory)
+ pop tempw0 ; move real mode DS from stack to temp
+ pop tempw1 ; move FLAGS from stack to temp
+ mov ax,SELDATA ; load descriptors with real mode seg
+ mov ds,ax ; attributes
+ mov es,ax
+ mov fs,ax
+ mov gs,ax
+ mov ss,ax ; load descriptor with real mode attr
+ movzx esp,bx ; load real mode SP, high word 0
+ lidt fptr rmidtlimit ; load real mode IDT
+ mov eax,cr0 ; switch to real mode
+ and al,0FEh ; turn off protected mode
+ mov cr0,eax
+ db 0EAh ; JMP FAR PTR _KERNEL:$+4
+ dw $+4,_KERNEL ; (clear prefetch que)
+ mov ss,dx ; load real mode SS
+ mov ds,cs:tempw0 ; load real mode DS
+ mov es,cx ; load real mode ES
+ xor ax,ax
+ mov fs,ax ; load real mode FS with NULL
+ mov gs,ax ; load real mode GS with NULL
+ push cs:tempw1 ; store old FLAGS
+ push si ; store real mode target CS
+ push di ; store real mode target IP
+ iret ; go to target addx in real mode
+
+
+;=============================================================================
+vxr_saverestorepm: ; VCPI/XMS/RAW save/restore status
+ db 66h ; no save/restore needed, 32bit RETF
+vxr_saverestorerm: ; VCPI/XMS/RAW save/restore status
+ retf ; no save/restore needed, 16bit RETF
+
diff -uNr a/dos32a/src/dos32a/text/oemtitle.asm b/dos32a/src/dos32a/text/oemtitle.asm
--- a/dos32a/src/dos32a/text/oemtitle.asm false
+++ b/dos32a/src/dos32a/text/oemtitle.asm e478320339d8dfd14b68cb0fb7cf300aeb3cc96784a90a195dd06505f42d82a42ef46b46d87ed0a64af9cbd8ab543b0ad5d692dc003266243b207b825a6a1d45
@@ -0,0 +1,47 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+
+;=============================================================================
+; OEM info
+;
+db 'DOS/32A' ,0
+db 'Copyright (C) 1996-2006 by Narech K.' ,0
+db ??date ,0
+db ??time ,0
diff -uNr a/dos32a/src/dos32a/text/testbeta.asm b/dos32a/src/dos32a/text/testbeta.asm
--- a/dos32a/src/dos32a/text/testbeta.asm false
+++ b/dos32a/src/dos32a/text/testbeta.asm fe662b35dee08d6866d8f292b38888b7451d4d337fd1b47d056a487021e47eb5adcb64c3ec1350d67075a7cc15ab64f70b0d3755dc624cff7a9454cfe2d61369
@@ -0,0 +1,195 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+;=============================================================================
+; Low-level debugging support for beta releases
+;
+; Note: this code is shared between CLIENT & KERNEL; whenever there is a need
+; to differentiate between the two (seg/sel regs and such), use the
+; BUILDING_KERNEL and BUILDING_CLIENT macro symbols
+;
+;=============================================================================
+
+
+;=============================================================================
+; write the contents of AL (8-bit) register to STDOUT
+;
+dbg_hexal:
+ push dx
+ mov dx,offs hexbuf+6
+ jmp mkhex
+
+;=============================================================================
+; write the contents of AX (16-bit) register to STDOUT
+;
+dbg_hexax:
+ push dx
+ mov dx,offs hexbuf+4
+ jmp mkhex
+
+;=============================================================================
+; write the contents of EAX (32-bit) register to STDOUT
+;
+; works from real & protected modes, should be fairly transparent to the app
+;
+dbg_hexeax:
+ push dx
+ mov dx,offs hexbuf
+mkhex: push eax cx si di ds dx
+ smsw si
+ test si,1
+ jz @@0
+;
+; TODO: rewrite this shit pronto! (in particular avoid memory r/w access a la CLIENT/strings.asm)
+;
+
+If BUILDING_KERNEL eq 0
+ mov ds,cs:_sel_ds
+ jmp @@1
+@@0: mov ds,cs:_seg_ds
+Else
+ mov ds,cs:seldata
+ jmp @@1
+@@0: mov ds,cs:kernel_code
+Endif
+
+@@1: mov di,7
+
+@@cvt: mov si,ax
+ and si,000Fh
+ mov cl,cs:hextab[si]
+ mov ds:hexbuf[di],cl
+ shr eax,4
+ dec di
+ jns @@cvt
+ pop si
+
+ mov cx,offs hexbuf+10
+ sub cx,si
+@@loop: lodsb
+ mov dl,al
+ mov ah,2
+ int 21h
+ loop @@loop
+ pop ds di si cx eax dx
+ ret
+hextab db '0123456789ABCDEF'
+hexbuf db ' ',13,10
+
+
+;=============================================================================
+; pause until a key is pressed
+;
+; note: this switches CPU to real mode (BIOS Fn Int16h/AX=0)
+;
+dbg_kbhit:
+ push ax
+ xor ax,ax
+ int 16h
+ pop ax
+ ret
+
+;=============================================================================
+; beep a sound from the PC speaker
+; AX = frequency
+; CX = time
+;
+dbg_beep:
+@@0: push cx dx ax ; AX=frequency, CX=time
+ mov al,0B6h ; set frequency
+ out 43h,al
+ pop ax
+ out 42h,al ; fLow
+ mov al,ah
+ out 42h,al ; fHigh
+ in al,61h ; beep on
+ or al,03h
+ out 61h,al
+@@loop: in al,40h
+ in al,40h
+ mov ah,al
+@@1: in al,40h
+ in al,40h
+ cmp ah,al
+ je @@1
+ loop @@loop
+ in al,61h ; beep off
+ and al,not 03h
+ out 61h,al
+ pop dx cx
+ ret
+
+;=============================================================================
+; halt execution forever
+;
+; this blocks app execution in an endless loop, with predicate AX being tested
+; for being zero; the state of AX is then expected to be changed by an external
+; debugger (i.e. from an emulator) so that debugging can proceed from that point
+;
+dbg_halt:
+ pushf
+ cli
+ push ax
+ xor ax,ax
+@@loop: test ax,ax
+ jz @@loop
+ pop ax
+ sti
+ popf
+ ret
+
+;=============================================================================
+; convinience fn: peep a beep, then die a little in hope of a better future
+;
+; real men don't use no hardware debuggers!
+;
+dbg_break:
+ pushf
+ push ax cx
+ mov cx,0200h
+ mov ax,0500h
+ call dbg_beep
+ mov ax,0100h
+ call dbg_beep
+ mov ax,0500h
+ call dbg_beep
+ pop cx ax
+ popf
+ jmp dbg_halt
+
diff -uNr a/dos32a/src/sb/main.c b/dos32a/src/sb/main.c
--- a/dos32a/src/sb/main.c false
+++ b/dos32a/src/sb/main.c 2a93fe78aab27f99d2c936b99b69a8d91d96b4262c255567ed72a644b3acf49b62b307bcfa67fc15a51f66fa5972266113a9a3212f9c4fdd82da7ea4b41cd037
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "main.h"
+
+ char* version = "9.1.2";
+ char newname[80];
+ char newname2[80];
+ char filename[80];
+ char name_bn[80];
+ char name_un[80];
+ char* bufptr;
+ char* bufptr2;
+ char* fileptr;
+
+ char* stubname;
+ char* stubname1 = "DOS32A.EXE";
+ char* stubname2 = "STUB32A.EXE";
+ char* stubname3 = "STUB32C.EXE";
+ char* errstr = "SB/32A fatal:";
+ char* tempname = "$$SB32$$.TMP";
+
+ int execargn = 1;
+ int filesize = 0;
+ int oldfilesize = 0;
+ int newfilesize = 0;
+
+ int Main_Type = -1;
+ int Exec_Type = -1;
+ int Extender_Type = -1;
+
+ int bind = FALSE;
+ int unbind = FALSE;
+ int overwrite = FALSE;
+ int quiet = FALSE;
+ int silent = TRUE;
+ int bind_name = FALSE;
+ int unbind_name = FALSE;
+
+
+
+
+/****************************************************************************/
+void err_open(char *str) {
+ printf("%s cannot open file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_rdonly(char *str) {
+ printf("%s cannot open Read-Only file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_seek(char *str) {
+ printf("%s error seeking in file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_read(char *str) {
+ printf("%s error reading from file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_support(char *str) {
+ printf("%s unsupported exec format in file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_dest(char *str) {
+ printf("%s destination file \"%s\" already exists\n",errstr,str);
+ exit(1);
+}
+void err_mem(char *str) {
+ printf("%s not enough memory to load file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_crtmp(void) {
+ printf("%s error creating temp file\n",errstr);
+ exit(1);
+}
+void err_wrtmp(void) {
+ printf("%s error writing to temp file\n",errstr);
+ exit(1);
+}
+void err_rdstub(void) {
+ printf("%s error reading from stub file\n",errstr);
+ exit(1);
+}
+void err_invstub(void) {
+ printf("%s invalid stub file format\n",errstr);
+ exit(1);
+}
+void err_nod32a(void) {
+ printf("%s cannot find file \"DOS32A.EXE\"\n",errstr);
+ exit(1);
+}
+void err_nostub(char *str) {
+ printf("%s cannot find file \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_arg(char *str) {
+ printf("%s invalid or misplaced command or option \"%s\"\n",errstr,str);
+ exit(1);
+}
+void err_sameact(void) {
+ printf("%s cannot Bind and Unbind at the same time\n",errstr);
+ exit(1);
+}
+void err_nullname(void) {
+ printf("%s you must specify a file name with /BN or /UN options\n",errstr);
+ exit(1);
+}
+void err_environment(void) {
+ printf("%s DOS/32A environment variable is not set up properly\n",errstr);
+ printf("You need to reinstall DOS/32 Advanced DOS Extender on this computer\n");
+ exit(1);
+}
+
+
+
+/****************************************************************************/
+void ShowCopyright()
+{
+ Print("SB/32A -- Bind Utility version %s\n",version);
+ Print("Copyright (C) 1996-2006 by Narech K.\n");
+}
+
+
+
+void ArgInit(int argc, char *argv[])
+{
+ int n,m;
+ int argn=14;
+ char *args[] = { "bs", "bc", "bn", "rs", "rc", "un", "b", "r", "u", "o", "q", "s", "h", "?" };
+
+ execargn=1;
+
+ if(argc>=2)
+ {
+ for(n=1; n=argc)
+ {
+l1: Print("SB/32A fatal: syntax is SB [commands] [options] \n\n");
+ Print("Commands:\n");
+ Print("---------\n");
+ Print("/B Bind DOS/32A to Linear Executable\n");
+ Print("/BS Bind STUB/32A to Linear Executable\n");
+ Print("/BC Bind STUB/32C to Linear Executable\n");
+ Print("/R Replace existing Stub/Extender with DOS/32A\n");
+ Print("/RS Replace existing Stub/Extender with STUB/32A\n");
+ Print("/RC Replace existing Stub/Extender with STUB/32C\n");
+ Print("/U Unbind Linear Executable from the existing Stub\n\n");
+ Print("Options:\n");
+ Print("--------\n");
+ Print("/BNfilename.xxx Specify destination file name when Binding\n");
+ Print("/UNfilename.xxx Specify destination file name when Unbinding\n");
+ Print("/O Unconditionally Overwrite existing files\n");
+ Print("/Q Quiet mode (partially disables console output)\n");
+ Print("/S Silent mode (totally disables console output)\n");
+ Print("/H or /? This help\n");
+ exit(1);
+ }
+}
+
+
+void OpenExec(char *argv[])
+{
+ int n,m;
+
+ strcpy(filename,argv[execargn]);
+ n=open_exec(filename);
+
+ if(n==-2)
+ err_rdonly(argv[execargn]);
+ if(n!=0)
+ {
+ strcpy(filename,argv[execargn]);
+ strcat(filename,".exe");
+ n=open_exec(filename);
+ if(n==-2)
+ err_rdonly(argv[execargn]);
+ if(n!=0)
+ {
+ strcpy(filename,argv[execargn]);
+ strcat(filename,".le");
+ n=open_exec(filename);
+ if(n==-2)
+ err_rdonly(argv[execargn]);
+ if(n!=0)
+ {
+ strcpy(filename,argv[execargn]);
+ strcat(filename,".lx");
+ n=open_exec(filename);
+ if(n==-2)
+ err_rdonly(argv[execargn]);
+ if(n!=0)
+ {
+ strcpy(filename,argv[execargn]);
+ strcat(filename,".lc");
+ n=open_exec(filename);
+ if(n==-2)
+ err_rdonly(argv[execargn]);
+ }
+ }
+ }
+ }
+ if(n==-1)
+ err_open(argv[execargn]);
+}
+
+
+
+
+/****************************************************************************/
+int GetExecType(char *argv[])
+{
+ int n;
+
+ n=check_if_unbound_exec();
+
+ if(n==-1)
+ err_seek(argv[execargn]);
+ else if(n==-2)
+ err_read(argv[execargn]);
+ else if(n==-3)
+ err_support(argv[execargn]);
+
+ return(n);
+}
+
+int FindExecType(char *argv[])
+{
+ int n;
+
+ n=get_exec_start();
+ if(n==-1)
+ err_read(argv[execargn]);
+ else if(n==-2)
+ return(-1);
+
+ n=get_exec_type();
+ if(n==-1)
+ err_read(argv[execargn]);
+ else if(n==-2)
+ return(-1);
+
+ return(n);
+}
+
+int GetExtenderType(char *argv[])
+{
+ int n;
+
+ n=get_extender_type();
+ if(n==-1)
+ err_read(argv[execargn]);
+
+ return(n);
+}
+
+
+
+
+
+
+
+
+
+
+/****************************************************************************/
+void main(int argc, char *argv[])
+{
+ int n=-1;
+ int m=-1;
+ int l=-1;
+ int e=-1;
+ int x,y;
+ char buf[80];
+
+ ArgInit(argc, argv);
+ OpenExec(argv);
+ filesize=filelength(exec_handle);
+ n=GetExecType(argv);
+
+ if(n==0)
+ {
+ m=FindExecType(argv);
+ l=GetExtenderType(argv);
+ }
+
+ Main_Type=n; /* file format: LE, LX, LC, PE */
+ Exec_Type=m; /* same as "n" when bound */
+ Extender_Type=l; /* Stub/Extender type */
+
+ Print("\n");
+ Print("Application Name: \"%s\"\n",argv[execargn]);
+ Print("Application Size: %d bytes\n",filesize);
+ Print("Application Type: ");
+ if(n!=0)
+ {
+ if(n==1) Print(" Unbound LE-style file format Linear Executable");
+ if(n==2) Print(" Unbound LX-style file format Linear Executable");
+ if(n==3) Print(" Unbound LC-style file format Linear Executable");
+ if(n==4) Print(" Unbound PE-style file format Linear Executable");
+ if(n==5) Print(" Unbound PMW1-style file format Linear Executable");
+ }
+ else
+ {
+ if(m==-1)
+ {
+ Print(" Standard DOS Executable\n");
+ close_exec();
+ exit(127); /* signal error to SC compressor */
+ }
+ if(l==0) Print(" Unknown Stub File bound to\n");
+ if(l==1) Print(" DOS/32 Advanced DOS Extender bound to\n");
+ if(l==2) Print(" STUB/32C Configurable Stub File bound to\n");
+ if(l==3) Print(" STUB/32A Standard Stub File bound to\n");
+ if(l==4) Print(" DOS/4G DOS Extender bound to\n");
+ if(l==5) Print(" PMODE/W DOS Extender bound to\n");
+
+ if(m==1) Print(" LE-style file format Linear Executable");
+ if(m==2) Print(" LX-style file format Linear Executable");
+ if(m==3) Print(" LC-style file format Linear Executable");
+ if(m==4) Print(" PE-style file format Portable Executable");
+ if(m==5) Print(" PMW1-style file format Linear Executable");
+ }
+ Print("\n");
+
+ if(n==3 || m==3)
+ DisplayOEMInfo();
+
+ unlink(tempname);
+
+ if(unbind_name==FALSE)
+ {
+ strcpy(newname,filename);
+ bufptr=(char *)strchr(newname,'.');
+ if(bufptr!=NULL) strset(bufptr,0);
+ if(Main_Type==1 || Exec_Type==1) strcat(newname,".le");
+ if(Main_Type==2 || Exec_Type==2) strcat(newname,".lx");
+ if(Main_Type==3 || Exec_Type==3) strcat(newname,".lc");
+ if(Main_Type==4 || Exec_Type==4) strcat(newname,".pe");
+ if(Main_Type==5 || Exec_Type==5) strcat(newname,".pmw");
+ }
+ else
+ strcpy(newname,name_un);
+
+ if(bind_name==FALSE)
+ {
+ strcpy(newname2,filename);
+ bufptr2=(char *)strchr(newname2,'.');
+ if(bufptr2!=NULL)
+ strset(bufptr2,0);
+ strcat(newname2,".exe");
+ }
+ else
+ strcpy(newname2,name_bn);
+
+
+ if(bind==TRUE && unbind==TRUE)
+ err_sameact();
+ if(bind)
+ {
+ BindExec(argv);
+ if(!silent) printf("SB/32A: File \"%s\" has been successfully bound\n", filename);
+ }
+ else if(n==0) if(unbind)
+ {
+ UnbindExec(argv);
+ if(!silent) printf("SB/32A: File \"%s\" has been successfully unbound\n", filename);
+ }
+
+ close_exec();
+ exit(0);
+}
+
+
+
+
+
+
+
+
+
+
+void UnbindExec(char *argv[])
+{
+ int n,m;
+
+ Print("\n");
+ Print(" Unbinding file: \"%s\"\n",filename);
+ Print("Destination file: \"%s\"\n",newname);
+ CheckIfExists(newname);
+
+ n=unbind_exec();
+ if(n==-1) err_mem(filename);
+ if(n==-2) err_read(filename);
+ if(n==-3) err_crtmp();
+ if(n==-4) err_wrtmp();
+
+ unlink(newname);
+ copy_file(tempname,newname);
+ unlink(tempname);
+
+ oldfilesize=GetFileSize(newname);
+ if(quiet!=TRUE)
+ printf("Destination size: %d bytes (%1.1f%%)\n", oldfilesize, (float)(oldfilesize+0.01)/(float)(filesize+0.01) *100);
+}
+
+
+void BindExec(char *argv[])
+{
+ int n,m;
+ int stubsize;
+ int execsize;
+ int stubhandle;
+ int exechandle;
+ char *ptr;
+ char *envname;
+ char envbuf[256];
+
+ CheckIfExists(newname2);
+ if(Main_Type==0)
+ UnbindExec(argv);
+
+ Print("\n");
+ Print(" Binding file: \"%s\"\n",newname);
+ Print("Destination file: \"%s\"\n",newname2);
+
+ stubhandle=open(stubname,O_RDWR | O_BINARY);
+ if(stubhandle==-1)
+ {
+ envname=getenv("DOS32A");
+ if(envname==0)
+ err_nod32a();
+ ptr=strchr(envname,' ');
+ if(ptr==NULL)
+ ptr=strchr(envname,0);
+ memset(envbuf,0,256);
+ strncpy(envbuf,envname,(dword)ptr-(dword)envname);
+ strcat(envbuf,"\\BINW\\"); strcat(envbuf,stubname);
+ stubhandle=open(envbuf,O_RDWR | O_BINARY);
+
+ if(stubhandle==-1)
+ err_nostub(envbuf);
+ }
+ stubsize=filelength(stubhandle);
+
+ exechandle=open(newname,O_RDWR | O_BINARY);
+ if(exechandle==-1)
+ err_open(newname);
+
+ execsize=filelength(exechandle);
+
+ n=bind_exec(stubhandle, exechandle, stubsize, execsize);
+ close(exechandle);
+ close(stubhandle);
+ unlink(newname);
+ close_exec();
+ switch(n)
+ {
+ case -1: err_mem(newname);
+ case -2: err_rdstub();
+ case -3: err_read(newname);
+ case -4: err_crtmp();
+ case -5: err_wrtmp();
+ case -6: err_invstub();
+ }
+
+ unlink(newname2);
+ copy_file(tempname,newname2);
+ unlink(tempname);
+
+ newfilesize=GetFileSize(newname2);
+ if(quiet!=TRUE)
+ printf("Destination size: %d bytes (%1.1f%%)\n", newfilesize, (float)(newfilesize+0.01)/(float)(filesize+0.01) *100);
+ if(quiet!=TRUE)
+ printf(" Stub file used: \"%s\"\n",stubname);
+}
+
+
+
+/****************************************************************************/
+void Print(char *format, ...)
+{
+ va_list arglist;
+ char buffer[1024];
+ if(quiet==FALSE)
+ {
+ va_start(arglist,format);
+ vsprintf(buffer,format,arglist);
+ printf(buffer);
+ va_end(arglist);
+ }
+}
+void CheckIfExists(char *name)
+{
+ int n;
+ n=open(name,O_RDWR | O_BINARY);
+ if(n!=-1)
+ {
+ close(n);
+ if(!overwrite)
+ err_dest(name);
+ }
+}
+int GetFileSize(char *name)
+{
+ int n;
+ int m=0;
+ n=open(name,O_RDWR | O_BINARY);
+ if(n!=-1)
+ {
+ m=filelength(n);
+ close(n);
+ }
+ return(m);
+}
+void CheckEnvironment()
+{
+ if(getenv("DOS32A")==NULL)
+ err_environment();
+}
+void copy_file(char *f1, char *f2)
+{
+ int c;
+ FILE *src;
+ FILE *dest;
+
+ if( (f1[1] != ':') && (f2[1] != ':') )
+ {
+ rename(f1,f2);
+ return;
+ }
+
+ if((src=fopen(f1,"rb"))!=NULL)
+ {
+ if((dest=fopen(f2,"wb"))!=NULL)
+ {
+ while((c=fgetc(src))!=EOF) fputc(c,dest);
+ fclose(dest);
+ }
+ fclose(src);
+ }
+}
+
+void DisplayOEMInfo()
+{
+
+ char *ptr;
+
+ if((ptr=find_oem_info()) == NULL)
+ return;
+
+ Print("\n");
+ Print("Application OEM Information:\n");
+
+ Print("-------------------------------------------------------------------------------\n");
+ Print("%s\n",ptr);
+ Print("-------------------------------------------------------------------------------\n");
+}
+
diff -uNr a/dos32a/src/sb/main.h b/dos32a/src/sb/main.h
--- a/dos32a/src/sb/main.h false
+++ b/dos32a/src/sb/main.h 5b19d7975c131e7063ea1b05c3791f5d29c155e71a7cbb2de7af3bf325b090e2167f5f6cfd14fe4bf758ba186204f8340fdb2208b1cfa81ec0e0d4f6be6dc9c2
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+
+extern int open_exec(char *);
+extern void close_exec(void);
+
+extern int check_if_unbound_exec(void);
+extern int get_exec_start(void);
+extern int get_exec_type(void);
+extern int get_extender_type(void);
+extern int unbind_exec(void);
+extern int bind_exec(int, int, int, int);
+extern char *find_oem_info(void);
+
+extern short exec_handle;
diff -uNr a/dos32a/src/sb/sbind.asm b/dos32a/src/sb/sbind.asm
--- a/dos32a/src/sb/sbind.asm false
+++ b/dos32a/src/sb/sbind.asm c2f600f3be23ac47109c0ec399b6b1dade0c992d545bd5c60fc26d80314e3314358af929286454d59c0716f25f473588453a706cf10a740b0e0662bf036e25ef
@@ -0,0 +1,819 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .486p
+ .MODEL flat
+ LOCALS
+ NOJUMPS
+
+include stddef.inc
+
+EXTRN _filesize :dword
+EXTRN _Main_Type :dword
+EXTRN _Exec_Type :dword
+EXTRN _tempname :dword
+
+PUBLIC open_exec_, close_exec_
+PUBLIC check_if_unbound_exec_
+PUBLIC get_exec_start_
+PUBLIC get_exec_type_
+PUBLIC get_extender_type_
+PUBLIC _exec_handle
+PUBLIC unbind_exec_
+PUBLIC bind_exec_
+PUBLIC find_oem_info_
+
+.CODE
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+
+
+
+
+
+bind_exec_:
+ pushad
+ mov _tmp_handle1,eax
+ mov _tmp_handle2,edx
+ mov _tmp_size1,ebx
+ mov _tmp_size2,ecx
+
+ lea eax,[ebx+ecx+0FFFh]
+ call allocate_memory
+ jc @@err1
+
+ mov ebx,_tmp_handle1 ; load stub
+ mov ecx,_tmp_size1
+ mov edx,dword ptr _mem_ptr
+ mov ah,3Fh
+ int 21h
+ jc @@err2
+
+ movzx eax,word ptr [edx+0018h] ; get reloc tab offset
+ mov esi,dword ptr _mem_ptr
+ add esi,eax
+ add esi,_tmp_size1
+ mov ebx,0040h
+ mov edi,dword ptr _mem_ptr
+ add edi,ebx
+ add edi,_tmp_size1
+ mov ecx,_tmp_size1
+ inc ecx
+ std
+ rep movsb
+ cld
+
+ mov edi,dword ptr _mem_ptr
+ add edi,eax
+ sub ebx,eax
+ jc @@err6 ; invalid stub format
+ mov ecx,ebx
+ xor eax,eax
+ rep stosb
+ mov eax,_tmp_size1
+ add eax,ebx
+ mov _tmp_size1,eax
+
+ mov esi,dword ptr _mem_ptr
+ mov edx,eax
+ and eax,1FFh
+ mov [esi+02h],ax
+
+ mov eax,edx
+ shr eax,9
+ inc eax
+ mov [esi+04h],ax
+
+ movzx eax,word ptr [esi+06]
+ lea eax,[eax*4]
+ add eax,004Fh
+ shr eax,4
+ mov [esi+08h],ax
+
+ mov ax,0040h
+ mov [esi+18h],ax
+
+ mov eax,_tmp_size1
+ mov [esi+3Ch],eax
+
+ mov ebx,_tmp_handle2 ; load exec
+ mov ecx,_tmp_size2
+ mov edx,dword ptr _mem_ptr
+ add edx,_tmp_size1
+ mov ah,3Fh
+ int 21h
+ jc @@err3
+
+ pushad
+ mov eax,_exec_start
+ mov ecx,eax
+ mov edx,eax
+ shr ecx,16
+ mov ebx,_tmp_handle2
+ mov ax,4200h
+ int 21h ; move to next exec in file
+ popad
+ jc @@err3
+
+ mov eax,_tmp_size1 ; update Data Pages Offset
+ mov ebp,[edx+80h]
+ add eax,ebp
+
+ cmp _Main_Type,0
+ jz @@0
+
+ cmp _Main_Type,1
+ jz @@1
+ cmp _Main_Type,2
+ jz @@1
+ jmp @@2
+
+@@0:
+ cmp _Exec_Type,1
+ jz @@1
+ cmp _Exec_Type,2
+ jz @@1
+ jmp @@2
+
+@@1: mov [edx+80h],eax
+
+@@2: mov edx,_tempname ; create temp file
+ mov ecx,00h
+ mov ah,3Ch
+ int 21h
+ mov _temp_handle,ax
+ jc @@err4
+
+ mov edx,dword ptr _mem_ptr
+ mov ecx,_tmp_size1
+ add ecx,_tmp_size2
+ mov bx,_temp_handle ; write to temp file
+ mov ah,40h
+ int 21h
+ jc @@err5
+
+ mov bx,_temp_handle ; close temp file
+ mov ah,3Eh
+ int 21h
+ call free_memory
+ popad
+ xor eax,eax
+ ret
+
+@@err1: call free_memory
+ popad
+ mov eax,-1
+ ret
+@@err2: call free_memory
+ popad
+ mov eax,-2
+ ret
+@@err3: call free_memory
+ popad
+ mov eax,-3
+ ret
+@@err4: call free_memory
+ popad
+ mov eax,-4
+ ret
+@@err5: call free_memory
+ popad
+ mov eax,-5
+ ret
+@@err6: call free_memory
+ popad
+ mov eax,-6
+ ret
+
+
+unbind_exec_:
+ pushad
+ call seek_to_start
+ mov eax,_filesize ; allocate memory
+ add eax,0FFFh
+ call allocate_memory
+ jc @@err1
+
+ mov bx,_exec_handle ; load exec
+ mov ecx,_filesize
+ mov edx,dword ptr _mem_ptr
+ mov ah,3Fh
+ int 21h
+ jc @@err2
+
+ mov edx,_tempname ; create temp file
+ mov ecx,00h
+ mov ah,3Ch
+ int 21h
+ mov _temp_handle,ax
+ jc @@err3
+
+ mov edx,dword ptr _mem_ptr
+ mov ecx,_filesize
+ add edx,_exec_start
+ sub ecx,_exec_start
+ mov eax,[edx+80h] ; update Data Pages Offset
+ mov ebp,_exec_start
+ sub ebp,_app_off_datapages
+ sub eax,ebp
+ cmp _Exec_Type,1
+ jz @@1
+ cmp _Exec_Type,2
+ jz @@1
+ jmp @@2
+@@1: mov [edx+80h],eax
+
+@@2: mov bx,_temp_handle ; write to temp file
+ mov ah,40h
+ int 21h
+ jc @@err4
+
+ mov bx,_temp_handle ; close temp file
+ mov ah,3Eh
+ int 21h
+ call free_memory
+ popad
+ xor eax,eax
+ ret
+
+@@err1: call free_memory
+ popad
+ mov eax,-1
+ ret
+@@err2: call free_memory
+ popad
+ mov eax,-2
+ ret
+@@err3: call free_memory
+ popad
+ mov eax,-3
+ ret
+@@err4: call free_memory
+ popad
+ mov eax,-4
+ ret
+
+
+
+
+;-----------------------------------------------------------------------------
+allocate_memory:
+ pushad
+ mov ebx,eax
+ mov ax,0FF91h
+ int 21h
+ mov _mem_ptr,ebx
+ mov _mem_handle,esi
+ popad
+ ret
+
+free_memory:
+ pushad
+ mov esi,_mem_handle
+ mov ax,0FF92h
+ int 21h
+ popad
+ ret
+
+
+
+
+
+
+
+open_exec_:
+ pushad
+ xor ecx,ecx
+ mov edx,eax
+ mov ax,4300h
+ int 21h
+ test ecx,01h
+ jnz @@err2
+ mov ax,3D02h
+ int 21h
+ jc @@err1
+ mov _exec_handle,ax
+ popad
+ xor eax,eax
+ ret
+@@err1: popad
+ mov eax,-1
+ ret
+@@err2: popad
+ mov eax,-2
+ ret
+
+close_exec_:
+ pushad
+ mov bx,_exec_handle
+ mov ah,3Eh
+ int 21h
+ popad
+ ret
+
+
+check_if_unbound_exec_:
+ pushad
+ call seek_to_start
+ jc @@err1
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,64 ; ECX = 64 bytes to load
+ mov edx,_buffer ; DS:EDX = ptr
+ int 21h
+ jc @@err2
+ call seek_to_start
+ jc @@err1
+ cmp word ptr [edx],'ZM' ; is exec 'MZ' file type
+ jz @@0
+ cmp word ptr [edx],'EL' ; is exec 'LE' file type
+ jz @@1
+ cmp word ptr [edx],'XL' ; is exec 'LX' file type
+ jz @@2
+ cmp word ptr [edx],'CL' ; is exec 'LC' file type
+ jz @@3
+ cmp word ptr [edx],'EP' ; is exec 'PE' file type
+ jz @@4
+ cmp dword ptr [edx],'1WMP' ; is exec 'PMW1' file type
+ jz @@5
+ popad
+ mov eax,-3
+ ret
+@@err1: popad
+ mov eax,-1
+ ret
+@@err2: popad
+ mov eax,-2
+ ret
+
+@@0: popad
+ mov eax,0
+ ret
+@@1: popad
+ mov eax,1
+ ret
+@@2: popad
+ mov eax,2
+ ret
+@@3: popad
+ mov eax,3
+ ret
+@@4: popad
+ mov eax,4
+ ret
+@@5: popad
+ mov eax,5
+ ret
+
+
+
+
+get_exec_start_:
+ pushad
+ mov _saved_stack,esp
+ call load_exec_header
+ popad
+ xor eax,eax
+ ret
+
+@err1: mov esp,_saved_stack
+ popad
+ mov eax,-1
+ ret
+@err2: mov esp,_saved_stack
+ popad
+ mov eax,-2
+ ret
+
+
+load_exec_header:
+ call seek_to_start
+ jc @err1
+
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,64 ; ECX = 64 bytes to load
+ mov edx,_buffer ; DS:EDX = ptr
+ int 21h
+ jc @err1
+
+ call seek_to_start
+ jc @err1
+
+ xor ebp,ebp ; reset ptr in app
+ cmp word ptr [edx],'ZM' ; is exec 'MZ' file type
+ jnz search_for_le ; if not, search for known exec type
+
+ mov eax,[edx+18h] ; MZ reloc-tab must be at offset 0040h
+ cmp ax,40h
+ jnz search_for_mz
+
+ mov eax,[edx+3Ch] ; get start of 32-bit code
+ test ax,ax ; check if exec is bound
+ jz search_for_mz ; if not, search
+ mov _exec_start,eax
+ mov _app_off_datapages,0
+ ret
+
+
+search_for_mz:
+ xor esi,esi
+
+@@0: movzx eax,wptr [edx+04h] ; get pages in file
+ shl eax,9 ; *512
+ movzx ebx,wptr [edx+02h] ; get bytes on last page
+ add eax,ebx
+ cmp wptr [edx],'ZM'
+ jz @@1
+ cmp wptr [edx],'WB'
+ jz @@2
+ jmp @@3
+@@1: sub eax,0200h
+@@2: mov esi,ebp
+ add ebp,eax
+
+ mov ecx,ebp
+ mov edx,ebp
+ shr ecx,16
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h ; move to next exec in file
+ jc @err1
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,64
+ mov edx,_buffer
+ int 21h
+ jc @err1
+ test eax,eax
+ jz @err2 ; unknown exec format
+ jmp @@0
+
+@@3: cmp wptr [edx],'EL'
+ jz @@4
+ cmp wptr [edx],'XL'
+ jz @@4
+ cmp wptr [edx],'CL'
+ jz @@4
+ mov ecx,ebp
+ mov edx,ebp
+ shr ecx,16
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h ; move to next exec in file
+ jc @err1
+ call search_for_le
+@@4: mov _exec_start,ebp
+ mov _app_off_datapages,esi
+ ret
+
+
+search_for_le:
+@@1: mov edx,_buffer ; DS:EDX = current ptr
+ mov ecx,1000h ; ECX = bytes to load
+ mov ax,3F00h
+ mov bx,_exec_handle
+ int 21h
+ jc @err1
+ test eax,eax ; check if no bytes read
+ jz @err2 ; if true, no app in file
+ shr ecx,1
+@@2: mov ax,[edx+0]
+ mov bx,[edx+2]
+ test bx,bx
+ jnz @@4
+ cmp ax,'EL' ; 'LE' type
+ jz @@3
+ cmp ax,'XL' ; 'LX' type
+ jz @@3
+@@4: cmp ax,'CL' ; 'LC' type (Linear Compressed)
+ jz @@3
+ add edx,2
+ add ebp,2 ; increment pointer in file
+ loop @@2
+ jmp @@1
+@@3: mov _app_off_datapages,0
+ ret
+
+
+get_exec_type_:
+ pushad
+ mov edx,_exec_start
+ mov ecx,edx
+ shr ecx,16
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h
+ jc @@err1
+
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,64
+ mov edx,_buffer
+ int 21h
+ jc @@err1
+ test eax,eax
+ jz @@err2 ; unknown exec format
+
+ cmp wptr [edx],'EL'
+ jz @@1
+ cmp wptr [edx],'XL'
+ jz @@2
+ cmp wptr [edx],'CL'
+ jz @@3
+ cmp wptr [edx],'EP'
+ jz @@4
+ cmp dptr [edx],'1WMP'
+ jz @@5
+
+@@err2: popad
+ mov eax,-2
+ ret
+@@err1: popad
+ mov eax,-1
+ ret
+
+@@0: popad
+ xor eax,eax
+ ret
+@@1: popad
+ mov eax,1
+ ret
+@@2: popad
+ mov eax,2
+ ret
+@@3: popad
+ mov eax,3
+ ret
+@@4: popad
+ mov eax,4
+ ret
+@@5: popad
+ mov eax,5
+ ret
+
+
+
+get_extender_type_:
+ pushad
+ call seek_to_start
+ jc @@err1
+
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,0400h ; ECX = 64 bytes to load
+ mov edx,_buffer ; DS:EDX = ptr
+ int 21h
+ jc @@err1
+
+ mov ebx,_buffer
+ mov esi,offs _str_dos32a
+ lea edi,[ebx+009Ah]
+ call check_string
+ jnc @@1
+ mov ebx,_buffer
+ mov esi,offs _str_stb32a
+ lea edi,[ebx+006Ah]
+ call check_string
+ jnc @@2
+ mov ebx,_buffer
+ mov esi,offs _str_stub32a
+ lea edi,[ebx+0040h]
+ call check_string
+ jnc @@3
+
+ mov ebx,_buffer
+ mov esi,offs _str_dos32a_new
+ lea edi,[ebx+009Ch]
+ call check_string
+ jnc @@1
+ mov ebx,_buffer
+ mov esi,offs _str_stub32c_new
+ lea edi,[ebx+006Ch]
+ call check_string
+ jnc @@2
+ mov ebx,_buffer
+ mov esi,offs _str_stub32a_new
+ lea edi,[ebx+0040h]
+ call check_string
+ jnc @@3
+
+ mov esi,offs _str_dos4g
+ lea edi,[ebx+025Ah]
+ call check_string
+ jnc @@4
+ mov esi,offs _str_dos4g
+ lea edi,[ebx+025Ch]
+ call check_string
+ jnc @@4
+
+ mov esi,offs _str_pmodew
+ lea edi,[ebx+0055h]
+ call check_string
+ jnc @@5
+
+ popad
+ xor eax,eax
+ ret
+@@err1: popad
+ mov eax,-1
+ ret
+
+@@1: popad
+ mov eax,1 ; DOS/32A
+ ret
+@@2: popad
+ mov eax,2 ; STUB/32A Configurable
+ ret
+@@3: popad
+ mov eax,3 ; STUB/32A Standard
+ ret
+@@4: popad
+ mov eax,4 ; DOS/4G
+ ret
+@@5: popad
+ mov eax,5 ; PMODE/W
+ ret
+
+
+check_string:
+ pushad
+@@0: mov al,[esi]
+ test al,al
+ jz @@ok
+ cmp al,[edi]
+ jnz @@err
+ inc esi
+ inc edi
+ jmp @@0
+@@ok: popad
+ clc
+ ret
+@@err: popad
+ stc
+ ret
+
+
+seek_to_start:
+ pushad
+ xor ecx,ecx
+ xor edx,edx
+ jmp common_seek
+seek_from_start:
+ pushad
+ mov ecx,edx
+ shr ecx,16
+common_seek:
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h
+ popad
+ ret
+seek_from_current:
+ pushad
+ mov ecx,edx
+ shr ecx,16
+ mov bx,_exec_handle
+ mov ax,4201h
+ int 21h
+ popad
+ ret
+read_from_exec:
+ pushad
+ mov ah,3Fh
+ mov bx,_exec_handle
+ int 21h
+ mov [esp+1Ch],eax
+ popad
+ ret
+
+
+find_oem_info_:
+ pushad
+ mov edx,_exec_start
+ call seek_from_start
+ jc @@err
+
+ mov ecx,10h ; read LC header
+ mov edx,_buffer
+ call read_from_exec
+ jc @@err
+
+ mov al,[edx+05h] ; get LC flags
+ test al,80h ; check if OEM is appended
+ jz @@err
+
+ xor esi,esi ; current Object #
+ movzx ebp,byte ptr [edx+04h] ; get # of Objects
+
+@@1: mov ecx,10h ; read Object header
+ mov edx,_buffer
+ call read_from_exec
+ jc @@err
+ mov edx,[edx+04h] ; get Object compressed size
+ call seek_from_current
+ jc @@err
+ inc esi
+ cmp esi,ebp
+ jnz @@1
+
+ mov ecx,0Ch ; read Fixups header
+ mov edx,_buffer
+ call read_from_exec
+ jc @@err
+ mov edx,[edx+04h] ; get Fixups compressed size
+ call seek_from_current
+ jc @@err
+
+ xor eax,eax
+ mov ecx,128
+ mov edi,_buffer
+ rep stosd
+
+ mov ecx,512
+ mov edx,_buffer
+ call read_from_exec
+ jc @@err
+ test eax,eax ; if read nothing, no OEM info
+ jz @@err
+
+ popad
+ mov eax,_buffer
+ ret
+
+@@err: popad
+ xor eax,eax
+ ret
+
+
+
+.DATA
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+_buffer dd offset @buffer
+
+_str_dos32a_new db 'DOS/32A',0
+_str_stub32a_new db 'STUB/32A',0
+_str_stub32c_new db 'STUB/32C',0
+
+_str_dos32a db 'DOS/32 Advanced.',0
+_str_stb32a db 'DOS/32 Advanced!',0
+_str_stub32a db 'DOS/32 Advanced stub file.',0
+_str_dos4g db 'DOS/4G',0
+_str_pmodew db 'PMODE/W',0
+
+_exec_start dd 0
+_app_off_datapages dd 0
+
+
+
+.DATA?
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+@buffer db 10000h dup(?)
+_tmp_handle1 dd ?
+_tmp_handle2 dd ?
+_tmp_size1 dd ?
+_tmp_size2 dd ?
+
+_mem_ptr dd ?
+_mem_handle dd ?
+
+_exec_handle dw ?
+_saved_stack dd ?
+_temp_handle dw ?
+
+end
diff -uNr a/dos32a/src/sc/encode.c b/dos32a/src/sc/encode.c
--- a/dos32a/src/sc/encode.c false
+++ b/dos32a/src/sc/encode.c 9ad61fb3cacf038c459d4ab9107d0c3ad7520830c77750a7bb03b6c820f5a132893dd600879c479f68afcfc2fa79c6c4783592ad5d8642e032f2601c214f6d49
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+//#include
+
+#define N 4*1024 // size of the buffer
+#define F 18
+#define THRESHOLD 2
+#define NIL N
+
+
+ uchar text_buf[N+F-1];
+
+ int match_position;
+ int match_length;
+ int node[N+1];
+ int lnode[N+1];
+ int rnode[N+257];
+
+ int bytecount = 0;
+ int printcount = 0;
+ ulong textsize = 0;
+ ulong codesize = 0;
+
+ char cc = 0;
+ char xc = 0;
+ char *srcaddr = NULL;
+ char *destaddr = NULL;
+
+
+int getbyte()
+{
+ if(bytecount-- > 0)
+ return(*srcaddr++);
+ else
+ return(EOF);
+}
+
+void putbyte(char c)
+{
+ *destaddr++=(c^xc);
+ xc=c;
+}
+
+void InitTree(void)
+{
+ int i;
+
+ for(i=N+1; i<=N+256; i++)
+ rnode[i]=NIL;
+ for(i=0; i=0)
+ {
+ if(rnode[p]!=NIL)
+ p=rnode[p];
+ else
+ {
+ rnode[p]=r;
+ node[r]=p;
+ return;
+ }
+ }
+ else
+ {
+ if(lnode[p]!=NIL)
+ p=lnode[p];
+ else
+ {
+ lnode[p]=r;
+ node[r]=p;
+ return;
+ }
+ }
+ for(i=1; imatch_length)
+ {
+ match_position=p;
+ if((match_length=i)>=F)
+ break;
+ }
+ }
+ node[r]=node[p];
+ lnode[r]=lnode[p];
+ rnode[r]=rnode[p];
+ node[lnode[p]]=r;
+ node[rnode[p]]=r;
+ if(rnode[node[p]]==p)
+ rnode[node[p]]=r;
+ else
+ lnode[node[p]]=r;
+ node[p]=NIL;
+}
+
+void DeleteNode(int p)
+{
+ int q;
+
+ if(node[p]==NIL)
+ return;
+ if(rnode[p]==NIL)
+ q=lnode[p];
+ else if(lnode[p]==NIL)
+ q=rnode[p];
+ else
+ {
+ q=lnode[p];
+ if(rnode[q]!=NIL)
+ {
+ do
+ {
+ q=rnode[q];
+ }
+ while(rnode[q]!=NIL);
+
+ rnode[node[q]]=lnode[q];
+ node[lnode[q]]=node[q];
+ lnode[q]=lnode[p];
+ node[lnode[p]]=q;
+ }
+ rnode[q]=rnode[p];
+ node[rnode[p]]=q;
+ }
+ node[q]=node[p];
+ if(rnode[node[p]]==p)
+ rnode[node[p]]=q;
+ else
+ lnode[node[p]]=q;
+ node[p]=NIL;
+}
+
+void Encode(void)
+{
+ int i, c, len, r, s, last_match_length, code_buf_ptr;
+ char code_buf[17], mask;
+
+ bytecount=textsize;
+ InitTree();
+ code_buf[0]=0;
+
+ code_buf_ptr=mask=1;
+ s=0;
+ r=N-F;
+
+ for(i=s; ilen)
+ match_length=len;
+ if(match_length<=THRESHOLD)
+ {
+ match_length=1;
+ code_buf[0]|=mask;
+ code_buf[code_buf_ptr++]=text_buf[r];
+ }
+ else
+ {
+ code_buf[code_buf_ptr++]=(uchar)match_position;
+ code_buf[code_buf_ptr++]=(uchar)(((match_position>>4)&0xf0)|(match_length-(THRESHOLD+1)));
+ }
+ if((mask<<=1)==0)
+ {
+ for(i=0; i=printcount)
+ {
+ printcount+=256;
+ if(bytecount<=0)
+ ShowCount(99);
+ else
+ ShowCount((int)(((float)(textsize-bytecount)/(float)textsize)*100));
+ }
+ while(i++0);
+
+ if(code_buf_ptr>1)
+ {
+ for(i=0; i=2)
+ {
+ for(n=1; n=argc)
+ {
+l1: Print("SC/32A fatal: syntax is SC [commands] [options] \n\n");
+ Print("Commands:\n");
+ Print("---------\n");
+ Print("/B Bind DOS/32A to produced LC Executable\n");
+ Print("/BS Bind STUB/32A to produced LC Executable\n");
+ Print("/BC Bind STUB/32C to produced LC Executable\n");
+ Print("/U Produce Unbound Linear Compressed Executable\n\n");
+ Print("Options:\n");
+ Print("--------\n");
+ Print("/D Turn off all optimization features\n");
+ Print("/DA Disable Advanced preprocessing of Executable\n");
+ Print("/DE Disable Encoding of LC Executable (no compression)\n");
+ Print("/DR Disable Removing of post-zero areas from Executable\n");
+ Print("/DS Disable Smart Encoding when compressing Executable\n");
+ Print("/V[0|1|2] Verbose mode (displays additional information)\n");
+ Print("/Q Quiet mode (partially disables console output)\n");
+ Print("/S Silent mode (totally disables console output)\n");
+ Print("/H or /? This help\n");
+ exit(0);
+
+ }
+}
+
+
+
+/****************************************************************************/
+void OpenExec()
+{
+ if(open_exec(tempname1)==-1)
+ {
+ CopyFile(oldfilename,tempname1);
+ if(open_exec(tempname1)==-1)
+ err_open(tempname1);
+ }
+}
+void CloseExec()
+{
+ close_exec();
+}
+void CreateTemp()
+{
+ if(create_temp()==-1) err_temp(tempname2);
+}
+int FindExecType()
+{
+ int n;
+
+ n=get_exec_type();
+ if(n==-1)
+ err_read(tempname1);
+ if(n==-2)
+ err_support(oldfilename);
+ if(n==3)
+ err_formlc(oldfilename);
+ if(n==4)
+ err_formpe(oldfilename);
+ if(n==5)
+ err_formpmw1(oldfilename);
+ return(n);
+}
+
+
+
+
+
+
+
+
+
+/****************************************************************************/
+void main(int argc, char *argv[])
+{
+ int n;
+
+// Debug_Init();
+
+ setbuf(stdout,NULL);
+// CheckEnvironment();
+ ArgInit(argc, argv);
+ DeleteTempFiles();
+ CreateD32AEnvVar();
+ CheckExec(argv);
+ oldfilesize=GetFileSize(oldfilename);
+ UnbindExec();
+
+ OpenExec();
+ Exec_Type=FindExecType();
+ Print("\n");
+ if(!verbose) Print("+ Unbinding Exec : Ok.\n");
+ else Print("+ Unbinding Exec : Ok. (%s-style)\n",execstyle[Exec_Type-1]);
+ CloseExec();
+
+ if(advanced)
+ {
+ if(!quiet) printf("+ Preprocessing Exec : ");
+ n=relocate_exec(tempname1);
+ if(n!=0)
+ {
+ Print("Error! \n");
+ err_relocator(n);
+ }
+ if(!verbose) Print("Ok.\n");
+ else Print("Ok. (%d fixups)\n",relocated_fixups);
+ }
+
+ OpenExec();
+ CompressExec();
+ CloseExec();
+
+ if(bind)
+ {
+ BindExec();
+ if(!verbose) Print("+ Binding Exec : Ok.\n");
+ else Print("+ Binding Exec : Ok. (Stub file used: \"%s\")\n",stubnames[bindtype]);
+ }
+ else
+ {
+ unlink(newfilename);
+ copy_file(tempname2,newfilename);
+ unlink(tempname2);
+
+ }
+ newfilesize=GetFileSize(newfilename);
+ DeleteTempFiles();
+
+ if(!quiet)
+ {
+ printf("\n Original Exec Stats: \"%s\", %s-style, %d bytes\n", oldfilename, execstyle[Exec_Type-1], oldfilesize);
+ printf("Compressed Exec Stats: \"%s\", %s-style, %d bytes (%1.1f%%)\n", newfilename, execstyle[2], newfilesize, (float)(newfilesize+0.01)/(float)(oldfilesize+0.01) *100);
+ }
+ else
+ {
+ if(!silent) printf("SC/32A: File \"%s\" has been successfully compressed\n", oldfilename);
+ }
+ exit(0);
+}
+
+
+
+
+/****************************************************************************/
+void CompressExec()
+{
+ int n;
+
+ CreateTemp();
+ CreateLCHeader();
+ CreateLCObjects();
+ CreateLCFixups();
+ AppendTitleFile();
+ close_temp();
+ unlink(tempname1);
+}
+
+
+/****************************************************************************/
+void CreateLCHeader()
+{
+ int n;
+
+ Print("+ Creating LC Header : ");
+ n=create_lc_header();
+ if(n!=0)
+ {
+ Print("Error! \n");
+ if(n==-1)
+ err_seek(tempname1);
+ if(n==-2)
+ err_read(tempname1);
+ if(n==-3)
+ err_write(tempname2);
+ if(n==-4)
+ err_linker(tempname1);
+ if(n==-5)
+ err_objects(tempname1);
+ }
+ else
+ {
+ if(!verbose)
+ Print("Ok.\n");
+ else
+ Print("Ok. (%d Objects)\n",app_num_objects);
+ }
+}
+
+
+void CreateLCObjects()
+{
+ int n;
+ int obj;
+ char c;
+
+ for(obj=1; obj<=app_num_objects; obj++)
+ {
+ Print("+ Encoding Object #%-2d: ",obj);
+
+ n=create_lc_object(obj);
+ if(n!=0)
+ {
+ Print("Error! \n");
+ if(n==-1) err_seek(tempname1);
+ if(n==-2) err_read(tempname1);
+ if(n==-3) err_mem();
+ if(n==-4) err_write(tempname2);
+ if(n==-5) err_lcobjhdr(tempname1);
+ }
+
+ c = app_obj_seekattr[obj] ? '*':' ';
+
+ if(!quiet)
+ {
+ printf("[û] ");
+ if(!verbose) printf("(%1.1f%%)\n", ((float)(obj_new_size+0.01)/(float)(obj_old_size+0.01))*100);
+ else
+ { printf("Old=%7d, New=%7d, (%1.1f%%) (%s)%c\n", obj_old_size,obj_new_size, ((float)(obj_new_size+0.01)/(float)(obj_old_size+0.01))*100, encodetype[app_enc_status], c);
+ if(verbxtra) printf(" ** %s **, ** %s **, %7d - fixups\n", app_obj_iscode ? "CODE":"DATA", app_obj_is32bit ? "32bit":"16bit", app_obj_seekattr[obj]);
+ }
+ }
+ }
+}
+
+
+void CreateLCFixups()
+{
+ int n;
+
+ Print("+ Encoding LC Fixups : ");
+ n=create_lc_fixups();
+ if(n!=0)
+ {
+ Print("Error!\n");
+ if(n==-1) err_seek(tempname1);
+ if(n==-2) err_read(tempname1);
+ if(n==-3) err_mem();
+ if(n==-4) err_write(tempname2);
+ }
+
+ if(quiet!=TRUE)
+ {
+ printf("[û] ");
+ if(!verbose) printf("(%1.1f%%)\n", ((float)(obj_new_size+0.01)/(float)(obj_old_size+0.01))*100);
+ else printf("Old=%7d, New=%7d, (%1.1f%%) (%s)\n", obj_old_size,obj_new_size, ((float)(obj_new_size+0.01)/(float)(obj_old_size+0.01))*100, encodetype[app_enc_status]);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+/****************************************************************************/
+void UnbindExec()
+{
+ int n;
+
+ char temppath[128]; // passed as *path argument
+ char tempname[128]; // passed as *argv[0]
+ char tempparm[128]; // name of file to be processed
+
+ const char *path=temppath;
+ const char *arg0=bindname;
+ const char *arg1="/U";
+ const char *arg2="/O";
+ const char *arg3="/S";
+ const char *arg4=tempparm;
+ const char *arg5=oldfilename;
+
+
+ strcpy(temppath,bindname);
+ strcpy(tempname,bindname);
+ strcpy(tempparm,"/UN");
+ strcat(tempparm,tempname1);
+ n=spawnle(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+
+ if(n==-1)
+ {
+ GetDOS32APath();
+ strcpy(temppath,dos32apath);
+ strcat(temppath,bindname);
+ strcpy(tempname,dos32apath);
+ strcat(tempname,bindname);
+ n=spawnle(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+ if(n==-1)
+ {
+ strcpy(temppath,bindname);
+ strcpy(tempname,bindname);
+ n=spawnlpe(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+ if(n==-1)
+ err_nosb();
+ }
+ }
+ if(n!=0)
+ {
+ if(n==127)
+ err_support(oldfilename);
+ else
+ {
+ DeleteTempFiles();
+ exit(1);
+ }
+ }
+}
+
+/****************************************************************************/
+void BindExec()
+{
+ int n;
+
+ char temppath[128]; // passed as *path argument
+ char tempname[128]; // passed as *argv[0]
+ char tempparm[128]; // -UN name of file
+ char tempparm2[128]; // -BN name of file
+ char temptype[8]; // action type, either "-R" or "-RS"
+
+ const char *path=temppath;
+ const char *arg0=bindname;
+ const char *arg1=temptype;
+ const char *arg2="/S";
+ const char *arg3=tempparm;
+ const char *arg4=tempparm2;
+ const char *arg5=tempname2;
+
+
+ if(bindtype==0)
+ strcpy(temptype,"/R");
+ else if(bindtype==1)
+ strcpy(temptype,"/RS");
+ else if(bindtype==2)
+ strcpy(temptype,"/RC");
+
+ strcpy(temppath,bindname);
+ strcpy(tempname,bindname);
+
+ strcpy(tempparm,"/UN");
+ strcat(tempparm,tempname2);
+ strcpy(tempparm2,"/BN");
+ strcat(tempparm2,newfilename);
+ n=spawnle(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+
+ if(n==-1)
+ {
+ GetDOS32APath();
+ strcpy(temppath,dos32apath);
+ strcat(temppath,bindname);
+ strcpy(tempname,dos32apath);
+ strcat(tempname,bindname);
+ n=spawnle(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+ if(n==-1)
+ {
+ strcpy(temppath,bindname);
+ strcpy(tempname,bindname);
+ n=spawnlpe(P_WAIT, path, arg0,arg1,arg2,arg3,arg4,arg5, NULL, NULL);
+ if(n==-1)
+ err_nosb();
+ }
+ }
+ if(n!=0)
+ {
+ if(n==127)
+ err_support(tempname2);
+ else
+ {
+ DeleteTempFiles();
+ exit(1);
+ }
+ }
+}
+
+
+/****************************************************************************/
+void Print(char *format, ...)
+{
+ va_list arglist;
+ char buffer[1024];
+ if(quiet==FALSE)
+ {
+ va_start(arglist,format);
+ vsprintf(buffer,format,arglist);
+ printf(buffer);
+ va_end(arglist);
+ }
+}
+int GetFileSize(char *name)
+{
+ int n,m;
+ if( (n=open(name,O_RDONLY | O_BINARY)) == -1) return(0);
+ m=filelength(n);
+ close(n);
+ return(m);
+}
+void GetDOS32APath()
+{
+ char *ptr;
+ char *envname;
+ char envbuf[512];
+
+ dos32apath[0]=NULL;
+ envname=getenv("DOS32A");
+ if(envname!=0)
+ {
+ ptr=strchr(envname,' ');
+ if(ptr==NULL)
+ ptr=strchr(envname,0);
+ memset(envbuf,0,256);
+ strncpy(envbuf,envname,(dword)ptr-(dword)envname);
+ strcat(envbuf,"\\BINW\\");
+ strcpy(dos32apath,envbuf);
+ }
+ else
+ strcat(dos32apath, ".\\");
+}
+void CreateD32AEnvVar()
+{
+ int n;
+ char *envname;
+
+ envname=getenv("DOS32A");
+ if(envname!=0)
+ {
+ strcpy(dos32aenv,envname);
+ strcat(dos32aenv," /NOC");
+ }
+ else
+ strcpy(dos32aenv," /NOC");
+ n=setenv("DOS32A",dos32aenv,1);
+// if(n!=0)
+// Print("WARNING: could not adjust DOS32A environment variable\n");
+}
+void DeleteTempFiles()
+{
+ close_temp();
+ close_exec();
+ unlink(tempname1);
+ unlink(tempname2);
+}
+void ShowCount(int count)
+{
+ if(quiet!=TRUE)
+ if(nocount!=TRUE)
+ printf("%02d%%\b\b\b",count);
+}
+void CopyFile(char *f1, char *f2) {
+ int c;
+ FILE *src;
+ FILE *dest;
+ unlink(f2);
+ if((src=fopen(f1,"rb"))!=NULL)
+ {
+ if((dest=fopen(f2,"wb"))!=NULL)
+ {
+ while((c=fgetc(src))!=EOF)
+ fputc(c,dest);
+ fclose(dest);
+ }
+ fclose(src);
+ }
+}
+void CheckExec(char *argv[])
+{
+ char *bufptr;
+
+ strcpy(oldfilename,argv[execargn]);
+ strcpy(newfilename,argv[execargn]);
+ bufptr=(char *)strchr(newfilename,'.');
+ if(bufptr!=NULL)
+ strset(bufptr,0);
+ if(bind==TRUE)
+ strcat(newfilename,".exe");
+ else
+ strcat(newfilename,".lc");
+
+ if(CheckIfExists(oldfilename)==TRUE)
+ return;
+ bufptr=(char *)strchr(oldfilename,'.');
+ if(bufptr!=NULL)
+ return;
+ strcat(oldfilename,".exe");
+
+ if(CheckIfExists(oldfilename)==TRUE)
+ return;
+ bufptr=(char *)strchr(oldfilename,'.');
+ if(bufptr!=NULL)
+ strset(bufptr,0);
+ strcat(oldfilename,".le");
+
+ if(CheckIfExists(oldfilename)==TRUE)
+ return;
+ bufptr=(char *)strchr(oldfilename,'.');
+ if(bufptr!=NULL)
+ strset(bufptr,0);
+ strcat(oldfilename,".lx");
+
+ if(CheckIfExists(oldfilename)==TRUE)
+ return;
+ strcpy(oldfilename,argv[execargn]);
+}
+int CheckIfExists(char *name)
+{
+ int n;
+ n=open(name,O_RDWR | O_BINARY);
+ if(n!=-1)
+ {
+ close(n);
+ return(TRUE);
+ }
+ return(FALSE);
+}
+void CheckEnvironment()
+{
+ if(getenv("DOS32A")==NULL)
+ err_environment();
+}
+
+void copy_file(char *f1, char *f2)
+{
+ int c;
+ FILE *src;
+ FILE *dest;
+
+ if( (f1[1] != ':') && (f2[1] != ':') )
+ {
+ rename(f1,f2);
+ return;
+ }
+ if((src=fopen(f1,"rb"))!=NULL)
+ {
+ if((dest=fopen(f2,"wb"))!=NULL)
+ {
+ while((c=fgetc(src))!=EOF)
+ fputc(c,dest);
+ fclose(dest);
+ }
+ fclose(src);
+ }
+}
+
+void AppendTitleFile()
+{
+ int n,m,k;
+ char *ptr;
+ char *dirptr;
+ char tempbuf[512];
+
+ dirptr=inffilename-1;
+ strcpy(inffilename,oldfilename);
+ for(ptr=inffilename; *ptr!=0; ptr++) if(*ptr=='\\') dirptr=ptr;
+
+ *(dirptr+1)=0;
+ strcat(inffilename,titlename);
+
+ m=GetFileSize(inffilename);
+ if(m==0 || m>512) return;
+
+ if( (n=open(inffilename,O_RDONLY | O_BINARY)) != -1)
+ {
+ k=0;
+ Print("+ Appending OEM Info : ");
+ memset(tempbuf,0,512);
+ if(read(n,&tempbuf,m) == -1) k++;
+ if(write_oem_to_temp(temp_handle,&tempbuf,m+1) == -1) k++;
+ if(k==0)
+ {
+ Print("Ok.");
+ if(verbose) Print(" (%d bytes)",m);
+ Print("\n");
+ }
+ else
+ Print("Error!\n");
+ close(n);
+ }
+}
diff -uNr a/dos32a/src/sc/main.h b/dos32a/src/sc/main.h
--- a/dos32a/src/sc/main.h false
+++ b/dos32a/src/sc/main.h e5664bdd7ef6611ce8cea95bc6b28adb8ff9c374d35dd80072377927808ea072380f11c357bb46ebbcc2f68735190896ef85eb51372ffbaed47a3727c63df238
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+
+extern int app_num_objects;
+
+extern int get_exec_type(void);
+
+extern int create_temp(void);
+extern int close_temp(void);
+
+extern int create_lc_header(void);
+extern int create_lc_object(long);
+extern int create_lc_fixups(void);
+
+extern int relocate_exec(char *);
+extern int write_oem_to_temp(int, char *, int);
+
+extern unsigned short exec_handle;
+extern unsigned short temp_handle;
+
+extern int obj_old_size;
+extern int obj_new_size;
+extern int relocated_fixups;
+
+extern byte app_enc_status;
+extern byte app_obj_iscode;
+extern byte app_obj_is32bit;
+extern long app_obj_seekattr[];
+
+
diff -uNr a/dos32a/src/sc/scomp.asm b/dos32a/src/sc/scomp.asm
--- a/dos32a/src/sc/scomp.asm false
+++ b/dos32a/src/sc/scomp.asm 7407f0f5dbf89fa2208bb0081acd65212aa69f8416e094abe601866bdae12bf6a87054dafbcea4884905f4e423bc48b41b02f9dbaaff5f5a43cfbdaea3da9b7c
@@ -0,0 +1,879 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .486p
+ .MODEL flat
+ LOCALS
+ NOJUMPS
+
+include stddef.inc
+
+APP_MAXOBJECTS = 64
+LC_SPECVER = 04h
+
+EXTRN _tempname2 :dword
+EXTRN _Exec_Type :dword
+EXTRN _quiet :dword
+EXTRN _smart :dword
+EXTRN _strip :dword
+EXTRN _encode :dword
+EXTRN _nocount :dword
+EXTRN CompressData_ :near
+
+PUBLIC _exec_handle
+PUBLIC _temp_handle
+PUBLIC _app_num_objects
+PUBLIC _app_enc_status
+PUBLIC _app_obj_iscode
+PUBLIC _app_obj_is32bit
+
+PUBLIC open_exec_, close_exec_
+PUBLIC create_temp_, close_temp_
+PUBLIC write_oem_to_temp_
+PUBLIC get_exec_type_
+
+PUBLIC _obj_old_size, _obj_new_size
+
+PUBLIC create_lc_header_
+PUBLIC create_lc_object_
+PUBLIC create_lc_fixups_
+
+
+.CODE
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+
+
+;-----------------------------------------------------------------------------
+; LC Header Format
+;
+; 0000 DD "LC" \0\0
+; 0004 DB # of Objects
+; 0005 DB reserved, 0
+; 0006 DB EIP Object #
+; 0007 DB ESP Object #
+; 0008 DD EIP Offset
+; 000C DD ESP Offset
+;
+
+create_lc_header_:
+ pushad
+ call seek_to_start ; move to exec start
+ jc @@err1
+ mov ecx,0A8h
+ mov edx,_buffer
+ call read_from_exec ; load LE/LX header
+ jc @@err2
+
+ mov esi,_buffer ; source LE/LX header
+ lea edi,[esi+0100h] ; destination LC header
+
+ mov eax,'CL'
+ mov [edi+0000h],eax ; LC signature
+ mov eax,[esi+0044h]
+ mov [edi+0004h],al ; # of Objects
+ mov al,LC_SPECVER
+ mov [edi+0005h],al ; LC implement.
+ mov eax,[esi+0018h]
+ mov [edi+0006h],al ; EIP Object #
+ mov eax,[esi+0020h]
+ mov [edi+0007h],al ; ESP Object #
+ mov eax,[esi+001Ch]
+ mov [edi+0008h],eax ; EIP Offset
+ mov eax,[esi+0024h]
+ mov [edi+000Ch],eax ; ESP Offset
+
+ mov eax,[esi+0010h] ; check Module Flags
+ and eax,2000h
+ jnz @@err4
+ mov eax,[esi+0044h] ; check # of Objects
+ cmp eax,APP_MAXOBJECTS
+ ja @@err5
+ mov _app_num_objects,eax
+ mov eax,[esi+0040h]
+ mov _app_off_objects,eax
+ mov eax,[esi+0048h]
+ mov _app_off_objpagetab,eax
+ mov eax,[esi+0068h]
+ mov _app_off_fixpagetab,eax
+ mov eax,[esi+006Ch]
+ mov _app_off_fixrectab,eax
+ mov eax,[esi+0080h]
+ mov _app_off_datapages,eax
+ mov eax,[esi+0030h]
+ mov _app_siz_fixrectab,eax
+ mov eax,[esi+002Ch]
+ mov _app_siz_lastpage,eax
+
+ mov eax,0FFFh
+ cmp _Exec_Type,1
+ jz @@1
+ mov eax,1
+ mov ecx,[esi+002Ch] ; get Page Offset Shift for LX-type
+ shl eax,cl ; max shift is 15 (8000h-1)
+ dec eax
+@@1: mov _app_off_pageshift,eax
+
+ mov ecx,16
+ mov edx,edi
+ call write_to_temp ; write LC header to temp file
+ jc @@err3
+ popad
+ xor eax,eax
+ ret
+
+@@err1: popad ; error seeking in exec
+ mov eax,-1
+ ret
+@@err2: popad ; error loading from exec
+ mov eax,-2
+ ret
+@@err3: popad ; error writing to temp
+ mov eax,-3
+ ret
+@@err4: popad ; error in application exec
+ mov eax,-4
+ ret
+@@err5: popad ; too many objects in exec
+ mov eax,-5
+ ret
+
+
+
+
+;-----------------------------------------------------------------------------
+; Object Header Format
+;
+; 0000 DD Virtual Size (Uncompressed Size)
+; bit 31: 0=encoded, 1=not encoded
+; 0004 DD Compressed Size
+; 0008 DW Object Flags
+; 000A DW Extended Object Flags
+; 000C DW Page Table Index
+; 000E DW # of Page Table Entries
+; 0010 ... ...Object Data...
+;
+
+create_lc_object_:
+ pushad
+ mov _tmp_cur_object,eax
+ mov _app_enc_status,1
+ mov _app_obj_iscode,0
+ mov _app_obj_is32bit,0
+
+ call print_reading
+
+ mov edx,_app_off_objects ; move to current Object head
+ call seek_to_edx
+ jc @@err1
+
+ mov ecx,18h ; load Object header
+ mov edx,_buffer
+ call read_from_exec
+ jc @@err2
+ add _app_off_objects,ecx
+
+ mov edx,_app_off_datapages
+ call seek_to_edx
+ jc @@err1
+
+ mov esi,_buffer
+ mov eax,[esi+0000h] ; Virtual Size
+ mov ebx,[esi+0010h] ; # of Page Table Entries
+ mov _app_obj_virtsize,eax
+
+ call alloc_exec_buffer
+ jc @@err3
+ call clear_exec_buffer
+
+ mov ecx,eax
+ mov eax,ebx
+ xor ebp,ebp
+ test eax,eax ; check if # Page Table Entries = 0
+ jz @@5 ; if yes, skip loading
+ shl eax,12 ; convert # Page Table Entries to bytes
+ cmp eax,ecx ; check if # bytes >= bytes to load
+ jae @@1 ; if yes, jump
+ mov ecx,eax ; else adjust number of bytes to read
+
+@@1: mov eax,_tmp_cur_object ; get Object #
+ cmp eax,_app_num_objects
+ jnz @@3
+ cmp _Exec_Type,1
+ jnz @@2
+ lea ecx,[ebx-1] ; load LE-style Last Object (BSS)
+ shl ecx,12
+ add ecx,_app_siz_lastpage
+ jmp @@3
+@@2: mov ecx,ebx ; load LX-style Last Object (BSS)
+ shl ecx,12
+ cmp ecx,_app_obj_virtsize
+ jb @@3
+ mov ecx,_app_obj_virtsize
+@@3: mov ebp,ecx ; EBP = bytes to load (phys. size)
+ mov edx,_exec_buffer
+ call read_from_exec ; load object data
+ jc @@err2
+
+ mov eax,ecx
+ mov edx,_app_off_pageshift
+ test eax,edx
+ jz @@4
+ mov ecx,edx
+ not edx
+ and eax,edx
+ lea eax,[eax+ecx+1]
+@@4: add _app_off_datapages,eax
+
+@@5: mov eax,ebp ; EAX = size
+ mov _obj_old_size,eax
+ shl eax,1 ; double that
+ add eax,10h ; + Object header size
+ call alloc_temp_buffer
+ jc @@err3
+ call clear_temp_buffer
+
+ mov eax,ebp
+ test eax,eax ; if null-size Object
+ jz @@6 ; then skip compressing it
+ call find_last_byte
+ mov ebp,eax
+
+ call print_nothing
+
+ mov eax,_exec_buffer ; EAX = source
+ mov edx,_temp_buffer ; EDX = destination
+ add edx,10h ; skip header size
+ mov ebx,ebp ; EBX = size
+ call compress_data ; returns: EAX = new size
+
+@@6: call print_writing
+
+ mov ebp,eax ; EBP = compressed size
+ mov _obj_new_size,eax
+ mov esi,_buffer
+ mov edi,_temp_buffer
+
+ mov eax,[esi+0000h] ; Virtual Size
+ cmp _app_enc_status,0
+ jz @@l1
+ or eax,80000000h
+@@l1: mov [edi+0000h],eax
+ mov eax,ebp ; Compressed Size
+ mov [edi+0004h],eax
+ mov eax,[esi+0008h] ; Object Flags
+ mov [edi+0008h],ax
+ mov eax,0 ; Extended Flags
+ mov [edi+000Ah],ax
+ mov eax,[esi+000Ch] ; Page Table Index
+ test eax,0FFFF0000h
+ jnz @@err5
+ mov [edi+000Ch],ax
+ mov eax,[esi+0010h] ; # of Page Table Entries
+ test eax,0FFFF0000h
+ jnz @@err5
+ mov [edi+000Eh],ax
+
+ lea ecx,[ebp+10h]
+ mov edx,_temp_buffer
+ call write_to_temp
+ jc @@err4
+
+ mov eax,[esi+0008h] ; Object Flags
+ test eax,0004h
+ setnz _app_obj_iscode ; 1=code, 0=data
+ test eax,2000h
+ setnz _app_obj_is32bit ; 1=32bit, 0=16bit
+
+ call free_temp_buffer
+ call free_exec_buffer
+
+ call print_nothing
+
+ popad
+ xor eax,eax
+ ret
+@@err1: popad ; error seeking in exec
+ mov eax,-1
+ ret
+@@err2: popad ; error reading from exec
+ mov eax,-2
+ ret
+@@err3: popad ; error allocating memory
+ mov eax,-3
+ ret
+@@err4: popad ; error writing to temp
+ mov eax,-4
+ ret
+@@err5: popad ; object header overflow
+ mov eax,-5
+ ret
+
+
+
+
+
+
+;-----------------------------------------------------------------------------
+;
+; Fixups Header Format
+;
+; 0000 DD Uncompresed Size
+; bit 31: 0=encoded, 1=not encoded
+; 0004 DD Compressed Size
+; 0008 DD Fixup Record Table Offset
+; 000C ... ...Fixup Page Table Data ...
+; 000C+[0008] ...Fixup Record Table Data ...
+
+create_lc_fixups_:
+ pushad
+ mov _app_enc_status,1
+
+ call print_reading
+
+ mov eax,_app_siz_fixrectab
+ call alloc_exec_buffer
+ jc @@err3
+ call clear_exec_buffer
+
+ mov edx,_app_off_fixpagetab
+ call seek_to_edx
+ jc @@err1
+ mov ecx,_app_siz_fixrectab
+ mov edx,_exec_buffer
+ call read_from_exec
+ jc @@err2
+
+ mov eax,_app_siz_fixrectab
+ mov _obj_old_size,eax
+ shl eax,1
+ add eax,0Ch
+ call alloc_temp_buffer
+ jc @@err3
+ call clear_temp_buffer
+
+ mov eax,_app_siz_fixrectab
+ call find_last_byte
+ mov ebp,eax
+
+ call print_nothing
+
+ mov eax,_exec_buffer ; EAX = source
+ mov edx,_temp_buffer ; EDX = destination
+ add edx,0Ch ; skip header size
+ mov ebx,ebp ; EBX = size
+ call compress_data
+ mov ebp,eax
+ mov _obj_new_size,eax
+
+ call print_writing
+
+ mov edi,_temp_buffer
+
+ mov eax,_app_siz_fixrectab
+ cmp _app_enc_status,0
+ jz @@l1
+ or eax,80000000h
+@@l1: mov [edi+0000h],eax
+ mov [edi+0004h],ebp
+ mov eax,_app_off_fixrectab
+ mov ebx,_app_off_fixpagetab
+ sub eax,ebx
+ mov [edi+0008h],eax
+
+ lea ecx,[ebp+0Ch]
+ mov edx,_temp_buffer
+ call write_to_temp
+ jc @@err4
+
+ call free_temp_buffer
+ call free_exec_buffer
+
+ call print_nothing
+
+ popad
+ xor eax,eax
+ ret
+
+@@err1: popad ; error seeking in exec
+ mov eax,-1
+ ret
+@@err2: popad ; error reading from exec
+ mov eax,-2
+ ret
+@@err3: popad ; error allocating memory
+ mov eax,-3
+ ret
+@@err4: popad ; error writing to temp
+ mov eax,-4
+ ret
+
+
+
+
+;-----------------------------------------------------------------------------
+compress_data:
+ mov _app_enc_status,0
+ cmp _encode,TRUE ; if NOT encode, copy data
+ jnz @@2
+ cmp _smart,TRUE ; if NOT smart, compress data
+ jnz CompressData_
+ test ebx,ebx
+ jnz @@0
+ xor eax,eax
+ mov _app_enc_status,1
+ ret
+
+@@0: push eax edx ebx
+ call CompressData_
+ pop ebx edx
+ cmp eax,ebx
+ ja @@1
+ add esp,4
+ ret
+
+@@1: pop eax
+@@2: pushad
+ mov esi,eax
+ mov edi,edx
+ mov ecx,ebx
+ shr ecx,2
+ rep movsd
+ mov ecx,ebx
+ and ecx,03h
+ rep movsb
+ popad
+ mov eax,ebx
+ mov _app_enc_status,1
+ ret
+
+
+comment ~
+;-----------------------------------------------------------------------------
+; Find the most common byte in the _exec_buffer (very slow)
+; In: EAX = size of buffer
+; Out: EAX = byte
+;
+find_common_byte:
+ pushad
+ mov ebp,eax
+ sub esp,0100h*4
+ xor eax,eax
+ mov edi,esp
+ mov ecx,0100h
+ rep stosd
+ xor eax,eax
+ mov ebx,0100h
+ Align 4
+@@1: mov ecx,ebp
+ mov edi,_exec_buffer
+ Align 4
+@@2: scasb
+ jnz @@3
+ inc dword ptr [esp+eax*4]
+ Align 4
+@@3: dec ecx
+ jnz @@2
+ inc eax
+ dec ebx
+ jnz @@1
+ xor eax,eax
+ xor ebx,ebx
+ xor edx,edx
+@@4: cmp eax,[esp+ebx*4]
+ jae @@5
+ mov eax,[esp+ebx*4]
+ mov edx,ebx
+@@5: inc ebx
+ cmp ebx,0100h
+ jb @@4
+ add esp,0100h*4
+ mov [esp+1Ch],edx
+ popad
+ ret
+~
+
+
+;-----------------------------------------------------------------------------
+; Find the last *non-zero* byte in the _exec_buffer
+; In: EAX = real size of the buffer
+; Out: EAX = virtual size of the buffer
+;
+find_last_byte:
+ pushad
+ cmp _strip,TRUE
+ jnz @@done
+
+ mov ecx,eax
+ jecxz @@done
+ xor eax,eax
+ mov edi,_exec_buffer
+ lea edi,[edi+ecx-1]
+ std
+ repe scasb
+ cld
+ cmp al,[edi+1]
+ jz @@1
+ inc ecx
+@@1: mov [esp+1Ch],ecx
+@@done: popad
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+open_exec_:
+ pushad
+ mov edx,eax
+ mov ax,3D02h
+ int 21h
+ jc @@0
+ mov _exec_handle,ax
+@@0: popad
+ mov eax,0
+ sbb eax,eax
+ ret
+
+close_exec_:
+ pushad
+ mov bx,_exec_handle
+ cmp bx,-1
+ jz @@0
+ mov ah,3Eh
+ int 21h
+ mov _exec_handle,-1
+@@0: popad
+ ret
+
+create_temp_:
+ pushad
+ mov edx,_tempname2 ; create temp2 file
+ mov ecx,00h
+ mov ah,3Ch
+ int 21h
+ jc @@0
+ mov _temp_handle,ax
+@@0: popad
+ mov eax,0
+ sbb eax,eax
+ ret
+
+close_temp_:
+ pushad
+ mov bx,_temp_handle
+ cmp bx,-1
+ jz @@0
+ mov ah,3Eh
+ int 21h
+ mov _temp_handle,-1
+@@0: popad
+ ret
+
+
+;-----------------------------------------------------------------------------
+get_exec_type_:
+ pushad
+ call seek_to_start
+ mov ax,3F00h
+ mov bx,_exec_handle
+ mov ecx,4
+ mov edx,_buffer
+ int 21h
+ jc @@err1
+ test eax,eax
+ jz @@err2 ; unknown exec format
+ cmp wptr [edx],'EL'
+ jz @@1
+ cmp wptr [edx],'XL'
+ jz @@2
+ cmp wptr [edx],'CL'
+ jz @@3
+ cmp wptr [edx],'EP'
+ jz @@4
+ cmp dptr [edx],'1WMP'
+ jz @@5
+@@err2: popad
+ mov eax,-2
+ ret
+@@err1: popad
+ mov eax,-1
+ ret
+@@1: popad
+ mov eax,1
+ ret
+@@2: popad
+ mov eax,2
+ ret
+@@3: popad
+ mov eax,3
+ ret
+@@4: popad
+ mov eax,4
+ ret
+@@5: popad
+ mov eax,5
+ ret
+
+
+;-----------------------------------------------------------------------------
+write_oem_to_temp_:
+ pushad
+ mov ecx,ebx
+ mov ebx,eax
+ mov ah,40h
+ mov bx,_temp_handle
+ int 21h
+ jc @@err
+
+ xor ecx,ecx
+ xor edx,edx
+ mov ax,4200h
+ mov bx,_temp_handle
+ int 21h
+ jc @@err
+
+ mov ah,3Fh
+ mov bx,_temp_handle
+ mov ecx,10h
+ mov edx,_buffer
+ int 21h
+ jc @@err
+
+ xor ecx,ecx
+ xor edx,edx
+ mov ax,4200h
+ mov bx,_temp_handle
+ int 21h
+ jc @@err
+
+ mov edx,_buffer
+ mov al,[edx+05h]
+ or al,80h
+ mov [edx+05h],al
+
+ mov ah,40h
+ mov bx,_temp_handle
+ mov ecx,10h
+ mov edx,_buffer
+ int 21h
+ jc @@err
+
+ popad
+ xor eax,eax
+ ret
+
+@@err: popad
+ mov eax,-1
+ ret
+
+;-----------------------------------------------------------------------------
+seek_to_start:
+ pushad
+ xor ecx,ecx
+ xor edx,edx
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h
+ popad
+ ret
+seek_to_edx:
+ pushad
+ mov ecx,edx
+ shr ecx,16
+ mov bx,_exec_handle
+ mov ax,4200h
+ int 21h
+ popad
+ ret
+read_from_exec:
+ pushad
+ mov ah,3Fh
+ mov bx,_exec_handle
+ int 21h
+ popad
+ ret
+write_to_temp:
+ pushad
+ mov ah,40h
+ mov bx,_temp_handle
+ int 21h
+ popad
+ ret
+alloc_exec_buffer:
+ pushad
+ lea ebx,[eax+10h]
+ mov ax,0FF91h
+ int 21h
+ mov _exec_buffer,ebx
+ mov _exec_bufhand,esi
+ popad
+ ret
+free_exec_buffer:
+ pushad
+ mov esi,_exec_bufhand
+ mov ax,0FF92h
+ int 21h
+ popad
+ ret
+alloc_temp_buffer:
+ pushad
+ lea ebx,[eax+10h]
+ mov ax,0FF91h
+ int 21h
+ mov _temp_buffer,ebx
+ mov _temp_bufhand,esi
+ popad
+ ret
+free_temp_buffer:
+ pushad
+ mov esi,_temp_bufhand
+ mov ax,0FF92h
+ int 21h
+ popad
+ ret
+clear_exec_buffer:
+ pushad
+ mov ecx,eax
+ mov edx,eax
+ shr ecx,2
+ and edx,3
+ xor eax,eax
+ mov edi,_exec_buffer
+ rep stosd
+ mov ecx,edx
+ rep stosb
+ popad
+ ret
+clear_temp_buffer:
+ pushad
+ mov ecx,eax
+ mov edx,eax
+ shr ecx,2
+ and edx,3
+ xor eax,eax
+ mov edi,_temp_buffer
+ rep stosd
+ mov ecx,edx
+ rep stosb
+ popad
+ ret
+
+
+print_reading:
+ pushad
+ cmp _quiet,0
+ jnz @@0
+ cmp _nocount,TRUE
+ jz @@0
+ mov ax,0FF80h
+ mov edx,offset _str_reading
+ int 21h
+@@0: popad
+ ret
+print_writing:
+ pushad
+ cmp _quiet,0
+ jnz @@0
+ cmp _nocount,TRUE
+ jz @@0
+ mov ax,0FF80h
+ mov edx,offset _str_writing
+ int 21h
+@@0: popad
+ ret
+print_nothing:
+ pushad
+ cmp _quiet,0
+ jnz @@0
+ cmp _nocount,TRUE
+ jz @@0
+ mov ax,0FF80h
+ mov edx,offset _str_nothing
+ int 21h
+@@0: popad
+ ret
+
+
+
+.DATA
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+_buffer dd offset @buffer
+_exec_handle dw -1
+_temp_handle dw -1
+
+_str_reading db 'Reading...',8,8,8,8,8,8,8,8,8,8,0
+_str_writing db 'Writing...',8,8,8,8,8,8,8,8,8,8,0
+_str_nothing db ' ',8,8,8,8,8,8,8,8,8,8,0
+
+
+
+.DATA?
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+@buffer db 1000h dup(?)
+
+_exec_type dd ?
+_exec_name dd ?
+
+_exec_buffer dd ?
+_exec_bufhand dd ?
+_temp_buffer dd ?
+_temp_bufhand dd ?
+
+__saved_esp dd ?
+_tmp_cur_object dd ?
+_tmp_cnt_bytes dd ?
+_obj_old_size dd ?
+_obj_new_size dd ?
+
+;-----------------------------------------------------------------------------
+_app_num_objects dd ?
+_app_off_objects dd ?
+_app_off_objpagetab dd ?
+_app_off_fixpagetab dd ?
+_app_off_fixrectab dd ?
+_app_off_datapages dd ?
+_app_siz_fixrectab dd ?
+_app_siz_lastpage dd ?
+_app_off_pageshift dd ?
+_app_obj_virtsize dd ?
+
+_app_enc_status db ? ; 0=encoded, 1=not encoded
+_app_obj_iscode db ?
+_app_obj_is32bit db ?
+
+end
diff -uNr a/dos32a/src/sc/sload.asm b/dos32a/src/sc/sload.asm
--- a/dos32a/src/sc/sload.asm false
+++ b/dos32a/src/sc/sload.asm f659b2e628b30b8fc9c60de5749927d9cd6e8c08a805cd23ca2f038e3be77dc952beda8a7b4967dadd7c8bcfb2bf8c831d8f130d274414acaef2109d68df4288
@@ -0,0 +1,857 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .386p
+ .MODEL flat
+ LOCALS
+ NOJUMPS
+
+APP_MAXOBJECTS = 64
+
+EXTRN _quiet :dword
+EXTRN _nocount :dword
+
+PUBLIC relocate_exec_
+PUBLIC _relocated_fixups
+PUBLIC _app_obj_seekattr
+
+include stddef.inc
+
+.CODE
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+
+relocate_exec_:
+ pushad
+ mov __saved_esp,esp
+ mov __filename_ptr,eax
+ mov _relocated_fixups,0
+ call clear_struct
+ call open_exec
+ call load_application
+; call relocate_application
+ call free_resources
+ call close_exec
+ xor eax,eax
+ jmp common_exit
+
+
+
+
+;=============================================================================
+load_application:
+ mov __loader_esp,esp
+ call load_header ; load 'LE'/'LX' exec header
+ mov ecx,1 ; start with Object #1
+@@1: call show_progress
+ mov _app_cur_object,ecx
+ call load_object ; load object
+ call create_selector ; allocate selector for loaded object
+ push edx ; save Object Selector/Object Flags
+ push edi ; save Address of loaded Object
+ push esi ; save Page Table Index
+ push ebx ; save # Page Table Entries
+ inc ecx ; increment Current_Object#
+ cmp ecx,_app_num_objects
+ jbe @@1 ; loop until all objects are loaded
+ call preload_fixups ; preload fixup tables and records
+ mov ebp,esp ; base pointer to last loaded Object
+ mov ebx,_app_num_objects ; number of Objects
+ dec ebx
+ shl ebx,4
+ mov _app_tmp_addr1,ebx
+ mov __current_object,0
+@@4: inc __current_object
+ call relocate_object
+ sub ebx,10h
+ jnc @@4
+ call unload_fixups ; free allocated memory for fixups
+ mov esp,__loader_esp
+ ret
+
+
+;relocate_application:
+; mov ebp,1
+; xor eax,eax
+; xor ebx,ebx
+; mov _err_code,3002h
+;@@1: cmp _app_obj_seekattr[ebp*4],0
+; jz @@2
+; mov edx,_app_obj_seekptr[ebp*4]
+; call seek_from_start
+; mov ah,40h
+; mov bx,__exec_handle
+; mov ecx,_app_obj_seeksize[ebp*4]
+; jecxz @@2
+; mov edx,_app_buf_allocbase[ebp*4]
+; int 21h
+; jc file_errorm
+;@@2: inc ebp ; increment Current_Object#
+; cmp ebp,_app_num_objects
+; jbe @@1 ; loop until all objects are loaded
+; ret
+
+
+
+
+;-----------------------------------------------------------------------------
+load_header:
+ sub esp,0ACh
+ mov ecx,0A8h ; load 'LE' header
+ mov ebp,esp
+ lea edx,[esp+4]
+ mov _err_code,3002h ; "error in app file"
+
+ call load_fs_block
+ mov edx,__exec_start
+
+ mov ax,[ebp+0010h] ; get Module Flags
+ and ax,2000h ; check if not-loadable;/no-fixups
+ mov ax,3005h
+ jnz file_error
+ mov eax,[ebp+0044h] ; get # Objects
+ mov ecx,eax
+ cmp eax,APP_MAXOBJECTS
+ mov ax,4001h ; "too many objects"
+ ja file_error
+ mov _app_num_objects,ecx
+
+ mov eax,[ebp+0040h] ; get Object Table Offset
+ add eax,edx
+ mov _app_off_objects,eax
+ mov eax,[ebp+0048h] ; get Object PageTable Offset
+ add eax,edx
+ mov _app_off_objpagetab,eax
+ mov eax,[ebp+0068h] ; get Fixup PageTable Offset
+ add eax,edx
+ mov _app_off_fixpagetab,eax
+ mov eax,[ebp+006Ch] ; get Fixup Record Table Offset
+ add eax,edx
+ mov _app_off_fixrectab,eax
+ mov eax,[ebp+0080h] ; get Data Pages Offset
+ add _app_off_datapages,eax
+
+ mov eax,[ebp+0030h] ; get Fixup Records Size
+ mov _app_siz_fixrecstab,eax
+ mov eax,[ebp+002Ch] ; get Bytes on Last Page (LE-only)
+ mov _app_siz_lastpage,eax
+
+ mov eax,0FFFh
+ cmp _app_type,0
+ jz @@done
+ mov eax,1
+ mov ecx,[ebp+002Ch] ; get Page Offset Shift for LX-type
+ shl eax,cl ; max shift is 15 (8000h-1)
+ dec eax
+
+@@done: mov _app_off_pageshift,eax
+ add esp,0ACh
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+load_object:
+ push ecx
+
+ mov _err_code,3002h ; "error in app file"
+ mov edx,_app_off_objects
+ call seek_from_start ; move to object header
+
+ sub esp,18h
+ mov ecx,18h
+ mov edx,esp
+ mov ebp,esp
+ call load_fs_block ; load object header
+ add _app_off_objects,eax
+
+ mov edx,_app_off_datapages ; get Data_Pages_Offset
+ mov eax,_app_cur_object
+ mov _app_obj_seekptr[eax*4],edx
+ call seek_from_start ; move to object data
+ mov eax,[ebp+0000h] ; get Virtual_Size[Object]
+ mov ebx,[ebp+0010h] ; get # Page Table Entries
+ mov ecx,[ebp+0008h] ; get Flags[Object]
+ mov esi,[ebp+000Ch] ; get Page Table Index
+ add esp,18h
+
+ push ecx ; save Object Flags
+ call alloc_block ; allocate EAX memory block to EDI
+ mov ecx,eax ; ECX = bytes to read
+ mov ebp,eax ; EBP = preserve Virtual Size
+ mov edx,edi ; EDX = addres to read to
+ call fill_zero_pages ; fill allocated memory with zeroes
+
+ mov eax,ebx
+ test eax,eax ; check if # Page Table Entries = 0
+ jz @@5 ; if yes, skip loading
+ shl eax,12 ; convert # Page Table Entries to bytes
+ cmp eax,ecx ; check if # bytes >= bytes to load
+ jae @@1 ; if yes, jump
+ mov ecx,eax ; else adjust number of bytes to read
+
+@@1: mov eax,[esp+4] ; get Object #
+ cmp eax,_app_num_objects
+ jnz @@3
+ cmp _app_type,0
+ jnz @@2
+ lea ecx,[ebx-1] ; load LE-style Last Object (BSS)
+ shl ecx,12
+ add ecx,_app_siz_lastpage
+ jmp @@3
+@@2: mov ecx,ebx ; load LX-style Last Object (BSS)
+ shl ecx,12
+
+@@3: mov _err_code,3002h ; "error in app file"
+ mov eax,_app_cur_object
+ push eax
+ call load_gs_block ; load object data
+ pop edx
+ mov _app_obj_seeksize[edx*4],eax
+ mov eax,ecx
+ mov edx,_app_off_pageshift
+ test eax,edx
+ jz @@4
+ mov ecx,edx
+ not edx
+ and eax,edx
+ lea eax,[eax+ecx+1]
+@@4: add _app_off_datapages,eax
+
+@@5: pop edx ; restore Object Flags
+@@done: pop ecx
+ ret
+
+
+
+
+;=============================================================================
+relocate_object:
+ xor eax,eax
+ cmp eax,[ebp+ebx+0] ; get # Page Table Entries[Object]
+ jnz @@0 ; if zero, done
+ ret
+@@0: cmp _app_type,0
+ jnz relocate_lx_object
+
+relocate_le_object:
+ mov ecx,[ebp+ebx+4] ; get Page Table Index
+ mov edx,_app_off_objpagetab ; get Object Page Table Offset in exec
+ lea edx,[ecx*4+edx-4]
+ mov _err_code,3002h ; "error in app file"
+ call seek_from_start ; *1) move file ptr
+@@1: push eax ; EAX = counter
+ mov ecx,4
+ sub esp,4
+ mov edx,esp
+ mov _err_code,3002h ; "error in app file"
+ call load_fs_block ; load block
+ xor ecx,ecx ; get index into FixupPageTab
+ mov ch,[esp+0001h]
+ mov cl,[esp+0002h]
+ add esp,4
+ jecxz @@2
+ mov eax,_app_off_fixpagetab ; get Fixup Page Table Offset
+ lea eax,[ecx*4+eax-4]
+ mov esi,[eax+00h] ; get offset of 1st fixup table
+ mov ecx,[eax+04h] ; get offset of 2nd fixup table
+ sub ecx,esi ; calculate size of 1st tab
+ jz @@2 ; if 1st == 2nd, no fixups
+ add esi,_app_off_fixrectab ; get Fixup Record Table Offset
+ mov edi,[esp] ; get current page number
+ shl edi,12
+ add edi,[ebp+ebx+8] ; address of page target to fix in mem
+ add ecx,esi
+ call apply_fixups ; patch target with fixup data
+@@2: pop eax
+ inc eax
+ cmp eax,[ebp+ebx+0]
+ jb @@1
+ ret
+
+relocate_lx_object:
+ mov ecx,[ebp+ebx+4] ; get Page Table Index
+ mov edx,_app_off_fixpagetab ; get Fixup Page Table Offset
+ lea edx,[ecx*4+edx-4]
+@@1: push eax edx ; EAX = counter
+ mov esi,[edx+00h] ; get offset of 1st fixup table
+ mov ecx,[edx+04h] ; get offset of 2nd fixup table
+ sub ecx,esi ; calculate size of 1st tab
+ jz @@2 ; if 1st == 2nd, no fixups
+ add esi,_app_off_fixrectab ; get Fixup Record Table Offset
+ mov edi,[esp+4] ; get current page number
+ shl edi,12
+ add edi,[ebp+ebx+8] ; address of page target to fix in mem
+ add ecx,esi
+ call apply_fixups ; patch target with fixup data
+@@2: pop edx eax
+ add edx,4
+ inc eax
+ cmp eax,[ebp+ebx+0]
+ jb @@1
+ ret
+
+
+
+;=============================================================================
+ Align 4
+apply_fixups:
+@@0: call show_progress
+ inc _relocated_fixups
+ push ecx edi
+ mov _err_code,4005h ; "unrecognized fixup data"
+ mov cx,[esi+0] ; get SRC/FLAGS
+ movsx edx,word ptr [esi+2] ; get SRCOFF
+ movzx eax,word ptr [esi+4] ; get OBJNUM
+ add edi,edx ; calculate dest addr to be fixed
+ test cx,0F20h ; SrcLists/Imports not supported
+ jnz file_errorm ; jump if one of these
+ test cx,4000h ; test if 16bit object number
+ jnz @@1 ; if yes, jump
+ mov ah,0
+ dec esi
+@@1: add esi,6
+ dec eax ; Object Number - 1
+ shl eax,4
+ mov edx,_app_tmp_addr1
+ sub edx,eax
+ jc file_errorm
+ mov _app_tmp_addr2,edx
+ mov edx,[ebp+edx+8] ; EDX = Destination Object Address
+ mov al,cl
+ and al,0Fh
+ cmp al,02h ; check if 16bit Selector
+ jz @@3 ; if yes, jump
+ cmp al,08h
+ ja file_errorm
+ mov eax,[esi]
+ test cx,1000h ; check for Alias flag
+ jnz @@2 ; if not, jump
+ movzx eax,ax
+ sub esi,2
+@@2: add esi,4
+@@3: push esi
+ mov esi,ecx
+ and esi,0Fh
+ lea esi,[esi*4]
+ mov _err_code,4006h ; "16bit fixup overflow"
+ call fix_tab[esi]
+ pop esi
+@@5: pop edi ecx
+ cmp esi,ecx
+ jb @@0
+ ret
+
+
+;
+; EAX = Data
+; EDX = Address of Object
+; EDI = Address to Fixup
+; EBP:EBX = Ptr to Current Object Table
+;-----------------------------------------------------------------------------
+fix_byte:
+ call mark_object
+ mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],al
+ call patch_it8
+ ret
+fix_16off:
+ call mark_object
+ mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],ax
+ call patch_it16
+ ret
+fix_32off:
+ call mark_object
+ add eax,edx
+ mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],eax
+ call patch_it32
+ ret
+fix_32selfrel:
+ call mark_object
+ add eax,edx
+ lea ecx,[edi+4]
+ sub eax,ecx
+ test word ptr [ebp+ebx+12],2000h
+ jnz @@1
+ lea ecx,[eax+8002h]
+ shr ecx,16
+ jnz file_errorm
+ mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],ax
+ call patch_it16
+ ret
+@@1: mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],eax
+ call patch_it32
+ ret
+fix_16sel:
+ call mark_object
+ call check_range
+ mov edx,_dummy_fill ;** dummy fill
+ mov [edi+0],dx
+ call patch_it16
+ ret
+fix_1616ptr:
+ call mark_object
+ call check_range
+ mov eax,_dummy_fill ;** dummy fill
+ mov edx,_dummy_fill ;** dummy fill
+ mov [edi+0],ax
+ mov [edi+2],dx
+ call patch_it32
+ ret
+fix_1632ptr:
+ call mark_object
+ add eax,edx
+ mov eax,_dummy_fill ;** dummy fill
+ mov [edi+0],eax
+ call patch_it32
+ call check_range
+ mov edx,_dummy_fill ;** dummy fill
+ mov [edi+4],dx
+ add edi,4
+ call patch_it16
+ ret
+fix_invalid:
+ mov ax,4005h ; "unrecognized fixup data"
+ jmp file_error
+
+check_range:
+ test word ptr [ebp+ebx+12],1000h ; check if 16:16 alias requird
+ jnz @@1 ; if yes, jump
+ test cl,10h
+ jnz @@1
+@@0: mov ecx,_app_tmp_addr2
+ mov dx,[ebp+ecx+14] ; get selector
+ ret
+@@1: test cl,10h
+ jz @@0
+ mov ecx,_app_tmp_addr2
+ mov dx,[ebp+ecx+14] ; get selector
+ test eax,0FFFF0000h ; check 64K range
+ jnz file_errorm
+ ret
+
+
+ Align 4
+fix_tab label dword
+ dd fix_byte ; 00h
+ dd fix_invalid ; 01h
+ dd fix_16sel ; 02h
+ dd fix_1616ptr ; 03h
+ dd fix_invalid ; 04h
+ dd fix_16off ; 05h
+ dd fix_1632ptr ; 06h
+ dd fix_32off ; 07h
+ dd fix_32selfrel ; 08h
+
+
+
+
+
+
+
+
+;-----------------------------------------------------------------------------
+; In: ECX = size
+; Out: EDI = address
+;
+fill_zero_pages:
+ pushad
+ mov dl,cl
+ shr ecx,2
+ xor eax,eax
+ rep stosd
+ mov cl,dl
+ and cl,3
+ rep stosb
+ popad
+ ret
+
+
+;-----------------------------------------------------------------------------
+; In: EAX = size
+; Out: EDI = address
+;
+alloc_block:
+ xor edi,edi
+ test eax,eax ; if size of Object is zero
+ jz @@null ; then report warning 9005
+ push eax ebx esi
+ mov _err_code,4003h ; "not enough DPMI mem"
+ mov ebx,eax
+ mov ax,0FF91h ; allocate DPMI memory
+ int 21h
+ mov _app_tmp_addr1,esi
+ mov edi,ebx
+ pop esi ebx eax
+ jc file_errorm ; if failed, error
+@@null: ret
+
+
+
+
+
+
+
+
+;-----------------------------------------------------------------------------
+create_selector:
+ push ebx edx
+ xor eax,eax
+ mov [esp+2],ax ; store selector in high word of EDX
+ pop edx
+ mov _app_buf_allocbase[ecx*4],edi
+ mov ebx,_app_tmp_addr1
+ mov _app_buf_allochandle[ecx*4],ebx
+ pop ebx
+ ret
+
+
+preload_fixups:
+ mov ebx,_app_siz_fixrecstab ; allocate memory for fixups
+ mov ax,0FF91h
+ int 21h
+ mov ax,4004h
+ jc file_error ; if not enough memory, error
+ mov _app_buf_fixrecstab,esi
+ mov _err_code,3002h ; "error in app file"
+ mov edx,_app_off_fixpagetab ; move file ptr to fixups
+ call seek_from_start
+ mov edx,ebx
+ mov ecx,_app_siz_fixrecstab
+ call load_gs_block
+ mov eax,_app_off_fixrectab
+ mov ebx,_app_off_fixpagetab
+ sub eax,ebx
+ add eax,edx
+ mov _app_off_fixpagetab,edx
+ mov _app_off_fixrectab,eax
+ ret
+
+
+unload_fixups:
+ mov esi,_app_buf_fixrecstab
+ mov ax,0FF92h
+ int 21h
+ ret
+
+
+
+;=============================================================================
+open_exec:
+ sub esp,40h
+ mov __exec_handle,-1
+ mov _err_code,3001h ; "could not open app exec"
+ mov ax,3D02h
+ mov edx,__filename_ptr
+ int 21h
+ jc file_errorm
+ mov __exec_handle,ax
+ mov ecx,40h
+ mov edx,esp
+ mov _err_code,3002h ; "error in app exec"
+ call load_fs_block
+ xor eax,eax
+ mov _err_code,3004h ; "exec format not supported"
+ cmp word ptr [edx],'EL'
+ jz @@1
+ cmp word ptr [edx],'XL'
+ jnz file_errorm
+@@1: mov __exec_start,eax
+ mov _app_off_datapages,0
+ mov edx,eax
+ mov _err_code,3002h ; "error in app exec"
+ call seek_from_start
+ mov ecx,04h
+ mov edx,esp
+ call load_fs_block
+ mov _err_code,3004h ; "exec format not supported"
+ cmp word ptr [edx],'EL'
+ mov _app_type,0
+ jz @@2
+ cmp word ptr [edx],'XL'
+ mov _app_type,1
+ jnz file_errorm
+@@2: add esp,40h
+ ret
+
+close_exec:
+ mov bx,__exec_handle
+ cmp bx,-1
+ jz @@1
+ mov ah,3Eh
+ int 21h
+ mov __exec_handle,-1
+@@1: ret
+
+
+free_resources:
+ mov ecx,_app_num_objects
+ jecxz @@2
+@@1: mov ax,0FF92h
+ mov esi,_app_buf_allochandle[ecx*4]
+ int 21h
+ loop @@1
+@@2: ret
+
+
+
+;=============================================================================
+clear_struct:
+ mov ecx,offset @app_struct_end
+ mov edi,offset @app_struct_begin
+ sub ecx,edi
+ xor eax,eax
+ rep stosb
+ ret
+
+
+
+
+;=============================================================================
+;dpmi_error:
+; movzx eax,ax
+; bts eax,31
+; jmp common_exit
+file_errorm:
+ mov ax,_err_code
+file_error:
+ movzx eax,ax
+common_exit:
+ mov esp,__saved_esp
+ mov [esp+1Ch],eax
+ call close_exec
+ popad
+ ret
+
+
+;=============================================================================
+seek_to_start:
+ pushad
+ xor ecx,ecx
+ xor edx,edx
+ jmp common_seek
+seek_from_start:
+ pushad
+ mov ecx,edx
+ shr ecx,16
+common_seek:
+ mov bx,__exec_handle
+ mov ax,4200h
+ int 21h
+ jc file_errorm
+ popad
+ ret
+seek_from_start@pos:
+ pushad
+ xor ecx,ecx
+ xor edx,edx
+ mov bx,__exec_handle
+ mov ax,4201h
+ int 21h
+ jc file_errorm
+ mov wptr __oldfilepos[0],ax
+ mov wptr __oldfilepos[2],dx
+ popad
+ jmp seek_from_start
+load_fs_block:
+load_gs_block:
+ push ebx
+ mov bx,__exec_handle
+ mov ah,3Fh
+ int 21h
+ pop ebx
+ jc file_errorm
+ ret
+
+mark_object:
+ push eax
+ mov eax,__current_object
+ inc _app_obj_seekattr[eax*4]
+ pop eax
+ ret
+
+patch_it32:
+ pushad
+ mov edx,edi
+ mov eax,__current_object
+ sub edx,_app_buf_allocbase[eax*4]
+ add edx,_app_obj_seekptr[eax*4]
+ call seek_from_start@pos
+ mov ah,40h
+ mov bx,__exec_handle
+ mov ecx,4
+ mov edx,offset _dummy_fill
+ int 21h
+ jc file_errorm
+ mov edx,__oldfilepos
+ call seek_from_start
+ popad
+ ret
+
+patch_it16:
+ pushad
+ mov edx,edi
+ mov eax,__current_object
+ sub edx,_app_buf_allocbase[eax*4]
+ add edx,_app_obj_seekptr[eax*4]
+ call seek_from_start@pos
+ mov ah,40h
+ mov bx,__exec_handle
+ mov ecx,2
+ mov edx,offset _dummy_fill
+ int 21h
+ jc file_errorm
+ mov edx,__oldfilepos
+ call seek_from_start
+ popad
+ ret
+
+patch_it8:
+ pushad
+ mov edx,edi
+ mov eax,__current_object
+ sub edx,_app_buf_allocbase[eax*4]
+ add edx,_app_obj_seekptr[eax*4]
+ call seek_from_start@pos
+ mov ah,40h
+ mov bx,__exec_handle
+ mov ecx,1
+ mov edx,offset _dummy_fill
+ int 21h
+ jc file_errorm
+ mov edx,__oldfilepos
+ call seek_from_start
+ popad
+ ret
+
+
+show_progress:
+ pushad
+ cmp _quiet,TRUE
+ jz @@done
+ cmp _nocount,TRUE
+ jz @@done
+ mov al,_str0
+ inc al
+ and al,03h
+ mov _str0,al
+ jnz @@done
+
+ mov ah,09h ; else show string1
+ mov edx,offset _str1
+ int 21h ; Note: nested calls (RM->PM->RM)
+
+ mov al,_str1+1 ; ajust string
+ mov ah,"\"
+ cmp al,"-"
+ jz @@1
+ mov ah,"|"
+ cmp al,"\"
+ jz @@1
+ mov ah,"/"
+ cmp al,"|"
+ jz @@1
+ mov ah,"-"
+ cmp al,"/"
+ jz @@1
+
+@@1: mov _str1+1,ah
+@@done: popad
+ ret
+
+.DATA
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+
+_err_code dw 0
+_dummy_fill dd 0
+_relocated_fixups dd 0
+
+_str0 db 0
+_str1 db '[-]',08h,08h,08h,'$'
+
+
+.DATA?
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+@app_struct_begin label byte
+_app_type db ?
+_app_load db ?
+_app_tmp_addr1 dd ?
+_app_tmp_addr2 dd ?
+_app_num_objects dd ?
+_app_off_objects dd ?
+
+_app_off_objpagetab dd ?
+_app_off_fixpagetab dd ?
+_app_off_fixrectab dd ?
+_app_off_datapages dd ?
+_app_off_pageshift dd ?
+_app_siz_fixrecstab dd ?
+_app_siz_lastpage dd ?
+_app_buf_fixrecstab dd ?
+
+_app_cur_object dd ?
+
+_app_buf_allocbase dd APP_MAXOBJECTS dup(?)
+_app_buf_allochandle dd APP_MAXOBJECTS dup(?)
+
+_app_obj_seekptr dd APP_MAXOBJECTS dup(?)
+_app_obj_seeksize dd APP_MAXOBJECTS dup(?)
+_app_obj_seekattr dd APP_MAXOBJECTS dup(?)
+@app_struct_end label byte
+
+;-----------------------------------------------------------------------------
+__filename_ptr dd ?
+__structure_ptr dd ?
+
+__current_object dd ?
+
+__oldfilepos dd ?
+__exec_handle dw ?
+__exec_start dd ?
+__saved_esp dd ?
+__saved_ss dw ?
+__loader_esp dd ?
+
+
+
+end
+
diff -uNr a/dos32a/src/ss/iface.c b/dos32a/src/ss/iface.c
--- a/dos32a/src/ss/iface.c false
+++ b/dos32a/src/ss/iface.c 4ee9764af5a0e2db23da67677a71a952212adb6b948f2e624da9a12e218240aea855fedeeff3c2215e20c9215b0ea98ff469462cf87dfae131d0382aacfd00fa
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+void CloseAllWindows()
+{
+ int n;
+ for(n=0; n<16; n++) CloseWindow();
+}
+
+void Print_At(int y, int x, char *format, ...)
+{
+ va_list arglist;
+ char buffer[256];
+ SetPos(y,x);
+ va_start(arglist,format);
+ vsprintf(buffer,format,arglist);
+ Prints(buffer);
+ va_end(arglist);
+}
+
+void Print(char *format, ...)
+{
+ va_list arglist;
+ char buffer[256];
+ va_start(arglist,format);
+ vsprintf(buffer,format,arglist);
+ Prints(buffer);
+ va_end(arglist);
+}
+
+
+unsigned long Input(int y, int x, int l, unsigned long old)
+{
+ int n;
+ char c;
+ char buf[80];
+
+ Print_At(y,x-1,"<");
+ Print_At(y,x+l,">");
+ for(n=0; n0)
+ {
+ Print_At(y,x+n,".");
+ n--;
+ goto l0;
+ } else goto l0;
+ }
+ buf[n]=c;
+ Print_At(y,x+n,"%c",c);
+ }
+
+l1: buf[n]=0;
+
+ Print_At(y,x-1," ");
+ Print_At(y,x+l," ");
+ for(n=0; n");
+ for(n=0; n8) m=0; x=xx; strcpy(buf,defbuf[m]); goto l8; }
+ if(keycode==DOWN) { m--; if(m<0) m=8; x=xx; strcpy(buf,defbuf[m]); goto l8; }
+ } while(c<0x20);
+
+ if(c==0x08)
+ {
+ if(n>0)
+ {
+ Print_At(y,x+n,".");
+ n--;
+ goto l0;
+ } else goto l0;
+ }
+ buf[n]=c;
+ Print_At(y,x+n,"%c",c);
+ }
+
+l1: buf[n]=0;
+
+ Print_At(y,x-1," ");
+ Print_At(y,x+l," ");
+ for(n=0; n [config.d32 | command] [option]\n\n", errstr);
+ printf("Commands:\n");
+ printf("---------\n");
+ printf("/I or /INFO Write DOS/32A Configuration to console\n");
+ printf("/L or /LOCK Lock Configuration in file\n");
+ printf("/U or /UNLOCK Unlock Configuration in file\n\n");
+ printf("Options:\n");
+ printf("--------\n");
+ printf("/Q or /QUIET Quiet mode (partially disables console output)\n");
+ printf("/S or /SILENT Silent mode (totally disables console output)\n");
+ printf("/H or /? This help\n");
+ exit(1);
+ }
+ if( stricmp(argv[1],"/h")==0 ||
+ stricmp(argv[1],"-h")==0 ||
+ stricmp(argv[1],"-?")==0) goto l2;
+
+ strcpy(buf,argv[1]);
+ n=ReadHeader(buf,&id32);
+ if(n==1)
+ {
+ strcat(buf,".exe");
+ n=ReadHeader(buf, &id32);
+ }
+ if(n==1) { printf("%s cannot open file \"%s\"\n", errstr, argv[1]); exit(1); }
+ if(n==2) { printf("%s cannot read from file \"%s\"\n", errstr, argv[1]); exit(1); }
+ if(n==3) { printf("%s unsupported executable format in file \"%s\"\n", errstr, argv[1]); exit(1); }
+ if(id32.id!='23DI') { printf("%s \"%s\" is not a DOS/32A executable\n", errstr, argv[1]); exit(1); }
+ id32_old=id32;
+
+ if(argc>2)
+ {
+ if( stricmp(argv[2],"-lock")==0 ||
+ stricmp(argv[2],"/lock")==0 ||
+ stricmp(argv[2],"-l")==0 ||
+ stricmp(argv[2],"/l")==0)
+ {
+ id32.dos32a_misc2=((id32.dos32a_misc2&0x3F)|0x40);
+ if(WriteHeader(&id32)==0) if(!silent) printf("SS/32A: Configuration has been successfully locked!\n");
+ else printf("SS/32A: Could not lock configuration!\n");
+ CloseFile();
+ exit(0);
+ }
+ else
+ if( stricmp(argv[2],"-unlock")==0 ||
+ stricmp(argv[2],"/unlock")==0 ||
+ stricmp(argv[2],"-u")==0 ||
+ stricmp(argv[2],"/u")==0)
+ {
+ id32.dos32a_misc2=((id32.dos32a_misc2&0x3F)&0xBF);
+ if(WriteHeader(&id32)==0) if(!silent) printf("SS/32A: Configuration has been successfully unlocked!\n");
+ else printf("SS/32A: Could not unlock configuration!\n");
+ CloseFile();
+ exit(0);
+ }
+ else
+ if( stricmp(argv[2],"-info")==0 ||
+ stricmp(argv[2],"/info")==0 ||
+ stricmp(argv[2],"-i")==0 ||
+ stricmp(argv[2],"/i")==0)
+ {
+ ShowHeaderInfo();
+ CloseFile();
+ exit(0);
+ }
+ if((id32.dos32a_misc2&0x40)==0x40)
+ {
+ printf("SS/32A: Configuration in file \"%s\" is locked!\n",buf);
+ exit(0);
+ }
+
+
+ n=open(argv[2],O_RDONLY | O_BINARY);
+ if(n==-1)
+ {
+ strcpy(buf2,argv[2]);
+ strcat(buf2,".d32");
+ n=open(buf2,O_RDONLY | O_BINARY);
+ if(n==-1)
+ {
+ envname=getenv("DOS32A");
+ if(envname!=NULL)
+ {
+ ptr=strchr(envname,' ');
+ if(ptr==NULL) ptr=strchr(envname,0);
+ memset(envbuf,0,256);
+ strncpy(envbuf,envname,(dword)ptr-(dword)envname);
+ strcat(envbuf,"\\D32\\"); strcat(envbuf,buf2);
+ n=open(envbuf,O_RDWR | O_BINARY);
+ }
+ }
+ }
+ if(n!=-1)
+ {
+ read(n,&id32,24);
+ close(n);
+ if(id32.id!='23DI') { printf("%s \"%s\" is not a DOS/32A configuration file\n", errstr, argv[2]); exit(1); }
+ id32.dos32a_misc2=((id32.dos32a_misc2&0x3F) | (id32_old.dos32a_misc2&0xC0));
+ if(WriteHeader(&id32)!=0) { printf("%s could not configure file \"%s\"\n", errstr, buf); exit(1); }
+ CloseFile();
+ if(!silent) printf("SS/32A: File \"%s\" has been successfully configured\n",buf);
+ exit(0);
+ }
+ else
+ {
+ printf("%s cannot open configuration file \"%s\"\n", errstr, argv[2]);
+ exit(1);
+ }
+ }
+ file_type=GetFileType();
+ extn_type=GetExtenderType();
+}
+
+
+
+
+/****************************************************************************/
+void ShowCopyright(int argc, char *argv[])
+{
+ char buf[80];
+ DrawBackground();
+ SetColor(YELLOW);
+ SetBackColor(BLUE);
+ Print_At(0,25,"þþþ Configuration Utility þþþ");
+ SetColor(LIGHTBLUE);
+ Print_At(0,1,"DOS/32A Extender");
+ Print_At(0,66,"Version %s",version);
+ Print_At(24,21,"Copyright (C) 1996-2006 by Narech K.");
+
+ strcpy(buf,argv[1]);
+ strupr(buf);
+ Print_At(24,14,"³");
+ Print_At(24,64,"³");
+ SetColor(LIGHTWHITE);
+ Print_At(24,1,"%.13s",buf);
+
+}
+
+void ShowHeaderInfo()
+{
+ printf("DOS/32A Header Info\n");
+ printf("----------------------------\n");
+ printf("Header signature: %.4s\n",&id32.id);
+ printf("Kernel misc. byte: 0x%02X\n",id32.kernel_misc);
+ printf("Kernel PageTables #: 0x%02X\n",id32.kernel_pagetables);
+ printf("Kernel PhysTables #: 0x%02X\n",id32.kernel_phystables);
+ printf("Kernel Callbacks #: 0x%02X\n",id32.kernel_callbacks);
+ printf("Kernel Selectors #: 0x%04X\n",id32.kernel_selectors);
+ printf("Kernel RM stacks #: 0x%02X\n",id32.kernel_rmstacks);
+ printf("Kernel PM stacks #: 0x%02X\n",id32.kernel_pmstacks);
+ printf("Kernel RM stack size: 0x%04X\n",id32.kernel_rmstacklen);
+ printf("Kernel PM stack size: 0x%04X\n",id32.kernel_pmstacklen);
+ printf("Kernel max. ext. mem: 0x%08X\n",id32.kernel_maxextmem);
+ printf("DOS/32A misc. byte: 0x%02X\n",id32.dos32a_misc);
+ printf("DOS/32A 2nd misc. byte: 0x%02X\n",id32.dos32a_misc2);
+ printf("DOS/32A low buf. size: 0x%04X\n",id32.dos32a_lowbufsize);
+ printf("DOS/32A version #: 0x%04X\n",id32.dos32a_version);
+/*
+ if(id32.dos32a_version>=0x0700)
+ {
+ printf("DOS/32A build name: %s\n",id32.dos32a_buildname);
+ printf("DOS/32A build version: %s\n",id32.dos32a_buildvers);
+ printf("DOS/32A copyright note: %s\n",id32.dos32a_copyright1);
+ printf(" %s\n",id32.dos32a_copyright2);
+ printf("DOS/32A build date: %s\n",id32.dos32a_builddate);
+ printf("DOS/32A build time: %s\n",id32.dos32a_buildtime);
+ }
+*/
+}
+
+void CheckIfLocked()
+{
+ if((id32.dos32a_misc2&0x40)==0x40)
+ {
+ SetColor(LIGHTWHITE);
+ SetBackColor(RED);
+ OpenWindow(10,24,5,32);
+ SetColor(YELLOW);
+ Print_At(11,28,"Configuration is Locked!");
+ SetColor(BLUE);
+ SetBackColor(WHITE);
+ SetBlink(ON);
+ Print_At(13,27," Press any key to exit... ");
+ SetBlink(OFF);
+ GetKey();
+ CloseAllWindows();
+ VideoReset();
+ exit(0);
+ }
+}
+
+void CheckVersion()
+{
+ if(id32.dos32a_version==0)
+ return;
+ if(id32.dos32a_version!=version2)
+ {
+ SetColor(LIGHTWHITE);
+ SetBackColor(RED);
+ OpenWindow(10,18,8,44);
+ SetColor(LIGHTWHITE);
+ Print_At(11,20,"WARNING:");
+ SetColor(YELLOW);
+ Print_At(11,29,"DOS Extender's version does not");
+ Print_At(12,20,"match the version of the Setup Program!!");
+ SetColor(BLUE);
+ SetBackColor(WHITE);
+ SetBlink(ON);
+ Print_At(15,27," Press any key to exit... ");
+ SetBlink(OFF);
+ GetKey();
+ CloseWindow();
+ DiscardExit();
+ }
+}
+
+int CheckIfModified()
+{
+ if( id32.id!=id32_old.id ||
+ id32.kernel_misc!=id32_old.kernel_misc ||
+ id32.kernel_pagetables!=id32_old.kernel_pagetables ||
+ id32.kernel_phystables!=id32_old.kernel_phystables ||
+ id32.kernel_callbacks!=id32_old.kernel_callbacks ||
+ id32.kernel_selectors!=id32_old.kernel_selectors ||
+ id32.kernel_rmstacks!=id32_old.kernel_rmstacks ||
+ id32.kernel_pmstacks!=id32_old.kernel_pmstacks ||
+ id32.kernel_rmstacklen!=id32_old.kernel_rmstacklen ||
+ id32.kernel_pmstacklen!=id32_old.kernel_pmstacklen ||
+ id32.kernel_maxextmem!=id32_old.kernel_maxextmem ||
+ id32.dos32a_misc!=id32_old.dos32a_misc ||
+ (id32.dos32a_misc2&0x3F)!=(id32_old.dos32a_misc2&0x3F) ||
+ id32.dos32a_lowbufsize!=id32_old.dos32a_lowbufsize ||
+ id32.dos32a_version!=id32_old.dos32a_version
+ ) modified_flag=TRUE;
+ else modified_flag=FALSE;
+ return(modified_flag);
+}
+
+void ShowModified()
+{
+ SetColor(LIGHTBLUE);
+ SetBackColor(BLUE);
+ if(CheckIfModified()==TRUE) Print_At(24,0,"*");
+ else Print_At(24,0," ");
+}
+
+
+/****************************************************************************/
+void AskExit()
+{
+ if(CheckIfModified()==TRUE)
+ {
+ SetColor(LIGHTWHITE);
+ SetBackColor(RED);
+ OpenWindow(10,24,5,32);
+ SetColor(YELLOW);
+ Print_At(11,29,"Apply Changes on Exit?");
+ SetColor(BLUE);
+ SetBackColor(WHITE);
+ SetBlink(ON);
+ Print_At(13,32," ");
+ Print_At(13,42," ");
+ SetBlink(OFF);
+ GetKey();
+ }
+ CloseAllWindows();
+ VideoReset();
+ if(keycode!=ESC && keychar!='n' && keychar!='N')
+ if(WriteHeader(&id32)!=0)
+ {
+ printf("%s could not write to file\n" ,errstr);
+ exit(1);
+ }
+ CloseFile();
+ exit(0);
+}
+
+void ApplyExit()
+{
+ CloseAllWindows();
+ VideoReset();
+ if(WriteHeader(&id32)!=0)
+ {
+ printf("%s could not write to file\n", errstr);
+ exit(1);
+ }
+ CloseFile();
+ exit(0);
+}
+
+void DiscardExit()
+{
+ CloseAllWindows();
+ VideoReset();
+ CloseFile();
+ exit(0);
+}
+
+void RestoreDefaults()
+{
+ id32.kernel_misc= 0x3F;
+ id32.kernel_pagetables= 64;
+ id32.kernel_phystables= 2;
+ id32.kernel_callbacks= 16;
+ id32.kernel_selectors= 256;
+ id32.kernel_rmstacks= 8;
+ id32.kernel_pmstacks= 8;
+ id32.kernel_rmstacklen= 0x20;
+ id32.kernel_pmstacklen= 0x20;
+ id32.kernel_maxextmem= 0xFFFFFFFF;
+ id32.dos32a_misc= 0x3F;
+ id32.dos32a_misc2= (id32.dos32a_misc2 & 0xC0) | 0x09;
+ id32.dos32a_lowbufsize= 0x0200;
+}
+
+
+void ValidateConfig()
+{
+ id32.kernel_misc = (id32.kernel_misc & 0xBF);
+ if(id32.kernel_maxextmem>=0x7FFFFFFF) id32.kernel_maxextmem=0xFFFFFFFF;
+ id32.dos32a_lowbufsize = (id32.dos32a_lowbufsize & 0x0FFF);
+ ShowModified();
+}
+
+
+void ShowMemory()
+{
+ memtotal=(
+ (mem_dos32a)+
+ (0x0400)+ // RM INT table
+ (0x0800)+ // PM INT table
+ (id32.dos32a_lowbufsize*16)+ // DOS buffer
+ (id32.kernel_selectors*8)+ // Selectors
+ (id32.kernel_callbacks*25)+ // Callbacks
+ (id32.kernel_rmstacks*id32.kernel_rmstacklen*16)+
+ (id32.kernel_pmstacks*id32.kernel_pmstacklen*16)
+ )/1024;
+
+ SetColor(LIGHTWHITE);
+ SetBackColor(CYAN);
+ Print_At(10,24," ");
+ if(memtotal<1024)
+ Print_At(10,24,"%3dKB",memtotal);
+ else
+ {
+ SetColor(RED);
+ Print_At(10,24," >1MB");
+ SetColor(LIGHTWHITE);
+ }
+
+ if(id32.dos32a_version==0)
+ Print_At(9,26,"N/A");
+ else
+ {
+ Print_At(9,25,"%d.%02d",(id32.dos32a_version&0xFF00)>>8,id32.dos32a_version&0x00FF);
+ if((id32.dos32a_misc2&0x80)!=0x80)
+ /* Professional */
+ //Print_At(9,21,"Pro");
+ ;
+ else
+ /* Beta */
+ Print_At(9,20,"Beta");
+ }
+}
+
+void CreateConfig()
+{
+ int n;
+ char *name;
+ char *ptr;
+ char buf[80];
+
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(10,10,3,60);
+ SetColor(YELLOW);
+ Print_At(10,13," Create Predefined Configuration ");
+ SetColor(LIGHTWHITE);
+ Print_At(11,12,"Enter file name:");
+ name=InputString(11,30,37,cfgfilename);
+ if(name!=NULL && name[0]!=0)
+ {
+ strcpy(buf,name);
+ ptr=(char *)strchr(buf,'.');
+ if(ptr!=NULL) strset(ptr,0);
+ strcpy(cfgfilename,buf);
+ strcat(buf,".D32");
+ n=open(buf,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
+ if(n!=-1)
+ {
+ write(n,&id32,24);
+ close(n);
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ strupr(buf);
+ for(n=0; n<13; n++)
+ {
+ SetPos(24,66+n);
+ PrintC(' ');
+ }
+ Print_At(24,66,"%.13s",buf);
+ }
+ else DiskError();
+ }
+ CloseWindow();
+}
+
+void RestoreConfig()
+{
+ int n;
+ char *envname;
+ char envbuf[256];
+ char *name;
+ char *ptr;
+ char buf[80];
+
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(10,10,3,60);
+ SetColor(YELLOW);
+ Print_At(10,13," Restore Predefined Configuration ");
+ SetColor(LIGHTWHITE);
+ Print_At(11,12,"Enter file name:");
+
+ name=InputString(11,30,37,cfgfilename);
+ if(name!=NULL && name[0]!=0)
+ {
+ strcpy(buf,name);
+ ptr=(char *)strchr(buf,'.');
+ if(ptr!=NULL) strset(ptr,0);
+ strcpy(cfgfilename,buf);
+ strcat(buf,".d32");
+ n=open(buf,O_RDONLY | O_BINARY);
+ if(n==-1)
+ {
+ envname=getenv("DOS32A");
+ if(envname!=NULL)
+ {
+ ptr=strchr(envname,' ');
+ if(ptr==NULL) ptr=strchr(envname,0);
+ memset(envbuf,0,256);
+ strncpy(envbuf,envname,(dword)ptr-(dword)envname);
+ strcat(envbuf,"\\D32\\"); strcat(envbuf,buf);
+ n=open(envbuf,O_RDWR | O_BINARY);
+ }
+ }
+ if(n!=-1)
+ {
+ read(n,&id32,24);
+ close(n);
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ strupr(buf);
+ for(n=0; n<13; n++)
+ {
+ SetPos(24,66+n);
+ PrintC(' ');
+ }
+ Print_At(24,66,"%.13s",buf);
+ }
+ else DiskError();
+ }
+ ValidateConfig();
+ CloseWindow();
+ if(mainmenu_sel==1) ShowBannerStatus();
+
+}
+
+void ClearConfigName()
+{
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ Print_At(24,66," ");
+}
+
+
+void ShowBannerStatus()
+{
+ if((id32.dos32a_misc2&0x80)==0)
+ {
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ Print_At(12,10,"10) Show Copyright Banner at Startup ..................");
+ }
+ else
+ {
+ SetColor(WHITE);
+ SetBackColor(BLUE);
+ Print_At(12,10,"10) Show Copyright Banner at Startup ..................");
+ SetColor(LIGHTWHITE);
+ }
+}
+
+void DiskError()
+{
+ SetColor(LIGHTWHITE);
+ SetBackColor(RED);
+ OpenWindow(10,24,5,32);
+ SetColor(YELLOW);
+ Print_At(11,28,"Error Reading/Writing!");
+ SetColor(BLUE);
+ SetBackColor(WHITE);
+ SetBlink(ON);
+ Print_At(13,26," Press a key to continue... ");
+ SetBlink(OFF);
+ GetKey();
+ CloseWindow();
+ keychar=keycode=0;
+}
+
+
+
+
+
+
+/****************************************************************************/
+void ShowSysInfo()
+{
+ unsigned long n;
+ char *systab[6]={" Clean"," XMS"," VCPI"," DPMI","WinDPMI","Unknown" };
+ char *cputab[6]={ "80386","80486","80586","80686","80786","80886" };
+ char *filetab[5]={ " N/A", "\"LE\"", "\"LX\"", "\"LC\"", "\"PE\"" };
+
+ SetColor(LIGHTWHITE);
+ SetBackColor(CYAN);
+ OpenWindow(2,1,10,30);
+ SetColor(LIGHTGREEN);
+ Print_At(2,4," General Information ");
+
+ SetColor(LIGHTBLUE);
+ Print_At( 3,3,"CPU Type:");
+ Print_At( 4,3,"System Type:");
+ Print_At( 5,3,"Free DOS Memory:");
+ Print_At( 6,3,"Free High Memory:");
+ Print_At( 8,3,"Bound File Type:");
+ if(extn_type==2) Print_At( 9,3,"STUB/32C Version:");
+ else Print_At( 9,3,"DOS/32A Version:");
+ Print_At(10,3,"DOS Memory Required:");
+ SetColor(LIGHTWHITE);
+
+ n=get_cpu_type();
+ if(n-3 > 5)
+ Print_At(3,24,"?????");
+ else
+ Print_At(3,24,cputab[n-3]);
+
+ systype=n=get_sys_type();
+ Print_At(4,22,systab[n]);
+
+ n=get_lomem_size()+get_dosmem_used(mem_dos32a);
+ Print_At(5,21,"%6dKB",(n/1024)+1);
+
+ n=get_himem_size();
+ Print_At(6,21,"%6dKB",n/1024);
+
+ Print_At(8,25,filetab[file_type]);
+
+}
+
+void ShowEnvInfo()
+{
+ char *str;
+ SetColor(LIGHTWHITE);
+ SetBackColor(WHITE);
+ OpenWindow(14,1,3,76);
+ SetColor(LIGHTGREEN);
+ Print_At(14,4," DOS/32A Environment String ");
+ SetColor(LIGHTWHITE);
+ str=getenv("DOS32A");
+ if(str==NULL) Print_At(15,3,"(Not Defined)");
+ else Print_At(15,3,"DOS32A=%.74s",str);
+}
+
+void ShowHelp(int menu, int header)
+{
+ char c;
+ SetColor(LIGHTWHITE);
+ SetBackColor(GREEN);
+ DrawWindow(18,1,5,76);
+ SetColor(LIGHTGREEN);
+ Print_At(18,4," Quick Help ");
+ SetColor(LIGHTWHITE);
+
+ SetPos(19,3);
+ if(menu==0) PrintHelp(mainhlp[header]);
+ if(menu==1) PrintHelp(kernelhlp[header]);
+ if(menu==2) PrintHelp(extenderhlp[header]);
+}
+
+
+
+void ShowMemReq()
+{
+ int n,m;
+
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(6,14,8,52);
+ SetColor(YELLOW);
+ Print_At(6,17," DOS/32A Memory Requirements ");
+ SetColor(LIGHTWHITE);
+
+
+ Print_At( 8,16,"Clean System:");
+ Print_At( 9,16,"XMS System: ");
+ Print_At(10,16,"VCPI System: ");
+ Print_At(11,16,"DPMI System: ");
+
+/*** Clean ***/
+/*** XMS ***/
+ n= (
+ (mem_dos32a)+
+ (0x0400)+ // RM INT table
+ (0x0800)+ // PM INT table
+ (id32.dos32a_lowbufsize*16)+ // DOS buffer
+ (id32.kernel_selectors*8)+ // Selectors
+ (id32.kernel_callbacks*25)+ // Callbacks
+ (id32.kernel_rmstacks*id32.kernel_rmstacklen*16)+
+ (id32.kernel_pmstacks*id32.kernel_pmstacklen*16)
+ )/1024;
+ Print_At( 8,30,"%3dKB",n);
+ Print_At( 9,30,"%3dKB",n);
+
+/*** VCPI ***/
+ m= get_total_mem()/1024;
+ if(id32.kernel_pagetables=3) Print_At(11,40,"(approximately)");
+ else Print_At(11,40,"(advisory info only)");
+
+
+ GetKey();
+ CloseWindow();
+ keychar=keycode=0;
+
+}
+
+#include "menus.c"
+#include "iface.c"
+
diff -uNr a/dos32a/src/ss/main.h b/dos32a/src/ss/main.h
--- a/dos32a/src/ss/main.h false
+++ b/dos32a/src/ss/main.h ef349ba2195e0c9f6432c9f6bd1098e21e21af6d391dc7c33466a2dd8a5fb10cd200ca37f60933fa8ef4c6e20a6639fcd9d97852d81ce1548f87553467b18175
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+
+#define BLACK 0
+#define BLUE 1
+#define GREEN 2
+#define CYAN 3
+#define RED 4
+#define MAGENTA 5
+#define BROWN 6
+#define WHITE 7
+#define LIGHTGREEN 10
+#define LIGHTBLUE 11
+#define LIGHTRED 12
+#define YELLOW 14
+#define LIGHTWHITE 15
+
+#define ESC 0x01
+#define ALT_X 0x2D
+#define TAB 0x0F
+#define ENTER 0x1C
+#define HOME 0x47
+#define END 0x4F
+#define PAGEUP 0x49
+#define PAGEDOWN 0x51
+#define SPACE 0x39
+#define UP 0x48
+#define DOWN 0x50
+#define LEFT 0x4B
+#define RIGHT 0x4D
+#define F1 0x3B
+#define F2 0x3C
+#define F3 0x3D
+#define F4 0x3E
+#define F5 0x3F
+#define F6 0x40
+#define F7 0x41
+#define F8 0x42
+#define F9 0x43
+#define F10 0x44
+
+void Print(char *, ...);
+void Print_At(int, int, char *, ...);
+void CloseAllWindows(void);
+void ShowSysInfo(void);
+void ShowEnvInfo(void);
+void ShowHelp(int, int);
+void ShowCopyright(int, char *[]);
+void AskExit(void);
+void ApplyExit(void);
+void DiscardExit(void);
+char *InputString(int, int, int, char *);
+
+void ShowKernelMenu(void);
+void ShowKernelConfig(void);
+void SelectKernelMenu(void);
+
+void ShowExtenderMemu(void);
+void ShowExtenderConfig(void);
+void SelectExtenderMenu(void);
+
+void ShowMainMenu(void);
+void SelectMainMenu(void);
+unsigned long Input(int, int, int, unsigned long);
+void ShowMemory(void);
+
+
+extern void VideoInit(void);
+extern void VideoReset(void);
+extern void DrawBackground(void);
+extern void SetPos(char, char);
+extern void SetColor(char);
+extern void SetBackColor(char);
+extern void SetBlink(char);
+extern void Prints(char *);
+extern void PrintHelp(char *);
+extern short int GetKey(void);
+extern void OpenWindow(char, char, char, char);
+extern void DrawWindow(char, char, char, char);
+extern void CloseWindow(void);
+extern void ShowCursor(char, char, char);
+extern dword get_cpu_type(void);
+extern dword get_fpu_type(void);
+extern dword get_sys_type(void);
+extern dword get_himem_size(void);
+extern dword get_lomem_size(void);
+extern dword test_cpu(void);
+extern dword get_dosmem_used(int);
+extern dword get_total_mem(void);
+extern dword get_dpmi_bufsize(void);
+extern int ReadHeader(char *, void *);
+extern int WriteHeader(void *);
+extern void CloseFile(void);
+extern int GetFileType(void);
+extern int GetExtenderType(void);
+
+extern char keychar;
+extern char keycode;
+
+
+/************** Variables ***************************************************/
+
+ struct header {
+ dword id;
+ byte kernel_misc;
+ byte kernel_pagetables;
+ byte kernel_phystables;
+ byte kernel_callbacks;
+ word kernel_selectors;
+ byte kernel_rmstacks;
+ byte kernel_pmstacks;
+ word kernel_rmstacklen;
+ word kernel_pmstacklen;
+ dword kernel_maxextmem;
+ byte dos32a_misc;
+ byte dos32a_misc2;
+ word dos32a_lowbufsize;
+ word dos32a_version;
+ word dos32a_reserved;
+
+ char dos32a_buildname[0x09];
+ char dos32a_buildvers[0x10];
+ char dos32a_copyright1[0x24];
+ char dos32a_copyright2[0x15];
+ char dos32a_builddate[0x09];
+ char dos32a_buildtime[0x09];
+ };
+
+ char* version = "9.1.2";
+ int version2 = 0x090C;
+ int changed = 0;
+ int hexmode = 0;
+
+ char startdir[80];
+
+ char cfgfilename[80];
+
+ int systype = 0;
+ int memtotal = 0;
+ int mem_dos32a = 0x75D0;
+ int mem_kernel = 0x27A0;
+ int file_type = 0;
+ int extn_type = 0;
+
+ int silent = FALSE;
+ int modified_flag = FALSE;
+
+ struct header id32;
+ struct header id32_old;
+
+ int mainmenu_sel=0;
+ int mainmenu_xpos[7] = { 36,36,36,36, 36,36,36 };
+ int mainmenu_ypos[7] = { 3, 4, 5, 6, 8, 9, 10 };
+ int mainmenu_xlen[7] = { 40,40,40,40, 40,40,40 };
+
+ int kernelmenu_sel=0;
+ int kernelmenu_xpos[16] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 39,39,39,39, 19 };
+ int kernelmenu_ypos[16] = { 3, 4, 5, 6, 7, 8, 9, 11,12,13,14, 11,12,13,14, 15 };
+ int kernelmenu_xlen[16] = { 62,62,62,62,62,62,62,28,28,28,28, 32,32,32,32, 30 };
+
+ int extendermenu_sel=0;
+ int extendermenu_xpos[13] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18 };
+ int extendermenu_ypos[13] = { 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14, 15 };
+ int extendermenu_xlen[13] = { 62,62,62,62,62,62,62,62,62,62,62,62, 35 };
+
+ char* errstr="SS/32A fatal:";
+
+
+ char* mainhlp[]={
+
+"Configure DOS/32 Advanced built-in DPMI Server.",
+
+
+"Configure DOS/32 Advanced DOS Extender.",
+
+
+"Create that can be used for quick configuration\n\
+of your DOS/32 Advanced programs from the command line.",
+
+
+"Restore previously created .",
+
+
+"Discard the changes and restore old configuration.",
+
+
+"Discard the changes you've made and Exit.",
+
+
+"Apply the changes you've made and Exit."
+
+};
+
+
+ char* kernelhlp[]={
+/*
+"Controls the order of . When set to VCPI/DPMI, the\n\
+DOS Extender will try to detect, and if succeeded initialize a VCPI\n\
+server even though a DPMI host may be present in the system.",
+
+"Controls the order of . When set to XMS/VCPI, the\n\
+DOS Extender will whenever possible favour Clean and XMS systems before\n\
+the slower VCPI/DPMI ones.",
+*/
+".",
+".",
+
+/*
+"Controls whether DOS/32 Advanced DPMI will internally handle and report\n\
+all the exceptions occured during program execution, or the program will\n\
+handle exceptions itself (no INT/EXC buffering and IRQ callbacking).",
+*/
+
+"When turned on, DOS/32 Advanced will use <0th PageTable> which maps first\n\
+4MB (including DOS' 640K), to map the extended memory it allocated. This\n\
+will often reduce the amount of used DOS memory by 4KB (one pagetable).",
+
+
+"When turned on, DOS/32 Advanced will try to allocate extended memory\n\
+from both VCPI and XMS servers, making it possible to have an access to\n\
+all the memory available even when EMM386 with \"RAM nnn\" is installed.",
+
+/*
+"Interrupts in range INT 08-0Fh can be , or .\n\
+DOS/32 Advanced is capable of trapping software INTs, issued to emulate\n\
+IRQs 0-7 (unremapped), and will do so when this option is turned on.",
+
+
+"When turned on, DOS/32 Advanced will check, that extended memory blocks\n\
+allocated with ADPMI are not overwritten or corrupted. An error will be\n\
+reported when a program tries to write to memory it hadn't allocated.",
+*/
+".",
+".",
+
+/*
+"DPMI function 0008h - requires limits greater than 1MB\n\
+to have low 12 bits set. DOS/32 Advanced allows users to manually choose\n\
+whether this check is to be done. Turn it off for DOS/4GW compatibility.",
+*/
+
+"When this option is turned on, DOS/32 Advanced DPMI will ignore calls to\n\
+function 0A00h with pointer in DS:ESI, thus forcing\n\
+programs to not to use DOS/4G API extensions.",
+
+
+"The number of DOS/32 Advanced will allocate and make available\n\
+for program's use. It is not recommended to set this value below 16.",
+
+
+"The number of DOS/32 Advanced will allocate and make available\n\
+for program's use. Note that at least 8 callbacks should be allocated to\n\
+ensure that DOS/32 Advanced itself will operate properly.",
+
+
+"The number of that will be allocated by the DOS\n\
+Extender. Each time the protected mode program needs to call real mode\n\
+INT- or IRQ-handler, a Virtual stack will be used.",
+
+
+"The number of that will be allocated by\n\
+DOS/32 Advanced. Whenever a real mode INT- or IRQ-handler needs to get\n\
+an access to the protected mode code, a Virtual stack will be used.",
+
+
+"Maximum number of that will be allocated (in DOS memory)\n\
+under VCPI. Each PageTable will map 4MB of memory. Note that this is a\n\
+limit, not the actual number of pagetables that will be allocated.",
+
+
+"Maximum number of for physical memory mapping under VCPI.\n\
+If you are sure that an application does not use physical memory mapping\n\
+feature, reset this value to zero.",
+
+
+"The size of one in paragraphs.",
+
+
+"The size of one in paragraphs.",
+
+
+"Amount of that will be allocated and made available for\n\
+program's use. Values greater than 2GB will cause the DOS Extender to\n\
+allocate all the extended memory available in the machine."
+
+};
+
+
+ char* extenderhlp[]={
+
+"When turned off, no warnings will be displayed on the screen. Only fatal\n\
+and run-time errors will be reported to the user.",
+
+
+"When turned on, run-time errors trapped by the DOS Extender will be\n\
+accompanied by a tone from the PC speaker. Note that no sound will be\n\
+generated on warnings and fatal errors.",
+
+
+"When turned on, DOS/32 Advanced will save the whole (all 256 interrupt vectors) on startup and restore it on exit.",
+
+
+"When turned on, the DOS Extender will on exit check and report all the\n\
+ which had been modified (and not restored)\n\
+by a protected mode program.",
+
+
+"Controls how application's are loaded into memory:\n\
+<#1> 16bit/32bit -> Low, High; <#2> 16bit -> Low, High 32bit -> High only\n\
+<#3> 16bit/32bit -> Low only; <#4> 16bit/32bit -> High only (as DOS/4GW)",
+
+
+"Defines that are loaded high (into extended\n\
+memory). Can be either graph (16 bytes), or (4096 bytes). Note\n\
+that Objects loaded low (into DOS memory) are always PARAgraph aligned.",
+
+
+"When turned on, DOS/32 Advanced will set VideoMode 03h (VideoBIOS Text\n\
+Mode) when it encounters a run-time error before writing a report on the\n\
+screen.",
+
+
+"When this option is turned on and running under Windows (v3 and 4+), the\n\
+DOS Extender will switch the DOS Box of the Virtual Machine in which it\n\
+is currently running to .",
+
+
+"When turned on, DOS/32 Advanced will write-protect the first 16 bytes of\n\
+memory starting at absolute address 0:0. Note that 386 debug registers\n\
+DR0-DR3 will be used to trap down writes to the memory at run-time.",
+
+
+"This option controls whether the is to be displayed on\n\
+DOS Extender's startup.",
+
+
+"When turned on, DOS/32 Advanced will search for \"\" string in the\n\
+environment, and if it is defined, configure itself according to it.",
+
+
+"When this option is turned on, the DOS Extender will start in , monitoring its actions as it loads a protected mode application\n\
+and showing additional information in exception listing on exceptions.",
+
+
+"Specifies the size of the (located in conventional\n\
+memory) which will be used by the DOS Extender when transferring data\n\
+from DOS to extended memory and back."
+
+
+};
diff -uNr a/dos32a/src/ss/menus.c b/dos32a/src/ss/menus.c
--- a/dos32a/src/ss/menus.c false
+++ b/dos32a/src/ss/menus.c 18461b05c0b6a850e67b0c94ba7c63cfe386d1d27fb4ab5e042d0a7781dfb7e20e1a3970f77caa5a48c5316cba70ba1511a4d6f8f878b394d370e9cdf16f202a
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+void ShowMainMenu()
+{
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(2,35,10,42);
+ SetColor(YELLOW);
+ Print_At(2,38," Main Menu ");
+ SetColor(LIGHTWHITE);
+
+ Print_At( 3,37,"F1 - Configure DOS/32A DPMI Kernel");
+ Print_At( 4,37,"F2 - Configure DOS/32A DOS Extender");
+ Print_At( 5,37,"F3 - Create Predefined Configuration");
+ Print_At( 6,37,"F4 - Restore Predefined Configuration");
+ Print_At( 8,37,"F5 - Restore Old Values");
+ Print_At( 9,37,"F9 - Discard Changes and Exit");
+ Print_At(10,37,"F10 - Apply Changes and Exit");
+}
+
+
+/*--------------------------------------------------------------------------*/
+void SelectMainMenu()
+{
+ do {
+ ShowModified();
+ ShowHelp(0,mainmenu_sel);
+ ShowCursor( mainmenu_ypos[mainmenu_sel],
+ mainmenu_xpos[mainmenu_sel],
+ mainmenu_xlen[mainmenu_sel]);
+ GetKey();
+ ShowCursor( mainmenu_ypos[mainmenu_sel],
+ mainmenu_xpos[mainmenu_sel],
+ mainmenu_xlen[mainmenu_sel]);
+
+ if(keycode==UP) mainmenu_sel--;
+ if(keycode==DOWN) mainmenu_sel++;
+ if(keycode==HOME) mainmenu_sel=0;
+ if(keycode==END) mainmenu_sel=6;
+ if(keycode==PAGEUP) mainmenu_sel=0;
+ if(keycode==PAGEDOWN) mainmenu_sel=6;
+
+ if(keycode==F1) { mainmenu_sel=0; break; }
+ if(keycode==F2) { mainmenu_sel=1; break; }
+ if(keycode==F3) { mainmenu_sel=2; break; }
+ if(keycode==F4) { mainmenu_sel=3; break; }
+ if(keycode==F5) { mainmenu_sel=4; break; }
+ if(keycode==F6) { RestoreDefaults(); ClearConfigName(); ShowMemory(); }
+ if(keycode==F7) { ValidateConfig(); ShowMemory(); }
+ if(keycode==F8) { ShowMemReq(); ShowMemory(); }
+ if(keycode==F9) { mainmenu_sel=5; break; }
+ if(keycode==F10) { mainmenu_sel=6; break; }
+
+ if(mainmenu_sel<0) mainmenu_sel=0;
+ if(mainmenu_sel>6) mainmenu_sel=6;
+ } while(keycode!=ESC && keycode!=ALT_X && keycode!=ENTER);
+ if(keycode==ESC || keycode==ALT_X) AskExit();
+}
+
+
+
+
+
+/****************************************************************************/
+void ShowKernelMenu()
+{
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(2,8,15,64);
+ SetColor(YELLOW);
+ Print_At(2,11," DPMI Kernel Configuration ");
+ SetColor(LIGHTWHITE);
+
+ SetColor(WHITE);
+ Print_At( 3,10,"1) VCPI/DPMI Detection Order ....................");
+ Print_At( 4,10,"2) XMS/VCPI Detection Order .....................");
+ SetColor(LIGHTWHITE);
+ Print_At( 5,10,"3) VCPI SmartPage Allocation Mode .....................");
+ Print_At( 6,10,"4) VCPI+XMS Allocation Scheme .........................");
+ SetColor(WHITE);
+ Print_At( 7,10,"5) Trap and Report Emulated IRQs ......................");
+ Print_At( 8,10,"6) Extended Memory Blocks Checking ....................");
+ SetColor(LIGHTWHITE);
+ Print_At( 9,10,"7) Ignore DOS/4G API Extension Calls ..................");
+ Print_At(11,10,"Selectors:");
+ Print_At(12,10,"Callbacks:");
+ Print_At(13,10,"RMode Stacks:");
+ Print_At(14,10,"PMode Stacks:");
+ Print_At(11,40,"VCPI PageTables:");
+ Print_At(12,40,"VCPI PhysTables:");
+ Print_At(13,40,"RMode Stack Length:");
+ Print_At(14,40,"PMode Stack Length:");
+ Print_At(15,20,"Extended Memory: (Bytes)");
+
+ do
+ {
+ SelectKernelMenu();
+ if(keycode!=ESC && keycode!=F1 && keycode!=F2)
+ switch(kernelmenu_sel)
+ {
+ case 0: id32.kernel_misc^=0x01; break;
+ case 1: id32.kernel_misc^=0x02; break;
+ case 2: id32.kernel_misc^=0x04; break;
+ case 3: id32.kernel_misc^=0x08; break;
+ case 4: id32.kernel_misc^=0x10; break;
+ case 5: id32.kernel_misc^=0x20; break;
+ case 6: id32.kernel_misc^=0x80; break;
+ case 7: id32.kernel_selectors=Input(11,29,6,id32.kernel_selectors); break;
+ case 8: id32.kernel_callbacks=Input(12,29,6,id32.kernel_callbacks); break;
+ case 9: id32.kernel_rmstacks=Input(13,29,6,id32.kernel_rmstacks); break;
+ case 10: id32.kernel_pmstacks=Input(14,29,6,id32.kernel_pmstacks); break;
+ case 11: id32.kernel_pagetables=Input(11,63,6,id32.kernel_pagetables); break;
+ case 12: id32.kernel_phystables=Input(12,63,6,id32.kernel_phystables); break;
+ case 13: id32.kernel_rmstacklen=Input(13,63,6,id32.kernel_rmstacklen); break;
+ case 14: id32.kernel_pmstacklen=Input(14,63,6,id32.kernel_pmstacklen); break;
+ case 15:
+ if(hexmode==0) id32.kernel_maxextmem=Input(15,38,10,id32.kernel_maxextmem);
+ else id32.kernel_maxextmem=Input(15,40,8,id32.kernel_maxextmem);
+ break;
+ }
+ }
+ while(keycode!=ESC && keycode!=F1 && keycode!=F2);
+ CloseWindow();
+}
+
+
+/*--------------------------------------------------------------------------*/
+void ShowKernelConfig()
+{
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+
+// if(id32.kernel_misc&0x01) Print_At(3,59," VCPI/DPMI");else Print_At(3,59," DPMI/VCPI");
+
+// if(id32.kernel_misc&0x02) Print_At(4,60," XMS/VCPI");else Print_At(4,60," VCPI/XMS");
+
+ SetColor(WHITE);
+ Print_At(3,60," reserved");
+ Print_At(4,60," reserved");
+ SetColor(LIGHTWHITE);
+
+
+ if(id32.kernel_pagetables==0 && !(id32.kernel_misc&0x04)) { SetColor(LIGHTRED); SetBlink(1); }
+ if(id32.kernel_misc&0x04) Print_At(5,65,". ON");else Print_At(5,65," OFF");
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_misc&0x08) Print_At(6,65,". ON");else Print_At(6,65," OFF");
+
+ SetColor(WHITE);
+ Print_At(7,60," reserved");
+ Print_At(8,60," reserved");
+ SetColor(LIGHTWHITE);
+
+ if(id32.kernel_misc&0x80) Print_At(9,65,". ON");else Print_At(9,65," OFF");
+
+ if(hexmode==0)
+ {
+ if(id32.kernel_selectors<16) SetColor(YELLOW);
+ if(id32.kernel_selectors==0) { SetColor(LIGHTRED); SetBlink(1); }
+ if(id32.kernel_selectors>8176) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(11,27,"%8d",id32.kernel_selectors);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_callbacks<8) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(12,27,"%8d",id32.kernel_callbacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_rmstacks<2) SetColor(YELLOW);
+ if(id32.kernel_rmstacks==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(13,27,"%8d",id32.kernel_rmstacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_pmstacks<2) SetColor(YELLOW);
+ if(id32.kernel_pmstacks==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(14,27,"%8d",id32.kernel_pmstacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_maxextmem>0x7FFFFFFF) Print_At(15,40," All");
+ else if(id32.kernel_maxextmem==0) Print_At(15,40," None");
+ else Print_At(15,38,"%10d",id32.kernel_maxextmem);
+
+ if(id32.kernel_pagetables>64) SetColor(YELLOW);
+ if(id32.kernel_pagetables==0 && !(id32.kernel_misc&0x04)) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(11,61,"%8d",id32.kernel_pagetables);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ Print_At(12,61,"%8d",id32.kernel_phystables);
+
+ if(id32.kernel_rmstacklen<0x10) SetColor(YELLOW);
+ if(id32.kernel_rmstacklen==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(13,61,"%8d",id32.kernel_rmstacklen);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_pmstacklen<0x10) SetColor(YELLOW);
+ if(id32.kernel_pmstacklen==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(14,61,"%8d",id32.kernel_pmstacklen);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ }
+ else
+ {
+
+ if(id32.kernel_selectors<16) SetColor(YELLOW);
+ if(id32.kernel_selectors==0) { SetColor(LIGHTRED); SetBlink(1); }
+ if(id32.kernel_selectors>8176) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(11,27,"%7Xh",id32.kernel_selectors);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_callbacks<8) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(12,27,"%7Xh",id32.kernel_callbacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_rmstacks<2) SetColor(YELLOW);
+ if(id32.kernel_rmstacks==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(13,27,"%7Xh",id32.kernel_rmstacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_pmstacks<2) SetColor(YELLOW);
+ if(id32.kernel_pmstacks==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(14,27,"%7Xh",id32.kernel_pmstacks);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_maxextmem>0x7FFFFFFF) Print_At(15,40," All");
+ else if(id32.kernel_maxextmem==0) Print_At(15,40," None");
+ else Print_At(15,38," %8Xh",id32.kernel_maxextmem);
+
+ if(id32.kernel_pagetables>64) SetColor(YELLOW);
+ if(id32.kernel_pagetables==0 && !(id32.kernel_misc&0x04)) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(11,61,"%7Xh",id32.kernel_pagetables);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ Print_At(12,61,"%7Xh",id32.kernel_phystables);
+
+ if(id32.kernel_rmstacklen<0x10) SetColor(YELLOW);
+ if(id32.kernel_rmstacklen==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(13,61,"%7Xh",id32.kernel_rmstacklen);
+ SetColor(LIGHTWHITE); SetBlink(0);
+
+ if(id32.kernel_pmstacklen<0x10) SetColor(YELLOW);
+ if(id32.kernel_pmstacklen==0) { SetColor(LIGHTRED); SetBlink(1); }
+ Print_At(14,61,"%7Xh",id32.kernel_pmstacklen);
+ SetColor(LIGHTWHITE); SetBlink(0);
+ }
+ SetColor(LIGHTBLUE);
+ if((id32.kernel_misc&0x01)!=(id32_old.kernel_misc&0x01)) Print_At(3,69,"*");else Print_At(3,69," ");
+ if((id32.kernel_misc&0x02)!=(id32_old.kernel_misc&0x02)) Print_At(4,69,"*");else Print_At(4,69," ");
+ if((id32.kernel_misc&0x04)!=(id32_old.kernel_misc&0x04)) Print_At(5,69,"*");else Print_At(5,69," ");
+ if((id32.kernel_misc&0x08)!=(id32_old.kernel_misc&0x08)) Print_At(6,69,"*");else Print_At(6,69," ");
+ if((id32.kernel_misc&0x10)!=(id32_old.kernel_misc&0x10)) Print_At(7,69,"*");else Print_At(7,69," ");
+ if((id32.kernel_misc&0x20)!=(id32_old.kernel_misc&0x20)) Print_At(8,69,"*");else Print_At(8,69," ");
+ if((id32.kernel_misc&0x80)!=(id32_old.kernel_misc&0x80)) Print_At(9,69,"*");else Print_At(9,69," ");
+ if((id32.kernel_selectors)!=(id32_old.kernel_selectors)) Print_At(11,35,"*");else Print_At(11,35," ");
+ if((id32.kernel_callbacks)!=(id32_old.kernel_callbacks)) Print_At(12,35,"*");else Print_At(12,35," ");
+ if((id32.kernel_rmstacks)!=(id32_old.kernel_rmstacks)) Print_At(13,35,"*");else Print_At(13,35," ");
+ if((id32.kernel_pmstacks)!=(id32_old.kernel_pmstacks)) Print_At(14,35,"*");else Print_At(14,35," ");
+ if((id32.kernel_pagetables)!=(id32_old.kernel_pagetables)) Print_At(11,69,"*");else Print_At(11,69," ");
+ if((id32.kernel_phystables)!=(id32_old.kernel_phystables)) Print_At(12,69,"*");else Print_At(12,69," ");
+ if((id32.kernel_rmstacklen)!=(id32_old.kernel_rmstacklen)) Print_At(13,69,"*");else Print_At(13,69," ");
+ if((id32.kernel_pmstacklen)!=(id32_old.kernel_pmstacklen)) Print_At(14,69,"*");else Print_At(14,69," ");
+ if((id32.kernel_maxextmem)!=(id32_old.kernel_maxextmem)) Print_At(15,48,"*");else Print_At(15,48," ");
+ SetColor(LIGHTWHITE);
+}
+
+
+/*--------------------------------------------------------------------------*/
+void SelectKernelMenu()
+{
+ do {
+ ShowModified();
+ ShowHelp(1,kernelmenu_sel);
+ ShowKernelConfig();
+ ShowCursor( kernelmenu_ypos[kernelmenu_sel],
+ kernelmenu_xpos[kernelmenu_sel],
+ kernelmenu_xlen[kernelmenu_sel]);
+ GetKey();
+ ShowCursor( kernelmenu_ypos[kernelmenu_sel],
+ kernelmenu_xpos[kernelmenu_sel],
+ kernelmenu_xlen[kernelmenu_sel]);
+// CloseWindow();
+
+ if(keychar>'0' && keychar<'8') kernelmenu_sel=keychar-'1';
+ if(keycode==F3) CreateConfig();
+ if(keycode==F4) RestoreConfig();
+ if(keycode==F5) { id32=id32_old; ClearConfigName(); }
+ if(keycode==F6) { RestoreDefaults(); ClearConfigName(); }
+ if(keycode==F8) ShowMemReq();
+ if(keycode==UP) kernelmenu_sel--;
+ if(keycode==DOWN) kernelmenu_sel++;
+ if(keycode==HOME) kernelmenu_sel=0;
+ if(keycode==END) kernelmenu_sel=16;
+ if(keycode==PAGEUP)
+ if(kernelmenu_sel>11) kernelmenu_sel=11;
+ else if(kernelmenu_sel>7) kernelmenu_sel=7;
+ else if(kernelmenu_sel>0) kernelmenu_sel=0;
+ if(keycode==PAGEDOWN)
+ if(kernelmenu_sel<7) kernelmenu_sel=7;
+ else if(kernelmenu_sel<11) kernelmenu_sel=11;
+ else if(kernelmenu_sel<15) kernelmenu_sel=15;
+
+ if(keycode==LEFT) if(kernelmenu_sel>10 && kernelmenu_sel<15) kernelmenu_sel-=4;
+ if(keycode==RIGHT) if(kernelmenu_sel>6 && kernelmenu_sel<11) kernelmenu_sel+=4;
+
+ if(keycode==TAB) hexmode^=1;
+ if(kernelmenu_sel<0) kernelmenu_sel=0;
+ if(kernelmenu_sel>15) kernelmenu_sel=15;
+ } while(keycode!=ESC && keycode!=F1 && keycode!=F2 && keycode!=ENTER && keycode!=SPACE);
+}
+
+
+
+
+
+/****************************************************************************/
+void ShowExtenderMenu()
+{
+ int n;
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ OpenWindow(2,8,15,64);
+ SetColor(YELLOW);
+ Print_At(2,11," DOS Extender Configuration ");
+ SetColor(LIGHTWHITE);
+
+ Print_At( 3,10," 1) Report Warnings ...................................");
+ Print_At( 4,10," 2) Sound Alert on Run-Time Errors ....................");
+ Print_At( 5,10," 3) Restore Real Mode INTs on Exit ....................");
+ Print_At( 6,10," 4) Report Modified Real Mode INTs ....................");
+ Print_At( 7,10," 5) Object Loading Scheme .............................");
+ Print_At( 8,10," 6) Object Alignment when Loaded High ...............");
+ Print_At( 9,10," 7) Clear Screen on Run-Time Errors ...................");
+ Print_At(10,10," 8) Start Full-Screen under Windows ...................");
+ Print_At(11,10," 9) Install Null-Pointer Protection ...................");
+
+ ShowBannerStatus();
+
+ Print_At(13,10,"11) Configure Using Environment .......................");
+ Print_At(14,10,"12) Start Extender in Verbose Mode ....................");
+ Print_At(15,19,"DOS Transfer Buffer Size: (Bytes)");
+
+ do {
+ SelectExtenderMenu();
+ if(keycode!=ESC && keycode!=F1 && keycode!=F2) switch(extendermenu_sel) {
+ case 0: id32.dos32a_misc^=0x01; break;
+ case 1: id32.dos32a_misc^=0x02; break;
+ case 2: id32.dos32a_misc^=0x04; break;
+ case 3: id32.dos32a_misc^=0x08; break;
+ case 4: { n=(id32.dos32a_misc&0x30)>>4; n=(n+1)&0x03;
+ id32.dos32a_misc=((id32.dos32a_misc&0xCF)|(n<<4)); } break;
+ case 5: id32.dos32a_misc2^=0x04; break;
+ case 6: id32.dos32a_misc^=0x40; break;
+ case 7: id32.dos32a_misc2^=0x02; break;
+ case 8: id32.dos32a_misc^=0x80; break;
+ case 9: if((id32.dos32a_misc2&0x80)==0) id32.dos32a_misc2^=0x08; break;
+ case 10: id32.dos32a_misc2^=0x01; break;
+ case 11: id32.dos32a_misc2^=0x10; break;
+ case 12: id32.dos32a_lowbufsize=
+ Input(15,46,6,id32.dos32a_lowbufsize<<4)>>4;
+ if(id32.dos32a_lowbufsize>0x0FFF) id32.dos32a_lowbufsize=0x0FFF;
+ break;
+ }
+ } while(keycode!=ESC && keycode!=F1 && keycode!=F2);
+ CloseWindow();
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+void ShowExtenderConfig()
+{
+ int n;
+ SetColor(LIGHTWHITE);
+ SetBackColor(BLUE);
+ if(id32.dos32a_misc&0x01) Print_At(3,65,". ON");else Print_At(3,65," OFF");
+ if(id32.dos32a_misc&0x02) Print_At(4,65,". ON");else Print_At(4,65," OFF");
+ if(id32.dos32a_misc&0x04) Print_At(5,65,". ON");else Print_At(5,65," OFF");
+ if(id32.dos32a_misc&0x08) Print_At(6,65,". ON");else Print_At(6,65," OFF");
+ Print_At(7,65,". #%d",((id32.dos32a_misc&0x30)>>4)+1);
+ if(id32.dos32a_misc2&0x04) Print_At(8,64," PAGE");else Print_At(8,64," PARA");
+ if(id32.dos32a_misc&0x40) Print_At(9,65,". ON");else Print_At(9,65," OFF");
+ if(id32.dos32a_misc2&0x02) Print_At(10,65,". ON");else Print_At(10,65," OFF");
+ if(id32.dos32a_misc&0x80) Print_At(11,65,". ON");else Print_At(11,65," OFF");
+ if((id32.dos32a_misc2&0x80)==0)
+ {
+ if(id32.dos32a_misc2&0x08) Print_At(12,65,". ON");else Print_At(12,65," OFF");
+ }
+ else
+ {
+ SetColor(WHITE);
+ if(id32.dos32a_misc2&0x08) Print_At(12,65,". ON");else Print_At(12,65," OFF");
+ SetColor(LIGHTWHITE);
+ }
+ if(id32.dos32a_misc2&0x01) Print_At(13,65,". ON");else Print_At(13,65," OFF");
+ if(id32.dos32a_misc2&0x10) Print_At(14,65,". ON");else Print_At(14,65," OFF");
+
+ if(((id32.dos32a_lowbufsize<<4)&0xFFFF)<4096) SetColor(YELLOW);
+ if(((id32.dos32a_lowbufsize<<4)&0xFFFF)<1024) { SetColor(LIGHTRED); SetBlink(1); }
+ if(hexmode==0) Print_At(15,44,"%8d",(id32.dos32a_lowbufsize<<4)&0xFFFF);
+ else Print_At(15,44,"%7Xh",(id32.dos32a_lowbufsize<<4)&0xFFFF);
+ SetBlink(0);
+
+ SetColor(LIGHTBLUE);
+ if((id32.dos32a_misc&0x01)!=(id32_old.dos32a_misc&0x01)) Print_At(3,69,"*");else Print_At(3,69," ");
+ if((id32.dos32a_misc&0x02)!=(id32_old.dos32a_misc&0x02)) Print_At(4,69,"*");else Print_At(4,69," ");
+ if((id32.dos32a_misc&0x04)!=(id32_old.dos32a_misc&0x04)) Print_At(5,69,"*");else Print_At(5,69," ");
+ if((id32.dos32a_misc&0x08)!=(id32_old.dos32a_misc&0x08)) Print_At(6,69,"*");else Print_At(6,69," ");
+ if((id32.dos32a_misc&0x30)!=(id32_old.dos32a_misc&0x30)) Print_At(7,69,"*");else Print_At(7,69," ");
+ if((id32.dos32a_misc2&0x04)!=(id32_old.dos32a_misc2&0x04)) Print_At(8,69,"*");else Print_At(8,69," ");
+ if((id32.dos32a_misc&0x40)!=(id32_old.dos32a_misc&0x40)) Print_At(9,69,"*");else Print_At(9,69," ");
+ if((id32.dos32a_misc2&0x02)!=(id32_old.dos32a_misc2&0x02)) Print_At(10,69,"*");else Print_At(10,69," ");
+ if((id32.dos32a_misc&0x80)!=(id32_old.dos32a_misc&0x80)) Print_At(11,69,"*");else Print_At(11,69," ");
+ if((id32.dos32a_misc2&0x08)!=(id32_old.dos32a_misc2&0x08)) Print_At(12,69,"*");else Print_At(12,69," ");
+ if((id32.dos32a_misc2&0x01)!=(id32_old.dos32a_misc2&0x01)) Print_At(13,69,"*");else Print_At(13,69," ");
+ if((id32.dos32a_misc2&0x10)!=(id32_old.dos32a_misc2&0x10)) Print_At(14,69,"*");else Print_At(14,69," ");
+ if((id32.dos32a_lowbufsize)!=(id32_old.dos32a_lowbufsize)) Print_At(15,52,"*");else Print_At(15,52," ");
+ SetColor(LIGHTWHITE);
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+void SelectExtenderMenu()
+{
+ int n;
+
+ do {
+ ShowModified();
+ ShowHelp(2,extendermenu_sel);
+ ShowExtenderConfig();
+ ShowCursor( extendermenu_ypos[extendermenu_sel],
+ extendermenu_xpos[extendermenu_sel],
+ extendermenu_xlen[extendermenu_sel]);
+ GetKey();
+ ShowCursor( extendermenu_ypos[extendermenu_sel],
+ extendermenu_xpos[extendermenu_sel],
+ extendermenu_xlen[extendermenu_sel]);
+// CloseWindow();
+
+ if(keychar>'0' && keychar<='9') extendermenu_sel=keychar-'1';
+ if(keychar=='0' || keychar=='a' || keychar=='A') extendermenu_sel=9;
+ if(keychar=='b' || keychar=='B') extendermenu_sel=10;
+ if(keychar=='c' || keychar=='C') extendermenu_sel=11;
+ if(keycode==F3) CreateConfig();
+ if(keycode==F4) RestoreConfig();
+ if(keycode==F5) { id32=id32_old; ClearConfigName(); ShowBannerStatus(); }
+ if(keycode==F6) { RestoreDefaults(); ClearConfigName(); }
+ if(keycode==F8) ShowMemReq();
+ if(keycode==UP) extendermenu_sel--;
+ if(keycode==DOWN) extendermenu_sel++;
+ if(keycode==HOME) extendermenu_sel=0;
+ if(keycode==END) extendermenu_sel=12;
+ if(keycode==PAGEUP)
+ if(extendermenu_sel>11) extendermenu_sel=11;
+ else if(extendermenu_sel>6) extendermenu_sel=6;
+ else extendermenu_sel=0;
+ if(keycode==PAGEDOWN)
+ if(extendermenu_sel<6) extendermenu_sel=6;
+ else if(extendermenu_sel<11) extendermenu_sel=11;
+ else extendermenu_sel=12;
+ if(keycode==TAB) hexmode^=1;
+ if(extendermenu_sel<0) extendermenu_sel=0;
+ if(extendermenu_sel>12) extendermenu_sel=12;
+ } while(keycode!=ESC && keycode!=F1 && keycode!=F2 && keycode!=ENTER && keycode!=SPACE);
+}
+
diff -uNr a/dos32a/src/ss/setup.asm b/dos32a/src/ss/setup.asm
--- a/dos32a/src/ss/setup.asm false
+++ b/dos32a/src/ss/setup.asm 435e4e724785e9c07ce7f45f78c638946cb524cdb209246ac5a21e6168e8d29d46110f4795bbf4d457b6f056b7c7a156d49c43c2e0b4be028516143725d6272a
@@ -0,0 +1,1058 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .486p
+ .MODEL flat
+ LOCALS
+ NOJUMPS
+
+
+PUBLIC VideoInit_, VideoReset_
+PUBLIC DrawBackground_
+PUBLIC GetKey_
+PUBLIC Printc_, Prints_, SetPos_, SetColor_, SetBackColor_, SetBlink_
+PUBLIC OpenWindow_, DrawWindow_, CloseWindow_, ShowCursor_, PrintHelp_
+PUBLIC get_himem_size_, get_lomem_size_, get_cpu_type_
+PUBLIC get_sys_type_, get_dosmem_used_, get_total_mem_, get_dpmi_bufsize_
+PUBLIC ReadHeader_, WriteHeader_, CloseFile_, GetFileType_, GetExtenderType_
+
+PUBLIC _keychar, _keycode
+
+EXTRN _mem_dos32a : dword
+EXTRN _mem_kernel : dword
+
+include stddef.inc
+
+.CODE
+
+
+GetFileType_:
+ pushad
+ mov esi,offs @file_buffer
+ mov ax,4200h
+ mov bx,_file_handle
+ xor ecx,ecx
+ movzx edx,wptr [esi+3Ch]
+ int 21h
+ jc @@t_no
+
+ mov ah,3Fh
+ mov bx,_file_handle
+ mov ecx,0004h
+ mov edx,offs @file_buffer+80h
+ int 21h
+ jc @@t_no
+
+ cmp wptr [edx],'EL'
+ jz @@t_le
+ cmp wptr [edx],'XL'
+ jz @@t_lx
+ cmp wptr [edx],'CL'
+ jz @@t_lc
+ cmp wptr [edx],'EP'
+ jz @@t_pe
+
+@@t_no: popad ; not bound
+ xor eax,eax
+ ret
+@@t_le: popad ; LE - style
+ mov eax,1
+ ret
+@@t_lx: popad ; LX - style
+ mov eax,2
+ ret
+@@t_lc: popad ; LC - style
+ mov eax,3
+ ret
+@@t_pe: popad ; PE - style
+ mov eax,4
+ ret
+
+
+;=============================================================================
+GetExtenderType_:
+ pushad
+ mov esi,_buffer
+ mov ax,4200h
+ mov bx,_file_handle
+ xor ecx,ecx
+ xor edx,edx
+ int 21h
+ jc @@0
+
+ mov ax,3F00h
+ mov bx,_file_handle
+ mov ecx,0100h
+ mov edx,_buffer
+ int 21h
+ jc @@0
+
+ mov ebx,_buffer
+ mov esi,offs _str_dos32a
+ lea edi,[ebx+007Ch]
+ call check_string
+ jnc @@1
+ mov ebx,_buffer
+ mov esi,offs _str_dos32a
+ lea edi,[ebx+009Ch]
+ call check_string
+ jnc @@1
+
+ mov ebx,_buffer
+ mov esi,offs _str_stub32c
+ lea edi,[ebx+004Ch]
+ call check_string
+ jnc @@2
+ mov ebx,_buffer
+ mov esi,offs _str_stub32c
+ lea edi,[ebx+006Ch]
+ call check_string
+ jnc @@2
+
+
+@@0: popad
+ xor eax,eax ; N/A
+ ret
+@@1: popad
+ mov eax,1 ; DOS/32A
+ ret
+@@2: popad
+ mov eax,2 ; STUB/32C
+ ret
+
+
+check_string:
+ pushad
+@@0: mov al,[esi]
+ test al,al
+ jz @@ok
+ cmp al,[edi]
+ jnz @@err
+ inc esi
+ inc edi
+ jmp @@0
+@@ok: popad
+ clc
+ ret
+@@err: popad
+ stc
+ ret
+
+
+;=============================================================================
+ReadHeader_:
+ pushad
+
+ mov ebp,edx
+ mov edx,eax
+ mov ax,3D02h
+ int 21h
+ jc @@err1
+ mov _file_handle,ax
+
+ mov ah,3Fh
+ mov bx,_file_handle
+ mov ecx,0040h
+ mov edx,offs @file_buffer
+ int 21h
+ jc @@err2
+
+ mov esi,offs @file_buffer
+ cmp wptr [esi+00h],'ZM'
+ jnz @@err3
+ mov ax,4200h
+ mov bx,_file_handle
+ xor ecx,ecx
+ movzx edx,wptr [esi+08h]
+ shl edx,4
+ int 21h
+ jc @@err2
+
+ mov ah,3Fh
+ mov bx,_file_handle
+ mov ecx,0080h
+ mov edx,ebp
+ int 21h
+ jc @@err2
+
+ popad
+ xor eax,eax
+ ret
+@@err1: popad
+ mov eax,1 ; error opening
+ ret
+@@err2: popad
+ mov eax,2 ; error reading
+ ret
+@@err3: popad
+ mov eax,3 ; invalid header type (not MZ exec)
+ ret
+
+
+
+;=============================================================================
+WriteHeader_:
+ pushad
+ push eax
+ mov esi,offs @file_buffer
+ mov ax,4200h
+ mov bx,_file_handle
+ xor ecx,ecx
+ movzx edx,wptr [esi+08h]
+ shl edx,4
+ int 21h
+ pop edx
+ jc @@err1
+ mov ah,40h
+ mov bx,_file_handle
+ mov ecx,0080h
+ int 21h
+ jc @@err1
+ popad
+ xor eax,eax
+ ret
+@@err1: popad
+ mov eax,1 ; error writing
+ ret
+
+CloseFile_:
+ pushad
+ mov bx,_file_handle
+ mov ah,3Eh
+ int 21h
+ popad
+ ret
+
+
+
+
+
+;=============================================================================
+ Align 4
+get_dosmem_used_:
+ pushad
+ mov ebp,eax ; preserve EAX
+ mov ax,0FF89h
+ int 21h
+ cmp eax,'ID32'
+ jz @@l1
+ popad
+ xor eax,eax
+ ret
+
+@@l1: pushad
+ mov ax,0FF8Ah
+ int 21h
+ cmp eax,'ID32'
+ jz @@l2
+ popad
+ popad
+ xor eax,eax
+ ret
+
+@@l2: cmp ch,03h ; if SYS = DPMI
+ popad
+ jnz @@l3
+ sub ebp,_mem_kernel ; kernel has been removed
+
+@@l3: mov eax,ebp ; DOS/32A exec size
+ add eax,0080h ; + DTA and Mouse_Buf
+ add eax,0400h ; + RM IDT
+ add eax,ecx ; + DOS Transfer Buffer
+
+ mov ebp,eax ; D32A API get ptr to client
+ mov ax,0FF8Eh
+ int 21h
+ movzx eax,word ptr gs:[edi+08h] ; get size of DPMI required buffer
+ shl eax,4
+ add eax,ebp
+
+ test word ptr gs:[edi+06h],0001h ; check if STUB/32C is resident
+ jz @@done
+ add eax,2048 ; count in size of STUB/32C
+
+@@done: mov [esp+1Ch],eax
+ popad
+ ret
+
+
+
+;=============================================================================
+get_himem_size_:
+ mov ax,0FF90h
+ int 21h
+ ret
+
+
+;=============================================================================
+get_lomem_size_:
+ mov ax,0FF94h
+ int 21h
+ ret
+
+
+;=============================================================================
+get_total_mem_:
+ pushad
+ xor eax,eax
+ mov al,30h
+ out 70h,al
+ in al,71h
+ mov ah,al
+ mov al,31h
+ out 70h,al
+ in al,71h
+ xchg al,ah
+ mov [esp+1Ch],eax
+ popad
+ ret
+
+
+;=============================================================================
+get_dpmi_bufsize_:
+ pushad
+ mov ax,0FF8Eh
+ int 21h
+ movzx eax,word ptr gs:[edi+08h] ; get size of DPMI required buffer
+ shl eax,4
+ mov [esp+1Ch],eax
+ popad
+ ret
+
+
+
+;=============================================================================
+; Get CPU type: 80386, 80486, PENTIUM, ...
+;
+ Align 4
+get_cpu_type_:
+ pushad
+ mov ax,0400h ; DPMI get CPU
+ int 31h
+ movzx eax,cl
+ mov [esp+1Ch],eax
+ cmp cl,3
+ ja @@1
+ popad
+ ret
+
+@@1: pushfd
+ cli
+ pushfd
+ pop eax
+ mov edx,eax
+ xor eax,00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ xor eax,edx
+ jne @@l4
+ jmp @@x
+@@l4: xor eax,eax
+ db 0Fh, 0A2h
+ mov dword ptr [esp+1Ch+4],5 ; CPU is 586
+ cmp eax,1 ; check CPUID level
+ jb @@x ; if level 1 not supported, exit
+ mov eax,1
+ db 0Fh, 0A2h
+ mov al,ah
+ and eax,0Fh
+ mov [esp+1Ch+4],eax
+@@x: sti
+ popfd
+ popad
+ ret
+
+
+;=============================================================================
+; Get SYSTEM type: raw, XMS, VCPI, DPMI
+;
+ Align 4
+get_sys_type_:
+ pushad
+ mov ax,1600h
+ int 2Fh
+ test al,al
+ jz @@0
+ cmp al,80h
+ jz @@0
+ mov ch,4
+ jmp @@1
+
+@@0: mov ax,0FF8Ah
+ push fs
+ int 21h
+ pop fs
+ cmp eax,'ID32'
+ jz @@1
+ mov ch,5
+
+@@1: movzx eax,ch
+ mov [esp+1Ch],eax
+ popad
+ ret
+
+
+
+
+;=============================================================================
+VideoInit_:
+ pushad
+ mov esi,_screen_addr
+ mov edi,_buffer_addr
+ mov ecx,0800h
+ rep movsd
+ call sync_display
+ mov ax,0300h
+ xor ebx,ebx
+ int 10h ; get DOS cursor position
+ mov _old_video_pos,dx
+ mov ax,0200h
+ xor edx,edx
+ int 10h ; set cursor to 0,0 (hide under bkgnd)
+ call set_video_mode_init
+ mov _xpos,0
+ mov _ypos,0
+ mov _color,0Fh
+ popad
+ ret
+
+VideoReset_:
+ pushad
+ call sync_display
+ call set_video_mode_exit
+ mov ax,0200h
+ mov dx,_old_video_pos
+ xor ebx,ebx
+ int 10h
+ mov esi,_buffer_addr
+ mov edi,_screen_addr
+ mov ecx,0800h
+ rep movsd
+ popad
+ ret
+
+set_video_mode_init:
+ pushad
+ mov ah,0Fh
+ int 10h
+ cmp al,03h
+ jnz @@0
+ cmp ah,80
+ jnz @@0
+ cmp bh,00h
+ jnz @@0
+ jmp @@1
+@@0: mov ax,0003h
+ int 10h
+@@1: mov ax,1003h ; toggle blink/background
+ mov bx,0001h
+ int 10h
+; xor eax,eax
+; mov edi,_screen_addr
+; mov ecx,0800h
+; rep stosd
+ popad
+ ret
+set_video_mode_exit:
+ pushad
+ mov ah,0Fh
+ int 10h
+ cmp al,03h
+ jnz @@0
+ cmp ah,80
+ jnz @@0
+ cmp bh,00h
+ jnz @@0
+ jmp @@1
+@@0: mov ax,0003h
+ int 10h
+@@1: mov ax,1003h ; toggle blink/background
+ mov bx,0000h
+ int 10h
+; xor eax,eax
+; mov edi,_screen_addr
+; mov ecx,0800h
+; rep stosd
+ popad
+ ret
+
+DrawBackground_:
+ pushad
+ call sync_display
+ mov edi,_screen_addr
+ mov ecx,80
+ mov ax,1120h
+ rep stosw
+ mov ecx,80*23
+ mov ax,1FB1h
+ rep stosw
+ mov ecx,80
+ mov ax,1120h
+ rep stosw
+ popad
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+GetKey_:
+ pushad
+ xor eax,eax
+ int 16h
+ mov [esp+1Ch],eax
+ mov _keychar,al
+ mov _keycode,ah
+ popad
+ ret
+
+
+Printc_:
+ pushad
+ cmp al,0Ah
+ jz @@1
+ cmp al,0Dh
+ jz @@2
+ mov edi,_screen_addr
+ movzx ebx,_ypos
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ movzx ebx,_xpos
+ lea ebx,[ebx*2]
+ add edi,ebx
+ mov [edi],al
+ inc edi
+ mov al,_color
+ mov [edi],al
+ popad
+ ret
+@@1: mov _xpos,0 ; handle 0Ah
+ popad
+ ret
+@@2: inc _ypos ; handle 0Dh
+ cmp _ypos,25
+ jb @@3
+ mov _ypos,0
+@@3: popad
+ ret
+
+
+
+Prints_:
+ pushad
+ mov esi,eax
+@@loop: mov al,[esi]
+ inc esi
+ test al,al
+ jz @@done
+ call Printc_
+ inc _xpos
+ cmp _xpos,80
+ jae @@1
+ jmp @@loop
+@@1: mov _xpos,0
+ inc _ypos
+ cmp _ypos,25
+ jae @@2
+ jmp @@loop
+@@2: mov _ypos,0
+ jmp @@loop
+@@done: popad
+ ret
+
+SetPos_:
+ pushad
+ mov _xpos,dl
+ mov _ypos,al
+ popad
+ ret
+
+SetColor_:
+ pushad
+ and al,0Fh
+ mov ah,_color
+ and ah,0F0h
+ or al,ah
+ mov _color,al
+ popad
+ ret
+
+SetBackColor_:
+ pushad
+ and al,0Fh
+ mov ah,_color
+ and ah,0Fh
+ shl al,4
+ or al,ah
+ mov _color,al
+ popad
+ ret
+
+
+SetBlink_:
+ pushad
+ and al,01h
+ jnz @@1
+ and _color,7Fh
+ jmp @@done
+@@1: or _color,80h
+@@done: popad
+ ret
+
+ShowCursor_:
+ pushad
+ movzx ebp,_xpos
+ push ebp
+ movzx ebp,_ypos
+ push ebp
+ mov _xpos,dl
+ mov _ypos,al
+ mov ecx,ebx
+ mov edi,_screen_addr
+ movzx ebx,_ypos
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ movzx ebx,_xpos
+ lea ebx,[ebx*2]
+ add edi,ebx
+ inc edi
+@@1: mov al,[edi]
+
+ mov ah,30h
+ cmp al,1Fh
+ jz @@2
+ mov ah,1Fh
+ cmp al,30h
+ jz @@2
+
+ mov ah,37h
+ cmp al,17h
+ jz @@2
+ mov ah,17h
+ cmp al,37h
+ jz @@2
+
+ mov ah,3Ch OR 80h
+ cmp al,1Ch OR 80h
+ jz @@2
+ mov ah,1Ch OR 80h
+ cmp al,3Ch OR 80h
+ jz @@2
+
+ mov ah,3Eh
+ cmp al,1Eh
+ jz @@2
+ mov ah,1Eh
+ cmp al,3Eh
+ jz @@2
+
+ mov ah,3Bh
+ cmp al,1Bh
+ jz @@2
+ mov ah,1Bh
+ cmp al,3Bh
+ jz @@2
+
+@@2: mov [edi],ah
+ add edi,2
+ loop @@1
+ pop eax
+ mov _ypos,al
+ pop eax
+ mov _xpos,al
+ popad
+ ret
+
+
+PrintHelp_:
+ pushad
+ mov esi,eax
+
+@@0: lodsb
+ test al,al
+ jz @@done
+ cmp al,'['
+ jz @@l1on
+ cmp al,']'
+ jz @@l1of
+ cmp al,'<'
+ jz @@l2on
+ cmp al,'>'
+ jz @@l2of
+ cmp al,0Dh
+ jz @@0
+ cmp al,0Ah
+ jnz @@1
+ inc _ypos
+ mov _xpos,3
+ jmp @@0
+@@1: call Printc_
+ inc _xpos
+ jmp @@0
+
+@@done: popad
+ ret
+
+@@l1on: mov al,_color
+ mov _color2,al
+ and al,0F0h
+ or al,004h
+ mov _color,al
+ jmp @@0
+@@l1of: mov al,_color2
+ mov _color,al
+ jmp @@0
+@@l2on: mov al,_color
+ mov _color3,al
+ and al,0F0h
+ or al,00Eh
+ mov _color,al
+ jmp @@0
+@@l2of: mov al,_color3
+ mov _color,al
+ jmp @@0
+
+
+sync_display:
+ push eax edx
+ mov dx,03DAh
+@@1: in al,dx
+ test al,08h
+ jnz @@1
+@@2: in al,dx
+ test al,08h
+ jz @@2
+ pop edx eax
+ ret
+
+
+
+save_window:
+ pushad
+ mov esi,_screen_addr
+ mov ebx,_ywinpos
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add esi,edx
+ mov ebx,_xwinpos
+ lea ebx,[ebx*2]
+ add esi,ebx
+ mov edi,_window_addr
+ mov ecx,_xwinlen
+ mov edx,_ywinlen
+@@1: push esi
+@@2: mov ax,[esi]
+ mov [edi],ax
+ add esi,2
+ add edi,2
+ dec ecx
+ jnz @@2
+ pop esi
+ add esi,80*2
+ mov ecx,_xwinlen
+ dec edx
+ jnz @@1
+ mov eax,_xwinpos
+ mov [edi+0*4],eax
+ mov eax,_ywinpos
+ mov [edi+1*4],eax
+ mov eax,_xwinlen
+ mov [edi+2*4],eax
+ mov eax,_ywinlen
+ mov [edi+3*4],eax
+ add edi,16
+ mov _window_addr,edi
+ popad
+ ret
+
+
+restore_window:
+ call sync_display
+ pushad
+ mov esi,_window_addr
+ sub esi,16
+ mov eax,[esi+0*4]
+ mov _xwinpos,eax
+ mov ebx,[esi+1*4]
+ mov _ywinpos,ebx
+ mov ecx,[esi+2*4]
+ mov _xwinlen,ecx
+ mov edx,[esi+3*4]
+ mov _ywinlen,edx
+ imul ecx,edx
+ add ecx,ecx
+ sub esi,ecx
+ mov _window_addr,esi
+ mov edi,_screen_addr
+ mov ebx,_ywinpos
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ mov ebx,_xwinpos
+ lea ebx,[ebx*2]
+ add edi,ebx
+ mov ecx,_xwinlen
+ mov edx,_ywinlen
+@@1: push edi
+@@2: mov ax,[esi]
+ mov [edi],ax
+ add esi,2
+ add edi,2
+ dec ecx
+ jnz @@2
+ pop edi
+ add edi,80*2
+ mov ecx,_xwinlen
+ dec edx
+ jnz @@1
+ popad
+ ret
+
+
+draw_window:
+ pushad
+ mov edi,_screen_addr
+ mov ebx,_ywinpos
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ mov ebx,_xwinpos
+ lea ebx,[ebx*2]
+ add edi,ebx
+ mov ecx,_xwinlen
+ mov edx,_ywinlen
+@@1: push edi
+@@2: mov [edi],ax
+ add edi,2
+ dec ecx
+ jnz @@2
+ pop edi
+ add edi,80*2
+ mov ecx,_xwinlen
+ dec edx
+ jnz @@1
+
+ mov eax,_xwinpos
+ mov edx,_ywinpos
+ mov _xpos,al
+ mov _ypos,dl
+ mov al, 'É'
+ call Printc_
+ inc _xpos
+ mov ecx,_xwinlen
+ sub ecx,2
+ mov al, 'Í'
+@@3: call Printc_
+ inc _xpos
+ loop @@3
+ mov al, '»'
+ call Printc_
+
+ mov eax,_xwinpos
+ mov edx,_ywinpos
+ inc edx
+ mov _xpos,al
+ mov _ypos,dl
+ mov ecx,_ywinlen
+ sub ecx,2
+ mov al, 'º'
+@@4: call Printc_
+ inc _ypos
+ loop @@4
+ mov al, 'È'
+ call Printc_
+
+ mov eax,_xwinpos
+ mov edx,_ywinpos
+ inc edx
+ dec eax
+ add eax,_xwinlen
+ mov _xpos,al
+ mov _ypos,dl
+ mov ecx,_ywinlen
+ sub ecx,2
+ mov al, 'º'
+@@5: call Printc_
+ inc _ypos
+ loop @@5
+ mov al, '¼'
+ call Printc_
+
+ mov eax,_xwinpos
+ mov edx,_ywinpos
+ inc eax
+ dec edx
+ add edx,_ywinlen
+ mov _xpos,al
+ mov _ypos,dl
+ mov ecx,_xwinlen
+ sub ecx,2
+ mov al, 'Í'
+@@6: call Printc_
+ inc _xpos
+ loop @@6
+
+ mov edi,_screen_addr
+ mov ebx,_ywinpos
+ inc ebx
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ mov ebx,_xwinpos
+ add ebx,_xwinlen
+ lea ebx,[ebx*2]
+ add edi,ebx
+ mov ecx,_ywinlen
+ inc edi
+ mov al,07h
+@@7: mov [edi+0],al
+ mov [edi+2],al
+ add edi,80*2
+ loop @@7
+
+ mov edi,_screen_addr
+ mov ebx,_ywinpos
+ add ebx,_ywinlen
+ lea edx,[ebx*4]
+ add edx,ebx
+ shl edx,5
+ add edi,edx
+ mov ebx,_xwinpos
+ inc ebx
+ inc ebx
+ lea ebx,[ebx*2]
+ add edi,ebx
+ mov ecx,_xwinlen
+ inc edi
+ mov al,07h
+@@8: mov [edi],al
+ add edi,2
+ loop @@8
+
+ popad
+ ret
+
+
+OpenWindow_:
+ pushad
+ inc ebx
+ inc ecx
+ inc ecx
+ mov _xwinpos,edx
+ mov _ywinpos,eax
+ mov _xwinlen,ecx
+ mov _ywinlen,ebx
+ call save_window
+ mov al,20h
+ mov ah,_color
+ dec _xwinlen
+ dec _xwinlen
+ dec _ywinlen
+ call draw_window
+ popad
+ ret
+
+DrawWindow_:
+ pushad
+ inc ebx
+ inc ecx
+ inc ecx
+ mov _xwinpos,edx
+ mov _ywinpos,eax
+ mov _xwinlen,ecx
+ mov _ywinlen,ebx
+ mov al,20h
+ mov ah,_color
+ dec _xwinlen
+ dec _xwinlen
+ dec _ywinlen
+ call draw_window
+ popad
+ ret
+
+CloseWindow_:
+ pushad
+ cmp _window_addr,offs @window_buffer
+ jbe @@done
+ call restore_window
+@@done: popad
+ ret
+
+
+
+
+.DATA
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+_str_dos32a db 'DOS/32A',0
+_str_stub32c db 'STUB/32C',0
+
+_screen_addr dd 000B8000h
+_buffer_addr dd offs @video_buffer
+_window_addr dd offs @window_buffer
+_buffer dd offs @file_buffer
+_old_video_pos dw 0
+_xpos db 0
+_ypos db 0
+_color db 0
+_color2 db 0
+_color3 db 0
+_xwinpos dd 0
+_ywinpos dd 0
+_xwinlen dd 0
+_ywinlen dd 0
+_keychar db 0
+_keycode db 0
+_file_handle dw 0
+
+
+.DATA?
+;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+@video_buffer db 2000h dup(?)
+@window_buffer db 10000h dup(?)
+@file_buffer db 400h dup(?)
+end
diff -uNr a/dos32a/src/stub32a/stub32a.asm b/dos32a/src/stub32a/stub32a.asm
--- a/dos32a/src/stub32a/stub32a.asm false
+++ b/dos32a/src/stub32a/stub32a.asm 840002ba05b31bde2e2b7300af98b246beecdc4cdfd02a6b99799a5371d0d66ff14769344c5a654c62d6de7b9eae0d042a507e56bb80af1fe752fef121bb5ef5
@@ -0,0 +1,250 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .286
+ .MODEL tiny
+ LOCALS
+
+.CODE
+;=============================================================================
+db 'STUB/32A' ,0
+db 'Copyright (C) 1996-2006 by Narech K.' ,0
+db ??date ,0
+db ??time ,0
+
+
+start: sti
+ push cs
+ pop ds
+ mov ax,es
+ mov bx,ss
+ mov _psp,ax
+ sub bx,ax
+ mov ax,sp
+ shr ax,4
+ add bx,ax
+ inc bx
+ mov ah,4Ah
+ int 21h
+ jc err1
+
+@@1: mov es,es:[002Ch] ; get environment
+ call make_cmd
+ mov bp,0090h
+ call exec
+ call find_path1
+ call find_path2
+
+err0: mov ah,09h
+ mov dx,offset str1
+ mov byte ptr byte0,22h
+ int 21h
+err1: mov ax,4CFFh
+ int 21h
+
+
+;-----------------------------------------------------------------------------
+make_cmd:
+ push ds es
+ push ss
+ pop ds
+ xor ax,ax
+ xor di,di
+ mov cx,7FFFh
+@@1: repne scasb
+ scasb
+ jnz @@1
+ inc di
+ inc di
+ mov si,di
+ repne scasb
+ sub di,si
+ mov cx,di
+ mov ax,di
+ mov di,0011h
+ push ss
+ push es
+ pop ds
+ pop es
+ rep movsb
+ mov byte ptr es:[di-1],20h
+ mov ds,cs:_psp
+ mov si,0081h
+ mov cl,[si-1]
+ add al,cl
+ inc cx
+ mov es:[0010h],al
+ rep movsb
+ pop es ds
+ ret
+
+
+;-----------------------------------------------------------------------------
+find_path1:
+ xor ax,ax
+ xor di,di
+@@1: mov cx,0007h
+ mov si,offset path1
+ rep cmpsb
+ jz @@2
+ mov cl,0FFh
+ repne scasb
+ cmp al,es:[di]
+ jnz @@1
+ ret
+@@2: mov al,20h ; skip leading spaces
+ mov cl,0FFh
+ rep scasb
+ cmp word ptr es:[di],'\:'
+ jz @@3
+ ret
+@@3: dec di
+ mov bp,0090h
+@@loop: mov al,es:[di]
+ test al,al
+ jz @@4
+ inc di
+ cmp al,20h
+ jz @@4
+ mov [bp],al
+ inc bp
+ jmp @@loop
+@@4: mov byte ptr [bp],'\'
+ mov word ptr [bp+1],'IB'
+ mov word ptr [bp+3],'WN'
+ add bp,5
+ jmp exec
+
+
+
+
+;-----------------------------------------------------------------------------
+find_path2:
+ xor ax,ax
+ xor di,di
+@@1: mov cx,0005h
+ mov si,offset path2
+ rep cmpsb
+ jz @@2
+ mov cl,0FFh
+ repne scasb
+ cmp al,es:[di]
+ jnz @@1
+ ret
+@@2: mov bp,0090h
+@@loop: mov al,es:[di]
+ test al,al
+ jz exec
+ inc di
+ cmp al,20h
+ jz @@loop
+ cmp al,';'
+ jz @@3
+ mov [bp],al
+ inc bp
+ jmp @@loop
+@@3: call exec
+ jmp @@2
+
+
+;-----------------------------------------------------------------------------
+exec: push ds es di
+ xor si,si
+ cmp bp,0090h
+ jz @@0
+ inc si
+ mov byte ptr [bp],'\'
+@@0: lea di,[bp+si]
+ mov si,offset name1
+ push ss
+ pop es
+ mov cx,11
+ rep movsb
+
+ push ss ss ss
+ pop ds es ax
+ xor bx,bx
+ mov word ptr ds:[0000h],bx
+ mov word ptr ds:[0002h],0010h
+ mov word ptr ds:[0004h],ax
+ mov word ptr ds:[0006h],005Ch
+ mov word ptr ds:[0008h],ax
+ mov word ptr ds:[000Ah],006Ch
+ mov word ptr ds:[000Ch],ax
+
+ mov dx,0090h
+ mov ax,4B00h
+ int 21h
+ jc @@1
+
+ mov ah,4Dh
+ int 21h
+ mov ah,4Ch
+ int 21h
+
+@@1: pop di es ds
+ ret
+
+
+
+
+
+
+
+;=============================================================================
+path1 db 'DOS32A='
+path2 db 'PATH='
+str1 db 'Cannot find file "'
+name1 db 'DOS32A.EXE'
+byte0 db 0,0Dh,0Ah,'$'
+
+$theend proc near
+ db 2 dup(0)
+$theend endp
+
+
+_psp dw ?
+
+
+
+.STACK
+;=============================================================================
+
+
+end start
diff -uNr a/dos32a/src/stub32a/stub32c.asm b/dos32a/src/stub32a/stub32c.asm
--- a/dos32a/src/stub32a/stub32c.asm false
+++ b/dos32a/src/stub32a/stub32c.asm 1564a5d4b4385c7fc5fbd3309d09e16ef8d2e5e12d7d9133672edc828f3fb54120131bf7c03d95e8c1c0dd68eaf2954fb297ae32e5ee44d1cd0e400410e31f05
@@ -0,0 +1,357 @@
+;
+; Copyright (C) 1996-2006 by Narech K. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are
+; met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; 3. The end-user documentation included with the redistribution, if any,
+; must include the following acknowledgment:
+;
+; "This product uses DOS/32 Advanced DOS Extender technology."
+;
+; Alternately, this acknowledgment may appear in the software itself, if
+; and wherever such third-party acknowledgments normally appear.
+;
+; 4. Products derived from this software may not be called "DOS/32A" or
+; "DOS/32 Advanced".
+;
+; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+
+ .286
+ .MODEL tiny
+ LOCALS
+
+;=============================================================================
+_ID32 segment para public use16 'CODE0'
+_ID32_SIZE=16 ; size excluding 'ID32' signature
+;-----------------------------------------------------------------------------
+db 'ID32' ; ID signature
+db 00111111b ; KERNEL misc. bits:
+ ; bit 0: **deprecated**
+ ; bit 1: **deprecated**
+ ; bit 2: 0=VCPI smart page alloc off, 1=on /1=def
+ ; bit 3: 0=VCPI+XMS alloc scheme off, 1=on /1=def
+ ; bit 4: **deprecated**
+ ; bit 5: **deprecated**
+ ; bit 6: reserved /0=def
+ ; bit 7: 0=ignore 4G extensions off, 1=on /0=def
+db 64 ; Max. number of page tables under VCPI /256MB
+db 2 ; Max. number of page tables mem_mapping /4MB
+db 16 ; Max. number of real mode callbacks /16
+dw 256 ; Max. number of Selectors under VCPI/XMS/raw /256
+db 8 ; Real mode Stack nesting
+db 8 ; Protected mode Stack nesting
+dw 20h ; Real mode Stack length, (in para)
+dw 20h ; Protected mode Stack length, (in para)
+dd 0FFFFFFFFh ; Max. extended memory to allocate in bytes
+;-----------------------------------------------------------------------------
+db 00111111b ; DOS/32A misc. bits:
+ ; bit 0: 0=console output off, 1=on /1=def
+ ; bit 1: 0=sound generation off, 1=on /1=def
+ ; bit 2: 0=restore INT table off, 1=on /1=def
+ ; bit 3: 0=report modified INTs off, 1=on /1=def
+ ; bit 4: 0=load 16 in lowmem off, 1=on /1=def
+ ; bit 5: 0=force load 16 low off, 1=on /1=def
+ ; bit 6: 0=cls on exception off, 1=on /0=def
+ ; bit 7: 0=null-ptr protect off, 1=on /0=def
+if EXEC_TYPE eq 0
+db 00001001b ; DOS/32A Pro second misc. bits
+else
+db 10001001b ; DOS/32A Beta second misc. bits
+endif
+ ; bit 0: 0=config by enironment off, 1=on /1=def
+ ; bit 1: 0=focus on this VM off, 1=on /0=def
+ ; bit 2: 0=align objects on PARA, 1=PAGE /0=def
+ ; bit 3: 0=show copyright off, 1=on /1=def
+ ; bit 4: 0=verbose mode off, 1=on /0=def
+ ; bit 5: reserved /0=def
+ ; bit 6: 0=lock configuration off, 1=on /*
+ ; bit 7: 0=Professional, 1=Beta /*
+dw 0200h ; DOS INT 21h buffer in low memory (in para) /8 KB
+dw 0000h ; Internal Version of DOS/32A (N/A for stub)
+dw 0000h ; Reserved (v7.0+)
+;-----------------------------------------------------------------------------
+db 'STUB/32C' ,0
+db 'Copyright (C) 1996-2006 by Narech K.' ,0
+db ??date ,0
+db ??time ,0
+
+_ID32 ends
+
+
+
+
+
+_TEXT16 segment dword public use16 'CODE1'
+assume cs:_TEXT16, ds:_TEXT16
+;=============================================================================
+
+start: push cs
+ pop ds
+ mov ax,es
+ mov bx,ss
+ mov _psp,ax
+ sub bx,ax
+ mov ax,sp
+ shr ax,4
+ add bx,ax
+ inc bx
+ mov ah,4Ah
+ int 21h
+ jc err1
+
+ push ax ds ; install INT 21h
+ xor ax,ax
+ mov ds,ax
+ cli
+ mov ax,ds:[21h*4+0]
+ mov cs:_ip21h,ax
+ mov ax,ds:[21h*4+2]
+ mov cs:_cs21h,ax
+ mov ax,offset int21h
+ mov ds:[21h*4+0],ax
+ mov ax,seg _TEXT16
+ mov ds:[21h*4+2],ax
+ sti
+ pop ds ax
+
+
+@@1: mov es,es:[002Ch] ; get environment
+ call make_cmd
+ mov bp,0090h
+ call exec
+ call find_path1
+ call find_path2
+
+err0: mov ah,09h
+ mov dx,offset str1
+ mov byte ptr byte0,22h
+ int 21h
+err1: mov ax,4CFFh
+ int 21h
+
+
+;-----------------------------------------------------------------------------
+make_cmd:
+ push ds es
+ push ss
+ pop ds
+ xor ax,ax
+ xor di,di
+ mov cx,7FFFh
+@@1: repne scasb
+ scasb
+ jnz @@1
+ inc di
+ inc di
+ mov si,di
+ repne scasb
+ sub di,si
+ mov cx,di
+ mov ax,di
+ mov di,0011h
+ push ss
+ push es
+ pop ds
+ pop es
+ rep movsb
+ mov byte ptr es:[di-1],20h
+ mov ds,cs:_psp
+ mov si,0081h
+ mov cl,[si-1]
+ add al,cl
+ inc cx
+ mov es:[0010h],al
+ rep movsb
+ pop es ds
+ ret
+
+
+;-----------------------------------------------------------------------------
+find_path1:
+ xor ax,ax
+ xor di,di
+@@1: mov cx,0007h
+ mov si,offset path1
+ rep cmpsb
+ jz @@2
+ mov cl,0FFh
+ repne scasb
+ cmp al,es:[di]
+ jnz @@1
+ ret
+@@2: mov al,20h ; skip leading spaces
+ mov cl,0FFh
+ rep scasb
+ cmp word ptr es:[di],'\:'
+ jz @@3
+ ret
+@@3: dec di
+ mov bp,0090h
+@@loop: mov al,es:[di]
+ test al,al
+ jz @@4
+ inc di
+ cmp al,20h
+ jz @@4
+ mov [bp],al
+ inc bp
+ jmp @@loop
+@@4: mov byte ptr [bp],'\'
+ mov word ptr [bp+1],'IB'
+ mov word ptr [bp+3],'WN'
+ add bp,5
+ jmp exec
+
+
+
+
+;-----------------------------------------------------------------------------
+find_path2:
+ xor ax,ax
+ xor di,di
+@@1: mov cx,0005h
+ mov si,offset path2
+ rep cmpsb
+ jz @@2
+ mov cl,0FFh
+ repne scasb
+ cmp al,es:[di]
+ jnz @@1
+ ret
+@@2: mov bp,0090h
+@@loop: mov al,es:[di]
+ test al,al
+ jz exec
+ inc di
+ cmp al,20h
+ jz @@loop
+ cmp al,';'
+ jz @@3
+ mov [bp],al
+ inc bp
+ jmp @@loop
+@@3: call exec
+ jmp @@2
+
+
+;-----------------------------------------------------------------------------
+exec: push ds es di
+ xor si,si
+ cmp bp,0090h
+ jz @@0
+ inc si
+ mov byte ptr [bp],'\'
+@@0: lea di,[bp+si]
+ mov si,offset name1
+ push ss
+ pop es
+ mov cx,11
+ rep movsb
+
+ push ss ss ss
+ pop ds es ax
+ xor bx,bx
+ mov word ptr ds:[0000h],bx
+ mov word ptr ds:[0002h],0010h
+ mov word ptr ds:[0004h],ax
+ mov word ptr ds:[0006h],005Ch
+ mov word ptr ds:[0008h],ax
+ mov word ptr ds:[000Ah],006Ch
+ mov word ptr ds:[000Ch],ax
+
+ mov dx,0090h
+ mov ax,4B00h
+ int 21h
+ jc @@1
+
+ mov ah,4Dh
+ int 21h
+ mov ah,4Ch
+ int 21h
+
+@@1: pop di es ds
+ ret
+
+
+
+;-----------------------------------------------------------------------------
+ Align 4
+int21h: cmp ah,4Ch
+ jz @@1
+ cmp ax,0FF87h
+ jz @@2
+@@0: jmp dword ptr cs:_ip21h
+
+@@1: push ax
+ call uninstall_int21h
+ pop ax
+ jmp @@0
+
+@@2: call uninstall_int21h
+ mov ax,seg _ID32
+ mov ds,ax ; DS:SI = pointer to configuration
+ xor si,si
+ mov dx,'ID' ; DX:AX = "ID32" ID-string
+ mov ax,'32'
+ iret
+
+;-----------------------------------------------------------------------------
+uninstall_int21h:
+ cli
+ xor ax,ax
+ mov ds,ax
+ mov ax,cs:_ip21h
+ mov ds:[21h*4+0],ax
+ mov ax,cs:_cs21h
+ mov ds:[21h*4+2],ax
+ ret
+
+
+
+;=============================================================================
+path1 db 'DOS32A='
+path2 db 'PATH='
+str1 db 'Cannot find file "'
+name1 db 'DOS32A.EXE'
+byte0 db 0,0Dh,0Ah,'$'
+
+$theend proc near
+ db 5 dup(0)
+$theend endp
+
+
+ evendata
+_ip21h dw ?
+_cs21h dw ?
+_psp dw ?
+
+
+_TEXT16 ends
+
+
+.STACK
+;=============================================================================
+
+
+end start
diff -uNr a/dos32a/src/sver/main.c b/dos32a/src/sver/main.c
--- a/dos32a/src/sver/main.c false
+++ b/dos32a/src/sver/main.c 2403a2520f3db8267b901ec7a16c0a140798ee20394b54d1e5dff0201b99ca6c2fede20bfdc8f6ecdd402369f3c2bef70474dddd652edb7b8c5a157d1a6963a6
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 1996-2006 by Narech K. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment:
+ *
+ * "This product uses DOS/32 Advanced DOS Extender technology."
+ *
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. Products derived from this software may not be called "DOS/32A" or
+ * "DOS/32 Advanced".
+ *
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+
+ char* version = "9.1.2";
+ char* errstr = "SVER fatal:";
+
+ int fileisbound = TRUE;
+ int extendertype= 0; // 1=DOS/32A, 2=STUB/32A, 3=STUB32C
+ char* fileverptr = NULL;
+
+ int extender_release;
+ int extender_revision;
+ int extender_major_version;
+ int extender_minor_version;
+ int extender_build_version;
+
+ FILE* fp;
+ char buffer[512];
+ char filename[256];
+ char orgfilename[256];
+
+
+void err_usage() {
+ printf("%s syntax is SVER \n",errstr);
+ exit(1);
+}
+void err_open() {
+ printf("%s cannot open file \"%s\"\n",errstr,filename);
+ exit(1);
+}
+void err_read() {
+ printf("%s cannot read from file \"%s\"\n",errstr,filename);
+ exit(1);
+}
+void err_seek() {
+ printf("%s error seeking in file \"%s\"\n",errstr,filename);
+ exit(1);
+}
+void err_format() {
+ printf("%s unsupported exec format in file \"%s\"\n",errstr,filename);
+ exit(1);
+}
+void err_extender() {
+ printf("%s \"%s\" is not a DOS/32A executable\n",errstr,filename);
+ exit(1);
+}
+
+
+/****************************************************************************/
+void ShowCopyright()
+{
+ printf("SVER -- Version Reporting Utility version %s\n",version);
+ printf("Copyright (C) 1996-2006 by Narech K.\n");
+}
+
+
+void ShowHelp()
+{
+ printf("\n");
+ printf("The SVER Utility Program should be used to determine the version\n");
+ printf("of DOS/32 Advanced DOS Extender, STUB/32A Standard Stub file and\n");
+ printf("STUB/32C Configurable Stub file.\n");
+
+ printf("\n");
+ printf("The SVER Utility Program can also be used to display any OEM\n");
+ printf("(Original Equipment Manufacturer) Information possibly bound to\n");
+ printf("the LC-style executables.\n");
+
+ printf("\n");
+ printf("To display version and OEM information run the SVER Utility on a\n");
+ printf("program you wish to inspect. Note that the SVER Utility supports\n");
+ printf("DOS Extender version 7.0 or higher only.\n");
+
+ printf("\n");
+ exit(0);
+}
+
+
+/****************************************************************************/
+void OpenFile()
+{
+ char buf[256];
+
+ strcpy(buf,filename);
+ if( (fp=fopen(buf,"rb")) == NULL)
+ {
+ strcpy(buf,filename);
+ strcat(buf,".exe");
+ if( (fp=fopen(buf,"rb")) == NULL)
+ {
+ strcpy(buf,filename);
+ strcat(buf,".le");
+ if( (fp=fopen(buf,"rb")) == NULL)
+ {
+ strcpy(buf,filename);
+ strcat(buf,".lx");
+ if( (fp=fopen(buf,"rb")) == NULL)
+ {
+ strcpy(buf,filename);
+ strcat(buf,".lc");
+ if( (fp=fopen(buf,"rb")) == NULL)
+ {
+ err_open();
+ }
+ }
+ }
+ }
+ }
+ strcpy(orgfilename,buf);
+}
+
+void ReadFileHeader()
+{
+ fread(&buffer,1,sizeof(buffer),fp);
+ if(ferror(fp))
+ err_read();
+}
+
+void CheckFileFormat()
+{
+ if(strncmp(buffer,"MZ",2) == 0)
+ {
+ fileisbound=TRUE;
+ return;
+ }
+ if(strncmp(buffer,"LC",2) == 0)
+ {
+ fileisbound=FALSE;
+ return;
+ }
+ err_format();
+}
+
+void CheckStubExtender()
+{
+ if(fileisbound==FALSE)
+ return;
+
+ if(strcmp(&buffer[0x7C],"DOS/32A") == 0)
+ {
+ fileverptr=(char *)(buffer+0x85);
+ extendertype=1;
+ return;
+ }
+ if(strcmp(&buffer[0x9C],"DOS/32A") == 0)
+ {
+ fileverptr=(char *)(buffer+0xA5);
+ extendertype=1;
+ return;
+ }
+ if(strcmp(&buffer[0x20],"STUB/32A") == 0)
+ {
+ fileverptr=(char *)(buffer+0x29);
+ extendertype=2;
+ return;
+ }
+ if(strcmp(&buffer[0x40],"STUB/32A") == 0)
+ {
+ fileverptr=(char *)(buffer+0x49);
+ extendertype=2;
+ return;
+ }
+ if(strcmp(&buffer[0x4C],"STUB/32C") == 0)
+ {
+ fileverptr=(char *)(buffer+0x55);
+ extendertype=3;
+ return;
+ }
+ if(strcmp(&buffer[0x6C],"STUB/32C") == 0)
+ {
+ fileverptr=(char *)(buffer+0x75);
+ extendertype=3;
+ return;
+ }
+ err_extender();
+}
+
+
+void ShowApplicationName()
+{
+
+ printf("\n");
+ printf("Application name:\n");
+ printf("-----------------\n");
+ printf("\"%s\"\n", orgfilename);
+}
+
+
+void ShowExtenderVersion()
+{
+ char buf[8];
+
+ if(fileisbound==FALSE)
+ return;
+
+ memset(buf,0,sizeof(buf));
+ buf[0] = *(fileverptr+1);
+ extender_release=atoi(buf);
+
+ memset(buf,0,sizeof(buf));
+ buf[0] = *(fileverptr+6);
+ buf[1] = *(fileverptr+7);
+ extender_revision=atoi(buf);
+
+ memset(buf,0,sizeof(buf));
+ buf[0] = *(fileverptr+3);
+ buf[1] = *(fileverptr+4);
+ extender_major_version=atoi(buf);
+
+ memset(buf,0,sizeof(buf));
+ buf[0] = *(fileverptr+8);
+ buf[1] = *(fileverptr+9);
+ extender_minor_version=atoi(buf);
+
+ memset(buf,0,sizeof(buf));
+ buf[0] = *(fileverptr+11);
+ buf[1] = *(fileverptr+12);
+ buf[2] = *(fileverptr+13);
+ buf[3] = *(fileverptr+14);
+ extender_build_version=atoi(buf);
+
+
+ printf("\n");
+ if(extendertype ==1 )
+ {
+ printf("DOS/32 Advanced DOS Extender:\n");
+ printf("-----------------------------\n");
+ }
+ else if(extendertype == 2)
+ {
+ printf("STUB/32A Standard Stub File:\n");
+ printf("----------------------------\n");
+ }
+ else if(extendertype == 3)
+ {
+ printf("STUB/32C Configurable Stub File:\n");
+ printf("--------------------------------\n");
+ }
+
+ // v9+
+ if(extender_major_version == 0 && extender_minor_version == 0)
+ {
+ if(*(fileverptr-3-9) >= 9)
+ {
+ extender_minor_version = *(fileverptr-4-9);
+ extender_major_version = *(fileverptr-3-9);
+ }
+ else
+ {
+ if(extendertype == 2 || extendertype == 3)
+ printf("Version: N/A\n");
+ else
+ printf("Version: Unknown\n");
+ return;
+ }
+ }
+
+
+ if(extender_release != 0)
+ printf("Release: %d\n", extender_release);
+
+ if(extender_major_version < 9)
+ printf("Version: %d.%d\n", extender_major_version, extender_minor_version);
+ else
+ printf("Version: %d.%d.%d\n", extender_major_version, extender_minor_version/10, extender_minor_version%10);
+
+ if(extender_revision != 0)
+ printf("Revision: [%c]\n", extender_revision+'A'-1);
+
+ if(extender_build_version != 0)
+ printf("Build: %04d\n", extender_build_version);
+}
+
+void ShowOEMInfo()
+{
+ int n;
+ int objects;
+ unsigned long offs;
+ unsigned long size;
+
+// file type must be MZ or LC
+ if(strncmp(buffer,"MZ",2) != 0 && strncmp(buffer,"LC",2) != 0) return;
+
+// if MZ, move to Linear Exec start
+ if(strncmp(buffer,"MZ",2) == 0)
+ {
+ offs=0;
+ offs|=(unsigned long)buffer[0x3C];
+ offs|=(unsigned long)buffer[0x3D]<<8;
+ offs|=(unsigned long)buffer[0x3E]<<16;
+ offs|=(unsigned long)buffer[0x3F]<<24;
+ if(offs == 0) return;
+ }
+ else offs=0;
+
+ if(fseek(fp,offs,SEEK_SET) != 0) err_seek();
+ fread(buffer,1,16,fp);
+ if(ferror(fp)) err_read();
+
+// check if LC-style file format
+ if(strncmp(buffer,"LC",2) != 0) return;
+
+// check if OEM Info is appended
+ if( (buffer[5]&0x80) != 0x80) return;
+
+ objects=buffer[4];
+
+// scan through Objects
+ for(n=0; n