Navigation Panel

Protel Autotrax
What is Autotrax?
What is the Purpose of this Site?
Installation - Tasks 1 and 2
Installation - Tasks 3 and 4
Installation - Task 5
Installation - Task 6
How it Works
The Resizing Problem

Let's Design a Circuit
Now Draw it
Place Components
Adding the Tracks

Aston Home

So, smart-arse, tell me how it works.

No.  It's top secret.  Only Illuminati and members of Opus Dei can know.

Oh, all right then.

It's really, really difficult to find any worthwhile documentation on this but Steve Murray gives a useful tutorial at the head of his DOS driver coding.  I've included this below.  I expect he won't mind.   Altium released the source code for the basic SVGA  and CGA drivers for the Autotrax and Easytrax programs.  These compile down to what is essentially a COM program (not Component Object Model; DOS-not-an-EXE-program-COM).  This is designed to be exactly 4k bytes long and is renamed as graph.drv.  Traxedit loads this up when it is invoked.

How does it talk to a 32-bit driver?

When the DOS program is loaded into NT-based OS's like W2K or XP, a program called NTVDM.exe is called upon to provide a virtual DOS environment for it to run in.  NTVDM.exe also exports a slew of functions that are similarly available to developers in NTVDM.lib.  When the NTVDM host encounters the instruction to switch to a graphics mode, it does so if that mode is available on the display.

Many years ago, I tried re-writing my own graph.drv to work with a Matrox video card on my old 486.  I wanted to get 1280 x 1024.  I managed after a long learning curve to get it working but it was very slow at drawing arcs.  This was because of the way an arc spans video pages.  The window is divided into strips that are selectively mapped to the video area of the DOS memory.  Changing pages is a faily slow process.  I worked out how to speed it up by altering the code but my driver was fairly crap.

I then discovered that Steve Murray had done the job much better than I could but hadn't spotted the trick for the faster arc routine.  Anyway, I used Steve's drivers for years.  Then Steve came up with a driver that ran on XP.  I have to confess that I didn't have much luck with it but thought what he was doing was very clever and I decided to have a crack at re-writing it to work in full screen mode.  This I managed to do in March of 2012 and used the driver until I couldn't sustain XP any longer and had to go to Windows 7.  I then went back to using Steve's VESA driver under DOSBox.

In a vain hope of being able to get back to where I had been with XP, I downloaded XPMode from the Microsoft site.  What a pile of shite that is. 

So I tried VirtualBox but my little driver didn't work on that either.  Then I found that it doesn't like to run DirectX in full-screen mode.  If I ran it in windowed mode, it worked fine.  Well, there's nowt wrong with making the window the full size of the screen without setting full screen mode.  So that's how it works.

This is the bit from Steve Murray's assembler code used to create the graph.drv file.

;       Autotrax XP Video driver - DOS 16 bit to Protected mode 32 bit
;Autotrax comes complete with a VGA640 driver, providing 640x480 resolution that
;seems reliable and runs on any hardware.  For those of us that want a higher
;resolution, we developed a VESA based video driver.  This has performed quite
;well, but it depends on VESA BIOS support from the video subsystem.  Back in
;WIN98 days, nearly all video cards supported VESA.  Increasingly, however,
;onboard video subsystems are cheating on VESA BIOS - it may not work completely
;Having said that, most Brand name video cards still offer VESA BIOS support, so
;there is still a method to run Autotrax with our old drivers, but at a cost.
;This driver does not use VESA but instead directX.  Autotrax itself, with this
;driver included, is 16 bit code.  When running under an XP/NT operating system
;this means that it cannot directly manipulate system hardware, and it cannot
;realistically just call the DirectX API.  In effect, under XP Autotrax is being
;run by a microsoft beastie called NTVDM (NT Virtual Dos Machine).  However, for
;your benefit microsoft have provided some NTVDM routines that enable us to
;build "Virtual Device Drivers" (VDD's) that can translate between 16 bit MS-DOS
;applications and "special purpose hardware" (in our case, just video, not so
;We write a VDD and use the NTVDM calls provided to run DirectX from Autotrax.

;--The VDD Calls:--
;The calls are so brilliantly simple it defies imagination.  I feel in awe of
;the engineer who included these in NTVDM - they are simple, basic and clean.
;Actually, I haven't said that about that big companies products before, ever.
;On the 16 bit app side, you just place 4 bytes in your code, for execution:
;Where N selects for: 2=DispatchCall, 1=UnRegisterModule, and 0=RegisterModule
;At the time of calling DispatchCall or UnRegisterModule the AX register should
;be set to the VDD handle ( identifying token...) that you obtain when you
;first call RegisterModule.  (The DispatchCall does the actual interface task.)
;This first call to RegisterModule also sets up the interface.  The interface is
;actually between our 16 bit DOS app and a two seperate 32 bit routines in a DLL
;When we call RegisterModule we pass pointers in registers indicating our DLL:
;DS:SI= Pointer to zero terminated ASCII string being the DLLname (autoxpdv.dll)
;ES:DI= Pointer to zero terminated ASCII string: DLL Init routine       (axinit)
;DS:BX= pointer to zero terminated ASCII string: DLL Dispatch routine   (axdisp)
;RegisterModule will return the VDD handle, or, if there is a problem, a code:
;AX = 1, Carry = 1:  DLL not found
;AX = 2, Carry = 1:  Dispatch routine not found
;AX = 3, Carry = 1:  Init routine not found
;AX = 4, Carry = 1:  Insufficient memory available
;AX=MMMM,Carry = 0:  Successful operation, File handle MMMM is returned
;By the nature of DLL's, there is actually a third routine in the 32 bit code,
;usually called LIBMAIN or DLLMAIN.  This routine is invoked when windows first
;brings up the DLL.  If it suits you, you could make the RegisterModule DLL Init
;routine redundant - and just use the LIBMAIN routine to this job.  If the
;RegisterModule DLL init routine is unused, set ES:DI to 0 in RegisterModule.
;The information presented here is the distilled version of what is needed to
;produce a 16 bit app to 32 bit DLL interface - google on some of the terms used
;and you will find the original information, with lots more detail (and lots of
;red herrings also - thunking and VXDs are alternative strategies we do not use)
;On the 32 bit side, we provide a DLL that must have 3 exposed routines as
;already mentioned - the LIBMAIN/DLLMAIN that all DLL's have, an Init routine
;(in our case axinit) and a dispatch routine (in our case axdisp).
;Regretfully, no data is automatically passed to our DLL.  Instead we ask NTVDM
;for the contents of the registers that were passed to it by the 16 bit app, and
;then tell NTVDM the register contents we want passed back to the 16 bit app.
;We do this through calls to "NTVDM.EXE" for functions of the style "getBX" and
;"setBX".  Each of these return or take (respectively) a 32 bit value, the lower
;16 bits of which are the register contents.  There is a seperate call for each
;of the CPU registers (eg getAX,getBX,getCX,getDX,getDI,getSI,getDS etc)
;You will need to include or declare function definitions in your DLL code.  The
;original source for these functions (if you cannot type them in) is NTVDM.LIB
;There are also functions for 8 bit and 32 bit registers, and much more besides.
;Credit is due to Japheth: - for help and advice on the VDD calls

I've made one or two minor changes.

1. Added dispatch calls for drawing horizontal and vertical lines and placed the code in the 32-bit part to avoid the overhead of the NTVDM dispatch mechanism.
2. Ditto for drawing arcs and angled lines by placing the Bresenham's line and circle algorithms in the 32-bit code.
3. Added a shadow memory to speed up pixel reads.  This makes a big difference when using blocks that use the XOR function to draw the block area.