Full Code of Baron-von-Riedesel/Jemm for AI

master 87055a625835 cached
197 files
1.2 MB
431.9k tokens
18 symbols
1 requests
Download .txt
Showing preview only (1,301K chars total). Download the full file or copy to clipboard to get everything.
Repository: Baron-von-Riedesel/Jemm
Branch: master
Commit: 87055a625835
Files: 197
Total size: 1.2 MB

Directory structure:
gitextract_t40dgl9z/

├── Artistic.txt
├── History.txt
├── Html/
│   └── Readme.html
├── Include/
│   ├── FILEACC.INC
│   ├── FINDRES.INC
│   ├── JLM.H
│   ├── JLM.INC
│   ├── JLMFASM.INC
│   ├── JSYSTEM.INC
│   ├── PRINTF.INC
│   ├── VDS.INC
│   └── X86.INC
├── JLM/
│   ├── AHCICD/
│   │   ├── AHCICD.ASM
│   │   ├── AHCICD.txt
│   │   ├── MAKE.BAT
│   │   └── MAKEM.BAT
│   ├── GENERIC/
│   │   ├── GENERIC.ASM
│   │   ├── MAKEFILE
│   │   ├── README.TXT
│   │   └── TESTGEN.ASM
│   ├── HELLO/
│   │   ├── HELLO.ASM
│   │   ├── MAKE.BAT
│   │   └── README.TXT
│   ├── HELLO2/
│   │   ├── HELLO2.C
│   │   ├── HELLO2W.C
│   │   ├── JLMW.ASM
│   │   ├── JLMW.h
│   │   ├── MAKEJLMW.BAT
│   │   ├── MAKEOW.BAT
│   │   ├── MAKEVC.BAT
│   │   ├── README.TXT
│   │   └── makeow.sh
│   ├── IOTRAP/
│   │   ├── IOTRAP.ASM
│   │   ├── MAKEFILE
│   │   ├── README.TXT
│   │   └── TESTIOT.ASM
│   ├── JCLOCK/
│   │   ├── JCLOCK.ASM
│   │   ├── JCLOCK2.ASM
│   │   ├── JCLOCK3.ASM
│   │   ├── MAKE.BAT
│   │   ├── MAKE3.BAT
│   │   └── README.TXT
│   ├── JLSTUB/
│   │   ├── Build/
│   │   │   └── JLSTUB.lst
│   │   ├── JLSTUB.ASM
│   │   ├── JLStub.txt
│   │   └── Make.BAT
│   ├── KEYBGR/
│   │   ├── KEYBGR.ASM
│   │   ├── MAKE.BAT
│   │   ├── MAKEFILE
│   │   └── README.TXT
│   ├── QPIEMU/
│   │   ├── MAKE.BAT
│   │   ├── MAKEFILE
│   │   ├── QPIEMU.ASM
│   │   ├── QPIEMU.txt
│   │   └── Test/
│   │       ├── MAKEFILE
│   │       ├── PRINTF16.INC
│   │       ├── SETARGV.INC
│   │       ├── TESTDMA.ASM
│   │       └── TESTQPI.ASM
│   ├── README.TXT
│   ├── REBOOT/
│   │   ├── FASTBOOT.ASM
│   │   ├── FASTBOOT.txt
│   │   ├── FASTBRM.ASM
│   │   ├── FBOOT.ASM
│   │   ├── LDI13EXT.ASM
│   │   ├── MAKE.BAT
│   │   ├── REBOOT.ASM
│   │   └── REBOOT.txt
│   ├── XCDROM32/
│   │   ├── History.txt
│   │   ├── MAKE.BAT
│   │   ├── MAKEM.BAT
│   │   ├── XCDROM32.ASM
│   │   └── XCDROM32.txt
│   └── XDMA32/
│       ├── History.txt
│       ├── IDENTIFY.INC
│       ├── MAKE.BAT
│       ├── MAKEM.BAT
│       ├── XDMA32.ASM
│       └── XDMA32.txt
├── JemmExL.mak
├── Linux.mak
├── Makefile
├── Readme.txt
├── Test/
│   ├── BMINTRM.ASM
│   ├── EMS4E.ASM
│   ├── EMS4F.ASM
│   ├── EMS56.ASM
│   ├── EMS57.ASM
│   ├── EMS57A.ASM
│   ├── EMS5B.ASM
│   ├── EXC00.ASM
│   ├── EXC06.ASM
│   ├── FRAMERES.ASM
│   ├── HLTTEST.ASM
│   ├── HLTTEST2.ASM
│   ├── I15MOVE.ASM
│   ├── INT67.ASM
│   ├── INT88.ASM
│   ├── MACROS.INC
│   ├── MAKE.BAT
│   ├── PRINTF.INC
│   ├── README.TXT
│   ├── TEST0C.DEB
│   ├── TEST0C1.DEB
│   ├── TEST0D.DEB
│   ├── TEST10.DEB
│   ├── TEST11.DEB
│   ├── TESTDMA.ASM
│   ├── TESTDMA2.ASM
│   ├── TESTDMA3.ASM
│   ├── TESTVCPI.ASM
│   ├── TESTVDS.ASM
│   ├── TESTVDS2.ASM
│   ├── TESTVDS3.ASM
│   ├── TIMERMS.INC
│   ├── VCPI.INC
│   ├── XMSTEST.ASM
│   ├── XMSTEST2.ASM
│   ├── XMSTEST3.ASM
│   ├── XMSTEST4.ASM
│   └── XMSTEST5.ASM
├── Tools/
│   ├── CLEAR.BAT
│   ├── CPUID/
│   │   ├── CPUID.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── Cpustat/
│   │   ├── CPUSTAT.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── EMSSTAT/
│   │   ├── EMSSTAT.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── JEMFBHLP/
│   │   ├── JEMFBHLP.ASM
│   │   └── MAKE.BAT
│   ├── JLOAD/
│   │   ├── DEBUG.INC
│   │   ├── DPRINTF.INC
│   │   ├── DPRNTF16.INC
│   │   ├── History.txt
│   │   ├── JLOAD.ASM
│   │   ├── JLOAD.INC
│   │   ├── JLOAD.TXT
│   │   ├── JLOAD.txt
│   │   ├── JLOAD32.ASM
│   │   ├── JLOAD32.INC
│   │   ├── Linux.mak
│   │   ├── MAKEFILE
│   │   ├── VDMAD.ASM
│   │   ├── VIOOUT.INC
│   │   ├── VMM.ASM
│   │   ├── WINNT.INC
│   │   └── license.txt
│   ├── MAKE.BAT
│   ├── MEMSTAT/
│   │   ├── MAKE.BAT
│   │   ├── MEMSTAT.ASM
│   │   └── PRINTF.INC
│   ├── MoveXBDA/
│   │   ├── MAKE.BAT
│   │   └── MOVEXBDA.ASM
│   ├── UMBM/
│   │   ├── MAKE.BAT
│   │   └── UMBM.ASM
│   ├── VCPI/
│   │   ├── MAKE.BAT
│   │   ├── PRINTF.INC
│   │   ├── VCPI.ASM
│   │   ├── VCPI.INC
│   │   └── VIOOUT.INC
│   └── XMSSTAT/
│       ├── MAKE.BAT
│       ├── PRINTF.INC
│       └── XMSSTAT.ASM
├── XMS35.txt
└── src/
    ├── AUXIO.INC
    ├── DEBUG.ASM
    ├── DEBUG16.INC
    ├── DEBUG32.INC
    ├── DEBUGSYS.INC
    ├── DEV.ASM
    ├── DMA.INC
    ├── DPRINTF.INC
    ├── DPRNTF16.INC
    ├── EMS.ASM
    ├── EMS.INC
    ├── EMS32.INC
    ├── EMU.ASM
    ├── EXTERN32.INC
    ├── I15.ASM
    ├── INIT.ASM
    ├── INIT16.ASM
    ├── JEMM.INC
    ├── JEMM16.ASM
    ├── JEMM16.INC
    ├── JEMM32.ASM
    ├── JEMM32.INC
    ├── POOL.ASM
    ├── UMB.ASM
    ├── VCPI.ASM
    ├── VCPI.INC
    ├── VDMA.ASM
    ├── VDS.ASM
    ├── XMS.ASM
    └── XMS.INC

================================================
FILE CONTENTS
================================================

================================================
FILE: Artistic.txt
================================================
The Artistic License Preamble

The intent of this document is to state the conditions under which a Package may 
be copied, such that the Copyright Holder maintains some semblance of artistic 
control over the development of the package, while giving the users of the 
package the right to use and distribute the Package in a more-or-less customary 
fashion, plus the right to make reasonable modifications.

Definitions:

"Package" refers to the collection of files distributed by the Copyright Holder, 
and derivatives of that collection of files created through textual 
modification. "Standard Version" refers to such a Package if it has not been 
modified, or has been modified in accordance with the wishes of the Copyright 
Holder. "Copyright Holder" is whoever is named in the copyright or copyrights 
for the package. "You" is you, if you're thinking about copying or distributing 
this Package. "Reasonable copying fee" is whatever you can justify on the basis 
of media cost, duplication charges, time of people involved, and so on. (You 
will not be required to justify it to the Copyright Holder, but only to the 
computing community at large as a market that must bear the fee.) "Freely 
Available" means that no fee is charged for the item itself, though there may be 
fees involved in handling the item. It also means that recipients of the item 
may redistribute it under the same conditions they received it. 1. You may make 
and give away verbatim copies of the source form of the Standard Version of this 
Package without restriction, provided that you duplicate all of the original 
copyright notices and associated disclaimers.

2. You may apply bug fixes, portability fixes and other modifications derived 
from the Public Domain or from the Copyright Holder. A Package modified in such 
a way shall still be considered the Standard Version.

3. You may otherwise modify your copy of this Package in any way, provided that 
you insert a prominent notice in each changed file stating how and when you 
changed that file, and provided that you do at least ONE of the following:

a) place your modifications in the Public Domain or otherwise make them Freely 
Available, such as by posting said modifications to Usenet or an equivalent 
medium, or placing the modifications on a major archive site such as ftp.uu.net, 
or by allowing the Copyright Holder to include your modifications in the 
Standard Version of the Package.

b) use the modified Package only within your corporation or organization.

c) rename any non-standard executables so the names do not conflict with 
standard executables, which must also be provided, and provide a separate manual 
page for each non-standard executable that clearly documents how it differs from 
the Standard Version.

d) make other distribution arrangements with the Copyright Holder.

4. You may distribute the programs of this Package in object code or executable 
form, provided that you do at least ONE of the following:

a) distribute a Standard Version of the executables and library files, together 
with instructions (in the manual page or equivalent) on where to get the 
Standard Version.

b) accompany the distribution with the machine-readable source of the Package 
with your modifications.

c) accompany any non-standard executables with their corresponding Standard 
Version executables, giving the non-standard executables non-standard names, and 
clearly documenting the differences in manual pages (or equivalent), together 
with instructions on where to get the Standard Version.

d) make other distribution arrangements with the Copyright Holder.

5. You may charge a reasonable copying fee for any distribution of this Package. 
You may charge any fee you choose for support of this Package. You may not 
charge a fee for this Package itself. However, you may distribute this Package 
in aggregate with other (possibly commercial) programs as part of a larger 
(possibly commercial) software distribution provided that you do not advertise 
this Package as a product of your own.

6. The scripts and library files supplied as input to or produced as output from 
the programs of this Package do not automatically fall under the copyright of 
this Package, but belong to whomever generated them, and may be sold 
commercially, and may be aggregated with this Package.

7. C or perl subroutines supplied by you and linked into this Package shall not 
be considered part of this Package.

8. The name of the Copyright Holder may not be used to endorse or promote 
products derived from this software without specific prior written permission.

9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

The End


================================================
FILE: History.txt
================================================

 History

 __.__.____: v5.87

 - fixed regression in v5.86: exceptions in PL0 were displayed incorrectly.
 - fixed: NMIs that occured while no full stack frame was setup caused
   a crash.
 - segment registers DS/ES/FS/GS and [CS:IP] now also displayed for PL0
   exceptions.
 - NMIs are masked while NMI exceptions are handled.
 - fixed: Simulate_Int() cleared bits 16-31 of register ESP.
 - JemmEx fix: if option XMSHANDLES was > 59 and Jemm wasn't allowed to move
   its resident part into the upper memory region, it crashed.
 - Linux.mak: GNU makefile added to create Jemm binaries on Linux.
 - fixed JemmEx: unknown A20METHOD value caused a crash.
 - AHCICD: driver now supports long reads in "raw mode".

 25.01.2026: v5.86
 - service table: added control proc member to allow Jemm to call out on
   certain events; currently "device_reboot_notify" is the only call-out.
 - service table: added v86faults member - allows programs to hook into
   v86 faults; used by JLOAD.
 - Simulate_Int: call an installed v86 hook proc before running the INT.
 - JemmEx, XMS AH=0Eh: invalid handle error returned if size > 65535 kB;
   this is MS Himem compatible.
 - JLMs Reboot & FastBoot added.
 - fixed debug displays in 16-bit part.
 - fixed debug displays in Jemm16.asm, UnloadJemm.
 - JemmEx: option NOE820 reintroduced; it's a noop unless MAXSEXT is 0.
 - fixed option UNLOAD: on 80386/80486 cpus, it wasn't safe.
 - JLM QPIEmu: added function ax=5000h.
 - reintroduced compatibility with SB emulation drivers SB(E)INIT for SB PCI
   cards by extending functionality of cmdline option SB.
 - NMI stability increased.

 10.01.2025: v5.85
 - fixed: VDS func ax=810Ch: set ZF if disable cnt reaches zero.
 - fixed: VDS: added several argument checks ( mostly DX ).
 - fixed: ISA DMA ports 000A-000F must be handled by Jemm to detect FD accesss
   even if external handler has trapped these ports.
 - fixed: it was assumed that value for TR to be loaded in VCPI function
   ax=DE0Ch ( switch from v86- to protected-mode) had bits 0-2 cleared.
 - linear address region 110000-3FFFFF is now only mapped as far as needed by
   the monitor program (looses SB(E)INIT compatibility).
 - optional kernel-debugger-aware variant calls int 68h for deinitialization.
 - cmdline switch NOVMW added.
 - easier log displays via macro @dprintf.
 - log displays redirected to kernel debugger if one has been detected.
 - buffered output of log displays removed.
 - switch ?SAFEKBD=1 is now default for JemmEx (restores IVT vector 15h before
   reading a key press via int 16h during system errors).
 - JemmDbg renamed to JDeb386 and removed from Jemm source package.
 - building JemmExL.exe removed from Makefile; to create it, use JemmExL.mak.
 - CPUSTAT: optionally displays interrupt redirection bitmap.

 12.02.2024: v5.84
 - fixed: Simulate_IO() no longer calls trap handler.
 - QPIEMU: new JLM that partly implements Qemm's API (QPI).
 - fixed: int 67h, ax=5B01h will return error code A3h if checksum invalid.
 - JemmDbg: removed from binary package.

 06.12.2022: v5.83
 - AHCICD: new JLM for CD/DVD devices attached to a SATA controller running
   in AHCI mode (cooked mode only).
 - XDMA32, XCDROM32: now accepting "AHCI-disabled" SATA controllers.
 - JemmEx: warning displayed if I15 memory blocks had to be ignored due
   to insufficient XMS "static" handles (8); static handles increased to 10.
 - JemmDbg: a PL0 debugger, based on Debug/X; may be used to debug JLMs.
 - Makefile supports creating variants of Jemm386/JemmEx that are kernel
   debugger aware.
 - CPUSTAT: optionally displays IOPB (trapped ports).

 09.08.2022: v5.82
 - JemmEx: minor adjustment to always keep monitor stack dword-aligned.
 - fixed: MOVEXBDA option didn't check that XBDA was adjacent to conv. mem.
 - JLoad: fixed: hook int 2Fh (used to get JLM API entry) was incorrect.
 - CPUID: fixed: feature information incorrect.
 - CPUSTAT: fixed: options -g and -i if physical != linear address.
 - XDMA32: fixed: did reject many disks if /M option wasn't set.

 12.04.2022: v5.81
 - JemmEx: XMS extension v3.51 (super-extended block moves) implemented.

 18.06.2021: v5.80
 - for exceptions other than page faults, the monitor will display register
   CR4 instead of CR2, if it exists.
 - Jemm might have reduced last MCB by 16 byte when loaded while UMBs
   where already available and used by DOS.
 - Jemm does again scan the region C000-EFFF for RAM. This avoids
   a system crash if upper memory has been supplied by UMBPCI and is
   used by DOS.
 - new option MOVEXBDA for Jemm implemented.
 - JemmEx will recognize memory blocks activated by UMBPCI and include them
   into its UMB pool. Makes option S=start-end virtually obsolete.
 - a warning is displayed if the extended memory block where Jemm386 will
   reside is beyond the 16MB limit.
 - strategy to realloc an EMB to increase its size has been changed and is
   now smart enough to check if the block can be increased without moving
   it.
 - UMBM no longer requires the /I parameter; it will scan for blocks with
   the UMBPCI signature.
 - UMBM has new option /XBDA.
 - UMBM now acts gracefully if line DOS=UMB is missing in CONFIG.SYS.
 - MOVEXBDA has got option /A to make it align the new XBDA to a kB boundary.
 - tool CPUSTAT split into CPUSTAT and CPUID.
 - emulation of Int 15h, ah=87 (move extended memory) has been enhanced
   to allow to access physical memory beyond the 4 GB border via PSE-36.
 - JemmEx XMM now implements XMS v3.5 (extended memory > 4 GB). Default XMS
   handles changed to 48 (previously 32). Added MAXSEXT option for JemmEx,
   and also added JemmExL.exe, that still supports XMS v3.0 only.
 - JemmEx: return DX=0 if XMS alloc functions fail (XMS spec).
 - option I=TEST does now indeed what's documented. Previously it only
   scanned regions of "external" ROMs ( i.e., the ROM of the VGA card ).
   This means it's more "aggressive" now.
 - ALTBOOT option sends "system reset" command to keyboard controller.

 02/02/2020: v5.79
 - if physical address of DMA buffer was beyond 16M, its size was reset
   to zero. This is no longer done.
 - default linker is now JWlink.
 - debug displays added for mode switch calls.
 - Jemm will now use info returned by Int 15h, ax=E820h to mark regions
   in the upper memory area as reserved. If the call was successful,
   Jemm won't scan the memory region C000-EFFF for RAM.
 - VME (virtual mode extensions) is now off by default; there exist CPUs
   that claim to support VME but actually don't.
 - JemmEx's built-in XMS host will now use up to 8 memory blocks listed
   by ACPI (int 0x15, ax=0xe820). Previously it could just use the one
   with base address 0x100000.
 - fixed: shrinking an EMB didn't work correctly.

 07/15/2012: v5.78

 - bugfix: if SPLIT option was set and there were 2 ROMs to be split on
   adjacent 4K-pages, the latter one may have been overwritten with zeros
   (problem found in Qemu v0.15.1).
 - bugfix: MOVEXBDA didn't restore the XBDA at reboot. This may have been
   a problem if the FASTBOOT option was active.
 - a warning is displayed if the page frame isn't set to a segment address
   divisible by 0x400 without remainder ( i.e, FRAME=DF00 will trigger the
   warning ).
 - MEMSTAT additionally displays location and size of XBDA.
 - source package only: extrsect.exe replaced by bin2inc.exe; bin2inc.exe
   is needed only if Masm is used to assemble the source.

 06/20/2012: v5.77

 - commandline option I=A000-B7FF didn't increase DOS low memory, the
   region became just the first UMB.
 - tool MOVEXBDA added.

 05/25/2012: v5.76

 - an 64kB EMS page frame may now be located inside address space included
   with 'I=XXXX'.

 05/21/2012: v5.75a

 - no changes in JemmEx/Jemm386, just bugfixes in XDMA32.DLL and
   XCDROM32.DLL.

 05/31/2011: v5.75

 - bugfix: when Jemm detected Ctrl-Alt-Del, it didn't reset the keyboard
   status. This may have caused a locked keyboard if FASTBOOT was set.

 04/14/2011: v5.74

 - tool MEMSTAT added, which will display the size of the reserved
   BIOS-ROM region.
 - Make process simplified, all sources are assembly now.

 12/02/2010: v5.73

 - bugfix: int 67h, ah=51h didn't complain if handle was invalid in 
   v5.61-5.72.
 - tool CPUSTAT added.
 - for emulation of Int 15h, AH=87h (extended memory block move), the
   region 100000h-10FFFFh is now handled similar to the rest of extended
   memory. Previously it was handled as "real-mode" memory, which means
   that access did depend on the A20 state. This new behavior matches
   more closely the BIOS implementation of this interrupt.
 - option V86EXC0D added.

 03/13/2008: v5.72

 - source has been made compatible with JWasm; OTOH, TASM compatibility
   has been abandoned.

 02/25/2008: v5.71

 - bugfix: DMA buffer size of 0 (D=0) didn't work in v5.70.
 - bugfix: JLOAD v5.70 made wrong assumptions about Jemm's TSS location,
   which caused JLM sample JCLOCK2 to fail.
 - some minor changes to make it compatible with JWasm.

 01/30/2008: v5.70

 - bugfix: the "copy memory" routine wasn't reentrant, making an XMS
   "block move" or a call of Int 15h, ah=87h from within an ISR slightly
   unsafe.
 - bugfix: int 67h, ah=57h returned error 8Ah instead of 93h when a 
   region exceeded the size of the EMS handle.
 - bugfix: int 67h, ah=57h accepted any region type (just 00 and 01 are
   valid ones).
 - bugfix: int 67h, ax=5701h accepted overlapping EMS regions. Now status
   97h is returned.
 - bugfix: since v5.61 (support for mappable pages in conventional memory)
   option NODYN often failed to make all memory available which was
   requested with the MIN=x option.
 - bugfix: exception 11h in v86-mode caused a loop in Jemm's exception
   handler.
 - bugfix: due to an alignment problem the low byte of max. free memory
   block for XMS v2 (X2MIN) was 0, as a result the default block size was
   65280 (0xFF00) instead of 65535 kB (JemmEx only, bug since v5.64).
 - int 67h,ax=5701h, "memory exchange" is now also done with interrupts
   enabled if client's interrupt flag is set.
 - port 60h access is now trapped only if the keyboard controller's output
   port is accessed.
 - tool XMSSTAT and source of EMSSTAT added.

 01/07/2008: v5.69

 - descriptions/changelogs for XDMA32 and XCDROM32 extracted from this
   readme into separate files XDMA32.TXT and XCDROM32.TXT.
 - memory block copies are now done with interrupts enabled - if client's
   interrupt flag is set. This avoids interrupt latency and makes the
   previously implemented "interrupt windows" obsolete. It also avoids
   problems with Jemm's HLT emulation causing IRQs to be misinterpreted
   as exceptions (08, 09, 74, ...) on some cpus.
 - bugfix: VDS scatter/gather lock with region size 0 returned 0 entries,
   but 1 entry must be returned in any case (MS Emm386 does as well).
 - bugfix: there was a risk that a ROM located contiguously behind another
   ROM in address space wasn't detected.
 - bugfix: if SPLIT option was set and a split ROM page followed an UMB
   page (which is possible if ROM size is < 4 kB), the ROM part of this
   page was added to the UMB.
 - bugfix: synchronization of VCPI and EMS free memory count did work
   for VCPI only, that is, allocating all VCPI memory didn't reduce free
   EMS memory to zero.
 - bugfix: the last XMS memory block allocated for EMS/VCPI memory was
   likely to be too large, thus wasting XMS memory.
 - VCPI/EMS memory alloc/release speed-up.
 - EMSSTAT -v displays more VCPI infos.
 - v86 exceptions >= 8 are routed to v86 interrupt 06h only if this vector
   has been changed by another program.
 - exception 10h (floating point) is now detected and displayed, thus avoiding
   the hazardous call of video interrupt 10h (MS Emm386 also detects
   exception 10h, but just allows to reboot then).

 12/03/2007: v5.68

 - bugfix: JLOAD's "Lock DMA" function ignored flag to check for 64 kB
   border crossing.
 - NMIs occuring inside the monitor are now silently routed to v86-mode.
   Previous Jemm versions displayed an exception dump.
 - XDMA32 v1.0 added.
 - XCDROM32 changed to v1.1.

 10/13/2007: v5.67

 - bugfix: I=TEST always scanned 4 kB chunks, although the last page
   of a ROM might be smaller (512, 1024, ... bytes).
 - bugfix: if I=TEST found an "unused" page in a ROM, v5.64-5.66 messed
   up an internal counter. As a result, there was a small risk that the
   begin of another ROM following this one in the address space wasn't
   detected.
 - error code displayed in exception dump.
 - selected A20 method now displayed in "verbose" mode only.
 - tool EMSSTAT added.

 08/24/2007: v5.66

 - bugfix: GDT, which has been moved to nonshared space in v5.6, moved
   to shared space again. Required by applications written for the Phar
   Lab TNT DOS extender.

 08/19/2007: v5.65

 - Standard reboot handler made fully MS Emm386 compatible. The ALTBOOT
   option is now a dummy.
 - auto-scanning for a page frame will now ensure that the frame begins
   on a 16 kB boundary. This is MS Emm386 compatible.

 07/12/2007: v5.64

 - bugfix: for FASTBOOT, IVT vectors 78h-7Fh should be reset to 0000:0000.
   This wasn't done.
 - SPLIT option added.

 06/22/2007: v5.63

 - bugfix: NOEMS didn't disable EMS in v5.62
 - bugfix [JemmEx only]: MAXEXT option wasn't displayed in help screen.

 06/19/2007: v5.62

 - bugfix: int 67h, ah=5301h (set handle name) didn't check if this name
   was already assigned (and return status A1h if yes).
 - bugfix: using I=TEST might have reduced amount of UMBs by 4 kB.
 - bugfix: in v5.61, Int 67h, ax=5900h still returned 8 as mapping context
   size, which usually is too small now (# of physical pages are > 4).
 - bugfix: in v5.61, if Jemm was loaded from the command line and 
   remained in low memory, it didn't hook into the driver chain.
 - bugfix: in v5.61, there was a risk that Jemm386 didn't install an
   UMB handler (and then the UMBs were "lost").
 - int 67h, ah=5Bh implemented (alternate map register sets).
 - the EMS system handle is now populated with the mappable pages below
   A000h, as described in EMS 4.0 docs (and also done by MS Emm386).

 06/04/2007: v5.61

 - bugfix: Int 67h, ah=51h (EMS reallocate) might have failed to increase
   the handle's pages although there were enough free pages available.
   This was a design flaw. Now for each EMS handle a linked lists of
   allocated pages is maintained.
 - bugfix: trying to release the NULL handle will now reallocate it with
   size 0. This is the behavior specified in the EMS docs.
 - bugfix: there was a chance that 4 VCPI pages got lost. They could be
   allocated, but weren't found anymore when trying to release them.
 - bugfix: memory for UMBs is no longer contained in EMS system handle 0.
   This handle should only contain pages which "backfill" conventional
   memory (segment addresses below A000h).
 - bugfix: int 67h, ah=56h (alter page map and call) ignored the "old"
   member in the "map_and_call" parameter.
 - value of GDTR, IDTR and TR exposed by Jemm. This allows JLoad to avoid
   usage of opcodes SGDT/SIDT, which caused problems with most virtualizers.
 - allocating a 4kB page with VCPI is now significantly faster.
 - B=xxxx parameter supported. Pages 4000-9FFF are mappable by default.

 05/24/2007: v5.6

 - bugfix: if Jemm had to emulate an IRET in v86-mode and the copy of the
   flag register onto the stack was "invalid" (IOPL != 3), a GPF occured
   at the next IO-sensitive instruction in v86-mode.
 - bugfix [JemmEx only]: NODYN option caused a GPF on initialization.
 - dword and string I/O now simulated correctly for trapped port access.
 - GDT and IDT moved to nonshared memory.
 - the ring 0 stack has been increased to 4 kB and moved to nonshared space.
   This allows "nested execution" without using the client's v86-stack.
 - JLOAD.EXE added. Jemm splitted in 2 packages: binaries and source.
   Some sample JLMs added (XCDROM32, KEYBGR, ...).
 - new EMMXXXX0 function exposes some of Jemm's internal call tables,
   thus allowing external modules (JLOAD) to implement a 32bit ring 0 API.
 - switched to a table-oriented IO-port trapping implementation, which
   allows external modules (JLOAD) to hook/take over port trapping.

 05/04/2007: v5.52

 - bugfix: a bug introduced in v5.5 caused garbage to be displayed if
   option I=B000-B7FF was used.

 05/03/2007: v5.51

 - bugfix [JemmEx only]: XMS memory realloc function (ah=0Fh) caused the
   stack not to be dword-aligned, which slows things down and might cause
   troubles if an interrupt occurs during a memory block move.
 - JemmEx: EMS block moves (int 67h, ah=57h) now also done with interrupt
   window if client's IF is set.

 04/29/2007: v5.5

 - bugfix: if Ctrl-Alt-Del was pressed with FASTBOOT active and an event
   proc for the PS/2 mouse was set, a crash might have occured. Now the
   PS/2 mouse is reset by Jemm before rebooting.
 - bugfix: S=XXXX was ignored if it was the only region to be added as UMBs.
 - in v5.46, FASTBOOT only worked by pressing Ctrl-Alt-Del. Now
   it should work as well if int 19h is called.
 - in v5.46, FASTBOOT always needed ALTBOOT to be set and therefore has set
   this option internally. This is no longer done.
 - JEMMEX.EXE added.
 - JemmEx opens interrupt window in block moves (int 15h, ah=87h and
   XMS function ah=0Bh) each 8 kB if client's IF is set.

 03/27/2007: v5.46

 - bugfix: free EMS pages not always reported correctly.
 - bugfix: translation DMA for 16-bit controller (channels 4-7) didn't work.
 - bugfix: Jemm always displayed "can't continue, please reboot" on
   invalid opcode exceptions in v5.45.
 - MIN= no longer restricted to a maximum of 512 MB (EMS pages still are).
 - FASTBOOT option implemented, JEMFBHLP.EXE added.

 03/02/2007: v5.45

 - bugfix: in v5.40, if no option was entered when installing Jemm, it
   might have displayed some garbage.
 - bugfix: invalid opcode generated by Jemm if running on a cpu < 80386.
 - bugfix: XMS function 11h (free UMB) always returned an error.
 - option UNLOAD added.
 - option RAM/NORAM implemented.
 - valid range for page frame set with FRAME=xxxx now 8000-E000.
 - the MAX= prefix can be omitted now. Makes the cmdline more MS Emm386
   compatible.
 - memory required for UMBs will no longer reduce the memory available for
   EMS. This is similiar to what MS Emm386 does.
 - installing Jemm from the command line now prohibited if a DPMI host
   is detected.

 02/20/2007: v5.4

 - some minor bugfixes.
 - Jemm now moves its resident part to the first UMB which it supplies.
 - NOHI option implemented.
 - Jemm now uses the true (=zero-based) flat memory model.

 01/11/2007: v5.34

 - bugfix: Jemm always hooked int 15h, ah=4Fh, thus always acting as
   if option ALTBOOT was set (bug introduced in v5.25).

 01/06/2007: v5.33

 - bugfix: Jemm erroneously might have disabled EMS
 - reboot code slightly changed, there were still some machines (old 80486?)
   were Ctrl-Alt-Del didn't work.

 11/13/2006: v5.32

 - removed an optimisation which PKZIP didn't like.

 11/09/2006: v5.31

 - some minor bugfixes in function int 67h, ah=57h.
 - bugfix: wrong register contents were displayed in v5.30 for exceptions
   occuring in protected-mode.
 - v86-mode int 06 handler moved to protected-mode, thus further reducing
   Jemm's conventional memory usage.

 10/27/2006: v5.30

 - bugfix: int 67h, ah=57h (move/exchange memory region) didn't always
   invalidate the TLB cache for the EMS memory to copy/exchange.
 - bugfix: int 67h, ax=4F01h didn't work.
 - int 67h, ah=55h/56h implemented.
 - int 67h, ah=57h now works with overlapping memory regions. Furthermore
   it is now ensured that all EMS pages involved in the copy operation are
   valid before copy actually begins.

 10/24/2006: v5.29

 - bugfix: the error msg when the EMS call to map UMBs failed contained
   garbage as "function".
 - int 67h, AH=58h will now return success even with NOEMS.
 - now error code 80h, not 91h is returned if functions int 67h,
   ah=41h or 47h or 48h are called and no page frame is defined.
 - NOINVLPG option added.
 - I=TEST is now a bit less restrictive and will increase compatibility
   with MS-Emm386.
 - help text displayed by Jemm adjusted where it was wrong or unclear.

 10/13/2006: v5.28

 - bugfix, VDS function scatter/gather lock (int 4Bh, ax=8105h): if lower
   12 bits of offset in EDDS were <> 000h, this function always returned
   the first page as a separate region.
 - bugfix, VDS function scatter/gather lock: if this function failed with
   AL=9, it did not always set the correct value for items required to
   describe the full region.
 - bugfix: int 67h, ah=53h (get/set handle name) and ah=54h (get handle
   directory) wrongly assumed that they won't be called with handles other
   than 0000 if NOEMS is set.
 - bugfix: int 67h, ah=57h (move/exchange memory region) didn't work without
   a page frame (NOEMS or FRAME=NONE).

 10/07/2006: v5.27

 - bugfix: allocating a EMS block with zero pages (int 67h, ah=5Ah, bx=0)
   returned with AH=0, but did not return a valid handle in DX.
 - bugfix: calling int 67h, AH=51h modified AL register.

 09/30/2006: v5.26

 - bugfix: VDS functions 03, 04, 07 and 08 may have failed if bit 1 of DX
   was set (request to copy in/out of DMA buffer) and registers BX,CX
   were <> 0.
 - bugfix: 1 kB of DMA buffer may have been inaccessible.
 - bugfix: releasing a DMA buffer with size > 0 and < 1 kB always failed.

 09/22/2006: v5.25

 - bugfix: if option ALTBOOT is set and Ctrl-Alt-Del being pressed has
   been detected, then the real-mode int 15h chain is called first before
   rebooting. This gives other hookers (SmartDrv) a chance to cleanup.

 09/19/2006: v5.24

 - bugfix: int 67h, ax=5001h (implemented in v5.2) didn't work.
 - bugfix: setting Jemm options from the command line did reset
   the options which were not explicitely entered.
 - PGE/NOPGE options added.

 09/14/2006: v5.23

 - bugfix: if the amount of preallocated EMS memory (MIN=xxxx) was
   not below largest XMS memory block - 384 kB, the amount of free/
   available EMS pages reported by Jemm was up to 384 kB too large.
 - implemented VDS function 05 (scatter lock) returning PTEs instead of
   "regions". This makes Jemm fully support the VDS API.
 - some message texts adjusted to make it clear what is an error, a
   warning or just informational.
 - warning about detected system memory region now displays all such
   regions, start and size.
 - if wanted EMS memory has to be reduced, a warning is displayed.
 - UMBM.EXE added.
 - EMX option added.

 09/09/2006: v5.22

 - bugfix: the DMA buffer 64kb alignment may cause up to 32 kB to be lost
   for EMS/VCPI memory. This wasn't taken into account, and may have
   resulted in Jemm unable to alloc UMBs if options NODYN and
   MIN=<value below size of UMBs+32> were set.
 - bugfix: in displayed text "wanted preallocated EMS memory <nnn> kB"
   <nnn> was always blank.
 - space for UMBs now rounded up to next 16 kB boundary (previously it
   was rounded to 32 kB).

 09/07/2006: v5.21

 - bugfix: in v5.2 if an invalid command line parameter was entered, the
   program displayed garbage.
 - bugfix: in v5.2 options setting both options NOEMS and NOVCPI might
   have caused Jemm to run out of memory for UMBs.
 - XMS dynamic memory allocation was automatically disabled if NOEMS and
   NOVCPI options were set, but this is no longer useful since option NODYN
   exists and VCPI can be dynamically set/reset from the command line.
 - DMA buffer size now always rounded up to a full 4 kB boundary.
 - LOAD option added which allows to install Jemm from the command line.

 09/06/2006: v5.2

 - bugfix: writing to "ROM" page FF000 if ALTBOOT wasn't set caused a crash.
 - bugfix: if XMS handle array was in HMA and A20 got disabled results may
   have been "unexpected".
 - bugfix: "disable A20 local" emulation did not return an error code if
   count was already 0.
 - there was slightly more XMS memory allocated than required.
 - support for Int 67h, ax=5001h implemented.
 - option MIN= no longer deactivates XMS dynamic memory allocation.
   option NODYN added, option EMM= discarded.
 - If XMS memory must be preallocated (because XMS host doesn't export its
   handle table) and MIN= option is not set, Jemm allocates half of
   extended memory (but not more than 32 MB) for EMS/VCPI memory.
 - Assembler: MASM may be used instead of TASM.
 - Compiler: Open Watcom WCC or MS VC 1.5 may be used instead of TC.
 - Linker: Digital Mars OPTLINK may be used instead of TLINK.
 - protected-mode code switched to 32-bit.
 - port trapping added to the A20 enable/disable emulation. XMS hook is
   still required due to the "A20 always on" case, which causes most XMS
   hosts not to touch the ports at all.

 08/30/2006: v5.1

 - bugfix: the DMA master mask register was read, which doesn't work
   on all machines and may have caused an "illegal instruction exception"
   if the floppy disk was accessed. This bug was introduced in v5.00.
 - bugfix in EMS function 4Eh.
 - bugfix: A20 emulation works now if no UMB handler has been installed.
 - DMA buffer size may be set by commandline option.
 - VDS functions 07/08 (request/release DMA buffer) and 09/0A (copy
   into/out of DMA buffer) implemented. VDS functions 03/04 (lock/unlock
   region) extended so that they call functions 07/08 if needed.
 - NOVCPI does no longer require NOEMS.
 - ALTBOOT (re)implemented, it hooks int 15h, ah=4Fh now.
 - VME mode may now be set/reset with VME/NOVME options.
 - LIBM.LIB no longer needed to create the JEMM386.EXE binary.

 08/25/2006: v5.01

 - bugfix: "A20 enabled"-count was 0 on startup, should have been 1.
 - bugfix: unsupported VDS functions caused a debug display, which didn't
   work and may have caused corruption of monitor data. Debug displays
   removed.
 - bugfix: original int 4Bh vector may have been 0000:0000 - if this is
   true, it must never be chained to of course. Instead carry flag is set.
 - VDS functions 0Bh and 0Ch (disable/enable translation) implemented.

 08/23/2006: v5.00

 - EMMXXXX0 device communication implemented
 - bugfix: DMA buffer is ensured to begin on a 64 kB physical address
   boundary.
 - bugfix: XMS handles which are no longer used now get the "in pool" flag
   set, not the "free" flag.
 - Pentium+ VME extensions supported.
 - A20 disable emulation activated.

 08/17/2006: v5.00pre

 - bugfix: in VCPI protected mode entry switch to host stack before
   context is switched.
 - command line option S=xxxx added.
 - option NOALTBOOT deleted.
 - the full physical memory is no longer mapped in the address space.
   This reduces extended memory usage a lot on machines with large amounts
   or RAM, since no page tables are needed.
 - VDS code moved to extended memory, reducing conventional memory usage
   by about 1 kB.

---------------------------------------------------------------------

  c't/Harald Albrecht: created the v86 monitor part and EMS functions
  1990

  tom ehlert: implemented UMB support,
  2001-2004   reboot hooks (keyboard ctrl-alt-del, BIOS FFFF:0000)
              int 15h ext memory copy,
              VDS lock function,
              introduced english comments.

  michael devore: implemented support for VCPI, VDS (partially), dynamic
  2004-2006           XMS memory allocation, EMS v4.0 (partially)
  - Modified for >64M and VCPI support
  - Updated for EMS 4.0, some extended API returns unsupported, this will
    change as requested or needed by other software requirements
  - Documented EMS 4.0 only supports up to 32M (0x800 pages), but some EMS
    drivers allow more than 32M.      The EMS 4.0 spec could be extended to 1G-32K
    (map value of 0xFFFF means unmap) without breaking the spec API,
    but unfortunately breaking unsophisticated programs which get confused.
    I have arbitrarily decided to allow up to 32M of EMS allocations,
    leaving the high bit of page allocation alone since specific drivers
    may make use of high bit values other than 0xFFFF for their own purposes,
    or may only check high bit for unmap -- as FreeDOS EMM386 does.
      - Minor English corrections where useful for comprehension

    Michael Devore's changes are not copyrighted and are released
    to the public domain.
    This does not affect copyright on the rest of the code.



================================================
FILE: Html/Readme.html
================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=IBM-850">
<META NAME="author" CONTENT="Japheth">
<META NAME="keywords" content="Jemm386, JemmEx">
</HEAD>
<BODY>
<TABLE BORDER=0 CELLSPACING=4 CELLPADDING=4 WIDTH="100%" HEIGHT="100%">
<TR BGCOLOR=#E0E0E0>
<TD>
<pre>

 Contents

  1.   About Jemm
  2.   Features
  3.   Commandline Options
  4.   Technical Details
  4.1  EMS Implementation Notes
  4.2  Emulation of privileged Opcodes
  4.3  IOPL Sensitive Instructions
  4.4  VMWare Detection
  4.5  Option FASTBOOT
  4.6  Option MAXSEXT
  4.7  Option NOEMS
  4.8  Option SB
  5.   Compatibility
  6.   Errors and Warnings
  7.   Troubleshooting, Hints
  8.   Additional Tools
  8.1  UMBM
  8.2  JEMFBHLP
  8.3  CPUSTAT
  8.4  MEMSTAT
  8.5  XMSSTAT
  8.6  EMSSTAT
  8.7  VCPI
  8.8  MOVEXBDA
  8.9  CPUID
  9.   License


 1. About Jemm

 Jemm is an "Expanded Memory Manager" (EMM), based on the source of FreeDOS
 Emm386. It should work with MS-DOS and compatible DOSes, including FreeDOS.
 Like other EMMs it installs the following services:

 - uses extended memory to simulate expanded memory (EMS) according to 
   EMS v3.2 and EMS v4.0.
 - upper memory blocks (UMB) where drivers and resident programs may
   be loaded, thus increasing available free DOS memory.
 - mapping RAM to the video address segments A000-AFFF and B000-B7FF.
 - VCPI services to allow DOS applications running in V86-mode to
   switch to protected mode. VCPI also implements a simple memory management.
 - VDS API to give drivers/applications some control over DMA and physical
   addresses in V86-mode.

 There exist 2 versions of Jemm:

 - Jemm386: standard version which needs an external eXtended Memory Manager
            (XMM; examples: Himem[S]X, MS Himem, XMGR ) to be loaded.
 - JemmEx:  extended version which has an XMM already included.

 JemmEx most likely is the better choice because it will need less DOS
 memory than an external XMM + Jemm386.


 2. Features

 The main purpose of making Jemm was to make it use less resources than
 other EMMs, without making compromises regarding speed or compatibility.
 The results currently are:

 - Jemm386 needs just 128 bytes DOS upper memory. JemmEx uses more, mostly
   because it includes the XMS handle array which is located in DOS memory.
   With 32 XMS handles JemmEx needs 496 bytes DOS memory.
 - Jemm's extended memory usage is:
   + 44 kB for Jemm itself
   + 64 kB for the DMA buffer (default size)
   + xx kB for UMBs mapped in the first MB
   +  4 kB fixed amount for EMS handle management.
   + xx kB variable amount for EMS/VCPI memory management. For each 1.5 MB
        VCPI memory 64 bytes are needed, for each EMS page 5 bytes are needed.
        For the default values (120 MB VCPI, 2048 EMS pages) this is 16 kB.
 - VCPI shared address space in extended memory is just 4 kB.

 Other features are:

 - Jemm can be loaded and unloaded from the command line. Disadvantage:
   DOS won't care about UMBs supplied this way.
 - CPUs which provide the Virtual-8086 Mode Extensions (Pentium+) are
   actively supported, which increases the emulation speed.
 - the FASTBOOT option shortens reboot time.
 - the SPLIT option can gain additional DOS high memory.
 - all "lengthy" memory copy operations ( EMS, VDS, Int 15h, JemmEx: XMS )
   are done with interrupts enabled.
 - Exceptions in protected-mode are detected and displayed.
 - a (rudimentary) API is supplied which allows to extend Jemm. [ JLoad
   uses this API to add support for 32bit protected-mode extensions (JLMs). ]
 - JemmEx supports XMS v3.5, allowing access to extended memory beyond the
   4 GB barrier. See XMS35.txt for technical details.


 3. Commandline Options

 For a list of available options enter:

 JEMM386/JEMMEX -?

 Option     Comment
 ----------------------------------------------------------
 A20/NOA20  will set the A20 enable/disable emulation accordingly.
 ALTBOOT    this option is meant to select an alternate reboot handler,
            if the standard handler doesn't work. The current implementation
            sends a "system reset" command to the keyboard controller.
 B=xxxx     specify lowest segment address for EMS banking (default=4000,
            min=1000).
 D=nnn      this option will set the size of the DMA buffer to &lt;nnn&gt; kB.
            The default size is 64 kB, max size is 128 kB. Will always be
            rounded up to next 4 kB.
 EMX        option to prevent EMX DOS extender from quickly terminating with
            message "out of memory (RM)" on machines with large amounts
            of RAM (&gt; 256 MB). This is optionally because it makes Jemm
            behave not fully VCPI compliant, but shouldn't hurt usually.
 FASTBOOT   option might allow a fast reboot. There is no guarantee that it
            will work, though, see the "Option FASTBOOT" chapter below.
 FRAME=nnn  instructs Jemm to use a certain page frame. Accepted are frame
            values from 8000 to E000 or NONE. The page frame should start
            at the beginning of a physical EMS page, that is, the frame 
            address should be divisible by 0x400 without remainder. FRAME=NONE
            disables the page frame, but there are quite some programs which
            won't run with this setting. A page frame below A000 should 
            be set only on computers with 512 kB of conventional memory.
            Usually it's better to let Jemm find a page frame on its own, 
            because choosing an address which is not free might cause troubles.
 I=mmmm-nnnn force Jemm to use a memory range for UMBs (or page frame).
            &lt;mmmm&gt; must be &gt;= A000. Specifying a range which is not
            really free may give "unexpected" results.
 I=TEST     scan ROMs for unused address space. This option will regard any
            4 kB page containing identical byte values in read-only memory as
            "unused".
 LOAD       installs Jemm from the command line. Be aware that UMBs
            cannot be provided this way, since DOS will ignore them.
 [MAX=]nnn  limit the maximum amount of memory to be allocated for VCPI (and
            EMS, if &lt;nnn&gt; is below 32 MB). The MAX= prefix is optional (a
            number found as option will be handled as if it has a MAX=
            prefix). Default value is 120 MB.
 MIN=nnn    preallocates &lt;nnn&gt; kB of XMS memory thus making sure this
            memory is truly available for EMS/VCPI. If MIN is higher than
            MAX, MAX will be adjusted accordingly. Default for &lt;nnn&gt; is 0.
 MOVEXBDA   move XBDA into UMB, thus increasing low DOS memory. This option
            may cause a system "lock" because the XBDA might contain buffers
            used for DMA operations. In such cases either use MOVEXBDA.EXE or
            UMBPCI+UMBM instead.
 NOCHECK    disallows access via Int 15h, AH=87h to address regions which
            aren't backuped by RAM. As for Jemm386: be aware that some old 
            XMMs return wrong values for highest physical RAM - then this 
            option may cause strange results. Also, this option may prevent
            real-mode programs from using the VESA LFB.
 NODYN      disables XMS dynamic memory allocation. Jemm will allocate
            XMS memory for EMS/VCPI on initialization. Default is size
            of largest XMS block/2, but max. 32MB. With option MIN=xxx one
            may override this.
 NOEMS      disables EMS support.
 NOHI       this option will prevent Jemm from moving its resident part
            into upper memory. If no UMBs are installed by Jemm, NOHI
            has no effect.
 NOINVLPG   disables usage of INVLPG opcode on 80486+ cpus. Might be useful
            if Jemm runs in a virtual environment (see "Troubleshooting").
 NOVCPI     disables VCPI. Option can be set from the command line.
 NOVMW      disables VMWare detection.
 PGE/NOPGE  options will enable/disable the Page Global Enable feature
            on Pentium Pro+ cpus. This allows to mark all PTEs for the
            real-mode address space 0-110000h as "global", which gives
            a slight speed benefit for VCPI applications. Option is off by
            default because some DOS extenders will not work with PGE
            enabled. Also setting both PGE + NOINVLPG will not work.
 RAM/NORAM  will instruct Jemm to supply UMBs or not. RAM is the default.
            NORAM is intended to be used when loading Jemm from the
            cmdline, in which case adding UMBs might be less useful.
 S=mmmm-nnnn add a memory region (which must be in range C800-EFFF) as UMB.
            The memory region has to be filled with Shadow-RAM activated by
            UMBPCI, which must have been loaded *before* Himem/JemmEx.
            NOTE: since v5.80, this option is virtually obsolete, because
            either Jemm should find RAM activated by UMBPCI automatically, or,
            if UMBM.EXE has been loaded in CONFIG.SYS, the RAM is already used
            by DOS.
 SB         Soundblaster driver compatibility mode on.
 SPLIT      if ROMs are found which don't end exactly at a 4 kB boundary
            then setting this option will increase available UMB space. ROM
            sizes are defined in 0.5 kB units, so there might be up to 3.5 kB
            wasted in the ROM's last 4 kB page. There is a small catch: the
            full 4k page will be made writeable, including the ROM part.
 UNLOAD     uninstalls Jemm from the command line. Uninstalling the EMM
            might confuse resident programs which rely on EMS or VCPI but
            didn't ensure this configuration to keep unchanged (by allocating
            an EMS page) while they are running.
 V86EXC0D   makes Jemm route General Protection Faults (GPF) that occur in
            V86-mode to Int 0Dh. Without this option they are routed to
            Int 06h. This option should only be set if a resident program
            is to be installed that can handle GPFs in V86-mode.
 VCPI       (re)enables VCPI. Option can be set from the command line.
 VERBOSE    talk a bit more during the load process (abbreviation: /V).
 VME/NOVME  options will enable/disable using the V86 Mode Extensions
            on Pentium+ CPUs. These options can be set from the command line.
            NOVME is the default.
 X=mmmm-nnnn exclude a memory range to be used as UMBs or page frame.
            &lt;mmmm&gt; must be &gt;= A000.
 X=TEST     will exclude all upper memory regions which contain byte values
            other than 00 or FF.

 JemmEx additionally understands:

 A20METHOD:x   select A20 switch method.
               Possible values for &lt;x&gt;:
               ALWAYSON    Assume that A20 line is permanently ON
               BIOS        Use BIOS to toggle the A20 line
               FAST        Use port 92h, bypass INT 15h test
               PS2         Use port 92h, bypass PS/2 test
               KBC         Use the keyboard controller
               PORT92      Use port 92h always
 HMAMIN=k      set minimum amount in kB to get the HMA (default=0, max=63).
 MAXEXT=l      limit extended memory controlled by XMM to &lt;l&gt; kB.
 MAXSEXT=l     limit extended memory beyond 4GB barrier ("super-extended") to
               &lt;l&gt; kB; setting MAXSEXT=0 will make JemmEx behave like a
               v3.0 XMM.
 NOE801        don't use int 15h, ax=E801h to get amount of extended memory.
 NOE820        don't use int 15h, ax=E820h to get amount of extended memory;
               option is ignored unless MAXSEXT=0 is set.
 X2MAX=m       limit for free extended memory in kB reported by XMS V2 
               (default 65535). It is reported that some old applications
               need a value of &lt;m&gt;=32767.
 XMSHANDLES=n  set number of XMS handles (default=48, min=10, max=128).


 4. Technical Details

 4.1 EMS Implementation Notes

 - The number of EMS pages is limited to 2048 (= 32 MB). It can be increased
   up to 32768 pages (= 512 MB) by setting MIN=&lt;nnn&gt; to a value higher than
   32 MB. However, this memory will then be preallocated, and not be available
   as XMS memory. Some applications will not work if EMS &gt; 32 MB.

 - There is one memory pool, which is shared by EMS and VCPI.

 - The following EMS 4.0 functions aren't implemented. Calling these
   functions will return error code 84h in register AH:

   + Int 67h, AH=5Ch, prepare expanded memory manager hardware for warm boot
   + Int 67h, AH=5Dh, enable/disable OS/E


 4.2 Emulation of privileged Opcodes

 To provide Expanded Memory an EMM Emulator like Jemm runs the cpu in
 so-called V86-mode. This mode does not allow to run privileged opcodes.
 Some of these opcodes which might be useful for application programs
 are emulated by Jemm. These are:

 - mov &lt;special_reg&gt;, &lt;reg&gt;   ;special_reg = CRn, DRn, TRn
 - mov &lt;reg&gt;, &lt;special_reg&gt;   ;reg = eax, ebx, ecx, edx, esi, edi, ebp
 - WBINVD
 - INVD
 - WRMSR
 - RDMSR
 - RDTSC
 - HLT

 Those instructions may generate an exception 0x0D if they occur in V86-mode
 ( for RDTSC, this depends on a bit in register CR4 ). Jemm's exception handler
 examines the opcode causing the exception and - if the instruction is to be
 "emulated" - runs it in ring 0.


 4.3 IOPL Sensitive Instructions

 Jemm runs V86-mode code with IOPL 3. That means, the instructions that are
 sensitive to IOPL in V86-mode - CLI, STI, PUSHF, POPF, INT xx, IRET - will
 run at full speed, without causing a GPF.


 4.4 VMWare Detection

 As default, Jemm tries to detect if it's running under VMWare. This is done
 by reading port 0x5658 with value "VMXh" in register EAX. If the detection
 is successful, Jemm assumes that address range E8000-EFFFF is not to be used.
 However, range E8000-EBFFF may still be included with the "I=" option.

 The VMWare detection can be disabled with option NOVMW.


 4.5 Option FASTBOOT

 The FASTBOOT option may work with many versions of DOS. However, there are
 quite a few restrictions. To speed up the boot process, FASTBOOT tries to
 avoid resetting the system. This implicates that the interrupt vector table
 and at least the disk devices can be reset to the state before DOS has been
 loaded. Resetting the interrupt vector table requires some cooperation from
 DOS. Other things that may get in the way are:

 - Moving the XBDA into an UMB with option MOVEXBDA is critical, because to
   move it back into conventional memory might not work for various reasons.

 - older FreeDOS versions may need JEMFBHLP.EXE to be installed prior to the
   XMM (Himem). Possibly this might also be needed for MS-DOS versions &lt; 5.

 - UMBPCI allows to activate "Shadow RAM", but there's no option to deactivate
   it. This may confuse Jemm, since it can only detect RAM activated by UMBPCI
   if UMBPCI's signature is found.

 - A boot loader (Grub) might have inserted code in conventional memory to
   modify hard disks numbers. There's no guarantee that this code survives the 
   fastboot process.


 4.6 Option MAXSEXT

 JemmEx only: this option limits amount of "super-extended" memory. Setting
 MAXSEXT=0 disables this feature. If enabled, JemmEx must exclusively manage
 this type of memory; to achieve this, interrupt 15h, AX=0xE820 is hooked and
 any memory region beyond 4 GB that's marked as available is changed to
 "reserved" ( tool MEMSTAT may be used to verify this behavior ).


 4.7 Option NOEMS

 Despite its name, this option does not fully disable EMS. What's done is:

 - device name changed from EMMXXXX0 to EMMQXXX0
 - no page frame installed
 - EMS memory pool is limited to 8 MB

 The change of the device name makes the usual EMM detection routines fail.
 OTOH, the interrupt 67h API is fully functional. Most of this is pretty
 similar to what "recent" MS Emm386 versions do - the only difference is
 that they won't limit the memory pool to 8 MB, but install it in its full
 size (32 MB).


 4.8 Option SB

 Option SB is supposed to help Creative's SoundBlaster emulation drivers for
 SB PCI devices. It does 2 things:

 a) It translates an exception 0Dh with error code 0x1A that may have occured
    in V86 mode to an INT 3. It's unclear what this is supposed to fix.
 b) Since v5.86, it "identity maps" region 0-0x3fffff in the first page table.
    This mapping was done generally until v5.85.

 With b), Creative's SBINIT/SBEINIT tools should again be compatible with Jemm.
 However, due to the rather hackish nature of those drivers ( they modify
 Jemm's IDT/GDT and page tables ), one may experience negative effects on
 stability.


 5. Compatibility

 Jemm is NOT an MS Emm386 clone. Differences are:
<UL> 
<LI> - obviously commandline options differ.
</LI>
<LI> - the device driver API, accessed by opening file "EMMXXXX0" and
   then issueing IOCTL cmds, differs.
</LI>
<LI> - Jemm doesn't support the so-called GEMMIS API.
</LI>
<LI> - Jemm doesn't support the IO port trapping API of MS Emm386.
</LI>
<LI> - Jemm supports UMBs (Upper Memory Blocks) accessed via the XMS API, but the
   management is different: unlike MS Emm386, there's no chain of UMBs, linked
   with a 16-byte header ( somewhat similar to DOS MCBs ). Instead, the UMB
   addresses and sizes are stored in a table in extended memory, not accessible
   by external programs. The table can hold up to 8 blocks.
</LI>
<LI> - MS Emm386 tries to map all of physical memory in its linear address space,
   in such a way that linear and physical addresses are identical. This isn't
   done by Jemm, because it may consume quite a lot of physical memory for paging
   tables - at least if 4KB pages are used, as it is the case with MS Emm386.
   See option SB, though, which triggers this kind of mapping for the first 4 MB.
</LI>
<LI> - Both Jemm and MS Emm386 supply the NOVCPI commandline option. However, the
   effects differ: with Jemm, VCPI function DE01h will be deactivated by this
   option, thus refusing to start any VCPI client. In contrast, MS Emm386's
   NOVCPI makes the monitor still offer the full API, but no VCPI memory can
   be allocated.
</LI>
</UL>


 6. Errors and Warnings

 Errors will make Jemm386/JemmEx abort the load process, while warnings
 will be displayed and then the load process continues.

 - "Error: no XMM found, required"
   Jemm386 only. Jemm386 needs an XMM - try Himem(S)X.

 - "Error: XMM already installed"
   JemmEx only. Since JemmEx has its very own XMM, it cannot tolerate
   another one in the system.

 - "Error: DPMI host detected"
   Both Jemm386 and JemmEx refuse to load if a DPMI host has been detected.

 - "Error: No supported A20 method detected"
   JemmEx only. JemmEx is NOT compatible with this system.

 - "Error: enable A20 failed"
   JemmEx only. JemmEx is NOT compatible with this system.

 - "Error: can't get I15 memory status"
   JemmEx only. Int 15h, AX=E820h ( and the fallbacks, Int 15h,
   ax=E801h/ah=88h ) failed or returned an amount of 0 kB extended memory.
   Tool memstat may help to find the problem.

 - "Error: can't get XMS memory status"
   Jemm386 only. The XMS host reports no extended memory. Tool xmsstat
   may give a hint what's wrong.

 - "Error: can't allocate enough I15 memory"
   JemmEx only. Run tool memstat to see how much extended memory the
   system is reporting.

 - "Error: can't allocate enough XMS memory"
   Jemm386 only. Run tool xmsstat to see how much extended memory the
   XMM is reporting.

 - "Error: can't lock XMS memory"
   Jemm386 only. Well, this shouldn't happen. Jemm386 needs the physical
   address of the memory block where it is to reside. The XMM most likely has
   to be replaced.

 - "Warning: unknown A20 method"
   JemmEx only. Option A20METHOD was given with an invalid method.

 - "Warning: option 'xxx=' rejected, invalid syntax"
   The option is ignored.

 - "Warning: E820 - too many ext memory blocks, block xxxxxxxx ignored!"
   JemmEx only. Occurs if int 15h, ax=e820h returns more than 10 available
   memory blocks. It's very well possible that super-extended memory isn't
   available if this warning has occured. The only cure is to adjust constant
   ?XMS_STATICHDLS in file jemm16.inc and recompile JemmEx.

 - "Warning: address of allocated EMB (=XXXXXX) is beyond 16MB" 
   Jemm386 only. Means that Jemm386 is forced to reside beyond the physical
   16MB barrier. No problem for Jemm386 itself, but the VDS API requires a
   DMA buffer that is located below that 16MB barrier. So one is better off not
   to ignore this warning. To fix it: a) ensure that Jemm386 is loaded just
   after the XMM; b) replace the XMM, use HimemX2.exe instead of HimemX.exe
   (if an extended memory block is allocated, HimemX2 tries to return the
   block with the lowest address that satisfies the request).

 - "Warning: no suitable page frame found, EMS functions limited."
   Most programs using EMS won't work without a page frame, so this warning
   should not be ignored. To analyze the problem, a first step may be to load
   Jemm from the command line, with the /V option to see why it cannot find a
   64 kB region to be used as page frame. Possible reasons are:
    - UMBPCI is used. Memory regions activated by UMBPCI are detected by Jemm
      and hence won't be used for mapping the Page Frame.
    - BIOS marks 128 kB ( E0000-FFFFF ) as reserved in Int 15h, ax=E820h.
    Using the video segment A000 as page frame is useful only for very specific
   applications and cannot be recommended. Using regions below A000 are even
   more problematic on machines with 640 kB conventional memory, since the
   address range is already "owned" by DOS. 
    If it's not possible to make Jemm use a valid page frame, it should be setup
   with option NOEMS.

 - "Warning: EMS banking start too low, set to 0x1000."
   This warning only occurs if option B=xxxx has been used inappropriately.

 - "Warning: MIN has been reduced to n kB"
   Warning occurs if the amount given for MIN exceeds available free memory. 

 - "Warning: wanted DMA buffer size too large, set to 128 kB"
   Warning occurs if option D=nnn has been used with a value larger than
   the maximum of 128 (kb).

 - "Warning: XMS host doesn't provide handle array, dynamic memory allocation off!"
   Jemm386 only. Jemm wants the XMM to reveal its handle table. If this feature
   isn't available, Jemm has to allocate its memory for EMS and VCPI statically
   on startup.


 7. Troubleshooting, Hints

 - If Jemm halts or reboots the machine, the following combinations
   of parameters may help to find the reason. Generally, Jemm386 should be
   loaded immediately after the XMM (HIMEM[S]X.EXE, HIMEM.SYS), and the XMM
   itself should be the first device driver to be loaded. For testing, it
   might also help to prevent DOS from loading in the HMA and/or not to
   use UMBs at all.

   - X=A000-FFFF NOHI NOINVLPG

     This is the safest combination. If this doesn't work, Jemm most
     likely isn't compatible with the current DOS/BIOS; for example,
     the BIOS might try to unconditionally use "unreal" mode to access
     USB mass storage devices - with Jemm, this will cause an exception.

   - X=TEST NOHI NOINVLPG

     This is slightly less safe, since Jemm will scan the upper memory
     region to find "unused" address ranges usable for UMBs. If this
     doesn't work, one has to manually set X=xxxx-yyyy to finally
     find the region which causes the troubles. Tool MEMSTAT may be used
     to find the address region which is reserved for the ROM-BIOS.

 - Jemm can be loaded from the command line with option LOAD. This may be
   helpful if there are so many displays during the boot process that one
   cannot read them carefully. Also, option /V should be added to make
   Jemm talkative. To load Jemm386 from the command line, ensure that a
   XMM has been loaded previously. For JemmEx, no XMM must be loaded, since
   it is included.

 - Jemm has been verified to run on the following virtual environments:

    Qemu, VMware, VirtualPC, Bochs, VirtualBox

   However, it might be necessary to set option NOINVLPG.

 - Some DOS programs will not work if EMS is enabled without a page frame.
   MS CodeView v4.1, for example, may refuse to start then.

 - Some DOS programs will crash if too much VCPI memory is offered. Jemm's
   default is 120 MB, it can be changed with option MAX=xxx. Popular
   programs that may cause troubles are programs that use Borland's DPMI hosts
   DPMI16BI.OVL/DPMI32VM.OVL (coupled with RTM.EXE/32RTM.EXE). Setting Jemm
   option MAX=32752K ( that's 32MB minus 16kB) should help; alternately, try
   setting environment variable "DPMIMEM=MAXMEM 16383".

 - The JEMM ;-) DOS extender (used for "Strike Commander" and "Privateer")
   isn't compatible with the VME option. This requirement is a strong sign
   that this extender switches to V86 mode on its own, which is a bad idea
   for a VCPI client.

 - Unlike MS Emm386, Jemm does not try to identity-map extended memory in its
   address space. This prevents the PL0 debugger 386SWAT from "intruding".

 - If Jemm is installed from the commandline, loading the CTMOUSE driver
   v1.9x and v2.0x might cause an exception. Adding option NOHI or NORAM
   when installing Jemm should avoid that. In CTMOUSE v2.1 the bug has
   been fixed.

 - With some BIOSes disk access speed slows down significantly in V86-mode.
   Most likely this is because the BIOS routines want to avoid using DMA in
   this mode. Loading XDMA32 ( and XCDROM32 ) might fix that.

 - FreeDOS regrettably accepts just one UMB provider. This makes it impossible
   for example to use UMBM.EXE to supply UMB D000-DFFF and then tell Jemm to
   additionally supply B000-B7FF as UMB. MS-DOS has no such problems.

 - Although including the region B000-B7FF might work in most cases, one
   should be aware that this region is not really free, it's used by the
   VGA "monochrome" video modes.

 - To make Jemm behave (almost) like MS Emm386 regarding UMBs one should
   set both options X=TEST and I=TEST. For better MS Emm386 compatibility
   one might also consider to restrict VCPI memory to 32 MB by adding
   option MAX=32M. If NODYN is used, one should also set at least MIN=256K.

 - The NOVCPI option may be used to setup an environment similiar to Windows
   DOS boxes:
   - install Jemm with VCPI enabled
   - install a DPMI host residently (HDPMI, DPMIONE, ...)
   - disable VCPI with the NOVCPI option
   This forces any DOS extended application to either use DPMI or abort.

 - If Jemm displays warning

     System memory found at XXXX-XXXX, region might be in use

   then that region is not used by Jemm. If you are sure that the region
   is ok to be used, include it with 'I=XXXX-XXXX'.

 - The I=XXXX commandline option may be used to include the VGA "graphics"
   segment A000h. It might be possible to increase DOS conventional memory
   up to 736 kB by option I=A000-B7FF. However, there are quite a few
   hurdles that may cause unexpected results:
   - conventional memory is increased only if the region to include is
     adjacent to current memory. On newer machines, there's very often a
     "hole", caused by the Extended BIOS Data Area (XBDA or EBDA); thus
     the included region just becomes an UMB and won't increase lower memory.
     Option MOVEXBDA or tool MOVEXBDA.EXE may fix this issue.
   - Once address space A000h is remapped, any attempts to run programs that
     use VGA graphics most likely will cause a crash.
   - Depending on the VGA-BIOS it may happen that some non-graphics functions
     won't work anymore and may also cause a crash. Not unusual is that the 
     current text font becomes corrupted ( text font bitmaps must be copied 
     from ROM to VGA memory when a video text mode is set ).
   - DOS conventional memory cannot be increased anymore once UMB have been 
     added to the DOS memory pool. So you cannot use tool UMBM here!
   - if MOVEXBDA.EXE causes a system lock during boot, add the /A option to 
     the line in CONFIG.SYS that loads the driver. This aligns the XBDA to 
     a kB boundary, which may cure the lock.
   - the GRUB boot loader may, under certain conditions, allocate a chunk
     of conventional memory BELOW the XBDA. In this case conventional memory
     cannot be increased anymore, even if the XBDA is moved.


 8. Additional Tools

 8.1 UMBM

 UMBM is a small tool only useful in conjunction with Uwe Sieber's UMBPCI.
 The main purpose of UMBM is to allow DOS to load the XMM into upper memory.
 This driver must be loaded before Jemm386 and therefore DOS can't use UMBs 
 provided by Jemm386. For JemmEx, UMBM is usually not needed, since the XMM is 
 included and needs no low memory.

 How does UMBM work? It expects to find a "shadow" RAM region activated by
 UMBPCI. Then it installs inself as a temporary XMS host which just provides
 support for allocating UMBs. This is enough for most DOSes to grab the
 memory (note: for this to work line DOS=UMB is required in CONFIG.SYS). After
 the UMBs have been allocated, UMBM will be removed from memory automatically.

 Additionally, UMBM understands the /XBDA option. This will cause UMBM
 to move the XBDA into its first UMB, thus freeing even more low DOS memory.
 
 UMBs based on "shadow" RAM, as it is supplied by UMBPCI+UMBM, may have
 limitations depending on the motherboard's chipset. Sometimes the memory
 is inaccessible for DMA (read the documentation coming with UMBPCI for more
 details). OTOH, logical and physical addresses for these UMBs are identical,
 which may be an advantage, especially for the XBDA. 

 Enter "UMBM" on the command line and read the example how to add UMBM
 to CONFIG.SYS. UMBM has been tested to run with MS-DOS 6/7 and FreeDOS.


 8.2 JEMFBHLP

 JEMFBHLP is a tiny device driver only needed if both FreeDOS and Jemm's
 FASTBOOT option are used. FreeDOS v1.0 does not provide the information
 that Jemm needs for FASTBOOT to work, so this driver tries to cure FreeDOS'
 incapability. It saves the values for interrupt vectors 15h and 19h at
 0070h:0100h, which is the MS-DOS compatible way to do it.

 In more recent FreeDOS versions this problem has been fixed.


 8.3 CPUSTAT

 CPUSTAT displays some system registers and tables. Most of the registers
 aren't accessible in v86-mode, so - for Jemm - this program may be seen as
 a test if the emulation of privileged opcodes works as expected.

 Optionally, if cpu runs in V86-mode, CPUSTAT may display GDT, IDT, paging
 tables and informations stored in the task state segment of the v86-monitor.
 Run "CPUSTAT -?" for more details.


 8.4 MEMSTAT

 MEMSTAT may be used to display the machine's memory layout, as it is
 returned by the BIOS. The most interesting infos are:

 - address region reserved for the ROM-BIOS
 - total amount of free memory


 8.5 XMSSTAT

 XMSSTAT can be used to display the current status of the installed XMM.
 It allows to check current values of JemmEx options X2MAX, MAXEXT and
 XMSHANDLES.


 8.6 EMSSTAT

 EMSSTAT can be used to display the current status of the installed EMM.
 It works with any EMM, not just Jemm.


 8.7 VCPI

 VCPI may be used to display the VCPI status of the installed EMM.
 With option -p it will display the page table entries for the conventional
 memory.


 8.8 MOVEXBDA

 MOVEXBDA is a device driver supposed to move the Extended BIOS Data
 Area ( XBDA or EBDA ) to low DOS memory. If an XBDA exists, it is usually
 located just below the A000 video segment, with a size of 1-12 kB.

 Some DOS versions will move the XBDA on their own - at least if its size
 doesn't exceed 1 kB; then MOVEXBDA is not needed and will do nothing if 
 launched. Also, both JemmEx and UMBM have the ability to move the XBDA as 
 well; those tools move the XBDA to upper memory, thus increasing low DOS 
 memory. However, sometimes MOVEXBDA may be the best option available -
 because moving the XBDA into an UMB supplied by Jemm (or UMBPCI) may cause
 the system to "lock".

 MOVEXBDA should work with any EMM.


 8.9 CPUID

 CPUID displays cpu features returned by the CPUID instruction.


 9. License

 - JEMM386/JEMMEX: partly Artistic License (see ARTISTIC.TXT for details)
 - UMBM:     Public Domain
 - JEMFBHLP: Public Domain
 - CPUSTAT:  Public Domain
 - MEMSTAT:  Public Domain
 - XMSSTAT:  Public Domain
 - EMSSTAT:  Public Domain
 - VCPI:     Public Domain
 - MOVEXBDA: Public Domain
 - CPUID:    Public Domain

 Binaries and source are distributed in separate packages. The binaries'
 package has a 'B' suffix in its name, the package containing the source
 has a 'S'.

 Japheth

</pre>
</TD></TR>
</TABLE>
</BODY>
</HTML>


================================================
FILE: Include/FILEACC.INC
================================================

;--- dos file access for JLMs
;--- although addresses are linear, they must
;--- be within 64 kB distance of v86 DS register.

w	textequ <word ptr>

;--- open file (for reading)
;--- edx = file name
;--- out: ax=handle

OpenFile proc
	movzx eax,word ptr [ebp].Client_Reg_Struc.Client_DS
	shl eax, 4
	sub edx, eax
	mov w [ebp].Client_Reg_Struc.Client_EDX, dx
	mov w [ebp].Client_Reg_Struc.Client_EAX, 3D00h
	mov eax,21h
	@VMMCall Exec_Int
	mov ax,w [ebp].Client_Reg_Struc.Client_EAX
	bt [ebp].Client_Reg_Struc.Client_EFlags,0
	ret
OpenFile endp

;--- close file
;--- ebx = file handle

CloseFile proc
	mov w [ebp].Client_Reg_Struc.Client_EBX, bx
	mov w [ebp].Client_Reg_Struc.Client_EAX, 3E00h
	mov eax,21h
	@VMMCall Exec_Int
	bt [ebp].Client_Reg_Struc.Client_EFlags,0
	ret
CloseFile endp

;--- get file size
;--- ebx = file handle
;--- out: eax=file size

GetFileSize proc
	mov w [ebp].Client_Reg_Struc.Client_EBX, bx
	mov w [ebp].Client_Reg_Struc.Client_EAX, 4202h   ;goto EOF
	mov w [ebp].Client_Reg_Struc.Client_ECX, 0
	mov w [ebp].Client_Reg_Struc.Client_EDX, 0
	mov eax,21h
	@VMMCall Exec_Int
	bt [ebp].Client_Reg_Struc.Client_EFlags,0
	jc exit
	mov ax, w [ebp].Client_Reg_Struc.Client_EDX
	shl eax, 16
	mov ax, w [ebp].Client_Reg_Struc.Client_EAX
	push eax
	mov w [ebp].Client_Reg_Struc.Client_EAX, 4200h	 ;goto start
	mov w [ebp].Client_Reg_Struc.Client_ECX, 0
	mov w [ebp].Client_Reg_Struc.Client_EDX, 0
	mov eax,21h
	@VMMCall Exec_Int
	pop eax
	bt [ebp].Client_Reg_Struc.Client_EFlags,0
exit:
	ret
GetFileSize endp

;--- Read file into buffer
;--- bx = file handle
;--- cx = bytes to read
;--- edx = buffer (in conv. memory)
;--- out: eax=bytes read

ReadFile proc
	movzx eax,w [ebp].Client_Reg_Struc.Client_DS
	shl eax, 4
	sub edx, eax
	mov w [ebp].Client_Reg_Struc.Client_EBX, bx
	mov w [ebp].Client_Reg_Struc.Client_ECX, cx
	mov w [ebp].Client_Reg_Struc.Client_EDX, dx
	mov w [ebp].Client_Reg_Struc.Client_EAX, 3F00h
	mov eax,21h
	@VMMCall Exec_Int
	movzx eax, w [ebp].Client_Reg_Struc.Client_EAX
	bt [ebp].Client_Reg_Struc.Client_EFlags,0
	ret
ReadFile endp



================================================
FILE: Include/FINDRES.INC
================================================

?NOCASEMAP	equ 0	;win32 std is 0

;--- eax = resource directory
;--- id may be an id (HIWORD=0) or a string pointer

;--- used by EnumResourceXXX as well !!

ScanResDir proc public uses esi pRes:DWORD, dwDir:DWORD, id:DWORD

	mov esi, pRes
	add esi, dwDir
	movzx ecx, [esi].IMAGE_RESOURCE_DIRECTORY.NumberOfNamedEntries
	mov eax, id
	.if (eax & 0FFFF0000h)
		.if (byte ptr [eax] == '#')
			lea edx,[eax+1]
			call GetNumber
			jmp ok
		.endif
		lea esi, [esi + sizeof IMAGE_RESOURCE_DIRECTORY]
		.while (ecx)
			mov edx, [esi].IMAGE_RESOURCE_DIRECTORY_ENTRY.Name_
			and edx, edx
			.if (SIGN?)
				and edx, 7FFFFFFFh
				add edx, pRes
				pushad
				mov esi, edx
				mov edi, eax
				lodsw
				movzx ecx, ax
@@:
if ?NOCASEMAP
				lodsw
				scasb
else
				lodsw
				call ToLower
				mov ah,al
				mov al,[edi]
				inc edi
				call ToLower
				cmp al,ah
endif
				loopz @B
				popad
				.if (ZERO? && (byte ptr [edi] == 0))
					mov eax, [esi].IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData
					jmp done
				.endif
			.endif
			add esi, sizeof IMAGE_RESOURCE_DIRECTORY_ENTRY
			dec ecx
		.endw
		jmp error
	.endif
ok:
	push eax
	mov eax, sizeof IMAGE_RESOURCE_DIRECTORY_ENTRY
	mul ecx
;-------------------- let esi point to resources with id entries
	movzx ecx, [esi].IMAGE_RESOURCE_DIRECTORY.NumberOfIdEntries
	lea esi, [esi + eax + sizeof IMAGE_RESOURCE_DIRECTORY]
	pop eax
	.while (ecx)
		.if ((ax == [esi].IMAGE_RESOURCE_DIRECTORY_ENTRY.Id) || (ax == 0))
			mov eax, [esi].IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData
			jmp done
		.endif
		add esi, sizeof IMAGE_RESOURCE_DIRECTORY_ENTRY
		dec ecx
	.endw
error:
	xor eax, eax
done:
	ret
ife ?NOCASEMAP
ToLower:
	cmp al,'A'
	jb @F
	cmp al,'Z'
	jae @F
	or al,20h
@@: 
	retn
endif
GetNumber:
	push ebx
	xor eax, eax
	.while (byte ptr [edx])
		movzx ebx,byte ptr [edx]
		inc edx
		sub bl,'0'
		add eax, eax
		push eax
		shl eax, 2
		add eax, [esp]
		add eax, ebx
		pop ebx
	.endw
	pop ebx
	retn
	align 4

ScanResDir endp

;--- hiword of lpName and lpType may be NULL
;--- in this case it is an integer identifier

FindResourceA proc public uses esi edi hModule:DWORD, lpName:DWORD, lpType:DWORD

	mov esi, hModule
	.if (!esi)
		invoke GetModuleHandle, esi
		mov esi, eax
		mov hModule, eax
	.endif

	add esi, [esi].IMAGE_DOS_HEADER.e_lfanew
	mov edi, [esi].IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
	mov edx, [esi].IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE * sizeof IMAGE_DATA_DIRECTORY].Size_
	.if (edi)
		add edi, hModule
		invoke ScanResDir, edi, 0, lpType
		.if (eax)
			and eax, eax
			.if (SIGN?)
				and eax, 7FFFFFFFh
				invoke ScanResDir, edi, eax, lpName
				.if (eax)
					and eax, eax
					.if (SIGN?)
						and eax, 7FFFFFFFh
						invoke ScanResDir, edi, eax, 0
						.if (eax)
							add eax, edi
							jmp done
						.endif
					.else
						add eax, edi
						jmp done
					.endif
				.endif
			.endif
		.endif
	.endif
error:
	xor eax, eax
done:
if 0;def _DEBUG
	@trace <"FindResourceA(">
	@tracedw hModule
	@trace <", ">
	.if (word ptr lpName+2) 
		@trace lpName
	.else
		@tracedw lpName
	.endif
	@trace <", ">
	.if (word ptr lpType+2) 
		@trace lpType
	.else
		@tracedw lpType
	.endif
	@trace <")=">
	@tracedw eax
	@trace <13,10>
endif

	ret
	align 4

FindResourceA endp

;--- attention: name and type are exchanged!

FindResourceExA proc public hModule:DWORD, lpType:DWORD, lpName:DWORD, wLanguage:DWORD

	invoke FindResourceA, hModule, lpName, lpType
;	@strace <"FindResourceExA(", hModule, ", ", lpType, ", ", lpName, ", ", wLanguage, ")=", eax>
	ret
	align 4

FindResourceExA endp

LoadResource proc public hModule:DWORD, hres:DWORD

	.if (!hModule)
		invoke GetModuleHandle, hModule
		mov hModule, eax
	.endif
	mov eax, hres
	.if (eax)
		mov eax, [eax].IMAGE_RESOURCE_DATA_ENTRY.OffsetToData
		add eax, hModule
	.endif
;	@strace <"LoadResource(", hModule, ", ", hres, ")=", eax>
	ret
	align 4

LoadResource endp

LockResource proc public hres:DWORD

	mov eax,hres
;	@strace <"LockResource(", hres, ")=", eax>
	ret
	align 4

LockResource endp

FreeResource proc public hres:DWORD

	mov eax,1
;	@strace <"FreeResource(", hres, ")=", eax>
	ret
	align 4

FreeResource endp

SizeofResource proc public hModule:DWORD, hres:DWORD

	mov eax, hres
	.if (eax)
		mov eax, [eax].IMAGE_RESOURCE_DATA_ENTRY.Size_
	.endif
;	@strace <"SizeofResource(", hModule, ", ", hres, ")=", eax>
	ret
	align 4

SizeofResource endp



================================================
FILE: Include/JLM.H
================================================

/* Header file for Jemm JLMs which defines the subset of the Win3x/Win9x */
/* ring 0 API (VMM) that Jemm/JLoad exposes.                             */
/* The parameters and return values of the functions are the same as in  */
/* the Windows implementation, register usage is as in Win32: EAX, ECX   */
/* and EDX may be modified inside functions, the other registers are     */
/* preserved (exception: Get_Cur_VM_Handle).                             */

typedef unsigned char   UCHAR;
typedef unsigned short  USHORT;
typedef unsigned long   ULONG;

struct Pushad_Struc {
    ULONG Pushad_EDI;       /* Client's EDI */
    ULONG Pushad_ESI;       /* Client's ESI */
    ULONG Pushad_EBP;       /* Client's EBP */
    ULONG Pushad_ESP;       /* ESP before pushad */
    ULONG Pushad_EBX;       /* Client's EBX */
    ULONG Pushad_EDX;       /* Client's EDX */
    ULONG Pushad_ECX;       /* Client's ECX */
    ULONG Pushad_EAX;       /* Client's EAX */
};

#define VMM_DEVICE_ID       0x00001
#define VDMAD_DEVICE_ID     0x00004

#define GetVxDServiceOrdinal(service)   __ ## service


#define Begin_Service_Table(device, seg) \
    enum device##_SERVICES { \
    device##_dummy = (device##_DEVICE_ID << 16) - 1,

#define Declare_Service(service) \
    GetVxDServiceOrdinal(service),

#define Declare_SCService(service, args, local) \
    GetVxDServiceOrdinal(service),

#define End_Service_Table(device, seg) \
    Num_##device##_Services};

#define VXDINLINE static __inline

/*  */

#define GetVxDServiceAddress(service)   service

#ifdef __WATCOMC__

// Open Watcom C currently can't call the VMM services directly
// because ENUM values aren't accessible by the inline assembler.

#define VxDCall(service) \
    _asm int 20h \
    _asm dd (GetVxDServiceOrdinal(service) ) \

#define VxDJmp(service) \
    _asm int 20h \
    _asm dd (GetVxDServiceOrdinal(service) | 0x8000 ) \

#else

#define VxDCall(service) \
    _asm _emit 0xcd \
    _asm _emit 0x20 \
    _asm _emit (GetVxDServiceOrdinal(service) & 0xff) \
    _asm _emit (GetVxDServiceOrdinal(service) >> 8) & 0xff \
    _asm _emit (GetVxDServiceOrdinal(service) >> 16) & 0xff \
    _asm _emit (GetVxDServiceOrdinal(service) >> 24) & 0xff \

#define VxDJmp(service) \
    _asm _emit 0xcd \
    _asm _emit 0x20 \
    _asm _emit (GetVxDServiceOrdinal(service) & 0xff) \
    _asm _emit ((GetVxDServiceOrdinal(service) >> 8) & 0xff) | 0x80 \
    _asm _emit (GetVxDServiceOrdinal(service) >> 16) & 0xff \
    _asm _emit (GetVxDServiceOrdinal(service) >> 24) & 0xff \

#endif

#define VMMCall VxDCall

#define VMMJmp  VxDJmp

#define SERVICE __cdecl

#define VMM_Service Declare_Service

Begin_Service_Table(VMM, VMM)

VMM_Service (Get_VMM_Version)
VMM_Service (Get_Cur_VM_Handle)
VMM_Service (Allocate_V86_Call_Back)
VMM_Service (Crash_Cur_VM)
VMM_Service (Hook_V86_Int_Chain)
VMM_Service (Get_V86_Int_Vector)
VMM_Service (Set_V86_Int_Vector)
VMM_Service (Get_PM_Int_Vector)
VMM_Service (Set_PM_Int_Vector)
VMM_Service (Simulate_Int)
VMM_Service (Simulate_Iret)
VMM_Service (Simulate_Far_Call)
VMM_Service (Simulate_Far_Jmp)
VMM_Service (Simulate_Far_Ret)
VMM_Service (Simulate_Far_Ret_N)
VMM_Service (Build_Int_Stack_Frame)
VMM_Service (Simulate_Push)
VMM_Service (Simulate_Pop)
VMM_Service (_PageFree)
VMM_Service (_PhysIntoV86)
VMM_Service (_LinMapIntoV86)
VMM_Service (Hook_V86_Fault)
VMM_Service (Hook_PM_Fault)
VMM_Service (Begin_Nest_Exec)
VMM_Service (Exec_Int)
VMM_Service (Resume_Exec)
VMM_Service (End_Nest_Exec)
VMM_Service (Save_Client_State)
VMM_Service (Restore_Client_State)
VMM_Service (Simulate_IO)
VMM_Service (Install_Mult_IO_Handlers)
VMM_Service (Install_IO_Handler)
VMM_Service (VMM_Add_DDB)
VMM_Service (VMM_Remove_DDB)
VMM_Service (Remove_IO_Handler)
VMM_Service (Remove_Mult_IO_Handlers)
VMM_Service (Unhook_V86_Int_Chain)
VMM_Service (Unhook_V86_Fault)
VMM_Service (Unhook_PM_Fault)
VMM_Service (_PageReserve)
VMM_Service (_PageCommit)
VMM_Service (_PageDecommit)
VMM_Service (_PageCommitPhys)

VMM_Service (Free_V86_Call_Back)
VMM_Service (Yield)
VMM_Service (MoveMemory)

VMM_Service (_Allocate_GDT_Selector)
VMM_Service (_Free_GDT_Selector)
VMM_Service (Get_DDB)

End_Service_Table(VMM, VMM)

struct cb_s {
    ULONG CB_VM_Status;     /* VM status flags */
    ULONG CB_High_Linear;   /* Address of VM mapped high */
    ULONG CB_Client_Pointer;
    ULONG CB_VMID;
    ULONG CB_Signature;
};

struct Client_Reg_Struc {
    ULONG Client_EDI;       /* Client's EDI */
    ULONG Client_ESI;       /* Client's ESI */
    ULONG Client_EBP;       /* Client's EBP */
    ULONG Client_res0;      /* ESP at pushall */
    ULONG Client_EBX;       /* Client's EBX */
    ULONG Client_EDX;       /* Client's EDX */
    ULONG Client_ECX;       /* Client's ECX */
    ULONG Client_EAX;       /* Client's EAX */
    ULONG Client_IntNo;
    ULONG Client_Error;     /* Dword error code */
    ULONG Client_EIP;       /* EIP */
    USHORT Client_CS;       /* CS */
    USHORT Client_res1;     /*   (padding) */
    ULONG Client_EFlags;    /* EFLAGS */
    ULONG Client_ESP;       /* ESP */
    USHORT Client_SS;       /* SS */
    USHORT Client_res2;     /*   (padding) */
    USHORT Client_ES;       /* ES */
    USHORT Client_res3;     /*   (padding) */
    USHORT Client_DS;       /* DS */
    USHORT Client_res4;     /*   (padding) */
    USHORT Client_FS;       /* FS */
    USHORT Client_res5;     /*   (padding) */
    USHORT Client_GS;       /* GS */
    USHORT Client_res6;     /*   (padding) */
};


================================================
FILE: Include/JLM.INC
================================================

;--- this is an assembler include file in MASM format,
;--- to be used for JLMs (Jemm Loadable Modules).
;--- it defines the API exposed by Jemm/JLoad.

;--- parameters, calling convention and return values are the same as
;--- for Win9x.
;--- the register usage usually is the same as for the Win32 stdcall 
;--- convention: registers EAX, ECX and EDX may be changed inside a function,
;---             registers EBX, ESI, EDI, EBP are preserved.
;--- the exception of this rule is Get_Cur_VM_Handle, which returns the
;--- "handle" in EBX.
;--------------------------------------------------------------------------

;--- v5.83: VMMCall renamed to @VMMCall ( VMMCALL is a x86 instruction now )

ifndef __POASM__
@VMMCall macro name_
    int 20h
    dw VMM_&name_
    dw 1
    endm
else
@VMMCall macro name_
    int 20h
    dw VMM_ # name_
    dw 1
    endm
endif

ifndef __POASM__
VMMJmp macro name_
    int 20h
    dw VMM_&name_ + 8000h
    dw 1
    endm
else
VMMJmp macro name_
    int 20h
    dw VMM_ # name_ + 8000h
    dw 1
    endm
endif

VxDCall macro name_
    int 20h
    dd name_
    endm

;--- macro to define a hook proc (Hook_V86_Int_Chain)

HookProc macro name_, oldvect
;    jmp $+8   ; v5.85: removed
    jmp dword ptr [oldvect]
name_ proc
    endm

;--------------------------------------------------------------------------
;--- VMM API. This device is installed by JLoad. The name is misleading,
;--- though, VMs aren't supported.

;--- the following functions aren't implemented yet and will always return
;--- an error: 
;---   Install_Mult_IO_Handlers, Remove_Mult_IO_Handlers
;---   Hook_V86_Fault, Unhook_V86_Fault
;---   Hook_PM_Fault, Unhook_PM_Fault
;---   Get_PM_Int_Vector, Set_PM_Int_Vector

@@VMM_Service_no = 0

ifndef __POASM__
VMM_Service macro name_
VMM_&name_  equ @@VMM_Service_no
@@VMM_Service_no = @@VMM_Service_no +1
    endm
else
VMM_Service macro name_
VMM_#name_  equ @@VMM_Service_no
@@VMM_Service_no = @@VMM_Service_no +1
    endm
endif

VMM_Service Get_VMM_Version
VMM_Service Get_Cur_VM_Handle
VMM_Service Allocate_V86_Call_Back
VMM_Service Crash_Cur_VM
VMM_Service Hook_V86_Int_Chain
VMM_Service Get_V86_Int_Vector
VMM_Service Set_V86_Int_Vector
VMM_Service Get_PM_Int_Vector
VMM_Service Set_PM_Int_Vector
VMM_Service Simulate_Int
VMM_Service Simulate_Iret
VMM_Service Simulate_Far_Call
VMM_Service Simulate_Far_Jmp
VMM_Service Simulate_Far_Ret
VMM_Service Simulate_Far_Ret_N
VMM_Service Build_Int_Stack_Frame
VMM_Service Simulate_Push
VMM_Service Simulate_Pop
VMM_Service _PageFree
VMM_Service _PhysIntoV86
VMM_Service _LinMapIntoV86
VMM_Service Hook_V86_Fault   ;implemented in v5.86 - previously a stub only
VMM_Service Hook_PM_Fault
VMM_Service Begin_Nest_Exec
VMM_Service Exec_Int
VMM_Service Resume_Exec
VMM_Service End_Nest_Exec
VMM_Service Save_Client_State
VMM_Service Restore_Client_State
VMM_Service Simulate_IO
VMM_Service Install_Mult_IO_Handlers
VMM_Service Install_IO_Handler
VMM_Service VMM_Add_DDB
VMM_Service VMM_Remove_DDB
VMM_Service Remove_IO_Handler
VMM_Service Remove_Mult_IO_Handlers
VMM_Service Unhook_V86_Int_Chain
VMM_Service Unhook_V86_Fault  ;implemented in v5.86 - previously a stub only
VMM_Service Unhook_PM_Fault
VMM_Service _PageReserve
VMM_Service _PageCommit
VMM_Service _PageDecommit
VMM_Service _PageCommitPhys

;--- the following functions are Jemm specific

VMM_Service Free_V86_Call_Back      ;release v86 callback in EAX
VMM_Service Yield                   ;release cpu for IRQs
VMM_Service MoveMemory              ;copy memory with ints enabled

;--- added in v5.83

VMM_Service _Allocate_GDT_Selector
VMM_Service _Free_GDT_Selector
VMM_Service Get_DDB

;--- added in v5.85

VMM_Service V86ToPM		; jump to VCPI client, esi->V86toPM struct, ebp->client regs

;--- added in v5.86

VMM_Service GetDOSBuffer; get linear address of 4kB DOS buffer in JLOAD (during init phase only)

;--- equates for the page memory functions

;_PageReserve() page parameter:
PR_PRIVATE  EQU 80000400H
PR_SHARED   EQU 80060000H
PR_SYSTEM   EQU 80080000H

;_PageCommit() hpd parameter:
PD_ZEROINIT     EQU 00000001H   ;not supported
PD_NOINIT       EQU 00000002H   ;not supported
PD_FIXEDZERO    EQU 00000003H
PD_FIXED        EQU 00000004H

;_PageCommit() flags parameter:
PC_FIXED        EQU 00000008H   ;PC_FIXED and/or PC_LOCKED must be set
PC_LOCKED       EQU 00000080H
PC_WRITEABLE    EQU 00020000H   ;also valid for _PageCommitPhys()
PC_USER         EQU 00040000H   ;also valid for _PageCommitPhys()
PC_CACHEWT      EQU 00080000H   ;write thru
PC_CACHEDIS     EQU 00100000H   ;cache disable
PC_INCR         EQU 40000000H   ;also valid for _PageCommitPhys()

; PTE bits

P_PRESBIT   EQU 0
P_PRES  EQU (1 SHL P_PRESBIT)
P_WRITEBIT  EQU 1
P_WRITE EQU (1 SHL P_WRITEBIT)
P_USERBIT   EQU 2
P_USER  EQU (1 SHL P_USERBIT)
P_ACCBIT    EQU 5
P_ACC   EQU (1 SHL P_ACCBIT)
P_DIRTYBIT  EQU 6
P_DIRTY EQU (1 SHL P_DIRTYBIT)

;--- equates for IO trapping functions

BYTE_INPUT      EQU 000H
BYTE_OUTPUT     EQU 004H
WORD_INPUT      EQU 008H
WORD_OUTPUT     EQU 00CH
DWORD_INPUT     EQU 010H
DWORD_OUTPUT    EQU 014H

OUTPUT_BIT      EQU 2
WORD_IO_BIT     EQU 3
DWORD_IO_BIT    EQU 4
STRING_IO_BIT   EQU 5
REP_IO_BIT      EQU 6   ;rep prefix with "string io"
ADDR_32_IO_BIT  EQU 7   ;ECX used instead of CX for "rep string io"
REVERSE_IO_BIT  EQU 8

OUTPUT      EQU (1 SHL OUTPUT_BIT)
WORD_IO     EQU (1 SHL WORD_IO_BIT)
DWORD_IO    EQU (1 SHL DWORD_IO_BIT)
STRING_IO   EQU (1 SHL STRING_IO_BIT)
REP_IO      EQU (1 SHL REP_IO_BIT)

;--- messages
SYSTEM_EXIT EQU 5
DEVICE_REBOOT_NOTIFY EQU 17h

;--------------------------------------------------------------------------
;--- VDMA device. This device is also installed by JLoad

@@VDMAD_Service_no = 0
VDMAD_Device equ 4

VDMAD_Service macro name_
name_   equ @@VDMAD_Service_no  + VDMAD_Device shl 16
@@VDMAD_Service_no = @@VDMAD_Service_no +1
    endm

VDMAD_Service VDMAD_Get_Version
VDMAD_Service VDMAD_Lock_DMA_Region
VDMAD_Service VDMAD_Unlock_DMA_Region
VDMAD_Service VDMAD_Scatter_Lock
VDMAD_Service VDMAD_Scatter_Unlock
VDMAD_Service VDMAD_Request_Buffer
VDMAD_Service VDMAD_Release_Buffer
VDMAD_Service VDMAD_Copy_To_Buffer      ;new v5.69
VDMAD_Service VDMAD_Copy_From_Buffer    ;new v5.69

;--------------------------------------------------------------------------

;--- VM control block structure
;--- since VMs aren't supported yet, the fields aren't that useful.
;--- CB_Client_Pointer will always contain a valid pointer.

cb_s    STRUC
CB_VM_Status        DD  ?
CB_High_Linear      DD  ?
CB_Client_Pointer   DD  ?
CB_VMID             DD  ?
cb_s    ENDS

;--- DDB (device description block)
;--- to be used for VMM_Add_DDB / VMM_Remove_DDB

UNDEFINED_INIT_ORDER	EQU 080000000H

VxD_Desc_Block  STRUC
DDB_Next                DD  ?
DDB_Version             DW  ?
DDB_Req_Device_Number   DW  0
DDB_Dev_Major_Version   DB  0
DDB_Dev_Minor_Version   DB  0
DDB_Flags               DW  0
ifndef __POASM__
DDB_Name                DB  8 dup (20h)
else
DDB_Name                DB  8 dup (?)
endif
DDB_Init_Order          DD  UNDEFINED_INIT_ORDER
DDB_Control_Proc        DD  ?
DDB_V86_API_Proc        DD  0
DDB_PM_API_Proc         DD  0
DDB_V86_API_CSIP        DD  0
DDB_PM_API_CSIP         DD  0
DDB_Reference_Data      DD  ?
DDB_Service_Table_Ptr   DD  0
DDB_Service_Table_Size  DD  0
DDB_Win32_Service_Table DD  0
DDB_Prev                DD  0
DDB_Size                DD  SIZE(VxD_Desc_Block)
DDB_Reserved1           DD  0  ;holds PE module handle
DDB_Reserved2           DD  0
DDB_Reserved3           DD  0
VxD_Desc_Block  ENDS

;--- client register structure
;--- note the "Client_Int" member, which is Jemm specific.

Client_Reg_Struc  struc
Client_EDI  dd ?    ;+0
Client_ESI  dd ?    ;+4
Client_EBP  dd ?    ;+8
Client_res0 dd ?    ;+12
Client_EBX  dd ?    ;+16
Client_EDX  dd ?    ;+20
Client_ECX  dd ?    ;+24
Client_EAX  dd ?    ;+28
Client_Int  dd ?    ;+32 (pushed as sign-extended byte - so check lowest byte only!)
Client_Error dd ?   ;+36
Client_EIP  dd ?    ;+40
Client_CS   dd ?    ;+44    
Client_EFlags dd ?  ;+48
Client_ESP  dd ?    ;+52
Client_SS   dd ?    ;+56
Client_ES   dd ?    ;+60
Client_DS   dd ?    ;+64
Client_FS   dd ?    ;+68
Client_GS   dd ?    ;+72
Client_Reg_Struc ends


;--------------------------------------------------------------------------
;--- JLoad init/term structure
;--- this is 3. parameter for a JLM's DllMain entry
;--- lpRequest is set for LOAD
;--- lpDrivers is set for UNLOAD

JLCOMM  struc
wLdrCS      dw ?    ;CS of JLOAD.EXE
wFlags      dw ?    ;flags (see below)
lpCmdLine   dd ?    ;linear address cmdline
union
lpRequest   dd ?    ;LOAD:   linear address DOS request hdr
lpDrivers   dd ?    ;UNLOAD: linear address DOS device driver list start
ends
JLCOMM  ends

JLF_UNLOAD  equ 1   ;set if JLM is to be unloaded
JLF_DRIVER  equ 2   ;set if JLoad is loaded as driver in config.sys

JLF_UNLOAD_BIT  equ 0
JLF_DRIVER_BIT  equ 1


================================================
FILE: Include/JLMFASM.INC
================================================

;--- this is an assembler include file in FASM format
;--- to be used for JLMs (Jemm Loadable Modules).
;--- it defines the API exposed by Jemm/JLoad.

;--- parameters, calling convention and return values are the same as
;--- for Win9x.
;--- the register usage usually is the same as for the Win32 stdcall 
;--- convention: registers EAX, ECX and EDX may be changed inside a function,
;---             registers EBX, ESI, EDI, EBP are preserved.
;--- the exception of this rule is Get_Cur_VM_Handle, which returns the
;--- "handle" in EBX.
;--------------------------------------------------------------------------

macro @VMMCall name_ {
    int 20h
    dw VMM_#name_
    dw 1
}

macro VMMJmp name_ {
    int 20h
    dw VMM_#name_ + 8000h
    dw 1
}

macro VxDCall name_ {
    int 20h
    dd name_
}

;--- macro to define a hook proc (Hook_V86_Int_Chain)

macro HookProc name_, oldvect {
    jmp $+8
    jmp dword [oldvect]
name_ proc
}

;--------------------------------------------------------------------------
;--- VMM API. This device is installed by JLoad. The name is misleading,
;--- though, VMs aren't supported.

;--- not implemented yet:
;---   Install_Mult_IO_Handlers, Remove_Mult_IO_Handlers
;---   Hook_V86_Fault, Unhook_V86_Fault
;---   Hook_PM_Fault, Unhook_PM_Fault
;---   Get_PM_Int_Vector, Set_PM_Int_Vector

@VMM_Service_no = 0

macro VMM_Service name_ {
VMM_#name_  = @VMM_Service_no
@VMM_Service_no = @VMM_Service_no +1
}

VMM_Service Get_VMM_Version
VMM_Service Get_Cur_VM_Handle
VMM_Service Allocate_V86_Call_Back
VMM_Service Crash_Cur_VM
VMM_Service Hook_V86_Int_Chain
VMM_Service Get_V86_Int_Vector
VMM_Service Set_V86_Int_Vector
VMM_Service Get_PM_Int_Vector
VMM_Service Set_PM_Int_Vector
VMM_Service Simulate_Int
VMM_Service Simulate_Iret
VMM_Service Simulate_Far_Call
VMM_Service Simulate_Far_Jmp
VMM_Service Simulate_Far_Ret
VMM_Service Simulate_Far_Ret_N
VMM_Service Build_Int_Stack_Frame
VMM_Service Simulate_Push
VMM_Service Simulate_Pop
VMM_Service _PageFree
VMM_Service _PhysIntoV86
VMM_Service _LinMapIntoV86
VMM_Service Hook_V86_Fault
VMM_Service Hook_PM_Fault
VMM_Service Begin_Nest_Exec
VMM_Service Exec_Int
VMM_Service Resume_Exec
VMM_Service End_Nest_Exec
VMM_Service Save_Client_State
VMM_Service Restore_Client_State
VMM_Service Simulate_IO
VMM_Service Install_Mult_IO_Handlers
VMM_Service Install_IO_Handler
VMM_Service VMM_Add_DDB
VMM_Service VMM_Remove_DDB
VMM_Service Remove_IO_Handler
VMM_Service Remove_Mult_IO_Handlers
VMM_Service Unhook_V86_Int_Chain
VMM_Service Unhook_V86_Fault
VMM_Service Unhook_PM_Fault
VMM_Service _PageReserve
VMM_Service _PageCommit
VMM_Service _PageDecommit
VMM_Service _PageCommitPhys

;--- the following functions are Jemm specific

VMM_Service Free_V86_Call_Back      ;release v86 callback in EAX
VMM_Service Yield                   ;release cpu for IRQs
VMM_Service MoveMemory              ;copy memory with ints enabled

;--- added in v5.83

VMM_Service _Allocate_GDT_Selector
VMM_Service _Free_GDT_Selector
VMM_Service Get_DDB

;--- equates for the page memory functions

;_PageReserve() page parameter:
PR_PRIVATE  EQU 80000400H
PR_SHARED   EQU 80060000H
PR_SYSTEM   EQU 80080000H

;_PageCommit() hpd parameter:
PD_ZEROINIT     EQU 00000001H   ;not supported
PD_NOINIT       EQU 00000002H   ;not supported
PD_FIXEDZERO    EQU 00000003H
PD_FIXED        EQU 00000004H

;_PageCommit() flags parameter:
PC_FIXED        EQU 00000008H   ;PC_FIXED and/or PC_LOCKED must be set
PC_LOCKED       EQU 00000080H
PC_WRITEABLE    EQU 00020000H   ;also valid for _PageCommitPhys()
PC_USER         EQU 00040000H   ;also valid for _PageCommitPhys()
PC_INCR         EQU 40000000H   ;also valid for _PageCommitPhys()

; PTE bits

P_PRESBIT   EQU 0
P_PRES  EQU (1 SHL P_PRESBIT)
P_WRITEBIT  EQU 1
P_WRITE EQU (1 SHL P_WRITEBIT)
P_USERBIT   EQU 2
P_USER  EQU (1 SHL P_USERBIT)
P_ACCBIT    EQU 5
P_ACC   EQU (1 SHL P_ACCBIT)
P_DIRTYBIT  EQU 6
P_DIRTY EQU (1 SHL P_DIRTYBIT)

;--- equates for IO trapping functions

BYTE_INPUT      EQU 000H
BYTE_OUTPUT     EQU 004H
WORD_INPUT      EQU 008H
WORD_OUTPUT     EQU 00CH
DWORD_INPUT     EQU 010H
DWORD_OUTPUT    EQU 014H

OUTPUT_BIT      EQU 2
WORD_IO_BIT     EQU 3
DWORD_IO_BIT    EQU 4
STRING_IO_BIT   EQU 5
REP_IO_BIT      EQU 6   ;rep prefix with "string io"
ADDR_32_IO_BIT  EQU 7   ;ECX used instead of CX for "rep string io"
REVERSE_IO_BIT  EQU 8

OUTPUT      EQU (1 SHL OUTPUT_BIT)
WORD_IO     EQU (1 SHL WORD_IO_BIT)
DWORD_IO    EQU (1 SHL DWORD_IO_BIT)
STRING_IO   EQU (1 SHL STRING_IO_BIT)
REP_IO      EQU (1 SHL REP_IO_BIT)

;--------------------------------------------------------------------------
;--- VDMA device. This device is also installed by JLoad

@VDMAD_Service_no = 0
VDMAD_Device equ 4

macro VDMAD_Service name_ {
name_   equ @VDMAD_Service_no  + VDMAD_Device shl 16
@VDMAD_Service_no = @VDMAD_Service_no +1
}

VDMAD_Service VDMAD_Get_Version
VDMAD_Service VDMAD_Lock_DMA_Region
VDMAD_Service VDMAD_Unlock_DMA_Region
VDMAD_Service VDMAD_Scatter_Lock
VDMAD_Service VDMAD_Scatter_Unlock
VDMAD_Service VDMAD_Request_Buffer
VDMAD_Service VDMAD_Release_Buffer
VDMAD_Service VDMAD_Copy_To_Buffer      ;new v5.69
VDMAD_Service VDMAD_Copy_From_Buffer    ;new v5.69

;--------------------------------------------------------------------------

;--- VM control block structure
;--- since VMs aren't supported yet, the fields aren't that useful.
;--- CB_Client_Pointer will always contain a valid pointer.

struct cb_s
  CB_VM_Status        DD  ?
  CB_High_Linear      DD  ?
  CB_Client_Pointer   DD  ?
  CB_VMID             DD  ?
ends

if 0
;--- DDB (device description block)
;--- to be used for VMM_Add_DDB / VMM_Remove_DDB

struct VxD_Desc_Block
DDB_Next                dd  ?
DDB_Version             DW  ?
DDB_Req_Device_Number   DW  ?
DDB_Dev_Major_Version   DB  ?
DDB_Dev_Minor_Version   DB  ?
DDB_Flags               DW  ?
DDB_Name                rb  8
DDB_Init_Order          DD  ?
DDB_Control_Proc        DD  ?
DDB_V86_API_Proc        DD  ?
DDB_PM_API_Proc         DD  ?
DDB_V86_API_CSIP        DD  ?
DDB_PM_API_CSIP         DD  ?
DDB_Reference_Data      DD  ?
DDB_Service_Table_Ptr   DD  ?
DDB_Service_Table_Size  DD  ?
DDB_Win32_Service_Table DD  ?
DDB_Prev                DD  ?
DDB_Size                DD  ?
DDB_Reserved1           DD  ?
DDB_Reserved2           DD  ?
DDB_Reserved3           DD  ?
ends
end if

;--- client register structure
;--- note the "Client_Int" member, which is Jemm specific.

struct Client_Reg_Struc
Client_EDI  dd ?    ;+0
Client_ESI  dd ?    ;+4
Client_EBP  dd ?    ;+8
Client_res0 dd ?    ;+12
Client_EBX  dd ?    ;+16
Client_EDX  dd ?    ;+20
Client_ECX  dd ?    ;+24
Client_EAX  dd ?    ;+28
Client_Int  dd ?    ;+32
Client_Error dd ?   ;+36
Client_EIP  dd ?    ;+40
Client_CS   dd ?    ;+44    
Client_EFlags dd ?  ;+48
Client_ESP  dd ?    ;+52
Client_SS   dd ?    ;+56
Client_ES   dd ?    ;+60
Client_DS   dd ?    ;+64
Client_FS   dd ?    ;+68
Client_GS   dd ?    ;+72
ends


;--------------------------------------------------------------------------
;--- JLoad init/term structure
;--- this is 3. parameter for a JLM's DllMain entry
;--- lpRequest is set for LOAD
;--- lpDrivers is set for UNLOAD

struct JLCOMM
wLdrCS      dw ?    ;CS of JLOAD.EXE
wFlags      dw ?    ;flags (see below)
lpCmdLine   dd ?    ;linear address cmdline
lpRequest   dd ?    ;LOAD:   linear address DOS request hdr
virtual at JLCOMM.lpRequest
lpDrivers   dd ?    ;UNLOAD: linear address DOS device driver list start
end virtual
ends

JLF_UNLOAD  equ 1   ;set if JLM is to be unloaded
JLF_DRIVER  equ 2   ;set if JLoad is loaded as driver in config.sys

JLF_UNLOAD_BIT  equ 0
JLF_DRIVER_BIT  equ 1


================================================
FILE: Include/JSYSTEM.INC
================================================

;--- constants used by Jemm & JLoad

?VERSIONHIGH    equ 5
?VERSIONLOW     equ 87

?BASE           EQU 110000h         ; base of Jemm 32bit code
?SYSBASE        EQU 0F8000000h      ; linear address system space
?PAGEDIR        EQU ?SYSBASE+1000h  ; linear address page dir
?PAGETABSYS     EQU 3000h           ; rel. offset (?SYSBASE) for system page table
;--- 3000 = 3 page tables ( pagedir, page tab0, system page tab )
?TOS            EQU ?SYSBASE+1000h+3000h+1000h  ;top of ring 0 stack

;--- this is the structure for a "Get VMM info" request
;--- v5.87: fields e08_pCallBack and e08_CallBackRM do now
;--- point to the *second* static breakpoint in Jemm32/Jemm16.
;--- Thus JLoad doesn't need to know anything about the breakpoint array.

EMX08 struct
e08_ServiceTable    dd ?	;linear address service table
e08_pCallBack       dd ?	;linear address callback BP in Jemm32
e08_CallBackRM      dd ?	;segment:offset of callback BP in Jemm16
e08_GDTR            df ?
e08_IDTR            df ?
e08_TR              dw ?
e08_FlatCS          dw ?
EMX08 ends



================================================
FILE: Include/PRINTF.INC
================================================

;--- simple printf

;--- i64toa(long long n, char * s, int base);
;--- convert 64-bit long long to string

i64toa proc stdcall uses edi number:qword, outb:ptr, base:dword

	mov ch,0
	mov edi, base
	mov eax, dword ptr number+0
	mov esi, dword ptr number+4
	cmp edi,-10
	jne @F
	neg edi
	and esi,esi
	jns @F
	neg esi
	neg eax
	sbb esi,0
	mov ch,'-'
@@:
	mov ebx,outb
	add ebx,22
	mov byte ptr [ebx],0
@@nextdigit:
	dec ebx
	xor edx,edx
	xchg eax,esi
	div edi
	xchg eax,esi
	div edi
	add dl,'0'
	cmp dl,'9'
	jbe @F
	add dl,7+20h
@@:
	mov [ebx],dl
	mov edx, eax
	or edx, esi
	jne @@nextdigit
	cmp ch,0
	je @F
	dec ebx
	mov [ebx],ch
@@:
	mov eax,ebx
	ret

i64toa endp

printf proc c fmt:ptr, args:vararg

local flag:byte
local longarg:byte
local size_:dword
local fillchr:dword
local szTmp[24]:byte
local crs:Client_Reg_Struc

	pushad
	mov ebp, [ebp]
	lea edi, crs
	@VMMCall Save_Client_State
	@VMMCall Begin_Nest_Exec
	mov ebp, [esp+2*4]	;restore EBP
	cld
	lea edi,args
@@L335:
	mov esi,fmt
nextchar:
	lodsb
	or al,al
	je done
	cmp al,'%'
	je formatitem
	call handle_char
	jmp nextchar
done:
	mov ebp, [ebp]
	@VMMCall End_Nest_Exec
	lea esi, crs
	@VMMCall Restore_Client_State
	popad
	ret

formatitem:
	push offset @@L335
	xor edx,edx
	mov [longarg],dl
	mov bl,1
	mov cl,' '
	cmp BYTE PTR [esi],'-'
	jne @F
	dec bl
	inc esi
@@:
	mov [flag],bl
	cmp BYTE PTR [esi],'0'
	jne @F
	mov cl,'0'
	inc esi
@@:
	mov [fillchr],ecx
	mov ebx,edx

	.while ( byte ptr [esi] >= '0' && byte ptr [esi] <= '9' )
		lodsb
		sub al,'0'
		movzx eax,al
		imul ecx,ebx,10		;ecx = ebx * 10
		add eax,ecx
		mov ebx,eax
	.endw

	mov [size_],ebx
	cmp BYTE PTR [esi],'l'
	jne @F
	mov [longarg],1
	inc esi
@@:
	lodsb
	mov [fmt],esi
	cmp al,'x'
	je handle_x
	cmp al,'X'
	je handle_x
	cmp al,'d'
	je handle_d
	cmp al,'u'
	je handle_u
	cmp al,'s'
	je handle_s
	cmp al,'c'
	je handle_c
	and al,al
	jnz @F
	pop eax
	jmp done
handle_c:
	mov eax,[edi]
	add edi, 4
@@:
	call handle_char
	retn

handle_s:
	mov esi,[edi]
	add edi,4
	jmp print_string
handle_d:
handle_i:
	mov ebx,-10
	jmp @F
handle_u:
	mov ebx, 10
	jmp @F
handle_x:
	mov ebx, 16
@@:
	xor edx,edx
	mov eax,[edi]
	add edi,4
	cmp longarg,1
	jnz @F
	mov edx,[edi]
	add edi,4
	jmp printnum
@@:
	and ebx,ebx
	jns @F
	cdq
@@:
printnum:
	lea esi, szTmp
	invoke i64toa, edx::eax, esi, ebx
	mov esi, eax

print_string:		;print string ESI, size EAX
	mov eax, esi
	.while byte ptr [esi]
		inc esi
	.endw
	sub esi, eax
	xchg eax, esi
	mov ebx,size_
	sub ebx,eax
	.if flag == 1
		.while sdword ptr ebx > 0
			mov eax, [fillchr]
			call handle_char	;print leading filler chars
			dec ebx
		.endw
	.endif

	.while byte ptr [esi]
		lodsb
		call handle_char	;print char of string
	.endw

	.while sdword ptr ebx > 0
		mov eax, [fillchr]
		call handle_char	;print trailing spaces
		dec ebx
	.endw
	retn


handle_char:
	push ebp
	mov ebp, [ebp]
	mov ah, 0Eh
	mov [ebp].Client_Reg_Struc.Client_EAX, eax
	mov byte ptr [ebp].Client_Reg_Struc.Client_EBX+1, 0
	mov eax, 10h
	@VMMCall Exec_Int
	pop ebp
	retn

printf endp


================================================
FILE: Include/VDS.INC
================================================

;--- VDS definitions

;--- flags in DX used by various VDS functions

VDSF_COPY       equ 02h	;bit 1 - copy in/out of DMA buffer (8107/8108)
VDSF_NOBUFFER   equ 04h	;bit 2 - don't alloc DMA buffer (8103)
VDSF_NOREMAP    equ 08h	;bit 3 - change PTEs; Jemm ignores this flag!
VDSF_64KALIGN   equ 10h	;bit 4
VDSF_128KALIGN  equ 20h	;bit 5
VDSF_PTE        equ 40h	;bit 6 - 1=scatter_lock returns PTEs 
VDSF_NPPTE      equ 80h	;bit 7 - allow non-present pages for scatter/gather remap

;--- error codes returned in AL by lock (8103)

VDSERR_NOTCONTIGUOUS equ 1	;region not in contiguous memory
VDSERR_CROSSEDBOUNDS equ 2	;region crossed alignemnt boundary
VDSERR_CANTLOCKPAGES equ 3	;
VDSERR_NOBUFFER      equ 4	; 8107
VDSERR_BUFFTOOSMALL  equ 5	; 8107
VDSERR_BUFFINUSE     equ 6	; 

;--- other VDS error codes

VDSERR_07            equ 7	; invalid memory region (8107)
VDSERR_REG_NOTLOCKED equ 8	; region wasn't locked (8106)
VDSERR_NAVL_TOOSMALL equ 9	; # of phys pages was > than table length (8105)
VDSERR_INVAL_BUFFID  equ 10	; invalid buffer ID (8108,8109,810A)
VDSERR_BNDVIOLATION  equ 11	; buffer boundary violated (8109,810A)
VDSERR_INVAL_DMACHN  equ 12	; invalid DMA channel # (810B, 810C)
VDSERR_DISCNTOVFL    equ 13	; disable cnt overflow (810B)
VDSERR_DISCNTUNFL    equ 14	; disable cnt underflow (810C)
VDSERR_FUNC_NOTSUPP  equ 15	; function not supported
VDSERR_DXRSVDBITSSET equ 16	; reserved flag bits set in DX (8102,8106,8108,8109,810A,810B,810C)

;--- DDS, used by 03-04, 07-08, 09-0A

DDS struct
dwSize  dd ?    ;+0  size of region
dwOfs   dd ?    ;+4  offset virtual start address
wSeg    dw ?    ;+8  segment/selector virtual start address (or 0000)
wID     dw ?    ;+10 buffer ID
dwPhys  dd ?    ;+12 physical address
DDS ends

;--- EDDS, used by 05-06

EDDS struct
dwSize  dd ?    ;+0
dwOfs   dd ?    ;+4
wSeg    dw ?    ;+8
wRes    dw ?    ;+10
wNumAvail   dw ?    ;+12
wNumUsed    dw ?    ;+14
EDDS ends

;--- EDDS suffix for regions

EDDSRG struct
dwPhysAddr  dd ?    ;+16
dwSizeRg    dd ?    ;+20
EDDSRG ends

;--- EDDS suffix for PTEs

EDDSPT struct
dwPTE       dd ?    ;+16
EDDSPT ends



================================================
FILE: Include/X86.INC
================================================

;--- generic X86 definitions

;--- page table flags

PTF_PRESENT equ 001h
PTF_RW      equ 002h
PTF_USER    equ 004h
PTF_PWT     equ 008h ; page write through
PTF_PCD     equ 010h ; page cache disable
PTF_ACCESS  equ 020h ; page accessed
PTF_DIRTY   equ 040h ; page dirty
PTF_4MB     equ 080h ; PDEs: 4MB PDE
PTF_GBL     equ 100h ; page global (P3+)

;--- features, returned by CPUID in EDX
CF_FPU      equ 0001h
CF_VME      equ 0002h
CF_DE       equ 0004h;debugging ext
CF_PSE      equ 0008h;Page Size Ext (4MB)
CF_TSC      equ 0010h;Time Stamp Counter
CF_MSR      equ 0020h;RDMSR/WRMSR supported
CF_PAE      equ 0040h;Physical Address Ext
CF_MCE      equ 0080h;Machine Check Exceptions
CF_CX8      equ 0100h;CMPXCHG8B supported
CF_APIC     equ 0200h;APIC exists
;rsvd       equ 0400h;
CF_SEP      equ 0800h;SYSENTER/SYSEXIT supported
CF_MTRR     equ 1000h
CF_PGE      equ 2000h

;--- flags in CR4
CR4_VME      equ 01h
CR4_PVI      equ 02h
CR4_TSD      equ 04h;1=time stamp disable
CR4_DE       equ 08h
CR4_PSE      equ 10h;1=page size extensions enabled
CR4_PAE      equ 20h
CR4_MCE      equ 40h
CR4_PGE      equ 80h

;--- descriptor

DESCRIPTOR struct
wLimit  dw ?    ;+0
wA0015  dw ?    ;+2
bA1623  db ?    ;+4
bAttr   db ?    ;+5
bLimEx  db ?    ;+6
bA2431  db ?    ;+7
DESCRIPTOR ends        

GATE struct
wOfsLo dw ?
wSeg   dw ?
wAttr  dw ?
wOfsHi dw ?
GATE ends

;--- TSS structure
;--- the only fields in the TSS which are needed are tsEsp0, tsSS0
;--- and tsOfs. Jemm386 will never switch tasks.

TSSSEG  struct
        dd ?    ;+00 selector
tsEsp0  dd ?    ;+04
tsSS0   dd ?    ;+08
        dq ?    ;+0C
        dq ?    ;+14
tsCR3   dd ?    ;+1C
tsEip   dd ?    ;+20
tsEfl   dd ?    ;+24
tsEax   dd ?    ;+28
tsEcx   dd ?    ;+2C
tsEdx   dd ?    ;+30
tsEbx   dd ?    ;+34
tsEsp   dd ?    ;+38
tsEbp   dd ?    ;+3C
tsEsi   dd ?    ;+40
tsEdi   dd ?    ;+44
tsES    dd ?    ;+48
tsCS    dd ?    ;+4C
tsSS    dd ?    ;+50
tsDS    dd ?    ;+54
tsFS    dd ?    ;+58
tsGS    dd ?    ;+5C
tsLDTR  dd ?    ;+60
tsFlags dw ?    ;+64
tsOfs   dw ?    ;+66
TSSSEG  ends

;--- stack frame for PUSHAD

PUSHADS struct
rEDI    dd ?
rESI    dd ?
rEBP    dd ?
        dd ?    ;reserved
rEBX    dd ?
rEDX    dd ?
rECX    dd ?
rEAX    dd ?
PUSHADS ends

;--- RETF stack frame for 16bit

RETFWS struct
union
 struct
_Ip     dw ?
_Cs     dw ?
 ends
_CsIp   dd ?
ends
RETFWS ends

;--- IRET stack frame for 16bit

IRETWS struct
        RETFWS <>
_Fl     dw ?
IRETWS ends

;--- IRET stack frame for 32bit protected-mode

IRETDS struct
_Eip    dd ?    ;+0
_Cs     dd ?    ;+4 
_Efl    dd ?    ;+8
IRETDS ends

;--- stack frame expected by ring0-IRETD to switch to v86-mode

IRETDV86 struct
_Eip    dd ?    ;+0
_Cs     dd ?    ;+4 
_Efl    dd ?    ;+8
_Esp    dd ?    ;+12
_Ss     dd ?    ;+16
_Es     dd ?    ;+20
_Ds     dd ?    ;+24
_Fs     dd ?    ;+28
_Gs     dd ?    ;+32
IRETDV86 ends

;--- bit positions of CPUID edx
CPUID_VME equ 1		; =2
CPUID_PGE equ 13	; =2000h
CPUID_PAT equ 16	; =10000h



================================================
FILE: JLM/AHCICD/AHCICD.ASM
================================================

;--- JLM to read CD/DVD in AHCI mode.
;--- "cooked" mode is supported only.

	.386
	.model flat
	option casemap:none
	option proc:private

	include jlm.inc

?OPTIONR equ 1      ; 1=enable /R option to relocate Port.CLB, Port.FB, Commandlist[0].CTBA
?IRQWND  equ 1      ; 1=use Jemm's MoveMemory() that allows interrupts during copy op
REQOFS   equ 16h	; must be at least "sizeof DOSDRV"
SLCOOKED equ 2048
SLRAW    equ 2352   ;CD-ROM "raw" sector length.

;--- macros

CStr macro text:vararg
local sym
	.const
sym db text,0
	.code
	exitm <offset sym>
endm

@dprintf macro text,args:vararg
local sym
ifdef _DEBUG
	.const
sym db text,0
	.code
	ifnb <args>
		invoke printf, offset sym, args
	else
		invoke printf, offset sym
	endif
endif
endm

;--- structs

DOSDRV struct
		dd ?
wAttr	dw ?
ofsStr	dw ?
ofsInt	dw ?
name_	db 8 dup (?);+10
wRes1	dw ?		;+18 req. for cd drivers, init with 0
bRes2	db ?		;+20 req. for cd drivers, modified by mscdex
bUnits	db ?		;+21 set by driver
DOSDRV ends

;--- DOS "Request Packet" Layouts.

RPH struct
RPHLen  db  ?       ;+0 Header byte count.
bSubU   db  ?       ;+1 Subunit number.
bOp     db  ?       ;+2 Command code.
wStat   dw  ?       ;+3 Status field.
        db 8 dup (?);+5 .. +12 (reserved).
RPH ends

RPERR   equ 8003h   ;Packet "error" flags.
RPDON   equ 0100h   ;Packet "done" flag.
RPBUSY  equ 0200h   ;Packet "busy" flag.

;--- Init "Request Packet" Layout

RPInit struct
        RPH <>
bUnit   db  ?       ;+13 Number of units found.
dwFree  dd  ?       ;+14 return: far16 ptr first free byte behind driver
CmdLine dd  ?       ;+18 Command-line data pointer.
RPInit  ends

;--- IOCTL "Request Packet" Layout

RPIOC struct
        RPH <>
        db  ?       ;+13 Media descriptor byte (Unused by us).
dwAddr  dd  ?       ;+14 Data-transfer address.
wLength dw  ?       ;+18 Data-transfer length.
        dw  ?       ;+20 Starting sector (unused by us).
        dd  ?       ;+22 Volume I.D. pointer (unused by us).
RPIOC ends

;--- Read Long "Request Packet" Layout

RPRL struct
        RPH <>
bAMode  db  ?       ;+13 Addressing mode.
dwAddr  dd  ?       ;+14 Data-transfer address.
wSecCnt dw  ?       ;+18 Data-transfer sector count.
dwStart dd  ?       ;+20 Starting sector number.
bDMode  db  ?       ;+24 Data-transfer mode (raw/cooked).
bILSize db  ?       ;+25 Interleave size.
bILSkip db  ?       ;+26 Interleave skip factor.
RPRL  ends

;--- AHCI structures

HBA struct
dwCAP   dd ?	;+0 HBA capabilities
dwGHC   dd ?	;+4 global HBA control
dwIS    dd ?	;+8 interrupt status
dwPI    dd ?	;+12 ports implemented
HBA ends

PORT struct
dqCLB   dq ?	;+0  Command list base addr ( 1 kB aligned )
dqFB    dq ?	;+8  (received) FIS base addr ( 256 B aligned )
dwIS    dd ?	;+16 interrupt status
dwIE    dd ?	;+20 interrupt enable
dwCMD   dd ?	;+24 command and status
        dd ?	;+28
dwTFD   dd ?	;+32 task file data
dwSIG   dd ?	;+36 signature
dwSSTS  dd ?	;+40 SATA status
dwSCTL  dd ?	;+44 SATA control
dwSERR  dd ?	;+48 SATA error
dwSACT  dd ?	;+52 SATA active
dwCI    dd ?	;+56 command issued
PORT ends

;--- flags dwIS field
PIS_CPDS equ 80000000h
PIS_TFES equ 40000000h
PIS_HBFS equ 20000000h
PIS_HBDS equ 10000000h
PIS_SDBS equ 00000008h	; set device bits interrupt
PIS_DSS  equ 00000004h	; DMA setup FIS interrupt
PIS_PSS  equ 00000002h	; PIO setup FIS interrupt
PIS_DHRS equ 00000001h	; device to host register FIS interrupt

;--- flags dwCMD field
PCMD_CR  equ 8000h	; RO, 1=command list DMA engine running
PCMD_FR  equ 4000h	; RO, 1=FIS Receive running
PCMD_FRE equ 0010h	; RW, 1=FIS Receive Enable
PCMD_CLO equ 0008h	; RW, 1=command list override
PCMD_POD equ 0004h	; RW, Power On Device
PCMD_SUD equ 0002h	; RW, Spin Up Device
PCMD_ST  equ 0001h	; RW, Start (HBA may process the command list)


;--- AHCI command list header

CLH struct
flags1  db ?	;+0  P[7]=Prefetchable, W[6]=Write, A[5]=ATAPI, CFL[4:0]=Command FIS Length
flags2  db ?	;+1  PMP[15:12]=Port Multiplier Port, R[11]=Reserved, C[10]=Clear Busy, B[9]=BIST, R[8]=Reset
PRDTL   dw ?	;+2  Physical Region Descriptor Table Length
PRDBC   dd ?	;+4  Physical Region Descriptor Byte Count
dwCTBA  dd ?	;+8  Command Table Base Address bits 0-31 (128 byte aligned)
dwCTBAU dd ?	;+12 Command Table Base Address bits 32-63
	dd 4 dup (?)
CLH ends

PRDT struct
dwBase   dd ?	;+0 base
dwBaseU  dd ?	;+4 base upper
dwRsvd   dd ?	;+8 reserved
dwCnt    dd ?	;+12 cnt  
PRDT ends

;--- AHCI command table

CT struct
cfis0  dd ?
cfis1  dd ?
cfis2  dd ?
cfis3  dd ?
       db 30h dup (?)	; 40h=offset ATAPI in command table
Pkt0   dd ?
Pkt1   dd ?
Pkt2   dd ?
       db 34h dup (?)	; 80h=offset PRDT in command table
p0     PRDT <>
CT ends

; packet commands:
; - 003h:  request sense
; - 01Bh:  start/stop unit
; - 01Eh:  prevent/allow media removal
; - 025h:  read capacity
; - 028h:  read (cooked)
; - 02Bh:  seek
; - 042h:  read sub-channel
; - 043h:  read TOC
; - 047h:  play audio MSF
; - 04Ah:  get event status notification
; - 04Bh:  pause/resume
; - 05Ah:  mode sense
; - 0BEh:  read CD (raw)

if 0
Packet struct
PktOPC  db  0       ;+0 packet command.
        db  0       ;+1 Unused (LUN and reserved).
PktLBA  dd  0       ;+2 CD-ROM logical block address.
PktLH   db  0       ;+6 "Transfer length" (sector count).
PktLn   dw  0       ;+7 Middle- and low-order sector count.
PktRM   db  0       ;+9 Read mode ("Raw" Read Long only).
        dw  0       ;+10 Unused ATAPI "pad" bytes (required).
Packet ends
endif

	.data?

if ?OPTIONR
cmdlst	CLH 32 dup (<>)	; must be 1024 B aligned
fis		db 100h dup (?)	; must be 256 B aligned
cmdtab  CT <>			; must be 128 B aligned
endif
buffer db SLCOOKED dup (?)
       db SLRAW - SLCOOKED dup (?)

ppReq       dd ?	; linear address where request header is stored
pRequest    dd ?	; linear address request header
pBase       dd ?	; linear address driver base
pDest       dd ?	; linear address destination
pHBA        dd ?	; linear address HBA
pBuff       dd ?	; linear address sector buffer
dwBuffPh    dd ?	; physical address sector buffer
dwSector    dd ?	; current sector to read
if ?OPTIONR
pCLB        dd ?	; linear address Port[x].CLB
pCTBA       dd ?	; linear address CL[0].CTBA
endif

wPort   dw 6 dup (?); port offsets of max. 6 CD/DVDs
wSecCnt dw ?		; #sectors to read
bUnits  db ?		; found units (during init)
bCntOpt db ?		; /C option default value
bQuiet  db ?		; /Q option
if ?OPTIONR
bReloc  db ?		; /R option
endif
bBanner db ?		; 1=banner displayed

	.const

ERRTAB  db 12,12,2,4,12,0,15,8,8,12,12,12,12,12,12,12

rmcode label byte
	db 2Eh, 89h, 1eh, REQOFS+0, 0	;mov cs:[16h],bx
	db 2Eh, 8Ch, 06h, REQOFS+2, 0	;mov cs:[18h],es
	db 0CBh 						;retf
SIZERMCODE equ $ - offset rmcode	
	db 0EAh 						;jmp ssss:oooo

	.code

ifdef _DEBUG
	include printf.inc
endif

DevInt proc

	.const

	align 4

;--- cmds 00-0E
Vector label dword
	dd Init		; 0 Init
	dd Error3	; 1 media check (block devices)
	dd Error3	; 2 build bpb (block devices)
	dd IOCtlInp	; 3 ioctl input
	dd Error3	; 4 input
	dd Error3	; 5 nondestr. input
	dd Error3	; 6 input status (char devices)
	dd Error3	; 7 input flush (char devices)
	dd Error3	; 8 output
	dd Error3	; 9 output with verify
	dd Error3	;10 output status (char devices)
	dd Error3	;11 output flush (char devices)
	dd Error3	;12 ioctl output
	dd Exit		;13 device open
	dd Exit		;14 device close
;	dd Error3	;15 removable media (block devices)
LVECTOR equ ($ - offset Vector) / sizeof dword

;--- cmds 128-13x
Vect2 label dword
	dd ReadL	;128 CD read long
	dd Error3	;129 CD reserved
	dd Exit		;130 CD read long prefetch
;	dd Error3	;131 CD seek
;	dd Error3	;132 CD play audio
;	dd Error3	;133 CD stop audio
;	dd Error3	;134 CD write long
;	dd Error3	;135 CD write long verify
;	dd Error3	;136 CD resume audio
LVECT2 equ ($ - offset Vect2) / sizeof dword

	.code

	mov ebx, [ppReq]
	movzx eax, word ptr [ebx+0]
	movzx ebx, word ptr [ebx+2]
	shl ebx, 4
	add ebx, eax			;Point to DOS request packet.
	mov [pRequest], ebx		;linear address request header

	mov al, [ebx].RPH.bOp

	@dprintf <'DevInt enter, Op=%X, flags=%X',13,10>, eax, [ebp].Client_Reg_Struc.Client_EFlags

	and al, al
	jz @F
	mov al, [bUnits]
	cmp [ebx].RPH.bSubU, al
	mov ax, 8101h
	jnc ExitAX
@@:
	mov esi, offset Vector
	mov cl, LVECTOR
	movzx eax, [ebx].RPH.bOp
	and al, al
	jns @F
	mov esi, offset Vect2
	and al, 7Fh
	mov cl, LVECT2
@@:
	cmp al, cl
	jnc Error3X
	push [ebp].Client_Reg_Struc.Client_EFlags
	or byte ptr [ebp].Client_Reg_Struc.Client_EFlags+1, 2	; set client IF so Yield will enable interrupts
	call dword ptr [esi+eax*4]
	pop [ebp].Client_Reg_Struc.Client_EFlags
ExitAX:
	@dprintf <'DevInt exit, ax=%X',13,10>, ax
	mov ebx, [pRequest]
	mov [ebx].RPH.wStat, ax
	@VMMCall Simulate_Far_Ret
	ret
Error3X:
	push ExitAX
Error3:
	mov ax, 8103h
	ret
Exit:
	mov ax, RPDON
	ret

DevInt endp

;--- IOCtl Input dispatcher

IOCtlInp proc

	.const

	align 4

;--- IOCTL input subcmds
IVect   label dword
	dd IOC_GetHdr	; 0 get device driver header address
	dd IOC_Error3	; 1 drive head location
	dd IOC_Error3	; 2 reserved
	dd IOC_Error3	; 3 error statistics
	dd IOC_Error3	; 4 audio channel info
	dd IOC_Error3	; 5 raw data bytes
	dd IOC_DevSt	; 6 device status
	dd IOC_SecSize	; 7 sector size
	dd IOC_Error3	; 8 volume size
	dd IOC_Media	; 9 media change status
;	dd IOC_Error3	;10 audio disk info
;	dd IOC_Error3	;11 audio track info
;	dd IOC_Error3	;12 audio q-channel info
;	dd IOC_Error3	;13 audio sub-channel info
;	dd IOC_Error3	;14 UPC code
;	dd IOC_Error3	;15 audio status info
LIVECT  equ ($ - offset IVect) shr 2

	.code

	movzx eax, word ptr [ebx].RPIOC.dwAddr+0
	movzx esi, word ptr [ebx].RPIOC.dwAddr+2
	shl esi, 4
	add esi, eax
	movzx eax, byte ptr [esi]
	@dprintf <'DevInt, ioctl input, buffer=%X, al=%X',13,10>, esi, eax
	cmp al, LIVECT
	jnc IOC_Error3
	jmp [eax*4][IVect]
IOC_Error3:
	mov ax, 8103h
	retn
IOC_Error12:
	mov ax, 810Ch
	retn

IOC_GetHdr:
	mov eax, [pBase]
	shl eax, 12
	@dprintf <'DevInt, ioctl input, gethdr, return=%X',13,10>, eax
	mov [esi+1], eax
IOC_done:
	mov ax, RPDON
	retn

;--- request "get device status"
;--- status flag bits:
;--- 001 - door opened
;--- 002 - door unlocked
;--- 004 - supports cooked AND raw
;--- 008 - read AND write
;--- 010 - data read AND play audio
;--- 020 - supports interleaving
;--- 040 - (res)
;--- 080 - supports prefetching
;--- 100 - supports audio channel manipulation
;--- 200 - supports HSG AND red book addressing modes

IOC_DevSt:
;	mov dword ptr [esi+1], 2	;set "door unlocked"
	mov dword ptr [esi+1], 2+4	;set "door unlocked" & "cooked AND raw"
	jmp IOC_done

IOC_SecSize:
	cmp byte ptr [esi+1],1	;read mode "cooked" or "raw"?
	ja IOC_Error12			;No?  Post "general failure" & exit.
	mov ax, SLRAW
	je @F
	mov ax, SLCOOKED
@@:
	mov [esi+2], ax
	jmp IOC_done

IOCtlInp endp

IOC_Media proc
	@dprintf <'DevInt, ioctl input, media',13,10>
	xor edi, edi
	call Setup		; set EDI=command table, ebx=port offset

;--- write packet data ( 12 bytes )
;--- 0: 4A - cmd "get event status notification"
;--- 1: 01 - bit 0=1 immediate
;--- 4: 10 - notification class request, bit 4=1 is "media"
;--- 7-8: 0008 - allocation length ( hibyte first )

;--- ACMD.00: 4A,01,00,00
;--- ACMD.04: 10,00,00,00
;--- ACMD.08: 08,00,00,00
	mov [edi].CT.Pkt0, 14AH
	mov [edi].CT.Pkt1, 10H
	mov [edi].CT.Pkt2, 8

	call Req8
	and al, al
	jnz MedChg

;--- request has returned 8 bytes,
;--- 0-3: event header (0-1 event data length, hibyte first)
;--- 4-7: event data ( 0=media event [bit 0-3], 1=media status [bit 0-1])	

	mov eax, [pBuff]
	mov ax, [eax+4]

	and al, al
	jnz MedChg
	test ah, 2  ; bit 1=1 if media present
	jz MedChg
	mov byte ptr [esi+1], 1
	jmp MedEnd
MedChg:
	mov byte ptr [esi+1], 0
MedEnd:
	call Setup
	call ReqSense

	mov eax, [pBuff]
	mov al, [eax+2]

	and al, 15
	jz @F
	mov byte ptr [esi+1], 0
	cmp al, 6
	jz MedEnd
@@:
	mov ax, RPDON
	ret
IOC_Media endp

;--- read sector(s)
;--- in: ebx=RL

ReadL proc
	mov al, 3
	cmp [ebx].RPRL.bAMode, 0; High Sierra addressing mode?
	jnz ErrorAL_AMode
	cmp [ebx].RPRL.bDMode, 1; 0=cooked, 1=raw
	ja ErrorAL_DMode

	movzx eax, word ptr [ebx].RPRL.dwAddr+0
	movzx edx, word ptr [ebx].RPRL.dwAddr+2
	shl edx, 4
	add eax, edx
	mov [pDest], eax

	mov cx, [ebx].RPRL.wSecCnt
	mov eax, [ebx].RPRL.dwStart
	mov [wSecCnt], cx
	mov [dwSector], eax
	@dprintf <'DevInt, readl, start=%X, sectors=%X, dst=%X',13,10>, eax, cx, pDest
	xor edi, edi
	mov esi, ebx
ReadLP:                 ;<----
	cmp [wSecCnt], 0
	jz Exit
	call Setup			; set EDI=command table, ebx=port offset

;--- write packet data ( 12 bytes )
;--- 0: cmd 28/0BE ( read cooked/raw )
;--- 1: flags
;--- 2-5: LBA (high byte first)
;--- 6: group no
;--- 7-8: transfer length [sector count] ( high byte first )
;--- 9: control (0 for cooked, 0F8h for raw mode)

	mov eax, [dwSector]
	shld ecx, eax, 16

;--- ax=sect[0-15]
;--- cx=sect[16-31]

	movzx eax, ax
	xchg al, ah
	xchg cl, ch

;--- al=sect[8-15], ah=sect[0-7], cl=sect[24-31], ch=sect[16-23]

	shl ecx, 16
	mov cl, 28H		; read cooked
;--- ACMD.00: 28h/0BEh (opcode "read cooked"),00,Sector.04,Sector.03
;--- ACMD.04: Sector.02, Sector.01, group#, length.02
;--- ACMD.08: length.01,00,00,00
	mov [edi].CT.Pkt0, ecx
	mov [edi].CT.Pkt1, eax
	mov [edi].CT.Pkt2, 1

	mov ecx, 800007FFH	; PRDT.0C: FF,07,00,80  (PRC=7FF transfer 2048 bytes, 80=I)
	cmp [esi].RPRL.bDMode, 0
	jz @F
;--- ACMD.00: 0BE (opcode "read raw"),00,Sector.04,Sector.03
	mov byte ptr [edi].CT.Pkt0, 0BEh
	mov byte ptr [edi].CT.Pkt2+1, 0F8h
	mov ecx, 8000092FH	; PRDT.0C: 2F,09,00,80  (PRC=92F transfer 2352 bytes, 80=I)
@@:
	call ReqECX
	and al, al
	jnz readerr
	push edi
	push esi
	mov ecx, SLCOOKED
	cmp [esi].RPRL.bDMode, 0
	jz @F
	mov ecx, SLRAW
@@:
	push ecx
	mov edi, [pDest]
	mov esi, [pBuff]
	cld
if ?IRQWND
	@VMMCall MoveMemory
else
	shr ecx, 2
	rep movsd
	@VMMCall Yield
endif
	pop ecx
	pop esi
	pop edi
	add [pDest], ecx
	inc [dwSector]
	dec [wSecCnt]
	jmp ReadLP
readerr:
	call Setup
	call ReqSense
	and al, al
	jnz ErrorAL
	mov eax, [pBuff]
	mov al, [eax+2]
	and al, 15
	mov ebx, offset ERRTAB
	xlat
ErrorAL_AMode:
ifdef _DEBUG
	@dprintf <'DevInt, readl, error, addressing mode',13,10>
	jmp ErrorAL
endif
ErrorAL_DMode:
ifdef _DEBUG
	@dprintf <'DevInt, readl, error, data mode',13,10>
	jmp ErrorAL
endif
ErrorAL:
	mov ah, 81h
	@dprintf <'DevInt, readl, error, ax=%X',13,10>, ax
	ret
Exit:
ifdef _DEBUG
	mov ebx, [pRequest]
	@dprintf <'DevInt, readl, ok, sector=%X',13,10>, [ebx].RPRL.dwStart
endif
	mov ax, RPDON
	ret
ReadL endp

;--- in:
;--- ebx=RP if edi==0
;--- out:
;--- ebx=port offset
;--- edi=linear address ATAPI command table

Setup proc
	cmp edi, 0			; first call?
	jnz @F
	movzx eax, byte ptr [ebx+1]
	movzx ebx, [eax*2][wPort]
	add ebx, [pHBA]

;--- get command list/table bases.
;--- those are physical addresses and hence "should" be translated to linear ones.

if ?OPTIONR
	mov eax, [pCLB]						; get command list base
	mov edi, [pCTBA]					; get command table base address
	@dprintf <'DevInt, setup, cmdlist=%X/%X, cmdtable=%X/%X',13,10>, eax, dword ptr [ebx].PORT.dqCLB, edi, [eax].CLH.dwCTBA
else
	mov eax, dword ptr [ebx].PORT.dqCLB	; get command list base
	mov edi, [eax].CLH.dwCTBA			; get command table base address
	@dprintf <'DevInt, setup, cmdlist=%X, cmdtable=%X',13,10>, eax, edi
endif

;--- CLH.00: 25,00,01,00 [CFL=5 dwords, A=1, PRD table length=1]
;--- CLH.04: 00,00,00,00 [PRD byte count=0]
	mov dword ptr [eax].CLH.flags1, 10025H
	mov [eax].CLH.PRDBC, 0

@@:
;--- CT.00: 27,80,A0,01 [27=H2D register FIS,80=set command register,A0=ATAPI packet command,01=Features]
;--- CT.04: 00,FF,FF,00 [LBA low,mid,high,device]
;--- CT.08: 00,00,00,00 [LBA (exp) low,mid,high,features]
;--- CT.0C: 01,00,00,00 [sector count, sector count,res,control]
	mov [edi].CT.cfis0, 1A08027H
	mov [edi].CT.cfis1, 0FFFF00H
	mov [edi].CT.cfis2, 0
	mov [edi].CT.cfis3, 1

;--- set base; must be physical address

	mov ecx, [dwBuffPh]
	mov [edi].CT.p0.dwBase, ecx
	xor ecx, ecx
	mov [edi].CT.p0.dwBaseU, ecx
	mov [edi].CT.p0.dwRsvd, ecx

	xor ecx, ecx
	mov [ebx].PORT.dwIE, ecx
	or ecx, -1
	mov [ebx].PORT.dwIS, ecx
	mov [ebx].PORT.dwSERR, ecx
	mov ecx, [ebx].PORT.dwCMD
	or cl, PCMD_FRE		; enable FIS receive
	mov [ebx].PORT.dwCMD, ecx
	or cl, PCMD_ST		; start processing command list
	mov [ebx].PORT.dwCMD, ecx
	@dprintf <'DevInt, setup, port=%X, cmdtable=%X, waiting',13,10>, ebx, edi
@@:
	mov eax, [ebx].PORT.dwCMD
	test ax, PCMD_CR	; command list running?
if 0 ; changed 04/2023
	jz @B
else
	jnz @F
	@VMMCall Yield
	jmp @B
@@:
endif
	ret
Setup endp

;--- initiate "request sense notification" cmd

ReqSense proc

;--- write packet data ( 12 bytes )
;--- 0: cmd 03 ( request sense )
;--- 1-3: reserved
;--- 4: allocation length
;--- 5: control

;--- ACMD.00: 03,00,00,00
;--- ACMD.04: 08,00,00,00
;--- ACMD.08: 00,00,00,00
	mov [edi].CT.Pkt0, 3
	mov [edi].CT.Pkt1, 8
	mov [edi].CT.Pkt2, 0

ReqSense endp

;--- fall thru!!!

;--- Req8: read 8 bytes into buffer

Req8:
	mov ecx, 80000007H	; PRDT.12: 07,00,00,80 (PRC=7; read 8 bytes, 80=I)

;--- ReqECX: 
;--- in: ecx: read ECX+1 bytes ( bit 31 = 1, indicating end of table )
;---     edi: cmd table
;---     ebx: port
;--- out: AL=0 ok, AL=12 error

ReqECX proc
	mov [edi].CT.p0.dwCnt, ecx
	mov [ebx].PORT.dwCI, 1	; bitmask, 1=slot 0 command issued
contwait:
	cmp [ebx].PORT.dwCI, 0
	jz done
	test [ebx].PORT.dwIS, PIS_TFES
	jnz error
	@VMMCall Yield
	cmp [ebx].PORT.dwSERR, 0
	JZ contwait
error:
	call Stop
	mov al, 12
	ret
done:
	mov eax, [ebx].PORT.dwTFD
	test al, 1
	jnz error
	call Stop
	mov al, 0
	ret

Stop:
	mov ecx, [ebx].PORT.dwCMD
	or cl, PCMD_CLO
	and cl, 0EEH		; good idea to reset PCMD_ST and PCMD_FRE here?
	mov [ebx].PORT.dwCMD, ecx
	retn

ReqECX endp

;--- read PCI config address/data ports
;--- in: edx = addr+80000000h
;--- out: eax = value

GetPCI proc
	push edx
	mov eax, edx
	mov dx, 0cf8h
	out dx, eax
	mov dl, 0fch
	in eax, dx
	pop edx
	ret
GetPCI endp

SavePCI proc
	mov dx, 0cf8h
	in eax, dx
	mov ebx, eax
	ret
SavePCI endp

RestPCI proc
	mov dx, 0cf8h
	mov eax, ebx
	out dx, eax
	ret
RestPCI endp

if 0

;--- in: edx = addr+80000000h, eax = value

PutPCI proc
	push edx
	push eax
	mov eax, edx
	mov dx, 0cf8h
	out dx, eax
	mov dl, 0fch
	pop eax
	out dx, eax
	pop edx
	ret
PutPCI endp

endif

;--- display string EDX

dispString proc
	push esi
	mov esi, edx
	@VMMCall Begin_Nest_Exec
nextitem:
	lodsb
	cmp al,0
	jz done
	mov byte ptr [ebp].Client_Reg_Struc.Client_EDX, al
	mov byte ptr [ebp].Client_Reg_Struc.Client_EAX+1, 2
	mov eax, 21h
	@VMMCall Exec_Int
	jmp nextitem
done:
	@VMMCall End_Nest_Exec
	pop esi
	ret
dispString endp

dispBanner proc
	cmp bQuiet, 0
	jnz @F
	cmp bBanner, 0
	jnz @F
	mov bBanner, 1
	push edx
	mov edx, CStr('AHCI Optical Disk Driver v1.2',13,10,"Inspired by Rudolph R. Loew's AHCICD",13,10)
	call dispString
	pop edx
@@:
	ret
dispBanner endp

;--- ebp: client reg struct
;--- esi: cmdline

Init proc

;--- scan cmdline args

nextchar:
	lodsb
	cmp al, ' '
	jz nextchar
	cmp al, 9
	jz nextchar
	cmp al, 13
	jz donecmdl
	cmp al, 0
	jz donecmdl
	cmp al, '/'
	jnz errcmdl
	lodsb
	mov ah, [esi]
	or al, 20h
	cmp ax, ':c'
	jz isOptC
	cmp ax, ':d'
	jz isOptD
	cmp AL, 'q'
	jz isOptQ
if ?OPTIONR
	cmp AL, 'r'
	jz isOptR
endif
	jmp errcmdl

isOptD:
	inc esi
	mov edi, [pBase]
	add edi, DOSDRV.name_
	mov dword ptr [edi+0], '    '
	mov dword ptr [edi+4], '    '
	mov ecx, sizeof DOSDRV.name_
nextdevchar:
	lodsb
	cmp al, ' '
	jbe doneOptD
	cmp al, 'a'
	jb @F
	cmp al, 'z'
	ja @F
	sub al, 20H
@@:
	stosb
	loop nextdevchar
	inc esi
doneOptD:
	dec esi
	jmp nextchar
isOptC:
	inc esi
	lodsb
	cmp al, '0'
	jb errcmdl
	cmp al, '9'
	Ja errcmdl
	sub al, '0'
	mov [bCntOpt], al
	jmp nextchar
isOptQ:
	mov [bQuiet], 1
	jmp nextchar
if ?OPTIONR
isOptR:
	mov [bReloc], 1
	jmp nextchar
endif

donecmdl:

;--- done cmdline processing

	call dispBanner

;--- scan for AHCI devices

	call SavePCI
	mov edx, 80000008H
nextHBA:
	call GetPCI
	mov al, 0			; clear bits 0-7 (interface doesn't matter)
	cmp eax, 1060100H	; AHCI device?
	jnz @F
	dec [bCntOpt]		; /C:x option?
	js  foundHBA
@@:
	@VMMCall Yield
	add edx, 100H		; next "function"
	cmp edx, 81000008H
	jc nextHBA
	call RestPCI
	jmp errnodisk

foundHBA:
	@dprintf <'found AHCI device at PCI=%X',13,10>, edx

	mov dl, 24h			;get ABAR5
	call GetPCI
	mov edi, eax

	call RestPCI

;--- HBA does not necessarily have to start at a page boundary
;--- so always reserve 2 pages.

	@dprintf <'HBA physical addr=%X',13,10>, edi

	push 0
	push 2
	push PR_SYSTEM
	@VMMCall _PageReserve
	add esp, 3*4
	cmp eax, -1
	jz errpr
	mov ebx, eax

	shr eax, 12		; convert linear address to page#
	mov ecx, edi
	shr ecx, 12
	push PC_WRITEABLE
	push ecx
	push 2			; map 2 pages ( in theory even 3 might be needed )
	push eax
	@VMMCall _PageCommitPhys
	add esp, 4*4

	and edi, 0fffh
	add ebx, edi
	mov [pHBA], ebx
	@dprintf <'HBA mapped at linear addr=%X',13,10>, ebx
	mov eax, [ebx].HBA.dwGHC	; get Global HBA Control
	@dprintf <'HBA.GHC=%X',13,10>, eax
	test eax, 80000000H	; AHCI enabled?
	jz errnoahci

	mov ecx, [ebx].HBA.dwPI	; get ports implemented (bit mask)
	@dprintf <'HBA.Ports=%X',13,10>, ecx

	mov edx, 100h		; port offsets are 100h, 180h, 200h, 280h, ..., 1080h
	mov edi, offset wPort
nextPort:
	shr ecx, 1
	jnc @F
	mov eax, [ebx+edx].PORT.dwSIG	; get signature
	cmp eax, 0EB140101H
	jnz @F
	@dprintf <'found ATAPI device at port=%X',13,10>, edx
	mov eax, [ebx+edx].PORT.dwSSTS	; get SATA status
	@dprintf <'device status=%X',13,10>, eax
	and al, 0FH			; bits 0-3: device detection
	cmp al, 3			; device detected and communication established?
	jnz @F
	mov eax, edx
	stosw
	cmp edi, offset wPort + sizeof wPort; table end reached?
	jz donePort
@@:
	add edx, 80H
	and ecx, ecx
	Jnz nextPort

donePort:
	sub edi, offset wPort
	shr edi, 1
	mov ecx, edi
	cmp ecx, 0
	jz errnodisk
	mov [bUnits], cl

if ?OPTIONR
	mov edi, offset wPort
	cmp [bReloc], 0
	jz noreloc
	mov esi, offset cmdlst
	mov [pCLB], esi
	mov [pCTBA], offset cmdtab
	mov [pBuff], offset buffer
	push ecx
	mov ecx, sizeof cmdlst + sizeof fis + sizeof cmdtab + sizeof buffer
	mov edx, 1
	VxDCall VDMAD_Lock_DMA_Region
	pop ecx
	@dprintf <'physical/logical address CLB=%X/%X',13,10>, edx, esi
	mov esi, edx
	.while ecx
		movzx edx, word ptr [edi]
		mov eax, esi
		mov dword ptr [ebx+edx].PORT.dqCLB, eax
		add eax, sizeof cmdlst
		mov dword ptr [ebx+edx].PORT.dqFB, eax
		add edi, sizeof WORD
		dec ecx
	.endw
	mov eax, esi
	add eax, sizeof cmdlst + sizeof fis
	mov edx, [pCLB]
	mov [edx].CLH.dwCTBA, eax
	@dprintf <'CLB.CTBA=%X',13,10>, eax
	add eax, sizeof cmdtab
	mov [dwBuffPh], eax
	jmp buffers_done
noreloc:
	movzx edx, word ptr [edi]
	mov eax, dword ptr [ebx+edx].PORT.dqCLB
	mov edx, [eax].CLH.dwCTBA
	mov [pCLB], eax
	mov [pCTBA], edx
	@dprintf <'linear address command list/table=%X/%X',13,10>, eax, edx
endif
	mov esi, offset buffer
	mov [pBuff], esi
	mov ecx, SLCOOKED
	mov edx, 1
	VxDCall VDMAD_Lock_DMA_Region
	mov [dwBuffPh], edx
	@dprintf <'physical address sector buffer=%X',13,10>, edx

buffers_done:

	mov ebx, [pBase]
	mov al, [bUnits]
	mov [ebx].DOSDRV.bUnits, al
	cmp [bQuiet], 0
	jnz @F
	add al,'0'
	movzx eax, al
	push eax
	mov edx, esp
	call dispString
	pop eax
	mov edx, CStr(' AHCI Optical Disk(s) Found',13,10)
	call dispString
@@:
	mov ebx, [pRequest]
	mov word ptr [ebx].RPInit.dwFree+0, REQOFS+4+SIZERMCODE+5
	mov ax, RPDON
	mov [ebx].RPInit.wStat, ax
	mov [ebx].RPInit.bUnit, 0
	ret

errpr:
	mov edx, CStr('_PageReserve() failed',13,10)
	jmp @F
errnoahci:
	mov edx, CStr('AHCI Controller not in AHCI Mode',13,10)
	jmp @F
errcmdl:
if ?OPTIONR
	mov edx, CStr('SYNTAX: DEVICE=JLOAD.EXE AHCICD.DLL [/C:#] /D:devname [/Q][/R]',13,10)
else
	mov edx, CStr('SYNTAX: DEVICE=JLOAD.EXE AHCICD.DLL [/C:#] /D:devname [/Q]',13,10)
endif
	jmp @F
errnodisk:
	MOV edx, CStr('No AHCI Optical Disk Found',13,10)
@@:
	call dispBanner
	call dispString
	mov ax, RPERR
	ret
Init endp

DllMain proc stdcall public uses esi edi hModule:dword, dwReason:dword, dwRes:dword

local pCmdLine:dword

	mov eax, dwReason
	cmp eax, 1
	jnz done

	mov esi, dwRes
	test [esi].JLCOMM.wFlags, JLF_DRIVER
	jz failed
	movzx ecx, [esi].JLCOMM.wLdrCS
	shl ecx, 4
	mov [pBase], ecx
	lea eax, [ecx+REQOFS]
	mov [ppReq], eax
	mov eax, [esi].JLCOMM.lpCmdLine
	mov [pCmdLine], eax
	mov eax, [esi].JLCOMM.lpRequest
	mov [pRequest], eax

	mov esi, offset DevInt
	xor edx, edx
	@VMMCall Allocate_V86_Call_Back
	jc failed

	mov edi, [pBase]
	mov [edi].DOSDRV.wAttr, 0C800h		;driver attributes
	mov [edi].DOSDRV.ofsStr, REQOFS+4
	mov [edi].DOSDRV.ofsInt, REQOFS+4+SIZERMCODE
	mov [edi].DOSDRV.wRes1, 0
	mov [edi].DOSDRV.bRes2, 0

	add edi, REQOFS+4
	mov esi, offset rmcode
	mov ecx, SIZERMCODE+1
	cld
	rep movsb
	stosd

	@VMMCall Get_Cur_VM_Handle

	mov esi, [pCmdLine]

;--- set EBP to the client pointer before calling I_Init

	push ebp
	mov ebp, [ebx].cb_s.CB_Client_Pointer
	call Init
	pop ebp

	cmp ax,RPDON
	setz al
	movzx eax,al
done:
	ret
failed:
	xor eax, eax
	ret

DllMain endp

	end DllMain



================================================
FILE: JLM/AHCICD/AHCICD.txt
================================================

  1. About AHCICD

  AHCICD is a JLM to access AHCI optical disks, "inspired" by Rudolph R. Loew's
  AHCICD.SYS. To load it, add the following line to your CONFIG.SYS:

   DEVICE=JLOAD.EXE AHCICD.DLL [options]

  options are:

   /C:device select AHCI controller if more than one exists.
   /D:name   set device name. Required.
   /Q        no displays unless errors occur.
   /R        relocate AHCI regions [CL/FIS/CT] to extended memory.


  2. Hints

  - AHCI uses tables that may be located in the XBDA - so if the XBDA is to
    be moved, setting option /R is required.
  - AHCICD.DLL needs JLOAD v5.83 - older versions won't disable caching
    of the controller's memory-mapped registers.



================================================
FILE: JLM/AHCICD/MAKE.BAT
================================================
@echo off

jwasm -c -coff -nologo -Fl -Sg -I..\..\Include AHCICD.ASM
rem jwasm -coff -nologo -D_DEBUG -Fl -Sg -I..\..\Include AHCICD.ASM
jwlink format win pe hx dll ru native file AHCICD.obj name AHCICD.DLL op q,map


================================================
FILE: JLM/AHCICD/MAKEM.BAT
================================================
@echo off

ml -c -coff -nologo -Fl -Sg -I..\..\Include AHCICD.ASM
link /nologo /subsystem:native /dll AHCICD.obj /OUT:AHCICD.DLL /MAP


================================================
FILE: JLM/GENERIC/GENERIC.ASM
================================================

;--- JLM sample GENERIC
;--- use Makefile to create GENERIC.DLL

;--- GENERIC is a very simple JLM. It doesn't hook v86-interrupt vectors.
;--- To be called from v86-mode, its entry point must be obtained by the
;--- caller.

	.386
	.model flat, stdcall

	.nolist
	include jlm.inc
	.list

DEVICE_ID equ 6660h

cr equ 13
lf equ 10

DLL_PROCESS_ATTACH  equ 1
DLL_PROCESS_DETACH  equ 0

	.data

;--- the DDB must be make public. The linker will "export" this
;--- symbol. This is the simplest method to make JLoad know the
;--- device id.

	public ddb

ddb VxD_Desc_Block <0,0,DEVICE_ID,1,0,0,"GENERIC",0, 0, v86_dispatch>

szHello db "Hello from JLM GENERIC",cr,lf,0

	.code

;--- dispatcher for v86 services

v86_dispatch proc

	@VMMCall Simulate_Far_Ret	;emulate a RETF in v86

	and [ebp].Client_Reg_Struc.Client_EFlags,not 1  ;clear Carry flag
	movzx eax, word ptr [ebp].Client_Reg_Struc.Client_EAX
	cmp eax,0
	jz getversion
	cmp eax,1
	jz display_hello
	or [ebp].Client_Reg_Struc.Client_EFlags,1  ;set Carry flag
	ret
	align 4

v86_dispatch endp

getversion proc

	mov word ptr [ebp].Client_Reg_Struc.Client_EAX, 0100h
	ret
	align 4

getversion endp

display_hello proc uses esi

	@VMMCall Begin_Nest_Exec 	;start nested execution
	mov esi, offset szHello
@@:
	lodsb
	and al,al
	jz done

;--- Call int 21h, ah=2 in v86-mode.
;--- Be aware that in Jemm's context is no DOS extender installed.
;--- So there is no translation for DOS functions which use pointers.

	mov byte ptr [ebp].Client_Reg_Struc.Client_EDX,al
	mov byte ptr [ebp].Client_Reg_Struc.Client_EAX+1,2
	mov eax,21h
	@VMMCall Exec_Int
	jmp @B
done:
	@VMMCall End_Nest_Exec		;end nested execution
	ret
	align 4

display_hello endp

;--- install the JLM: just set eax=1
;--- this tells JLOAD that it's ok to add GENERIC to the list of
;--- loaded modules.

install proc uses esi pcomm:ptr JLCOMM

	mov eax,1
	ret
	align 4

install endp

;--- deinstall the JLM: just set eax=1.
;--- this tells JLOAD that it's ok to remove the module.

deinstall proc pcomm:ptr JLCOMM

	mov eax,1
	ret
	align 4

deinstall endp

DllMain proc stdcall public hModule:dword, dwReason:dword, dwRes:dword

	mov eax,dwReason
	cmp eax,DLL_PROCESS_ATTACH
	jnz @F
	invoke install, dwRes
	jmp exit
@@:
	cmp eax,DLL_PROCESS_DETACH
	jnz @F
	invoke deinstall, dwRes
@@:
exit:
	ret
	align 4

DllMain endp

	end DllMain


================================================
FILE: JLM/GENERIC/MAKEFILE
================================================

# NMake/WMake Makefile to create GENERIC.DLL
#
#  tools                      alternatives
#----------------------------------------------------------
#  JWasm                      Masm v6.x
#  JWLink                     Link, WLink, ALink

NAME = GENERIC
OUTDIR=Release
AOPT=-nologo -c -coff -nologo -Fl$*.lst -Fo$*.obj -I..\..\Include
ASM=jwasm.exe
#LINK=link.exe /NOLOGO /SUBSYSTEM:NATIVE /DLL $*.obj /OUT:$*.DLL /MAP:$*.MAP /EXPORT:ddb /Entry:DllMain /OPT:NOWIN98
LINK=jwlink format win nt hx dll ru native file $*.obj name $*.DLL op q,map=$*.MAP export _ddb.1

ALL: $(OUTDIR) $(OUTDIR)\$(NAME).DLL $(OUTDIR)\TESTGEN.COM

$(OUTDIR):
	@mkdir $(OUTDIR)

$(OUTDIR)\$(NAME).DLL: $(OUTDIR)\$(NAME).obj Makefile
	@$(LINK)

$(OUTDIR)\$(NAME).obj: $(NAME).asm
	@$(ASM) $(AOPT) $(NAME).asm

$(OUTDIR)\TESTGEN.COM: TESTGEN.ASM
	@jwasm -nologo -bin -Fo$*.COM -Fl$* testgen.asm


================================================
FILE: JLM/GENERIC/README.TXT
================================================

 1. About

 GENERIC is a JLM sample which demonstrates how to implement a
 protected-mode TSR.


 2. How to install and uninstall GENERIC

 GENERIC can be installed either as a device driver in CONFIG.SYS:

   DEVICE=JLOAD.EXE GENERIC.DLL

 or as a TSR from the command line:

   JLOAD GENERIC.DLL

 To uninstall, use JLOAD's -u option:

   JLOAD -u GENERIC.DLL


 3. How to use GENERIC

 GENERIC doesn't hook real-mode interrupt vectors. If a real-mode program
 wants to call a function provided by GENERIC, it first has to get the JLM's
 entry point. This is done similiar to Windows 9x: a call of Int 2F, 
 AX=1684h with register BX containing the "device id". On return, if the
 "device" has been found, ES:DI will contain its entry address:
 
  mov ax, 1684h   ;standard value to get VxD entry points
  mov bx, 6660h   ;6660h is the ID of GENERIC
  int 2Fh
  cmp al,0
  jnz not_installed
  mov word ptr [genpm+0],di
  mov word ptr [genpm+2],es

 The protected-mode TSR implements two functions, which are selected
 by the value of register AX:

  mov ax, 0000             ;0000=get version
  call dword ptr [genpm]

  mov ax, 0001             ;0001=display hello
  call dword ptr [genpm]

 There's a test program - TESTGEN.EXE - supplied which uses GENERIC.


 4. License

 GENERIC is Public Domain.

 Japheth



================================================
FILE: JLM/GENERIC/TESTGEN.ASM
================================================

;--- test app which calls some "services" of JLM GENERIC.
;--- assemble: JWasm -bin -Fo testgen.com testgen.asm

	.model tiny

	.data

szOK    db "GENERIC found!",13,10,'$'
szError db "GENERIC is NOT installed!",13,10,'$'

	.code

	org 100h

start:
	mov ax, 1684h	;get GENERIC's entry point
	mov bx, 6660h
	int 2Fh
	cmp al,0
	jnz not_installed
	push es
	push di
	mov bp,sp
	mov dx,offset szOk
	mov ah,9
	int 21h
	mov ax,0000     ;call "get version"
	call dword ptr [bp]
	mov ax,0001     ;call "display hello"
	call dword ptr [bp]
	add sp,4
	int 20h
not_installed:
	mov dx,offset szError
	mov ah,9
	int 21h
	int 20h

	end start



================================================
FILE: JLM/HELLO/HELLO.ASM
================================================

;--- a simple JLM which displays a message onto the screen
;--- with the help of v86-int 21h and nested execution

        .386
        .MODEL FLAT, stdcall

        include jlm.inc

ifdef FMTPE
;--- since v2.19, JWasm's -pe option knows how to interpret linker directives supplied
;--- in the .drectve info section. Thus no extra link step is required.
        option dotname
.drectve segment info	;linker directives
        db "-subsystem:native -fixed:no"
.drectve ends
.hdr$1 segment use16
%       incbin <STUB>
.hdr$1 ends
endif

        .DATA

szText  db "Hello, world!", 13,10,0

        .CODE

_main   proc

        push esi
        @VMMCall Begin_Nest_Exec     ;start nested execution
        mov esi, offset szText
@@nextitem:
        lodsb
        and al,al
        jz @@done

;--- Call int 21h, ah=2 in v86-mode.
;--- Be aware that in Jemm's context is no DOS extender installed.
;--- So there is no translation for DOS functions that use pointers.

        mov byte ptr [ebp].Client_Reg_Struc.Client_EDX,al
        mov byte ptr [ebp].Client_Reg_Struc.Client_EAX+1,2
        mov eax,21h
        @VMMCall Exec_Int

        jmp @@nextitem
@@done:
        @VMMCall End_Nest_Exec       ;end nested execution
        pop esi
        mov eax, 80000001h	;bit 31=1: suppress JLoad msg
        ret

_main   ENDP

        END _main



================================================
FILE: JLM/HELLO/MAKE.BAT
================================================
@echo off
rem
rem use JWasm & JWlink
rem
jwasm -nologo -coff -Fl=Release\Hello -Fo=Release\Hello -I..\..\Include Hello.asm
jwlink format win pe hx ru native file Release\Hello.obj name Release\Hello.exe op q,m=Release\Hello,stack=0x1000

rem use JWasm - since JWasm v2.19, cmdline option -pe supports several linker features;
rem also, stub JLSTUB.BIN may be added. Then the program can be launched simply by typing its name.
rem
rem jwasm -nologo -pe -DFMTPE -DSTUB=..\JLSTUB\Build\jlstub.bin -Fl=Release\Hello -Fo=Release\Hello -I..\..\Include Hello.asm
rem patchPE -x -s:0x1000 Release\Hello.exe

rem use Masm & Link
rem
rem ml -c -coff -FlRelease\Hello -FoRelease\Hello -I..\..\Include Hello.asm
rem link /NOLOGO Release\HELLO.OBJ /subsystem:native /FIXED:NO /map /out:Release\Hello.exe /ENTRY:_main /OPT:NOWIN98
rem \hx\bin\patchpe -s:0x4000 -x Release\Hello.exe


================================================
FILE: JLM/HELLO/README.TXT
================================================

  About

  This is the inevitable "hello world" JLM, written for Masm/JWasm.
  It displays a welcome message. After execution the module's resources
  are released.

  Usage: C:\>JLOAD -q HELLO.EXE


================================================
FILE: JLM/HELLO2/HELLO2.C
================================================

// for MS VC

#include <jlm.h>

struct Client_Reg_Struc * pcl;

struct cb_s * Get_Cur_VM_Handle()
{
    VxDCall(Get_Cur_VM_Handle);
    _asm mov eax,ebx;
}

ULONG Begin_Nest_Exec()
{
    _asm mov ebp,pcl;
    VxDCall(Begin_Nest_Exec);
}

ULONG End_Nest_Exec()
{
    _asm mov ebp,pcl;
    VxDCall(End_Nest_Exec);
}

ULONG Exec_Int(unsigned long intno)
{
    _asm mov eax, intno;
    _asm mov ebp,pcl;
    VxDCall(Exec_Int);
}

int main()
{
    struct cb_s * hVM;
    unsigned char * psz = "Hello world\r\n";

    hVM = Get_Cur_VM_Handle();
    pcl = (struct Client_Reg_Struc *)hVM->CB_Client_Pointer;
    Begin_Nest_Exec();

    for (;*psz;psz++) {
        pcl->Client_EAX = 0x0200;
        pcl->Client_EDX = *psz;
        Exec_Int(0x21);
    }

    End_Nest_Exec();

    return 1;
};


================================================
FILE: JLM/HELLO2/HELLO2W.C
================================================

// for Open Watcom C
// OW inline assembly doesn't know values of enums!
// therefore it needs external module jlmw.asm

#include <JLM.H>
#include "JLMW.h"

struct Client_Reg_Struc * pcl;

int main()
{
    struct cb_s * hVM;
    unsigned char * psz = "Hello world\r\n";

    hVM = Get_Cur_VM_Handle();
    pcl = (struct Client_Reg_Struc *)hVM->CB_Client_Pointer;
    Begin_Nest_Exec(pcl);

    for (;*psz;psz++) {
        pcl->Client_EAX = 0x0200;
        pcl->Client_EDX = *psz;
        Exec_Int(0x21, pcl);
    }

    End_Nest_Exec(pcl);

    return 1;
};


================================================
FILE: JLM/HELLO2/JLMW.ASM
================================================

;--- helpers for (Watcom) C

	.386
    .model flat
    
	include JLM.INC

	.code

Get_Cur_VM_Handle proc stdcall public uses ebx
    @VMMCall Get_Cur_VM_Handle
    mov eax, ebx
    ret
    align 4
Get_Cur_VM_Handle endp

Begin_Nest_Exec proc stdcall public uses ebp pcl:ptr
    mov ebp,pcl
    @VMMCall Begin_Nest_Exec 
    ret
    align 4
Begin_Nest_Exec endp

End_Nest_Exec proc stdcall public uses ebp pcl:ptr
    mov ebp,pcl
    @VMMCall End_Nest_Exec
	ret
    align 4
End_Nest_Exec endp

Exec_Int proc stdcall public uses ebp intno:dword, pcl:ptr
    mov eax, intno
    mov ebp,pcl
    @VMMCall Exec_Int
    ret
    align 4
Exec_Int endp

	end


================================================
FILE: JLM/HELLO2/JLMW.h
================================================

// helper procs needed by Open Watcom C

extern struct cb_s * _stdcall Get_Cur_VM_Handle( void );
extern ULONG _stdcall Begin_Nest_Exec(struct Client_Reg_Struc * pcl);
extern ULONG _stdcall End_Nest_Exec(struct Client_Reg_Struc * pcl);
extern ULONG _stdcall Exec_Int( unsigned long intno, struct Client_Reg_Struc * pcl );


================================================
FILE: JLM/HELLO2/MAKEJLMW.BAT
================================================
@echo off
rem assembles helper module jlmw for Open Watcom.
jwasm -I ..\..\Include jlmw.asm


================================================
FILE: JLM/HELLO2/MAKEOW.BAT
================================================
@echo off
rem uses Open Watcom C and WLink
rem OW needs a helper module: jlmw.obj
wcc386 -mf -zl -zls -s -I..\..\Include hello2w.c
jwlink format win nt hx ru native file hello2w.obj, jlmw.obj name hello2w.exe option start=main_, map


================================================
FILE: JLM/HELLO2/MAKEVC.BAT
================================================
@echo off
rem uses MS VC and MS Link
\msvc71\bin\cl -c -I..\..\Include hello2.c
link /LIBPATH:\msvc71\lib hello2.obj /subsystem:native /fixed:no /out:hello2.exe /entry:main
\hx\bin\patchpe hello2.exe


================================================
FILE: JLM/HELLO2/README.TXT
================================================

 About
 
 Another JLM "hello world", this time written in C.
 MAKEVC.BAT: for MS VC (or Pelles C, CC386, ...)
 MAKEOW.BAT: for Open Watcom.

 to run it: jload /q hello2(w).exe

 There is room for improvement. 


================================================
FILE: JLM/HELLO2/makeow.sh
================================================
#!/bin/sh
set -e
# uses Open Watcom C, JWAsm and JWLink which must be in PATH
# OW needs a helper module: jlmw.obj
jwasm -I../../Include JLMW.ASM
wcc386 -mf -zl -zls -s -I../../Include HELLO2W.C
jwlink format win nt hx ru native file HELLO2W.o, JLMW.o name hello2w.exe option start=main_, map



================================================
FILE: JLM/IOTRAP/IOTRAP.ASM
================================================

;--- JLM sample IOTRAP
;--- use Makefile to create IOTRAP.DLL

;--- IOTRAP traps IO port 100h when the first client
;--- wants to register a callback.
;--- The client is notified whenever an IO access happens.

	.386
	.model flat, stdcall

PORT equ 100h	;port to trap

CODE16_SEL	equ 20h
DATA16_SEL	equ 28h

	.nolist
	include jlm.inc
	.list

DEVICE_ID equ 6661h

cr equ 13
lf equ 10

DLL_PROCESS_ATTACH  equ 1
DLL_PROCESS_DETACH  equ 0

	.data

;--- the DDB must be make public. The linker will "export" this
;--- symbol. This is the simplest method to make JLoad know the
;--- device id.

	public ddb

ddb VxD_Desc_Block <0,0,DEVICE_ID,1,0,0,"IOTRAP",0,0, v86_dispatch >

szHello db "Hello from JLM IOTRAP",cr,lf,0

cntCB dd 0
callbacks label dword
	dd 8*2 dup (0)	;allow 8 callbacks

	.code

;--- dispatcher for v86 services

v86_dispatch proc

	@VMMCall Simulate_Far_Ret	;emulate a RETF in v86

	and [ebp].Client_Reg_Struc.Client_EFlags,not 1  ;clear Carry flag
	movzx eax, word ptr [ebp].Client_Reg_Struc.Client_EAX
	cmp eax,0
	jz getversion
	cmp eax,1
	jz register_callback
	or [ebp].Client_Reg_Struc.Client_EFlags,1  ;set Carry flag
	ret
	align 4

v86_dispatch endp

getversion proc

	mov word ptr [ebp].Client_Reg_Struc.Client_EAX, 0100h
	ret
	align 4

getversion endp

register_callback proc
	.if ( cntCB >= 8 )
		or [ebp].Client_Reg_Struc.Client_EFlags,1  ;set Carry flag
		mov word ptr [ebp].Client_Reg_Struc.Client_EAX, 8
		ret
	.endif
;--- when the first client registers, install an io handler 
	.if ( cntCB == 0 )
		mov esi, offset iocb
		mov edx, PORT
		@VMMCall Install_IO_Handler
		.if ( CARRY? )
			or [ebp].Client_Reg_Struc.Client_EFlags,1  ;set Carry flag
			mov word ptr [ebp].Client_Reg_Struc.Client_EAX, 9
			ret
		.endif
	.endif
	mov cx, word ptr [ebp].Client_Reg_Struc.Client_ECX	;callback's CS
	shl ecx,16
	mov cx, word ptr [ebp].Client_Reg_Struc.Client_EDX	;callback's IP
	mov eax, cntCB
	mov [eax*8+callbacks+0], ecx
	mov ecx, [ebp].Client_Reg_Struc.Client_EBX			;callback's param
	mov [eax*8+callbacks+4], ecx
	inc cntCB
	ret
	align 4

register_callback endp

;--- io handler proc
;--- ecx=type of io
;--- edx=port
;--- ebp=client struct
;--- eax=io data

PF32 typedef ptr far32

iocb proc
if 0 ;if the client is to be called in v86-mode
	push esi
	push edi
	sub esp, sizeof Client_Reg_Struc
	mov edi, esp
	push ecx
	push edx
	push eax
	@VMMCall Save_Client_State
	@VMMCall Begin_Nest_Exec 	;start nested execution
	mov esi, offset callbacks
	mov ecx, cntCB

	.while ecx
		push ecx
		mov eax,[esp+4]
		mov edx,[esp+8]
		mov ecx,[esp+12]
		mov [ebp].Client_Reg_Struc.Client_EDX, edx
		mov [ebp].Client_Reg_Struc.Client_ECX, ecx
		mov [ebp].Client_Reg_Struc.Client_EAX, eax
		lodsd
		movzx edx,ax
		shr eax,16
		mov ecx, eax
		@VMMCall Simulate_Far_Call
		lodsd
		mov [ebp].Client_Reg_Struc.Client_EBX, eax
		@VMMCall Resume_Exec		;run the VM
		pop ecx
		dec ecx
	.endw

	@VMMCall End_Nest_Exec		;end nested execution
	lea esi, [esp+3*4]
	@VMMCall Restore_Client_State
	pop eax
	pop edx
	pop ecx
	add esp, sizeof Client_Reg_Struc
	pop edi
	pop esi
	ret
else ;if the client is to be called in protected-mode
	pushad
	push ecx
	push edx
	push eax
	sub esp,8
	sgdt [esp]
	mov eax,[esp+2]
	add esp,8
	mov esi, offset callbacks
	mov ecx, cntCB

	.while ecx
		push ecx
		push eax
		lodsd
		push CODE16_SEL
		pushw 0
		push ax
		shr eax,16
		shl eax, 4
		mov edx,[esp+2*4]
		mov [edx+CODE16_SEL+2],ax
		mov [edx+DATA16_SEL+2],ax
		shr eax,16
		mov [edx+CODE16_SEL+4],al
		mov [edx+DATA16_SEL+4],al
		lodsd
		mov ebx, eax
		mov eax,[esp+4*4+0]
		mov edx,[esp+4*4+4]
		mov ecx,[esp+4*4+8]
		push ds
		push DATA16_SEL
		pop ds
		call PF32 ptr [esp+4]
		pop ds
		add esp,2*4
		pop eax
		pop ecx
		dec ecx
	.endw

	add esp,3*4
	popad
	ret
endif
	align 4
iocb endp

;--- install the JLM: just set eax=1
;--- this tells JLOAD that it's ok to add IOTRAP to the list of
;--- loaded modules.

install proc uses esi pcomm:ptr JLCOMM

	mov eax,1
	ret
	align 4

install endp

;--- deinstall the JLM: just set eax=1.
;--- this tells JLOAD that it's ok to remove the module.

deinstall proc pcomm:ptr JLCOMM

	.if ( cntCB )
		mov edx, PORT
		@VMMCall Remove_IO_Handler
	.endif
	mov eax,1
	ret
	align 4

deinstall endp

DllMain proc stdcall public hModule:dword, dwReason:dword, dwRes:dword

	mov eax,dwReason
	cmp eax,DLL_PROCESS_ATTACH
	jnz @F
	invoke install, dwRes
	jmp exit
@@:
	cmp eax,DLL_PROCESS_DETACH
	jnz @F
	invoke deinstall, dwRes
@@:
exit:
	ret
	align 4

DllMain endp

	end DllMain


================================================
FILE: JLM/IOTRAP/MAKEFILE
================================================

# NMake/WMake Makefile to create IOTRAP.DLL
#
#  tools                      alternatives
#----------------------------------------------------------
#  JWasm                      Masm v6.x
#  JWLink                     MS Link, WLink, ALink
#  (PatchPE) 
# 
# PatchPE: HX tool to patch a PE binary to PX ( not required for jwlink ).

NAME = IOTRAP
OUTDIR=Release
AOPT=-c -coff -nologo -Fl$*.lst -Fo$*.obj -I..\..\Include
ASM=jwasm.exe
#LINK=link.exe /NOLOGO /SUBSYSTEM:NATIVE /DLL $*.obj /OUT:$*.DLL /MAP:$*.MAP /EXPORT:ddb /Entry:DllMain /OPT:NOWIN98
LINK=jwlink format win nt hx dll ru native file $*.obj name $*.DLL op q,MAP=$*.MAP export _ddb.1

ALL: $(OUTDIR) $(OUTDIR)\$(NAME).DLL $(OUTDIR)\TESTIOT.COM

$(OUTDIR):
	@mkdir $(OUTDIR)

$(OUTDIR)\$(NAME).DLL: $(OUTDIR)\$(NAME).obj Makefile
	@$(LINK)
#	@..\patchpe $*.DLL

$(OUTDIR)\$(NAME).obj: $(NAME).asm
	@$(ASM) $(AOPT) $(NAME).asm

$(OUTDIR)\TESTIOT.COM: TESTIOT.asm
	@$(ASM) -nologo -bin -Fo=$*.COM TESTIOT.asm


================================================
FILE: JLM/IOTRAP/README.TXT
================================================

 1. About

 IOTRAP is a JLM sample which demonstrates how to trap IO port access.

 Note: This is somewhat obsolete now; trapping I/O port access in V86-mode
 is now better done with the help of JLM QPIEMU.


 2. How to install and uninstall IOTRAP

 IOTRAP can be installed either as a device driver in CONFIG.SYS:

   DEVICE=JLOAD.EXE IOTRAP.DLL

 or as a TSR from the command line:

   JLOAD IOTRAP.DLL

 To uninstall, use JLOAD's -u option:

   JLOAD -u IOTRAP.DLL


 3. How to test IOTRAP

  - install IOTRAP:  C:\>JLOAD iotrap.dll
  - install TESTIOT: C:\>testiot
  - start DEBUG:     C:\>debug
  - read port 100:   -i 100

  now a colored string '*#!+' should appear on line 25.


 4. License

 IOTRAP is Public Domain.

 Japheth



================================================
FILE: JLM/IOTRAP/TESTIOT.ASM
================================================

;--- tsr to test JLM IOTRAP.
;--- it installs a callback which is called whenever port 100h
;--- is accessed.
;--- the callback displays some colored characters on line 25.
;--- assemble: JWasm -bin -Fo testiot.com testiot.asm

	.286
	.model tiny
	.stack 2048
	.dosseg
	.386

	.data

szOK1   db "IOTRAP found.",13,10,'$'
szOK2   db "TESTIOT installed.",13,10,'$'
szErr1  db "IOTRAP is NOT installed!",13,10,'$'
szErr2  db "IOTRAP has wrong version!",13,10,'$'
szErr3  db "register callback failed!",13,10,'$'

	.code

	org 100h

start:
	mov ax, 1684h	;get IOTRAP's entry point
	mov bx, 6661h
	int 2Fh
	cmp al,0        ;IOTRAP installed?
	jnz not_installed
	push es
	push di
	mov bp,sp
	mov dx,offset szOK1
	mov ah,9
	int 21h
	mov ax,0000     ;call "get version"
	call dword ptr [bp]
;--- check version and exit if not ok
;	cmp ax,???
;	jc wrong_version
;--- API: CX:DX=CS:IP of callback, BX=param
	mov cx,cs
	mov dx,offset iocb
	mov bx,0
	mov ax,0001     ;call "register callback"
	call dword ptr [bp]
	jc  register_failed
	mov dx,offset szOK2
	mov ah,9
	int 21h
	mov dx,offset resident
	shr dx,4
	inc dx
	mov ax,3100h
	int 21h

iocb:

;--- callback when i/o was detected.
;--- cpu is in 16-bit protected-mode, ring 0.
;--- EAX=data of IO
;--- DX=IO port
;--- CX=type of IO
;--- BX=value when callback was "registered"
;--- DS=data segment
;--- ES=flat segment
;--- SS:ESP=flat host stack!

	push esi
	mov esi,0B8000h

;--- display '*#!+' in colors at line 25

	mov word ptr es:[esi+160*24+0],'*'+100h*40h
	mov word ptr es:[esi+160*24+2],'#'+100h*51h
	mov word ptr es:[esi+160*24+4],'!'+100h*62h
	mov word ptr es:[esi+160*24+6],'+'+100h*73h
	pop esi
	retd    ;a 32bit RETF is needed!!!

resident label byte

not_installed:
	mov dx,offset szErr1
	mov ah,9
	int 21h
	int 20h
wrong_version:
	mov dx,offset szErr2
	mov ah,9
	int 21h
	int 20h
register_failed:
	mov dx,offset szErr3
	mov ah,9
	int 21h
	int 20h

	end start



================================================
FILE: JLM/JCLOCK/JCLOCK.ASM
================================================
;
; JCLOCK 1.1
;
; JLM example -- CLOCK for JEMM386/JEMMEX
; It is the first JLM with screen input/output  :-)
;
; (C) 2007 Alexey Voskov
;
; Compile with FASM for WIN32
; and change PE signature into PX
;

format PE CONSOLE 4.0 DLL
entry DllEntryPoint

include '%FASMINC%\win32a.inc'

; Constants
; 1. Addresses
DispMode = 000449h ; BYTE  - display mode
ColNum   = 00044Ah ; WORD  - number of columns 
Timer    = 00046Ch ; DWORD - timer of BIOS
CoVideo  = 0B8000h ; Video buffer offset for MODE CO80/CO40
MoVideo  = 0B0000h ; Video buffer offset for MODE MONO
; 2. Text properties
attr  = 2Eh                       ; TEXT ATTRIBUTE
mask0 = attr*1000000h + attr*100h ; Masks for text field
mask1 = mask0 + ':'               ; initialization
mask2 = mask0 + ':' * 10000h      ;
;*********************************************************************
section '.code' code readable executable
;
; This procedure is a new INT 08h subroutine
;
proc newint08
	; Initialization
	pushad
	mov ebp, esp
	push ss
	pop  ds
	push ss
	pop  es
	; Timer check
	mov eax, [Timer] ; Get BIOS timer
	and eax, 7       ; eax % 8 == 0 
	test eax, eax    ; 
	jnz intexit      ; if not -- quit
                         ; (we don't have to do IN/OUT every 1/19 sec!)

	; Video mode check
	mov al, [DispMode]
	cmp al, 07h      ; MODE MONO ?
	jne color        ; if not -- check color mode
	mov ebx, MoVideo ; Load video buffer offset
	jmp mono

color:
	cmp al, 03h      ; MODE CO80/CO40 ?
	ja  intexit      ; if not -- quit
	mov ebx, CoVideo ; Load video buffer offset
mono:
	; Set up initial position
	movzx esi, word [ColNum] ; ESI = 2*ColNum - 16 + EBX
	shl esi, 1  
	sub esi, 16
	add esi, ebx ; EBX == 0B8000h or 0B0000h

	; Clock output
clkout: ; 1. Draw mask
	mov dword [esi],    mask0
	mov dword [esi+4],  mask1
	mov dword [esi+8],  mask2
	mov dword [esi+12], mask0
	; 2. Get current time
	mov al, 4 ; Hours
	call printBCDcell
	add  esi, 6
	mov al, 2 ; Minutes
	call printBCDcell
	add  esi, 6
	mov al, 0 ; Seconds
	call printBCDcell
        ; Call the old INT 08h subroutine
intexit:
	  popad       ; Restore registers and stack
	  db 0EAh     ; ASM command:
oldint08: db 6 dup 0  ; jmp far 0000:00000000
                      ; (48-bit far call)
endp

; Procedure prints CMOS cell 
; cell must be in BCD format
;
; AL      - cell number
; EBX+ESI - video RAM address
;
proc printBCDcell
	; Get byte from CMOS RTC
	out 70h, al     ; Set cell number in CMOS RTC
	mov ecx, 02000h ; A short delay
@@dl:   inc ecx         ; CMOS RTC memory is slow
	dec ecx         ;
	loop @@dl       ;
	in  al,  71h    ; Get byte from cell
	; High half-byte of BCD
	push ax 
	and  al, 0F0h
	shr  al, 4
	add  al, '0'
	mov  [esi], al
	pop  ax 
	; Low half-byte of BCD
	and  al, 00Fh
	add  al, '0'
	mov  [esi+2], al

	ret
endp

; This procedure hooks INT 08h
;
; WARNING -- it contains low-level work with IDT
; In newer versions of JEMM it probably 
; will be replaced with special API
;
intn = 08h                          ; INTERRUPT NUMBER
proc install
        ; Beginning
	sub esp,8                   ; Reserve memory in stack
	; Get pointer to IDT
        sidt [esp]                  ; Write register of interrupt 
                                    ; descriptor table to [ESP]
	mov esi,[esp+2]             ; Get IDT beginning address into ESI
	; Save old interrupt descriptor
        mov ax,[esi+6+intn*8]       ; Get bits 31-16
        shl eax,16                  ; of offset
        mov ax,[esi+0+intn*8]       ; Get bits 15-0 of offset
	mov dword ptr oldint08, eax ; Save offset
        mov ax,[esi+2+intn*8]       ; Get selector
        mov word ptr oldint08+4,ax  ; Save selector
	; Set up new interrupt descriptor
        mov eax, newint08           ; Get offset of new interrupt procedure
        mov [esi+0+intn*8],ax       ; And write it 
        shr eax, 16                 ; into IDT
        mov [esi+6+intn*8],ax       ; (SELECTOR UNCHANGED!)
        ; Final
        add esp,8                   ; Free memory in stack
	ret                         ; Exit 
endp
; NOTE:
;
; Interrupt descriptor format (gate):
; | OFFSET(bits 31-16) | FLAGS | SEG SELECTOR | OFFSET (bits 15-0)
;


;
; DLL entry point
;
proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
	cmp	[fdwReason], DLL_PROCESS_ATTACH
	jne     @@exitDLL
	call    install
	mov	eax,TRUE
@@exitDLL:
	ret
endp

;*********************************************************************
;
; * DON'T STRIP RELOCATIONS ! JLM MUST HAVE THEM ! *
;
section '.reloc' fixups data discardable


================================================
FILE: JLM/JCLOCK/JCLOCK2.ASM
================================================

; this is a modified JCLOCK version which uses the Jemm API to hook int 1Ch.
; Thus, it can be unloaded.
;
; (C) 2007 Alexey Voskov
;
; Compile with FASM for WIN32
; and change PE signature into PX

format PE CONSOLE 4.0 DLL
entry DllEntryPoint

include '%FASMINC%\win32a.inc'
include '%JLMINC%\jlmfasm.inc'

; Constants
; 1. Addresses
DispMode = 000449h ; BYTE  - display mode
ColNum   = 00044Ah ; WORD  - number of columns 
Timer    = 00046Ch ; DWORD - timer of BIOS
CoVideo  = 0B8000h ; Video buffer offset for MODE CO80/CO40
MoVideo  = 0B0000h ; Video buffer offset for MODE MONO
; 2. Text properties
attr  = 2Eh                       ; TEXT ATTRIBUTE
mask0 = attr*1000000h + attr*100h ; Masks for text field
mask1 = mask0 + ':'               ; initialization
mask2 = mask0 + ':' * 10000h      ;
;*********************************************************************
section '.code' code readable executable
;
; This procedure is a hook for INT 1Ch
;
oldvec dd 0

	dd oldvec        ; a hook procedure must be preceeded by a dword
                     ; which contains the address where the old vector
                     ; will be stored.
proc hookproc
	; Initialization
	; Timer check
	pushad
	mov eax, [Timer] ; Get BIOS timer
	and eax, 7       ; eax % 8 == 0 
	test eax, eax    ; 
	jnz intexit      ; if not -- quit
                         ; (we don't have to do IN/OUT every 1/19 sec!)

	; Video mode check
	mov al, [DispMode]
	cmp al, 07h      ; MODE MONO ?
	jne color        ; if not -- check color mode
	mov ebx, MoVideo ; Load video buffer offset
	jmp mono

color:
	cmp al, 03h      ; MODE CO80/CO40 ?
	ja intexit       ; if not -- quit
	mov ebx, CoVideo ; Load video buffer offset
mono:
	; Set up initial position
	movzx esi, word [ColNum] ; ESI = 2*ColNum - 16 + EBX
	shl esi, 1  
	sub esi, 16
	add esi, ebx ; EBX == 0B8000h or 0B0000h

	; Clock output
clkout: ; 1. Draw mask
	mov dword [esi],    mask0
	mov dword [esi+4],  mask1
	mov dword [esi+8],  mask2
	mov dword [esi+12], mask0
	; 2. Get current time
	mov al, 4 ; Hours
	call printBCDcell
	add  esi, 6
	mov al, 2 ; Minutes
	call printBCDcell
	add  esi, 6
	mov al, 0 ; Seconds
	call printBCDcell
intexit:
	popad
	stc		; signal this INT hasn't been handled yet
	ret
endp

; Procedure prints CMOS cell 
; cell must be in BCD format
;
; AL      - cell number
; EBX+ESI - video RAM address
;
proc printBCDcell
	; Get byte from CMOS RTC
	out 70h, al     ; Set cell number in CMOS RTC
	mov ecx, 02000h ; A short delay
@@dl:   inc ecx     ; CMOS RTC memory is slow
	dec ecx         ;
	loop @@dl       ;
	in  al,  71h    ; Get byte from cell
	; High half-byte of BCD
if 1
	db 0d4h,10h		;AAM 10h
	add ax,3030h
	mov [esi+0],ah
	mov [esi+2],al
else
	push ax 
	and  al, 0F0h
	shr  al, 4
	add  al, '0'
	mov  [esi], al
	pop  ax 
	; Low half-byte of BCD
	and  al, 00Fh
	add  al, '0'
	mov  [esi+2], al
end if
	ret
endp

; This procedure hooks INT 1Ch
;
intn = 1Ch                          ; INTERRUPT NUMBER

proc install

	mov eax,intn
	mov esi,hookproc
	@VMMCall Hook_V86_Int_Chain
	ret                         ; Exit 
endp

proc deinstall

	mov eax,intn
	mov esi,hookproc
	@VMMCall Unhook_V86_Int_Chain
	ret                         ; Exit 
endp

;
; DLL entry point
;
proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
	cmp [fdwReason], DLL_PROCESS_ATTACH
	jne @F
	call install
	mov eax,TRUE
	jmp @@exitDLL
@@:
	cmp [fdwReason], DLL_PROCESS_DETACH
	jne @@exitDLL
	call deinstall
	mov eax,TRUE
@@exitDLL:
	ret
endp

section '.data' data readable writeable

;--- Sorry, no idea how to create an instance of a structure in fasm ...

;ddb VxD_Desc_Block 0,0,6655h,1,0,0,0,0,0, 0, 0, 0, 0
ddb dd 0
	dw 0
	dw 6655h
	db 1
	db 0
	db 0
	db "JCLOCK2 "
	dd 80000000h
	dd 0
	dd 0
	dd 0
	dd 0
	rd 10

;--- to make the JLM unloadable, it must have a "device id". A "device id"
;--- is obtained by exporting a DDB

section '.edata' export data readable

	export 'JCLOCK2.DLL',\
	ddb,1

;*********************************************************************
;
; * DON'T STRIP RELOCATIONS ! JLM MUST HAVE THEM ! *
;
section '.reloc' fixups data discardable


================================================
FILE: JLM/JCLOCK/JCLOCK3.ASM
================================================

;--- JCLOCK2 in Masm/JWasm syntax

	.386
	.model flat
	option casemap:none

	include jlm.inc

; Constants

DLL_PROCESS_ATTACH equ 1
DLL_PROCESS_DETACH equ 0

; 1. Addresses
DispMode equ 000449h ; BYTE  - display mode
ColNum   equ 00044Ah ; WORD  - number of columns 
Timer    equ 00046Ch ; DWORD - timer of BIOS
CoVideo  equ 0B8000h ; Video buffer offset for MODE CO80/CO40
MoVideo  equ 0B0000h ; Video buffer offset for MODE MONO

; 2. Text properties
attr  = 2Eh                       ; TEXT ATTRIBUTE
mask0 = attr*1000000h + attr*100h ; Masks for text field
mask1 = mask0 + ':'               ; initialization
mask2 = mask0 + ':' * 10000h      ;

	.data

	public export ddb

ddb VxD_Desc_Block <0,0,6655h,1,0,0,"JCLOCK3 ",80000000h>
oldvec dd 0

	option dotname

.drectve segment info
	db "-dll -fixed:no -subsystem:native "
.drectve ends

.hdr$2 segment dword
	db "PX"
.hdr$2 ends

	.code
;
; This procedure is a hook for INT 1Ch
;
HookProc hookproc, oldvec
	; Initialization
	; Timer check
	pushad
	mov eax, ds:[Timer] ; Get BIOS timer
	and eax, 7       ; eax % 8 == 0 
	test eax, eax    ; 
	jnz intexit      ; if not -- quit
                         ; (we don't have to do IN/OUT every 1/19 sec!)

	; Video mode check
	mov al, ds:[DispMode]
	cmp al, 07h      ; MODE MONO ?
	jne color        ; if not -- check color mode
	mov ebx, MoVideo ; Load video buffer offset
	jmp mono

color:
	cmp al, 03h      ; MODE CO80/CO40 ?
	ja intexit       ; if not -- quit
	mov ebx, CoVideo ; Load video buffer offset
mono:
	; Set up initial position
	movzx esi, word ptr ds:[ColNum] ; ESI = 2*ColNum - 16 + EBX
	shl esi, 1  
	sub esi, 16
	add esi, ebx ; EBX == 0B8000h or 0B0000h

	; Clock output
clkout: ; 1. Draw mask
	mov dword ptr [esi],    mask0
	mov dword ptr [esi+4],  mask1
	mov dword ptr [esi+8],  mask2
	mov dword ptr [esi+12], mask0
	; 2. Get current time
	mov al, 4 ; Hours
	call printBCDcell
	add  esi, 6
	mov al, 2 ; Minutes
	call printBCDcell
	add  esi, 6
	mov al, 0 ; Seconds
	call printBCDcell
intexit:
	popad
	stc		; signal this INT hasn't been handled yet
	ret
hookproc endp

; Procedure prints CMOS cell 
; cell must be in BCD format
;
; AL      - cell number
; EBX+ESI - video RAM address
;
printBCDcell proc
	; Get byte from CMOS RTC
	out 70h, al     ; Set cell number in CMOS RTC
	jmp $+2
	jmp $+2
	in  al,  71h    ; Get byte from cell
	; High half-byte of BCD
if 1
	db 0d4h,10h		;AAM 10h
	add ax,3030h
	mov [esi+0],ah
	mov [esi+2],al
else
	push ax 
	and  al, 0F0h
	shr  al, 4
	add  al, '0'
	mov  [esi], al
	pop  ax 
	; Low half-byte of BCD
	and  al, 00Fh
	add  al, '0'
	mov  [esi+2], al
endif
	ret
printBCDcell endp

; This procedure hooks INT 1Ch
;
intn = 1Ch                          ; INTERRUPT NUMBER

install proc

	mov eax,intn
	mov esi,hookproc
	@VMMCall Hook_V86_Int_Chain
	ret                         ; Exit 
install endp

deinstall proc

	mov eax,intn
	mov esi,hookproc
	@VMMCall Unhook_V86_Int_Chain
	ret                         ; Exit 
deinstall endp

;
; DLL entry point
;
DllEntryPoint proc stdcall hinstDLL:dword, fdwReason:dword, lpvReserved:dword

	cmp [fdwReason], DLL_PROCESS_ATTACH
	jne @F
	call install
	mov eax,1
	jmp @@exitDLL
@@:
	cmp [fdwReason], DLL_PROCESS_DETACH
	jne @@exitDLL
	call deinstall
	mov eax,1
@@exitDLL:
	ret
DllEntryPoint endp

	end DllEntryPoint


================================================
FILE: JLM/JCLOCK/MAKE.BAT
================================================
@echo off
set FASMINC=\fasm\Include
set JLMINC=..\..\Include
fasm JCLOCK.ASM
fasm JCLOCK2.ASM
\hx\bin\patchpe JCLOCK.DLL
\hx\bin\patchpe JCLOCK2.DLL


================================================
FILE: JLM/JCLOCK/MAKE3.BAT
================================================
@echo off
rem make jclock3.dll - no link step required.
jwasm -pe -I..\..\Include -Fo=JCLOCK3.DLL JCLOCK3.ASM


================================================
FILE: JLM/JCLOCK/README.TXT
================================================
JCLOCK 1.4 -- Second JLM (JemmEx Loadable Module)
(C) 2007 Alexey Voskov

Shows clock in the text mode.

Usage
~~~~~
DEVICE=JEMMEX.EXE
DEVICE=JLOAD.EXE JCLOCK.DLL

History
~~~~~~~
Ver Date        Changed
-----------------------------------------------------------------
1.4 17-APR-2009 JClock2 supports JLoad's -u switch.
1.3 19-FEB-2008 patchpe missed in MAKE.BAT
1.2 30-JAN-2008 environment variables FASMINC and JLMINC used
1.1 05-MAY-2007 VME compatibility added
                Improved source code (easy change of clock color)
1.0 04-MAY-2007 Original release

================================================
FILE: JLM/JLSTUB/Build/JLSTUB.lst
================================================
JWasm v2.18, May  7 2024
JLSTUB.ASM

                                ;--- MZ stub to run jload.exe
                                ;--- to be assembled with Masm or JWasm
                                ;--- it's a derivate of dpmildxx... 

 = 600                          ?MINMEM	 = 600h		;min free paragraphs for JLOAD.EXE
 = 44                           MAXDIR   = 64+4		;max length of a directory path (including 00h)
 = 50                           MAXPATH  = MAXDIR+12
 = 1                            ?BESAFE  = 1		;1=check if JLoad.exe looks ok.
 = 1                            ?DOSMEMCHK = 1		;0=check for sufficient DOS memory

                                	.286

                                ifdef __JWASM__
                                	option MZ:40h
                                endif

 = D                            cr		equ 13
 = A                            lf		equ 10

00000000                        mzhdr struct
00000000                          e_magic           WORD      ?		;+0
00000002                          e_cblp            WORD      ?		;+2
00000004                          e_cp              WORD      ?		;+4
00000006                          e_crlc            WORD      ?		;+6		number of relocation records
00000008                          e_cparhdr         WORD      ?		;+8
0000000A                          e_minalloc        WORD      ?		;+10
0000000C                          e_maxalloc        WORD      ?		;+12
0000000E                          e_ss              WORD      ?		;+14
00000010                          e_sp              WORD      ?		;+16
00000012                          e_csum            WORD      ?		;+18
00000014                          e_ip              WORD      ?		;+20
00000016                          e_cs              WORD      ?		;+22
00000018                          e_lfarlc          WORD      ?		;+24	begin relocation records
0000001A                        mzhdr ends


0000                            _TEXT   segment public 'CODE'

 = [bp+00h]                     szPgm   equ [bp+00h]     ;execute program name ("JLOAD.EXE")
 = [bp-MAXPATH]                 szParm  equ [bp-MAXPATH] ;application name (from environment)

0000                            launch proc

0000 33D2                       	xor DX,DX
0002 B120                       	mov cl,20h
0004 B43F                       	mov ah,3Fh		;read the MZ header
0006 CD21                       	int 21h
0008 7303E9DD00                 	jc readerror

                                if ?BESAFE

                                ;--- additional tests

000D 33F6                       	xor si,si
000F 8B04                       	mov ax, [si].mzhdr.e_magic
0011 3D4D5A                     	cmp ax,"ZM"
0014 7403E9CC00                 	jnz formerror
0019 8B4406                     	mov ax, [si].mzhdr.e_crlc	; no of relocation entries
001C 8BF8                       	mov di,ax
001E 23C0                       	and ax,ax
0020 7420                       	jz norelocs
0022 50                         	push ax
0023 33C9                       	xor cx,cx
0025 8B5418                     	mov dx,[si].mzhdr.e_lfarlc	; begin relocations
0028 B80042                     	mov ax,4200h
002B CD21                       	int 21h
002D 59                         	pop cx
002E C1E102                     	shl cx,2					; 4 byte each reloc
0031 2BE1                       	sub sp,cx
0033 8BD4                       	mov dx,sp
0035 1E                         	push ds
0036 16                         	push ss
0037 1F                         	pop ds
0038 B43F                       	mov ah,3Fh					; read relocs at SS:SP
003A CD21                       	int 21h
003C 1F                         	pop ds
003D 7303E9A300                 	jc formerror
0042                            norelocs:
0042 8B4408                     	mov ax,[si].mzhdr.e_cparhdr	; size of header in paragraphs
0045 FF740E                     	push [si].mzhdr.e_ss
0048 FF7410                     	push [si].mzhdr.e_sp
004B 8B7414                     	mov si, [si].mzhdr.e_ip
004E C1E004                     	shl ax,4
0051 8BD0                       	mov dx,ax
0053 33C9                       	xor cx,cx
0055 B80042                     	mov ax,4200h
0058 CD21                       	int 21h
005A 33D2                       	xor dx,dx
                                endif

                                ;--- read JLoad.exe binary

005C B43F                       	MOV AH,3Fh
005E B90060                     	mov cx,?MINMEM shl 4
0061 CD21                       	INT 21h
0063 7303E98200                 	JC readerror	;---> error "read error"
                                if ?BESAFE        
0068 3BC1                       	cmp ax,cx		;JLOAD binary must be < 24 kB
006A 7379                       	jnc formerror
                                endif
006C B43E                       	mov ah,3Eh
006E CD21                       	int 21h

0070 5A                         	pop dx
0071 5D                         	pop bp

                                if ?BESAFE
0072 8BCF                       	mov cx,di		;some relocs to resolve?
0074 E317                       	jcxz norelocs2
0076 8BFC                       	mov di,sp
0078 8CD8                       	mov ax,ds
007A                            @@:
007A 368B5D02                   	mov bx,ss:[di+2]
007E C1E304                     	shl bx,4		;size of loader is <= 24 kB, so no overflow possible
0081 36031D                     	add bx,ss:[di+0]
0084 0107                       	add [bx],ax
0086 83C704                     	add di,4
0089 E2EF                       	loop @B
008B 8BE7                       	mov sp,di
008D                            norelocs2:
                                endif

                                ;--- fill JLoad's PSP - don't overwrite possible cmdline arguments

008D B451                       	mov ah,51h
008F CD21                       	int 21h
0091 56                         	push si
0092 8BF4                       	mov si, sp
0094 83C602                     	add si, 2
0097 BF8000                     	mov di, 80h
009A 268A0D                     	mov cl, es:[di]
009D B500                       	mov ch, 0
009F 47                         	inc di
00A0 E312                       	jcxz nocmdl
00A2 2BE1                       	sub sp, cx
00A4 8BDC                       	mov bx, sp
00A6 51                         	push cx
00A7 57                         	push di
00A8                            @@:
00A8 268A05                     	mov al, es:[di]
00AB 368807                     	mov ss:[bx], al
00AE 47                         	inc di
00AF 43                         	inc bx
00B0 E2F6                       	loop @B
00B2 5F                         	pop di
00B3 59                         	pop cx
00B4                            nocmdl:
00B4 B020                       	mov al,' '
00B6 AA                         	stosb
00B7                            @@:
00B7 36AC                       	lodsb ss:[si]
00B9 AA                         	stosb
00BA 22C0                       	and al, al
00BC 75F9                       	jnz @B
00BE 4F                         	dec di
00BF E307                       	jcxz @F
00C1 8BF4                       	mov si, sp
00C3 F336A4                     	rep movsb es:[di], ss:[si]
00C6 8BE6                       	mov sp, si
00C8                            @@:
00C8 26C6050D                   	mov byte ptr es:[di],13
00CC 8BC7                       	mov ax, di
00CE BF8000                     	mov di, 80h
00D1 2BC7                       	sub ax, di	; might actually be larger than 127 bytes ... ignore for now.
00D3 AA                         	stosb

00D4 5E                         	pop si

                                ;--- setup SS:SP

00D5 8CC0                       	mov ax, es
00D7 03C5                       	add ax, bp
00D9 83C010                     	add ax, 10h
00DC 8ED0                       	mov ss, ax
00DE 8BE2                       	mov sp, dx

00E0 1E                         	push ds
00E1 56                         	push si

00E2 06                         	push es
00E3 1F                         	pop ds
00E4 CB                         	retf
00E5                            launch endp

                                if ?BESAFE
00E5                            formerror:
00E5 BA0000                     	mov dx,offset dFormError
00E8 EB03                       	jmp error1
                                endif

00EA                            readerror:
00EA BA0000                     	mov dx,offset dReadError
00ED                            error1:
                                if 0
                                endif
00ED                            errorX: 				;<--- errors
00ED 0E                         	push cs
00EE 1F                         	pop ds
00EF E80B00                     	call DispError
00F2 BA0000                     	MOV DX,offset dFatal
00F5 E80500                     	call DispError
00F8 B8F04C                     	mov ax,4CF0h	;error code F0h
00FB CD21                       	int 21h
00FD                            DispError:				;display error msg in DX
00FD B409                       	MOV AH,09h
00FF CD21                       	INT 21h
0101 C3                         	ret

0102 202D206C6F6164696E         dFatal		db ' - loading aborted',cr,lf,'$'
0117 72656164206572726F         dReadError	db "read error",'$'
                                if ?BESAFE
0122 696E76616C6964204A         dFormError	db "invalid JLoad.exe",'$'
                                endif

0134                            endcopy label byte

0134                            start proc

                                ;--- setup stack at end of memory block

0134 FC                         	cld
0135 A10200                     	mov ax,ds:[0002]
                                ife ?DOSMEMCHK        
                                endif
0138 83E830                     	sub ax,30h
013B 8ED0                       	mov ss,ax
013D BCB002                     	mov sp,300h-MAXPATH

                                ;--- setup BP stack frame

0140 8BEC                       	mov BP,SP
0142 83EC50                     	sub SP,MAXPATH

                                ;--- fill szParm with application name

0145 8BF4                       	mov SI,SP    		;SI=szParm
0147 06                         	push es				;save PSP
0148 268E062C00                 	mov es,es:[002Ch]	;ES=environment
014D E82300                     	CALL GetAppName		;get name to SS:SI ( SI modified! )

0150 0E                         	push cs
0151 1F                         	pop ds

                                ;--- search "PATH=", DI=NULL if it doesn't exist

0152 E83900                     	CALL SearchPath
0155 8BF7                       	MOV SI,DI			;set SI to start of PATH= value

                                ;--- fill szPgm (search JLOAD)

0157 16                         	push SS
0158 1F                         	pop DS
0159 E84C00                     	CALL SearchJLoad
015C BA0000                     	MOV DX,offset dNotFnd
015F 728C                       	JB errorX  			;---> error "not found"

                                ;--- copy the final code to end of memory block

0161 B90000                     	mov cx,offset endcopy
0164 16                         	push ss
0165 07                         	pop es
0166 33FF                       	xor di,di
0168 33F6                       	xor si,si
016A 2E                         	db 2Eh			;CS prefix
016B F3A4                       	rep movsb

016D 07                         	pop es			;restore PSP

016E 1E                         	push ds
016F 51                         	push cx			;CX is 0

0170 0E                         	push cs
0171 1F                         	pop ds
0172 CB                         	retf

0173                            start endp

                                ;--- search name of app in environment
                                ;--- the name may be a full path or not
                                ;--- depending on caller
                                ;--- in: ES=environment, SS:SI=dest
                                ;--- modifies AX,CX,SI,DI

0173                            GetAppName proc
0173 2BFF                       	SUB DI,DI
0175 B000                       	mov al,00
0177 B9FFFF                     	mov cx,-1
017A                            @@:
017A F2AE                       	repnz scasb		;search end of environ (00,00)
017C AE                         	scasb
017D 75FB                       	jnz @B
017F 47                         	inc di			;skip 0001
0180 47                         	inc di

0181                            @@:
0181 268A05                     	mov al,es:[di]
0184 368804                     	mov ss:[si],al
0187 46                         	inc si
0188 47                         	inc di
0189 22C0                       	and al,al
018B 75F4                       	jnz @B
018D C3                         	RET
018E                            GetAppName endp

                                ;--- search PATH= in Environment
                                ;--- In: ES=environment
                                ;--- Out: DI-> behind "PATH=" or NULL
                                ;--- modifies AX,CX,SI,DI

018E                            SearchPath proc
018E 2BFF                       	SUB DI,DI
0190                            nextitem:
0190 BE0000                     	MOV SI,offset szPath
0193 B90500                     	MOV CX,SIZPATH
0196 F3A6                       	REPZ CMPSB
0198 740D                       	JZ found
019A B000                       	mov al,00
019C B57F                       	mov ch,7Fh
019E F2AE                       	repnz scasb
01A0 263A05                     	cmp al,es:[di]
01A3 75EB                       	JNZ nextitem
01A5 2BFF                       	sub di,di
01A7                            found:
01A7 C3                         	RET
01A8                            SearchPath endp

                                ;--- search JLOAD, first in current Dir, then scan PATH
                                ;--- Input: ES=environ, SI=address PATH variable or 0000 (no PATH exists)
                                ;--- Output: NC if found, C if error
                                ;--- full loader path in szPgm
                                ;--- modifies AX,BX,CX,DX,SI,DI

01A8                            SearchJLoad proc
01A8 8D7E00                     	lea DI,[bp+00h]
01AB 8BD7                       	mov dx,di
01AD                            nextentry:					;<----
01AD 56                         	PUSH SI
01AE BE0000                     	mov si,offset ldrname	;Name "JLOAD.EXE"
01B1 B90900                     	mov cx,SIZLDRNAME
01B4                            @@:
01B4 2E                         	db 2Eh		;CS prefix
01B5 AC                         	lodsb
01B6 8805                       	mov [di],al
01B8 47                         	inc di
01B9 E2F9                       	loop @B
01BB 880D                       	mov [di],cl

01BD B8003D                     	MOV AX,3D00h			;open JLOAD.EXE
01C0 CD21                       	INT 21h
01C2 5E                         	POP SI
01C3 7328                       	JNB ldrfound			;jmp if found!
01C5 23F6                       	AND SI,SI
01C7 F9                         	stc
01C8 7424                       	JZ notfound				;PATH not defined, so we are done
01CA 8BFA                       	MOV DI,DX
01CC B94400                     	mov cx,MAXDIR
01CF                            @@:
01CF 268A04                     	mov al,es:[si]
01D2 8805                       	mov [di],al
01D4 46                         	inc si
01D5 47                         	inc di
01D6 3C3B                       	CMP AL,';'
01D8 7406                       	JZ @F
01DA 3C00                       	CMP AL,00
01DC E0F1                       	LOOPNZ @B				;PATH done
01DE 33F6                       	XOR SI,SI
01E0                            @@:
01E0 4F                         	DEC DI
01E1 807DFF5C                   	CMP Byte Ptr [DI-01],'\'
01E5 74C6                       	JZ nextentry
01E7 C6055C                     	MOV Byte Ptr [DI],'\'
01EA 47                         	INC DI
01EB EBC0                       	JMP nextentry
01ED                            ldrfound:
01ED 93                         	XCHG ax,bx				;=MOV BX,AX
                                ;	MOV AH,3Eh				;close file
                                ;	INT 21h
                                ;	CLC
01EE                            notfound:
01EE C3                         	RET
01EF                            SearchJLoad endp

01EF 504154483D                 szPath  db   'PATH='
 = 5                            SIZPATH equ $ - szPath

01F4 43616E27742066696E         dNotFnd db "Can't find "
01FF                            ldrname	label byte
01FF 4A4C4F41442E455845         	db 'JLOAD.EXE'
 = 9                            SIZLDRNAME equ $ - ldrname
0208 24                         	db '$'

                                ife ?DOSMEMCHK
                                endif

0209                            _TEXT ends

                                if ?DOSMEMCHK
0000                            _BSS segment public 'DATA'
0000 000000000000000000         	db (?MINMEM+14h) * 16 dup (?)
6140                            _BSS ends
                                endif

0000                            STACK segment stack 'STACK'
0000                            STACK ends

                                	end start


Binary Map:

Segment                  Pos(file)     RVA  Size(fil) Size(mem)
---------------------------------------------------------------
<header>                        0        0        40         0
_TEXT                          40        0       209       209
_BSS                            0      210         0      6140
STACK                           0     6350         0         0
---------------------------------------------------------------
                                                 249      6350


Macros:

                N a m e                 Type

@CatStr  . . . . . . . . . . . .        Func
@Environ . . . . . . . . . . . .        Func
@InStr . . . . . . . . . . . . .        Func
@SizeStr . . . . . . . . . . . .        Func
@SubStr  . . . . . . . . . . . .        Func


Structures and Unions:

                N a m e                 Size/Ofs   Type

mzhdr  . . . . . . . . . . . . .              1A
  e_magic  . . . . . . . . . . .               0   Word
  e_cblp . . . . . . . . . . . .               2   Word
  e_cp . . . . . . . . . . . . .               4   Word
  e_crlc . . . . . . . . . . . .               6   Word
  e_cparhdr  . . . . . . . . . .               8   Word
  e_minalloc . . . . . . . . . .               A   Word
  e_maxalloc . . . . . . . . . .               C   Word
  e_ss . . . . . . . . . . . . .               E   Word
  e_sp . . . . . . . . . . . . .              10   Word
  e_csum . . . . . . . . . . . .              12   Word
  e_ip . . . . . . . . . . . . .              14   Word
  e_cs . . . . . . . . . . . . .              16   Word
  e_lfarlc . . . . . . . . . . .              18   Word


Segments and Groups:

                N a m e                 Size     Length   Align   Combine Class

STACK  . . . . . . . . . . . . .        16 Bit   0000     Para    Stack   'STACK'
_BSS . . . . . . . . . . . . . .        16 Bit   6140     Para    Public  'DATA'
_TEXT  . . . . . . . . . . . . .        16 Bit   0209     Para    Public  'CODE'


Procedures, parameters and locals:

                N a m e                 Type     Value    Segment  Length

GetAppName . . . . . . . . . . .        P Near   0173     _TEXT    001B Public   
  L&_0006  . . . . . . . . . . .        L Near   0181     _TEXT
  L&_0005  . . . . . . . . . . .        L Near   017A     _TEXT
SearchJLoad  . . . . . . . . . .        P Near   01A8     _TEXT    0047 Public   
  L&_0008  . . . . . . . . . . .        L Near   01CF     _TEXT
  notfound . . . . . . . . . . .        L Near   01EE     _TEXT
  L&_0009  . . . . . . . . . . .        L Near   01E0     _TEXT
  L&_0007  . . . . . . . . . . .        L Near   01B4     _TEXT
  nextentry  . . . . . . . . . .        L Near   01AD     _TEXT
  ldrfound . . . . . . . . . . .        L Near   01ED     _TEXT
SearchPath . . . . . . . . . . .        P Near   018E     _TEXT    001A Public   
  found  . . . . . . . . . . . .        L Near   01A7     _TEXT
  nextitem . . . . . . . . . . .        L Near   0190     _TEXT
launch . . . . . . . . . . . . .        P Near   0000     _TEXT    00E5 Public   
  L&_0004  . . . . . . . . . . .        L Near   00C8     _TEXT
  L&_0002  . . . . . . . . . . .        L Near   00A8     _TEXT
  L&_0003  . . . . . . . . . . .        L Near   00B7     _TEXT
  L&_0001  . . . . . . . . . . .        L Near   007A     _TEXT
  nocmdl . . . . . . . . . . . .        L Near   00B4     _TEXT
  norelocs . . . . . . . . . . .        L Near   0042     _TEXT
  norelocs2  . . . . . . . . . .        L Near   008D     _TEXT
start  . . . . . . . . . . . . .        P Near   0134     _TEXT    003F Public   


Symbols:

                N a m e                 Type       Value     Attr

?BESAFE  . . . . . . . . . . . .        Number             1h 
?DOSMEMCHK . . . . . . . . . . .        Number             1h 
?MINMEM  . . . . . . . . . . . .        Number           600h 
DispError  . . . . . . . . . . .        L Near            FDh _TEXT 
MAXDIR . . . . . . . . . . . . .        Number            44h 
MAXPATH  . . . . . . . . . . . .        Number            50h 
SIZLDRNAME . . . . . . . . . . .        Number             9h 
SIZPATH  . . . . . . . . . . . .        Number             5h 
cr . . . . . . . . . . . . . . .        Number             Dh 
dFatal . . . . . . . . . . . . .        Byte[21]         102h _TEXT 
dFormError . . . . . . . . . . .        Byte[18]         122h _TEXT 
dNotFnd  . . . . . . . . . . . .        Byte[11]         1F4h _TEXT 
dReadError . . . . . . . . . . .        Byte[11]         117h _TEXT 
endcopy  . . . . . . . . . . . .        Byte             134h _TEXT 
error1 . . . . . . . . . . . . .        L Near            EDh _TEXT 
errorX . . . . . . . . . . . . .        L Near            EDh _TEXT 
formerror  . . . . . . . . . . .        L Near            E5h _TEXT 
ldrname  . . . . . . . . . . . .        Byte             1FFh _TEXT 
lf . . . . . . . . . . . . . . .        Number             Ah 
readerror  . . . . . . . . . . .        L Near            EAh _TEXT 
szParm . . . . . . . . . . . . .        Text   [bp-MAXPATH]
szPath . . . . . . . . . . . . .        Byte[5]          1EFh _TEXT 
szPgm  . . . . . . . . . . . . .        Text   [bp+00h]

JLSTUB.ASM: 418 lines, 2 passes, 2 ms, 0 warnings, 0 errors


================================================
FILE: JLM/JLSTUB/JLSTUB.ASM
================================================

;--- MZ stub to run jload.exe
;--- to be assembled with Masm or JWasm
;--- it's a derivate of dpmildxx... 

?MINMEM	 = 600h		;min free paragraphs for JLOAD.EXE
MAXDIR   = 64+4		;max length of a directory path (including 00h)
MAXPATH  = MAXDIR+12
?BESAFE  = 1		;1=check if JLoad.exe looks ok.
?DOSMEMCHK = 1		;0=check for sufficient DOS memory

	.286

ifdef __JWASM__
	option MZ:40h
endif

cr		equ 13
lf		equ 10

mzhdr struct
  e_magic           WORD      ?		;+0
  e_cblp            WORD      ?		;+2
  e_cp              WORD      ?		;+4
  e_crlc            WORD      ?		;+6		number of relocation records
  e_cparhdr         WORD      ?		;+8
  e_minalloc        WORD      ?		;+10
  e_maxalloc        WORD      ?		;+12
  e_ss              WORD      ?		;+14
  e_sp              WORD      ?		;+16
  e_csum            WORD      ?		;+18
  e_ip              WORD      ?		;+20
  e_cs              WORD      ?		;+22
  e_lfarlc          WORD      ?		;+24	begin relocation records
mzhdr ends


_TEXT   segment public 'CODE'

szPgm   equ [bp+00h]     ;execute program name ("JLOAD.EXE")
szParm  equ [bp-MAXPATH] ;application name (from environment)

launch proc

	xor DX,DX
	mov cl,20h
	mov ah,3Fh		;read the MZ header
	int 21h
	jc readerror

if ?BESAFE

;--- additional tests

	xor si,si
	mov ax, [si].mzhdr.e_magic
	cmp ax,"ZM"
	jnz formerror
	mov ax, [si].mzhdr.e_crlc	; no of relocation entries
	mov di,ax
	and ax,ax
	jz norelocs
	push ax
	xor cx,cx
	mov dx,[si].mzhdr.e_lfarlc	; begin relocations
	mov ax,4200h
	int 21h
	pop cx
	shl cx,2					; 4 byte each reloc
	sub sp,cx
	mov dx,sp
	push ds
	push ss
	pop ds
	mov ah,3Fh					; read relocs at SS:SP
	int 21h
	pop ds
	jc formerror
norelocs:
	mov ax,[si].mzhdr.e_cparhdr	; size of header in paragraphs
	push [si].mzhdr.e_ss
	push [si].mzhdr.e_sp
	mov si, [si].mzhdr.e_ip
	shl ax,4
	mov dx,ax
	xor cx,cx
	mov ax,4200h
	int 21h
	xor dx,dx
endif

;--- read JLoad.exe binary

	MOV AH,3Fh
	mov cx,?MINMEM shl 4
	INT 21h
	JC readerror	;---> error "read error"
if ?BESAFE        
	cmp ax,cx		;JLOAD binary must be < 24 kB
	jnc formerror
endif
	mov ah,3Eh
	int 21h

	pop dx
	pop bp

if ?BESAFE
	mov cx,di		;some relocs to resolve?
	jcxz norelocs2
	mov di,sp
	mov ax,ds
@@:
	mov bx,ss:[di+2]
	shl bx,4		;size of loader is <= 24 kB, so no overflow possible
	add bx,ss:[di+0]
	add [bx],ax
	add di,4
	loop @B
	mov sp,di
norelocs2:
endif

;--- fill JLoad's PSP - don't overwrite possible cmdline arguments

	mov ah,51h
	int 21h
	push si
	mov si, sp
	add si, 2
	mov di, 80h
	mov cl, es:[di]
	mov ch, 0
	inc di
	jcxz nocmdl
	sub sp, cx
	mov bx, sp
	push cx
	push di
@@:
	mov al, es:[di]
	mov ss:[bx], al
	inc di
	inc bx
	loop @B
	pop di
	pop cx
nocmdl:
	mov al,' '
	stosb
@@:
	lodsb ss:[si]
	stosb
	and al, al
	jnz @B
	dec di
	jcxz @F
	mov si, sp
	rep movsb es:[di], ss:[si]
	mov sp, si
@@:
	mov byte ptr es:[di],13
	mov ax, di
	mov di, 80h
	sub ax, di	; might actually be larger than 127 bytes ... ignore for now.
	stosb

	pop si

;--- setup SS:SP

	mov ax, es
	add ax, bp
	add ax, 10h
	mov ss, ax
	mov sp, dx

	push ds
	push si

	push es
	pop ds
	retf
launch endp

if ?BESAFE
formerror:
	mov dx,offset dFormError
	jmp error1
endif

readerror:
	mov dx,offset dReadError
error1:
if 0
;--- close file? Will be done by DOS.
	mov ah,3Eh
	int 21h
endif
errorX: 				;<--- errors
	push cs
	pop ds
	call DispError
	MOV DX,offset dFatal
	call DispError
	mov ax,4CF0h	;error code F0h
	int 21h
DispError:				;display error msg in DX
	MOV AH,09h
	INT 21h
	ret

dFatal		db ' - loading aborted',cr,lf,'$'
dReadError	db "read error",'$'
if ?BESAFE
dFormError	db "invalid JLoad.exe",'$'
endif

endcopy label byte

start proc

;--- setup stack at end of memory block

	cld
	mov ax,ds:[0002]
ife ?DOSMEMCHK        
	mov bp,es
	push ax
	sub ax,bp
	cmp ax,?MINMEM+30h	;enough free memory in this block?
	pop ax
	mov dx,offset dMemory
	jc errorX
endif
	sub ax,30h
	mov ss,ax
	mov sp,300h-MAXPATH

;--- setup BP stack frame

	mov BP,SP
	sub SP,MAXPATH

;--- fill szParm with application name

	mov SI,SP    		;SI=szParm
	push es				;save PSP
	mov es,es:[002Ch]	;ES=environment
	CALL GetAppName		;get name to SS:SI ( SI modified! )

	push cs
	pop ds

;--- search "PATH=", DI=NULL if it doesn't exist

	CALL SearchPath
	MOV SI,DI			;set SI to start of PATH= value

;--- fill szPgm (search JLOAD)

	push SS
	pop DS
	CALL SearchJLoad
	MOV DX,offset dNotFnd
	JB errorX  			;---> error "not found"

;--- copy the final code to end of memory block

	mov cx,offset endcopy
	push ss
	pop es
	xor di,di
	xor si,si
	db 2Eh			;CS prefix
	rep movsb

	pop es			;restore PSP

	push ds
	push cx			;CX is 0

	push cs
	pop ds
	retf

start endp

;--- search name of app in environment
;--- the name may be a full path or not
;--- depending on caller
;--- in: ES=environment, SS:SI=dest
;--- modifies AX,CX,SI,DI

GetAppName proc
	SUB DI,DI
	mov al,00
	mov cx,-1
@@:
	repnz scasb		;search end of environ (00,00)
	scasb
	jnz @B
	inc di			;skip 0001
	inc di

@@:
	mov al,es:[di]
	mov ss:[si],al
	inc si
	inc di
	and al,al
	jnz @B
	RET
GetAppName en
Download .txt
gitextract_t40dgl9z/

├── Artistic.txt
├── History.txt
├── Html/
│   └── Readme.html
├── Include/
│   ├── FILEACC.INC
│   ├── FINDRES.INC
│   ├── JLM.H
│   ├── JLM.INC
│   ├── JLMFASM.INC
│   ├── JSYSTEM.INC
│   ├── PRINTF.INC
│   ├── VDS.INC
│   └── X86.INC
├── JLM/
│   ├── AHCICD/
│   │   ├── AHCICD.ASM
│   │   ├── AHCICD.txt
│   │   ├── MAKE.BAT
│   │   └── MAKEM.BAT
│   ├── GENERIC/
│   │   ├── GENERIC.ASM
│   │   ├── MAKEFILE
│   │   ├── README.TXT
│   │   └── TESTGEN.ASM
│   ├── HELLO/
│   │   ├── HELLO.ASM
│   │   ├── MAKE.BAT
│   │   └── README.TXT
│   ├── HELLO2/
│   │   ├── HELLO2.C
│   │   ├── HELLO2W.C
│   │   ├── JLMW.ASM
│   │   ├── JLMW.h
│   │   ├── MAKEJLMW.BAT
│   │   ├── MAKEOW.BAT
│   │   ├── MAKEVC.BAT
│   │   ├── README.TXT
│   │   └── makeow.sh
│   ├── IOTRAP/
│   │   ├── IOTRAP.ASM
│   │   ├── MAKEFILE
│   │   ├── README.TXT
│   │   └── TESTIOT.ASM
│   ├── JCLOCK/
│   │   ├── JCLOCK.ASM
│   │   ├── JCLOCK2.ASM
│   │   ├── JCLOCK3.ASM
│   │   ├── MAKE.BAT
│   │   ├── MAKE3.BAT
│   │   └── README.TXT
│   ├── JLSTUB/
│   │   ├── Build/
│   │   │   └── JLSTUB.lst
│   │   ├── JLSTUB.ASM
│   │   ├── JLStub.txt
│   │   └── Make.BAT
│   ├── KEYBGR/
│   │   ├── KEYBGR.ASM
│   │   ├── MAKE.BAT
│   │   ├── MAKEFILE
│   │   └── README.TXT
│   ├── QPIEMU/
│   │   ├── MAKE.BAT
│   │   ├── MAKEFILE
│   │   ├── QPIEMU.ASM
│   │   ├── QPIEMU.txt
│   │   └── Test/
│   │       ├── MAKEFILE
│   │       ├── PRINTF16.INC
│   │       ├── SETARGV.INC
│   │       ├── TESTDMA.ASM
│   │       └── TESTQPI.ASM
│   ├── README.TXT
│   ├── REBOOT/
│   │   ├── FASTBOOT.ASM
│   │   ├── FASTBOOT.txt
│   │   ├── FASTBRM.ASM
│   │   ├── FBOOT.ASM
│   │   ├── LDI13EXT.ASM
│   │   ├── MAKE.BAT
│   │   ├── REBOOT.ASM
│   │   └── REBOOT.txt
│   ├── XCDROM32/
│   │   ├── History.txt
│   │   ├── MAKE.BAT
│   │   ├── MAKEM.BAT
│   │   ├── XCDROM32.ASM
│   │   └── XCDROM32.txt
│   └── XDMA32/
│       ├── History.txt
│       ├── IDENTIFY.INC
│       ├── MAKE.BAT
│       ├── MAKEM.BAT
│       ├── XDMA32.ASM
│       └── XDMA32.txt
├── JemmExL.mak
├── Linux.mak
├── Makefile
├── Readme.txt
├── Test/
│   ├── BMINTRM.ASM
│   ├── EMS4E.ASM
│   ├── EMS4F.ASM
│   ├── EMS56.ASM
│   ├── EMS57.ASM
│   ├── EMS57A.ASM
│   ├── EMS5B.ASM
│   ├── EXC00.ASM
│   ├── EXC06.ASM
│   ├── FRAMERES.ASM
│   ├── HLTTEST.ASM
│   ├── HLTTEST2.ASM
│   ├── I15MOVE.ASM
│   ├── INT67.ASM
│   ├── INT88.ASM
│   ├── MACROS.INC
│   ├── MAKE.BAT
│   ├── PRINTF.INC
│   ├── README.TXT
│   ├── TEST0C.DEB
│   ├── TEST0C1.DEB
│   ├── TEST0D.DEB
│   ├── TEST10.DEB
│   ├── TEST11.DEB
│   ├── TESTDMA.ASM
│   ├── TESTDMA2.ASM
│   ├── TESTDMA3.ASM
│   ├── TESTVCPI.ASM
│   ├── TESTVDS.ASM
│   ├── TESTVDS2.ASM
│   ├── TESTVDS3.ASM
│   ├── TIMERMS.INC
│   ├── VCPI.INC
│   ├── XMSTEST.ASM
│   ├── XMSTEST2.ASM
│   ├── XMSTEST3.ASM
│   ├── XMSTEST4.ASM
│   └── XMSTEST5.ASM
├── Tools/
│   ├── CLEAR.BAT
│   ├── CPUID/
│   │   ├── CPUID.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── Cpustat/
│   │   ├── CPUSTAT.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── EMSSTAT/
│   │   ├── EMSSTAT.ASM
│   │   ├── MAKE.BAT
│   │   └── PRINTF.INC
│   ├── JEMFBHLP/
│   │   ├── JEMFBHLP.ASM
│   │   └── MAKE.BAT
│   ├── JLOAD/
│   │   ├── DEBUG.INC
│   │   ├── DPRINTF.INC
│   │   ├── DPRNTF16.INC
│   │   ├── History.txt
│   │   ├── JLOAD.ASM
│   │   ├── JLOAD.INC
│   │   ├── JLOAD.TXT
│   │   ├── JLOAD.txt
│   │   ├── JLOAD32.ASM
│   │   ├── JLOAD32.INC
│   │   ├── Linux.mak
│   │   ├── MAKEFILE
│   │   ├── VDMAD.ASM
│   │   ├── VIOOUT.INC
│   │   ├── VMM.ASM
│   │   ├── WINNT.INC
│   │   └── license.txt
│   ├── MAKE.BAT
│   ├── MEMSTAT/
│   │   ├── MAKE.BAT
│   │   ├── MEMSTAT.ASM
│   │   └── PRINTF.INC
│   ├── MoveXBDA/
│   │   ├── MAKE.BAT
│   │   └── MOVEXBDA.ASM
│   ├── UMBM/
│   │   ├── MAKE.BAT
│   │   └── UMBM.ASM
│   ├── VCPI/
│   │   ├── MAKE.BAT
│   │   ├── PRINTF.INC
│   │   ├── VCPI.ASM
│   │   ├── VCPI.INC
│   │   └── VIOOUT.INC
│   └── XMSSTAT/
│       ├── MAKE.BAT
│       ├── PRINTF.INC
│       └── XMSSTAT.ASM
├── XMS35.txt
└── src/
    ├── AUXIO.INC
    ├── DEBUG.ASM
    ├── DEBUG16.INC
    ├── DEBUG32.INC
    ├── DEBUGSYS.INC
    ├── DEV.ASM
    ├── DMA.INC
    ├── DPRINTF.INC
    ├── DPRNTF16.INC
    ├── EMS.ASM
    ├── EMS.INC
    ├── EMS32.INC
    ├── EMU.ASM
    ├── EXTERN32.INC
    ├── I15.ASM
    ├── INIT.ASM
    ├── INIT16.ASM
    ├── JEMM.INC
    ├── JEMM16.ASM
    ├── JEMM16.INC
    ├── JEMM32.ASM
    ├── JEMM32.INC
    ├── POOL.ASM
    ├── UMB.ASM
    ├── VCPI.ASM
    ├── VCPI.INC
    ├── VDMA.ASM
    ├── VDS.ASM
    ├── XMS.ASM
    └── XMS.INC
Download .txt
SYMBOL INDEX (18 symbols across 4 files)

FILE: Include/JLM.H
  type UCHAR (line 9) | typedef unsigned char   UCHAR;
  type USHORT (line 10) | typedef unsigned short  USHORT;
  type ULONG (line 11) | typedef unsigned long   ULONG;
  type Pushad_Struc (line 13) | struct Pushad_Struc {
  function VMM_Service (line 92) | VMM_Service (Get_VMM_Version)
  type Client_Reg_Struc (line 154) | struct Client_Reg_Struc {

FILE: JLM/HELLO2/HELLO2.C
  type Client_Reg_Struc (line 6) | struct Client_Reg_Struc
  type cb_s (line 8) | struct cb_s
  function ULONG (line 14) | ULONG Begin_Nest_Exec()
  function ULONG (line 20) | ULONG End_Nest_Exec()
  function ULONG (line 26) | ULONG Exec_Int(unsigned long intno)
  function main (line 33) | int main()

FILE: JLM/HELLO2/HELLO2W.C
  type Client_Reg_Struc (line 9) | struct Client_Reg_Struc
  function main (line 11) | int main()

FILE: JLM/HELLO2/JLMW.h
  type cb_s (line 4) | struct cb_s
  type Client_Reg_Struc (line 5) | struct Client_Reg_Struc
  type Client_Reg_Struc (line 6) | struct Client_Reg_Struc
  type Client_Reg_Struc (line 7) | struct Client_Reg_Struc
Condensed preview — 197 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,413K chars).
[
  {
    "path": "Artistic.txt",
    "chars": 4922,
    "preview": "The Artistic License Preamble\r\n\r\nThe intent of this document is to state the conditions under which a Package may \r\nbe c"
  },
  {
    "path": "History.txt",
    "chars": 28966,
    "preview": "\r\n History\r\n\r\n __.__.____: v5.87\r\n\r\n - fixed regression in v5.86: exceptions in PL0 were displayed incorrectly.\r\n - fixe"
  },
  {
    "path": "Html/Readme.html",
    "chars": 33404,
    "preview": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 FINAL//EN\">\r\n<HTML>\r\n<HEAD>\r\n<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/h"
  },
  {
    "path": "Include/FILEACC.INC",
    "chars": 2158,
    "preview": "\r\n;--- dos file access for JLMs\r\n;--- although addresses are linear, they must\r\n;--- be within 64 kB distance of v86 DS "
  },
  {
    "path": "Include/FINDRES.INC",
    "chars": 4726,
    "preview": "\r\n?NOCASEMAP\tequ 0\t;win32 std is 0\r\n\r\n;--- eax = resource directory\r\n;--- id may be an id (HIWORD=0) or a string pointer"
  },
  {
    "path": "Include/JLM.H",
    "chars": 5658,
    "preview": "\r\n/* Header file for Jemm JLMs which defines the subset of the Win3x/Win9x */\r\n/* ring 0 API (VMM) that Jemm/JLoad expos"
  },
  {
    "path": "Include/JLM.INC",
    "chars": 9225,
    "preview": "\r\n;--- this is an assembler include file in MASM format,\r\n;--- to be used for JLMs (Jemm Loadable Modules).\r\n;--- it def"
  },
  {
    "path": "Include/JLMFASM.INC",
    "chars": 7925,
    "preview": "\r\n;--- this is an assembler include file in FASM format\r\n;--- to be used for JLMs (Jemm Loadable Modules).\r\n;--- it defi"
  },
  {
    "path": "Include/JSYSTEM.INC",
    "chars": 1083,
    "preview": "\r\n;--- constants used by Jemm & JLoad\r\n\r\n?VERSIONHIGH    equ 5\r\n?VERSIONLOW     equ 87\r\n\r\n?BASE           EQU 110000h   "
  },
  {
    "path": "Include/PRINTF.INC",
    "chars": 3236,
    "preview": "\r\n;--- simple printf\r\n\r\n;--- i64toa(long long n, char * s, int base);\r\n;--- convert 64-bit long long to string\r\n\r\ni64toa"
  },
  {
    "path": "Include/VDS.INC",
    "chars": 2183,
    "preview": "\r\n;--- VDS definitions\r\n\r\n;--- flags in DX used by various VDS functions\r\n\r\nVDSF_COPY       equ 02h\t;bit 1 - copy in/out"
  },
  {
    "path": "Include/X86.INC",
    "chars": 3136,
    "preview": "\r\n;--- generic X86 definitions\r\n\r\n;--- page table flags\r\n\r\nPTF_PRESENT equ 001h\r\nPTF_RW      equ 002h\r\nPTF_USER    equ 0"
  },
  {
    "path": "JLM/AHCICD/AHCICD.ASM",
    "chars": 24844,
    "preview": "\n;--- JLM to read CD/DVD in AHCI mode.\n;--- \"cooked\" mode is supported only.\n\n\t.386\n\t.model flat\n\toption casemap:none\n\to"
  },
  {
    "path": "JLM/AHCICD/AHCICD.txt",
    "chars": 722,
    "preview": "\r\n  1. About AHCICD\r\n\r\n  AHCICD is a JLM to access AHCI optical disks, \"inspired\" by Rudolph R. Loew's\r\n  AHCICD.SYS. To"
  },
  {
    "path": "JLM/AHCICD/MAKE.BAT",
    "chars": 221,
    "preview": "@echo off\r\n\r\njwasm -c -coff -nologo -Fl -Sg -I..\\..\\Include AHCICD.ASM\r\nrem jwasm -coff -nologo -D_DEBUG -Fl -Sg -I..\\.."
  },
  {
    "path": "JLM/AHCICD/MAKEM.BAT",
    "chars": 138,
    "preview": "@echo off\r\n\r\nml -c -coff -nologo -Fl -Sg -I..\\..\\Include AHCICD.ASM\r\nlink /nologo /subsystem:native /dll AHCICD.obj /OUT"
  },
  {
    "path": "JLM/GENERIC/GENERIC.ASM",
    "chars": 2480,
    "preview": "\r\n;--- JLM sample GENERIC\r\n;--- use Makefile to create GENERIC.DLL\r\n\r\n;--- GENERIC is a very simple JLM. It doesn't hook"
  },
  {
    "path": "JLM/GENERIC/MAKEFILE",
    "chars": 898,
    "preview": "\r\n# NMake/WMake Makefile to create GENERIC.DLL\r\n#\r\n#  tools                      alternatives\r\n#------------------------"
  },
  {
    "path": "JLM/GENERIC/README.TXT",
    "chars": 1373,
    "preview": "\r\n 1. About\r\n\r\n GENERIC is a JLM sample which demonstrates how to implement a\r\n protected-mode TSR.\r\n\r\n\r\n 2. How to inst"
  },
  {
    "path": "JLM/GENERIC/TESTGEN.ASM",
    "chars": 670,
    "preview": "\r\n;--- test app which calls some \"services\" of JLM GENERIC.\r\n;--- assemble: JWasm -bin -Fo testgen.com testgen.asm\r\n\r\n\t."
  },
  {
    "path": "JLM/HELLO/HELLO.ASM",
    "chars": 1393,
    "preview": "\r\n;--- a simple JLM which displays a message onto the screen\r\n;--- with the help of v86-int 21h and nested execution\r\n\r\n"
  },
  {
    "path": "JLM/HELLO/MAKE.BAT",
    "chars": 886,
    "preview": "@echo off\r\nrem\r\nrem use JWasm & JWlink\r\nrem\r\njwasm -nologo -coff -Fl=Release\\Hello -Fo=Release\\Hello -I..\\..\\Include Hel"
  },
  {
    "path": "JLM/HELLO/README.TXT",
    "chars": 207,
    "preview": "\r\n  About\r\n\r\n  This is the inevitable \"hello world\" JLM, written for Masm/JWasm.\r\n  It displays a welcome message. After"
  },
  {
    "path": "JLM/HELLO2/HELLO2.C",
    "chars": 836,
    "preview": "\r\n// for MS VC\r\n\r\n#include <jlm.h>\r\n\r\nstruct Client_Reg_Struc * pcl;\r\n\r\nstruct cb_s * Get_Cur_VM_Handle()\r\n{\r\n    VxDCal"
  },
  {
    "path": "JLM/HELLO2/HELLO2W.C",
    "chars": 588,
    "preview": "\r\n// for Open Watcom C\r\n// OW inline assembly doesn't know values of enums!\r\n// therefore it needs external module jlmw."
  },
  {
    "path": "JLM/HELLO2/JLMW.ASM",
    "chars": 690,
    "preview": "\r\n;--- helpers for (Watcom) C\r\n\r\n\t.386\r\n    .model flat\r\n    \r\n\tinclude JLM.INC\r\n\r\n\t.code\r\n\r\nGet_Cur_VM_Handle proc stdc"
  },
  {
    "path": "JLM/HELLO2/JLMW.h",
    "chars": 330,
    "preview": "\r\n// helper procs needed by Open Watcom C\r\n\r\nextern struct cb_s * _stdcall Get_Cur_VM_Handle( void );\r\nextern ULONG _std"
  },
  {
    "path": "JLM/HELLO2/MAKEJLMW.BAT",
    "chars": 95,
    "preview": "@echo off\r\nrem assembles helper module jlmw for Open Watcom.\r\njwasm -I ..\\..\\Include jlmw.asm\r\n"
  },
  {
    "path": "JLM/HELLO2/MAKEOW.BAT",
    "chars": 238,
    "preview": "@echo off\r\nrem uses Open Watcom C and WLink\r\nrem OW needs a helper module: jlmw.obj\r\nwcc386 -mf -zl -zls -s -I..\\..\\Incl"
  },
  {
    "path": "JLM/HELLO2/MAKEVC.BAT",
    "chars": 205,
    "preview": "@echo off\r\nrem uses MS VC and MS Link\r\n\\msvc71\\bin\\cl -c -I..\\..\\Include hello2.c\r\nlink /LIBPATH:\\msvc71\\lib hello2.obj "
  },
  {
    "path": "JLM/HELLO2/README.TXT",
    "chars": 221,
    "preview": "\r\n About\r\n \r\n Another JLM \"hello world\", this time written in C.\r\n MAKEVC.BAT: for MS VC (or Pelles C, CC386, ...)\r\n MAK"
  },
  {
    "path": "JLM/HELLO2/makeow.sh",
    "chars": 294,
    "preview": "#!/bin/sh\nset -e\n# uses Open Watcom C, JWAsm and JWLink which must be in PATH\n# OW needs a helper module: jlmw.obj\njwasm"
  },
  {
    "path": "JLM/IOTRAP/IOTRAP.ASM",
    "chars": 4751,
    "preview": "\r\n;--- JLM sample IOTRAP\r\n;--- use Makefile to create IOTRAP.DLL\r\n\r\n;--- IOTRAP traps IO port 100h when the first client"
  },
  {
    "path": "JLM/IOTRAP/MAKEFILE",
    "chars": 1004,
    "preview": "\r\n# NMake/WMake Makefile to create IOTRAP.DLL\r\n#\r\n#  tools                      alternatives\r\n#-------------------------"
  },
  {
    "path": "JLM/IOTRAP/README.TXT",
    "chars": 779,
    "preview": "\r\n 1. About\r\n\r\n IOTRAP is a JLM sample which demonstrates how to trap IO port access.\r\n\r\n Note: This is somewhat obsolet"
  },
  {
    "path": "JLM/IOTRAP/TESTIOT.ASM",
    "chars": 2021,
    "preview": "\r\n;--- tsr to test JLM IOTRAP.\r\n;--- it installs a callback which is called whenever port 100h\r\n;--- is accessed.\r\n;--- "
  },
  {
    "path": "JLM/JCLOCK/JCLOCK.ASM",
    "chars": 4677,
    "preview": ";\r\n; JCLOCK 1.1\r\n;\r\n; JLM example -- CLOCK for JEMM386/JEMMEX\r\n; It is the first JLM with screen input/output  :-)\r\n;\r\n;"
  },
  {
    "path": "JLM/JCLOCK/JCLOCK2.ASM",
    "chars": 4289,
    "preview": "\r\n; this is a modified JCLOCK version which uses the Jemm API to hook int 1Ch.\r\n; Thus, it can be unloaded.\r\n;\r\n; (C) 20"
  },
  {
    "path": "JLM/JCLOCK/JCLOCK3.ASM",
    "chars": 3471,
    "preview": "\r\n;--- JCLOCK2 in Masm/JWasm syntax\r\n\r\n\t.386\r\n\t.model flat\r\n\toption casemap:none\r\n\r\n\tinclude jlm.inc\r\n\r\n; Constants\r\n\r\nD"
  },
  {
    "path": "JLM/JCLOCK/MAKE.BAT",
    "chars": 156,
    "preview": "@echo off\r\nset FASMINC=\\fasm\\Include\r\nset JLMINC=..\\..\\Include\r\nfasm JCLOCK.ASM\r\nfasm JCLOCK2.ASM\r\n\\hx\\bin\\patchpe JCLOC"
  },
  {
    "path": "JLM/JCLOCK/MAKE3.BAT",
    "chars": 113,
    "preview": "@echo off\r\nrem make jclock3.dll - no link step required.\r\njwasm -pe -I..\\..\\Include -Fo=JCLOCK3.DLL JCLOCK3.ASM\r\n"
  },
  {
    "path": "JLM/JCLOCK/README.TXT",
    "chars": 584,
    "preview": "JCLOCK 1.4 -- Second JLM (JemmEx Loadable Module)\r\n(C) 2007 Alexey Voskov\r\n\r\nShows clock in the text mode.\r\n\r\nUsage\r\n~~~"
  },
  {
    "path": "JLM/JLSTUB/Build/JLSTUB.lst",
    "chars": 23300,
    "preview": "JWasm v2.18, May  7 2024\r\nJLSTUB.ASM\r\n\r\n                                ;--- MZ stub to run jload.exe\r\n                 "
  },
  {
    "path": "JLM/JLSTUB/JLSTUB.ASM",
    "chars": 7068,
    "preview": "\r\n;--- MZ stub to run jload.exe\r\n;--- to be assembled with Masm or JWasm\r\n;--- it's a derivate of dpmildxx... \r\n\r\n?MINME"
  },
  {
    "path": "JLM/JLSTUB/JLStub.txt",
    "chars": 293,
    "preview": "\r\n 1. About JLStub\r\n\r\n  JLStub is NOT a JLM. It's a stub, supposed to be added to other JLMs.\r\n It's purpose is to avoid"
  },
  {
    "path": "JLM/JLSTUB/Make.BAT",
    "chars": 108,
    "preview": "@echo off\r\nif not exist Build\\NUL mkdir Build\r\njwasm -nologo -mz -FlBuild\\ -Fo=Build\\jlstub.bin jlstub.asm\r\n"
  },
  {
    "path": "JLM/KEYBGR/KEYBGR.ASM",
    "chars": 9183,
    "preview": "\r\n;*** german keyboard driver for MF keyboards\r\n;--- the first JLM (Jemm Loadable Module) ever.\r\n\r\n;--- v1.0: initial\r\n;"
  },
  {
    "path": "JLM/KEYBGR/MAKE.BAT",
    "chars": 231,
    "preview": "@echo off\r\nrem\r\nrem JWasm v2.19: cmdline option -pe will create a JLM without external linker\r\nrem\r\njwasm -nologo -pe -D"
  },
  {
    "path": "JLM/KEYBGR/MAKEFILE",
    "chars": 745,
    "preview": "\r\n# Makefile for NMAKE\r\n#  tools                      Alternatives\r\n#---------------------------------------------------"
  },
  {
    "path": "JLM/KEYBGR/README.TXT",
    "chars": 302,
    "preview": "\r\n Deutscher Tastaturtreiber fuer DOS der mit 48 Bytes DOS Speicher \r\n auskommt. Funktioniert nur in Verbindung mit Jemm"
  },
  {
    "path": "JLM/QPIEMU/MAKE.BAT",
    "chars": 264,
    "preview": "@echo off\r\nrem create QPIEMU.DLL without linker, requires jwasm v2.19+\r\nrem Jemm's src directory has to be included sinc"
  },
  {
    "path": "JLM/QPIEMU/MAKEFILE",
    "chars": 900,
    "preview": "\r\n# NMake/WMake Makefile to create QPIEMU.DLL\r\n#\r\n#  tools                      alternatives\r\n#-------------------------"
  },
  {
    "path": "JLM/QPIEMU/QPIEMU.ASM",
    "chars": 5584,
    "preview": "\r\n;--- JLM sample QPIEMU\r\n;--- use Makefile to create QPIEMU.DLL\r\n\r\n;--- QPIEMU installs a small subset of Qemm's QPI,\r\n"
  },
  {
    "path": "JLM/QPIEMU/QPIEMU.txt",
    "chars": 1584,
    "preview": "\r\n 1. About\r\n\r\n QPIEMU is a JLM that partly emulates the Qemm API (QPI). Its\r\n purpose is to provide the IO trapping par"
  },
  {
    "path": "JLM/QPIEMU/Test/MAKEFILE",
    "chars": 370,
    "preview": "\r\n# NMake/WMake Makefile to create TESTQPI.EXE & TESTDMA.EXE\r\n\r\nNAME1 = TESTQPI\r\nNAME2 = TESTDMA\r\nOUTDIR= .\r\nASM=jwasm.e"
  },
  {
    "path": "JLM/QPIEMU/Test/PRINTF16.INC",
    "chars": 2958,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "JLM/QPIEMU/Test/SETARGV.INC",
    "chars": 3094,
    "preview": "\r\n;--- read the commandline at PSP:81h\r\n;--- and create an argc/argv structure on the stack.\r\n;--- in: ES=PSP, DS=DGROUP"
  },
  {
    "path": "JLM/QPIEMU/Test/TESTDMA.ASM",
    "chars": 4612,
    "preview": "\r\n;--- test Qemm/QPIEMU ( IO trap part )\r\n;--- this time test ISA DMA ports\r\n\r\n\t.286\r\n\t.model small\r\n\t.dosseg\r\n\t.stack 1"
  },
  {
    "path": "JLM/QPIEMU/Test/TESTQPI.ASM",
    "chars": 5282,
    "preview": "\r\n;--- test Qemm/QPIEMU ( IO trap part )\r\n\r\n\t.286\r\n\t.model small\r\n\t.dosseg\r\n\t.stack 1024\r\n\r\nlf equ 10\r\n\r\nCStr macro text"
  },
  {
    "path": "JLM/README.TXT",
    "chars": 1207,
    "preview": "\r\n 1. About\r\n\r\n This directory contains some JLMs:\r\n\r\n AHCICD:   AHCI Optical disk driver.\r\n GENERIC:  protected-mode TS"
  },
  {
    "path": "JLM/REBOOT/FASTBOOT.ASM",
    "chars": 9946,
    "preview": "\r\n;--- Sample how to handle DEVICE_REBOOT_NOTIFY control message;\r\n;--- handles fastboot only.\r\n;--- Requires Jemm v5.86"
  },
  {
    "path": "JLM/REBOOT/FASTBOOT.txt",
    "chars": 1386,
    "preview": "\r\n  About FastBoot JLM\r\n\r\n   The FastBoot JLM allows some fine-tuning of Jemm's fast reboot behavior\r\n  (which is activa"
  },
  {
    "path": "JLM/REBOOT/FASTBRM.ASM",
    "chars": 5147,
    "preview": "\r\n;--- real-mode part of the fastboot JLM;\r\n;--- this code is moved to address 07E00h by the fastboot JLM;\r\n;--- on entr"
  },
  {
    "path": "JLM/REBOOT/FBOOT.ASM",
    "chars": 2711,
    "preview": "\r\n;--- Set /D and /P option for currently loaded fastboot JLM.\r\n;--- This program uses the API installed by FASTBOOT.DLL"
  },
  {
    "path": "JLM/REBOOT/LDI13EXT.ASM",
    "chars": 3223,
    "preview": "\r\n;--- sample how to load an int 13h extension into FASTBOOT JLM.\r\n;--- this sample just swaps HDs 0 and 1 in int 13h; i"
  },
  {
    "path": "JLM/REBOOT/MAKE.BAT",
    "chars": 186,
    "preview": "@echo off\r\njwasm -nologo -pe  -Fl -Fo=REBOOT.DLL -I..\\..\\Include REBOOT.ASM \r\njwasm -nologo -bin -Fl FASTBRM.ASM \r\njwasm"
  },
  {
    "path": "JLM/REBOOT/REBOOT.ASM",
    "chars": 1504,
    "preview": "\r\n;--- sample how to handle DEVICE_REBOOT_NOTIFY control message\r\n;--- requires Jemm v5.86+\r\n\r\n\t.386\r\n\t.MODEL FLAT, stdc"
  },
  {
    "path": "JLM/REBOOT/REBOOT.txt",
    "chars": 220,
    "preview": "\r\n  About ReBoot\r\n\r\n  Reboot is just a sample, supposed to be modified if Jemm's default\r\n  way to reboot doesn't work o"
  },
  {
    "path": "JLM/XCDROM32/History.txt",
    "chars": 1122,
    "preview": "\r\n  History\r\n\r\n  10/2022: v1.5\r\n   - fixed: the driver was unable to handle multiple controllers with\r\n     identical cl"
  },
  {
    "path": "JLM/XCDROM32/MAKE.BAT",
    "chars": 193,
    "preview": "@echo off\r\nrem add -D_DEBUG to create a debug version\r\njwasm -coff -nologo -Fl -I..\\..\\Include XCDROM32.ASM\r\njwlink form"
  },
  {
    "path": "JLM/XCDROM32/MAKEM.BAT",
    "chars": 217,
    "preview": "@echo off\r\nrem add -D_DEBUG to create a debug version\r\nrem using MS tools\r\nml -c -coff -Fl -I..\\..\\Include XCDROM32.ASM\r"
  },
  {
    "path": "JLM/XCDROM32/XCDROM32.ASM",
    "chars": 75810,
    "preview": ";\r\n; XCDROM32.ASM  - a JLM driver for  UltraDMA CD-ROMs/DVDs\r\n; based on XCDROM v1.9 by Jack R. Ellis\r\n; released under "
  },
  {
    "path": "JLM/XCDROM32/XCDROM32.txt",
    "chars": 2182,
    "preview": "\r\n 1. About XCDROM32\r\n\r\n XCDROM32 is a JLM based on Jack R. Ellis' XCDROM Ultra-DMA CD-ROM driver.\r\n It supports PCI IDE"
  },
  {
    "path": "JLM/XDMA32/History.txt",
    "chars": 1179,
    "preview": "\r\n  10/2022: v1.5\r\n\r\n   - ensure that busmaster flag in PCI command register is set.\r\n   - created .data segment with va"
  },
  {
    "path": "JLM/XDMA32/IDENTIFY.INC",
    "chars": 13283,
    "preview": "\r\n;--- data returned by Identify Device from ATA disks\r\n;--- it's 256 * 16-bit words.\r\n\r\nIDENTIFY_DEVICE_DATA struct \r\ni"
  },
  {
    "path": "JLM/XDMA32/MAKE.BAT",
    "chars": 265,
    "preview": "@echo off\r\nrem Assemble and link file for the XDMA32 JLM.\r\nrem jwasm: option -zzs is needed for OW WLink v1.8!\r\n\r\njwasm "
  },
  {
    "path": "JLM/XDMA32/MAKEM.BAT",
    "chars": 166,
    "preview": "@echo off\r\nrem using MS tools\r\nml -c -coff -Fl -D_DEBUG -I..\\..\\Include XDMA32.ASM\r\nlink /NOLOGO /SUBSYSTEM:native /DLL "
  },
  {
    "path": "JLM/XDMA32/XDMA32.ASM",
    "chars": 52567,
    "preview": ";\r\n; XDMA32.ASM  - a JLM driver for UltraDMA hard-disks\r\n; based on XDMA v3.3 by Jack R. Ellis\r\n; released under the GNU"
  },
  {
    "path": "JLM/XDMA32/XDMA32.txt",
    "chars": 1924,
    "preview": "\r\n 1. About XDMA32\r\n\r\n XDMA32 is a JLM based on Jack R. Ellis' XDMA Ultra-DMA HD driver.\r\n It supports PCI IDE controlle"
  },
  {
    "path": "JemmExL.mak",
    "chars": 3251,
    "preview": "#\r\n# builds JemmExL, the \"legacy\" variant of JemmEx, without support\r\n# of XMS v3.5 ( super-extended memory )\r\n\r\nNAME3=J"
  },
  {
    "path": "Linux.mak",
    "chars": 4178,
    "preview": "#\r\n# To build Jemm386 and JemmEx on Linux, you will need:\r\n#\r\n# Tool\r\n#---------------------------\r\n# Assembler:   JWasm"
  },
  {
    "path": "Makefile",
    "chars": 7094,
    "preview": "#\r\n# To build Jemm386 and JemmEx, you will need:\r\n#\r\n# Tool        Default (recommended) Alternatives\r\n#----------------"
  },
  {
    "path": "Readme.txt",
    "chars": 32804,
    "preview": "\r\n Contents\r\n\r\n  1.   About Jemm\r\n  2.   Features\r\n  3.   Commandline Options\r\n  4.   Technical Details\r\n  4.1  EMS Impl"
  },
  {
    "path": "Test/BMINTRM.ASM",
    "chars": 1212,
    "preview": "\r\n;--- benchmark\r\n;*** call int 69h a number of times and count timer ticks\r\n;--- jwasm -mz bmintrm.asm\r\n\r\n\t.286\r\n\t.MODE"
  },
  {
    "path": "Test/EMS4E.ASM",
    "chars": 1655,
    "preview": "\r\n;*** test EMS get/set page map \r\n\r\n\t.286\r\n\t.model small\r\n\toption casemap:none\r\n\t.stack 1024\r\n\t.dosseg\r\n\t.386\r\n\r\nCStr m"
  },
  {
    "path": "Test/EMS4F.ASM",
    "chars": 2303,
    "preview": "\r\n;*** test EMS get/set partial page map \r\n\r\n\t.286\r\n\t.model small\r\n\toption casemap:none\r\n\t.stack 1024\r\n\t.dosseg\r\n\r\nCStr "
  },
  {
    "path": "Test/EMS56.ASM",
    "chars": 3628,
    "preview": "\r\n;*** test int 67h, ah=56h (alter map and call)\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg\r\n\toption casemap:none\r\n"
  },
  {
    "path": "Test/EMS57.ASM",
    "chars": 2829,
    "preview": "\r\n;*** EMS move\r\n\r\n\t.286\r\n\t.model tiny\r\n\toption casemap:none\r\n\toption casemap:none\r\n\t.stack 1024\r\n\t.dosseg\r\n\r\nCStr macro"
  },
  {
    "path": "Test/EMS57A.ASM",
    "chars": 4351,
    "preview": "\r\n;*** test EMS move (int 67h, ah=57h)\r\n;*** move 1024 kB conv to EMS memory\r\n;*** move 1024 kB EMS to EMS memory non-ov"
  },
  {
    "path": "Test/EMS5B.ASM",
    "chars": 1938,
    "preview": "\r\n;*** test EMS 5B\r\n;--- 5b00: get alternate map register set ( if BL=0 on ret, es:di will be current pointer to context"
  },
  {
    "path": "Test/EXC00.ASM",
    "chars": 166,
    "preview": "\r\n;*** EXC 00\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\n\t.code\r\n\r\nstart:\r\n\tmov dx, -1\r\n\tmov cx, 8000h\r\n\t"
  },
  {
    "path": "Test/EXC06.ASM",
    "chars": 155,
    "preview": "\r\n;*** EXC 06 - requires a P6+ cpu\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.686\r\n\r\n\t.code\r\n\r\nstart:\r\n\tud2\r\n\tmo"
  },
  {
    "path": "Test/FRAMERES.ASM",
    "chars": 520,
    "preview": "\r\n;--- create binary:\r\n;--- jwasm -bin -Fo frameres.com frameres.asm\r\n\r\n\t.286\r\n\t.MODEL tiny\r\n\r\n\t.CODE\r\n\r\n\torg 100h\r\n\r\nst"
  },
  {
    "path": "Test/HLTTEST.ASM",
    "chars": 1032,
    "preview": "\r\n;*** HLT test (v86)\r\n\r\n\t.286\r\n\t.model tiny\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\n\tinclude macros.inc\r\n\r\n\t.data\r\n\r\ndwOldInt"
  },
  {
    "path": "Test/HLTTEST2.ASM",
    "chars": 1033,
    "preview": "\r\n;*** HLT test (v86) with IF=0\r\n\r\n\t.286\r\n\t.model tiny\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\n\tinclude macros.inc\r\n\r\n\t.data\r\n"
  },
  {
    "path": "Test/I15MOVE.ASM",
    "chars": 2886,
    "preview": "\r\n;*** move block by int 15h, ah=87h\r\n\r\n\t.286\r\n\t.model tiny\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\nlf equ 10\r\n\r\nCStr macro te"
  },
  {
    "path": "Test/INT67.ASM",
    "chars": 484,
    "preview": "\r\n;--- the EMS handler runs slightly differently if IVT vector 67h is hooked!\r\n\r\n\t.286\r\n\t.model tiny\r\n\t.stack 256\r\n\r\n\t.c"
  },
  {
    "path": "Test/INT88.ASM",
    "chars": 932,
    "preview": "\r\n;--- test int# >= 0x80;\r\n;--- the monitor program uses the \"PUSH byte const\" instruction\r\n;--- to push a sign-extended"
  },
  {
    "path": "Test/MACROS.INC",
    "chars": 98,
    "preview": "\r\nCStr macro text:VARARG\r\nlocal sym\r\n\t.const\r\nsym db text,0\r\n\t.code\r\n\texitm <offset sym>\r\nendm\r\n\r\n"
  },
  {
    "path": "Test/MAKE.BAT",
    "chars": 115,
    "preview": "@echo off\r\nrem the programs may all be created without link step,\r\nrem using jwasm's -mz option\r\njwasm -mz %1.asm\r\n"
  },
  {
    "path": "Test/PRINTF.INC",
    "chars": 3057,
    "preview": "\r\n;--- simple printf() implementation\r\n;--- assume ds=dgroup\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmo"
  },
  {
    "path": "Test/README.TXT",
    "chars": 1278,
    "preview": "\r\nbmintrm:    benchmark int 69h real-mode\r\nems4e:      get/set page map\r\nems4f:      get/set partial page map\r\nems56:   "
  },
  {
    "path": "Test/TEST0C.DEB",
    "chars": 62,
    "preview": "; test v86 exc 0C\r\na\r\nmov sp,ffff\r\npop ax\r\nint 3\r\n\r\ng=100\r\nq\r\n"
  },
  {
    "path": "Test/TEST0C1.DEB",
    "chars": 60,
    "preview": "; test v86 exc 0C\r\na\r\nmov sp,1\r\npush ax\r\nint 3\r\n\r\ng=100\r\nq\r\n"
  },
  {
    "path": "Test/TEST0D.DEB",
    "chars": 56,
    "preview": "; test v86 exc 0D\r\na\r\nmov ax,[ffff]\r\nint 3\r\n\r\ng=100\r\nq\r\n"
  },
  {
    "path": "Test/TEST10.DEB",
    "chars": 291,
    "preview": "; test v86 exc 10\r\n; set CR0 NE bit\r\n; enable exceptions in FP control word\r\n; the do an FP pop\r\n; the exception occurs "
  },
  {
    "path": "Test/TEST11.DEB",
    "chars": 228,
    "preview": "; test v86 exc 11\r\n; set CR0 AM bit\r\n; set EFL AC bit\r\n; then access stack unaligned\r\na\r\nmov eax,cr0\r\nor eax,40000\r\nmov "
  },
  {
    "path": "Test/TESTDMA.ASM",
    "chars": 1433,
    "preview": "\r\n;--- test FD read in UMB\r\n;--- using Int 25h\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\nCStr macro text"
  },
  {
    "path": "Test/TESTDMA2.ASM",
    "chars": 1991,
    "preview": "\r\n;--- test FD read in UMB\r\n;--- using Int 13h\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg\r\n\t.386\r\n\r\n?SIZE equ 1000h"
  },
  {
    "path": "Test/TESTDMA3.ASM",
    "chars": 3194,
    "preview": "\r\n;--- test FD read in UMB\r\n;--- using Int 13h\r\n;--- this variant ensures that a 64kb border is crossed,\r\n;--- forcing t"
  },
  {
    "path": "Test/TESTVCPI.ASM",
    "chars": 11250,
    "preview": "\r\n;--- the purpose of the test is to see if page table 0, returned by int 67h, ax=DE01h\r\n;--- is updated by the VCPI hos"
  },
  {
    "path": "Test/TESTVDS.ASM",
    "chars": 13634,
    "preview": "\r\n;--- VDS API test\r\n;--- 8103/8104:      lock/unlock region\r\n;--- 8107/8108/8109/810A: request/release DMA buffer, copy"
  },
  {
    "path": "Test/TESTVDS2.ASM",
    "chars": 1609,
    "preview": "\r\n;--- VDS API test; test disable/enable auto DMA translation (810B/810C)\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosse"
  },
  {
    "path": "Test/TESTVDS3.ASM",
    "chars": 1309,
    "preview": "\r\n;--- VDS API test; display ISA DMA translation status for channels 0-7\r\n\r\n\t.286\r\n\t.model small\r\n\t.stack 2048\r\n\t.dosseg"
  },
  {
    "path": "Test/TIMERMS.INC",
    "chars": 1456,
    "preview": "\r\n;--- gettimer() returns timer in EAX in ms\r\n\r\n_GetTimerValue proc\r\n\tpush ds\r\n\tpush 0\r\n\tpop ds\r\ntryagain:\r\n\tmov edx,ds:"
  },
  {
    "path": "Test/VCPI.INC",
    "chars": 976,
    "preview": "\r\ndesc struct\r\nlimit   dw ?\r\nA0015   dw ?\r\nA1623   db ?\r\nattrib  db ?\r\nlim_gr  db ?\r\nA2431   db ?\r\ndesc ends\r\n\r\n;--- VCP"
  },
  {
    "path": "Test/XMSTEST.ASM",
    "chars": 4300,
    "preview": "\r\n;--- XMSTEST: test xms memory moves\r\n;--- Public Domain.\r\n;--- to be assembled with JWasm or Masm v6.\r\n\r\n\t.model tiny\r"
  },
  {
    "path": "Test/XMSTEST2.ASM",
    "chars": 3393,
    "preview": "\r\n;--- XMSTEST2: test max block allocation\r\n;--- Public Domain.\r\n;--- to be assembled with JWasm or Masm v6.\r\n\r\n\t.model "
  },
  {
    "path": "Test/XMSTEST3.ASM",
    "chars": 2214,
    "preview": "\r\n;--- test ah=0Eh (get handle info)\r\n;--- Public Domain.\r\n;--- to be assembled with JWasm or Masm v6.\r\n\r\n\t.model tiny\r\n"
  },
  {
    "path": "Test/XMSTEST4.ASM",
    "chars": 2619,
    "preview": "\r\n;--- XMSTEST4: test block resize (shrink)\r\n;--- Public Domain.\r\n;--- to be assembled with JWasm or Masm v6.\r\n\r\n\t.model"
  },
  {
    "path": "Test/XMSTEST5.ASM",
    "chars": 3111,
    "preview": "\r\n;--- XMSTEST5: test block resize (shrink)\r\n;--- this variant allocates a 64MB block with xms v3,\r\n;--- but tries to re"
  },
  {
    "path": "Tools/CLEAR.BAT",
    "chars": 407,
    "preview": "@echo off\r\nerase CPUID\\*.EXE\r\nerase CPUID\\*.lst\r\nerase CpuStat\\*.EXE\r\nerase CpuStat\\*.lst\r\nerase EMSSTAT\\*.EXE\r\nerase EM"
  },
  {
    "path": "Tools/CPUID/CPUID.ASM",
    "chars": 8210,
    "preview": "\r\n;--- CPUID displays status of CPU. \r\n;--- Public Domain.\r\n;--- Masm syntax. To be assembled with JWasm or Masm.\r\n;--- "
  },
  {
    "path": "Tools/CPUID/MAKE.BAT",
    "chars": 85,
    "preview": "@echo off\r\nrem creates CPUID.EXE with JWasm\r\njwasm -c -nologo -Fl -Sg -mz CPUID.ASM\r\n"
  },
  {
    "path": "Tools/CPUID/PRINTF.INC",
    "chars": 2881,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "Tools/Cpustat/CPUSTAT.ASM",
    "chars": 18364,
    "preview": "\r\n;--- CPUSTAT displays status of CPU. \r\n;--- Public Domain.\r\n;--- Masm syntax. To be assembled with JWasm or Masm.\r\n;--"
  },
  {
    "path": "Tools/Cpustat/MAKE.BAT",
    "chars": 89,
    "preview": "@echo off\r\nrem creates CPUSTAT.EXE with JWasm\r\njwasm -c -nologo -Fl -Sg -mz CPUSTAT.ASM\r\n"
  },
  {
    "path": "Tools/Cpustat/PRINTF.INC",
    "chars": 2881,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "Tools/EMSSTAT/EMSSTAT.ASM",
    "chars": 12251,
    "preview": "\r\n;--- EMSSTAT: display EMS status.\r\n;--- Public Domain.\r\n;--- tools: JWasm/Masm v6 and WLink.\r\n\r\n\t.286\r\n\t.model small\r\n"
  },
  {
    "path": "Tools/EMSSTAT/MAKE.BAT",
    "chars": 81,
    "preview": "@echo off\r\nrem creates EMSSTAT.EXE with JWasm\r\njwasm -c -nologo -mz EMSSTAT.ASM\r\n"
  },
  {
    "path": "Tools/EMSSTAT/PRINTF.INC",
    "chars": 2881,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "Tools/JEMFBHLP/JEMFBHLP.ASM",
    "chars": 2752,
    "preview": "\r\n;*** save some interrupt vectors the way MS-DOS does\r\n;*** needed for FreeDOS if Jemm386's FASTBOOT option is used\r\n\r\n"
  },
  {
    "path": "Tools/JEMFBHLP/MAKE.BAT",
    "chars": 86,
    "preview": "@echo off\r\nrem create JEMFBHLP.EXE with JWasm\r\njwasm -c -nologo -mz -Fl JEMFBHLP.ASM\r\n"
  },
  {
    "path": "Tools/JLOAD/DEBUG.INC",
    "chars": 986,
    "preview": "\r\n;*** debug macros and equates\r\n\r\n?USEMONO equ 0\t;1=use monochrome video mode\r\n\r\nifndef ?RMDBG\r\n?RMDBG   = 0\t;log real-"
  },
  {
    "path": "Tools/JLOAD/DPRINTF.INC",
    "chars": 3340,
    "preview": "\r\n;--- printf for debug displays, 32-bit\r\n\r\n;--- i64toa(long long n, char * s, int base);\r\n;--- convert 64-bit long long"
  },
  {
    "path": "Tools/JLOAD/DPRNTF16.INC",
    "chars": 3304,
    "preview": "\r\n;--- printf for debug displays, 16-bit\r\n\r\n;--- itoa(long n, char * s, int base);\r\n;--- convert 32-bit long to string\r\n"
  },
  {
    "path": "Tools/JLOAD/History.txt",
    "chars": 2076,
    "preview": "\r\n v5.87:\r\n   - Linux.mak added to create JLOAD.EXE on Linux.\r\n\r\n v5.86:\r\n   - Jemm's control notifications handled (DEV"
  },
  {
    "path": "Tools/JLOAD/JLOAD.ASM",
    "chars": 24666,
    "preview": "\r\n;--- 16-bit part of JLoad\r\n;--- JLoad loads a 32bit PE binary in Jemm's address space\r\n;--- best viewed with TABSIZE 4"
  },
  {
    "path": "Tools/JLOAD/JLOAD.INC",
    "chars": 694,
    "preview": "\r\n;--- assembly conditionals\r\n\r\n;--- constants\r\n;--- ?SYSBASE is from JSYSTEM.INC (=0F8000000h)\r\n\r\n?SYSTEMADDR\t\tequ ?SYS"
  },
  {
    "path": "Tools/JLOAD/JLOAD.TXT",
    "chars": 4267,
    "preview": "\r\n 1. About JLoad and JLMs\r\n\r\n  JLoad is an extension for Jemm (both Jemm386 and JemmEx) which allows to\r\n load 32bit fl"
  },
  {
    "path": "Tools/JLOAD/JLOAD.txt",
    "chars": 4267,
    "preview": "\r\n 1. About JLoad and JLMs\r\n\r\n  JLoad is an extension for Jemm (both Jemm386 and JemmEx) which allows to\r\n load 32bit fl"
  },
  {
    "path": "Tools/JLOAD/JLOAD32.ASM",
    "chars": 11034,
    "preview": "\r\n;--- JLoad's PE file loader\r\n;--- this code is copied to linear address ?SYSTEMADDR when\r\n;--- JLoad is running for th"
  },
  {
    "path": "Tools/JLOAD/JLOAD32.INC",
    "chars": 753,
    "preview": "\r\n;--- macros\r\n\r\nCStr macro text:vararg\r\nlocal sym\r\n\t.const\r\n ifidni <text>,<\"\">\r\nsym db 0\r\n else\r\nsym db text,0\r\n endif"
  },
  {
    "path": "Tools/JLOAD/Linux.mak",
    "chars": 1939,
    "preview": "\r\n# makefile that creates JLOAD.EXE\r\n# tools used:\r\n#------------------------\r\n# Assembler:    jwasm\r\n# OMF linker:   jw"
  },
  {
    "path": "Tools/JLOAD/MAKEFILE",
    "chars": 2340,
    "preview": "\r\n# nmake makefile that creates JLOAD.EXE\r\n# tools used:\r\n#               default      alternate\r\n#---------------------"
  },
  {
    "path": "Tools/JLOAD/VDMAD.ASM",
    "chars": 5224,
    "preview": "\r\n;--- VDMAD support\r\n;--- best viewed with TAB size 4\r\n\r\n\t.386\r\n\t.model flat\r\n\r\n\toption casemap:none\r\n\toption proc:priv"
  },
  {
    "path": "Tools/JLOAD/VIOOUT.INC",
    "chars": 1537,
    "preview": "\r\n;--- low-level video access\r\n;--- no assumption about ds,es.\r\n;--- ss is supposed to be flat.\r\n\r\nVPUTCHR PROC\r\n\tpush d"
  },
  {
    "path": "Tools/JLOAD/VMM.ASM",
    "chars": 38586,
    "preview": "\r\n;--- VMM functions\r\n;--- best viewed with TAB size 4\r\n\r\n\t.386\r\n\t.model flat\r\n\r\n\toption casemap:none\r\n\toption proc:priv"
  },
  {
    "path": "Tools/JLOAD/WINNT.INC",
    "chars": 19655,
    "preview": "\r\nifndef WINNT_INCLUDED\r\n\r\n\tpushcontext listing\r\n\t.nolist\r\n\t.xcref\r\n\r\nifdef @list_on\r\n\t.list\r\n\t.cref\r\nendif\r\n\r\nWINNT_INC"
  },
  {
    "path": "Tools/JLOAD/license.txt",
    "chars": 1069,
    "preview": "\nCopyright (c) 2021 Andreas Grech (japheth)\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "Tools/MAKE.BAT",
    "chars": 307,
    "preview": "@echo off\r\ncd CPUID\r\ncall MAKE\r\ncd ..\r\ncd CpuStat\r\ncall MAKE\r\ncd ..\r\ncd EMSSTAT\r\ncall MAKE\r\ncd ..\r\ncd JEMFBHLP\r\ncall MAK"
  },
  {
    "path": "Tools/MEMSTAT/MAKE.BAT",
    "chars": 85,
    "preview": "@echo off\r\nrem creates MEMSTAT.EXE with JWasm\r\njwasm -c -nologo -mz -Fl MEMSTAT.ASM\r\n"
  },
  {
    "path": "Tools/MEMSTAT/MEMSTAT.ASM",
    "chars": 6379,
    "preview": "\r\n;*** get extended memory status using int 15h\r\n;*** AH=88h\r\n;*** AH=C7h if supported\r\n;*** AX=E801h\r\n;*** AX=E820h\r\n\r\n"
  },
  {
    "path": "Tools/MEMSTAT/PRINTF.INC",
    "chars": 2881,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "Tools/MoveXBDA/MAKE.BAT",
    "chars": 83,
    "preview": "@echo off\r\nrem create MOVEXBDA.EXE with JWasm\r\njwasm -nologo -mz -Fl MOVEXBDA.ASM\r\n"
  },
  {
    "path": "Tools/MoveXBDA/MOVEXBDA.ASM",
    "chars": 4840,
    "preview": "\r\n;--- MOVEXBDA moves XBDA to low memory. If the XBDA is already moved\r\n;--- or if it is too large, nothing is done.\r\n;-"
  },
  {
    "path": "Tools/UMBM/MAKE.BAT",
    "chars": 86,
    "preview": "@echo off\r\nrem BAT to create UMBM.EXE with JWasm\r\njwasm -mz -nologo -Fl -Sg UMBM.ASM\r\n"
  },
  {
    "path": "Tools/UMBM/UMBM.ASM",
    "chars": 12954,
    "preview": "\r\n;***   UMBM is a DOS device driver, but will not install permanently:\r\n;***   if UMBs activated by UMBPCI are found, U"
  },
  {
    "path": "Tools/VCPI/MAKE.BAT",
    "chars": 80,
    "preview": "@echo off\r\nrem creates VCPI.EXE with JWasm\r\njwasm -mz -nologo -Fl -Sg VCPI.ASM\r\n"
  },
  {
    "path": "Tools/VCPI/PRINTF.INC",
    "chars": 2809,
    "preview": "\r\n;--- ltob(long n, char * s, int base);\r\n;--- convert long to string\r\n\r\nltob PROC stdcall uses edi edx number:dword, ou"
  },
  {
    "path": "Tools/VCPI/VCPI.ASM",
    "chars": 18526,
    "preview": "\r\n;*** display VCPI information\r\n;*** and use VCPI to switch to protected mode and back\r\n\r\n;--- if segments are defined "
  },
  {
    "path": "Tools/VCPI/VCPI.INC",
    "chars": 976,
    "preview": "\r\ndesc struct\r\nlimit   dw ?\r\nA0015   dw ?\r\nA1623   db ?\r\nattrib  db ?\r\nlim_gr  db ?\r\nA2431   db ?\r\ndesc ends\r\n\r\n;--- VCP"
  },
  {
    "path": "Tools/VCPI/VIOOUT.INC",
    "chars": 1970,
    "preview": "\r\n;--- vio output for 16-bit protected-mode\r\n\r\n@getcursorpos macro\r\n\tmovzx ebx, byte ptr ds:[462h];page\r\n\tmov bx, ds:[EB"
  },
  {
    "path": "Tools/XMSSTAT/MAKE.BAT",
    "chars": 84,
    "preview": "@echo off\r\nrem  create XMSSTAT.EXE\r\nrem  uses JWasm\r\njwasm -nologo -mz XMSSTAT.ASM\r\n"
  },
  {
    "path": "Tools/XMSSTAT/PRINTF.INC",
    "chars": 2881,
    "preview": "\r\n;--- simple printf() implementation\r\n\r\nhandle_char proc\r\n\r\n\tmov dl,al\r\n\tcmp al,10\r\n\tjnz @F\r\n\tmov dl,13\r\n\tcall @F\r\n\tmov"
  },
  {
    "path": "Tools/XMSSTAT/XMSSTAT.ASM",
    "chars": 9687,
    "preview": "\r\n;--- XMSSTAT: display xms status.\r\n;--- Public Domain.\r\n;--- to be assembled with JWasm or Masm v6.\r\n\r\n\t.model small\r\n"
  },
  {
    "path": "XMS35.txt",
    "chars": 3033,
    "preview": "\r\n  1. XMS v3.5 API\r\n  \r\n   XMS v3.5 has been created to allow accessing extended memory beyond the 4 GB\r\n  barrier. \r\n\r"
  },
  {
    "path": "src/AUXIO.INC",
    "chars": 1560,
    "preview": "\r\n;--- handle AUX I/O\r\n\r\nifndef COMNO\r\nCOMNO       equ 1\r\nendif\r\n_XONXOFF_   equ 1\r\nXON         equ 11h\r\nXOFF        equ"
  },
  {
    "path": "src/DEBUG.ASM",
    "chars": 3485,
    "preview": "\r\n;*** implements debug displays\r\n;--- written by japheth\r\n;--- public domain\r\n;--- to be assembled with JWasm or Masm v"
  },
  {
    "path": "src/DEBUG16.INC",
    "chars": 669,
    "preview": "\r\n@dbgdef macro name_\r\nifndef name_\r\nname_ equ 0\r\nendif\r\n?DBGOUT = ?DBGOUT + name_\r\nendm\r\n\r\n?DBGOUT = 0\r\n@dbgdef ?INITRM"
  },
  {
    "path": "src/DEBUG32.INC",
    "chars": 2632,
    "preview": "\r\n@dbgdef macro name_\r\nifndef name_\r\nname_ equ 0\r\nendif\r\n?DBGOUT = ?DBGOUT + name_\r\nendm\r\n\r\n?DBGOUT = 0\r\n@dbgdef ?V86DBG"
  },
  {
    "path": "src/DEBUGSYS.INC",
    "chars": 11929,
    "preview": "\r\n;\r\n;  Real mode Debugger services:\r\n;\r\n\r\nD386_RM_Int\t\tequ 68h\t; hooked by the debugger in real mode.\r\n\r\nD386_Id\t\t\tequ "
  },
  {
    "path": "src/DEV.ASM",
    "chars": 7785,
    "preview": "\r\n;*** implements EMMXXXX0 device\r\n;--- public domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n    .m"
  },
  {
    "path": "src/DMA.INC",
    "chars": 1300,
    "preview": "\n;--- ports ISA DMA controller\n\nDMA_STATUS_CMD     equ 8\t; R status / W command\nDMA_REQUEST        equ 9\t; W b0+1: chann"
  },
  {
    "path": "src/DPRINTF.INC",
    "chars": 3501,
    "preview": "\r\n;--- printf for debug displays\r\n;--- assume CS and SS flat;\r\n;--- no assumptions about DS/ES\r\n\r\n;--- i64toa(long long "
  },
  {
    "path": "src/DPRNTF16.INC",
    "chars": 3361,
    "preview": "\r\n;--- printf for debug displays, 16-bit\r\n\r\n;--- itoa(long n, char * s, int base);\r\n;--- convert 32-bit long to string\r\n"
  },
  {
    "path": "src/EMS.ASM",
    "chars": 47673,
    "preview": "\r\n;--- EMS implementation\r\n;--- EMS 4.0 is Public Domain, originally written by Michael Devore,\r\n;--- extended and modif"
  },
  {
    "path": "src/EMS.INC",
    "chars": 1582,
    "preview": "\r\n;--- EMS status codes\r\n\r\nEMSS_OK                 equ 00h\r\nEMSS_SOFTWARE_ERR       equ 80h ;unexpected error\r\nEMSS_HARD"
  },
  {
    "path": "src/EMS32.INC",
    "chars": 13460,
    "preview": "\r\n;--- this is the Jemm EMS 3.2 implementation (functions 40h - 4Eh)\r\n;--- since this part is copyright Harald Albrecht/"
  },
  {
    "path": "src/EMU.ASM",
    "chars": 2355,
    "preview": "\r\n;--- privileged opcode emulation\r\n;--- copyright Tom Ehlert\r\n\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .3"
  },
  {
    "path": "src/EXTERN32.INC",
    "chars": 4401,
    "preview": "\r\n;--- publics for Jemm32\r\n\r\n@seg macro name_, align_\r\nname_ SEGMENT align_ FLAT public 'CODE'\r\nendm\r\n\r\n;--- sections:\r\n"
  },
  {
    "path": "src/I15.ASM",
    "chars": 4458,
    "preview": "\r\n;--- I15, ah=87 extended memory move \r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n"
  },
  {
    "path": "src/INIT.ASM",
    "chars": 37283,
    "preview": "\r\n;--- Jemm's initialization part\r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n    .m"
  },
  {
    "path": "src/INIT16.ASM",
    "chars": 67631,
    "preview": "\r\n;--- 16-bit initialization part\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n\t.model tiny\r\n\t.386\r\n\r\nCStr macro te"
  },
  {
    "path": "src/JEMM.INC",
    "chars": 7470,
    "preview": "\r\n;--- common definitions for both Jemm32 and Jemm16\r\n\r\n\toption proc:private\r\n\toption casemap:none\r\n\r\nLF              EQ"
  },
  {
    "path": "src/JEMM16.ASM",
    "chars": 30784,
    "preview": "\r\n;--- 16 bit part of Jemm;\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n;--- _RTEXT must be first segment; it has "
  },
  {
    "path": "src/JEMM16.INC",
    "chars": 1660,
    "preview": "\r\n;--- globals for jemm16.asm and init16.asm\r\n\r\nif ?INTEGRATED\r\nNAMEEXE equ <\"JEMMEX\">\r\nNAMEMOD equ <\"JemmEx\">\r\nelse\r\nNA"
  },
  {
    "path": "src/JEMM32.ASM",
    "chars": 73242,
    "preview": ";*****************************************************************************\r\n;** This is the main 32bit ASM part of J"
  },
  {
    "path": "src/JEMM32.INC",
    "chars": 8275,
    "preview": "\r\n;--- these files contains things for 32-bit ONLY\r\n\r\n?RING0EXC       EQU 1       ; 1=display more infos on exc in ring "
  },
  {
    "path": "src/POOL.ASM",
    "chars": 41006,
    "preview": "\r\n;--- Jemm's memory pool implementation\r\n;--- originally written by Michael Devore\r\n;--- Public Domain\r\n;--- to be asse"
  },
  {
    "path": "src/UMB.ASM",
    "chars": 8733,
    "preview": "\r\n;--- XMS UMB part implementation\r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n    ."
  },
  {
    "path": "src/VCPI.ASM",
    "chars": 16528,
    "preview": "\r\n;--- VCPI implementation\r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n;--- originally written b"
  },
  {
    "path": "src/VCPI.INC",
    "chars": 390,
    "preview": "\r\n; structure for VCPI switch from V86 to protected mode\r\n\r\nV86TOPM  STRUCT\r\ndwCR3       DD  ?   ; client's CR3 value\r\nd"
  },
  {
    "path": "src/VDMA.ASM",
    "chars": 18659,
    "preview": "\r\n;--- DMA port trapping code\r\n;--- originally written by Harald Albrecht\r\n;--- modified for Jemm by Japheth\r\n;--- copyr"
  },
  {
    "path": "src/VDS.ASM",
    "chars": 26469,
    "preview": "\r\n;--- Jemm's VDS implementation\r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n    .mo"
  },
  {
    "path": "src/XMS.ASM",
    "chars": 37985,
    "preview": "\r\n;--- XMS/A20 implementation\r\n;--- Public Domain\r\n;--- to be assembled with JWasm or Masm v6.1+\r\n\r\n    .386\r\n    .model"
  },
  {
    "path": "src/XMS.INC",
    "chars": 2483,
    "preview": "\r\n;--- XMS definitions\r\n\r\nXMS_GETVERSION   equ  0h\r\nXMS_ENABLEA20    equ  5h\r\nXMS_DISABLEA20   equ  6h\r\nXMS_V2_QUERYMEM "
  }
]

About this extraction

This page contains the full source code of the Baron-von-Riedesel/Jemm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 197 files (1.2 MB), approximately 431.9k tokens, and a symbol index with 18 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!