diff --git a/README.md b/README.md index b4bc405..9281069 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ MS-DOS logo -# MS-DOS v1.25 and v2.0 Source Code +# MS-DOS v1.25, v2.0, v4.0 Source Code -This repo contains the original source-code and compiled binaries for MS-DOS v1.25 and MS-DOS v2.0. +This repo contains the original source-code and compiled binaries for MS-DOS v1.25 and MS-DOS v2.0, plus the source-code for MS-DOS v4.00 jointly developed by IBM and +Microsoft. -These are the same files [originally shared at the Computer History Museum on March 25th, 2014]( http://www.computerhistory.org/atchm/microsoft-ms-dos-early-source-code/) and are being (re)published in this repo to make them easier to find, reference-to in external writing and works, and to allow exploration and experimentation for those interested in early PC Operating Systems. +The MS-DOS v1.25 and v2.0 files [were originally shared at the Computer History Museum on March 25th, 2014]( http://www.computerhistory.org/atchm/microsoft-ms-dos-early-source-code/) and are being (re)published in this repo to make them easier to find, reference-to in external writing and works, and to allow exploration and experimentation for those interested in early PC Operating Systems. # License diff --git a/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf b/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf new file mode 100644 index 0000000..e56cb3d Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf b/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf new file mode 100644 index 0000000..6df8d3d Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf b/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf new file mode 100644 index 0000000..7054542 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf b/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf new file mode 100644 index 0000000..d40f2c5 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf b/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf new file mode 100644 index 0000000..abc1ee9 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf b/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf new file mode 100644 index 0000000..c9f9a07 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf b/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf new file mode 100644 index 0000000..ce6f077 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf b/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf new file mode 100644 index 0000000..8a632f3 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf b/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf new file mode 100644 index 0000000..5c02646 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf b/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf new file mode 100644 index 0000000..e09f284 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf b/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf new file mode 100644 index 0000000..80cbbdb Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf differ diff --git a/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf b/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf new file mode 100644 index 0000000..a19def0 Binary files /dev/null and b/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf differ diff --git a/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT b/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT new file mode 100644 index 0000000..7842e98 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT @@ -0,0 +1,5 @@ +date +time +prompt $p$g +path a:\bin;a:\ + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE b/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE new file mode 100644 index 0000000..0bf52f1 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE b/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE new file mode 100644 index 0000000..1414161 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE b/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE new file mode 100644 index 0000000..3a6dded Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE b/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE new file mode 100644 index 0000000..148ce1c Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT new file mode 100644 index 0000000..c4f8563 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT @@ -0,0 +1,3 @@ +cd bin +pound 290 a:bbset.exe a:sm.exe + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT new file mode 100644 index 0000000..49fe3d6 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT @@ -0,0 +1,4 @@ +c: +cd \bin +pound 800 bbset.exe sm.exe + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT new file mode 100644 index 0000000..eb99c7b --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT @@ -0,0 +1,7 @@ +c: +cd \bin +cd a:\bin +detach pound 800 bbset.exe sm.exe +detach pound 290 a:bbset.exe a:sm.exe +basica a:prime + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE b/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE new file mode 100644 index 0000000..dc75d46 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE b/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE new file mode 100644 index 0000000..3cf823b Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE b/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE new file mode 100644 index 0000000..ef240b6 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE b/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE new file mode 100644 index 0000000..1ed27f1 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS b/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS new file mode 100644 index 0000000..a088c0c Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE b/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE new file mode 100644 index 0000000..fdeaa14 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/SM.EXE b/v4.0-ozzie/bin/DISK1/BIN/SM.EXE new file mode 100644 index 0000000..15da78c Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/SM.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE b/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE new file mode 100644 index 0000000..edcc27f Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE differ diff --git a/v4.0-ozzie/bin/DISK1/COMMAND.COM b/v4.0-ozzie/bin/DISK1/COMMAND.COM new file mode 100644 index 0000000..3546cbd Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/COMMAND.COM differ diff --git a/v4.0-ozzie/bin/DISK1/COMMANDS.DOC b/v4.0-ozzie/bin/DISK1/COMMANDS.DOC new file mode 100644 index 0000000..0fcfed7 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/COMMANDS.DOC @@ -0,0 +1,199 @@ + + + + + + + Multi-Tasking MS-DOS + Beta Test Release 1.00 + + Command Guide + + + ARENA.EXE - Prints out arena assignments + + arena + + The system's memory arena is printed out. The + number listed under the owner field is the PID of + the process which owns the memory. + + + BBSET.EXE - Set and report on behavior bits + + bbset [-o] [ {+|-}bitname ... ] fname ... + + BBSET sets or clears behavior bits in an .EXE file + header. Multi-Tasking MS-DOS uses the behavior + bits to determine the level of special + compatibility support needed to run the + application. + + BBSET will set (if +bitname) or clear (if - + bitname) the named behavior bit(s) from the + specified files. If the -o switch is specified, + BBSET writes a report on the current setting of + all the defined behavior bits to stdout after + making the requested changes. + + For a list of behavior bits that BBSET knows + about, type BBSET without any arguments. + + + COUNTDOW.EXE - Count down a CPU loop + + countdown number + + Its argument is a number; it counts the number + down to 0, at about a 1hz rate. It prints out + the countdown. Another CPU loop program like + TEXT, but this one terminates when the count + reaches 0 + + + DETACH.EXE - Detaches a child process + + detach command [argument ...] + + The command given is run as a background process. + Detach prints out the Command Subgroup ID (CSID) + which may be used as an argument to KILL to + terminate the process. + + + + + + + + + + Multi-Tasking MS-DOS Command Guide - Page: 2 + + HE_DAEM.EXE - Hard error catcher + + detach he_daem + + Intercepts hard errors, reports them and requests + user action. This should always be run in the + background for now. Put the above command line in + your AUTOEXEC.BAT file if you're not going to use + the Session Manager (SM). + + + KILL.EXE - send a signal to a process + + kill [-nn] [sig=nn] [disp=mm] pid ... + + Sends signal nn with disposition mm to processes + mentioned in pid. Defaults to SIGTERM and process + tree disposition. + + + POUND.EXE - Exercise disk I/O system + + pound [t]count filea fileb + + Pound reads sequencially through filea and fileb, + reading 512 bytes at a time alternating between + the files on each read. When the end of file is + read the following read for that file begins at + the beginning of the file. If a count is + specified without the preceeding "t" then pound + reads 512 bytes, count number of times from each + file before the program terminates. If "t" + preceeds the count value then the files are read + for count number of seconds before the program + terminates. + + + SLEEP.EXE - Sleep for a while + + sleep sec[.millisec] + + Sleep will execute a sleep system call for the + number of seconds and milliseconds specified. + This might be useful in batch files to pause for + an interval as opposed to waiting for a user + response. + + + SM.EXE - Session manager + + sm + + Manages multiple processes running on different + screens. Uses initialization file SM.INI. This + + + + + + + + + + + Multi-Tasking MS-DOS Command Guide - Page: 3 + + program includes the hard error catcher, so don't + run HE_DAEM if you're going to use this. See the + file SM.DOC for more information. + + + TEXT.EXE - Loop and print text + + text argument + + CPU loops and prints its argument every 2 CPU + seconds or so + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/CONFIG.SYS b/v4.0-ozzie/bin/DISK1/CONFIG.SYS new file mode 100644 index 0000000..3d6d514 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/CONFIG.SYS @@ -0,0 +1,3 @@ +buffers = 40 +files = 20 +break=on diff --git a/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM b/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM new file mode 100644 index 0000000..b4e3af1 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM differ diff --git a/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM b/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM new file mode 100644 index 0000000..306fc49 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM differ diff --git a/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM b/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM new file mode 100644 index 0000000..d26e982 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM differ diff --git a/v4.0-ozzie/bin/DISK1/IBMBIO.COM b/v4.0-ozzie/bin/DISK1/IBMBIO.COM new file mode 100644 index 0000000..280a2ef Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/IBMBIO.COM differ diff --git a/v4.0-ozzie/bin/DISK1/IBMDOS.COM b/v4.0-ozzie/bin/DISK1/IBMDOS.COM new file mode 100644 index 0000000..a859665 Binary files /dev/null and b/v4.0-ozzie/bin/DISK1/IBMDOS.COM differ diff --git a/v4.0-ozzie/bin/DISK1/README b/v4.0-ozzie/bin/DISK1/README new file mode 100644 index 0000000..4163d4f --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/README @@ -0,0 +1,67 @@ + + + + + + + Multi-Taking MS-DOS + Beta Test Release 1.00 + + Release Notes + + + Enclosed you will find Microsoft's first beta release + of Multi-tasking MS-DOS. This version is based upon MS-DOS + Version 2 sources, we will be reimplementing the multi- + tasking enhancements on top of Version 3 sources shortly. + + Although we have distributed a bootable disk for the + IBM PC, this package can be adapted to any MS-DOS machine. + Those manufacturers who are designing IBM compatible ROMs, + would be wise to keep multi-tasking in mind. Specifically, + this IBM PC implementation has had to hook out the entire + disk (both floppy and hard disk) ROM code because after he + IBM code set's up the DMA transfer it simply loops in ROM + waiting for the interrupt to occur (routine WAIT_INT). + + Problems you may wish to avoid within future ROMs are: + 1) loading ES with the physical video RAM location + (label M3) + 2) Looping in ROM on Cntrl-NumLock (label K40) + 3) No way to add special detecting special key + strokes which a jump out into RAM after reading + the keystroke at KB_INT would avoid + 4) Not being able to hook the loading of DS to point + to DATA (EQU 40H) in numerous routines. + Other than these deficiencies the ROM code developed should + be very usable. + + By implementing the above suggestions, the size of your + BIOS can be reduced since it will not be necessary to + duplicate functionality in RAM. + + More detailed specifications of the device driver + formats will be forth coming. For the time being you will + have to make use of the sample source code for the IBM PC. + If you have further questions please contact Microsoft OEM + customer support through Technical Assist Requests (TAR). + + + * * * WARNING * * * WARNING * * * WARNING * * * + + Each copy of this software distribution has been + individually serialized to facilitate tracing of + unauthorized duplication. + + * * * WARNING * * * WARNING * * * WARNING * * * + + + + + + + + + + + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/SM.DOC b/v4.0-ozzie/bin/DISK1/SM.DOC new file mode 100644 index 0000000..ebbe220 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/SM.DOC @@ -0,0 +1,199 @@ + + + + + + + Multi-Tasking MS-DOS + Beta Test Release 1.00 + + Session Manager + User's Guide + + + Introduction + + The Session Manager(SM) for Multi-Tasking MS-DOS + allows you to run up to six programs at one time and switch + between them with a couple of keystrokes. Each program's + screen is preserved so that it can be restored when you + switch back to it. SM also contains the system-wide, Int24 + Handler. + + + Initialization + + The first thing SM does when it is started is look for + any program initialization information you may have. SM + looks for the initialization information in a file named + SM.INI in the current directory. Although recommended, no + initialization information is needed. + + There are two types of initialization lines: + 1) define [program args] + + 2) start + + "program key" - a printable ascii character, a control + character (^A thru ^^), or a function key (F1 + - F10). + "working directory" - a well formed path; i.e., begins + with drive letter (d:\). + + Each define line will associate a key with a program. + If there is more than one define line using the same key, + only the information in the last one is used. + + A start line is optional. If one exists, the program + associated with the key on the start line is run as soon as + SM finishes initializing. If more than one start line is + given, the last one is used. + + This is what a sample initialization file might look like: + + define f1 a:\command.com c:\bin\src + define ^z z.exe foo.c a:\foo\bar + start f1 + + + Running the Session Manager + + To run Session Manager, just type SM. It does not + require any arguments. If there was a start line in the + + + + + + + + + Session Manager User's Guide - Page: 2 + + initialization file, the program associated with the start + key will be run. Otherwise, the SM screen will be displayed + and you will be prompted for input. + + The SM screen contains a chart that describes each + defined program's key, status, arguments, and working + directory. There are 3 types of program status: + + 1) New - the program has never been run. + 2) Active - the program has been started. + 3) Dead - the program has terminated. + + The input choices at this point are to either type a + program key or hit the button to enter command mode. + If you hit a program key, the screen associated with that + program will be displayed and the program will + start/continue executing. If this is the first time the + program has been run, a chdir to the program's working + directory is made before it is started. If SM cannot start + the program you desired, the SM screen will reappear. + + If the program you chose to run has died, its screen + will still be displayed so that you can check its output. + That is all you can do while in a dead programs screen + except switch back to SM. + + To switch back to SM, hit Alt-F10. Alt-F10 is + currently the program key for SM and will be recognized no + matter what other programs are running. This is the only + program key that works this way. All of the others will + only be recognized if SM is running and the SM screen is + being displayed. + + Whenever any of SM's children die, their status is + changed to dead. You will see the status change the next + time the SM screen is displayed. If the program using the + current screen dies, you will go back into SM. + + + Command Mode + + When you enter SM's command mode the prompt "SM command or + HELP>" is displayed. The valid SM commands are: + + 1) INIT + Initialize the program associated with key so that + it can be run again. The program's status is + changed to "New" and its screen memory is freed. + If the program is active, it is killed before it + is initialized. + + 2) DEFINE [program args] + + Define and run a new program using the supplied + information. If the key was previously defined, + redefine it. + + + + + + + + + Session Manager User's Guide - Page: 3 + + 3) RUN + Run the program associated with key. + + 4) RESTART + Restart the program associated with key. This + like issuing an INIT and a RUN command. + + 5) KILL + Kill the program associated with key. Its status + is changed to dead. + + 6) HELP + Display a help screen. + + 7) EXIT + Kill all of SM's children and exit SM. + + In all of the above commands, "key" is the printable + ascii representation of a programs key. If a command fails, + you will either be asked to enter a new command or placed in + SM's top level. + + + Session Manager's Int24 Handler + + Whenever an Int24 occurs, SM's Int24 handler is called. + No matter what program is using the screen and no matter + which program caused the error, SM's Int24 screen is always + displayed. This screen will contain information on the type + of Int24 that happened, and the name and pid of the program + that caused the error. You will then be prompted for one of + the valid actions for this type of error. After the action + typed in has been taken, you are returned to the screen you + were using before the Int24. + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v4.0-ozzie/bin/DISK1/SM.INI b/v4.0-ozzie/bin/DISK1/SM.INI new file mode 100644 index 0000000..bf7dfc8 --- /dev/null +++ b/v4.0-ozzie/bin/DISK1/SM.INI @@ -0,0 +1,2 @@ +define F7 a:\command.com a:\ +define F8 a:\command.com c:\ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC b/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC new file mode 100644 index 0000000..37e661b --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC @@ -0,0 +1,573 @@ +; Termcap description of capabilities: + +;ibmans4:mtcon:IBM PC with V4.0 ANSI driver:\ +; :al=\E[L:am:bs:ce=\E[K:cl=\E[2J\E[H:cm=\E[%;%H:co#80:\ +; :dl=\E[M:do=\E[B:ho=\E[H:li#24:mi:nd=\E[C:\ +; :ms:pt:se=\E[m:so=\E[1;36m:up=\E[A:\ +; :kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:kh=\E[H:kn#8:\ +; :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\ +; :k6=\EP:k7=\EQ:k8=\ER: + +CMDTABL DB 'A' + DW CUU ;CUrsor Up + DB 'B' + DW CUD ;CUrsor Down + DB 'C' + DW CUF ;CUrsor Forward + DB 'D' + DW CUB ;CUrsor Back + DB 'H' + DW CUP ;CUrsor Position + DB 'J' + DW ED ;Erase in Display + DB 'K' + DW EL ;Erase in Line + DB 'L' + DW IL ;Insert Line + DB 'M' + DW xDL ;Delete Line +;; DB 'R' +;; DW CPR ;Cursor Postion Report + DB 'f' + DW HVP ;Horizontal and Vertical Position + DB 'h' + DW SM ;Set Mode + DB 'l' + DW RM ;Reset Mode + DB 'm' + DW SGR ;Select Graphics Rendition +;; DB 'n' +;; DW DSR ;Device Status Report + DB 's' + DW SCP ;Save Cursor Position + DB 'u' + DW RCP ;Restore Cursor Position + DB 00 + +; Graphic Rendition modes: parameter, mask, set +GRMODE DB 00,00000000B,00000111B ; all off + DB 01,11111111B,00001000B ; bold (increased intensity) + DB 04,11111000B,00000001B ; underscore + DB 05,11111111B,10000000B ; blink + DB 07,11111000B,01110000B ; reverse video + DB 08,10001000B,00000000B ; concealed + DB 30,11111000B,00000000B ; foreground colors ... + DB 31,11111000B,00000100B + DB 32,11111000B,00000010B + DB 33,11111000B,00000110B + DB 34,11111000B,00000001B + DB 35,11111000B,00000101B + DB 36,11111000B,00000011B + DB 37,11111000B,00000111B + DB 40,10001111B,00000000B ; background colors ... + DB 41,10001111B,01000000B + DB 42,10001111B,00100000B + DB 43,10001111B,01100000B + DB 44,10001111B,00010000B + DB 45,10001111B,01010000B + DB 46,10001111B,00110000B + DB 47,10001111B,01110000B + DB 0FFH + +; Set/Reset Modes: indexed by (SelChar-'<'*8) + (PARAM0 AND 7) +SRMODE DW 0,0,0,0,0,0,0,0 ; SelChar '<' + DW 1,1,1,1,1,1,1,WRAP ; SelChar '=' + DW 0,EnaL25,0,0,0,0,0,0 ; SelChar '>' + DW 0,0,0,0,0,0,0,WRAP ; SelChar '?' + +PAGE +; The following are duplicates of the same variables from the ROM +; +;* WARNING - the following two variables are accessed as a word +MODE DB 3 +MAXCOL DB 79 +IF LINE25 ; special treatment of line 25? +maxrow equ 24 +ELSE +maxrow equ 25 +ENDIF +;* WARNING - the following two variables are accessed as a word +COL DB 0 ; current column +ROW DB 0 ; current row + + +AnsiState LABEL BYTE ; the following must be saved on a screen swap +WRAP DB 1 ; 0 = NO WRAP, 1 = WRAP +EnaL25 DB 0 ; 0 = 25th line disabled, 1 = enabled +STATE DW S1 +SAVCR DW 0 ; saved cursor position +;* WARNING - the following two variables are accessed as a word +SelChar DB 0 ; <,=,> or ? private use indicators +PRMCNT LABEL BYTE ; number of parameters for command +PRMCNTW DW 0 +NUMPARAM equ 5 ; max. number of parameters +PARAM DB NUMPARAM DUP (?) ; buffer for command parameters +;* WARNING - the following two variables are accessed as a word +attrw LABEL WORD +ATTR DB 00000111B ;CHARACTER ATTRIBUTE +BPAGE DB 0 ;BASE PAGE + +AnsiSize equ ($-AnsiState) + +IF (AnsiSize GT TermSize) + .RADIX 0 ; ERROR - Terminal state not big enough +ENDIF + +;------------------------------------------------------------- +; +; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE +; +base dw 0b800h +screen_seg dw 00000h + +chrout: cmp al,13 ; carriage return? + ja outchr + jnz trylf + mov [col],0 +;; jmp short setit + jmp setit + +trylf: cmp al,10 ; line feed? + jz lf + cmp al,7 ; bell? + jnz trytab +torom: + mov bx,[attrw] + and bl,7 + mov ah,14 + int 10h +ret5: ret + +trytab: + cmp al,9 ; tab? + jnz tryback + mov al,[col] + add al,8 + mov ah,al + and ah,7 + sub al,ah + cmp al,[maxcol] + jb tunder + mov al,[maxcol] +tunder: + mov [col],al + jmp short setit + +tryback: + cmp al,8 ; backspace? + jnz outchr + cmp [col],0 + jz ret5 + dec [col] + jmp short setit + +outchr: + mov bx,[attrw] + mov cx,1 + mov ah,9 + int 10h + inc [col] + mov al,[col] + cmp al,[maxcol] + jbe setit + cmp [wrap],1 + jz outchr1 + dec [col] + ret +outchr1: + mov [col],0 +lf: cmp [row],(maxrow-1) + ja setit ; on line 25, don't move + jz lf1 ; on 24th line, scroll + inc [row] + jmp short setit +lf1: call scroll + +setit: mov dx,word ptr col + mov bh,[bpage] + mov ah,2 + int 10h + ret + +scroll: mov al,mode + cmp al,2 + jz myscroll + cmp al,3 + jz myscroll +IF LINE25 + xor cx,cx ; from 0,0 + mov dh,(maxrow-1) ; to maxrow-1,maxcol + mov dl,maxcol + mov bh,attr + mov ax,0601h ; scroll up one line + int 10h + ret +ELSE + mov al,10 + jmp torom +ENDIF +myscroll: + mov bh,[attr] + mov bl,' ' + mov bp,80 + mov ax,[base] + add ax,[screen_seg] + mov es,ax + mov ds,ax + xor di,di + mov si,160 + mov cx,(maxrow-1)*80 + cld + +; This code will never get executed since we get here when +; mode = 2 or 3 only. +;; cmp cs:[base],0b800h +;; jz colorcard + +;; rep movsw +;; mov ax,bx +;; mov cx,bp +;; rep stosw +;; jmp short sret + +;;colorcard: + mov dx,3dah +wait2: in al,dx + test al,8 + jz wait2 + mov al,25h + mov dx,3d8h + out dx,al ;turn off video + rep movsw + mov ax,bx + mov cx,bp + rep stosw + mov al,29h + mov dx,3d8h + out dx,al ;turn on video +sret: push cs + pop ds + ret + + +CharOut: PUSH AX ; Main entry point + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES + PUSH BP + + MOV [base],0B800H + XCHG AX,SI ; SAVE CHARACTER TO STUFF + MOV AX,40H ; POINT TO ROS BIOS + MOV DS,AX + MOV AX,DS:[49H] ; AL=MODE, AH=MAX COL + DEC AH ; ANSI NEEDS 0-79 OR 0-39 + MOV WORD PTR CS:[MODE],AX ; SAVE MODE AND MAX COL + CMP AL,7 + JNZ NOT_BW + MOV WORD PTR CS:[base],0B000H +NOT_BW: MOV AL,DS:[62H] ; GET ACTIVE PAGE + MOV CS:[BPAGE],AL + CBW + ADD AX,AX + MOV BX,AX + MOV AX,DS:[BX+50H] ; AL=COL, AH=ROW + MOV WORD PTR CS:[COL],AX ; SAVE ROW AND COLUMN + MOV AX,DS:[4EH] ; GET START OF SCREEN SEG + MOV CL,4 + SHR AX,CL ; CONVERT TO A SEGMENT + PUSH CS + POP DS + MOV [screen_seg],AX + XCHG AX,SI ; GET BACK CHARACTER IN AL + + CALL VIDEO + POP BP + POP ES + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + RET + + +;---------------------------------------------------------- +; +; OUTPUT SINGLE CHAR IN AL TO VIDEO DEVICE +; +VIDEO: MOV SI,OFFSET STATE + JMP [SI] + +S2: CMP AL,'[' + JZ S22 + JMP S1 +S22: MOV WORD PTR [SI],OFFSET S30 + XOR BX,BX + MOV WORD PTR SelChar,BX + MOV WORD PTR PARAM,BX + JMP SHORT S3B + +S30: CMP AL,'?' ; experimental use selector (SM/RM)? + JA S7 + mov SelChar,al + MOV WORD PTR [SI],OFFSET S3 + cmp al,'<' + jae S3B + +S3: CMP AL,';' + JNZ S3C +S3A: INC PRMCNT +S3B: CALL GETPTR + XOR AX,AX + MOV WORD PTR [BX],AX ;DEFAULT VALUE IS ZERO + RET + +S3C: CMP AL,'0' + JB S3D + CMP AL,'9' + JA S7 + CALL GETPTR + SUB AL,'0' + XCHG AL,BYTE PTR [BX] + MOV AH,10 + MUL AH ;*10 + ADD BYTE PTR [BX],AL ;MOVE IN DIGIT + RET + +S3D: +;; CMP AL,'"' ;BEGIN QUOTED STRING +;; JZ S3E +;; CMP AL,"'" + JNZ S7 +;;S3E: MOV WORD PTR [SI],OFFSET S4 +;; MOV [INQ],AL +S3RET: RET + +; +; ENTER QUOTED STRINGS +; + +;;S4: CMP AL,[INQ] ;CHECK FOR STRING TERMINATOR +;; JNZ S4A +;; DEC PRMCNT ;TERMINATE STRING +;; MOV WORD PTR [SI],OFFSET S3 +;; RET + +;;S4A: CALL GETPTR +;; MOV BYTE PTR [BX],AL +;; MOV WORD PTR [SI],OFFSET S4 +;; JMP S3A +; +; LOOK FOR ANSI COMMAND SPECIFIED IN AL +; + +S7: MOV BX,OFFSET CMDTABL-3 +; +S7A: ADD BX,3 + CMP BYTE PTR [BX],0 + JZ S1B + CMP BYTE PTR [BX],AL + JNZ S7A +; +S7B: MOV AX,WORD PTR [BX+1] ;AX = JUMP ADDRESS + MOV BX,OFFSET PARAM + MOV DL,BYTE PTR [BX] + XOR DH,DH ;DX = FIRST PARAMETER + MOV CX,DX + OR CX,CX + JNZ S7C + INC CX ; if DX=0, CX=1 else CX = DX +S7C: JMP AX ;AL = COMMAND + +S1: CMP AL,1Bh ;ESCAPE SEQUENCE? + JNZ S1B + MOV WORD PTR [SI],OFFSET S2 + RET + +S1B: CALL CHROUT +S1A: MOV WORD PTR [STATE],OFFSET S1 + RET + +MOVCUR: CMP BYTE PTR [BX],AH + JZ SETCUR + ADD BYTE PTR [BX],AL + LOOP MOVCUR +SETCUR: MOV DX,WORD PTR COL + XOR BX,BX + MOV AH,2 + int 10h ; call ROM + JMP S1A + +HVP: +CUP: +IF LINE25 + CMP CL,(maxrow+1) + jb cup3 ; new row is 24 or less + JA SETCUR ; error - 26 or greater + cmp EnaL25,0 ; else 25, is it allowed? + jz SETCUR +cup3: +ELSE + CMP CL,maxrow + JA SETCUR +ENDIF + MOV AL,MAXCOL + MOV CH,BYTE PTR [BX+1] + OR CH,CH + JZ CUP1 + DEC CH +CUP1: CMP AL,CH + JA CUP2 + MOV CH,AL +CUP2: XCHG CL,CH + DEC CH + MOV WORD PTR COL,CX + JMP SETCUR + +CUF: MOV AH,MAXCOL + MOV AL,1 +CUF1: MOV BX,OFFSET COL + JMP MOVCUR + +CUB: MOV AX,00FFH + JMP CUF1 + +CUU: MOV AX,00FFH +CUU1: MOV BX,OFFSET ROW + JMP MOVCUR + +CUD: MOV AX,(maxrow-1)*256+1 +IF LINE25 + cmp ah,[row] ; at bottom of screen? + ja SETCUR +ENDIF + JMP CUU1 + +SCP: MOV AX,WORD PTR COL + MOV SAVCR,AX + JMP SETCUR + +RCP: MOV AX,SAVCR +IF LINE25 + cmp ch,maxrow + jb rcp1 + cmp EnaL25,0 + jz rcp2 +ENDIF +rcp1: MOV WORD PTR COL,AX +rcp2: JMP SETCUR + +SGR: XOR CX,CX + XCHG CL,PRMCNT + CALL GETPTR + INC CX +SGR1: MOV AL,BYTE PTR [BX] + PUSH BX + MOV BX,OFFSET GRMODE +SGR2: MOV AH,BYTE PTR [BX] + ADD BX,3 + CMP AH,0FFH + JZ SGR3 + CMP AH,AL + JNZ SGR2 + MOV AX,WORD PTR [BX-2] + AND ATTR,AL + OR ATTR,AH +SGR3: POP BX + INC BX + LOOP SGR1 + JMP SETCUR + +ED: +IF LINE25 + cmp row,maxrow ; on 25th line? + je EL ; yes, treat like Erase in Line +ENDIF + xor cx,cx + mov dl,maxcol + mov dh,(maxrow-1) + cmp param,1 ; which subcommand? + ja el2 ; all + jb ed1 + mov dh,row ; to beginning + dec dh + jle EL + jmp short ed2 +ed1: mov ch,row ; to end + inc ch + cmp ch,dh + jae EL +ed2: mov bh,attr + MOV AX,0600H + int 10h ; call ROM + +EL: MOV CX,WORD PTR COL + MOV dx,cx + mov al,param + inc al ; 0,1,2 => 1,2,3 + test al,1 ; to end? + je el1 + mov dl,maxcol +el1: test al,2 ; to beginning? + je el2 + mov cl,0 +el2: mov bh,attr + mov ax,0600H + int 10h +S1A_j: jmp S1A + +IL: mov ah,7 ; scroll down + jmp short dl1 + +xDL: mov ah,6 ; scroll up +dl1: mov al,cl ; number of lines + mov ch,row + xor cl,cl + mov dh,(maxrow-1) + mov dl,maxcol + mov bh,attr + int 10h + jmp S1A_j + +RM: XOR CL,CL + JMP SHORT SM1 + +SM: MOV CL,1 +SM1: mov bl,SelChar ; get selection character + sub bl,'<' ; adjust + jb S1A_j ; less than '<' + cmp bl,4 + jae S1A_j ; greater than '?' + xor bh,bh + shl bx,1 + shl bx,1 + shl bx,1 + MOV AL,DL + CMP AL,7 + JA S1A_j + or bl,al + shl bx,1 + mov bx,SRMODE[bx] ; get function indicator + cmp bx,1 ; no or special function? + jb S1A_j + jz SM2 ; sets screen mode + MOV [bx],CL + JMP S1A_j + +SM2: MOV AH,0 + int 10h ; call ROM + JMP S1A_j + +; GetPtr - get a pointer to the current parameter +GETPTR: MOV BX,PRMCNTW + CMP BX,NUMPARAM + JB GET1 + DEC PRMCNT + JMP GETPTR +GET1: ADD BX,OFFSET PARAM + RET diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK b/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK new file mode 100644 index 0000000..e69d153 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK @@ -0,0 +1,20 @@ +ibmbio.obj: ibmbio.asm defdbug.inc bugcode.inc + masm ibmbio; + +ibmmtcon.obj: ibmmtcon.asm ansi.inc defdbug.inc + masm ibmmtcon; + +ibmdsk.obj: ibmdsk.asm defdbug.inc + masm ibmdsk; + +sysini.obj: sysini.asm dossym.inc devsym.inc syscalls.inc + masm sysini; + +sysimes.obj: sysimes.asm + masm sysimes; + +ibmbio.exe: ibmbio.obj ibmmtcon.obj ibmdsk.obj sysini.obj sysimes.obj + link ibmbio ibmmtcon ibmdsk sysini sysimes,ibmbio,ibmbio/map; + +ibmbio.com: ibmbio.exe + exe2bin ibmbio ibmbio.com diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE b/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE new file mode 100644 index 0000000..378331e Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE differ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC new file mode 100644 index 0000000..4a87725 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC @@ -0,0 +1,553 @@ +;*** Bugcode.inc - Debug code for including into sysini.asm and ibmbio.asm +; +; Can't link in via buglib due to memory and relocation games played +; by these modules. Each gets a private, local-only copy of these +; modules. + + +IFDEF DEBUGFLG + + +;** DPRINTF _ Debug Printf +; +; Dprintf is a kernel debug print formatting package. It is intended +; to produce conviently formatted output. +; +; Dprintf is called, indirectly, by a macro: +; +; DEBUG n,m,"string", +; +; string = format string +; a1 = first argument +; an = last argument +; +; The format string is an ASCIZ string which can contain 2 types of +; specifications: data-format specifications and literal characters. +; Data format specifications always begin with a '$' character; all +; characters not part of a data format specification are treated as +; literal characters. +; +; Literal characters +; - any character not part of a format specification. Special +; non-printing characters are: +; \n - CRLF +; \t - tab +; \b - bell +; \\ - \ +; \$ - $ +; +; Format Specifications +; +; A format specification takes the form: +; $ [@] +; +; where = +; +; x - print argument as a hex word +; d - print argument as decimal word +; c - print argument as ascii character +; b - print argument as hex byte +; For each of the above formats, the supplied argument +; is a 16-bit word - the value to be printed. The optional @ +; (described below) allows a segmented address to be supplied, +; instead. +; +; s[nn] - print argument as asciz string; if optional decimal +; argument follows the format character this specifys +; a maximum string length. Non printing characters are +; printed in the form \nnn where "nnn" is the octal byte +; value. +; Note that this format character cannot be directly +; followed by a digit unless that digit is to be taken +; as the start of a length argument. +; +; Bnn - print argument as hex bytes. The required following +; decimal argument is the number of bytes to print. +; +; Both of these formats take a long address as their argument. +; The '@' character is thus invalid for these formats. +; +; WARNINGS +; As befitting a debug routine, DPRINTF does not have a whole lot +; of "failsafe" code in it. Supplying screwed up formats can +; muck things up. Specifically: +; The @ argument must NOT be specified with the 's' or 'B' +; format +; A string/byte-length argument of 0 is taken as 65536 +; The string "%% BAD FMT %%" appears in the output when +; 1) an illegal format specifier is given, or +; 2) the B format is given a 0 or missing length +; +; ENTRY (sp+n ) = address of format string (offset from return cs value) +; (sp+n-2) = first argument word +; (sp+n-4) = second argument word +; . +; (sp+4 ) = last argument word +; (sp+2 ) = seg of return address +; (sp ) = offset of return address +; (bp) = offset of format string on the stack +; EXIT none +; USES flags + + PUBLIC DPRINTF +DPRINTF PROC near + + push ds + push es + push bp + push di + push si + push dx + push cx + push bx + push ax ; save registers + cld + + mov si,[bp] ; get address of format string + sub bp,2 + mov bx,sp + mov ds,ss:20[bx] ; (ds:si) = address of format string + push cs + pop ds + +; Scan format string for next character +; +; (ds:si) = address of format string +; (ss:bp) = address of next argument + +dpf1: lodsb ; (al) = format string byte + and al,al + je dpf3 ; all done + cmp al,'$' + je dpf4 ; is data escape + cmp al,'\' + jnz dpf2 ; got the character + +; it's an "\" escape code - crack the argument character + + lodsb + and al,al + je dpf3 ; all done, ignore hanging \ + xchg ah,al + mov al,0Ch + cmp ah,'n' + jne dpf1$5 ; not \n + mov al,0dH + call putchar + mov al,0aH + jmp SHORT dpf2 ; print LF + +dpf1$5: cmp ah,'t' + mov al,9 + je dpf2 ; is \t + cmp ah,'b' + mov al,7 + je dpf2 ; is \b + xchg ah,al +dpf2: call putchar + jmp dpf1 + +; have the end of the format string - exit + +dpf3: pop ax + pop bx + pop cx + pop dx + pop si + pop di + pop bp + pop es + pop ds + ret + + +;* Have a '$' character - is data format escape +; +; Get address of data into es:di +; +; (bp) = address of data value + +dpf4: mov di,bp + push ss + pop es ; (es:di) = address of data value + sub bp,2 ; point to next argument + lodsb ; (al) = format specifier + cmp al,'@' + jne dpf5 ; not an indirect flag + les di,[bp] + sub bp,2 ; have an extra 2 for @ + lodsb +dpf5: cmp al,'x' + jne dpfd1 ; not 'x' + +; is 'x' format - print hex word + + mov ax,es:[di] + call THW ; type hex word + jmp dpf1 + +dpfd1: cmp al,'d' + jnz dpfc1 ; not 'd' + +; is 'd' format - print decimal word + + mov ax,es:[di] + call TDW ; type decimal word + jmp dpf1 + +dpfc1: cmp al,'c' + jne dpfb1 + +; is 'c' format - print character + + mov al,es:[di] + call putchar + jmp dpf1 + +dpfb1: cmp al,'b' + jne dpfs1 + +; is 'b' format - print hex byte + + mov al,es:[di] + call THB ; type hex byte + jmp dpf1 + +dpfs1: cmp al,'s' + jne dpfbb1 + +; is 's' format - print ASCIZ string. First, check for +; optional decimal limit + + public SSB +SSB: sub cx,cx ; set 65536 limit + les di,[bp] ; (es:DI) = fwa of string + sub bp,2 ; argument to 's' was two words + mov al,[si] + cmp al,'0' + jb dpfs2 ; not decimal + cmp al,'9' + ja dpfs2 ; not decimal + call atod ; (ax) = decimal value, (ds:si) updated + xchg cx,ax + +; print asciz string at es:di, max of (cx) characters +; (cx) = 0 means max of 65536 +; +; Other sections of code in dpf jump here to print strings + +dpfs2: mov al,es:[di] + inc di + and al,al + je dpfs3 + call putchar + loop dpfs2 ; continue if not at limit +dpfs3: jmp dpf1 + +dpfbb1: cmp al,'B' + je dpfbb2 ; is 'B' format + +; error in format code - print message + +dpferr: push cs + pop es + mov di,OFFSET dpfa ; (es:di) = error message + sub cx,cx + jmp dpfs2 + +dpfa: DB '%% BAD FMT %%',0 + +; have B format + +dpfbb2: call atod ; (ax) = length specifier + jc dpferr ; number not there - error + xchg cx,ax + jcxz dpferr ; number is 0 - error + les di,[bp] ; (es:DI) = fwa of string + sub bp,2 ; argument to 's' was two words +dpfbb3: mov al,es:[di] + call THB ; type hex byte + mov al,' ' + call putchar ; space em out + inc di + loop dpfbb3 ; do em all + jmp dpf1 + +DPRINTF ENDP + + +;** THB - Type Hex Byte +; +; THB types a hex byte (via "putchar") +; +; ENTRY (AL) = byte +; EXIT none +; USES ax, flags + +THBA DB '0123456789abcdef' + + PUBLIC THB +THB PROC near + + push ax + shr al,1 + shr al,1 + shr al,1 + shr al,1 + and ax,0fH + xchg bx,ax + mov bl,CS:THBA[bx] + xchg ax,bx + call putchar ; put first character + pop ax + and ax,0fH + xchg bx,ax + mov bl,CS:THBA[bx] + xchg ax,bx + call putchar + ret + +THB ENDP + + + + +;** THW - Type Hex Word +; +; THW types a word in hex (via "putchar") +; +; ENTRY (AX) = word +; EXIT none +; USES AX, flags + + PUBLIC THW +THW PROC near + + push ax + xchg ah,al + call THB + pop ax + call THB + ret + +THW ENDP + + + +;** TDW - Type Decimal Word +; +; TDW types (via "putchar") the unsigned decimal representation +; of a 16-bit unsigned integer. Only significant digits are +; printed; if the number is 0 a "0" is printed. +; +; ENTRY (AX) = number +; EXIT none +; USES AX, flags + + PUBLIC TDW +TDW PROC near + + push cx ; preserve registers + push dx + mov cx,10 + call tdw$ ; recurse cracking digits + pop dx + pop cx + ret + +TDW ENDP + + +;* tdw$ - crack number recursively +; +; tdw$ cracks the least significant decimal digit. If there +; are no higher-significant digits, print and return. +; else, recurse for higher digits +; +; (AX) = value +; (CX) = 10 + +tdw$ PROC NEAR + + sub dx,dx + div cx ; (ax) = quotient, (dx) = remainder + and ax,ax + jz tdw$1 ; this is highest-order, do it + push dx + call tdw$ + pop dx +tdw$1: xchg ax,dx + add al,'0' + call putchar + ret + +TDW$ ENDP + + + +;** ATOD - Convert ASCII string to decimal number +; +; ATOD is called to convert an ascii string of digits to a +; decimal number. Digits are converted until we run out of them. +; +; ENTRY (DS:SI) = address of first digit +; EXIT 'C' clear if OK +; (AX) = value +; (SI) updated to first non-digit +; 'C' set if error - no digits, or result >65535 +; (DS:SI) points to error character +; USES AX, SI, FLAGS + + PUBLIC ATOD +ATOD PROC near + + push dx + push cx ; save registers + mov al,[si] + sub al,'0' + jc atod9 ; error - no digits + cmp al,10 + cmc + jc atod9 ; error - no digits + sub ax,ax ; clear accumulator + mov cx,10 ; base 10 + +; crack next digit +; +; (AX) = number accumulated so near +; (CX) = 10 +; (DS:SI) = next character + +atod1: xchg dx,ax ; keep accum in dx for a while + lodsb ; (al) = character + sub al,'0' + jc atod7 ; not digit - all done + cmp al,9 + ja atod7 ; not digit - all done + sub ah,ah ; (ax) = digit value (0 - 9) + push ax + xchg ax,dx + mul cx ; (ax) = 10*accum + pop dx ; (dx) = digit to add + jo atod8 ; overflow + add ax,dx + jmp atod1 ; go back for more + +; Done with number, all OK +; +; (dx) = number +; (ds:si) = address+1 of first unused character + +atod7: clc + +; Done with number, error +; 'C' set + +atod8: dec si ; backup over non-decimal (or error) char +atod9: pop cx + xchg ax,dx ; (ax) = number iff no error + pop dx ; restore registers + ret ; exit + +ATOD ENDP + +;** putchar - put a character on the console +; +; ENTRY (al) = character +; EXIT none +; USES ax,flags + + +UR_DAT = 02f8H ; COM1 = 03f8H, COM2 = 02f8H +UR_IEN = UR_DAT+1 ; Interrupt enable +UR_IER = UR_DAT+2 ; interrupt ID +UR_LCR = UR_DAT+3 ; line control registers +UR_MCR = UR_DAT+4 ; modem control register +UR_LSR = UR_DAT+5 ; line status register +UR_MSR = UR_DAT+6 ; modem status regiser +UR_DLL = UR_DAT ; divisor latch least sig +UR_DLM = UR_DAT+1 ; divisor latch most sig + +iflag DB 0 ; != 0 when initialized 8250 + +;* inchr - input character +; +; EXIT 'z' set if no character +; 'z' clear if char +; (al) = char + +inchr: mov dx,UR_LSR + in al,dx + and al,1 + jz inchr1 + mov dx,UR_DAT + in al,dx + and al,07fh +inchr1: ret + + + PUBLIC putchar +putchar PROC NEAR + pushf + cli + push dx + push cx + push bx + push ax ; (al) = character + test iflag,255 + jnz putc1 ; is initialized + inc iflag + +; program the usart + + mov dx,UR_LCR + mov al,80h + out dx,al ; command it + sub al,al + mov dx,UR_DLM + out dx,al + mov dx,UR_DLL + mov al,12 ; 9600 baud = 12, 19.2 Kbaud = 6 + out dx,al + mov al,3 + mov dx,UR_LCR + out dx,al ; command normal mode + +; see if CTL-Q or CTL-S + +putc1: pushf + cli + call inchr + jz putc3 ; no characters incomming + cmp al,19 ; ctl-S? + jnz putc3 ; no, ignore + +; have ctl-s. wait till we see ctl-Q + +putc2: call inchr + jz putc2 + cmp al,17 + jnz putc2 + +putc3: popf + mov dx,UR_LSR +putc4: in al,dx + test al,020h + jz putc4 + +; ready. crank it out! + + mov dx,UR_DAT + + pop ax + out dx,al + + pop bx + pop cx + pop dx + popf + ret + +putchar ENDP + +ENDIF diff --git a/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC b/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC new file mode 100644 index 0000000..590e376 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC @@ -0,0 +1,122 @@ +;** DEFDBUG.ASM - Debugging Macro Definitions +; +; +; DEBUG n,m,, +; +; + +.sall + +DEBUG MACRO N,M,string,args + local b,c + IFDEF DEBUGFLG + pushf + DEBUGTST N,M + jz b + push ax + push bp + call c ;; push address of string + DB '&string',0 +c: mov bp,sp +; IFNB + IRP Y, + IFIDN , + push 4[bp] + ELSE + IFIDN , + push 4[bp] + ELSE + IFIDN , + push 2[bp] + ELSE + IFIDN , + push 2[bp] + ELSE + mov ax,Y + push ax + ENDIF + ENDIF + ENDIF + ENDIF + ENDM +; ENDIF + call DPRINTF + mov sp,bp + pop ax ;; discard format string offset + pop bp + pop ax +b: popf + ENDIF +ENDM + + + + +;** ERRNZ - generate assembly error if arg != 0 +; + +ERRNZ MACRO EXPR + IF1 + IFE expr + ELSE + RADIX 0 ; CONDITION NOT MET - ERROR + ENDIF + ENDIF + ENDM + + +;** DBBEG - Start debugging range +; + +DBBEG MACRO N,M + LOCAL lab + IFDEF DEBUGFLG + pushf + DEBUGTST N,M + jnz lab ;; am to do it + DBJMP %DBCNT +lab: + ENDM + + + +DBJMP MACRO N + jmp DBLAB&N + ENDM + + +;** DEBUGTST - Test Debug Flags +; +; DEBUGTST n,m +; +; Where N and M are bit masks. +; +; If one or more of the bits in N is set in the high byte +; of BUGBITS, and one or more of the bits in M is set in +; the low byte of BUGBITS then clear the Z flag. +; +; In other words: +; +; If both masks show a "hit" clear 'Z' else set 'Z' +; +; USES FLAGS + +DEBUGTST MACRO N,M + LOCAL A + test BYTE PTR BUGBITS,n + jz A + test BYTE PTR BUGBITS+1,m +A: + ENDM + +DBEND MACRO + DBLAB %DBCNT +DBCNT = DBCNT+1 + popf + ENDM + +DBLAB MACRO N +DBLAB&N: + ENDM + + DBCNT = 1 diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM new file mode 100644 index 0000000..318b1b0 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM @@ -0,0 +1,2214 @@ +TITLE IBMBIO IBM BIOS FOR MS-DOS 4.0 + +; Modified for 3.0, July '83, Marc McDonald +; +; arw 02/01/84 +; split disk driver into separate file +; arw 05/01/84 +; split out console driver + +;:::::::::::::::::::::::::::::::::::::::::::::: +; +; IBM ADDRESSES FOR I/O +; +;:::::::::::::::::::::::::::::::::::::::::::::: + + PAGE ,132 +;DEBUGFLG = 1 ; don't enable debug printfs +CONSFLAG = 0 ; =1 to include console driver here + +.xlist + INCLUDE DEFDBUG.INC +.list + + BIOSEG=70H ;0070 SEGMENT FOR THE BIOS + SYSIZE=100H ;Number of paragraphs in sysinit module + RSINIT=0A3H ;RS232 INITIALIZATION + ;9600 BAUD:NO PARITY:1 STOP:8 BIT WORD + LF=10 ;LINE FEED + CR=13 ;CARRIAGE RETURN + BACKSP=8 ;BACKSPACE + BRKADR=6CH ;006C BREAK VECTOR ADDRESS + DSKADR=1EH*4 ;ADDRESS OF PTR TO DISK PARAMETERS + SEC9=522H ;ADDRESS OF DISK PARAMETERS + AKPORT=20H + EOI=20H + + +;** Timer and Clock Definitions + +SCHEDCOUNT EQU 50 ; # msec/scheduler tick +MOTORCOUNT EQU 55 ; # msec/ROM BIOS tick + + EXTRN CURRENT_DOS_LOCATION:WORD + EXTRN FINAL_DOS_LOCATION:WORD + EXTRN DEVICE_LIST:DWORD + EXTRN MEMORY_SIZE:WORD + EXTRN DEFAULT_DRIVE:BYTE + EXTRN SYSINIT:FAR + +BiosSeg GROUP Code,BiosInit +Code SEGMENT BYTE PUBLIC 'CODE' + + ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING + +START$: + JMP INIT + + DB 20 DUP (0) ; IBM WANTS SOME ZEROED AREA + +SUBTTL Jump tables for devices + ;-------------------------------------------------------------- +; +; COMMAND JUMP TABLES +; +; BEWARE - These tables overlap somewhat! -c.p. +; +IF CONSFLAG +CONTBL: + DW SetAddr + DW StatusComplete + DW StatusComplete + DW CMDERR + DW CON$READ + DW CON$RDND + DW StatusComplete + DW CON$FLSH + DW CON$WRIT + DW CON$WRIT + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR +ENDIF ;CONSFLAG + +AUXTBL: + DW StatusComplete + DW StatusComplete + DW StatusComplete + DW CMDERR + DW AUX$READ + DW AUX$RDND + DW StatusComplete + DW AUX$FLSH + DW AUX$WRIT + DW AUX$WRIT + DW AUX$WRST + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + +TIMTBL: + DW StatusComplete + DW StatusComplete + DW StatusComplete + DW CMDERR + DW TIM$READ + DW StatusDevReady + DW StatusComplete + DW StatusComplete + DW TIM$WRIT + DW TIM$WRIT + +PRNTBL: + DW StatusComplete + DW StatusComplete + DW StatusComplete + DW CMDERR + DW StatusNoXfer ; Printer doesn't read + DW StatusDevReady + DW StatusComplete + DW StatusComplete + DW PRN$WRIT + DW PRN$WRIT + DW PRN$STAT + DW StatusComplete + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + DW CMDERR + +SUBTTL Device entry points + ;--------------------------------------------------- +; +; Device Entry point +; +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +Dfun = DWORD PTR 14 ; Passed addr of dos function +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER + +AUXNUM DB 0 ;WHICH AUX DEVICE WAS REQUESTED + +; Dos routine to do functions for device drivers + PUBLIC DosFunction +DosFunction DD 0 ; Device help function entry point +ScrnIOok dd 0 ; (char *) true if in current screen locus + +TIM_DRV DB -1 ; TIME WHEN LAST DISK I/O PERFORMED +TIM_REM DW 0 ; scheduler tics left until media presumed + ; changed + +;** Debugging control: +; +; Group Level Controls +; 01 General BIOS, bootstrapping and initialization +; 01 Device initialization +; 02 MS-DOS bootstrapping +; 04 Driver error conditions +; 10 Command dispatch +; 04 Diskette driver +; 01 Initialization +; 02 System entrys +; 04 Details of read/write processing +; 08 Hard disk driver +; 01 Initialization +; 02 System entrys +; 10 Console display driver + + + PUBLIC BUGBITS +BUGBITS DB 000H ; group bits + DB 0ffH ; level bits + +Strategy PROC FAR + RET +Strategy ENDP + +IF CONSFLAG +CON$IN: + PUSH SI + MOV SI,OFFSET CONTBL + JMP SHORT Interrupt +ENDIF ;CONSFLAG + +AUX0$IN: + PUSH SI + PUSH AX + XOR AL,AL + JMP SHORT AUXENT + +AUX1$IN: + PUSH SI + PUSH AX + MOV AL,1 +AUXENT: + MOV SI,OFFSET AUXTBL + JMP SHORT entry1 + +PRN0$IN: + PUSH SI + PUSH AX + XOR AL,AL + JMP SHORT PRNENT + +PRN1$IN: + PUSH SI + PUSH AX + MOV AL,1 + JMP SHORT PRNENT + +PRN2$IN: + PUSH SI + PUSH AX + MOV AL,2 +PRNENT: + MOV SI,OFFSET PRNTBL + JMP SHORT entry1 + +TIM$IN: + PUSH SI + MOV SI,OFFSET TIMTBL + + +COMMENT * + Interrupt is the main part of the interrupt device entry point( a +misnomer, actually is the execute function entry ) for all devices. +The various devices set up the dispatch table address and unit choice +and then jump to Interrupt which then dispatches to the appropriate +device routine. + +Entry parameters: + SI Address of device dispatch table + AL Unit # for Aux/Prn( stored in AuxNum ) + ES:BX Device request packet address + +Exit parameters: ( to device routine ) + AL Unit code from packet + AH Media descriptor from packet + CX Count from packet + DX Start sector from packet + ES:DI Buffer address from packet + DS:BX Packet address + SS TaskArea segment( from dos call ) + * + + PUBLIC Interrupt +Interrupt PROC FAR + PUSH AX +entry1: + PUSH CX + PUSH DX + PUSH DI + PUSH BP + PUSH DS + PUSH ES + PUSH BX + debug 1,10H,< INTERRUPT cmdtbl $x >, + MOV CS:[AUXNUM],AL ; Save unit choice of AUX/PRN + MOV AX,ES + MOV DS,AX ; DS:BX also points to packet + + MOV AL,DS:[BX].Cmd ; Get device command + XOR AH,AH + ADD SI,AX + ADD SI,AX ; Get Address of routine + CMP AL,18 ; Too high a command number? + JA CmdErr ; Yes, error + MOV AL,DS:[BX].UNIT ;AL = Unit code + MOV AH,DS:[BX].MEDIA ;AH = Media descriptor + MOV CX,DS:[BX].COUNT ;CX = Count + MOV DX,DS:[BX].START ;DX = Start sector + LES DI,DS:[BX].TRANS ; ES:DI = buffer addr + debug 1,10H,, + JMP WORD PTR CS:[SI] ; Do request +Interrupt ENDP + +SUBTTL Routines used by device routines + COMMENT * + All routines on this page are various exits for device functions. +They each return different information in the request packet for the +dos. The routines are as follows: + + StatusDevReady + The busy and done bits are set in the packet. This + means that the device has input to be read or can + do output without any waiting. + + StatusPartialXfer + The device was unable to do the I/O for the requested + number of bytes/blocks. CX contains the number that are + left to do. Fall into StatusError to set error has + happened. + + StatusError + Set the error and done bits in the status. + + StatusNoXfer + The device couldn't do the read or write, set the + number of bytes transferred to 0, but don't set the + error bit. + + StatusComplete + The device actually completed the request and every- + thing was just fine, so just set the done bit in the + request status. + + StatusWait + The device driver is for 3.0 and saw that it would + have to wait in a loop to do the request, so instead + it will not set the done bit which tells the dos to + put the task into the I/O wait queue. + +Entry parameters: ( for all of the above routines ) + DS:BX Address of device request packet + CX Count of bytes/blocks left to transfer if applicable + AL Error code if applicable + +Exit parameters: + ES:BX Pointer to packet + AX Destroyed + SI Destroyed + All other registers preserved + * + + PUBLIC StatusDevReady +StatusDevReady PROC NEAR ; Device has data or can send + MOV AH,00000011B ; Done + busy + JMP SHORT SetStatus +StatusDevReady ENDP + + PUBLIC CmdErr +CmdErr PROC NEAR ; Bad device command number + debug 1,4,< CMDERR - $b $x\n>, + MOV AL,3 ; Unknown command error +CmdErr ENDP + +StatusPartialXfer PROC NEAR + SUB [BX].COUNT,CX ;# of successful I/O's +StatusPartialXfer ENDP + + PUBLIC StatusError +StatusError PROC NEAR + MOV AH,10000001B ; Error + done + JMP SHORT SetStatus +StatusError ENDP + +StatusNoXfer PROC NEAR + XOR AX,AX + MOV [BX].COUNT,AX ; No chars read +StatusNoXfer ENDP + + PUBLIC StatusComplete +StatusComplete PROC NEAR + MOV AH,00000001B ; Done + PUBLIC SetStatus +SetStatus: + POP BX + POP ES + MOV ES:WORD PTR [BX].STATUS,AX ;MARK OPERATION COMPLETE + POP DS + POP BP + POP DI + POP DX + POP CX + POP AX + POP SI +XXX PROC FAR + RET ;RESTORE REGS AND RETURN +XXX ENDP +StatusComplete ENDP + +StatusWait PROC NEAR + MOV AH,0 ; Don't set done bit + MOV [BX].Count,CX ; Set number completed + MOV WORD PTR [BX].Trans,DI ; Set new offset + JMP SetStatus +StatusWait ENDP + +IF CONSFLAG +; Set the address of the dos function routine for drivers +SetAddr PROC NEAR + MOV AX,WORD PTR [BX].Dfun + MOV WORD PTR DosFunction,AX + MOV AX,WORD PTR [BX+2].Dfun + MOV WORD PTR (DosFunction+2),AX + mov ax,0 + mov cx,1 + mov dx,16 + call DosFunction + mov word ptr ScrnIOok,ax + mov word ptr ScrnIOok+2,dx + JMP StatusComplete +SetAddr ENDP + + +;------------------------------------------------------------- +; +; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE +; +; CALLED VIA INT 29H +; +CHROUT = 29H + +OUTCHR: STI + PUSH AX + MOV BX,7 + MOV AH,14 ;WRITE CHARACTER + INT 10H ;SEND THE CHARACTER + POP AX + IRET +ENDIF ;CONSFLAG + +;---------------------------------------------- +; +; SET DX TO AUXNUM +; +GETDX: MOV DL,[AUXNUM] + XOR DH,DH + RET + +SUBTTL Console driver + COMMENT * + This is the console( CON ) device driver. The input side is assigned +to the keyboard and the output to the video screen. The output code +remains more or less the same as in 2.0. The input side, however, is +changed for 4.0 to enter an I/O wait rather than loop waiting for a +character. + * + +IF CONSFLAG +CONDEV LABEL WORD ;HEADER FOR DEVICE "CON" + DW AUXDEV,BIOSEG + DW 1000000000010011B ;CON IN AND CON OUT + SPECIAL + DW STRATEGY + DW CON$IN + DB 'CON ' +ELSE + EXTRN CONDEV:NEAR + PUBLIC AUXDEV +ENDIF ;CONSFLAG + +IF CONSFLAG +Key2ndPart DB 0 ; Leftover byte of 2 key codes + +RomData SEGMENT AT 40H + ORG 1AH +Bufferhead DW ? +BufferTail DW ? +KeyBuffer LABEL WORD +KeyBufLen equ 32 ; length of KeyBuffer +RomData ENDS + +; BREAK interrupt routine +; ROM interrupt handler resets buffer pointers to beginning of buffer +; and places a 0000h dummy character into the buffer. + +Break PROC NEAR + mov Key2ndPart,3 ; Force next char to be ^C( stop ) + IRET +Break ENDP + +SUBTTL Console read and subroutines + PAGE + +COMMENT * + The console read dispatch tries to read the selected number of +characters from the keyboard. If at any point there is no key in +the queue, it returns to the dos to allow another process to run +until a key is depressed. + +Entry parameters: + ES:DI Pointer to buffer in which to store characters + CX Number of characters to read + DS:BX Pointer to device request packet + +Exit parameters: + CX Number of characters left to read + DS:BX Pointer to device request packet + * + +Con$Read PROC NEAR + JCXZ StatusComplete +CON$LOOP: + PUSH CX ;SAVE COUNT + CALL ChrIn ;GET CHAR IN AL + POP CX + STOSB ;STORE CHAR AT ES:DI + LOOP CON$LOOP + JMP StatusComplete +Con$Read ENDP + +COMMENT * + ChrIn attempts to read a character from the keyboard queue that +is maintained by the ROM BIOS. If the queue is not empty, the code +is returned. Otherwise, the packet is added to the list of keyboard +reads and carry is set to cause the driver routine to return to the +dos with the done bit not set which results in an I/O wait. + +Entry parameters: + DS:BX Pointer to device request packet + +Exit parameters: + AL Character from keyboard if present +* + +ChrIn PROC NEAR +ConReadLoop: + XOR AX,AX + XCHG AL,Key2ndPart ; GET CHARACTER & ZERO Key2ndPart + OR AL,AL + JNZ KeyRet + MOV AH,0 + INT 16H ; Get the char + OR AX,AX ;Check for non-key after BREAK + JZ ConReadLoop + CMP AX,7200H ;Check for CTRL-PRTSC + JNZ ALT15 + MOV AL,16 +ALT15: + OR AL,AL ; 2 byte keycode? + JNZ KeyRet ; No, have whole code + MOV Key2ndPart,AH ; Yes, store scan code for next read +KeyRet: RET +ChrIn ENDP + + +COMMENT * + The non-destructive keyboard read routine returns the next char +in the queue if there is one. + +Entry parameters: + DS:BX Pointer to device request packet + +Exit parameters: + DS:BX Pointer to device request packet + * +Con$RdNd PROC NEAR + MOV AL,[Key2ndPart] + OR AL,AL + JNZ RDexit + mov ah,1 + int 16h + JZ CONBUS + OR AX,AX + JNZ NOTBRK ;CHECK FOR NULL AFTER BREAK + MOV AH,0 + INT 16H ;READ THE NULL + JMP CON$RDND ;AND GET A REAL STATUS +NOTBRK: CMP AX,7200H ;CHECK FOR CTRL-PRTSC + JNZ RDexit + MOV AL,16 +RDexit: + MOV [BX].MEDIA,AL +EXVEC: JMP StatusComplete +CONBUS: JMP StatusDevReady +Con$RdNd ENDP + +;-------------------------------------------------------------- +; +; KEYBOARD FLUSH ROUTINE +; +Con$Flsh PROC NEAR + MOV [Key2ndPart],0 ;Clear out holding buffer + + CALL Flush ; Flush the keyboard + JMP EXVEC +Con$Flsh ENDP + + +Flush PROC NEAR + PUSH DS + MOV AX,RomData + MOV DS,AX + ASSUME DS:RomData + + CLI ; ** Disable interrupts + MOV AX,offset RomData:KeyBuffer ; Start of Rom buffer + MOV BufferHead,AX + MOV BufferTail,AX ; Empty the queue + STI ; ** enable interrupts + POP DS + ASSUME DS:NOTHING + + RET +Flush ENDP + +SUBTTL Console output( video ) routines + PAGE + +;---------------------------------------------------------- +; +; CONSOLE WRITE ROUTINE +; +CON$WRIT: + JCXZ EXVEC +CON$LP: MOV AL,ES:[DI] ;GET CHAR + INC DI + PUSH CX + PUSH DI + INT CHROUT ;OUTPUT CHAR + POP DI + POP CX + LOOP CON$LP ;REPEAT UNTIL ALL THROUGH + JMP EXVEC + +SUBTTL Keyboard interrupt routine +PAGE +; Replacement for ROM keyboard interrupt, tacks on the front. +; OldKeyInterrupt is set to original contents of INT 09H. +; The input character is passed to the O.S. console input filter +; to determine if any special action should be taken. The filter +; return value indicates if the character should be saved in the +; type ahead buffer or if it should be discarded. A keyboard +; semaphore exists to indicate if a process is waiting for input. +; If the keboard semaphore is set all of the processes sleeping on +; it are woken up. + +OldKeyInterrupt DD ? +KeySem db 0 ; non-zero if someone waiting on input + +KeyboardInterrupt PROC FAR + INT 32H ; Save regs + MOV AX,RomData + MOV DS,AX + ASSUME DS:RomData + + PUSHF ; Save flags to simulate INT + CALL CS:OldKeyInterrupt ; Now do ROM code +; Now tell scheduler keyboard had char + cli ; interrupts off! + mov bx,BufferTail ; Get tail of queue + cmp bx,BufferHead ; Anything in keyboard queue? + JE NoKey ; No, don't requeue then + dec bx + dec bx + cmp bx,offset RomData:KeyBuffer + jae kbi1 ; no rap around in buffer + mov bx,offset RomData:KeyBuffer+KeyBufLen +kbi1: + mov ax,[bx] ; get last queued char. + mov dx,5 ; ConsInputFilter subfunction + call DosFunction + jnz kbi2 ; key should remain in buffer + mov BufferTail,bx ; discard key from buffer + jmp SHORT NoKey +kbi2: + cli + CMP KeySem,0 ; Outstanding request? + JE NoKey ; No, may not be inited either + push ax + push bx + push cx + push dx + mov ax,cs + mov bx,OFFSET KeySem + mov cs:byte ptr [bx],0 ; reset keyboard semaphore + mov dx,10 ;; ProcRun + call [DosFunction] ; awaken anyone waiting on input + pop dx + pop cx + pop bx + pop ax +NoKey: + IRET +KeyBoardInterrupt ENDP + +;------------------------------------------------------------- +; Keyboard INT 16 intercept routine to allow console input to sleep. +; Only console input function 1 is intercepted, all other functions +; are allowed to go directly to the ROM BIOS. For the function 1 +; the input status is checked, if a character is ready the function +; is allowed to go to the ROM BIOS. Otherwise the keyboard semaphore +; is set and the process is put to sleep on the address of the +; semaphore. When a key is typed the keyboard interrupt routine +; will wakeup any processes sleeping on this semaphore. +; +; WARNING: The following routines can be entered recursively +; due to the fact that the ROM BIOS routines called +; reenable interrupts. It's not usually a problem +; since interrupts will generally be processed faster +; than anyone can type. + +OldKbdHandler dd ? + +;------------------------------------------------------------- + +KeyBoardHandler proc far + or ah,ah + je DoLocalRead + cmp ah,1 + je DoLocalStat +OldKBint: + jmp [OldKbdHandler] + +DoLocalStat: + push bx + push ds + lds bx,ScrnIOok + test byte ptr [bx],0FFh + pop ds + pop bx + jnz OldKBint + xor ax,ax + ret 2 + +DoLocalRead: + push ax + push bx + push cx + push dx +DoLocalRd1: + push ds + lds bx,ScrnIOok + mov ax,ds + test byte ptr [bx],0FFh + pop ds + jnz DoLocalRd2 + xor cx,cx + mov dx,9 ;; ProcBlock + call [DosFunction] ; sleep until a char is typed + jmp DoLocalRd1 + +DoLocalRd2: + mov ah,1 ; get console status + pushf ; simulate INT to old handler + cli + call [OldKbdHandler] + cli ; subfunction 1 unconditionally sets IF + jnz LocalRead ; go read character + mov ax,cs + mov bx,OFFSET KeySem + mov cs:byte ptr [bx],0FFh ; set keyboard semaphore + xor cx,cx + mov dx,9 ;; ProcBlock + call [DosFunction] ; sleep until a char is typed + jmp DoLocalRd1 + +LocalRead: + pop dx + pop cx + pop bx + pop ax + jmp [OldKbdHandler] ; read the character and return + +KeyBoardHandler endp + +ENDIF ;CONSFLAG + +SUBTTL Aux driver + ;------------------------------------------------------ +; +; A U X - AUXILARY DEVICE DRIVER +; +AUXDEV LABEL WORD ;HEADER FOR DEVICE "AUX" + DW PRNDEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'AUX ' + + PUBLIC COM1DEV +COM1DEV LABEL WORD + DW LPT1DEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'COM1 ' + +COM2DEV LABEL WORD + DW -1,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW AUX1$IN + DB 'COM2 ' + +AUXBUF DB 0,0 +;------------------------------------------------------- +; +; READ FROM AUXILARY DEVICE +; +AUX$READ: + JCXZ EXVEC2 + CALL GETBX + XOR AX,AX + XCHG AL,[BX] ;Get character and zero buffer + OR AL,AL + JNZ AUX2 +AUX1: CALL AUXIN +AUX2: STOSB ;STORE CHARACTER + LOOP AUX1 +EXVEC2: JMP StatusComplete + +AUXIN: MOV AH,2 ;INDICATES A READ + CALL AUXOP ;READ THE AUXILIARY PORT + TEST AH,0EH ;Check framing, parity, overrun + JZ AROK + POP AX ;Clean up the stack + MOV AL,0BH ;READ ERROR + JMP StatusPartialXfer +AROK: RET +;-------------------------------------------------------- +; +; AUX NON-DESTRUCTIVE READ, NO WAITING +; +AUX$RDND: + CALL GETBX + MOV AL,[BX] ;GET KEY AND ZERO BUFFER + OR AL,AL + JNZ AUXRDX ;KEY IN BUFFER? + CALL AUXSTAT + TEST AH,00000001B ;TEST DATA READY + JZ AUXBUS + TEST AL,00100000B ;TEST DATA SET READY + JZ AUXBUS + CALL AUXIN + CALL GETBX + MOV [BX],AL ;GET AND SAVE KEY +AUXRDX: JMP StatusComplete +AUXBUS: JMP StatusDevReady +;---------------------------------------------------------- +; +; AUX OUTPUT STATUS +; +AUX$WRST: + CALL AUXSTAT + TEST AL,00100000B ;TEST DATA SET READY + JZ AUXBUS + TEST AH,00100000B ;TEST CLEAR TO SEND + JZ AUXBUS + JMP EXVEC2 + +AUXSTAT: + MOV AH,3 +AUXOP: CALL GETDX + INT 14H + RET +;--------------------------------------------------------- +; +; FLUSH AUX INPUT BUFFER +; +AUX$FLSH: + CALL GETBX + MOV BYTE PTR [BX],0 + JMP EXVEC2 +;--------------------------------------------------------- +; +; WRITE TO AUXILARY DEVICE +; +AUX$WRIT: + JCXZ EXVEC2 +AUX$LOOP: + MOV AL,ES:[DI] ;GET CHAR + INC DI ;POINT TO NEXT ONE + MOV AH,1 ;INDICATES A WRITE + CALL AUXOP ;SEND CHARACTER OVER AUX PORT + TEST AH,80H ;CHECK FOR ERROR + JZ AWOK + MOV AL,10 ;INDICATE WRITE FAULT + JMP StatusPartialXfer +AWOK: LOOP AUX$LOOP + JMP EXVEC2 + +GETBX: CALL GETDX + MOV BX,DX + ADD BX,OFFSET AUXBUF + RET +SUBTTL Printer driver + ;------------------------------------------------------------- +; +; P R N - PRINTER DEVICE +; +PRNDEV LABEL WORD ;HEADER FOR DEVICE "PRN" + DW TIMDEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW PRN0$IN + DB 'PRN ' + +LPT1DEV LABEL WORD + DW LPT2DEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW PRN0$IN + DB 'LPT1 ' + +LPT2DEV LABEL WORD + DW LPT3DEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW PRN1$IN + DB 'LPT2 ' + +LPT3DEV LABEL WORD + DW COM2DEV,BIOSEG + DW 1000000000000000B + DW STRATEGY + DW PRN2$IN + DB 'LPT3 ' + +ERRFLG DB 0 + +;---------------------------------------------------------- +; +; WRITE TO PRINTER DEVICE +; +PRN$WRIT: + JCXZ EXVEC3 +PRN$LOOP: + MOV AL,ES:[DI] ;GET CHAR INTO AL + INC DI ;POINT TO NEXT CHAR + MOV [ERRFLG],0 ;INITIALIZE RETRY FLAG + +PRETRY: XOR AH,AH ;AH=0 + CALL PRNOP ;TO INDICATE PRINT CHAR IN AL + +ERRCHK: JZ PROK + XOR [ERRFLG],1 ;DO 1 AUTOMATIC RETRY + JNZ PRETRY +PMESSG: JMP StatusPartialXfer ;RETURN WITH THE ERROR + +PROK: LOOP PRN$LOOP +EXVEC3: JMP StatusComplete +;-------------------------------------------------------- +; +; PRINTER STATUS ROUTINE +; +PRN$STAT: + CALL PRNSTAT ;DEVICE IN DX + JNZ PMESSG + TEST AH,10000000B + JNZ EXVEC3 + JMP StatusDevReady + +PRNSTAT: + MOV AH,2 +PRNOP: CALL GETDX + INT 17H + + MOV AL,2 + TEST AH,0001B ;TEST FOR NOT READY + JNZ PRNOP2 + + MOV AL,10 ;WRITE FAULT CODE + TEST AH,1000B ;TEST FOR I/O ERROR + JZ PRNOP2 + + TEST AH,00100000B ;OUT-OF-PAPER? + JZ PRNOP1 + MOV AL,9 ;OUT OF PAPER CODE +PRNOP1: OR AL,AL ;SET NZ FLAG +PRNOP2: RET + +SUBTTL Timer (clock) driver + PAGE + +;** Time Functions +; +; Uses clock with 1000 ticks per second. User sees only +; time in hours, minutes, seconds, and 1/100 second, in registers +; CH, CL, DH, DL respectively. (Each is a binary number.) +; Modified for 4.0. The ROM bios timer routines are completely +; replaced with code on this page. This provides a better time base +; for the scheduler. + + + EXTRN Floppydevice:NEAR +TIMDEV LABEL WORD + DW Floppydevice,BIOSEG + DW 1000000000001000B + DW STRATEGY + DW TIM$IN + DB 'CLOCK$ ' + +DAYCNT DW 0 + +;-------------------------------------------------------------------- +; +; Settime sets the current time +; +; On entry ES:[DI] has the current time: +; +; number of days since 1-1-80 (WORD) +; minutes (0-59) (BYTE) +; hours (0-23) (BYTE) +; hundredths of seconds (0-99) (BYTE) +; seconds (0-59) (BYTE) +; +; Each number has been checked for the correct range. + +TIM$WRIT: + PUSH BX + MOV AX,ES:[DI] + MOV DAYCNT,AX + MOV CX,ES:[DI+2] + MOV AL,60 + MUL CH ;Hours to minutes + MOV CH,0 + ADD AX,CX ;Total minutes + MOV CX,60000 ;60*1000 + MUL CX ;Convert to milliseconds + MOV SI,AX + MOV BX,DX ; Save hours, min in Msecs in BX:SI + MOV AL,ES:[DI+5] ; Get # seconds + MOV CX,100 + MUL CL ; Get seconds in 1/100s + MOV CL,ES:[DI+4] ; Hundredths of second + ADD AX,CX ; Now have seconds and 1/100ths + MOV CL,10 + MUL CX ; Get DX:AX = milliseconds + ADD AX,SI + MOV CS:TickLow,AX + ADC BX,0 + MOV CS:TickHigh,BX ; Set time in milliseconds + POP BX + JMP StatusComplete + + +;*************************************** +; +; Gettime reads date and time +; and returns the following information: +; +; ES:[DI] =count of days since 1-1-80 +; ES:[DI+2]=minutes +; ES:[DI+3]=hours +; ES:[DI+4]=hundredths of seconds +; ES:[DI+5]=seconds +; +;*************************************** + PUBLIC TIM$READ +TIM$READ: + PUSH BX + MOV AX,DayCnt + STOSW ; return day + MOV DX,CS:TickHigh + MOV AX,CS:TickLow ; Get current time + MOV CX,60000 ; # milliseconds in a minute + DIV CX ; Get AX= minutes, DX = seconds&msecs + MOV BX,DX ; Save seconds and fraction + XOR DX,DX + MOV CX,60 ; # minutes/hour + DIV CX ; Get AX= hour, DX= minute + xchg ax,dx + STOSB ; Return minutes + xchg ax,dx + STOSB ; Return hours + MOV AX,BX + XOR DX,DX + MOV CX,1000 + DIV CX ; Get AX= seconds, DX= milliseconds + xchg ax,bx ; (bx) = seconds + MOV AX,DX + XOR DX,DX + MOV CX,10 + DIV CX ; Get hundredths of second + STOSB ; Return hundredths of second + xchg ax,bx + STOSB ; Return second + POP BX + JMP StatusComplete + +SUBTTL Clock interrupt and replacement for ROM code +PAGE + +COMMENT * + The clock code in the ROM is replaced with the following code which +provides the clock interface to the scheduler and a 1 ms time base. The +1AH interrupt is simulated to return the approximate time for those +routines which still call 1AH. The time period for motor start up is +preserved since that code has not yet been rewritten. + * + +RomData SEGMENT AT 040H + ORG 03FH +Motor_Status DB 1 DUP(?) +Motor_Count DB 1 DUP(?) +RomData ENDS + +TickLow DW ? ; Low part of time in Msec +TickHigh DW ? ; High part of time in msec +MotorFlag DB 0 ; There is an active motor +MotorTick DB MOTORCOUNT ; # ticks until 1/18.2 secs +SchedTick DB SCHEDCOUNT ; Scheduler countdown + +; Interrupt 8H - timer interrupt + + ASSUME DS:NOTHING +TimerInterrupt PROC FAR + PUSH AX + INC TickLow + JNZ NoOverflow + INC TickHigh +NoOverFlow: + CMP TickHigh,1318 ; Close to 24 hours? + JNZ NotDay ; No + CMP TickLow,23552 ; Reach 24 hours? + JNZ NotDay ; No +; Have reached a day, bump day count + INC DayCnt + XOR AX,AX + MOV TickHigh,AX + MOV TickLow,AX ; Reset time of day +NotDay: +;; DEC MotorTick ; Time to decrement motor? +;; JNZ CheckSched ; No +;; MOV MotorTick,MOTORCOUNT ; Reset 1/18 sec worth of msecs +;; PUSH DS +;; MOV AX,RomData +;; MOV DS,AX +;; ASSUME DS:RomData + +;; TEST MotorFlag,0FFH ; Active motor timer? +;; JZ CheckMotor ; No, see if new one +;; DEC Motor_Count +;; JNZ CheckMotor ; Not time to shut down +;; AND Motor_Status,0F0H ; Turn off motor running bits +;; MOV AL,0CH +;; PUSH DX +;; MOV DX,03F2H +;; OUT DX,AL ; Turn off the motors +;; POP DX +;; MOV MotorFlag,0 ; No motor timeout running +;; POP DS +;; JMP CheckSched ; Go see if time to sched + +;;CheckMotor: +;; MOV AL,Motor_Count +;; POP DS +;; JNZ CheckSched ; Motor already active +;; OR AL,AL ; Need to start countdown? +;; JZ CheckSched ; No +;; MOV MotorFlag,0FFH ; Yes, set flag +;; MOV MotorTick,MOTORCOUNT ; 1/18.2 sec later + +; The scheduler is called every 10ms, rather than every 1 ms to see if +; it should switch tasks. +CheckSched: +; First reset the timer so will interrupt again + MOV AL,36H + OUT 43H,AL + MOV AL,169 + OUT 40H,AL + MOV AL,4 + OUT 40H,AL ; Set 1 msec delay + MOV AL,20H + OUT 20H,AL ; Tell 8259 interrupt done +; Now see if should call scheduler + DEC SchedTick ; Time to call scheduler? + JNZ NoSched ; No, all done + MOV SchedTick,SCHEDCOUNT ; Reset countdown +csch1: POP AX ; Stack is now clean + INT 32H ; Save all regs + CMP WORD PTR (DosFunction+2),0 ; Dos installed? + JE NoSchedActive ; Not yet, don't call sched + sub dx,dx ; (dx) = 0 = tic subfunction + mov ax,SCHEDCOUNT ; 10 milliseconds per tic + CALL DosFunction ; Do the tick + EXTRN FloppyTimer:FAR + CALL FloppyTimer ; timer service for floppy disk also +NoSchedActive: + IRET ; All done + +NoSched: + POP AX +INTRET: IRET ; All done +TimerInterrupt ENDP + +; INT 1AH - Get/Set time based in 55msec tick + +TimeOfDay PROC FAR + OR AH,AH ; Function 0: Read time? + JZ ReadOld ; Yes + DEC AH ; Function 1: Write time? + JZ WriteOld ; Yes + IRET ; No, bad function code + +; Read old( 1/18.2 second tick ) time +ReadOld: + MOV AX,TickHigh + xor dx,dx + MOV CX,MOTORCOUNT ; # milliseconds in 1/18.2 secs + DIV CX ; Get value in old ticks + push ax + MOV AX,TickLow + div cx + pop cx ; get high order count + XOR AL,AL ; Never have oveflow + IRET ; Return the time + +; Set time using old resolution +WriteOld: + MOV AX,DX + push bx + MOV BX,MOTORCOUNT ; Conversion factor + MUL BX + MOV TickLow,AX ; Set low part of time + mov ax,cx + mov cx,dx + MUL BX + pop bx + ADD AX,CX ; Combine high parts + MOV TickHigh,AX ; Set time + IRET ; Return with new time set +TimeOfDay ENDP + +;++++ +memsizmsg db 13,10,'Error - Interrupt 12',13,10,0 +memsizint dd 0 + +memsizhandler proc far + push ax + push bx + push si + push ds + push cs + pop ds + mov SI,offset CS:memsizmsg + call WRMSG + pop ds + pop si + pop bx + pop ax + jmp memsizint +memsizhandler endp +;++++ + +;---------------------------------------------- +; WRITE OUT MESSAGE POINTED TO BY [SI] +; +WRMSG: LODSB ;GET THE NEXT CHARACTER OF THE MESSAGE + AND AL,7FH ;SEE IF END OF MESSAGE + JZ WRMRET + MOV BX,7 + MOV AH,14 ;WRITE CHARACTER + INT 10H ;SEND THE CHARACTER + JMP SHORT WRMSG +WRMRET: RET + +.xlist + INCLUDE BUGCODE.INC +.list + +Code ENDS + +SUBTTL Diskette driver -- now used only for bootup + ;----------------------------------------------------------------- +; +; DISK INTERFACE ROUTINES +; +BiosInit SEGMENT PARA PUBLIC 'CODE' + +DRVMAX DB 4 + + ASSUME CS:BiosSeg + +MAXERR = 5 +LSTDRV = 504H + +WRTVERIFY LABEL WORD +RFLAG DB 2 ;2 for read, 3 for write +VERIFY DB 0 ;1 if verify after write +SINGLE DB 0 ;1 if single drive system +SWPFLG DB 0 ;1 if BIOS swapped out +SECCNT DW 0 +HARDNUM DB 99 ;logical drive number of first hardfile + +RESSEC = 3 +DRVLIM = 8 ;Number of sectors on device +SECLIM = 13 ;MAXIMUM SECTOR +HDLIM = 15 ;MAXIMUM HEAD +HIDSEC = 17 ;NUMBER OF HIDDEN SECTORS + +;WARNING - preserve order of drive and curhd! -c.p. + +DRIVE DB 0 ;PHYSICAL DRIVE CODE +CURHD DB 0 ;CURRENT HEAD +CURSEC DB 0 ;CURRENT SECTOR +CURTRK DW 0 ;CURRENT TRACK + + +ERRIN: ;DISK ERRORS RETURNED FROM THE IBM ROM + DB 80H ;NO RESPONSE + DB 40H ;Seek failure + DB 10H ;BAD CRC + DB 8 ;DMA OVERRUN + DB 4 ;SECTOR NOT FOUND + DB 3 ;WRITE ATTEMPT TO WRITE-PROTECT DISK +LSTERR DB 0 ;ALL OTHER ERRORS + + +ERROUT: ;RETURNED ERROR CODES CORRESPONDING TO ABOVE + DB 2 ;NO RESPONSE + DB 6 ;SEEK FAILURE + DB 4 ;BAD CRC + DB 4 ;DMA OVERRUN + DB 8 ;SECTOR NOT FOUND + DB 0 ;WRITE ATTEMPT ON WRITE-PROTECT DISK + DB 12 ;GENERAL ERROR + +NUMERR= ERROUT-ERRIN +;--------------------------------------------------------------------- +SPSAV DW 0 ;SAVE THE STACK POINTER +; + +GETBP: PUSH AX + PUSH CX + PUSH DX + PUSH BX + MOV CL,AH ;SAVE MEDIA + AND CL,0F8H ;NORMALIZE + CMP CL,0F8H ;COMPARE WITH GOOD MEDIA BYTE + JZ GOODID + MOV AH,0FEH ;DEFAULT TO 8-SECTOR, SINGLE-SIDED +GOODID: MOV DI,OFFSET CS:HDRIVE + CMP AL,[HARDNUM] + JZ GETRET + JB GETBP1 + MOV DI,OFFSET CS:DRIVEX + JMP SHORT GETRET + +GETBP1: MOV AL,1 ;SET NUMBER OF FAT SECTORS + MOV BX,64*256+8 ;SET DIR ENTRIES AND SECTOR MAX + MOV CX,40*8 ;SET SIZE OF DRIVE + MOV DX,01*256+1 ;SET HEAD LIMIT AND SEC/ALL UNIT + MOV DI,OFFSET CS:FDRIVE + TEST AH,00000010B ;TEST FOR 8 OR 9 SECTOR + JNZ HAS8 ;NZ = HAS 8 SECTORS + INC AL ;INC NUMBER OF FAT SECTORS + INC BL ;INC SECTOR MAX + ADD CX,40 ;INCREASE SIZE +HAS8: TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS + JZ HAS1 ;Z = 1 HEAD + ADD CX,CX ;DOUBLE SIZE OF DISK + MOV BH,112 ;INCREASE NUMBER OF DIRECTORY ENTRIES + INC DH ;INC SEC/ALL UNIT + INC DL ;INC HEAD LIMIT +HAS1: MOV CS:[DI].2,DH + MOV CS:[DI].6,BH + MOV CS:[DI].8,CX + MOV CS:[DI].10,AH + MOV CS:[DI].11,AL + MOV CS:[DI].13,BL + MOV CS:[DI].15,DL +GETRET: POP BX +RET88: POP DX + POP CX + POP AX + RET + +;********************************************************************* +; "FDRIVE" IS A FLOPPY DISK, VARIOUS PARAMETERS ARE PATCHED +; BY GETBP TO REFLECT THE TYPE OF MEDIA INSERTED +FDRIVE: + DW 512 ;Physical sector size in bytes + DB 1 ;Sectors/allocation unit + DW 1 ;Reserved sectors for DOS + DB 2 ;No. allocation tables + DW 64 ;Number directory entries + DW 9*40 ;Number sectors (at 512 bytes ea.) + DB 11111100B ;Media descriptor + DW 2 ;Number of FAT sectors + DW 9 ;Sector limit + DW 1 ;Head limit + DW 0 ;Hidden sector count + +;------------------------------------------------------------ +; +; DISK I/O HANDLER +; +; AL = DRIVE NUMBER (0-3) +; AH = MEDIA DESCRIPTOR +; CX = SECTOR COUNT +; DX = FIRST SECTOR +; ES:DI = TRANSFER ADDRESS +; [RFLAG]=OPERATION (2=READ, 3=WRITE) +; [VERIFY]=1 FOR VERIFY AFTER WRITE +; +; IF SUCCESSFUL CARRY FLAG = 0 +; ELSE CF=1 AND AL CONTAINS ERROR CODE +; +DISKRD: + debug 1,4,, + MOV [RFLAG],2 +DISKIO: + CLC + JCXZ IORET + MOV [TIM_DRV],AL ;SAVE DRIVE LETTER + + MOV [SPSAV],SP ;SAVE SP + XCHG BX,DI ;ES:BX = TRANSFER ADDRESS + CALL GETBP ;CS:DI = PTR TO B.P.B + MOV SI,DX + ADD SI,CX + ADD DX,CS:[DI].HIDSEC ;ADD IN THE HIDDEN SECTORS + CMP SI,CS:[DI].DRVLIM ;COMPARE AGAINST DRIVE MAX + JBE INRANGE + MOV AL,8 +STCRET: STC +IORET: RET + +INRANGE:CMP AL,[HARDNUM] + JB NOTHARD + MOV AL,CS:[HARDDRV] ;SET DRIVE NUMBER OF HARDFILE + JZ RDWR + INC AL + JMP SHORT RDWR + +NOTHARD:CMP [SINGLE],1 ;SINGLE FLOPPY INSTALLED? + JNZ RDWR + CALL SWPDSK ;ASK USER FOR CORRECT DISK +RDWR: + MOV [DRIVE],AL + MOV [SECCNT],CX ;SAVE SECTOR COUNT + XCHG AX,DX ;SETUP LOGICAL SECTOR FOR DIVIDE + XOR DX,DX + DIV WORD PTR CS:[DI].SECLIM ;DIVIDE BY SEC PER TRACK + INC DL + MOV [CURSEC],DL ;SAVE CURRENT SECTOR + MOV CX,CS:[DI].HDLIM ;GET NUMBER OF HEADS + XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER + DIV CX + MOV [CURHD],DL ;SAVE CURRENT HEAD + MOV [CURTRK],AX ;SAVE CURRENT TRACK + + debug 1,4,< Drv $b Hd $b Trk $x Sec $b\n>,<,,CURTRK,> + MOV AX,[SECCNT] + MOV SI,ES ;Check for 64k boundary error + SHL SI,1 + SHL SI,1 + SHL SI,1 + SHL SI,1 ;Segment converted to absolute address + ADD SI,BX ;Combine with offset + ADD SI,511 ;Add sector size and see if overflow + JC BUFIO ;Must handle special if so + + XCHG BX,SI + SHR BH,1 + MOV AH,128 ;Max. sectors in 64K + SUB AH,BH ;Number of sectors left in this 64K + XCHG BX,SI + + CMP AH,AL ;Does it exceed total request? + JBE FIRBLK + MOV AH,AL ;If so, limit transfer to the request +FIRBLK: +;At this point, AL=total number of sectors to be read, AH=number +; of sectors that can be read before 64K boundary error. AH<=AL. +; ES:BX points to load area, DS:DI points to B.P.B + + PUSH AX + MOV AL,AH ;No. of sectors to read at once (<>0) + CALL BLOCK ;Transfer portion before boundary + POP AX + SUB AL,AH + JZ DONE +BUFIO: + PUSH AX + PUSH ES + PUSH BX ;SAVE CURRENT TRANSFER ADDRESS + CALL SWAP ;SWAP BUFFER WITH BIOS CODE + + ADD BH,2 ;POINT TO TEMP BUFFER + CALL DISK1 ;Perform disk operation + + POP BX ;RECALL TRANSFER ADDRESS + POP ES + POP AX + CALL SWAP ;SWAP BACK + + DEC AL ;Dec sectors to read by 1 + ADD BH,2 ;Add 200H to transfer address + CALL BLOCK ;Read the remaining sectors +DONE: + debug 1,4,< DISKIO DONE\n> + CLC ;No error + RET ;From subroutine DISKIO + +; Swap 512 bytes of BIOS with transfer address + +SWAP: PUSH DI + PUSH BX + PUSH AX + MOV DI,BX ;ES:DI POINTS TO USER BUFFER + ADD BH,2 + MOV SI,BX ;ES:SI POINTS TO TEMP BUFFER + CLD + debug 1,4,< SWAP $x:$x <==> $x:$x\n>, + MOV CX,256 ;256 WORDS TO SWAP +SWAP1: MOV BX,WORD PTR ES:[DI] ;GET USER WORD + MOV AX,WORD PTR ES:[SI] ;GET SCRATCH WORD + MOV WORD PTR ES:[SI],BX ;PUT SCRATCH WORD + STOSW ;PUT BIOS WORD + INC SI + INC SI + LOOP SWAP1 + XOR [SWPFLG],1 ;TOGGLE SWAPPED FLAG + POP AX + POP BX + POP DI +RETZ: RET + +;Read the number of sectors specified in AL, handling track boundaries + +BLOCK: OR AL,AL ;See if any sectors to read + JZ RETZ + + MOV AH,CS:[DI].SECLIM ;Sectors per track + INC AH + SUB AH,[CURSEC] ;Number of sectors left on this track + CMP AH,AL ;Compare with no. of sectors needed + JBE DOIO + MOV AH,AL ;Limit to only those requested +DOIO: + PUSH AX + MOV AL,AH ;Put count where ROM needs it + CALL DISK ;Call ROM and trap errors + POP AX + SUB AL,AH ;Reduce request by amount just done + SHL AH,1 ;AH * 2^8 = no. of bytes + ADD BH,AH ;Bump address pointer + JMP BLOCK + +;Perform disk I/O with retries +; AL = number of sectors (1-8, all on one track) +; ES:BX = Transfer address (must not cross a 64K physical boundary) +; [RFLAG] = 2 if read, 3 if write +; [VERIFY] = 0 for normal, 1 for verify after write + +DISK1: MOV AL,1 ;Only one sector for buffered I/O + +DISK: MOV SI,MAXERR + MOV AH,RFLAG ;Get read/write indicator + +RETRY: PUSH AX + +CALLROM:MOV DX,[CURTRK] ;Load current cylinder + MOV CL,6 ;move high bits of cyl to sec + SHL DH,CL + OR DH,[CURSEC] + MOV CX,DX + XCHG CH,CL ;CL = sector, CH = cylinder + MOV DX,WORD PTR [DRIVE] ;Load physical drive number + ;and current head number +;; debug 1,4,< CALLROM $x $x $x $x $x\n>, + INT 13H ;Request disk read/write + JC DSKERR + POP AX ;Restore sector count + PUSH AX + CMP WRTVERIFY,103H ;Check for write and verify + JNZ NOVERIFY + MOV AH,4 ;Request verify + INT 13H + JC DSKERR +NOVERIFY: +;; debug 1,4,< back from ROM\n>,<> + POP AX + AND CL,03FH ;Eliminate cylinder bits from sector + XOR AH,AH + SUB [SECCNT],AX ;Reduce count of sectors to go + ADD CL,AL ;Next sector + MOV [CURSEC],CL + CMP CL,CS:[DI].SECLIM ; Reached limit? + JBE RET1 + + MOV [CURSEC],1 ;Start with first sector of next track + MOV DH,[CURHD] + INC DH + CMP DH,CS:[DI].HDLIM + JB NOXOR + XOR DH,DH + INC [CURTRK] ;NEXT TRACK +NOXOR: MOV [CURHD],DH + +RET1: RET + +DSKERR: + debug 1,4,< DSKERR $x >, + PUSH AX ;Save error code + MOV AH,0 ;Ask for disk reset + INT 13H + POP AX ;Restore error code + DEC SI ;decrement retry count + JZ HARDERR + CMP AH,80H ;Timeout? + JZ HARDERR ;*** +DSKERR1:POP AX ;Restore sector count + JMP RETRY + +HARDERR: + CMP [SWPFLG],0 ;If BIOS swapped out + JZ HARD1 + POP BX ;Get disk1 return address + POP BX ;Get low part of transfer address + POP ES ;Get high part of transfer address + CALL SWAP ;swap it back in +HARD1: PUSH CS + POP ES ;Make ES the local segment + MOV AL,AH ;Put error code in AL + MOV [LSTERR],AL ;Terminate list with error code + MOV CX,NUMERR ;Number of possible error conditions + MOV DI,OFFSET CS:ERRIN ;Point to error conditions + REPNE SCASB + MOV AL,es:NUMERR-1[DI] ;Get translation + MOV CX,SECCNT ;Get count of sectors to go + MOV SP,[SPSAV] ;Recover entry stack pointer + STC ;Flag error condition + RET ;and return + +INITAB DW FDRIVE + DW FDRIVE + DW FDRIVE + DW FDRIVE +INITABH DW HDRIVE + DW DRIVEX + +RomData SEGMENT AT 040H + ORG 03EH +Seek_Status DB 1 DUP(?) +RomData ENDS + + +;------------------------------------------------- +; +; ASK TO SWAP THE DISK IN DRIVE A: +; +SWPDSK: PUSH DS + XOR SI,SI ;Select segment 0 + MOV DS,SI + MOV AH,AL ;Make copy of drive number + XCHG AH,DS:LSTDRV ;Xchange with last drive used + CMP AL,AH ;See if same as last drive + JZ RDWR0 +;Using a different drive in a one drive system so request the user change disks + ADD AL,"A" ;Add "A" to convert to drive letter + MOV CS:DRVLET,AL + push cs + pop ds + MOV SI,OFFSET CS:SNGMSG + PUSH BX + CALL WRMSG ;Print disk change message + XOR AH,AH + INT 16H ;Wait for a keyboard character + POP BX +RDWR0: + POP DS + XOR AL,AL ;Always use drive 0 + RET + + +SNGMSG DB CR,LF,"Insert diskette for drive " +DRVLET DB "A: and strike",CR,LF,"any key when ready",CR,LF,LF,0 +HNUM DB 0 ;NUMBER OF HARDFILES + + +;** End of Permanently Resident BIOS + + +HARDDRV DB 80H ;Physical drive number of first hardfile +;********************************************************************** +; "HDRIVE" IS A HARD DISK WITH 512 BYTE SECTORS +;********************************************************************* +HDRIVE: + DW 512 + DB 1 ;Sectors/allocation unit + DW 1 ;Reserved sectors for DOS + DB 2 ;No. of allocation tables + DW 16 ;Number of directory entries + DW 0000 ;Number of sectors (at 512 bytes each) + DB 11111000B ;Media descriptor + DW 1 ;Number of FAT sectors + DW 00 ;Sector limit + DW 00 ;Head limit + DW 00 ;Hidden sector count +;********************************************************************** +; "DRIVEX " IS AN EXTRA TYPE OF DRIVE USUALLY RESERVED FOR AN +; ADDITIONAL HARD FILE +;********************************************************************* +DRIVEX: + DW 512 + DB 00 ;Sectors/allocation unit + DW 1 ;Reserved sectors for DOS + DB 2 ;No. of allocation tables + DW 0000 ;Number of directory entries + DW 0000 ;Number of sectors (at 512 bytes each) + DB 11111000B ;Media descriptor + DW 0000 ;Number of FAT sectors + DW 00 ;Sector limit + DW 00 ;Head limit + DW 00 ;Hidden sector count + +SUBTTL Bios initialization + ;********************************************************* +; SYSTEM INITIALIZATION +; +; THE ENTRY CONDITIONS ARE ESTABLISHED BY THE BOOTSTRAP +; LOADER AND ARE CONSIDERED UNKNOWN. THE FOLLOWING JOBS +; WILL BE PERFORMED BY THIS MODULE: +; +; 1. ALL DEVICE INITIALIZATION IS PERFORMED +; 2. A LOCAL STACK IS SET UP AND DS:SI ARE SET +; TO POINT TO AN INITIALIZATION TABLE. THEN +; AN INTER-SEGMENT CALL IS MADE TO THE FIRST +; BYTE OF THE DOS +; 3. ONCE THE DOS RETURNS FROM THIS CALL THE DS +; REGISTER HAS BEEN SET UP TO POINT TO THE START +; OF FREE MEMORY. THE INITIALIZATION WILL THEN +; LOAD THE COMMAND PROGRAM INTO THIS AREA +; BEGINNING AT 100 HEX AND TRANSFER CONTROL TO +; THIS PROGRAM. +; +;******************************************************** + +DRVFAT DW 0000 ;DRIVE AND FAT ID OF DOS +BIOS$ DW 0000 ;FIRST SECTOR OF DATA +DOSCNT DW 0000 ;HOW MANY SECTORS TO READ + +BootBufr EQU 17C0H ; High memory scratch area + + ASSUME DS:NOTHING,ES:NOTHING + +INIT: mov dx,1000h + MOV SS,DX + MOV SP,7C00h ;LOCAL STACK 1000:7C00 + STI + PUSH CX ;Save number of floppies + MOV [BIOS$],BX + PUSH AX ;Save Drive info + MOV AL,EOI + OUT AKPORT,AL ;TURN ON THE TIMER + + MOV SI,OFFSET LPT3DEV + CALL PRINT_INIT ;INIT LPT3 + MOV SI,OFFSET LPT2DEV + CALL PRINT_INIT ;INIT LPT2 + MOV SI,OFFSET LPT1DEV + CALL PRINT_INIT ;INIT LPT1 + + MOV SI,OFFSET COM2DEV + CALL AUX_INIT ;INIT COM2 + MOV SI,OFFSET COM1DEV + CALL AUX_INIT ;INIT COM1 +;* Can't do any DEBUG prints till now + debug 1,1,,<> + XOR DX,DX + MOV DS,DX ;TO INITIALIZE PRINT SCREEN VECTOR + MOV ES,DX + + MOV AX,CS ;FETCH SEGMENT + +IF CONSFLAG + MOV WORD PTR DS:BRKADR,OFFSET BREAK + MOV DS:BRKADR+2,AX ;VECTOR FOR BREAK + MOV WORD PTR DS:(CHROUT*4),OFFSET OUTCHR + MOV DS:(CHROUT*4+2),AX +ENDIF + MOV WORD PTR DS:DSKADR,SEC9 ;DISK PARAMETERS + MOV DS:DSKADR+2,ES + + MOV DI,4 + MOV BX,OFFSET INTRET ; Rest just return + XCHG AX,BX + STOSW ;Location 4 + XCHG AX,BX + STOSW ;INT 1 ;Location 6 + ADD DI,4 + XCHG AX,BX + STOSW ;Location 12 + XCHG AX,BX + STOSW ;INT 3 ;Location 14 + XCHG AX,BX + STOSW ;Location 16 + XCHG AX,BX + STOSW ;INT 4 ;Location 18 +; Set up some vectors for scheduler and change rom interrupts +; + CLI ; Disable, changing int vectors + ADD DI,3*4 ; Move up to INT 8 + MOV CX,OFFSET TimerInterrupt + XCHG AX,CX + STOSW + XCHG AX,CX + STOSW ; Set new INT 8: Timer +IF CONSFLAG + MOV CX,DS:[DI] ; Save old addr to hook to + MOV WORD PTR OldKeyInterrupt,CX + MOV CX,DS:2[DI] + MOV WORD PTR (OldKeyInterrupt+2),CX + MOV CX,OFFSET KeyboardInterrupt + XCHG AX,CX + STOSW + XCHG AX,CX + STOSW ; Set new keyboard interrupt +ELSE + ADD DI,4 +ENDIF + XCHG AX,BX + STOSW + XCHG AX,BX ; INT 0A unused + STOSW + XCHG AX,BX + STOSW + XCHG AX,BX ; INT 0B unused + STOSW + add di,4*6 ; skip 0C - 11 + MOV CX,DS:[DI] ; Save INT 12 addr to hook to + MOV WORD PTR memsizint,CX + MOV CX,DS:2[DI] + MOV WORD PTR (memsizint+2),CX + mov cx,offset memsizhandler + xchg ax,cx + stosw + xchg ax,cx + stosw + add di,4*2 ; skip 13 - 14 + STI +; End of new 3.0 vectors + XCHG AX,BX + STOSW ;INT 15 ;Location 60 + XCHG AX,BX + STOSW ;Location 62 +IF CONSFLAG + MOV CX,DS:[DI] ; Save INT 16 addr to hook to + MOV WORD PTR OldKbdHandler,CX + MOV CX,DS:2[DI] + MOV WORD PTR (OldKbdHandler+2),CX + MOV CX,OFFSET KeyboardHandler + XCHG AX,CX + STOSW + XCHG AX,CX ; Set new keyboard Handler + STOSW +; Set new get/set time vector, time base changed + ADD DI,4*3 ; skip 17 - 19 +ELSE + ADD DI,4*4 ; skip 16 - 19 +ENDIF ;CONSFLAG + MOV CX,OFFSET TimeOfDay + XCHG AX,CX + STOSW ; setup 1A to TimeofDay + XCHG AX,CX + STOSW + ADD DI,4*23 ; skip 1B - 31 + XCHG AX,BX + STOSW ; no-op INT 32 until Sched:SchedInit + XCHG AX,BX + STOSW + debug 1,1,,<> + + MOV DS:WORD PTR 500H,DX ;SET PRINT SCREEN & BREAK =0 + MOV DS:WORD PTR LSTDRV,DX ;clean out last drive spec + + MOV DI,SEC9 ;location of drive table + MOV AX,02DFH ;Stuff the disk speedup/9 sector + STOSW ;code + MOV AX,0225H + STOSW + MOV AX,2A09H + STOSW + MOV AX,50FFH + STOSW + MOV AX,00F6H + STOSW + MOV AL,2 + STOSB + + pushf ;simulate int 12h + call memsizint ;Get memory size--1K blocks in AX + MOV CL,6 + SHL AX,CL ;Convert to 16-byte blocks(segment no.) + POP CX ;Recall drive info + MOV [DRVFAT],CX ;SAVE DRIVE TO LOAD DOS + + MOV DX,SEG SYSINIT + MOV DS,DX + + ASSUME DS:SEG SYSINIT + + MOV MEMORY_SIZE,AX + INC CL + MOV DEFAULT_DRIVE,CL ;SAVE DEFAULT DRIVE SPEC + + add dx,SYSIZE + MOV CURRENT_DOS_LOCATION,dx ; load address of DOS + + MOV FINAL_DOS_LOCATION,SEG BiosInit + debug 1,2,, + MOV WORD PTR DEVICE_LIST,OFFSET CONDEV ;DS:SI = ptr to device list + MOV AX,CS + MOV WORD PTR DEVICE_LIST+2,AX +;************************************************************** +; WILL INITIALIZE THE NUMBER OF DRIVES +; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL +; THE INDICATIONS ARE AS FOLLOWS: +; +; BITS 7 6 DRIVES +; 0 0 1 +; 0 1 2 +; 1 0 3 +; 1 1 4 +;************************************************************** + PUSH CS + PUSH CS + POP DS + POP ES + + ASSUME DS:BiosSeg,ES:BiosSeg + + INT 11H ;GET EQUIPMENT STATUS + AND AL,11000000B ;MASK DRIVE BITS + JNZ NOTSNGL ;Zero means single drive system + INC [SINGLE] ;REMEMBER THIS +NOTSNGL: + POP AX ;BOOT specifies number of floppies + MOV [HARDNUM],AL ;Remember which drive is hard disk + MOV [DRVMAX],AL ;And set initial number of drives + MOV AH,8 + MOV DL,80H + INT 13H ;Request number of hardfiles attached + JC ENDDRV ;Carry indicates old rom, so no hardfile + MOV [HNUM],DL +ENDDRV: + MOV DL,80H + MOV DI,OFFSET CS:HDRIVE + CMP [HNUM],0 + JLE ITSOK1 + CALL SETHRD ;SET UP FIRST HARDFILE + + MOV DL,81H ;SET UP FOR NEXT CALL + MOV DI,OFFSET CS:DRIVEX + JC NOTOK + CMP [HNUM],2 + JZ SETIT + JMP SHORT ITSOK + +NOTOK: MOV [HARDDRV],DL + MOV DI,OFFSET CS:HDRIVE + DEC [HNUM] + CMP [HNUM],0 + JZ ITSOK1 +SETIT: CALL SETHRD ;SET UP SECOND HARDFILE + JNC ITSOK + DEC [HNUM] + +; End of drive initialization + +ITSOK: MOV AL,[HNUM] + OR AL,AL + JZ ITSOK1 + ADD AL,[HARDNUM] + MOV [DRVMAX],AL + MOV AL,[HNUM] + JMP SHORT ITSOK2 ;GO SET DESTINATION SEGMENT + +ITSOK1: CMP BYTE PTR [SINGLE],1 + JMP SHORT GOINIT + + ASSUME DS:BiosSeg + +ITSOK2: + DEC AL + +GOINIT: + debug 1,1,,<,drvfat> + PUSH CS + POP DS + + ASSUME DS:BiosSeg,ES:NOTHING + + CALL GETFAT ;READ IN THE FAT SECTOR + XOR DI,DI + MOV AL,ES:[DI] ;GET FAT ID BYTE + MOV BYTE PTR DRVFAT+1,AL ;SAVE FAT BYTE + debug 1,2,< FAT ID: $b ds:$x\n>, + MOV AX,[DRVFAT] + CALL GETBP ;GET DISK POINTER + MOV CL,[DI+2] ;GET SECTORS/CLUSTER + MOV AX,[DI].HIDSEC ;GET NUMBER OF HIDDEN SECTORS + SUB [BIOS$],AX ;SUBTRACT HIDDEN SECTOR OFFSET + XOR CH,CH ;CX = SECTORS/CLUSTER + PUSH DS + XOR DI,DI + MOV DS,DI +; +; THE BOOT PROGRAM HAS LEFT THE DIRECTORY AT 0:500 +; + MOV BX,DS:WORD PTR 53AH ;GET FIRST CLUSTER OF DOS + POP DS ;BX = FIRST CLUSTER OF DOS +LOADIT: MOV AX,SEG SYSINIT + add ax,SYSIZE + MOV ES,AX ;ES:DI POINTS TO LOAD LOCATION + CALL GETCLUS ;READ IN A CLUSTER + CMP BX,0FFFH + JNZ LOADIT ;END OF FILE? + + EXTRN Disk_Init:NEAR + call Disk_Init ; do some device driver initialization + debug 1,2,,<> + JMP SYSINIT + +SUBTTL Routines for reading in MSDOS + +; +; READ A FAT SECTOR INTO 17C0:0 +; +GETFAT: debug 1,2,,<> + XOR DI,DI + MOV CX,1 + MOV DX,CX + MOV AX,BootBufr + MOV ES,AX + MOV AL,BYTE PTR DRVFAT + MOV AH,0FCH + JMP DISKRD +; +; READ A BOOT RECORD INTO 17C0:0 +; +GETBOOT:debug 1,2,,<> + MOV CX,1 + MOV AX,0201H + MOV BX,BootBufr + MOV ES,BX + XOR BX,BX + MOV DH,BH + INT 13H + JC SETRET + CMP WORD PTR ES:[1FEH],0AA55H + JNZ SETRET + RET +; +; SETUP VARIABLE SIZED HARDFILE +; ON ENTRY DL=DRIVE NUMBER (80 OR 81) +; DI=PTR TO B.P.B +; +SETHRD: PUSH DX + MOV AH,8 ;GET DRIVE PARAMETERS + INT 13H + INC DH + MOV [DI].HDLIM,DH + POP DX + JC SETRET + AND CL,3FH + MOV [DI].SECLIM,CL + CALL GETBOOT ;GET THE BOOT RECORD + JC SETRET + MOV BX,1C2H +SET1: CMP BYTE PTR ES:[BX],1 + JZ SET2 + ADD BX,16 + CMP BX,202H + JNZ SET1 +SETRET: STC ;NOT FOUND SO USE DEFAULTS + RET + +SET2: MOV AX,ES:[BX+4] + MOV DS:[DI].HIDSEC,AX ;SET HIDDEN SECTOR COUNT + MOV AX,ES:[BX+8] + CMP AX,64 ;HAS TO BE AT LEAST 32K + JB SETRET + MOV DS:[DI].8,AX ;SAVE LOGICAL SECTOR COUNT + MOV CX,0100H ;SET CLUS SIZE AND SHIFT COUNT + MOV DX,64 ;SET NUMBER OF DIR ENTRIES + CMP AX,512 + JBE SET3 + + ADD CH,CH + INC CL + MOV DX,112 + CMP AX,2048 + JBE SET3 + + ADD CH,CH + INC CL + MOV DX,256 + CMP AX,8192 + JBE SET3 + + ADD CH,CH + INC CL + ADD DX,DX + CMP AX,32680 ;NOT 32768! MAX NUMBER OF CLUSTERS=4085 + JBE SET3 + + ADD CH,CH + INC CL + ADD DX,DX +SET3: +; +; DX=NUMBER OF DIR ENTRIES, CH=NUMBER OF SECTORS PER CLUSTER +; CL=LOG BASE 2 OF CH +; +; NOW CALCULATE SIZE OF FAT TABLE +; + MOV [DI].6,DX ;SAVE NUMBER OF DIR ENTRIES + MOV [DI].2,CH ;SAVE SECTORS PER CLUSTER + XOR BX,BX + MOV BL,CH + DEC BX + ADD BX,AX + SHR BX,CL ;DIVIDE BY SECTORS/CLUSTER + INC BX + AND BL,11111110B ;MAKE SURE COUNT IS EVEN + MOV SI,BX + SHR BX,1 + ADD BX,SI ;MULTIPY BY 1.5 + ADD BX,511 + SHR BH,1 + MOV [DI].11,BH ;SAVE NUMBER OF FAT SECTORS + CLC + RET +; +; READ CLUSTER SPECIFIED IN BX +; CX = SECTORS PER CLUSTER +; DI = LOAD LOCATION +; +GETCLUS:debug 1,2,, + PUSH CX + PUSH DI + MOV [DOSCNT],CX ;SAVE NUMBER OF SECTORS TO READ + MOV AX,BX + DEC AX + DEC AX + MUL CX ;CONVERT TO LOGICAL SECTOR + ADD AX,[BIOS$] ;ADD IN FIRST DATA SECTOR + MOV DX,AX ;DX = FIRST SECTOR TO READ + +GETCL1: CALL UNPACK ;SI = BX, BX = NEXT ALLOCATION UNIT + SUB SI,BX + CMP SI,-1 ;one apart? + JNZ GETCL2 + ADD [DOSCNT],CX + JMP GETCL1 + +GETCL2: PUSH BX + MOV AX,[DRVFAT] ;GET DRIVE AND FAT SPEC + MOV CX,[DOSCNT] + CALL DISKRD ;READ THE CLUSTERS + POP BX + POP DI + MOV AX,[DOSCNT] ;GET NUMBER OF SECTORS READ + XCHG AH,AL ;MULTIPLY BY 256 + SHL AX,1 ;TIMES 2 EQUAL 512 + ADD DI,AX ;UPDATE LOAD LOCATION + POP CX ;RESTORE SECTORS/CLUSTER + RET +; +; GET THE FAT ENTRY AT BX, WHEN FINISHED SI=ENTRY BX +; +UNPACK: PUSH DS + PUSH BX + MOV SI,BootBufr + MOV DS,SI + MOV SI,BX + SHR SI,1 + MOV BX,[SI+BX] + JNC HAVCLUS + SHR BX,1 + SHR BX,1 + SHR BX,1 + SHR BX,1 +HAVCLUS:AND BX,0FFFH + POP SI + POP DS + RET +; +; SI POINTS TO DEVICE HEADER +; +PRINT_INIT: + MOV BH,1 + MOV DL,17H + JMP SHORT DEV_INIT +AUX_INIT: + MOV BX,RSINIT + MOV DL,14H +DEV_INIT: + MOV CS:[INTNUM],DL + MOV AL,CS:[SI+13] ;GET DEVICE NUMBER FROM THE NAME + SUB AL,"1" + CBW + MOV DX,AX + MOV AX,BX ;SET THE CALL + DB 0CDH ;INT 17H +INTNUM DB 17H + RET + +END$: + +BiosInit ENDS + END diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ new file mode 100644 index 0000000..28d0720 Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ differ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM new file mode 100644 index 0000000..47869d0 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM @@ -0,0 +1,2551 @@ +TITLE DISK - MS-DOS 4.0 disk drivers for IBM +NAME DISK + + PAGE ,132 + +;DEBUGFLG=1 + +.xlist + INCLUDE DEFDBUG.INC +.list + +; Constants + +ErrLim= 5 ; Number of retries on error + +; Floppy delay constants + +DelayLoad= 35 ; 35 milliseconds to load head + +; Constants for floppy disk controller + +Rate99= 000H ; Step rate 96tpi disk in 96tpi drive +Rate49= 001H ; Step rate 48tpi disk in 96tpi drive +Rate44= 002H ; Step rate 48tpi disk in 48tpi drive + +; Commands to floppy disk controller + +FD_CRESET= 007H ; Recalibrate drive +FD_CSENSE= 008H ; Sense interrupt status +FD_CSEEK= 00FH ; Seek to another track +FD_CREAD= 046H ; MFM read, skip deleted data +FD_CWRITE= 045H ; MFM write, skip deleted data +FD_CSPEC= 003H ; Special - step rate, head load/unload + +; Status codes + +FD_SDIO= 01000000B ; Transfer direction (0 -> controller) +FD_SRQM= 10000000B ; Controller ready for next data + +; Hard disk controller commands +HD_CSENS= 03H ; request sense block +HD_CREAD= 08H ; read +HD_CWRITE= 0AH ; write + +HDcontrolbyte= 05H ; step rate = 70 us. + +; I/O ports + +FD_PSEL= 03F2H ; Controls drive select and motors +FD_PDAT= 03F5H ; Data transfer to/from controller +FD_PSTAT= 03F4H ; Controller status +FD_PCMD= 03F7H ; Controller command register + +HD_PDAT= 0320H ; read/write data +HD_PSTAT= 0321H ; controller status +HD_PSEL= 0322H ; controller select +HD_PMSK= 0323H ; DMA and interrupt mask bits + +PDMA= 0 ; Base of ports for DMA control +PDMAX= 7FH ; Address extension regs for DMA + ;NOTE base address suitable for ch. 2 & 3 only +FD_DMA= 2 ; floppy disk DMA channel +HD_DMA= 3 ; hard disk DMA channel + +DMA_READ= 44H ; DMA read command +DMA_WRITE= 48H ; DMA write command + +; Misc + +DORmask= 00CH ; Not reset, enable DMA & interrupt + + + +SUBTTL Data for performing requests +PAGE + + +;* Dos Request Packet structure + +DosPacket STRUC + RqCmdLen DB 0 ; Length of this command + RqUnit DB 0 ; Unit in this driver + RqCmd DB 0 ; Command to do + RqStatus DW 0 ; Status of request + DD 0 + DD 0 ; Not used + RqMedia DB 0 ; Media descriptor + RqAddr DW 0 ; Offset of data + DW 0 ; Segment of data + RqCount DW 0 ; Number of sectors + RqFirst DW 0 ; First sector to do +DosPacket ENDS + +; The disk drivers work as a state machine performing the various actions +; that make up disk I/O. + +; Driver states +; The following states are common to both drivers +Start= 0 ; Starting I/O +Calc= 1 ; Calculate position on disk +Done= 7 ; I/O is done +Idle= 8 ; Drive is inactive +Error= 9 ; Have an error +; The following states are used by the floppy driver only +Select= 2 ; Select drive, start motor, seek +Recal= 3 ; Drive was just recalibrated +Seek= 4 ; Seek just finished +Settle= 5 ; Head has settled +RdWri= 6 ; Read/write is done +; The following states are used by the fixed driver only +Verify= 6 ; Start verify portion of write + + +DeviceStruc STRUC + State DW Idle ; Current drive state + Current DW -1 ; Current active drive + ErrCnt DB 0 ; # of errors in doing request + Flags DB 0 ; Various bit flags, see below + DOR DB 0 ; Copy of select/motor reg +; Following values are set by Setup from the request packet and are +; updated after each transfer is completed. + Unit DB 0 ; Unit + First DW 0 ; 1st sector of request + RealAddr DD 0 ; Real addr of data when Addr is + ; scratch buffer. + Count DW 0 ; Number of sectors to xfer +; Following values are set by MapSector. + Cyl DW 0 ; Cylinder + Sector DB 0 ; Sector - zero based + Head DB 0 ; Head + NumSectors DW 0 ; Number of sectors to do + NumBytes DW 0 ; Number of bytes + Addr DD 0 ; Pointer to data buffer +; Device dependent data + ST0 DB 0 ; floppy controller ST0 + ST1 DB 0 ; floppy controller ST1 + ST2 DB 0 ; floppy controller ST2 + CHRN DB 0,0,0,0 ; other floppy status returns +DeviceStruc ENDS + DCB EQU ST0 ; Fixed disk Device Control Block + +; Bits in Flags + + Factive= 1 ; Actively working on something + F2step= 2 ; Must double step when seeking + Fwrite= 4 ; This is a write, not a read + Fverify= 8 ; This is a verify, not a rd/wr + Fwrap1= 010H ; We are currently using ScratchBuffer + Fwrap2= 020H ; We have used ScratchBuffer in this req + +BiosSeg GROUP Code,BiosInit + +Code SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:BiosSeg + +IFDEF DEBUGFLG + EXTRN BUGBITS:BYTE,DPRINTF:NEAR +ENDIF + +SUBTTL Device data +PAGE + + +Floppy DeviceStruc <> +Fixed DeviceStruc <> + +;* Per drive information, including BPBs + +DriveStruc STRUC + BPBsecsiz DW 512 ; Physical sector size + BPBsecpau DB 1 ; Sectors/Allocation unit + BPBressec DW 1 ; Reserved sectors for DOS + BPBnfat DB 2 ; # of allocation tables + BPBndir DW 64 ; # of directory entries + BPBnsec DW 9*40 ; Number of sectors + BPBmediab DB 0FCH ; Media descriptor + BPBnfatsec DW 2 ; # of FAT sectors + BPBtrksiz DW 9 ; # of sectors/track + BPBnhead DW 1 ; # of heads + BPBhidsec DW 0 ; Hidden sector count + Timer DB 0 ; Countdown for motor off + DrvFlag DB 1 ; Per-drive flags, see below + TPI DB 0 ; Drive TPI= Not present, 48, 96 + CurCyl DW -1 ; Current cylinder +DriveStruc ENDS + +; DrvFlag values +Frestor= 1 ; restore needed +Fmotoron= 2 ; motor is on + +DriveA DriveStruc <> ; floppy drive 0 +DriveB DriveStruc <> ; floppy drive 1 or 0 +DriveC DriveStruc <> ; hard drive 0 or floppy drive 2 +DriveD DriveStruc <> ; hard drive 1 or floppy drive 3 + +FDinfo DW DriveA + DW DriveB +HDinfo DW DriveC + DW DriveD + + +; Structure of parameter block for floppy pointed to by 0:4*1E + +FloppyParameter STRUC + Spec1 DB 0 ; 0 1st byte for specify cmd + Spec2 DB 0 ; 1 2nd byte for specify cmd + DelayOff DB 0 ; 2 # of Ticks(1/18.2) until + ; motor shut off + SectorSize DB 0 ; 3 Sector size(128,256,512,1024) + ; = (O,1,2,3 are put here) + CylSize DB 0 ; 4 Number of sectors/cylinder + DataGap DB 0 ; 5 Gap length of read/write + ValueDTL DB 0 ; 6 Data length (ignored) + FormatGap DB 0 ; 7 Gap for format operation + FormatFill DB 0 ; 8 Fill char for format + DelaySettle DB 0 ; 9 Head settle time in msec + DelayMotor DB 0 ; 10 Motor start time in 1/8 sec +FloppyParameter ENDS + + +ScratchBuffer DB 512 DUP(?) ; Scratch buffer for when DMA fails + ; Hope we don't handle >512 sector + ; size + +;* Miscellaneous data + +Single DB 0 ; non-zero if 1 floppy disk system + ; in this case, NumFloppy will be 2 + +SUBTTL Data for interface to 4.0 +PAGE + + + EXTRN DosFunction:DWORD ; Addr of DOS function routine + +; Dos helper functions used by disk driver + + PullRequest = 2 ; Pull a request from the queue + PushRequest = 4 ; Add a request to the queue + BlockProcess = 9 ; Block process until I/O done + ContinueProcess = 10 ; I/O done, continue process + +int_savregs= 32H ; interrupt routine which saves all regs + + +SwapSem1 DB 0 ; non-zero if waiting to swap disks +SwapSem2 DB 0 ; non-zero if waiting to prompt for swap +ScratchBufSem DB 0 ; semaphore controlling ScratchBuffer + +SEM_WANT= 2 +SEM_BUSY= 1 + +SemWait Macro wchan +local l1,l2 + pushf +l1: cli + test wchan,SEM_BUSY ;;semaphore busy? + jz l2 ;;no + or wchan,SEM_WANT ;;say we want it + mov ax,cs + mov bx,OFFSET wchan + xor cx,cx + mov dx,BlockProcess + call [DosFunction] ;;wait till semaphore released + jmp l1 +l2: or wchan,SEM_BUSY ;;claim semaphore + popf + endm + +SemSig Macro wchan +local l + test wchan,SEM_WANT ;;anyone waiting on semaphore? + jz l + mov ax,cs + mov bx,OFFSET wchan + mov dx,ContinueProcess + call [DosFunction] +l: and wchan,NOT (SEM_WANT+SEM_BUSY) + endm + + +FloppyQueue DD 0 ; List of requests for floppy +FixedQueue DD 0 ; List of requests for fixed disk + +; Device driver headers + + PUBLIC FloppyDevice +FloppyDevice LABEL WORD + DD FixedDevice ; Next device is hard disk + DW 100000B ; This is 4.0 driver + DW JustReturn ; Strategy does nothing + DW FloppyRequest ; Interrupt does the work +NumFloppy DB 4 ; Handle 4 floppys maximum + DB 0 ; can be addressed as word also + + EXTRN Com1Dev:NEAR + +FixedDevice LABEL WORD + DD Com1Dev ; Next device is comm port 1 + DW 100000B ; This is 4.0 driver + DW JustReturn ; Strategy does nothing + DW FixedRequest ; Interrupt does work (misnomer) +NumFixed DB 0 ; Handle 2 hard disks maximum + + +; Utility routines which reside in the BIOS main module + + EXTRN Interrupt:NEAR ; BIOS interrupt routine(misnomer) + EXTRN CmdErr:NEAR + EXTRN StatusDevReady:NEAR + EXTRN StatusComplete:NEAR + EXTRN StatusError:NEAR + EXTRN SetStatus:NEAR + +JustReturn PROC FAR + RET +JustReturn ENDP + +FloppyRequest PROC FAR + debug 4,2,,> + PUSH SI + LEA SI,FloppyFunction ; 4.0 function routines + JMP Interrupt ; Let BIOS figure out what to do +FloppyRequest ENDP + +; Dispatch table for actions of the floppy requested by 4.0 + +FloppyFunction LABEL WORD + DW FloppyInit ; 0 Initialize + DW FloppyCheck ; 1 Check media + DW FloppyBuild ; 2 Build BPB + DW CmdErr ; 3 IOCTL input + DW FloppyRead ; 4 Read + DW StatusDevReady ; 5 Non-destructive read + DW StatusComplete ; 6 Input status + DW StatusComplete ; 7 Input flush + DW FloppyWrite ; 8 Write + DW FloppyWriteV ; 9 Write with verify + DW CmdErr ; 10 Output status + DW CmdErr ; 11 Output flush + DW CmdErr ; 12 IOCTL output + DW CmdErr ; 13 Device open + DW CmdErr ; 14 Device close + DW CmdErr ; 15 Removable media + DW CmdErr ; 16 Generic IOCTL request + +FixedRequest PROC FAR + debug 8,2,,> + PUSH SI + LEA SI,FixedFunction ; 4.0 function routines + JMP Interrupt ; Let BIOS figure out what to do +FixedRequest ENDP + +; Dispatch table for actions of the hard disk requested by 4.0 + +FixedFunction LABEL WORD + DW FixedInit ; 0 Initialize + DW FixedCheck ; 1 Check media + DW FixedBuild ; 2 Build BPB + DW CmdErr ; 3 IOCTL input + DW FixedRead ; 4 Read + DW StatusDevReady ; 5 Non-destructive read + DW StatusComplete ; 6 Input status + DW StatusComplete ; 7 Input flush + DW FixedWrite ; 8 Write + DW FixedWriteV ; 9 Write with verify + DW CmdErr ; 10 Output status + DW CmdErr ; 11 Output flush + DW CmdErr ; 12 IOCTL output + DW CmdErr ; 13 Device open + DW CmdErr ; 14 Device close + DW CmdErr ; 15 Removable media + DW CmdErr ; 16 Generic IOCTL request + + +SUBTTL Data for routines that make direct Int 13 requests +PAGE + + + +RealInt13Vec dw 0 ; Used to make Int 13 requests + dw 0 +OldIntDVec dw 0 ; Must be reset when Int 13's on hard + dw 0 ; disk. +OldIntEVec dw 0 ; Must be reset when Int 13's on floppy + dw 0 ; disk. +SemDiskIO db 0 ; Semaphore controlling disk io +SemInt13 db 0 ; Semaphore controlling Int 13's + + +SUBTTL 4.0 device driver routines (system entry points) +PAGE + + +BiosInit SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:BiosSeg + + PUBLIC Disk_Init +Disk_Init PROC +;************************************************************** +; This routine performs device dependent initialization +; during the BIOS initialization. Not to be confused +; with the device initialization entry points which are +; called later on and perform different functions. +; +; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL +; THE NUMBER OF FLOPPY DISKS IN THE SYSTEM. +; THE INDICATIONS ARE AS FOLLOWS: +; +; BITS 7 6 DRIVES +; 0 0 1 +; 0 1 2 +; 1 0 3 +; 1 1 4 +;************************************************************** + + debug 12,1,,<> + PUSH CS + POP DS + + ASSUME DS:BiosSeg + INT 11H ;GET EQUIPMENT STATUS + rol al,1 ; rotate around to low order bits + rol al,1 + AND AL,11B ;MASK DRIVE BITS + JNZ NOTSNGL ;Zero means single drive system + INC [SINGLE] ;REMEMBER THIS + inc al ; make it look like two-drive system +NOTSNGL: + inc al + MOV [NumFloppy],AL ;Remember how many drives + MOV AH,8 + MOV DL,80H + INT 13H ;Request number of hardfiles attached + JC ENDDRV ;Carry indicates old rom, so no hardfile + MOV [NumFixed],DL + test dl,dl ; any specified? + jz ENDDRV ; no + cmp NumFloppy,2 ; too many floppies? + jbe ENDDRV + mov NumFloppy,2 ; limit to two floppies max. +ENDDRV: + +;* Initialize the hard disk BPBs + + MOV DL,80H + MOV DI,OFFSET DriveC + CMP [NumFixed],0 + JLE ITSOK + CALL SETHRD ;SET UP FIRST HARDFILE + + MOV DL,81H ;SET UP FOR NEXT CALL + MOV DI,OFFSET DriveD + JC NOTOK + CMP [NumFixed],2 + JZ SETIT + JMP SHORT ITSOK +NOTOK: + MOV DI,OFFSET DriveC + DEC [NumFixed] + CMP [NumFixed],0 + JZ ITSOK +SETIT: CALL SETHRD ;SET UP SECOND HARDFILE + JNC ITSOK + DEC [NumFixed] +ITSOK: + cmp [NumFixed],0 ; any hard disks found? + jnz itsok2 ; yes + mov ax,[FixedDevice] ; no, patch device chain to skip fixed disk + mov [FloppyDevice],ax +itsok2: + push es ; Install Int 13 handler and save the + xor ax,ax ; old value of the interrupt vector. + mov es,ax + mov ax,es:[4*13h] + mov [RealInt13Vec],ax + mov ax,OFFSET Int13Handler + mov es:[4*13H],ax + mov ax,es:[4*13h+2] + mov [RealInt13Vec+2],ax + mov es:[4*13H+2],cs + mov ax,es:[4*0dh] ; Save original Int D vector + mov [OldIntDVec],ax + mov ax,es:[4*0dh+2] + mov [OldIntDVec+2],ax + mov ax,es:[4*0eh] ; Save original Int E vector + mov [OldIntEVec],ax + mov ax,es:[4*0eh+2] + mov [OldIntEVec+2],ax + pop es + ret +Disk_Init ENDP + +; +; READ A BOOT RECORD INTO Scratch buffer +; +GETBOOT: + MOV CX,1 + MOV AX,0201H + push CS + pop es + mov BX,OFFSET ScratchBuffer + xor DH,DH + INT 13H + JC SETRET + CMP WORD PTR ES:[BX+1FEH],0AA55H + JNZ SETRET + RET +; +; SETUP VARIABLE SIZED HARDFILE +; ON ENTRY DL=DRIVE NUMBER (80 OR 81) +; DI=PTR TO B.P.B +; +SETHRD: PUSH DX + MOV AH,8 ;GET DRIVE PARAMETERS + INT 13H + INC DH + MOV BYTE PTR [DI].BPBnhead,DH + POP DX + JC SETRET + AND CL,3FH + MOV BYTE PTR [DI].BPBtrksiz,CL + CALL GETBOOT ;GET THE BOOT RECORD + JC SETRET + add BX,1C2H + mov cx,4 +SET1: CMP BYTE PTR ES:[BX],1 + JZ SET2 + ADD BX,16 + loop SET1 +SETRET: STC ;NOT FOUND SO USE DEFAULTS + debug 8,3,, + RET + +SET2: MOV AX,ES:[BX+4] + MOV DS:[DI].BPBhidsec,AX ;SET HIDDEN SECTOR COUNT + MOV AX,ES:[BX+8] + CMP AX,64 ;HAS TO BE AT LEAST 32K + JB SETRET + MOV DS:[DI].BPBnsec,AX ;SAVE LOGICAL SECTOR COUNT + MOV CX,0100H ;SET CLUS SIZE AND SHIFT COUNT + MOV DX,64 ;SET NUMBER OF DIR ENTRIES + CMP AX,512 + JBE SET3 + + ADD CH,CH + INC CL + MOV DX,112 + CMP AX,2048 + JBE SET3 + + ADD CH,CH + INC CL + MOV DX,256 + CMP AX,8192 + JBE SET3 + + ADD CH,CH + INC CL + ADD DX,DX + CMP AX,32680 ;NOT 32768! MAX NUMBER OF CLUSTERS=4085 + JBE SET3 + + ADD CH,CH + INC CL + ADD DX,DX +SET3: +; +; DX=NUMBER OF DIR ENTRIES, CH=NUMBER OF SECTORS PER CLUSTER +; CL=LOG BASE 2 OF CH +; +; NOW CALCULATE SIZE OF FAT TABLE +; + MOV [DI].BPBndir,DX ;SAVE NUMBER OF DIR ENTRIES + MOV [DI].BPBsecpau,CH ;SAVE SECTORS PER CLUSTER + XOR BX,BX + MOV BL,CH + DEC BX + ADD BX,AX + SHR BX,CL ;DIVIDE BY SECTORS/CLUSTER + INC BX + AND BL,11111110B ;MAKE SURE COUNT IS EVEN + MOV SI,BX + SHR BX,1 + ADD BX,SI ;MULTIPY BY 1.5 + ADD BX,511 + SHR BH,1 + MOV BYTE PTR [DI].BPBnfatsec,BH ;SAVE NUMBER OF FAT SECTORS + MOV [DI].BPBmediab,0F8H ; set media byte + CLC + RET +BiosInit ENDS + + ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING + +FloppyInit PROC + debug 4,3,,<> + push ds ; install floppy interrupt routine + xor ax,ax + mov ds,ax + mov ax,OFFSET FloppyInterrupt + mov ds:[4*0eH],ax + mov ds:[4*0eH+2],cs + pop ds + call Rst765 + mov ah,[NumFloppy] + mov di,OFFSET FDinfo +DBBEG 4,3 + jmp SHORT iniret +DBEND + jmp bpbret +ELSE + jmp SHORT bpbret +ENDIF +FloppyInit ENDP + +FixedInit PROC + debug 8,3,,<> + push ds ; install fixed disk interrupt routine + xor ax,ax + mov ds,ax + mov ax,OFFSET FixedInterrupt + mov ds:[4*0dH],ax + mov ds:[4*0dH+2],cs + pop ds + in al,21H ; unmask fixed disk interrupts + and al,0DFH + out 21H,al + mov dx,HD_PMSK ; set interrupt and DMA mask bits + mov al,3 + out dx,al + mov ah,[NumFixed] + mov di,OFFSET HDinfo +DBBEG 8,3 +iniret: debug 12,3,< - Num=$x BPB table=$x:$x\n>, +DBEND +ENDIF + jmp SHORT bpbret +FixedInit ENDP + +FloppyBuild PROC + mov ah,byte ptr es:[di] + call FDGetBPB +bpbret: mov [bx.RqMedia],ah + mov [bx.RqCount],di + mov [bx.RqCount+2],CS + jmp StatusComplete +FloppyBuild ENDP + +FixedBuild PROC + mov ah,byte ptr es:[di] + call HDGetBPB + jmp SHORT bpbret +FixedBuild ENDP + +;*** FloppyCheck - check to see if the disk may have been changed. +; +; ENTRY AL = unit # +; AH = media byte +; EXIT Return value in request header set to one of: +; 1 Media may have been changed +; 0 Media not changed +; -1 Media was probably changed +; + +FloppyCheck PROC + MOV DL,1 ; Assume not changed + cmp AH,0f8H ; Is disk removable? + JE FloppyCheckDone ; No, can't be changed then + cmp Single,0 ; single drive system? + je flchk1 ; no, check drive state + cmp Floppy.Unit,al ; unit = current drive? + je flchk1 ; yes, check drive state + mov DL,-1 ; say media changed for sure + jmp FloppyCheckDone +flchk1: MOV CX,AX + XOR CH,CH + MOV SI,CX + ADD SI,SI + MOV SI,FDinfo[SI] ; Get pointer to drive info + TEST CS:[SI].DrvFlag,Fmotoron ; Is motor on? + JNZ FloppyCheckDone ; Yes, media not changed then + XOR DL,DL ; No, might have been changed +FloppyCheckDone: + MOV BYTE PTR DS:[BX].RqAddr,DL + JMP StatusComplete ; Return whether media changed +FloppyCheck ENDP + + +FixedCheck PROC + MOV DL,1 + JMP FloppyCheckDone +FixedCheck ENDP +;*** FloppyRead, FloppyWrite, FloppyWriteV - Basic I/O entry points +; +; FloppyRead, FloppyWrite and FloppyWriteV are the basic I/O +; routines used by the DOS. They really do not do much except +; queue the request and start the device if it is idle. +; For single drive floppy systems, they also handle the +; switching of disks when I/O changes from A to B or vice-versa. +; +; ENTRY DS:BX Packet address +; ES:DI Transfer address +; AL Unit # +; AH Media Byte +; CX # of sectors +; DX Starting sector +; +; EXIT DS:BX Packet Addr +; CX # of sectors left to do +; +; USES SI + +FloppyRead LABEL NEAR +FloppyWrite LABEL NEAR +FloppyWriteV PROC + debug 4,2,, + call BlockIfLocked + push di + call FDGetBPB ; cs:di => BPB + mov si,dx + add si,cx ; compute last sector + 1 + cmp si,cs:[di.BPBnsec] + mov si,di + pop di + jbe flrw1 + mov al,8 ; ERROR - Sector not found + jmp StatusError + +flrw1: OR CX,CX ; Anything to do? + JNZ flrw2 ; Yes + JMP StatusComplete ; No, all done now +flrw2: + CMP Single,0 ; Is this a single drive system? + JE flrw3 ; No, don't check for drive change + CALL FloppyChange ; See if should change disks +flrw3: + call CheckWrap + push ds + pop es ; ES:BX = Request addr + push cs + pop ds + LEA SI,FloppyQueue ; DS:SI = ptr to head of queue + MOV DX,PushRequest + CALL DosFunction ; Add request to list + push es + pop ds ; Back to DS:BX is request + pushf + cli ; interrupts off while testing state + TEST Floppy.Flags,Factive ; Is driver active? + JNE FloppyActive ; Yes, driver will get to it + PUSH DS + PUSH BX ; Save some regs + OR Floppy.Flags,Factive + MOV Floppy.State,Start ; Want to start I/O + CALL FloppyExecute ; Start up the driver + POP BX + POP DS ; Restore regs +flrw4: test DS:[BX].RqStatus,0100H ; IO completed? + JNZ FloppyIOdone ; yes + +FloppyActive: + MOV AX,DS ; AX:BX = request + xor cx,cx + push bx + MOV DX,BlockProcess + CALL DosFunction ; Block until I/O is done + pop bx + jmp flrw4 ; test completion status again +FloppyIOdone: + popf + MOV AX,DS:[BX].RqStatus ; Need AX = status + MOV CX,DS:[BX].RqCount ; Need CX = count left to do + debug 4,2,, + JMP SetStatus ; Return to DOS with results +FloppyWriteV ENDP + + +FixedRead LABEL NEAR +FixedWrite LABEL NEAR +FixedWriteV PROC + debug 8,2,, + call BlockIfLocked + push di + call HDGetBPB ; cs:di => BPB + mov si,dx + add si,cx ; compute last sector + 1 + cmp si,cs:[di.BPBnsec] + mov si,di + pop di + jbe fxrw1 + mov al,8 ; ERROR - Sector not found + jmp StatusError + +fxrw1: OR CX,CX ; Anything to do? + JNZ fxrw2 ; Yes + JMP StatusComplete ; No, all done now +fxrw2: + call CheckWrap + push ds + pop es ; ES:BX = Request addr + push cs + pop ds + LEA SI,FixedQueue ; DS:SI = ptr to head of queue + MOV DX,PushRequest + CALL DosFunction ; Add request to list + push es + pop ds ; Back to DS:BX is request + pushf + cli ; interrupts off while testing state + TEST Fixed.Flags,Factive ; Is driver active? + JNE FixedActive ; Yes, driver will get to it + PUSH DS + PUSH BX ; Save some regs + OR Fixed.Flags,Factive + MOV Fixed.State,Start ; Want to start I/O + CALL FixedExecute ; Start up the driver + POP BX + POP DS ; Restore regs +fxrw4: test DS:[BX].RqStatus,0100H ; IO completed? + JNZ FixedIOdone ; yes + +FixedActive: + MOV AX,DS ; AX:BX = request + xor cx,cx + push bx + MOV DX,BlockProcess + CALL DosFunction ; Block until I/O is done + pop bx + jmp fxrw4 ; test completion status again +FixedIOdone: + popf + MOV AX,DS:[BX].RqStatus ; Need AX = status + MOV CX,DS:[BX].RqCount ; Need CX = count left to do + debug 8,2,, + JMP SetStatus ; Return to DOS with results +FixedWriteV ENDP + +;*** CheckWrap - check whether a request crosses a 64Kb boundary +; +; CheckWrap will check whether the request given in DS:BX +; crosses a 64Kb boundary. A portion of such requests must +; be done using ScratchBuffer for a single sector transfer. +; This routine ensures that only one such request is put into +; either of the request queues at any time. +; +; ENTRY DS:BX Request header +; ES:DI Transfer address +; CS:SI Pointer to BPB +; CX Sector count +; EXIT When it's safe to proceed. +; USES AX,BP + +CheckWrap PROC + push dx + push cx + mov ax,cx + mul cs:[si.BPBsecsiz] + mov dx,es ; compute offset + mov cl,4 + shl dx,cl + add dx,di + clc ; now see if offset+nbytes overflows + add dx,ax + jnc chkw8 + debug 12,10h,, + push bx + SemWait ScratchBufSem ; wait for ScratchBuffer to be available + pop bx + +chkw8: pop cx + pop dx + ret +CheckWrap ENDP + + +;*** FloppyChange - check whether floppy disk must be changed +; +; FloppyChange is called on a single drive system to simulate a +; two drive system. The current request for I/O is checked against +; what the driver considers to be the current drive. If they are +; the same, FloppyChange just returns. Otherwise, SwapSem2 is set +; and the current process is blocked on SwapSem2. Any process that +; attempts I/O while SwapSem2 is set is blocked on SwapSem1. When +; SwapSem2 is cleared, these processes are continued. When the +; driver becomes idle and SwapSem2 is set, the Idle state continues +; the blocked process. This process then puts out the message about +; switching disks and waits for a user reply. When it is given, +; FloppyChange clears SwapSem1 and causes the I/O to be started. +; +; ENTRY DS:BX Pointer to I/O request +; +; USES AX,DX +; + + +FloppyChange PROC + push cx + pushf + push bx + SemWait SwapSem1 ; Currently waiting to switch disk? + pop bx + +flcha1: and SwapSem1,NOT SEM_BUSY ; reset BUSY for now + MOV AL,DS:[BX].RqUnit ; Get desired unit + CMP AL,Floppy.Unit ; Switching A and B drive? + JE flcha7 ; No, keep using this drive + CLI ; ** Disable interrupts + OR SwapSem1,SEM_BUSY ; Flag waiting to switch + test Floppy.Flags,Factive ; Is driver idle? + JE flcha2 ; Yes, don't need to wait + push bx + SemWait SwapSem2 + pop bx + jmp flcha1 +flcha2: + popf ; restore interrupt state + pushf + ADD AL,"A" ; Convert to drive letter + MOV CS:DriveLetter,AL ; Set the letter + PUSH DS + PUSH SI + push bx + push cs + pop ds + LEA SI,SwitchMsg +flcha4: + LODSB + OR AL,AL ; End of message? + JZ flcha5 ; Yes + INT 29H ; No, output char + JMP flcha4 ; Put out whole msg + +flcha5: + mov ah,1 ; Flush keyboard input + int 16H + jz flcha5 + XOR AH,AH + INT 16H ; Wait for a char + pop bx + POP SI + POP DS +flcha7: + push bx + SemSig SwapSem1 ; Allow blocked processes to continue + pop bx +flcha8: + popf + pop cx + RET + +FloppyChange ENDP + + +SwitchMsg LABEL WORD + DB 13,10,"Insert diskette for drive " +DriveLetter LABEL BYTE + DB "A: and strike",13,10,"any key when ready",13,10,10,0 + + +Int13Handler Proc Far + push dx ; Save regs used in local processing + push cx + push bx + push ax + pushf +LockCheck: + cli ; If any Int 13 request is already + cmp SemInt13,0 ; pending, block this process until + jz NotLocked ; the previous one finishes. + mov ax,cs + mov bx,offset SemInt13 + xor cx,cx + mov dx,BlockProcess + call DosFunction + jmp LockCheck +NotLocked: + mov SemInt13,1 ; Lock out other disk requests + popf + pushf +BusyCheck: + cli + cmp SemDiskIO,0 ; If the disks are busy, block this + jz DiskFree ; process till they free up. + mov ax,cs + mov bx,offset SemDiskIO + xor cx,cx + mov dx,BlockProcess + call DosFunction + jmp BusyCheck +DiskFree: + popf + sti + pop ax ; Restore regs for call + pop bx + pop cx + pop dx + push dx + push cx + push bx + pushf + call dword ptr [RealInt13Vec] + mov SemInt13,0 + push ax + pushf + mov ax,cs ; Unblock anything that is waiting + mov bx,offset SemInt13 + mov dx,ContinueProcess + call DosFunction + popf ; Restore user regs + pop ax + pop bx + pop cx + pop dx + ret 2 +Int13Handler endp + + +SUBTTL Fixed disk startup routine +PAGE + + +; FixedExecute processes a disk request after it has been set up. When the +; disk is inactive (State = Idle), it is called to start the device. For all +; subsequent events, it is called on the disk interrupt which signaled the +; completion of that subfunction. Some states do not involve waiting for an +; interrupt to occur. This routine runs entirely off the 'Fixed' data structure + +FixedDispatch LABEL WORD + DW FxExStart + DW FxExCalc + DW FxExError ;; BUGBUG really error in state machine + DW FxExError ;; BUGBUG really error in state machine + DW FxExError ;; BUGBUG really error in state machine + DW FxExError ;; BUGBUG really error in state machine + DW FxExVerify + DW FxExDone + DW FxExIdle + DW FxExError + +FixedExecute PROC + push cs ; CS -> DS + pop ds + ASSUME DS:BiosSeg + MOV BX,Fixed.State ; Get current state + debug 8,4,, + ADD BX,BX + JMP FixedDispatch[BX] ; Dispatch to correct routine + + +;* Fixed state Start +; +; Do setup calculations to figure out sector, start +; up motor, advance to Calc state. +; +; Entered on initially picking up a new request to do and on error retries. +; If error retries start here, then multiple sector requests will always start +; at the beginning rather than at the point of the error! Why? + +FxExStart: + mov si,OFFSET Fixed ; SI = pointer to per-device info. + les bx,FixedQueue ; ES:BX = pointer to current request + mov al,es:[bx].RqUnit + call HDGetBPB ; DI = drive parameters + CALL Setup ; Do setup calculations + MOV Fixed.State,Calc ; Advance to next state + JMP FixedExecute ; Now return to do Calc code + + + +;* Fixed state Calc +; +; Calculate cylinder, head and sector, wait for motor +; start or head load, advance to Select state. +; +; Entered after Start state and also on further sectors of a multiple sector +; request. + +FxExCalc: + mov si,OFFSET Fixed ; SI = pointer to per-device info. + les bx,FixedQueue ; ES:BX = pointer to current request + mov al,es:[bx].RqUnit + call HDGetBPB ; DI = drive parameters + CALL MapSector ; Get head, cylinder and sector + test Fixed.Flags,Fwrite + jnz fxxc1 + mov al,DMA_read + mov Fixed.DCB,HD_CREAD + jmp SHORT fxxc2 +fxxc1: mov al,DMA_write + mov Fixed.DCB,HD_CWRITE +fxxc2: mov ah,HD_DMA + call DMAsetup ; set up DMA transfer + mov al,Fixed.Unit + mov cl,5 + shl ax,cl + or al,Fixed.Head + mov Fixed.DCB+1,al ; set head/unit + mov ax,Fixed.cyl + mov Fixed.DCB+3,al ; set low cylinder + shr ax,1 + shr ax,1 + and al,0C0H + or al,Fixed.Sector + mov Fixed.DCB+2,al ; set high cylinder/sector + mov al,BYTE PTR Fixed.Numsectors + mov Fixed.DCB+4,al ; set sector count + mov Fixed.DCB+5,HDcontrolbyte ;BUGBUG - what do we want here? + mov al,3 + call HDCommand + mov al,Done ; assume next state is Done + test Fixed.Flags,Fverify + jz fxxc3 + mov al,Verify +fxxc3: mov BYTE PTR Fixed.State,al ; set next state + ret + + +;* Fixed state Verify +; +; Have executed a write function, must now verify. +; BUGBUG For now just go to done state. + +FxExVerify: + mov Fixed.State,Done + jmp FixedExecute + + + +;* Fixed state Done +; +; If whole request is now complete, mark the request +; as done and then start the next one if there is one. If the request is not +; yet done, adjust values to show the amount of the request done and then go +; back to the Calc state to do next part. + +FxExDone: + MOV AL,Fixed.Flags + AND AL,Fwrite+Fwrap1 ; Only interested in these bits + CMP AL,Fwrap1 ; Just read into scratch? + JNE fxxd1 ; No + PUSH DS + PUSH ES + MOV CX,Fixed.NumBytes ; CS = # bytes to write from scr + LES DI,Fixed.RealAddr ; ES:DI = real buffer + LDS SI,Fixed.Addr ; DS:SI = scratch buffer + CLD + REP MOVSB ; Copy into real buffer + POP ES + POP DS +fxxd1: + MOV AX,Fixed.NumSectors ; AX = # of sectors we did + SUB Fixed.Count,AX ; Adjust count to number left + JZ fxxd3 ; Request is done, tell DOS + ADD Fixed.First,AX ; Advance sector number + MOV AX,Fixed.NumBytes ; Number of bytes handled + ADD WORD PTR Fixed.RealAddr,AX ; Advance data address + MOV Fixed.State,Calc ; Go to Calc state +fxexj4: JMP FixedExecute + +fxxd3: + mov DI,OFFSET Fixed + mov SI,OFFSET FixedQueue ; DS:SI = head of queue + call DoneRequest + JMP fxexj4 + + +;* Fixed state Idle +; +; Nothing hapenning, become inactive. + +FxExIdle: + and Fixed.Flags,NOT Factive + RET + + +;* Fixed state Error +; +; Entered when a non-recoverable error is detected. +; A sense block has been requested and put into the +; DCB. + +FxExError: + MOV Fixed.State,Done ; Request is done +; Set error bits in request packet + MOV AL,Fixed.DCB ; Get status byte + mov bl,al ; isolate error type as word address + and bx,0030h + mov cl,3 + shr bx,cl + mov bx,HDErrType[BX] ; index into error table by type + and ax,0Fh ; get error code + cmp al,ds:[bx] ; outside range of table? + jae fxxe1 + add bx,ax + mov ah,ds:[bx+1] ; translate error code + jmp SHORT fxxe2 +fxxe1: + mov ah,12 +fxxe2: dbbeg 8,4 + mov di,OFFSET Fixed.DCB + debug 8,4,,<<[di]>,<[di+1]>,<[di+2]>,<[di+3]>,ax> + dbend + endif + PUSH ES + LES DI,FixedQueue ; Get ptr to request + MOV AL,ah + MOV AH,10000001B + MOV ES:[DI].RqStatus,AX ; Set error and code + POP ES + JMP fxxd3 ; Advance to Done state +FixedExecute ENDP + +;* Traslation of controller error codes to DOS error codes + +HDErrType DW HDErrTyp0 + DW HDErrTyp1 + DW HDErrTyp2 + DW HDErrTyp3 + +HDErrTyp0 DB 9, 12, 2, 6,10, 2,12, 6,12, 6 +HDErrTyp1 DB 10, 4, 4, 8,12, 8, 6,12,12, 4, 6 +HDErrTyp2 DB 2, 3, 8 +HDErrTyp3 DB 3, 4, 4, 4 + + ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING + +FixedInterrupt PROC FAR + debug 8,8,,<> + cmp word [SemDiskIO],0001h + jnz fxinot13 + cmp SemInt13,0 ; If a direct Int13 request is being + jz fxinot13 ; made call the ROM floppy interrupt + cmp SemDiskIO,0 ; routine to handle it. + jnz fxinot13 + int int_savregs +;; in al,21H ; Mask fixed disk interrupts +;; or al,20h +;; out 21H,al + pushf + call dword ptr [OldIntDVec] + in al,21H ; Unmask fixed disk interrupts + and al,0DFH + out 21H,al + mov dx,HD_PMSK ; set interrupt and DMA mask bits + mov al,3 + out dx,al + iret +fxinot13: + TEST Fixed.Flags,Factive ; device active? + JZ fxinret ; no, go away + INT int_savregs ; save registers + mov dx,HD_PDAT + in al,dx ; get status reg. +;; mov ah,al +;; mov dx,HD_PMSK +;; xor al,al +;; out dx,al ; turn off intr. and DMA. +;; test ah,02h ; error bit set? + test al,02h ; error bit set? + jz fxin4 ; no +;* error occurred. see if retry, else get error code. + push cs + pop ds + ASSUME ds:BiosSeg + CMP Fixed.ErrCnt,ErrLim ; Reach error limit? + JAE fxin0 ; Yes, request fails + INC Fixed.ErrCnt ; We are doing another try + MOV Fixed.State,Start ; Restart the request + JMP fxin4 +fxin0: mov Fixed.DCB,HD_CSENS ; send sense command + xor al,al ; reset intr. & DMA masks + call HDCommand + push cs + pop es + mov di,OFFSET Fixed.DCB + mov cx,5 +fxin1: call HDWaitReq ; get the sense block back + mov dx,HD_PDAT + in al,dx + stosb + loop fxin1 + mov Fixed.State,Error + + ASSUME ds:NOTHING +fxin4: CALL FixedExecute +fxinret: push ax + MOV AL,20H ; send EOI to 8259 + OUT 20H,AL + pop ax + IRET +FixedInterrupt ENDP + +SUBTTL Floppy disk startup routine +PAGE + + +; FloppyExecute processes a disk request after it has been set up. +; When the disk is inactive (State = Idle), it is called to start +; the device. For all subsequent events, it is called on the disk +; interrupt which signaled the completion of that subfunction. +; Some states do not involve waiting for an interrupt to occur. +; This routine runs entirely off the 'Floppy' data structure + +FloppyDispatch LABEL WORD + DW FlExStart + DW FlExCalc + DW FlExSelect + DW FlExRecal + DW FlExSeek + DW FlExSettle + DW FlExRdWri + DW FlExDone + DW FlExIdle + DW FlExError + +FloppyExecute PROC + push cs ; CS -> DS + pop ds + ASSUME DS:BiosSeg + MOV BX,Floppy.State ; Get current state + debug 4,4,, + ADD BX,BX + JMP FloppyDispatch[BX] ; Dispatch to correct routine + + +;* Floppy state Start +; +; Do setup calculations to figure out sector, start +; up motor, advance to Calc state. +; +; Entered on initially picking up a new request to do and on error retries. +; If error retries start here, then multiple sector requests will always start +; at the beginning rather than at the point of the error! Why? + +FlExStart: + mov si,OFFSET Floppy ; SI = pointer to per-device info. + les bx,FloppyQueue ; ES:BX = pointer to current request + mov al,es:[bx].RqUnit + mov ah,es:[bx].RqMedia + call FDGetBPB ; DI = drive parameters + CALL Setup ; Do setup calculations + MOV DX,FD_PCMD + MOV AL,Rate44 + OUT DX,AL ; Set step rate + MOV Floppy.State,Calc ; Advance to next state +flexj1: JMP FloppyExecute ; Now return to do Calc code + + + +;* Floppy state Calc +; +; Calculate cylinder, head and sector, wait for motor +; start or head load, advance to Select state. +; +; Entered after Start state and also on further sectors of a multiple sector +; request. + +FlExCalc: + mov si,OFFSET Floppy ; SI = pointer to per-device info. + les bx,FloppyQueue ; ES:BX = pointer to current request + mov al,es:[bx].RqUnit + mov ah,es:[bx].RqMedia + call FDGetBPB ; DI = drive parameters + CALL MapSector ; Get head, cylinder and sector + MOV Floppy.State,Select ; Will advance to Select state + CALL Sel765 ; Select the drive and maybe wait + JNC FloppyExecute ; Did select with no waiting + RET ; Have set a timer, get out + + + +;* Floppy state Select +; +; Recalibrate the drive if needed. If Seek is +; needed, start it and advance to Seek state. Otherwise advance to Settle +; state. + +FlExSelect: + call GetDrivePtr + OR [BX].DrvFlag,Fmotoron ; we've been selected, so motor is on + TEST [BX].DrvFlag,Frestor ; Is a restore needed? + JE NoRestore ; No + call SetTimer2 ; set a sanity/motor stop timer + MOV Floppy.State,Recal ; Next state will be recalibrate + CALL Rcl765 ; Start the recalibrate + RET ; Done until floppy interrupt arrives + +NoRestore: ; Start the seek if any + CALL Seek765 ; Start the seek to cylinder + JNC SeekOK ; Already on correct cylinder + MOV Floppy.State,Seek ; Next state is Seek + call GetDrivePtr + call SetTimer2 ; set sanity timer + RET ; Done until interrupt on seek done + + + +;* Floppy state Recal +; +; If error, set state is Error. Else, load drive +; specs into controller and advance to Select state. + +FlExRecal: + CALL Sense765 + OR AX,AX ; Error in recal? + JNZ SeekErr ; Yes +RecalOK: + CALL Spec765 ; Load drive specs + MOV Floppy.State,Select ; Back to select state now +flexj2: JMP flexj1 + + + +;* Floppy state Seek +; +; If error, advance to Error state. Otherwise, wait +; for head to settle and advance to Settle state. + +FlExSeek: + CALL Sense765 ; Get status of seek + OR AX,AX ; Any error? + JZ SeekOK ; No +SeekErr: + CALL GetDrivePtr + OR [BX].DrvFlag,Frestor ; flag restore needed + MOV Floppy.State,Error ; Yes, next state is Error + or Floppy.ST1,8 ; indicate seek error in an unused bit + JMP flexj2 + +SeekOK: + MOV Floppy.State,Settle ; Next state is Settle + MOV AL,DelaySettle + CALL GetFloppyParam ; Get the settle time in Msecs + xor ah,ah + CALL SetTimer1 ; Set the timer + JNC flexj2 + RET + + + +;* Floppy state Settle +; +; Start the read/write request and advance to the RdWri state. + +FlExSettle: + MOV Floppy.State,RdWri ; Advance to read/write state + CALL RdWr765 ; Start the I/O + call GetDrivePtr + call SetTimer2 ; set sanity timer + RET ; Done until floppy interrupt + + + +;* Floppy state RdWri +; +; If error, next state is Error. Otherwise next state is Done. + +FlExRdWri: + CALL Fini765 ; Get status of I/O + OR AX,AX ; Any error? + JZ RdWriOK ; No + MOV Floppy.State,Error ; Yes, go to error state + JMP flexj2 + +RdWriOK: + MOV Floppy.State,Done ; I/O is done +flexj3: JMP flexj2 + + + +;* Floppy state Done +; +; If whole request is now complete, mark the request +; as done and then start the next one if there is one. If the request is not +; yet done, adjust values to show the amount of the request done and then go +; back to the Calc state to do next part. + +FlExDone: + MOV AL,Floppy.Flags + AND AL,Fwrite+Fverify+Fwrap1 ; Only interested in these bits + CMP AL,Fwrap1 ; Just read into scratch? + JNE DoneNotWrap ; No + PUSH DS + PUSH ES + MOV CX,Floppy.NumBytes ; CS = # bytes to write from scr + LES DI,Floppy.RealAddr ; ES:DI = real buffer + LDS SI,Floppy.Addr ; DS:SI = scratch buffer + CLD + REP MOVSB ; Copy into real buffer + POP ES + POP DS +DoneNotWrap: + AND AL,Fwrite+Fverify ; Just want to see these bits + CMP AL,Fwrite+Fverify ; Just do write part of write+verify? + JNE DoneNotWritePart ; No + AND Floppy.Flags,NOT Fwrite ; Yes, do verify next + mov Floppy.State,Settle ; don't need to calc or seek + jmp flexj3 + +DoneNotWritePart: + CMP AL,Fverify ; Just do verify part of write+verify? + JNE DoneNotVerify ; No + OR Floppy.Flags,Fwrite ; Yes, flip write back up for next +DoneNotVerify: + MOV AX,Floppy.NumSectors ; AX = # of sectors we did + SUB Floppy.Count,AX ; Adjust count to number left + JZ flxd3 ; Request is done, tell DOS + ADD Floppy.First,AX ; Advance sector number + MOV AX,Floppy.NumBytes ; Number of bytes handled + ADD WORD PTR Floppy.RealAddr,AX ; Advance data address + MOV Floppy.State,Calc ; Go to Calc state +flexj4: JMP flexj3 + +flxd3: + mov di,OFFSET Floppy + mov SI,OFFSET FloppyQueue ; DS:SI = head of floppy queue + call DoneRequest + JMP flexj4 + + +;* Floppy state Idle +; +; Nothing hapenning except possible motor off timeout. + +FlExIdle: + call GetDrivePtr + CALL SetTimer2 ; Set the motor timer + and Floppy.Flags,NOT Factive + SemSig SwapSem2 ; someone waiting to switch drive? + RET + + +;* Floppy state Error +; +; If error count not exceeded, restore the drive and start +; the request over again. Otherwise set error in the packet and +; advance to the Done state. + +FlExError: + CALL Rst765 ; Reset the controller + CMP Floppy.ErrCnt,ErrLim ; Reach error limit? + JAE FloppyFails ; Yes, request fails + INC Floppy.ErrCnt ; We are doing another try + MOV Floppy.State,Start ; Restart the request + JMP flexj4 ; Back to state machine loop + +FloppyFails: + call GetDrivePtr + OR CS:[BX].DrvFlag,Frestor ; Set drive needs a restore + MOV Floppy.State,Done ; Request is done +; Set error bits in request packet + MOV AX, WORD PTR Floppy.ST0 ; Get ST0, ST1 + mov BL,2 ; Drive not ready? + test AL,0cH + jne ErrorFound + MOV BL,6 ; Bad seek? + TEST AH,8 + JNE ErrorFound + MOV BL,4 ; CRC error? + TEST AH,30H + JNE ErrorFound + MOV BL,8 ; Sector not found? + TEST AH,85H + JNE ErrorFound + MOV BL,0 ; Write protect? + TEST AH,2 + JNE ErrorFound + MOV BL,12 ; Catch-all error +ErrorFound: + debug 4,4,, + PUSH ES + LES DI,FloppyQueue ; Get ptr to request + MOV AL,BL + MOV AH,10000001B + MOV ES:[DI].RqStatus,AX ; Set error and code + POP ES + JMP flxd3 ; Advance to Done state (via shortcut) + +FloppyExecute ENDP + + + ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING + +FloppyInterrupt PROC FAR + debug 4,8,,<> + cmp SemInt13,0 ; If a direct Int13 request is being + jz flinot13 ; made call the ROM floppy interrupt + cmp SemDiskIO,0 ; routine to handle it. + jnz flinot13 + int int_savregs + pushf + call dword ptr [OldIntEVec] + iret +flinot13: + TEST Floppy.Flags,Factive ; device active? + JZ flinret ; no, go away + INT int_savregs ; save registers + CALL FloppyExecute +flinret: push ax + MOV AL,20H ; send EOI to 8259 + OUT 20H,AL + pop ax + IRET +FloppyInterrupt ENDP + +SUBTTL Timing routines for floppy disk +PAGE + + +;* Data for timers +TimerActive DB 0 ; bit flags for active timers +TimerConv DB 50 ; conversion factor for ms => ticks +Timer1 DB 0 ; One-shot time till restart intr. rtn. +Timer2 DB 0 ; Repetitive 1 Hz timer +Timer2count = 20 ; Reload value for timer2 + +MOFFDELAY= 2 ; turn off motor after 2 sec. inactivity + +;*** SetTimer1 - Arm timer 1 +; +; SetTimer1 will arm the Timer1. Input parameter +; values in milliseconds will be converted to timer +; ticks. +; +; ENTRY AX = delay value in milliseconds +; EXIT AL = timer ticks +; CF set if timer armed +; CF clear if zero count passed +; USES AX + +SetTimer1 PROC + TEST AX,AX ; zero count? + JNZ sett10 ; no + CLC + RET + +sett10: DIV TimerConv + TEST AH,AH ; remainder? + JZ sett11 + INC AL ; yes, round up +sett11: MOV Timer1,AL + OR TimerActive,1 + debug 4,8,, + STC + RET +SetTimer1 ENDP + +;*** SetTimer2 - Arm timer 2 +; +; SetTimer2 will set a motor off timeout for the +; drive whose parameter block is pointed to by +; CS:BX +; +; ENTRY CS:BX = pointer to per drive info. +; EXIT +; USES NONE + +SetTimer2 PROC + TEST TimerActive,2 + JNZ sett21 + MOV Timer2,Timer2Count + OR TimerActive,2 +sett21: MOV CS:[BX].Timer,MOFFDELAY + debug 4,8,,<> + RET +SetTimer2 ENDP + + + +; FloppyTimer is called every scheduler tick to perform +; time related services for the floppy driver. There are +; two services performed; rescheduling of interrupt time +; service after a head load or motor startup delay, and +; a motor turn off service when a drive is not active. +; +; It's assumed that all registers have been saved by the +; caller. + + ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING + + PUBLIC FloppyTimer +FloppyTimer PROC FAR + TEST TimerActive,0ffH ; any timers active? + JNZ fltim1 ; yes + RET ; no, return quickly +fltim1: TEST TimerActive,1 ; Timer1 active? + JZ fltim3 ; no + DEC Timer1 ; Timer1 expired? + JNZ fltim3 ; no +;* Perform Timer1 service + debug 4,8,,<> + AND TimerActive,NOT 1 + CALL FloppyExecute ; push the states around a while + RET ; don't do Timer2 service this time. + +fltim3: TEST TimerActive,2 ; Timer2 active? + JZ fltim4 ; no + DEC Timer2 ; 1 Hz clock time? + JZ fltim5 ; no +fltim4: JMP fltim9 +fltim5: + debug 4,8,,<> + MOV BL,Timer2count ; reload the counter + MOV Timer2,BL + +;* Perform Timer2 service + XOR CH,CH ; No active timeouts seen + XOR DI,DI ; Start with drive A +TimeOutLoop: + MOV BX,DI + ADD BX,BX + MOV BX,FDinfo[BX] ; Get ptr to drive info + TEST CS:[BX].DrvFlag,Fmotoron ; motor on? + JZ fltim8 ; no + CMP CS:[BX].Timer,0 ; Is timer active for drive? + JZ fltim8 ; No + DEC CS:[BX].Timer ; Yes, another tick has passed + JNZ fltim7 + cmp di,Floppy.Current ; Current drive? + jnz fltim6 ; no + test Floppy.Flags,Factive ; device active? + jz fltim6 ; no, go ahead + mov Floppy.State,Error + mov Floppy.ErrCnt,ErrLim ; don't retry this one + mov Floppy.ST0,048H ; set not ready error + call FloppyExecute ; oops, sanity timeout + jmp fltim9 +fltim6: + AND CS:[BX].DrvFlag,NOT Fmotoron ; stop drive motor + MOV AX,DI + MOV CL,AL + ADD CL,4 + MOV AL,1 + SHL AL,CL ; Get bit mask for motor on + TEST Floppy.DOR,AL ; Is motor already off? + JE fltim8 ; Yes, go on to next drive + NOT AL ; Get all bits except this motor + AND Floppy.DOR,AL ; Clear this motor on + MOV DX,FD_PSEL + MOV AL,Floppy.DOR + OUT DX,AL ; Turn off motor +;; cmp di,Floppy.Current ; Current drive? +;; jnz fltim8 ; no +;; test Floppy.Flags,Factive ; device active +;; jz fltim8 ; no, go on to next drive +;; call DumpRegs ; oops, sanity timeout + +fltim7: INC CH ; Flag still active +fltim8: INC DI ; Advance to next drive + CMP DI,WORD PTR NumFloppy ; Any more to check? + JNE TimeOutLoop ; Yes, do them + OR CH,CH ; Need to keep timer active? + JNZ fltim9 ; Yes + AND TimerActive,NOT 2 ; No, clear timeout is active +fltim9: RET + +FloppyTimer ENDP + + +IFDEF DEBUGFLG +DumpRegs PROC + push cs + pop ds + debug 4,0fh,,<> + mov di,OFFSET Floppy + debug 4,0fh,,<[di],[di.2],[di.4],[di.6],[di.8],[di.10],[di.12],[di.14]> + debug 4,0fh,< $x $x $x $x $x $x $x $x\n>,<[di.10h],[di.12h],[di.14h],[di.16h],[di.18h],[di.1ah],[di.1ch],[di.1eh]> + call GetDrivePtr + debug 4,0fh,,<[bx],[bx.2],[bx.4],[bx.6],[bx.8],[bx.10],[bx.12],[bx.14]> + debug 4,0fh,< $x $x $x $x\n>,<[bx.16],[bx.18],[bx.20],[bx.22]> + debug 4,0fh,< IMR IRR ISR 8259 status\n>,<> + mov al,0ah + out 20h,al + in al,20h + mov bl,al + + mov al,0bh + out 20h,al + in al,20h + mov cl,al + in al,21h + debug 4,0fh,< $b $b $b\n>, + debug 4,0fh,<765 status, data\n>,<> + mov dx,FD_PSTAT + in al,dx + mov bl,al + mov dx,FD_PDAT + in al,dx + debug 4,0fh,< $b $b\n>, + sti +dmpr0: jmp dmpr0 +DumpRegs ENDP +ENDIF ;DEUBGFLAG + +SUBTTL Routines shared between Floppy and Hard disk drivers +PAGE + + +;*** Setup - Set request parameters into local structure. +; +; Setup sets the Unit, First, Addr, Count and Flags fields in the +; device structure which are used to drive the I/O. The following +; flags are affected: +; Fwrite This is a write request, not a read +; Fverify This is a write with verify (verify when write +; is cleared). +; Other fields are copied from the DOS request packet. +; +; ENTRY SI Pointer to device variables +; ES:BX Current request +; AL Unit number +; DI BPB for drive +; DS CS +; +; EXIT The following variables are set +; [SI].Unit +; [SI].First The hidden sectors are added +; [SI].RealAddr +; [SI].Count +; [SI].Flags + + ASSUME CS:BiosSeg,DS:BiosSeg + +Setup PROC + MOV AX,ES:[BX].RqCount + MOV [SI].Count,AX ; Set number of sectors to do + MOV AX,ES:[BX].RqAddr + MOV WORD PTR [SI].RealAddr,AX + MOV AX,ES:[BX].RqAddr+2 + MOV WORD PTR [SI].RealAddr+2,AX ; Copy data address + MOV AL,ES:[BX].RqUnit ; Get unit number + MOV [SI].Unit,AL ; Set drive needed + MOV AX,ES:[BX].RqFirst ; Get the starting sector number + ADD AX,[DI].BPBhidsec ; Add # of hidden sectors + MOV [SI].First,AX ; Set 1st sector of I/O + and [SI].Flags,Factive+F2step ; mask excess flags + CMP ES:[BX].RqCmd,4 ; Is this a read? + JE SetupDone ; Yes, all done + OR [SI].Flags,Fwrite ; No, flag this is a read + CMP ES:[BX].RqCmd,9 ; Write with verify? + JNE SetupDone ; No, just write + OR [SI].Flags,Fverify ; Yes, set to verify too +SetupDone: + RET +Setup ENDP + + +;*** MapSector - compute head, sector, cylinder +; +; MapSector takes the fields set up by Setup and figures out the +; head, cylinder and sector involved. If the request involves +; multiple sectors, it figures out how many can be done at once +; based on the number of sectors left on the track and that the +; target address' offset does not wrap around 64k (the DMA on the +; PC uses a 20 bit address, but the high 4 bits do not change when +; the low 16 cycle back to 0). If the request wraps around 64k, it +; is split into 2 or 3 pieces which are all data before wrap, after +; wrap and the wrap itself. The wrap itself is transferred via a temp +; buffer (ScratchBuffer). +; +; ENTRY SI Pointer to device variables +; ES:BX Current request +; AL Unit number +; DI BPB for drive +; DS CS +; EXIT The following variables are set +; [SI].Flags +; [SI].Head +; [SI].Cyl +; [SI].Sector +; [SI].NumSectors +; [SI].NumBytes +; [SI].Addr +; USES AX,CX,DX,DI +; + +MapSector PROC + PUSH ES + les CX,[SI].RealAddr + MOV WORD PTR [SI].Addr,CX ; copy RealAddr to Addr + MOV WORD PTR [SI].Addr+2,ES + AND [SI].Flags,NOT Fwrap1 ; Clear buffer wrap flag + +; Calculate the head, cylinder and sector of the start of the request +; from [SI].First + POP ES + MOV AX,[SI].First + XOR DX,DX + DIV [DI].BPBtrksiz ; Divide by sectors/track +;; INC DL + MOV [SI].Sector,DL ; Set sector to start at + XOR DX,DX + DIV [DI].BPBnhead ; Divide by number of heads + MOV [SI].Head,DL ; Set head number + MOV [SI].Cyl,AX ; Set cylinder number + debug 8,4,,> +; +; Now see how many sectors of request can be done. The floppy +; controller will not advance tracks, but will allow reading or +; writing the remaining sectors on the track. +; + MOV AX,[DI].BPBtrksiz + SUB AL,[SI].Sector ; AL = # of sectors left on + ; track after desired. + XOR AH,AH +;; inc ax + CMP AX,[SI].Count ; Is whole request on this cyl? + JB maps2 ; No, can only do what is left + MOV AX,[SI].Count ; Yes, use the actual # wanted +maps2: + MOV [SI].Numsectors,AX ; Set number to do this time +; +; Now have to normalize offset (add in paragraph) and then see if adding +; [SI].Numsectors causes overflow. If it does, DMA will trash memory, so +; decrement Numsectors and loop. +; + MOV AX,WORD PTR([SI].Addr+2) + MOV CL,4 + SHL AX,CL ; Convert para to offset + ADD AX,WORD PTR [SI].Addr ; Add in offset + MOV CX,AX ; Save offset of buffer +maps4: + MOV AX,[DI].BPBsecsiz + MUL [SI].NumSectors ; Get # bytes in transfer + MOV [SI].NumBytes,AX ; Set # bytes involved + ADD AX,CX ; Get final offset + JAE maps6 ; No overflow, DMA will be ok + OR [SI].Flags,Fwrap2 ; Flag we will be using scratch + DEC [SI].NumSectors ; Overflow, try using one less + JNZ maps4 +; +; If we got here, no sectors can be transferred before the 64K +; boundary. One sector must be transferred through a scratch buffer. +; + debug 12,10h,, + INC [SI].NumSectors ; Doing 1 sector of I/O + OR [SI].Flags,Fwrap1 ; Flag we are using scratch + MOV AX,CS + MOV DI,OFFSET ScratchBuffer + MOV WORD PTR([SI].Addr),DI + MOV WORD PTR([SI].Addr+2),AX ; Change buffer to scratch + TEST [SI].Flags,Fwrite ; Doing a write? + JE maps6 ; No, All done + PUSH ES + PUSH DS + PUSH SI + MOV ES,AX ; ES:DI = scratch buffer + mov cx,[SI].NumBytes + LDS SI,[SI].RealAddr ; DS:SI = Data buffer + CLD +REP MOVSB ; Copy the write buffer + POP SI + POP DS + POP ES +maps6: + RET +MapSector ENDP + + + + +;*** DMAsetup - Set the DMA channel up to do the I/O +; +; ENTRY AL = DMA mode +; AH = DMA channel number (2 or 3 only) +; SI = pointer to device parameters +; USES AX,CX,DX +; + +DMAsetup PROC + PUSH AX + XCHG AH,AL + OR AL,4 + OUT PDMA+10,AL ; set channel's mask bit + OUT PDMA+12,AL ; clear byte pointer F/F + pop ax + push ax ; restore AH, AL + OR AL,AH ; add channel number to command + OUT PDMA+11,AL ; Set DMA mode + MOV DX,PDMA + ROL AH,1 + ADD DL,AH + MOV AX,WORD PTR [SI].Addr+2 ; Get segment of addr + MOV CL,4 + ROL AX,CL ; Convert para to bytes + MOV CH,AL ; CH = 4 bits ROLed around + AND AL,0F0H ; Lose high bits rotated around + ADD AX,WORD PTR [SI].Addr ; Add in offset value + ADC CH,0 ; Add in any carry + OUT DX,AL ; Output low byte of address + MOV AL,AH + OUT DX,AL ; Output high byte of address + inc dx ; address `word' count register + MOV AX,[SI].NumBytes ; # bytes in request + dec ax + OUT DX,AL + MOV AL,AH + OUT DX,AL ; Tell DMA how many bytes + pop ax ; get back channel number + mov dl,PDMAX + add dl,ah + MOV AL,CH + AND AL,0FH ; Only 4 bits are good + OUT DX,AL ; Output highest 4 bits of address + MOV AL,AH ; Channel to start + OUT PDMA+10,AL ; Clear channel's mask bit + RET +DMAsetup ENDP + +;*** DoneRequest - Mark a request complete, setup to start next one +; +; DoneRequest does common processing needed when a request +; has been completed. It will reset the device state, +; dequeue the request, mark it complete, restart the +; process and restart any process waiting on ScratchBuffer +; if this request had reserved it. +; +; ENTRY SI Pointer to head of queue +; DI Pointer to device information +; EXIT ES:BX Next request +; USES AX,BX,DX,BP,ES + + +DoneRequest PROC + push cs + pop ds + ASSUME ds:BiosSeg + MOV [DI].ErrCnt,0 ; Reset error count + MOV [DI].State,Idle ; Assume will be idle + MOV DX,PullRequest + CALL DosFunction ; Pull the current request out + JZ dnrq2 ; Nothing really completed + MOV AX,[DI].Count ; Get I/O left to do + SUB ES:[BX].RqCount,AX ; Adjust requested count by residual + OR ES:[BX].RqStatus,0100h ; set done bit + MOV AX,ES ; AX:BX = Request completed + MOV DX,ContinueProcess + CALL DosFunction ; Make process run again + CMP WORD PTR [SI]+2,0 ; Is there another request to do? + JZ dnrq2 ; No, let device shut down + MOV [DI].State,Start ; Yes, start up next request +dnrq2: + test [DI].Flags,Fwrap2 ; had this request used ScratchBuffer? + jz dnrq4 ; no + SemSig ScratchBufSem ; let anyone waiting proceed + and [DI].Flags,NOT Fwrap2 +dnrq4: ; If both the fixed and floppy drivers + push bx ; are idle, reset the busy flag and + cmp Floppy.State,Idle ; continue any processes that were + jne dnrq5 ; waiting for it. + cmp Fixed.State,Idle + jne dnrq5 + mov SemDiskIO,0 + mov ax,ds + mov bx,offset SemDiskIO + mov dx,ContinueProcess + call DosFunction +dnrq5: + pop bx + ret +DoneRequest ENDP + + +; FDGetBPB returns a pointer to the floppy disk BPB for the +; selected media byte. The BPB contains various drive parameters +; such as physical disk dimensions and the size of FATs and the +; root directory. +; +; Input: AH = Media byte +; AL = Drive number +; Destroys: None +; Output: CS:DI = Pointer to BPB + + ASSUME DS:NOTHING,ES:NOTHING + +FDGetBPB PROC + + PUSH AX + PUSH BX + PUSH CX + PUSH DX ; Save regs + MOV CL,AH ; Copy media value + AND CL,0F8H ; Look at just top 5 bits + CMP CL,0F8H ; Valid media byte? + JE BPBGood ; Yes + MOV AH,0FEH ; No, make it 8 sector 1 sided +BPBgood: + MOV BL,AL ; Get pointer to per drive info. + XOR BH,BH + ADD BX,BX + MOV DI,CS:FDinfo[BX] + CMP AH,CS:[DI].BPBmediab ; already set? + JE BPBdone ; yes, don't bother rebuilding + MOV AL,1 ; Assume will have 1 FAT sector + MOV BX,64*256+8 ; Assume # dir = 64, 8 sector + MOV CX,40*8 ; Assume 320 sectors/disk + MOV DX,1*256+1 ; Assume 1 head, 1 sector/allocate + TEST AH,2 ; Is drive 8 or 9 sector? + JNZ BPBKnowSectors ; It's 8, we assumed right + INC AL ; 9 sector, incr # of FAT sectors + INC BL ; Set we have 9 sectors/cylinder + ADD CX,40 ; Increase size to 360 sectors +BPBKnowSectors: + TEST AH,1 ; Is disk double sided? + JE BPBKnowHeads ; No, we guessed right + ADD CX,CX ; Double size of disk + MOV BH,112 ; Increase # of directory entries + INC DH ; Set 2 sectors/allocation unit + INC DL ; Set 2 heads +BPBKnowHeads: + MOV CS:[DI].BPBsecpau,DH ; Set sectors/allocation unit + MOV BYTE PTR CS:[DI].BPBndir,BH ; Set # of directory entries + MOV CS:[DI].BPBnsec,CX ; Set size of disk in sectors + MOV CS:[DI].BPBmediab,AH ; Set media byte + MOV BYTE PTR CS:[DI].BPBnfatsec,AL ; Set number of FAT sectors + MOV BYTE PTR CS:[DI].BPBtrksiz,BL ; Set sectors/track + MOV BYTE PTR CS:[DI].BPBnhead,DL ; Set # of heads +BPBdone: + POP DX + POP CX + POP BX + POP AX + RET +FDGetBPB ENDP + + +; HDGetBPB returns a pointer to the hard disk BPB for the +; selected unit. The BPB contains various drive parameters +; such as physical disk dimensions and the size of FATs and the +; root directory. +; +; Input: AL = Drive number +; Destroys: None +; Output: CS:DI = Pointer to BPB + + ASSUME DS:NOTHING,ES:NOTHING + +HDGetBPB PROC + PUSH BX + MOV BL,AL ; Get pointer to per drive info. + XOR BH,BH + ADD BX,BX + MOV DI,CS:HDinfo[BX] + POP BX + RET +HDGetBPB ENDP + + + ASSUME DS:NOTHING,ES:NOTHING + +BlockIfLocked Proc Near ; Block the current process if it has + pushf ; been locked out by an Int 13 request. +bifl1: cli ; Otherwise, set the busy flag to block + cmp SemInt13,0 ; out Int 13 requests. + jz bifl2 + push dx + push cx + push bx + push ax + mov ax,cs + mov bx,offset SemInt13 + xor cx,cx + mov dx,BlockProcess + call DosFunction + pop ax + pop bx + pop cx + pop dx + jmp bifl1 +bifl2: + mov SemDiskIO,1 + popf + ret +BlockIfLocked endp + +SUBTTL Routines that interface to hard disk controller +PAGE + + +;*** HDCommand - send a command to the hard disk controller +; +; HDCommand will send the previously set up command block +; to the hard disk controller. +; +; ENTRY AL = value to be put in interrupt/DMA mask +; EXIT AL = status port value +; USES AX,CX,DX,SI + +HDCommand PROC + mov dx,HD_PSEL ; point to select port + out dx,al +;; mov cx,10 ;BUGBUG - timing prob. w/ expansion box? +;;hdcom0: loop hdcom0 ;BUGBUG - timing prob. w/ expansion box? + inc dx ; point to mask port + out dx,al + mov dx,HD_PSTAT +hdcom1: in al,dx ; get status + and al,0FH + cmp al,0DH ; test for busy, command/data, request + jnz hdcom1 + mov si,OFFSET Fixed.DCB + mov cx,6 + cld + dec dx ; point to data port +hdcom2: lodsb + out dx,al + loop hdcom2 + inc dx +;; mov cx,10 ;BUGBUG - timing prob. w/ expansion box? +;;hdcom3: loop hdcom3 ;BUGBUG - timing prob. w/ expansion box? + in al,dx + ret +HDCommand ENDP + +;*** HDWaitReq - wait for request bit in status register +; +; HDWaitReq will pause until the request bit in the hard disk +; status register is set. +; +; ENTRY +; EXIT AL = status byte +; USES AX,DX + +HDWaitReq PROC + mov dx,HD_PSTAT + in al,dx + test al,01h ; request bit? + jz HDWaitReq + ret +HDWaitReq ENDP +SUBTTL Routines that interface to floppy disk controller +PAGE + + +;*** GetDrivePtr - compute ptr to per drive info. +; +; GetDrivePtr returns a pointer to the per-drive information +; for the current drive. Should not be called before the +; current drive is set up by Sel765 in state CALC. +; +; EXIT BX = pointer to per drive table +; USES BX + +GetDrivePtr PROC + mov bx,cs:Floppy.Current + add bx,bx + mov bx,cs:FDinfo[bx] + ret +GetDrivePtr ENDP + + +; GetFloppyParam is called to get a disk parameter from the parameter +; block set up by the BIOS. This block allows disk parameters to be changed +; from the standard. +; +; Input: AL = parameter desired (see FloppyParam structure) +; Destroys: AX +; Output: AL = parameter byte desired + +GetFloppyParam PROC + PUSH DS + PUSH BX + XOR AH,AH + MOV BX,AX + XOR AX,AX + MOV DS,AX ; Point to INT area + LDS AX,DWORD PTR DS:(4*1EH) ; Get pointer to param block + ADD BX,AX ; Add in block offset + MOV AL,[BX] + POP BX + POP DS + RET +GetFloppyParam ENDP + + + +; Recalibrate the current drive. Clear Restore flag, set cylinder to +; unknown and issue command to controller. +; +; Destroys: AX,BX,DX +; + +Rcl765 PROC + AND CS:[BX].DrvFlag,NOT Frestor ; Have restored drive + MOV CS:[BX].CurCyl,-1 ; Flag don't know where we are + MOV AL,FD_CRESET + CALL Put765 ; Put out reset command + MOV AX,Floppy.Current ; Get current drive + CALL Put765 ; Tell controller which drive + RET +Rcl765 ENDP + + +; Reset the controller. +; +; Destroys: AX,CX,DX +; + +Rst765 PROC + MOV AL,CS:Floppy.DOR + AND AL,NOT(DORmask) + MOV DX,FD_PSEL + OUT DX,AL + MOV CX,10000 +RstDelayLoop: + loop RstDelayLoop + OR AL,DORmask + MOV CS:Floppy.DOR,AL ; Update value + OUT DX,AL + RET +Rst765 ENDP + + +; Load the drive specs into the controller. +; +; Destroys: AX,DX +; + +Spec765 PROC + MOV AL,FD_CSPEC + CALL Put765 + MOV AL,Spec1 + CALL GetFloppyParam + CALL Put765 + MOV AL,Spec2 + CALL GetFloppyParam + CALL Put765 + RET +Spec765 ENDP + + +; Get the interrupt status from the controller and into AX +; +; Destroys: AX,CX,DX +; + +Sense765 PROC + MOV AL,FD_CSENSE ; Get status + CALL Put765 + CALL Get765 ; Read ST0 + PUSH AX ; Save status + CALL Get765 ; Read PCN (present cylinder number) + POP AX ; Restore status + MOV CL,6 + SHR AL,CL ; Shift bits down + AND AX,3 ; Leave only error bits + RET +Sense765 ENDP + + +; Select the current drive. Return carry set if must wait until drive is +; ready. FloppyExecute will be called again when the drive is ready. The +; code must wait either for a motor start or head load delay, otherwise it +; returns with carry clear. +; +; Destroys: AX,BX,CX,DX +; + +Sel765 PROC + MOV DX,FD_PSEL ; set DX = Digital Output Register + MOV CL,Floppy.Unit ; Get unit we want to use + XOR CH,CH ; CX = wanted unit + CMP Single,0 ; Single drive system? + JE Sel765Double ; No, Unit is accurate + MOV CL,CH ; Yes, there is only drive 0 +Sel765Double: + CMP CX,Floppy.Current ; Wanted same as current? + MOV Floppy.Current,CX ; Set new current unit + JNE SelectUnit ; No, must select new drive + ADD CL,4 + MOV AL,1 + SHL AL,CL ; AL = Bit for drive's motor on + TEST AL,Floppy.DOR ; Is the drive's motor still on? + JE SelectUnit ; No, must turn it back on + MOV AL,Floppy.DOR + OUT DX,AL ; ? For some reason output value again + CLC ; Clear carry, don't have to wait + RET + +SelectUnit: + MOV AL,NOT(3) ; Drive select is low 2 bits + AND AL,Floppy.DOR ; Lose old select bits + OR AL,DORmask + MOV CL,BYTE PTR Floppy.Current ; get unit number + OR AL,CL ; Put in new select bits + MOV Floppy.DOR,AL ; Save new bits + ADD CL,4 + MOV AL,1 + SHL AL,CL ; Get bit for motor is on + TEST AL,Floppy.DOR ; Is drive's motor on? + JE SelectStartMotor ; No, must start motor + MOV AL,Floppy.DOR + OUT DX,AL ; Load the head + MOV AX,DelayLoad ; Load head delay + CALL SetTimer1 + RET + +SelectStartMotor: + OR Floppy.DOR,AL ; Add in motor start bit + MOV AL,Floppy.DOR + OUT DX,AL ; Start the motor + MOV AL,DelayMotor + CALL GetFloppyParam ; Get the proper delay time in 1/8 sec + mov cl,125 + mul cl ; convert to milliseconds + CALL SetTimer1 ; Set timer for motor startup + RET +Sel765 ENDP + + +; Seek to the correct cylinder. Set carry if have to wait for operation +; to complete (we are not on right cylinder). +; +; Destroys: AX,BX,DX +; + +Seek765 PROC + MOV AX,Floppy.Cyl ; Get cylinder wanted + CMP AX,CS:[BX].CurCyl ; Already on cylinder? + JE SeekDone ; Yes, return with carry clear + MOV CS:[BX].CurCyl,AX ; Set the new current cylinder + MOV AL,FD_CSEEK + CALL Put765 ; Seek command + MOV AL,Floppy.Head ; Get head desired + SHL AL,1 + SHL AL,1 ; Move head # 2 bits left + ADD AL,BYTE PTR Floppy.Current ; Low 2 bits are unit (hhuu) + CALL Put765 ; Put out drive and head select + MOV AX,Floppy.Cyl + TEST Floppy.Flags,F2step ; Need to double step? + JE SeekNoDouble ; No + ADD AX,AX ; Yes, double cylinder number +SeekNoDouble: + CALL Put765 ; Give controller the cylinder + STC ; Set carry, must wait for seek intr. +SeekDone: + RET +Seek765 ENDP + + + +; Start the Read/write. Set up the DMA channel and give a read or write +; command to the controller depending on flag. +; +; Destroys: AX,CX,DX +; + +RdWr765 PROC + mov ah,FD_DMA + mov si,OFFSET Floppy + TEST Floppy.Flags,Fwrite ; Is this a write? + JNE WriteSetup ; Yes + MOV AL,DMA_READ ; No, read + CALL DMAsetup ; Set up the DMA + MOV AL,FD_CREAD ; Want to read + JMP SHORT RdWrLoc ; Now put out rest of command + +WriteSetup: + MOV AL,DMA_WRITE + CALL DMAsetup ; Set DMA up for write + MOV AL,FD_CWRITE ; Want to write +RdWrLoc: + CALL Put765 ; Put out command + MOV AL,Floppy.Head + ADD AL,AL + ADD AL,AL ; Form HHxx Binary + ADD AL,BYTE PTR Floppy.Current ; Form HHUU + CALL Put765 ; Output unit and head + MOV AX,Floppy.Cyl + CALL Put765 ; Output cylinder + MOV AL,Floppy.Head + CALL Put765 ; Output head again? + MOV AL,Floppy.Sector + inc al + CALL Put765 ; Output sector + MOV AL,SectorSize + CALL GetFloppyParam ; Get sector size code + CALL Put765 ; Tell controller sector size + MOV AL,CylSize + CALL GetFloppyParam ; Get number of sectors/cylinder + CALL Put765 ; Tell controller + MOV AL,DataGap ; Gap length for read/write + CALL GetFloppyParam + CALL Put765 ; Tell controller gap length + MOV AL,ValueDTL + CALL GetFloppyParam ; Get value for DTL + CALL Put765 ; Since bytes/sector#0, this is a + ; meaningless value, but controller + ; wants to see something + RET +RdWr765 ENDP + + + +; Fini765 gets the completion status. +; +; Destroys: AX,CX,DX +; Returns: AL +; + +Fini765 PROC + push es + push di + push cs + pop es + mov di,OFFSET Floppy.ST0 + MOV CX,7 +fini1: CALL Get765 + stosb + loop fini1 + mov al,Floppy.ST0 + mov cl,6 + SHR AL,CL + AND AX,3 ; Mask down to value to return + pop di + pop es + RET +Fini765 ENDP + + + +; Put765 writes a command to the controller. +; +; Input: AL = value +; Destroys: AX,DX +; + +Put765 PROC + PUSH AX ; Save the value to write +PutWaitLoop: + MOV DX,FD_PSTAT + IN AL,DX ; Get status + AND AL,FD_SDIO+FD_SRQM + CMP AL,FD_SRQM ; Controller ready for data? + JNE PutWaitLoop ; No, keep waiting + POP AX ; Get value back + MOV DX,FD_PDAT + OUT DX,AL ; Put out value + RET +Put765 ENDP + + +; Get765 gets a value back from the controller into AL. +; +; Destroys: AX,DX +; Returns: AL +; + +Get765 PROC + MOV DX,FD_PSTAT + IN AL,DX ; Get status + AND AL,FD_SDIO+FD_SRQM + CMP AL,FD_SDIO+FD_SRQM ; Controller data available? + JNE Get765 ; No, wait for it + MOV DX,FD_PDAT + IN AL,DX ; Get value from controller + ret +Get765 ENDP + +Code ENDS + END diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ new file mode 100644 index 0000000..daf953a Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ differ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM new file mode 100644 index 0000000..6cfefbe --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM @@ -0,0 +1,1424 @@ + TITLE MTCON - Console device driver for MT-MSDOS + page ,132 + + +;; TODO - +;; split CON and KBD +;; interruptible waits and unwinding +;; per screen keyboard buffers + +;------------------------------------------------------------------------ +; Revision History +; +; V1.00 04/10/84 M.A.Ulloa +; First Implementation: Only one segment used and only +; one screen in the color card (alpha mode). +; +; V1.01 04/15/84 M.A.Ulloa +; Re-enabled the blocking of writing from processes not +; with the current screen. +; +; V1.02 04/16/84 M.A.Ulloa +; Increased to 8 the num of screens. Added the screen +; blanking when reading and writing the screen data +; (see BLANK switch). Added screen # for writes. +; +; V1.03 04/17/84 M.A.Ulloa +; Corrected problem with flush. +; +; V1.05 04/30/84 A.R.Whitney +; Added conditional compilation to allow linking with +; resident BIOS. +; +; V1.06 05/08/84 A.R.Whitney +; Added ANSI escape sequences. Conditional on ANSI. +; +; V1.07 05/15/84 A.R.Whitney +; Fixed compatibility problems with Eagle PC Turbo. +; Fixed BLANK conditional code to allow saving graphics +; mode screens. +; Added enable/disable 25th line to Ansi. +; +; V1.08 05/22/84 A.R.Whitney +; Fixed problem with scrolling in screen modes other +; than 80x25. Bug due to 25th line stuff. +; +;------------------------------------------------------------------------ + +;DEBUGFLG = 1 + +.xlist + include DEFDBUG.INC +.list + +FALSE EQU 0 +TRUE EQU NOT FALSE + +CVERS equ 01 ; update version number!! +CREV equ 08 + +BLANK equ TRUE ; blank screen during data r/w +INBIOS equ TRUE ; link with BIOS +ANSI equ TRUE ; include ANSI escape sequences + LINE25 equ TRUE ; special 25th line like VT52 +EAGLE equ TRUE ; Eagle PC ROM botches CRT_LEN + + +subttl Screen Information Block Definition +page + +;------------------------------------------------------------------------ +; Screen Information Block (SIB) Definition +; +; This structure contains all information necessary to +; describe the state of the screen, plus pointers to buffers +; which contain the actual screen content. +; + +;------------------------------------------------------------------------ +MaxSEG equ 2 ; NOTE: assumption is made in the + ; code that all SIB's have same + ; number os SEGs +SEGst struc +SizeNeeded dw 0 ; needed size for seg, (0 = unused) +MemFlag dw ? ; maintened by system (0 = in mem) +MPointer dd ? ; vaild iff MemFlag == 0 +SEGst ends + +;------------------------------------------------------------------------ +MaxSIB equ 8 ; maximum number of Screens + + +IF ANSI +TermSize EQU 20 ; max. size of terminal emulation state +ENDIF + +SIBst struc +ctlS db 0 ; if the screen is NOT frozen = 0 + ; NOTE: this field should be the + ; FIRST of each SIB !! (see ConWrit) +OffsetVal dw 7 ; start of Seg Descriptors +SegCnt dw MaxSeg ; max number of Segments +SIBlen dw (SIZE SIBst) ; length of the SIB +;--- Segments + db ((SIZE SEGst) * MaxSeg) dup (?) +;--- PC video state info +xCRT_MODE DB ? +xCRT_COLS DW ? +xCRT_LEN DW ? +xCRT_START DW ? +xCURSOR_POSN DW 8 DUP(?) +xCURSOR_MODE DW ? +xACTIVE_PAGE DB ? +xADDR_6845 DW ? +xCRT_MODE_SET DB ? +xCRT_PALETTE DB ? +xTERM_STATE DB TermSize DUP(?) +SIBst ends + + +subttl Request packet definitions +page + +;------------------------------------------------------------------------ +; Request packet offset definitions +; + +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER + + +subttl IBM-PC ROM Data area Locations +page + +;------------------------------------------------------------------------ +; IBM-PC ROM Data area Locations +; + +RomData SEGMENT AT 40H + ORG 1AH +BufferHead DW ? +BufferTail DW ? +KeyBuffer DW 16 DUP (?) +KeyBufLen equ ($-KeyBuffer) ; length of KeyBuffer + + ORG 49H +CRT_MODE DB ? +CRT_COLS DW ? +CRT_LEN DW ? +CRT_START DW ? +CURSOR_POSN DW 8 DUP(?) +CURSOR_MODE DW ? +ACTIVE_PAGE DB ? +ADDR_6845 DW ? +CRT_MODE_SET DB ? +CRT_PALETTE DB ? + +CrtLen EQU ($-CRT_MODE) ; length of screen state area +RomData ENDS + +MonoSc SEGMENT AT 0B000H +;--- 4k of screen memory +MonoSc ENDS + +ColorSc SEGMENT AT 0B800H +;--- 16k of screen memory +ColorSc ENDS + +BRKADR equ 006CH ; Break vector address + + +subttl Device Header +page + + +BiosSeg group Code,BiosInit +Code Segment byte public 'CODE' + +;------------------------------------------------------------------------ +; Device Header +; + +assume cs:Code,ds:NOTHING,es:NOTHING,ss:NOTHING + + PUBLIC CONDEV +IF INBIOS + extrn AUXDEV:FAR +CONDEV dd AUXDEV +ELSE +CONDEV dw 0FFFFh,0FFFFh +ENDIF ;INBIOS +;*** should ioctl bit be set for gen ioctl too? + dw 1100000000010011b ; console in and out + dw Strategy + dw Entry + db "CON " + + +;------------------------------------------------------------------------ +; Command dispatch table +; + +ComTbl: +;--- 2.0 + dw OFFSET BiosSeg:$ConInit ; Initialization function + dw StatusComplete ; Media Check + dw StatusComplete ; Build BPB + dw CmdErr ; IOCTL Input + dw $ConRead ; Input (Read) + dw $ConRdnd ; Non-Destructive read, no wait + dw StatusComplete ; Input Status + dw $ConFlsh ; Input Flush + dw $ConWrit ; Output (Write) + dw $ConWrit ; Output with verify + dw StatusComplete ; Output Status + dw StatusComplete ; Output Flush + dw StatusComplete ; IOCTL Output +;--- 3.0 + dw StatusComplete ; Device Open + dw StatusComplete ; Device Close + dw StatusComplete ; Removable Media +;--- 4.0 + dw $GenIOCTL ; Generic IOCTL + dw $ConStop ; Pause Device + dw $ConStart ; Continue Device + +ComTblEnd: + +CTSIZE equ (ComTblEnd - ComTbl)/2 ; number of table entries + + +subttl Device Data Area +page + +;------------------------------------------------------------------------ +; Device Data Area +; + +SaveFlg db 0 ; Screen being saved flag, (true = 1) +IF INBIOS + EXTRN DosFunction:DWORD +ELSE +DosFunction dd ? ; pointer to dos "helper" functions +ENDIF ;INBIOS +AltAH db 0 ; Side buffer for input +CurrSc dw 0 ; Current screen number +CurrSIB dw SIB ; offset to the current SIB +SIB SIBst MaxSIB dup (<>) ; allocate room for SIB's + +IF EAGLE +ScreenLen db 08h ; table of (high byte of) regen. buffer + db 08h ; len. Indexed by screen mode. + db 10h ; 80x25 text modes + db 10h + db 40h ; graphics modes + db 40h + db 40h + db 10h ; monochrome +ENDIF + + +IFDEF DEBUGFLG +IF INBIOS + EXTRN BUGBITS:BYTE,DPRINTF:NEAR +ELSE +BUGBITS db 0ffh,0ffh +ENDIF +ENDIF + +subttl Device Entry Points +page + +;------------------------------------------------------------------------ +; 2.0 Interrupt Routine (Not Used) +; + +EntryP proc far +Entry: ret +EntryP endp + + +;------------------------------------------------------------------------ +; 2.0 Strategy Routine, main entry point +; +; entry +; ES:BX points to Request packet +; + +StratP proc far + +Strategy: +IF INBIOS + extrn Interrupt:NEAR + + push si + mov si,OFFSET CS:ComTbl + jmp Interrupt +ELSE + push ax ; save all + push cx + push dx + push si + push di + push bp + push ds + + push es ; DS = ES + pop ds + + push es + push bx + mov al, byte ptr ds:[bx].CMD + cmp al,CTSIZE ; Command within range? + jae CmdErr ; no must be an error + mov cx, word ptr ds:[bx].COUNT + les di, dword ptr ds:[bx].TRANS + xor ah,ah + mov si, offset ComTbl + add si,ax + add si,ax + + jmp word ptr cs:[si] ; dispatch +ENDIF ;INBIOS + +StratP endp + + +subttl Exit Routines +page + +;------------------------------------------------------------------------ +; Exit Routines, Common to all device functions +; + +IF INBIOS + extrn StatusComplete:NEAR,StatusError:NEAR,StatusDevReady:NEAR + extrn CmdErr:NEAR +ELSE + +assume ds:NOTHING,es:NOTHING + +StatusDevReady: + mov ah,00000011b ; device busy + jmp short errEx + +CmdErr: + mov al,3 ; Unknown command Error +StatusError: + mov ah,10000001b + jmp short errEx + +ExitP proc far +StatusComplete: mov ah,00000001b +errEx: pop bx + pop es + + mov word ptr es:[bx].STATUS,ax ; put status out + + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop ax + ret +ExitP endp + +ENDIF ;INBIOS + + +subttl Break - Break interrupt routine +page + +;------------------------------------------------------------------------ +; Break interrupt routine +; + +assume ds:NOTHING,es:NOTHING + +Break PROC NEAR + int 32H ; save registers + cli ; ints should be off, make sure! + mov ax,RomData + mov ds,ax + assume ds:RomData + mov ax,offset RomData:KeyBuffer + mov [BufferHead],ax + mov [BufferTail],ax + assume ds:NOTHING + mov ax,3 ; send char to system + mov dx,5 ; ConsInputFilter subfunction + call [DosFunction] + jz brk1 ; key was eaten by system + mov [AltAH],al ; force a ^C +brk1: + iret +Break ENDP + +SUBTTL Keyboard interrupt routine +PAGE +; Replacement for ROM keyboard interrupt, tacks on the front. +; OldKeyInterrupt is set to original contents of INT 09H. +; The input character is passed to the O.S. console input filter +; to determine if any special action should be taken. The filter +; return value indicates if the character should be saved in the +; type ahead buffer or if it should be discarded. A keyboard +; semaphore exists to indicate if a process is waiting for input. +; If the keboard semaphore is set all of the processes sleeping on +; it are woken up. + +OldKeyInterrupt DD ? +KeySem db 0 ; non-zero if someone waiting on input + +KeyboardInterrupt PROC FAR + INT 32H ; Save regs + MOV AX,RomData + MOV DS,AX + ASSUME DS:RomData + + PUSHF ; Save flags to simulate INT + CALL CS:OldKeyInterrupt ; Now do ROM code +; Now tell DOS keyboard had char + cli ; interrupts off! + mov bx,BufferTail ; Get tail of queue + cmp bx,BufferHead ; Anything in keyboard queue? + JE NoKey ; No, don't requeue then + dec bx + dec bx + cmp bx,offset RomData:KeyBuffer + jae kbi1 ; no wrap around in buffer + mov bx,offset RomData:KeyBuffer+(KeyBufLen-2) +kbi1: + mov ax,[bx] ; get last queued char. + mov dx,5 ; ConsInputFilter subfunction + call [DosFunction] + jnz kbi2 ; key should remain in buffer + mov BufferTail,bx ; discard key from buffer + jmp SHORT NoKey +kbi2: + cli + CMP KeySem,0 ; Outstanding request? + JE NoKey ; No, may not be inited either + push ax + push bx + push cx + push dx + mov ax,cs + mov bx,OFFSET KeySem + mov cs:byte ptr [bx],0 ; reset keyboard semaphore + mov dx,10 ;; ProcRun + call [DosFunction] ; awaken anyone waiting on input + pop dx + pop cx + pop bx + pop ax +NoKey: + IRET +KeyBoardInterrupt ENDP + +;------------------------------------------------------------- +; Keyboard INT 16 intercept routine to allow console input to sleep. +; Only console input function 1 is intercepted, all other functions +; are allowed to go directly to the ROM BIOS. For the function 1 +; the input status is checked, if a character is ready the function +; is allowed to go to the ROM BIOS. Otherwise the keyboard semaphore +; is set and the process is put to sleep on the address of the +; semaphore. When a key is typed the keyboard interrupt routine +; will wakeup any processes sleeping on this semaphore. +; +; WARNING: The following routines can be entered recursively +; due to the fact that the ROM BIOS routines called +; reenable interrupts. It's not usually a problem +; since interrupts will generally be processed faster +; than anyone can type. + +OldKbdHandler dd ? +ScrnIoOk dd ? + +;------------------------------------------------------------- + +KeyBoardHandler proc far + or ah,ah + je DoLocalRead + cmp ah,1 + je DoLocalStat +OldKBint: + jmp [OldKbdHandler] + +DoLocalStat: + push bx + push ds + lds bx,ScrnIoOk + test byte ptr [bx],0FFh + pop ds + pop bx + jnz OldKBint + xor ax,ax + ret 2 +DoInt16 LABEL FAR ; entry for ChrIn +DoLocalRead: + push ax + push bx + push cx + push dx +DoLocalRd1: + push ds + lds bx,ScrnIoOk + mov ax,ds + test byte ptr [bx],0FFh + pop ds + jnz DoLocalRd2 + xor cx,cx + mov dx,9 ;; ProcBlock + call [DosFunction] ; sleep until a screen switch + jmp DoLocalRd1 + +DoLocalRd2: + mov ah,1 ; get console status + pushf ; simulate INT to old handler + cli + call [OldKbdHandler] + cli ; subfunction 1 unconditionally sets IF + jnz LocalRead ; go read character + mov ax,cs + mov bx,OFFSET KeySem + mov cs:byte ptr [bx],0FFh ; set keyboard semaphore + xor cx,cx + mov dx,9 ;; ProcBlock + call [DosFunction] ; sleep until a char is typed + jmp DoLocalRd1 + +LocalRead: + pop dx + pop cx + pop bx + pop ax + jmp [OldKbdHandler] ; read the character and return + +KeyBoardHandler endp + + +subttl $ConRead - Console Input (Read) +page + +;------------------------------------------------------------------------ +; Console Input (Read) +; +; entry: +; DS:BX = pointer to Request packet +; ES:DI = Transfer address +; CX = Count +; + +assume ds:NOTHING,es:NOTHING + +$ConRead: + and cx,cx + jnz jgl2 + jmp CRExit +; jcxz CRExit ; no chars to read BUGBUG restore +jgl2: cld ; make sure! + mov dx,word ptr ds:[bx].START ; get screen number + cmp dx,(MaxSIB-1) ; valid number? + jbe ConRLoop ; yes, do input + mov al,0BH ; no, READ FAULT ERROR + jmp StatusError +ConRLoop: + DEBUG 10h,1,, + cmp dx,[CurrSc] + je sjp0 + call GetSIBAdr ; get pointer to the SIB + DEBUG 10h,1,,<> + call DoPBlock ; block the process + jmp short ConRLoop ; test flag again +sjp0: + call ChrIn + stosb +; loop ConRLoop + loop jgl3 +CRExit: jmp StatusComplete + +jgl3: jmp ConRLoop + +subttl ChrIn - Read a single character In +page + +;------------------------------------------------------------------------ +; Read a single character In +; +; exit: +; Character in AL +; +; modifies: AX +; + +assume ds:NOTHING,es:NOTHING + +ChrIn: + DEBUG 10h,1,,<> + xor ax,ax + xchg al,[AltAH] ; Get Character & zero AltAH + or al,al ; A char available? + jnz KeyRet +; +;--- NOTE: The blocking on read is done at int 16h level +; in IBMBIO. No need to block here. +; + DEBUG 10h,1,< con.do.16 >,<> + mov ah,0 ; no, do a read call + pushf + call DoInt16 +;; int 16h + DEBUG 10h,1,< con.got.$x >, + or ax,ax ; check for non-key after BREAK + jnz jgl1 + jmp chrin + +jgl1: cmp ax,7200h ; CTRL-PRTSC ? + jnz sja0 + mov al,10h ; yes, make it a ctrl-P +sja0: or al,al ; special case? + jnz KeyRet + mov [AltAH],ah +KeyRet: + ret + + +subttl $ConRdnd - Console non-destructive Input, no wait +page + +;------------------------------------------------------------------------ +; Console non-destructive Input, no wait +; +; entry: +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +$ConRdnd: + mov dx,word ptr ds:[bx].START ; get screen number + cmp dx,(MaxSIB-1) ; valid number? + jbe sjq0 ; yes, do input + mov al,0BH ; no, READ FAULT ERROR + jmp StatusError +sjq0: + DEBUG 10h,1,, + cmp dx,[CurrSc] +IFDEF DEBUGFLG + je sjq1 + jmp ConBus +ELSE + jne ConBus ; not current screen, no char avail +ENDIF +; call GetSIBAdr ; get pointer to the SIB +; call DoPBlock ; block the process +; jmp short sjq0 ; test flag again +sjq1: + mov al,[AltAH] ; char avail already? + or al,al + jnz rdExit + DEBUG 10h,1,< NRD:do.16 >,<> + mov ah,1 ; no, get status + int 16h + jz ConBus + DEBUG 10h,1,< NRD:nonbus $x >, + or ax,ax + jnz NotBk ; Check for null after break + mov ah,0 ; flush the null + int 16h + jmp $ConRdnd ; try again +; jmp short $ConRdnd ; try again BUGBUG +NotBk: + cmp ax,7200h ; CTRL-PRTSC ? + jnz rdExit + mov al,10h ; yes, make it a ctrl-P +rdExit: + mov byte ptr ds:[bx].MEDIA,al ; save character +DoExit: jmp StatusComplete + +ConBus: DEBUG 10h,1,< ConBus - >,<> + jmp StatusDevReady + + +subttl $ConFlsh - Console Flush Input +page + +;------------------------------------------------------------------------ +; Console Flush Input +; +; entry: +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +$ConFlsh: + mov dx,word ptr ds:[bx].START ; get screen number + cmp dx,(MaxSIB-1) ; valid number? + jbe sjr0 ; yes, do flush + mov al,0BH ; no, READ FAULT ERROR + jmp StatusError +sjr0: + cmp dx,[CurrSc] + je sjr1 + call GetSIBAdr ; get pointer to the SIB + call DoPBlock ; block the process + jmp short sjr0 ; test flag again +sjr1: + mov [AltAH],0 ; clear side bufer + push ds + mov ax,RomData + mov ds,ax + assume ds:RomData + cli ; Disable interrupts + mov ax,offset RomData:KeyBuffer ; Start of Rom buffer + mov [BufferHead],ax + mov [BufferTail],ax ; Empty the queue + sti + pop ds + assume ds:NOTHING + jmp StatusComplete + + +subttl $ConWrit - Console Output (Write) +page + +;------------------------------------------------------------------------ +; Console Output (Write) +; +; entry: +; DS:BX = pointer to Request packet +; ES:DI = Transfer address +; CX = Count +; + +assume ds:NOTHING,es:NOTHING + +$ConWrit: + jcxz CWExit + mov dx, word ptr ds:[bx].START ; get screen number + cmp dx,(MaxSIB-1) ; valid screen number? + jbe sjb0 + mov al,0AH ; no, write fault error + jmp StatusError +sjb0: push cs + pop ds + assume ds:Code + mov bx,[CurrSIB] + +ConWLoop: + cmp dx,[CurrSc] ; Is it to the current screen? + je sjb2 ; yes, do not block + call GetSIBAdr ; get pointer to the SIB +sjb1: call DoPBlock ; block the process + jmp short ConWLoop ; test ALL flags again +sjb2: + cmp [bx].ctlS,0 ; is the screen frozen? + je sjb3 + mov ax,bx ; AX = [CurrSIB] = [CurrSIB].ctlS !!!! + jmp short sjb1 ; yes, block the process +sjb3: + cmp [SaveFlg],0 ; are we in the middle of a save? + je sjb4 ; no, do write + mov ax,offset SaveFlg + jmp short sjb1 ; yes, block... +sjb4: + mov al,es:[di] ; get a character + inc di + call CharOut + loop ConWLoop +CWExit: jmp StatusComplete + + +subttl CharOut - Output a character to the screen +page + +;------------------------------------------------------------------------ +; Output a character to the screen +; +; entry: +; AL = Character to write +; +; preserves: +; BX, CX, DX, DI, DS & ES +; + +assume ds:NOTHING,es:NOTHING + +IF ANSI + include ansi.inc +ELSE +CharOut: + push bx + push di + mov bx,7 + mov ah,14 + int 10h ; Write Character + pop di + pop bx + ret +ENDIF + + +subttl $GenIOCTL - Generic IOCTL +page + +;------------------------------------------------------------------------ +; Generic IOCTL +; +; entry: +; DS:BX = pointer to Request packet +; + +;--- Offsets into the request packet +;*** Check offset are correct +FunCode = 14 ; Function Code +FunCat = 13 ; Function Category +;*** +RegSI = 15 ; Contents of SI +RegDI = 17 ; Contents of DI +DatBuf = 19 ; Pointer to data buffer + +;--- Code & Category definitions +IOC_SC = 03h ;--- Screen Control +IOSC_LS = 41h ; Locate SIB +IOSC_SS = 42h ; save segment +IOSC_RS = 43h ; restore segment +IOSC_EI = 44h ; re-enable i/o +IOSC_IS = 45h ; initialize screen + +assume ds:NOTHING,es:NOTHING + +$GenIOCTL: + cmp byte ptr ds:[bx].FunCode,IOC_SC + jne GI_BadCode ; function not suported + mov si,word ptr ds:[bx].RegSI + mov al,byte ptr ds:[bx].FunCat + cmp al,IOSC_LS + jne sjc0 + jmp short do_IOSC_LS +sjc0: cmp al,IOSC_SS + jne sjc1 + jmp short do_IOSC_SS +sjc1: cmp al,IOSC_RS + jne sjc2 + jmp do_IOSC_RS +sjc2: cmp al,IOSC_EI + jne sjc3 + jmp do_IOSC_EI +sjc3: cmp al,IOSC_IS + jne GI_BadCode + jmp do_IOSC_IS + +GI_BadCode: + jmp CmdErr ; error exit: Command error + + +subttl do_IOSC_LS - Locate SIB +page + +;------------------------------------------------------------------------ +; Locate SIB +; +; entry: +; SI = SIB Number +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +do_IOSC_LS: + cmp si,(MaxSIB-1) ; index within range? + ja BadNum + push bx + push ds + push cs + pop ds + assume ds:Code + cmp si,[CurrSc] ; is it the current screen? + je CurrLS + mov [CurrSc],si ; no, just switch curr screens + mov dx,si ; index + call GetSIBAdr ; get pointer to SIB + mov [CurrSIB],ax ; save pointer to curr SIB + jmp short retLS + +CurrLS: + mov [SaveFlg],1 ; Signal we are Saving the screen + +;*** Only one segment for now + + mov ax,0 + call GetSegAdr ; on return BX points to segment + mov ax,RomData + mov es,ax + assume es:RomData +IF EAGLE + mov al,es:[CRT_MODE] + xor ah,ah + mov si,ax + mov ah,ScreenLen[si] + xor al,al +ELSE + mov ax,es:[CRT_LEN] + assume es:NOTHING ; not true, but just to be safe +ENDIF + mov [bx].SizeNeeded,ax ; save size of segment + mov ax,dx ; pointer to current SIB +retLS: + pop ds + pop bx + assume ds:NOTHING + mov word ptr ds:[bx].DatBuf,ax ; offset + mov word ptr ds:[bx].DatBuf+2,cs ; segment + mov word ptr ds:[bx].RegSI,0 ; operation ok + jmp StatusComplete + +BadNum: + mov word ptr ds:[bx].RegSI,1 ; bad SIB number error + jmp StatusComplete + + +subttl do_IOSC_SS - Save Segment +page + +;------------------------------------------------------------------------ +; Save Segment +; +; entry: +; SI = Segment Index (into the Current SIB) +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +do_IOSC_SS: + cmp si,(MaxSeg-1) ; within range? +BadNumJ1: + ja BadNum ; no, somebody screwed up... + push bx + push ds + cmp si,0 ; first segment save? + jne nfSS ; no, just save screen data +;--- save screen state data + push si ; save index + mov ax,RomData + mov ds,ax ; DS = ROM data area + assume ds:RomData + mov si,offset RomData:CRT_MODE + mov cx,CrtLen ; length of screen state data + push cs + pop es + assume es:Code + mov di,[CurrSIB] + lea di,[di].xCRT_MODE + cld + rep movsb ; copy ROM info to SIB area +IF ANSI + push cs + pop ds + assume ds:Code + mov si,offset AnsiState ; point to ANSI state info + mov cx,AnsiSize + rep movsb ; save ANSI state info in SIB +ENDIF + pop si ; restore segment index +;--- save a segment of screen data +nfSS: + push cs + pop ds + assume ds:Code + mov ax,si + call GetSegAdr ; get adress of segment and curr SIB ptr + mov cx,[bx].SizeNeeded ; CX = Ammount to transfer + shr cx,1 ; words! + les di,[bx].MPointer ; ES:DI = Screen save area + assume es:NOTHING + +;*** For now we are using only one segment + + mov si,dx ; SI points to the current SIB + mov bx,ColorSc ; assume color card + cmp [si].xCRT_MODE,7 ; is this a BW monitor? + jne do_save + mov bx,MonoSc +do_save: +IF BLANK + mov dx,[si].xADDR_6845 ; point to mode register + add dx,4 + mov al,[si].xCRT_MODE_SET ; and get value + and al,NOT 8 + out dx,al ; turn off video +ENDIF + mov ds,bx ; DS points to apropiate screen area + assume ds:NOTHING + mov si,0 + cld + rep movsw ; copy the screen +IF BLANK + or al,8 + out dx,al ; turn on video +ENDIF + pop ds + pop bx + mov word ptr ds:[bx].RegSI,0 ; operation ok + jmp StatusComplete + + +subttl do_IOSC_RS - Restore Segment +page + +;------------------------------------------------------------------------ +; Restore Segment +; +; entry: +; SI = Segment Index (into the Current SIB) +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +do_IOSC_RS: + cmp si,(MaxSeg-1) ; within range? + ja BadNumJ1 ; no, somebody screwed up... + push bx + push ds + push cs + pop ds + assume ds:Code + cmp si,0 ; first segment save? + jne nfRS ; no, just restore screen data +;--- restore screen state data + push si ; save index + mov si,[CurrSIB] + push si + lea si,[si].xCRT_MODE + mov ax,RomData + mov es,ax ; ES = ROM data area + assume es:RomData + mov cx,CrtLen ; length of screen state data + mov di,offset RomData:CRT_MODE + cld + rep movsb ; copy ROM info from SIB area +IF ANSI + push es + push cs + pop es + assume es:Code + mov di,offset AnsiState ; point to ANSI state info + mov cx,AnsiSize + rep movsb ; restore ANSI state info from SIB + pop es + assume es:RomData +ENDIF + +;--- Setup new screen state + pop si + mov al,[si].xCRT_MODE + cmp al,7 ; is this the BW monitor? + jne sjd0 + mov al,2 ; this is the "real" mode +sjd0: + mov ah,0 + int 10h ; set new mode + mov cx,[si].xCURSOR_MODE + mov ah,1 + int 10h ; set cursor type + mov dx,[si].xCURSOR_POSN + mov bh,[si].xACTIVE_PAGE + mov ah,2 + int 10h ; set cursor position + mov al,[si].xACTIVE_PAGE + mov ah,5 + int 10h ; set page # + mov dx,[si].xADDR_6845 + add dx,5 + mov al,[si].xCRT_PALETTE + out dx,al ; set color port + mov es:CRT_PALETTE,al + pop si ; restore segment index +;--- restore a segment of screen data +nfRS: + mov ax,si + call GetSegAdr ; get adress of segment + mov cx,[bx].SizeNeeded ; CX = Ammount to transfer + shr cx,1 ; words! + lds si,[bx].MPointer ; DS:SI = Screen save area + assume ds:NOTHING + +;*** For now we are using only one segment + + mov di,dx ; DI points to the current SIB + mov bx,ColorSc ; assume color card + cmp cs:[di].xCRT_MODE,7 ; is this a BW monitor? + jne do_rest + mov bx,MonoSc +do_rest: +IF BLANK + mov dx,cs:[di].xADDR_6845 ; point to mode register + add dx,4 + mov al,cs:[di].xCRT_MODE_SET ; and get value + and al,NOT 8 + out dx,al ; turn off video +ENDIF + mov es,bx ; ES points to apropiate screen area + assume es:NOTHING + mov di,0 + cld + rep movsw ; copy the screen +IF BLANK + or al,8 + out dx,al ; turn on video +ENDIF + + pop ds + assume ds:NOTHING + pop bx + mov word ptr ds:[bx].RegSI,0 ; operation ok + jmp StatusComplete + +BadNumJ: + jmp BadNum + + +subttl do_IOSC_EI - Re-enable i/o +page + +;------------------------------------------------------------------------ +; Re-enable i/o +; +; entry: +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +do_IOSC_EI: + mov [SaveFlg],0 ; Signal we are done Saving the screen + mov ax,offset Code:SaveFlg + call DoPRun ; ProcRun + mov ax,[CurrSIB] ; pointer to current SIB + call DoPRun ; ProcRun any output blocked because + ; screen was not current + jmp StatusComplete + + +subttl do_IOSC_IS - Initialize Screen +page + +;------------------------------------------------------------------------ +; Initialize Screen +; +; entry: +; SI = SIB Number +; DS:BX = pointer to Request packet +; + +assume ds:NOTHING,es:NOTHING + +do_IOSC_IS: + cmp si,(MaxSIB-1) ; index within range? + ja BadNumJ + push ds + push cs + pop ds + assume ds:Code + mov [CurrSc],si ; switch curr screens + mov dx,si ; index + call GetSIBAdr ; get pointer to SIB + mov [CurrSIB],ax ; save pointer to curr SIB + mov si,ax + mov [si].ctlS,0 ; screen not frozen +;--- set screen mode to pc mode 3 (80x25 BW) + mov ax,0003 ; Set mode 3 + int 10h + pop ds + assume ds:NOTHING + mov word ptr ds:[bx].RegSI,0 ; operation ok + jmp StatusComplete + + +subttl $ConStop - Stop (freeze) console output +page + +;------------------------------------------------------------------------ +; Stop (freeze) console output +; + +assume ds:NOTHING,es:NOTHING + +$ConStop: + mov bx,[CurrSIB] ; pointer to current SIB + mov cs:[bx].ctlS,01 ; set the freeze flag + jmp StatusComplete + + +subttl $ConStart - Start (continue) console output +page + +;------------------------------------------------------------------------ +; Start (continue) console output +; + +assume ds:NOTHING,es:NOTHING + +$ConStart: + mov bx,[CurrSIB] ; pointer to current SIB + cmp cs:[bx].ctlS,0 ; is it already going? + je csRet ; yes, no need to re-enable + mov cs:[bx].ctlS,0 ; reset the freeze flag + lea ax,[bx].ctlS ; get address of current ctlS + call DoPRun ; do ProcRun +csRet: jmp StatusComplete + + +subttl DoPBlock - Block the current process +page + +;------------------------------------------------------------------------ +; Block the current process +; +; entry: +; CS:AX = address to block on +; +; modifies: AX, FLAGS +; + +assume ds:NOTHING,es:NOTHING + +DoPBlock: + push bx + push cx + push dx + mov bx,ax + mov ax,cs ; AX:BX = event identifier + xor cx,cx ; No timeout +;; mov dx,0109h ;;BUGBUG - should be interruptible wait; will + ;; give InternalError (SchedFind - not on Q) + mov dx,0009h ; PROCBLOC function + cli ; No races! + call [DosFunction] + pop dx ; on return ints are back on + pop cx + pop bx + ret + + +subttl DoPRun - Restart a process +page + +;------------------------------------------------------------------------ +; Restart a process +; +; entry: +; CS:AX = address to signal on (same as blocked on) +; +; modifies: AX, FLAGS +; + +assume ds:NOTHING,es:NOTHING + +DoPRun: + push bx + push cx + push dx + mov bx,ax + mov ax,cs + mov dx,10 ; PROCRUN function + call [DosFunction] + pop dx + pop cx + pop bx + ret + + +subttl GetSIBAdr - Return SIB address +page + +;------------------------------------------------------------------------ +; Returns the adress of the specified SIB +; +; entry: +; DX = index to the SIB +; +; exit: +; AX = pointer to the SIB +; +; preserves: ALL +; + +assume ds:Code,es:NOTHING + +GetSIBAdr: + push dx ; save screen # + mov ax,dx ; index + mov dx,(SIZE SIBst) + mul dx ; multiply by size of SIB entry + pop dx ; restore screen # + add ax,offset SIB ; AX = pointer to SIB for the write + ret + + +subttl GetSegAdr - Return segment address +page + +;------------------------------------------------------------------------ +; Returns the adress of a segment in the current SIB +; +; entry: +; AX = index to the segment +; +; exit: +; BX = pointer to the segment +; DX = pointer to the Current SIB +; + +assume ds:Code,es:NOTHING + +GetSegAdr: + mov dx,(SIZE SEGst) + mul dx ; multiply by size of SEG entry + mov bx,[CurrSIB] ; pointer to SIB + mov dx,bx ; save for exit + mov bx,[bx].OffsetVal ; pointer to start of SEGs in SIB + add bx,ax ; BX = pointer to SEG from start of SIB + add bx,dx ; BX = absolute pointer to SEG to use + ret + +ifdef DEBUGFLG +if NOT INBIOS + INCLUDE BUGCODE.INC +endif +endif + + +subttl $ConInit - Initialization Routine +page + +;------------------------------------------------------------------------ +; Initialization Routine +; +;entry: +; DS:BX = pointer to Request packet +; ES:DI = Dos Functions entry point address +; + +assume ds:NOTHING,es:NOTHING + +$ConInit: +IF NOT INBIOS + push ds ; print greeting + push cs + pop ds + mov dx,offset Intro + MOV ah,9 + int 21h + pop ds + mov word ptr ds:[bx].TRANS, offset $ConInit + mov word ptr ds:[bx].TRANS+2,cs +ENDIF + mov cs:Word Ptr DosFunction,di ; Save pointer to service routines + mov cs:Word Ptr DosFunction+2,es + + mov ax,0 + mov cx,1 + mov dx,16 + call [DosFunction] ; get DOS variable ScrnIoOk + mov word ptr ScrnIoOk,ax + mov word ptr ScrnIoOk+2,dx + +;* Initialize interrupt vectors. +;;BUGBUG - we should be using Get/Set_Interrupt_Vector calls + + xor ax,ax ; initialize break interrupt handler + mov es,ax ; points to page 0 + mov ax,cs + mov word ptr es:BRKADR,offset Break + mov word ptr es:BRKADR+2,ax ; Vector for Break + + MOV DI,9*4 ; INT 9 - Keyboard interrupt vector + MOV CX,es:[DI] ; Save old addr to hook to + MOV WORD PTR OldKeyInterrupt,CX + MOV CX,es:2[DI] + MOV WORD PTR (OldKeyInterrupt+2),CX + MOV CX,OFFSET KeyboardInterrupt + XCHG AX,CX + STOSW + XCHG AX,CX + STOSW ; Set new keyboard interrupt + + mov di,16h*4 ; INT 16 - keyboard input + MOV CX,es:[DI] ; Save INT 16 addr to hook to + MOV WORD PTR OldKbdHandler,CX + MOV CX,es:2[DI] + MOV WORD PTR (OldKbdHandler+2),CX + MOV CX,OFFSET KeyboardHandler + XCHG AX,CX + STOSW + XCHG AX,CX ; Set new keyboard Handler + STOSW + jmp StatusComplete + + +IF INBIOS +Code ends + +BiosInit segment para public 'CODE' +ENDIF + +Intro db "--- Installing MTCON Device Driver V" + db CVERS+"0",".",CREV/10+"0" + db (CREV-CREV/10*10)+"0"," ---" + db 13,10,"$" + +BiosInit ends + + END diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ new file mode 100644 index 0000000..ed4dc74 Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ differ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/READ_ME b/v4.0-ozzie/bin/DISK2/BIOS/READ_ME new file mode 100644 index 0000000..03623a4 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/READ_ME @@ -0,0 +1,25 @@ +29 May 1984 + +The object files given here are sufficient to create the BIOS +for the IBM system. Some sources are given as examples for +OEM supplied device drivers. These sources do not necessarily +implement all the features described in the device driver +documentation. They have evolved in parallel with the +documentation, so some features described in the documentation +may not yet be present in the drivers. Below is a summary of +the files supplied: + + read_me This file. + ibmbio.asm Main body of the BIOS. + ibmdsk.asm Floppy and Hard disk drivers. + ibmmtcon.asm Multi-screen console driver. + ansi.inc ANSI X3.64 terminal emulation. + bugcode.inc Module which implements debugging + prints. The routine PUTC must be + modified for other devices. See + also the file DEFDBUG.INC. + sys*.obj The SYSINIT program. No source supplied. + biosobj.mak Contains instructions for building the + IBM BIOS. + bootpach.exe Modifies a V2.0 boot sector (on A:) for + the IBM to accomodate the larger BIOS. diff --git a/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ new file mode 100644 index 0000000..4439f35 Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ differ diff --git a/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ new file mode 100644 index 0000000..0fc06ba Binary files /dev/null and b/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ differ diff --git a/v4.0-ozzie/bin/DRDOS1.IMD b/v4.0-ozzie/bin/DRDOS1.IMD new file mode 100644 index 0000000..0a7a84f Binary files /dev/null and b/v4.0-ozzie/bin/DRDOS1.IMD differ diff --git a/v4.0-ozzie/bin/DRDOS1_IMD.img b/v4.0-ozzie/bin/DRDOS1_IMD.img new file mode 100644 index 0000000..d6d7165 Binary files /dev/null and b/v4.0-ozzie/bin/DRDOS1_IMD.img differ diff --git a/v4.0-ozzie/bin/DRDOS2.IMD b/v4.0-ozzie/bin/DRDOS2.IMD new file mode 100644 index 0000000..972058b Binary files /dev/null and b/v4.0-ozzie/bin/DRDOS2.IMD differ diff --git a/v4.0-ozzie/bin/DRDOS2_IMD.img b/v4.0-ozzie/bin/DRDOS2_IMD.img new file mode 100644 index 0000000..64d8395 Binary files /dev/null and b/v4.0-ozzie/bin/DRDOS2_IMD.img differ diff --git a/v4.0/LICENSE b/v4.0/LICENSE new file mode 100644 index 0000000..b13d100 --- /dev/null +++ b/v4.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) IBM and Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/v4.0/src/BIOS/BIOSTRUC.INC b/v4.0/src/BIOS/BIOSTRUC.INC new file mode 100644 index 0000000..f131e11 --- /dev/null +++ b/v4.0/src/BIOS/BIOSTRUC.INC @@ -0,0 +1,103 @@ +%OUT BIOSTRUC.INC... +; SCCSID = @(#)BIOSTRUC.INC 1.0 86/09/30 +; ROM BIOS CALL PACKET STRUCTURES + +;******************************* +;System Service call ( Int 15h ) +;******************************* +;Function AH = 0C0h, Return system configuration +;For PC and PCJR on return: +; (AH) = 80h +; (CY) = 1 +;For PCXT, PC PORTABLE and PCAT on return: +; (AH) = 86h +; (CY) = 1 +;For all others: +; (AH) = 0 +; (CY) = 0 +; (ES:BX) = pointer to system descriptor vector in ROS +; System descriptor : +; DW xxxx length of descriptor in bytes, +; minimum length = 8 +; DB xx model byte +; 0FFh = PC +; 0FEh = PC/XT, Portable +; 0FDh = PC/JR +; 0FCh = PC/AT, 6Mhz PC/AT, +; 6Mhz PC/AT running coprocessor(?), +; PS/2 Model 50, 50 z +; 0FAh = PS/2 Model 25, 30 +; 0F9h = PC Convertible +; 0F8h = PS/2 Model 80 +; 0F7h = Nova +; 0E0 thru 0EFh = reserved +; +; DB xx secondary model byte +; 000h = PC1 +; 000h = PC/XT, Portable +; 000h = PC/JR +; 000h = PC/AT +; 001h = 6Mhz PC/AT +; 003h = 6Mhz PC/AT running coprocessor(?) +; 004h = PS/2 Model 50, 50z +; 001h = PS/2 Model 25 +; 000h = PC Convertible +; 000h = PS/2 Model 80 +; 000h = Nova +; +; DB xx bios revision level +; 00 for first release, subsequent release +; of code with same model byte and +; secondary model byte require revison level +; to increase by one. +; +; DB xx feature information byte 1 +; X0000000 = 1, bios use DMA channel 3 +; = 0, DMA channel 3 not used +; +; 0X000000 = 1, 2nd Interrupt chip present +; = 0, 2nd Interrupt chip not present +; +; 00X00000 = 1, Real Time Clock present +; = 0, Real Time Clock not present +; +; 000X0000 = 1, Keyboard escape sequence(INT15h) +; called in keyboard interrupt +; (Int 09h). +; = 0, Keyboard escape sequence not +; called. +; 0000XXXX reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; + +BIOS_SYSTEM_DESCRIPTOR struc +bios_SD_leng dw ? +bios_SD_modelbyte db ? +bios_SD_scnd_modelbyte db ? + db ? +bios_SD_featurebyte1 db ? + db 4 dup (?) +BIOS_SYSTEM_DESCRIPTOR ends + +;FeatureByte1 bit map equates +DMAchannel3 equ 10000000b +ScndIntController equ 01000000b +RealTimeClock equ 00100000b +KeyEscapeSeq equ 00010000b +; +;Model Byte +MDL_PC1 EQU 0FFH +MDL_XT EQU 0FEH +MDL_JR EQU 0FDH +MDL_AT EQU 0FCH +MDL_CONVERT EQU 0F9H + +mdl_ps2_30 equ 0fah +mdl_ps2_80 equ 0f8h diff --git a/v4.0/src/BIOS/CLOCKSUB.INC b/v4.0/src/BIOS/CLOCKSUB.INC new file mode 100644 index 0000000..65b6698 --- /dev/null +++ b/v4.0/src/BIOS/CLOCKSUB.INC @@ -0,0 +1,78 @@ +; +; date_verify loosely checks bcd date values to be in range in bin_date_time +; +date_verify: ; +assume ds:code,es:nothing + cmp byte ptr bin_date_time+0,20h ; century check + ja date_error ; jmp error + jz century_20 ; jmp in 20th century + cmp byte ptr bin_date_time+0,19h ; century check + jb date_error ; jmp error + cmp byte ptr bin_date_time+1,80h ; year check + jb date_error ; jmp error +century_20: ; + cmp byte ptr bin_date_time+1,99h ; year check + ja date_error ; jmp error + cmp byte ptr bin_date_time+2,12h ; month check + ja date_error ; jmp error + cmp byte ptr bin_date_time+2,00h ; month check + jbe date_error ; jmp error + cmp byte ptr bin_date_time+3,31h ; day check + ja date_error ; jmp error + cmp byte ptr bin_date_time+3,00h ; day check + jbe date_error ; jmp error + clc ; set success flag + ret ; +date_error: ; + stc ; set error flag + ret ; + +; +; time_verify very loosely checks bcd date values to be in range in bin_date_time +; +time_verify: +assume ds:code,es:nothing + cmp byte ptr bin_date_time+0,24H + ja time_error + cmp byte ptr bin_date_time+1,59H + ja time_error + cmp byte ptr bin_date_time+2,59H + ja time_error + clc + ret +time_error: + stc + ret + +; +; bcd_verify checks values in bin_date_time to be valid +; bcd numerals. carry set if any nibble out of range +; +bcd_verify: ; +assume ds:code,es:nothing + mov cx,4 ; 4 bytes to check + mov bx,offset bin_date_time ; +bv_loop: ; + mov al,[bx] ; get a bcd number (0..99) + mov ah,al ; + and ax,0f00fh ; 10's place in high ah, 1's in al + cmp al,10 ; is 1's place in range? + ja bv_error ; jmp out of range + shr ah,1 ; swap nibbles + shr ah,1 ; ... + shr ah,1 ; ... + shr ah,1 ; ... + and ah,0fh ; get rid of any erroneous bits + cmp ah,10 ; is 10's place in range + ja bv_error ; jmp out of range + inc bx ; next byte + dec cx ; + jnz bv_loop ; + clc ; set success flag + ret ; +bv_error: ; + stc ; set error flag + ret ; +; +; Dos 3.30 - The real time clock structures were moved to msbio2.asm +; diff --git a/v4.0/src/BIOS/CMOSEQU.INC b/v4.0/src/BIOS/CMOSEQU.INC new file mode 100644 index 0000000..b52b259 --- /dev/null +++ b/v4.0/src/BIOS/CMOSEQU.INC @@ -0,0 +1,50 @@ + ;;Rev 3.30 Modification +;Equates for CMOS. + +;---------------------------------------- +; CMOS EQUATES FOR THIS SYSTEM : +;------------------------------------------------------------------------------- +CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT +CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT +NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - + ; HIGH BIT OF CMOS LOCATION ADDRESS + +;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- +CMOS_SECONDS EQU 000H ; SECONDS +CMOS_SEC_ALARM EQU 001H ; SECONDS ALARM ## NOTE: ALL LOCATIONS +CMOS_MINUTES EQU 002H ; MINUTES | IN THE CMOS AREA +CMOS_MIN_ALARM EQU 003H ; MINUTES ALARM | ARE IBM USE ONLY +CMOS_HOURS EQU 004H ; HOURS | AND SUBJECT TO +CMOS_HR_ALARM EQU 005H ; HOURS ALARM | CHANGE. ONLY THE +CMOS_DAY_WEEK EQU 006H ; DAY OF THE WEEK | POST & BIOS CODE +CMOS_DAY_MONTH EQU 007H ; DAY OF THE MONTH | SHOULD DIRECTLY +CMOS_MONTH EQU 008H ; MONTH | ACCESS LOCATIONS +CMOS_YEAR EQU 009H ; YEAR (TWO DIGITS) | IN CMOS STORAGE. +CMOS_REG_A EQU 00AH ; STATUS REGISTER A '----------------- +CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM +CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS +CMOS_REG_D EQU 00DH ; STATUS REGISTER D BATTERY +CMOS_DIAG EQU 00EH ; POST DIAGNOSTIC STATUS RESULTS BYTE +CMOS_SHUT_DOWN EQU 00FH ; SHUTDOWN STATUS COMMAND BYTE +CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; +; EQU 011H ; - RESERVED ;C +CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H +; EQU 013H ; - RESERVED ;E +CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C +CMOS_B_M_S_LO EQU 015H ; BASE MEMORY SIZE - LOW BYTE (X1024) ;K +CMOS_B_M_S_HI EQU 016H ; BASE MEMORY SIZE - HIGH BYTE ;S +CMOS_E_M_S_LO EQU 017H ; EXPANSION MEMORY SIZE - LOW BYTE ;U +CMOS_E_M_S_HI EQU 018H ; EXPANSION MEMORY SIZE - HIGH BYTE ;M +CMOS_DISK_1 EQU 019H ; FIXED DISK TYPE - DRIVE C EXTENSION ;E +CMOS_DISK_2 EQU 01AH ; FIXED DISK TYPE - DRIVE D EXTENSION ;D +; EQU 01BH ; - 1BH THROUGH 2DH - RESERVED ; +CMOS_CKSUM_HI EQU 02EH ; CMOS CHECKSUM - HIGH BYTE ;* +CMOS_CKSUM_LO EQU 02FH ; CMOS CHECKSUM - LOW BYTE ;* +CMOS_U_M_S_LO EQU 030H ; USABLE MEMORY ABOVE 1 MEG - LOW BYTE +CMOS_U_M_S_HI EQU 031H ; USABLE MEMORY ABOVE 1 MEG - HIGH BYTE +CMOS_CENTURY EQU 032H ; DATE CENTURY BYTE (BCD) +CMOS_INFO128 EQU 033H ; 128KB INFORMATION STATUS FLAG BYTE +; EQU 034H ; - 34H THROUGH 3FH - RESERVED +; + ;;End of Modification + \ No newline at end of file diff --git a/v4.0/src/BIOS/DEFEMS.INC b/v4.0/src/BIOS/DEFEMS.INC new file mode 100644 index 0000000..a1786d0 --- /dev/null +++ b/v4.0/src/BIOS/DEFEMS.INC @@ -0,0 +1,33 @@ +;J.K. This is a temporary version of EMS function definitions needed for +;IBMBIO SYSINIT. + +EMS_INT equ 67h ;interrupt vector designated for EMS. + +EMS_STATUS equ 40h ;status of memery manager +EQ_PAGES equ 42h ;get number of unallocated & total pages +E_GET_HANDLE equ 43h ;allocate pages +EMAP_L_TO_P equ 44h ;Map logical to physical page +EMAP_STATE equ 4Fh ;Mapping status + GET_MAP_STATE equ 00h + GET_MAP_SIZE equ 02h + SET_MAP_STATE equ 01h +EDE_ALLOCATE equ 45h ;deallocate pages +EMS_VERSION equ 46h ;Get EMM version number +GET_PAGE_FRAME equ 58h ;Get page frame address + GET_PAGEFRAME_TAB equ 00H + GET_NUM_PAGEFRAME equ 01H +EMS_HANDLE_NAME equ 53h + SET_HANDLE_NAME equ 01h + +IBM_PAGE_ID equ 255 ;Physical page id that will be used by + ;IBMBIO and IBMDOS for buffer manipulation. + +;MAX_NUM_PAGEFRAME equ 12 ;maximum number of page frames IBMBIO can + ;handle + +MAX_NUM_PAGEFRAME equ 64 ;maximum number of page frames MSBIO can + ;handle + +EMSVERSION equ 40h ;4.0 + + \ No newline at end of file diff --git a/v4.0/src/BIOS/DEVMARK.INC b/v4.0/src/BIOS/DEVMARK.INC new file mode 100644 index 0000000..1b919f7 --- /dev/null +++ b/v4.0/src/BIOS/DEVMARK.INC @@ -0,0 +1,23 @@ +;Structure, Equtes for DEVMARK for MEM command. + +DEVMARK struc +DEVMARK_ID db 0 +DEVMARK_SEG dw 0 +DEVMARK_SIZE dw 0 +DEVMARK_DUM db 3 dup (?) +DEVMARK_FILENAME db 8 dup (' ') +DEVMARK ends + +DEVMARK_STK equ 'S' +DEVMARK_DEVICE equ 'D' +DEVMARK_IFS equ 'I' +DEVMARK_BUF equ 'B' +DEVMARK_CDS equ 'L' ;lastdrive +DEVMARK_FILES equ 'F' +DEVMARK_FCBS equ 'X' +DEVMARK_INST equ 'T' ;used for SYSINIT BASE for INSTALL= command. +DEVMARK_EMS_STUB equ 'E' + +SETBRKDONE equ 00000001b +FOR_DEVMARK equ 00000010b +NOT_FOR_DEVMARK equ 11111101b diff --git a/v4.0/src/BIOS/JUMPMAC.INC b/v4.0/src/BIOS/JUMPMAC.INC new file mode 100644 index 0000000..e631e2e --- /dev/null +++ b/v4.0/src/BIOS/JUMPMAC.INC @@ -0,0 +1,31 @@ + ;;Rev 3.30 Modification +; +; given a label either 2 byte jump to another label _J +; if it is near enough or 3 byte jump to +; + +jump macro lbl + local a +.xcref + + ifndef lbl&_j ;; is this the first invocation +a: + JMP lbl + ELSE + IF (lbl&_J GE $) OR ($-lbl&_J GT 126) +a: + JMP lbl ;; is the jump too far away? + ELSE +a: + JMP lbl&_J ;; do the short one... + ENDIF + ENDIF +lbl&_j = a +.cref + endm +.xcref jump +;REDEFINE THE ABOVE MACRO TO ALWAYS TRY A 3 BYTE NEAR JUMP +JUMP MACRO LBL + JMP LBL + ENDM ;;End of Modification + \ No newline at end of file diff --git a/v4.0/src/BIOS/LOCSCR b/v4.0/src/BIOS/LOCSCR new file mode 100644 index 0000000..2bbd69c --- /dev/null +++ b/v4.0/src/BIOS/LOCSCR @@ -0,0 +1 @@ +70 diff --git a/v4.0/src/BIOS/MAKEFILE b/v4.0/src/BIOS/MAKEFILE new file mode 100644 index 0000000..66a281f --- /dev/null +++ b/v4.0/src/BIOS/MAKEFILE @@ -0,0 +1,167 @@ +#************************** makefile for bios *************************** + +dest =io +msg =..\messages +dos =..\dos +inc =..\inc +hinc =..\h + +# +####################### dependencies begin here. ######################### +# + +all: $(dest).sys + +msbio.cl1: msbio.skl \ + $(msg)\$(COUNTRY).msg + +msload.obj: msload.asm \ + makefile \ + msbio.cl1 \ + $(inc)\bootform.inc \ + $(inc)\versiona.inc \ + msload.inc + +msload.com: msload.obj + link msload.obj,msload,,; + exe2bin msload.exe msload.com + +msbio1.obj: msbio1.asm \ + makefile \ + msbdata.inc \ + msgroup.inc \ + jumpmac.inc \ + pushpop.inc \ + $(inc)\devsym.inc \ + msdskpr.inc \ + msmacro.inc + +mscon.obj: mscon.asm \ + makefile \ + msgroup.inc \ + jumpmac.inc \ + msmacro.inc + +msaux.obj: msaux.asm \ + makefile \ + msgroup.inc \ + jumpmac.inc \ + msmacro.inc + +mslpt.obj: mslpt.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + msmacro.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc $(inc)\bpb.inc + +msclock.obj: msclock.asm \ + makefile \ + msgroup.inc \ + msmacro.inc + +msdisk.obj: msdisk.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + pushpop.inc \ + msmacro.inc \ + $(inc)\devsym.inc \ + msdskpr.inc \ + msioctl.inc $(inc)\ioctl.inc $(inc)\bpb.inc + +msinit.obj: msinit.asm \ + makefile \ + msgroup.inc \ + msdskpr.inc \ + msequ.inc $(inc)\msbds.inc \ + $(inc)\cputype.inc \ + msmacro.inc \ + readcloc.inc \ + clocksub.inc \ + msextrn.inc + + +sysinit1.obj: sysinit1.asm \ + makefile \ + msstack.inc \ + msbio.cl4 \ + msbio.cl5 \ + stkinit.inc \ + devmark.inc \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\cputype.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + + +sysconf.obj: sysconf.asm \ + makefile \ + psoption.inc \ + devmark.inc \ + $(inc)\psdata.inc \ + $(inc)\parse.asm \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + +sysinit2.obj: sysinit2.asm \ + makefile \ + devmark.inc \ + $(inc)\copyrigh.inc \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + +sysimes.obj: sysimes.asm \ + makefile \ + msmacro.inc \ + msbio.cl3 \ + msequ.inc $(inc)\msbds.inc + +msbio2.obj: msbio2.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + $(inc)\devsym.inc \ + pushpop.inc \ + msmacro.inc \ + msbio.cl2 \ + ms96tpi.inc msvolid.inc + +mshard.obj: mshard.asm $(inc)\postequ.inc $(inc)\dseg.inc + +$(dest).sys: msbio.cl1 msbio1.obj mscon.obj msaux.obj \ + mslpt.obj msclock.obj msdisk.obj msbio2.obj \ + msinit.obj mshard.obj sysinit1.obj sysconf.obj \ + sysinit2.obj sysimes.obj \ + msload.com \ + makefile + link @msbio.lnk + exe2bin msbio.exe msbio.bin + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS LOGICAL DRIVE + CALL SETDRIVE ;GET BDS FOR DRIVE + INC WORD PTR DS:[DI].OPCNT + JMP EXIT ;ARR 2.41 + +DSK$CLOSE: ;ARR 2.41 + PUBLIC DSK$CLOSE + + MESSAGE FTESTDISK,<"DISK CLOSE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS LOGICAL DRIVE + CALL SETDRIVE ;GET BDS FOR DRIVE + CMP WORD PTR DS:[DI].OPCNT,0 + JZ EXITJX ; WATCH OUT FOR WRAP ARR 2.41 + DEC WORD PTR DS:[DI].OPCNT +EXITJX: + JMP EXIT + +; INPUT : DS:DI POINTS TO CURRENT BDS FOR DRIVE. +; RETURN : ZERO SET IF NO OPEN FILES +; ZERO RESET IF OPEN FILES +CHKOPCNT: + MESSAGE FTEST96,<"CHECK OPEN COUNT "> + MNUM FTEST96,AX + MESSAGE FTEST96, + CMP WORD PTR DS:[DI].OPCNT,0 + RET + +; +; AT MEDIA CHECK TIME, WE NEED TO REALLY GET DOWN AND CHECK WHAT THE CHANGE IS. +; THIS IS GUARANTEED TO BE EXPENSIVE. +; + PUBLIC MEDIACHECK +MEDIACHECK: + CALL CHECKSINGLE ; MAKE SURE CORRECT DISK IS IN PLACE + XOR SI,SI + CALL HASCHANGE + JZ MEDIARET + CALL CHECKROMCHANGE + JNZ MEDIADOVOLID + PUSH AX + PUSH DX +;SB33001**************************************************************** + mov DL, DS:[DI.drivenum] ;SB ; set logical drive number ;3.30* + mov AH, 16h ;SB ; get changeline status ;3.30* + int 13h ;SB ; call rom diskette routine ;3.30* +;SB33001**************************************************************** + POP DX + POP AX + JC MEDIADOVOLID + MOV SI,1 ; SIGNAL NO CHANGE +; THERE ARE SOME DRIVES WITH CHANGELINE THAT "LOSE" THE CHANGELINE INDICATION +; IF A DIFFERENT DRIVE IS ACCESSED AFTER THE CURRENT ONE. IN ORDER TO AVOID +; MISSING A MEDIA CHANGE, WE RETURN AN "I DON'T KNOW" TO DOS IF THE CHANGELINE +; IS NOT ACTIVE AND WE ARE ACCESSING A DIFFERENT DRIVE FROM THE LAST ONE. +; IF WE ARE ACCESSING THE SAME DRIVE, THEN WE CAN SAFELY RELY ON THE CHANGELINE +; STATUS. + PUBLIC LOSECHNG +LOSECHNG: + MOV BL,CS:[TIM_DRV] ; GET LAST DRIVE ACCESSED + CMP BYTE PTR [DI].DRIVENUM,BL + JZ MEDIARET +; DO THE 2 SECOND TWIDDLE. IF TIME >= 2 SECONDS, DO A VOLID CHECK. +; OTHERWISE RETURN "I DON'T KNOW" (STRICTLY SPEAKING, WE SHOULD RETURN A +; "NOT CHANGED" HERE SINCE THE 2 SECOND TEST SAID NO CHANGE.) - RS. + SAVEREG + CALL CHECK_TIME_OF_ACCESS + RESTOREREG + OR SI,SI + JZ MEDIADOVOLID ; CHECK_TIME SAYS ">= 2 SECS PASSED" + XOR SI,SI ; RETURN "I DON'T KNOW" + PUBLIC MEDIARET +MEDIARET: + RET +; +; SOMEHOW THE MEDIA WAS CHANGED. LOOK AT VID TO SEE. WE DO NOT LOOK AT FAT +; BECAUSE THIS MAY BE DIFFERENT SINCE WE ONLY SET MEDBYT WHEN DOING A READ +; OR WRITE. +; +MEDIADOVOLID: + CALL GETBP ; BUILD A NEW BPB IN CURRENT BDS + JC MEDIARET + CALL CHECK_VID + JNC MEDIARET + CALL MAPERROR ; FIX UP AL FOR RETURN TO DOS + RET +; +; SIMPLE, QUICK CHECK OF LATCHED CHANGE. IF NO INDICATION, THEN RETURN +; OTHERWISE DO EXPENSIVE CHECK. IF THE EXPENSIVE TEST FAILS, POP OFF THE +; RETURN AND SET AL = 15 (FOR INVALID MEDIA CHANGE) WHICH WILL BE RETURNED TO +; DOS. +;J.K. 9/16/86 For DOS 3.3, this will work only for the drive that has +;J.K. 9/16/86 changeline. + PUBLIC CHECKLATCHIO +CHECKLATCHIO: +; IF RETURNING FAKE BPB THEN ASSUME THE DISK HAS NOT CHANGED +; TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB +; JNZ CHECKRET +;J.K. 9/16/86 +; call HasChange ;change line supported? +; jz CheckRet ;No. Just return + CALL CHKOPCNT + JNZ CHECKROM +CHECKRET: + RET +; +; CHECK FOR PAST ROM INDICATIONS. IF NO ROM CHANGE INDICATED, THEN RETURN OK. +; + PUBLIC CHECKROM +CHECKROM: + CALL CHECKROMCHANGE + JZ CHECKRET ; NO CHANGE +; +; WE NOW SEE THAT A CHANGE LINE HAS BEEN SEEN IN THE PAST. LET'S DO THE +; EXPENSIVE VERIFICATION. +; + MESSAGE FTEST96,<"CHECKROMCHANGE SAYS YES...",CR,LF> + CALL GETBP ; BUILD BPB IN CURRENT BDS + JC RET_NO_ERROR_MAP ; GETBP HAS ALREADY CALLED MAPERROR + CALL CHECK_VID + JC CHECKLATCHRET ; DISK ERROR TRYING TO READ IN. + OR SI,SI ; IS CHANGED FOR SURE? + JNS CHECKRET + CALL RETURNVID +CHECKLATCHRET: + CALL MAPERROR ; FIX UP AL FOR RETURN TO DOS +RET_NO_ERROR_MAP: + STC + POP SI ; POP OFF RETURN ADDRESS + RET + +; +; CHECK THE FAT AND THE VID. RETURN IN DI -1 OR 0. RETURN WITH CARRY SET +; ONLY IF THERE WAS A DISK ERROR. RETURN THAT ERROR CODE IN AX. +; + PUBLIC CHECKFATVID +CHECKFATVID: + MESSAGE FTEST96,<"CHECK FAT",CR,LF> + CALL FAT_CHECK + OR SI,SI + JS CHANGED_DRV +; +; THE FAT WAS THE SAME. HOW ABOUT THE VOLUME ID? +; +CHECK_VID: +;J.K. Now with the extended BOOT record, the logic should be enhanced. +;If it is the extended BOOT record, then we check the volume serial +;number instead of volume id. If it is different, then set SI to -1. +;If it is same, then SI= 1 (No change). +;If it is not the extended BOOT record, then just follows the old +;logic. DOS 4.00 will check if the # of FAT in the boot record BPB +;is not 0. If it is 0 then it must be Non_FAT based system and +;should have already covered by extended boot structure checking. +;So, we will return "I don't know" by setting SI to 0. +;This routine assume the newest valid boot record is in CS:[DISKSECTOR]. +;(This will be gauranteed by a successful GETBP call right before this +;routine.) + MESSAGE FTEST96,<"CHECK VID",CR,LF> +;SB34MS96TPI001********************************************************* +;SB check the EXT_Boot_Sig variable for the Extended boot signature +;SB if it is set then go to do the extended ID check otherwise continue +;SB with code below +;SB 2 LOCS + + cmp cs:[Ext_Boot_Sig],Ext_Boot_Signature + jz Do_Ext_Check_Id +;SB34MS96TPI001********************************************************* + call HasChange ;AN000; + jz CheckRet ;AN000; + + xor si,si ;AN000; assume I don't know. + cmp byte ptr cs:[SECPERCLUSINSECTOR]+3,0 ;AN000; Don't read vol id from + je CHECKFATRET ;AN000; the directory if not FAT system + CALL READ_VOLUME_ID + JC CHECKFATRET + CALL CHECK_VOLUME_ID + OR SI,SI + JNZ CHANGED_DRV + MESSAGE FTEST96,<"VID NOT CHANGED",CR,LF> + +VID_NO_Changed: + CALL RESETCHANGED + clc ;AN000; +CHECKFATRET: + RET +CHANGED_DRV: + MOV CS:[TIM_DRV],-1 ; ENSURE THAT WE ASK ROM FOR MEDIA + RET ; CHECK NEXT TIME ROUND + ; + ; extended ID check + ; +Do_Ext_Check_ID: ;AN000; + push ax ;AN000; +;SB34MS96TPI002************************************************************** +;SB The code to check extended ID is basically a check to see if the +;Sb volume serial number is still the same. The volume serial number +;SB previously read is in cs:[Boot_Serial_H] and cs:[Boot_Serial_L] +;SB high and low words respectively. DS:DI points to the BDS of the +;SB drive under consideration. The BDS has fields containing the +;SB high and low words of the volume serial number of the media in the +;SB drive. Compare these fields to the fields mentioned above. If these +;SB fields do not match the media has changed and so we should jump +;SB to the code starting at Ext_Changed else return "I don't know" status +;SB in the register used for the changeline status and continue executing +;SB the code given below. For temporary storage use the register which +;SB has been saved and restored around this block. +;SB 7 LOCS +;SB BDS fields in inc\msbds.inc + + mov ax,cs:[Boot_Serial_L] + cmp ax,word ptr ds:[di+VOL_SERIAL] + jnz Ext_Changed + mov ax,cs:[Boot_Serial_H] + cmp ax,word ptr ds:[di+VOL_SERIAL+2] + jnz Ext_Changed + xor si,si ; don't know + +;SB34MS96TPI002************************************************************** + pop ax ;AN000; +; jmp CheckFatRet ;AN000; + jmp VID_NO_Changed ;AN001;Reset the flag +Ext_Changed: ;AN000; Serial number is different! + pop ax ;AN000; + mov si, -1 ;AN000; disk changed! + clc ;AN000; clear carry. Only SI is meaningful here. + jmp Changed_Drv ;AN000; + +; +; AT I/O TIME, WE DETECTED THE ERROR. NOW WE NEED TO DETERMINE WHETHER THE +; MEDIA WAS TRULY CHANGED OR NOT. WE RETURN NORMALLY IF MEDIA CHANGE UNKNOWN. +; AND WE POP OFF THE CALL AND JMP TO HARDERR IF WE SEE AN ERROR. +; + PUBLIC CHECKIO +CHECKIO: + CMP AH,06 + JNZ CHECKFATRET + CALL CHKOPCNT + JZ CHECKFATRET ; NO OPEN FILES +; IF RETURNING FAKE BPB THEN IGNORE DISK CHANGES +; TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB +; JNZ IGNORECHANGE + CALL GETBP ; BUILD UP A NEW BPB IN CURRENT BDS + JC NO_ERROR_MAP ; GETBP HAS ALREADY CALLED MAPERROR + CALL CHECKFATVID + JC CHECKIORET ; DISK ERROR TRYING TO READ IN. + OR SI,SI ; IS CHANGED FOR SURE? + JS CHECKIOERR ; YES CHANGED +IGNORECHANGE: + INC BP ; ALLOW A RETRY + RET +CHECKIOERR: + CALL RETURNVID +CHECKIORET: +; POP SI ; POP OFF RETURN + STC ; MAKE SURE CARRY GETS PASSED THROUGH + JMP HARDERR + +NO_ERROR_MAP: + JMP HARDERR2 +; +; RETURN VID SETS UP THE VID FOR A RETURN TO DOS. +; + PUBLIC RETURNVID +RETURNVID: + MESSAGE FTEST96,<"RETURN VID",CR,LF> + PUSH DS ; SAVE POINTER TO CURRENT BDS + PUSH DI + PUSH CX + CALL INIT_VID_LOOP ; SETS ES:DI -> VID + LDS BX,CS:[PTRSAV] + MOV [BX.EXTRA],DI + MOV [BX.EXTRA+2],ES + POP CX + POP DI ; RESTORE CURRENT BDS + POP DS + MOV AH,6 ; INVALID MEDIA CHANGE + STC + RET + +; +; MUNGE THE TIME OF LAST SUCCESSFUL ACCESS FOR TWEEKED DRIVES +; +; DON'T NEED ANY MORE +; TWEEKCHECK: +; PUSH AX +; MOV AX,WORD PTR DS:[DI].FLAGS +; TEST AL,FCHANGED_BY_FORMAT +; JZ TWEEKDONE +; MOV CS:[TIM_DRV],-1 +; TWEEKDONE: +; POP AX +; RET + +; +; DRIVE IS THE LOGICAL DRIVE TO USE +; +; FORMAT_MEDIA_CHECK: ;ARR 2.42 +; PUSH AX +; MOV AX,WORD PTR DS:[DI].FLAGS +; TEST AL,FCHANGED_BY_FORMAT +; JZ RETF1 ; MEDIA NOT CHANGED VIA FORMAT +; AND AL,NOT FCHANGED_BY_FORMAT +; MOV WORD PTR [DI].FLAGS,AX ; RESET CHANGED_BY_FORMAT BIT +; MOV SI,-1 ; MEDIA CHANGED VIA FORMAT +; RETF1: +; POP AX +; RET + +; +; MOVES THE POINTER TO THE VOLID FOR THE DRIVE INTO THE ORIGINAL REQUEST PACKET +; ON ENTRY, DS:BX POINTS TO THE ORIGINAL PACKET. +; NO ATTEMPT IS MADE TO PRESERVE REGISTERS. +; +MEDIA_SET_VID: ; ARR 2.42 + PUBLIC MEDIA_SET_VID + + CALL INIT_VID_LOOP ; SETS ES:DI -> VID + LDS BX,CS:[PTRSAV] ; GET POINTER TO PACKET + MOV WORD PTR [BX.TRANS+1],DI + MOV WORD PTR [BX.TRANS+3],ES + RET + + +; +; HIDENSITY - EXAMINE A DRIVE/MEDIA DESCRIPTOR TO SET THE MEDIA TYPE. IF +; THE MEDIA DESCRIPTOR IS NOT F9 (NOT 96TPI OR 3 1/2), WE RETURN AND LET THE +; CALLER DO THE REST. OTHERWISE, WE POP OFF THE RETURN AND JUMP TO THE TAIL +; OF GETBP. FOR 3.5" MEDIA, WE JUST RETURN. +; +; INPUTS: DS:DI POINT TO CORRECT BDS FOR THIS DRIVE +; AH HAS MEDIA BYTE +; +; OUTPUTS: CARRY CLEAR +; NO REGISTERS MODIFIED +; CARRY SET +; AL = SECTORS/FAT +; BH = NUMBER OF ROOT DIRECTORY ENTRIES +; BL = SECTORS PER TRACK +; CX = NUMBER OF SECTORS +; DH = SECTORS PER ALLOCATION UNIT +; DL = NUMBER OF HEADS +; +HIDENSITY: + PUBLIC HIDENSITY +; +; CHECK FOR CORRECT DRIVE +; + TEST WORD PTR DS:[DI].FLAGS,FCHANGELINE ; IS IT SPECIAL? + JZ DOFLOPPY ; NO, DO NORMAL FLOPPY TEST +; +; WE HAVE A MEDIA BYTE THAT IS PRETTY COMPLEX. EXAMINE DRIVE INFORMATION +; TABLE TO SEE WHAT KIND IT IS. +; + CMP BYTE PTR DS:[DI].FORMFACTOR,FFSMALL; IS IT SINGLE-MEDIA? + JZ DOFLOPPY ; YES, USE FATID... +; +; 96 TPI DRIVE +; + CMP AH,0F9H + JNZ DOFLOPPY + MOV AL,7 ; SEVEN SECTORS / FAT + MOV BX,224*256+0FH ; 224 ROOT DIR ENTRIES & 0F SECTOR MAX + MOV CX,80*15*2 ; 80 TRACKS, 15 SECTORS/TRACK, 2 SIDES + MOV DX,01*256+2 ; SECTORS/ALLOCATION UNIT & HEAD MAX +POPR: + ADD SP,2 ; POP OFF RETURN ADDRESS + JMP HAS1 ; RETURN TO TAIL OF GETBP + +DOFLOPPY: + RET + + PATHSTART 001,TPI96 + +; +; CERTAIN BOGUS PROGRAMS AVOID DOS ALTOGETHER AND USE INT 13 DIRECTLY. THESE +; PROGRAMS EVEN RETRY OPERATIONS AND, THUS, WILL IGNORE THE DISK CHANGE LOGIC. +; +; WE HOOK INT 13 AND NOTE ALL ERRORS. +; + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUBLIC REAL13 +REAL13 DD ? +OLDINT DD ? +DMY DW ? + + PATHEND 001,TPI96 + + PUBLIC INT13 +INT13 PROC FAR + POP WORD PTR OLDINT + POP WORD PTR OLDINT+2 + POP DMY + MESSAGE FTEST13,<"*"> + PUSHF + CALL REAL13 ; SIMULATE ANOTHER INT 13 + JC ERR13 ; DID AN ERROR OCCUR? + JMP OLDINT ; NO, RETURN AND POP OFF FLAGS +ERR13: + MESSAGE FTEST13,<"INT 13 ERROR "> + MNUM FTEST13,AX + MESSAGE FTEST13, + PUSHF ; SAVE STATE + CMP AH,06H ; DID I SEE A CHANGE EVENT? + JZ GOTERR ; YES +B: POPF ; NO, SOME OTHER ERROR, IGNORE IT + JMP OLDINT ; RETURN AND POP OFF FLAGS +GOTERR: OR DL,DL ; IS THIS FOR THE HARD DISK? + JS B ; YES, IGNORE + MOV WORD PTR CS:[FLAGBITS],FCHANGED + CALL SET_CHANGED_DL + JMP B +INT13 ENDP + +; +; SET_CHANGED_DL - SETS FLAG BITS ACCORDING TO BITS SET IN [FLAGBITS]. +; ESSENTIALLY USED TO INDICATE CHANGELINE, OR FORMAT. +; +; INPUTS: DL CONTAINS PHYSICAL DRIVE NUMBER +; [FLAGBITS] CONTAINS BITS TO SET IN THE FLAG FIELD IN THE BDSS +; OUTPUTS: NONE +; REGISTERS MODIFIED: FLAGS +; +SET_CHANGED_DL: + PUBLIC SET_CHANGED_DL + + MESSAGE FTEST96,<"SET CHANGED",CR,LF> + PUSH BX + PUSH DX + MOV BL,DL +ALL_SET: + MOV DX,CS:[FLAGBITS] ; GET BITS TO SET IN FLAG FIELD + XOR BH,BH +; +; IN THE VIRTUAL DRIVE SYSTEM WE *MUST* FLAG THE OTHER DRIVES AS BEING CHANGED +; +; ASSUME FIRST BDS IS IN THIS SEGMENT + PUSH AX + PUSH DS ; SAVE CURRENT BDS + PUSH DI + LDS DI,DWORD PTR CS:[START_BDS] +SCAN_BDS: + CMP DI,-1 + JZ SKIPSET + CMP BYTE PTR [DI].DRIVENUM,BL + JNZ GET_NEXT_BDS +; +; SOMEONE MAY COMPLAIN, BUT THIS *ALWAYS* MUST BE DONE WHEN A DISK CHANGE IS +; NOTED. THERE ARE *NO* OTHER COMPROMISING CIRCUMSTANCES. +; +SETCHANGED: + OR WORD PTR DS:[DI].FLAGS,DX ; SIGNAL CHANGE ON OTHER DRIVE +GET_NEXT_BDS: + MOV AX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,AX + JMP SHORT SCAN_BDS +SKIPSET: + POP DI ; RESTORE CURRENT BDS + POP DS + POP AX + POP DX + POP BX + RET + +; +; CHECKROMCHANGE - SEE IF EXTERNAL PROGRAM HAS DIDDLED ROM CHANGE LINE. +; +; INPUTS: DS:DI POINTS TO CURRENT BDS. +; OUTPUTS: ZERO SET - NO CHANGE +; ZERO RESET - CHANGE +; REGISTERS MODIFIED: NONE + +CHECKROMCHANGE: + MESSAGE FTEST13,<"CHECKROM "> + MNUM FTEST13 + MESSAGE FTEST13, + TEST WORD PTR [DI].FLAGS,FCHANGED + RET + +; +; RESETCHANGED - RESTORE VALUE OF CHANGE LINE +; +; INPUTS: DS:DI POINTS TO CURRENT BDS +; OUTPUTS: NONE +; REGISTERS MODIFIED: NONE + + public ResetChanged +RESETCHANGED: + MESSAGE FTEST13,<"RESETCHANGED "> + MNUM FTEST13 + MESSAGE FTEST13, + AND WORD PTR DS:[DI].FLAGS,NOT FCHANGED + RET + +; +; HASCHANGE - SEE IF DRIVE CAN SUPPLY CHANGE LINE +; +; INPUTS: DS:DI POINTS TO CURRENT BDS +; OUTPUTS: ZERO SET - NO CHANGE LINE AVAILABLE +; ZERO RESET - CHANGE LINE AVAILABLE +; REGISTERS MODIFIED: NONE + + PUBLIC HASCHANGE +HASCHANGE: + MESSAGE FTEST13,<"HASCHANGE "> + MNUM FTEST13 + MESSAGE FTEST13, + TEST WORD PTR [DI].FLAGS,FCHANGELINE + RET + + ASSUME DS:CODE + + INCLUDE MSVOLID.INC + + PUBLIC END96TPI +END96TPI LABEL BYTE diff --git a/v4.0/src/BIOS/MSAUX.ASM b/v4.0/src/BIOS/MSAUX.ASM new file mode 100644 index 0000000..4d5a95e --- /dev/null +++ b/v4.0/src/BIOS/MSAUX.ASM @@ -0,0 +1,281 @@ + TITLE MSAUX - DOS 3.3 +;---------------------------------------------------------------- +; : +; A U X - AUXILARY DEVICE DRIVER : +; : +; : +; This file contains the Auxilary Device Driver. The : +; auxilary driver handles calls to and from the RS-232 port. : +; Three devices uses this code: AUX, COM1, and COM2. AUX and : +; COM1 talk to the zero RS-232 card and COM2 talks to the : +; 'one' RS-232 card. The beginning of the interrupt entry : +; point for these devices sets the variable AUXNUM in the : +; msbio.asm module. If the value is 0 the routines in this : +; file will talk to the the 'zero' card. If the value in : +; AUXNUM is 1 the routines will talk to the 'one' card. : +; The procedure GETDX is called to put the value 0 or 1 in : +; the DX register depending on the value in AUXBUF. : +; : +; The routines in this files are: : +; : +; routine function : +; ------- -------- : +; AUX$READ Read characters from the : +; specified device. : +; AUX$RDND Non-desrucrtive read with : +; no waiting. : +; AUX$FLSH Flush specified device input : +; buffer. : +; AUX$WRIT Write characters to the : +; specified device. : +; AUX$WRST Get status of specified : +; device : +; : +; These routines are not called directly. Call are made via : +; the strategy and interrupt entry point (see Device Header). : +; : +; Data structure: : +; The Aux Device has a two byte buffer called AUXBUF. The : +; first byte is for the zero card, the second byte is for the : +; one card. A zero value in the byte indicates the buffer is : +; empty. The routines use GETBX to get the address of the : +; buffer. : +; : +;---------------------------------------------------------------- + +;;Ver 3.30 modification --------------------------- + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE JUMPMAC.INC + INCLUDE MSMACRO.INC + + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN GETDX:NEAR ;MSBIO1 + EXTRN RDEXIT:NEAR ;MSCON + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + ;DATA + EXTRN AUXBUF:BYTE ;MSDATA + +; VALUES IN AH, REQUESTING FUNCTION OF INT 14H IN ROM BIOS +AUXFUNC_SEND EQU 1 ;TRANSMIT +AUXFUNC_RECEIVE EQU 2 ;READ +AUXFUNC_STATUS EQU 3 ;REQUEST STATUS + +; ERROR FLAGS, REPORTED BY INT 14H + +; THESE FLAGS REPORTED IN AH: +FLAG_DATA_READY EQU 01H ;DATA READY +FLAG_OVERRUN EQU 02H ;OVERRUN ERROR +FLAG_PARITY EQU 04H ;PARITY ERROR +FLAG_FRAME EQU 08H ;FRAMING ERROR +FLAG_BREAK EQU 10H ;BREAK DETECT +FLAG_TRANHOL_EMP EQU 20H ;TRANSMIT HOLDING REGISTER EMPTY +FLAG_TRANSHF_EMP EQU 40H ;TRANSMIT SHIFT REGISTER EMPTY +FLAG_TIMEOUT EQU 80H ;TIMEOUT + +; THESE FLAGS REPORTED IN AL: +FLAG_DELTA_CTS EQU 01H ;DELTA CLEAR TO SEND +FLAG_DELTA_DSR EQU 02H ;DELTA DATA SET READY +FLAG_TRAIL_RING EQU 04H ;TRAILING EDGE RING INDICATOR +FLAG_DELTA_SIG EQU 08H ;DELTA RECEIVE LINE SIGNAL DETECT +FLAG_CTS EQU 10H ;CLEAR TO SEND +FLAG_DSR EQU 20H ;DATA SET READY +FLAG_RING EQU 40H ;RING INDICATOR +FLAG_REC_SIG EQU 80H ;RECEIVE LINE SIGNAL DETECT +;;End of modification ------------------ + + +;---------------------------------------------------------------- +; : +; Read zero or more characters from Auxilary Device : +; : +; input:es:[di] points to area to receive aux data : +; cx has number of bytes to be read : +; "auxnum" first byte has number of aux device (rel 0): +; : +;---------------------------------------------------------------- + PUBLIC AUX$READ +AUX$READ PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + jcxz EXVEC2 ; if no characters, get out + call GETBX ; put address of AUXBUF in BX + xor AX,AX ; clear AX register + xchg AL,[BX] ; Get character , if any, from + ; buffer and clear buffer + or AL,AL ; if AL is nonzero there was a + ; character in the buffer + jnz AUX2 ; if so skip AUXIN call +AUX1: ; + call AUXIN ; get character from port +AUX2: ; + stosb ; store character + loop AUX1 ; if more character, go around again +EXVEC2: ; + Jump EXIT ; all done, successful exit +AUX$READ ENDP + +; +; AUXIN: make a call on ROM BIOS to read character from +; the auxilary device, then do some error checking. +; If an error occurs then AUXIN jumps to ERR$CNT and +; does NOT return to where it was called from. +; + +AUXIN PROC NEAR + + mov ah,AUXFUNC_RECEIVE + call AUXOP + ;check for Frame, Parity, or Overrun errors + ;WARNING: these error bits are unpredictable + ; if timeout (bit 7) is set + test ah,FLAG_FRAME or FLAG_PARITY or FLAG_OVERRUN + jz AROK ;No error if all bits are clear + + ;Error getting character + add sp,+2 ;Remove rtn address (near call) + xor al,al + or al,FLAG_REC_SIG or FLAG_DSR or FLAG_CTS + + JUMP ERR$CNT +AROK: + RET ;CHAR JUST READ IS IN AL, STATUS IS IN AH +AUXIN ENDP + +;---------------------------------------------------------------- +; : +; Aux non-destructive read with no waiting : +; : +; input: es:[di] points to area to receive aux data : +; : +;---------------------------------------------------------------- +; + PUBLIC AUX$RDND +AUX$RDND PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call GETBX ; have BX point to AUXBUF + mov AL,[BX] ; copy contents of buffer to AL + or AL,AL ; if AL is non-zero (char in buffer) + jnz AUXRDX ; then return character + call AUXSTAT ; if not, get status of AUX device + TEST AH,FLAG_DATA_READY ;TEST DATA READY + jz AUXBUS ; then device is busy (not ready) + + TEST AL,FLAG_DSR ;TEST DATA SET READY + jz AUXBUS ; then device is busy (not ready) + call AUXIN ; else aux is ready, get character + call GETBX ; have bx point to AUXBUF + mov [BX],AL ; save character in buffer +AUXRDX: ; + Jump RDEXIT ; return character + +AUXBUS: ; + Jump BUS$EXIT ; jump to device busy exit +AUX$RDND ENDP + +;---------------------------------------------------------------- +; : +; Aux Output Status : +; : +;---------------------------------------------------------------- + PUBLIC AUX$WRST +AUX$WRST PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call AUXSTAT ; get status of AUX in AX + ; now test to see if device is busy + ; if this bit is not set, +;;Ver 3.30 modification ----------------------- + TEST AL,FLAG_DSR ;TEST DATA SET READY + jz AUXBUS ; then device is busy (not ready) + TEST AH,FLAG_TRANHOL_EMP ;TEST TRANSMIT HOLD REG EMPTY +;;End of modification ------------------------- + jz AUXBUS ; then device is busy (not ready) + Jump Exit + +AUX$WRST ENDP + +; +; AUXSTAT makes a call on the ROM-BIOS to determine the status +; of the auxilary device +; Outputs: +; AX is filled with status of port. +; DX is changes to specify which card - either 0, 1 (, 2, 3) ;ba +; NO other registers are modified +; + +AUXSTAT proc near + mov ah,AUXFUNC_STATUS + call AUXOP + ret +AUXSTAT endp + +AUXOP PROC NEAR + ;AH=FUNCTION CODE + ;0=INIT, 1=SEND, 2=RECEIVE, 3=STATUS + call GETDX ; have DX point to proper card + int 14h ; call rom-bios for status + ret +AUXOP ENDP + +;---------------------------------------------------------------- +; : +; Flush AUX Input buffer - set contents of AUXBUF to zero : +; : +;---------------------------------------------------------------- + PUBLIC AUX$FLSH +AUX$FLSH PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call GETBX ; get BX to point to AUXBUF + mov BYTE PTR [BX],0 ; zero out buffer + Jump Exit ; all done, successful return +AUX$FLSH ENDP + + + +;---------------------------------------------------------------- +; : +; Write to Auxilary Device : +; : +;---------------------------------------------------------------- + PUBLIC AUX$WRIT +AUX$WRIT PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + jcxz EXVEC2 ; if CX is zero, no characters + ; to be written, jump to exit +AUX$LOOP: + mov AL,ES:[DI] ; get character to be written + inc DI ; move DI pointer to next character +;;Ver 3.30 modification --------------------------- + MOV AH,AUXFUNC_SEND ;VALUE=1, INDICATES A WRITE + CALL AUXOP ;SEND CHARACTER OVER AUX PORT + + TEST AH,FLAG_TIMEOUT ;CHECK FOR ERROR +;;End of modification --------------------------- + jz AWOK ; then no error + mov AL,10 ; else indicate write fault + Jump ERR$CNT ; call error routines + + ; if CX is non-zero, still more +AWOK: + loop AUX$LOOP ; more characrter to print + Jump Exit ; all done, successful return +AUX$WRIT ENDP + + +; +; GETBX puts the address of AUXBUF (the Auxilary Device buffer) +; in BX. After calling GETBX, a routine can get to AUXBUF +; with [BX]. +; +; NOTE: The getdx routine is in msbio1 and looks like: +; mov dx,word ptr cs:[auxnum] +; +GETBX PROC NEAR + call GETDX + mov BX,DX + add BX,OFFSET AUXBUF + ret +GETBX ENDP + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSBDATA.INC b/v4.0/src/BIOS/MSBDATA.INC new file mode 100644 index 0000000..d0be320 --- /dev/null +++ b/v4.0/src/BIOS/MSBDATA.INC @@ -0,0 +1,722 @@ +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 3.4 - J.K. +;AC000 - Changed for DOS Version 3.4 - J.K. +;ANxxx - PTR, DCRs +;============================================================================== +;AN001 - d9 Double word MOV instruction for 80386 based machine. 7/1/87 J.K. +;AN002 - d25 Change DASD ERP to that recommended by Storage Systems. 7/29/87 J.K. +;AN003; d304 Boot record structure change for OS2 11/9/87 J.K. +;============================================================================== + EXTRN INIT:NEAR + + PUBLIC START$ +START$: + JMP INIT ;START$ PATCH BY INIT TO POINT TO + ;HDRIVE BPB +; PUBLIC FORMAT_PATCH +;FORMAT_PATCH: ;ARR 2.42 +; JMP FMTSET ;MJB001 DISPATCH FOR CALL FROM FORMAT UTILITY + + + PATHSTART 001,BIO + +; DB 20 DUP (0) ;IBM WANTS SOME ZEROED AREA (DELETED) + + +;HEADER DB "Ver 2.45" +;-------------------------------------------------------------- +; +; COMMAND JUMP TABLES +; +; BEWARE - THESE TABLES OVERLAP SOMEWHAT! -C.P. +; + ODD +DSKTBL LABEL BYTE + DB 24 ; THIS IS THE SIZE OF THE TABLE YUK!!!! + DW DSK$INIT + DW MEDIA$CHK + DW GET$BPB + DW CMDERR ;RS + DW DSK$READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW DSK$WRIT + DW DSK$WRITV + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW CMDERR ;RS + + PUBLIC TABLE_PATCH +TABLE_PATCH LABEL WORD ;ARR 2.42 + DW DSK$OPEN ;ARR 2.41 + DW DSK$CLOSE ;ARR 2.41 + DW DSK$REM ;ARR 2.41 + DW EXIT + DW EXIT + DW EXIT + DW GENERIC$IOCTL ; KGS 3.20 + DW EXIT + DW EXIT + DW EXIT + DW IOCTL$GETOWN ; RS 3.20 + DW IOCTL$SETOWN ; RE 3.20 + + ODD +CONTBL LABEL BYTE + DB 10 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW CON$READ + DW CON$RDND + DW EXIT + DW CON$FLSH + DW CON$WRIT + DW CON$WRIT + DW EXIT ;ARR 2.41 + +; DW CMDERR ;J.K. 4/29/86 for CON$GENIOCTL support +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CON$GENIOCTL ;J.K. 4/29/86 + + ODD +AUXTBL LABEL BYTE + DB 10 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW AUX$READ + DW AUX$RDND + DW EXIT + DW AUX$FLSH + DW AUX$WRIT + DW AUX$WRIT + DW AUX$WRST + + ODD +TIMTBL LABEL BYTE + DB 9 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW TIM$READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW TIM$WRIT + DW TIM$WRIT + + ODD +PRNTBL LABEL BYTE + DB 24 + DW EXIT ;INIT + DW EXIT + DW EXIT + DW CMDERR + DW EXIT$ZER ;INDICATE ZERO CHARS READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW PRN$WRIT + DW PRN$WRIT + DW PRN$STAT + DW EXIT + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW PRN$TILBUSY + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW PRN$GENIOCTL ;RS 3.20 + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW CMDERR ;RS 3.20 + DW CMDERR ;RS 3.20 + + EVENB + PUBLIC OLD13 ;(MOVED HERE FROM IBMBIO2) +OLD13 label DWORD + db '5986' ;J.K. 11/7/86 Secrete Code for DOS 3.30 IBMBIO. + PUBLIC ORIG13 +ORIG13 label DWORD + db '21',0,0 ;J.K. 11/8/86 This is my employee serial # !!! + + EVENB + PUBLIC PTRSAV +PTRSAV DD 0 + PUBLIC AUXBUF +AUXBUF DB 0,0,0,0 ;SET OF 1 BYTE BUFFERS FOR COM 1,2,3, AND 4 + + EVENB + PUBLIC PREVOPER,NUMBER_OF_SEC +PREVOPER DW ? ; HOLDS INT 13 REQUEST (I.E. REGISTER AX). +NUMBER_OF_SEC DB ? ; HOLDS NUMBER OF SECTORS TO READ ON AN ECC ERROR + + IF ($-CODE) GT 100H + %OUT VDISK BUFFER NOT CORRECTLY LOCATED + ELSE + ORG 100H + ENDIF + PUBLIC VDISK_AREA +VDISK_AREA DB 108 DUP(0) ;FOR USE BY VDISK + + EVENB +; WARNING!!! THESE ARE ADDRESSED TOGETHER IN GETDX +AUXNUM DB 0 ;WHICH AUX DEVICE WAS REQUESTED + DB 0 + + EVENB + PUBLIC CONHEADER +CONHEADER LABEL WORD ;HEADER FOR DEVICE "CON" + DD AUXDEV2 + DW 1000000000010011B ;CON IN AND CON OUT + SPECIAL + DW STRATEGY + DW CON$IN + DB 'CON ' + + EVENB + PUBLIC AUXDEV2 +AUXDEV2 LABEL WORD ;HEADER FOR DEVICE "AUX" + DD PRNDEV2 + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'AUX ' + + EVENB + PUBLIC PRNDEV2 +PRNDEV2 LABEL WORD ;HEADER FOR DEVICE "PRN" + DD TIMDEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN0$IN + DB 'PRN ' + + EVENB + PUBLIC TIMDEV +TIMDEV LABEL WORD + DD DSKDEV + DW 1000000000001000B + DW STRATEGY + DW TIM$IN + DB 'CLOCK$ ' + + EVENB + PUBLIC DSKDEV +DSKDEV LABEL WORD + DD COM1DEV + DW 0000100001000010B ;J.K.I1. 32 bit sector calculation + DW STRATEGY + DW DSK$IN +DRVMAX DB 4 + PUBLIC DRVMAX + + PUBLIC STEP_DRV +STEP_DRV DB -2 ; ARR 2.20 LAST DRIVE ACCESSED + + PUBLIC PHYS_DRV +PHYS_DRV DB 0 ; USED BY SETDRIVE FOR GETTING BDS FOR + ; LOGICAL DRIVE, OR PHYSICAL DRIVE. + PUBLIC FHAVE96 +FHAVE96 DB 0 ; FLAG TO INDICATE PRESENCE OF + ; 96TPI SUPPORT + PUBLIC SINGLE +SINGLE DB 0 ; USED TO DETECT SINGLE DRIVE SYSTEMS + + PUBLIC FHAVEK09 +FHAVEK09 DB 0 ;INDICATES IF THIS IS A K09 OR NOT + ; USED BY CONSOLE DRIVER. + PUBLIC NEW_ROM +NEW_ROM DB 0 ;SET TO 1 IF WE HAVE A ROM THAT CAN + ; HANDLE STRANGE MEDIA LAYOUTS. + + PUBLIC FSETOWNER +FSETOWNER DB ? ;=1 IF WE ARE SETTING THE OWNER OF A + ;DRIVE. (EXAMINED BY CHECKSINGLE). + public Secrete_Code +Secrete_Code dw 'jk' ;J.K. 11/7/86 Secrete code for DOS 3.30 IBMBIO. + + EVENB + PUBLIC COM1DEV +COM1DEV LABEL WORD + DD LPT1DEV + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'COM1 ' + + EVENB + PUBLIC LPT1DEV +LPT1DEV LABEL WORD + DD LPT2DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN1$IN + DB 'LPT1 ' + + EVENB + PUBLIC LPT2DEV +LPT2DEV LABEL WORD + DD LPT3DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN2$IN + DB 'LPT2 ' + + EVENB + PUBLIC LPT3DEV +LPT3DEV LABEL WORD + DD COM2DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN3$IN + DB 'LPT3 ' + + EVENB + PUBLIC COM2DEV +COM2DEV LABEL WORD + DD COM3DEV + DW 1000000000000000B + DW STRATEGY + DW AUX1$IN + DB 'COM2 ' + + EVENB + PUBLIC COM3DEV +COM3DEV LABEL WORD ;EDK + DD COM4DEV + DW 1000000000000000B + DW STRATEGY + DW AUX2$IN + DB 'COM3 ' + + EVENB + PUBLIC COM4DEV +COM4DEV LABEL WORD ;EDK + DW -1,CODE + DW 1000000000000000B + DW STRATEGY + DW AUX3$IN + DB 'COM4 ' + +; HARD-WIRE THE LINK TO THE NEXT INT2F HANDLER. + EVENB + PUBLIC NEXT2F_13 +NEXT2F_13 LABEL WORD + EXTRN INT2F_DISK:FAR ;IBMBIO2 + DD INT2F_DISK + + EVENB + PUBLIC START_BDS +START_BDS LABEL WORD + DD BDS1 ;START OF BDS LINKED LIST. + PUBLIC ACCESSCOUNT +ACCESSCOUNT DB 0 ; NUMBER OF TIMES MEDIA CHECK CALLED + PUBLIC TIM_DRV +TIM_DRV DB -1 ; TIME WHEN LAST DISK I/O PERFORMED + PUBLIC FLAGBITS +FLAGBITS DW 0 ; BITS TO SET IN FLAG FIELD WHEN DOING + ; A SET_CHANGED_DL + PUBLIC MEDBYT +MEDBYT DB ? + + EVENB + PUBLIC WRTVERIFY +WRTVERIFY LABEL WORD + PUBLIC RFLAG +RFLAG DB ROMREAD ;2 FOR READ, 3 FOR WRITE +VERIFY DB 0 ;1 IF VERIFY AFTER WRITE + PUBLIC SECCNT +SECCNT DW 0 + PUBLIC HARDNUM +HARDNUM DB 99 ;LOGICAL DRIVE NUMBER OF FIRST HARDFILE + PUBLIC MOTORSTARTUP,SETTLECURRENT,SETTLESLOW +MOTORSTARTUP DB ? ; VALUE FROM TABLE +SETTLECURRENT DB ? ; VALUE FROM TABLE +SETTLESLOW DB ? ; SLOW SETTLE VALUE + +NEXTSPEED DB ? ; VALUE OF SPEED TO BE USED + public save_head_sttl +Save_head_sttl db ? ;used by READ_SECTOR routine + + PUBLIC EOT +EOT DB 9 + + EVENB + PUBLIC DPT +DPT DD ? + +;KEEP THE NEXT TWO ITEMS CONTIGUOUS - SEE IOCTL_BLOCK FOR REASON + PUBLIC CURSEC,CURHD,CURTRK,SPSAV +CURSEC DB 0 ;CURRENT SECTOR +CURHD DB 0 ;CURRENT HEAD +CURTRK DW 0 ;CURRENT TRACK +SPSAV DW 0 ;SAVE THE STACK POINTER + +; THE FOLLOWING ARE USED FOR IOCTL FUNCTION CALLS + PUBLIC FORMT_EOT,HDNUM,TRKNUM,GAP_PATCH +FORMT_EOT DB 8 ; EOT USED FOR FORMAT +HDNUM DB 0 ; HEAD NUMBER +TRKNUM DW 0 ; TRACK BEING MANIPULATED +GAP_PATCH DB 50H ; FORMAT GAP PATCHED INTO DPT + +;DISK ERRORS RETURNED FROM THE IBM ROM + PUBLIC ERRIN +ERRIN LABEL BYTE + db 0cch ;AN002; Write Fault error + DB 80H ;NO RESPONSE + DB 40H ;SEEK FAILURE + DB 10H ;BAD CRC + DB 8 ;DMA OVERRUN + DB 6 ; MEDIA CHANGE + DB 4 ;SECTOR NOT FOUND + DB 3 ;WRITE ATTEMPT TO WRITE-PROTECT DISK + PUBLIC LSTERR +LSTERR DB 0 ;ALL OTHER ERRORS + +;RETURNED ERROR CODES CORRESPONDING TO ABOVE + PUBLIC ERROUT +ERROUT LABEL BYTE + db 10 ;AN002; Write Fault error + DB 2 ;NO RESPONSE + DB 6 ;SEEK FAILURE + DB 4 ;BAD CRC + DB 4 ;DMA OVERRUN + DB 15 ; INVALID MEDIA CHANGE + DB 8 ;SECTOR NOT FOUND + DB 0 ;WRITE ATTEMPT ON WRITE-PROTECT DISK + DB 12 ;GENERAL ERROR + PUBLIC NUMERR +NUMERR = ERROUT-ERRIN + +;------------------------------------------------------------- + +; READ IN BOOT SECTOR HERE, READ DONE IN READBOOT. +; ALSO READ SECTOR FOR DMA CHECK FOR HARD DISK. + +;J.K. The buffer for a disk sector is going to be at a double word boundary +; for 80386 machine. + + IF ($-CODE) Mod 4 ;AN001; + Org ($-CODE)+4-(($-CODE) Mod 4) ;AN001; + ENDIF ;AN001; + + PUBLIC DISKSECTOR +DiskSector DB 11 DUP(?) ; TAKE CARE OF 3 JUMP BYTES PLUS OEM NAME. + PUBLIC BPB_IN_SECTOR +Bpb_In_Sector DW ? + PUBLIC SECPERCLUSINSECTOR +SecPerClusInSector DB ? + DW ? + public NumberOfFats +NumberOfFats DB ? + DW ? + DW ? + PUBLIC MEDIABYTE +MediaByte DB ? + DW ? + DW ? + DW ? + DW ? + DW ? ;AN000; Extended Hidden sector (high) + DW ? ;AN000; Extended Total sector (low) + DW ? ;AN000; Extended Total sector (high) + db ? ;AN003; PHYDRV in boot record. + db ? ;AN003; CURRENT HEAD in boot record. + public Ext_Boot_Sig +Ext_Boot_Sig DB ? ;AN000; Extended Boot record sig. (=90h) + public Boot_Serial_L +Boot_Serial_L DW ? ;AN000; Boot volume serial number (Low) + public Boot_Serial_H +Boot_Serial_H DW ? ;AN000; Boot volume serial number (High) + public Boot_Volume_Label +Boot_Volume_Label DB 11 dup (' ') ;AN000; Volume label + public Boot_System_ID +Boot_System_ID DB 8 dup (' ') ;AN000; File system Id. + DB 512-($-DISKSECTOR) DUP (?) + +;********************************************************************* +; "BDS" CONTAINS INFORMATION FOR EACH DRIVE IN THE SYSTEM. +; VARIOUS VALUES ARE PATCHED WHENEVER ACTIONS ARE PERFORMED. +; SECTORS/ALLOC. UNIT IN BPB INITIALLY SET TO -1 TO SIGNIFY THAT +; THE BPB HAS NOT BEEN FILLED. LINK ALSO SET TO -1 TO SIGNIFY END +; OF LIST. # OF CYLINDERS IN MAXPARMS INITIALIZED TO -1 TO INDICATE +; THAT THE PARAMETERS HAVE NOT BEEN SET. +; + EVENB +BDS1 LABEL WORD + DD BDS2 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE1 +FDRIVE1 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT1 DW 0 ;OPEN REF. COUNT + + DB 3 ;FORM FACTOR +FLAGS1 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB1 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK1 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO1 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI1 DW -1 +VOLID1 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER1 dd 0 ;Current volume serial number from Boot record +SYSID1 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS2 LABEL WORD + DD BDS3 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE2 +FDRIVE2 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT2 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS2 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB2 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK2 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO2 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI2 DW -1 +VOLID2 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER2 dd 0 ;Current volume serial number from Boot record +SYSID2 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS3 LABEL WORD + DD BDS4 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE3 +FDRIVE3 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT3 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS3 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB3 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK3 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO3 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI3 DW -1 +VOLID3 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER3 dd 0 ;Current volume serial number from Boot record +SYSID3 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS4 LABEL WORD + DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE4 +FDRIVE4 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT4 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS4 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB4 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK4 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO4 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI4 DW -1 +VOLID4 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER4 dd 0 ;Current volume serial number from Boot record +SYSID4 db "FAT12 ",0 ;Current file system id from Boot record + +BPBTYPE STRUC +SPF DB ? +SPT DB ? +CDIRE DB ? +CSEC DW ? +SPA DB ? +CHEAD DB ? +BPBTYPE ENDS + PUBLIC SM92 +SM92 BPBTYPE <3,9,70H,2*9*80,2,2> + +;----------------------------------------------- +; +; C O N - CONSOLE DEVICE DRIVER +; + PUBLIC ALTAH +ALTAH DB 0 ;SPECIAL KEY HANDLING + public KEYRD_Func +KEYRD_Func DB 0 ;AN000; Default is conventional keyboard read + public KEYSTS_Func +KEYSTS_Func DB 1 ;AN000; Defualt if conventional keyboard status check. + +; PUBLIC SAV_SC_INFO ;J.K. 4/29/86 FOR CON$GENIOCTL +; PUBLIC SAV_SC_MODE +; PUBLIC SAV_SC_COLORS +; PUBLIC SAV_SC_WIDTH +; PUBLIC SAV_SC_LENGTH +;SAV_SC_INFO LABEL BYTE +;SAV_SC_MODE DB 0 +;SAV_SC_COLORS DW 0 +;SAV_SC_WIDTH DW 0 +;SAV_SC_LENGTH DW 0 ;J.K. 4/29/86 FOR CON$GENIOCTL + +;------------------------------------------------------------- +; +; P R N - PRINTER DEVICE +; + PUBLIC PRINTDEV +PRINTDEV DB 0 ; INDEX INTO ABOVE ARRAY + +; THE FOLLOWING VARIABLE CAN BE MODIFIED VIA IOCTL SUB-FUNCTION 16. IN THIS +; WAY, THE WAIT CAN BE SET TO SUIT THE SPEED OF THE PARTICULAR PRINTER BEING +; USED. ONE FOR EACH PRINTER DEVICE. + + EVENB + PUBLIC WAIT_COUNT +WAIT_COUNT DW 4 DUP (50H) ; ARRAY OF RETRY COUNTS FOR PRINTER + + EVENB + PUBLIC DAYCNT +DAYCNT DW 0 + + + IF iTEST ;Testing Mode for IBMBIO. + PUBLIC NUMBUF +NUMBUF DB 5 DUP (?) + PUBLIC DIGITS +DIGITS DB "0123456789ABCDEF" + PUBLIC FTESTBITS +;FTESTBITS DW FTESTDISK+FTESTINIT +FTESTBITS DW fTestDISK +;ftestbits dw ftestclock + ENDIF + + PATHEND 001,BIO + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSBIO.LNK b/v4.0/src/BIOS/MSBIO.LNK new file mode 100644 index 0000000..d1a15bd --- /dev/null +++ b/v4.0/src/BIOS/MSBIO.LNK @@ -0,0 +1,14 @@ +msbio1+ +msCON+ +msAUX+ +msLPT+ +msCLOCK+ +msDISK+ +msBIO2+ +mshard+ +msinit+ +sysinit1+ +sysconf+ +sysinit2+ +sysimes,msbio,msBIO/M; + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSBIO.SKL b/v4.0/src/BIOS/MSBIO.SKL new file mode 100644 index 0000000..9c890df --- /dev/null +++ b/v4.0/src/BIOS/MSBIO.SKL @@ -0,0 +1,139 @@ +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.0 - J.K. +;AC000 - Changed for DOS Version 4.0 - J.K. +;AN00x - PTM number for DOS Version 4.0 - J.K. +;============================================================================== +;============================================================================== +;AN001 D246, P976 Show "Bad command or parameters - ..." msg 9/22/87 J.K. +;AN002 D274 Take "file" out from "Incorrect order..." msg 10/07/87 J.K. +;AN003 D486 Share installation for large media 02/24/88 J.K. +;============================================================================== +;=================== +:class 1 +;=================== +; MESSAGES FOR THE IBM BOOT SECTOR. NUL Terminated. +; This is used by IBMBOOT and IBMLOAD program and it stays in IBMBOOT directory. + +;For IBMLOAD program +;SYSMSG DB 13,10,"Non-System disk or disk error",13,10 +; DB "Replace and strike any key when ready",13,10,0 +:use 001 BOOT SYSMSG + +;=================== +:class 2 +;=================== +; SCCSID = @(#)biomes.asm 1.2 85/07/25 +; SINGLE DRIVE MESSAGE FOR IBMBIO.COM. NUL TERMINATED. +;IFNDEF PATHSTART +;PATHSTART MACRO INDEX,ABBR +; IFDEF PATHGEN +; PUBLIC ABBR&INDEX&S,ABBR&INDEX&E +; ABBR&INDEX&S LABEL BYTE +; ENDIF +; ENDM +;ENDIF +; +;IFNDEF PATHEND +;PATHEND MACRO INDEX,ABBR +; IFDEF PATHGEN +; ABBR&INDEX&E LABEL BYTE +; ENDIF +; ENDM +;ENDIF +; PATHSTART 001,BIOMS + + +:def 20 SNGMSG DB 13,10,"Insert diskette for drive " +:def 21 DRVLET DB "A: and strike",13,10,"any key when ready",13,10,10,0 + +; PATHEND 001,BIOMS + +;================== +:class 3 +;================== + +; PRINTED when there is a bad command in CONFIG.SYS. '$' TERMINATED, note +; that this message includes crlfm! +;PATHSTART 001,SYSMES + +:def 03 BADOPM DB 13,10,"Unrecognized command in CONFIG.SYS" + +;BADSIZ_POST LABEL BYTE +;BADLD_POST LABEL BYTE + +:def 04 CRLFM DB 13,10,'$' + +:def 22 BadParm db 13,10,"Bad command or parameters - $" ;AN001; + +;PRINTED when installed device specifies too large a sector size.'$' terminated. +; FORM: device name +:def 05 BADSIZ_PRE DB 13,10,"Sector size too large in file $" + +;PRINTED when installed device cannot be found. '$' terminated. +; FORM: device name +:def 06 BADLD_PRE DB 13,10,"Bad or missing $" + +;PRINTED when command interpreter is not found. NUL terminated. +; FORM: +:def 07 BADCOM DB "Command Interpreter",0 + +;PRINTED when country code, code page combination was not found in country.sys file. '$' terminated. +; FORM: +:def 08 BADCOUNTRY DB 13,10,"Invalid country code or code page",13,10,"$" + +;PRINTED when code page id is missing or wrong syntax. - J.K. +; FORM: +:def 09 BADCOUNTRYCOM DB 13,10,"Error in COUNTRY command",13,10,"$" + +;PRINTED when the memory left is not sufficient to handle COUTRY.SYS file +; FORM: +:def 10 INSUFMEMORY DB 13,10, "Insufficient memory for COUNTRY.SYS file",13,10,"$" + +; PRINTED when there is insufficient memory. '$' TERMINATED, note +; that this message includes crlfm! +:def 11 BADMEM DB 13,10,"Configuration too large for memory",13,10,"$" + +; PRINTED when the attempt is made to install a block device which would +; have a drive letter > 'Z' +:def 12 BADBLOCK DB 13,10,"Too many Block Devices",13,10,"$" + +; PRINTED when the attempt is made to install a stack with invalid +; combinations of # of stacks, stack size. - J.K. 5/23/86 +:def 13 BADSTACK DB 13,10,"Invalid STACK parameters",13,10,"$" + +;AN000; - PRINTED when encountering a command that is not "install=" after +; we had a "Install=" command. - J.K.I1. +; Translation::: Please leave the last blank space at the end of the line +; as it is. +:def 14 BADORDER DB 13,10,"Incorrect order in CONFIG.SYS line ","$" + +;AN000; - PRINTED when the command failed. +; Translation::: Please leave the last blank space at the end of the line +; as it is. +:def 15 ERRORCMD DB "Error in CONFIG.SYS line ","$" + +;AN003; - PRINTED when SHARE.EXE is not loaded and has a large media > 32 MB. +:def 23 SHAREWARNMSG db "WARNING! SHARE should be loaded for large media",13,10,"$" + +;================== +:class 4 +;================== +;IBMBIO SYSINIT +;Message for SYSINIT_BASE program. +:def 16 Mem_alloc_err db 13,10,"Memory allocation error","$" + + +;================== +:class 5 +;================== +; %OUT STKMES.INC... +; SCCSID = @(#)stkmes.inc 1.0 86/10/21 + +; PUBLIC FATAL_MSG +:def 17 FATAL_MSG DB 0DH,0AH,7,0DH,0AH + DB "Internal stack overflow",0DH,0AH + DB "System halted",0DH,0AH,"$" +; +:END + diff --git a/v4.0/src/BIOS/MSBIO1.ASM b/v4.0/src/BIOS/MSBIO1.ASM new file mode 100644 index 0000000..36dac91 --- /dev/null +++ b/v4.0/src/BIOS/MSBIO1.ASM @@ -0,0 +1,645 @@ + + PAGE ,132 ; + TITLE MSBIO1.asm - BIOS +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +COMMENT * +THE LINK STEP IS PERFORMED BY USING THE FOLLOWING "NEW.ARF" FILE: +msbio1+ +msSTACK+ +MsCON+ +msAUX+ +msLPT+ +msCLOCK+ +msdISK+ +msBIO2+ +C:\BIO2\OLDOBJ\disk+ +C:\BIO2\OLDOBJ\msinit+ +C:\BIO2\OLDOBJ\sysinit1+ +C:\BIO2\OLDOBJ\sysinit2+ +C:\BIO2\OLDOBJ\sysimes,msbio,/M; + +THE FOLLOWING IS A BATCH FILE THAT CAN BE USED TO CREATE THE IBMBIO.COM +WHERE "LOCSCR" IS A FILE THAT JUST HAS THE NUMBER, 70: + +link @NEW.ARF +exe2bin ibmbio ibmbio.com buffer to dump in Hex. +; CX -> # of bytes (Length of the buffer) +; +DUMPBYTES proc near + pushf + push ax +dumploops: + lodsb + mov ah, al + shr ah, 1 + shr ah, 1 + shr ah, 1 + shr ah, 1 + call hex_to_ascii + push ax + mov al, ah + call outchar + pop ax + call outchar + mov al, ' ' + call outchar + loop dumploops + + mov al, 0dh + call outchar + mov al, 0ah + call outchar + + pop ax + popf + ret +DUMPBYTES endp + + PUBLIC Hex_to_ascii +Hex_to_ascii proc near ;J.K. - 4/9/86 + and ax, 0f0fh + add ah, 30h + cmp ah, 3ah + jb hta_$1 + add ah, 7 +hta_$1: + add al, 30h + cmp al, 3ah + jb hta_$2 + add al, 7 +hta_$2: + ret +Hex_to_ascii endp + + PUBLIC outchar +Outchar proc near + PUSH AX + PUSH SI + PUSH DI + PUSH BP + PUSH BX +;SB33002******************************************************* + MOV AH, 0Eh ;SET COMMAND TO WRITE A CHAR ;SB;3.30* + MOV BX, 7 ;SET FOREGROUND COLOR ;SB;3.30* + INT 10h ;CALL ROM-BIOS ;SB;3.30* +;SB33002******************************************************* + POP BX + POP BP + POP DI + POP SI + POP AX + RET +Outchar endp + + ENDIF + INCLUDE MSMACRO.INC + +;--------------------------------------------------- +; +; DEVICE ENTRY POINT +; +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER +EXTRA = 22 ;USUALLY A POINTER TO VOL ID FOR ERROR 15 +START_L = 26 ;AN000; Extended start sector (Low) +START_H = 28 ;AN000; Extended start sector (High) + + PUBLIC STRATEGY +STRATEGY PROC FAR + MOV WORD PTR CS:[PTRSAV],BX + MOV WORD PTR CS:[PTRSAV+2],ES + RET +STRATEGY ENDP + + PUBLIC CON$IN +CON$IN PROC FAR + PUSH SI + MOV SI,OFFSET CONTBL + JMP SHORT ENTRY +CON$IN ENDP + + PUBLIC AUX0$IN +AUX0$IN PROC FAR + PUSH SI + PUSH AX + XOR AL,AL + JMP SHORT AUXENT +AUX0$IN ENDP + + PUBLIC AUX1$IN +AUX1$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,1 + JMP short AUXENT ;J.K. 4/15/86 +AUX1$IN ENDP + +;SB33102**************************************************************** +;SB Add code to handle two more COM Ports +;boban + + PUBLIC AUX2$IN +AUX2$IN proc far + push si + push ax + mov al,2 + jmp short AUXENT +AUX2$IN endp + + PUBLIC AUX3$IN +AUX3$IN proc far + push si + push ax + mov al,3 + jmp short AUXENT + +;SB33102**************************************************************** + +AUXENT: + MOV SI,OFFSET AUXTBL + JMP SHORT ENTRY1 +AUX3$IN ENDP + +PRN0$IN PROC FAR + PUBLIC PRN0$IN + + PUSH SI + PUSH AX + XOR AX,AX + JMP SHORT PRNENT +PRN0$IN ENDP + + PUBLIC PRN1$IN +PRN1$IN PROC FAR + PUSH SI + PUSH AX + XOR AL,AL + MOV AH,1 + JMP SHORT PRNENT +PRN1$IN ENDP + + PUBLIC PRN2$IN +PRN2$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,1 + MOV AH,2 + JMP SHORT PRNENT +PRN2$IN ENDP + + PUBLIC PRN3$IN +PRN3$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,2 + MOV AH,3 +PRNENT: + MOV SI,OFFSET PRNTBL + MOV CS:[PRINTDEV],AH ;SAVE INDEX INTO ARRAY OF RETRY COUNTS + JMP SHORT ENTRY1 +PRN3$IN ENDP + + PUBLIC TIM$IN +TIM$IN PROC FAR + PUSH SI + MOV SI,OFFSET TIMTBL + JMP SHORT ENTRY +TIM$IN ENDP + + PUBLIC DSK$IN +DSK$IN PROC FAR + PUSH SI + MOV SI,OFFSET DSKTBL + +ENTRY: + PUSH AX +ENTRY1: + PUSH CX + PUSH DX + PUSH DI + PUSH BP + PUSH DS + PUSH ES + PUSH BX + + MOV CS:[AUXNUM],AL ;SAVE CHOICE OF AUX/PRN DEVICE + + LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET + ASSUME DS:NOTHING + + MOV AL,BYTE PTR DS:[BX].UNIT ;AL = UNIT CODE + MOV AH,BYTE PTR DS:[BX].MEDIA ;AH = MEDIA DESCRIP + MOV CX,WORD PTR DS:[BX].COUNT ;CX = COUNT + MOV DX,WORD PTR DS:[BX].START ;DX = START SECTOR + +;SB34MSB100********************************************************************* +;SB +;SB The disk device driver can now handle 32 bit start sector number. +;SB So we should check to see if a 32 bit sector number has been specified +;SB and if so get it. Whether a 32 bit sector has been specified or not +;SB the disk driver expects a 32 bit sector number with the high word +;SB in cs:Start_Sec_H and the low word in dx. +;SB +;SB Algorithm: +;SB 1. Check to see if the request is for the disk driver by +;SB checking to see if SI points to DSKTBL. +;SB +;SB 2. If request not for the disk nothing special needs to be done. +;SB +;SB 3. If request for the disk then check to see if a 32 bit +;SB sector number has been specified by seeing whether the +;SB the conventional sector number specified is -1. If so +;SB we need to pick the 32 bit sector number from the new +;SB fields in the request packet. See the request header +;SB struc for the fields you need. If the conventional +;SB sector field is not -1 then a 16 bit sector number +;SB has been specified and we just need to initalise the +;SB high word in cs:Start_Sec_H to 0 +;SB +;SB NOTE: START_L and START_H are the offsets withing the IO_REQUEST packet +;SB which contain the low and hi words of the 32 bit start sector if +;SB it has been used. +;SB +;SB NOTE:Remember not to destroy the registers which have been set up before + + CMP SI,OFFSET DSKTBL + JNZ DSK_REQ_CONT ; Not Disk Req + CMP DX,-1 + JNZ DSK_REQ_16 + MOV DX,DS:[BX].START_H ; 32 bits DSK REQ + MOV CS:START_SEC_H,DX ; CS:Start_sec_H = Packet.Start_H + MOV DX,DS:[BX].START_L ; DX = Packet.Start_L + JMP SHORT DSK_REQ_CONT +DSK_REQ_16: + MOV CS:START_SEC_H,0 +DSK_REQ_CONT: + +;SB34MSB100********************************************************************* + + XCHG DI,AX + MOV AL,BYTE PTR DS:[BX].CMD + CMP AL,CS:[SI] ;ARR 2.41 + JA CMDERR + + CBW ; NOTE THAT AL <= 15 MEANS OK + SHL AX,1 + + ADD SI,AX + XCHG AX,DI + + LES DI,DWORD PTR DS:[BX].TRANS + + PUSH CS + POP DS + + ASSUME DS:CODE + + CLD + JMP WORD PTR [SI+1] ;GO DO COMMAND +DSK$IN ENDP + PAGE +;===================================================== +;= +;= SUBROUTINES SHARED BY MULTIPLE DEVICES +;= +;===================================================== +;---------------------------------------------------------- +; +; EXIT - ALL ROUTINES RETURN THROUGH THIS PATH +; + PUBLIC BUS$EXIT +BUS$EXIT PROC FAR + ASSUME DS:NOTHING + MOV AH,00000011B + JMP SHORT ERR1 + + PUBLIC CMDERR +CMDERR: + MOV AL,3 ;UNKNOWN COMMAND ERROR + + PUBLIC ERR$CNT +ERR$CNT: + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + + PUBLIC ERR$EXIT +ERR$EXIT: + MOV AH,10000001B ;MARK ERROR RETURN + JMP SHORT ERR1 +BUS$EXIT ENDP + +EXITP PROC FAR + ASSUME DS:CODE ; WE ARE NOT SURE THIS IS CORRECT 3/18/86 +EXIT$ZER: + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + XOR AX,AX + MOV WORD PTR [BX].COUNT,AX ;INDICATE NO CHARS READ + + PUBLIC EXIT +EXIT: + ASSUME DS:NOTHING + MOV AH,00000001B +ERR1: + ASSUME DS:NOTHING + LDS BX,CS:[PTRSAV] + MOV WORD PTR [BX].STATUS,AX ;MARK OPERATION COMPLETE + + POP BX + POP ES + POP DS + POP BP + POP DI + POP DX + POP CX + POP AX + POP SI + RET ;RESTORE REGS AND RETURN +EXITP ENDP + +;------------------------------------------------------------- +; +; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE +; +; CALLED VIA INT 29H +; + PUBLIC CHROUT +CHROUT = 29H + + PUBLIC OUTCHR +OUTCHR PROC FAR + PUSH AX + PUSH SI + PUSH DI + PUSH BP +;SB33002a******************************************************* + push bx ; ;SB ;3.30 + mov AH, 0Eh ; set command to write a character;SB;3.30 + mov BX, 7 ; set foreground color ;SB ;3.30 + int 10h ; call rom-bios ;SB ;3.30 + pop bx ; ;SB ;3.30 +;SB33002a******************************************************* + POP BP + POP DI + POP SI + POP AX + IRET +OUTCHR ENDP +;---------------------------------------------- +; +; SET DX TO AUXNUM +; + PUBLIC GETDX +GETDX PROC NEAR + MOV DX,WORD PTR CS:[AUXNUM] + RET +GETDX ENDP + PAGE +;************************************************** ARR 2.15 + +;----------------------------------------------- +; +; TIMER INTERRUPT HANDLER +; +;TIMER_LOW DW 0 +;TIMER_HIGH DW 0 +; +;TIMER: +; STI +; PUSH AX +; PUSH CX +; PUSH DX +; PUSH DS +; PUSH CS +; POP DS +; XOR AX,AX +; INT 1AH ; GET ROM TIME AND ZAP ROLL OVER +; MOV [TIMER_HIGH],CX +; MOV [TIMER_LOW],DX +; OR AL,AL +; JZ T5 +; INC WORD PTR [DAYCNT] ; ONE DAY GONE BY +;T5: +; POP DS +; POP DX +; POP CX +; POP AX +; IRET +;************************************************** ARR 2.15 +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSBIO2.ASM b/v4.0/src/BIOS/MSBIO2.ASM new file mode 100644 index 0000000..50b25bc --- /dev/null +++ b/v4.0/src/BIOS/MSBIO2.ASM @@ -0,0 +1,572 @@ + PAGE ,132 ; + TITLE MSBIO2 - BIOS + + %OUT ...MSBIO2.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; - P1820 New Message SKL file 10/20/87 J.K. +;AN002; - P5045 New INT 2fh for Get BDS table vector for EMS 06/06/88 J.K. +;============================================================================== + +ROMSEGMENT EQU 0F000H +MODELBYTE EQU DS:BYTE PTR [0FFFEH] +MODELPCJR EQU 0FDH + + itest=0 + + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE DEVSYM.INC + INCLUDE PUSHPOP.INC + INCLUDE MSMACRO.INC + + ASSUME DS:NOTHING,ES:NOTHING + + EXTRN DSK$IN:NEAR + EXTRN SETPTRSAV:NEAR + EXTRN OUTCHR:NEAR + EXTRN SETDRIVE:NEAR + EXTRN FLUSH:NEAR + EXTRN HARDERR:NEAR + EXTRN HARDERR2:NEAR + EXTRN MAPERROR:NEAR + EXTRN GETBP:NEAR + EXTRN CHECKSINGLE:NEAR + EXTRN CHECK_TIME_OF_ACCESS:NEAR + EXTRN EXIT:NEAR + EXTRN HAS1:NEAR + EXTRN READ_SECTOR:NEAR + EXTRN INT_2F_13:FAR + + EXTRN OLD13:DWORD + +;DATA + EXTRN PTRSAV:DWORD ;IBMBIO1 + EXTRN START_BDS:WORD + EXTRN FDRIVE1:WORD + EXTRN FDRIVE2:WORD + EXTRN FDRIVE3:WORD + EXTRN FDRIVE4:WORD + EXTRN FLAGBITS:WORD + EXTRN TIM_DRV:BYTE + EXTRN MEDBYT:BYTE + EXTRN DRVMAX:BYTE + extrn Ext_Boot_Sig:byte ;AN000; ibmbdata + extrn SecPerClusInSector:byte ;AN000; ibmbdata + extrn Boot_Serial_L:word ;AN000; ibmbdata + extrn Boot_Serial_H:word ;AN000; ibmbdata + + PATHSTART 005,DISK + EVENB + public Model_Byte +MODEL_BYTE DB 0FFH ; MODEL BYTE. SET UP AT INIT TIME. + ; FF - PC1 + ; FE - XT (64/256K PLANAR) + ; FD - PC-JR + ; FC - PC/AT + public Secondary_Model_Byte +Secondary_Model_Byte db 0 + + PUBLIC ORIG19 +ORIG19 DD ? + + PUBLIC INT19SEM +INT19SEM DB 0 ; INDICATE THAT ALL INT 19 + ; INITIALIZATION IS COMPLETE + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + public Int19OLD&AA +Int19OLD&AA dd -1 ;Orignal hardware int. vectors for INT 19h. + ENDM + + EVENB + PUBLIC DSKDRVS +DSKDRVS DW FDRIVE1 + DW FDRIVE2 + DW FDRIVE3 + DW FDRIVE4 + PUBLIC HDSKTAB +HDSKTAB DW HDRIVE + DW DRIVEX +;* Next area is reseved for mini disk BPB pointers *** J.K. 4/7/86 +;* Don't change this position. Should be addressible from DskDrvs *** J.K. 4/7/86 +MINI_DISK_BPB_PTRS DB 40 dup (?) ;J.K. 4/7/86 - memory reserved for Mini disk. + + EVENB + PUBLIC INT_2F_NEXT +INT_2F_NEXT DD ? + +RET_ADDR DD ? + + PATHEND 005,DISK +; = = = = = = = = = = = = = = = = = = = = + +; INT19 +; +; WE "HOOK" THE INT 19 VECTOR, BECAUSE CONTRARY TO IBM DOCUMENTATION, +; IT DOES NOT "BOOTSTRAP" THE MACHINE. IT LEAVES MEMORY ALMOST UNTOUCHED. +; SINCE THE BIOS_INIT CODE ASSUMES THAT CERTAIN INTERRUPT VECTORS POINT TO +; THE ROM_BIOS WE MUST "UNHOOK" THEM BEFORE ISSUING THE ACTUAL INT_19. +; CURRENTLY THE ONLY VECTORS THAT NEED TO BE UNHOOKED ARE INT_19, INT_13, +; AND THE HARDWARE INTERRUPTS. +; + PUBLIC INT19 +INT19 PROC FAR + XOR AX,AX + MOV DS,AX + assume ds:nothing + assume es:nothing + + LES DI,OLD13 + MOV DS:[13H*4],DI + MOV DS:[13H*4+2],ES + + CMP BYTE PTR INT19SEM, 0 + JNZ INT19VECS + JMP DOINT19 + +; ON THE PCJR, DON'T REPLACE ANY VECTORS +; MODEL BYTE DEFINITIONS FROM IBMSTACK.ASM + MOV AX,ROMSEGMENT + MOV DS,AX + MOV AL,MODELPCJR + + CMP AL,MODELBYTE + JNE INT19VECS + JMP DOINT19 + +;Stacks code has changed these hardware interrupt vectors +;STKINIT in SYSINIT1 will initialzie Int19hOLDxx values. +INT19VECS: + XOR AX,AX + MOV DS,AX + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + + LES DI,Int19OLD&AA +;SB33103****************************************************************** + + mov ax,es ; + cmp ax,-1 ;OPT 0ffffh is unlikely segment + je skip_int&AA ;OPT no need to check selector too + cmp di,-1 ;OPT 0ffffh is unlikely offset + je skip_int&AA + +;SB33103****************************************************************** + MOV DS:[AA&H*4],DI + MOV DS:[AA&H*4+2],ES +skip_int&AA: + ENDM + +DOINT19: + LES DI,ORIG19 + MOV DS:[19H*4],DI + MOV DS:[19H*4+2],ES + + INT 19H +INT19 ENDP + + ASSUME DS:CODE + PUBLIC DSK$INIT +DSK$INIT PROC NEAR + PUSH CS + POP DS + MOV AH,BYTE PTR DRVMAX + MOV DI,OFFSET DSKDRVS + JMP SETPTRSAV +DSK$INIT ENDP + +; +; INT 2F HANDLER FOR EXTERNAL BLOCK DRIVERS TO COMMUNICATE WITH THE INTERNAL +; BLOCK DRIVER IN IBMDISK. THE MULTIPLEX NUMBER CHOSEN IS 8. THE HANDLER +; SETS UP THE POINTER TO THE REQUEST PACKET IN [PTRSAV] AND THEN JUMPS TO +; DSK$IN, THE ENTRY POINT FOR ALL DISK REQUESTS. +; ON EXIT FROM THIS DRIVER (AT EXIT), WE WILL RETURN TO THE EXTERNAL DRIVER +; THAT ISSUED THIS INT 2F, AND CAN THEN REMOVE THE FLAGS FROM THE STACK. +; THIS SCHEME ALLOWS US TO HAVE A SMALL EXTERNAL DEVICE DRIVER, AND MAKES +; THE MAINTAINANCE OF THE VARIOUS DRIVERS (DRIVER AND IBMBIO) MUCH EASIER, +; SINCE WE ONLY NEED TO MAKE CHANGES IN ONE PLACE (MOST OF THE TIME). +; +; 06/03/88 J.K. When AL=3, return DS:DI -> Start of BDS table. +; (EMS device driver hooks INT 13h to handle 16KB DMA overrun +; problem. BDS table is going to be used to get head/sector +; informations without calling Generic IOCTL Get Device Parm call.) +; +; AL CONTAINS THE INT2F FUNCTION: +; 0 - CHECK FOR INSTALLED HANDLER - RESERVED +; 1 - INSTALL THE BDS INTO THE LINKED LIST +; 2 - DOS REQUEST +; 3 - Get BDS vector ;06/03/88 J.K. +; Return BDS table starting pointer in DS:DI + +MYNUM EQU 8 + + PUBLIC INT2F_DISK +INT2F_DISK PROC FAR + CMP AH,MYNUM + JE MINE + JMP CS:[INT_2F_NEXT] ; CHAIN TO NEXT INT 2F HANDLER +MINE: + CMP AL,0F8H ; IRET ON RESERVED FUNCTIONS + JB DO_FUNC + IRET +DO_FUNC: + OR AL,AL ; A GET INSTALLED STATE REQUEST? + JNE DISP_FUNC + MOV AL,0FFH + IRET +DISP_FUNC: + MESSAGE FTESTINIT,<"INT2F_DISK",CR,LF> + CMP AL,1 ; REQUEST FOR INSTALLING BDS? + JNE DO_DOS_REQ + CALL INSTALL_BDS + IRET + +DO_DOS_REQ: +; SET UP POINTER TO REQUEST PACKET + cmp al, 3 ;AN002; Get BDS vector? + je DO_Get_BDS_Vector ;AN002; + MOV WORD PTR CS:[PTRSAV],BX ;othrwise DOS function. + MOV WORD PTR CS:[PTRSAV+2],ES + JMP DSK$IN + +DO_Get_BDS_Vector: ;AN002; AL=3 + push cs ;AN002; + pop ds ;AN002; + mov di, Start_BDS ;AN002; + IRET ;AN002; + +INT2F_DISK ENDP + +; +; INSTALL_BDS INSTALLS A BDS A LOCATION DS:DI INTO THE CURRENT LINKED LIST OF +; BDS MAINTAINED BY THIS DEVICE DRIVER. IT PLACES THE BDS AT THE END OF THE +; LIST. + PUBLIC INSTALL_BDS +INSTALL_BDS PROC NEAR + MESSAGE FTESTINIT,<"INSTALL BDS",CR,LF> +; DS:DI POINT TO BDS TO BE INSTALLED + LES SI,DWORD PTR CS:[START_BDS] ; START AT BEGINNING OF LIST + PUSH ES ; SAVE POINTER TO CURRENT BDS + PUSH SI +; ES:SI NOW POINT TO BDS IN LINKED LIST +LOOP_NEXT_BDS: + CMP SI,-1 ; GOT TO END OF LINKED LIST? + JZ INSTALL_RET +; IF WE HAVE SEVERAL LOGICAL DRIVES USING THE SAME PHYSICAL DRIVE, WE MUST +; SET THE I_AM_MULT FLAG IN EACH OF THE APPROPRIATE BDSS. + MOV AL,BYTE PTR DS:[DI].DRIVENUM + CMP BYTE PTR ES:[SI].DRIVENUM,AL + JNZ NEXT_BDS + MESSAGE FTESTINIT,<"LOGICAL DRIVES",CR,LF> + XOR BX,BX + MOV BL,FI_AM_MULT + OR WORD PTR DS:[DI].FLAGS,BX ; SET FLAGS IN BOTH BDSS CONCERNED + OR WORD PTR ES:[SI].FLAGS,BX + MOV BL,FI_OWN_PHYSICAL + XOR BX,-1 + AND WORD PTR DS:[DI].FLAGS,BX ; RESET THAT FLAG FOR 'NEW' BDS +; WE MUST ALSO SET THE FCHANGELINE BIT CORRECTLY. + MOV BX,WORD PTR ES:[SI].FLAGS ; DETERMINE IF CHANGELINE AVAILABLE + AND BL,FCHANGELINE + XOR BH,BH + OR WORD PTR DS:[DI].FLAGS,BX + +NEXT_BDS: +; BEFORE MOVING TO NEXT BDS, PRESERVE POINTER TO CURRENT ONE. THIS IS NEEDED AT +; THE END WHEN THE NEW BDS IS LINKED INTO THE LIST. + POP BX ; DISCARD PREVIOUS POINTER TO BDS + POP BX + PUSH ES + PUSH SI + MOV BX,WORD PTR ES:[SI].LINK + 2 + MOV SI,WORD PTR ES:[SI].LINK + MOV ES,BX + JMP SHORT LOOP_NEXT_BDS + +INSTALL_RET: + POP SI ; RETRIEVE POINTER TO LAST BDS + POP ES ; IN LINKED LIST. + MOV AX,DS + MOV WORD PTR ES:[SI].LINK+2,AX ; INSTALL BDS + MOV WORD PTR ES:[SI].LINK,DI + MOV WORD PTR DS:[DI].LINK,-1 ; SET NEXT POINTER TO NULL + RET +INSTALL_BDS ENDP + +; +; RE_INIT INSTALLS THE INT 2F VECTOR THAT WILL HANDLE COMMUNICATION BETWEEN +; EXTERNAL BLOCK DRIVERS AND THE INTERNAL DRIVER. IT ALSO INSTALLS THE +; RESET_INT_13 INTERFACE. IT IS CALLED BY SYSYINIT +; + PUBLIC RE_INIT +RE_INIT PROC FAR + MESSAGE FTESTINIT,<"REINIT",CR,LF> + PUSH AX + PUSH DS + PUSH DI + XOR DI,DI + MOV DS,DI + MOV DI,2FH*4 ; POINT IT TO INT 2F VECTOR + MOV AX,WORD PTR DS:[DI] + MOV WORD PTR CS:[INT_2F_NEXT],AX + MOV AX,WORD PTR DS:[DI+2] ; PRESERVE OLD INT 2F VECTOR + MOV WORD PTR CS:[INT_2F_NEXT+2],AX + +; INSTALL THE RESET_INT_13 +; INTERFACE + +; +; THE FOLLOWING TWO LINES ARE NOT NEEDED ANYMORE BECAUSE THE LINK HAS BEEN +; HARD-WIRED INTO THE CODE AT NEXT2F_13. - RAJEN. +;------------------------------------------------------------------------------ +; MOV WORD PTR CS:[NEXT2F_13],OFFSET INT2F_DISK ; PRESERVE INT2F_DISK POINTER +; MOV WORD PTR CS:[NEXT2F_13+2],CS +;------------------------------------------------------------------------------ + + CLI + MOV WORD PTR DS:[DI],OFFSET INT_2F_13 ; INSTALL NEW VECTORS + MOV WORD PTR DS:[DI+2],CS + STI + POP DI + POP DS + POP AX + + RET + +RE_INIT ENDP + +;------------------------------------------------- +; +; ASK TO SWAP THE DISK IN DRIVE A: +; + PUBLIC SWPDSK +SWPDSK PROC NEAR + MOV AL,BYTE PTR DS:[DI].DRIVELET ; GET THE DRIVE LETTER +;USING A DIFFERENT DRIVE IN A ONE DRIVE SYSTEM SO REQUEST THE USER CHANGE DISKS + ADD AL,"A" + MOV CS:DRVLET,AL + PUSH DS ; PRESERVE SEGMENT REGISTER + PUSH CS + POP DS + MOV SI,OFFSET SNGMSG ; DS:SI -> MESSAGE + PUSH BX + CALL WRMSG ;PRINT DISK CHANGE MESSAGE + CALL FLUSH +;SB33003*************************************************************** + xor AH, AH ; set command to read character;SB + int 16h ; call rom-bios ;SB +;SB33003*************************************************************** + POP BX + POP DS ; RESTORE SEGMENT REGISTER +WRMRET: + RET +SWPDSK ENDP + +;---------------------------------------------- +; +; WRITE OUT MESSAGE POINTED TO BY [SI] +; + PUBLIC WRMSG +WRMSG PROC NEAR + LODSB ;GET THE NEXT CHARACTER OF THE MESSAGE + OR AL,AL ;SEE IF END OF MESSAGE + JZ WRMRET +; INT CHROUT + PUSHF + PUSH CS + CALL OUTCHR + JMP SHORT WRMSG +WRMSG ENDP + +; INCLUDE BIOMES.INC + include MSBIO.CL2 + +; +; END OF SUPPORT FOR MULTIPLE FLOPPIES WITH NO LOGICAL DRIVES +; THIS IS NOT 'SPECIAL' ANY MORE BECAUSE WE NOW HAVE THE CAPABILITY OF +; DEFINING LOGICAL DRIVES IN CONFIG.SYS. WE THEREFORE KEEP THE CODE FOR +; SWAPPING RESIDENT ALL THE TIME. +; + +;J.K. 10/1/86 ******************************************************* +;Variables for Dynamic Relocatable modules +;These should be stay resident. + + public INT6C_RET_ADDR +INT6C_RET_ADDR DD ? ; return address from INT 6C for P12 machine + + PATHSTART 001,CLK +; +; DATA STRUCTURES FOR REAL-TIME DATE AND TIME +; + public BIN_DATE_TIME + public MONTH_TABLE + public DAYCNT2 + public FEB29 +BIN_DATE_TIME: + DB 0 ; CENTURY (19 OR 20) OR HOURS (0-23) + DB 0 ; YEAR IN CENTURY (0...99) OR MINUTES (0-59) + DB 0 ; MONTH IN YEAR (1...12) OR SECONDS (0-59) + DB 0 ; DAY IN MONTH (1...31) +MONTH_TABLE: ; + DW 0 ;MJB002 JANUARY + DW 31 ;MJB002 FEBRUARY + DW 59 ;MJB002 + DW 90 ;MJB002 + DW 120 ;MJB002 + DW 151 ;MJB002 + DW 181 ;MJB002 + DW 212 ;MJB002 + DW 243 ;MJB002 + DW 273 ;MJB002 + DW 304 ;MJB002 + DW 334 ;MJB002 DECEMBER +DAYCNT2 DW 0000 ;MJB002 TEMP FOR COUNT OF DAYS SINCE 1-1-80 +FEB29 DB 0 ;MJB002 FEBRUARY 29 IN A LEAP YEAR FLAG + PATHEND 001,CLK + +;******************************************************************** +; + + PUBLIC ENDFLOPPY +ENDFLOPPY LABEL BYTE +; +; END OF CODE FOR VIRTUAL FLOPPY DRIVES +; + PUBLIC ENDSWAP +ENDSWAP LABEL BYTE + + PATHSTART 004,BIO + + PUBLIC HNUM +HNUM DB 0 ;NUMBER OF HARDFILES + PUBLIC HARDDRV +HARDDRV DB 80H ;PHYSICAL DRIVE NUMBER OF FIRST HARDFILE +;********************************************************************** +; "HDRIVE" IS A HARD DISK WITH 512 BYTE SECTORS +;********************************************************************* + EVENB + PUBLIC BDSH +BDSH DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 80 ;INT 13 DRIVE NUMBER + DB "C" ;LOGICAL DRIVE LETTER + PUBLIC HDRIVE +HDRIVE: + DW 512 + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. OF ALLOCATION TABLES + DW 16 ;NUMBER OF DIRECTORY ENTRIES + DW 0000 ;NUMBER OF SECTORS (AT 512 BYTES EACH) + DB 11111000B ;MEDIA DESCRIPTOR + DW 1 ;NUMBER OF FAT SECTORS + DW 00 ;SECTOR LIMIT + DW 00 ;HEAD LIMIT + DW 00 ;HIDDEN SECTOR COUNT(low) + dw 00 ;AN000; Hidden Sector (high) + dw 00 ;AN000; Number of Sectors (low) + dw 00 ;AN000; Number of Sectors (high) + DB 0 ; TRUE => BIGFAT +OPCNTH DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGSH DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +RECBPBH DB 31 DUP (?) ; RECOMMENDED BPB FOR DRIVE +TRACKH DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LOH DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HIH DW -1 +VOLIDH DB "NO NAME ",0 ;AN000; VOLUME ID FOR THIS DISK +VolSerH dd 0 ;AN000; Current volume serial number from Boot record +SysIDH db "FAT12 " ,0 ;AN000; Current file system id from Boot record + +; +; END OF SINGLE HARD DISK SECTION +; + PUBLIC ENDONEHARD +ENDONEHARD LABEL BYTE +;********************************************************************** +; "DRIVEX " IS AN EXTRA TYPE OF DRIVE USUALLY RESERVED FOR AN +; ADDITIONAL HARD FILE +;********************************************************************* + EVENB + PUBLIC BDSX +BDSX DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 81 ;INT 13 DRIVE NUMBER + DB "D" ;LOGICAL DRIVE LETTER + PUBLIC DRIVEX +DRIVEX: + DW 512 + DB 00 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. OF ALLOCATION TABLES + DW 0000 ;NUMBER OF DIRECTORY ENTRIES + DW 0000 ;NUMBER OF SECTORS (AT 512 BYTES EACH) + DB 11111000B ;MEDIA DESCRIPTOR + DW 0000 ;NUMBER OF FAT SECTORS + DW 00 ;SECTOR LIMIT + DW 00 ;HEAD LIMIT + DW 00 ;HIDDEN SECTOR COUNT (low) + dw 00 ;AN000; Hidden Sector (high) + dw 00 ;AN000; Number of Sectors (low) + dw 00 ;AN000; Number of Sectors (high) + DB 0 ; TRUE => BIGFAT +OPCNTD DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGSD DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +RECBPBD DB 31 DUP (?) ; RECOMMENDED BPB FOR DRIVE +TRACKD DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LOD DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HID DW -1 +VOLIDD DB "NO NAME ",0 ;AN000; VOLUME ID FOR THIS DISK +VolSerD dd 0 ;AN000; Current volume serial number from Boot record +SysIDD db "FAT12 " ,0 ;AN000; Current file system id from Boot record + +; +; END OF SECTION FOR TWO HARD DISKS + PUBLIC ENDTWOHARD +ENDTWOHARD LABEL BYTE + + PATHEND 004,BIO + + PUBLIC TWOHARD +TWOHARD LABEL BYTE + PAGE + INCLUDE MS96TPI.INC + +;********************************************************************* +;Memory allocation for BDSM table. - J.K. 2/21/86 +;********************************************************************* + PUBLIC BDSMs +BDSMs BDSM_type Max_mini_dsk_num dup (<>) ;currently max. 23 + +;** End_of_BDSM defined in IBMINIT.ASM will be used to set the appropriate +;** ending address of BDSM table. + +; +;;3.3 BUG FIX -SP ------------------------------ +;;Migrated into 4.00 -MRW +;Paragraph buffer between the BDSMs and MSHARD +; +;The relocation code for MSHARD needs this. this cannot be used for +;anything. nothing can come before this or after this.....IMPORTANT!!!! +;don't get too smart and using this buffer for anything!!!!!! +; + db 16 dup(0) +; +;end of bug fix buffer +;; +;;3.3 BUG FIX -SP------------------------------ + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSCLOCK.ASM b/v4.0/src/BIOS/MSCLOCK.ASM new file mode 100644 index 0000000..5d66d03 --- /dev/null +++ b/v4.0/src/BIOS/MSCLOCK.ASM @@ -0,0 +1,296 @@ + TITLE MSCLOCK - DOS 3.3 +;---------------------------------------------------------------- +; : +; CLOCK DEVICE DRIVER : +; : +; : +; This file contains the Clock Device Driver. : +; : +; The routines in this files are: : +; : +; routine function : +; ------- -------- : +; TIM$WRIT Set the current time : +; TIM$READ Read the current time : +; Time_To_Ticks Convert time to corresponding : +; number of clock ticks : +; : +; The clock ticks at the rate of: : +; : +; 1193180/65536 ticks/second (about 18.2 ticks per second): +; See each routine for information on the use. : +; : +;---------------------------------------------------------------- + + + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSMACRO.INC + + EXTRN EXIT:NEAR +; +; DAYCNT is the number of days since 1-1-80. +; Each time the clock is read it is necessary to check if another day has +; passed. The ROM only returns the day rollover once so if it is missed +; the time will be off by a day. +; + EXTRN DAYCNT:WORD ;MSDATA + +;;Rev 3.30 Modification ------------------------------------------------ +; variables for real time clock setting + public HaveCMOSClock +HaveCMOSClock db 0 ;set by MSINIT. + public base_century +base_century db 19 + public base_year +base_year db 80 + public month_tab +month_tab db 31,28,31,30,31,30,31,31,30,31,30,31 + +; The following are indirect intra-segment call addresses. The +;procedures are defined in MSINIT for relocation. MSINIT will set these +;address when the relocation is done. + public BinToBCD +BinToBCD dw 0 ;should point to Bin_To_BCD proc in MSINIT + public DaycntToDay +DaycntToDay dw 0 ;should point to Daycnt_to_day in MSINIT + +;******************************************************************** +; Indirect call address of TIME_TO_TICKS procedure. +;This will be used by the relocatable portable suspend/resume code. + + public TimeToTicks +TimeToTicks dw Time_To_Ticks + +;;End of Modification ------------------------------------------------ + +;-------------------------------------------------------------------- +; +; Settime sets the current time +; +; On entry ES:[DI] has the current time: +; +; number of days since 1-1-80 (WORD) +; minutes (0-59) (BYTE) +; hours (0-23) (BYTE) +; hundredths of seconds (0-99) (BYTE) +; seconds (0-59) (BYTE) +; +; Each number has been checked for the correct range. +; + PUBLIC TIM$WRIT +TIM$WRIT PROC NEAR + ASSUME DS:CODE + mov AX,WORD PTR ES:[DI] + push AX ;DAYCNT. We need to set this at the very + ; end to avoid tick windows. +;;Rev 3.30 Modification + cmp HaveCMOSClock, 0 + je No_CMOS_1 + mov al,es:[di+3] ;get binary hours + call BinToBCD ;convert to BCD + mov ch,al ;CH = BCD hours + mov al,es:[di+2] ;get binary minutes + call BinToBCD ;convert to BCD + mov cl,al ;CL = BCD minutes + mov al,es:[di+5] ;get binary seconds + call BinToBCD ;convert to BCD + mov dh,al ;DH = BCD seconds + mov dl,0 ;DL = 0 (ST) or 1 (DST) + cli ;turn off timer + mov ah,03h ;set RTC time + int 1Ah ;call rom bios clock routine + sti + +;;End of Modification +No_CMOS_1: + mov CX,WORD PTR ES:[DI+2] + mov DX,WORD PTR ES:[DI+4] +;;Rev 3.30 Modification + call time_to_ticks ; convert time to ticks + ;CX:DX now has time in ticks + cli ; Turn off timer + mov AH, 1 ; command is set time in clock + int 1Ah ; call rom-bios clock routines + pop [DAYCNT] + sti +;CMOS clock ------------------------------------- + cmp HaveCMOSClock, 0 + je No_CMOS_2 + call DaycntToDay ; convert to BCD format + cli ; Turn off timer + mov AH,05h ; set RTC date + int 1Ah ; call rom-bios clock routines + sti +;------------------------------------------------ + +No_CMOS_2: + jmp EXIT +TIM$WRIT ENDP +;;End of Modification + + + +; +; convert time to ticks +; input : time in CX and DX +; ticks returned in CX:DX +; +public time_to_ticks +TIME_TO_TICKS PROC NEAR + + ; first convert from Hour,min,sec,hund. to + ; total number of 100th of seconds + mov AL,60 + mul CH ;Hours to minutes + mov CH,0 + add AX,CX ;Total minutes + mov CX,6000 ;60*100 + mov BX,DX ;Get out of the way of the multiply + mul CX ;Convert to 1/100 sec + mov CX,AX + mov AL,100 + mul BH ;Convert seconds to 1/100 sec + add CX,AX ;Combine seconds with hours and min. + adc DX,0 ;Ripple carry + mov BH,0 + add CX,BX ;Combine 1/100 sec + adc DX,0 + +;;Rev 3.30 Modification +;DX:CX IS TIME IN 1/100 SEC + XCHG AX,DX + XCHG AX,CX ;NOW TIME IS IN CX:AX + MOV BX,59659 + MUL BX ;MULTIPLY LOW HALF + XCHG DX,CX + XCHG AX,DX ;CX->AX, AX->DX, DX->CX + MUL BX ;MULTIPLY HIGH HALF + ADD AX,CX ;COMBINE OVERLAPPING PRODUCTS + ADC DX,0 + XCHG AX,DX ;AX:DX=TIME*59659 + MOV BX,5 + DIV BL ;DIVIDE HIGH HALF BY 5 + MOV CL,AL + MOV CH,0 + MOV AL,AH ;REMAINDER OF DIVIDE-BY-5 + CBW + XCHG AX,DX ;USE IT TO EXTEND LOW HALF + DIV BX ;DIVDE LOW HALF BY 5 + MOV DX,AX + ; CX:DX is now number of ticks in time + ret +TIME_TO_TICKS ENDP +;;End of Modification + + +; +; Gettime reads date and time +; and returns the following information: +; +; ES:[DI] =count of days since 1-1-80 +; ES:[DI+2]=hours +; ES:[DI+3]=minutes +; ES:[DI+4]=seconds +; ES:[DI+5]=hundredths of seconds +; + PUBLIC TIM$READ +TIM$READ PROC NEAR + ; read the clock + xor AH, AH ; set command to read clock + int 1Ah ; call rom-bios to get time + + or al,al ; check for a new day + jz noroll1 ; if al=0 then don't reset day count + INC [DAYCNT] ; CATCH ROLLOVE +noroll1: + MOV SI,[DAYCNT] + +; +; we now need to convert the time in tick to the time in 100th of +; seconds. The relation between tick and seconds is: +; +; 65536 seconds +; ---------------- +; 1,193,180 tick +; +; To get to 100th of second we need to multiply by 100. The equation is: +; +; Ticks from clock * 65536 * 100 +; --------------------------------- = time in 100th of seconds +; 1,193,180 +; +; Fortunately this fromula simplifies to: +; +; Ticks from clock * 5 * 65,536 +; --------------------------------- = time in 100th of seconds +; 59,659 +; +; The calculation is done by first multipling tick by 5. Next we divide by +; 59,659. In this division we multiply by 65,536 by shifting the dividend +; my 16 bits to the left. +; +; start with ticks in CX:DX +; multiply by 5 + MOV AX,CX + MOV BX,DX + SHL DX,1 + RCL CX,1 ;TIMES 2 + SHL DX,1 + RCL CX,1 ;TIMES 4 + ADD DX,BX + ADC AX,CX ;TIMES 5 + XCHG AX,DX + + +; now have ticks * 5 in DX:AX +; we now need to multiply by 65,536 and divide by 59659 d. + + mov CX,59659 ; get divisor + div CX + ; DX now has remainder + ; AX has high word of final quotient + mov BX,AX ; put high work if safe place + xor AX,AX ; this is the multiply by 65536 + div CX ; BX:AX now has time in 100th of seconds + +; +;Rounding based on the remainder may be added here +;The result in BX:AX is time in 1/100 second. + mov DX,BX + mov CX,200 ;Extract 1/100's +;Division by 200 is necessary to ensure no overflow--max result +;is number of seconds in a day/2 = 43200. + div CX + cmp DL,100 ;Remainder over 100? + jb NOADJ + sub DL,100 ;Keep 1/100's less than 100 +NOADJ: + cmc ;If we subtracted 100, carry is now set + mov BL,DL ;Save 1/100's +;To compensate for dividing by 200 instead of 100, we now multiply +;by two, shifting a one in if the remainder had exceeded 100. + rcl AX,1 + mov DL,0 + rcl DX,1 + mov CX,60 ;Divide out seconds + div CX + mov BH,DL ;Save the seconds + div CL ;Break into hours and minutes + xchg AL,AH + +;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) + + push AX + MOV AX,SI ; DAYCNT + stosw + pop AX + stosw + mov AX,BX + stosw + jmp EXIT + +TIM$READ ENDP +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSCON.ASM b/v4.0/src/BIOS/MSCON.ASM new file mode 100644 index 0000000..68fcfff --- /dev/null +++ b/v4.0/src/BIOS/MSCON.ASM @@ -0,0 +1,328 @@ + PAGE ,132 ; + TITLE MSCON - BIOS + %OUT ...MSCON.ASM +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== + + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE JUMPMAC.INC + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + +;*** DOS 3.3 will not support more than 25 rows +; INCLUDE DEVSYM.INC ;J.K. 4/29/86 for CON$GENIOCTL support +; INCLUDE IOCTL.INC ;J.K. 4/29/86 for CON$GENIOCTL support + + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + +; EXTRN CMDERR:NEAR ;MSBIO1 J.K. 4/29/86 + +;DATA + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN FHAVEK09:BYTE ;MSDISK + EXTRN ALTAH:BYTE ;MSBDATA + EXTRN KEYRD_Func:Byte ;MSBDATA + EXTRN KEYSTS_Func:Byte ;MSBDATA + +; EXTRN SAV_SC_INFO:BYTE ;MSBDATA J.K. 4/29/86 +; EXTRN SAV_SC_MODE:BYTE ;MSBDATA J.K. 4/29/86 +;------------------------------------------------------ +; +; CONSOLE READ ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$READ +CON$READ PROC NEAR + JCXZ CON$EXIT +CON$LOOP: + CALL CHRIN ;GET CHAR IN AL + STOSB ;STORE CHAR AT ES:DI + LOOP CON$LOOP +CON$EXIT: + JUMP EXIT +CON$READ ENDP +;--------------------------------------------------------- +; +; INPUT SINGLE CHAR INTO AL +; +;J.K.5/12/87 We are going to issue extended keyboard function, if supported. +;The returning value of the extended key stroke of the extended key board +;function uses 0E0h in AL instead of 00 as in the conventional key board +;function. This creates a conflict when the user entered real Greek Alpha +;charater (= 0E0h) to distinguish the extended key stroke and the Greek Alpha. +;This case will be handled in the following manner; +; AH = 16h +; INT 16h +; If AL == 0, then extended code (in AH) +; else If AL == 0E0h, then +; IF AH <> 0, then extended code (in AH) +; else Greek_Alpha character. +;Also, for compatibility reason, if an extended code is detected, then we +;are going to change the value in AL from 0E0h to 00h. + + +CHRIN PROC NEAR +;AN000; +; XOR AX,AX + mov ah,KEYRD_Func ;AN000; Set by MSINIT. 0 or 10h + xor al,al ;AN000; + XCHG AL,ALTAH ;GET CHARACTER & ZERO ALTAH + + OR AL,AL + JNZ KEYRET +;SB34CON000************************************************************** +;SB Keyboard I/O interrupt +;SB AH already contains the keyboard read function number +;SB 1 LOC + + int 16h +;SB34CON000************************************************************** +ALT10: + OR AX,AX ;CHECK FOR NON-KEY AFTER BREAK + JZ CHRIN + CMP AX,7200H ;CHECK FOR CTRL-PRTSC + JNZ ALT_Ext_Chk ;AN000; + MOV AL,16 + jmp KeyRet ;AN000; +ALT_Ext_Chk: +;SB34CON001************************************************************** +;SB IF operation was extended function (i.e. KEYRD_Func != 0) THEN +;SB IF character read was 0E0h THEN +;SB IF extended byte was zero (i.e. AH == 0) THEN +;SB goto keyret +;SB ELSE +;SB set AL to zero +;SB goto ALT_SAVE +;SB ENDIF +;SB ENDIF +;SB ENDIF +;SB 9 LOCS + + cmp BYTE PTR KEYRD_Func,0 + jz NOT_EXT + cmp al,0E0h + jnz NOT_EXT + or ah,ah + jz KEYRET + xor al,al + jmp short ALT_SAVE +NOT_EXT: + +;SB34CON001************************************************************** + OR AL,AL ;SPECIAL CASE? + JNZ KEYRET +ALT_SAVE: + MOV ALTAH,AH ;STORE SPECIAL KEY +KEYRET: + RET +CHRIN ENDP + +;-------------------------------------------------------------- +; +; KEYBOARD NON DESTRUCTIVE READ, NO WAIT +; +; PC-CONVERTIBLE-TYPE MACHINE: IF BIT 10 IS SET BY THE DOS IN THE STATUS WORD +; OF THE REQUEST PACKET, AND THERE IS NO CHARACTER IN THE INPUT BUFFER, THE +; DRIVER ISSUES A SYSTEM WAIT REQUEST TO THE ROM. ON RETURN FROM THE ROM, IT +; RETURNS A 'CHAR-NOT-FOUND' TO THE DOS. +; +CONBUSJ: + ASSUME DS:NOTHING + JMP CONBUS + + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$RDND +CON$RDND: + MOV AL,[ALTAH] + OR AL,AL + JZ RD1 + JMP RDEXIT + +RD1: +;SB34CON002************************************************************** +;SB Keyboard I/O interrupt +;SB Get keystroke status (KEYSTS_Func) +;SB 2 LOCS + + mov ah,KEYSTS_Func + int 16h +;SB34CON002************************************************************** + JZ NOCHR + JMP GOTCHR +NOCHR: + CMP FHAVEK09,0 + JZ CONBUSJ + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + TEST [BX].STATUS,0400H ; SYSTEM WAIT ENABLED? + JZ CONBUSJ + +;******************************** +; NEED TO WAIT FOR IBM RESPONSE TO REQUEST FOR CODE ON HOW TO USE THE SYSTEM +; WAIT CALL. +;******************************** + MESSAGE FTESTCON,<"SYSTEM WAIT STAGE",CR,LF> + MOV AX,4100H ; WAIT ON AN EXTERNAL EVENT +; MOV BX,0300H ; NO TIMEOUT +; MOV DX,60H ; LOOK AT I/O PORT 60H + INT 15H ; CALL ROM FOR SYSTEM WAIT + MESSAGE FTESTCON,<"OUT OF WAIT. AX IS "> + MNUM FTESTCON,AX + MESSAGE FTESTCON, + JMP CONBUS + + ASSUME DS:CODE +GOTCHR: + OR AX,AX + JNZ NOTBRK ;CHECK FOR NULL AFTER BREAK +;SB34CON004************************************************************** +;SB Keyboard I/O interrupt +;SB Keyboard read function (KEYRD_Func) +;SB 2 LOCS + + mov ah,KEYRD_Func + int 16h +;SB34CON004************************************************************** + JUMP CON$RDND ;AND GET A REAL STATUS +NOTBRK: + CMP AX,7200H ;CHECK FOR CTRL-PRTSC + JNZ RD_Ext_Chk ;AN000; + MOV AL,16 + jmp RDEXIT ;AN000; +RD_Ext_Chk: ;AN000; + cmp KEYRD_Func, 0 ;AN000; Extended Keyboard function? + jz RDEXIT ;AN000; No. Normal exit. + cmp al,0E0h ;AN000; Extended key value or Greek Alpha? + jne RDEXIT ;AN000; + cmp ah, 0 ;AN000; Scan code exist? + jz RDEXIT ;AN000; Yes. Greek Alpha char. + mov al, 0 ;AN000; No. Extended key stroke. Change it for compatibility + PUBLIC RDEXIT +RDEXIT: + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + MOV [BX].MEDIA,AL +EXVEC: + JUMP EXIT + +CONBUS: + ASSUME DS:NOTHING + JUMP BUS$EXIT +;-------------------------------------------------------------- +; +; KEYBOARD FLUSH ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$FLSH +CON$FLSH: + CALL FLUSH + JUMP EXIT + + PUBLIC FLUSH +FLUSH: + MOV [ALTAH],0 ;CLEAR OUT HOLDING BUFFER + +FLLOOP: +;SB33012**************************************************************** + ;SB ; Is there a char there? + mov AH, 1 ;SB ; command code for check status + int 16h ;SB ; call rom-bios keyboard routine +;SB33012**************************************************************** + JZ FLDONE +;SB33013**************************************************************** + xor AH, AH ;SB ; if zf is nof set, get character + int 16h ;SB ; call rom-bios to get character +;SB33013**************************************************************** + JMP FLLOOP +FLDONE: + + RET +;---------------------------------------------------------- +; +; CONSOLE WRITE ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$WRIT +CON$WRIT: + JCXZ EXVEC +CON$LP: + MOV AL,ES:[DI] ;GET CHAR + INC DI + INT CHROUT ;OUTPUT CHAR + LOOP CON$LP ;REPEAT UNTIL ALL THROUGH + JUMP EXIT +;----------------------------------------------- +; +; BREAK KEY HANDLING +; + PUBLIC CBREAK +CBREAK: + MOV CS:ALTAH,3 ;INDICATE BREAK KEY SET + + PUBLIC INTRET +INTRET: + IRET + +;------------------------------------------------------------------------------ +;J.K. 4/29/86 - CONSOLE GENERIC IOCTL SUPPORT FOR DOS 3.3. +;CON$GENIOCTL supports Get mode information, Set mode information functions. +;It will only save the value from "Set mode information" and will return +;the value through "Get mode information". It is supposed to be set by +;the MODE.COM and other application program can retrieve information +;through "Get mode information" call. +;Initially, there is no valuable informaton until set by MODE command, so +;any attemp to "Get mode information" at that points will fail. (unknown +;command with carry set.) +;At entry: CS = DS = code +; CS:[PTRSAV] has seg, address of the Request Header saved in +; in Strategy routine. +; +; PUBLIC CON$GENIOCTL +; ASSUME DS:CODE +;CON$GENIOCTL: +; les di, CS:[PTRSAV] ;get the request header +; cmp es:[di].MajorFunction, IOC_SC +; je Major_SC_OK +;SC_CMDERR: +; stc +; jmp cmderr ;carry is set, exit to cmderr +;Major_SC_OK: +; mov al, es:[di].MinorFunction ;save minor function +; les di, es:[di].GenericIOCTL_Packet ;pointer of SC_MODE_INFO structure +; mov cx, es:[di].SC_INFO_LENGTH ;save length +; inc di +; inc di ;ES:DI -> SC_MODE in Info. Packet +; cmp cx, SC_INFO_PACKET_LENGTH ;currently 9. +; jne SC_CMDERR ;cannot accept the different packet +; cmp al, GET_SC_MODE ;minor function = 60h ? +; jne SC_SET_MODE_FUNC ;no, check if it is "Set mode function" +; cmp SAV_SC_MODE, 0 ;information set before? +; je SC_CMDERR ;no, cannot get the info. +;;SC_GET_MODE_FUNC: ;es:di -> SC_MODE in info. packet +; ;cx - length +; mov si, offset SAV_SC_INFO +; rep movsb ;ds:si -> sav_sc_info, es:di -> sc_mode +; jmp exit +; +;SC_SET_MODE_FUNC: ;es:di -> SC_MODE +; cmp al, SET_SC_MODE ;minor function = 40h ? +; jne SC_CMDERR +; mov si, offset SAV_SC_INFO +; xchg di, si +; push es +; push ds +; pop es +; pop ds +; rep movsb ;ds:si -> sc_mode, es:di -> sav_sc_info +; jmp exit +; +;J.K. 4/29/86 - End of CONSOLE GENERIC IOCTL SUPPORT FOR DOS 3.3. + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSDISK.ASM b/v4.0/src/BIOS/MSDISK.ASM new file mode 100644 index 0000000..f132e7f --- /dev/null +++ b/v4.0/src/BIOS/MSDISK.ASM @@ -0,0 +1,2443 @@ + PAGE ,132 ; + TITLE MSDISK - BIOS + %OUT ...MSDISK.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; d24 Multi Track enable/disable command in CONFIG.SYS 6/27/87 J.K. +;AN002; d9 Double word MOV instruction 7/1/87 J.K. +;AN003: d25 Change DASD ERP to that recommended by Storage systems 7/28/87 J.K. +;AN004; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN005; P985 Allow I/O access to unformatted media 9/14/87 J.K. +;AN006; P1535 Disallow I/O access to unformatted media. 10/15/87 J.K. +; (Give the user to control this - Generic IOCTL subfunction 64h/44h +;AN007; p2828 Do not retry for multi-track format request 12/08/87 J.K. +;AC008; p3197 Should reset change line after BPB set in BDS table 01/21/88 J.K. +;AN009; p3349 Should retry at hard file timeout error 02/03/88 J.K. +;AN010; p4696 ECC error handler should cover PC ATs for CMC disks 05/04/88 J.K. +;AN011; p5034 Possible virgin hard file problem with direct INT 13 06/03/88 J.K. +;AN012; P5049 Attempt to write at DISK BASE table in ROM BIOS 06/06/88 J.K. +;AN013; P5055 Diskcopy fails (Regression of P5049) 06/09/88 J.K. +;============================================================================== + +;for testing, set itest to 1. So as MSBIO1.ASM. + itest=0 + EXTRN NUMERR:ABS ;MSDATA + + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE PUSHPOP.INC + INCLUDE MSMACRO.INC + INCLUDE DEVSYM.INC + INCLUDE MSDSKPR.INC + include biostruc.inc + + EXTRN INT2F_DISK:FAR ;MSBIO2 + EXTRN MEDIACHECK:NEAR ;96TPI + EXTRN HASCHANGE:NEAR ;96TPI + EXTRN MEDIA_SET_VID:NEAR ;96TPI + EXTRN HIDENSITY:NEAR ;96TPI + EXTRN CHECKLATCHIO:NEAR ;96TPI + EXTRN CHECKIO:NEAR ;96TPI + EXTRN SET_CHANGED_DL:NEAR ;96TPI + EXTRN SET_VOLUME_ID:NEAR ;MSVOLID + EXTRN SWPDSK:NEAR ;MSBIO2 + EXTRN CMDERR:NEAR ;MSBIO1 + EXTRN STRATEGY:NEAR ;MSBIO1 + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN DSK$IN:NEAR ;MSBIO1 + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + EXTRN ERR$EXIT:NEAR ;MSBIO1 + extrn ResetChanged:near ;AN000; MS96TPI + +;DATA + EXTRN OLD13:DWORD ;MSBIO2 + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN COM1DEV:WORD ;MSAUX + EXTRN DAYCNT:WORD ;MSCLOCK + EXTRN TIM_DRV:BYTE ;MSDATA + EXTRN ACCESSCOUNT:BYTE ;MSDATA + EXTRN SM92:BYTE ;MSDATA + EXTRN DISKSECTOR:BYTE ;MSDATA + EXTRN MEDIABYTE:BYTE ;MSDATA + EXTRN SECPERCLUSINSECTOR:BYTE ;MSDATA + EXTRN BPB_IN_SECTOR:WORD ;MSDATA + EXTRN DISKSECTOR:BYTE ;MSDATA + EXTRN STEP_DRV:BYTE ;MSDATA + EXTRN START_BDS:WORD ;MSDATA + EXTRN PHYS_DRV:BYTE ;MSDATA + EXTRN WRTVERIFY:WORD ;MSDATA + EXTRN FSETOWNER:BYTE ;MSDATA + EXTRN SINGLE:BYTE ;MSDATA + EXTRN RFLAG:BYTE ;MSDATA + EXTRN MEDBYT:BYTE ;MSDATA + EXTRN SPSAV:WORD ;MSDATA + EXTRN SECCNT:WORD ;MSDATA + EXTRN DPT:DWORD ;MSDATA + EXTRN CURSEC:BYTE,CURHD:BYTE ;MSDATA + EXTRN CURTRK:WORD ;MSDATA + EXTRN EOT:BYTE ;MSDATA + EXTRN MOTORSTARTUP:BYTE,SETTLECURRENT:BYTE,SETTLESLOW:BYTE ;MSDATA + EXTRN CURHD:BYTE ;MSDATA + EXTRN LSTERR:BYTE ;MSDATA + EXTRN ERRIN:BYTE,ERROUT:BYTE ;MSDATA + EXTRN PREVOPER:WORD ;MSDATA + EXTRN ORIG13:DWORD ;MSDATA + EXTRN FLAGBITS:WORD ;MSDATA + EXTRN NUMBER_OF_SEC:BYTE ;MSDATA + EXTRN FHAVE96:BYTE ;MSDATA + EXTRN NEW_ROM:BYTE ;MSDATA + EXTRN FORMT_EOT:BYTE,HDNUM:BYTE,TRKNUM:WORD,GAP_PATCH:BYTE ;MSDATA + EXTRN NEXT2F_13:WORD ;MSDATA + extrn Save_head_sttl:byte ;msbdata + extrn Secrete_Code:word ;msbdata J.K. 11/7/86 Secrete code for DOS 3.3 MSBIO + extrn Ext_Boot_Sig:byte ;AN000; msbdata + extrn Boot_Serial_L:word ;AN000; msbdata + extrn Boot_Serial_H:word ;AN000; msbdata + extrn Boot_Volume_Label:byte ;AN000; msbdata + extrn Boot_System_ID:byte ;AN000; msbdata + extrn Model_Byte:Byte ;MSBIO2 + extrn Secondary_Model_Byte:Byte ;MSBIO2 + +;----------------------------------------------------------------- +; +; DISK INTERFACE ROUTINES +; +; DEVICE ATTRIBUTE BITS: +; BIT 6 - GET/SET MAP FOR LOGICAL DRIVES AND GENERIC IOCTL. +; + +MAXERR = 5 +LSTDRV = 504H + +; SOME FLOPPIES DO NOT HAVE CHANGELINE. AS A RESULT, MEDIA-CHECK WOULD +; NORMALLY RETURN I-DON'T-KNOW, THE DOS WOULD CONTINUALLY REREAD THE FAT, AND +; DISCARD CACHED DATA. WE OPTIMIZE THIS BY IMPLEMENTING A LOGICAL DOOR- +; LATCH: IT IS PHYSICALLY IMPOSSIBLE TO CHANGE A DISK IN UNDER 2 SECONDS. WE +; RETAIN THE TIME OF THE LAST SUCCESSFUL DISK OPERATION AND COMPARE IT WITH +; THE CURRENT TIME DURING MEDIA-CHECK. IF < 2 SECONDS AND AT LEAST 1 TIMER +; TICK HAS PASSED, THE WE SAY NO CHANGE. IF > 2 SECONDS THEN WE SAY I- +; DON'T-KNOW. FINALLY, SINCE WE CANNOT TRUST THE TIMER TO BE ALWAYS +; AVAILABLE, WE RECORD THE NUMBER OF MEDIA CHECKS THAT HAVE OCCURRED WHEN NO +; APPARENT TIME HAS ELAPSED. WHILE THIS NUMBER IS < A GIVEN THRESHOLD, WE SAY +; NO CHANGE. WHEN IT EXCEEDS THAT THRESHOLD, WE SAY I-DON'T-KNOW AND RESET +; THE COUNTER TO 0. WHEN WE STORE THE TIME OF LAST SUCCESSFUL ACCESS, IF WE +; SEE THAT TIME HAS PASSED TOO, WE RESET THE COUNTER. +; +ACCESSMAX = 5 +; +; DUE TO VARIOUS BOGOSITIES, WE NEED TO CONTINUALLY ADJUST WHAT THE HEAD +; SETTLE TIME IS. THE FOLLOWING ALGORITHM IS USED: +; +; GET THE CURRENT HEAD SETTLE VALUE. +; IF IT IS 0, THEN +; SET SLOW = 15 +; ELSE +; SET SLOW = VALUE +; ... +;********************************************* +;************ OLD ALGORITHM ****************** +;* IF WE ARE SEEKING AND WRITING THEN +;* USE SLOW +;* ELSE +;* USE FAST +;********************************************* +;*********** IBM'S REQUESTED LOGIC *********** +; IF WE ARE SEEKING AND WRITING AND NOT ON AN AT THEN +; USE SLOW +; ELSE +; USE FAST +; ... +; RESTORE CURRENT HEAD SETTLE VALUE +; + +Set_ID_Flag db 0 ;AN000; If 1, GETBP routine will set the + ;Vol_Serial and FileSys_ID in BDS table + ;from the media Boot record, if it is > DOS 4.00 + ;formatted one. Then Set_ID_flag will be set to 2 + ;to signal that volume_label is set from the extended + ;boot record and do not set it from the root + ;directory as done in SET_VOLUME_ID routine. + ;For the old version, Vol_Serial + ;will be set to -1, and FileSys_ID will be set + ;to "FAT12 " if it is a floppy. + + public Fat_12_ID +Fat_12_ID DB "FAT12 ",0 ;AN000; Default System ID for floppy. + public Fat_16_ID +Fat_16_ID DB "FAT16 ",0 ;AN000; + public Vol_No_Name +Vol_No_Name db "NO NAME ",0 ;AN000; + public Temp_H +Temp_H dw 0 ;AN000; Temporary for 32 bit calculation. + + public Start_Sec_H +Start_Sec_H dw 0 ;AN000; Starting sector number high word. + ;Used as an input to DISKIO subroutine. +Saved_Word dw 0 ;AN000; Tempory saving place for a word. + +;--------------------------------------- +;J.K. 6/29/87 For Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + public MulTrk_Flag +MulTrk_Flag dw 0 ;AN001; +;J.K. 6/29/87 End of Multi-track definition. +;--------------------------------------------------------------------- + public EC35_Flag +EC35_Flag db 0 ; flags for electrically compatible 3.5 inch disk drives (mrw 4/88) +;--------------------------------------------------------------------- +VRetry_Cnt dw 0 ;AN003; +Soft_ECC_Cnt dw 0 ;AN003; +;--------------------------------------------------------------------- +MultiTrk_Format_Flag db 0 ;AN007;Testing. If 1, then Multi track format request +;--------------------------------------------------------------------- +; +; IF ID IS F9, HAVE A 96TPI DISK ELSE +; IF BIT 2 IS 0 THEN MEDIA IS NOT REMOVABLE AND COULD NOT HAVE CHANGED +; OTHERWISE IF WITHIN 2 SECS OF LAST DISK OPERATION MEDIA COULD NOT +; HAVE CHANGED, OTHERWISE DONT KNOW IF MEDIA HAS CHANGED +; + PUBLIC MEDIA$CHK +MEDIA$CHK PROC NEAR + MESSAGE FTESTDISK,<"DISK MEDIA CHECK "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, + CALL SETDRIVE + + cmp cs:Secrete_Code, 'jk' ;J.K.11/7/86 Secrete code for DOS 3.3 IBMBIO. + jne media$done ;J.K.11/7/86 + +; FOR NON-REMOVABLE DISKS ONLY RETURN CHANGED IF CHANGED BY FORMAT, OTHERWISE +; RETURN 'NOT CHANGED'. + MOV SI,1 ; ASSUME NO CHANGE + TEST WORD PTR [DI].FLAGS,FCHANGED_BY_FORMAT + JZ WEARENOTFAKINGIT + AND WORD PTR [DI].FLAGS,NOT FCHANGED_BY_FORMAT ; RESET FLAG +; IF MEDIA HAS BEEN CHANGED BY FORMAT, WE MUST ASK THE ROM. CANNOT RELY ON THE +; 2 SECOND TIME CHECK. + MOV CS:[TIM_DRV],-1 ; ENSURE THAT WE ASK THE ROM IF MEDIA + ; HAS CHANGED + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JZ WEHAVEAFLOPPY + MOV SI,-1 ; INDICATE MEDIA CHANGED + JMP SHORT MEDIA$DONE +; +; WE NEED TO RETURN 'NOT CHANGED' IF WE HAVE A HARD FILE. +; +WEARENOTFAKINGIT: + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ MEDIA$DONE +WEHAVEAFLOPPY: + XOR SI,SI ; PRESUME "I DON'T KNOW" +; +; IF WE HAVE A FLOPPY WITH CHANGELINE SUPPORT, WE ASK THE ROM TO DETERMINE IF +; MEDIA HAS CHANGED. WE DO NOT PERFORM THE 2 SECOND CHECK FOR THESE DRIVES. +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC MEDIA_PATCH ;| +MEDIA_PATCH: ;| + CALL MEDIACHECK ;| + JC ERR$EXITJ ;| + CALL HASCHANGE ;| + JNZ MEDIA$DONE ;| +;----------------------------------------| +; IF WE COME HERE, WE HAVE A FLOPPY WITH NO CHANGELINE SUPPORT + MOV SI,1 ; PRESUME NO CHANGE + MOV AL,CS:[TIM_DRV] ; LAST DRIVE ACCESSED + CMP AL,BYTE PTR [DI].DRIVENUM ;IS DRIVE OF LAST ACCESS THE SAME? + JNZ MEDIA$UNK ; NO, THEN "I DON'T KNOW" +; +; CHECK TO SEE IF THIS DRIVE HAS BEEN ACCESSED IN THE LAST 2 SECONDS. + CALL CHECK_TIME_OF_ACCESS ; SETS SI CORRECTLY + JMP SHORT MEDIA$DONE + +MEDIA$UNK: + DEC SI ; RETURN "I DON'T KNOW" +; +; SI NOW CONTAINS THE CORRECT VALUE FOR MEDIA CHANGE. CLEAN UP THE LEFT OVERS +; +MEDIA$DONE: + LES BX,CS:[PTRSAV] ; GET ORIGINAL PACKET + MOV WORD PTR ES:[BX].TRANS,SI + OR SI,SI + JS INIT_PATCH + JMP EXIT +MEDIA$CHK ENDP +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC INIT_PATCH ;| +INIT_PATCH PROC NEAR ;| + CALL MEDIA_SET_VID ;| +;----------------------------------------| + MOV CS:[TIM_DRV],-1 ; MAKE SURE WE ASK ROM FOR MEDIA CHECK +VOLIDOK: + JMP EXIT +INIT_PATCH ENDP + +ERR$EXITJ PROC NEAR + + MESSAGE FTESTCOM,<"ERR$EXITJ: "> + MNUM FTESTCOM,AX + MESSAGE FTESTCOM,<" == "> + CALL MAPERROR + MNUM FTESTCOM,AX + MESSAGE FTESTCOM, + JMP ERR$EXIT +ERR$EXITJ ENDP + +; +; PERFORM A CHECK ON THE TIME PASSED SINCE THE LAST ACCESS FOR THIS PHYSICEL +; DRIVE. +; WE ARE ACCESSING THE SAME DRIVE. IF THE TIME OF LAST SUCCESSFUL ACCESS WAS +; LESS THAN 2 SECONDS AGO, THEN WE MAY PRESUME THAT THE DISK WAS NOT CHANGED. +; RETURNS IN SI: +; 0 - IF TIME OF LAST ACCESS WAS >= 2 SECONDS +; 1 - IF TIME WAS < 2 SECONDS (I.E NO MEDIA CHANGE ASSUMED) +; REGISTERS AFFECTED AX,CX,DX, FLAGS. +; +CHECK_TIME_OF_ACCESS PROC NEAR + PUBLIC CHECK_TIME_OF_ACCESS + + MOV SI,1 ; PRESUME NO CHANGE. +;SB33014************************************************************* + xor AH,AH ; set command to read time + int 1Ah ; call rom-bios clock routine +;SB33014************************************************************* +; +; NOW THAT WE ARE READING THE TIME, WE MUST MAKE SURE THAT WE DO NOT LOSE A +; DATE WRAP. THE ROM WILL RETURN THE VALUE ONLY ONCE, SO WE NEED TO NOTE THIS +; FACT. +; + SHR AL,1 + ADC CS:[DAYCNT],0 ; ADD IT IN TO OUR REMEMBERED DAY COUNT +; +; COMPUTE ELAPSED TIME +; + MOV AX,WORD PTR DS:[DI].TIM_LO ; GET STORED TIME + SUB DX,AX + MOV AX,WORD PTR DS:[DI].TIM_HI + SBB CX,AX +; +; CX:DX IS THE ELAPSED TIME +; + JNZ TIMECHECK_UNK ; CX <> 0 => > 1 HOUR + OR DX,DX ; TIME MUST PASS + JNZ TIMEPASSED ; YES, EXAMINE MAX VALUE +; +; NO NOTICEABLE TIME HAS PASSED. WE CANNOT TRUST THE COUNTER TO BE ALWAYS +; AVAILABLE AS THERE ARE BOGUS PROGRAMS THAT GO AND REPROGRAM THE THING. WE +; KEEP A COUNT OF THE NUMBER OF MEDIA CHECKS THAT WE'VE SEEN THAT DO NOT HAVE +; ANY TIME PASSING. IF WE EXCEED A GIVE THRESHOLD, WE GIVE UP ON THE TIMER. +; + INC BYTE PTR CS:ACCESSCOUNT + CMP BYTE PTR CS:ACCESSCOUNT,ACCESSMAX + JB TIMECHECK_RET ; IF COUNT IS LESS THAN THRESHOLD, OK + DEC BYTE PTR CS:ACCESSCOUNT ; DON'T LET THE COUNT WRAP + JMP SHORT TIMECHECK_UNK ; "I DON'T KNOW" IF MEDIA CHANGED +; +; 18.2 TICS PER SECOND. +; +TIMEPASSED: + CMP DX,18 * 2 ; MIN ELAPSED TIME? + JBE TIMECHECK_RET ; YES, PRESUME NO CHANGE +; +; EVERYTHING INDICATES THAT WE DO NOT KNOW WHAT HAS HAPPENED. +; +TIMECHECK_UNK: + DEC SI ; PRESUME I DON'T KNOW +TIMECHECK_RET: + RET +CHECK_TIME_OF_ACCESS ENDP + +ERR$EXITJ2: JMP ERR$EXITJ +; +; BUILD A VALID BPB FOR THE DISK IN THE DRIVE. +; + PUBLIC GET$BPB +GET$BPB PROC NEAR + MESSAGE FTESTDISK,<"DISK BUILD BPB "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, + MOV AH,BYTE PTR ES:[DI] ;GET FAT ID BYTE READ BY DOS + CALL SETDRIVE ; GET THE CORRECT BDS FOR THE DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ ALREADY_GOTBPB ; NO NEED TO BUILD FOR FIXED DISKS +;J.K. Let's set the default value for VOLID,Vol_Serial,FileSys_ID in BDS table + call Clear_IDs ;AN000; + mov cs:[Set_ID_Flag],1 ;AN000; Indicate to set system id in BDS + CALL GETBP ;BUILD A BPB IF NECESSARY. + JC ERR$EXITJ2 ;AN000; If error, Set_ID_flag is set to 0 already. + cmp cs:[Set_ID_Flag],2 ;AN000; Already, volume_Label set from Boot record + mov cs:[Set_ID_Flag],0 ;AN000; to BDS table? + je Already_GotBPB ;AN000; Then do not set it again from Root directory. + ;AN000; Otherwise, conventional Boot record. +GET$BPB ENDP +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC SET_PATCH ;| +SET_PATCH PROC NEAR ;| + CALL SET_VOLUME_ID ;| +;----------------------------------------| + MESSAGE FTESTDISK,<"SET VOLUME ID"> + MNUM FTESTDISK,DI + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DS + MESSAGE FTESTDISK, + +ALREADY_GOTBPB: + ADD DI,BYTEPERSEC ; RETURN THE BPB THAT IS IN THE CURRENT BDS + + PUBLIC SETPTRSAV +SETPTRSAV: ; RETURN POINT FOR DSK$INIT + LES BX,CS:[PTRSAV] + MOV ES:[BX].MEDIA,AH + MOV ES:[BX].COUNT,DI + MOV ES:[BX].COUNT+2,DS + JMP EXIT +SET_PATCH ENDP + +;J.K. Clear IDs in BDS table. Only applied for Floppies. +;Input: DS:DI -> BDS table +;Output: VOLID set to "NO NAME " +; VOL_SERIAL set to 0. +; FileSys_ID set to "FAT12 " or "FAT16 " +; depending on the flag FATSIZE in BDS. +;All registers saved. + public Clear_IDs +Clear_IDs proc near ;AN000; + push ds ;AN000; + push di ;AN000; + push es ;AN000; + push si ;AN000; + push cx ;AN000; + + push ds ;AN000; + pop es ;AN000; es -> bds + push cs ;AN000; + pop ds ;AN000; ds = cs + + mov cx, 0 ;AN000; no serial number + mov word ptr es:[di.VOL_SERIAL],cx ;AN000; + mov word ptr es:[di.VOL_SERIAL]+2,cx ;AN000; + + mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000; =11 + mov si, offset VOL_NO_NAME ;AN000; + push di ;AN000; save BDS pointer + add di, VOLID ;AN000; points to VOLID field + rep movsb ;AN000; + pop di ;AN000; restore BDS pointer + test es:[di.FATSIZ], FBIG ;AN000; + jnz CI_BigFat ;AN000; small fat + mov si, offset FAT_12_ID ;AN000; + jmp CI_Filesys ;AN000; +CI_BigFat: ;AN000; + mov si, offset FAT_16_ID ;AN000; big fat +CI_Filesys: ;AN000; + mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8 + add di, FILESYS_ID ;AN000; points to FILESYS_ID field + rep movsb ;AN000; + + pop cx ;AN000; + pop si ;AN000; + pop es ;AN000; + pop di ;AN000; + pop ds ;AN000; + ret ;AN000; +Clear_IDs endp ;AN000; + + +; GETBP - RETURN BPB FROM THE DRIVE SPECIFIED BY THE BDS. +; IF THE RETURN_FAKE_BPB FLAG IS SET, THEN IT DOES NOTHING. +; NOTE THAT WE NEVER COME HERE FOR FIXED DISKS. +; FOR ALL OTHER CASES, +; - IT READS BOOT SECTOR TO PULL OUT THE BPB +; - IF NO VALID BPB IS FOUND, IT THEN READS THE FAT SECTOR, +; TO GET THE FAT ID BYTE TO BUILD THE BPB FROM THERE. +; +; INPUTS: DS:DI POINT TO CORRECT BDS. +; +; OUTPUTS: FILLS IN BPB IN CURRENT BDS IF VALID BPB OR FAT ID ON DISK. +; CARRY SET, AND AL=7 IF INVALID DISK. +; CARRY SET AND ERROR CODE IN AL IF OTHER ERROR. +; If failed to recognize the Boot Record, then will set the +; Set_ID_Flag to 0. +; J.K. This routine will only work for a floppy diskette. +; For a fixed disk, it will just return. + + PUBLIC GETBP +GETBP PROC NEAR +; IF RETURNING FAKE BPB THEN RETURN BPB AS IS. + TEST WORD PTR [DI].FLAGS,RETURN_FAKE_BPB OR FNON_REMOVABLE + JZ GETBP1 + JMP GETRET_EXIT + +GETBP1: + MESSAGE FTESTDISK,<"BUILDING BPB FROM SCRATCH",CR,LF> + SAVEREG +; +; ATTEMPT TO READ IN BOOT SECTOR AND DETERMINE BPB. +; WE ASSUME THAT THE 2.X AND GREATER DOS DISKS ALL HAVE A VALID BOOT SECTOR. +; +RDBOOT: + CALL READBOOTSEC + JC GETBP_ERR_RET_brdg ; CARRY SET IF THERE WAS ERROR. + CMP BX,0 ; BX IS 0 IF BOOT SECTOR IS VALID. + JNZ DOFATBPB + + CALL MOVBPB ; MOVE BPB INTO REGISTERS. + JMP HAS1 + +Getbp_err_ret_brdg: jmp Getbp_err_ret +; +; WE HAVE A 1.X DISKETTE. +; IN THIS CASE READ IN THE FAT ID BYTE AND FILL IN BPB FROM THERE. +; +DOFATBPB: + CALL READFAT ; PUTS MEDIA DESCRIPTOR BYTE IN AH + JC GETBP_ERR_RET_Brdg +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC GETBP1_PATCH ;| +GETBP1_PATCH: ;| + CALL HIDENSITY ;| +;----------------------------------------| +;TEST FOR A VALID 3.5" MEDIUM + CMP [DI].FORMFACTOR,FFSMALL + JNZ IS_FLOPPY + CMP AH,0F9H ; IS IT A VALID FAT ID BYTE FOR 3.5" ? + JNZ GOT_UNKNOWN_MEDIUM + MOV BX,OFFSET SM92 ; POINTER TO CORRECT BPB + PUSH CS + POP ES + + ASSUME ES:CODE +;J.K. DS points to segment of BDS. The following should be modified +;J.K. to get spf,csec,spa,spt correctly. It had been wrong if DRIVER.SYS +;J.K. is loaded since the BDS is inside the driver.sys. + MOV AL,es:[BX.SPF] + MOV CX,es:[BX.CSEC] + MOV DX,WORD PTR es:[BX.SPA] + MOV BX,WORD PTR es:[BX.SPT] + JMP SHORT HAS1 +; MUST BE A 5.25" FLOPPY IF WE COME HERE +IS_FLOPPY: + MOV CL,AH ;SAVE MEDIA + AND CL,0F8H ;NORMALIZE + CMP CL,0F8H ;COMPARE WITH GOOD MEDIA BYTE + JNZ GOT_UNKNOWN_MEDIUM + +GOODID: + MOV AL,1 ;SET NUMBER OF FAT SECTORS + MOV BX,64*256+8 ;SET DIR ENTRIES AND SECTOR MAX + MOV CX,40*8 ;SET SIZE OF DRIVE + MOV DX,01*256+1 ;SET HEAD LIMIT AND SEC/ALL UNIT + TEST AH,00000010B ;TEST FOR 8 OR 9 SECTOR + JNZ HAS8 ;NZ = HAS 8 SECTORS + INC AL ;INC NUMBER OF FAT SECTORS + INC BL ;INC SECTOR MAX + ADD CX,40 ;INCREASE SIZE +HAS8: + TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS + JZ HAS1 ;Z = 1 HEAD + ADD CX,CX ;DOUBLE SIZE OF DISK + MOV BH,112 ;INCREASE NUMBER OF DIRECTORY ENTRIES + INC DH ;INC SEC/ALL UNIT + INC DL ;INC HEAD LIMIT + +HAS1: + PUBLIC HAS1 + + MOV BYTE PTR DS:[DI].SECPERCLUS,DH + MOV BYTE PTR DS:[DI].CDIR,BH + MOV WORD PTR DS:[DI].DRVLIM,CX + MOV BYTE PTR DS:[DI].MEDIAD,AH + MOV BYTE PTR DS:[DI].CSECFAT,AL + MOV BYTE PTR DS:[DI].SECLIM,BL + MOV BYTE PTR DS:[DI].HDLIM,DL +;SB34DISK001******************************************************************* +;SB the HIDSEC_H field and DRVLIM_L field and the +;SB DRVLIM_H fields need to be set to 0 since this code here is for floppies +;SB 3 LOCS + + mov word ptr ds:[di].HIDSEC_H,0 + mov word ptr ds:[di].HIDSEC_L,0 + mov word ptr ds:[di].DRVLIM_H,0 + +;SB34DISK001******************************************************************* +GETRET: + POP BX + RESTOREREG + + ASSUME ES:NOTHING + +GETRET_EXIT: + RET + +GETBP_ERR_RET: +;J.K. Before doing anything else, set Set_ID_Flag to 0. + mov cs:Set_ID_Flag, 0 ;AN000; + CALL MAPERROR + JMP SHORT GETRET +; +; WE HAVE A 3.5" DISKETTE FOR WHICH WE CANNOT BUILD A BPB. WE DO NOT ASSUME ANY +; TYPE OF BPB FOR THIS MEDIUM. +; +GOT_UNKNOWN_MEDIUM: + mov cs:Set_ID_Flag, 0 ;AN000; + MOV AL,ERROR_UNKNOWN_MEDIA + STC + JMP SHORT GETRET +GETBP ENDP + +BPBTYPE STRUC +SPF DB ? +SPT DB ? +CDIRE DB ? +CSEC DW ? +SPA DB ? +CHEAD DB ? +BPBTYPE ENDS + +; +; READ IN THE BOOT SECTOR. SET CARRY IF ERROR IN READING SECTOR. +; BX IS SET TO 1 IF THE BOOT SECTOR IS INVALID, OTHERWISE IT IS 0. +; +READBOOTSEC PROC NEAR + MOV DH,0 ;HEAD 0 + MOV CX,0001 ;CYLINDER 0, SECTOR 1 + CALL READ_SECTOR + JC ERR_RET + XOR BX,BX ; ASSUME VALID BOOT SECTOR. + +;******************************************************************************* +; PUT A SANITY CHECK FOR THE BOOT SECTOR IN HERE TO DETECT BOOT SECTORS THAT +; DO NOT HAVE VALID BPBS. +; WE EXAMINE THE FIRST TWO BYTES - THEY MUST CONTAIN A LONG JUMP (69H) OR A +; SHORT JUMP (EBH) FOLLOWED BY A NOP (90H), OR A SHORT JUMP (E9H). +; IF THIS TEST IS PASSED, WE FURTHER CHECK BY EXAMINING THE SIGNATURE AT +; THE END OF THE BOOT SECTOR FOR THE WORD AA55H. +; IF THE SIGNATURE IS NOT PRESENT, WE EXAMINE THE MEDIA DESCRIPTOR BYTE TO +; SEE IF IT IS VALID. +;J.K. 10/15/86 DCR00012. For DOS 3.3, this logic is modified a little bit. +; We are not going to check Signature. Instead we are going to sanity +; check the media byte in BPB regardless of the validity of signature. +; This is to save the already developed commercial products that have +; good jump instruction and signature but with the false BPB informations +; that will crash the diskette drive operation. (For example, Symphony diskette). +;****************************************************************************** + CMP BYTE PTR CS:[DISKSECTOR],069H ; IS IT A DIRECT JUMP? + JE Check_bpb_MediaByte ; DON'T NEED TO FIND A NOP + CMP BYTE PTR CS:[DISKSECTOR],0E9H ; DOS 2.0 JUMP? + JE Check_bpb_MediaByte ; NO NEED FOR NOP + CMP BYTE PTR CS:[DISKSECTOR],0EBH ; HOW ABOUT A SHORT JUMP. + JNE INVALIDBOOTSEC + CMP BYTE PTR CS:[DISKSECTOR]+2,090H ; IS NEXT ONE A NOP? + JNE INVALIDBOOTSEC + + +;J.K. 10/15/86 Don't have to perform the following signature check since +; we need to check the media byte even with the good signatured diskette. +;CHECK_SIGNATURE: +; CMP WORD PTR CS:[DISKSECTOR+1FEH],0AA55H ; SEE IF NON-IBM DISK OR 1.X +; ; MEDIA. +; JZ CHECKSINGLESIDED ; GO SEE IF SINGLE SIDED MEDIUM. MAY +; ; NEED SOME SPECIAL HANDLING +; +; CHECK FOR NON-IBM DISKS WHICH DO NOT HAVE THE SIGNATURE AA55 AT THE +; END OF THE BOOT SECTOR, BUT STILL HAVE A VALID BOOT SECTOR. THIS IS DONE +; BY EXAMINING THE MEDIA DESCRIPTOR IN THE BOOT SECTOR. +; + +Check_bpb_MediaByte: + + MOV AL,BYTE PTR CS:MEDIABYTE + AND AL,0F0H + CMP AL,0F0H ; ALLOW FOR STRANGE MEDIA + JNZ INVALIDBOOTSEC +; +; THERE WERE SOME (APPARENTLY A LOT OF THEM) DISKETTES THAT HAD BEEN FORMATTED +; UNDER DOS 3.1 AND EARLIER VERSIONS WHICH HAVE INVALID BPBS IN THEIR BOOT +; SECTORS. THESE ARE SPECIFICALLY DISKETTES THAT WERE FORMATTED IN DRIVES +; WITH ONE HEAD, OR WHOSE SIDE 0 WAS BAD. THESE CONTAIN BPBS IN THE BOOT +; SECTOR THAT HAVE THE SEC/CLUS FIELD SET TO 2 INSTEAD OF 1, AS IS STANDARD +; IN DOS. IN ORDER TO SUPPORT THEM, WE HAVE TO INTRODUCE A "HACK" THAT WILL +; HELP OUR BUILD BPB ROUTINE TO RECOGNISE THESE SPECIFIC CASES, AND TO +; SET UP OUT COPY OF THE BPB ACCORDINGLY. +; WE DO THIS BY CHECKING TO SEE IF THE BOOT SECTOR IS OFF A DISKETTE THAT +; IS SINGLE-SIDED AND IS A PRE-DOS 3.20 DISKETTE. IF IT IS, WE SET THE +; SEC/CLUS FIELD TO 1. IF NOT, WE CARRY ON AS NORMAL. +CHECKSINGLESIDED: + MOV AL,BYTE PTR CS:MEDIABYTE + TEST AL,0001H ; IS LOW BIT SET? - INDICATES DOUBLE SIDED + JNZ GOODDSK + CMP WORD PTR CS:[DISKSECTOR+8],"." SHL 8 + "3" + JNZ MUSTBEEARLIER + CMP BYTE PTR CS:[DISKSECTOR+10],"2" + JAE GOODDSK + +; WE MUST HAVE A PRE-3.20 DISKETTE. SET THE SEC/CLUS FIELD TO 1 +MUSTBEEARLIER: + MOV BYTE PTR CS:[SECPERCLUSINSECTOR],1 + JMP SHORT GOODDSK +;****************************************************************************** + +INVALIDBOOTSEC: + INC BX ; INDICATE THAT BOOT SECTOR INVALID +GOODDSK: ; CARRY ALREADY RESET + CLC + RET + +ERR_RET: ; CARRY IS ALREADY SET ON ENTRY HERE + MESSAGE FTESTDISK,<"ERROR IN READBOOT",CR,LF> + RET +READBOOTSEC ENDP + +; MOVES THE BPB READ FROM THE BOOT SECTOR INTO REGISTERS FOR USE BY +; GETBP ROUTINE AT HAS1 +;J.K.- +; If the Set_ID_Flag is 1, and if an extended Boot Record, then set Volume +; Serial Number, Volume Label, File System ID in BDS according to +; the BOOT reocrd. After that, this routine will set the Set_ID_Flag to 2 +; to signal that VOLUME Label is set already from the Extended BOOT record +; (so, don't set it again by calling "SET_VOLUME_ID" routine which uses +; the volume label in the root directory. + +MOVBPB PROC NEAR + SAVEREG + PUSH CS + POP DS + MOV DI,OFFSET BPB_IN_SECTOR + MOV DH,BYTE PTR [DI].SECALL ;SECTORS PER UNIT + MOV BH,BYTE PTR [DI].DIRNUM ;NUMBER OF DIRECTORY ENTRIES + MOV CX,WORD PTR [DI].SECNUM ;SIZE OF DRIVE + MOV AH,BYTE PTR [DI].FATID ;MEDIA DESCRIPTOR + MOV AL,BYTE PTR [DI].FATSIZE ;NUMBER OF FAT SECTORS + MOV BL,BYTE PTR [DI].SLIM ;SECTORS PER TRACK + MOV DL,BYTE PTR [DI].HLIM ;NUMBER OF HEADS + RESTOREREG + cmp cs:[Set_ID_Flag], 1 ;AC008 called by GET$BPB? + jne MovBPB_Ret ;AC008 + call Mov_Media_IDs ;AC008 + jc MovBPB_Conv ;AC008 Conventional boot record? + mov cs:[Set_ID_Flag],2 ;AC008 signals that Volume ID is set. +MovBPB_Conv: ;AC008 + cmp cs:fHave96, 1 ;AC008 + jne MovBPB_Ret ;AC008 + call ResetChanged ;AC008 Reset Flags in BDS to NOT fCHANGED. +MovBPB_Ret: ;AC008 + clc ;AC008 + ret ;AC008 +MOVBPB ENDP ;AC008 + + +; + public Mov_Media_IDs +Mov_Media_IDs Proc near ;AN000; +;copy the boot_serial number, Volume id, and Filesystem id from the +;***Extended Boot record*** in cs:DiskSector to the BDS table pointed +;by DS:DI. +;In.) DS:DI -> BDS +; CS:DiskSector = Valid extended boot record. +;Out.) Vol_Serial, Volid and System_Id in BDS are set according to +; the boot record information. +; Carry flag set if not an extended BPB. +; All registers saved except the flag. + + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN000; = 41 + jne MMI_Not_Ext ;AN000; + push cx ;AN000; + mov cx, cs:[Boot_Serial_L] ;AN000; + mov word ptr ds:[di.VOL_SERIAL],cx ;AN000; + mov cx, cs:[Boot_Serial_H] ;AN000; + mov word ptr ds:[di.VOL_SERIAL+2],cx ;AN000; + push ds ;AN000; Save regs. + push di ;AN000; + push es ;AN000; + push si ;AN000; + + push ds ;AN000; ds-> cs, es-> bds + pop es ;AN000; + push cs ;AN000; + pop ds ;AN000; + + mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000; + mov si, offset Boot_Volume_Label;AN000; + push di + add di, VOLID ;AN000; + rep movsb ;AN000; + pop di + mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8 + mov si, offset Boot_System_ID ;AN000; + add di, FILESYS_ID ;AN000; + rep movsb ;AN000; + + pop si ;AN000; + pop es ;AN000; + pop di ;AN000; + pop ds ;AN000; + pop cx ;AN000; + clc ;AN000; +MMI_Ret: ;AN000; + ret ;AN000; +MMI_Not_Ext: ;AN000; + stc ;AN000; + ret ;AN000; +Mov_Media_IDs endp ;AN000; + + +; READ IN THE FAT SECTOR AND GET THE MEDIA BYTE FROM IT. +; INPUT : AL CONTAINS LOGICAL DRIVE. +; OUTPUT: +; CARRY SET IF AN ERROR OCCURS, AX CONTAINS ERROR CODE. +; OTHERWISE, AH CONTAINS MEDIA BYTE ON EXIT. AL IS PRESERVED. + +READFAT PROC NEAR + PUSH AX ; PRESERVE LOGICAL DRIVE IN AL + MOV DH,0 ; HEAD 0 + MOV CX,0002 ; CYLINDER 0, SECTOR 2 + CALL READ_SECTOR ; CS:BX POINTS TO FAT SECTOR + JC BAD_FAT_RET + POP AX ; RESET LOGICAL DRIVE + MOV AH,BYTE PTR CS:[BX] ; MEDIA BYTE + RET + +BAD_FAT_RET: ; CARRY SET ON ENTRY + MESSAGE FTESTDISK,<"ERROR IN FAT READ",CR,LF> + POP CX ; CLEAR STACK + RET +READFAT ENDP + +; READ A SINGLE SECTOR INTO THE TEMP BUFFER. +; PERFORM THREE RETRIES IN CASE OF ERROR. +; INPUTS: DRIVE HAS PHYSICAL DRIVE TO USE +; CX HAS SECTOR AND CYLINDER +; DH HAS HEAD +; OUTPUTS: CARRY CLEAR +; CS:BX POINT TO SECTOR +; CARRY SET +; AX HAS ROM ERROR CODE +; REGISTERS ES AND BP ARE PRESERVED. + +READ_SECTOR PROC NEAR + PUBLIC READ_SECTOR + + PUSH BP + MOV BP,3 ; MAKE 3 ATTEMPTS + PUSH ES +;SB33015***************************************************************** + mov DL, byte ptr ds:[di].DriveNum ;SB;3.30* + mov BX, offset DiskSector ; Get ES:BX to point to buffer ;SB;3.30* + push CS ; get the segment right ;SB;3.30* + pop ES ; now ES:BX is correct ;SB;3.30* +;SB33015***************************************************************** +RD_RET: +;SB33016***************************************************************** + mov AX, 0201h ; number of sectors to 1 (AL=1);SB;3.30* + int 13h ; call rom-bios disk routines ;SB;3.30* + +;SB33016***************************************************************** + JNC OKRET2 +Rd_rty: + CALL AGAIN ; RESET DISK, DECREMENT BP, PRESERVE AX + jz Err_RD_RET + test word ptr ds:[di].flags,fNon_Removable + JNZ RD_RET + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Rd_Skip1_DPT ;AN012; + push ds ;J.K. 11/7/86 For retry, set the head settle time + push ax ;to 0Fh. PTM845. + lds si,cs:DPT + mov al, ds:[si].disk_head_sttl + mov cs:[save_head_sttl],al + mov byte ptr ds:[si].disk_head_sttl, NormSettle + pop ax + pop ds +Rd_Skip1_DPT: ;AN012; +;SB33017***************************************************************** + ; SET CMD TO READ (AH=2) AND ;SB ;3.30 + MOV AX, 0201h ; NUM OF SECTORS TO 1 (AL=1) ;SB ;3.30 + INT 13h ; CALL ROM-BIOS DISK ROUTINES ;SB ;3.30 +;SB33017***************************************************************** + pushf ;AN012; + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Rd_Skip2_DPT ;AN012; + push ds + push ax + lds si,cs:DPT + mov al, cs:[save_head_sttl] + mov byte ptr ds:[si].disk_head_sttl, al + pop ax + pop ds +Rd_Skip2_DPT: ;AN012; + popf ;AN012; + jnc OKRET2 + jmp Rd_rty +ERR_RD_RET: + MOV DL,-1 ; MAKE SURE WE ASK ROM IF MEDIA HAS CHANGED + STC ; RETURN ERROR +; UPDATE INFORMATION PERTAINING TO LAST DRIVE ACCESSED, TIME OF ACCESS, LAST +; TRACK ACCESSED IN THAT DRIVE. +OKRET2: + MOV CS:[STEP_DRV],DL ; SET UP FOR HEAD SETTLE LOGIC IN DISK. + MOV CS:[TIM_DRV],DL ;SAVE DRIVE LAST ACCESSED + MOV BYTE PTR [DI].TRACK,CH ; SAVE LAST TRACK ACCESSED ON THIS DRIVE + PUSHF ; PRESERVE FLAGS IN CASE ERROR OCCURRED + CALL SET_TIM + POPF ; RESTORE FLAGS + POP ES + POP BP + RET +READ_SECTOR ENDP + +;----------------------------------------------------------- +; +; DISK REMOVABLE ROUTINE ARR 2.41 +; + +DSK$REM PROC NEAR ;ARR 2.41 + PUBLIC DSK$REM + + MESSAGE FTESTDISK,<"DISK REMOVABLE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS UNIT # + CALL SETDRIVE ; GET BDS FOR THIS DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ NON_REM + JMP EXIT + +NON_REM: + JMP BUS$EXIT ;ARR 2.41 +DSK$REM ENDP + +; SETDRIVE SCANS THROUGH THE DATA STRUCTURE OF BDSS, AND RETURNS A POINTER TO +; THE ONE THAT BELONGS TO THE DRIVE SPECIFIED. CARRY IS SET IF NONE EXISTS FOR +; THE DRIVE. +; IF THE BYTE [PHYS_DRV] IS 0 THEN +; ON ENTRY, AL CONTAINS THE LOGICAL DRIVE NUMBER. +; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR. + +; ELSE IF THE BYTE [PHYS_DRV] IS 1 THEN (ONLY USED FOR FIXED DISKS WHEN AN ECC +; ERROR OCCURS) +; ON ENTRY, DL CONTAINS THE PYHSICAL DRIVE NUMBER. +; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR. + + PUBLIC SETDRIVE +SETDRIVE PROC NEAR + MESSAGE FTESTDISK,<"SETDRIVE",CR,LF> + PUSH BX + PUSH CS + POP DS + ASSUME DS:CODE + +; ASSUME FIRST BDS IS IN THIS SEGMENT + MOV DI,WORD PTR START_BDS +SCAN_LOOP: + CMP BYTE PTR CS:[PHYS_DRV],1 ; DOES AL HAVE PHYSICAL DRIVE? + JB USE_LOGICAL_DRV + CMP BYTE PTR [DI].DRIVENUM,AL + JE SETDRV + JMP SHORT GET_NXT_BDS +USE_LOGICAL_DRV: + CMP BYTE PTR [DI].DRIVELET,AL + JE SETDRV +GET_NXT_BDS: + MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + ASSUME DS:NOTHING + + CMP DI,-1 + JNZ SCAN_LOOP + STC +SETDRV: + POP BX + RET +SETDRIVE ENDP + +;----------------------------------------------------------- +; +; DISK I/O ROUTINES +; + +DSK$WRITV PROC NEAR + PUBLIC DSK$WRITV + + MESSAGE FTESTDISK,<"DISK WRITE WITH VERIFY "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + MOV CS:[WRTVERIFY],103H + JMP SHORT DSK$CL + +DSK$WRIT: + PUBLIC DSK$WRIT + MESSAGE FTESTDISK,<"DISK WRITE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + MOV CS:[WRTVERIFY],ROMWRITE + +DSK$CL: + CALL DISKIO +DSK$IO: + JC DSKBAD + JMP EXIT +DSKBAD: + JMP ERR$CNT +DSK$WRITV ENDP + +DSK$READ PROC NEAR + PUBLIC DSK$READ + MESSAGE FTESTDISK,<"DISK READ "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + CALL DISKRD + JMP DSK$IO +DSK$READ ENDP + +; MISCELLANEOUS ODD JUMP ROUTINES. MOVED OUT OF MAINLINE FOR SPEED. + + +; IF WE HAVE A SYSTEM WHERE WE HAVE VIRTUAL DRIVES, WE NEED TO PROMPT THE +; USER TO PLACE THE CORRECT DISK IN THE DRIVE. + +CHECKSINGLE PROC NEAR + PUBLIC CHECKSINGLE + + PUSH AX + PUSH BX + MOV BX,WORD PTR DS:[DI].FLAGS + ; IF HARD DRIVE, CANNOT CHANGE DISK. + ; IF CURRENT OWNER OF PHYSICAL DRIVE, NO NEED TO CHANGE DISKETTE. + TEST BL,FNON_REMOVABLE OR FI_OWN_PHYSICAL + JNZ SINGLERET + TEST BL,FI_AM_MULT ; IS THERE A DRIVE SHARING THIS + ; PHYSICAL DRIVE? + JZ SINGLERET +; LOOK FOR THE PREVIOUS OWNER OF THIS PHYSICAL DRIVE AND RESET ITS OWNERSHIP +; FLAG. + MOV AL,DS:[DI].DRIVENUM ; GET PHYSICAL DRIVE NUMBER + PUSH DS ; PRESERVE POINTER TO CURRENT BDS + PUSH DI + PUSH CS + POP DS + ASSUME DS:CODE + + MOV DI,OFFSET START_BDS +SCAN_LIST: + MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + ASSUME DS:NOTHING + + CMP DI,-1 ; END OF LIST? + JZ SINGLE_ERR_RET ; MUST BE ERROR + CMP BYTE PTR [DI].DRIVENUM,AL + JNZ SCAN_LIST + +CHECK_OWN: + MOV BX,WORD PTR [DI].FLAGS + TEST BL,FI_OWN_PHYSICAL + JZ SCAN_LIST + XOR BL,FI_OWN_PHYSICAL ; RESET OWNERSHIP FLAG + MOV WORD PTR DS:[DI].FLAGS,BX + POP DI ; RESTORE POINTER TO CURRENT BDS + POP DS + XOR BX,BX + OR BL,FI_OWN_PHYSICAL ; ESTABLISH CURRENT BDS AS OWNER + OR WORD PTR [DI].FLAGS,BX + +; +; WE EXAMINE THE FSETOWNER FLAG. IF IT IS SET, THEN WE ARE USING THE CODE IN +; CHECKSINGLE TO JUST SET THE OWNER OF A DRIVE. WE MUST NOT ISSUE THE PROMPT +; IN THIS CASE. +; + CMP BYTE PTR CS:[FSETOWNER],1 + JZ SINGLERET +; TO SUPPORT "BACKWARD" COMPATIBILITY WITH IBM'S "SINGLE DRIVE STATUS BYTE" +; WE NOW CHECK TO SEE IF WE ARE IN A SINGLE DRIVE SYSTEM AND THE APPLICATION +; HAS "CLEVERLY" DIDDLED THE SDSB + CMP CS:[SINGLE],2 ; IF (SINGLE_DRIVE_SYSTEM) + JNE SHORT IGNORE_SDSB + + SAVEREG ; THEN + MOV AL,DS:[DI].DRIVELET ; IF (CURR_DRV == REQ_DRV) + MOV AH,AL + XOR DI,DI + MOV DS,DI + XCHG AL,DS:BYTE PTR LSTDRV ; THEN SWAP(CURR_DRV,REQ_DRV) + CMP AH,AL ; ELSE + RESTOREREG ; SWAP(CURR_DRV,REQ_DRV) + JE SINGLERET ; ISSUE SWAP_DSK_MSG + +IGNORE_SDSB: + CALL SWPDSK ; ASK USER FOR CORRECT DISK +SINGLERET: + POP BX + POP AX + RET + +SINGLE_ERR_RET: + STC + POP DI ; RESTORE CURRENT BDS + POP DS + JMP SHORT SINGLERET + +BADDRIVE: + MOV AL,8 ;Sector not found + jmp short BadDrive_Ret ;AN004;AN005;AN006; +UnformattedDrive: ;AN004;AN005;AN006; + mov al,7 ;AN004;Unknown media;AN005;AN006; +BadDrive_Ret: + STC +IORET: RET + +BOGUSSETTLE: + MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE + JMP GOTSLOWSETTLE +CHECKSINGLE ENDP +;------------------------------------------------------------ +; +; DISK I/O HANDLER +; +; AL = DRIVE NUMBER (0-6) +; AH = MEDIA DESCRIPTOR +; CX = SECTOR COUNT +; DX = FIRST SECTOR (low) +; [Start_Sec_H] = FIRST SECTOR (high) ;J.K. 32 bit calculation. +; DS = CS +; ES:DI = TRANSFER ADDRESS +; [RFLAG]=OPERATION (2=READ, 3=WRITE) +; [VERIFY]=1 FOR VERIFY AFTER WRITE +; +; IF SUCCESSFUL CARRY FLAG = 0 +; ELSE CF=1 AND AL CONTAINS ERROR CODE +; + PUBLIC DISKRD +DISKRD PROC NEAR + MOV CS:[RFLAG],ROMREAD + +DISKIO: + MOV BX,DI ; ES:BX = TRANSFER ADDRESS + CALL SETDRIVE ; MAP LOGICAL AND PHYSICAL + MOV AL,BYTE PTR DS:[DI].MEDIAD + MOV CS:MEDBYT,AL ; PRESERVE MEDIA BYTE FOR DRIVE FOR USE + ; IN DETERMINING MEDIA CHANGE. + JCXZ IORET +;SB34DISK006****************************************************************** +;SB See if the Media is formatted or not by checking the flags field in +;SB in the BDS. If it is unformatted we cannot allow I/O, so we should +;SB go to the error exit at label UnformattedDrive. 2LOCS + + test word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA + jnz UnformattedDrive +;SB34DISK006****************************************************************** + mov cs:[SECCNT],CX ;save sector count + MOV CS:[SPSAV],SP ; SAVE SP + +; ENSURE THAT WE ARE TRYING TO ACCESS VALID SECTORS ON THE DRIVE +; + + mov ax,dx ;AN000; save DX to AX + xor si,si ;AN000; + add dx,cx ;AN000; + adc si,0 ;AN000; + cmp [di].DrvLim, 0 ;AN000; Is this drive > 32 bit sector ? + je Sanity32 ;AN000; + cmp si,0 ;AN000; + jne BADDRIVE ;AN000; + cmp dx, [di].DrvLim ;AN000; + ja BADDRIVE ;AN000; + jmp short SanityOK ;AN000; +Sanity32: ;AN000; + add si, cs:[Start_Sec_H] ;AN000; + cmp si, [di].DrvLim_H ;AN000; + jb SanityOK ;AN000; + ja BADDRIVE ;AN000; + cmp dx, [di].DrvLim_L ;AN000; + ja BADDRIVE ;AN000; +SanityOK: ;AN000; + mov dx,cs:[Start_Sec_H] ;AN000; + add ax,word ptr [di].HIDSEC_L ;AN000; + adc dx,word ptr [di].Hidsec_H ;AN000; +;J.K. Now DX;AX have the physical first sector. +;Since the following procedures is going to destroy AX, let's +;save it temporarily to SAVED_WORD. + mov cs:[Saved_Word], ax ;AN000; Save the sector number (low) + +; MOV SI,DX +; ADD SI,CX +; ADD DX,WORD PTR [DI].HIDSEC ; ADD IN THE HIDDEN SECTORS +; CMP SI,WORD PTR [DI].DRVLIM ; COMPARE AGAINST DRIVE MAX +; JA BADDRIVE + +; SET UP POINTER TO DISK BASE TABLE IN [DPT]. WE CANNOT ASSUME THAT IOSETUP +; WILL DO IT BECAUSE WE WILL SKIP THE SET UP STUFF WITH HARD DISKS. + PUSH DS + XOR AX,AX + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR]; CURRENT DISK PARM TABLE + MOV WORD PTR CS:DPT,SI + MOV WORD PTR CS:DPT+2,DS + POP DS + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ SKIP_SETUP + CALL CHECKSINGLE +; +; CHECK TO SEE IF WE HAVE PREVIOUSLY NOTED A CHANGE LINE. THE ROUTINE +; RETURNS IF EVERYTHING IS OK. OTHERWISE, IT POPS OFF THE STACK AND RETURNS +; THE PROPER ERROR CODE. +; +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC DISKIO_PATCH ;| +DISKIO_PATCH: ;| + CALL CHECKLATCHIO ;| +;----------------------------------------| +; +; SET UP TABLES AND VARIABLES FOR I/O + CALL IOSETUP +; +; NOW THE SETTLE VALUES ARE CORRECT FOR THE FOLLOWING CODE +; +SKIP_SETUP: +;J.K. 32 bit sector calculation. +; DX;[Saved_Word] = starting sector number. + mov ax,dx ;AN000; + xor dx,dx ;AN000; + DIV WORD PTR [DI].SECLIM ;DIVIDE BY SEC PER TRACK + mov cs:[Temp_H],ax ;AN000; + mov ax, cs:[Saved_Word] ;AN000; Restore the lower word + div word ptr [di].SecLim ;AN000; +;Now, [Temp_H],AX = track #, DX = sector + INC DL ;Sector number is 1 based. + MOV CS:[CURSEC],DL ;SAVE CURRENT SECTOR + MOV CX,WORD PTR [DI].HDLIM ;GET NUMBER OF HEADS + + push ax ;AN000; + XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER + mov ax, cs:[Temp_H] ;AN000; + DIV CX + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + div cx ;AN000; +;Now, [Temp_H],AX = cyliner #, DX = head + cmp cs:[Temp_H],0 ;AN000; + ja BADDRIVE_brdg ;AN000; + cmp AX, 1024 ;AN000; 2**10 currently maxium for track #. + ja BADDRIVE_brdg ;AN000; + MOV CS:[CURHD],DL ;SAVE CURRENT HEAD + MOV CS:[CURTRK],AX ;SAVE CURRENT TRACK + +; +; WE ARE NOW SET UP FOR THE I/O. NORMALLY, WE CONSIDER THE DMA BOUNDARY +; VIOLATIONS HERE. NOT TRUE. WE PERFORM THE OPERATION AS IF EVERYTHING IS +; SYMMETRIC; LET THE INT 13 HANDLER WORRY ABOUT THE DMA VIOLATIONS. +; + MOV AX, CS:[SECCNT] + CALL BLOCK + CALL DONE + RET +DISKRD ENDP + +; +BADDRIVE_Brdg:jmp Baddrive +; + +; SET THE DRIVE-LAST-ACCESSED FLAG FOR DISKETTE ONLY. WE KNOW THAT THE HARD +; DISK WILL NOT BE REMOVED. +; DS:DI -> CURRENT BDS. +; AX,CX,SI ARE DESTROYED. +; + PUBLIC IOSETUP +IOSETUP PROC NEAR + MOV AL,[DI].DRIVENUM + MOV CS:[TIM_DRV],AL ; SAVE DRIVE LETTER +; +; DETERMINE PROPER HEAD SETTLE VALUES +; + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Skip_DPT_Setting ;AN012; + MOV CX,DS + LDS SI,DWORD PTR CS:[DPT] ; GET POINTER TO DISK BASE TABLE + MOV AL,CS:[EOT] + MOV [SI].DISK_EOT,AL ; BUMP FOR US + MOV AL,[SI].DISK_MOTOR_STRT ; PRESERVE OLD MOTOR START TIME + MOV CS:MOTORSTARTUP,AL +; +; FOR 3.5" DRIVES, BOTH EXTERNAL AS WELL AS ON THE K09, WE NEED TO SET THE +; MOTOR START TIME TO 4. THIS CHECKING FOR EVERY I/O IS GOING TO AFFECT +; PERFORMANCE ACROSS THE BOARD, BUT IS NECESSARY!! - RS +; + PUSH ES + MOV ES,CX ; ES:DI -> TO CURRENT BDS + CMP BYTE PTR ES:[DI].FORMFACTOR,FFSMALL + JNZ MOTOR_START_OK + MOV AL,4 + XCHG AL,[SI].DISK_MOTOR_STRT +MOTOR_START_OK: + POP ES +; +; DS:SI NOW POINTS TO DISK PARAMETER TABLE. GET CURRENT SETTLE AND SET FAST +; SETTLE +; + XOR AL,AL + INC AL ; IBM WANTS FAST SETTLE TO BE 1 - RS. + XCHG AL,[SI].DISK_HEAD_STTL ; GET SETTLE AND SET UP FOR FAST + MOV CS:SETTLECURRENT,AL + MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE +GOTSLOWSETTLE: + MOV DS,CX + MOV CS:SETTLESLOW,AL +Skip_DPT_Setting: ;AN012; + RET +; +; SET TIME OF LAST ACCESS, AND RESET DEFAULT VALUES IN THE DPT. +; +DONE: + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ RETZ ; DO NOT SET FOR NON-REMOVABLE MEDIA + CALL SET_TIM ; SET TIME OF LAST ACCESS FOR DRIVE +; +; RESTORE HEAD SETTLE AND EOT VALUES +; +DIDDLEBACK: + pushf ;AN013;Save flag + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne NoDiddleBack ;AN012; + PUSH AX + MOV DX,DS + MOV AL,CS:SETTLECURRENT + MOV AH,CS:MOTORSTARTUP + LDS SI,CS:DPT +; MOV [SI].DISK_EOT,9 ;J.K. 4/25/86. Should not change the EOT value + ;of diskbase to 9. This cause a problem + ;with 1.44M diskette in Polaris when the user + ;issue INT 13 with the default system + ;diskbase. + mov [si].DISK_EOT,9 ;J.K. 11/5/86. For compatibility reason, return + ;back to set it to 9 ( PTM826 ). + MOV [SI].DISK_HEAD_STTL,AL + MOV [SI].DISK_SECTOR_SIZ,2 + MOV [SI].DISK_MOTOR_STRT,AH + MOV DS,DX + POP AX +NoDiddleBack: ;AN013; + popf ;AN013;Restore flag +RETZ: + RET + +;READ THE NUMBER OF SECTORS SPECIFIED IN AX, HANDLING TRACK BOUNDARIES +;DS:DI -> BDS FOR THIS DRIVE +BLOCK: + OR AX,AX ;SEE IF ANY SECTORS TO READ + JZ RETZ +;Fixed disk will not be restricted to the track-by-track basis. -J.K.4/10/86 + test word ptr [di].Flags, fNon_Removable ;J.K. Fixed disk? + jz BLOCK_FLOPPY ;J.K. +;SB34DISK002***************************************************************** +;SB Check to see if multi track operation is allowed. If not +;SB we have to go to the block_floppy below to break up the operation. +;SB 2 LOCS + test word ptr CS:MulTrk_Flag, MulTrk_ON + jz BLOCK_FLOPPY +;SB34DISK002***************************************************************** + call DISK ;J.K. + xor ax,ax + RET ;J.K. +BLOCK_FLOPPY: ;J.K.4/10/86 +; +; READ AT MOST 1 TRACK WORTH. PERFORM MINIMIZATION AT SECTOR / TRACK +; + MOV CL,BYTE PTR [DI].SECLIM + INC CL + SUB CL,CS:CURSEC ; LEEAC 3.20 ADD SEGMENT OVERRIDE + XOR CH,CH + CMP AX,CX + JAE GOTMIN + MOV CX,AX +GOTMIN: +; +; AX IS THE REQUESTED NUMBER OF SECTORS TO READ +; CX IS THE NUMBER THAT WE CAN DO ON THIS TRACK +; + PUSH AX + PUSH CX + MOV AX,CX ; AL IS NUMBER OF SECTORS TO READ + CALL DISK + POP CX + POP AX +; +; CX IS THE NUMBER OF SECTORS JUST TRANSFERRED +; + SUB AX,CX ; REDUCE SECTORS-REMAINING BY LAST I/O + SHL CL,1 + ADD BH,CL ; ADJUST TRANSFER ADDRESS + JMP BLOCK +IOSETUP ENDP + +DskErr_Brdg: jmp DskErr ;AN003; + +; +;PERFORM DISK I/O WITH RETRIES +; AL = NUMBER OF SECTORS (1-8, ALL ON ONE TRACK) +; DI POINT TO DRIVE PARAMETERS +; ES:BX = TRANSFER ADDRESS (MUST NOT CROSS A 64K PHYSICAL BOUNDARY) +; [RFLAG] = 2 IF READ, 3 IF WRITE +; [VERIFY] = 0 FOR NORMAL, 1 FOR VERIFY AFTER WRITE + + PUBLIC DISK +DISK PROC NEAR + MOV BP,MAXERR ; SET UP RETRY COUNT + mov cs:VRetry_Cnt, BP ;AN003;Verify op. retry cnt for Write-Verify. + mov cs:Soft_ECC_Cnt, BP ;AN003;Soft ECC error retry count. + MOV AH,CS:RFLAG ;GET READ/WRITE INDICATOR + +RETRY: + PUSH AX + + MOV DX,CS:[CURTRK] ;LOAD CURRENT CYLINDER + + test word ptr [di].FLAGS, fNon_Removable ;Fixed disk? - J.K. 4/7/86 + jz DISK_NOT_MINI ;no, skip this. - J.K. 4/7/86 + cmp [di].IsMini, 1 ;Is this a mini disk? - J.K. 4/7/86 + jnz DISK_NOT_MINI ;No. continue to next.- J.K. 4/7/86 + add dx, [di].Hidden_Trks ;else add hidden trks.- J.K. 4/7/86 +DISK_NOT_MINI: ;J.K. 4/7/86 + ROR DH,1 + ROR DH,1 + + OR DH,CS:[CURSEC] + MOV CX,DX + XCHG CH,CL ; CL = SECTOR, CH = CYLINDER + MOV DH,BYTE PTR CS:[CURHD] ; LOAD CURRENT HEAD NUMBER AND + MOV DL,BYTE PTR [DI].DRIVENUM ; PHYSICAL DRIVE NUMBER + CMP BYTE PTR [DI].FORMFACTOR,FFHARDFILE + JZ DO_FAST ; HARD FILES USE FAST SPEED +; IF WE HAVE [STEP_DRV] SET TO -1, WE USE THE SLOW SETTLE TIME. +; THIS HELPS WHEN WE HAVE JUST DONE A RESED DISK OPERATION AND THE HEAD HAS +; BEEN MOVED TO ANOTHER CYLINDER - THE PROBLEM CROPS UP WITH 3.5" DRIVES. + CMP CS:[STEP_DRV],-1 + JZ DO_WRITEJ + CMP AH,ROMREAD ; ARR 2.20 + JE DO_FAST + CMP AH, ROMVERIFY + JE DO_FAST +DO_WRITEJ: +; READS ALWAYS FAST, UNLESS WE HAVE JUST DONE A DISK RESET OPERATION + JMP DO_WRITE ; ARR 2.20 READS ALWAYS FAST +DO_FAST: ; ARR 2.20 + CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE +TESTERR: ; MZ 2.21 + JC DSKERR_brdg +; SET DRIVE AND TRACK OF LAST ACCESS + MOV CS:[STEP_DRV],DL ; ARR 2.20 SET DRIVE + MOV BYTE PTR [DI].TRACK,CH ; ARR 2.20 SAVE TRACK +NO_SET: + CMP CS:WRTVERIFY,103H ; CHECK FOR WRITE AND VERIFY + JZ DOVERIFY +NOVERIFY: + POP AX + +;SB34DISK003***************************************************************** +;SB Check the flags word in the BDS to see if the drive is non removable +;SB If not we needn't do anything special +;SB If it is a hard disk then check to see if multi-track operation +;SB is specified. If specified we don't have to calculate for the next +;SB track since we are already done. So we can go to the exit of this +;SB routine. 5 LOCS + + test word ptr [di].FLAGS, fNON_REMOVABLE + jz ITS_REMOVABLE + test CS:MulTrk_Flag, MulTrk_ON + jnz DISK_RET +ITS_REMOVABLE: +;SB34DISK003***************************************************************** + AND CL,03FH ; ELIMINATE CYLINDER BITS FROM SECTOR + XOR AH,AH + SUB CS:[SECCNT],AX ; REDUCE COUNT OF SECTORS TO GO + ADD CL,AL ; NEXT SECTOR + MOV CS:[CURSEC],CL + CMP CL,BYTE PTR [DI].SECLIM ; SEE IF SECTOR/TRACK LIMIT REACHED + JBE DISK_RET +NEXTTRACK: + MOV CS:[CURSEC],1 ; START WITH FIRST SECTOR OF NEXT TRACK + MOV DH,CS:[CURHD] + INC DH + CMP DH,BYTE PTR [DI].HDLIM + JB NOXOR + XOR DH,DH + INC CS:[CURTRK] ;NEXT TRACK +NOXOR: + MOV CS:[CURHD],DH +DISK_RET: + CLC ; LEEAC + RET +DISK ENDP + + +; THE REQUEST IS FOR WRITE. DETERMINE IF WE ARE TALKING ABOUT THE SAME +; TRACK AND DRIVE. IF SO, USE THE FAST SPEED. + +DO_WRITE PROC NEAR + CMP DL,CS:[STEP_DRV] ; ARR 2.20 + JNZ DO_NORM ; WE HAVE CHANGED DRIVES + + CMP CH,BYTE PTR [DI].TRACK ; ARR 2.20 + JZ DO_FAST ; WE ARE STILL ON THE SAME TRACK + +DO_NORM: + CALL NORMSPEED + JMP SHORT TESTERR ; MZ 2.21 TEST FOR ERROR +DO_WRITE ENDP +; +; WE HAVE A VERIFY REQUEST ALSO. GET STATE INFO AND GO VERIFY +; + +DOVERIFY PROC NEAR + POP AX ; RESTORE SECTOR COUNT + PUSH AX + MOV AH,ROMVERIFY ; REQUEST VERIFY + CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE + JNC NOVERIFY + +;SB34DISK004************************************************************** +;SB check the error returned in AH to see if it is a SOFT ECC error. +;SB If it is not we needn't do anything special. If it is a SOFT +;SB ECC error then decrement the SOFT_ECC_CNT error retry count. If +;SB this retry count becomes 0 then we just ignore the error and go to +;SB No_verify but if we can still try then we call the routine to reset +;SB the disk and go to DSKerr1 to retry the operation. 6 LOCS + + cmp ah,11h ;SOFT ECC error ? + jnz Not_SoftECC_Err + dec SOFT_ECC_CNT + jz NoVerify ;no more retry + call ResetDisk ;reset disk + jmp DskErr1 ;retry + +;SB34DISK004************************************************************** + +Not_SoftECC_Err: ;AN003;Other error. + call ResetDisk ;AN003; + dec VRetry_Cnt ;AN003; + jmp DskErr0 ;AN003; +DOVERIFY ENDP +; +; NEED TO SPECIAL CASE THE CHANGE-LINE ERROR AH=06H. IF WE GET THIS, WE +; NEED TO RETURN IT. +; +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC DSKERR ;| +DSKERR PROC NEAR ;| + CALL CHECKIO ;| +;---------------------------------------;| + + cmp cs:MultiTrk_Format_Flag, 1 ;AN007;Multi trk format request? + jne DoChkAgain ;AN007; + mov bp, 1 ;AN007;No more retry. + mov cs:MultiTrk_Format_Flag, 0 ;AN007;Clear the flag. +DoChkAgain: ;AN007; + CALL AGAIN +DskErr0: ;AN003; + JZ HARDERR + test word ptr [di].FLAGS, fNon_Removable ;AN009; + jnz Skip_TimeOut_Chk ;AN009; + CMP AH,80H ;TIMEOUT? + JZ HARDERR ;*** +Skip_TimeOut_Chk: ;AN009; + cmp ah, 0cch ;AN003;Write Fault error? + jz Write_Fault_Err ;AN003; Then, don't retry. + mov cs:Soft_ECC_Cnt, MAXERR ;AN003;Set Soft_ECC_Cnt back to MAXERR +DSKERR1: + POP AX ;RESTORE SECTOR COUNT + JMP RETRY + +Write_Fault_Err: ;AN003; + mov bp, 1 ;AN003;Just retry only once for Write Fault error. + jmp DskErr1 ;AN003; + +HARDERR: + PUBLIC HARDERR + + CALL MAPERROR + +HARDERR2: ; FOR ROUTINES THAT CALL MAPERROR THEMSELVES + PUBLIC HARDERR2 + + MOV CS:[TIM_DRV],-1 ;FORCE A MEDIA CHECK THROUGH ROM + MOV CX,CS:SECCNT ;GET COUNT OF SECTORS TO GO + MOV SP,CS:[SPSAV] ;RECOVER ENTRY STACK POINTER +; +; SINCE WE ARE PERFORMING A NON-LOCAL GOTO, RESTORE THE DISK PARAMETERS +; +MEDBYT_OK: + CALL DIDDLEBACK + RET ;AND RETURN +DSKERR ENDP + +; +; CHANGE SETTLE VALUE FROM SETTLECURRENT TO WHATEVER IS APPROPRIATE +; NOTE THAT THIS ROUTINE IS NEVER CALLED FOR A FIXED DISK. +; +NORMSPEED PROC NEAR + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne FASTSPEED ;AN012; + PUSH DS + PUSH AX + MOV AL,CS:SETTLESLOW + LDS SI,CS:DPT ; CURRENT DISK PARM TABLE + MOV [SI].DISK_HEAD_STTL,AL + POP AX + POP DS + CALL FASTSPEED + PUSH DS + LDS SI,CS:DPT + MOV [SI].DISK_HEAD_STTL,1 ; 1 IS FAST SETTLE VALUE + POP DS + RET +NORMSPEED ENDP + +FASTSPEED PROC NEAR +; +; IF THE DRIVE HAS BEEN MARKED AS TOO BIG (I.E. STARTING SECTOR OF THE +; PARTITION IS > 16 BITS, THEN ALWAYS RETURN DRIVE NOT READY. +; + TEST BYTE PTR [DI].FATSIZ,FTOOBIG + IF iTEST + JZ READY + JMP NOTREADY +READY: + ELSE + JNZ NOTREADY + ENDIF + + MESSAGE FTESTINIT,<"<"> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,ES + MESSAGE FTESTINIT,<":"> + MNUM FTESTINIT + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,CX + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,DX + MESSAGE FTESTINIT,<">"> + INT 13H +DEATH: + RET +NOTREADY: + STC + MOV AH,80H + JMP DEATH +FASTSPEED ENDP + +; MAP ERROR RETURNED BY ROM IN AH INTO CORRESPONDING CODE TO BE RETURNED TO +; DOS IN AL. +; +MAPERROR PROC NEAR + PUBLIC MAPERROR + + PUSH CX ; SAVE CX + PUSH CS + POP ES ;MAKE ES THE LOCAL SEGMENT + MOV AL,AH ;PUT ERROR CODE IN AL + MOV CS:[LSTERR],AL ;TERMINATE LIST WITH ERROR CODE + MOV CX,NUMERR ;NUMBER OF POSSIBLE ERROR CONDITIONS + MOV DI,OFFSET ERRIN ;POINT TO ERROR CONDITIONS + REPNE SCASB + MOV AL,CS:[DI + NUMERR - 1] ;GET TRANSLATION + POP CX ; RESTORE CX + STC ;FLAG ERROR CONDITION + RET +MAPERROR ENDP + +; SET THE TIME OF LAST ACCESS FOR THIS DRIVE. THIS IS DONE ONLY FOR REMOVABLE +; MEDIA. + + PUBLIC SET_TIM +SET_TIM PROC NEAR + PUSH AX +;SB33018****************************************************************** + xor AH, AH ; set command to get time ;SB;3.30* + int 1Ah ; call rom-bios timer function ;SB;3.30* +;SB33018****************************************************************** + OR AL,AL + JZ NOROLL3 + INC CS:[DAYCNT] ; CATCH ROLLOVER +NOROLL3: +; WE HAVE THE NEW TIME. IF WE SEE THAT THE TIME HAS PASSED, THEN WE RESET +; THE THRESHOLD COUNTER... + CMP DX,WORD PTR [DI].TIM_LO + JNZ SETACCESS + CMP CX,WORD PTR [DI].TIM_HI + JZ DONE_SET +SETACCESS: + MOV BYTE PTR CS:[ACCESSCOUNT],0 + MOV WORD PTR [DI].TIM_LO,DX ;SAVE IT + MOV WORD PTR [DI].TIM_HI,CX +DONE_SET: + CLC + POP AX + RET +SET_TIM ENDP + + ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; THIS IS THE TRUE INT 13 HANDLER. WE PARSE THE REQUEST TO SEE IF THERE IS +; A DMA VIOLATION. IF SO, DEPENDING ON THE FUNCTION, WE: +; READ/WRITE BREAK THE REQUEST INTO THREE PIECES AND MOVE THE MIDDLE ONE +; INTO OUR INTERNAL BUFFER. +; FORMAT COPY THE FORMAT TABLE INTO THE BUFFER +; VERIFY POINT THE TRANSFER ADDRESS INTO THE BUFFER +; +; THIS IS THE BIGGEST BOGOSITY OF ALL. THE IBM CONTROLLER DOES NOT HANDLE +; OPERATIONS THAT CROSS PHYSICAL 64K BOUNDARIES. IN THESE CASES, WE COPY +; THE OFFENDING SECTOR INTO THE BUFFER BELOW AND DO THE I/O FROM THERE. +; +INT13FRAME STRUC +OLDBP DW ? +OLDAX DW ? +OLDBX DW ? +OLDCX DW ? +OLDDX DW ? +OLDDD DD ? +OLDF DW ? +INT13FRAME ENDS + +;J.K. 1/30/87 To handle the ps2_30 machine INT 13h, AH = 8 Problem. +;Save Registers here. +Save_AX DW ? +Save_BX DW ? +Save_CX DW ? +Save_DX DW ? +Save_DI DW ? +Save_SI DW ? +Save_BP DW ? +Save_DS DW ? +Save_ES DW ? +Prev_DX DW ? +Save_Flag DW ? + + +; ENTRY CONDITIONS: +; AH = FUNCTION +; AL = NUMBER OF SECTORS +; ES:BX = DMA ADDRESS +; CX = PACKED TRACK AND SECTOR +; DX = HEAD AND DRIVE +; OUTPUT CONDITIONS: +; NO DMA VIOLATION. +; + PUBLIC BLOCK13 +BLOCK13 PROC FAR +; +; LET THE OPPERATION PROCEED. IF THERE IS A DMA VIOLATION, THEN WE DO THINGS. +; + MOV CS:PREVOPER,AX ; SAVE REQUEST + PUSHF + CMP AH,ROMFORMAT + JNZ NOT_FORMAT +; SET CHANGED BY FORMAT BIT FOR ALL LOGICAL DRIVES USING THIS PHYSICAL DRIVE +;---------------------------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. +; IT GETS PATCHED IN AT INIT TIME | + PUBLIC CHANGED_PATCH +CHANGED_PATCH: + MOV WORD PTR CS:[FLAGBITS],FCHANGED_BY_FORMAT+FCHANGED + CALL SET_CHANGED_DL ; INDICATE THAT MEDIA CHANGED BY FORMAT +; | +;---------------------------------------------------------| +NOT_FORMAT: + test dl, 80h ; floppy or hard disk? + jnz not_floppy ; if hard, skip this nonsense + cmp cs:EC35_Flag, 0 ; any electrically compat. drives? + jz not_floppy ; no; proceed unhindered + SAVEREG + mov cl, dl ; turn drive number into bit map: + mov al, 1 ; assume drive 0 + shl al, cl ; shift over correct number of times + test al, cs:EC35_Flag ; is THIS drive an electrically compatible 3.5 incher? + jz not_EC35 ; no; don't change anything + mov bl, dl ; which drive was it? + xor bh, bh ; need only one byte of index + push es ; need a segment register + mov ax, 40h ; the machine state byte is in the... + mov es, ax ; ...segment at 40h + mov byte ptr es:[90h+bx], 93H ; establish drive type as: (360k disk in 360k drive, no double-stepping, 250 kbs transfer rate) + pop es ; fix up register again +not_EC35: + RESTOREREG +not_floppy: + cmp cs:[model_byte], mdl_ps2_30 ; is this a ps2/30? + jne not_ps2_30 ; if not, just do normal call + cmp ah, 8 ;J.K. 1/30/87 Read Driver Parm ? + je ps2_30_Problem ;J.K. 1/30/87 + cmp ah, 15h + je ps2_30_Problem +not_ps2_30: + CALL ORIG13 ; SIMULATE INT 13 + JC GOTERR13_br ; ERROR? + RET 2 ; NO, RETURN AND CLEAR FLAGS + +GOTERR13_br: jmp Goterr13 + +;J.K.1/30/87 ps2_30 machine has some problem with AH=8h(Read Drive Parm), Int 13h. +;This function does not reset the common buses after the execution. +;To solve this problem, when we detect AH=8h, then we will save the result and +;will issue AH=1 (Read Status) call to reset the buses. + +ps2_30_Problem: ;J.K. 1/30/87; ps2_30 = PS2 Model 30. + mov cs:Prev_DX, DX ;save orignal drive number + call Orig13 ;Do "Read drive parm" + + mov cs:Save_AX, AX ;Save registers,flag + mov cs:Save_BX, BX + mov cs:Save_CX, CX + mov cs:Save_DX, DX + mov cs:Save_DI, DI + mov cs:Save_SI, SI + mov cs:Save_BP, BP + mov cs:Save_DS, DS + mov cs:Save_ES, ES + pushf + pop cs:Save_Flag + + mov dx, cs:Prev_DX ;restore orignal drive + pushf + mov ah, 1 ;Read Status. + call Orig13 ;Reset the bus as a side effect of this call. + + mov AX, cs:Save_AX ;restore registers,flag + mov BX, cs:Save_BX + mov CX, cs:Save_CX + mov DX, cs:Save_DX + mov DI, cs:Save_DI + mov SI, cs:Save_SI + mov BP, cs:Save_BP + mov DS, cs:Save_DS + mov ES, cs:Save_ES + push cs:Save_Flag + popf + jc GotErr13 ;AH=8 had been an error? + ret 2 + +; +; SOME KIND OF ERROR OCCURRED. SEE IF IT IS DMA VIOLATION +; +GOTERR13: + PUSHF + cmp ah, 09h ;AN011; DMA error? + je Chk_ValidMedia_ERR13 ;AN011; + cmp ah, 11h ;AN011; ECC error? + je Chk_ValidMedia_ERR13 ;AN011; + jmp Skip_Ecc_Check ;AN011; Other error. Just return back. + +Chk_ValidMedia_ERR13: ;AN011;If SetDrive fails, then just + push ds ;AN011; return back to INT 13h caller, + push di ;AN011; without performing ECC, DMA + push ax ;AN011; error handling. + mov byte ptr cs:[Phys_Drv], 1 ;AN011; + mov al, dl ;AN011; + call SetDrive ;AN011; + mov byte ptr cs:[Phys_Drv], 0 ;AN011; + pop ax ;AN011; + pop di ;AN011; + pop ds ;AN011; + jc Skip_Ecc_Check ;AN011; + +; TEST OF BIT PATTERN 08H LET OTHER ERRORS BE PASSED AS DMA ERRORS - PTR 32D0519 +; TEST AH,08H ; DMA BIT + CMP AH, 09H ; DMA ERROR CODE + JNZ CHECK_ECC + JMP GOTDMAERR +CHECK_ECC: +;J.K. AN003; Soft ECC bug is only applied to PC1 and PC-XT. So, we will enforce +;this ECC error handler for them. Also, since CMC hardfiles in PC AT also +;generate a lot of unnecessary ECC errors, we will still cover PC ATs as +;it is done in the earlier version of MSBIO. +;During Format/Verify operation, we are going to consider any Soft Ecc as a +;hard error. + +;SB34DISK005***************************************************************** +;SB See if the machine we are operating on is a PC, XT or AT by checking +;SB the model byte. The soft ECC bug is only on these machines and if +;SB the machine we are operating on is not one of these three then we +;SB needn't do anything special. If we are operating one these however +;SB we check to see if the error occured during format by checking +;SB media_set_for_format. If it did occur during format we cannot do +;SB anything but if not during format then check to see if the error +;SB returned in AH is the SOFT_ECC error and if so go to OK11 since +;SB the error can be ignored. 6 LOCS + + cmp cs:[Media_Set_For_Format], 1 ; formatting? + je Skip_Ecc_Check + cmp cs:[Model_Byte], 0FEh ; PC or XT? + jae Go_Chk_Ecc + cmp cs:[Model_Byte], 0FBh ; XT? + je Go_Chk_Ecc + cmp cs:[Model_Byte], 0FCh + jne Skip_Ecc_Check + cmp cs:[Secondary_Model_Byte], 2 ; AT? + ja Skip_Ecc_Check +Go_Chk_Ecc: ; for PC, XT, AT + CMP AH,11H + JZ OK11 +Skip_Ecc_Check: ;AN003; Just return back to INT 13h caller. + +;SB34DISK005***************************************************************** + + POPF + RET 2 +; +; WE HAVE AN ERROR STATUS 11H. THIS INDICATES AN ECC-CORRECTED ERROR. NOTE +; THAT THIS INDICATES THAT THE DATA IS PROBABLY CORRECT BUT NOT CERTAINLY +; CORRECT. THE ROMS ON PC-1S AND PC_XTS HAVE A 'BUG' IN THAT IF AN ECC ERROR +; OCCURS FOR A MULTI-SECTOR READ, ONLY THE SECTORS UP TO THE ONE WHERE THE +; ERROR OCCURRED ARE READ IN. WE HAVE NO WAY OF KNOWING HOW MANY WERE READ IN +; THIS CASE, SO WE REDO THE OPERATION, READING ONE SECTOR AT A TIME. IF WE +; GET AN ECC ERROR ON READING ONE SECTOR, WE IGNORE THE ERROR BECAUSE THE +; SECTOR HAS BEEN READ IN. +; + PUBLIC OK11 +OK11: +; POPF +;J.K. 8/29/86 Here, it is better reset the system. So, we are going to +;call Orig13 again + + xor ah, ah + call Orig13 ;reset. Don't care about the result + + MOV AX,CS:[PREVOPER] ; RETRIEVE REQUEST +; +; THIS WILL PROVIDE A TERMINATION POINT. +; + CMP AL,1 ; IF REQUEST FOR ONE SECTOR, ASSUME OK + JNZ ECC_ERR_HANDLE + XOR AH,AH ; CLEAR CARRY TOO! + RET 2 + + PUBLIC ECC_ERR_HANDLE +ECC_ERR_HANDLE: + SAVEREG + MOV CS:[NUMBER_OF_SEC],AL +LOOP_ECC: + MOV AX,CS:[PREVOPER] + MOV AL,1 ; REQUEST FOR ONE SECTOR ONLY +; +; WE DO READS ONE SECTOR AT A TIME. THIS ENSURES THAT WE WILL EVENTUALLY +; FINISH THE REQUEST SINCE ECC ERRORS ON ONE SECTOR DO READ IN THAT SECTOR. +; +; WE NEED TO PUT IN SOME "INTELLIGENCE" INTO THE ECC HANDLER TO HANDLE READS +; THAT ATTEMPT TO READ MORE SECTORS THAN ARE AVAILABLE ON A PARTICULAR +; TRACK. +; WE CALL CHECK_WRAP TO SET UP THE SECTOR #, HEAD # AND CYLINDER # FOR +; THIS REQUEST. +; AT THIS POINT, ALL REGISTERS ARE SET UP FOR THE CALL TO ORIG13, EXCEPT +; THAT THERE MAY BE A STARTING SECTOR NUMBER THAT IS BIGGER THAN THE NUMBER +; OF SECTORS ON A TRACK. +; + CALL CHECK_WRAP ; GET CORRECT PARAMETERS FOR INT 13 + PUSHF + CALL ORIG13 + JNC OK11_OP + CMP AH,11H ; ONLY ALLOW ECC ERRORS + JNZ OK11_EXIT_err ;J.K. 8/26/86 Other error? + mov ah, 0 ;J.K. ECC error. Reset the system again. + pushf + call Orig13 + xor ax, ax ; clear the error code so that if this + ; was the last sector, no error code + ; will be returned for the corrected + ; read. (clear carry too.) +OK11_OP: + DEC CS:[NUMBER_OF_SEC] + JZ OK11_EXIT ; ALL DONE? + INC CL ; ADVANCE SECTOR NUMBER + INC BH ; ADD 200H TO ADDRESS + INC BH + JMP SHORT LOOP_ECC +OK11_EXIT_err: + stc ;J.K. 8/28/86 Set carry bit again. +OK11_EXIT: + RESTOREREG + RET 2 +; +; WE TRULY HAVE A DMA VIOLATION. RESTORE REGISTER AX AND RETRY THE +; OPERATION AS BEST WE CAN. +; +GOTDMAERR: + POP AX ; CLEAN UP STACK + MOV AX,CS:PREVOPER + STI + CMP AH,ROMREAD ; SAVE USER FLAGS + JB INTDONE + CMP AH,ROMVERIFY + JZ INTVERIFY + CMP AH,ROMFORMAT + JZ INTFORMAT + JA INTDONE +; +; WE ARE DOING A READ/WRITE CALL. CHECK FOR DMA PROBLEMS +; + SAVEREG + PUSH BP + MOV BP,SP + MOV DX,ES ; CHECK FOR 64K BOUNDARY ERROR + + SHL DX,1 + SHL DX,1 + SHL DX,1 + SHL DX,1 ; SEGMENT CONVERTED TO ABSOLUTE ADDRESS + + ADD DX,BX ; COMBINE WITH OFFSET + ADD DX,511 ; SIMULATE A TRANSFER +; +; IF CARRY IS SET, THEN WE ARE WITHIN 512 BYTES OF THE END OF THE SEGMENT. +; WE SKIP THE FIRST TRANSFER AND PERFORM THE REMAINING BUFFERING AND TRANSFER +; + JNC NO_SKIP_FIRST + MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER + JMP BUFFER ;J.K. 4/10/86 +; JMP SHORT BUFFER +; +; DX IS THE PHYSICAL 16 BITS OF START OF TRANSFER. COMPUTE REMAINING +; SECTORS IN SEGMENT. +; +NO_SKIP_FIRST: + SHR DH,1 ; DH = NUMBER OF SECTORS BEFORE ADDRESS + MOV AH,128 ; AH = MAX NUMBER OF SECTORS IN SEGMENT + SUB AH,DH +; +; AH IS NOW THE NUMBER OF SECTORS THAT WE CAN SUCCESSFULLY WRITE IN THIS +; SEGMENT. IF THIS NUMBER IS ABOVE OR EQUAL TO THE REQUESTED NUMBER, THEN WE +; CONTINUE THE OPERATION AS NORMAL. OTHERWISE, WE BREAK IT INTO PIECES. +; + CMP AH,AL ; CAN WE FIT IT IN? + JB DOBLOCK ; NO, PERFORM BLOCKING. +; +; YES, THE REQUEST FITS. LET IT HAPPEN +; + MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER + CALL DOINT + JMP BAD13 +; +; VERIFY THE GIVEN SECTORS. PLACE THE BUFFER POINTER INTO OUR SPACE. +; +INTVERIFY: + SAVEREG + PUSH CS + POP ES +DOSIMPLE: + MOV BX,OFFSET DISKSECTOR + PUSHF + CALL ORIG13 + RESTOREREG + RET 2 + +; +; FORMAT OPERATION. COPY THE PARAMETER TABLE INTO MEMORY +; +INTFORMAT: + SAVEREG + SAVEREG + PUSH ES + PUSH CS + POP ES + POP DS + MOV SI,BX + MOV DI,OFFSET DISKSECTOR + CALL MOVE + RESTOREREG + JMP DOSIMPLE +; +; INLINE CONTINUATION OF OPERATION +; +INTDONE: + JMP ORIG13 + +; +; We can't fit the request into the entire block. Perform the operation on +; the first block. +; +; DoBlock is modified to correctly handle multi-sector disk I/O. -J.K. 4/10/86 +; Old DoBlock had added the number of sectors I/Oed (Ah in Old DoBlock) after +; the DoInt call to CL. Observing only the lower 6 bits of CL(=max. 64) can +; represent a starting sector, if AH was big, then CL would be clobbered. +; By the way, we still are going to use CL for this purpose since Checkwrap +; routine will use it as an input. To prevent CL from being clobbered, a +; safe number of sectors should be calculated like "63 - # of sectors/track". +; DoBlock will handle the first block of requested sectors within the +; boundary of this safe value. - J.K. 2/28/86 + +DoBlock: +;Try to get the # of sectors/track from BDS via Rom drive number. +;For any mini disks installed, here we have to pray that they have the +;same # of sector/track as the main DOS partition disk drive. + + Message ftestDisk,<"!!!DMA DoBlock!!!"> + + mov dx, word ptr [bp.olddx] ;set head # + push di + push ds + push ax ;AH - # of sectors before DMA boundary + ;AL - User requeseted # of sectors for I/O. + mov byte ptr CS:[phys_drv],1 + mov al, dl + call SetDrive ;get BDS pointer for this DISK. + pop ax + mov byte ptr CS:[phys_drv],0 + test word ptr [DI].Flags, fNon_Removable ;don't have to worry + jnz DoBlockHard ;about floppies. They are track by track operation. + mov al, ah ;set al = ah for floppies + jmp short DoBlockCont +DoBlockHard: + push cx + xor cx, cx + mov cx, [DI].SecLim ;# of sectors/track + mov ch, 63 + sub ch, cl + mov al, ch + xchg ah, al ;now ah - safe # of sectors + ;al - # of sectors before DMA boundary + pop cx +DoBlockCont: + pop ds + pop di +DoBlockContinue: + Message ftestDisk,<"%%DMA DoBlock Loop%%"> + cmp ah, al ;if safe_# >= #_of_sectors_to_go_before DMA, + jae DoBlocklast ;then #_of_sectors_to_go as it is for DoInt. + push ax ;save AH, AL + mov al, ah ;Otherwise, set al to ah to operate. + jmp short DoBlockDoInt ;DoInt will set AH to a proper function in [BP.Oldax] +DoBlocklast: + mov ah, al + push ax ;save AH +DoBlockDoInt: ;let AH = AL = # of sectors for this shot + CALL DoInt + JC BAD13 ;something happened, bye! + pop ax + SUB BYTE PTR [BP.oldax], AH ;decrement by the successful operation + ADD CL,AH ;advance sector number. Safety gauranteed. + ADD BH,AH ;advance DMA address + ADD BH,AH ;twice for 512 byte sectors. + cmp ah, al ;check the previous value + je Buffer ;if #_of_sectors_to_go < safe_#, then we are done already. + sub al, ah ;otherwise, #_sector_to_go = #_of_sector_to_go - safe_# + call Check_Wrap ;get new CX, DH for the next operation. + jmp short DoBlockContinue ;handles next sectors left. +;End of modificaion of DoBlock - J.K. 2/28/86 +;The following is the original one. +; PUSH AX +; MOV AL,AH ; get max to operate on +; MOV AH,BYTE PTR [BP.oldax+1]; get function +; mov dh,byte ptr [BP.olddx+1] ; set up head number +; CALL DoInt +; JC Bad13 ; something happened, bye! +; POP AX +; SUB BYTE PTR [BP.oldax],AH ; decrement by the successful operation +; ADD CL,AH ; advance sector number +; ADD BH,AH ; advance DMA address +; ADD BH,AH ; twice for 512 byte sectors. + +; +; THE NEXT REQUEST WILL WRAP THE 64K BOUNDARY. IF WE ARE WRITING, THEN COPY +; THE OFFENDING SECTOR INTO OUR SPACE. +; +; ES:BX POINTS TO THE SECTOR +; CX,DX CONTAIN THE CORRECT TRACK/SECTOR/HEAD/DRIVE INFO +; [BP.OLDAX] HAS CORRECT FUNCTION CODE +; +BUFFER: + PUSH BX + MOV AH,BYTE PTR [BP.OLDAX+1] + CMP AH,ROMWRITE + JNZ DOREAD +; +; COPY THE OFFENDING SECTOR INTO LOCAL BUFFER +; + SAVEREG + PUSH CS ; EXCHANGE SEGMENT REGISTERS + PUSH ES + POP DS + POP ES + MOV DI,OFFSET DISKSECTOR ; WHERE TO MOVE + PUSH DI ; SAVE IT + MOV SI,BX ; SOURCE + CALL MOVE + POP BX ; NEW TRANSFER ADDRESS + RESTOREREG + MOV AL,1 +; SEE IF WE ARE WRAPPING AROUND A TRACK OR HEAD + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND +; +; AH IS FUNCTION +; AL IS 1 FOR SINGLE SECTOR TRANSFER +; ES:BX IS LOCAL TRANSFER ADDRES +; CX IS TRACK/SECTOR NUMBER +; DX IS HEAD/DRIVE NUMBER +; SI,DI UNCHANGED +; + CALL DOINT + RESTOREREG + JC BAD13 ; GO CLEAN UP + JMP SHORT DOTAIL +; +; READING A SECTOR. DO INT FIRST, THEN MOVE THINGS AROUND +; +DOREAD: + SAVEREG + PUSH CS + POP ES + MOV BX,OFFSET DISKSECTOR + MOV AL,1 +; SEE IF OUR REQUEST WILL WRAP A TRACK OR HEAD BOUNDARY + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND +; +; AH = FUNCTION +; AL = 1 FOR SINGLE SECTOR +; ES:BX POINTS TO LOCAL BUFFER +; CX, DX ARE TRACK/SECTOR, HEAD/DRIVE +; + CALL DOINT + RESTOREREG + JC BAD13 ; ERROR => CLEAN UP + SAVEREG + PUSH CS + POP DS + MOV DI,BX + MOV SI,OFFSET DISKSECTOR + CALL MOVE + RESTOREREG +; +; NOTE THE FACT THAT WE'VE DONE 1 MORE SECTOR +; +DOTAIL: + POP BX ; RETRIEVE NEW DMA AREA + ADD BH,2 ; ADVANCE OVER SECTOR + INC CX + MOV AL,BYTE PTR [BP.OLDAX] + CLC + DEC AL + JZ BAD13 ; NO MORE I/O +; SEE IF WE WRAP AROUND A TRACK OR HEAD BOUNDARY WITH STARTING SECTOR +; WE ALREADY HAVE THE CORRECT HEAD NUMBER TO PASS TO CHECK_WRAP + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND + CALL DOINT +; +; WE ARE DONE. AX HAS THE FINAL CODE; WE THROW AWAY WHAT WE GOT BEFORE +; +BAD13: + MOV SP,BP + RESTOREREG + RET 2 +BLOCK13 ENDP + PAGE + INCLUDE MSIOCTL.INC + PAGE +; CHECK_WRAP IS A ROUTINE THAT ADJUSTS THE STARTING SECTOR, STARTING HEAD +; AND STARTING CYLINDER FOR AN INT 13 REQUEST THAT REQUESTS I/O OF A LOT +; OF SECTORS. IT ONLY DOES THIS FOR FIXED DISKS. IT IS USED IN THE SECTIONS +; OF CODE THAT HANDLE ECC ERRORS AND DMA ERRORS. IT IS NECESSARY, BECAUSE +; ORDINARILY THE ROM WOULD TAKE CARE OF WRAPS AROUND HEADS AND CYLINDERS, +; BUT WE BREAK DOWN A REQUEST WHEN WE GET AN ECC OR DMA ERROR INTO SEVERAL +; I/O OF ONE OR MORE SECTORS. IN THIS CASE, WE MAY ALREADY BE BEYOND THE +; NUMBER OF SECTORS ON A TRACK ON THE MEDIUM, AND THE REQUEST WOULD FAIL. +; +; INPUT CONDITIONS: +; ALL REGISTERS SET UP FOR AN INT 13 REQUEST. +; +; OUTPUT: +; DH - CONTAINS STARTING HEAD NUMBER FOR REQUEST +; CX - CONTAINS STARTING SECTOR AND CYLINDER NUMBERS +; (THE ABOVE MAY OR MAY NOT HAVE BEEN CHANGED, AND ARE 0-BASED) +; ALL OTHER REGISTERS PRESERVED. +; + PUBLIC CHECK_WRAP +CHECK_WRAP: + Message ftestDisk,<"Entering Check_Wrap...",cr,lf> + SAVEREG + MOV BYTE PTR CS:[PHYS_DRV],1; USE PHYSICAL DRIVE IN AL TO GET BDS + MOV AL,DL ; AL HAS PHYSICAL DRIVE NUMBER + CALL SETDRIVE ; GET POINTER TO BDS FOR DRIVE + MOV BYTE PTR CS:[PHYS_DRV],0; RESTORE FLAG TO USE LOGICAL DRIVE + JC NO_WRAP ; DO NOTHING IF WRONG PHYSICAL DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JZ NO_WRAP ; NO WRAPPING FOR REMOVABLE MEDIA + MOV BX,[DI].SECLIM + MOV AX,CX + AND AX,003FH ; EXTRACT SECTOR NUMBER + CMP AX,BX ; ARE WE GOING TO WRAP? + JBE NO_WRAP + DIV BL ; AH=NEW SECTOR #, AL=# OF HEAD WRAPS +; WE NEED TO BE CAREFUL HERE. IF THE NEW SECTOR # IS 0, THEN WE ARE ON THE +; LAST SECTOR ON THAT TRACK. + OR AH,AH + JNZ NOT_ON_BOUND + MOV AH,BL ; SET SECTOR=SECLIM IF ON BOUNDARY + DEC AL ; ALSO DECREMENT # OF HEAD WRAPS +NOT_ON_BOUND: + AND CL,0C0H ; ZERO OUT SECTOR # + OR CL,AH ; OR IN NEW SECTOR # + XOR AH,AH ; AX = # OF HEAD WRAPS + INC AX + ADD AL,DH ; ADD IN STARTING HEAD # + ADC AH,0 ; CATCH ANY CARRY + CMP AX,[DI].HDLIM ; ARE WE GOING TO WRAP AROUND A HEAD? + JBE NO_WRAP_HEAD ; DO NOT LOSE NEW HEAD NUMBER!! + PUSH DX ; PRESERVE DRIVE NUMBER AND HEAD NUMBER + XOR DX,DX + MOV BX,[DI].HDLIM + DIV BX ; DX=NEW HEAD #, AX=# OF CYLINDER WRAPS +; CAREFUL HERE! IF NEW HEAD # IS 0, THEN WE ARE ON THE LAST HEAD. + OR DX,DX + JNZ NO_HEAD_BOUND + MOV DX,BX ; ON BOUNDARY. SET TO HDLIM +; IF WE HAD SOME CYLINDER WRAPS, WE NEED TO REDUCE THEM BY ONE!! + OR AX,AX + JZ NO_HEAD_BOUND + DEC AX ; REDUCE NUMBER OF CYLINDER WRAPS +NO_HEAD_BOUND: + MOV BH,DL ; BH HAS NEW HEAD NUMBER + POP DX ; RESTORE DRIVE NUMBER AND HEAD NUMBER + DEC BH ; GET IT 0-BASED + MOV DH,BH ; SET UP NEW HEAD NUMBER IN DH + MOV BH,CL + AND BH,3FH ; PRESERVE SECTOR NUMBER + MOV BL,6 + XCHG CL,BL + SHR BL,CL ; GET MS CYLINDER BITS TO LS END + ADD CH,AL ; ADD IN CYLINDER WRAP + ADC BL,AH ; ADD IN HIGH BYTE + SHL BL,CL ; MOVE UP TO MS END + XCHG BL,CL ; RESTORE CYLINDER BITS INTO CL + OR CL,BH ; OR IN SECTOR NUMBER + +NO_WRAP: + CLC ; RESET CARRY + RESTOREREG + RET + +NO_WRAP_HEAD: + MOV DH,AL ; DO NOT LOSE NEW HEAD NUMBER + DEC DH ; GET IT 0-BASED + JMP SHORT NO_WRAP + +; +; INT_2F_13: +; THIS CODE IS CHAINED INTO THE INT_2F INTERRUPT DURING BIOS +; INITIALIZATION. IT ALLOWS THE USER TO CHANGE THE ORIG13 INT_13 VECTOR +; AFTER BOOTING. THIS ALLOWS TESTING AND IMPLEMENTATION OF CUSTOM INT_13 +; HANDLERS, WITHOUT GIVING UP MS-DOS ERROR RECOVERY +; +; ENTRY CONDITIONS +; AH == RESET_INT_13 (13H) +; DS:DX == ADDRESS OF NEW INT_13 HANDLER +; ES:BX == ADDRESS OF NEW INT_13 VECTOR USED BY WARM BOOT +; (INT 19) +; +; EXIT CONDITIONS +; ORIG13 == ADDRESS OF NEW INT_13 HANDLER +; DS:DX == OLD ORIG13 VALUE +; ES:BX == OLD OLD13 VALUE + + ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUBLIC INT_2F_13 +INT_2F_13 PROC FAR + + CMP AH,13H ; IF (INTERRUPT_VALUE != RESET_INT_13) + JE CHG_ORIG13 + JMP CS:[NEXT2F_13] ; THEN CONTINUE ON INT_2F CHAIN + +CHG_ORIG13: ; ELSE + PUSH WORD PTR CS:[ORIG13] ; SAVE OLD VALUE OF OLD13 AND + PUSH WORD PTR CS:[ORIG13 + 2]; ORIG13 SO THAT WE CAN + + PUSH WORD PTR CS:[OLD13] ; RETURN THEM TO CALLER + PUSH WORD PTR CS:[OLD13 + 2] + + MOV WORD PTR CS:[ORIG13],DX ; ORIG13 := ADDR. OF NEW INT_13 + ; VECTOR + MOV WORD PTR CS:[ORIG13+2],DS + + MOV WORD PTR CS:[OLD13],BX ; OLD13 := ADDR. OF NEW + ; BOOT_13 VECTOR + MOV WORD PTR CS:[OLD13+2],ES + + POP ES ; ES:BX := OLD OLD13 VECTOR + POP BX + + POP DS ; DS:DX := OLD ORIG13 VECTOR + POP DX + + IRET ; END ELSE + +INT_2F_13 ENDP + +MOVE PROC NEAR + CLD + PUSH CX + MOV CX,512/2 +;J.K. Warning!!! Do not change the position of this label. +; The following three bytes will be NOPed out by MSINIT if the system +; does not support the DOUBLE WORD MOV instruction, i.e., (if +; not 386 base machine.) +;---------------------------------------------------------------------------- + public DoubleWordMov +DoubleWordMov: ;AN002; + shr cx, 1 ;AN002;Make it a double word. + db 66h ;AN002;Machine code for double word mov +;---------------------------------------------------------------------------- + REP MOVSW + POP CX + RET +MOVE ENDP + +DOINT PROC NEAR + MOV DL,BYTE PTR [BP.OLDDX] ; GET PHYSICAL DRIVE NUMBER + XOR AH,AH + OR AL,AL + JZ DOINTDONE + MOV AH,BYTE PTR [BP.OLDAX+1] ; GET REQUEST CODE + PUSH [BP.OLDF] + CALL ORIG13 + PUSHF + POP [BP.OLDF] +DOINTDONE: + RET +DOINT ENDP +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSDSKPR.INC b/v4.0/src/BIOS/MSDSKPR.INC new file mode 100644 index 0000000..6b24bff --- /dev/null +++ b/v4.0/src/BIOS/MSDSKPR.INC @@ -0,0 +1,22 @@ +; The following structure defines the disk parameter table +; pointed to by Interrupt vector 1EH (location 0:78H) + +DISK_PARMS STRUC +DISK_SPECIFY_1 DB ? +DISK_SPECIFY_2 DB ? +DISK_MOTOR_WAIT DB ? ; Wait till motor off +DISK_SECTOR_SIZ DB ? ; Bytes/Sector (2 = 512) +DISK_EOT DB ? ; Sectors per track (MAX) +DISK_RW_GAP DB ? ; Read Write Gap +DISK_DTL DB ? +DISK_FORMT_GAP DB ? ; Format Gap Length +DISK_FILL DB ? ; Format Fill Byte +DISK_HEAD_STTL DB ? ; Head Settle Time (MSec) +DISK_MOTOR_STRT DB ? ; Motor start delay +DISK_PARMS ENDS + +ROMStatus equ 1 +ROMRead equ 2 +ROMWrite equ 3 +ROMVerify equ 4 +ROMFormat equ 5 diff --git a/v4.0/src/BIOS/MSEQU.INC b/v4.0/src/BIOS/MSEQU.INC new file mode 100644 index 0000000..d45577b --- /dev/null +++ b/v4.0/src/BIOS/MSEQU.INC @@ -0,0 +1,76 @@ +%OUT MSEQU.INC... +;============================================================================== + +FTOOBIG EQU 80H +FBIG EQU 40H +ROMSTATUS EQU 1 +ROMREAD EQU 2 +ROMWRITE EQU 3 +ROMVERIFY EQU 4 +ROMFORMAT EQU 5 +VID_SIZE EQU 12 + +INCLUDE MSBDS.INC ; VARIOUS EQUATES FOR BDS + +;AN000; Extended BPB structure. +BPB_TYPE STRUC +SECSIZE DW ? +SECALL DB ? +RESNUM DW ? +FATNUM DB ? +DIRNUM DW ? +SECNUM DW ? +FATID DB ? +FATSIZE DW ? +SLIM DW ? +HLIM DW ? +HIDDEN_L DW ? +HIDDEN_H dw 0 ;J.K. +SECNUM_L dw 0 ;J.K. +SECNUM_H dw 0 ;J.K. +BPB_TYPE ENDS + +;;;;;;;;;;; +BOOT_SERIAL_SIZE equ 4 ;J.K. +BOOT_VOLUME_LABEL_SIZE equ 11 ;J.K. +BOOT_SYSTEM_ID_SIZE equ 8 ;J.K. +EXT_BOOT_SIGNATURE equ 41 ;J.K. +RSINIT=0A3H ;RS232 INITIALIZATION + ;9600 BAUD:NO PARITY:1 STOP:8 BIT WORD +LF=10 ;LINE FEED +CR=13 ;CARRIAGE RETURN +BACKSP=8 ;BACKSPACE +BRKADR=1BH * 4 ;006C 1BH BREAK VECTOR ADDRESS +TIMADR=1CH * 4 ;0070 1CH TIMER INTERRUPT +DSKADR=1EH * 4 ;ADDRESS OF PTR TO DISK PARAMETERS +SEC9=522H ;ADDRESS OF DISK PARAMETERS +HEADSETTLE=SEC9+9 ; ARR 2.20 ADDRESS OF HEAD SETTLE TIME +NORMSETTLE=15 ; ARR 2.20 NORMAL HEAD SETTLE +SPEEDSETTLE=0 ; ARR 2.20 SPEED UP SETTLE TIME +INITSPOT=534H ; ARR IBM WANTS 4 ZEROS HERE +AKPORT=20H +EOI=20H +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER +EXTRA = 22 ;USUALLY A POINTER TO VOL ID FOR ERROR 15 +CHROUT = 29H +MAXERR = 5 +LSTDRV = 504H + +BOOTBIAS = 200H +NOTBUSYSTATUS = 10000000B ; NOT BUSY +ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?) +NOPAPERSTATUS = 00100000B ; NO MORE PAPER +SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED +IOERRSTATUS = 00001000B ; SOME KINDA ERROR +RESERVED = 00000110B ; NOPS +TIMEOUTSTATUS = 00000001B ; TIME OUT. +ERROR_UNKNOWN_MEDIA = 7 ; FOR USE IN BUILD BPB CALL + +PATHGEN = 1 diff --git a/v4.0/src/BIOS/MSEXTRN.INC b/v4.0/src/BIOS/MSEXTRN.INC new file mode 100644 index 0000000..b72d879 --- /dev/null +++ b/v4.0/src/BIOS/MSEXTRN.INC @@ -0,0 +1,97 @@ +; SCCSID = @(#)IBMEXTRN.ASM 1.11 85/11/18 +;This is for IBMINIT module. +;======================================================= +;REVISION HISTORY: +;AN000; - NEW Version 4.00. J.K. +;AC000; - Modified Line 4.00. J.K. +;ANxxx; - PTMyyy +;============================================================================== +;AN001; D486 SHARE installation for large media 2/23/88 J.K. +;============================================================================== + + EXTRN ORIG13:DWORD,ORIG19:DWORD + EXTRN COM2DEV:WORD,COM1DEV:WORD + EXTRN COM4DEV:WORD,COM3DEV:WORD + EXTRN LPT3DEV:WORD,LPT2DEV:WORD,LPT1DEV:WORD + EXTRN HARDDRV:BYTE,HARDNUM:BYTE,DRVMAX:BYTE,HDSKTAB:WORD + EXTRN DSKDRVS:WORD,HNUM:BYTE,EOT:BYTE,FHAVE96:BYTE + EXTRN REAL13:DWORD,DAYCNT:WORD,CONHEADER:WORD + EXTRN TWOHARD:BYTE,INT_2F_NEXT:DWORD + EXTRN BDSH:WORD,BDSX:WORD,START_BDS:DWORD + EXTRN FHAVEK09:BYTE, NEW_ROM:BYTE + EXTRN SINGLE:BYTE + EXTRN BDSMs:BYTE ;for Mini Disk -J.K. 4/7/86 + EXTRN HaveCMOSClock:byte ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN BinToBCD:word ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN DaycntToDay:word ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN OLD13:DWORD + extrn Temp_H:word ;J.K. For 32 bit calculation. IBMDISK + extrn Start_Sec_H:word ;J.K. IBMDISK. + extrn KEYRD_Func:byte ;J.K. For IBMCON. Defined in IBMBDATA. + extrn KEYSTS_Func:byte ;J.K. For IBMCON. Defined in IBMBDATA. + extrn DiskSector:byte ;J.K. IBMBDATA + extrn Bpb_In_Sector:word ;J.K. IBMBDATA + extrn SecPerCLusInSector:Byte ;J.K. IBMBDATA + extrn NumberOfFats:byte ;J.K. IBMBDATA + extrn MediaByte:byte ;J.K. IBMBDATA + extrn Ext_Boot_Sig:Byte ;J.K. IBMBDATA + extrn Boot_Serial_L:Word ;J.K. IBMBDATA + extrn Boot_Serial_H:Word ;J.K. IBMBDATA + extrn Boot_Volume_Label:Byte ;J.K. IBMBDATA + extrn Boot_System_ID:Byte ;J.K. IBMBDATA + extrn Fat_12_ID:Byte ;J.K. IBMDISK + extrn Fat_16_ID:Byte ;J.K. IBMDISK + extrn Vol_No_Name:Byte ;J.K. IBMDISK + extrn MotorStartup:Byte ;J.K. IBMBDATA + extrn DoubleWordMov:Byte ;J.K. IBMDISK + extrn Model_Byte:Byte ;J.K. IBMBIO2 + extrn Secondary_Model_Byte:Byte ;J.K. IBMBIO2 + + IF iTEST + IFNDEF NUMBUF + EXTRN NUMBUF:BYTE,DIGITS:BYTE,FTESTBITS:WORD + ENDIF + ENDIF + + EXTRN START$:NEAR,ERROUT:NEAR,BLOCK13:FAR,INT19:FAR + EXTRN INTRET:NEAR,HDRIVE:NEAR,DRIVEX:NEAR,INT13:FAR,CBREAK:NEAR,OUTCHR:NEAR + EXTRN DISKRD:NEAR,MEDIA_PATCH:NEAR,GETBP1_PATCH:NEAR + EXTRN SET_PATCH:NEAR,DISKIO_PATCH:NEAR,DSKERR:NEAR,INIT_PATCH:NEAR + EXTRN TABLE_PATCH:NEAR,EXIT:NEAR,CHANGED_PATCH:NEAR + EXTRN ERRIN:NEAR,GETBP:NEAR,SWPDSK:NEAR + EXTRN OUTCHR:NEAR,WRMSG:NEAR,TIME_TO_TICKS:NEAR + EXTRN INT2F_DISK:NEAR,INSTALL_BDS:NEAR,SETDRIVE:NEAR + extrn Mov_Media_IDs:Near ;J.K. + extrn Clear_IDs:Near ;J.K. + IF iTEST + IFNDEF NUMBUF + EXTRN MSGNUM:NEAR,MSGOUT:NEAR,dumpbytes:near,hex_to_ascii:near + EXTRN outchar:near + ENDIF + ENDIF + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + ASSUME CS:SYSINITSEG + EXTRN CURRENT_DOS_LOCATION:WORD + EXTRN FINAL_DOS_LOCATION:WORD + EXTRN DEVICE_LIST:DWORD + EXTRN MEMORY_SIZE:WORD + EXTRN DEFAULT_DRIVE:BYTE + EXTRN BUFFERS:WORD + EXTRN SYSINIT:FAR + extrn Big_Media_Flag:Byte ;AN001; +SYSINITSEG ENDS + + ASSUME CS:CODE + +; END OF DISK MODULES FOR CONFIGURATION + + EXTRN END96TPI:BYTE + EXTRN ENDTWOHARD:BYTE + EXTRN ENDONEHARD:BYTE + EXTRN ENDSWAP:BYTE + EXTRN ENDFLOPPY:BYTE + +; IBM FIXED UP AT ROM + + EXTRN IBM_DISK_IO:FAR diff --git a/v4.0/src/BIOS/MSGROUP.INC b/v4.0/src/BIOS/MSGROUP.INC new file mode 100644 index 0000000..ac6202d --- /dev/null +++ b/v4.0/src/BIOS/MSGROUP.INC @@ -0,0 +1,46 @@ +EVBOUND = 1 ;THIS VALUE BEING 0 DOES NO BOUNDARY ALLIGNMENT, VALUE 1 ;3.30 + ; ALIGNS TO EVEN ;3.30 +; : : : : : : : : : : : : : : ;3.30 + IF EVBOUND ;;IF EVEN (WORD) ALLIGNMENT IS REQUESTED, ;3.30 +; : : : : : : : : : : : : : : ;3.30 +EVENB MACRO ;3.30 + EVEN ;;ADJUST TO EVEN BOUNDARY ;3.30 + ENDM ;3.30 + ;3.30 +ODD MACRO ;3.30 +;;GENERATE BOUNDARY PADDING TO FORCE ODD OFFSET ;3.30 + IF (($-CODE) MOD 2) EQ 0 ;3.30 + DB ? ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + ;3.30 +CODE_SEGMENT MACRO ;3.30 +;;ALLIGN THE SEGMENT ON WORD BOUNDARY TO ALLOW FOR EVEN ALLIGNMENT OF DATA;3.30 +CODE SEGMENT WORD PUBLIC 'CODE' ;3.30 ;3.30 + ENDM ;3.30 + ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ELSE ;;SINCE EVEN ALLIGNMENT IS NOT DESIRED, JUST USE BYTE ALLI;3.30 GNMENT +; : : : : : : : : : : : : : : ;3.30 + ;3.30 +EVENB MACRO ;3.30 +;;REQUEST FOR WORD ALLIGNMENT DOES NOTHING ;3.30 + ENDM ;3.30 + ;3.30 +ODD MACRO ;3.30 +;;REQUEST FOR ODD ALLIGNMENT DOES NOTHING ;3.30 + ENDM ;3.30 + ;3.30 +CODE_SEGMENT MACRO ;3.30 +;;SEGMENT IS ALLIGNED ON BYTE BOUNDARY FOR MINIMUM SIZE OF GENERATION ;3.30 +CODE SEGMENT BYTE PUBLIC 'CODE' ;3.30 + ENDM ;3.30 + ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ENDIF ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ;3.30 + CODE_SEGMENT ;3.30 + ASSUME CS:CODE ;3.30 + ;3.30 + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSHARD.ASM b/v4.0/src/BIOS/MSHARD.ASM new file mode 100644 index 0000000..51c0dc8 --- /dev/null +++ b/v4.0/src/BIOS/MSHARD.ASM @@ -0,0 +1,427 @@ +;*** +; Title: Disk +; C: (C) Copyright 1988 by Microsoft corp. +; Date: 1/11/85 +; +; There is a bug in some versions of IBM's AT ROM BIOS. +; Interrupts are not disabled during read operations. +; +; Use: This program should be chained in line with the disk +; interupt 13h, it intercepts read calls to the hard disk +; and handles them appropriately. For other functions it +; passes controll to OLD13, which should contain the +; address of the AT ROM disk routine. The entry point for +; this program is IBM_DISK_IO. +; + + + .286c ;Use 80286 non-protected mode + +BIOSEG = 040h ;Segment for ROM BIOS Data +ROMSEG = 0F000h ;Segment of ROM + + +BAD_DISK = 01 + +HF_PORT = 01F0h +HF_REG_PORT = 03F6h + +;* Offsets into Fixed disk parameter table +FDP_PRECOMP = 5 +FDP_CONTROL = 8 + +DATA SEGMENT AT BIOSEG ;ROM BIOS data segment + + ORG 42h +CMD_BLOCK DB 6 DUP (?) + +;* Offsets into CMD_BLOCK for registers +PRE_COMP = 0 ;Write Pre-compensation +SEC_CNT = 1 ;Sector count +SEC_NUM = 2 ;Sector number +CYL_LOW = 3 ;Cylinder number, low part +CYL_HIGH = 4 ;Cylinder number, high part +DRV_HEAD = 5 ;Drive/Head (Bit 7 = ECC mode, Bit 5 = 512 byte sectors, + ; Bit 4 = drive number, Bits 3-0 have head number) +CMD_REG = 6 ;Command register + + + ORG 074h + +DISK_STATUS1 DB ? +HF_NUM DB ? +CONTROL_BYTE DB ? + +DATA ENDS + + + +;*** Define where the ROM routines are actually located +ROM SEGMENT AT ROMSEG + + ORG 02E1Eh +ROMCOMMAND PROC FAR +ROMCOMMAND ENDP + + ORG 02E7Fh +ROMWAIT PROC FAR +ROMWAIT ENDP + + ORG 02EE2h +ROMWAIT_DRQ PROC FAR +ROMWAIT_DRQ ENDP + + ORG 02EF8h +ROMCHECK_STATUS PROC FAR +ROMCHECK_STATUS ENDP + + ORG 02F69h +ROMCHECK_DMA PROC FAR +ROMCHECK_DMA ENDP + + ORG 02F8Eh +ROMGET_VEC PROC FAR +ROMGET_VEC ENDP + + ORG 0FF65h +ROMFRET PROC FAR ;Far return at F000:FF65 in AT ROM. +ROMFRET ENDP + +ROM ENDS + + +CODE SEGMENT BYTE PUBLIC 'code' + +EXTRN OLD13:DWORD ;Link to AT bios int 13h + +PUBLIC IBM_DISK_IO + + + ASSUME CS:CODE + ASSUME DS:DATA + + +;*** IBM_DISK_IO - main routine, fixes AT ROM bug +; +; ENTRY: (AH) = function, 02 or 0A for read. +; (DL) = drive number (80h or 81h). +; (DH) = head number. +; (CH) = cylinder number. +; (CL) = Sector number (high 2 bits has cylinder number). +; (AL) = number of sectors. +; (ES:BX) = address of read buffer. +; For more on register contents see ROM BIOS listing. +; Stack set up for return by an IRET. +; +; EXIT: (AH) = status of current operation. +; (CY) = 1 IF failed, 0 if successful. +; For other register contents see ROM BIOS listing. +; +; USES: +; +; +; WARNING: Uses OLD13 vector for non-read calls. +; Does direct calls to the AT ROM. +; Does segment arithmatic. +; +; EFFECTS: Performs DISK I/O operation. +; +IBM_DISK_IO PROC FAR + CMP DL, 80h + JB ATD1 ;Pass through floppy disk calls. + CMP AH, 02 + JE ATD2 ;Intercept call 02 (read sectors). + CMP AH, 0Ah + JE ATD2 ;and call 0Ah (read long). +ATD1: + JMP OLD13 ;Use ROM INT 13h handler. +ATD2: + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH DS + PUSH ES + PUSH AX + MOV AX,BIOSEG ;Establish BIOS segment addressing. + MOV DS,AX + MOV DISK_STATUS1, 0 ;Initially no error code. + AND DL, 07fh ;Mask to hard disk number + CMP DL, HF_NUM + JB ATD3 ;Disk number in range + MOV DISK_STATUS1, BAD_DISK + JMP SHORT ATD4 ;Disk number out of range error, return + +ATD3: + PUSH BX + MOV AX, ES ;Make ES:BX to Seg:000x form. + SHR BX, 4 + ADD AX, BX + MOV ES, AX + POP BX + AND BX,000Fh + PUSH CS + CALL CHECK_DMA + JC ATD4 ;Abort if DMA across segment boundary + + POP AX ;Restore AX register for SETCMD + PUSH AX + CALL SETCMD ;Set up command block for disk op + MOV DX, HF_REG_PORT + OUT DX, AL ;Write out command modifier + CALL DOCMD ;Carry out command +ATD4: +;; Old code - Carry cleared after set by logical or opearation +;; POP AX +;; MOV AH,DISK_STATUS1 ;On return AH has error code +;; STC +;; OR AH,AH +;; JNZ ATD5 ;Carry set if error +;; CLC +;;--------------------------------------------------- +;; New Code - Let Logical or clear carry and then set carry if ah!=0 +;; And save a couple bytes while were at it. + POP AX + MOV AH,DISK_STATUS1 ;On return AH has error code + OR AH,AH + JZ ATD5 ;Carry set if error + STC + +ATD5: + POP ES + POP DS + POP DI + POP DX + POP CX + POP BX + RET 2 ;Far return, dropping flags +IBM_DISK_IO ENDP + + + +;*** SETCMD - Set up CMD_BLOCK for the disk operation +; +; ENTRY: (DS) = BIOS Data segment. +; (ES:BX) in seg:000x form. +; Other registers as in INT 13h call +; +; EXIT: CMD_BLOCK set up for disk read call. +; CONTROL_BYTE set up for disk operation. +; (AL) = Control byte modifier +; +; +; Sets the fields of CMD_BLOCK using the register contents +; and the contents of the disk parameter block for the given drive. +; +; WARNING: (AX) destroyed. +; Does direct calls to the AT ROM. +; +SETCMD PROC NEAR + MOV CMD_BLOCK[SEC_CNT], AL + MOV CMD_BLOCK[CMD_REG], 020h ;Assume function 02 + CMP AH, 2 + JE SETC1 ;CMD_REG = 20h if function 02 (read) + MOV CMD_BLOCK[CMD_REG], 022h ;CMD_REG = 22h if function 0A (" long) +SETC1: ;No longer need value in AX + MOV AL, CL + AND AL, 03fh ;Mask to sector number + MOV CMD_BLOCK[SEC_NUM], AL + MOV CMD_BLOCK[CYL_LOW], CH + MOV AL, CL + SHR AL, 6 ;Get two high bits of cylender number + MOV CMD_BLOCK[CYL_HIGH], AL + MOV AX, DX + SHL AL, 4 ;Drive number + AND AH, 0Fh + OR AL, AH ;Head number + OR AL, 0A0h ;Set ECC and 512 bytes per sector + MOV CMD_BLOCK[DRV_HEAD], AL + PUSH ES ;GET_VEC destroys ES:BX + PUSH BX + PUSH CS + CALL GET_VEC + MOV AX, ES:FDP_PRECOMP[BX] ;Write pre-comp from disk parameters + SHR AX, 2 + MOV CMD_BLOCK[PRE_COMP],AL ;Only use low part + MOV AL, ES:FDP_CONTROL[BX] ;Control byte modifier + POP BX + POP ES + MOV AH, CONTROL_BYTE + AND AH, 0C0h ;Keep disable retry bits + OR AH, AL + MOV CONTROL_BYTE, AH + RET +SETCMD ENDP + + + +;*** DOCMD - Carry out READ operation to AT hard disk +; +; ENTRY: (ES:BX) = address for read in data. +; CMD_BLOCK set up for disk read. +; +; EXIT: Buffer at (ES:BX) contains data read. +; DISK_STATUS1 set to error code (0 if success). +; +; +; +; WARNING: (AX), (BL), (CX), (DX), (DI) destroyed. +; No check is made for DMA boundary overrun. +; +; EFFECTS: Programs disk controller. +; Performs disk input. +; +DOCMD PROC NEAR + MOV DI, BX ;(ES:DI) = data buffer addr. + PUSH CS + CALL COMMAND + JNZ DOC3 +DOC1: + PUSH CS + CALL WAITT ;Wait for controller to complete read + JNZ DOC3 + MOV CX, 100h ;256 words per sector + MOV DX, HF_PORT + CLD ;String op goes up + CLI ;Disable interrupts (BUG WAS FORGETTING THIS) + REPZ INSW ;Read in sector + STI + TEST CMD_BLOCK[CMD_REG], 02 + JZ DOC2 ;No ECC bytes to read. + PUSH CS + CALL WAIT_DRQ + JC DOC3 + MOV CX, 4 ;4 bytes of ECC + MOV DX, HF_PORT + CLI + REPZ INSB ;Read in ECC + STI +DOC2: + PUSH CS + CALL CHECK_STATUS + JNZ DOC3 ;Operation failed + DEC CMD_BLOCK[SEC_CNT] + JNZ DOC1 ;Loop while more sectors to read +DOC3: + RET +DOCMD ENDP + + + +;*** GET_VEC - Get pointer to hard disk parameters. +; +; ENTRY: (DL) = Low bit has hard disk number (0 or 1). +; +; EXIT: (ES:BX) = address of disk parameters table. +; +; USES: AX for segment computation. +; +; Loads ES:BX from interrupt table in low memory, vector 46h (disk 0) +; or 70h (disk 1). +; +; WARNING: (AX) destroyed. +; This does a direct call to the AT ROM. +; +GET_VEC PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMGET_VEC +GET_VEC ENDP + + + +;*** COMMAND - Send contents of CMD_BLOCK to disk controller. +; +; ENTRY: Control_byte +; CMD_BLOCK - set up with values for hard disk controller. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR for no error. +; +; +; WARNING: (AX), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +; EFFECTS: Programs disk controller. +; +COMMAND PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCOMMAND +COMMAND ENDP + + + +;*** WAITT - Wait for disk interrupt +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR if no error. +; +; +; WARNING: (AX), (BL), (CX) destroyed. +; Does a direct call to the AT ROM. +; +; EFFECTS: Calls int 15h, function 9000h. +; +WAITT PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMWAIT +WAITT ENDP + + + +;*** WAIT_DRQ - Wait for data request. +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; CY if error, NC if no error. +; +; +; WARNING: (AL), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +WAIT_DRQ PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMWAIT_DRQ +WAIT_DRQ ENDP + + + +;*** CHECK_STATUS - Check hard disk status. +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR if no error. +; +; +; WARNING: (AX), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +CHECK_STATUS PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCHECK_STATUS +CHECK_STATUS ENDP + + + +;*** CHECK_DMA - check for DMA overrun 64k segment. +; +; ENTRY: (ES:BX) = addr. of memory buffer in seg:000x form. +; CMD_BLOCK set up for operation. +; +; EXIT: DISK_STATUS1 - Error code. +; CY if error, NC if no error. +; +; +; WARNING: Does a direct call to the AT ROM. +; +CHECK_DMA PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCHECK_DMA +CHECK_DMA ENDP + + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSINIT.ASM b/v4.0/src/BIOS/MSINIT.ASM new file mode 100644 index 0000000..d00c8af --- /dev/null +++ b/v4.0/src/BIOS/MSINIT.ASM @@ -0,0 +1,2819 @@ + PAGE ,132 ; + %OUT ...MSINIT.ASM +;======================================================= +;REVISION HISTORY: +;AN000; - NEW Version 4.00. J.K. +;AC000; - Modified Line 4.00. J.K. +;ANxxx; - PTMyyy +;============================================================================== +;AN001; P87 Set the value of MOTOR START TIME Variable 6/25/87 J.K. +;AN002; P40 Boot from the system with no floppy diskette drives 6/26/87 J.K. +;AN003; D9 Double Word MOV instruction for 386 based machine 7/1/87 J.K. +;AN004; D64 Extend DOS 3.3 FAT tables to 64 K entries. 7/8/87 J.K. +;AN005; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN006; p941 D113 does not implemented properly. 9/11/87 J.K. +;AN007; p969 Should Honor OS2 boot record. 9/11/87 J.K. +;AN008; p985 Allow I/O access to unformtted media 9/14/87 J.K. +;AN009; p1535 Disallow I/O access to unformtted media 10/15/87 J.K. +;AN010; p2349 Cover DOS 3.3 and below FDISK bug 11/10/87 J.K. +;AN011; P2431 OS2 boot record version number is at offset 7 (not 8)11/12/87 J.K. +;AN012; P2900 DOS 4.0 does not recognize 3.0 formatted media 12/18/87 J.K. +;AN013; P3409 Extended keyboard not recognized 02/05/88 J.K. +;AN014; D486 Share installation for big media 02/23/88 J.K. +;AN015; P3929 Boot record buffer overlaps MSBIO code 03/18/88 J.K. +;============================================================================== + + itest = 0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSDSKPR.INC + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + INCLUDE MSEXTRN.INC + INCLUDE BIOSTRUC.INC + INCLUDE CMOSEQU.INC + include cputype.inc + +; THE FOLLOWING LABEL DEFINES THE END OF THE AT ROM PATCH. THIS IS USED AT +; CONFIGURATION TIME. +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + + PUBLIC ENDATROM ;NOT REFERENCES EXTERNALLY, BUT + ; JUST TO CAUSE ENTRY IN LINK MAP +ENDATROM LABEL BYTE + +;CMOS Clock setting support routines used by MSCLOCK. +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + + EXTRN base_century:byte + EXTRN base_year:byte + EXTRN month_tab:byte + + public Daycnt_to_day ;J.K. 4/30/86 for real time clock support +Daycnt_to_day proc near ;J.K. 4/30/86 for real time clock support +;Entry: [DAYCNT] = number of days since 1-1-80 +;Return: CH - centry in BCD, CL - year in BCD, DH - month in BCD, DL - day in BCD + + push [daycnt] ;save daycnt + cmp daycnt, (365*20+(20/4)) ;# of days from 1-1-1980 to 1-1-2000 + jae century20 + mov base_century, 19 + mov base_year, 80 + jmp years +century20: ;20th century + mov base_century, 20 + mov base_year, 0 + sub daycnt, (365*20+(20/4)) ;adjust daycnt +years: + xor dx, dx + mov ax, daycnt + mov bx, (366+365*3) ;# of days in a Leap year block + div bx ;AX = # of leap block, DX = daycnt + mov daycnt, dx ;save daycnt left +; or ah, ah ;ax should be less than 256 +; jz OK1 +; jmp Erroroccur +;OK1: + mov bl,4 + mul bl ;AX = # of years. Less than 100 years! + add base_year, al ;So, ah = 0. Adjust year accordingly. + inc daycnt ;set daycnt to 1 base + cmp daycnt, 366 ;the daycnt here is the remainder of the leap year block. + jbe Leapyear ;So, it should within 366+355+355+355 days. + inc base_year ;First if daycnt <= 366, then leap year + sub daycnt, 366 ;else daycnt--, base_year++; + ;And the next three years are regular years. + mov cx, 3 +Regularyear: + cmp daycnt, 365 ;for(i=1; i>3 or daycnt <=365;i++) + jbe YearDone ;{if (daycnt > 365) + inc base_year ; { daycnt -= 365 + sub daycnt, 365 ; } + loop regularyear ;} +; jmp Erroroccur ;cannot come to here +Leapyear: + mov byte ptr month_tab+1,29 ;leap year. change the month table. +Yeardone: + xor bx,bx + xor dx,dx + mov ax, daycnt + mov si, offset month_tab + mov cx, 12 +Months: + inc bl ; + mov dl, byte ptr ds:[si] ;compare daycnt for each month until fits + cmp ax, dx ;dh=0. + jbe Month_done + inc si ;next month + sub ax, dx ;adjust daycnt + loop Months +; jmp Erroroccur +Month_done: + mov byte ptr month_tab+1, 28 ;restore month table value + mov dl, bl + mov dh, base_year + mov cl, base_century ;now, al=day, dl=month,dh=year,cl=century + call word ptr BinToBCD ;Oh my!!! To save 15 bytes, Bin_To_BCD proc + ;was relocated seperately from Daycnt_to_Day proc. +; call Bin_to_bcd ;convert "day" to bcd + xchg dl, al ;dl = bcd day, al = month + call word ptr BinToBCD +; call Bin_to_bcd + xchg dh, al ;dh = bcd month, al = year + call word ptr BinToBCD +; call Bin_to_bcd + xchg cl, al ;cl = bcd year, al = century + call word ptr BinToBCD +; call Bin_to_bcd + mov ch, al ;ch = bcd century + pop [daycnt] ;restore original value + ret +Daycnt_to_day endp + + public EndDaycntToDay +EndDaycntToDay label byte + + public Bin_to_bcd +Bin_to_bcd proc near ;J.K. 4/30/86 for real time clock support +;Convert a binary input in AL (less than 63h or 99 decimal) +;into a bcd value in AL. AH destroyed. + push cx + xor ah, ah + mov cl, 10 + div cl ;al - high digit for bcd, ah - low digit for bcd + mov cl, 4 + shl al, cl ;mov the high digit to high nibble + or al, ah + pop cx + ret +Bin_to_bcd endp + + Public EndCMOSClockset ;End of supporting routines for CMOS clock setting. +EndCMOSClockset label byte +; + + EXTRN INT6C_RET_ADDR:DWORD ; RETURN ADDRESS FROM INT 6C + EXTRN BIN_DATE_TIME:BYTE + EXTRN MONTH_TABLE:WORD + EXTRN DAYCNT2:WORD + EXTRN FEB29:BYTE + EXTRN TimeToTicks:Word ;indirect intra-segment call address + + EVENB +; +; THE K09 REQUIRES THE ROUTINES FOR READING THE CLOCK BECAUSE OF THE SUSPEND/ +; RESUME FACILITY. THE SYSTEM CLOCK NEEDS TO BE RESET AFTER RESUME. +; + ASSUME ES:NOTHING + +; THE FOLLOWING ROUTINE IS EXECUTED AT RESUME TIME WHEN THE SYSTEM +; POWERED ON AFTER SUSPENSION. IT READS THE REAL TIME CLOCK AND +; RESETS THE SYSTEM TIME AND DATE, AND THEN IRETS. + +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + +INT6C PROC FAR + PUSH CS + POP DS + + ASSUME DS:CODE + + POP WORD PTR INT6C_RET_ADDR ; POP OFF RETURN ADDRESS + POP WORD PTR INT6C_RET_ADDR+2 + POPF + CALL READ_REAL_DATE ; GET THE DATE FROM THE CLOCK + CLI + MOV DS:DAYCNT,SI ; UPDATE DOS COPY OF DATE + STI + CALL READ_REAL_TIME ; GET THE TIME FROM THE RTC + CLI +;SB33019*************************************************************** + MOV AH, 01h ; COMMAND TO SET THE TIME ;SB;3.30 + INT 1Ah ; CALL ROM-BIOS TIME ROUTINE ;SB;3.30 +;SB33019*************************************************************** + STI + JMP INT6C_RET_ADDR ; LONG JUMP + +INT6C ENDP + + + INCLUDE READCLOC.INC + INCLUDE CLOCKSUB.INC + + PUBLIC ENDK09 ;NOT REFERENCES EXTERNALLY, BUT + ; JUST TO CAUSE ENTRY IN LINK MAP +ENDK09 LABEL BYTE + ASSUME DS:NOTHING,ES:NOTHING + +;********************************************************* +; SYSTEM INITIALIZATION +; +; THE ENTRY CONDITIONS ARE ESTABLISHED BY THE BOOTSTRAP +; LOADER AND ARE CONSIDERED UNKNOWN. THE FOLLOWING JOBS +; WILL BE PERFORMED BY THIS MODULE: +; +; 1. ALL DEVICE INITIALIZATION IS PERFORMED +; 2. A LOCAL STACK IS SET UP AND DS:SI ARE SET +; TO POINT TO AN INITIALIZATION TABLE. THEN +; AN INTER-SEGMENT CALL IS MADE TO THE FIRST +; BYTE OF THE DOS +; 3. ONCE THE DOS RETURNS FROM THIS CALL THE DS +; REGISTER HAS BEEN SET UP TO POINT TO THE START +; OF FREE MEMORY. THE INITIALIZATION WILL THEN +; LOAD THE COMMAND PROGRAM INTO THIS AREA +; BEGINNING AT 100 HEX AND TRANSFER CONTROL TO +; THIS PROGRAM. +; +;******************************************************** + +;SYSIZE=200H ;NUMBER OF PARAGRAPHS IN SYSINIT MODULE +sysize=500h ;AC000; + +; DRVFAT MUST BE THE FIRST LOCATION OF FREEABLE SPACE! + EVENB +DRVFAT DW 0000 ;DRIVE AND FAT ID OF DOS +BIOS$_L DW 0000 ;FIRST SECTOR OF DATA (Low word) +bios$_H dw 0000 ;First sector of data (High word) +DOSCNT DW 0000 ;HOW MANY SECTORS TO READ +FBIGFAT DB 0 ; FLAGS FOR DRIVE +;an004 +;FATLEN DW ? ; NUMBER OF SECTORS IN FAT. +FATLOC DW ? ; SEG ADDR OF FAT SECTOR +Init_BootSeg dw ? ;AN015; seg addr of buffer for reading boot record +ROM_drv_num db 80h ;AN000; rom drv number +;Boot_Sec_Per_Fat dw 0 ;AN000; Boot media sectors/FAT +Md_SectorSize dw 512 ;AN004; Used by Get_Fat_Sector proc. +Temp_Cluster dw 0 ;AN004; Used by Get_Fat_Sector proc. +Last_Fat_SecNum dw -1 ;AN004; Used by Get_Fat_Sector proc. + +; THE FOLLOWING TWO BYTES ARE USED TO SAVE THE INFO RETURNED BY INT 13, AH = 8 +; CALL TO DETERMINE DRIVE PARAMETERS. +NUM_HEADS DB 2 ; NUMBER OF HEADS RETURNED BY ROM +SEC_TRK DB 9 ; SEC/TRK RETURNED BY ROM +NUM_CYLN DB 40 ; NUMBER OF CYLINDERS RETURNED BY ROM + +FakeFloppyDrv db 0 ;AN002; If 1, then No diskette drives in the system. + +BOOTBIAS = 200H +BOOT_ADDR = 7C00H +EXT_BOOT_SIG_OFF = 11+size BPB_TYPE ;AN000; 3 byte jmp+8 byte OEM +extended bpb + + + EVENB +DISKTABLE DW 512, 0100H, 64, 0 + DW 2048, 0201H, 112, 0 + DW 8192, 0402H, 256, 0 + DW 32680, 0803H, 512, 0 ;Warning !!! Old values +; DW 20740, 0803H, 512, 0 ;PTM P892 J.K. 12/3/86 DOS 3.3 will use this. + ;J.K.3/16/87 P54 Return back to old value for compatibility.!!! + DW 65535, 1004H, 1024, 0 + +;DISKTABLE2 DW 32680, 0803H, 512, 0 ;Warning !!! Old values ;J.K.3/16/87 P54 Return to old value!!! +;DISKTABLE2 DW 20740, 0803H, 512, 0 ;PTM p892 J.K. 12/3/86 DOS 3.3 will use this. +; DW 65535, 0402H, 512, FBIG +;AN000; +;DISKTABLE2 dw 0, 32680, 0803h, 512, 0 ;table with the assumption of the +; dw 2h, 0000h, 0402h, 512, FBIG ;total fat size <= 64KB. +; dw 4h, 0000h, 0803h, 512, FBIG ;-This will cover upto 134 MB +; dw 8h, 0000h, 1004h, 512, FBIG ;-This will cover upto 268 MB +; dw 10h, 0000h, 2005h, 512, FBIG ;-This will cover upto 536 MB + +;AN004 Default DiskTable under the assumption of Total FAT size <= 128 KB, and +; the maxium size of FAT entry = 16 Bit. +DiskTable2 dw 0, 32680, 0803h, 512, 0 ;For compatibility. + dw 4h, 0000h, 0402h, 512, FBIG ;Covers upto 134 MB media. + dw 8h, 0000h, 0803h, 512, FBIG ; upto 268 MB + dw 10h, 0000h, 1004h, 512, FBIG ; upto 536 MB + dw 20h, 0000h, 2005h, 512, FBIG ; upto 1072 MB + dw 40h, 0000h, 4006h, 512, FBIG ; upto 2144 MB + dw 80h, 0000h, 8007h, 512, FBIG ; upto 4288 MB... + +;****************************************************************************** +;Variables for Mini disk initialization - J.K. 4/7/86 +;****************************************************************************** +End_Of_BDSM dw ? ;offset value of the ending address + ;of BDSM table. Needed to figure out + ;the Final_DOS_Location. +numh db 0 ;number of hard files +mininum db 0 ;logical drive number for mini disk(s) +num_mini_dsk db 0 ;# of mini disk installed +Rom_Minidsk_num db 80h ;physical mini disk number +Mini_HDLIM dw 0 +Mini_SECLIM dw 0 +Mini_BPB_ptr dw 0 ;temporary variable used to save the + ;Mini Disk BPB pointer address in DskDrvs. +;J.K. 4/7/86 End of Mini Disk Init Variables ********************************** + + +BIOS_DATE DB '01/10/84',0 ;This is used for checking AT ROM BIOS date. + +; THE FOLLOWING ARE THE RECOMMENDED BPBS FOR THE MEDIA THAT WE KNOW OF SO +; FAR. + +; 48 TPI DISKETTES + EVENB +BPB48T DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 2*9*40 + DB 0FDH + DW 2 + DW 9 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + +; 96TPI DISKETTES + EVENB +BPB96T DW 512 + DB 1 + DW 1 + DB 2 + DW 224 + DW 2*15*80 + DB 0F9H + DW 7 + DW 15 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + +BPBSIZ = $-BPB96T + +; 3 1/2 INCH DISKETTE BPB + + EVENB +BPB35 DW 512 + DB 2 + DW 1 ; DOUBLE SIDED WITH 9 SEC/TRK + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + + EVENB +BPBTABLE DW BPB48T ; 48TPI DRIVES + DW BPB96T ; 96TPI DRIVES + DW BPB35 ; 3.5" DRIVES + ;DW BPB48T ; NOT USED - 8" DRIVES + ;DW BPB48T ; NOT USED - 8" DRIVES + ;DW BPB48T ; NOT USED - HARD FILES + ;DW BPB48T ; NOT USED - TAPE DRIVES + ;DW BPB48T ; NOT USED - OTHER + +PATCHTABLE LABEL BYTE + DW 10,MEDIA_PATCH + DW 3,GETBP1_PATCH + DW 3,SET_PATCH + DW 3,DISKIO_PATCH + DW 3,DSKERR + DW 10,CHANGED_PATCH + DW 3,INIT_PATCH + DW 0 + + ASSUME DS:NOTHING,ES:NOTHING + +; +; ENTRY FROM BOOT SECTOR. THE REGISTER CONTENTS ARE: +; DL = INT 13 DRIVE NUMBER WE BOOTED FROM +; CH = MEDIA BYTE +; BX = FIRST DATA SECTOR ON DISK. +;J.K. +; AX = first data sector (High) +; DI = Sectors/FAT for the boot media. +; + PUBLIC INIT +INIT PROC NEAR + MESSAGE FTESTINIT,<"IBMBIO",CR,LF> + CLI + push ax + XOR AX,AX + MOV DS,AX + pop ax +;J.K. MSLOAD will check the extended boot record and set AX, BX accordingly. + +;SB34INIT000************************************************************* +;SB MSLOAD passes a 32 bit sector number hi word in ax and low in bx +;SB Save this in cs:BIOS$_H and cs:BIOS$_L. This is for the start of +;SB data sector of the BIOS. + + mov cs:BIOS$_H,ax + mov cs:BIOS$_L,bx + +;SB34INIT000************************************************************* + +;J.K. With the following information from MSLOAD, we don't need the +; Boot sector any more.-> This will solve the problem of 29 KB size +; limitation of MSBIO.COM file. +;J.K. AN004 - Don't need this information any more, since we are not going to +; read the whole FAT into memory. +; mov cs:Boot_Sec_Per_FAT, di ;sectors/FAT for boot media. ;AN000; + +; +; PRESERVE ORIGINAL INT 13 VECTOR +; WE NEED TO SAVE INT13 IN TWO PLACES IN CASE WE ARE RUNNING ON AN AT. +; ON ATS WE INSTALL THE IBM SUPPLIED ROM_BIOS PATCH DISK.OBJ WHICH HOOKS +; INT13 AHEAD OF ORIG13. SINCE INT19 MUST UNHOOK INT13 TO POINT TO THE +; ROM INT13 ROUTINE, WE MUST HAVE THAT ROM ADDRESS ALSO STORED AWAY. +; + MOV AX,DS:[13H*4] + MOV WORD PTR OLD13,AX + MOV WORD PTR ORIG13,AX + MOV AX,DS:[13H*4+2] + MOV WORD PTR OLD13+2,AX + MOV WORD PTR ORIG13+2,AX +; +; SET UP INT 13 FOR NEW ACTION +; + MOV WORD PTR DS:[13H*4],OFFSET BLOCK13 + MOV DS:[13H*4+2],CS +; +; PRESERVE ORIGINAL INT 19 VECTOR +; + MOV AX,DS:[19H*4] + MOV WORD PTR ORIG19,AX + MOV AX,DS:[19H*4+2] + MOV WORD PTR ORIG19+2,AX +; +; SET UP INT 19 FOR NEW ACTION +; + MOV WORD PTR DS:[19H*4],OFFSET INT19 + MOV DS:[19H*4+2],CS + STI + INT 11H ;GET EQUIPMENT STATUS +;J.K.6/24/87 We have to support a system that does not have any diskette +;drives but only hardfiles. This system will IPL from the hardfile. +;If the equipment flag bit 0 is 1, then the system has diskette drive(s). +;Otherwise, the system only have hardfiles. +;Important thing is that still, for compatibility reason, the drive letter +;for the hardfile start from "C". So, we still need to allocate dummy BDS +;drive A and driver B. In SYSINIT time, we are going to set CDS table entry +;of DPB pointer for these drives to 0, so any user attempt to access this +;drives will get "Invalid drive letter ..." message. We are going to +;establish "FAKEFLOPPYDRV" flag. ***SYSINIT module should call INT 11h to check +;if there are any diskette drivers in the system or not.!!!*** + +;SB34INIT001************************************************************** +;SB check the register returned by the equipment determination interrupt +;SB we have to handle the case of no diskettes in the system by faking +;SB two dummy drives. +;SB if the register indicates that we do have floppy drives we don't need +;SB to do anything special. +;SB if the register indicates that we don't have any floppy drives then +;SB what we need to do is set the FakeFloppyDrv variable, change the +;SB register to say that we do have floppy drives and then go to execute +;SB the code which starts at NOTSINGLE. This is because we can skip the +;SB code given below which tries to find if there are one or two drives +;SB since we already know about this. 6 LOCS + + test ax,1 + jnz DO_FLOPPY + mov cs:FakeFloppyDrv,1 ; fake floppy + mov ax,1 ; set to indicate 2 floppies + jmp short NOTSINGLE + +DO_FLOPPY: + +;SB34INIT001************************************************************** + ; + ; Determine if there are one or two diskette drives in system + ; + ROL AL,1 ;PUT BITS 6 & 7 INTO BITS 0 & 1 + ROL AL,1 + AND AX,3 ;ONLY LOOK AT BITS 0 & 1 + JNZ NOTSINGLE ;ZERO MEANS SINGLE DRIVE SYSTEM + INC AX ;PRETEND IT'S A TWO DRIVE SYSTEM + INC CS:SINGLE ;REMEMBER THIS +NOTSINGLE: + INC AX ;AX HAS NUMBER OF DRIVES, 2-4 + ;IS ALSO 0 INDEXED BOOT DRIVE IF WE + ; BOOTED OFF HARD FILE + MOV CL,AL ;CH IS FAT ID, CL # FLOPPIES + TEST DL,80H ;BOOT FROM FLOPPY ? + JNZ GOTHRD ;NO. + XOR AX,AX ;INDICATE BOOT FROM DRIVE A +GOTHRD: +; +; AX = 0-BASED DRIVE WE BOOTED FROM +; BIOS$_L, BIOS$_H set. +; CL = NUMBER OF FLOPPIES INCLUDING FAKE ONE +; CH = MEDIA BYTE +; + MESSAGE FTESTINIT,<"INIT",CR,LF> + XOR DX,DX + CLI + MOV SS,DX + MOV SP,700H ;LOCAL STACK + STI + ASSUME SS:NOTHING + + PUSH CX ;SAVE NUMBER OF FLOPPIES AND MEDIA BYTE + MOV AH,CH ;SAVE FAT ID TO AH + PUSH AX ;SAVE BOOT DRIVE NUMBER, AND MEDIA BYTE +;J.K. Let Model_byte, Secondary_Model_Byte be set here!!! +;SB33020****************************************************************** + mov ah,0c0h ; return system environment ;SB;3.30 + int 15h ; call ROM-Bios routine ;SB;3.30 +;SB33020****************************************************************** + jc No_Rom_System_Conf ; just use Model_Byte + cmp ah, 0 ; double check + jne No_Rom_System_Conf + mov al, ES:[BX.bios_SD_modelbyte] ;get the model byte + mov [Model_Byte], al + mov al, ES:[BX.bios_SD_scnd_modelbyte] ;secondary model byte + mov [Secondary_Model_Byte], al + jmp short Turn_Timer_On +No_Rom_System_Conf: + MOV SI,0FFFFH ;MJB001 + MOV ES,SI ;MJB001 + MOV AL,ES:[0EH] ; GET MODEL BYTE ARR 2.41 + MOV MODEL_BYTE,AL ; SAVE MODEL BYTE ARR 2.41 +Turn_Timer_On: + MOV AL,EOI + OUT AKPORT,AL ;TURN ON THE TIMER + +; NOP out the double word MOV instruction in MSDISK, if +; this is not a 386 machine... + Get_CPU_Type ; macro to determine cpu type + cmp ax, 2 ; is it a 386? + je Skip_Patch_DoubleWordMov; yes: skip the patch + +Patch_DoubleWordMov: + push es ;AN003; + push cs ;AN003; + pop es ;AN003;ES -> CS + mov di, offset DoubleWordMov ;AN003; + mov cx, 3 ;AN003; 3 bytes to NOP + mov al, 90h ;AN003; + rep stosb ;AN003; + pop es ;AN003; +Skip_Patch_DoubleWordMov: ;AN003; + MESSAGE FTESTINIT,<"COM DEVICES",CR,LF> +;SB33IN1********************************************************* + + mov si,offset COM4DEV + call AUX_INIT + mov si,offset COM3DEV + call AUX_INIT +;SB33IN1********************************************************* + MOV SI,OFFSET COM2DEV + CALL AUX_INIT ;INIT COM2 + MOV SI,OFFSET COM1DEV + CALL AUX_INIT ;INIT COM1 + + MESSAGE FTESTINIT,<"LPT DEVICES",CR,LF> + MOV SI,OFFSET LPT3DEV + CALL PRINT_INIT ;INIT LPT3 + MOV SI,OFFSET LPT2DEV + CALL PRINT_INIT ;INIT LPT2 + MOV SI,OFFSET LPT1DEV + CALL PRINT_INIT ;INIT LPT1 + + XOR DX,DX + MOV DS,DX ;TO INITIALIZE PRINT SCREEN VECTOR + MOV ES,DX + + XOR AX,AX + MOV DI,INITSPOT + STOSW ;INIT FOUR BYTES TO 0 + STOSW + + MOV AX,CS ;FETCH SEGMENT + + MOV DS:WORD PTR BRKADR,OFFSET CBREAK ;BREAK ENTRY POINT + MOV DS:BRKADR+2,AX ;VECTOR FOR BREAK + +;*********************************************** ARR 2.15 +; SINCE WE'RE FIRST IN SYSTEM, NO NEED TO CHAIN THIS. +; CLI ; ARR 2.15 DON'T GET BLOWN +; MOV DS:WORD PTR TIMADR,OFFSET TIMER ; ARR 2.15 TIMER ENTRY POINT +; MOV DS:TIMADR+2,AX ; ARR 2.15 VECTOR FOR TIMER +; STI +;*********************************************** ARR 2.15 + +; BAS DEBUG + MOV DS:WORD PTR CHROUT*4,OFFSET WORD PTR OUTCHR + MOV DS:WORD PTR CHROUT*4+2,AX + + MESSAGE FTESTINIT,<"INTERRUPT VECTORS",CR,LF> + MOV DI,4 + MOV BX,OFFSET INTRET ;WILL INITIALIZE REST OF INTERRUPTS + XCHG AX,BX + STOSW ;LOCATION 4 + XCHG AX,BX + STOSW ;INT 1 ;LOCATION 6 + ADD DI,4 + XCHG AX,BX + STOSW ;LOCATION 12 + XCHG AX,BX + STOSW ;INT 3 ;LOCATION 14 + XCHG AX,BX + STOSW ;LOCATION 16 + XCHG AX,BX + STOSW ;INT 4 ;LOCATION 18 + + MOV DS:WORD PTR 500H,DX ;SET PRINT SCREEN & BREAK =0 + MOV DS:WORD PTR LSTDRV,DX ;CLEAN OUT LAST DRIVE SPEC + + MESSAGE FTESTINIT,<"DISK PARAMETER TABLE",CR,LF> + +;;** MOV SI,WORD PTR DS:DSKADR ; ARR 2.41 +;;** MOV DS,WORD PTR DS:DSKADR+2 ; DS:SI -> CURRENT TABLE ARR 2.41 +;;** +;;** MOV DI,SEC9 ; ES:DI -> NEW TABLE ARR 2.41 +;;** MOV CX,SIZE DISK_PARMS ; ARR 2.41 +;;** REP MOVSB ; COPY TABLE ARR 2.41 +;;** PUSH ES ; ARR 2.41 +;;** POP DS ; DS = 0 ARR 2.41 + +;;** MOV WORD PTR DS:DSKADR,SEC9 ; ARR 2.41 +;;** MOV WORD PTR DS:DSKADR+2,DS ; POINT DISK PARM VECTOR TO NEW TABLE + ; ARR 2.41 +;SB34INIT002****************************************************************** +;SB We need to initalise the cs:MotorStartup variable from the disk +;SB parameter table at SEC9. The offsets in this table are defined in +;SB the DISK_PARMS struc in MSDSKPRM.INC. 2 LOCS + + mov al,ds:SEC9 + DISK_MOTOR_STRT + mov cs:MotorStartup,al +;SB34INIT002****************************************************************** + CMP MODEL_BYTE,0FDH ; IS THIS AN OLD ROM? ARR 2.41 + JB NO_DIDDLE ; NO ARR 2.41 + MOV WORD PTR DS:(SEC9 + DISK_HEAD_STTL),0200H+NORMSETTLE + ; SET HEAD SETTLE AND MOTOR START + ; ON PC-1 PC-2 PC-XT HAL0 ARR 2.41 + MOV DS:(SEC9 + DISK_SPECIFY_1),0DFH + ; SET 1ST SPECIFY BYTE + ; ON PC-1 PC-2 PC-XT HAL0 ARR 2.41 +NO_DIDDLE: ; ARR 2.41 + INT 12H ;GET MEMORY SIZE--1K BLOCKS IN AX + MOV CL,6 + SHL AX,CL ;CONVERT TO 16-BYTE BLOCKS(SEGMENT NO.) + POP CX ; RETREIVE BOOT DRIVE NUMBER, AND FAT ID + MOV DRVFAT,CX ;SAVE DRIVE TO LOAD DOS, AND FAT ID + + PUSH AX +;J.K. Don't have to look at the boot addr. +; MOV DX,DS:(7C00H + 16H) ; NUMBER OF SECTORS/FAT FROM BOOT SEC +;an004 +; mov dx, cs:Boot_Sec_Per_FAT ;AC000;Do not use the bpb info from Boot record any more. +; XOR DH,DH +; MOV FATLEN,DX +; +; CONVERT SECTOR COUNT TO PARAGRAPH COUNT:512 BYTES / SEC / 16 BYTES / PARA +; = 32 PARA /SECTOR +; + +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SUB AX,DX ; ROOM FOR FAT + sub ax, 64 ;AN004; Room for FATLOC segment. (1 KB buffer) + MOV FATLOC,AX ; LOCATION TO READ FAT + sub ax, 64 ;Room for Boot Record buffer segment (1 KB) + mov Init_BootSeg, ax ;AN015; + POP AX + + MOV DX,SYSINITSEG + MOV DS,DX + + ASSUME DS:SYSINITSEG + + MOV WORD PTR DEVICE_LIST,OFFSET CONHEADER + MOV WORD PTR DEVICE_LIST+2,CS + + MOV MEMORY_SIZE,AX + INC CL + MOV DEFAULT_DRIVE,CL ;SAVE DEFAULT DRIVE SPEC + +;DOSSEG = (((END$ - START$)+15)/16)+BIOSEG+SYSIZE + +; BAS DEBUG +;MOV CURRENT_DOS_LOCATION,(((END$ - START$)+15)/16)+SYSIZE + MOV AX, OFFSET END$ + SUB AX, OFFSET START$ + ADD AX, 15 + RCR AX, 1 ; DIVIDE BY 16 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + ADD AX, SYSIZE + ADD AX, CODE + MOV CURRENT_DOS_LOCATION, AX +; BAS DEBUG +; ADD CURRENT_DOS_LOCATION,CODE + +; IMPORTANT: SOME OLD IBM HARDWARE GENERATES SPURIOUS INT F'S DUE TO BOGUS +; PRINTER CARDS. WE INITIALIZE THIS VALUE TO POINT TO AN IRET ONLY IF + +; 1) THE ORIGINAL SEGMENT POINTS TO STORAGE INSIDE VALID RAM. + +; 2) THE ORIGINAL SEGMENT IS 0F000:XXXX + +; THESES ARE CAPRICIOUS REQUESTS FROM OUR OEM FOR REASONS BEHIND THEM, READ +; THE DCR'S FOR THE IBM DOS 3.2 PROJECT. + + PUSH AX + + ASSUME ES:SYSINITSEG, DS:NOTHING + + MOV AX,SYSINITSEG + MOV ES,AX + + XOR AX,AX ; AX := SEGMENT FOR INT 15 + MOV DS,AX + MOV AX,WORD PTR DS:(0FH*4+2) + + CMP AX,ES:MEMORY_SIZE ; CONDITION 1 + JNA RESETINTF + + CMP AX,0F000H ; CONDITION 2 + JNE KEEPINTF + +RESETINTF: + MOV WORD PTR DS:[0FH*4],OFFSET INTRET + MOV WORD PTR DS:[0FH*4+2],CS +KEEPINTF: + POP AX + +; END IMPORTANT + +;SB34INIT003**************************************************************** +;SB We will check if the system has IBM extended key board by +;SB looking at a byte at 40:96. If bit 4 is set, then extended key board +;SB is installed, and we are going to set KEYRD_Func to 10h, KEYSTS_Func to 11h +;SB for the extended keyboard function. Use cx as the temporary register. 8 LOCS + + xor cx,cx + mov ds,cx + assume ds:nothing + mov cl,ds:0496h ; get keyboard flag + test cl,00010000b + jz ORG_KEY ; orginal keyboard + mov byte ptr KEYRD_func,10h ; extended keyboard + mov byte ptr KEYSTS_func,11h ; change for extended keyboard functions +ORG_KEY: + +;SB34INIT003**************************************************************** + +;************************************************************** +; WILL INITIALIZE THE NUMBER OF DRIVES +; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL +; THE INDICATIONS ARE AS FOLLOWS: +; +; BITS 7 6 DRIVES +; 0 0 1 +; 0 1 2 +; 1 0 3 +; 1 1 4 +;************************************************************** + PUSH CS + POP DS + PUSH CS + POP ES + + ASSUME DS:CODE,ES:CODE + + call CMOS_Clock_Read ;Before doing anythig else if CMOS clock exists, + ;then set the system time according to that. + ;Also, reset the cmos clock rate. + + MESSAGE FTESTINIT,<"DISK DEVICES",CR,LF> + + XOR SI,SI + MOV WORD PTR [SI],OFFSET HARDDRV ;SET UP POINTER TO HDRIVE + + POP AX ;NUMBER OF FLOPPIES AND FAT ID + XOR AH,AH ; CHUCK FAT ID BYTE + MOV HARDNUM,AL ;REMEMBER WHICH DRIVE IS HARD DISK + MOV DRVMAX,AL ;AND SET INITIAL NUMBER OF DRIVES + SHL AX,1 ;TWO BYTES PER ADDRESS + MOV DI,OFFSET DSKDRVS + ADD DI,AX ;POINT TO HARDFILE LOCATION + MOV SI,OFFSET HDSKTAB + MOVSW ;TWO ADDRESSES TO MOVE + MOVSW + MESSAGE FTESTINIT,<"BEFORE INT 13",CR,LF> +;SB33021******************************************************************** + mov DL, 80h ;SB ; tell rom bios to look at hard drives + mov AH, 8h ;SB ; set command to get drive parameter + int 13h ;SB ; call ROM-BIOS to get number of drives +;SB33021******************************************************************** + JC ENDDRV ;CARRY INDICATES OLD ROM, SO NO HARDFILE + MOV HNUM,DL +ENDDRV: + MESSAGE FTESTINIT,<"SETTING UP BDSS",CR,LF> + +; +; SCAN THE LIST OF DRIVES TO DETERMINE THEIR TYPE. WE HAVE THREE FLAVORS OF +; DISKETTE DRIVES: +; +; 48TPI DRIVES WE DO NOTHING SPECIAL FOR THEM +; 96TPI DRIVES MARK THE FACT THAT THEY HAVE CHANGELINE SUPPORT. +; 3 1/4 DRIVES MARK CHANGELINE SUPPORT AND SMALL. +; +; THE FOLLOWING CODE USES REGISTERS FOR CERTAIN VALUES: +; DL - PHYSICAL DRIVE +; DS:DI - POINTS TO CURRENT BDS +; CX - FLAG BITS FOR BDS +; DH - FORM FACTOR FOR THE DRIVE (1 - 48TPI, 2 - 96TPI, 3 - 3.5" MEDIUM) +; + XOR DL,DL ; START OUT WITH DRIVE 0. + PUSH CS + POP DS + ASSUME DS:CODE + + MOV EOT,9 + MOV DI,OFFSET START_BDS +;J.K.6/24/87 Check if the system has no physical diskette drives. +;J.K. If it is, then we don't have to set BDS tables. But since we +;J.K. pretend that we have 2 floppies, we are going to reserve two +;J.K. BDS tables for the fake drive A, and B. and set the end of link +;J.K. pointer. + +;SB34INIT004********************************************************* +;SB Check to see if we are faking floppy drives. If not we don't +;SB do anything special. If we are faking floppy drives we need +;SB to set aside two BDSs for the two fake floppy drives. We +;SB don't need to initalise any fields though. So starting at START_BDS +;SB use the link field in the BDS structure to go to the second BDS +;SB in the list and initalise it's link field to -1 to set the end of +;SB the list. Then jump to the routine at DoHard to allocate/initialise +;SB the BDS for HardDrives. + + cmp cs:FakeFloppyDrv,1 + jnz LOOP_DRIVE ; system has floppy + mov di,word ptr [di].link ; di <- first BDS link + mov di,word ptr [di].link ; di <- second BDS link + mov word ptr [di].link,-1 ; set end of link + jmp DoHard ; allocate/initialise BDS for HardDrives +;SB34INIT004********************************************************* + +LOOP_DRIVE: + CMP DL,DRVMAX + JB GOT_MORE + JMP DONE_DRIVES +GOT_MORE: + XOR CX,CX ; ZERO ALL FLAGS + MOV DI,WORD PTR [DI].LINK ; GET NEXT BDS + MOV DH,FF48TPI ; SET FORM FACTOR TO 48 TPI + MOV NUM_CYLN,40 ; 40 TRACKS PER SIDE + + PUSH DS + PUSH DI + PUSH DX + PUSH CX + PUSH ES + +;SB33022******************************************************************** + MOV AH, 8h ;GET DRIVE PARAMETERS ;SB;3.30 + INT 13h ;CALL ROM-BIOS ;SB;3.30 +;SB33022******************************************************************** + JNC PARMSFROMROM + JMP NOPARMSFROMROM ; GOT AN OLD ROM +PARMSFROMROM: +;J.K. 10/9/86 If CMOS is bad, it gives ES,AX,BX,CX,DH,DI=0. CY=0. +;In this case, we are going to put bogus informations to BDS table. +;We are going to set CH=39,CL=9,DH=1 to avoid divide overflow when +;they are calculated at the later time. This is just for the Diagnostic +;Diskette which need MSBIO,MSDOS to boot up before it sets CMOS. +;This should only happen with drive B. + + CMP CH,0 ; if ch=0, then cl,dh=0 too. + JNE PFR_OK + MOV CH,39 ; ROM gave wrong info. + MOV CL,9 ; Let's default to 360K. + MOV DH,1 +PFR_OK: + INC DH ; MAKE NUMBER OF HEADS 1-BASED + INC CH ; MAKE NUMBER OF CYLINDERS 1-BASED + MOV NUM_HEADS,DH ; SAVE PARMS RETURNED BY ROM + AND CL,00111111B ; EXTRACT SECTORS/TRACK + MOV SEC_TRK,CL + MOV NUM_CYLN,CH ; ASSUME LESS THAN 256 CYLINDERS!! +; MAKE SURE THAT EOT CONTAINS THE MAX NUMBER OF SEC/TRK IN SYSTEM OF FLOPPIES + CMP CL,EOT ; MAY SET CARRY + JBE EOT_OK + MOV EOT,CL +EOT_OK: + POP ES + POP CX + POP DX + POP DI + POP DS + +; CHECK FOR CHANGELINE SUPPORT ON DRIVE +;SB33023******************************************************************** + mov AH, 15h ;SB ; set command to get DASD type + int 13h ;SB ; call ROM-BIOS +;SB33023******************************************************************** + JC CHANGELINE_DONE + CMP AH,02 ; CHECK FOR PRESENCE OF CHANGELINE + JNE CHANGELINE_DONE +; +; WE HAVE A DRIVE WITH CHANGE LINE SUPPORT. +; + MESSAGE FTESTINIT,<"96TPI DEVICES",CR,LF> + + OR CL,FCHANGELINE ; SIGNAL TYPE + MOV FHAVE96,1 ; REMEMBER THAT WE HAVE 96TPI DISKS +; +; WE NOW TRY TO SET UP THE FORM FACTOR FOR THE TYPES OF MEDIA THAT WE KNOW +; AND CAN RECOGNISE. FOR THE REST, WE SET THE FORM FACTOR AS "OTHER". +; +CHANGELINE_DONE: +; 40 CYLINDERS AND 9 OR LESS SEC/TRK, TREAT AS 48 TPI MEDIUM. + CMP NUM_CYLN,40 + JNZ TRY_80 + CMP SEC_TRK,9 + JBE GOT_FF +GOTOTHER: + MOV DH,FFOTHER ; WE HAVE A "STRANGE" MEDIUM + JMP SHORT GOT_FF + +; +; 80 CYLINDERS AND 9 SECTORS/TRACK => 720 KB DEVICE +; 80 CYLINDERS AND 15 SEC/TRK => 96 TPI MEDIUM +; +TRY_80: + CMP NUM_CYLN,80 + JNZ GOTOTHER + CMP SEC_TRK,15 + JZ GOT96 + CMP SEC_TRK,9 + JNZ GOTOTHER + MOV DH,FFSMALL + JMP SHORT GOT_FF + +GOT96: + MOV DH,FF96TPI + +GOT_FF: + JMP SHORT NEXTDRIVE + +; WE HAVE AN OLD ROM, SO WE EITHER HAVE A 48TPI OR 96TPI DRIVE. IF THE DRIVE +; HAS CHANGELINE, WE ASSUEM IT IS A 96TPI, OTHERWISE WE TREAT IT AS A 48TPI. + +NOPARMSFROMROM: + POP ES + POP CX + POP DX + POP DI + POP DS + +;SB33024**************************************************************** + MOV AH, 15h ; SET COMMAND TO GET DASD TYPE ;SB;3.30 + INT 13h ; CALL ROM-BIOS ;SB;3.30 +;SB33024**************************************************************** + JC NEXTDRIVE + CMP AH,2 ; IS THERE CHANGELINE? + JNZ NEXTDRIVE + OR CL,FCHANGELINE + MOV FHAVE96,1 ; REMEMBER THAT WE HAVE 96TPI DRIVES + MOV NUM_CYLN,80 + MOV DH,FF96TPI + MOV AL,15 ; SET EOT IF NECESSARY + CMP AL, EOT + JBE EOT_OK2 + MOV EOT,AL +EOT_OK2: + +NEXTDRIVE: + OR CL,FI_OWN_PHYSICAL ; SET THIS TRUE FOR ALL DRIVES + MOV BH,DL ;SAVE INT13 DRIVE NUMBER + +; WE NEED TO DO SPECIAL THINGS IF WE HAVE A SINGLE DRIVE SYSTEM AND ARE SETTING +; UP A LOGICAL DRIVE. IT NEEDS TO HAVE THE SAME INT13 DRIVE NUMBER AS ITS +; COUNTERPART, BUT THE NEXT DRIVE LETTER. ALSO RESET OWNERSHIP FLAG. +; WE DETECT THE PRESENCE OF THIS SITUATION BY EXAMINING THE FLAG SINGLE FOR THE +; VALUE 2. + + CMP SINGLE,2 + JNZ NOT_SPECIAL + DEC BH ; INT13 DRIVE NUMBER SAME FOR LOGICAL DRIVE + XOR CL,FI_OWN_PHYSICAL ; RESET OWNERSHIP FLAG FOR LOGICAL DRIVE +NOT_SPECIAL: +; THE VALUES THAT WE PUT IN FOR RHDLIM AND RSECLIM WILL ONLY REMAIN IF THE +; FORM FACTOR IS OF TYPE "FFOTHER". + XOR AX,AX + MOV AL,NUM_HEADS + MOV WORD PTR [DI].RHDLIM,AX + MOV AL,SEC_TRK + MOV WORD PTR [DI].RSECLIM,AX + MOV WORD PTR [DI].FLAGS,CX + MOV BYTE PTR [DI].FORMFACTOR,DH + MOV BYTE PTR [DI].DRIVELET,DL + MOV BYTE PTR [DI].DRIVENUM,BH + MOV BL,BYTE PTR NUM_CYLN + MOV BYTE PTR [DI].CCYLN,BL ; ONLY THE L.S. BYTE IS SET HERE + CMP SINGLE,1 ; SPECIAL CASE FOR SINGLE DRIVE SYSTEM + JNZ NO_SINGLE + MESSAGE FTESTINIT,<"SINGLE DRIVE SYSTEM",CR,LF> + MOV SINGLE,2 ; DON'T LOSE INFO THAT WE HAVE SINGLE SYSTEM + OR CX,FI_AM_MULT + OR WORD PTR [DI].FLAGS,CX + MOV DI,WORD PTR [DI].LINK ; MOVE TO NEXT BDS IN LIST + INC DL + JMP SHORT NEXTDRIVE ; USE SAME INFO FOR BDS A PREVIOUS +NO_SINGLE: + INC DL + JMP LOOP_DRIVE + +DONE_DRIVES: + MOV AX,-1 ; SET LINK TO NULL + MOV WORD PTR [DI].LINK,AX + +; SET UP ALL THE HARD DRIVES IN THE SYSTEM + +DOHARD: + MNUM FTESTINIT+FTESTHARD,AX + MESSAGE FTESTINIT+FTESTHARD,<" HARD DISK(S) TO INITIALIZE",CR,LF> + MESSAGE FTESTINIT+FTESTHARD,<"HARD DISK 1",CR,LF> + + CMP HNUM,0 ; IF (NO_HARD_FILES) + JLE STATIC_CONFIGURE ; THEN EXIT TO CONFIGURE + + MOV DL,80H + MOV DI,OFFSET BDSH ; SET UP FIRST HARD FILE. + MOV BL,HARDNUM + CALL SETHARD + assume es:nothing + JNC HARDFILE1_OK + + DEC HNUM ; FIRST HARD FILE IS BAD. + CMP HNUM,0 ; IF (SECOND_HARD_FILE) + JG SECOND_HARD ; THEN SET UP SECOND HARD FILE + JMP SHORT STATIC_CONFIGURE + +HARDFILE1_OK: + CALL INSTALL_BDS ; INSTALL BDS INTO LINKED LIST + CMP HNUM,2 ; IF (ONLY_ONE_HARDFILE) + JB SETIT ; THEN SETIT "IN PLACE" + + MOV BL,HARDNUM + INC BL ; NEXT DRIVE LETTER + MOV DI,OFFSET BDSX + +SECOND_HARD: ; SETUP SECOND HARD FILE + + MESSAGE FTESTINIT+FTESTHARD,<"HARD DISK 2",CR,LF> + MOV DL,81H ; NEXT HARD FILE + CALL SETHARD + assume es:nothing + JNC HARDFILE2_OK + DEC HNUM + JMP SHORT SETIT + +HARDFILE2_OK: + CALL INSTALL_BDS + +SETIT: + MOV AL,HNUM + OR AL,AL + JZ STATIC_CONFIGURE + ADD AL,HARDNUM + MOV DRVMAX,AL + +; End of physical drive initialization. +; *** Do not change the position of the following statement.-J.K.4/7/86 +; *** DoMini routine will use [DRVMAX] value for the start of the logical +; *** drive number of Mini disk(s). + + call DoMini ;For setting up mini disks, if found -J.K. + + assume es:nothing +; END OF DRIVE INITIALIZATION. + +;J.K. 9/24/86 We now decide, based on the configurations available so far, what +;code or data we need to keep as a stay resident code. The following table +;shows the configurations under consideration. They are listed in the order +;of their current position memory. +;Configuration will be done in two ways: +;First, we are going to set "Static configuration". Static configuration will +;consider from basic configuration to ENDOF96TPI configuration. The result +;of static configuration will be the address the Dynamic configuration will +;use to start with. +;Secondly, "Dynamic cofiguration" will be performed. Dynamic configuration +;involves possible relocation of CODE or DATA. Dynamic configuration routine +;will take care of BDSM tables and AT ROM Fix module thru K09 suspend/resume +;code individually. After these operation, FINAL_DOS_LOCATION will be set. +;This will be the place SYSINIT routine will relocate MSDOS module for good. +; +; 1. BASIC CONFIGURATION FOR IBMBIO (EndFloppy, EndSwap) +; 2. ENDONEHARD +; 3. ENDTWOHARD +; 4. END96TPI ;a system that supports "Change Line Error" +; 5. End of BDSM ;BDSM tables for mini disks. +; 6. ENDATROM ;Some of AT ROM fix module. +; 7. ENDCMOSCLOCKSET;Supporting program for CMOS clock write. +; 8. ENDK09 ;K09 CMOS Clock module to handle SUSPEND/RESUME operation. +; +;J.K. 9/24/86. + +; *** For mini disk configuration. -J.K. 4/7/86 +; *** END_OF_BDSM will contains the ending address(offset) of BDSM table for +; *** mini disks which is located right after the label END96TPI. +; *** The variable NUM_MINI_DSK will indicate the existance of the mini disk.-J.K. 4/7/86 + + +STATIC_CONFIGURE: + + + PUSH AX + mov ax, offset END96TPI ;let's start with the biggest one. + cmp fHave96, 0 ;Is change line support there? + jnz Config96 ;Yes. + + mov ax, offset ENDTWOHARD + cmp HNUM, 1 ;1 hard file? + jbe No_Two_HRD + jmp ConfigTwoHard +No_Two_HRD: + mov ax, offset ENDONEHARD + jnz Basic_Floppy + jmp ConfigOneHard +Basic_Floppy: + mov ax, offset ENDFLOPPY + jmp Dynamic_Configure ;static configuration is done! + +; +; KEEP THE 96TPI CODE +; +CONFIG96: +; +; SAVE OLD INT 13 VECTOR +; + PUSH AX + PUSH DS + XOR AX,AX + MOV DS,AX + ASSUME DS:NOTHING + + MOV AX,DS:[4 * 13H] + MOV WORD PTR CS:REAL13,AX + MOV AX,DS:[4 * 13H+2] + MOV WORD PTR CS:REAL13+2,AX +; +; INSERT NEW VECTOR +; + MOV WORD PTR DS:[4 * 13H],OFFSET INT13 + MOV DS:[4 * 13H + 2],CS + + POP DS + ASSUME DS:CODE + + POP AX + +; KEEP TWO HARD DISK BPBS + +CONFIGTWOHARD: + +; KEEP ONE HARD DISK BPB + +CONFIGONEHARD: + +; ADJUST THE NUMBER OF DRIVES TO INCLUDE THE HARD DISKS. + + PUSH AX + + MOV AL,HARDNUM + ADD AL,HNUM + add al, num_mini_dsk ;J.K. 4/7/86 for mini disks installed + ;if not installed, then num_mini_dsk = 0. + MOV DRVMAX,AL + POP AX ;now, static config is done. + + +DYNAMIC_CONFIGURE: + call Get_Para_Offset ;For dynamic allocation, we are + ;going to use offset address that + ;is in paragraph boundary. + push cs + pop es ;es -> code + assume es:code + cld ;clear direction + + cmp [num_mini_dsk], 0 ;Mini disk(s) installed ? + jz CheckATROM ;No. + mov ax, End_Of_BDSM ;set the new ending address + call Get_Para_Offset +CheckATROM: + cmp Model_Byte, 0FCh ;AT ? + jnz CheckCMOSClock + cmp HNUM, 0 ;No hard file? + jz CheckCMOSClock + + mov si, 0F000h + mov es, si ;ES -> BIOS segment + assume es:nothing ; + mov si, offset BIOS_DATE ; + mov di, 0FFF5H ;ROM BIOS string is at F000:FFF5 +Cmpbyte: ;Only patch ROM for bios dated 01/10/84 + cmpsb ; + jnz CheckCMOSClock ; + cmp byte ptr [si-1],0 ; + jnz Cmpbyte ; +SetRomCode: ;Now we have to install ROM fix + ;AX is the address to move. + push cs ; + pop es ;set ES to CODE seg + assume es:code + + mov word ptr ORIG13, ax + mov word ptr ORIG13+2, cs ;set new ROM bios int 13 vector + mov cx, offset ENDATROM + mov si, offset IBM_DISK_IO + sub cx, si ;size of AT ROM FIX module + mov di, ax ;destination + rep movsb ;relocate it + mov ax, di ;new ending address + call Get_Para_Offset ;in AX + +CheckCMOSClock: + push cs + pop es ;set ES to CODE seg + assume es:code + cmp HaveCMOSClock, 1 ;CMOS Clock exists? + jne CheckK09 + mov DaycntToDay, ax ;set the address for MSCLOCK + mov cx, offset EndDaycntToDay + mov si, offset Daycnt_To_Day + sub cx, si ;size of CMOS clock supporting routine + mov di, ax + rep movsb + mov ax, di + call Get_Para_Offset + mov BinToBCD, ax ;set the address for MSCLOCK + mov cx, offset EndCMOSClockSet + mov si, offset Bin_To_BCD + sub cx, si + mov di, ax + rep movsb + mov ax, di + call Get_Para_Offset + +CheckK09: +;SB33025**************************************************************** + push ax ;save ax ;SB ;3.30* + mov ax,4100h ;Q: is it a K09 ;SB ;3.30* + mov bl,0 ; ;SB ;3.30* + int 15h ; ;SB ;3.30* +;SB33025**************************************************************** + pop ax + jc CONFIGDONE + + mov si, offset INT6C + mov cx, offset ENDK09 + sub cx, si ;size of K09 routine + mov di, ax + push di ;save destination + rep movsb + mov ax, di ; + call Get_Para_Offset ;AX = new ending address + pop di + + push ax + push ds + mov fHaveK09, 1 ;remember we have a K09 type + xor ax,ax + mov ds, ax + assume ds:nothing + + mov word ptr ds:[4 * 6Ch], di ;new INT 6Ch handler + mov ds:[4 * 6Ch +2], cs + + pop ds + assume ds:code + pop ax ;restore the ending address + +; SET UP CONFIG STUFF FOR SYSINIT + +CONFIGDONE: ;AX is final ending address of MSBIO. + MOV DX,SYSINITSEG + MOV DS,DX + ASSUME DS:SYSINITSEG + + SUB AX,OFFSET START$ + ADD AX,15 + RCR AX,1 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + MOV FINAL_DOS_LOCATION, AX + POP AX + +GOINIT: + ADD FINAL_DOS_LOCATION,CODE + MESSAGE FTESTINIT,<"FINAL DOS LOCATION IS "> + MNUM FTESTINIT,FINAL_DOS_LOCATION + MESSAGE FTESTINIT, + PUSH CS + POP DS + + ASSUME DS:CODE,ES:NOTHING + + CMP BYTE PTR FHAVE96,0 + JNZ READDOS + CALL PURGE_96TPI ;MJB001 ELIMINATE CALLS TO 96TPI HOOHAH + +READDOS: + MESSAGE FTESTINIT,<"LOAD FAT",CR,LF> + MOV AX,DRVFAT ; GET DRIVE AND FAT ID + CALL SETDRIVE ; GET BDS FOR DRIVE + + CALL GETBP ; ENSURE VALID BPB IS PRESENT + +;AN004; J.K. Don't need this. We are not read the whole FAT at once. +; CALL GETFAT ;READ IN THE FAT SECTOR + + XOR DI,DI + MOV AL,ES:[DI] ;GET FAT ID BYTE + MOV BYTE PTR DRVFAT+1,AL ;SAVE FAT BYTE + MOV AX,DRVFAT + MESSAGE FTESTINIT,<"FATID READ "> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT, + CALL SETDRIVE ;GET CORRECT BDS FOR THIS DRIVE + + mov bx, [di].BYTEPERSEC + mov cs:Md_SectorSize, bx ;AN004;Used by Get_Fat_Sector proc. + MOV BL,[DI].FATSIZ ; GET SIZE OF FAT ON MEDIA + MOV FBIGFAT,BL + MOV CL,[DI].SECPERCLUS ;GET SECTORS/CLUSTER +;J.K.32 bit calculation + MOV AX,[DI].HIDSEC_L ;GET NUMBER OF HIDDEN SECTORS (low) + SUB BIOS$_L,AX ;SUBTRACT HIDDEN SECTORS since we + ;need a logical sector number that will + ;be used by GETCLUS(diskrd procedure) +;SB34INIT005****************************************************************** +;SB We have 32 bit sector number now though. SO the high word also needs +;SB to be adjusted. Update BIOS$_H too. 2 LOCS + + mov ax,[di].HIDSEC_H ;subtract upper 16 bits of sector num + sbb BIOS$_H,ax +;SB34INIT005****************************************************************** + XOR CH,CH ;CX = SECTORS/CLUSTER + +; THE BOOT PROGRAM HAS LEFT THE DIRECTORY AT 0:500 + + PUSH DS + XOR DI,DI + MOV DS,DI ; ES:DI POINTS TO LOAD LOCATION + MOV BX,DS:WORD PTR [53AH] ; CLUS=*53A; + POP DS ; + MESSAGE FTESTINIT,<"LOAD DOS",CR,LF> +; BAS DEBUG +;LOADIT: MOV AX,(((END$ - START$)+15)/16)+SYSIZE + +LOADIT: + MOV AX, OFFSET END$ + SUB AX, OFFSET START$ + ADD AX, 15 + RCR AX, 1 ; DIVIDE BY 16 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + ADD AX, SYSIZE + + ADD AX,CODE + + MOV ES,AX ; + CALL GETCLUS ; CLUS = GETCLUS (CLUS); + +ISEOF: + TEST FBIGFAT,FBIG ; IF (FBIGFAT) + JNZ EOFBIG + MESSAGE FTESTINIT, + CMP BX,0FF7H ; RETURN (CLUS > 0FF7H); + JMP SHORT ISEOFX +EOFBIG: + MESSAGE FTESTINIT, + CMP BX,0FFF7H ; ELSE +ISEOFX: + JB LOADIT ; } WHILE (!ISEOF (CLUS)); + + CALL SETDRVPARMS + + MESSAGE FTESTINIT,<"SYSINIT",CR,LF> + ZWAIT + MESSAGE FTESTINIT,<"ON TO SYSINIT...",CR,LF> + JMP SYSINIT + +INIT ENDP + +;**************************** + +Get_Para_Offset proc near +;in: AX - offset value +;out: AX - offset value adjusted for the next paragraph boundary. + add ax, 15 ;make a paragraph + rcr ax, 1 + shr ax, 1 + shr ax, 1 + shr ax, 1 + shl ax, 1 ;now, make it back to offset value + shl ax, 1 + shl ax, 1 + shl ax, 1 + ret +Get_Para_Offset endp + +;AN004; Don't need this procedure. Get_FAT_Sector replace this. +; READ A FAT SECTOR INTO FAT LOCATION +;GETFAT PROC NEAR +; XOR DI,DI ; OFFSET +; MOV DX,1 ; RELATIVE SECTOR (1ST SECTOR OF FAT) +; MOV CX,FATLEN ; READ ENTIRE FAT. +; MOV AX,FATLOC ; +; MOV ES,AX ; LOCATION TO READ +; MOV AX,DRVFAT ; AH FAT ID BYTE, AL DRIVE +; JMP DISKRD +;GETFAT ENDP + +; READ A BOOT RECORD INTO 7C0:BOOTBIAS +;AN015; Read a boot record into Init_BootSeg:BOOTBIAS + +GETBOOT PROC NEAR +;SB33026**************************************************************** + mov AX, cs:Init_BootSeg ; prepare to load ES + mov ES, AX ;SB ; load ES segment register + assume es:nothing + mov BX, BootBias ;SB ; load BX, ES:BX is where sector goes + mov AX, 0201h ;SB ; command to read & num sec. to 1 + xor DH, DH ;SB ; head number zero + mov CX, 0001h ;SB ; cylinder zero and sector one + int 13h ;SB ; call rom bios +;SB33026**************************************************************** + JC ERRET + + CMP WORD PTR ES:[BOOTBIAS+1FEH],0AA55H ; DAVE L**** MAGIC BYTE? + JZ NORM_RET + MESSAGE FTESTHARD,<"SIGNATURE AA55 NOT FOUND",CR,LF> +ERRET: + MESSAGE FTESTHARD,<"ERROR IN GETBOOT",CR,LF> + STC +NORM_RET: + RET +GETBOOT ENDP + +; SETHARD - GENERATE BPB FOR A VARIABLE SIZED HARD FILE. IBM HAS A +; PARTITIONED HARD FILE; WE MUST READ PHYSICAL SECTOR 0 TO DETERMINE WHERE +; OUR OWN LOGICAL SECTORS START. WE ALSO READ IN OUR BOOT SECTOR TO +; DETERMINE VERSION NUMBER + +; INPUTS: DL IS ROM DRIVE NUMBER (80 OR 81) +; DS:DI POINTS TO BDS +; OUTPUTS: CARRY CLEAR -> BPB IS FILLED IN +; CARRY SET -> BPB IS LEFT UNINITIALIZED DUE TO ERROR + +SETHARD PROC NEAR + assume ds:code,es:nothing + PUSH DI + PUSH BX + PUSH DS + MOV BYTE PTR [DI].DRIVELET,BL + MOV BYTE PTR [DI].DRIVENUM,DL + XOR AX,AX + OR AL,FNON_REMOVABLE + OR WORD PTR [DI].FLAGS,AX + MOV BYTE PTR [DI].FORMFACTOR,FFHARDFILE + MOV FBIGFAT,0 ; ASSUME 12 BIT FAT + PUSH DX +;SB33027*************************************************************** + mov AH, 8 ;SB ; set command to get drive parameters + int 13h ;SB ; call rom-bios disk routine +;SB33027*************************************************************** +; DH IS NUMBER OF HEADS-1 +; DL IS NUMBER OF HARD DISKS ATTACHED +; LOW 6 BITS OF CL IS SECTORS/TRACK +; HIGH 2 BITS OF CL WITH CH ARE MAX # OF CYLINDERS + INC DH ; GET NUMBER OF HEADS + MOV BYTE PTR [DI].HDLIM,DH + POP DX + JC SETRET ; CARRY HERE MEANS NO HARD DISK + AND CL,3FH ; EXTRACT NUMBER OF SECTORS/TRACK + MOV BYTE PTR [DI].SECLIM,CL + CALL GETBOOT ; IF (GETBOOT ()) + assume es:nothing + JC SETRET ; RETURN -1; + MOV BX,1C2H+BOOTBIAS ; P = &BOOT[0X1C2]; +SET1: + CMP BYTE PTR ES:[BX],1 ; WHILE (P->PARTITIONTYPE != 1 && + JZ SET2 + + CMP BYTE PTR ES:[BX],4 ; P->PARTITIONTYPE != 4 && + JZ SET2 + +;SB34INIT006****************************************************************** +;SB we have a new partition type 6 now. add code to support this too. + + cmp byte ptr es:[bx],6 ; P->PARTITIONTYPE !=6 + jz set2 +;SB34INIT006****************************************************************** + + ADD BX,16 ; P += SIZEOF PARTITION; + CMP BX,202H+BOOTBIAS ; IF (P == &BOOT[0X202H]) + JNZ SET1 ; RETURN -1;} + +SETRET: + STC ;AN000; Note: Partitiontype 6 means either + JMP RET_HARD ;1).the partition has not been formatted yet, or + ;2).(# of sectors before the partition + + ; # of sectors in this partition) > word boundary + ; i.e., needs 32 bit sector calculation, or + ;3).the partition is not a FAT file system. + +;J.K. Until we get the real logical boot record and get the bpb, +;DRVLIM_H,DRVLIM_L will be used instead of DRVLIM for the convenience of +;the computation. +;At the end of this procedure, if a BPB information is gotten from +;the valid boot record, then we are going to use those BPB information +;without change. +;Otherwise, if (hidden sectors + total sectors) <= a word, then +;we will move DRVLIM_L to DRVLIM and zero out DRVLIM_L entry to make +;it a conventional BPB format. + +SET2: +; PUSH DX ;AN000; + mov cs:ROM_drv_num, dl ;AN000; save the ROM BIOS drive number we are handling now. + + MOV AX,WORD PTR ES:[BX+4] ;Hidden sectors + MOV DX,WORD PTR ES:[BX+6] + + + ;Decrement the sector count by 1 to make it zero based. Exactly 64k + ;sectors should be allowed + ; + SUB AX,1 ; PTM 901 12/12/86 MT + SBB DX,0 ; PTM 901 12/12/86 MT + + ADD AX,WORD PTR ES:[BX+8] ;Sectors in Partition + ADC DX,WORD PTR ES:[BX+10] +; JZ OKDRIVE + jnc Okdrive ;AC000; + MESSAGE FTESTHARD,<"PARTITION INVALID",CR,LF> + OR FBIGFAT,FTOOBIG +OKDRIVE: +; POP DX + MOV AX,WORD PTR ES:[BX+4] + + MOV [DI].HIDSEC_L,AX ; BPB->HIDSECCT = P->PARTITIONBEGIN; + mov ax,word ptr es:[bx+6] ;AN000; + mov [di].HIDSEC_H,ax ;AN000; + + mov dx,word ptr es:[bx+10] ;AN000; # of sectors (High) + MOV AX,WORD PTR ES:[BX+8] ;# of sectors (Low) + mov word ptr [di].DRVLIM_H,dx ;AN000; + MOV WORD PTR [DI].DRVLIM_L,AX ; BPB->MAXSEC = P->PARTITIONLENGTH; + cmp dx,0 ;AN000; + ja OKDrive_Cont ;AN000; + CMP AX,64 ; IF (P->PARTITIONLENGTH < 64) + JB SETRET ; RETURN -1; + +OKDrive_Cont: ;AN000; + ; PUSH DX ;AC000; + mov dx,[di].HIDSEC_H ;AN000; + MOV AX,[DI].HIDSEC_L ; BOOT SECTOR NUMBER - For mini disk,;J.K. +; XOR DX,DX ; this will be logical and equal to ;AC000; + xor bx,bx ;usUally equal to the # of sec/trk. ;J.K. +; MOV BH,DH ;AC000; + MOV BL,BYTE PTR [DI].SECLIM + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div bx ;AN000; + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV BX ;(Sectors)DX;AX / (Seclim)BX =(Track) Temp_H;AX + (Sector)DX + MOV CL,DL ; CL IS SECTOR NUMBER;J.K.Assume sector number < 255. + INC CL ; SECTORS ARE 1 BASED +; CWD ;AC000; + + xor bx,bx ;AN000; + MOV BL,BYTE PTR [DI].HDLIM + push ax ;AN000; + xor dx,dx ;AN000; + mov ax, cs:[Temp_H] ;AN000; + div bx ;AN000; + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV BX ; DL IS HEAD, AX IS CYLINDER + cmp cs:[Temp_H],0 ;AN000; + ja SetRet_brdg ;AN000; Exceeds the limit of Int 13h + cmp ax, 1024 ;AN000; + ja SetRet_brdg ;AN000; Exceeds the limit of Int 13h + +; DL IS HEAD. +; AX IS CYLINDER +; CL IS SECTOR NUMBER (assume less than 2**6 = 64 for INT 13h) + +;*** For Mini Disks *** J.K. 4/7/86 + cmp word ptr [di].ISMINI, 1 ;check for mini disk -J.K. 4/7/86 + jnz OKnotMini ;not mini disk. -J.K. 4/7/86 + add ax, [di].HIDDEN_TRKS ;set the physical track number -J.K. 4/7/86 +OKnotMini: ;J.K. 4/7/86 +;*** End of added logic for mini disk + ROR AH,1 ; MOVE HIGH TWO BITS OF CYL TO HIGH + ROR AH,1 ; TWO BITS OF UPPER BYTE + AND AH,0C0H ; TURN OFF REMAINDER OF BITS + OR CL,AH ; MOVE TWO BITS TO CORRECT SPOT + MOV CH,AL ; CH IS CYLINDER + +; CL IS SECTOR + 2 HIGH BITS OF CYLINDER +; CH IS LOW 8 BITS OF CYLINDER +; DL IS HEAD +; ROM_drv_num IS DRIVE + +; POP AX ;AC000; AL IS DRIVE + MOV DH,DL ; DH IS HEAD +; MOV DL,AL ;AC000; DL IS DRIVE + mov dl, cs:ROM_drv_num ;AN000; Set the drive number + +; CL IS SECTOR + 2 HIGH BITS OF CYLINDER +; CH IS LOW 8 BITS OF CYLINDER +; DH IS HEAD +; DL IS DRIVE +;J.K. For convenience, we are going to read the logical boot sector +;into cs:DiskSector area. + +;SB34INIT009************************************************************* +;SB Read in boot sector using BIOS disk interrupt. The buffer where it +;SB is to be read in is cs:Disksector. +;SB 5 LOCS + + push cs + pop es + mov bx,offset DiskSector + mov ax,0201h ; read, one sector + int 13h + +;SB34INIT009************************************************************* + +; cs:Disksec contains THE BOOT SECTOR. IN THEORY, (HA HA) THE BPB IN THIS THING +; IS CORRECT. WE CAN, THEREFORE, SUCK OUT ALL THE RELEVANT STATISTICS ON THE +; MEDIA IF WE RECOGNIZE THE VERSION NUMBER. + mov bx, offset DiskSector ;AN000; +; look for a signature for msdos... + cmp word ptr cs:[bx+3], "S" shl 8 + "M" + jnz notmssig + cmp word ptr cs:[bx+5], "O" shl 8 + "D" + jnz notmssig + cmp byte ptr cs:[bx+7], "S" + je sigfound +; ...or perhaps pcdos... +notmssig: + CMP WORD PTR cs:[bx+3], "B" SHL 8 + "I" + jnz notibmsig + CMP WORD PTR cs:[bx+5], " " SHL 8 + "M" + je sigfound +;---------------------------------------------------------------------- +; check for Microsoft OS/2 signature also. 7/29/88. HKN +notibmsig: + CMP WORD PTR cs:[bx+3], "S" SHL 8 + "O" + JNZ UNKNOWNJ + CMP WORD PTR cs:[bx+5], " " SHL 8 + "2" + JNZ UNKNOWNJ +;----------------------------------------------------------------------- + +sigfound: ; signature was found, now check version + CMP WORD PTR cs:[bx+8], "." SHL 8 + "2" + JNZ TRY5 + CMP BYTE PTR cs:[bx+10], "0" + JNZ TRY5 + MESSAGE FTESTHARD,<"VERSION 2.0 MEDIA",CR,LF> + JMP SHORT COPYBPB + +SetRet_Brdg: + jmp SETRET + +UNKNOWNJ: + JMP UNKNOWN ;Unformatted or illegal media. +UNKNOWN3_0_J: ;AN012;Legally formatted media, + jmp Unknown3_0 ;AN012; although, content might be bad. + +TRY5: + call Cover_Fdisk_Bug ;AN010; + CMP WORD PTR cs:[bx+8],"." SHL 8 + "3" + jb Unknown3_0_J ;AN012; Must be 2.1 boot record. Do not trust it, but still legal. + JNZ COPYBPB ;AN007; Honor OS2 boot record, or DOS 4.0 version + cmp byte ptr cs:[bx+10],"1" ;do not trust 3.0 boot record. But still legal J.K. 4/15/86 + jb UnKnown3_0_J ;AN012; if version >= 3.1, then O.K. + Message ftestHard,<"VERSION 3.1 OR ABOVE MEDIA",CR,LF> + +COPYBPB: +; WE HAVE A VALID BOOT SECTOR. USE THE BPB IN IT TO BUILD THE +; BPB IN BIOS. IT IS ASSUMED THAT ONLY SECPERCLUS, CDIR, AND +; CSECFAT NEED TO BE SET (ALL OTHER VALUES IN ALREADY). FBIGFAT +; IS ALSO SET. + +;If it is non FAT based system, then just copy the BPB from the BOOT sector +;into the BPB in BDS table, and also set the Boot serial number, Volume id, +;and System ID according to the Boot record. +;For the non_FAT system, don't need to set the other value. So just +;do GOODRET.- J.K. + + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN000; + jne COPYBPB_FAT ;AN000; Conventional Fat system + cmp cs:[NumberOfFats], 0 ;AN000; If (# of FAT <> 0) then + jne COPYBPB_FAT ;AN000; a Fat system. +;J.K. Non Fat based media. + push di ;AN000; Sav Reg. + push ds ;AN000; + + push ds ;AN000; + pop es ;AN000; now es:di -> bds + push cs ;AN000; + pop ds ;AN000; ds = cs + + mov si, offset Bpb_In_Sector ;AN000; ds:si -> BPB in Boot + add di, BYTEPERSEC ;AN000; es:di -> BPB in BDS + mov cx, size BPB_TYPE ;AN000; + rep movsb ;AN000; + + pop ds ;AN000; Restore Reg. + pop di ;AN000; + call Mov_Media_IDs ;AN000; Set Volume id, SystemId, Serial. + jmp GoodRet + +COPYBPB_FAT: ;AN000; Fat system + xor dx,dx ;AN000; + mov si, offset Bpb_In_Sector ;AN000; cs:bx -> bpb in boot + mov ax, cs:[si.SECNUM] ;AN000; total sectors + cmp ax,0 ;AN000; double word sector number? + jnz Fat_Big_Small ;AN000; No. Conventional BPB. + mov ax, word ptr cs:[si.SECNUM_L] ;AN000; Use double word + mov dx, word ptr es:[si.SECNUM_H] ;AN000; + +Fat_Big_Small: ;AN000; Determine Fat entry size. +;At this moment DX;AX = Total sector number +; DEC AX ; SUBTRACT # RESERVED (ALWAYS 1) + sub ax,1 ;AN000; Subtrack # reserved (always 1) + sbb dx,0 ;AN000; + mov bx, cs:[si.FATSIZE] ;AN000; BX = Sectors/Fat + mov [di.CSECFAT],bx ;AN000; Set in BDS BPB + shl bx,1 ;AN000; Always 2 FATS + sub ax,bx ;AN000; Sub # fat sectors + sbb dx,0 ;AN000; + mov bx, cs:[si.DIRNUM] ;AN000; # root entries + mov [di.cDIR],bx ;AN000; Set in BDS BPB + + MOV CL,4 + shr bx,cl ;AN000; Div by 16 ents/sector + sub ax,bx ;AN000; sub # dir sectors + sbb dx,0 ;AN000; + ;AN000; DX;AX now contains the # of data sectors + xor cx,cx ;AN000; + MOV CL, cs:[si.SECALL] ; SECTORS PER CLUSTER + MOV [DI.SECPERCLUS],CL ; SET IN BIOS BPB +; XOR DX,DX +; MOV CH,DH + MNUM FTESTHARD,CX + MESSAGE FTESTHARD,<" SECPERCLUS",CR,LF> +;J.K. 3/16/87 P54 Returning back to old logic for compatibility reason. +;So, use the old logic again that once had been commented out!!!!!!!!!!!! +;Old logic to determine FAT Entry Size J.K. 12/3/86 + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; cx = sectors per cluster + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV CX ;AN000; [Temp_H];AX NOW CONTAINS THE # CLUSTERS. + cmp cs:[Temp_H],0 ;AN000; + ja TooBig_Ret ;AN000; Too big cluster number + CMP AX,4096-10 ; IS THIS 16-BIT FAT? + JB CopyMediaID ; NO, small FAT + OR FBIGFAT,FBIG ; 16 BIT FAT +;End of Old logic +CopyMediaID: + call Mov_Media_IDs ;AN000; Copy Filesys_ID, Volume label, + ;and Volume serial to BDS table, if extended + ;boot record. + JMP Massage_bpb ;AN000; Now final check for BPB info. and return. + +TooBig_Ret: ;AN000; + OR cs:FBIGFAT,FTOOBIG + JMP GOODRET ;AN000; Still drive letter is assigned + ;AN000; But useless. To big for + ;AN000; current PC DOS FAT file system +UNKNOWN: +; or [di].FLAGS, UNFORMATTED_MEDIA ;AN005; Set unformatted media flag. + ; preceeding line commented out 10/88 by MRW-- The boot signature + ; may not be recognizable, but we should TRY and read it anyway. + ;AN006; + ;AN008; For the time being, allow it. + ;AN009; Now implemented again +Unknown3_0: ;AN012;Skip setting UNFORMATTED_MEDIA bit + MESSAGE FTESTHARD,<"UNKNOWN HARD MEDIA. ASSUMING 3.0.",CR,LF> + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + MOV SI,OFFSET DISKTABLE2 +SCAN: +; CMP AX,[SI] +; JBE GOTPARM +; ADD SI,4 * 2 + + cmp dx, word ptr cs:[si] ;AN000; + jb GotParm ;AN000; + ja Scan_Next ;AN000; + cmp ax, word ptr cs:[si+2] ;AN000; + jbe GotParm ;AN000; +Scan_Next: ;AN000; + add si, 5 * 2 ;AN000; + JMP SCAN ;AN000; Covers upto 512 MB media +GOTPARM: +; MOV CL,BYTE PTR [SI+6] + mov cl,byte ptr [si+8] ;AN000; Fat size for FBIGFAT flag + OR FBIGFAT,CL +; MOV CX,[SI+2] +; MOV DX,[SI+4] + mov cx, word ptr cs:[SI+4] ;AN000; + mov dx, word ptr cs:[SI+6] ;AN000; + +; DX = NUMBER OF DIR ENTRIES, +; CH = NUMBER OF SECTORS PER CLUSTER +; CL = LOG BASE 2 OF CH + +; NOW CALCULATE SIZE OF FAT TABLE + + MNUM FTESTHARD,AX + MESSAGE FTESTHARD,<" SECTORS "> + MNUM FTESTHARD,DX + MESSAGE FTESTHARD,<" DIRECTORY ENTRIES "> + MNUM FTESTHARD,CX + MESSAGE FTESTHARD,<" SECPERCLUS|CLUSSHIFT"> + + MOV WORD PTR CDIR[DI],DX ;SAVE NUMBER OF DIR ENTRIES + +;Now, CX = SecPerClus|Clusshift +; [DI.CDIR] = number of directory entries. + + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + MOV BYTE PTR SECPERCLUS[DI],CH ;SAVE SECTORS PER CLUSTER + TEST FBIGFAT,FBIG ; IF (FBIGFAT) + JNZ DOBIG ; GOTO DOBIG; + MESSAGE FTESTHARD,<" SMALL FAT",CR,LF> +;J.K. We don't need to change "small fat" logic since it is gauranteed +;that double word total sector will not use 12 bit fat (unless +;it's sectors/cluster >= 16 which will never be in this case.) +;So in this case we assume DX = 0 !!!. + + XOR BX,BX + MOV BL,CH + DEC BX + ADD BX,AX ;AN000; DX=0 + SHR BX,CL ; BX = 1+(BPB->MAXSEC+SECPERCLUS-1)/ + INC BX ; SECPERCLUS + AND BL,11111110B ; BX &= ~1; (=NUMBER OF CLUSTERS) + MOV SI,BX + SHR BX,1 + ADD BX,SI + ADD BX,511 ; BX += 511 + BX/2 + SHR BH,1 ; BH >>= 1; (=BX/512) + MOV BYTE PTR [DI].CSECFAT,BH ;SAVE NUMBER OF FAT SECTORS + JMP SHORT Massage_BPB +DOBIG: +;J.K. For BIGFAT we do need to extend this logic to 32 bit sector calculation. + MESSAGE FTESTHARD,<" BIG FAT",CR,LF> + MOV CL,4 ; 16 (2^4) DIRECTORY ENTRIES PER SECTOR + push dx ;AN000; Save total sectors (high) + mov dx, CDIR[DI] ;AN000; + SHR DX,CL ; CSECDIR = CDIR / 16; + SUB AX,DX ; DX;AX -= CSECDIR; DX;AX -= CSECRESERVED; + pop dx ;AN000; + SBB dx,0 ;AN000; +; DEC AX ; AX = T - R - D + SUB ax,1 ;AN000; DX;AX = T - R - D + SBB dx,0 ;AN000; + MOV BL,2 + MOV BH,SECPERCLUS[DI] ; BX = 256 * SECPERCLUS + 2 +; XOR DX,DX +;J.K. I don't understand why to add BX here!!! + ADD AX,BX ; AX = T-R-D+256*SPC+2 + ADC DX,0 + SUB AX,1 ; AX = T-R-D+256*SPC+1 + SBB DX,0 +;J.K. Assuming DX in the table will never be bigger than BX. + DIV BX ; CSECFAT = CEIL((TOTAL-DIR-RES)/ + ; (256*SECPERCLUS+2)); + MOV WORD PTR [DI].CSECFAT,AX ; NUMBER OF FAT SECTORS +;J.K. Now, set the default FileSys_ID, Volume label, Serial number + MOV BL,FBIGFAT + MOV [DI].FATSIZ,BL ; SET SIZE OF FAT ON MEDIA + call Clear_IDs ;AN000; + +;J.K. At this point, in BPB of BDS table, DRVLIM_H,DRVLIM_L which were +;set according to the partition information. We are going to +;see if (hidden sectors + total sectors) > a word. If it is true, +;then no change. Otherwise, DRVLIM_L will be moved to DRVLIM +;and DRVLIM_L will be set to 0. +;We don't do this for the bpb information from the boot record. We +;are not going to change the BPB information from the boot record. +Massage_bpb: ;AN000; + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + cmp dx,0 ;AN000; Double word total sector? + ja GOODRET ;AN000; don't have to change it. + cmp [di.HIDSEC_H], 0 ;AN000; + ja GOODRET ;AN000; don't have to change it. + add ax, [di.HIDSEC_L] ;AN000; + jc GOODRET ;AN000; bigger than a word boundary + mov ax, [di.DRVLIM_L] ;AN000; + mov [di.DRVLIM], ax ;AN000; + mov [di.DRVLIM_L], 0 ;AN000; +GOODRET: + cmp [di].DRVLIM_H, 0 ;AN014; Big media? + jbe Not_BigMedia ;AN014; No. + push es ;AN014; + push ax ;AN014; + mov ax, SYSINITSEG ;AN014; + mov es, ax ;AN014; + mov es:Big_Media_Flag, 1 ;AN014; Set the flag in SYSINITSEG. + pop ax ;AN014; + pop es ;AN014; +Not_BigMedia: ;AN014; + MOV BL,FBIGFAT + MOV [DI].FATSIZ,BL ; SET SIZE OF FAT ON MEDIA + CLC +RET_HARD: + POP DS + POP BX + POP DI + RET + +SETHARD ENDP + +Cover_FDISK_Bug proc ;AN010; +;FDISK of PC DOS 3.3 and below, OS2 1.0 has a bug. The maximum number of +;sector that can be handled by PC DOS 3.3 ibmbio should be 0FFFFh. +;Instead, sometimes FDISK use 10000h to calculate the maximum number. +;So, we are going to check that if SECNUM + Hidden sector = 10000h +;then subtrack 1 from SECNUM. + push ax ;AN010; + push dx ;AN010; + push si ;AN010; + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN010; + je CFB_Retit ;AN010;if extended BPB, then >= PC DOS 4.00 + cmp word ptr cs:[bx+7], "0" shl 8 + "1" ;AN011; OS2 1.0 ? = IBM 10.0 + jne CFB_Chk_SECNUM ;AN010; + cmp byte ptr cs:[bx+10], "0" ;AN010; + jne CFB_Retit ;AN010; +CFB_Chk_SECNUM: ;AN010; + mov si, offset BPB_In_Sector ;AN010; + cmp cs:[si.SECNUM], 0 ;AN010;Just to make sure. + je CFB_Retit ;AN010; + mov ax, cs:[si.SECNUM] ;AN010; + add ax, cs:[si.HIDDEN_L] ;AN010; + jnc CFB_Retit ;AN010; + xor ax, ax ;AN010;if carry set and AX=0? + jnz CFB_Retit ;AN010; + dec cs:[si.SECNUM] ;AN010; then decrease SECNUM by 1. + dec [di].DRVLIM_L ;AN010; +CFB_Retit: ;AN010; + pop si ;AN010; + pop dx ;AN010; + pop ax ;AN010; + ret ;AN010; +Cover_FDISK_Bug endp ;AN010; + + +; SETDRVPARMS SETS UP THE RECOMMENDED BPB IN EACH BDS IN THE SYSTEM BASED ON +; THE FORM FACTOR. IT IS ASSUMED THAT THE BPBS FOR THE VARIOUS FORM FACTORS +; ARE PRESENT IN THE BPBTABLE. FOR HARD FILES, THE RECOMMENDED BPB IS THE SAME +; AS THE BPB ON THE DRIVE. + +; NO ATTEMPT IS MADE TO PRESERVE REGISTERS SINCE WE ARE GOING TO JUMP TO +; SYSINIT STRAIGHT AFTER THIS ROUTINE. + +SETDRVPARMS PROC NEAR + MESSAGE FTESTINIT,<"SETTING DRIVE PARAMETERS",CR,LF> + XOR BX,BX + LES DI,DWORD PTR CS:[START_BDS] ; GET FIRST BDS IN LIST +NEXT_BDS: + CMP DI,-1 + JNZ DO_SETP +DONE_SETPARMS: + RET + +DO_SETP: + PUSH ES + PUSH DI ; PRESERVE POINTER TO BDS + MOV BL,ES:[DI].FORMFACTOR + CMP BL,FFHARDFILE + JNZ NOTHARDFF + + xor dx,dx ;AN000; + MOV AX,ES:[DI].DRVLIM + cmp ax,0 ;AN000; + jne GET_cCYL ;AN000; + mov dx,es:[di].DRVLIM_H ;AN000; Use Double word sector number + MOV AX,ES:[DI].DRVLIM_L ;AN000; +GET_cCYL: + push dx ;AN000; + PUSH AX + MOV AX,WORD PTR ES:[DI].HDLIM + MUL WORD PTR ES:[DI].SECLIM ;Assume Sectorsp per cyl. < 64K. + MOV CX,AX ; CX HAS # SECTORS PER CYLINDER + POP AX ; + pop dx ;AN000; Restore drvlim. + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; + mov cs:[Temp_H],ax ;AN000; AX be 0 here. + pop ax ;AN000; + DIV CX ; DIV #SEC BY SEC/CYL TO GET # CYL. + OR DX,DX + JZ NO_CYL_RND ; CAME OUT EVEN + INC AX ; ROUND UP +NO_CYL_RND: + MOV ES:[DI].CCYLN,AX + MESSAGE FTESTINIT,<"CCYLN "> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT, + PUSH ES + POP DS + LEA SI,[DI].BYTEPERSEC ; DS:SI -> BPB FOR HARD FILE + JMP SHORT SET_RECBPB + +NOTHARDFF: +;J.K. We don't use the extended BPB for a floppy. + PUSH CS + POP DS + assume ds:code +;J.K.6/24/87 + +;SB34INIT007****************************************************************** +;SB If Fake floppy drive variable is set then we don't have to handle this +;SB BDS. We can just go and deal with the next BDS at label Go_To_Next_BDS. + + cmp cs:FakeFloppyDrv,1 + jz Go_To_Next_BDS +;SB34INIT007****************************************************************** + + CMP BL,FFOTHER ; SPECIAL CASE "OTHER" TYPE OF MEDIUM + JNZ NOT_PROCESS_OTHER +PROCESS_OTHER: + XOR DX,DX + MOV AX,[DI].CCYLN + MOV BX,[DI].RHDLIM + MUL BX + MOV BX,[DI].RSECLIM + MUL BX + MOV [DI].RDRVLIM,AX ; HAVE THE TOTAL NUMBER OF SECTORS + DEC AX + +;J.K. Old logic was... +; MOV BX,515 +; DIV BX +; OR DX,DX +; JZ NO_ROUND_UP +; INC AX ; ROUND UP NUMBER OF FAT SECTORS + +;J.K. New logic to get the sectors/fat area. + ;Fat entry is assumed to be 1.5 bytes!!! + mov bx, 3 + mul bx + mov bx,2 + div bx + xor dx, dx + mov bx, 512 + div bx + inc ax + +NO_ROUND_UP: + MOV [DI].RCSECFAT,AX + JMP SHORT GO_TO_NEXT_BDS +NOT_PROCESS_OTHER: + SHL BX,1 ; BX IS WORD INDEX INTO TABLE OF BPBS + MOV SI,OFFSET BPBTABLE + MOV SI,WORD PTR [SI+BX] ; GET ADDRESS OF BPB +SET_RECBPB: + LEA DI,[DI].RBYTEPERSEC ; ES:DI -> RECBPB + MOV CX,BPBSIZ + REP MOVSB ; MOVE BPBSIZ BYTES +GO_TO_NEXT_BDS: + POP DI + POP ES ; RESTORE POINTER TO BDS + MOV BX,WORD PTR ES:[DI].LINK+2 + MOV DI,WORD PTR ES:[DI].LINK + MOV ES,BX + JMP NEXT_BDS + +SETDRVPARMS ENDP + +; READ CLUSTER SPECIFIED IN BX +; CX = SECTORS PER CLUSTER +; DI = LOAD LOCATION +; +GETCLUS PROC NEAR + PUSH CX + PUSH DI + MOV DOSCNT,CX ;SAVE NUMBER OF SECTORS TO READ + MOV AX,BX + DEC AX + DEC AX + MUL CX ;CONVERT TO LOGICAL SECTOR +;J.K. Now DX;AX = matching logical sector number starting from the data sector. +;SB34INIT008************************************************************* +;SB Add the BIOS start sector to the sector number in DX:AX. The BIOS +;SB start sector number is in BIOS$_H:BIOS$_L + + add ax,cs:BIOS$_L + adc dx,cs:BIOS$_H +;SB34INIT008************************************************************* +;J.K. Now DX;AX = first logical sector to read +; MOV DX,AX ;DX = FIRST SECTOR TO READ +GETCL1: + MNUM FTESTINIT + MESSAGE FTESTINIT,<" => "> +; ;SI = BX, BX = NEXT ALLOCATION UNIT + +; GET THE FAT ENTRY AT BX + +UNPACK: + PUSH DS + push ax ;AN004;Save First logical sector (Low) + PUSH BX + MOV SI,FATLOC + MOV DS,SI ;DS -> FATLOC segment + mov si, bx ;AN004; + TEST cs:FBIGFAT,FBIG ;16 bit fat? + JNZ UNPACK16 +; MOV SI,BX + SHR SI,1 ;12 bit fat. si=si/2 + add si, bx ;AN004; si = clus + clus/2 + call Get_Fat_Sector ;AN004; offset of FAT entry in BX + mov ax, [bx] ;AN004;Save it into AX + jne Even_Odd ;AN004;IF not a splitted FAT, check even-odd. + mov al, byte ptr [bx] ;AN004;Splitted FAT. + mov byte ptr cs:Temp_Cluster, al ;AN004; + inc si ;AN004; + call Get_Fat_Sector ;AN004; + mov al, byte ptr ds:[0] ;AN004; + mov byte ptr cs:Temp_Cluster+1, al ;AN004; + mov ax, cs:Temp_Cluster ;AN004; +Even_Odd: ;AN004; + pop bx ;AN004;Restore old Fat entry value + push bx ;AN004;Save it right away. + shr bx, 1 ;AN004;Was it even or odd? + jnc HAVCLUS ;It was even. + SHR ax,1 ;Odd. Massage FAT value and keep + SHR ax,1 ;the highest 12 bits. + SHR ax,1 + SHR ax,1 +HAVCLUS: + mov bx, ax ;AN004; Now BX = New FAT entry. + AND BX,0FFFH ;AN004; keep low 12 bits. + JMP SHORT UNPACKX +UNPACK16: ;16 bit fat. + shl si, 1 ;Get the offset value. + call Get_Fat_Sector ;AN004; + mov bx, [bx] ;AN004; Now BX = New FAT entry. +UNPACKX: + POP SI ;Retore Old BX value into SI + pop ax ;AN004;Restore logical sector (low) + POP DS + + MNUM FTESTINIT + MESSAGE FTESTINIT,<" "> + SUB SI,BX + CMP SI,-1 ;ONE APART? + JNZ GETCL2 + ADD DOSCNT,CX + JMP GETCL1 + +GETCL2: + PUSH BX + push dx ;AN000; Sector to read (High) + push ax ;AN000; Sector to read (low) + MOV AX,DRVFAT ;GET DRIVE AND FAT SPEC + MOV CX,DOSCNT + pop dx ;AN000; Sector to read for DISKRD (Low) + pop cs:[Start_Sec_H] ;AN000; Sector to read for DISKRD (High) + CALL DISKRD ;READ THE CLUSTERS + + POP BX + POP DI + MOV AX,DOSCNT ;GET NUMBER OF SECTORS READ + XCHG AH,AL ;MULTIPLY BY 256 + SHL AX,1 ;TIMES 2 EQUAL 512 + ADD DI,AX ;UPDATE LOAD LOCATION + POP CX ;RESTORE SECTORS/CLUSTER + RET + +GETCLUS ENDP ; RETURN; + +Get_FAT_Sector proc near ;AN004; +;Function: FInd and read the corresponding FAT sector into DS:0 +;In). SI - offset value (starting from FAT entry 0) of FAT entry to find. +; DS - FATLOC segment +; cs:DRVFAT - Logical drive number, FAT id +; cs:Md_SectorSize +; cs:Last_Fat_SecNum - Last FAT sector number read in. +;Out). Corresponding FAT sector read in. +; BX = offset value from FATLOG segment. +; Other registera saved. +; Zero flag set if the FAT entry is splitted, i.e., wehn 12 bit FAT entry +; starts at the last byte of the FAT sector. In this case, the caller +; should save this byte, and read the next FAT sector to get the rest +; of the FAT entry value. (This will only happen with the 12 bit fat.) + + push ax ;AN004; + push cx ;AN004; + push dx ;AN004; + push di ;AN004; + push si ;AN004; + push es ;AN004; + push ds ;AN004; + xor dx, dx ;AN004; + mov ax, si ;AN004; + mov cx, cs:Md_SectorSize ;AN004; =512 bytes + div cx ;AN004; AX=sector number, dx = offset + inc ax ;AN004; Make AX to relative logical sector number + cmp ax, cs:Last_Fat_SecNum ;AN004; by adding Reserved sector number. + je GFS_Split_Chk ;AN004; Don't need to read it again. + mov cs:Last_Fat_SecNum, ax ;AN004; Update Last_Fat_SecNum + push dx ;AN004; save offset value. + mov cs:[Start_Sec_H],0 ;AN004; Prepare to read the FAT sector + mov dx, ax ;AN004; Start_Sec_H is always 0 for FAT sector. + mov cx, 1 ;AN004; 1 sector to read + mov ax, cs:DrvFAT ;AN004; + push ds ;AN004; + pop es ;AN004; + xor di, di ;AN004; es:di -> FatLoc segment:0 + call DiskRD ;AN004; cross your finger. + pop dx ;AN004; restore offset value. + mov cx, cs:Md_SectorSize ;AN004; +GFS_Split_Chk: ;AN004; + dec cx ;AN004;if offset points to the + cmp dx, cx ;AN004;last byte of this sector, then splitted entry. + mov bx, dx ;AN004;Set BX to DX + pop ds ;AN004; + pop es ;AN004; + pop si ;AN004; + pop di ;AN004; + pop dx ;AN004; + pop cx ;AN004; + pop ax ;AN004; + ret ;AN004; +Get_FAT_Sector endp ;AN004; + +; +; SI POINTS TO DEVICE HEADER +; J.K. 4/22/86 - print_init, aux_init is modified to eliminate the self-modifying +; J.K. code. + +PRINT_INIT: + call Get_device_number +;SB33028***************************************************************** + mov ah,1 ;initalize printer port ;SB;3.30 + int 17h ;call ROM-Bios routine ;SB;3.30 +;SB33028***************************************************************** + ret + +AUX_INIT: + call Get_device_number +;SB33028***************************************************************** + mov al,RSINIT ;2400,N,1,8 (MSEQU.INC) ;SB ;3.30* + mov ah,0 ;initalize AUX port ;SB ;3.30* + int 14h ;call ROM-Bios routine ;SB ;3.30* +;SB33028***************************************************************** + ret + +GET_DEVICE_NUMBER: +;SI -> device header + MOV AL,CS:[SI+13] ;GET DEVICE NUMBER FROM THE NAME + SUB AL,"1" + CBW + MOV DX,AX + RET + +; +; PURGE_96TPI NOP'S CALLS TO 96TPI SUPPORT. +; +PURGE_96TPI PROC NEAR ;MJB001 + PUSH DS + PUSH ES + + PUSH CS ;MJB001 + POP ES ;MJB001 + PUSH CS ;MJB001 + POP DS ;MJB001 + ASSUME DS:CODE,ES:CODE + + MOV SI,OFFSET PATCHTABLE +PATCHLOOP: + LODSW + MOV CX,AX + JCXZ PATCHDONE + LODSW + MOV DI,AX + MOV AL,90H + REP STOSB + JMP PATCHLOOP + +PATCHDONE: +;**************NOT NEEDED ANY MORE*********************** +; MOV DI,OFFSET FORMAT_PATCH ; ARR 2.42 +; MOV AL,CS:INST_FAR_RET +; STOSB +;******************************************************** + MOV DI,OFFSET TABLE_PATCH ; ARR 2.42 + MOV AX,OFFSET EXIT + STOSW + STOSW + + POP ES + POP DS + RET ;MJB001 +PURGE_96TPI ENDP + +;Mini disk initialization routine. Called right after DoHard - J.K. 4/7/86 +; DoMini ********************************************************************** +; **CS=DS=ES=code +; **DoMini will search for every extended partition in the system, and +; initialize it. +; **BDSM stands for BDS table for Mini disk and located right after the label +; End96Tpi. End_Of_BDSM will have the offset value of the ending +; address of BDSM table. +; **BDSM is the same as usual BDS structure except that TIM_LO, TIM_HI entries +; are overlapped and used to identify mini disk and the number of Hidden_trks. +; Right now, they are called as IsMini, Hidden_Trks respectively. +; **DoMini will use the same routine in SETHARD routine after label SET1 to +; save coding. +; **DRVMAX determined in DoHard routine will be used for the next +; available logical mini disk drive number. +; +; Input: DRVMAX, DSKDRVS +; +; Output: MiniDisk installed. BDSM table established and installed to BDS. +; num_mini_dsk - the number of mini disks installed in the system. +; End_Of_BDSM - ending offset address of BDSM. +; +; +; Called modules: +; GetBoot, WRMSG, int 13h (AH=8, Rom) +; FIND_MINI_PARTITION (new), Install_BDSM (new), +; SetMini (new, it will use SET1 routine) +; Variables used: End_Of_BDSM, numh, mininum, num_mini_dsk, +; Rom_Minidsk_num, Mini_HDLIM, Mini_SECLIM +; BDSMs, BDSM_type (struc), Start_BDS +;****************************************************************************** +; + +DoMini: + push cs + pop es + push cs + pop ds + assume ds:code,es:code + Message fTestHard,<"Start of DoMini...",cr,lf> + + push ax ;Do I need to do this? + + mov di, offset BDSMs ;from now on, DI points to BDSM +;SB33028******************************************************************** + mov dl, 80h ;look at first hard drive ;SB ;3.30* + mov ah, 8h ;get drive parameters ;SB ;3.30* + int 13h ;call ROM-Bios ;SB ;3.30* +;SB33028******************************************************************** + cmp dl, 0 + jz DoMiniRet ;no hard file? Then exit. + mov numh, dl ;save the number of hard files. + xor ax,ax + mov al, drvmax + mov mininum, al ;this will be the logical drive letter + ;for mini disk to start with. + + shl ax, 1 ;ax=number of devices. make it to word boundary + push bx + mov bx, offset DSKDRVS + add bx, ax + mov Mini_BPB_ptr, BX ;Mini_BPB_ptr points to the first available + ;spot in DskDrvs for Mini disk which + ;points to BPB area of BDSM. + pop bx + + mov Rom_Minidsk_num, 80h +DoMiniBegin: + inc dh ;Get # of heads (convert it to 1 based) + xor ax, ax + mov al, dh + mov Mini_HDLIM, ax ;save it. + xor ax, ax + and cl, 3fh ;Get # of sectors/track + mov al, cl + mov Mini_SECLIM, ax ;and save it. + + mov dl, Rom_Minidsk_num ;drive number
+ call GETBOOT ;read master boot record into 7c0:BootBias + assume es:nothing + jc DoMiniNext + call FIND_MINI_PARTITION +DoMiniNext: + dec numh + jz DoMiniRet + inc Rom_MiniDsk_Num ;Next hard file +;SB33028******************************************************************** + mov dl, Rom_MiniDsk_Num ;look at next hard drive ;SB ;3.30* + mov ah, 8h ;get drive parameters ;SB ;3.30* + int 13h ;call ROM-Bios ;SB ;3.30* +;SB33028******************************************************************** + jmp DoMiniBegin + +DoMiniRet: + pop ax + ret + + +;Find_Mini_Partition tries to find every Extended partition on a disk. +;At entry: DI -> BDSM entry +; ES:BX -> 07c0:BootBias - Master Boot Record +; Rom_MiniDsk_Num - ROM drive number +; MiniNum - Logical drive number +; Mini_HDLIM, Mini_SECLIM +; +;Called routine: SETMINI which uses SET1 (in SETHARD routine) +;Variables & equates used from original BIOS - flags, fNon_Removable, fBigfat +; +; +FIND_MINI_PARTITION: + + add bx, 1C2h ;BX -> system id. + +FmpNext: + cmp byte ptr ES:[BX], 5 ; 5 = extended partition ID. + jz FmpGot + add bx, 16 ; for next entry + cmp bx, 202h+BootBias + jnz FmpNext + jmp FmpRet ;not found extended partition + +FmpGot: ;found my partition. + Message ftestHard,<"Found my partition...",cr,lf> + xor ax,ax + or al, fNon_Removable + or word ptr [DI].Flags, ax + mov byte ptr [DI].FormFactor, ffHardFile + mov fBigFat, 0 ;assume 12 bit Fat. + mov ax, Mini_HDLIM + mov [DI].HDLIM, ax + mov ax, Mini_SECLIM + mov [DI].SECLIM, ax + mov al, Rom_MiniDsk_Num + mov [DI].DRIVENUM, al ;set physical number + mov al, Mininum + mov [DI].DRIVELET, al ;set logical number + + cmp word ptr es:[bx+10], 0 ;AN000; + ja FmpGot_Cont ;AN000; + cmp word ptr ES:[BX+8], 64 ;**With current BPB, only lower word + ; is meaningful. + jb FmpRet ;should be bigger than 64 sectors at least +FmpGot_Cont: ;AN000; + sub bx, 4 ;let BX point to the start of the entry + mov dh, byte ptr ES:[BX+2] + and dh, 11000000b ;get higher bits of cyl + rol dh, 1 + rol dh, 1 + mov dl, byte ptr ES:[BX+3] ;cyl byte + mov [DI].HIDDEN_TRKS, dx ;set hidden trks +;** Now, read the volume boot record into BootBias. +;SB33029****************************************************************** + mov cx,ES:[BX+2] ;cylinder,cylinder/sector ;SB ;3.30* + mov dh,ES:[BX+1] ;head ;SB ;3.30* + mov dl,Rom_MiniDsk_Num ;drive ;SB ;3.30* + mov bx,BOOTBIAS ;buffer offset ;SB ;3.30* + mov ax,0201h ;read,1 sector ;SB ;3.30* + int 13h ;call ROM-Bios routine ;SB ;3.30* +;SB33029****************************************************************** + jc FmpRet ;cannot continue. + mov bx, 1c2h+BOOTBIAS + + push es ;;DCL/KWC 8/2/87 addressability to + ;; next minidisk + + call SetMini ;install a mini disk. BX value saved. + + pop es ;;DCL/KWC 8/2/87 + + jc FmpnextChain + + call Install_BDSM ;install the BDSM into the BDS table +; call Show_Installed_Mini ;show the installed message. 3/35/86 - Don't show messages. J.K. + inc mininum ;increase the logical drive number for next + inc num_mini_dsk ;increase the number of mini disk installed. + + push bx ;now, set the DskDrvs pointer to BPB info. + mov bx, Mini_BPB_ptr + lea si, [di].BYTEPERSEC ;points to BPB of BDSM + mov [bx], si + inc Mini_BPB_ptr ;advance to the next address + inc Mini_BPB_ptr + pop bx + + add DI, type BDSM_type ;adjust to the next BDSM table entry. + mov End_OF_BDSM, DI ;set the ending address of BDSM table to this. +; Message fTestHard,<"Mini disk installed.",cr,lf> +FmpnextChain: jmp FmpNext ;let's find out if we have any chained partition +FmpRet: + ret + +SetMini: + push di + push bx + push ds + jmp SET1 ;will be returned to Find mini partition routine. + ;Some logic has been added to SET1 to + ;deal with Mini disks. + +; +;Install BDSM installs a BDSM (pointed by DS:DI) into the end of the current +;linked list of BDS. +;Also, set the current BDSM pointer segment to DS. +;At entry: DS:DI -> BDSM +; +Install_BDSM: +assume ds:code,es:nothing + push ax + push si + push es + + les si, dword ptr cs:Start_BDS ;start of the beginning of list +I_BDSM_Next: + cmp word ptr es:[si], -1 ;end of the list? + jz I_BDSM_New + mov si, word ptr es:[si].LINK + mov ax, word ptr es:[si].LINK+2 ;next pointer + mov es, ax + jmp short I_BDSM_Next +I_BDSM_New: + mov ax, ds + mov word ptr ds:[di].LINK+2, ax ;BDSM segment had not been initialized. + mov word ptr es:[si].LINK+2, ax + mov word ptr es:[si].LINK, di + mov word ptr ds:[di].LINK, -1 ;make sure it is a null ptr. + +I_BDSM_ret: + pop es + pop si + pop ax + ret + +;***The following code is not needed any more. Don't show any +;***messages to be compatible with the behavior of IBMBIO.COM. +;;Show the message "Mini disk installed ..." +;;This routine uses WRMSG procedure which will call OUTCHR. +;Show_Installed_Mini: +; push ax +; push bx +; push ds +; +; mov al, Mininum ;logical drive number +; add al, Drv_Letter_Base ;='A' +; mov Mini_Drv_Let, al +; mov si, offset Installed_Mini +; call WRMSG +; +; pop ds +; pop bx +; pop ax +; ret +;**End of mini disk initialization** ;J.K. 4/7/86 + + +CMOS_Clock_Read proc near + + assume ds:code,es:code +; IN ORDER TO DETERMINE IF THERE IS A CLOCK PRESENT IN THE SYSTEM, THE FOLLOWING +; NEEDS TO BE DONE. + PUSH AX + PUSH CX + PUSH DX + PUSH BP + + XOR BP,BP +LOOP_CLOCK: + XOR CX,CX + XOR DX,DX +;SB33030******************************************************************** + MOV AH,2 ;READ REAL TIME CLOCK ;SB ;3.30 + INT 1Ah ;CALL ROM-BIOS ROUTINE ;SB ;3.30 +;SB33030******************************************************************** + CMP CX,0 + JNZ CLOCK_PRESENT + + CMP DX,0 + JNZ CLOCK_PRESENT + + CMP BP,1 ; READ AGAIN AFTER A SLIGHT DELAY, IN CASE CLOCK + JZ NO_READDATE ; WAS AT ZERO SETTING. + + INC BP ; ONLY PERFORM DELAY ONCE. + MOV CX,4000H +DELAY: + LOOP DELAY + JMP LOOP_CLOCK + +CLOCK_PRESENT: + mov cs:HaveCMOSClock, 1 ;J.K. Set the flag for cmos clock + + call CMOSCK ;J.K. Reset CMOS clock rate that may be + ;possibly destroyed by CP DOS and POST routine did not + ;restore that. + + PUSH SI + MESSAGE FTESTINIT,<"CLOCK DEVICE",CR,LF> + CALL READ_REAL_DATE ;MJB002 READ REAL-TIME CLOCK FOR DATE + + CLI ;MJB002 + MOV DAYCNT,SI ;MJB002 SET SYSTEM DATE + STI ;MJB002 + POP SI ;MJB002 +NO_READDATE: + POP BP + POP DX + POP CX + POP AX + RET + +CMOS_Clock_Read endp +; +;J.K. 10/28/86 +;J.K. THE FOLLOWING CODE IS WRITTEN BY JACK GULLEY IN ENGINEERING GROUP. +;J.K. CP DOS IS CHANGING CMOS CLOCK RATE FOR ITS OWN PURPOSES AND IF THE +;J.K. USE COLD BOOT THE SYSTEM TO USE PC DOS WHILE RUNNING CP DOS, THE CMOS +;J.K. CLOCK RATE ARE STILL SLOW WHICH SLOW DOWN DISK OPERATIONS OF PC DOS +;J.K. WHICH USES CMOS CLOCK. PC DOS IS PUT THIS CODE IN MSINIT TO FIX THIS +;J.K. PROBLEM AT THE REQUEST OF CP DOS. +;J.K. THE PROGRAM IS MODIFIED TO BE RUN ON MSINIT. Equates are defined in CMOSEQU.INC. +;J.K. This program will be called by CMOS_Clock_Read procedure. +; +; The following code CMOSCK is used to insure that the CMOS has not +; had its rate controls left in an invalid state on older AT's. +; +; It checks for an AT model byte "FC" with a submodel type of +; 00, 01, 02, 03 or 06 and resets the periodic interrupt rate +; bits incase POST has not done it. This initilization routine +; is only needed once when DOS loads. It should be ran as soon +; as possible to prevent slow diskette access. +; +; This code exposes one to DOS clearing CMOS setup done by a +; resident program that hides and re-boots the system. +; +CMOSCK PROC NEAR ; CHECK AND RESET RTC RATE BITS + assume ds:nothing,es:nothing + +;Model byte and Submodel byte were already determined in MSINIT. + push ax + cmp cs:Model_byte, 0FCh ;check for PC-AT model byte + ; EXIT IF NOT "FC" FOR A PC-AT + JNE CMOSCK9 ; Exit if not an AT model + + CMP cs:Secondary_Model_Byte,06H ; Is it 06 for the industral AT + JE CMOSCK4 ; Go reset CMOS periodic rate if 06 + CMP cs:Secondary_Model_Byte,04H ; Is it 00, 01, 02, or 03 + JNB CMOSCK9 ; EXIT if problem fixed by POST + ;J.K. Also,Secondary_model_byte = 0 when AH=0c0h, int 15h failed. +CMOSCK4: ; RESET THE CMOS PERIODIC RATE + ; Model=FC submodel=00,01,02,03 or 06 +;SB33IN2*********************************************************************** + + mov al,CMOS_REG_A or NMI ;NMI disabled on return + mov ah,00100110b ;Set divider & rate selection + call CMOS_WRITE + +;SB33IN2*********************************************************************** + + ; CLEAR SET,PIE,AIE,UIE AND SQWE + mov al,CMOS_REG_B or NMI ;NMI disabled on return + call CMOS_READ + and al,00000111b ;clear SET,PIE,AIE,UIE,SQWE + mov ah,al + mov al,CMOS_REG_B ;NMI enabled on return + call CMOS_WRITE + +;SB33IN3*********************************************************************** + +CMOSCK9: ; EXIT ROUTINE + pop ax + RET ; RETurn to caller + ; Flags modifyied +CMOSCK ENDP +PAGE +;--- CMOS_READ ----------------------------------------------------------------- +; READ BYTE FROM CMOS SYSTEM CLOCK CONFIGURATION TABLE : +; : +; INPUT: (AL)= CMOS TABLE ADDRESS TO BE READ : +; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : +; BITS 6-0 = ADDRESS OF TABLE LOCATION TO READ : +; : +; OUTPUT: (AL) VALUE AT LOCATION (AL) MOVED INTO (AL). IF BIT 7 OF (AL) WAS : +; ON THEN NMI LEFT DISABLED. DURING THE CMOS READ BOTH NMI AND : +; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : +; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : +; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : +; ONLY THE (AL) REGISTER AND THE NMI STATE IS CHANGED. : +;------------------------------------------------------------------------------- + +CMOS_READ PROC NEAR ; READ LOCATION (AL) INTO (AL) + assume es:nothing,ds:nothing + PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS +;SB33IN4******************************************************************** + + cli + push bx + push ax ;save user NMI state + or al,NMI ;disable NMI for us + out CMOS_PORT,al + nop ;undocumented delay needed + in al,CMOS_DATA ;get data value + + ;set NMI state to user specified + mov bx,ax ;save data value + pop ax ;get user NMI + and al,NMI + or al,CMOS_SHUT_DOWN + out CMOS_PORT,al + nop + in al,CMOS_DATA + + mov ax,bx ;data value + pop bx + +;SB33IN4******************************************************************** + PUSH CS ; *PLACE CODE SEGMENT IN STACK AND + CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 + RET ; RETURN WITH FLAGS RESTORED + +CMOS_READ ENDP + +CMOS_POPF PROC NEAR ; POPF FOR LEVEL B- PARTS + IRET ; RETURN FAR AND RESTORE FLAGS + +CMOS_POPF ENDP + +;--- CMOS_WRITE ---------------------------------------------------------------- +; WRITE BYTE TO CMOS SYSTEM CLOCK CONFIGURATION TABLE : +; : +; INPUT: (AL)= CMOS TABLE ADDRESS TO BE WRITTEN TO : +; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : +; BITS 6-0 = ADDRESS OF TABLE LOCATION TO WRITE : +; (AH)= NEW VALUE TO BE PLACED IN THE ADDRESSED TABLE LOCATION : +; : +; OUTPUT: VALUE IN (AH) PLACED IN LOCATION (AL) WITH NMI LEFT DISABLED : +; IF BIT 7 OF (AL) IS ON. DURING THE CMOS UPDATE BOTH NMI AND : +; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : +; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : +; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : +; ONLY THE CMOS LOCATION AND THE NMI STATE IS CHANGED. : +;------------------------------------------------------------------------------- + +CMOS_WRITE PROC NEAR ; WRITE (AH) TO LOCATION (AL) + assume es:nothing,ds:nothing + PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS + PUSH AX ; SAVE WORK REGISTER VALUES + + cli + push ax ;save user NMI state + or al,NMI ;disable NMI for us + out CMOS_PORT,al + nop + mov al,ah + out CMOS_DATA,al ;write data + + ;set NMI state to user specified + pop ax ;get user NMI + and al,NMI + or al,CMOS_SHUT_DOWN + out CMOS_PORT,al + nop + in al,CMOS_DATA + +;SB33IN5******************************************************************** + POP AX ; RESTORE WORK REGISTERS + PUSH CS ; *PLACE CODE SEGMENT IN STACK AND + CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 + RET + +CMOS_WRITE ENDP +; + + +END$: +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSIOCTL.INC b/v4.0/src/BIOS/MSIOCTL.INC new file mode 100644 index 0000000..9967605 --- /dev/null +++ b/v4.0/src/BIOS/MSIOCTL.INC @@ -0,0 +1,1362 @@ + %OUT MSIOCTL.SIL... + INCLUDE IOCTL.INC +; $SALUT $ioctl$ + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 - P58 Diskcopy format fails when error occurs during format op.6/26/87 J.K. +;AN002; - d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; - p155 Format intermittant failre due to haed settle time 8/18/87 J.K. +;AN004; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN005; P985 Allow I/O access to unformtted media 9/14/87 J.K. +;AN006; D241 Provide support of Multi-track Format/Verify 9/23/87 J.K. +;AN007; P1535 Unformatted hard file problem 10/15/87 J.K. +;AN008; P2590 Change the recommended BPB info. after AFS format 11/20/87 J.K. +;AN009; P2828 Do not retry for multi-track format request 12/08/87 J.K. +;AN010; P2781 Changeline error behavior incompatibile with DOS 3.3. 1/06/88 J.K. +;AN011; P3178 Set Media ID should update media info in BDS table. 1/21/88 J.K. +;AN012; D490 IOCTL subfunction 63h,43h,64h,44h conflicts with OS2 2/26/88 J.K. +;============================================================================== + +;J.K. 10/15/87 +;NOTE: GetAccessFlag/SetAccessFlag is unpublished function. +; This function is intended to give the user to control the +; BDS table FLAGS of UNFORMATTED_MEDIA bit. +; GetAccessFlag will show the status - +; A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 DISK I/O not allowed +; 1 DISK I/O allowed +; SetAccessFlag will Set/Reset the UNFORMATTED_MEDIA bit in FLAGS - +; A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 Allow disk I/O +; 1 Disallow disk I/O +;------------------------------------------------------------------------------ + +; GENERIC IOCTL DISPATCH TABLES +; +IOREADJUMPTABLE DB 7 ;AN012;maximum number (0 based) + DW OFFSET GETDEVICEPARAMETERS ;60h + DW OFFSET READTRACK ;61h + DW OFFSET VERIFYTRACK ;62h + dw Cmd_Err_Proc ;AN012;Overlapped with OS2 subfunction + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw GetMediaID ;AN000;AN012;66h + dw GetAccessFlag ;AN007;AN012;67h Unpublished function + +IOWRITEJUMPTABLE DB 7 ;AN012; + DW OFFSET SETDEVICEPARAMETERS ;40h + DW OFFSET WRITETRACK ;41h + DW OFFSET FORMATTRACK ;42h + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw SetMediaID ;AN000;AN012;46h + dw SetAccessFlag ;AN007;AN012;47h Unpublished function +; +; TRACKTABLE CONTAINS A 4-TUPLES (C,H,R,N) FOR EACH SECTOR IN A TRACK +; C = CYLINDER NUMBER, H = HEAD NUMBER, R = SECTOR ID, N = BYTES PER SECTOR +; N BYTES PER SECTOR +; --- ---------------- +; 0 128 +; 1 256 +; 2 512 +; 3 1024 +; +MAX_SECTORS_CURR_SUP EQU 63 ; CURRENT MAXIMUM SEC/TRK THAT + ; WE SUPPORT (Was 40 in DOS 3.2) +SECTORSPERTRACK DW 36 +TRACKTABLE DB 0,0,1,2 + DB 0,0,2,2 + DB 0,0,3,2 + DB 0,0,4,2 + DB 0,0,5,2 + DB 0,0,6,2 + DB 0,0,7,2 + DB 0,0,8,2 + DB 0,0,9,2 + DB 0,0,10,2 + DB 0,0,11,2 + DB 0,0,12,2 + DB 0,0,13,2 + DB 0,0,14,2 + DB 0,0,15,2 + db 0,0,16,2 + db 0,0,17,2 + db 0,0,18,2 + db 0,0,19,2 + db 0,0,20,2 + db 0,0,21,2 + db 0,0,22,2 + db 0,0,23,2 + db 0,0,24,2 + db 0,0,25,2 + db 0,0,26,2 + db 0,0,27,2 + db 0,0,28,2 + db 0,0,29,2 + db 0,0,30,2 + db 0,0,31,2 + db 0,0,32,2 + db 0,0,33,2 + db 0,0,34,2 + db 0,0,35,2 + db 0,0,36,2 + DB 4*MAX_SECTORS_CURR_SUP - ($ - TRACKTABLE) DUP (0) + +; THIS IS A REAL UGLY PLACE TO PUT THIS +; IT SHOULD REALLY GO IN THE BDS +MEDIATYPE DB 0 + +MEDIA_SET_FOR_FORMAT DB 0 ; 1 IF WE HAVE DONE AN INT 13 SET MEDIA + ; TYPE FOR FORMAT CALL +Had_Format_Error db 0 ; 1 if the previous format operation + ; failed. - J.K. 7/8/86 +Dsk_time_out_Err equ 80h ; Time out error (No media present). +Dsk_change_line_Err equ 6h ; Change line error +Dsk_illegal_combination equ 0Ch ; Return code of ah=18h function. + +; TEMP DISK BASE TABLE. IT HOLDS THE THE CURRENT DPT WHICH IS THEN REPLACED BY +; THE ONE PASSED BY "NEW ROMS" BEFORE WE PERFORM A FORMAT OPERATION. THE OLD +; DPT IS RESTORED IN RESTOREOLDDPT. THE FIRST ENTRY (DISK_SPECIFY_1) IS -1 IF +; THIS TABLE DOES NOT CONTAIN THE PREVIOUSLY SAVED DPT. +TEMPDPT DD -1 + +; +; GENERIC$IOCTL: +; PERFORM GENERIC IOCTL REQUEST +; INPUT: +; AL - UNIT NUMBER +; OUTPUT: +; IF CARRY SET THEN AL CONTAINS ERROR CODE +; + PUBLIC GENERIC$IOCTL +GENERIC$IOCTL: + MESSAGE FTESTDISK,<"GENERIC IOCTL",CR,LF> + LES BX,CS:[PTRSAV] ; ES:BX POINTS TO REQUEST HEADER. + CALL SETDRIVE ; DS:DI POINTS TO BDS FOR DRIVE. +; +; AT THIS POINT: +; ES:BX - POINTS TO THE REQUEST HEADER +; DS:DI POINTS TO THE BDS FOR THE DRIVE +; + CMP ES:[BX].MAJORFUNCTION, RAWIO + JNE IOCTL_FUNC_ERR + MOV AL, ES:[BX].MINORFUNCTION + MOV SI, OFFSET IOREADJUMPTABLE + TEST AL, GEN_IOCTL_FN_TST ; TEST OF REQ. FUNCTION + JNZ NOTGENERICIOCTLWRITE ; FUNCTION IS A READ. + MOV SI, OFFSET IOWRITEJUMPTABLE +NOTGENERICIOCTLWRITE: +; AND AL, 0FH + and al, 9fH ;AN000; Try to check other than 6x, 4x. + CMP AL, CS:[SI] + JA IOCTL_FUNC_ERR + CBW + SHL AX, 1 + INC SI + ADD SI,AX + LES BX, ES:[BX].GENERICIOCTL_PACKET + CALL CS:[SI] + JC FAILGENERIC$IOCTL + JMP EXIT + +FAILGENERIC$IOCTL: + JMP ERR$EXIT + +IOCTL_FUNC_ERR: + JMP CMDERR +Cmd_Err_Proc: ;AN012; + pop dx ;AN012;clear up stack + pop dx ;AN012;clear up stack + jmp IOCTL_FUNC_ERR ;AN012;Cmd error +; +; GETDEVICEPARAMETERS: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO DEVICE PARAMETER PACKET +; + PUBLIC GETDEVICEPARAMETERS +GETDEVICEPARAMETERS PROC NEAR +; COPY INFO FROM BDS TO THE DEVICE PARAMETERS PACKET + MOV AL, BYTE PTR DS:[DI].FORMFACTOR + MOV BYTE PTR ES:[BX].DP_DEVICETYPE, AL + MOV AX, WORD PTR DS:[DI].FLAGS + AND AX,FNON_REMOVABLE+FCHANGELINE ; MASK OFF OTHER BITS + MOV WORD PTR ES:[BX].DP_DEVICEATTRIBUTES, AX + MOV AX, WORD PTR DS:[DI].CCYLN + MOV WORD PTR ES:[BX].DP_CYLINDERS, AX + +; SET MEDIA TYPE TO DEFAULT + XOR AL, AL + MOV BYTE PTR ES:[BX].DP_MEDIATYPE, AL + +; COPY RECOMMENDED BPB + LEA SI, BYTE PTR [DI].RBYTEPERSEC + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, BUILD_DEVICE_BPB + JZ USE_BPB_PRESENT +; GET THE CORRECT DISK IN THE DRIVE + CALL CHECKSINGLE +; BUILD THE BPB FROM SCRATCH + CALL GETBP + JC GET_PARM_RET + LEA SI,BYTE PTR [DI].BYTEPERSEC +USE_BPB_PRESENT: + LEA DI, BYTE PTR [BX].DP_BPB + MOV CX, SIZE BPB_TYPE ; FOR NOW USE 'SMALL' BPB + REP MOVSB + CLC +GET_PARM_RET: + RET +GETDEVICEPARAMETERS ENDP + +; +; SETDEVICEPARAMETERS: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO DEVICE PARAMETER PACKET +; + PUBLIC SETDEVICEPARAMETERS +SETDEVICEPARAMETERS PROC NEAR +; MAKE SURE THE FCHANGED_BY_FORMAT FLAG GETS SET TO KICK DOS INTO LOOKING AT +; THE BPB + OR WORD PTR DS:[DI].FLAGS, FCHANGED_BY_FORMAT OR FCHANGED + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, ONLY_SET_TRACKLAYOUT + JZ SHORT SETDEVPARM_1 + JMP SETTRACKTABLE ; ORIGINALLY TRACKLAYOUT + +SETDEVPARM_1: +; COPY INFO FROM THE DEVICE PARAMETERS PACKET TO BDS + MOV AL, BYTE PTR ES:[BX].DP_DEVICETYPE + MOV BYTE PTR DS:[DI].FORMFACTOR, AL + + MOV AX, WORD PTR ES:[BX].DP_CYLINDERS + MOV WORD PTR DS:[DI].CCYLN, AX + +; IF CHANGE LINE IS NOT LOADED THEN IGNORE CHANGELING FLAG + MOV AX, WORD PTR ES:[BX].DP_DEVICEATTRIBUTES + CMP CS:[FHAVE96],0 + JNZ HAVE_CHANGE + AND AX,NOT FCHANGELINE +HAVE_CHANGE: +; IGNORE ALL BITS EXCEPT NON_REMOVABLE AND CHANGELINE + AND AX,FNON_REMOVABLE OR FCHANGELINE + MOV CX, WORD PTR DS:[DI].FLAGS +; AND CX, NOT (FNON_REMOVABLE OR FCHANGELINE OR GOOD_TRACKLAYOUT) + AND CX, NOT (FNON_REMOVABLE OR FCHANGELINE OR GOOD_TRACKLAYOUT or UNFORMATTED_MEDIA) ;AN004;AN005;AN007; + OR AX, CX + MOV WORD PTR DS:[DI].FLAGS, AX + +; SET MEDIA TYPE + MOV AL, BYTE PTR ES:[BX].DP_MEDIATYPE + MOV CS:MEDIATYPE, AL +; THE MEDIA CHANGED (MAYBE) SO WE WILL HAVE TO DO A SETDASD THE NEXT TIME +; WE FORMAT A TRACK + OR WORD PTR DS:[DI].FLAGS, SET_DASD_TRUE + + SAVEREG +; FIGURE OUT WHAT WE ARE SUPPOSED TO DO WITH THE BPB + +; WERE WE ASKED TO INSTALL A FAKE BPB? + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, INSTALL_FAKE_BPB + JNZ SHORT INSTALLFAKEBPB + +; WERE WE RETURNING A FAKE BPB WHEN ASKED TO BUILD A BPB? + TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB + JZ SHORT INSTALLRECOMMENDEDBPB + +; WE WERE RETURNING A FAKE BPB BUT WE CAN STOP NOW + AND WORD PTR DS:[DI].FLAGS, NOT RETURN_FAKE_BPB +; JMP DONEWITHBPBSTUFF ;AN008; Comment out this instruction. + +INSTALLRECOMMENDEDBPB: + MOV CX, SIZE A_BPB + LEA DI, BYTE PTR [DI].RBYTEPERSEC + JMP SHORT COPYTHEBPB + +INSTALLFAKEBPB: + or word ptr ds:[di].flags, return_fake_bpb ;AN000; Problem + ;reported by WHS. + MOV CX, SIZE BPB_TYPE ; MOVE 'SMALLER' BPB + LEA DI, BYTE PTR [DI].BYTEPERSEC +COPYTHEBPB: + LEA SI, BYTE PTR [BX].DP_BPB +; EXCHANGE ES AND DS + PUSH ES + PUSH DS + POP ES + POP DS + + REP MOVSB + +DONEWITHBPBSTUFF: + CALL RESTOREOLDDPT ; RESTORE THE OLD DPT FROM TEMPDPT + RESTOREREG + +; SET UP TRACK TABLE (IF NECCESSARY) +SETTRACKTABLE: + MOV CX, WORD PTR ES:[BX].DP_TRACKTABLEENTRIES + MOV CS:SECTORSPERTRACK, CX + AND WORD PTR DS:[DI].FLAGS, NOT GOOD_TRACKLAYOUT + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, TRACKLAYOUT_IS_GOOD + JZ UGLYTRACKLAYOUT + OR WORD PTR DS:[DI].FLAGS, GOOD_TRACKLAYOUT + +UGLYTRACKLAYOUT: + CMP CX, MAX_SECTORS_IN_TRACK + JA TOOMANYSECTORSPERTRACK + JCXZ SECTORINFOSAVED + MOV DI, OFFSET TRACKTABLE + LEA SI, ES:[BX].DP_SECTORTABLE + PUSH ES + POP DS + PUSH CS + POP ES +STORESECTORINFO: + INC DI ; SKIP OVER CYLINDER + INC DI ; SKIP OVER HEAD + LODSW ; GET SECTOR ID + PUSH AX ; SAVE IT + LODSW ; GET SECTOR SIZE + CALL SECTORSIZETOSECTORINDEX + POP DX ; GET SECTOR ID BACK + MOV AL, DL ; AH = SECTOR SIZE INDEX + ; AL = SECTOR ID + STOSW + LOOP STORESECTORINFO + +SECTORINFOSAVED: + CLC + RET + +TOOMANYSECTORSPERTRACK: + MOV AL, 0CH + STC + RET + +SETDEVICEPARAMETERS ENDP + +; +; SET MEDIA TYPE FOR FORMAT +; PERFORMS THE INT 13 WITH AH = 18H TO SEE IF THE MEDIUM DESCRIBED IN THE +; BPB AREA IN THE BDS CAN BE HANDLED BY THE ROM. +; ON INPUT, DS:DI -> CURRENT BDS. +; THE STATUS OF THE OPERATION IS RETURNED IN AL +; - 0 - IF THE SUPPORT IS AVAILABLE, AND THE COMBINATION IS VALID. +; - 1 - NO ROM SUPPORT +; - 2 - ILLEGAL COMBINATION +; - 3 - No media present (ROM support exists but cannot determine now) +; FLAGS ALSO MAY BE ALTERED. ALL OTHER REGISTERS PRESERVED. +; IF THE CALL TO ROM RETURNS NO ERROR, THEN THE CURRENT DPT IS "REPLACED" BY +; THE ONE RETURNED BY THE ROM. THIS IS DONE BY CHANGING THE POINTER IN [DPT] +; TO THE ONE RETURNED. THE ORIGINAL POINTER TO THE DISK BASE TABLE IS STORED +; IN TEMPDPT, UNTIL IT IS RESTORED. +; + PUBLIC SET_MEDIA_FOR_FORMAT +SET_MEDIA_FOR_FORMAT PROC NEAR + SAVEREG + XOR AX,AX + cmp cs:[Had_Format_Error],1 ;Did we have a format error before? + jne No_Form_Err ;AN001; + call ResetDisk +No_Form_Err: ;AN001; + CMP BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 + jnz Do_Set_Media_for_Format + jmp SET_MED_RET ; MEDIA ALREADY SET +Do_Set_Media_for_Format: + SAVEREG + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR] ; GET POINTER TO DISK BASE TABLE + MOV WORD PTR CS:[DPT],SI + MOV WORD PTR CS:[DPT+2],DS ; SAVE POINTER TO TABLE +;SB34IOCTL000****************************************************************** +;SB Initialise the head settle time to 0fh. See the offsets given in +;SB DSKPRM.INC. 1 LOC. + + mov ds:[si].DISK_HEAD_STTL, 0Fh +;SB34IOCTL000****************************************************************** + RESTOREREG + mov cs:[New_Rom], 1 ;assume a new ROM. + XOR AL,AL +;SB33031**************************************************************** + mov cx,ds:[di.ccyln] ;get number of cylinders ;SB ;3.30* + dec cx ;cylinder must be zero based ;SB ;3.30* + and ch,03h ; blank out unnecessary bits + ror ch,1 ;put in int form ;SB ;3.30* + ror ch,1 ; ;SB ;3.30* + xchg ch,cl ; ;SB ;3.30* + or cl,byte ptr ds:[di.seclim] ;get number of sectors ;SB ;3.30* + mov dl,ds:[di.drivenum] ;get drive number ;SB ;3.30* + mov ah,18h ;set media for format ;SB ;3.30* + SAVEREG + int 13h ;call rom bios ;SB ;3.30* +;SB33031**************************************************************** + JC FORMAT_STAT_ERR +; ES:DI POINTS TO A DISK BASE TABLE FOR THIS COMBINATION FOR THIS DRIVE. + XOR CX,CX + MOV DS,CX ; HAVE DS -> SEGMENT 0 + LDS SI,DWORD PTR DS:[DSKADR] ; GET CURRENT DISK BASE TABLE + MOV WORD PTR CS:[TEMPDPT],SI + MOV WORD PTR CS:[TEMPDPT+2],DS ; SAVE IT + MOV WORD PTR DS:[DSKADR],DI + MOV WORD PTR DS:[DSKADR+2],ES ; REPLACE WITH ONE RETURNED BY ROM + MOV BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 +Skip_Disk_Base_setting: + XOR AL,AL ; LEGAL COMBINATION + ROM SUPPORT CODE + mov cs:[Had_Format_Error],al ;reset the flag + JMP SHORT POP_STAT_RET + +FORMAT_STAT_ERR: + cmp ah, Dsk_illegal_combination ;J.K. illegal combination = 0ch + je Format_stat_illegal_comb + cmp ah, Dsk_Time_Out_Err ;J.K. = 80h + je Format_stat_Time_out + mov al, 1 ;Function not supported. + mov cs:[New_Rom], 0 ;So, it is an old rom. + jmp short Pop_stat_ret +Format_stat_illegal_comb: ;J.K. Function supported, but + MOV AL,2 ;J.K. illegal sect/trk, trk combination. + jmp short Pop_stat_ret +Format_stat_Time_out: ;J.K. Function supported, but + mov al, 3 ;J.K. media not present. +POP_STAT_RET: + RESTOREREG +SET_MED_RET: + RESTOREREG + RET + +SET_MEDIA_FOR_FORMAT ENDP + +; +; FORMATTRACK: +; IF SPECIALFUNCTION BYTE IS 1, THEN THIS IS A STATUS CALL TO SEE IF THERE IS +; ROM SUPPORT FOR THE COMBINATION OF SEC/TRK AND # OF CYLN, AND IF THE +; COMBINATION IS LEGAL. IF SPECIALFUNCTION BYTE IS 0, THEN FORMAT THE TRACK. +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO FORMAT PACKET +; +; OUTPUT: +; FOR STATUS CALL: +; SPECIALFUNCTION BYTE SET TO: +; 0 - ROM SUPPORT + LEGAL COMBINATION +; 1 - NO ROM SUPPORT +; 2 - ILLEGAL COMBINATION +; 3 - no media present ;J.K. 7/8/86 +; CARRY CLEARED. +; +; FOR FORMAT TRACK: +; CARRY SET IF ERROR +; + PUBLIC FORMATTRACK +FORMATTRACK PROC NEAR + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS,STATUS_FOR_FORMAT + JZ DO_FORMAT_TRACK + CALL SET_MEDIA_FOR_FORMAT ; ALSO MOVES CURRENT DPT TO TEMPDPT +STAT_RET: + MOV BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS,AL + CLC + RET + +DO_FORMAT_TRACK: + CMP BYTE PTR DS:[DI].FORMFACTOR, DEV_HARDDISK + jne Do_Format_Diskette + jmp DoVerifyTrack +Do_Format_Diskette: + SAVEREG +;SB34IOCTL001************************************************************* +;SB check the special functions word to see if DO_FAST_FORMAT has been +;SB specified. If so it is an error and we need to finish this operation +;SB by indicating the error value 1 in register ah and going to the +;SB the code at DO_MAP_IT to map the error. This is because we cannot +;SB allow multitrack format on floppies - 5 LOCS + + test byte ptr es:[bx].FP_SPECIALFUNCTIONS,DO_FAST_FORMAT + jz NO_FAST_FORMAT + mov ah, 1 + jmp DO_MAP_IT +NO_FAST_FORMAT: +;SB34IOCTL001************************************************************* + CALL SET_MEDIA_FOR_FORMAT ; ALSO MOVES CURRENT DPT TO TEMPDPT + CMP AL,1 ; DO WE HAVE ROM SUPPORT FOR sector/trk, # trks combination? + JZ Need_Set_DASD ;Old ROM. + cmp al,3 ;time out error? + jnz No_Set_DASD ;No, fine.(At this point, don't care about the illegal combination.) + jmp Format_Failed +Need_Set_DASD: + CALL SETDASD ;AH=17h, INT 13h +; +; STORE CYLINDER,HEAD IN TRACK TABLE +; ***** ASSUMPTION ******* +; SINCE FORMAT REQUESTS ON FIXED MEDIA ARE CONVERTED TO VERIFIES, WE +; ASSUME THAT WE ARE FORMATTING A FLOPPY AND HENCE HAVE 255 OR LESS +; TRACKS AND HEADS. WE THEREFORE MUST CHANGE THE CYLINDER, HEAD DATA +; FROM THE REQUEST PACKET SIZE TO THAT OF THE TRACKTABLE (SEE INT 13 +; INTERFACE IN IBM'S TECH REF.). + +NO_SET_DASD: +; CHECK TO ENSURE CORRECT DISK IS IN DRIVE + CALL CHECKSINGLE + + MOV AX, WORD PTR ES:[BX].FP_CYLINDER + MOV WORD PTR CS:[TRKNUM],AX + MOV CX, WORD PTR ES:[BX].FP_HEAD + MOV BYTE PTR CS:[HDNUM],CL + MOV AH,CL + + PUSH DI ; SAVE PTR TO BDS + MOV DI, OFFSET TRACKTABLE + PUSH CS + POP ES + MOV CX, CS:SECTORSPERTRACK +STORECYLINDERHEAD: + STOSW + INC DI ; SKIP SECTOR ID + INC DI ; SKIP SECTOR SIZE + LOOP STORECYLINDERHEAD + POP DI ; RESTORE PTR TO BDS + + MOV CX, MAXERR ; SET UP RETRY COUNT +FORMATRETRY: + PUSH CX + MOV BX, OFFSET TRACKTABLE + PUSH CS + POP ES + MOV AX, CS:SECTORSPERTRACK + MOV AH, ROMFORMAT + CALL TO_ROM + POP CX + JNC FORMATOK + call resetdisk + mov cs:[Had_Format_Error],1 + push ax + push cx + push dx + call Set_Media_For_Format + cmp al, 1 + jnz While_Err + call SetDASD +While_Err: + pop dx + pop cx + pop ax + LOOP FORMATRETRY +;SB33106******************************************************************* +Format_Failed: + mov cs:[Had_Format_Error], 1 ;set the format error flag. + cmp ah, Dsk_Change_Line_Err ;=06h. Convert change line + jne Do_Map_it ;error to Time Out error. + mov ah, Dsk_Time_Out_Err ;=80h +;SB33106******************************************************************* +Do_Map_it: + CALL MAPERROR + RESTOREREG + RET + +FORMATOK: + mov cs:[Had_Format_Error],0 ;reset the format error flag. + RESTOREREG + +DOVERIFYTRACK: + CALL VERIFYTRACK + RET + +FORMATTRACK ENDP + +VerifyTrack_Err: ;AN006; + mov ah, 1 ;AN006; + call MapError ;AN006; + ret ;AN006; + +; +; VERIFYTRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO VERIFY PACKET +; + PUBLIC VERIFYTRACK +VERIFYTRACK PROC NEAR + MOV CS:RFLAG, ROMVERIFY + MOV AX, WORD PTR ES:[BX].VP_CYLINDER + MOV CS:CURTRK, AX + MOV AX, WORD PTR ES:[BX].VP_HEAD + +; ****** ASSUMPTION ****** +; WE ASSUME THAT WE HAVE LESS THAN 256 HEADS, AND THAT THE REQUEST +; HEADER DATA STRUCTURE IS UNNECCESSARILY BIG + MOV CS:CURHD, AL + MOV CX, CS:SECTORSPERTRACK ;CL = sectors/track +;SB34IOCTL005************************************************************* +;SB +;SB Check SPECIALFUNCTIONS to see if DO_FAST_FORMAT has been specified +;SB If not we should go to the normal track verification routine. If +;SB fast format has been specified we should get the number of tracks +;SB to be verified and check it to see if it is > 255. If it is then +;SB it is an error and we should go to VerifyTrack_Err. If not multiply +;SB the number of tracks by the sectors per track to get the total +;SB number of sectors to be verified. This should also be less than +;SB equal to 255 otherwise we go to same error exit. If everything +;SB is okay we initalise cx to the total sectors. use ax as a temporary +;SB register. 9 LOCS + + test byte ptr es:[bx].FP_SPECIALFUNCTIONS,DO_FAST_FORMAT + jz Norm_VerifyTrack + mov ax,es:[bx].FP_TRACKCOUNT ;ax <- tracks to be verify + cmp ax,0FFh + ja VerifyTrack_Err ;#tracks > 255 + mul cl + cmp ax,0FFh ;#sectors > 255 + ja VerifyTrack_Err + mov cx,ax ;#sectors to verify +;SB34IOCTL005************************************************************* + +;Set the multi track request flag + test word ptr [di].Flags, fNON_REMOVABLE ;AN009;hard disk? + jz Norm_VerifyTrack ;AN009; + test cs:Multrk_Flag, MULTRK_ON ;AN009;MultiTrack operation = on? + jz Norm_VerifyTrack ;AN009; + mov cs:Multitrk_Format_Flag, 1 ;AN009; then set the flag +Norm_VerifyTrack: ;AN006; + XOR AX, AX ;1st sector +; USE 0:0 AS THE TRANSFER ADDRESS FOR VERIFY + XOR BX, BX + MOV ES, BX + CALL TRACKIO + mov cs:Multitrk_Format_Flag, 0 ;AN009;Reset the flag. + RET +VERIFYTRACK ENDP + +; +; READTRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO READ PACKET +; + PUBLIC READTRACK +READTRACK: + MOV CS:RFLAG, ROMREAD + JMP READWRITETRACK + +; +; WRITETRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO WRITE PACKET +; + PUBLIC WRITETRACK +WRITETRACK: + MOV CS:RFLAG, ROMWRITE + JMP READWRITETRACK +; +; READWRITETRACK: +; +; INPUT: +; DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO WRITE PACKET +; RFLAG - 2 FOR READ, 3 FOR WRITE +; + PUBLIC READWRITETRACK +READWRITETRACK PROC NEAR + MOV AX, WORD PTR ES:[BX].TRWP_CYLINDER + MOV CS:CURTRK, AX + MOV AX, WORD PTR ES:[BX].TRWP_HEAD + +; ****** ASSUMPTION ****** +; WE ASSUME THAT WE HAVE LESS THAN 256 HEADS, AND THAT THE REQUEST +; HEADER DATA STRUCTURE IS UNNECCESSARILY BIG + MOV CS:CURHD, AL + MOV AX, WORD PTR ES:[BX].TRWP_FIRSTSECTOR + MOV CX, WORD PTR ES:[BX].TRWP_SECTORSTOREADWRITE + LES BX, ES:[BX].TRWP_TRANSFERADDRESS + CALL TRACKIO + RET +READWRITETRACK ENDP + + +; +; TRACKIO: +; PERFORMS TRACK READ/WRITE/VERIFY +; +; INPUT: +; RFLAG - 2 = READ +; 3 = WRITE +; 4 = VERIFY +; AX - INDEX INTO TRACK TABLE OF FIRST SECTOR TO IO +; CX - NUMBER OF SECTORS TO IO +; ES:BX - TRANSFER ADDRESS +; DS:DI - POINTER TO BDS +; CURTRK - CURRENT CYLINDER +; CURHD - CURRENT HEAD +; + PUBLIC TRACKIO +TRACKIO PROC NEAR +; PROCEDURE `DISK' WILL POP STACK TO SPSAV AND RETURN IF ERROR + MOV CS:SPSAV, SP +; ENSURE CORRECT DISK IS IN DRIVE + CALL CHECKSINGLE +; SEE IF WE HAVE ALREADY SET THE DISK BASE TABLE + CMP BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 + JZ DPTALREADYSET +; +; SET UP TABLES AND VARIABLES FOR I/O +; + SAVEREG + CALL IOSETUP + RESTOREREG +; +; POINT SI AT THE TABLE ENTRY OF THE FIRST SECTOR TO BE IO'D +; +DPTALREADYSET: + MOV SI, OFFSET TRACKTABLE + SHL AX, 1 + SHL AX, 1 + ADD SI, AX +; +; WE WANT: +; CX TO BE THE NUMBER OF TIMES WE HAVE TO LOOP +; DX TO BE THE NUMBER OF SECTORS WE READ ON EACH ITERATION + MOV DX, 1 + TEST WORD PTR DS:[DI].FLAGS, GOOD_TRACKLAYOUT + JZ IONEXTSECTOR + +; HEY! WE CAN READ ALL THE SECTORS IN ONE BLOW + XCHG DX, CX + +IONEXTSECTOR: + PUSH CX + PUSH DX +; SKIP OVER THE CYLINDER AND HEAD IN THE TRACK TABLE + INC SI + INC SI +; GET SECTOR ID FROM TRACK TABLE + LODS BYTE PTR CS:[SI] + MOV CS:CURSEC, AL +;*** For a Fixed disk multi-track disk I/O - J.K. 4/14/86 +;Assumptions: 1). In the input CX (# of sectors to go) to TRACKIO, only CL is +;valid. 2). Sector size should be set to 512 bytes. 3). GOODTRACKLAYOUT. +; + test word ptr [di].Flags, fNon_Removable ;Fixed disk? - J.K. + jz IOREMOVABLE ;no -J.K. + test cs:MulTrk_Flag, MULTRK_ON ;AN002; Allow multi-track operation? + jz IORemovable ;AN002; No, don't do that. + mov cs:[seccnt], dx ;# of sectors to I/O -J.K. + mov ax, dx ;J.K. + call disk ;J.K. + pop dx ;J.K. + pop cx ;J.K. + clc ;J.K. + ret ;J.K. +IOREMOVABLE: ;J.K. +; GET SECTOR SIZE INDEX FROM TRACK TABLE AND SAVE IT + LODS BYTE PTR CS:[SI] + PUSH AX +; PATCH SECTOR SIZE IN DPT + PUSH SI + PUSH DS + LDS SI, CS:DPT + MOV BYTE PTR DS:[SI].DISK_SECTOR_SIZ,AL + MOV AL,CS:[EOT] + MOV [SI].DISK_EOT,AL ; SET UP THE MAX NUMBER OF SEC/TRACK + POP DS + MOV AL, DL +DOTHEIO: + MOV CS:[SECCNT],AX ; SET UP THE COUNT OF SECTORS TO I/O + CALL DISK +; ADVANCE BUFFER POINTER BY ADDING SECTOR SIZE + POP SI + POP AX + CALL SECTORSIZEINDEXTOSECTORSIZE + ADD BX, AX + POP DX + POP CX + LOOP IONEXTSECTOR + cmp byte ptr cs:[Media_Set_For_Format], 1 ;AN001; + je No_Need_Done ;AN001; + CALL DONE ; SET TIME OF LAST ACCESS, AND RESET +No_Need_Done: ;AN001; + CLC ; ENTRIES IN DPT. + RET + +TRACKIO ENDP +; +; THE SECTOR SIZE IN BYTES NEEDS TO BE CONVERTED TO AN INDEX VALUE FOR THE IBM +; ROM. (0=>128, 1=>256,2=>512,3=>1024). IT IS ASSUMED THAT ONLY THESE VALUES +; ARE PERMISSIBLE. +; ON INPUT AX CONTAINS SECTOR SIZE IN BYTES +; ON OUTPUT AL CONTAINS INDEX +; + PUBLIC SECTORSIZETOSECTORINDEX +SECTORSIZETOSECTORINDEX PROC NEAR + CMP AH,2 ; EXAMINE UPPER BYTE ONLY + JA ONEK + MOV AL,AH ; VALUE IN AH IS THE INDEX! + RET +ONEK: + MOV AL,3 + RET +SECTORSIZETOSECTORINDEX ENDP + +SECTORSIZEINDEXTOSECTORSIZE PROC NEAR + MOV CL, AL + MOV AX,128 + SHL AX, CL + RET +SECTORSIZEINDEXTOSECTORSIZE ENDP + +; +; SET UP THE ROM FOR FORMATTING. +; WE HAVE TO TELL THE ROM BIOS WHAT TYPE OF DISK IS IN THE DRIVE. +; ON INPUT - DS:DI - POINTS TO BDS +; + PUBLIC SETDASD +SETDASD: +; SEE IF WE HAVE PREVIOUSLY SET DASD TYPE +;SB33114****************************************************************** + cmp cs:[Had_Format_Error],1 + je DoSetDasd +;SB33114****************************************************************** + TEST WORD PTR DS:[DI].FLAGS, SET_DASD_TRUE + JZ DASDHASBEENSET + AND WORD PTR DS:[DI].FLAGS, NOT SET_DASD_TRUE +;SB33115****************************************************************** +DoSetDasd: + mov cs:[Had_Format_Error],0 ;reset it +;SB33115****************************************************************** + MOV CS:[GAP_PATCH],50H ; FORMAT GAP FOR 48TPI DISKS + MOV AL,4 + CMP BYTE PTR DS:[DI].FORMFACTOR,DEV_3INCH720KB + JZ DO_SET + CMP BYTE PTR DS:[DI].FORMFACTOR, DEV_5INCH96TPI + JZ GOT_BIG + MOV AL,1 ; 160/320K IN A 160/320K DRIVE + JMP SHORT DO_SET +GOT_BIG: + MOV AL,2 ; 160/320K IN A 1.2 MEG DRIVE + CMP CS:MEDIATYPE, 0 + JNE DO_SET + MOV AL,3 ; 1.2MEG IN A 1.2MEG DRIVE + MOV CS:[GAP_PATCH],54H +DO_SET: + push ds ;AN003; + push si ;AN003; +;SB34IOCTL002**************************************************************** +;SB Get the disk parameter table address (dword address) from the location +;SB 0:[DSKADR] and fix the head settle time in this to be 0fh. 4 LOCS + + xor si, si + mov ds, si + lds si, dword ptr ds:[DSKADR] + mov ds:[si].DISK_HEAD_STTL, 0Fh +;SB34IOCTL002**************************************************************** + pop si ;AN003; + pop ds ;AN003; +;SB33032****************************************************************** + mov AH, 17h ; set command to Set DASD type;SB ;3.30* + mov DL, [di].DriveNum ; set drive number ;SB ;3.30* + int 13h ; call rom-bios ;SB ;3.30* +;SB33032****************************************************************** +DASDHASBEENSET: + MOV AH,BYTE PTR [DI].SECLIM + MOV CS:[FORMT_EOT],AH + RET + +; +; THIS ROUTINE IS CALLED IF AN ERROR OCCURS WHILE FORMATTING OR VERIFYING. +; IT RESETS THE DRIVE, AND DECREMENTS THE RETRY COUNT. +; ON ENTRY - DS:DI - POINTS TO BDS FOR THE DRIVE +; BP - CONTAINS RETRY COUNT +; ON EXIT FLAGS INDICATE RESULT OF DECREMENTING RETRY COUNT +; +AGAIN: + CALL RESETDISK + +;(deleted section here, as requested by D.L.) + + DEC BP ; DECREMENT RETRY COUNT + RET + + +; RESET THE DRIVE. +; WE ALSO SET [STEP_DRV] TO -1 TO FORCE THE MAIN DISK ROUTINE TO USE THE +; SLOW HEAD SETTLE TIME FOR THE NEXT OPERATION. THIS IS BECAUSE THE RESET +; OPERATION MOVES THE HEAD TO CYLINDER 0, SO WE NEED TO DO A SEEK THE NEXT +; TIME AROUND - THERE IS A PROBLEM WITH 3.5" DRIVES IN THAT THE HEAD DOES +; NOT SETTLE DOWN IN TIME, EVEN FOR READ OPERATIONS!! +; + PUBLIC RESETDISK +RESETDISK: + SAVEREG +;SB33033****************************************************************** + xor AH, AH ; set command to reset disk ;SB ;3.30* + int 13h ; call the rom-bios ;SB ;3.30* +;SB33033****************************************************************** + MOV CS:[STEP_DRV],-1 ; ZAP UP THE SPEED + RESTOREREG + RET + +; +; THIS ROUTINE SETS UP THE DRIVE PARAMETER TABLE WITH THE VALUES NEEDED FOR +; FORMAT, DOES AN INT 13. VALUES IN DPT ARE RESTORED AFTER A VERIFY IS DONE. +; +; ON ENTRY - DS:DI - POINTS TO BDS FOR THE DRIVE +; ES:BX - POINTS TO TRKBUF +; AL - NUMBER OF SECTORS +; AH - INT 13 FUNCTION CODE +; CL - SECTOR NUMBER FOR VERIFY +; ON EXIT - DS,DI,ES,BX REMAIN UNCHANGED. +; AX AND FLAGS ARE THE RESULTS OF THE INT 13 +; + PUBLIC TO_ROM +TO_ROM: + SAVEREG + TEST BYTE PTR CS:[NEW_ROM],1 + JNZ GOT_VALID_DPT + PUSH AX + MOV DX,DS ; SAVE DS:DI-> BDS + XOR AX,AX + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR] ; GET POINTER TO DISK BASE TABLE + MOV WORD PTR CS:[DPT],SI + MOV WORD PTR CS:[DPT+2],DS ; SAVE POINTER TO TABLE + MOV AL,CS:[FORMT_EOT] + MOV [SI].DISK_EOT,AL + MOV AL,CS:[GAP_PATCH] + MOV [SI].DISK_FORMT_GAP,AL ; IMPORTANT FOR FORMAT + MOV [SI].DISK_HEAD_STTL,15 ; ASSUME WE ARE DOING A SEEK OPERATION +; SET UP MOTOR START CORRECTLY FOR 3.5" DRIVES. + PUSH ES + MOV ES,DX + CMP BYTE PTR ES:[DI].FORMFACTOR,FFSMALL ; IS IT A 3.5" DRIVE? + JNZ MOTORSTRTOK + MOV AL,4 + XCHG AL,[SI].DISK_MOTOR_STRT +MOTORSTRTOK: + POP ES +;---------------------------------------------------------------------------- +; THE FOLLOWING TWO LINES ARE NO LONGER NECESSARY SINCE THEY ARE ONLY USEFUL +; FOR A VERIFY OPERATION. +; MOV AL,CS:[SECTOR_SIZ_IND] +; MOV [SI].DISK_SECTOR_SIZ,AL ; IMPORTANT FOR VERIFY +;---------------------------------------------------------------------------- + MOV DS,DX ; RESTORE DS:DI-> BDS + POP AX +GOT_VALID_DPT: +;SB33034******************************************************************* + mov dx, cs:[trknum] ; set track number ;SB ;3.30* + mov ch,dl ; set low 8 bits in ch ;SB ;3.30* + mov DL, ds:[di].DriveNum ; set drive number ;SB ;3.30* + mov DH, CS:[HDNUM] ; set head number ;SB ;3.30* + int 13h ; call the rom-bios routines ;SB ;3.30* +;SB33034******************************************************************* + RESTOREREG + RET + +; +; GET THE OWNER OF THE PHYSICAL DRIVE REPRESENTED BY THE LOGICAL DRIVE IN BL. +; THE ASSUMPTION IS THAT WE **ALWAYS** KEEP TRACK OF THE OWNER OF A DRIVE!! +; IF THIS IS NOT THE CASE, THE SYSTEM MAY HANG, JUST FOLLOWING THE LINKED LIST. +; + PUBLIC IOCTL$GETOWN +IOCTL$GETOWN: + CALL SETDRIVE + MOV AL,BYTE PTR [DI].DRIVENUM ; GET PHYSICAL DRIVE NUMBER + PUSH CS + POP DS + MOV DI,WORD PTR START_BDS +OWN_LOOP: + CMP BYTE PTR [DI].DRIVENUM,AL + JNE GETNEXTBDS + TEST WORD PTR [DI].FLAGS,FI_OWN_PHYSICAL + JNZ DONE_GETOWN +GETNEXTBDS: + MOV BX,WORD PTR [DI].LINK+2 + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + JMP SHORT OWN_LOOP +DONE_GETOWN: + JMP SHORT EXIT_OWN + +; +; SET THE OWNERSHIP OF THE PHYSICAL DRIVE REPRESENTED BY THE LOGICAL DRIVE IN +; BL TO BL. +; + PUBLIC IOCTL$SETOWN +IOCTL$SETOWN: + CALL SETDRIVE + MOV BYTE PTR CS:[FSETOWNER],1 ; SET FLAG FOR CHECKSINGLE TO + ; LOOK AT. + CALL CHECKSINGLE ; SET OWNERSHIP OF DRIVE + MOV BYTE PTR CS:[FSETOWNER],0 ; RESET FLAG + XOR BX,BX + MOV ES,BX + MOV CL,-1 + MOV BYTE PTR ES:[LSTDRV],CL ; SET UP SDSB AS WELL + +EXIT_OWN: +; IF THERE IS ONLY ONE LOGICAL DRIVE ASSIGNED TO THIS PHYSICAL DRIVE, RETURN +; 0 TO USER TO INDICATE THIS. + XOR CL,CL + TEST WORD PTR [DI].FLAGS,FI_AM_MULT + JZ EXIT_NO_MULT + MOV CL,BYTE PTR [DI].DRIVELET ; GET LOGICAL DRIVE NUMBER + INC CL ; GET IT 1-BASED +EXIT_NO_MULT: + LDS BX,CS:[PTRSAV] + MOV BYTE PTR [BX].UNIT,CL + JMP EXIT + + +; +; MOVES THE OLD DPT THAT HAD BEEN SAVED IN TEMPDPT BACK TO DPT. THIS IS DONE +; ONLY IF THE FIRST BYTE OF TEMPDPT IS NOT -1. +; ALL REGISTERS (INCLUDING FLAGS) ARE PRESERVED. +; + PUBLIC RESTOREOLDDPT +RESTOREOLDDPT: +; IF WE HAVE ALREADY RESTORED THE DISK BASE TABLE EARLIER, DO NOT DO IT +; AGAIN. + PUSH AX + XOR AL,AL +; RESET FLAG AND GET CURRENT FLAG SETTING + mov cs:[Had_Format_Error],al + XCHG BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],AL + OR AL,AL + JZ DONTRESTORE + SAVEREG + LDS SI,CS:[TEMPDPT] + XOR AX,AX + MOV ES,AX ; HAVE ES -> SEGMENT 0 + MOV WORD PTR ES:[DSKADR],SI + MOV WORD PTR ES:[DSKADR+2],DS +GOTCURRENTDPT: + RESTOREREG +DONTRESTORE: + POP AX + CLC ; CLEAR CARRY + RET + +;****************************************************************************** +;AN000; Get Media ID +;******************************************************************************* +; * +; Function: Get the volume label, the system id and the serial number from * +; the media that has the extended boot record. * +; For the conventional media, this routine will return "Unknown * +; media type" error to DOS. * +; * +; Input : DS:DI -> BDS table for this drive. * +; ES:BX -> Request packet (= A_Media_ID_INFO structure) * +; * +; Output: The request packet filled with the information, if not carry. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; Register DS,DX,AX,CX,DI,SI destroyed. * +; Subroutines to be called: * +; BOOT_IO:NEAR * +; * +; Logic: * +; /*To recognize the extended boot record, this logic will actually */ * +; /*access the boot sector even if it is a hard disk. */ * +; /*NOTE:the valid extended bpb is recognized by looking at the mediabyte* +; /*field of BPB and the extended Boot Signature. * +; * +; { * +; Get logical drive number from BDS table; * +; RFLAG = Read operation; * +; BOOT_IO; /*Get the media boot record into the buffer*/ * +; IF (no error) THEN * +; IF (extended boot record) THEN * +; { set Volume Label, Volume Serial number and System id * +; of the Request packet to those of the boot record; * +; }; * +; ELSE /*Not an extended BPB */ * +; { set Register AL to "Unknown media.." error code; * +; set Carry bit; * +; }; * +; ELSE * +; Exit; /*Already error code is set in the register AL* +; * +; Expected LOC: 40 (New) * +;******************************************************************************* + +GetMediaID proc near ;AN000; + call Changeline_Chk ;AN010; + mov al, DS:[DI].DRIVELET ;AN000; logical drive number + mov cs:RFlag, ROMREAD ;AN000; read operation + call Boot_IO ;AN000; read boot sector into cs:DiskSector +; $IF NC ;AN000; + JC $IOCTL$IF1 + mov cl, cs:MediaByte ;AN000; Mediabyte in BPB + and cl, 0F0h ;AN000; + cmp cl, 0F0h ;AN000; Is it a valid BPB? +; $IF E,AND ;AN000; + JNE $IOCTL$IF2 + cmp cs:Ext_Boot_Sig, EXT_BOOT_SIGNATURE ;AN000; =90h +; $IF E ;AN000; Extended Boot Record + JNE $IOCTL$IF2 + push cs ;AN000; + pop ds ;AN000; + mov si, offset Boot_Serial_L ;AN000; + mov di, bx ;AN000; + add di, MI_SERIAL ;AN000; + mov cx, BOOT_SERIAL_SIZE+BOOT_VOLUME_LABEL_SIZE+BOOT_SYSTEM_ID_SIZE + rep movsb ;AN000; +; $ELSE ;AN000; + JMP SHORT $IOCTL$EN2 +$IOCTL$IF2: + mov al, ERROR_UNKNOWN_MEDIA ;AN000; =7 + stc ;AN000; +; $ENDIF ;End Extended Boot Record check. +$IOCTL$EN2: +; $ENDIF ;Read boot sector failed. Hard error. +$IOCTL$IF1: + ret ;AN000; +GetMediaID endp + +;****************************************************************************** +;AN000; Set Media ID +;******************************************************************************* +; * +; Function: Set the volume label, the system id and the serial number of * +; the media that has the extended boot record. * +; For the conventional media, this routine will return "Unknown * +; media.." error to DOS. * +; This routine will also set the corresponding informations in * +; the BDS table. * +; * +; Input : DS:DI -> BDS table for this drive. * +; ES:BX -> Request packet (= A_Media_ID_INFO structure) * +; * +; Output: The extended boot record in the media will be set according to * +; the Request packet. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; * +; Subroutines to be called: * +; BOOT_IO:NEAR * +; * +; Logic: * +; * +; * +; { * +; Get Drive_Number from BDS; * +; RFLAG = "Read operation"; * +; BOOT_IO; * +; IF (no error) THEN * +; IF (extended boot record) THEN * +; { set Volume Label, Volume Serial number and System id * +; of the boot record to those of the Request packet; * +; RFLAG = "Write operation"; * +; Get Drive Number from BDS; * +; BOOT_IO; /*Write it back*/ * +; }; * +; ELSE /*Not an extended BPB */ * +; { set Register AL to "Unknown media.." error code; * +; set Carry bit; * +; Exit; /*Return back to caller */ * +; }; * +; ELSE * +; Exit; /*Already error code is set */ * +; * +; Expected LOC: 45 (New) * +;******************************************************************************* + +SetMediaID proc near + call Changeline_Chk ;AN010; + mov al, DS:[DI].DRIVELET ;AN000; logical drive number + mov dl, al ;AN000; save it for the time being. + mov cs:RFlag, ROMREAD ;AN000; read operation + push dx ;AN000; save drive number + call Boot_IO ;AN000; read boot sector into cs:DiskSector + pop dx ;AN000; restore drive number +; $IF NC ;AN000; + JC $IOCTL$IF6 + mov cl, cs:MediaByte ;AN000; Mediabyte in BPB + and cl, 0F0h ;AN000; + cmp cl, 0F0h ;AN000; Is it a valid BPB? +; $IF E,AND ;AN000; + JNE $IOCTL$IF7 + cmp cs:Ext_Boot_Sig, EXT_BOOT_SIGNATURE ;AN000; =41 (=29h) +; $IF E ;AN000; Extended Boot Record + JNE $IOCTL$IF7 + push ds ;AN011; save BDS pointer + push di ;AN011; + push es ;AN000; + pop ds ;AN000;Now DS-> Request packet + push cs ;AN000; + pop es ;AN000;Now ES -> Boot Record + mov di, offset Boot_Serial_L ;AN000; + mov si, bx ;AN000; + add si, MI_Serial ;AN000; + mov cx, BOOT_SERIAL_SIZE+BOOT_VOLUME_LABEL_SIZE+BOOT_SYSTEM_ID_SIZE + rep movsb ;AN000; + pop di ;AN011;Restore BDS pointer + pop ds ;AN011; + call Mov_Media_IDs ;AN011; Update the BDS media ID info. + mov al, dl ;AN000; set drive number for Boot_IO + mov cs:RFlag, ROMWRITE ;AN000; + call Boot_IO ;AN000; write it back. + mov cs:[TIM_DRV], -1 ;AN011; Make sure chk$media check the driver +; $ELSE ;AN000; + JMP SHORT $IOCTL$EN7 +$IOCTL$IF7: + mov al, ERROR_UNKNOWN_MEDIA ;AN000; =7 + stc ;AN000; +; $ENDIF ;End Extended Boot Record check. +$IOCTL$EN7: +; $ENDIF ;Read boot sector failed. Hard error. +$IOCTL$IF6: + ret ;AN000; +SetMediaID endp + +;****************************************************************************** +;AN000; Boot_IO +;******************************************************************************* +; * +; Function: Read/Write the boot record into Boot sector. * +; * +; Input : * +; AL=logical drive number * +; RFLAG = operation (read/write) * +; * +; Output: For read operation, the boot record of the drive specified in BDS * +; be read into the DISKSECTOR buffer. * +; For write operation, the DISKSECTOR buffer image will be written * +; to the drive specified in BDS. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; AX,CX,DX register destroyed. * +; If carry set, then AL will contain the error code from DISKIO. * +; * +; Subroutines to be called: * +; DISKIO:NEAR * +; * +; Logic: * +; * +; { * +; First_Sector = 0; /*logical sector 0 is the boot sector */ * +; SectorCount = 1; /*read 1 sector only */ * +; Buffer = DISKSECTOR; /*read it into the disksector buffer */ * +; Call DISKIO (RFLAG, Drive_Number,First_Sector,SectorCount,Buffer); * +; } * +; Expected LOC: 6 (New) * +;******************************************************************************* +Boot_IO proc near ;AN000; + push ds ;AN000; + push es ;AN000; + push di ;AN000; + push bx ;AN000; +;SB34IOCTL003************************************************************** +;SB Call DISKIO to read/write the boot sector. The parameters which +;SB need to be initialised for this subroutine out here are +;SB - transfer address to cs:DiskSector +;SB - low sector needs to be initalised to 0. This is a reg. param +;SB - hi sector in cs:[Start_Sec_H] needs to be initialised to 0. +;SB - number of sectors <-- 1 +;SB 7 LOCS + + mov di, cs + mov ds, di + mov es, di + mov di, offset DiskSector ;es:di -> transfer address + xor dx, dx ;first sector (H) -> 0 + mov [Start_Sec_H], dx ;start sector (H) -> 0 + mov cx, 01 ;one sector + call DISKIO +;SB34IOCTL003************************************************************** + pop bx ;AN000; + pop di ;AN000; + pop es ;AN000; + pop ds ;AN000; + ret ;AN000; +Boot_IO endp ;AN000; + +;******************************************************************************* +;AN010; Changeline_Chk +;******************************************************************************* +;When the user calls Get/Set media ID call before DOS establishes the media * +;by calling "Media$Chk", the change line activity of the drive is going to be * +;lost. This routine will check the change line activity and will save the * +;history in the flags. * +; * +; Function: Check the change line error activity * +; * +; Input : DS:DI -> BDS table. * +; * +; Output: FLAG in BDS table will be updated if change line occurs. * +; * +; Subroutines to be called: * +; SET_CHANGED_DL * +; * +;******************************************************************************* +Changeline_Chk proc near ;AN010; + mov dl, byte ptr ds:[di].DRIVENUM ;AN010; + or dl, dl ;AN010;Fixed disk? + js Chln_Chk_Ret ;AN010;Yes, skip it. + cmp cs:[fHave96], 1 ;AN011;This ROM support change line? + jne Chln_Chk_Ret ;AN011; + call HasChange ;AN011;This drive support change line? + jz Chln_Chk_Ret ;AN011;do nothing +;SB34IOCTL004***************************************************************** +;SB Execute the ROM disk interrupt to check changeline activity. 2 LOCS + + mov ah, 16h + int 13h +;SB34IOCTL004***************************************************************** + jnc Chln_Chk_Ret ;AN010;no change line activity? + mov word ptr cs:[FLAGBITS], FCHANGED ;AN010; + call SET_CHANGED_DL ;AN010;Update FLAG in BDS for this physical drive +Chln_Chk_Ret: ;AN010; + ret ;AN010; +Changeline_Chk endp ;AN010; + +;****************************************************************************** +;AN007; GetAccessFlag +;******************************************************************************* +; * +; Function: Get the status of UNFORMATTED_MEDIA bit of FLAGS in BDS table * +; * +; Input : * +; es:bx -> A_DISKACCESS_CONTROL structure * +; ds:di -> BDS table * +; * +; Output: A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 if disk I/O not allowed. * +; = 1 if disk I/O allowed. * +;******************************************************************************* +GetAccessFlag proc ;AN007; + test word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA ;AN007;Is it unformtted media? + jz GAF_Allowed ;AN007;No, formatted media + mov es:[bx].DAC_ACCESS_FLAG, 0 ;AN007; + jmp short GAF_Done ;AN007; +GAF_Allowed: ;AN007; + mov es:[bx].DAC_ACCESS_FLAG, 1 ;AN007; +GAF_Done: ;AN007; + ret ;AN007; +GetAccessFlag endp ;AN007; + +;****************************************************************************** +;AN007; SetAccessFlag +;******************************************************************************* +; * +; Function: Set/Reset the UNFORMATTED_MEDIA bit of FLAGS in BDS table * +; * +; Input : * +; es:bx -> A_DISKACCESS_CONTROL structure * +; ds:di -> BDS table * +; * +; Output: UNFORMTTED_MEDIA bit modified according to the user request * +;******************************************************************************* +SetAccessFlag proc ;AN007; + cmp es:[bx].DAC_ACCESS_FLAG, 0 ;AN007; + jne SAF_Allow_Access ;AN007; + or word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA ;AN007; + jmp short SAF_Done ;AN007; +SAF_Allow_Access: ;AN007; + and word ptr ds:[di].FLAGS, not UNFORMATTED_MEDIA ;AN007; +SAF_Done: ;AN007; + ret ;AN007; +SetAccessFlag endp ;AN007; + + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSLOAD.ASM b/v4.0/src/BIOS/MSLOAD.ASM new file mode 100644 index 0000000..859a318 --- /dev/null +++ b/v4.0/src/BIOS/MSLOAD.ASM @@ -0,0 +1,1090 @@ + +page ,132; +title Non-Contiguous IBMBIO Loader (MSLOAD) +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTMs for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; - P1820 New Message SKL file 10/20/87 J.K. +;AN002; - D381 For SYS.COM, put the version number 01/06/88 J.K. +;============================================================================== +;JK, 1987 - +; For DOS 4.00, MSLOAD program has been changed to allow: +; 1. 32 bit calculation, +; 2. Reading a FAT sector when needed, instead of reading the whole FAT +; sectors at once. This will make the Boot time faster, and eliminate +; the memory size limitation problem, +; 3. Solving the limitation of the file size (29 KB) of IBMBIO.COM, +; 4. Adding the boot error message. Show the same boot error message +; and do the same behavior when the read operation of IBMBIO.COM +; failes as the MSBOOT program, since MSLOAD program is the +; extention of MSBOOT program. +; + +IF1 + %OUT ASSEMBLING: Non-Contiguous IBMBIO Loader (MSLOAD) + %OUT + +ENDIF + + +DSKADR = 1Eh * 4 ;ROM bios diskette table vector position + +bootseg segment at 0h + + + org 7C00h +Boot_Sector label byte +bootseg ends + + +dosloadseg segment at 70h + org 00h +IBMBIO_Address label byte + +dosloadseg ends + + +cseg segment public para 'code' + assume cs:cseg,ds:nothing,es:nothing,ss:nothing + +include MSload.inc +include Bootform.inc ;AN000; Extended bpb, boot record defintion. +include versiona.inc ;AN001; Version number for SYS.COM + +sec9 equ 522h ;;** 8/3/87 DCL + +BIOOFF equ 700h +; +org 0h + +start: + jmp Save_Input_Values +SYS_Version dw EXPECTED_VERSION ;AN001; From VERSIONA.INC file +Mystacks dw 64 dup (0) ;AN000; local stack +MyStack_ptr label word + +;local data +Number_Of_Heads dw 0 +Size_Cluster dw 0 +Start_Sector_L dw 0 +Start_Sector_H dw 0 ;J.K. +Temp_H dw 0 ;J.K. For 32 bit calculation +Temp_Cluster dw 0 ;J.K. Temporary place for cluster number +Last_Fat_SecNum dw -1 ;Fat sector number starting from the first fat entry. +Sector_Count dw 0 +Number_Of_FAT_Sectors dw 0 +Hidden_Sectors_L dw 0 +Hidden_Sectors_H dw 0 ;J.K. +Sector_Size dw 0 +Reserved_Sectors dw 0 +Last_Found_Cluster dw 0 +Next_BIO_Location dw 0 +First_Sector_L dw 0 +First_Sector_H dw 0 ;J.K. +Drive_Lim_L dw 0 ;J.K. Max. number of sectors +Drive_Lim_H dw 0 ;J.K. +Sectors_Per_Track dw 0 +Drive_Number db 0 +FAT_Size db 0 +Media_Byte db 0 +EOF db 0 +Org_Rom_Disktable dd 0 +FAT_Segment dw 0 +Sectors_Per_Cluster db 0 + +subttl Save Input Values +page +;*********************************************************************** +; Save_Input_Values +;*********************************************************************** +; +; Input: none +; +; DL = INT 13 drive number we booted from +; CH = media byte +; BX = First data sector (low) on disk (0-based) +; DS:SI = Original ROM BIOS DISKETTE Parameter table. +;J.K. 6/2/87 If an extended Boot Record, then AX will be the First data sector +;J.K. high word. Save AX and set First_Sector_H according to AX if it is an +;J.K. extended boot record. +; AX = First data sector (High) on disk ; +; Output: +; +; BX = first data sector on disk +; +; Media_Byte = input CH +; Drive_Number = input DL +; First_Sector_L = input BX +; First_Sector_H = input AX, if an extended Boot record.;J.K. +; Drive_Lim_L = maximum sector number in this media ;J.K. +; Drive_Lim_H = high word of the above +; Hidden_Sectors_L = hidden secotrs +; Hidden_Sectors_H +; Reserved_Sectors = reserved sectors +; Sectors_Per_Track = Sectors/track +; Number_Of_Heads = heads/cylinder +; +; DS = 0 +; AX,DX,SI destroyed +; +; Calls: none +;----------------------------------------------------------------------- +;Function: +; Save input information and BPB informations from the boot record. +; +;---------------------------------------------------------------------- +Save_Input_Values: + + + mov First_Sector_L,bx ;AC000; + mov media_Byte,ch + mov Drive_Number,dl + mov word ptr Org_Rom_Disktable, si + push ds + pop word ptr Org_Rom_Disktable+2 + xor cx,cx ;Segment 0 + mov ds,cx + assume ds:Bootseg + + push es ;;** DCL 8/3/87 + mov es,cx ;;** DCL 8/3/87 + assume es:Bootseg ;;** DCL 8/3/87 + + MOV SI,WORD PTR DS:DSKADR ; ARR 2.41 + MOV DS,WORD PTR DS:DSKADR+2 ; DS:SI -> CURRENT TABLE ARR 2.41 + + MOV DI,SEC9 ; ES:DI -> NEW TABLE ARR 2.41 + MOV CX,11 ; taken from ibmboot.asm ARR 2.41 + CLD ; + REP MOVSB ; COPY TABLE ARR 2.41 + PUSH ES ; ARR 2.41 + POP DS ; DS = 0 ARR 2.41 + + MOV WORD PTR DS:DSKADR,SEC9 ; ARR 2.41 + MOV WORD PTR DS:DSKADR+2,DS ; POINT DISK PARM VECTOR TO NEW TABLE + pop es ;;** DCL 8/3/87 + assume es:nothing + + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AN000; + mov cs:Sector_Size, cx ;AN000; + mov cl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; + mov cs:Sectors_Per_Cluster, cl ;AN000; + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERTRACK ;Get Sectors per track + mov cs:Sectors_Per_Track,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_HEADS ;Get BPB heads per cylinder + mov cs:Number_Of_Heads,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERFAT ;Get sectors per FAT + mov cs:Number_Of_FAT_Sectors,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_RESERVEDSECTORS ;Get Reserved Sectors + mov cs:Reserved_Sectors,cx + mov cx,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR ;Get hidden sectors + mov cs:Hidden_Sectors_L,cx + mov cx, Boot_Sector.EXT_BOOT_BPB.EBPB_TOTALSECTORS ;AN000; + mov cs:Drive_Lim_L, cx ;AN000; + +;J.K. First of all, check if it the boot record is an extended one. +;J.K. This is just a safe guard in case some user just "copy" the 4.00 IBMBIO.COM +;J.K. to a media with a conventional boot record. + + cmp Boot_Sector.EXT_BOOT_SIG, EXT_BOOT_SIGNATURE ;AN000; + jne Relocate ;AN000; + mov cs:First_Sector_H, AX ;AN000; start data sector (high) + mov ax,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR+2 ;AN000; + mov cs:Hidden_Sectors_H,ax ;AN000; + cmp cx, 0 ;AN000; CX set already before (=Totalsectors) + jne Relocate ;AN000; + mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS ;AN000; + mov cs:Drive_Lim_L, ax ;AN000; + mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS+2 ;AN000; + mov cs:Drive_Lim_H, ax ;AN000; +subttl Relocate +page +; +;*********************************************************************** +; RELOCATE +;*********************************************************************** +; +; Notes: +; +; Relocate the loader code to top-of-memory. +; +; Input: none +; +; Output: Code and data relocated. +; ax,cx,si,di destroyed +; +; Calls: none +;----------------------------------------------------------------------- +; Copy code from Start to Top of memory. +; +; The length to copy is Total_length +; +; Jump to relocated code +;----------------------------------------------------------------------- +; +Relocate: + assume ds:nothing + cld ;AN000; + xor si,si ;AN000; + mov di,si ;AN000; +;SB34LOAD000**************************************************************** +;SB Determine the number of paragraphs (16 byte blocks) of memory. +;SB This involves invoking the memory size determination interrupt, +;SB which returns the number of 1K blocks of memory, and then +;SB converting this to the number of paragraphs. +;SB Leave the number of paragraphs of memory in AX. + + int 12h ;get system memory size in Kbytes + mov cl,6 ; + shl ax,cl ;memory size in paragraphs +;SB34LOAD000**************************************************************** + mov cl,4 ;AN000; + mov dx, cs:Sector_Size ;AN000; + shr dx,cl ;AN000; + inc dx ;AN000; + sub ax, dx ;AN000; + mov cs:Fat_Segment, ax ;AN000;This will be used for FAT sector + mov dx, offset total_length ;AN000; + shr dx, cl ;AN000; + inc dx ;AN000; + sub ax, dx ;AN000; + mov es, ax ;AN000;es:di -> place be relocated. + push cs ;AN000; + pop ds ;AN000;ds:si -> source + mov cx, offset total_length ;AN000; + rep movsb ;AN000; + + push es ;AN000; + mov ax, offset Setup_stack ;AN000; + push ax ;AN000;massage stack for destination of cs:ip +Dumbbb proc far ;AN000; + ret ;AN000; +Dumbbb endp ;AN000; + + +; push cs ;Set up ds segreg +; pop ds +; xor ax,ax ;Set up ES segreg +; mov es,ax +; +; assume es:bootseg,ds:cseg +; +; mov si,offset Start ;Source +; mov di,offset Relocate_Start ;Target +; mov cx,Relocate_Length ;Length +; rep movsb ;Go do it +; jmp far ptr Relocate_Start + + + +subttl Setup Stack +page +;*********************************************************************** +; Setup_Stack +;*********************************************************************** +; +; Input: none +; +; Output: +; +; SS:SP set +; AX destroyed +;----------------------------------------------------------------------- +; First thing is to reset the stack to a better and more known place. +; +; Move the stack to just under the boot record and relocation area (0:7C00h) +; +; Preserve all other registers +;---------------------------------------------------------------------- + +Setup_Stack: + assume ds:nothing, es:nothing, ss:nothing +; CLI ;Stop interrupts till stack ok + mov ax,cs + MOV SS,AX ;Set up the stack to the known area. + mov sp, offset MyStack_Ptr +; MOV SP,7C00h - 50 ;Leave room for stack frame +; MOV BP,7C00h - 50 ;Point BP as stack index pointer +; STI + +subttl Find_Cluster_Size +page +;*********************************************************************** +; Find_Cluster_Size +;*********************************************************************** +; +; Input: BPB information in loaded boot record at 0:7C00h +; +; Output: +; +; DS = 0 +; AX = Bytes/Cluster +; BX = Sectors/Cluster +; SI destroyed +; Calls: none +;----------------------------------------------------------------------- +; +; Get Bytes/sector from BPB +; +; Get sectors/cluster from BPB +; +; Bytes/cluster = Bytes/sector * sector/cluster +;---------------------------------------------------------------------- +Find_Cluster_Size: + +;For the time being just assume the boot record is valid and the BPB +;is there. + + xor ax,ax ;Segment 0 + mov ds,ax + + assume ds:bootseg + + mov ax,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AC000;Get BPB bytes/sector + xor bx,bx + mov bl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AC000;Get sectors/cluster + mul bx ;Bytes/cluster + mov cs:Size_Cluster,ax ;Save it + + +subttl Determine FAT size +page +;*********************************************************************** +; Determine_FAT_Size +;*********************************************************************** +; +; Notes: +; +; Determine if FAT is 12 or 16 bit FAT. 12 bit FAT if floppy, read MBR +; to find out what system id byte is. +; +; Input: +; +; Output: +; +; cs:Fat_Size = FAT12_bit or FAT16_bit +; All other registers destroyed +; +;---------------------------------------------------------------------- +Determine_FAT_Size: + mov cs:FAT_Size,FAT12_bit ;AN000;Assume 12 bit fat + mov dx, cs:Drive_Lim_H ;AN000; + mov ax, cs:Drive_Lim_L ;AN000; + sub ax, cs:Reserved_Sectors ;AN000; + sbb dx, 0 ;AN000;now, dx;ax = available total sectors + mov bx, cs:Number_Of_FAT_Sectors ;AN000; + shl bx, 1 ;AN000;2 FATs + sub ax, bx ;AN000; + sbb dx, 0 ;AN000;now, dx;ax = tatal sectors - fat sectors + mov bx, Boot_Sector.EXT_BOOT_BPB.EBPB_ROOTENTRIES ;AN000; + mov cl, 4 ;AN000; + shr bx, cl ;AN000;Sectors for dir entries = dir entries / Num_DIR_Sector + sub ax, bx ;AN000; + sbb dx, 0 ;AN000; + xor cx, cx ;AN000; + mov cl, Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + div cx ;AN000; + mov cs:Temp_H, ax ;AN000; + pop ax ;AN000; +;J.K. We assume that cx > dx. + div cx ;AN000; + cmp ax, 4096-10 ;AN000; +; jb Determine_First_Cluster ;AN000; + jb Read_In_FirstClusters + mov cs:FAT_Size, FAT16_Bit ;AN000;16 bit fat + +; cmp cs:Media_Byte,0F8h ;Is it floppy +; jne FAT_Size_Found ;Yep, all set +; mov cs:Logical_Sector,0 ;Got hardfile, go get MBR +; xor ax,ax +; mov es,ax +; mov di,offset Relocate_Start +; mov cs:Sector_Count,1 +; call Disk_Read +; mov si,offset Relocate_Start+1C2h +; mov cx,4 +; xor ax,ax +; mov ds,ax +;Find_Sys_Id: +; mov cs:FAT_Size,FAT12_bit ;Assume 12 bit fat +; cmp byte ptr [si],1 +; je FAT_Size_Found +; mov cs:FAT_Size,FAT16_bit ;Assume 12 bit fat +; cmp byte ptr [si],4 +; je Fat_Size_Found +; add si,16 +; loop Find_Sys_Id +; ;xxxxxxxxxxxxxxxxxxxxxxxxxx error +;FAT_Size_Found: + + +subttl Read_In_FirstClusters +page +;*********************************************************************** +; Read_In_FirstClusters +;*********************************************************************** +; +; Notes: Read the start of the clusters that covers at least IBMLOADSIZE +; fully. For example, if sector/cluster = 2, and IBMLOADSIZE=3 +; then we are going to re-read the second cluster to fully cover +; MSLOAD program in the cluster boundary. +; +; Input: +; IBMLOADSIZE - Make sure this value is the same as the one in +; MSBOOT program when you build the new version!!!!! +; +; Sectors_Per_Cluster +; Size_Cluster +; First_Sector_L +; First_Sector_H +; +; Output: MSLOAD program is fully covered in a cluster boundary. +; AX = # of clusters we read in so far. +; +; Calls: Disk_Read +; Logic: +; AX; DX = IBMLOADSIZE / # of sector in a cluster. +; if DX = 0 then Ok. (MSLOAD is in a cluster boundary.) +; else (Has to read (AX+1)th cluster to cover MSLOAD) +; read (AX+1)th cluster into the address after the clusters we +; read in so far. +;----------------------------------------------------------------------- + +Read_In_FirstClusters: + mov ax, IBMLOADSIZE ;AN000; + div cs:Sectors_Per_Cluster ;AN000; + cmp ah, 0 ;AN000; + je Set_Next_Cluster_Number ;AN000; + xor ah, ah ;AN000; + push ax ;AN000; + mov cx, cs:First_Sector_L ;AN000; + mov cs:Start_Sector_L, cx ;AN000; + mov cx, cs:First_Sector_H ;AN000; + mov cs:Start_Sector_H, cx ;AN000; + mul cs:Sectors_Per_Cluster ;AN000; Now, AX=# of sectors + add cs:Start_Sector_L, ax ;AN000; + adc cs:Start_Sector_H, 0 ;AN000; + pop ax ;AN000; + push ax ;AN000; + mov di, BIOOFF ;AN000; + mul cs:Size_Cluster ;AN000;AX = # of bytes read in before this cluster + add di, ax ;AN000; + xor ax, ax ;AN000; + mov es, ax ;AN000; + mov al, cs:Sectors_Per_Cluster ;AN000; + mov cs:Sector_Count, ax ;AN000; + call Disk_Read ;AN000; + pop ax ;AN000; + inc ax ;AN000;# of clusters read in so far. + +subttl Set_Next_Cluster_Number +page +;*********************************************************************** +; Set_Next_Cluster_Number +;*********************************************************************** +; +; Notes: Set LAST_Found_Cluster for the next use. +; Last_Found_Cluster is the cluster number we are in now. +; Since cluster number is 0 based and there are 2 clusters int +; the beginning of FAT table used by the system, we just add +; 1 to set Last_Found_Cluster. +; +; Input: +; AX = # of clusters read in so far. +; +; Output: +; +; cs:Last_Found_Cluster +; +; Calls: none +;------------------------------------------------------------------ +Set_Next_Cluster_Number: + inc ax ;AN000; For Last_Found_Cluster + mov cs:Last_Found_Cluster,ax ;2 is the first data cluster number(0 based) + +subttl Read In FAT +page +;*********************************************************************** +; Read_In_FAT +;*********************************************************************** +; +; Notes: +; +; Reads in the entire FAT at 800:0. This gives the relocated portion +; of this loader a maximum size of 768 bytes (8000 - 7D00). +; With 64 KB memory system, this can support maximum size of FAT to +; be 32 KB. We assumes that the system memory size be 128 KB, if +; the system has a big media with the total fat size bigger than +; 32 KB. +; +; Input: none +; +; Output: +; +; ES = 0 +; All sectors destroyed +; +; Calls: READ DISK +;----------------------------------------------------------------------- +; Get number of sectors in FAT +; +; Set ES:DI to 800:0 +; +; Read in the sectors +; +;---------------------------------------------------------------------- +;Read_In_FAT: +; mov ax,cs:Number_Of_FAT_Sectors ;Get sectors/FAT +; mov cs:Sector_Count,ax ;Number of sectors to read +; mov ax,cs:Hidden_Sectors_L ;Hidden+Reserved = start of FAT sector +; mov dx,cs:Hidden_Sectors_H ;AN000; +; add ax,cs:Reserved_Sectors +; adc dx, 0 +; mov cs:Start_Sector_L,ax ;AC000;Save it, setup for disk read +; mov cs:Start_Sector_H,dx ;AN000; +; mov di, 800h ;AC000; +; mov es, di ;AC000; +; xor di, di ;AC000; +; assume es:nothing +; call Disk_Read +; +subttl Keep Loaded BIO +page +;*********************************************************************** +; KEEP LOADED BIO +;*********************************************************************** +; +; Notes: +; +; Determine how much of IBMBIO was loaded in when the loader was loaded +; by the boot record (only the portion that is guaranteed to be contiguous) +; +; Input: +; +; cs:Last_Found_Cluster = number of clusters used for loader+2 +; +; Output: +; ES=70h +; DI = Next offset to load IBMBIO code +; AX,BX,CX,DX,SI destroyed +; +; cs:Next_BIO_Location = DI on output +; cs:Last_Cluster = last cluster loaded +; +; Calls: none +;----------------------------------------------------------------------- +;Number of clusters loaded+2 is in cs:Last_Found_Cluster +; +;Multiply cluster * cluster size in bytes to get total loaded for MSLOAD +; +;Subtract TOTAL_LOADED - LOADBIO_SIZE to get loaded IBMBIO in last cluster +; +;Relocate this piece of IBMBIO down to 70:0 +; +;---------------------------------------------------------------------- +Keep_Loaded_BIO: + push ds + mov ax,cs:Last_Found_Cluster ;Point to last cluster loaded + sub ax,1 ;Get number of clusters loaded + mul cs:Size_Cluster ;Get total bytes loaded by + ;This is always < 64k, so + ;lower 16 bits ok + sub ax,LoadBio_Size ;Get portion of IBMBIO loaded + mov cx,ax ;Save length to move + mov ax,70h ;Segment at 70h + mov ds,ax + mov es,ax + mov si,offset Total_Length ;Point at IBMBIO + mov di,0 ;Point at 70:0 + rep movsb ;Relocate this code + mov cs:Next_Bio_Location,di ;Save where to load next + pop ds + +subttl Get Contiguous Clusters +page +;*********************************************************************** +; Get_Contiguous_Clusters +;*********************************************************************** +; +; Notes: Go find clusters as long as they are contiguous +; +; +; Input: +; +; cs:Next_BIO_Location +; cs: +; +; +; Output: +; +; +; Calls: Get_Next_FAT_Entry +;----------------------------------------------------------------------- +; +;Set cs:Sector_Count to Sectors per cluster +; +;Call Get_Next_FAT_Entry to get next cluster in file +; +;Call Check_for_EOF +; +;IF (NC returned) +; +; {Call Get_Next_FAT_Entry +; +; IF (New cluster is contig to old cluster) +; {Add sectors per cluster to cs:Sector_Count +; +; Call Check_For_EOF +; +; IF (NC returned) +; +; +;---------------------------------------------------------------------- +Get_Contiguous_Cluster: + xor ah,ah + mov al,cs:Sectors_Per_Cluster ;Assume we will get one cluster + mov cs:Sector_Count,ax + push cs:Sector_Count + call Get_Next_Fat_Entry ;Go get it in AX + pop cs:Sector_Count + mov cs:Last_Found_Cluster,ax ;Update the last one found + cmp cs:EOF,END_OF_FILE + je GO_IBMBIO + +; je GOTO_IBMBIO +;Got_Contig_Clusters: + + xor dx,dx ;AN000; + sub ax,2 ;Zero base the cluster + xor ch,ch + mov cl,cs:Sectors_Per_Cluster ;Get sectors per cluster + mul cx ;Get how many + add ax,cs:First_Sector_L ;AC000;See where the data sector starts + adc dx,cs:First_Sector_H ;AN000; + mov cs:Start_Sector_L,ax ;AC000;Save it + mov cs:Start_Sector_H,dx ;AN000; + mov di,cs:Next_Bio_Location ;Get where to put code + push cs:Sector_Count ;Save how many sectors + mov ax,dosloadseg ;Get area to load code + mov es,ax + call Disk_Read + pop ax ;Get back total sectors read in +; jc ########## + mul cs:Sector_Size ;AC000;Get number of bytes we loaded +; mul Boot_Sector.ByteSec + add cs:Next_Bio_Location,ax ;Point to where to load next + jmp Get_Contiguous_Cluster + +subttl GOTO IBMBIO +page +;*********************************************************************** +; GOTO_IBMBIO +;*********************************************************************** +; +; Notes: +; +; Set up required registers for IBMBIO, then jump to it (70:0) +; +; Input: none +; +; cs:Media_Byte = media byte +; cs:Drive_Number = INT 13 drive number we booted from +; cs:First_Sector_L = First data sector on disk (Low) (0-based) +; cs:First_Sector_H = First data sector on disk (High) +; +; Output: +; +; Required by MSINIT +; DL = INT 13 drive number we booted from +; CH = media byte +; BX = First data sector on disk (0-based) +; AX = First data sector on disk (High) +; DI = Sectors/FAT for the boot media. +; +; Calls: none +;----------------------------------------------------------------------- +; +; Set up registers for MSINIT then do Far Jmp +; +;---------------------------------------------------------------------- +GO_IBMBIO: + mov ch,cs:Media_Byte ;Restore regs required for MSINT + mov dl,cs:Drive_Number ;Physical Drive number we booted from. + mov bx,cs:First_Sector_L ;AC000; + mov ax,cs:First_Sector_H ;AN000; AX will be the First data sector (High) +;J.K. Don't need this information any more. +; mov di,cs:Number_Of_FAT_Sectors ;AN000 + jmp far ptr IBMBIO_Address + + +subttl Disk Read +page +;*********************************************************************** +; Disk_Read +;*********************************************************************** +; +; Notes: +; +; Read in the cs:Sector_Count number of sectors at ES:DI +; +; +; Input: none +; +; DI = Offset of start of read +; ES = Segment of read +; cs:Sector_Count = number of sectors to read +; cs:Start_sector_L = starting sector (Low) +; cs:Start_sector_H = starting sector (High) +; Following is BPB info that must be setup prior to call +; cs:Number_Of_Heads +; cs:Number_Of_Sectors +; cs:Drive_Number +; cs:Sectors_Per_Track +; +; Output: +; +; AX,BX,CX,DX,SI,DI destroyed +;----------------------------------------------------------------------- +; Divide start sector by sectors per track +; The remainder is the actual sector number, 0 based +; +; Increment actual sector number to get 1 based +; +; The quotient is the number of tracks - divide by heads to get the cyl +; +; The remainder is actual head, the quotient is cylinder +; +; Figure the number of sectors in that track, set AL to this +; +; Do the read +; +; If Error, Do RESET, then redo the INT 13h +; +; If successful read, Subtract # sectors read from Sector_Count, Add to Logical +; Sector, add #sectors read * Sector_Size to BX; +; +; If Sector_Count <> 0 Do next read +;---------------------------------------------------------------------- +Disk_Read: + +; +; convert a logical sector into Track/sector/head. AX has the logical +; sector number +; +DODIV: + MOV cx,5 ;5 retries + +Try_Read: + PUSH cx ;Save it + MOV AX,cs:Start_Sector_L ;AC000; Get starting sector + mov dx, cs:Start_Sector_H ;AN000; +; XOR DX,DX + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + DIV word ptr cs:Sectors_Per_Track + mov cs:Temp_H, ax ;AN000; + pop ax ;AN000; + div word ptr cs:Sectors_Per_Track ;AN000;[temp_h];AX = track, DX = sector number + MOV bx,cs:Sectors_Per_Track ;Get number of sectors we can read in + sub bx,dx ;this track + mov si,bx + cmp cs:Sector_Count,si ;Is possible sectors in track more + jae Got_Length ;than what we need to read? + mov si,cs:Sector_Count ;Yes, only read what we need to +Got_Length: + INC DL ; sector numbers are 1-based + MOV bl,dl ;Start sector in DL + mov dx, cs:Temp_H ;AN000;now, dx;ax = track +; XOR DX, DX + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + DIV word ptr cs:Number_Of_Heads ;Start cyl in ax,head in DL + mov cs:Temp_h, ax ;AN000; + pop ax ;AN000; + div word ptr cs:Number_of_Heads ;AN000;now [temp_h];AX = cyliner, dx = head +;J.K. At this moment, we assume that Temp_h = 0, AX <= 1024, DX <= 255 + MOV DH,DL +; +; Issue one read request. ES:BX have the transfer address, AL is the number +; of sectors. +; + MOV CL,6 + SHL AH,CL ;Shift cyl high bits up + OR AH,BL ;Mix in with sector bits + MOV CH,AL ;Setup Cyl low + MOV CL,AH ;Setup Cyl/high - Sector + mov bx,di ;Get back offset + MOV DL,cs:Drive_Number ;Get drive + mov ax,si ;Get number of sectors to read (AL) + + MOV AH,2 ;Read + push ax ;Save length of read + push di +; Issue one read request. ES:BX have the transfer address, AL is the number +; of sectors. + INT 13H + pop di + pop ax + pop cx ;Get retry count back + jnc Read_OK + mov bx,di ;Get offset + xor ah,ah + push cx + mov dl,cs:Drive_Number + push di + int 13h + pop di + pop cx +; loop Try_Read ;AC000; + ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error + dec cx ;AN000; + jz Read_Error ;AN000; + jmp Try_Read ;AN000; +Read_Error: ;AN000; + jmp ErrorOut ;AN000; + +Read_OK: + xor ah,ah ;Mask out read command, just get # read + sub cs:Sector_Count,ax ;Bump number down + jz Read_Finished + add cs:Start_Sector_L,ax ;AC000;Where to start next time + adc cs:Start_Sector_H, 0 ;AN000; + xor bx,bx ;Get number sectors read + mov bl,al + mov ax,cs:Sector_Size ;Bytes per sector + mul bx ;Get total bytes read + add di,ax ;Add it to offset + jmp DODIV +Read_Finished: + RET + +subttl GET NEXT FAT ENTRY +page +;*********************************************************************** +; GET_NEXT_FAT_ENTRY +;*********************************************************************** +; +; Notes: +; +; Given the last cluster found, this will return the next cluster of +; IBMBIO. If the last cluster is (F)FF8 - (F)FFF, then the final cluster +; of IBMBIO has been loaded, and control is passed to GOTO_IBMBIO +; MSLOAD can handle maximum FAT area size of 64 KB. +; +; Input: +; +; cs:Last_Found_Cluster +; cs:Fat_Size +; +; Output: +; +; cs:Last_Found_Cluster (updated) +; +; Calls: Get_Fat_Sector +;----------------------------------------------------------------------- +; Get Last_Found_Cluster +; +; IF (16 bit FAT) +; {IF (Last_Found_Cluster = FFF8 - FFFF) +; {JMP GOTO_IBMBIO} +; ELSE +; {Get offset by multiply cluster by 2} +; +; ELSE +; {IF (Last_Found_Cluster = FF8 - FFF) +; {JMP GOTO_IBMBIO} +; ELSE +; {Get offset by - multiply cluster by 3 +; +; Rotate right to divide by 2 +; +; IF (CY set - means odd number) +; {SHR 4 times to keep high twelve bits} +; +; ELSE +; {AND with 0FFFh to keep low 12 bits} +; } +; } +; +; +;---------------------------------------------------------------------- +Get_Next_FAT_Entry: + + push es ;AN000; + mov ax, cs:FAT_Segment ;AN000; + mov es, ax ;AN000; es-> Fat area segment + assume es:nothing + + mov cs:EOF,End_Of_File ;Assume last cluster + mov ax,cs:Last_Found_Cluster ;Get last cluster + cmp cs:Fat_Size,FAT12_bit + jne Got_16_Bit + mov si, ax ;AN000; + shr ax, 1 ;AN000; + add si, ax ;AN000; si = ax*1.5 = ax+ax/2 + call Get_Fat_Sector ;AN000; + jne Ok_cluster ;AN000; + mov al, byte ptr es:[bx] ;AN000; + mov byte ptr cs:Temp_cluster, al ;AN000; + inc si ;AN000; + call Get_Fat_Sector ;AN000;read next FAT sector + mov al, byte ptr es:[0] ;AN000; + mov byte ptr cs:Temp_cluster+1, al ;AN000; + mov ax, cs:Temp_cluster ;AN000; + jmp short Even_Odd ;AN000; +Ok_cluster: ;AN000; + mov ax, es:[bx] ;AN000; +Even_Odd: ;AN000; + +; xor bx,bx +; mov bl,3 ;Mult by 3 +; mul bx +; shr ax,1 ;Div by 2 to get 1.5 +; mov si,ax ;Get the final buffer offset +; mov ax,[si]+8000h ;Get new cluster + + test cs:Last_Found_Cluster,1 ;Was last cluster odd? + jnz Odd_Result ;If Carry set it was odd + and ax,0FFFh ;Keep low 12 bits + jmp short Test_EOF ; + +Odd_Result: + mov cl,4 ;AN000;Keep high 12 bits for odd + shr ax,cl +Test_EOF: + cmp ax,0FF8h ;Is it last cluster? + jae Got_Cluster_Done ;Yep, all done here + jmp short Not_Last_CLuster + +Got_16_Bit: + shl ax,1 ;Multiply cluster by 2 + mov si,ax ;Get the final buffer offset + call Get_Fat_Sector ;AN000; + mov ax, es:[bx] ;AN000; +; mov ax,[si]+8000h ;Get new cluster + cmp ax,0FFF8h + jae Got_Cluster_Done + +Not_Last_Cluster: + mov cs:EOF,not END_OF_FILE ;Assume last cluster + +Got_Cluster_Done: + pop es + ret + + +Get_Fat_Sector proc near +;Function: Find and read the corresponding FAT sector into ES:0 +;In). SI = offset value (starting from FAT entry 0) of FAT entry to find. +; ES = FAT sector segment +; cs:Sector_Size +;Out). Corresponding FAT sector read in. +; BX = offset value of the corresponding FAT entry in the FAT sector. +; CX destroyed. +; Zero flag set if the FAT entry is splitted, i.e. when 12 bit FAT entry +; starts at the last byte of the FAT sector. In this case, the caller +; should save this byte, and read the next FAT sector to get the rest +; of the FAT entry value. (This will only happen with the 12 bit fat). + + push ax ;AN000; + push si ;AN000; + push di ;AN000; + push dx ;AN000; + xor dx, dx ;AN000; + mov ax, si ;AN000; + mov cx, cs:Sector_Size ;AN000; + div cx ;AN000;ax = sector number, dx = offset + cmp ax, cs:Last_Fat_SecNum ;AN000;the same fat sector? + je GFS_Split_Chk ;AN000;don't need to read it again. + mov cs:Last_Fat_SecNum, ax ;AN000; + push dx ;AN000; + xor dx, dx ;AN000; + add ax, cs:Hidden_Sectors_L ;AN000; + adc dx, cs:Hidden_Sectors_H ;AN000; + add ax, cs:Reserved_Sectors ;AN000; + adc dx, 0 ;AN000; + mov cs:Start_Sector_L, ax ;AN000; + mov cs:Start_Sector_H, dx ;AN000;set up for Disk_Read + mov cs:Sector_Count, 1 ;AN000;1 sector + xor di, di ;AN000; + call Disk_Read ;AN000; + pop dx ;AN000; + mov cx, cs:Sector_Size ;AN000; +GFS_Split_Chk: ;AN000; + dec cx ;AN000;now, cx= sector size - 1 + cmp dx, cx ;AN000;if the last byte of the sector, then splitted entry. + mov bx, dx ;AN000;Set BX to DX + pop dx ;AN000; + pop di ;AN000; + pop si ;AN000; + pop ax ;AN000; + ret ;AN000; +Get_Fat_Sector endp ;AN000; + + +Errorout: ;AN000; + push cs ;AN000; + pop ds ;AN000; + mov si, offset Sysmsg ;AN000; + call write ;AN000; +;SB34LOAD001**************************************************************** +;SB Wait for a keypress on the keyboard. Use the BIOS keyboard interrupt. +;SB 2 LOCS + + xor ah,ah + int 16h ;read keyboard +;SB34LOAD001**************************************************************** + +;SB34LOAD002**************************************************************** +;SB We have to restore the address of the original rom Disk parameter table +;SB to the location at [0:DSKADR]. The address of this original table has been +;SB saved previously in 0:Org_Rom_DiskTable and 0:Org_Rom_Disktable+2. +;SB After this table address has been restored we can reboot by +;SB invoking the bootstrap loader BIOS interrupt. + + xor bx, bx + mov ds, bx + les bx, dword ptr ds:Org_Rom_DiskTable + mov si, DSKADR + mov word ptr ds:[si], bx ;restore offset + mov word ptr ds:[si+2], es ;restore segment + int 19h ;reboot +;SB34LOAD002**************************************************************** + +Write proc near ;show error messages +;In) DS:SI -> ASCIIZ string. + + lodsb ;AN000; + or al, al ;AN000; + jz Endwr ;AN000; +;SB34LOAD003**************************************************************** +;SB Write the character in al to the screen. +;SB Use Video service 'Write teletype to active page' (ROM_TELETYPE) +;SB Use normal character attribute + mov ah, ROM_TELETYPE + mov bl, 7 ;"normal" attribute ? + int 10h ;video write +;SB34LOAD003**************************************************************** + jmp Write ;AN000; +Endwr: ;AN000; + ret ;AN000; +Write endp +; + +;include MSbtmes.inc ;AN000; +include MSbio.cl1 ;AN001; + +Relocate_Length equ $ - start +Total_Length label byte +LoadBIO_Size equ $ - Start + +cseg ends + end start diff --git a/v4.0/src/BIOS/MSLOAD.INC b/v4.0/src/BIOS/MSLOAD.INC new file mode 100644 index 0000000..1f8d73c --- /dev/null +++ b/v4.0/src/BIOS/MSLOAD.INC @@ -0,0 +1,7 @@ +;MSLOAD.INC +End_Of_File equ 0FFh +FAT12_Bit equ 01h +FAT16_Bit equ 04h +ROM_TELETYPE equ 14 ;INT 10h, Teletype function + +NUM_DIR_PER_SECTOR equ 16 ; number of directory entries per sector diff --git a/v4.0/src/BIOS/MSLPT.ASM b/v4.0/src/BIOS/MSLPT.ASM new file mode 100644 index 0000000..ad858a0 --- /dev/null +++ b/v4.0/src/BIOS/MSLPT.ASM @@ -0,0 +1,270 @@ + PAGE ,132 ; + TITLE MSLPT - BIOS + %OUT ...MSLPT.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 - P156 KBMLPT device driver's retry logic. 8/18/87 J.K. +;============================================================================== + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + INCLUDE DEVSYM.INC + INCLUDE IOCTL.INC + + EXTRN BUS$EXIT:NEAR ;MSBIO1 + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN CMDERR:NEAR ;MSBIO1 + EXTRN GETDX:NEAR ;MSBIO1 + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN ERR$EXIT:NEAR ;MSBIO1 +;DATA + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN TIMDEV:WORD ;MSCLOCK + EXTRN LPT2DEV:WORD ;MSBIO2 + EXTRN WAIT_COUNT:WORD ;MSDATA + EXTRN PRINTDEV:BYTE ;MSDATA +; IBM ROM STATUS BITS (I DON'T TRUST THEM, NEITHER SHOULD YOU) + +NOTBUSYSTATUS = 10000000B ; NOT BUSY +ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?) +NOPAPERSTATUS = 00100000B ; NO MORE PAPER +SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED +IOERRSTATUS = 00001000B ; SOME KINDA ERROR +RESERVED = 00000110B ; NOPS +TIMEOUTSTATUS = 00000001B ; TIME OUT. + + +; WARNING!!! THE IBM ROM DOES NOT RETURN JUST ONE BIT. IT RETURNS A +; WHOLE SLEW OF BITS, ONLY ONE OF WHICH IS CORRECT. + +;---------------------------------------------------------- +;J.K. AN001; PRN$WRIT will retry only if error code is TIMEOUT. + +; WRITE TO PRINTER DEVICE + +; CX HAS COUNT OF BYTES +; ES:DI POINT TO DESTINATION +; AUXNUM HAS PRINTER NUMBER + + PUBLIC PRN$WRIT +PRN$WRIT PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + jcxz Prn$Done ;No char to output +Prn$Loop: + mov bx, 2 ;Initialize retry count +Prn$Out: +;SB34LPT000**************************************************************** +;SB Print the character at ES:[DI] +;SB Call the function PrnOP to do this +;SB The character to be printed goes in AL and the function code +;SB for 'Output character' goes in AH +;SB Check for error in printing. +;SB If there is no error go to print the next character. +;SB If there is an error indicated see if it is due to TIMEOUT. If the +;SB error is not TIMEOUT then we can do nothing about it. Just go to +;SB print the next character. If it is due to timeout we can execute +;SB the code to retry the print which follows this piece of code +;SB LOCS: 6 + + mov al,es:[di] ; assume AX disposible since enter + xor ah,ah ; via int 21h + call PrnOp ; print to printer + jz Prn$Con ; no error - continue + test ah,TIMEOUTSTATUS + jz Prn$Con ; NOT time out - continue + +;SB34LPT000**************************************************************** + dec bx ;Retry until count is exhausted. + jnz Prn$Out ;Retry it. + jmp short Pmessg ;Return with error. + ; + ; next character + ; +Prn$Con: + inc di ;point to next char and continue + loop Prn$Loop +Prn$Done: + jmp Exit +Pmessg: + jmp Err$Cnt +PRN$WRIT endp + +; JCXZ EXVEC3 ; NO CHARS TO OUTPUT.. +;PRN$LOOP: +; MOV BX,2 ; INITIALIZE RETRY FLAG +;PRN$OUT: +; MOV AL,ES:[DI] ; GET CHAR INTO AL +; INC DI ; POINT TO NEXT CHAR +; XOR AH,AH ; AH=0 => OUTPUT CHAR IN DL +; CALL PRNOP ; TO INDICATE PRINT CHAR IN AL +; JNZ PRRETRY +; LOOP PRN$LOOP +;EXVEC3: +; JMP EXIT +;PRRETRY: +; DEC DI ; UNDO THE INC ABOVE... +; DEC BX +; JNZ PRN$OUT +;PMESSG: +; JMP ERR$CNT ;RETURN WITH THE ERROR +;PRN$WRIT ENDP + +;-------------------------------------------------------- + +; PRINTER STATUS ROUTINE + + PUBLIC PRN$STAT +PRN$STAT PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + CALL PRNSTAT ;DEVICE IN DX + JNZ PMESSG ; OTHER ERRORS WERE FOUND +;J.K. The next three lines are commented out, since it is a dead code. +; MOV AL,9 ; AGAIN, ASSUME OUT OF PAPER... +; TEST AH,NOPAPERSTATUS +; JNZ PMESSG + TEST AH,NOTBUSYSTATUS + jnz Prn$Done ;No error. Exit + JMP BUS$EXIT +PRN$STAT ENDP + +; TAKE THE APPROPRIATE PRINTER AND DO THE OPERATION. TRIAGE THE STATUS +; RETURNED IN AH INTO SOME MEANINGFUL ERROR. + +PRNSTAT PROC NEAR +;SB33037********************************************************************** + mov AH, 2 ; set command for get status ;SB ;3.30* +PRNOP: ;SB ;3.30* + call GETDX ; determine which printer ;SB ;3.30* + int 17h ; call ROM-BIOS printer routine ;SB;3.30* + +;SB33037********************************************************************** + +; EXAMINE THE STATUS BITS TO SEE IF AN ERROR OCCURRED. UNFORTUNATELY, SEVERAL +; OF THE BITS ARE SET SO WE HAVE TO PICK AND CHOOSE. WE MUST BE EXTREMELY +; CAREFUL ABOUT BREAKING BASIC. + + TEST AH,IOERRSTATUS ; I/O ERROR? + JZ CHECKNOTREADY ; NO, TRY NOT READY + +; AT THIS POINT, WE KNOW WE HAVE AN ERROR. THE CONVERSE IS NOT TRUE. + + MOV AL,9 ; FIRST, ASSUME OUT OF PAPER + TEST AH,NOPAPERSTATUS ; OUT OF PAPER SET? + JNZ RET1 ; YES, ERROR IS SET + INC AL ; INDICATE I/O ERROR +RET1: + +; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) + + RET ; RETURN WITH ERROR + +; THE BITS SAID NO ERROR. UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK +; HERE. + +CHECKNOTREADY: + MOV AL,2 ; ASSUME NOT-READY + TEST AH,TIMEOUTSTATUS ; IS TIME-OUT SET? + ; IF NZ THEN ERROR, ELSE OK??? +PRNOP2: + RET +PRNSTAT ENDP + +; OUTPUT UNTIL BUSY. THIS ENTRY POINT IS USED EXCLUSIVELY BY THE PRINT +; SPOOLERS. UNDER NO CURCUMSTANCES SHOULD THE DEVICE DRIVER BLOCK WAITING FOR +; THE DEVICE TO BECOME READY. + +; INPUTS: CX HAS COUNT OF BYTES TO OUTPUT. +; ES:DI POINTS TO SOURCE BUFFER +; OUTPUTS: SET THE NUMBER OF BYTES TRANSFERRED APPROPRIATELY + PUBLIC PRN$TILBUSY +PRN$TILBUSY PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + PUSH DS + PUSH ES + POP DS ; NOW ES AND DS BOTH POINT TO SOURCE BUFFER + ASSUME DS:NOTHING + + MOV SI,DI ; EVERYTHING IS SET FOR LODSB +PRN$TILBLOOP: + PUSH CX + PUSH BX + XOR BX,BX + MOV BL,CS:[PRINTDEV] + SHL BX,1 + MOV CX,CS:WAIT_COUNT[BX] ; WAIT COUNT TIMES TO COME READY + POP BX +PRN$GETSTAT: + CALL PRNSTAT ; GET STATUS + JNZ PRN$BPERR ; ERROR + TEST AH,10000000B ; READY YET? + LOOPZ PRN$GETSTAT ; NO, GO FOR MORE + POP CX ; GET ORIGINAL COUNT + JZ PRN$BERR ; STILL NOT READY => DONE + LODSB + XOR AH,AH + CALL PRNOP + JNZ PRN$BERR ; ERROR + LOOP PRN$TILBLOOP ; GO FOR MORE +PRN$B: + POP DS + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + JMP EXIT +PRN$TILBUSY ENDP + +PRN$BPERR PROC NEAR + ASSUME DS:CODE + POP CX +PRN$BERR: + POP DS + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + JMP ERR$EXIT +PRN$BPERR ENDP +; +; MANIPULATES THE VALUE IN WAIT_COUNT DEPENDING ON THE VALUE PASSED IN THE +; GENERIC IOCTL PACKET. +; IT EITHER SETS OR RETURNS THE CURRENT VALUE FOR THE RETRY COUNT FOR THE +; DEVICE. +; + PUBLIC PRN$GENIOCTL +PRN$GENIOCTL PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + LES DI,[PTRSAV] + CMP ES:[DI].MAJORFUNCTION,IOC_PC + JE PRNFUNC_OK +PRNFUNCERR: + JMP CMDERR + +PRNFUNC_OK: + MOV AL,ES:[DI].MINORFUNCTION + LES DI,ES:[DI].GENERICIOCTL_PACKET + XOR BX,BX + MOV BL,[PRINTDEV] ; GET INDEX INTO RETRY COUNTS + SHL BX,1 + MOV CX,WAIT_COUNT[BX] ; PULL OUT RETRY COUNT FOR DEVICE + CMP AL,GET_RETRY_COUNT + JZ PRNGETCOUNT + CMP AL,SET_RETRY_COUNT + JNZ PRNFUNCERR + MOV CX,ES:[DI].RC_COUNT +PRNGETCOUNT: + MOV WAIT_COUNT[BX],CX ; PLACE "NEW" RETRY COUNT + MOV ES:[DI].RC_COUNT,CX ; RETURN CURRENT RETRY COUNT + JMP EXIT +PRN$GENIOCTL ENDP +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSMACRO.INC b/v4.0/src/BIOS/MSMACRO.INC new file mode 100644 index 0000000..efc034c --- /dev/null +++ b/v4.0/src/BIOS/MSMACRO.INC @@ -0,0 +1,192 @@ +; +; This file contains three macros used in debugging the system. If the +; variable "itest" (in msbio.asm) is nonzero code is included in the +; modules to print debugging messages. The level of debugging is controlled +; by the value of the variable fTestBits in msbio.asm. Specific bits in +; the variable determine which messages to print. The equ's below tell +; which bits control which funcitons. For example the fifth bit +; cooresponds to disk activity (see fTestDisk equ below). +; +; The macros in the file are: +; +; message Prints an ascii string on the screen. +; Example usage: +; +; message fTestDisk, <"Start Disk Write", CR, LF> +; message fTestINIT, <"Begin BDS initialization"> +; +; +; MNUM Print the value in a register or memory location on +; the screen. Value is displayed in hex. +; Usage: +; MNUM bitpattern, valueLocation +; +; valueLocation is typically a regester: +; +; mnum fTestCom, AX +; mnum fTestDisk, DX +; +; ValueLocation can also be a memory location: +; +; mnum fTestINIT, Final_Dos_Location +; +; If no valueLocation is given the macro defaults to +; the BX register. +; +; ZWAIT Stops the program until any key is pressed. +; +; +; The three macros preserve all register values. If "test" is zero +; defined during assembly then the marco produce no code. +; + + IF iTEST ;3.30 + IFNDEF MSGOUT ;3.30 + EXTRN MSGOUT:NEAR,MSGNUM:NEAR ;3.30 + ENDIF ;3.30 + IFNDEF NUMBUF ;3.30 + EXTRN NUMBUF:BYTE,DIGITS:BYTE,FTESTBITS:WORD ;3.30 + ENDIF ;3.30 + IFNDEF DUMPBYTES ;3.30 + EXTRN DUMPBYTES:NEAR,OUTCHAR:NEAR,HEX_TO_ASCII:NEAR ;3.30 + ENDIF ;3.30 + + + +fTestALL equ 1111111111111111b ; watch everything +fTestHARD equ 0000000000000001b ; watch hard disk initialization +fTest96 equ 0000000000000010b ; watch 96 tpi activity +FTEST13 EQU 0000000000000100B ; WATCH INT 13 ACTIVITY ;3.30 +FTESTCOM EQU 0000000000001000B ; WATCH PACKET ACTIVITY ;3.30 +FTESTINIT EQU 0000000000010000B ; WATCH INITIALIZATION MESSAGES ;3.30 +FTESTDISK EQU 0000000000100000B ; WATCH DISK DEVICE DRIVER CALLS ;3.30 +FTESTCON EQU 0000000001000000B ; WATCH SYSTEM WAIT ACTIVITY IN CO;3.30 NSOLE +FtestClock equ 0000000010000000b ; wathc clock device 5/2/86 ;3.30 + + +; +; message macro -- see above for description +; + +MESSAGE MACRO Bits,msg + LOCAL A,B ;3.30 + jmp SHORT b +a: db msg,0 +b: push SI + push AX + mov AX,Bits + mov SI,OFFSET a + call MSGOUT + pop AX + pop SI +endm + + +; +; mnum macro -- see above for description +; + +MNum MACRO Bits,num + push AX +ifb + mov AX,Bits + call MSGNUM +else + push BX + mov BX,num + mov AX,Bits + call MSGNUM + pop BX +endif + pop AX +endm + + +; +; zwait macro -- see above for description +; + +ZWAIT MACRO + Message fTestALL,<"? "> + CALL ZWAITrtn +ENDM + +ZWAITrtn: + pushf ; save the flags + push AX ; preserve AX + xor AH, AH ; set command to get character ;3.30* + int 16h ; call rom keyboard routine ;3.30* + pop AX ; restore AX + popf ; restore the flags + ret + +;Dump_byte dumps the memory contents in hex. ;3.30 +;DUMPOFFLABEL should be a label or a variable defined in DUMPSEG. ;3.30 +DUMP_BYTE MACRO DUMPSEG, DUMPOFFLABEL, BYTELENGTH ;3.30 + push es ;3.30 + PUSH DS ;3.30 + PUSH SI ;3.30 + PUSH CX ;3.30 + ;3.30 + MOV CX, DUMPSEG ;3.30 + MOV DS, CX ;3.30 + MOV SI, OFFSET DUMPOFFLABEL ;3.30 + MOV CX, BYTELENGTH ;3.30 + call dumpbytes ;3.30 + ;3.30 + POP CX ;3.30 + POP SI ;3.30 + POP DS ;3.30 + pop es ;3.30 + ENDM ;3.30 + ;3.30 +;Dump_Byte_Reg dumps the memory contents in hex. - 4/9/86 ;3.30 +;DUMPOFFREG should be a register contains the offset value in DUMPSEG. ;3.30 +DUMP_BYTE_REG MACRO DUMPSEG, DUMPOFFREG, BYTELENGTH ;3.30 + push es ;3.30 + PUSH DS ;3.30 + PUSH SI ;3.30 + PUSH CX ;3.30 + ;3.30 + MOV CX, DUMPSEG ;3.30 + MOV DS, CX ;3.30 + MOV SI, DUMPOFFREG ;3.30 + MOV CX, BYTELENGTH ;3.30 + call dumpbytes ;3.30 + ;3.30 + POP CX ;3.30 + POP SI ;3.30 + POP DS ;3.30 + pop es ;3.30 + ENDM ;3.30 + +else + ; if test is not defined then make macro into null statements +Message macro +ENDM + +MNUM macro +ENDM + +ZWAIT macro +ENDM + +DUMP_BYTE MACRO ;3.30 + ENDM ;3.30 +DUMP_BYTE_REG MACRO ;3.30 + ENDM ;3.30 + ENDIF ;3.30 + ;3.30 +PATHSTART MACRO INDEX,ABBR ;3.30 + IFDEF PATHGEN ;3.30 + PUBLIC ABBR&INDEX&S,ABBR&INDEX&E ;3.30 + ABBR&INDEX&S LABEL BYTE ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + ;3.30 +PATHEND MACRO INDEX,ABBR ;3.30 + IFDEF PATHGEN ;3.30 + ABBR&INDEX&E LABEL BYTE ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + diff --git a/v4.0/src/BIOS/MSSTACK.INC b/v4.0/src/BIOS/MSSTACK.INC new file mode 100644 index 0000000..21a2095 --- /dev/null +++ b/v4.0/src/BIOS/MSSTACK.INC @@ -0,0 +1,306 @@ +; MSStack.inc +; +; Interrupt level 2, 3, 4, 5, 6, 7,(10, 11, 12, 14, 15 - AT level) +; should follow the standard Interrupt Sharing Scheme which has +; a standard header structure. +; Fyi, the following shows the relations between +; the interrupt vector and interrupt level. +; VEC(Hex) 2 8 9 A B C D E 70 72 73 74 76 77 +; LVL(Deci) 9 0 1 2 3 4 5 6 8 10 11 12 14 15 +; MSSTACK module modifies the following interrupt vectors +; to meet the standard Interrupt Sharing standard; +; A, B, C, D, E, 72, 73, 74, 76, 77. +; Also, for interrupt level 7 and 15, the FirstFlag in a standard header +; should be initialized to indicat whether this interrupt handler is +; the first (= 80h) or not. The FirstFlag entry of INT77h's +; program header is initialized in STKINIT.INC module. +; FirstFlag is only meaningful for interrupt level 7 and 15. +; + +; User specifies the number of stack elements - default = 9 +; minimum = 8 +; maximum = 64 +; +; Intercepts Asynchronous Hardware Interrupts only +; +; Picks a stack from pool of stacks and switches to it +; +; Calls the previously saved interrupt vector after pushing flags +; +; On return, returns the stack to the stack pool +; + + +; This is a modification of STACKS: +; 1. To fix a bug which was causing the program to take up too much space. +; 2. To dispense stack space from hi-mem first rather than low-mem first. +; . Clobbers the stack that got too big instead of innocent stack +; . Allows system to work if the only stack that got too big was the most +; deeply nested one +; 3. Disables NMI interrupts while setting the NMI vector. +; 4. Does not intercept any interupts on a PCjr. +; 5. Double checks that a nested interrupt didn't get the same stack. +; 6. Intercepts Ints 70, 72-77 for PC-ATs and other future products + +;The following variables are for MSSTACK.inc + EVEN + dw 0 ; SPARE FIELD BUT LEAVE THESE IN ORDER +StackCount dw 0 +StackAt dw 0 +StackSize dw 0 +Stacks dw 0 + dw 0 + +FirstEntry dw Stacks +LastEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize +NextEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize + +;End of variables defined for MSSTACK. + +;******************************************************************* +;Macro Interrupt handler for the ordinary interrupt vectors and +;the shared interrupt vectors. +;***************************** +Stack_Main MACRO AA + ASSUME DS:NOTHING + ASSUME ES:NOTHING + ASSUME SS:NOTHING +PUBLIC Int&AA +PUBLIC Old&AA +;----------------------------- + ife IntSharingFlag ;if not IntSharingFlag +;----------------------------- + Old&AA DD 0 +Int&AA PROC FAR +;----------------------------- + else ;for shared interrupt. A Header exists. + +PUBLIC FirstFlag&AA +Int&AA PROC FAR + jmp short Entry_Int&AA&_Stk + Old&AA dd 0 ;Forward pointer + dw 424Bh ;compatible signature for Int. Sharing + FirstFlag&AA db 0 ;the firstly hooked. + jmp short Intret_&AA ;Reset routine. We don't care this. + db 7 dup (0) ;Reserved for future. +Entry_Int&AA&_Stk: +;----------------------------- + endif +;----------------------------- + +; +; Keyboard interrupt must have a three byte jump, a NOP and a zero byte +; as its first instruction for compatibility reasons + ifidn <&aa>,<09> + jmp Keyboard_lbl + nop + db 0 +Keyboard_lbl label near + endif + +; This patches INTERRUPT 75h to be "unhooked". We do this Wierdness, +; rather than never hooking INT 75h, to maintain maximum compat. with IBMs +; post production patch. + push ax + + ifidn <&aa>,<02> + +; ********************************************************************* +; +; This is special support for the PC Convertible / NMI handler +; +; On the PC Convertible, there is a situation where an NMI can be +; caused by using the "OUT" instructions to certain ports. When this +; occurs, the PC Convertible hardware *GUARANTEES* that **NOTHING** +; can stop the NMI or interfere with getting to the NMI handler. This +; includes other type of interrupts (hardware and software), and +; also includes other type of NMI's. When any NMI has occured, +; no other interrtupt (hardware, software or NMI) can occur until +; the software takes specific steps to allow further interrupting. +; +; For PC Convertible, the situation where the NMI is generated by the +; "OUT" to a control port requires "fixing-up" and re-attempting. In +; otherwords, it is actually a "restartable exception". In this +; case, the software handler must be able to get to the stack in +; order to figure out what instruction caused the problem, where +; it was "OUT"ing to and what value it was "OUT"ing. Therefore, +; we will not switch stacks in this situation. This situation is +; detected by interrogating port 62h, and checking for a bit value +; of 80h. If set, *****DO NOT SWITCH STACKS*****. +; +; ********************************************************************* + + push es + mov ax,0f000h + mov es,ax + cmp byte ptr es:[0fffeh],mdl_convert ;check if convertible + pop es + jne Normal&aa + + in al,62h + test al,80h + jz Normal&aa + +Special&aa: + pop ax + jmp dword ptr Old&aa + +Normal&aa: + +; ********************************************************************* + + endif + + push bp + push es + mov es, cs:[STACKS+2] ; Get segment of stacks + + mov bp,NextEntry ; get most likely candidate + mov al,Allocated + xchg AllocByte,al ; grab the entry + cmp al,Free ; still avail? + jne NotFree&aa + + sub NextEntry,EntrySize ; set for next interrupt + +Found&aa: + mov SavedSP,sp ; save sp value + mov SavedSS,ss ; save ss also +; mov IntLevel,aa&h ; save the int level + + mov ax,bp ; temp save of table offset + + mov bp,NewSP ; get new SP value + cmp es:[bp],ax ; check for offset into table + jne FoundBad&aa + + mov ax,es ; point ss,sp to the new stack + mov ss,ax + mov sp,bp + + pushf ; go execute the real interrupt handler + call dword ptr old&aa ; which will iret back to here + + mov bp,sp ; retrieve the table offset for us + mov bp,es:[bp] ; but leave it on the stack + mov ss,SavedSS ; get old stack back + mov sp,SavedSP + +; cmp AllocByte,Allocated ; If an error occured, +; jne NewError&aa ; do not free us + + mov AllocByte,Free ; free the entry + mov NextEntry,bp ; setup to use next time + +NewError&aa: + pop es + pop bp ; saved on entry + pop ax ; saved on entry + +INTRET_&AA: ;3.30 + iret ; done with this interrupt + +NotFree&aa: + cmp al,Allocated ; error flag + je findnext&aa ; no, continue + xchg AllocByte,al ; yes, restore error value + +FindNext&aa: + call LongPath + jmp Found&aa + +FoundBad&aa: + cmp bp,FirstEntry + jc findnext&aa + mov bp,ax ; flag this entry + mov AllocByte,Clobbered +; add bp,EntrySize ; and previous entry +; mov AllocByte,Overflowed +; sub bp,EntrySize + jmp findnext&aa ; keep looking + +int&aa endp + + + endm + +;***************************** ;3.30 +;End of Macro definition ;3.30 +;******************************************************************** ;3.30 +; THESE ARE THE INDIVIDUAL INTERRUPT HANDLERS ;3.30 + ;3.30 + IRP A,<02,08,09,70> ;3.30 + IntSharingFlag=0 ;3.30 + Stack_Main &A ;3.30 + ENDM ;3.30 + ;3.30 + IRP A,<0A,0B,0C,0D,0E,72,73,74,76,77> ;3.30 + IntSharingFlag=1 ;3.30 + Stack_Main &A ;3.30 + ENDM ;3.30 + ;3.30 +;******************************************************************** ;3.30 +;Common routines ;3.30 + +longpath: + mov bp,LastEntry ; start with last entry in table + +LPLOOPP: ;3.30 + cmp AllocByte,Free ; is entry free? + jne inuse ; no, try next one + + mov al,Allocated + xchg AllocByte,al ; allocate entry + cmp al,Free ; is it still free? + je found ; yes, go use it + + cmp al,Allocated ; is it other than Allocated or Free? + je inuse ; no, check the next one + + mov AllocByte,al ; yes, put back the error state + +inuse: + cmp bp,FirstEntry + je Fatal + sub bp,EntrySize + JMP LPLOOPP ;3.30 + +found: + ret + + page + +fatal proc near + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? ;3.30 + pop ds ;3.30 + jne Skip_NMIS ;3.30 + ;3.30 + mov al,07h ; disable PC Convertible NMIs + out 72h,al + +Skip_NMIS: ;3.30 + cli ; disable and mask + mov al,0ffh ; all other ints + out 021h,al + out 0a1h,al + + mov si,cs + mov ds,si + mov si,offset fatal_msg + +fatal_loop: + lodsb + cmp al,'$' + je fatal_done + + mov bl,7 ;3.30* + mov ah,14 ;3.30* + int 010h ; whoops, this enables ints ;3.30* + jmp fatal_loop + +fatal_done: + jmp fatal_done +fatal endp diff --git a/v4.0/src/BIOS/MSVOLID.INC b/v4.0/src/BIOS/MSVOLID.INC new file mode 100644 index 0000000..d1a9588 --- /dev/null +++ b/v4.0/src/BIOS/MSVOLID.INC @@ -0,0 +1,297 @@ +;------------------------------------------------------------------------- +; +; File: msvolid.asm +; This file contains the volume_id subroutines and data structures. +; +; Routines in this file are: +; Set_Volume_ID - main routine, calls other routines. +; read_volume_id - read the volume ID and tells if it has +; been changed. +; Transfer_volume_id - copy the volume ID from TMP to special +; drive. +; Check_Volume_ID - compare volume ID in TMP area with one +; expected for drive. +; Fat_Check - see of the fatID has changed in the +; specified drive. +; Init_Vid_loop - set up for VID scan or move +; +; +;------------------------------------------------------------------------- + +; +; length of the volume id +; + +vid_size equ 12 + + PATHSTART 001,VOLID ;3.30 + +; +; null volume id +; + +nul_vid db "NO NAME ",0 + +; +; data scratch area used to hold volume ids +; + +tmp_vid db "NO NAME ",0 + + PATHEND 001,VOLID ;3.30 + +; +; Set_Volume_ID +; If drive has changeline support, read in and set the volume_ID +; and the last FAT_ID byte. If no change line support then do nothing. +; +; On entry: +; DS:DI points to the BDS for this disk. +; AH contains media byte +; +; On Exit: +; Carry clear: +; Successful call +; Carry set +; Error and AX has error code +; + +Set_Volume_ID: + PUBLIC SET_VOLUME_ID ;3.30 + push dx ; save registers + push ax + CALL HasChange ; does drive have changeline support? + jz setvret ; no, get out + push di + call read_volume_ID ; read the volume ID + pop di + jc SetErr ; if error go to error routine + call transfer_volume_ID ; copy the volume id to special drive + call ResetChanged ; restore value of change line + +setvret: ; SET Volume RETurn + clc ; no error, clear carry flag + pop ax ; restore registers + pop dx + ret +SetErr: + pop dx ; pop stack but don't overwrite AX + pop dx ; restore DX + ret + + + +root_sec DW ? ;Root sector # + + + + +; +; read_volume_id read the volume ID and tells if it has been changed. +; +; On entry: +; DS:DI points to current BDS for drive. +; On Exit: +; Carry Clear +; SI = 1 No change +; SI = 0 ? +; SI = -1 Change +; +; Carry Set: +; Error and AX has error code. +; + +read_volume_id: + push ES ; preserve registers + push DX + push CX + push BX + push AX + push DS ; Preserve Current BDS + push DI + push cs ; get ES segment correct + pop es + push cs ; get DS segment correct + pop ds + mov di,offset tmp_vid + mov si,offset nul_vid + mov cx,vid_size + rep movsb ; initialize tmp_vid to null vi_id + + pop DI ; Restore Current BDS + pop DS + mov al,byte ptr ds:[di].cFAT ; # of fats + mov cx,word ptr ds:[di].csecfat ; sectors / fat + mul cl ; size taken by fats + add ax,word ptr ds:[di].ressec ; add on reserved sectors + ; AX is now sector # (0 based) + mov cs:[root_sec],ax ; set initial value + mov ax,[di].cDir ; # root dir entries + mov cl,4 ; 16 entries/sector + shr ax,cl ; divide by 16 + mov cx,ax ; cx is # of sectors to scan +next_sec: + push cx ; save outer loop counter + mov ax,cs:[root_sec] ; get sector # + mov cx,word ptr ds:[di].seclim ; sectors / track + xor DX,DX + div cx + ; set up registers for call to read_sector + inc DX ; dx= sectors into track, ax= track count from 0 + mov cl,dl ; sector to read + xor DX,DX + div word ptr ds:[di].hdlim ; # heads on this disc + mov dh,dl ; Head number + mov ch,al ; Track # + call read_sector ; get first sector of the root directory, + ; ES:BX -> BOOT + jc ReadVIDErr ; error on read + mov cx,16 ; # of dir entries in a block of root + mov al,08h ; volume label bit +fvid_loop: + cmp byte ptr es:[bx],0 ; End of dir? + jz no_vid ; yes, no vol id + cmp byte ptr es:[bx],0E5h ; empty entry? + jz ent_loop ; yes, skip + test es:[bx+11],al ; is volume label bit set in fcb? + jnz found_vid ; jmp yes +ent_loop: + ADD BX,32 ;MJB003 ADD LENGTH OF DIRECTORY ENTRY ;3.30 + loop fvid_loop + pop cx ; outer loop + inc cs:[root_sec] ; next sector + loop next_sec ; continue +NotFound: + XOR SI,SI + jmp short fvid_ret + +found_vid: + pop cx ; clean stack of outer loop counter + mov si,bx ; point to volume_id + push ds ; preserve currnet BDS + push di + push es ; es:si points to volume id. + pop ds ; source segment + push cs + pop es ; destination segment + mov di,offset tmp_vid ; dest of volume_id + mov cx,vid_size -1 ; length of string minus NUL + rep movsb ; mov volume label to tmp_vid + xor al,al + stosb ; Null terminate + XOR SI,SI + pop DI ; restore current BDS + pop DS +fvid_ret: + pop ax + clc +RVIDRet: + pop BX ; restore register + pop CX + pop DX + pop ES + ret +no_vid: + pop cx ; clean stack of outer loop counter + jmp NotFound ; not found +ReadVIDErr: + pop SI + pop SI + jmp RVIDRet + + + +; +; Transfer_volume_id - copy the volume ID from TMP to special drive +; +; Inputs: DS:DI nas current BDS +; Outputs: BDS for drive has volume ID from TMP +; + +transfer_volume_ID: + push DS ; preserve current BDS + push DI + push ES + push SI + push CX + call init_vid_loop + cld + rep MOVSB ; transfer + pop CX + pop SI + pop ES + pop DI ; restore current BDS + pop DS + ret + + +; +; Check_Volume_ID - compare volume ID in TMP area with one expected for +; drive +; +; Inputs: DS:DI has current BDS for drive +; Outputs: SI = 0 if compare succeeds +; SI = -1 if compare fails. + +check_volume_id: + push DS ; preserve current BDS for drive + push DI + push ES + push CX + call init_vid_loop + cld + repz cmpsb ; are the 2 volume_ids the same? + mov si,0 ; assume unknown + jz check_vid_ret ; carry clear if jump taken + mov si,-1 ; failure +check_vid_ret: + pop CX + pop ES + pop DI ; restore current BDS + pop DS + ret + +; +; Fat_Check - see of the fatID has changed in the specified drive. +; - uses the FAT ID obtained from the boot sector. +; +; Inputs: MedByt is expected FAT ID +; DS:DI points to current BDS +; Output: Carry Clear +; SI = -1 if fat ID different, +; SI = 0 otherwise +; No other registers changed. + +FAT_CHECK: + push AX + xor SI, SI ; say FAT ID's are same. + mov AL, cs:MedByt + cmp AL, byte ptr [DI].Mediad ; compare it with the BDS medbyte + jz OKRET1 ; carry clear + dec SI +OkRet1: clc + pop AX + ret + + +; +; Init_Vid_loop - set up for VID scan or move +; +; Inputs: DS:DI pionts to BDS for the drive +; Outputs: DS:SI points to tmp_vid +; ES:DI points to vid for drive +; CX has size for VID compare +; + +init_vid_loop: + push ax + push ds + pop es + push cs + pop ds + mov si,offset tmp_vid ; source + add di,volid + mov cx,vid_size + pop ax + ret + diff --git a/v4.0/src/BIOS/PSOPTION.INC b/v4.0/src/BIOS/PSOPTION.INC new file mode 100644 index 0000000..d7f56d4 --- /dev/null +++ b/v4.0/src/BIOS/PSOPTION.INC @@ -0,0 +1,63 @@ +;******************************************************************* +; Parser Options set for IBMBIO SYSCONF module +;******************************************************************* +; +;**** Default assemble swiches definition ************************** + +IFNDEF FarSW +FarSW equ 0 ; Near call expected +ENDIF + +IFNDEF DateSW +DateSW equ 0 ; Check date format +ENDIF + +IFNDEF TimeSW +TimeSW equ 0 ; Check time format +ENDIF + +IFNDEF FileSW +FileSW equ 1 ; Check file specification +ENDIF + +IFNDEF CAPSW +CAPSW equ 0 ; Perform CAPS if specified +ENDIF + +IFNDEF CmpxSW +CmpxSW equ 0 ; Check complex list +ENDIF + +IFNDEF NumSW +NumSW equ 1 ; Check numeric value +ENDIF + +IFNDEF KeySW +KeySW equ 0 ; Support keywords +ENDIF + +IFNDEF SwSW +SwSW equ 1 ; Support switches +ENDIF + +IFNDEF Val1SW +Val1SW equ 1 ; Support value definition 1 +ENDIF + +IFNDEF Val2SW +Val2SW equ 0 ; Support value definition 2 +ENDIF + +IFNDEF Val3SW +Val3SW equ 1 ; Support value definition 3 +ENDIF + +IFNDEF DrvSW +DrvSW equ 1 ; Support drive only format +ENDIF + +IFNDEF QusSW +QusSW equ 0 ; Support quoted string format +ENDIF + + \ No newline at end of file diff --git a/v4.0/src/BIOS/PUSHPOP.INC b/v4.0/src/BIOS/PUSHPOP.INC new file mode 100644 index 0000000..aaa76eb --- /dev/null +++ b/v4.0/src/BIOS/PUSHPOP.INC @@ -0,0 +1,20 @@ + IF1 ;3.30 + +SaveReg MACRO reglist ;; push those registers +IRP reg, + ?stackdepth = ?stackdepth + 1 + PUSH reg +ENDM +ENDM +.xcref SaveReg + + +RestoreReg MACRO reglist ;; pop those registers +IRP reg, + ?stackdepth = ?stackdepth - 1 + POP reg +ENDM +ENDM +.xcref RestoreReg + + ENDIF ;3.30 diff --git a/v4.0/src/BIOS/READCLOC.INC b/v4.0/src/BIOS/READCLOC.INC new file mode 100644 index 0000000..700f0aa --- /dev/null +++ b/v4.0/src/BIOS/READCLOC.INC @@ -0,0 +1,165 @@ +; SCCSID = @(#)readclock.asm 1.2 85/07/25 +;************************************************************************ +; +; read_real_date reads real-time clock for date and returns the number +; of days elapsed since 1-1-80 in si +; +read_real_date: ;mjb002 + assume ds:code,es:nothing + PUSH AX + PUSH CX + PUSH DX + XOR AH,AH ; throw away clock roll over ;3.30* + INT 1AH ;3.30* + POP DX + POP CX + POP AX + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV CS:DAYCNT2,1 ;MJB002 REAL TIME CLOCK ERROR FLAG (+1 DA;3.30Y) + mov ah,4 ;mjb002 read date function code ;3.30* + int 1ah ;mjb002 read real-time clock ;3.30* + jnc read_ok ;mjb002 jmp success + jmp r_d_ret ;mjb002 jmp error +read_ok: ;mjb002 ******* get bcd values in binary ***** + mov byte ptr bin_date_time+0,ch ;mjb002 store as hex value + mov byte ptr bin_date_time+1,cl ;mjb002 ... + mov byte ptr bin_date_time+2,dh ;mjb002 ... + mov byte ptr bin_date_time+3,dl ;mjb002 ... + MOV CS:DAYCNT2,2 ;MJB002 READ OF R-T CLOCK SUCCESSFUL ;3.30 + call bcd_verify ;mjb002 verify bcd values in range + jc r_d_ret ;mjb002 jmp some value out of range + MOV CS:DAYCNT2,3 ;MJB002 READ OF R-T CLOCK SUCCESSFUL ;3.30 + call date_verify ;mjb002 verify date values in range + jc r_d_ret ;mjb002 jmp some value out of range + MOV CS:DAYCNT2,0 ;MJB002 VERIFY SUCCESSFUL ;3.30;3.30 + call in_bin ;mjb002 convert date to binary + ;mjb002 ******* years since 1-1-80 ********* + mov al,byte ptr bin_date_time+1 ;mjb002 get years into century + cbw ;mjb002 + cmp byte ptr bin_date_time+0,20 ;mjb002 20th century? + jnz century_19 ;mjb002 jmp no + add ax,100 ;mjb002 add in a century +century_19: ;mjb002 + sub ax,80 ;mjb002 subtract off 1-1-80 + mov cl,4 ;mjb002 leap year every 4 + div cl ;mjb002 al= # leap year blocks, ah= remainder + mov bl,ah ;mjb002 save odd years + cbw ;mjb002 zero ah + mov cx,366+3*365 ;mjb002 # of days in leap year blocks + mul cx ;mjb002 dx:ax is result + MOV CS:DAYCNT2,AX ;MJB002 SAVE COUNT OF DAYS ;3.30 + mov al,bl ;mjb002 get odd years count + cbw ;mjb002 + or ax,ax ;mjb002 is ax= 0? + jz leap_year ;mjb002 jmp if none + mov cx,365 ;mjb002 days in year + mul cx ;mjb002 dx:ax is result + ADD CS:DAYCNT2,AX ;MJB002 ADD ON DAYS IN ODD YEARS ;3.30 + jmp short leap_adjustment ;mjb002 account for leap year +leap_year: ;mjb002 possibly account for a leap day + cmp byte ptr bin_date_time+2,2 ;mjb002 is month february + jbe no_leap_adjustment ;mjb002 jan or feb. no leap day yet. +leap_adjustment: ;mjb002 account for leap day + INC CS:DAYCNT2 ;MJB002 ... ;3.30 +no_leap_adjustment: ;mjb002 ******* get days of month ******* + mov cl,byte ptr bin_date_time+3 ;mjb002 ... + xor ch,ch ;mjb002 + dec cx ;mjb002 because of offset from day 1, not day 0 + ADD CS:DAYCNT2,CX ;MJB002 ******* GET DAYS IN MONTHS PRECEE;3.30DING ***** + mov cl,byte ptr bin_date_time+2 ;mjb002 get month + xor ch,ch ;mjb002 + dec cx ;mjb002 january starts at offset 0 + shl cx,1 ;mjb002 word offset + mov si,offset month_table ;mjb002 beginning of month_table + add si,cx ;mjb002 point into month table + mov ax,word ptr [si];mjb002 get # days in previous months + ADD CS:DAYCNT2,AX ;MJB002 ... ;3.30 +r_d_ret: ;mjb002 + MOV SI,CS:DAYCNT2 ;MJB002 RESULT IN SI ;3.30 + POP DX + POP CX + POP BX + POP AX + ret ;mjb002 + +r_t_retj: + xor cx,cx + xor dx,dx + jmp r_t_ret +; +; Read_Real_Time reads the time from the RTC. on exit, it has the number of +; ticks (at 18.2 ticks per sec.) in CX:DX. +; +Read_Real_Time: + mov ah,2 ;3.30* + int 1AH ;3.30* + jc r_t_retj +oktime: + mov byte ptr bin_date_time,ch ; hours + mov byte ptr bin_date_time+1,cl ; minutes + mov byte ptr bin_date_time+2,dh ; seconds + mov byte ptr bin_date_time+3,0 ; unused for time + call bcd_verify + jc r_t_retj + call time_verify + jc r_t_retj + call in_bin + MOV ch,byte ptr bin_date_time + MOV cl,byte ptr bin_date_time+1 + MOV dh,byte PTR bin_date_time+2 + MOV dl,byte PTR bin_date_time+3 + message ftestinit,<"Read Time "> + mnum ftestinit,cx + message ftestinit,<" "> + mnum ftestinit,dx + message ftestinit, +; get time in ticks in CX:DX + CALL word ptr cs:TimeToTicks ;3.30 + message ftestinit,<"Conv Time "> + mnum ftestinit,cx + message ftestinit,<" "> + mnum ftestinit,dx + message ftestinit, +r_t_ret: + ret + +; +; in_bin converts bin_date_time values from bcd to bin +; +in_bin: ;mjb002 + assume ds:code,es:nothing + mov al,byte ptr bin_date_time+0 ; century or hours + call bcd_to_bin ; ... + mov byte ptr bin_date_time+0,al ; + mov al,byte ptr bin_date_time+1 ; years or minutes + call bcd_to_bin ; ... + mov byte ptr bin_date_time+1,al ; + mov al,byte ptr bin_date_time+2 ; months or seconds + call bcd_to_bin ; ... + mov byte ptr bin_date_time+2,al ; + mov al,byte ptr bin_date_time+3 ; days (not used for time) + call bcd_to_bin ; ... + mov byte ptr bin_date_time+3,al ; + ret ; +; +; bcd_to_bin converts two bcd nibbles in al (value <= 99.) to +; a binary representation in al +; ah is destroyed +; +bcd_to_bin: ;mjb002 + assume ds:nothing,es:nothing + mov ah,al ;mjb002 copy bcd number to ah + and ax,0f00fh ;mjb002 clear unwanted nibbles + mov bl,al ;mjb002 save units place + xchg ah,al ;mjb002 10's place to al + xor ah,ah ;mjb002 ah not wanted + mov cl,4 ;mjb002 shift count + shr ax,cl ;mjb004 swap nibbles + mov cl,10 ;mjb002 convert al to ... + mul cl ;mjb002 ... its binary value + add al,bl ;mjb002 add in units + ret ;mjb002 diff --git a/v4.0/src/BIOS/STKINIT.INC b/v4.0/src/BIOS/STKINIT.INC new file mode 100644 index 0000000..8298fb8 --- /dev/null +++ b/v4.0/src/BIOS/STKINIT.INC @@ -0,0 +1,271 @@ +; +; To follow the standard interrupt sharing scheme, MSSTACK.ASM ;3.30 +; has been modified. This initialization routine also has to ;3.30 +; be modified because for the interrupt level 7 and 15, FirstFlag ;3.30 +; should be set to signal that this interrupt handler is the ;3.30 +; first handler hooked to this interrupt vector. ;3.30 +; We determine this by looking at the instruction pointed by ;3.30 +; this vector. If it is IRET, then this handler should be the ;3.30 +; first one. In our case, only the interrupt vector 77h is the ;3.30 +; interrupt level 15. (We don't hook interrupt level 7.) ;3.30 +; 9/10/1986 ;3.30 +; The followings are mainly due to M.R.T; PTM fix of P886 12/3/86;3.30 +; Some design changes are needed to the above interrupt sharing ;3.30 +; method. The above sharing scheme assumes that 1). Interrupt ;3.30 +; sharing is NEVER done on levels that have BIOS support. 2). "Phantom" ;3.30 +; interrupts would only be generated on levels 7 and 15. ;3.30 +; These assumptions are not true any more. We have to use the FirstFlag ;3.30 +; for EVERY level of interrupt. We will set the firstFlag on the following;3.30 +; conditions: ;3.30 +; a. if the CS portion of the vector is 0000, then "first" ;3.30 +; b. else if CS:IP points to valid shared header, then NOT "first" ;3.30 +; c. else if CS:IP points to an IRET, then "first" ;3.30 +; d. else if CS:IP points to DUMMY, then "first" ;3.30 +; where DUMMY is - the CS portion must be F000, and the IP portion must ;3.30 +; be equal to the value at F000:FF01. This location is the initial value ;3.30 +; from VECTOR_TABLE for interrupt 7, one of the preserved addresses in all;3.30 +; the BIOSes for all of the machines. ;3.30 +; ;3.30 +; System design group requests BIOS to handle the phantom interrupts. ;3.30 +; ;3.30 +; The "Phantom" interrupt is an illegal interrupt such as an interrupt ;3.30 +; produced by the bogus adapter card even without interrupt request is ;3.30 +; set. More specifically, 1). The 8259 has a feature when running in ;3.30 +; edge triggered mode to latch a pulse and present the interrupt when ;3.30 +; the processor indicates interrupt acknowledge (INTA). The interrupt ;3.30 +; pulse was exist at the time of INTA to get a "phantom" interrupt. ;3.30 +; 2). or, this is caused by adapter cards placing a glitch on the ;3.30 +; interrupt line. ;3.30 +; ;3.30 +; To handle those "phantom" interrupts, the main stack code will check ;3.30 +; the own FirstFlag, and if it is not "first" (which means the forward ;3.30 +; pointer points to the legal shared interrupt handler), then pass the ;3.30 +; control. If it is the first, then the following action should be ;3.30 +; taken. We don't have to implement skack logic in this case. ;3.30 +; ;3.30 +; To implement this logic, we rather choose a simple method. ;3.30 +; If ont of the above "FirstFlag" conditions is met, we are not ;3.30 +; going to hook this interrupt vector. The reason is if the original ;3.30 +; vector points to "IRET" and do nothing, we don't need ;3.30 +; to implement the stack logic for it. This will simplify implementation;3.30 +; while maintaining compatibility with the old version of DOS. ;3.30 +; This implies that in the main stack code, there might be a stack code ;3.30 +; that will never be used, a dead code. ;3.30 +; ;3.30 +; 12/3/86 ;3.30 + ;3.30 +;In - CS, DS -> sysinitseg, ES -> relocated stack code & data. ;3.30 + ;3.30 + PAGE ;3.30 + assume ds:sysinitseg ; sunilp SB340 +StackInit proc near ;3.30 + ;3.30 + PUSH AX ;SAVE ALL ;3.30 + PUSH DS ;3.30 + PUSH ES ;3.30 + PUSH BX ;3.30 + PUSH CX ;3.30 + PUSH DX ;3.30 + PUSH DI ;3.30 + PUSH SI ;3.30 + PUSH BP ;3.30 + ;3.30 +;Currently ES -> stack code area ;3.30 + MOV AX, cs:[STACK_COUNT] ;defined in CS ;3.30 + MOV es:[STACKCOUNT], AX ;defined in STACK CODE AREA ;3.30 + MOV AX, [STACK_SIZE] ;in CS ;3.30 + MOV es:[STACKSIZE], AX ; ;3.30 + MOV AX, WORD PTR cs:[STACK_ADDR] ; OFFSET ;3.30 + MOV WORD PTR es:[STACKS], AX ;3.30 + MOV AX, WORD PTR cs:[STACK_ADDR+WORD] ; SEGMENT ;3.30 + MOV WORD PTR es:[STACKS+WORD], AX ;3.30 + ;3.30 +; INITIALIZE THE DATA FIELDS WITH THE PARAMETERS ;3.30 + ;3.30 +; "FIRSTENTRY" WILL ALWAYS BE AT STACKS ;3.30 + ;3.30 + MOV BP, word ptr es:STACKS ; GET OFFSET OF STACK ;3.30 + MOV es:FIRSTENTRY,BP ;3.30 + ;3.30 +; THE STACKS WILL ALWAYS IMMEDIATELY FOLLOW THE TABLE ENTRIES ;3.30 + ;3.30 + MOV AX,ENTRYSIZE ;3.30 + MOV CX,es:STACKCOUNT ;3.30 + MUL CX ;3.30 + ADD AX,BP ;3.30 + MOV es:STACKAT,AX ;3.30 + MOV BX,AX ;3.30 + SUB BX,2 ;3.30 + ;3.30 +; ZERO THE ENTIRE STACK AREA TO START WITH ;3.30 + ;3.30 + MOV DI,es:STACKAT ;3.30 + MOV AX,es:STACKSIZE ;3.30 + MUL CX ;3.30 + MOV CX,AX ;3.30 + xor ax,ax ;3.30 + push es ;3.30 + pop ds ;ds = Relocated stack code seg.;3.30 + assume ds:nothing ;3.30 +;Now, DS -> stack code area ;3.30 + MOV ES, word ptr ds:[STACKS+2] ; GET SEGMENT OF STACK AREA.;3.30 + CLD ;3.30 + REP STOSB ;3.30 + ;3.30 + MOV CX, ds:STACKCOUNT ;3.30 + ;3.30 +; LOOP FOR "COUNT" TIMES, BUILDING A TABLE ENTRY ;3.30 +; cs = sysinitseg, ds = Relocated stack code seg , es = segment of stack space;3.30 +; CX = NUMBER OF ENTRIES ;3.30 +; ES:BP => BASE OF STACKS - 2 ;3.30 +; ES:BX => FIRST TABLE ENTRY ;3.30 + ;3.30 +BUILDLOOP: ;3.30 + MOV ALLOCBYTE,FREE ;3.30 + MOV INTLEVEL,AL ;AX = 0 ;3.30 + MOV SAVEDSP,AX ;3.30 + MOV SAVEDSS,AX ;3.30 + ADD BX,ds:STACKSIZE ;3.30 + MOV NEWSP,BX ;3.30 + MOV ES:[BX],BP ;3.30 + ADD BP,ENTRYSIZE ;3.30 + ;3.30 + LOOP BUILDLOOP ;3.30 + ;3.30 + SUB BP,ENTRYSIZE ;3.30 + MOV ds:LASTENTRY,BP ;3.30 + MOV ds:NEXTENTRY,BP ;3.30 + ;3.30 + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? ;3.30 + pop ds ;3.30 + jne Skip_disableNMIS ;3.30 + ;3.30 + MOV AL,07H ; DISABLE Convertible NMIS ;3.30 + OUT 72H,AL ;3.30 + ;3.30 +Skip_disableNMIS: ;3.30 + XOR AX,AX ;3.30 + MOV es,AX ;es - SEGID OF VECTOR TABLE AT 0;3.30 + ASSUME es:NOTHING ;ds - Relocated Stack code segment;3.30 + ;3.30 + CLI ;3.30 + ;3.30 + IRP AA,<02,08,09,70> ;3.30 + ;3.30 + MOV SI,AA&H*4 ;PASS WHERE VECTOR IS TO BE ADJUSTED ;3.30 + mov di, offset Int19OLD&AA ;we have to set OLD&AA for Int19 handler too.;3.30 + MOV BX,OFFSET OLD&AA ;PASS WHERE TO SAVE ORIGINAL OWNER POINTER;3.30 + MOV DX,OFFSET INT&AA ;PASS WHERE NEW HANDLER IS ;3.30 + CALL NEW_INIT_LOOP ;ADJUST THE VECTOR TO NEW HANDLER, ;3.30 + ; SAVING POINTER TO ORIGINAL OWNER ;3.30 + ENDM ;3.30 + ;3.30 + IRP AA,<0A,0B,0C,0D,0E,72,73,74,76,77> ;shared interrupts ;3.30 + ;3.30 + MOV SI,AA&H*4 ;PASS WHERE VECTOR IS TO BE ADJUSTED ;3.30 + push ds ;save relocated stack code segment ;3.30 + lds bx, es:[si] ;ds:bx -> original interrupt handler ;3.30 + push ds ;3.30 + pop dx ;dx = segment value ;3.30 + + cmp dx,0 + jz int&AA&_first + + cmp byte ptr ds:[bx],0cfh ;Does vector point to an IRET? + jz int&AA&_first + + cmp word ptr ds:[bx.6],424Bh ;Magic offset (see INT&AA, msstack.inc) + jz int&AA&_Not_first + + cmp dx,0f000h ;ROM BIOS segment + jnz int&AA&_Not_first + + push es + push dx + mov dx,0f000h + mov es,dx + cmp bx,word ptr es:0ff01h + pop dx + pop es + jz int&AA&_first + +int&AA&_Not_first: ;Not the first. We are going to hook vector.;3.30 + pop ds ;3.30 + mov di, offset Int19OLD&AA ;we have to set OLD&AA for Int19 handler too.;3.30 + mov BX, OFFSET OLD&AA ;PASS WHERE TO SAVE ORIGINAL OWNER POINTER;3.30 + MOV DX, OFFSET INT&AA ;PASS WHERE NEW HANDLER IS ;3.30 + CALL NEW_INIT_LOOP ;ADJUST THE VECTOR TO NEW HANDLER, SAVING;3.30 + ;POINTER TO ORIGINAL OWNER. ;3.30 + jmp short int&AA&_end ;3.30 +int&AA&_first: ;the first. Don't have to hook stack code.;3.30 + pop ds ;3.30 +int&AA&_end: ;3.30 + ;3.30 + ENDM ;3.30 + ;3.30 + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;PC convertible? ;3.30 + pop ds ;3.30 + jne Skip_EnableNMIS ;3.30 + ;3.30 + MOV AL,27H ; ENABLE Convertible NMIS ;3.30 + OUT 72H,AL ;3.30 + ;3.30 +Skip_EnableNMIS: ;3.30 + STI ;3.30 + MOV AX,code ;3.30 + MOV DS,AX ;3.30 + ASSUME DS:CODE ;3.30 + ;3.30 +; MOV SI,OFFSET STKMSG1 ;3.30 +; CALL WRMSG ;3.30 + ;3.30 + mov [INT19SEM],1 ; INDICATE THAT INT 19 ;3.30 + ; INITIALIZATION IS COMPLETE ;3.30 + ;3.30 + POP BP ; RESTORE ALL ;3.30 + POP SI ;3.30 + POP DI ;3.30 + POP DX ;3.30 + POP CX ;3.30 + POP BX ;3.30 + ;3.30 + POP ES ;3.30 + POP DS ;3.30 + assume ds:sysinitseg ;3.30 + POP AX ;3.30 + RET ;3.30 +STACKINIT ENDP ;3.30 +; ;3.30 + ;3.30 +NEW_INIT_LOOP PROC NEAR ;3.30 +;INPUT: SI=OFSET INTO VECTOR TABLE OF THE PARTICULAR INT VECTOR BEING ADJUSTED ;3.30 +; BX=ds:OFFSET OF OLDxx, WHERE WILL BE SAVED THE POINTER TO ORIGINAL OWNER;3.30 +; DX=ds:OFFSET OF INTxx, THE NEW INTERRUPT HANDLER ;3.30 +; di=offset value of Int19OLD&AA variable in BIOS. ;3.30 +; es=ZERO, SEGID OF VECTOR TABLE ;3.30 +; ds=Relocated Stack code segment ;3.30 + ;3.30 + MOV AX,es:[SI+0] ;REMEMBER OFFSET IN VECTOR ;3.30 + MOV WORD PTR ds:[BX],AX ; TO ORIGINAL OWNER in DS ;3.30 + MOV AX,es:[SI+2] ;REMEMBER SEGID IN VECTOR ;3.30 + MOV WORD PTR ds:[BX]+2,AX ; TO ORIGINAL OWNER in DS ;3.30 + push ds ;3.30 + mov ax, code ;3.30 + mov ds, ax ;Set Int19OLDxx value in BIOS for ;3.30 + mov ax,es:[si+0] ;Int 19 handler ;3.30 + mov word ptr ds:[di],ax ;3.30 + mov ax,es:[si+2] ;3.30 + mov word ptr ds:[di]+2,ax ;3.30 + pop ds ;3.30 + ;3.30 + MOV WORD PTR es:[SI+0],DX ;SET VECTOR TO POINT TO NEW INT HANDLER ;3.30 + MOV es:[SI+2],ds ;3.30 + RET ;3.30 +NEW_INIT_LOOP ENDP ;3.30 + ;3.30 diff --git a/v4.0/src/BIOS/SYSCONF.ASM b/v4.0/src/BIOS/SYSCONF.ASM new file mode 100644 index 0000000..7de3d30 --- /dev/null +++ b/v4.0/src/BIOS/SYSCONF.ASM @@ -0,0 +1,3392 @@ + PAGE ,132 ; +; SCCSID = @(#)sysconf.asm 0.0 86/10/20 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSCONF + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; P132 Multiple character device installation problem. 06/27/87 J.K. +;AN002; D24 MultiTrack= command added. 06/29/87 J.K. +;AN003; D41 REM command in CONFIG.SYS. 07/6/87 J.K. +;AN004; D184 Set DEVMARK for MEM command 08/25/87 J.K. +;AN005; P568 CONFIG.SYS parsing error with FCBS=10,15 08/31/87 J.K. +;AN006; P887 STACKS=0 does not show "ERROR in CONFIG.SYS..." 09/09/87 J.K. +;AN007; D246, P976 Show "Bad command or parameters - ..." msg 09/22/87 J.K. +;AN008; P1299 Set the second entry of DEVMARK for MEM command 09/25/87 J.K. +;AN009; P1326 New Extended attribute 09/28/87 J.K. +;AN010; P1820 New message SKL file 10/20/87 J.K. +;AN011; P1970 AUTOTEST FCBS= command error msg inconsistent 10/23/87 J.K. +;AN012; P2211 Setting the EA=7 for ANSI.SYS hangs the system 11/02/87 J.K. +;AN013; P2342 REM not allowed after INSTALL command 11/09/87 J.K. +;AN014; P2546 DEVICE= command still allowed after IFS= 11/17/87 J.K. +;AN015; D358 New device driver INIT function package 12/03/87 J.K. +;AN016; D285 Undo the extended error handling 12/17/87 J.K. +;AN017; P3170 Do not call block device driver when drive # > 26 01/20/88 J.K. +;AN018; P3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN019; D479 New option to disable extended INT 16h function call 02/12/88 J.K. +;AN020; P3607 MEM does not give correct filename 02/24/88 J.K. +;AN021; D493 Undo D358 & do not show error message for device driv 02/24/88 J.K. +;AN022; P3807 Single buffer unprotected - System hangs 03/10/88 J.K. +;AN023; P3797 An INSTALL cmd right after Bad cmd is not executed 03/10/88 J.K. +;AN024; D503 Version change to 4.0 - IBMCACHE.SYS is an exception 03/15/88 J.K. +;AN025; D474 Change BUFFERS= /E option to /X for expanded memory 03/16/88 J.K. +;AN026; D506 Take out the order dependency of the IFS= 03/28/88 J.K. +;AN027; P3957 Undo D503 - IBMCACHE.SYS version check problem 03/30/88 J.K. +;AN028; P4086 Memory allocation error when loading share.exe 03/31/88 J.K. +;AN029; D528 Install XMAEM.SYS first before everything else 04/29/88 J.K. +;AN030; P4759 INT2f, INT 67h handlers for XMA 05/11/88 J.K. +;AN031; P4889 Should check the validity of INT 67h call 05/17/88 G.A. +;AN032; P4934 P4759 INT 2fh number should be changed to 1Bh 05/20/88 J.K. +;AN033; P5002 EMS w/single page allocated now works 05/20/88 G.A. +;AN034; P5128 EMS INT 2FH HANDLER BUG 06/24/88 +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +LF equ 10 +CR equ 13 +TAB equ 9 +SEMICOLON equ ';' + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE + +HAVE_INSTALL_CMD equ 00000001b ;AN018; CONFIG.SYS has INSTALL= commands +HAS_INSTALLED equ 00000010b ;AN018; SYSINIT_BASE installed. + +IS_IFS equ 00000001b ;IFS command? +NOT_IFS equ 11111110b +; +;AN016; Undo the extended attribute handling +;;Extended attribute value +;EA_UNSPECIFIED equ 0 ;AN009; +;EA_DEVICE_DRIVER equ 6 ;AN009; +;EA_IFS_DRIVER equ 7 ;AN009; + +DEFAULT_FILENUM = 8 +; + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H +;dossize equ 0C000H ;J.K. for the debugging version of IBMDOS. + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include BIOSTRUC.INC + include smifssym.inc ;AN000; Reduced version of IFSSYM.INC. + include DEVMARK.inc ;AN004; + include version.inc +.list + + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + +; + +;J.K. 6/29/87 External variable defined in IBMBIO module for Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + +CODE segment public 'code' + EXTRN MulTrk_flag:word ;AN002; + extrn KEYRD_Func:byte ;AN019; + extrn KEYSTS_Func:byte ;AN019; +CODE ends +;J.K. 6/29/87 End of Multi-track definition. + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE + EXTRN BADSIZ_PRE:BYTE,BADLD_PRE:BYTE +; EXTRN BADSIZ_POST:BYTE,BADLD_POST:BYTE + EXTRN BADSTACK:BYTE,BADCOUNTRYCOM:BYTE + EXTRN SYSSIZE:BYTE,BADCOUNTRY:BYTE,INSUFMEMORY:BYTE + EXTRN CONDEV:BYTE,AUXDEV:BYTE,PRNDEV:BYTE,COMMND:BYTE,CONFIG:BYTE + EXTRN Cntry_Drv:BYTE,Cntry_Root:BYTE,Cntry_Path:BYTE + EXTRN DeviceParameters:byte + EXTRN MEMORY_SIZE:word + EXTRN BUFFERS:word + EXTRN FILES:byte,NUM_CDS:byte + EXTRN DOSINFO:dword,ENTRY_POINT:dword + EXTRN FCBS:byte,KEEP:byte + EXTRN CONFBOT:word,ALLOCLIM:word,COMMAND_LINE:byte + EXTRN ZERO:byte,SEPCHR:byte + EXTRN COUNT:word,CHRPTR:word,CNTRYFILEHANDLE:word + EXTRN MEMLO:word,MEMHI:word,PRMBLK:word,LDOFF:word + EXTRN PACKET:byte,UNITCOUNT:byte,BREAK_ADDR:dword + EXTRN BPB_ADDR:dword,DRIVENUMBER:byte,SYSI_COUNTRY:dword + extrn Config_Size:word ;AN000; + extrn Install_Flag:word ;AN000; + extrn BadOrder:byte ;AN000; + extrn Errorcmd:byte ;AN000; + extrn LineCount:word ;AN000; + extrn ShowCount:byte ;AN000; + extrn Buffer_LineNum:word ;AN000; + extrn IFS_Flag:word ;AN000; + extrn IFS_RH:byte ;AN000; + extrn H_Buffers:word ;AN000; + extrn Buffer_Slash_X:byte ;AN000;AN025; + extrn Badparm:byte ;AN007; + extrn ConfigMsgFlag:Word ;AN015; + extrn Org_Count:Word ;AN018; + extrn Multi_Pass_Id:byte ;AN026; + + EXTRN MEM_ERR:NEAR,SetDOSCountryInfo:NEAR + EXTRN PARAROUND:NEAR,TEMPCDS:NEAR + EXTRN Set_Country_Path:NEAR,Move_ASCIIZ:NEAR,DELIM:NEAR + EXTRN BADFIL:NEAR,ROUND:NEAR + extrn Do_Install_Exec:NEAR ;AN018; + extrn SetDevMark:NEAR ;AN030; + +;AN016; Undo the extended attribute handling +; extrn Get_Ext_Attribute:near ;AN009; + + IF STACKSW + +; Internal Stack Parameters + EntrySize equ 8 + + MinCount equ 8 + DefaultCount equ 9 + MaxCount equ 64 + + MinSize equ 32 + DefaultSize equ 128 + MaxSize equ 512 + + extrn stack_count:word + extrn stack_size:word + extrn stack_addr:dword + + ENDIF + + PUBLIC DOCONF + PUBLIC GETCHR + public Multi_Pass ;AN018;AN026; + + public MultDeviceFlag +MultDeviceFlag db 0 ;AN001; + public DevMark_Addr +DevMark_Addr dw ? ;AN004;Segment address for DEVMARK. + public SetDevMarkFlag +SetDevMarkFlag db 0 ;AN004;Flag used for DEVMARK + +EMS_Stub_Installed db 0 ;AN030; + +Badparm_Ptr label dword +Badparm_Off dw 0 ;AN007; +Badparm_Seg dw 0 ;AN007; + +XMAEM_file db 'XMAEM.SYS',0 ;AN029; + +;IBMCACHE_file db 'IBMCACHE.SYS',0;AN024;AN026;To cope with the IBMCACHE.SYS + ; problem of DOS version checking. + +;****************************************************************************** +;Take care of Config.sys file. +;SYSTEM parser data and code. +;****************************************************************************** +.xlist + include PSOPTION.INC ;Parsing options for SYSCONF. + include PARSE.ASM ;together with PSDATA.INC +.list +;Control block definitions for PARSER. +;--------------------------------------------------- +; BUFFER = [n | n,m] {/E} + +Buf_Parms label byte ;AN000; + dw Buf_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Buf_Parmsx label byte ;AN000; + db 1,2 ;AN000; Min 1, Max 2 positional + dw Buf_Pos1 ;AN000; + dw Buf_Pos2 ;AN000; + db 1 ;AN000; 1 switch + dw SW_X_Ctrl ;AN000;AN025; /X control + db 0 ;AN000; no keywords + +Buf_Pos1 label word ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no function + dw Result_Val ;AN000; Result value buffer + dw Buf_Range_1 ;AN000; value list + db 0 ;AN000; no switches/keywords + +Buf_Range_1 label byte ;AN000; value definition + db 1 ;AN000; range definition + db 1 ;AN000; 1 definition of range + db 1 ;AN000; item tag for this range + dd 1,10000 ;AN000; from 1 to 10000 + +Buf_Pos2 label word ;AN000; + dw 8001h ;AN000; Numeric value, Optional + dw 0 ;AN000; no function + dw Result_Val ;AN000; Result value buffer + dw Buf_Range_2 ;AN000; value list + db 0 ;AN000; no switches/keywords + +Buf_Range_2 label byte ;AN000; value definition + db 1 ;AN000; range definition + db 1 ;AN000; 1 definition of range + db 1 ;AN000; item tag for this range + dd 0,8 ;AN000; from 0 to 8. + +SW_X_Ctrl label word ;AN000;AN025; + dw 0 ;AN000; no matching flag + dw 0 ;AN000; no function + dw Result_Val ;AN000; return value + dw NoVal ;AN000; no value definition + db 1 ;AN000; # of switches +Switch_X label byte ;AN000;AN025; + db '/X',0 ;AN000;AN025; +;local variables +P_Buffers dw 0 ;AN000; +P_H_Buffers dw 0 ;AN000; +P_Buffer_Slash_X db 0 ;AN000;AN025; +Buffer_Pre_Scan db 0 ;AN030; + +;Common definitions ------------- +NoVal db 0 ;AN000; + +Result_Val label byte ;AN000; + db ? ;AN000; type returned + db ? ;AN000; item tag returned + dw ? ;AN000; ES:offset of the switch defined +RV_Byte label byte ;AN000; +RV_Dword label dword ;AN000; + dd ? ;AN000; value if number, or seg:offset to string. +;-------------------------------- + +; BREAK = [ ON | OFF ] + +Brk_Parms label byte ;AN000; + dw Brk_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Brk_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw Brk_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Brk_Pos label word ;AN000; + dw 2000h ;AN000; Simple string + dw 0 ;AN000; No functions + dw Result_Val ;AN000; + dw On_Off_String ;AN000; ON,OFF string descriptions + db 0 ;AN000; no keyword/switch synonyms + +On_Off_String label byte ;AN000; + db 3 ;AN000; signals that there is a string choice + db 0 ;AN000; no range definition + db 0 ;AN000; no numeric values choice + db 2 ;AN000; 2 strings for choice + db 1 ;AN000; the 1st string tag + dw On_String ;AN000; + db 2 ;AN000; the 2nd string tag + dw Off_String ;AN000; + +On_String db "ON",0 ;AN000; +Off_String db "OFF",0 ;AN000; +;local variable +P_Ctrl_Break db 0 ;AN000; local variable + +;-------------------------------- + +; COUNTRY = n {m {path}} +; or +; COUNTRY = n,,path + +Cntry_Parms label byte ;AN000; + dw Cntry_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Cntry_Parmsx label byte ;AN000; + db 1,3 ;AN000; Min 1, Max 3 positional + dw Cntry_Pos1 ;AN000; + dw Cntry_Pos2 ;AN000; + dw Cntry_Pos3 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Cntry_Pos1 label word ;AN000; control definition for positional 1 + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Cntry_Codepage_Range ;AN000; country id code range description + db 0 ;AN000; no switch/keyword synonyms + +Cntry_Codepage_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 1,999 ;AN000; + +Cntry_Pos2 label word ;AN000; control definition for positional 2 + dw 8001h ;AN000; Numeric value, optional + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Cntry_Codepage_Range ;AN000; code page range descriptions. + db 0 ;AN000; no switch/keyword synonyms + +Cntry_Pos3 label word ;AN000; control definition for positional 3 + dw 0201h ;AN000; File spec, optional + dw 0 ;AN000; No functions. Don't need to CAP. + dw Result_Val ;AN000; + dw NoVal ;AN000; no value list + db 0 ;AN000; no switch/keyword synonyms + +;Local variables +P_Cntry_Code dw 0 ;AN000; +P_Code_Page dw 0 ;AN000; + +;-------------------------------- + +; FILES = n + +Files_Parms label byte ;AN000; + dw Files_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Files_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw Files_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Files_Pos label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Files_Range ;AN000; Files range description + db 0 ;AN000; no switch/keyword synonyms + +Files_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 8,255 ;AN000; +;local variable +P_Files db 0 ;AN000; + +;-------------------------------- + +; FCBS = n,m + +FCBS_Parms label byte ;AN000; + dw FCBS_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +FCBS_Parmsx label byte ;AN000; + db 2,2 ;AN000; Min 2, Max 2 positional + dw FCBS_Pos_1 ;AN000; + dw FCBS_Pos_2 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +FCBS_Pos_1 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw FCBS_Range ;AN000; FCBS range descriptions + db 0 ;AN000; no switch/keyword synonyms + +FCBS_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 1,255 ;AN000; + +FCBS_Pos_2 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw FCBS_Keep_Range ;AN000; FCBS KEEP range descriptions + db 0 ;AN000; no switch/keyword synonyms + +FCBS_Keep_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,255 ;AN000; + +;local variable +P_Fcbs db 0 ;AN000; +P_Keep db 0 ;AN000; +;-------------------------------- + +; LASTDRIVE = x + +LDRV_Parms label byte ;AN000; + dw LDRV_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +LDRV_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw LDRV_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +LDRV_Pos label byte ;AN000; + dw 0110h ;AN000; Drive only, Ignore colon. + dw 0010h ;AN000; Remove colon at end + dw Result_Val ;AN000; + dw NoVal ;AN000; No value list + db 0 ;AN000; no switch/keyword synonyms + +;local variable +P_Ldrv db 0 ;AN000; +;-------------------------------- + +; STACKS = n,m + +STKS_Parms label byte ;AN000; + dw STKS_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +STKS_Parmsx label byte ;AN000; + db 2,2 ;AN000; Min 2, Max 2 positional + dw STKS_Pos_1 ;AN000; + dw STKS_Pos_2 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +STKS_Pos_1 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw STKS_Range ;AN000; number of stack range descriptions + db 0 ;AN000; no switch/keyword synonyms + +STKS_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,64 ;AN000; + +STKS_Pos_2 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw STK_SIZE_Range ;AN000; stack size range descriptions + db 0 ;AN000; no switch/keyword synonyms + +STK_SIZE_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,512 ;AN000; +;local variables +P_Stack_Count dw 0 ;AN000; +P_Stack_Size dw 0 ;AN000; + +;-------------------------------- + +; MULTITRACK = [ ON | OFF ] + +MTrk_Parms label byte ;AN002; + dw MTrk_Parmsx ;AN002; + db 1 ;AN002; An extra delimeter list + db 1 ;AN002; length is 1 + db SEMICOLON ;AN002; + +MTrk_Parmsx label byte ;AN002; + db 1,1 ;AN002; Min 1, Max 1 positional + dw MTrk_Pos ;AN002; + db 0 ;AN002; no switches + db 0 ;AN002; no keywords + +MTrk_Pos label word ;AN002; + dw 2000h ;AN002; Simple string + dw 0 ;AN002; No functions + dw Result_Val ;AN002; + dw On_Off_String ;AN002; ON,OFF string descriptions + db 0 ;AN002; no keyword/switch synonyms + +;local variables +P_Mtrk db 0 ;AN002; +;-------------------------------- + +; CPSW = [ ON | OFF ] + +CPSW_Parms label byte ;AN002; + dw CPSW_Parmsx ;AN002; + db 1 ;AN002; An extra delimeter list + db 1 ;AN002; length is 1 + db SEMICOLON ;AN002; + +CPSW_Parmsx label byte ;AN002; + db 1,1 ;AN002; Min 1, Max 1 positional + dw CPSW_Pos ;AN002; + db 0 ;AN002; no switches + db 0 ;AN002; no keywords + +CPSW_Pos label word ;AN002; + dw 2000h ;AN002; Simple string + dw 0 ;AN002; No functions + dw Result_Val ;AN002; + dw On_Off_String ;AN002; ON,OFF string descriptions + db 0 ;AN002; no keyword/switch synonyms + +;local variables +P_CPSW db 0 ;AN002; + +;-------------------------------- +; SWITCHES=/K + +Swit_Parms label byte ;AN019; + dw Swit_Parmsx ;AN019; + db 1 ;AN019; An extra delimeter list + db 1 ;AN019; length is 1 + db SEMICOLON ;AN019; + +Swit_Parmsx label byte ;AN019; + db 0,0 ;AN019; No positionals + db 1 ;AN019; 1 switch for now. + dw Swit_K_Ctrl ;AN019; /K control + db 0 ;AN019; no keywords + +Swit_K_Ctrl label word ;AN019; + dw 0 ;AN019; no matching flag + dw 0 ;AN019; no function + dw Result_Val ;AN019; return value + dw NoVal ;AN019; no value definition + db 1 ;AN019; # of switches +Swit_K label byte ;AN019; + db '/K',0 ;AN019; +;local variables +P_Swit_K db 0 ;AN019; + +;****************************************************************************** + +DOCONF: + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + MOV AX,(CHAR_OPER SHL 8) ;GET SWITCH CHARACTER + INT 21H + MOV [COMMAND_LINE+1],DL ; Set in default command line + + MOV DX,OFFSET CONFIG ;NOW POINTING TO FILE DESCRIPTION + MOV AX,OPEN SHL 8 ;OPEN FILE "CONFIG.SYS" + STC ;IN CASE OF INT 24 + INT 21H ;FUNCTION REQUEST +; JC ENDCONF ;Wasn't there, or couldn't open (sickness) + jc No_Config_sys ;AN028; + JMP NOPROB ;PROBLEM WITH OPEN +No_Config_sys: ;AN028; + mov Multi_Pass_Id, 11 ;AN028; set it to unreasonable number +ENDCONF: + return + + +BADOP: MOV DX,OFFSET BADOPM ;WANT TO PRINT COMMAND ERROR "Unrecognized command..." + invoke PRINT + call Error_Line ;show "Error in CONFIG.SYS ..." . + JMP COFF + +Badop_p proc near ;AN000; +;Same thing as BADOP, but will make sure to set DS register back to SYSINITSEG +;and return back to the calller. + push cs + pop ds ;set ds to CONFIGSYS seg. + mov dx, offset badopm + invoke PRINT + call Error_Line + ret +Badop_p endp + +Badparm_p proc near ;AN007; +;Show "Bad command or parameters - xxxxxx" +;In Badparm_seg, Badparm_off -> xxxxx +; + cmp cs:Buffer_Pre_Scan, 1 ;AN030; Pre scanning Buffers ... /X? + je BadParmp_Ret ;AN030; then do not show any message. + push ds ;AN007; + push dx ;AN007; + push si ;AN007; + + push cs ;AN007; + pop ds ;AN007; + mov dx, offset Badparm ;AN007; + invoke PRINT ;AN007;"Bad command or parameters - " + lds si, Badparm_ptr ;AN007; +Badparm_Prt: ;AN007;print "xxxx" until CR. + mov dl, byte ptr [si] ;AN007; + mov ah,STD_CON_OUTPUT ;AN007; + int 21h ;AN007; + inc si ;AN007; + cmp dl, CR ;AN007; + jne Badparm_Prt ;AN007; + push cs ;AN007; + pop ds ;AN007; + mov dx, offset CRLFM ;AN007; + invoke PRINT ;AN007; + call Error_Line ;AN007; + pop si ;AN007; + pop dx ;AN007; + pop ds ;AN007; +BadParmp_Ret: ;AN030; + ret ;AN007; +Badparm_p endp + +NOPROB: ;GET FILE SIZE (NOTE < 64K!!) + MOV BX,AX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + INT 21H + MOV [COUNT],AX + XOR DX,DX + MOV AX,LSEEK SHL 8 ;Reset pointer to beginning of file + INT 21H +; MOV DX,CS + mov dx, [ConfBot] ;AN022;Use current CONFBOT value + MOV AX,[COUNT] + mov [config_size], ax ;save the size of config.sys file. + call ParaRound + SUB DX,AX + SUB DX,11H ;ROOM FOR HEADER + MOV [CONFBOT],DX ; Config starts here. New CONBOT value. + CALL TEMPCDS ; Finally get CDS to "safe" location +ASSUME DS:NOTHING,ES:NOTHING + + MOV DX,[CONFBOT] + MOV DS,DX + MOV ES,DX + XOR DX,DX + MOV CX,[COUNT] + MOV AH,READ + STC ;IN CASE OF INT 24 + INT 21H ;Function request + PUSHF +; +; Find the EOF mark in the file. If present, then trim length. + + SaveReg + MOV AL,1Ah ; eof mark + MOV DI,DX ; point ro buffer + JCXZ PutEOL ; no chars + REPNZ SCASB ; find end + JNZ PutEOL ; none found and count exahusted +; +; We found a 1A. Back up +; + DEC DI ; backup past 1A +; +; Just for the halibut, stick in an extra EOL +; +PutEOL: + MOV AL,CR + STOSB ; CR + MOV AL,LF + STOSB ; LF + SUB DI,DX ; difference moved + MOV Count,DI ; new count +; +; Restore registers +; + RestoreReg + + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + PUSH AX + MOV AH,CLOSE + INT 21H + POP AX + POPF + JC CONFERR ;IF NOT WE'VE GOT A PROBLEM + CMP CX,AX + JZ GETCOM ;COULDN'T READ THE FILE +CONFERR: + MOV DX,OFFSET CONFIG ;WANT TO PRINT CONFIG ERROR + CALL BADFIL +ENDCONV:JMP ENDCONF + +Multi_Pass: ;AN018;AN026; called to execute IFS=, INSTALL= commands + push cs ;AN018; + pop ds ;AN018; + cmp Multi_Pass_id, 10 ;J.K. + jae Endconv ;J.K. Do nothing. Just return. + push Confbot ;AN018; + pop es ;AN018; ES -> Confbot + mov si, Org_Count ;AN018; + mov Count, si ;AN018; set Count + xor si,si ;AN018; + mov Chrptr, si ;AN018; reset Chrptr, LineCount + mov LineCount, si ;AN018; + call GetChr ;AN018; + jmp Conflp ;AN018; +GETCOM: + invoke ORGANIZE ;ORGANIZE THE FILE + CALL GETCHR + +CONFLP: JC ENDCONV + call Reset_DOS_Version ;AN024;AN026; Still need to reset version even IBMDOS handles this through + ; function 4Bh call, since IBMDOS does not know when Load/Overlay call finishes. + +IF NOT BUFFERFLAG + call EMS_Stub_handler ;AN030; +ENDIF + + inc LineCount ;AN000; Increase LineCount. + mov Buffer_Pre_Scan, 0 ;AN030; Reset Buffer_Pre_Scan. + mov MultDeviceFlag,0 ;AN001; Reset MultDeviceFlag. + mov SetDevMarkFlag,0 ;AN004; Reset SetDevMarkFlag. + cmp al, LF ;AN000; LineFeed? + je Blank_Line ;AN000; then ignore this line. + MOV AH,AL + CALL GETCHR + jnc TryI ;AN000; + cmp Multi_Pass_ID, 2 ;AN026; + jae Endconv ;AN026;Do not show Badop again for multi_pass. + JMP BADOP + +COFF: PUSH CS + POP DS + invoke NEWLINE + JMP CONFLP +Blank_Line: ;AN000; + call Getchr ;AN000; + jmp CONFLP ;AN000; + +COFF_P: + push cs + pop ds + + +;J.K. 1/27/88 ;;;;;;;;;;;;;;;;;; +;To handle INSTALL= commands, we are going to use multi-pass. +;The first pass handles the other commands and only set Install_Flag when +;it finds any INSTALL command. The second pass will only handle the +;INSTALL= command. + +;------------------------------------------------------------------------------ +;INSTALL command +;------------------------------------------------------------------------------ +TRYI: + cmp Multi_Pass_Id, 0 ;AN029; the initial pass for XMAEM.SYS + je Multi_Try_XMAEM ;AN029; and BUFFERS= ... /X pre scan. + cmp Multi_Pass_Id, 2 ;AN026; the second pass for IFS= ? + je Multi_Try_J ;AN026; + cmp Multi_Pass_Id, 3 ;AN026; the third pass for INSTALL= ? + je Multi_Try_I ;AN026; + cmp ah, 'I' ;AN018; INSTALL= command? + jne TryB ;AN018; the first pass is for normal operation. + or Install_Flag, HAVE_INSTALL_CMD ;AN018; Set the flag + jmp coff ;AN018; and handles the next command + +Multi_Try_XMAEM: ;AN029; + cmp ah, 'D' ;AN029; device= command? + jne Multi_Try_Buff ;AN029; no skip it. + call Chk_XMAEM ;AN029; is it for XMAEM.SYS? + jnz Multi_Pass_FIlter ;AN029; no skip it. + mov byte ptr es:[si-1], 0FFh ;AN029; mark this command as a Null command for the next pass. + jmp TryDJ ;AN029; execute this command. +Multi_Try_Buff: ;AN030; + cmp ah, 'B' ;AN030; Buffers= command? + jne Multi_Pass_Filter ;AN030; + mov Buffer_Pre_Scan, 1 ;AN030; Set Buffer_Pre_Scan + jmp TryB ;AN030; TryB will set P_Buffer_Slash_X to non-zero value. + +Multi_Try_J: ;AN026; + cmp ah, 'J' ;AN026; IFS= command? + jne Multi_Pass_Filter ;AN026; No. Ignore this. + jmp GotJ ;AN026; Handles IFS= command. + +Multi_Try_I: ;AN026; + cmp ah, 'I' ;AN026; INSTALL= command? + jne Multi_Pass_Filter ;AN026; No. Ignore this. + call Do_Install_Exec ;Install it. + jmp Coff ;to handle next Install= command. + +Multi_Pass_Filter: ;AN023;AN026; + cmp ah, 'Y' ;AN023; Comment? + je Multi_Pass_Adjust ;AN023; + cmp ah, 'Z' ;AN023; Bad command? + je Multi_Pass_Adjust ;AN023; + cmp ah, '0' ;AN023; REM? + jne Multi_Pass_Coff ;AN023; ignore the rest of the commands. +Multi_Pass_Adjust: ;AN023; These commands need to + dec Chrptr ;AN023; adjust chrptr, count + inc Count ;AN023; for NEWLINE proc. +Multi_Pass_Coff: ;AN023; + jmp Coff ;AN018; To handle next INSTALL= commands. + +;------------------------------------------------------------------------------ + +Sysinit_Parse proc +;Set up registers for SysParse +;In) ES:SI -> command line in CONFBOT +; DI -> offset of the parse control defintion. +; +;Out) Calls SYSPARSE. +; Carry will set if Parse error. +; *** The caller should check the EOL condition by looking at AX +; *** after each call. +; *** If no parameters are found, then AX will contain a error code. +; *** If the caller needs to look at the SYNOMYM@ of the result, +; *** the caller should use CS:@ instead of ES:@. +; CX register should be set to 0 at the first time the caller calls this +; procedure. +; AX - exit code +; BL - TErminated delimeter code +; CX - new positional ordinal +; SI - set to pase scanned operand +; DX - selected result buffer + + push es ;save es,ds + push ds + + push es + pop ds ;now DS:SI -> command line + push cs + pop es ;now ES:DI -> control definition + + mov cs:Badparm_Seg,ds ;AN007;Save the pointer to the parm + mov cs:Badparm_Off,si ;AN007; we are about to parse for Badparm msg. + mov dx, 0 + call SysParse + cmp ax, $P_NO_ERROR ;no error +; $IF E,OR + JE $$LL1 + cmp ax, $P_RC_EOL ;or the end of line? +; $IF E + JNE $$IF1 +$$LL1: + clc +; $ELSE + JMP SHORT $$EN1 +$$IF1: + stc +; $ENDIF +$$EN1: + pop ds + pop es ;restore es,ds + ret +Sysinit_Parse endp + +;------------------------------------------------------------------------------ +; Buffer command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of buffers= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Buffers set * +; Buffer_Slash_X flag set if /X option chosen. * +; H_Buffers set if secondary buffer cache specified. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to Buf_Parms; /*Parse control definition*/ * +; Set DX,CX to 0; * +; Reset Buffer_Slash_X; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; if (Result_Val.$P_SYNONYM_ptr == Slash_E) then /*Not a switch * +; Buffer_Slash_X = 1 * +; else if (CX == 1) then /* first positional */ * +; Buffers = Result_Val.$P_Picked_Val; * +; else H_Buffers = Result_Val.$P_Picked_Val; * +; else {Show Error message;Error Exit} * +; }; * +; If (Buffer_Slash_X is off & Buffers > 99) then Show_Error; * +; }; * +; * +;******************************************************************************* +;TryB: CMP AH,'B' ;BUFFER COMMAND? +; JNZ TRYC +; invoke GETNUM +; JZ TryBBad ; Gotta have at least one +; CMP AX,100 ; check for max number +; JB SaveBuf +;TryBBad:JMP BadOp +;SaveBuf: +; MOV [BUFFERS],AX +;CoffJ1: JMP COFF + +TryB: + CMP AH,'B' + JNZ TryC + mov P_Buffer_Slash_X, 0 ;AN000;AN025; + mov di, offset Buf_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO4: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF4 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR4 +$$IF4: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then jmp to $Endloop for semantic check. + JE $$EN4 + cmp Result_Val.$P_SYNONYM_PTR, offset Switch_X ;AN000;AN025; +; $IF E ;AN000; + JNE $$IF8 + mov P_Buffer_Slash_X, 1 ;AN000;AN025; set the flag +; $ELSE ;AN000; + JMP SHORT $$EN8 +$$IF8: + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF10 + mov P_Buffers, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN10 +$$IF10: + mov P_H_Buffers, ax ;AN000; +; $ENDIF ;AN000; +$$EN10: +; $ENDIF ;AN000; +$$EN8: +; $ENDLOOP ;AN000; + JMP SHORT $$DO4 +$$EN4: + cmp P_Buffers, 99 ;AN000; +; $IF A,AND ;AN000; + JNA $$IF15 + cmp P_Buffer_Slash_X, 0 ;AN000;AN025; +; $IF E ;AN000; + JNE $$IF15 + call Badparm_p ;AN000; + mov P_H_Buffers, 0 ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN15 +$$IF15: + mov ax, P_Buffers ;AN000; We don't have any problem. + mov Buffers, ax ;AN000; Now, let's set it really. + mov ax, P_H_Buffers ;AN000; + mov H_Buffers, ax ;AN000; + mov al, P_Buffer_Slash_X ;AN000;AN025; + mov Buffer_Slash_X, al ;AN000;AN025; + mov ax, LineCount ;AN000; + mov Buffer_LineNum, ax ;AN000; Save the line number for the future use. +; $ENDIF ;AN000; +$$EN15: +; $ENDSRCH ;AN000; +$$SR4: + jmp Coff + +;------------------------------------------------------------------------------ +; Break command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of Break = command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn the Control-C check on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to Brk_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_Ctrl_Break, on; * +; else /*OFF */ * +; Set P_Ctrl_Break, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set Ctrl_Break check according to * +; }; * +; * +;******************************************************************************** +;TryC: CMP AH,'C' +; JZ GOTC +; JMP TRYDJ +;GOTC: +; CMP AL,'O' ;FIRST LETTER OF "ON" or "OFF" +; JNZ TryCBad +; CALL GETCHR +; JC TryCBad +; CMP AL,'N' ;SECOND LETTER OF "ON" +; JNZ TryCoff +; MOV AH,SET_CTRL_C_TRAPPING ;TURN ON CONTROL-C CHECK +; MOV AL,1 +; MOV DL,AL +; INT 21H +;CoffJ2: JMP Coff +;TryCOff:CMP AL,'F' +; JNZ TryCBad ; Check for "OFF" +; CALL GetChr +; JC TryCBad +; CMP AL,'F' +; JZ COffJ2 +;TryCBad:JMP BadOp +; +TryC: + CMP AH,'C' + JNZ TRYM + mov di, offset Brk_Parms ;AN000; + xor cx,cx ;AN000; + mov dx,cx ;AN000; +; $SEARCH ;AN000; +$$DO19: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse error + JNC $$IF19 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN000; + JMP SHORT $$SR19 +$$IF19: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN19 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF23 + mov P_Ctrl_Break, 1 ;AN000; Turn it on +; $ELSE ;AN000; + JMP SHORT $$EN23 +$$IF23: + mov P_Ctrl_Break, 0 ;AN000; Turn it off +; $ENDIF ;AN000; +$$EN23: +; $ENDLOOP ;AN000; we actually set the ctrl break + JMP SHORT $$DO19 +$$EN19: + mov ah, SET_CTRL_C_TRAPPING ;AN000; if we don't have any parse error. + mov al, 1 ;AN000; + mov dl, P_Ctrl_Break ;AN000; + Int 21h ;AN000; +; $ENDSRCH ;AN000; +$$SR19: + jmp Coff + +;------------------------------------------------------------------------------ +; MultiTrack command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of MultiTrack= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn MulTrk_Flag on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to Brk_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_Mtrk, on; * +; else /*OFF */ * +; Set P_Mtrk, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set MulTrk_Flag according to P_Mtrk. * +; * +; }; * +; * +;******************************************************************************** +TryM: ;AN002; + CMP AH,'M' ;AN002; + JNZ TRYW ;AN002; + mov di, offset Mtrk_Parms ;AN002; + xor cx,cx ;AN002; + mov dx,cx ;AN002; +; $SEARCH ;AN002; +$$DO28: + call Sysinit_Parse ;AN002; +; $EXITIF C ;AN002; Parse error + JNC $$IF28 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN002; + JMP SHORT $$SR28 +$$IF28: + cmp ax, $P_RC_EOL ;AN002; End of Line? +; $LEAVE E ;AN002; then end the $ENDLOOP + JE $$EN28 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; +; $IF E ;AN002; + JNE $$IF32 + mov P_Mtrk, 1 ;AN002; Turn it on temporarily. +; $ELSE ;AN002; + JMP SHORT $$EN32 +$$IF32: + mov P_Mtrk, 0 ;AN002; Turn it off temporarily. +; $ENDIF ;AN002; +$$EN32: +; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. + JMP SHORT $$DO28 +$$EN28: + push ds ;AN002; + mov ax, Code ;AN002; + mov ds, ax ;AN002; + assume ds:Code + cmp P_Mtrk, 0 ;AN002; +; $IF E ;AN002; + JNE $$IF36 + mov MulTrk_Flag, MULTRK_OFF2 ;AN002; 0001h +; $ELSE ;AN002; + JMP SHORT $$EN36 +$$IF36: + mov MulTrk_Flag, MULTRK_ON ;AN002; 8000h +; $ENDIF ;AN002; +$$EN36: + pop ds ;AN002; + assume ds:SYSINITSEG +; $ENDSRCH ;AN002; +$$SR28: + jmp Coff ;AN002; + +;------------------------------------------------------------------------------ +; CPSW command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of CPSW= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn CPSW on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to CPSW_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_CPSW, on; * +; else /*OFF */ * +; Set P_CPSW, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set CPSW according to P_CPSW. * +; }; * +; * +;******************************************************************************** +TryW: ;AN002; + CMP AH,'W' ;AN002; + JNZ TRYDJ ;AN002; + mov di, offset CPSW_Parms ;AN002; + xor cx,cx ;AN002; + mov dx,cx ;AN002; +; $SEARCH ;AN002; +$$DO40: + call Sysinit_Parse ;AN002; +; $EXITIF C ;AN002; Parse error + JNC $$IF40 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN002; + JMP SHORT $$SR40 +$$IF40: + cmp ax, $P_RC_EOL ;AN002; End of Line? +; $LEAVE E ;AN002; then end the $ENDLOOP + JE $$EN40 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; +; $IF E ;AN002; + JNE $$IF44 + mov P_CPSW, 1 ;AN002; Turn it on temporarily. +; $ELSE ;AN002; + JMP SHORT $$EN44 +$$IF44: + mov P_CPSW, 0 ;AN002; Turn it off temporarily. +; $ENDIF ;AN002; +$$EN44: +; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. + JMP SHORT $$DO40 +$$EN40: + mov ah, SET_CTRL_C_TRAPPING ;AN000; The same function number as Ctrl_Break + mov al, 4 ;AN000; Set CPSW state function + mov dl, P_CPSW ;AN000; 0=off, 1=on + Int 21h ;AN000; +; $ENDSRCH ;AN002; +$$SR40: + jmp Coff ;AN002; + +;------------------------------------------------------------------------------ +; Device command +;------------------------------------------------------------------------------ +TRYDJ: + and cs:IFS_Flag, NOT_IFS ;AN000; Reset the flag + CMP AH,'D' + JZ GOTDJ + CMP AH,'J' + jz GOTJ + JMP TRYQ +GOTJ: ;AN000; IFS= command. + or cs:[IFS_Flag], IS_IFS ;AN000; set the flag. + cmp Multi_Pass_Id, 2 ;second pass? + je GOTDJ ;then proceed + jmp Coff ;else ignore this until the second pass. + +; jmp GOTDJ_Cont +;GOTD: +; test cs:[IFS_Flag], HAD_IFS ;AN000; Cannot have DEVICE= command after IFS= command. +; jz GOTDJ_Cont ;AN000; +; call Incorrect_Order ;AN000; Display "Incorrect order ..." msg. +; jmp COFF ;AN000; + +GOTDJ: + MOV BX,CS ;DEVICE= or IFS= command. + MOV DS,BX + + MOV WORD PTR [BPB_ADDR],SI + MOV WORD PTR [BPB_ADDR+2],ES + +;J.K. In case it is for IFS=, then set the parameter pointer. + mov word ptr [ifs_rh.IFSR_PARMS@], SI ;AN000; for IFS + mov word ptr [ifs_rh.IFSR_PARMS@+2], ES ;AN000; + + CALL ROUND +;J.K. Set up the DEVMARK entries here for MEM command. +;J.K. Only the DEVMARK_ID and DEVMARK_FILENAME will be set. +;J.K. DEVMARK_SIZE should be set after a successful process of this file. + call Set_DevMark ;AN004; + inc [MEMHI] ;AN004;Size of DEVMARK is a paragraph!! + ;Don't forget decrease MEMHI + ; with an unsuccessful process of this file!!. + XOR AX,AX + MOV WORD PTR [ENTRY_POINT],AX + MOV AX,[MEMHI] + MOV WORD PTR [ENTRY_POINT+2],AX ;SET ENTRY POINT + + IF NOT NOEXEC + MOV [LDOFF],AX ;SET LOAD OFFSET + ENDIF + + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV DX,SI ;DS:DX POINTS TO FILE NAME + + IF NOEXEC + LES BX,DWORD PTR CS:[MEMLO] + CALL LDFIL ;LOAD IN THE DEVICE DRIVER + ELSE +; We are going to open the cdevice driver and size it as is done +; in LDFIL. The reason we must do this is that EXEC does NO checking +; for us. We must make sure there is room to load the device without +; trashing SYSINIT. This code is not +; perfect (for instance .EXE device drivers are possible) because +; it does its sizing based on the assumption that the file being loaded +; is a .COM file. It is close enough to correctness to be usable. + MOV ES,AX ;ES:0 is LOAD addr + MOV AX,OPEN SHL 8 ;OPEN THE FILE + STC ;IN CASE OF INT 24 + INT 21H + JC BADLDRESET + MOV BX,AX ;Handle in BX +;AN016; UNDO THE EXTENDED ATTRIBUTE HANDLING +; call Get_Ext_Attribute ;AN009; +; jc BadLdReset ;AN009; +; test cs:[IFS_Flag], IS_IFS ;AN009; +; jnz Chk_Ext_Attr_IFS ;AN009; +; cmp al, EA_UNSPECIFIED ;AN009;Check the extended attr. for device driver +; je Ext_Attr_Ok ;AN009; Allow 0 and EA_DEVICE_DRIVER +; cmp al, EA_DEVICE_DRIVER ;AN009; +; je Ext_Attr_Ok ;AN009; +; stc ;AN012;BadLdReset depends on the carry bit. +; jmp BadLdReset ;AN009; +;Chk_Ext_Attr_IFS: ;AN009; +; cmp al, EA_IFS_DRIVER ;AN009; +; je Ext_Attr_Ok ;AN012; +; stc ;AN012; +; jmp BadLdReset ;AN012; +;Ext_Attr_Ok: ;AN009; + PUSH DX ; Save pointer to name + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JNC GO_AHEAD_LOAD + MOV AH,CLOSE ; Close file + INT 21H + POP DX ; Clean stack + STC ; Close may clear carry + JMP SHORT BADLDRESET + +GO_AHEAD_LOAD: + ; Convert size in DX:AX to para in AX + ADD AX,15 ; Round up size for conversion to para + ADC DX,0 + MOV CL,4 + SHR AX,CL + MOV CL,12 + SHL DX,CL ; Low nibble of DX to high nibble + OR AX,DX ; AX is now # of para for file + + MOV CX,ES ; CX:0 is xaddr + ADD CX,AX ; New device will take up to here + JC MEM_ERRJY ; WOW!!!! + CMP CX,CS:[ALLOCLIM] + JB OKLDX +MEM_ERRJY: + JMP MEM_ERR + +OKLDX: + POP DX ; Recover name pointer + MOV AH,CLOSE ; Close file + INT 21H + MOV BX,CS + MOV ES,BX + MOV BX,OFFSET PRMBLK ;ES:BX POINTS TO PARAMETERS + MOV AL,3 + MOV AH,EXEC + STC ;IN CASE OF INT 24 + INT 21H ;LOAD IN THE DEVICE DRIVER + ENDIF + +BADLDRESET: + PUSH DS + POP ES ;ES:SI BACK TO CONFIG.SYS + PUSH CS + POP DS ;DS BACK TO SYSINIT +ASSUME DS:SYSINITSEG + JNC GOODLD +BADBRK: + test cs:[SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip0_ResetMEMHI ;AN004; then do not + dec cs:[MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip0_ResetMEMHI: + cmp byte ptr es:[si], CR ;file name is CR? (Somebody entered "device=" without filename) + jne BADBRK_1 + jmp BADOP ;show "Unrecognized command in CONFIG.SYS" +BADBRK_1: + invoke BADLOAD + JMP COFF + +GOODLD: +;J.K. If it is IFS=, then we should set IFS_DOSCALL@ field in IFSHEADER. + test cs:[IFS_Flag], IS_IFS ;AN000; + jz Skip_IFSHEADER_Set ;AN000; + push es ;AN000; + push di ;AN000; + push ds ;AN000; + mov bx, word ptr cs:[ENTRY_POINT+2] ;AN000; + mov ds, bx ;AN000; DS:0 will be the header + les di, cs:[DosInfo] ;AN000; + mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@] ;AN000; + mov word ptr ds:[IFS_DOSCALL@], bx ;AN000; + mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@]+2 ;AN000; + mov word ptr ds:[IFS_DOSCALL@]+2, bx ;AN000; + pop ds ;AN000; + pop di ;AN000; + pop es ;AN000; +Skip_IFSHEADER_Set: ;AN000; + SaveReg ;INITIALIZE THE DEVICE +; call Chk_IBMCACHE ;AN024 IBMCACHE.SYS problem.;AN026;IBMDOS will handles this thru 4Bh call. +Restore:MOV BL,ES:[SI] ; while ((c=*p) != 0) + OR BL,BL + JZ Got + INC SI ; p++; + JMP Restore +Got: MOV BYTE PTR ES:[SI],' ' ; *p = ' '; + SaveReg + PUSH CS + POP ES + + test cs:[IFS_Flag], IS_IFS ;AN000; + jz Got_Device_Com ;AN000; + mov bx, IFS_CALL@ ;AN000; offset from the start of IFSHEADER + call CallIFS ;AN000; + jmp short End_Init_Call +Got_Device_Com: + push ds ;AN017; + push si ;AN017; + lds si, cs:[ENTRY_POINT] ;AN017; Peeks the header attribute + test word ptr ds:[si.SDEVATT], DEVTYP ;AN017;Block device driver? + jnz Got_Device_Com_Cont ;AN017;No. + lds si, cs:[DOSINFO] ;AN017; DS:SI -> SYS_VAR + cmp ds:[si.SYSI_NUMIO], 26 ;AN017; No more than 26 drive number + jb Got_Device_Com_Cont ;AN017; + pop si ;AN017; + pop ds ;AN017; + pop si ;AN017;clear the stack + pop es ;AN017; + jmp BadNumBlock ;AN017; +Got_Device_Com_Cont: ;AN017; + pop si ;AN017; + pop ds ;AN017; + MOV BX,SDEVSTRAT + invoke CALLDEV ; CallDev (SDevStrat); + MOV BX,SDEVINT + invoke CALLDEV ; CallDev (SDevInt); +End_Init_Call: + RestoreReg + MOV BYTE PTR [SI],0 ; *p = 0; + + PUSH CS + POP DS + + test [IFS_Flag], IS_IFS ;AN000; + jz Was_Device_Com ;AN000; + cmp [ifs_rh.IFSR_RETCODE], 0 ;AN000; Was a success ? + jne Erase_Dev_do ;AN000; + pop si ;AN000; restore es:si to clean up the + pop es ;AN000; stack for Set_Break call. + mov ax, word ptr [Entry_Point+2] ;AN000; Get the loaded segment + add ax, word ptr [ifs_rh.IFSR_RESSIZE] ;AN000; + mov word ptr [Break_addr], 0 ;AN000; + mov word ptr [Break_addr+2], ax ;AN000; + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004; + invoke Set_Break ;AN000; Will also check the memory size too. + push es ;AN000; Save it again, in case, for Erase_Dev_Do. + push si ;AN000; + jc Erase_Dev_do ;AN000; +Link_IFS: ;AN000; + les di, cs:[dosinfo] ;AN000; + mov cx, word ptr es:[di.SYSI_IFS] ;AN000; save old pointer + mov dx, word ptr es:[di.SYSI_IFS+2] ;AN000; + lds si, cs:[Entry_Point] ;AN000; + mov word ptr es:[di.SYSI_IFS],si ;AN000; + mov word ptr es:[di.SYSI_IFS+2], ds ;AN000; + mov word ptr ds:[si], cx ;AN000; We don't permit multiple IFSs. + mov word ptr ds:[si+2], dx ;AN000; + pop si ;AN000; Restore es:si for the next command. + pop es ;AN000; +; mov cs:[IFS_Flag], HAD_IFS ;AN014; Set the flag. + jmp COFF ;AN000; + +ERASE_DEV_do: ;AC000;; Modified to show message "Error in CONFIG.SYS..." + pop si + pop es + push cs + pop ds + test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip1_ResetMEMHI ;AN004; then do not + dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip1_ResetMEMHI: + cmp ConfigMsgFlag, 0 ;AN015; + je No_Error_Line_Msg ;AN015; + call Error_Line ;AN021; No "Error in CONFIG.SYS" msg for device driver. DCR D493 + mov ConfigMsgFlag, 0 ;AN015;AN021;Set the default value again. +No_Error_Line_Msg: ;AN015; + JMP Coff + +Was_Device_Com: ;AN000; + MOV AX,WORD PTR [BREAK_ADDR+2] + CMP AX,[MEMORY_SIZE] + JB BREAKOK + POP SI + POP ES + JMP BADBRK + +BREAKOK: + LDS DX,[ENTRY_POINT] ;SET DS:DX TO HEADER + MOV SI,DX + ADD SI,SDEVATT ;DS:SI POINTS TO ATTRIBUTES + LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO + MOV AX,DS:[SI] ;GET ATTRIBUTES + TEST AX,DEVTYP ;TEST IF BLOCK DEV + JZ ISBLOCK + or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; + invoke Set_Break ; Go ahead and alloc mem for device + jc Erase_Dev_do ;device driver's Init routien failed. + TEST AX,ISCIN ;IS IT A CONSOLE IN? + JZ TRYCLK + MOV WORD PTR ES:[DI.SYSI_CON],DX + MOV WORD PTR ES:[DI.SYSI_CON+2],DS + +TRYCLK: TEST AX,ISCLOCK ;IS IT A CLOCK DEVICE? + JZ GOLINK + MOV WORD PTR ES:[DI+SYSI_CLOCK],DX + MOV WORD PTR ES:[DI+SYSI_CLOCK+2],DS +GOLINK: JMP LINKIT + +ISBLOCK: + MOV AL,CS:[UNITCOUNT] ;IF NO UNITS FOUND, erase the device + OR AL,AL + jz Erase_Dev_do +; JNZ PERDRV +; MOV AX, -1 +; JMP ENDDEV + +PERDRV: + CBW ; WARNING NO DEVICE > 127 UNITS + MOV CX,AX + MOV DH,AH + MOV DL,ES:[DI.SYSI_NUMIO] ;GET NUMBER OF DEVICES + MOV AH,DL + ADD AH,AL ; Check for too many devices + CMP AH,26 ; 'A' - 'Z' is 26 devices + JBE OK_BLOCK +BadNumBlock: ;AN017; + PUSH CS + POP DS + MOV DX,OFFSET BADBLOCK + invoke PRINT + JMP ERASE_DEV_do + +OK_BLOCK: + or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; + invoke SET_BREAK ; Alloc the device + ADD ES:[DI.SYSI_NUMIO],AL ;UPDATE THE AMOUNT + ADD CS:DriveNumber,AL ; remember amount for next device + LDS BX,CS:[BPB_ADDR] ;POINT TO BPB ARRAY +PERUNIT: + LES BP,CS:[DOSINFO] + LES BP,DWORD PTR ES:[BP.SYSI_DPB] ;GET FIRST DPB + +SCANDPB:CMP WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + JZ FOUNDPB + LES BP,ES:[BP.DPB_NEXT_DPB] + JMP SCANDPB +FOUNDPB: + MOV AX,CS:[MEMLO] + MOV WORD PTR ES:[BP.DPB_NEXT_DPB],AX + MOV AX,CS:[MEMHI] + MOV WORD PTR ES:[BP.DPB_NEXT_DPB+2],AX + LES BP,DWORD PTR CS:[MEMLO] + ADD WORD PTR CS:[MEMLO],DPBSIZ + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004;Add DPB area for this unit + CALL ROUND ;Check for alloc error + MOV WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + MOV ES:[BP.DPB_FIRST_ACCESS],-1 + + MOV SI,[BX] ;DS:SI POINTS TO BPB + INC BX + INC BX ;POINT TO NEXT GUY + MOV WORD PTR ES:[BP.DPB_DRIVE],DX + MOV AH,SETDPB ;HIDDEN SYSTEM CALL + INT 21H + MOV AX,ES:[BP.DPB_SECTOR_SIZE] + PUSH ES + LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO + CMP AX,ES:[DI.SYSI_MAXSEC] + POP ES + ja Bad_BPB_Size_Sector + PUSH DS + PUSH DX + LDS DX,CS:[ENTRY_POINT] + MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR],DX + MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR+2],DS + POP DX + POP DS + INC DX + INC DH + LOOP PERUNIT + PUSH CS + POP DS + CALL TEMPCDS ; Set CDS for new drives + +LINKIT: + LES DI,CS:[DOSINFO] ;ES:DI = DOS TABLE + MOV CX,WORD PTR ES:[DI.SYSI_DEV] ;DX:CX = HEAD OF LIST + MOV DX,WORD PTR ES:[DI.SYSI_DEV+2] + + LDS SI,CS:[ENTRY_POINT] ;DS:SI = DEVICE LOCATION + MOV WORD PTR ES:[DI.SYSI_DEV],SI ;SET HEAD OF LIST IN DOS + MOV WORD PTR ES:[DI.SYSI_DEV+2],DS + MOV AX,DS:[SI] ;GET POINTER TO NEXT DEVICE + MOV WORD PTR CS:[ENTRY_POINT],AX ;AND SAVE IT + + MOV WORD PTR DS:[SI],CX ;LINK IN THE DRIVER + MOV WORD PTR DS:[SI+2],DX +ENDDEV: + POP SI + POP ES + INC AX ;AX = FFFF (no more devs if YES)? + JZ COFFJ3 + inc cs:MultDeviceFlag ;AN001; Possibly multiple device driver. + JMP GOODLD ;OTHERWISE PRETEND WE LOADED IT IN +COFFJ3: mov cs:MultDeviceFlag, 0 ;AN001; Reset the flag + JMP COFF + +Bad_BPB_Size_Sector: + POP SI + POP ES + MOV DX,OFFSET BADSIZ_PRE +; MOV BX,OFFSET BADSIZ_POST + mov bx, offset CRLFM ;AN???; + invoke PRNERR + test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip2_ResetMEMHI ;AN004; then do not + dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip2_ResetMEMHI: + JMP COFF + + +;------------------------------------------------------------------------------ +; Country command +; J.K. The syntax is: +; COUNTRY=country id {,codepage {,path}} +; COUNTRY=country id {,,path} :Default CODEPAGE ID in DOS +;------------------------------------------------------------------------------ +TRYQ: + CMP AH,'Q' + JZ TRYQ_CONT + JMP TRYF +TRYQ_CONT: + +; invoke GETNUM +; JZ TryQBad ; 0 is never a valid code, or number is +; ; bad +; MOV BX,AX ; Country code in BX +; +; ;J.K. 5/26/86 +; MOV DX,0 ; assume no code page id +; +; invoke skip_delim ;skip the delimeters after the first num +; jc TryQ_Def_File ;no more characters left? then use default file +; cmp al, CR ; +; je TryQ_Def_File +; cmp al, LF +; jne TRYQ_YES_EXTENDED +; inc [COUNT] ;This is for NEWLINE routine in COFF. +; dec [CHRPTR] +;COFFJ41: +; JMP TryQ_Def_File ;O.K. no code page, no path specified. Use default path. +; +;TRYQ_YES_EXTENDED: +; cmp al, ',' ;was the second comma? +; jne TryQ_GETNUM +; invoke skip_delim ;Yes, skip ',' and other possible delim +; jmp short TRYQ_PATH ;and No code page id entered. +;TRYQ_GETNUM: +; invoke GETNUM +; jc TryQBadCOM ;"Country=xxx,path" will not be accepted. +;; jc TRYQ_PATH ;Codepage is not specified. No code page. +;; ;At this point, AL already contain the +;; ;first char of the PATH. +; jz TryQBad ;codepage=0 entered. Error +; mov DX, AX ;save code page in DX +; invoke skip_delim ;move CHRPTR to the path string +; jc TryQ_Def_File ;no more char? then use default filename +; cmp al, CR +; je TryQ_Def_File +; cmp al, LF +; jne TryQ_PATH ;path entered. +; inc [COUNT] +; dec [CHRPTR] +;TryQ_Def_File: +; push dx ;save code page +; mov cs:CNTRY_DRV, 0 ;flag that the default path has been used!!! +; mov dx, offset CNTRY_ROOT ;the default path +; jmp TRYQ_OPEN +; +;TryQBad: ;"Invalid country code or code page" +; STC +; MOV DX,OFFSET BADCOUNTRY +; jmp TryQChkErr +; +;TryQBadCOM: ;Error in COUNTRY command +; STC +; MOV DX,OFFSET BADCOUNTRYCOM +; jmp TryQChkErr +; +;TRYQ_PATH: ;DS - sysinitseg, ES - CONFBOT, +; mov CX, [COUNT] ;AL - the first char of path +; inc CX ;BX - country id, DX - codepage id, 0 = No code page +; mov DI, SI +;TRYQ_PATH_LOOP: ;find the end of path to put 0 after that. +; mov AL, byte ptr ES:[DI] +; call delim +; jz TRYQ_PATH_END +; cmp al, 13 +; jz TRYQ_PATH_END +; inc DI +; jmp short TRYQ_PATH_LOOP +;TryQBad_Brg:jmp short TryQBad +;TRYQ_PATH_END: +; mov es:byte ptr [di], 0 ;make it a ASCIIZ string. (Organize did not handle this string) +; push ds ;switch ds,es +; push es +; pop ds +; pop es +; +; mov di, offset CNTRY_DRV ;move the user specified path to CNTRY_DRV +; call Move_ASCIIZ +; +; push ds ;restore ds,es +; push es +; pop ds +; pop es +; +;; call Set_Country_Path ;set CNTRY_DRV +; +; push dx ;save DX +; mov dx, offset CNTRY_DRV ;Now DS:DX -> CNTRY_DRV + + mov Cntry_Drv, 0 ;AN000; Reset the drive,path to default value. + mov P_Code_Page,0 ;AN000; + mov di, offset Cntry_Parms ;AN000; + xor cx,cx ;AN000; + mov dx,cx ;AN000; +; $SEARCH ;AN000; +$$DO49: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse error, check the error code and + JNC $$IF49 + call Cntry_Error ;AN000; Show message and end the serach loop. + mov P_Cntry_Code, -1 ;AN000; Signals that parse error. +; $ORELSE ;AN000; + JMP SHORT $$SR49 +$$IF49: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $SEARCH LOOP + JE $$EN49 + cmp Result_Val.$P_TYPE, $P_NUMBER ;AN000; Numeric? +; $IF E ;AN000; + JNE $$IF53 + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF54 + mov P_Cntry_Code, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN54 +$$IF54: + mov P_Code_Page, ax ;AN000; +; $ENDIF ;AN000; +$$EN54: +; $ELSE ;AN000; Path entered. + JMP SHORT $$EN53 +$$IF53: + push ds ;AN000; + push es ;AN000; + push si ;AN000; + push di ;AN000; + push cs ;AN000; + pop es ;AN000; + lds si, RV_Dword ;AN000; Move the path to known place. + mov di, offset CNTRY_Drv ;AN000; + call Move_ASCIIZ ;AN000; + pop di ;AN000; + pop si ;AN000; + pop es ;AN000; + pop ds ;AN000; +; $ENDIF ;AN000; +$$EN53: +; $ENDLOOP + JMP SHORT $$DO49 +$$EN49: +; $ENDSRCH ;AN000; +$$SR49: + cmp P_Cntry_Code, -1 ;AN000; Had a parse error? + jne TRYQ_OPEN ;AN000; + jmp Coff ;AN000; + +TryQBad: ;"Invalid country code or code page" + STC + MOV DX,OFFSET BADCOUNTRY + jmp TryQChkErr + +TRYQ_OPEN: + cmp CNTRY_Drv, 0 ;AC000; + je TRYQ_Def ;AC000; + mov dx, offset CNTRY_Drv ;AC000; + jmp TryQ_Openit ;AC000; +TRYQ_Def: ;AC000; + mov dx, offset CNTRY_Root ;AC000; +TryQ_Openit: + mov ax, 3d00h ;open a file + stc + int 21h + jc TryQFileBad ;open failure + + mov cs:CntryFileHandle, ax ;save file handle + mov bx, ax + mov ax, cs:P_Cntry_Code ;AN000; + mov dx, cs:P_Code_Page ;AN000; Now, AX=country id, bx=filehandle +; xchg ax, bx ;now, AX = country id, BX = file handle + mov cx, cs:[MEMHI] + add cx, 128 ;I need 2K buffer to handle COUNTRY.SYS + cmp cx, cs:[ALLOCLIM] + ja TryQMemory ;cannot allocate the buffer for country.sys + + mov si, offset CNTRY_DRV ;DS:SI -> CNTRY_DRV + cmp byte ptr [si],0 ;default path? + jne TRYQ_Set_for_DOS + inc si + inc si ;DS:SI -> CNTRY_ROOT +TRYQ_Set_for_DOS: + les di, cs:SYSI_Country ;ES:DI -> country info tab in DOS + push di ;save di + add di, ccPath_CountrySys + call MOVE_ASCIIZ ;Set the path to COUNTRY.SYS in DOS. + pop di ;ES:DI -> country info tab again. + mov cx, cs:[MEMHI] + mov ds, cx + xor si, si ;DS:SI -> 2K buffer to be used. + call SetDOSCountryInfo ;now do the job!!! + jnc TryQchkERR ;read error or could not find country,code page combination + cmp cx, -1 ;Could not find matching country_id,code page? + je TryQBad ;then "Invalid country code or code page" +TryQFileBad: + push cs ;AN000; + pop es ;AN000; + cmp cs:CNTRY_DRV,0 ;Is the default file used? + je TryQDefBad +; mov si, cs:[CONFBOT] +; mov es, si +; mov si, cs:[CHRPTR] +; dec si ;ES:SI -> path in CONFBOT + mov si, offset CNTRY_Drv + jmp short TryQBADLOAD +TryQDefBad: ;Default file has been used. +; push cs +; pop es + mov si, offset CNTRY_ROOT ;ES:SI -> \COUNTRY.SYS in SYSINIT_SEG +TryQBADLOAD: + call BADLOAD ;DS will be restored to SYSINIT_SEG + mov cx, cs:[CONFBOT] + mov es, cx ;Restore ES -> CONFBOT. + jmp short CoffJ4 +TryQMemory: + MOV DX,OFFSET INSUFMEMORY +TryQChkErr: + mov cx, cs:[CONFBOT] + mov es, cx ;restore ES -> CONFBOT seg + push cs + pop ds ;retore DS to SYSINIT_SEG + jnc CoffJ4 ;if no error, then exit + invoke PRINT ;else show error message + call Error_Line ;AN000; +CoffJ4: + mov bx, CntryFileHandle + mov ah, 3eh + int 21h ;close a file. Don't care even if it fails. + JMP COFF + +Cntry_Error proc near +;Function: Show "Invalid country code or code page" messages, or +; "Error in COUNTRY command" depending on the error code +; in AX returned by SYSPARSE; +;In: AX - error code +; DS - Sysinitseg +; ES - CONFBOT +;Out: Show message. DX destroyed. + + cmp ax, $P_OUT_OF_RANGE +; $IF E + JNE $$IF61 + mov dx, offset BadCountry ;"Invalid country code or code page" +; $ELSE + JMP SHORT $$EN61 +$$IF61: + mov dx, offset BadCountryCom ;"Error in CONTRY command" +; $ENDIF +$$EN61: + invoke Print + call Error_Line + ret +Cntry_Error endp + +;------------------------------------------------------------------------------ +; Files command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of FILES= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Variable FILES set. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to FILES_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; Files = Result_Val.$P_Picked_Val * +; else * +; Error Exit; * +; }; * +; }; * +; * +;******************************************************************************* +TRYF: + CMP AH,'F' + JNZ TRYL + +; invoke GETNUM +; CMP AX,5 ;j.k. change it to 8!!!!!!!! +; JB TryFBad ; Gotta have at least 5 +; CMP AX,256 +; JAE TryFBad ; Has to be a byte +; MOV [FILES],AL +;CoffJ5: JMP COFF +;TryFBad:JMP BadOp + + mov di, offset Files_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO64: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF64 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR64 +$$IF64: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN64 + mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; + mov P_Files, al ;AN000; Save it temporarily +; $ENDLOOP ;AN000; + JMP SHORT $$DO64 +$$EN64: + mov al, P_Files ;AN000; + mov Files, al ;AN000; No error. Really set the value now. +; $ENDSRCH ;AN000; +$$SR64: + jmp Coff + +;------------------------------------------------------------------------------ +; LastDrive command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of LASTDRIVE= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variable NUM_CDS. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to LDRV_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; Set NUM_CDS to the returned value; * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; }; * +; * +;******************************************************************************* +TRYL: + CMP AH,'L' + JNZ TRYP + +; OR AL,020h +; SUB AL,'a' +; JB TryLBad +; INC AL +; CMP AL,26 ; a-z are allowed +; JA TryLBad +; MOV [NUM_CDS],AL +;CoffJ6: JMP COFF +;TryLBad:JMP BadOp + + mov di, offset LDRV_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO70: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF70 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR70 +$$IF70: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN70 + mov al, RV_Byte ;AN000; Pick up the drive number + mov P_Ldrv, al ;AN000; Save it temporarily +; $ENDLOOP ;AN000; + JMP SHORT $$DO70 +$$EN70: + mov al, P_Ldrv ;AN000; +; sub al, 'A' ;AN000; Convert it to drive number +; inc al ;AN000; make it to be a number of drives. + mov Num_CDS, al ;AN000; No error. Really set the value now. +; $ENDSRCH ;AN000; +$$SR70: + jmp Coff + + +;------------------------------------------------------------------------------- +; Setting Drive Parameters +;------------------------------------------------------------------------------- +TRYP: + CMP AH,'P' + JNZ TRYK + invoke PARSELINE + JC TryPBad + invoke SETPARMS + INVOKE DIDDLEBACK + jc TryPBad + JMP COFF +TryPBad:jmp Badop +;------------------------------------------------------------------------------- +; Setting Internal Stack Parameters +; STACKS=M,N where +; M is the number of stacks (range 8 to 64, default 9) +; N is the stack size (range 32 to 512 bytes, default 128) +; J.K. 5/5/86: STACKS=0,0 implies no stack installation. +; Any combinations that are not within the specified limits will +; result in "Unrecognized command" error. +;------------------------------------------------------------------------------- +;******************************************************************************* +; * +; Function: Parse the parameters of STACKS= command. * +; The minimum value for "number of stacks" and "stack size" is * +; 8 and 32 each. In the definition of SYSPARSE value list, they * +; are set to 0. This is for accepting the exceptional case of * +; STACKS=0,0 case (,which means do not install the stack.) * +; So, after SYSPARSE is done, we have to check if the entered * +; values (STACK_COUNT, STACK_SIZE) are within the actual range, * +; (or if "0,0" pair has been entered.) * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variables STACK_COUNT, STACK_SIZE. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to STKS_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; { if (CX == 1) then /* first positional = stack count */ * +; P_Stack_Count = Result_Val.$P_Picked_Val; * +; if (CX == 2) then /* second positional = stack size */ * +; P_Stack_Size = Result_Val.$P_Picked_Val; * +; } * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; Here check P_STACK_COUNT,P_STACK_SIZE if it meets the condition; * +; If O.K., then set Stack_Count, Stack_Size; * +; else Error_Exit; * +; }; * +;******************************************************************************* +TRYK: + CMP AH,'K' + JE Do_TryK + jmp TRYS + + IF STACKSW + +; MOV SepChr,',' +; INVOKE GetNum ; Get number of stacks +; MOV SepChr,0 +; cmp ax, 0 ;J.K. 5/5/86 +; je TRYK_0 ;J.K. Let's accept 0. +; CMP AX, MinCount ; 8 <= Number of Stacks <= 64 +; JB TryKBad +; CMP AX, MaxCount +; JA TryKBad +;TRYK_0: +; MOV [STACK_COUNT], AX +; +; Skip delimiters after the first number. +; +; invoke Skip_delim ;J.K. +; JC TryKBad +; +; INVOKE GetNum ; Get size of individual stack +; JC TryKBad ; Number bad +; +; cmp ax, 0 ;J.K. 5/5/86 +; je TRYK_SIZE0 ;J.K. 5/5/86. Accept 0 +; +; CMP AX, MinSize ; 32 <= Stack Size <= 512 +; JB TryKBad +; CMP AX, MaxSize +; JA TryKBad +;TRYK_SIZE0: +; MOV [STACK_SIZE], AX +; cmp ax,0 +; je TRYK_BOTH0 +;TRYK_OK: +; mov word ptr [stack_addr], -1 ;set the flag that the user entered stacks= command. +; JMP COFF +;TRYK_BOTH0: +; cmp [STACK_COUNT],0 ;stack_size = 0. Stack_Count = 0 too? +; je TRYK_OK ;yes. accepted. +;TryKBad: +; MOV DX, OFFSET BADSTACK ;J.K. 5/26/86 "Invalid stack parameter" +; invoke PRINT +; JMP COFF + +Do_TryK: + mov di, offset STKS_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO76: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF76 + mov dx, offset BadStack ;AN000; "Invalid stack parameter" + call Print ;AN000; and Show messages and end the search loop. + call Error_Line ;AN006; +; $ORELSE ;AN000; + JMP SHORT $$SR76 +$$IF76: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN76 + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF80 + mov P_Stack_Count, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN80 +$$IF80: + mov P_Stack_Size, ax ;AN000; +; $ENDIF ;AN000; +$$EN80: +; $ENDLOOP ;AN000; + JMP SHORT $$DO76 +$$EN76: + cmp P_Stack_Count, 0 ;AN000; +; $IF NE ;AN000; + JE $$IF84 + cmp P_Stack_Count, MINCOUNT ;AN000; +; $IF B,OR ;AN000; + JB $$LL85 + cmp P_Stack_Size, MINSIZE ;AN000; +; $IF B ;AN000; + JNB $$IF85 +$$LL85: + mov P_Stack_Count, -1 ;AN000; Invalid +; $ENDIF ;AN000; +$$IF85: +; $ELSE ;AN000; + JMP SHORT $$EN84 +$$IF84: + cmp P_Stack_Size, 0 ;AN000; +; $IF NE ;AN000; + JE $$IF88 + mov P_Stack_Count, -1 ;AN000; Invalid +; $ENDIF ;AN000; +$$IF88: +; $ENDIF ;AN000; +$$EN84: + cmp P_Stack_Count, -1 ;AN000; Invalid? +; $IF E ;AN000; + JNE $$IF91 + mov Stack_Count, DEFAULTCOUNT ;AN000;Reset to default value. + mov Stack_Size, DEFAULTSIZE ;AN000; + mov word ptr STACK_ADDR, 0 ;AN000; + mov dx, offset BadStack ;AN000; + call Print ;AN000; + call Error_Line ;AN006; +; $ELSE ;AN000; + JMP SHORT $$EN91 +$$IF91: + mov ax, P_Stack_Count ;AN000; + mov Stack_Count, ax ;AN000; + mov ax, P_Stack_Size ;AN000; + mov Stack_Size, ax ;AN000; + mov word ptr Stack_Addr, -1 ;AN000;STACKS= been accepted. +; $ENDIF ;AN000; +$$EN91: +; $ENDSRCH ;AN000; +$$SR76: + jmp Coff + ENDIF +;------------------------------------------------------------------------------ +; Switch command ;No longer supported. +;------------------------------------------------------------------------------ +;TRYW: +; CMP AH,'W' +; JNZ TRYA +; JMP BadOp ; no longer implemented +; MOV DL,AL +; MOV AX,(CHAR_OPER SHL 8) OR 1 ;SET SWITCH CHARACTER +; MOV [COMMAND_LINE+1],DL +; INT 21H +; JMP COFF +;------------------------------------------------------------------------------ +; Availdev command ;No longer supported. +;------------------------------------------------------------------------------ +;TRYA: +; CMP AH,'A' +; JNZ TRYS +; JMP BadOp ; NO LONGER IMPLEMENTED +; CMP AL,'F' ;FIRST LETTER OF "FALSE" +; JNZ COFFJ7 +; MOV AX,(CHAR_OPER SHL 8) OR 3 ;TURN ON "/DEV" PREFIX +; XOR DL,DL +; INT 21H +;COFFJ7: JMP COFF + +;------------------------------------------------------------------------------ +; shell command +;------------------------------------------------------------------------------ +TRYS: + CMP AH,'S' + JNZ TRYX + MOV [COMMAND_LINE+1],0 + MOV DI,OFFSET COMMND + 1 + MOV [DI-1],AL +STORESHELL: + CALL GETCHR + OR AL,AL + JZ GETSHPARMS + CMP AL," " + JB ENDSH + MOV [DI],AL + INC DI + JMP STORESHELL + +ENDSH: + MOV BYTE PTR [DI],0 + CALL GETCHR + CMP AL,LF + JNZ CONV + CALL GETCHR +CONV: JMP CONFLP + +GETSHPARMS: + MOV BYTE PTR [DI],0 + MOV DI,OFFSET COMMAND_LINE+1 +PARMLOOP: + CALL GETCHR + CMP AL," " + JB ENDSH + MOV [DI],AL + INC DI + JMP PARMLOOP + +;------------------------------------------------------------------------------ +; FCBS Command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of FCBS= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variables FCBS, KEEP. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to FCBS_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { SYSPARSE; * +; if (no error) then * +; { if (CX == 1) then /* first positional = FCBS */ * +; FCBS = Result_Val.$P_Picked_Val; * +; if (CX == 2) then /* second positional = KEEP */ * +; KEEP = Result_Val.$P_Picked_Val; * +; } * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; }; * +;******************************************************************************* +TRYX: + CMP AH,'X' + JNZ TRYY +; invoke GETNUM +; JZ TryXBad ; gotta have at least one +; CMP AX,256 +; JAE TryXBad ; Can't be more than 8 bits worth +; MOV [FCBS],AL +; +; Skip delimiters after the first number including "," +; +; invoke Skip_delim ;J.K. +; jc tryxbad +; invoke GetNum +; JC TryXBad ; Number bad (Zero is OK here) +; CMP AX,256 +; JAE TryXBad +; CMP AL,FCBS +; JA TryXBad +; MOV Keep,AL +; JMP COFF +;TryXBad:JMP BadOp + + mov di, offset FCBS_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO95: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF95 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR95 +$$IF95: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN95 + mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; The first positional? +; $IF E ;AN000; + JNE $$IF99 + mov P_Fcbs, al ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN99 +$$IF99: + mov P_Keep, al ;AN000; +; $ENDIF ;AN000; +$$EN99: +; $ENDLOOP ;AN000; + JMP SHORT $$DO95 +$$EN95: + mov al, P_Fcbs ;AN005;make sure P_Fcbs >= P_Keep + cmp al, P_Keep ;AN005; +; $IF B ;AN005; + JNB $$IF103 +; call Badop_p ;AN005; + call Badparm_p ;AN011;show "Bad parameter -" msg. + mov P_Keep, 0 ;AN005; +; $ELSE ;AN005; + JMP SHORT $$EN103 +$$IF103: + mov Fcbs, al ;AN000; No error. Really set the value now. + mov al, P_Keep ;AN000; + mov Keep, al ;AN000; +; $ENDIF ;AN005; +$$EN103: +; $ENDSRCH ;AN000; +$$SR95: + jmp Coff + +;------------------------------------------------------------------------------ +; Comment= Do nothing. Just decrese CHRPTR, and increase COUNT for correct +; line number +;------------------------------------------------------------------------------ +TRYY: ;AN000; + cmp ah, 'Y' ;AN000; + jne Try0 ;AN000; +DoNothing: + dec CHRPTR ;AN000; + inc COUNT ;AN000; + jmp COFF ;AN000; + +;------------------------------------------------------------------------------ +; REM command +;------------------------------------------------------------------------------ +Try0: ;AN003;do nothing with this line. + cmp ah, '0' ;AN003; + je DoNothing ;AN003; + +;------------------------------------------------------------------------------ +; SWITCHES command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the option switches specified. * +; Note - This command is intended for the future use also. When we need to * +; to set system data flag, use this command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; P_Swit_K set if /K option chosen. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to Swit_Parms; /*Parse control definition*/ * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; if (Result_Val.$P_SYNONYM_ptr == Swit_K) then * +; P_Swit_K = 1 * +; endif * +; else {Show Error message;Error Exit} * +; }; * +; }; * +; * +;******************************************************************************* + + cmp ah, '1' ;AN019;Switches= command entered? + jne Tryz ;AN019; + + mov di, offset Swit_Parms ;AN019; + xor cx, cx ;AN019; + mov dx, cx ;AN019; + +; $SEARCH ;AN019; +$$DO107: + call Sysinit_Parse ;AN019; +; $EXITIF C ;AN019; Parse Error, + JNC $$IF107 + call Badparm_p ;AN019; and Show messages and end the search loop. +; $ORELSE ;AN019; + JMP SHORT $$SR107 +$$IF107: + cmp ax, $P_RC_EOL ;AN019; End of Line? +; $LEAVE E ;AN019; then jmp to $Endloop for semantic check. + JE $$EN107 + cmp Result_Val.$P_SYNONYM_PTR, offset Swit_K ;AN019; +; $IF E ;AN019; + JNE $$IF111 + mov P_Swit_K, 1 ;AN019; set the flag +; $ENDIF ;AN019; +$$IF111: +; $ENDLOOP ;AN019; + JMP SHORT $$DO107 +$$EN107: + cmp P_Swit_K, 1 ;AN019;If /K entered, + push ds ;AN019; + mov ax, Code ;AN019; + mov ds, ax ;AN019; + assume ds:Code ;AN019; +; $IF E ;AN019; + JNE $$IF114 + mov KEYRD_Func, 0 ;AN019;Use the conventional keyboard functions + mov KEYSTS_Func, 1 ;AN019; +; $ENDIF ;AN019; +$$IF114: + pop ds ;AN019; + assume ds:SYSINITSEG ;AN019; +; $ENDSRCH ;AN019; +$$SR107: + jmp Coff ;AN019; + +;------------------------------------------------------------------------------ +; Bogus command +;------------------------------------------------------------------------------ +TRYZ: + cmp ah, 0FFh ;AN029; + je TryFF ;AN029; + dec CHRPTR + inc COUNT + JMP BADOP + +;------------------------------------------------------------------------------ +; Null command +;------------------------------------------------------------------------------ +TryFF: ;AN029;Skip this command. + jmp DoNothing ;AN029; + +GETCHR: + PUSH CX + MOV CX,COUNT + JCXZ NOCHAR + MOV SI,CHRPTR + MOV AL,ES:[SI] + DEC COUNT + INC CHRPTR + CLC +GET_RET: + POP CX + return +NOCHAR: STC + JMP SHORT GET_RET + +Incorrect_Order proc near ;AN000; +;Show "Incorrect order in CONFIG.SYS ..." message. + mov dx, offset BADORDER ;AN000; + call print ;AN000; + call ShowLineNum ;AN000; + ret ;AN000; +Incorrect_Order endp ;AN000; +; + public Error_Line +Error_Line proc near ;AN000; +;Show "Error in CONFIG.SYS ..." message. + push cs ;AN000; + pop ds ;AN000; + mov dx, offset ErrorCmd ;AN000; + call print ;AN000; + call ShowLineNum ;AN000; + ret ;AN000; +Error_Line endp ;AN000; +; +ShowLineNum proc near ;AN000; +;J.K. Convert the binary LineCount to Decimal ASCII string in ShowCount +;and Display Showcount at the current curser position. +;In.) LineCount +; +;Out) the number is printed. + push es ;AN000; + push ds ;AN000; + push di ;AN000; + + push cs ;AN000; + pop es ;AN000; es=cs + push cs ;AN000; + pop ds ;AN000; + +; mov ax, ' ' +; mov di, offset ShowCount ;clean it up. +; stosw +; stosw +; stosb ;lenght of ShowCount is 5. +; dec di ;let DI points to the least significant ASCII field. + + mov di, offset ShowCount+4 ;AN000; DI -> the least significant decimal field. + mov cx, 10 ;AN000; decimal devide factor + mov ax, cs:LineCount ;AN000; +SLN_Loop: ;AN000; + cmp ax, 10 ;AN000; < 10? + jb SLN_Last ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; + or dl, 30h ;AN000; add "0" (= 30h) to make it an ascii. + mov [di],dl ;AN000; + dec di ;AN000; + jmp SLN_Loop ;AN000; +SLN_Last: ;AN000; + or al, 30h ;AN000; + mov [di],al ;AN000; + mov dx, di ;AN000; + call print ;AN000; show it. + pop di ;AN000; + pop ds ;AN000; + pop es ;AN000; + ret ;AN000; +ShowLineNum endp ;AN000; + + +CallIFS proc near ;AN000; +;******************************************************************************* +; Function: Interface to IFS call. This procedure will call IFS_CALL@ * +; * +; Input : * +; Entry_Point - Segment:Offset of loaded IFS. * +; BX = IFS_CALL@ (offset of IFS_CALL@ from the IFS header) * +; ES = Segment of IFS request header * +; IFS_Packet - IFS Request packet * +; * +; Output: Nothing * +;******************************************************************************* + push ax ;AN000; + mov ds, word ptr cs:[Entry_Point+2] ;AN000; + add bx, word ptr cs:[Entry_Point] ;AN000; DS:[BX] = Real IFS_CALL@ addr. + mov ax, ds:[bx] ;AN000; save it + push word ptr cs:[Entry_Point] ;AN000; save Entry point offset + mov word ptr cs:[Entry_Point], ax ;AN000; set for the call + mov bx, offset IFS_RH ;AN000; Now, ES:BX -> Request packet + call cs:[Entry_Point] ;AN000; Far call + pop word ptr cs:[Entry_Point] ;AN000; Restore Entry point offset + pop ax ;AN000; + ret ;AN000; +CallIFS endp ;AN000; + + +Set_DevMark proc near ;AN004; +;******************************************************************************* +; Function: Set a paragraph of informations infront of a Device file or * +; an IFS file to be loaded for MEM command. * +; The structure is: * +; DEVMARK_ID byte "D" for device, "I" for IFS * +; DEVMARK_SIZE size in para for the device loaded * +; DEVMARK_FILENAME 11 bytes. Filename * +; * +; Input : * +; [MEMHI] = address to set up DEVMARK. * +; [MEMLO] = 0 * +; ES:SI -> pointer to [drive][path]filename,0 * +; [IFS_Flag] = IS_IFS bit set if IFS= command. * +; * +; Output: DEVMARK_ID, DEVMARK_FILENAME set * +; cs:[DevMark_addr] set. * +; AX, CX register destroyed. * +;******************************************************************************* + push ds ;AN004; + push si ;AN004; + push es ;AN004; + push di ;AN004; + + mov di, cs:[MEMHI] ;AN004; + mov ds, di ;AN004; + assume ds:nothing ;AN004; + mov [DevMark_Addr], di ;AN004; save the DEVMARK address for the future. + test [IFS_Flag], IS_IFS ;AN004; + jnz SDVMK_IFS ;AN004; + mov al, DEVMARK_DEVICE ;AN004; ='D' + jmp short SDVMK_ID ;AN004; +SDVMK_IFS: + mov al, DEVMARK_IFS ;AN004; ='I' +SDVMK_ID: ;AN004; + mov ds:[DEVMARK_ID], al ;AN004; + inc di ;AN008; + mov ds:[DEVMARK_SEG], di ;AN008; + xor al,al ;AN004; + push si ;AN004; + pop di ;AN004; now es:si = es:di = [path]filename,0 + mov cx, 128 ;AN004; Maximum 128 char + repnz scasb ;AN004; find 0 + dec di ;AN020; Now es:di-> 0 +SDVMK_Backward: ;AN004; find the pointer to the start of the filename. + mov al, byte ptr es:[di] ;AN004;;AN020;We do this by check es:di backward until + cmp al, '\' ;AN004;;AN020; DI = SI or DI -> '\' or DI -> ':'. + je SDVMK_GotFile ;AN004;;AN020; + cmp al, ':' ;AN004; + je SDVMK_GotFile ;AN004; + cmp di, si ;AN004; + je SDVMK_FilePtr ;AN004; + dec di ;AN004; + jmp SDVMK_BackWard ;AN004; +SDVMK_GotFile: ;AN004; + inc di ;AN004; +SDVMK_FilePtr: ;AN004; now es:di -> start of file name + push di ;AN004; + pop si ;AN004; save di to si. + push ds ;AN004; switch es, ds + push es ;AN004; + pop ds ;AN004; + pop es ;AN004; now, ds:si -> start of filename + mov di, DEVMARK_FILENAME ;AN004; + push di ;AN004; + mov al, ' ' ;AN004; + mov cx, 8 ;AN004; + rep stosb ;AN004; Clean up Memory. + pop di ;AN004; + mov cx, 8 ;AN004; Max 8 char. only +SDVMK_Loop: ;AN004; + lodsb ;AN004; + cmp al, '.' ;AN004; + je SDVMK_Done ;AN004; + cmp al, 0 ;AN004; + je SDVMK_Done ;AN004; + stosb ;AN004; + loop SDVMK_Loop ;AN004; +SDVMK_Done: ;AN004; + pop di ;AN004; + pop es ;AN004; + pop si ;AN004; + pop ds ;AN004; + ret ;AN004; +Set_DevMark endp ;AN004; + +Chk_XMAEM proc near ;AN029; +;Function: Check XMAEM.SYS file name. +;In: ES:SI -> path, filename, 0 +;out: if XMAEM.SYS, then zero flag set. + + push es ;AN029; + push si ;AN029; + push ds ;AN029; + push di ;AN029; + push cx ;AN029; + mov di, si ;AN029;save current starting pointer +CX_Cmp: ;AN029; + cmp byte ptr es:[si], 0 ;AN029; + je CX_Endfile ;AN029; + inc si ;AN029; + jmp CX_Cmp ;AN029; +CX_Endfile: ;AN029; + dec si ;AN029; + cmp byte ptr es:[si], '\' ;AN029; + je CX_Got_Tail ;AN029; + cmp byte ptr es:[si], ':' ;AN029; + je CX_Got_Tail ;AN029; + cmp di, si ;AN029; + je CX_Got_Tail0 ;AN029; + jmp CX_Endfile ;AN029; +CX_Got_Tail: ;AN029; + inc si ;AN029; +CX_Got_Tail0: ;AN029; + push cs ;AN029; + pop ds ;AN029; + push si ;AN029; + pop di ;AN029;now es:di -> filename,0 + mov cx, 9 ;AN029; + mov si, offset XMAEM_File ;AN029;ds:si -> XMAEM.SYS,0 + repe cmpsb ;AN029; +CX_Ret: ;AN029; + pop cx ;AN029; + pop di ;AN029; + pop ds ;AN029; + pop si ;AN029; + pop es ;AN029; + ret ;AN029; +Chk_XMAEM endp + +;Chk_IBMCACHE proc near ;AN024;AN026; Don't need this any more. + ; IBMDOS is going to handle this through 4Bh call. +;Function: IBMCACHE.SYS does not handle a DOS version 4.0 or above. +; So, this procedure will check if the device driver is IBMCACHE.SYS. +; If it is, through new INT 2fh interface "Set/Restore DOS version" +; AX=122Fh +; DX= 0 ; reset +; otherwise ; DH = minor version, DL = major version +; INT 2fh +;In: ES:SI -> path, filename, 0 +;out: if IBMCACHE.SYS, then DOS version changed to 4.00 temporarily. +; Reset_Dos_Version proc will later reset it back to current DOS version 4.0. + +; push es ;AN024; +; push si ;AN024; +; push ds ;AN024; +; push di ;AN024; +; push cx ;AN024; +; mov di, si ;AN024;save current starting pointer +;CIC_Cmp: ;AN024; +; cmp byte ptr es:[si], 0 ;AN024; +; je CIC_Endfile ;AN024; +; inc si ;AN024; +; jmp CIC_Cmp ;AN024; +;CIC_Endfile: ;AN024; +; dec si ;AN024; +; cmp byte ptr es:[si], '\' ;AN024; +; je CIC_Got_Tail ;AN024; +; cmp byte ptr es:[si], ':' ;AN024; +; je CIC_Got_Tail ;AN024; +; cmp di, si ;AN024; +; je CIC_Got_Tail0 ;AN024; +; jmp CIC_Endfile ;AN024; +;CIC_Got_Tail: ;AN024; +; inc si ;AN024; +;CIC_Got_Tail0: ;AN024; +; push cs ;AN024; +; pop ds ;AN024; +; push si ;AN024; +; pop di ;AN024;now es:di -> filename,0 +; mov cx, 12 ;AN024; +; mov si, offset IBMCACHE_File ;AN024;ds:si -> IBMCACHE.SYS,0 +; repe cmpsb ;AN024; +; jnz CIC_ret ;AN024; +; mov ax, 122Fh ;AN024;Change DOS version to +; mov dx, 2803h ;AN024; DOS 3.4 temporarily. +; int 2fh ;AN024; +;CIC_Ret: ;AN024; +; pop cx ;AN024; +; pop di ;AN024; +; pop ds ;AN024; +; pop si ;AN024; +; pop es ;AN024; +; ret ;AN024; +;Chk_IBMCACHE endp +; + +Reset_DOS_Version proc near ;AN024; +;Function: issue AX=122Fh, DX=0, INT 2fh to restore the DOS version. + push ax ;AN024; + push dx ;AN024; + mov ax, 122Fh ;AN024; + mov dx, 0 ;AN024; + int 2fh ;AN024; + pop dx ;AN024; + pop ax ;AN024; + ret ;AN024; +Reset_DOS_Version endp + + +;Int 2F EMS handler + Int 67h handler for EMS +;========================================================================= +; Int_2F_EMS - This routine provides support for VDISK, +; FASTOPEN, and BUFFERS to determine the physical +; EMS pages available for their usage. +; +; Inputs : AH - Function code (18h) to return available phys. page +; DI - FEh (Signals to return useable page for VDISK & FASTOPEN) +; FFh (Signals to return useable page for BUFFERS) +; +; AL = 0 is for installation check. - J.K. +; +; Outputs : ES - Segment value for physical page +; DI - Physical Page number +; AH - Non-zero (physical page not available) +; Zero (valid physical page data returned) +; +; For installation check, AL = 0FFh for being present. - J.K. +; For the other functions, AX = 0 for successful op. +; AX = -1 for an error. +; +; Date : 5/5/88 +; Release : DOS 4.0 +;========================================================================= + +;Int_2F_Handler proc ;traps Int_2f and checks for EMS ;an000; dms; + +EMS_STUB_START label byte ;AN030;J.K. +;Dummy DEVICE HEADER for other dummy ;AN031; Symphony assumes int 67h handler seg as a device driver! + DD -1 ;AN031;becomes pointer to next device header + DW 0C040H ;AN031;attribute (character device) + DW 0000 ;AN031;pointer to harzard area. System will hang. + DW 0000 ;AN031;pointer to harzard area. System will hang. + DB 'EMMXXXX0' ;AN031;device name + +INTV2F equ $-EMS_STUB_START ;AN030;J.K.pointer to old 2Fh handler ;an000; dms; +IntV2FO DW ? ;AN030;;offset ;an000; dms; +IntV2FS DW ? ;AN030;;segment ;an000; dms; + +OLDINT67_VECTOR equ $-EMS_STUB_START ;AN030;J.K. +OldInt67 dd ? ;AN030;; save pointer to old INT 67 handler here + +IF BUFFERFLAG + +LOCKFLAG equ $-EMS_STUB_START +LOCK_FLAG db ? + +ELSE + +EMSPAGE_CNT equ $-EMS_STUB_START ;AN030;J.K. +EMSPageCount dw ? ;AN030;; save count of EMS mappable pages here + +EMSReservedArray_X label word ;AN030;;J.K. For initialization routine +EMSRESERVEDARRAY equ $-EMS_STUB_START ;AN030;;J.K. + dw 0ffffh,0ffffh ;AN030;; array of reserved pages + dw 0ffffh,0ffffh ;AN030;; phys_page_segment, phys_page_number * 2 entries +MappableArray_X label word ;AN030;;J.K. for initialization routine +MAPPABLEARRAY equ $-EMS_STUB_START ;AN030;;J.K. + dw 64 dup (0,0) ;AN030;; table to get addresses from old INT 67 handler + +ENDIF + ; 64 entries * 2 words +NEWEMS2F_OFF equ $-EMS_STUB_START;AN030; +Int_2F_EMS: ;AN030;;J.K. Name changed. + cmp ah,1Bh ;AN030;;AN032;2Fh trap for Mappable Phys. Add. Array ;an000; dms; + je Int_2F_EMS_MINE ;AN030;;This one we want ;an000; dms; + + jmp dword ptr cs:IntV2F ;AN030;;go to old interrupt handler ;an000; dms; + +Int_2F_EMS_MINE: ;AN030; + or al, al ;AN030;;J.K. Installation check? + jnz Int_2F_5800_Func ;AN030;;J.K. + mov al, 0FFh ;AN030;;J.K. Yes, I am here! + iret ;AN030;;J.K. + +Int_2F_5800_Func: ;AN030; + +IF BUFFERFLAG +; int 3 + cmp di, 80h + jne st_flag + mov byte ptr cs:LOCKFLAG, 0 + jmp Int_2f_5800_Good_Exit +st_flag: + cmp di, 81h + jne Int_2f_5800_Err_Exit + mov byte ptr cs:LOCKFLAG, 1 + jmp Int_2f_5800_Good_Exit +ELSE + + push si ;AN030;; ;an000; dms; + +; mov si,offset EMSReservedArray ;point to array containing pages ;an000; dms; + mov si, EMSRESERVEDARRAY ;AN030;;J.K. + + cmp di,0feh ;AN030;;VDISK or FASTOPEN request? ;an000; dms; + jne Int_2F_5800_Buff_Ck ;AN030;;no - check for buffers ;an000; dms; + + cmp word ptr cs:[si],0ffffh ;AN030;;valid entry? ;an000; dms; + je Int_2F_5800_Err_Exit ;AN030;;no - exit ;an000; dms; + + mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; + mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; + jmp Int_2F_5800_Good_Exit ;AN030;;exit routine ;an000; dms; + +Int_2F_5800_Buff_Ck: ;AN030; + + cmp di,0ffh ;AN030;;BUFFERS request? ;an000; dms; + jne Int_2F_5800_Err_Exit ;AN030;;no - exit with error ;an000; dms; + + add si,4 ;AN030;;point to second element in array ;an000; dms; + + cmp word ptr cs:[si],0ffffh ;AN034;;valid entry? ;an000; dms; + je Int_2F_5800_Err_Exit ;AN034;;no - exit ;an000; dms; + + mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; + mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; + +ENDIF + +Int_2F_5800_Good_Exit: ;AN030; + + xor ax,ax ;AN030;;signal good return ;an000; dms; + jmp Int_2F_Exit ;AN030;;exit routine ;an000; dms; + +Int_2F_5800_Err_Exit: ;AN030; + + mov ax,0ffffh ;AN030;;signal error ;an000; dms; + +Int_2F_Exit: ;AN030; + + +IF NOT BUFFERFLAG + pop si ;AN030;;restore regs ;an000; dms; +ENDIF + iret ;AN030;;return to caller ;an000; dms; + + + +;------------------------------------------------------------------- +; +; INT 67h Filter +; +; This routine filters INT 67's looking for AH=58h. When initialized, +; the original INT 67 handler is called and the mappable address array +; is changed to "reserve" two pages for DOS use. This new array is +; then returned to the calling program when INT 67 AH=58h is found. +; +; Information about the two pages "reserved" for DOS is returned +; via an unpublished INT 2Fh interface. +; +; 5/10/88 for DOS 4.0. +;------------------------------------------------------------------- + +IF NOT BUFFERFLAG + +GetMappableArray equ 58h ; INT 67 function code for Get Mappable Array +GetPageFrame equ 41h ; function code for getting the page frame address +null equ 0 ; zero value +I67Error8F equ 8fh ;AN031;; invalid sub-function error + +ENDIF + +;------------------------------------------------------------------- +NEW67_OFFSET equ $-EMS_STUB_START ;J.K. +Int67Filter: ;AN030; + +IF BUFFERFLAG +; int 3 + cmp byte ptr cs:LOCKFLAG, 1 + jne PassThru + mov ah, 80h + stc + iret +ELSE + cmp ah,GETMAPPABLEARRAY ;AN030;; is this the INT 67 call we are interested in? + jne PassThru ;AN030;; no, pass it to old INT 67 handler + ;AN030;; yes ... + cmp al,0 ;AN031;; AL=0 return count and table + je I67Fcn0 + + cmp al,1 ;AN031;; AL=1 return count only + jne I67Error ;AN031;; otherwise, error + + +; return count of mappable pages + + sti ;AN031;; turn interrupts on + + mov cx,word ptr cs:EMSPAGE_CNT ;AN031;J.K. get number of mappable pages in fake table + xor ah,ah ;AN031;; good return code + iret + +; return invalid sub-function code + +I67Error: + sti ;AN031;; turn interrupts on + mov ah,I67Error8F ;AN031;; invalid sub-function error + iret + + +I67Fcn0: ;AN031 + +; copy the fake table to user's buffer + + sti ;AN030;; turn interrupts on + + push ds ;AN030; save some regs + push di ;AN030; + push si ;AN030; + + mov cx,word ptr cs:EMSPAGE_CNT ;AN030;J.K. get number of mappable pages in fake table + shl cx,1 ;AN030;; count * 2 = number of words to copy + + push cs ;AN030;; point DS:SI to fake table + pop ds ;AN030; +; lea si,MappableArray + mov si, MAPPABLEARRAY ;AN030;;J.K. + + rep movsw ;AN030;; copy CX words from DS:SI to ES:DI + + xor ah,ah ;AN030;; good return code + mov cx,word ptr cs:EMSPAGE_CNT ;AN030;; page count returned to user in CX + + + pop si ;AN030;; restore some regs + pop di ;AN030; + pop ds ;AN030; + + iret ;AN030;; end of INT 67 filter routine + +ENDIF + +;------------------------------------------------------------------- +; +; PassThru - send request to old INT 67 handler +; +;------------------------------------------------------------------- + +PassThru: + jmp dword ptr cs:OldINT67_VECTOR ;AN030;;J.K. jump to old INT 67 handler + ; (IRET will return to calling program) + + +EMS_STUB_END label byte ;AN030; +;------------------------------------------------------------------- + +IF NOT BUFFERFLAG +;------------------------------------------------------------------- +; +; Int67FilterInit - This routine is called to initialize the INT 67 +; filter. It should be called as soon as possible after installation. +; +;------------------------------------------------------------------- + +Int67FilterInit: ;AN030; + push es ;AN030;; save caller's ES:DI + push di ;AN030; + + push cs ;AN030;; make ES:DI point to our array + pop es ;AN030; + mov di,offset MappableArray_X ;AN030; + +; call dword ptr cs:OldInt67 ; get mappable array from EMS DD + + mov ah, GetMappableArray ;AN030; + xor al,al ;AN030; + int 67h ;AN030;;J.K. + + +;------------------------ +; scan table looking for highest phys_page_number + + xor ax,ax ;AN030;; + + cmp cx,0 ;AN033;; are the any pages left? + je NoMoreEMSPages ;AN033;; no, don't bother looking any more + + call GetHighestPage ;AN030;; get highest entry from table + + mov EMSReservedArray_X+4,bx ;AN030;; phys_page_segment + mov EMSReservedArray_X+6,ax ;AN030;; phys_page_number + + cmp cx,0 ;AN033;; are the any pages left? + je NoMoreEMSPages ;AN033;; no, don't bother looking any more + + call GetHighestPage ;AN030;; get next highest entry from table + + mov EMSReservedArray_X+0,bx ;AN030;; phys_page_segment + mov EMSReservedArray_X+2,ax ;AN030;; phys_page_number + +NoMoreEMSPages: ;AN033;; + mov EMSPageCount,cx ;AN030;; save new page count for INT 67 filter + + pop di + pop es + ret ;AN030;; return to calling program + + + page +;------------------------------------------------------------------- +; +; GetHighestPage - returns highest physical page number in AX +; and segment for it in BX. A -1 means no valid page found. +; +;------------------------------------------------------------------- +GetHighestPage: + + xor ax,ax ;AN030;; zero candidate register + mov bx,ax ;AN030;; zero pointer to candidate page + + push cx ;AN030;; save count + push dx ;AN030; + push di ;AN030;; save pointer + +PageScanLoop: ;AN030; + cmp ax,ES:[di+2] ;AN030;; get phys_page_number + ja LookAtNextPage ;AN030;; this one is lower than the one we are holding + + cmp es:[di], 0a000h ; Only reserve pages in memory above 640K.. + jb LookAtNextPage ; fix for ps2emm and m20emm with motherboard + ; disabled. 7/25/88. HKN. + + mov ax,ES:[di+2] ;AN030;; this one is higher, make it new candidate + mov bx,di ;AN030;; pointer to new candidate page, used to zero + ; it later so we don't get the same one again + mov dx,cx ;AN030;; save count where we found candidate + +LookAtNextPage: ;AN030; + add di,4 ;AN030;; point to next entry in mappable table + + loop PageScanLoop ;AN030;; look at next entry + + cmp bx,null ;AN030;; did we find any pages? + jne FoundOne ;AN030;; yes, exit + + jmp ReturnError ;AN030; + +;------------------------ +FoundOne: ;AN030; + cmp ax,3 ;AN030;; could the one we found be part of a page frame + ja NotFrame ;AN030;; no, carry on + +; yes, find out if it is part of frame + + push ax ;AN030;; save physical page number + push bx ;an030;; dms; bx destroyed by call + mov ah,GetPageFrame ;AN030;; function code to get page frame ... +; call dword ptr cs:OldInt67 ; ... from the EMS DD + int 67h ;AN030;;J.K. + or ah,ah ;an030;;dms; error? + pop bx ;an030;;dms; restore bx + pop ax ;AN030;; restore phys page number + jnz NotFrame ;AN030;; no frame available, carry on + +; there is a frame, this page is part of frame, so return -1's + +ReturnError: ;AN030; + mov ax,0ffffh ;AN030;; indicate failure + mov bx,ax ;AN030;; ax and bx = -1 + + pop di ;AN030;; restore pointer + pop dx + pop cx ;AN030;; restore count + + jmp GHPExit ;AN030; + + + + +;------------------------ +; Found a page, and it is not part of a page frame, so re-pack table +; and return info. The entry we "reserve" for DOS must be removed +; from the table and the other entries moved up to repack the table. +; The count must be reduced by 1 to reflect this change. + +Notframe: ;AN030; + + mov di,bx ;AN030;; make ES:DI point to highest page table entry + + mov bx,ES:[di] ;AN030;; get segment address of page + + mov cx,dx ;AN030;; get count from candidate page + + push ax ;AN030; +PackLoop: ;AN030; + mov ax, es:[di+4] ;AN030; + mov es:[di+0], ax ;AN030; + mov ax, es:[di+6] ;AN030; + mov es:[di+2], ax ;AN030; + add di, 4 ;AN030; + loop PackLoop ;AN030;; do it until done + pop ax ;AN030; + + pop di ;AN030;; restore pointer + pop dx ;AN030; + pop cx ;AN030;; restore count + + sub cx,1 ;AN030;; reduce count by one, one less page in table now + +GHPExit: ;AN030; + + ret ;AN030;; return to caller + +ENDIF + +;========================================================================= +; EMS_Install_Check : THIS MODULE DETERMINES WHETHER OR NOT EMS IS +; INSTALLED FOR THIS SESSION. +; +; INPUTS : NONE +; +; OUTPUTS : ES:BX - FRAME ARRAY +; CY - EMS NOT AVAILABLE +; NC - EMS AVAILABLE +; +; Date : 5/6/88 +;========================================================================= + +EMS_Install_Check proc near ;AN030;; check if EMS is installed ;an000; dms; + + push ax ;AN030;; save regs ;an000; dms; + + push ds ;AN030;; save ds ;an000; dms; + xor ax,ax ;AN030;; set ax to 0 ;an000; dms; + mov ds,ax ;AN030;; set ds to 0 ;an000; dms; + cmp ds:word ptr[067h*4+0],0 ;AN030;; see if int 67h is there ;an000; dms; + pop ds ;AN030;; restore ds ;an000; dms; + je EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; + + mov ah,40h ;AN030;; Get Status function ;an000; dms; + xor al,al ;AN030;; clear al ;an000; dms; + int 67h ;AN030;; ;an000; dms; + or ah,ah ;AN030;; EMS installed? ;an000; dms; + jnz EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; + + mov ah,46h ;AN030;; Get Version number ;an000; dms; + xor al,al ;AN030;; clear al ;an000; dms; + int 67h ;AN030;; ;an000; dms; + cmp al,40h ;AN030;; Version 4.0? ;an000; dms; + jb EMS_Install_Ck_Err_Exit ;AN030;; exit routine - wrong EMS loaded ;an000; dms; + + clc ;AN030;; signal EMS loaded ;an000; dms; + jmp EMS_Install_Ck_Exit ;AN030;; exit routine ;an000; dms; + +EMS_Install_Ck_Err_Exit: ;AN030; + + stc ;AN030;; signal EMS not loaded ;an000; dms; + +EMS_Install_Ck_Exit: ;AN030; + + pop ax ;AN030;; restore regs ;an000; dms; + + ret ;AN030;; return to caller ;an000; dms; + +EMS_Install_Check endp ; ;an000; dms; + +EMS_Stub_Handler proc near ;AN030; +;At the request of Architecture Group, this logic is implemented. +;Function: If (Buffer_Slash_X <> 0 and EMS_Stub_Installed == 0), +; then { call Chk_EMS; +; if EMS is there, then install EMS_Stub dynamically +; and initialize it.} +; Note: EMS_Stub consists of INT 2fh EMS handler and INT 67h handler. +; When EMS_Stub is installed, EMS_Stub_Installed will be set to 1. + + push es ;AN030; + push si ;AN030; + push ds ;AN030; + push di ;AN030; + push ax ;AN030; + push cx ;AN030; + cmp EMS_Stub_Installed, 0 ;AN030; + je EMS_Stub_X ;AN030; + jmp EMS_SH_Ret ;AN030; +EMS_Stub_X: ;AN030; + cmp Buffer_Slash_X, 0 ;AN030; + je EMS_SH_Ret ;AN030; + call EMS_Install_Check ;AN030; + jc EMS_SH_Ret ;AN030; +;Install EMS_Stub. ;AN030; +EMS_Stub_Do: + push es ;AN030; + xor ax,ax ;AN030;save current Int 2fh, 67h vectors. + mov es, ax ;AN030; + mov ax, word ptr es:[2fh*4] ;AN030; + mov IntV2FO, ax ;AN030; + mov ax, word ptr es:[2fh*4+2] ;AN030; + mov IntV2FS, ax ;AN030; + mov ax, word ptr es:[67h*4] ;AN030; + mov word ptr cs:[OldInt67], ax ;AN030; + mov ax, word ptr es:[67h*4+2] ;AN030; + mov word ptr cs:[OldInt67+2], ax ;AN030; + pop es ;AN030; + +IF NOT BUFFERFLAG +;initalize tables in INT 67h handler + call Int67FilterInit ;AN030; + cmp ax, 0ffffh ; if the page found was part of a lim 4.0 page frame + je EMS_SH_ret ; do not install stub. 7/24/88. HKN +ENDIF + call Round ;AN030; + mov ax, DEVMARK_EMS_STUB ;AN030; + call SetDevMark ;AN030; + mov ax, [memhi] ;AN030; + mov es, ax ;AN030; + assume es:nothing ;AN030; + xor di, di ;AN030; + push cs ;AN030; + pop ds ;AN030; + mov cx, offset EMS_STUB_END ;AN030; + mov si, offset EMS_STUB_START ;AN030; + sub cx, si ;AN030;cx = size in byte + mov [memlo], cx ;AN030; + rep movsb ;AN030; + or [SetDevMarkFlag], FOR_DEVMARK ;AN030;set the devmark_size for MEM command. + call Round ;AN030;and get the next [memhi] avaiable. + mov EMS_Stub_Installed, 1 ;AN030; + + xor ax, ax ;AN030; + mov ds, ax ;AN030; + cli ;AN030; + mov word ptr ds:[2Fh*4],NEWEMS2F_OFF;AN030;set the new int 2fh, 67h vectors. + mov word ptr ds:[2Fh*4+2], es ;AN030; + mov word ptr ds:[67h*4],NEW67_OFFSET;AN030; + mov word ptr ds:[67h*4+2], es ;AN030; + sti ;AN030; +EMS_SH_Ret: ;AN030; + pop cx ;AN030; + pop ax ;AN030; + pop di ;AN030; + pop ds ;AN030; + pop si ;AN030; + pop es ;AN030; + ret ;AN030; + +EMS_Stub_Handler endp ;AN030; + + +SYSINITSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/SYSIMES.ASM b/v4.0/src/BIOS/SYSIMES.ASM new file mode 100644 index 0000000..0640282 --- /dev/null +++ b/v4.0/src/BIOS/SYSIMES.ASM @@ -0,0 +1,38 @@ + ;SCCSID = @(#)sysimes.asm 1.2 85/07/25 +%OUT ...SYSIMES + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 D246, P976 Show "Bad command or parameters - ..." msg 9/22/87 J.K. +;AN002 P1820 New Message SKL file 10/20/87 J.K. +;AN003 D486 Share installation for large media 02/24/88 J.K. +;============================================================================== + +iTEST = 0 +include MSequ.INC +include MSmacro.INC + +SYSINITSEG SEGMENT PUBLIC BYTE 'SYSTEM_INIT' + + PUBLIC BADOPM,CRLFM,BADSIZ_PRE,BADLD_PRE,BADCOM,SYSSIZE,BADCOUNTRY +; PUBLIC BADLD_POST,BADSIZ_POST,BADMEM,BADBLOCK,BADSTACK + PUBLIC BADMEM,BADBLOCK,BADSTACK + PUBLIC INSUFMEMORY,BADCOUNTRYCOM + public BadOrder,Errorcmd ;AN000; + public BadParm ;AN001; + public SHAREWARNMSG ;AN003; + + +;include sysimes.inc +include MSbio.cl3 ;AN002; + +SYSSIZE LABEL BYTE + +PATHEND 001,SYSMES + +SYSINITSEG ENDS + END diff --git a/v4.0/src/BIOS/SYSINIT1.ASM b/v4.0/src/BIOS/SYSINIT1.ASM new file mode 100644 index 0000000..7869b76 --- /dev/null +++ b/v4.0/src/BIOS/SYSINIT1.ASM @@ -0,0 +1,2668 @@ + PAGE ,132 ; +; SCCSID = @(#)sysinit1.asm 1.7 85/10/24 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSINIT1 +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; p40 Boot from the system with no floppy diskette drives 6/26/87 J.K. +;AN002; d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; d9 Double word mov for 386 machine 7/15/87 J.K. +;AN004; p447 BUFFERS = 50 /E without EMS installed hangs 8/25/87 J.K. +;AN005; d184 Set DEVMARK for MEM command 8/25/87 J.K. +;AN006; p851 Installable files not recognized corretly. 9/08/87 J.K. +;AN007; p1299 Set the second entry of DEVMARK for MEM command 9/25/87 J.K. +;AN008; p1361 New Extended Attribute 9/28/87 J.K. +;AN009; p1326 Buffers = 50 /e hangs 9/28/87 J.K. +;AN010; New EMS Interface +;AN011; New Message SKL file 10/20/87 J.K. +;AN012; P2211 Setting EA=7 for ANSI.SYS hangs the system 11/02/87 J.K. +;AN013; p2343 Set the name for SYSINIT_BASE for MEM command 11/11/87 J.K. +;AN014; D358 New device driver INIT function package 12/03/87 J.K. +;AN015; For Installed module with no parameter 12/11/87 J.K. +;AN016; D285 Undo the Extended Attribute handling 12/17/87 J.K. +;AN017; P2806 Show "Error in CONFIG.SYS ..." for INSTALL= command 12/17/87 J.K. +;AN018; P2914 Add Extended Memory Size in SYSVAR 01/05/88 J.K. +;AN019; P3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN020; P3497 Performace fix for new buffer scheme 02/15/88 J.K. +;AN021; D486 SHARE installation for big media 02/23/88 J.K. +;AN022; D493 Undo D358 & do not show error message for device driv02/24/88 J.K. +;AN023; D474 Change BUFFERS= /E option to /X for expanded memory 03/16/88 J.K. +;AN024; D506 Take out the order dependency of the IFS= 03/28/88 J.K. +;AN025; P4086 Memory allocation error when loading SHARE.EXE 03/31/88 J.K. +;AN026; D517 New Balanced Real memory buffer set up scheme 04/18/88 J.K. +;AN027; D528 Install XMAEM.SYS first before everything else 04/29/88 J.K. +;AN028; P4669 SHARE /NC causes an error 05/03/88 J.K. +;AN029; P4759 Install EMS INT2fh, INT 67h handler 05/12/88 J.K. +;AN030; P4934 P4759 INT 2Fh handler number be changed to 1Bh 05/20/88 J.K. +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +CR equ 13 +LF equ 10 +TAB equ 9 + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE +MYCDS_SIZE equ 88 ;J.K. Size of Curdir_List. If it is not + ;the same, then will generate compile error. + +; + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H +;dossize equ 0C000H ;J.K. for the debugging version of IBMDOS. + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include BIOSTRUC.INC + include smifssym.inc ;AN000; + include defems.inc ;AN010; + include DEVMARK.inc ;AN005; + include cputype.inc + + include version.inc + +.list + +;AN000 J.K. If MYCDS_SIZE <> CURDIRLEN, then force a compilatiaon error. + if MYCDS_SIZE NE CURDIRLEN + %OUT  !!! SYSINIT1 COMPILATION FAILED. DIFFERENT CDS SIZE !!! + .ERRE MYCDS_SIZE EQ CURDIRLEN + endif + + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + +;--------------------------------------- +;Equates for Main stack and stack Initialization program + IF STACKSW + +EntrySize equ 8 + +MinCount equ 8 +DefaultCount equ 9 +MaxCount equ 64 + +MinSize equ 32 +DefaultSize equ 128 +MaxSize equ 512 + +AllocByte equ es:byte ptr [bp+0] +IntLevel equ es:byte ptr [bp+1] +SavedSP equ es:word ptr [bp+2] +SavedSS equ es:word ptr [bp+4] +NewSP equ es:word ptr [bp+6] +Free equ 0 +allocated equ 1 +overflowed equ 2 +clobbered equ 3 + + +;External variables in IBMBIO for INT19h handling rouitne. J.K. 10/23/86 +CODE segment public 'code' + EXTRN Int19sem:byte + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + EXTRN Int19OLD&AA:dword + ENDM +CODE ends + ENDIF +;--------------------------------------- +;J.K. 6/29/87 External variable defined in IBMBIO module for Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + +CODE segment public 'code' + EXTRN MulTrk_flag:word ;AN002; +CODE ends +;J.K. 6/29/87 End of Multi-track definition. + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADCOM:BYTE + EXTRN SYSSIZE:BYTE + EXTRN CONDEV:BYTE,AUXDEV:BYTE,PRNDEV:BYTE,COMMND:BYTE + extrn DeviceParameters:byte + extrn DevMark_Addr:word + extrn SetDevMarkFlag:byte + extrn PathString:byte ;AN021; + extrn LShare:byte ;AN021; + extrn ShareWarnMsg:byte ;AN021; + + EXTRN INT24:NEAR,MEM_ERR:NEAR + EXTRN DOCONF:NEAR + extrn Multi_Pass:NEAR ;AN024; + extrn BadLoad:near + extrn Error_Line:near + + PUBLIC CURRENT_DOS_LOCATION + PUBLIC FINAL_DOS_LOCATION + PUBLIC DEVICE_LIST + PUBLIC SYSI_COUNTRY + PUBLIC MEMORY_SIZE + PUBLIC DEFAULT_DRIVE + PUBLIC BUFFERS + PUBLIC FILES + PUBLIC NUM_CDS + PUBLIC SYSINIT + PUBLIC CNTRYFILEHANDLE + PUBLIC COMMAND_LINE + public Big_Media_Flag ;AN021;Set by IBMINIT + + IF STACKSW + ;Internal Stack Information + PUBLIC STACK_COUNT + PUBLIC STACK_SIZE + PUBLIC STACK_ADDR + ENDIF + + PUBLIC dosinfo,entry_point + PUBLIC fcbs,keep + PUBLIC confbot,alloclim + PUBLIC zero,sepchr,STALL + PUBLIC count,chrptr,org_count + PUBLIC bufptr,memlo,prmblk,memhi + PUBLIC ldoff,area,PACKET,UNITCOUNT + PUBLIC BREAK_ADDR,BPB_ADDR,drivenumber + public Config_Size + public Install_Flag + public COM_Level + public CMMT + public CMMT1 + public CMMT2 + public Cmd_Indicator + public LineCount + public ShowCount + public Buffer_LineNum + public DoNotShowNum + public IFS_Flag + public IFS_RH + public H_Buffers + public Buffer_Slash_X ;AN023; + public ConfigMsgFlag ;AN014; + public Do_Install_Exec ;AN019; + public Multi_Pass_Id ;AN024; + + +; +SYSINIT$: + IF STACKSW +.SALL + include MSSTACK.INC ;Main stack program and data definitions +; include STKMES.INC ;Fatal stack error message + include MSBIO.CL5 ;Fatal stack error message +.XALL + public Endstackcode +Endstackcode label byte + ENDIF + +; +SYSINIT: + JMP GOINIT +DOSINFO LABEL DWORD + DW 0000 +CURRENT_DOS_LOCATION DW 0000 + +MSDOS LABEL DWORD +ENTRY_POINT LABEL DWORD + DW 0000 +FINAL_DOS_LOCATION DW 0000 +DEVICE_LIST DD 00000000 + +SYSI_Country LABEL DWORD ;J.K. 5/29/86 Pointer to + DW 0000 ;country table in DOS + DW 0000 + +Fake_Floppy_Drv db 0 ;AN001;Set to 1 if this machine + ;does not have any floppies!!! +Big_Media_Flag db 0 ;AN021;Set by IBMINIT if > 32 MB fixed media exist. +; +;Variables for Stack Initialization Program. + IF STACKSW +STACK_COUNT DW DefaultCount +STACK_SIZE DW DefaultSize +STACK_ADDR DD 00000000 + ENDIF +; various default values + +MEMORY_SIZE DW 0001 +DEFAULT_DRIVE DB 00 ;initialized by IBMINIT. +BUFFERS DW -1 ; initialized during buffer allocation +H_Buffers dw 0 ;AN000; # of the Heuristic buffers. Initially 0. +Buffer_Pages dw 0 ;AN000; # of extended memory pages for the buffer. +BufferBuckets dw 0 ;AN000; +Buffer_odds dw 0 ;AN000; +SingleBufferSize dw ? ;AN000; Maximum sector size + buffer header +MaxNumBuf1 db 15 ;AN026;Num of buffers in a bucket group 1. +MaxNumBuf2 db 15 ;AN026;Num of buffers in a possible bucket group 2. +NthBuck db 0 ;AN026; 1st bucket group = 1st bucket through Nth Bucket. The rest = second group + +IF BUFFERFLAG + +FIRST_PAGE DW 0, 0 +LAST_PAGE DW 0, 0 +NPA640 DW 0 +EMS_SAVE_BUF DB 0,0,0,0,0,0,0,0,0,0,0,0 + +ENDIF + +FILES DB 8 ; enough files for pipe +FCBS DB 4 ; performance for recycling +Keep DB 0 ; keep original set +NUM_CDS DB 5 ; 5 net drives +CONFBOT DW ? +ALLOCLIM DW ? +FOOSTRNG DB "A:\",0 +COMMAND_LINE DB 2,0,"P" ;Default Command.com Args + DB 29 DUP (0) +ZERO DB 0 +SepChr DB 0 +LineCount dw 0 ;AN000; Line count in config.sys +ShowCount db ' ',CR,LF,'$' ;AN000; Used to convert Linecount to ASCII. +Buffer_LineNum dw 0 ;AN000; Line count for "BUFFERS=" command if entered. + +Sys_Model_Byte db 0FFh ;model byte used in SYSINIT +Sys_Scnd_Model_Byte db 0 ;secondary model byte used in SYSINIT +; +Buffer_Slash_X db 0 ;AN000;AN023; BUFFERS= ... /X option entered. +Real_IBM_Page_Id dw 0 ;AN029; +IBM_Frame_Seg dw 0 ;AN000; segment value for physical IBM page frame. +Frame_Info_Buffer dw (MAX_NUM_PAGEFRAME * 4) dup (0) ;AN010; For EMS. as per spec. 2 words per entry +EMSHandleName db 'BUFFERS ' ;AN010; 8 char. EMS handle name +EMS_Ctrl_Tab dd 0 ;AN010; +EMS_State_Buf dd 0 ;AN010; +BUF_PREV_OFF dw 0 ;AN020; +EMS_Buf_First dw 0 ;AN020; + + IF NOT NOEXEC +COMEXE EXEC0 <0,COMMAND_LINE,DEFAULT_DRIVE,ZERO> + ENDIF + +;------------------------------------------------------------------ +;J.K. 2/23/87 ;variables for INSTALL= command. + +Multi_Pass_Id db 0 ;AN024;AN027; +Install_Flag dw 0 ;AN000; + HAVE_INSTALL_CMD equ 00000001b ;AN019; CONFIG.SYS has INSTALL= commands + HAS_INSTALLED equ 00000010b ;AN019; SYSINIT_BASE installed. + SHARE_INSTALL equ 00000100b ;AN021; Used to install SHARE.EXE + +Config_Size dw 0 ;AN000; size of config.sys file. Set by SYSCONF.ASM +Sysinit_Base_Ptr dd 0 ;AN000; pointer to SYSINIT_BASE +Sysinit_Ptr dd 0 ;AN000; returning addr. from SYSINIT_BASE +CheckSum dw 0 ;AN000; Used by Sum_up + +Ldexec_FCB db 20 dup (' ') ;AN000;big enough +Ldexec_Line db 0 ;AN000;# of parm characters +Ldexec_start db ' ' ;AN000; +Ldexec_parm db 80 dup (0) ;AN000; + +INSTEXE EXEC0 <0,Ldexec_Line,Ldexec_FCB,Ldexec_FCB> ;AN000; + +;AN016; Undo the extended attribute handling +;EA_QueryList label byte +; dw 1 ;AN008; I need just one EA info. +; db 02h ;AN008; Type is BINARY +; dw 8000h ;AN008; Flag is SYSTEM DEFINED. +; db 8 ;AN008; Length of name is 8 bytes +; db 'FILETYPE' ;AN008; Name is FILETYPE +;Ext_Attr_List dw 1 ;AN008; Just 1 Extended attribute List +; db 2 ;AN008;EA_TYPE +; dw 8000h ;AN008;FLAG +; db 0 ;AN008;Failure reason +; db 8 ;AN008;Length of NAME +; dw 1 ;AN008;Length of VALUE +; db 'FILETYPE' ;AN008;Name +;Ext_Attr_Value db 0 ;AN008;Value +;SIZE_EXT_ATTR_LIST equ $-Ext_Attr_List ;AN008; +; +;;Extended attribute value +;EA_INSTALLABLE equ 4 ;AN008;Value for Installable file + +;------------------------------------------------------------------ +;J.K. 5/15/87 ;Request header, variables for IFS= command. + +IFS_Flag dw 0 ;AN000; Set to 1 if it is an IFS. + IS_IFS equ 00000001b ;IFS command? + NOT_IFS equ 11111110b + +IFS_RH IFSRH ;AN000; IFS initialization request packet + +;------------------------------------------------------------------ +;Variables for Comment= +COM_Level db 0 ;AN000;level of " " in command line +CMMT db 0 ;AN000;length of COMMENT string token +CMMT1 db 0 ;AN000;token +CMMT2 db 0 ;AN000;token +Cmd_Indicator db ? ;AN000; +DoNotShowNum db 0 ;AN000; + +;------------------------------------------------------------------ +COUNT DW 0000 +Org_Count dw 0000 ;AN019; +CHRPTR DW 0000 +CntryFilehandle DW 0000 +Old_Area dw 0 ;AN013; +Impossible_Owner_Size dw 0 ;AN013; Paragraph +;------------------------------------------------------------------ +BucketPTR LABEL dword ;AN000; +BUFPTR LABEL DWORD ;LEAVE THIS STUFF IN ORDER! +MEMLO DW 0 +PRMBLK LABEL WORD +MEMHI DW 0 +LDOFF DW 0 +AREA DW 0 + +PACKET DB 24 ;AN014; Was 22 + DB 0 + DB 0 ;INITIALIZE CODE + DW 0 + DB 8 DUP (?) +UNITCOUNT DB 0 +BREAK_ADDR DD 0 +BPB_ADDR DD 0 +DriveNumber DB 0 +ConfigMsgFlag dw 0 ;AN014;AN022; Used to control "Error in CONFIG.SYS line #" message + +TempStack DB 80h DUP (?) + +GOINIT: +;J.K. before doing anything else, let's set the model byte +;SB33043***************************************************************** + mov ah,0c0h ;get system configuration ;SB ;3.30* + int 15h ; * ;SB ;3.30* +;SB33043***************************************************************** + jc No_ROM_Config + cmp ah, 0 ; double check + jne No_ROM_Config + mov al, ES:[BX.bios_SD_modelbyte] + mov cs:[Sys_Model_Byte], al + mov al, ES:[BX.bios_SD_scnd_modelbyte] + mov cs:[Sys_Scnd_Model_Byte], al + jmp short Move_Myself +No_ROM_Config: ; Old ROM + mov ax, 0f000h + mov ds, ax + mov al, byte ptr ds:[0fffeh] + mov cs:[Sys_Model_Byte], al ;set the model byte. +;J.K.6/24/87 Set Fake_Floppy_Drv if there is no diskette drives in this machine. +;SB34SYSINIT1001******************************************************** +;SB execute the equipment determination interrupt and then +;SB check the returned value to see if we have any floppy drives +;SB if we have no floppy drive we set cs:Fake_Floppy_Drv to 1 +;SB See the AT Tech Ref BIOS listings for help on the equipment +;SB flag interrupt (11h) + + int 11h + test ax,1 ; has floppy ? + jnz Move_Myself + mov cs:Fake_Floppy_Drv,1 ; no floppy, fake. + +;SB34SYSINIT1001******************************************************** +Move_Myself: + CLD ; Set up move + XOR SI,SI + MOV DI,SI + + IF MSVER + MOV CX,cs:[MEMORY_SIZE] + CMP CX,1 ; 1 means do scan + JNZ NOSCAN + MOV CX,2048 ;START SCANNING AT 32K BOUNDARY + XOR BX,BX + +MEMSCAN:INC CX + JZ SETEND + MOV DS,CX + MOV AL,[BX] + NOT AL + MOV [BX],AL + CMP AL,[BX] + NOT AL + MOV [BX],AL + JZ MEMSCAN +SETEND: + MOV cs:[MEMORY_SIZE],CX + ENDIF + + IF IBMVER OR IBMJAPVER + MOV CX,cs:[MEMORY_SIZE] + ENDIF + +NOSCAN: ; CX is mem size in para + MOV AX,CS + MOV DS,AX +ASSUME DS:SYSINITSEG + + MOV AX,OFFSET SYSSIZE + Call ParaRound + SUB CX,AX ;Compute new sysinit location + MOV ES,CX + MOV CX,OFFSET SYSSIZE + 1 + SHR CX,1 ;Divide by 2 to get words + REP MOVSW ;RELOCATE SYSINIT + + ASSUME ES:SYSINITSEG + + PUSH ES + MOV AX,OFFSET SYSIN + PUSH AX + +AAA_DUMMY PROC FAR + RET +AAA_DUMMY ENDP +; +; MOVE THE DOS TO ITS PROPER LOCATION +; +SYSIN: + + ASSUME DS:NOTHING,ES:SYSINITSEG,SS:NOTHING + + MOV AX,[CURRENT_DOS_LOCATION] ; Where it is (set by BIOS) + MOV DS,AX + MOV AX,[FINAL_DOS_LOCATION] ; Where it is going (set by BIOS) + MOV ES,AX + + ASSUME ES:NOTHING + + XOR SI,SI + MOV DI,SI + + MOV CX,DOSSIZE/2 + REP MOVSW + + LDS SI,[DEVICE_LIST] ; Set for call to DOSINIT + MOV DX,[MEMORY_SIZE] ; Set for call to DOSINIT + + CLI + MOV AX,CS + MOV SS,AX + MOV SP,OFFSET LOCSTACK ; Set stack + + ASSUME SS:SYSINITSEG + + IF NOT ALTVECT + STI ; Leave INTs disabled for ALTVECT + ENDIF +LOCSTACK LABEL BYTE + + CALL MSDOS ; Call DOSINIT + ;ES:DI -> SysInitVars_Ext + mov ax, word ptr es:[di.SYSI_InitVars] ;J.K. 5/29/86 + mov word ptr [dosinfo], ax + mov ax, word ptr es:[di.SYSI_InitVars+2] + mov word ptr [dosinfo+2],ax ;set the sysvar pointer + + mov ax, word ptr es:[di.SYSI_Country_Tab] + mov word ptr [SYSI_Country],ax + mov ax, word ptr es:[di.SYSI_Country_Tab+2] + mov word ptr [SYSI_Country+2],ax ;set the SYSI_Country pointer J.K. + + les di, dosinfo ;es:di -> dosinfo + + clc ;AN018;Get the extended memory size +;SB34SYSINIT1002************************************************************** +;SB execute the get extended memory size subfunction in the BIOS INT 15h +;SB if the function reports an error do nothing else store the extended +;SB memory size reported at the appropriate location in the dosinfo buffer +;SB currently pointed to by es:di. Use the offsets specified in the +;SB definition of the sysinitvars struct in inc\sysvar.inc +;SB 5 LOCS + + mov ah,88h + int 15h ;check extended memory size + jc No_Ext_Memory + mov es:[di].SYSI_EXT_MEM,ax ;save extended memory size +No_Ext_Memory: + +;SB34SYSINIT1002************************************************************** + mov word ptr es:[di.SYSI_IFS], -1 ;AN000; Initialize SYSI_IFS chain. + mov word ptr es:[di.SYSI_IFS+2], -1 ;AN000; + + mov ax, es:[di.SYSI_MAXSEC] ;AN020; Get the sector size + add ax, BUFINSIZ ;AN020; size of buffer header + mov [SingleBufferSize], ax ;AN020; total size for a buffer + + mov al, Default_Drive ;AN000;Get the 1 based boot drive number set by IBMINIT + mov es:[di.SYSI_BOOT_DRIVE], al ;AN000; set SYSI_BOOT_DRIVE + +; Determine if 386 system... + Get_CPU_Type ; macro to determine cpu type + cmp ax, 2 ; is it a 386? + jne Not_386_System ; no: don't mess with flag + mov es:[di.SYSI_DWMOVE], 1 ;AN003; +Not_386_System: ;AN003; + MOV AL,ES:[DI.SYSI_NUMIO] + MOV DriveNumber,AL ; Save start of installable block drvs + + MOV AX,CS + SUB AX,11H ; room for header we will copy shortly + mov cx, [SingleBufferSize] ;AN020;Temporary Single buffer area + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; Paragraphs + inc cx ;AN020; + sub ax, cx ;AN020; + MOV [CONFBOT],AX ; Temp "unsafe" location + + push es ;AN020; + push di ;AN020; + les di, es:[di.SYSI_BUF] ;AN020;get the buffer hash entry pointer + les di, es:[di.HASH_PTR] ;AN020; + mov word ptr es:[di.BUFFER_BUCKET],0 ;AN020; + mov word ptr es:[di.BUFFER_BUCKET+2], ax ;AN020; + mov es, ax ;AN020; + xor ax, ax ;AN020; + mov di, ax ;AN020;es:di -> Single buffer + mov es:[di.BUF_NEXT], ax ;AN020;points to itself + mov es:[di.BUF_PREV], ax ;AN020;points to itself + mov word ptr es:[di.BUF_ID],00FFh ;AN020;free buffer, clear flag + mov word ptr es:[di.BUF_SECTOR], 0 ;AN020; + mov word ptr es:[di.BUF_SECTOR+2], 0 ;AN020; + pop di ;AN020; + pop es ;AN020; + + PUSH DS ; Save as input to RE_INIT + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + CALL TEMPCDS ; Set up CDSs so RE_INIT and SYSINIT + ; can make DISK system calls + + POP DS ; Recover DS input to RE_INIT +ASSUME DS:NOTHING + + IF NOT IBMJAPVER + CALL RE_INIT ; Re-call the BIOS + ENDIF + + STI ; INTs OK + CLD ; MAKE SURE +; DOSINIT has set up a default "process" (PHP) at DS:0. We will move it out +; of the way by putting it just below SYSINIT at end of memory. + MOV BX,CS + SUB BX,10H + MOV ES,BX + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP MOVSW + MOV WORD PTR ES:[PDB_JFN_Pointer + 2],ES ; Relocate + MOV AH,SET_CURRENT_PDB + INT 21H ; Tell DOS we moved it + PUSH DS + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + MOV DX,OFFSET INT24 ;SET UP INT 24 HANDLER + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H + INT 21H + + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H ;FIRST TIME FAILS + MOV AH,ALLOC + INT 21H ;SECOND TIME GETS IT + MOV [AREA],AX + MOV [MEMHI],AX ; MEMHI:MEMLO now points to + ; start of free memory + IF ALTVECT + MOV DX,OFFSET BOOTMES + invoke PRINT ;Print message DOSINIT couldn't + ENDIF + + POP DS +ASSUME DS:NOTHING + + MOV DL,[DEFAULT_DRIVE] + OR DL,DL + JZ NODRVSET ; BIOS didn't say + DEC DL ;A = 0 + MOV AH,SET_DEFAULT_DRIVE + INT 21H ;SELECT THE DISK +;J.K. 2/23/87 Modified to handle INSTALL= command. +NODRVSET: + CALL DOCONF ;DO THE CONFIG STUFF + inc cs:Multi_Pass_Id ;AN027; + call Multi_Pass ;AN027; + inc cs:Multi_Pass_Id ;AN024; + call Multi_Pass ;AN024; + call EndFile + test Install_Flag, HAVE_INSTALL_CMD ;AN019; + jz DoLast ;AN019; + inc cs:Multi_Pass_Id ;AN024; + call Multi_Pass ;AN019;AN024; Execute INSTALL= commands + +;J.K. [AREA] has the segment address for the allocated memory of SYSINIT,CONFBOT. +;Free the CONFBOT area used for CONFIG.SYS and SYSINIT itself. +DoLast: + call LoadShare ;AN021; Try to load share.exe, if needed. + mov cs:[DoNotShowNum], 1 ;AN000; Done with CONFIG.SYS. Do not show line number message. + mov cx, [area] ;AN000; + mov es, cx ;AN000; + mov ah, 49h ;AN000; Free allocated memory for command.com + int 21h ;AN000; + + test cs:[Install_flag], HAS_INSTALLED ;AN013; SYSINIT_BASE installed? + jz Skip_Free_SYSINITBASE ;AN013; No. +;Set Block from the Old_Area with Impossible_Owner_size. +;This will free the unnecessary SYSINIT_BASE that had been put in memory to +;handle INSTALL= command. + push es ;AN013; + push bx ;AN013; + mov ax, cs:[Old_Area] ;AN013; + mov es, ax ;AN013; + mov bx, cs:[Impossible_Owner_Size] ;AN013; + mov ah, SETBLOCK ;AN013; + int 21h ;AN013; + MOV AX,ES ;AN013; + DEC AX ;AN013; + MOV ES,AX ;Point to arena + MOV ES:[arena_owner],8 ;Set impossible owner + pop bx ;AN013; + pop es ;AN013; +Skip_Free_SYSINITBASE: ;AN013; + IF NOEXEC + MOV BP,DS ;SAVE COMMAND.COM SEGMENT + PUSH DS + POP ES + MOV BX,CS + SUB BX,10H ; Point to current PHP + MOV DS,BX + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP MOVSW ; Copy it to new location for shell + MOV WORD PTR ES:[PDB_JFN_Pointer + 2],ES ; Relocate + MOV BX,ES + MOV AH,SET_CURRENT_PDB + INT 21H ; Tell DOS we moved it + MOV ES:[PDB_PARENT_PID],ES ;WE ARE THE ROOT + ENDIF + + PUSH CS + POP DS +ASSUME DS:SYSINITSEG +; +; SET UP THE PARAMETERS FOR COMMAND +; + + MOV SI,OFFSET COMMAND_LINE+1 + + IF NOEXEC + MOV DI,81H + ELSE + PUSH DS + POP ES + MOV DI,SI + ENDIF + + MOV CL,-1 +COMTRANLP: ;FIND LENGTH OF COMMAND LINE + INC CL + LODSB + STOSB ;COPY COMMAND LINE IN + OR AL,AL + JNZ COMTRANLP + DEC DI + MOV AL,CR ; CR terminate + STOSB + + IF NOEXEC + MOV ES:[80H],CL ; Set up header + MOV AL,[DEFAULT_DRIVE] + MOV ES:[5CH],AL + ELSE + MOV [COMMAND_LINE],CL ;Count + ENDIF + + MOV DX,OFFSET COMMND ;NOW POINTING TO FILE DESCRIPTION + + IF NOEXEC + MOV ES,BP ;SET LOAD ADDRESS + MOV BX,100H + CALL LDFIL ;READ IN COMMAND + JC COMERR + MOV DS,BP + MOV DX,80H + MOV AH,SET_DMA ;SET DISK TRANFER ADDRESS + INT 21H + CLI + MOV SS,BP + MOV SP,DX + STI + XOR AX,AX ;PUSH A WORD OF ZEROS + PUSH AX + PUSH BP ;SET HIGH PART OF JUMP ADDRESS + MOV AX,100H + PUSH AX ;SET LOW PART OF JUMP ADDRESS +CCC PROC FAR + RET ;CRANK UP COMMAND! +CCC ENDP + + ELSE +; We are going to open the command interpreter and size it as is done in +; LDFIL. The reason we must do this is that SYSINIT is in free memory. If +; there is not enough room for the command interpreter, EXEC will probably +; overlay our stack and code so when it returns with an error SYSINIT won't be +; here to catch it. This code is not perfect (for instance .EXE command +; interpreters are possible) because it does its sizing based on the +; assumption that the file being loaded is a .COM file. It is close enough to +; correctness to be usable. + + PUSH DX ; Save pointer to name + +; First, find out where the command interpreter is going to go. + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H ;Get biggest piece + MOV AH,ALLOC + INT 21H ;SECOND TIME GETS IT + JC MEMERRJX ; Oooops + MOV ES,AX + MOV AH,DEALLOC + INT 21H ; Give it right back + MOV BP,BX +; ES:0 points to Block, and BP is the size of the block +; in para. + +; We will now adjust the size in BP DOWN by the size of SYSINIT. We +; need to do this because EXEC might get upset if some of the EXEC +; data in SYSINIT is overlayed during the EXEC. + MOV BX,[MEMORY_SIZE] + MOV AX,CS + SUB BX,AX ; BX is size of SYSINIT in Para + ADD BX,11H ; Add the SYSINIT PHP + SUB BP,BX ; BAIS down + JC MEMERRJX ; No Way. + + MOV AX,(OPEN SHL 8) ;OPEN THE FILE being EXECED + STC ;IN CASE OF INT 24 + INT 21H + JC COMERR ; Ooops + MOV BX,AX ;Handle in BX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JC COMERR + ; Convert size in DX:AX to para in AX + ADD AX,15 ; Round up size for conversion to para + ADC DX,0 + MOV CL,4 + SHR AX,CL + MOV CL,12 + SHL DX,CL ; Low nibble of DX to high nibble + OR AX,DX ; AX is now # of para for file + ADD AX,10H ; 100H byte PHP + CMP AX,BP ; Will it fit? + JB OKLD ; Jump if yes. +MEMERRJX: + JMP MEM_ERR + +OKLD: + MOV AH,CLOSE + INT 21H ; Close file + POP DX ; Recover pointer to name + PUSH CS + POP ES + ASSUME ES:SYSINITSEG + MOV BX,OFFSET COMEXE ; Point to EXEC block + MOV WORD PTR [BX.EXEC0_COM_LINE+2],CS ; Set segments + MOV WORD PTR [BX.EXEC0_5C_FCB+2],CS + MOV WORD PTR [BX.EXEC0_6C_FCB+2],CS + XOR AX,AX ;Load and go + MOV AH,EXEC + STC ;IN CASE OF INT 24 + INT 21H ;GO START UP COMMAND + ENDIF +; NOTE FALL THROUGH IF EXEC RETURNS (an error) + +COMERR: + MOV DX,OFFSET BADCOM ;WANT TO PRINT COMMAND ERROR + INVOKE BADFIL +STALL: JMP STALL + + PUBLIC TEMPCDS +TEMPCDS: +ASSUME DS:SYSINITSEG + LES DI,[DOSINFO] + + MOV CL,BYTE PTR ES:[DI.SYSI_NUMIO] + XOR CH,CH + MOV ES:[DI.SYSI_NCDS],CL + MOV AL,CL + MOV AH,SIZE curdir_list + MUL AH + call ParaRound + MOV SI,[CONFBOT] + SUB SI,AX + MOV [ALLOCLIM],SI ; Can't alloc past here! + MOV WORD PTR ES:[DI.SYSI_CDS + 2],SI + MOV AX,SI + MOV WORD PTR ES:[DI.SYSI_CDS],0 + LDS SI,ES:[DI.SYSI_DPB] +ASSUME DS:NOTHING + MOV ES,AX + XOR DI,DI + +FOOSET: ; Init CDSs + MOV AX,WORD PTR [FOOSTRNG] + STOSW + MOV AX,WORD PTR [FOOSTRNG + 2] + STOSW + INC BYTE PTR [FOOSTRNG] + XOR AX,AX + PUSH CX + MOV CX,curdir_flags - 4 + REP STOSB + CMP SI,-1 +; JNZ NORMCDS +;J.K. 6/24/87 Should handle the system that does not have any floppies. +;J.K. In this case, we are going to pretended there are two dummy floppies +;J.K. in the system. Still they have DPB and CDS, but we are going to +;J.K. 0 out Curdir_Flags, Curdir_devptr of CDS so IBMDOS can issue +;J.K. "Invalid drive specification" message when the user try to +;J.K. access them. + je Fooset_Zero ;AN001;Don't have any physical drive. +;SB34SYSINIT1003************************************************************* +;SB Check to see if we are faking floppy drives. If not go to NORMCDS. +;SB If we are faking floppy drives then see if this CDS being initialised +;SB is for drive a: or b: by checking the appropriate field in the DPB +;SB pointed to by ds:si. If not for a: or b: then go to NORMCDS. If +;Sb for a: or b: then execute the code given below starting at Fooset_Zero. +;SB For dpb offsets look at inc\dpb.inc. +;SB 5 LOCS + + cmp cs:Fake_Floppy_Drv,1 ;fake drive ? + jnz NORMCDS + cmp ds:[si].dpb_drive,02 ;check for a: or b: + jae NORMCDS + +;SB34SYSINIT1003************************************************************* +Fooset_Zero: ;AN001; + XOR AX,AX + MOV CL,3 + REP STOSW + POP CX + JMP SHORT FINCDS +NORMCDS: + POP CX +;J.K. If a non-fat based media is detected (by DPB.NumberOfFat == 0), then +; set curdir_flags to 0. This is for signaling IBMDOS and IFSfunc that +; this media is a non-fat based one. + cmp [SI.dpb_FAT_count], 0 ;AN000; Non fat system? + je SetNormCDS ;AN000; Yes. Set curdir_Flags to 0. AX = 0 now. + MOV AX,CURDIR_INUSE ;AN000; else, FAT system. set the flag to CURDIR_INUSE. +SetNormCDS: ;AN000; + STOSW ; curdir_flags + MOV AX,SI + STOSW ; curdir_devptr + MOV AX,DS + STOSW + LDS SI,[SI.dpb_next_dpb] +FINCDS: + MOV AX,-1 + STOSW ; curdir_ID + STOSW ; curdir_ID + STOSW ; curdir_user_word + mov ax,2 + stosw ; curdir_end + mov ax, 0 ;AN000;Clear out 7 bytes (curdir_type, + stosw ;AN000; curdir_ifs_hdr, curdir_fsda) + stosw ;AN000; + stosw ;AN000; + stosb ;AN000; + LOOP FOOSET + MOV BYTE PTR [FOOSTRNG],"A" + return + +;------------------------------------------------------------------------------ +; Allocate FILEs +;------------------------------------------------------------------------------ +ENDFILE: +; WE ARE NOW SETTING UP FINAL CDSs, BUFFERS, FILES, FCSs STRINGs etc. We no +; longer need the space taken by The TEMP stuff below CONFBOT, so set ALLOCLIM +; to CONFBOT. + +;J.K. 2/23/87 If this procedure has been called to take care of INSTALL= command, +;then we have to save ES,SI registers. + +; test [Install_Flag],IS_INSTALL ;AN000; Called to handle INSTALL=? +; jz ENDFILE_Cont ;AN000; +; push es ;AN000; Save es,si for CONFIG.SYS +; push si ;AN000; +; test [Install_Flag],HAS_INSTALLED ;AN000; Sysinit_base already installed? +; jz ENDFILE_Cont ;AN000; No. Install it. +; jmp DO_Install_EXEC ;AN000; Just handle "INSTALL=" cmd only. +;ENDFILE_Cont: ;AN000; + + push ds ;AN002; + mov ax, Code ;AN002; + mov ds, ax ;AN002; + assume ds:Code + cmp MulTrk_flag, MULTRK_OFF1 ;AN002;=0, MULTRACK= command entered? + jne MulTrk_Flag_Done ;AN002; + or MulTrk_flag, MULTRK_ON ;AN002; Default will be ON. +MulTrk_Flag_Done: ;AN002; + pop ds ;AN002; + assume ds:nothing + + MOV AX,[CONFBOT] + MOV [ALLOCLIM],AX + + PUSH CS + POP DS + INVOKE ROUND + MOV AL,[FILES] + SUB AL,5 + JBE DOFCBS + push ax ;AN005; + mov al, DEVMARK_FILES ;AN005; + call SetDevMark ;AN005; Set DEVMARK for SFTS (FILES) + pop ax ;AN005; + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV BX,[MEMLO] + MOV DX,[MEMHI] + LDS DI,[DOSINFO] ;GET POINTER TO DOS DATA + LDS DI,[DI+SYSI_SFT] ;DS:BP POINTS TO SFT + MOV WORD PTR [DI+SFLINK],BX + MOV WORD PTR [DI+SFLINK+2],DX ;SET POINTER TO NEW SFT + PUSH CS + POP DS + LES DI,DWORD PTR [MEMLO] ;POINT TO NEW SFT + MOV WORD PTR ES:[DI+SFLINK],-1 + MOV ES:[DI+SFCOUNT],AX + MOV BL,SIZE SF_ENTRY + MUL BL ;AX = NUMBER OF BYTES TO CLEAR + MOV CX,AX + ADD [MEMLO],AX ;ALLOCATE MEMORY + MOV AX,6 + ADD [MEMLO],AX ;REMEMBER THE HEADER TOO + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before the STOSB + ADD DI,AX + XOR AX,AX + REP STOSB ;CLEAN OUT THE STUFF + +;------------------------------------------------------------------------------ +; Allocate FCBs +;------------------------------------------------------------------------------ +DOFCBS: + PUSH CS + POP DS + INVOKE ROUND + mov al, DEVMARK_FCBS ;AN005;='X' + call SetDevMark ;AN005; + MOV AL,[FCBS] + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV BX,[MEMLO] + MOV DX,[MEMHI] + LDS DI,[DOSINFO] ;GET POINTER TO DOS DATA + ASSUME DS:NOTHING + MOV WORD PTR [DI+SYSI_FCB],BX + MOV WORD PTR [DI+SYSI_FCB+2],DX ;SET POINTER TO NEW Table + MOV BL,CS:Keep + XOR BH,BH + MOV [DI+SYSI_keep],BX + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + LES DI,DWORD PTR [MEMLO] ;POINT TO NEW Table + MOV WORD PTR ES:[DI+SFLINK],-1 + MOV ES:[DI+SFCOUNT],AX + MOV BL,SIZE SF_ENTRY + MOV CX,AX + MUL BL ;AX = NUMBER OF BYTES TO CLEAR + ADD [MEMLO],AX ;ALLOCATE MEMORY + MOV AX,size sf-2 + ADD [MEMLO],AX ;REMEMBER THE HEADER TOO + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before the STOSB + ADD DI,AX ;Skip over header + MOV AL,"A" +FillLoop: + PUSH CX ; save count + MOV CX,SIZE sf_entry ; number of bytes to fill + cld + REP STOSB ; filled + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_ref_count],0 + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_position],0 + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_position+2],0 + POP CX + LOOP FillLoop + +;------------------------------------------------------------------------------ +; Allocate Buffers +;------------------------------------------------------------------------------ + +; Search through the list of media supported and allocate 3 buffers if the +; capacity of the drive is > 360KB + + CMP [BUFFERS], -1 ; Has buffers been already set? + je DoDefaultBuff + cmp Buffer_Slash_X, 1 ;AN000; + jne DO_Buffer ;AN000; + call DoEMS ;AN000; Carry set if (enough) EMS is not available + jc DoDefaultBuff ;AN000; Error. Just use default buffer. +DO_Buffer: + jmp DOBUFF ; the user entered the buffers=. + +DoDefaultBuff: + mov [H_Buffers], 0 ;AN000; Default is no heuristic buffers. + MOV [BUFFERS], 2 ; Default to 2 buffers + PUSH AX + PUSH DS + LES BP,CS:[DOSINFO] ; Search through the DPB's + LES BP,DWORD PTR ES:[BP.SYSI_DPB] ; Get first DPB + +ASSUME DS:SYSINITSEG + PUSH CS + POP DS + +NEXTDPB: + ; Test if the drive supports removeable media + MOV BL, BYTE PTR ES:[BP.DPB_DRIVE] + INC BL + MOV AX, (IOCTL SHL 8) OR 8 + INT 21H + +; Ignore fixed disks + OR AX, AX ; AX is nonzero if disk is nonremoveable + JNZ NOSETBUF + +; Get parameters of drive + XOR BX, BX + MOV BL, BYTE PTR ES:[BP.DPB_DRIVE] + INC BL + MOV DX, OFFSET DeviceParameters + MOV AX, (IOCTL SHL 8) OR GENERIC_IOCTL + MOV CX, (RAWIO SHL 8) OR GET_DEVICE_PARAMETERS + INT 21H + JC NOSETBUF ; Get next DPB if driver doesn't support + ; Generic IOCTL + +; Determine capacity of drive +; Media Capacity = #Sectors * Bytes/Sector + MOV BX, WORD PTR DeviceParameters.DP_BPB.BPB_TotalSectors + +; To keep the magnitude of the media capacity within a word, +; scale the sector size +; (ie. 1 -> 512 bytes, 2 -> 1024 bytes, ...) + MOV AX, WORD PTR DeviceParameters.DP_BPB.BPB_BytesPerSector + XOR DX, DX + MOV CX, 512 + DIV CX ; Scale sector size in factor of + ; 512 bytes + + MUL BX ; AX = #sectors * size factor + OR DX, DX ; Just in case of LARGE floppies + JNZ SETBUF + CMP AX, 720 ; 720 Sectors * size factor of 1 + JBE NOSETBUF +SETBUF: + MOV [BUFFERS], 3 + jmp Chk_Memsize_for_Buffers ; Now check the memory size for default buffer count +; JMP BUFSET ; Jump out of search loop +NOSETBUF: + CMP WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + jz Chk_Memsize_for_Buffers +; JZ BUFSET + LES BP,ES:[BP.DPB_NEXT_DPB] + JMP NEXTDPB + +;J.K. 10/15/86 DCR00014. +;From DOS 3.3, the default number of buffers will be changed according to the +;memory size too. +; Default buffers = 2 +; If diskette Media > 360 kb, then default buffers = 3 +; If memory size > 128 kb (2000H para), then default buffers = 5 +; If memory size > 256 kb (4000H para), then default buffers = 10 +; If memory size > 512 kb (8000H para), then default buffers = 15. + +Chk_Memsize_for_Buffers: + cmp [memory_size], 2000h + jbe BufSet + mov [buffers], 5 + cmp [memory_size], 4000h + jbe BufSet + mov [buffers], 10 + cmp [memory_size], 8000h + jbe BufSet + mov [buffers], 15 + +BUFSET: +ASSUME DS:NOTHING + POP DS + POP AX + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;J.K. Here we should put extended stuff and new allocation scheme!!! +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;******************************************************************************* +; * +; Function: Actually allocate BUFFERS into the (extended) memory and initialize* +; it. * +; If it is installed in real memory, the number of buffers in each * +; bucket will be balanced out as far as possible for perfermance. * +; Also, if the user specified the secondary buffer cache, it will * +; be installed in the real memory. * +; * +; Input : * +; BuffINFO.EMS_MODE - 0=IBM mode, -1 = do not use extended memory. * +; BuffINFO.Frame_Page - Page frame 0 segment address * +; MEMHI:MEMLO - Start of the next available memory * +; Buffer_Pages = Number of extended memory pages for buffer * +; BUFFERS = Number of buffers * +; H_Buffers = Number of secondary buffers * +; * +; Output: * +; BuffINFO.Cache_Count - # of caches to be installed. * +; Hash table set. * +; BuffINFO set. * +; BufferBuckets set. * +; MaxNumBuf1, MaxNumBuf2, and NthBuck set. * +; * +; Subroutines to be called: * +; * +; Logic: * +; { * +; IF (BuffINFO.EMS_MODE == -1) THEN * +; { * +; IF BUFFERS < 30 THEN * +; {# of Bucket = 1; MaxNumBuf1 = BUFFERS; NthBuck = 1} * +; ELSE { * +; # of Bucket = BUFFERS/15; * +; r = BUFFERS mod 15; * +; IF r == 0 THEN NthBuck = # of Bucket * +; ELSE * +; { * +; AddBuff = r / # of Bucket; * +; NthBuck = r mod # of Bucket; * +; MaxNumBuf1 = 15 + AddBuff; /* 1st Bucket - Nth Bucket* +; MaxNumBuf2 = 15 + AddBuff +1;/*(N+1)th Bucket to last* +; } * +; } * +; } * +; ELSE * +; { * +; # of Bucket = Buffer_Pages * 2; /* 2 buckets per page * +; }; * +; * +; /*Now allocate memory for Hash table */ * +; Hash Table Size = (size Buffer_Hash_Entry) * # of Bucket; * +; Set BuffINFO.Hash_ptr to MEMHI:MEMLO; * +; Adjust MEMHI:MEMLO according to Hash table size; * +; * +; /*Set buffers*/ * +; IF (EMS_MODE <> -1) THEN * +; Set_EMS_Buffer * +; ELSE /*Do not use the extended memory */ * +; Set_Buffer; * +;/*Now set the caches if specified.*/ * +; IF (BuffINFO.Cache_count > 0) THEN * +; {Set BuffINFO.Cache_ptr to MEMHI:MEMLO; * +; MEMHI:MEMLO = MEMHI:MEMLO + 512 * BuffINFO.Cache_count; * +; }; * +; }; * +; * +;******************************************************************************* +DOBUFF: ;AN000; + lds bx, cs:[DosInfo] ;AN000; ds:bx -> SYSINITVAR + + mov ax, [Buffers] ;AN000;Set SYSI_BUFFERS + mov word ptr ds:[bx.SYSI_BUFFERS], ax ;AN000; + mov ax, [H_Buffers] ;AN000; + mov word ptr ds:[bx.SYSI_BUFFERS+2], ax ;AN000; + + lds bx, ds:[bx.SYSI_BUF] ;AN000; now, ds:bx -> BuffInfo + cmp ds:[bx.EMS_MODE], -1 ;AN000; +; $IF E, LONG ;AN000; + JE $$XL1 + JMP $$IF1 +$$XL1: + xor dx, dx ;AN000; + mov ax, [Buffers] ;AN000; < 99 + cmp al, 30 ;AN026; if less than 30, +; $IF B ;AN026; + JNB $$IF2 + mov [BufferBuckets], 1 ;AN026; then put every buffer + mov ds:[bx.HASH_COUNT], 1 ;AN026; into one bucket + mov [MaxNumBuf1], al ;AN026; + mov [NthBuck], 1 ;AN026; +; $ELSE ;AN026; else... + JMP SHORT $$EN2 +$$IF2: + mov cl, 15 ;AN026; Magic number 15. + div cl ;AN026; al=# of buckets, ah=remainders + push ax ;AN026; save the result + xor ah, ah ;AN026; + mov [BufferBuckets], ax ;AN026; + mov ds:[bx.HASH_COUNT], ax ;AN026; + pop ax ;AN026; + or ah, ah ;AN026; +; $IF Z ;AN026;if no remainders + JNZ $$IF4 + mov [NthBuck], al ;AN026;then set NthBuck=# of bucket for Set_Buffer proc. +; $ELSE ;AN026;else + JMP SHORT $$EN4 +$$IF4: + mov cl, al ;AN026; + mov al, ah ;AN026;remainder/# of buckets + xor ah, ah ;AN026; = + div cl ;AN026;al=additional num of buffers + or ah, ah ;AN026;ah=Nth bucket +; $IF Z ;AN026; + JNZ $$IF6 + add [MaxNumBuf1], al ;AN026; + mov ax, [BufferBuckets] ;AN026; + mov [NthBuck], al ;AN026; +; $ELSE ;AN026; + JMP SHORT $$EN6 +$$IF6: + mov [NthBuck], ah ;AN026; + add [MaxNumBuf1], al ;AN026;MaxNumNuf are initially set to 15. + add [MaxNumBuf2], al ;AN026; + inc [MaxNumBuf1] ;AN026;Additional 1 more buffer for group 1 buckets. +; $ENDIF ;AN026; +$$EN6: +; $ENDIF ;AN026; +$$EN4: +; $ENDIF ;AN026; +$$EN2: +; $ELSE ;AN000; Use the extended memory. + JMP SHORT $$EN1 +$$IF1: + mov ax, [Buffer_Pages] ;AN000; + mov cx, MAXBUCKETINPAGE ;AN000; + mul cx ;AN000; gauranteed to be word boundary. + mov [BufferBuckets], ax ;AN000; + mov ds:[bx.HASH_COUNT], ax ;AN000; +; $ENDIF ;AN000; +$$EN1: + invoke Round ;AN000; get [MEMHI]:[MEMLO] + mov al, DEVMARK_BUF ;AN005; ='B' + call SetDevMark ;AN005; +;Now, allocate Hash table at [memhi]:[memlo]. AX = Hash_Count. + mov ax, [BufferBuckets] ;AN026; # of buckets==Hash_Count + mov cx, size BUFFER_HASH_ENTRY ;AN000; + mul cx ;AN000; now AX = Size of hash table. + les di, ds:[bx.HASH_PTR] ;AN000; save Single buffer address. + mov cx, [MemLo] ;AN000; + mov word ptr ds:[bx.HASH_PTR], cx ;AN000; set BuffINFO.HASH_PTR + mov cx, [MemHi] ;AN000; + mov word ptr ds:[bx.HASH_PTR+2], cx ;AN000; + mov [Memlo], ax ;AN000; + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + call Round ;AN000; get new [memhi]:[memlo] +;Allocate buffers + push ds ;AN000; Save Buffer info. ptr. + push bx ;AN000; + cmp ds:[bx.EMS_MODE], -1 ;AN000; +; $IF NE ;AN000; + JE $$IF13 + call Set_EMS_Buffer ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN13 +$$IF13: + call Set_Buffer ;AN000; +; $ENDIF ;AN000; +$$EN13: + pop bx ;AN000; + pop ds ;AN000; +;Now set the secondary buffer if specified. + cmp [H_Buffers], 0 ;AN000; +; $IF NE ;AN000; + JE $$IF16 + call Round ;AN000; + mov cx, [MemLo] ;AN000; + mov word ptr ds:[bx.CACHE_PTR], cx ;AN000; + mov cx, [MemHi] ;AN000; + mov word ptr ds:[bx.CACHE_PTR+2], cx ;AN000; + mov cx, [H_Buffers] ;AN000; + mov ds:[bx.CACHE_COUNT], cx ;AN000; + mov ax, 512 ;AN000; 512 byte + mul cx ;AN000; + mov [Memlo], ax ;AN000; + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + call Round ;AN000; +; $ENDIF ;AN000; +$$IF16: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;J.K. END OF NEW BUFFER SCHEME. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;DOBUFF: +; INVOKE ROUND +; DEC [BUFFERS] ; FIRST DEC acounts for buffer already +; ; in system. +; JZ BUF1 ; All done +; PUSH DS +; LES DI,BUFPTR +; LDS BX,DOSINFO +; MOV AX,WORD PTR [BX.SYSI_BUF] ; Link in new buffer +; MOV WORD PTR ES:[DI.buf_link],AX +; MOV AX,WORD PTR [BX.SYSI_BUF+2] +; MOV WORD PTR ES:[DI.buf_link+2],AX +; MOV WORD PTR [BX.SYSI_BUF],DI +; MOV WORD PTR [BX.SYSI_BUF+2],ES +; MOV WORD PTR ES:[DI.buf_ID],00FFH ;NEW BUFFER FREE +; mov word ptr es:[di.buf_Sector],0 ;AN000; +; mov word ptr es:[di.buf_Sector+2],0 ;AN000; +; MOV BX,[BX.SYSI_MAXSEC] +; POP DS +; ADD BX,BUFINSIZ +; ADD [MEMLO],BX +; JMP DOBUFF + +;------------------------------------------------------------------------------ +; Allocate CDSs +;------------------------------------------------------------------------------ +BUF1: + INVOKE ROUND + push ax ;AN005; + mov ax, DEVMARK_CDS ;AN005;='L' + call SetDevMark ;AN005; + pop ax ;AN005; + LES DI,[DOSINFO] + MOV CL,BYTE PTR ES:[DI.SYSI_NUMIO] + CMP CL,[NUM_CDS] + JAE GOTNCDS ; User setting must be at least NUMIO + MOV CL,[NUM_CDS] +GOTNCDS: + XOR CH,CH + MOV ES:[DI.SYSI_NCDS],CL + MOV AX,[MEMHI] + MOV WORD PTR ES:[DI.SYSI_CDS + 2],AX + MOV AX,[MEMLO] + MOV WORD PTR ES:[DI.SYSI_CDS],AX + MOV AL,CL + MOV AH,SIZE curdir_list + MUL AH + call ParaRound + ADD [MEMHI],AX + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before initializing + LDS SI,ES:[DI.SYSI_DPB] +ASSUME DS:NOTHING + LES DI,ES:[DI.SYSI_CDS] + CALL FOOSET + +;------------------------------------------------------------------------------ +; Allocate Space for Internal Stack +;------------------------------------------------------------------------------ + + IF STACKSW + + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + IF IBM +;Don't install the system stack on the PCjr. Ignore STACKS=command too. + CMP [Sys_Model_Byte], 0FDh ; PCjr = 0FDh + JE SkipStack_brdg + ENDIF + +;J.K. 10/15/86 DCR00013 +;If the use does not entered STACKS= command, as a default, do not install +;sytem stacks for PC1, PC XT, PC Portable cases. +;Otherwise, install it to the user specified value or to the default +;value of 9, 128 for the rest of the system. + + cmp word ptr [stack_addr], -1 ;Has the user entered "stacks=" command? + je DoInstallStack ;Then install as specified by the user + cmp [Sys_Scnd_Model_Byte], 0 ;PC1, XT has the secondary model byte = 0 + jne DoInstallStack ;Other model should have default stack of 9, 128 + cmp [Sys_Model_Byte], 0FFh ;PC1 ? + je SkipStack_brdg + cmp [Sys_Model_Byte], 0FEh ;PC/XT or PC Portable ? + jne DoInstallStack +SkipStack_Brdg: + jmp SkipStack +DoInstallStack: + mov ax, [stack_count] ;J.K. Stack_count = 0? + cmp ax, 0 ;then, stack size must be 0 too. + jz SkipStack_brdg ;Don't install stack. +;J.K. 10/21/86 Dynamic Relocation of Stack code. + call Round ;[memhi] = Seg. for stack code + ;[memlo] = 0 +;J.K. Set DEVMARK block into memory for MEM command +;J.K. DEVMARK_ID = 'S' for stack + mov al, DEVMARK_STK ;AN005;='S' + call SetDevMark + + mov ax, [memhi] + mov es, ax ;ES -> Seg. the stack code is going to move. + assume es:nothing + push cs + pop ds + xor si,si ;!!We know that Stack code is at the beginning of SYSINIT. + xor di,di + mov cx, offset Endstackcode + mov [memlo],cx + call Round ;Have enough space for relocation? + rep movsb + + mov ax, [memlo] + mov word ptr [stack_addr],ax ;set for stack area initialization + mov ax, [memhi] ;This will be used by Stack_Init routine. + mov word ptr [stack_addr+2],ax + +; Space for Internal Stack area = STACK_COUNT(ENTRYSIZE + STACK_SIZE) + MOV AX, EntrySize + ADD AX, [STACK_SIZE] + MOV CX, [STACK_COUNT] + MUL CX + call ParaRound ; Convert size to pargraphs + ADD [MEMHI], AX + or [SetDevMarkFlag], FOR_DEVMARK ;AN005;To set the DEVMARK_SIZE for Stack by ROUND routine. + INVOKE ROUND ; Check for memory error before + ; continuing + CALL StackInit ; Initialize hardware stack. CS=DS=sysinitseg, ES=Relocated stack code & data + +SkipStack: + ENDIF + + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + MOV AL,[FILES] + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV CX,AX + XOR BX,BX ;Close standard input + MOV AH,CLOSE + INT 21H + MOV BX,2 +RCCLLOOP: ;Close everybody but standard output + MOV AH,CLOSE ; Need output so we can print message + INT 21H ; in case we can't get new one open. + INC BX + LOOP RCCLLOOP + + MOV DX,OFFSET CONDEV + MOV AL,2 + MOV AH,OPEN ;OPEN CON FOR READ/WRITE + STC ; Set for possible INT 24 + INT 21H + JNC GOAUX + INVOKE BADFIL + JMP SHORT GOAUX2 + +GOAUX: PUSH AX + MOV BX,1 ;close standard output + MOV AH,CLOSE + INT 21H + POP AX + + MOV BX,AX ;New device handle + MOV AH,XDUP + INT 21H ;Dup to 1, STDOUT + MOV AH,XDUP + INT 21H ;Dup to 2, STDERR + +GOAUX2: MOV DX,OFFSET AUXDEV + MOV AL,2 ;READ/WRITE ACCESS + INVOKE OPEN_DEV + + MOV DX,OFFSET PRNDEV + MOV AL,1 ;WRITE ONLY + INVOKE OPEN_DEV + +;J.K.9/29/86 ******************* +;Global Rearm command for Shared Interrupt devices attached in the system; +;Shared interrupt attachment has some problem when it issues interrupt +;during a warm reboot. Once the interrupt is presented by the attachment, +;no further interrupts on that level will be presented until a global rearm +;is issued. By the request of the system architecture group, IBMBIO will +;issue a global rearm after every device driver is loaded. +;To issue a global rearm: ;For PC1, XT, Palace +; OUT 02F2h, XX ; Interrupt level 2 +; OUT 02F3h, XX ; Interrupt level 3 +; OUT 02F4h, XX ; Interrupt level 4 +; OUT 02F5h, XX ; Interrupt level 5 +; OUT 02F6h, XX ; Interrupt level 6 +; OUT 02F7h, XX ; Interrupt level 7 +; +; ;For PC AT, in addition to the above commands, +; ;need to handle the secondary interrupt handler +; OUT 06F2h, XX ; Interrupt level 10 +; OUT 06F3h, XX ; Interrupt level 11 +; OUT 06F4h, XX ; Interrupt level 12 +; OUT 06F6h, XX ; Interrupt level 14 +; OUT 06F7h, XX ; Interrupt level 15 +; +; ;For Round-Up machine +; None. +; where XX stands for any value. +; For your information, after Naples level machine, the system service bios +; call (INT 15h), function AH=0C0h returns the system configuration parameters +; + + cmp [sys_model_byte], 0FDh ;PCjr? +; je GoCheckInstall + je Set_Sysinit_Base +;SB33045******************************************************************* + push ax ;Save Regs ;SB ;3.30* + push bx ; * ;SB ;3.30* + push dx ; * ;SB ;3.30* + push es ; * ;SB ;3.30* + mov al,0ffh ;Reset h/w by writing to port ;SB ;3.30* + mov dx,2f2h ;Get starting address ;SB ;3.30* + out dx,al ; out 02f2h,0ffh + inc dx + out dx,al ; out 02f3h,0ffh + inc dx + out dx,al ; out 02f4h,0ffh + inc dx + out dx,al ; out 02f5h,0ffh + inc dx + out dx,al ; out 02f6h,0ffh + inc dx + out dx,al ; out 02f7h,0ffh +;SB33045******************************************************************* + +;SB33046******************************************************************* +;SB Secondary global rearm ;3.30 + mov ax,0f000h ;Get machine type ;SB ;3.30* + mov es,ax ; * ;SB ;3.30* + cmp byte ptr es:[0fffeh],0fch ;Q:Is it a AT type machine ;SB ;3.30* + je startrearm ; *if AT no need to check + mov ah,0c0h ;Get system configuration ;SB ;3.30* + int 15h ; * ;SB ;3.30* + jc finishrearm ; *jmp if old rom ;SB ;3.30* +; ;SB ;3.30* +; Test feature byte for secondary interrupt controller ;SB ;3.30* +; ;SB ;3.30* + test es:[bx.bios_SD_featurebyte1],ScndIntController ; ;SB ;3.30* + je finishrearm ;Jmp if it is there ;SB ;3.30* +startrearm: + mov al,0ffh ;Write any pattern to port ;SB ;3.30* + mov dx,6f2h ;Get starting address ;SB ;3.30* + out dx,al ;out 06f2h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f3h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f4h,0ffh + inc dx ;Bump address ;SB ;3.30* + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f6h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f7h,0ffh +finishrearm: ; ;SB ;3.30* + pop es ;Restore regs ;SB ;3.30* + pop dx ; * ;SB ;3.30* + pop bx ; * ;SB ;3.30* + pop ax ; * ;SB ;3.30* +;SB33046******************************************************************* + +;J.K. 9/29/86 Global Rearm end ******************* + +;------------------------------------------------------------------------------ +; Allocate SYSINIT_BASE for INSTALL= command +;------------------------------------------------------------------------------ +;J.K. SYSINIT_BASE allocation. +;Check if ENDFILE has been called to handle INSTALL= command. + +Set_Sysinit_Base: +;GoCheckInstall: +; test [Install_Flag], HAVE_INSTALL_CMD ;AN019;;AN021;install sysinit base all the time. +; jz Skip_SYSINIT_BASE ;AN019; + +;J.K.-------------------------------------------------------------------------- +;SYSINIT_BASE will be established in the secure area of +;lower memory when it handles the first INSTALL= command. +;SYSINIT_BASE is the place where the actual EXEC function will be called and +;will check SYSINIT module in high memory if it is damaged by the application +;program. If SYSINIT module has been broken, then "Memory error..." message +;is displayed by SYSINIT_BASE. +;------------------------------------------------------------------------------ + push ax ;AN013; Set DEVMARK for MEM command + mov ax, [memhi] ;AN013; + sub ax, [area] ;AN013; + mov [Impossible_owner_size], ax ;AN013;Remember the size in case. + mov al, DEVMARK_INST ;AN013; + call SetDevMark ;AN013; + pop ax ;AN013; + + mov di, [memhi] ;AN000; + mov es, di ;AN000; + assume es:nothing ;AN000; + mov word ptr [sysinit_base_ptr+2],di ;AN000; save this entry for the next use. + xor di, di ;AN000; + mov word ptr [sysinit_base_ptr], di ;AN000; es:di -> destination. + mov si, offset SYSINIT_BASE ;AN000; ds:si -> source code to be relocated. + mov cx, Size_SYSINIT_BASE ;AN000; + add [memlo],cx ;AN000; + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN013; + call round ;AN000; check mem error. Also, readjust MEMHI for the next use. + rep movsb ;AN000; reallocate it. + + mov word ptr [Sysinit_Ptr], offset SYSINITPTR ;AN000; Returing address from + mov word ptr [Sysinit_Ptr+2], cs ;AN000; SYSINIT_BASE back to SYSINIT. + or [Install_Flag],HAS_INSTALLED ;AN000; Set the flag. + +;------------------------------------------------------------------------------ +; Free the rest of the memory from MEMHI to CONFBOT. Still from CONFBOT to +; the top of the memory will be allocated for SYSINIT and CONFIG.SYS if +; HAVE_INSTALL_CMD. +;------------------------------------------------------------------------------ +;Skip_SYSINIT_BASE: ;AN021; + + INVOKE ROUND + MOV BX,[MEMHI] + MOV AX,[AREA] + mov [Old_Area], ax ;AN013; Save [AREA] + MOV ES,AX ;CALC WHAT WE NEEDED + SUB BX,AX + MOV AH,SETBLOCK + INT 21H ;GIVE THE REST BACK + PUSH ES + MOV AX,ES + DEC AX + MOV ES,AX ;Point to arena + MOV ES:[arena_owner],8 ;Set impossible owner + POP ES + + mov bx,0ffffh ;AN000; + mov ah,Alloc ;AN000; + int 21h ;AN000; + mov ah,Alloc ;AN000; + int 21h ;AN000; Allocate the rest of the memory + + mov [memhi],ax ;AN000; Start of the allocated memory + mov [memlo],0 ;AN000; to be used next. + + ;;;; At this moment, memory from [MEMHI]:0 to Top-of-the memory is + ;;;; allocated. + ;;;; To protect sysinit, confbot module (From CONFBOT (or =ALLOCLIM at + ;;;; this time) to the Top-of-the memory), here we are going to + ;;;; 1). "SETBLOCK" from MEMHI to CONFBOT. + ;;;; 2). "ALLOC" from CONFBOT to the top of the memory. + ;;;; 3). "Free Alloc Memory" from MEMHI to CONFBOT. +;Memory allocation for SYSINIT, CONFBOT module. + mov es, ax ;AN000; + mov bx, [confbot] ;AN000; + sub bx, ax ;AN000; CONFBOT - MEMHI + dec bx ;AN000; Make a room for the memory block id. + dec bx ;AN000; make sure!!!. + mov ah, SETBLOCK ;AN000; + int 21h ;AN000; this will free (CONFBOT to top of memory) + mov bx, 0ffffh ;AN000; + mov ah, ALLOC ;AN000; + int 21h ;AN000; + mov ah, ALLOC ;AN000; + int 21h ;AN000; allocate (CONFBOT to top of memory) + mov [area],ax ;AN000; Save Allocated memory segment. + ;AN000; Need this to free this area for COMMAND.COM. + mov es, [memhi] ;AN000; + mov ah, 49h ;AN000; Free Allocated Memory. + int 21h ;AN000; Free (Memhi to CONFBOT(=AREA)) + +; IF NOEXEC +; MOV BX,0FFFFH ;ALLOCATE THE REST OF MEM FOR COMMAND +; MOV AH,ALLOC +; INT 21H +; MOV AH,ALLOC +; INT 21H +; MOV DS,AX +; ENDIF + +; test cs:[Install_Flag],IS_INSTALL ;AN000; +; jnz DO_Install_Exec ;AN000; + +ENDFILE_Ret: + return + + +Do_Install_Exec proc near ;AN000; Now, handles INSTALL= command. + + push si ;AN000; save SI for config.sys again. + + ;;;; We are going to call LOAD/EXEC function. + ;;;;;Set ES:BX to the parameter block here;;;;;;; + ;;;;;Set DS:DX to the ASCIIZ string. Remember that we already has 0 + ;;;;;after the filename. So parameter starts after that. If next + ;;;;;character is a line feed (i.e. 10), then assume that the 0 + ;;;;;we already encountered used to be a carrage return. In this + ;;;;;case, let's set the length to 0 which will be followed by + ;;;;;carridge return. +;J.K. ES:SI -> command line in CONFIG.SYS. Points to the first non blank +;character after =. + push es ;AN000; + push ds ;AN000; + pop es ;AN000; + pop ds ;AN000; es->sysinitseg, ds->confbot seg + assume ds:nothing ;AN000; + mov dx, si ;AN000; ds:dx->file name,0 in CONFIG.SYS image. +;AN016; UNDO THE EXTENDED ATTRIBUTES HANDLING +; mov ax, OPEN SHL 8 ;AN008; +; int 21h ;AN008; +; jc SysInitPtr ;AN008; +; mov bx, ax ;AN008;handle +; call Get_Ext_Attribute ;AN008;Get the extended attribute. +; cmp al, EA_INSTALLABLE ;AN008; +; je EA_Installable_OK ;AN012; +; stc ;AN012; +; jmp SysInitPtr ;AN012; +;EA_Installable_OK: ;AN012; + xor cx,cx ;AN000; + cld ;AN000; + mov cs:Ldexec_start, ' ' ;AN015; Clear out the parm area + mov di, offset Ldexec_parm ;AN000; +InstallFilename: ;AN000; skip the file name + lodsb ;AN000; al = ds:si; si++ + cmp al, 0 ;AN000; + je Got_InstallParm ;AN000; + jmp InstallFilename ;AN000; +Got_InstallParm: ;AN000; copy the parameters to Ldexec_parm + lodsb ;AN000; + mov es:[di], al ;AN000; + cmp al, LF ;AN000;AN028; line feed? + je Done_InstallParm ;AN000;AN028; + inc cl ;AN000; # of char. in the parm. + inc di ;AN000; + jmp Got_Installparm ;AN000; +Done_Installparm: ;AN000; + mov byte ptr cs:[Ldexec_line], cl ;AN000; length of the parm. + cmp cl, 0 ;AN015;If no parm, then + jne Install_Seg_Set ;AN015; let the parm area + mov byte ptr cs:[Ldexec_Start],CR ;AN015; starts with CR. +Install_Seg_Set: ;AN015; + mov word ptr cs:0, 0 ;AN000; Make a null environment segment + mov ax, cs ;AN000; by overlap JMP instruction of SYSINITSEG. + mov cs:[INSTEXE.EXEC0_ENVIRON],ax ;AN000; Set the environment seg. + mov word ptr cs:[INSTEXE.EXEC0_COM_LINE+2],ax ;AN000; Set the seg. + mov word ptr cs:[INSTEXE.EXEC0_5C_FCB+2],ax ;AN000; + mov word ptr cs:[INSTEXE.EXEC0_6C_FCB+2],ax ;AN000; + call Sum_up ;AN000; + mov es:CheckSum, ax ;AN000; save the value of the sum + xor ax,ax ;AN000; + mov ah, EXEC ;AN000; Load/Exec + mov bx, offset INSTEXE ;AN000; ES:BX -> parm block. + push es ;AN000; Save es,ds for Load/Exec + push ds ;AN000; these registers will be restored in SYSINIT_BASE. + jmp cs:dword ptr SYSINIT_BASE_PTR ;AN000; jmp to SYSINIT_BASE to execute + ; LOAD/EXEC function and check sum. + +;J.K. This is the returning address from SYSINIT_BASE. +SYSINITPTR: ;AN000; returning far address from SYSINIT_BASE + pop si ;AN000; restore SI for CONFIG.SYS file. + push es ;AN000; + push ds ;AN000; + pop es ;AN000; + pop ds ;AN000; now ds - sysinitseg, es - confbot + jnc Exec_Exit_Code + test cs:Install_Flag, SHARE_INSTALL ;AN021; Called by LoadShare proc? + jnz Install_Error_Exit ;AN021; Just exit with carry set. + push si ;AN000; Error in loading the file for INSTALL=. + call BadLoad ;AN000; ES:SI-> path,filename,0. + pop si ;AN000; + jmp Install_Exit_Ret +Exec_Exit_Code: + test cs:Install_Flag, SHARE_INSTALL ;AN021; Called by LoadShare proc? + jnz Install_Exit_Ret ;AN021; Just exit. + mov ah, 4dh ;AN017; + int 21h ;AN017; + cmp ah, 3 ;AN017;Only accept "Stay Resident" prog. + je Install_Exit_Ret ;AN017; + call Error_Line ;AN017;Inform the user +Install_Error_Exit: ;AN021; + stc ;AN021; +Install_Exit_Ret: + ret +Do_Install_Exec endp + +Public ParaRound +ParaRound: + ADD AX,15 + RCR AX,1 + SHR AX,1 + SHR AX,1 + SHR AX,1 + return + +;------------------------------------------------------------------------------ +;J.K. SYSINIT_BASE module. +;In: After relocation, +; AX = 4B00h - Load and execute the program DOS function. +; DS = CONFBOT. Segment of CONFIG.SYS file image +; ES = Sysinitseg. Segment of SYSINIT module itself. +; DS:DX = pointer to ASCIIZ string of the path,filename to be executed. +; ES:BX = pointer to a parameter block for load. +; SYSSIZE (Byte) - offset vaule of End of SYSINIT module label +; BIGSIZE (word) - # of word from CONFBOT to SYSSIZE. +; CHKSUM (word) - Sum of every byte from CONFBOT to SYSSIZE in a +; word boundary moduler form. +; SYSINIT_PTR (dword ptr) - Return address to SYSINIT module. +;Note: SYSINIT should save necessary registers and when the control is back + + + public Sysinit_Base +Sysinit_Base: ;AN000; + mov word ptr cs:SYSINIT_BASE_SS, SS ;AN000; save stack + mov word ptr cs:SYSINIT_BASE_SP, SP ;AN000; + int 21h ;AN000; LOAD/EXEC DOS call. + mov SS, word ptr cs:SYSINIT_BASE_SS ;AN000; restore stack + mov SP, word ptr cs:SYSINIT_BASE_SP ;AN000; + pop ds ;AN000; restore CONFBOT seg + pop es ;AN000; restore SYSINITSEG + jc SysInit_Base_End ;AN000; LOAD/EXEC function failed. + ;At this time, I don't have to worry about + ;that SYSINIT module has been broken or not. + call Sum_up ;AN000; Otherwise, check if it is good. + cmp es:CheckSum, AX ;AN000; + je SysInit_Base_End ;AN000; +;Memory broken. Show "Memory allocation error" message and stall. + mov ah, 09h ;AN000; + push cs ;AN000; + pop ds ;AN000; + mov dx, Mem_alloc_err_msg ;AN000; + int 21h ;AN000; +Stall_now: jmp Stall_now ;AN000; + +SysInit_Base_End: jmp es:Sysinit_Ptr ;AN000; return back to sysinit module + +Sum_up: ;AN000; +;In: +; ES - SYSINITSEG. +;OUT: AX - Result +;Remark: Since this routine will only check starting from "LocStack" to the end of +; Sysinit segment, the data area, and the current stack area are not +; coverd. In this sense, this check sum routine only gives a minimal +; gaurantee to be safe. +;First sum up CONFBOT seg. + push ds ;AN021; + mov ax,es:ConfBot ;AN021; + mov ds,ax ;AN021; + xor si,si ;AN000; + xor ax,ax ;AN000; + mov cx,es:Config_Size ;AN000; If CONFIG_SIZE has been broken, then this + ;whole test better fail. + shr cx, 1 ;AN000; make it a word count + jz Sum_Sys_Code ;AN025; When CONFIG.SYS file not exist. +Sum1: ;AN000; + add ax, ds:word ptr [si] ;AN000; + inc si ;AN000; + inc si ;AN000; + loop Sum1 ;AN000; +;Now, sum up SYSINIT module. +Sum_Sys_Code: ;AN025; + mov si, offset LocStack ;AN000; Starting after the stack. + ;AN000; This does not cover the possible STACK code!!! + mov cx, offset SYSSIZE ;AN000; SYSSIZE is the label at the end of SYSINIT + sub cx, si ;AN000; From After_Checksum to SYSSIZE + shr cx, 1 ;AN000; +Sum2: ;AN000; + add ax, es:word ptr [si] ;AN000; + inc si ;AN000; + inc si ;AN000; + loop Sum2 ;AN000; + pop ds ;AN021; + ret ;AN000; + +Sysinit_Base_SS equ $-Sysinit_Base ;AN000; + dw ? ;AN000; +Sysinit_Base_SP equ $-Sysinit_Base ;AN000; + dw ? ;AN000; +Mem_Alloc_Err_msg equ $-Sysinit_Base ;AN000; +;include BASEMES.INC ;AN000; Memory allocation error message +include MSBIO.CL4 ;AN011; Memory allocation error message +End_Sysinit_Base label byte ;AN000; +SIZE_SYSINIT_BASE equ $-Sysinit_Base ;AN000; + +; +;AN016; Undo the extended attribute handling +; public Get_Ext_Attribute +;Get_Ext_Attribute proc near ;AN008; +;;In: BX - file handle +;;Out: AL = The extended attribute got from the handle. +;; AX destroyed. +;; Carry set when DOS function call fails. +; +; push ds ;AN008; +; push si ;AN008; +; push es ;AN008; +; push di ;AN008; +; push cx ;AN008; +; +; push cs ;AN008; +; pop ds ;AN008; +; push cs ;AN008; +; pop es ;AN008; +; +; mov Ext_Attr_Value, 0ffh ;AN008; Initialize to unrealistic value +; mov ax, 5702h ;AN008;Get extended attribute by handle thru LIST +; mov si, offset EA_QueryList ;AN008; +; mov di, offset Ext_Attr_List ;AN008; +; mov cx, SIZE_EXT_ATTR_LIST ;AN008; +; int 21h ;AN008; +; mov al, Ext_Attr_Value ;AN008; +; pop cx ;AN008; +; pop di ;AN008; +; pop es ;AN008; +; pop si ;AN008; +; pop ds ;AN008; +; ret ;AN008; +;Get_Ext_Attribute endp ;AN008; + + +;------------------------------------------------------------------------------ + +DoEMS proc near +;******************************************************************************* +; Function: Called prior to DOBUFF subroutine. Only called when /E option * +; for the buffers= command has been specified. * +; This routine will check if the extended memory is avaiable, * +; and determine what is the page number. We only use physical page * +; 254. if it is there, then this routine will calculate the number * +; of pages needed for buffers and will allocate logical pages in the * +; extended memory and get the page handle of them. * +; * +; Input : * +; Buffers - Number of buffers * +; Buffer_LineNum - Saved line number to be used in case of Error case * +; * +; Output: * +; BuffINFO.EMS_Handle * +; Buffer_Pages = Number of pages for buffer in the extended memory. * +; BuffINFO.EMS_MODE = -1 No extended memory or Non-IBM compatible mode. * +; Buffers = the number will be changed to be a multiple of 30. * +; Carry set if no extended memory exist or if it is not big enough. * +; AX, BX, CX, DX destroyed. * +; * +; Logic: * +; { * +; Get EMS Version (AH=46h); * +; If (EMS not installed or it is not IBM compatible or * +; (Available_pages * 30 < Buffers) then * +; {Show error message "Error in CONFIG.SYS line #"; * +; Set carry; Exit }; * +; else * +; Buffer_Pages = Roundup(BUFFERS/30); /* Round up 30 buffers per page*/ * +; Buffers = Buffer_Pages * 30; /* Set the new number of Buffers*/* +; Allocate Buffer_Pages (AH=43h) and set EMS_Handle; * +; }; * +; * +;******************************************************************************* + + push es ;AN000; + push di ;AN000; save es, di + push si ;AN010; + push bx ;AN010; + xor di,di ;AN004; if vector pointer of + mov es, di ;AN004; EMS (INT 67h) is 0,0 + mov di, word ptr es:[EMS_INT * 4] ;AN004; then error. + mov ax, word ptr es:[EMS_INT * 4 +2] ;AN009; + or ax,di ;AN009; +; $IF NZ,AND,LONG ;AN004; + JNZ $$XL2 + JMP $$IF18 +$$XL2: + les di, cs:[DosInfo] ;AN000; es:di -> SYSINITVAR + les di, es:[di.SYSI_BUF] ;AN000; now, es:di -> BuffInfo + + mov ah, EMS_STATUS ;AN000; get the status of EMS = 40h + int EMS_INT ;AN000; + or ah, ah ;AN000; EMS installed? +; $IF Z,AND,LONG ;AN000; + JZ $$XL3 + JMP $$IF18 +$$XL3: + mov ah, EMS_VERSION ;AN010;=46h + int EMS_INT ;AN010; + cmp AL, EMSVERSION ;AN010;40h = 4.0 +; $IF AE,AND,LONG ;AN010; + JAE $$XL4 + JMP $$IF18 +$$XL4: + call Check_IBM_PageID ;AN000; IBM (compatible) mode? + +IF BUFFERFLAG + mov ax, cs:[LAST_PAGE] + mov es:[di.EMS_LAST_PAGE], ax + mov ax, cs:[LAST_PAGE+2] + mov es:[di.EMS_LAST_PAGE+2], ax + mov ax, cs:[FIRST_PAGE] + mov es:[di.EMS_FIRST_PAGE], ax + mov ax, cs:[FIRST_PAGE+2] + mov es:[di.EMS_FIRST_PAGE+2], ax + mov ax, cs:[NPA640] + mov es:[di.EMS_NPA640], ax + mov es:[di.EMS_SAFE_FLAG], 1 +ENDIF + +; $IF NC,AND,LONG ;AN000; + JNC $$XL5 + JMP $$IF18 +$$XL5: + mov ah, EMAP_STATE ;AN010; Check if the size of + mov al, GET_MAP_SIZE ;AN010; the MAP state table + mov bx, 1 ;AN010; # of pages + int EMS_INT ;AN010; is acceptable. + or ah, ah ;AN010; +; $IF Z,AND ;AN010; + JNZ $$IF18 + cmp al, EMS_MAP_BUFF_SIZE ;AN010; Curretly=12 bytes +; $IF BE,AND ;AN010; + JNBE $$IF18 + mov ah, EQ_PAGES ;AN000; Get number of unallocated & total pages = 42h + int EMS_INT ;AN000; result in BX + xor dx, dx ;AN000; + mov ax, cs:[Buffers] ;AN000; + mov cx, MAXBUFFINBUCKET*MAXBUCKETINPAGE ;AN000; + call Roundup ;AN000; find out how many pages are needed. + cmp bx, ax ;AN000; AX is the number of pages for [buffers] +; $IF AE,AND ;AN000; + JNAE $$IF18 + mov cs:[Buffer_Pages], ax ;AN000; + mov bx, ax ;AN000; prepare for Get handle call. + mul cx ;AN000; + mov cs:[Buffers], ax ;AN000; set new [Buffers] for the extended memory. + mov ah, E_GET_HANDLE ;AN000; allocate pages = 43h + int EMS_INT ;AN000; page handle in DX. + or ah, ah ;AN000; +; $IF Z ;AN000; pages allocated. + JNZ $$IF18 + mov ah, EMS_HANDLE_NAME ;AN010; + mov al, SET_HANDLE_NAME ;AN010; + push es ;AN010; + push di ;AN010; + push ds ;AN010; + push cs ;AN010; + pop ds ;AN010; + mov si, offset EMSHandleName ;AN010; + int EMS_INT ;AN010; Set the handle name + pop ds ;AN010; + pop di ;AN010; + pop es ;AN010; + xor ah,ah ;AN010; + mov es:[di.EMS_MODE], ah ;AN000; put 0 in EMS_mode. + mov es:[di.EMS_HANDLE], dx ;AN000; save EMS handle + mov ax, cs:[IBM_Frame_Seg] ;AN010; + mov es:[di.EMS_PAGE_FRAME],ax ;AN010; + mov ax, cs:[Real_IBM_Page_Id] ;AN029; + mov es:[di.EMS_PAGEFRAME_NUMBER], ax;AN029; + mov ax, es ;AN010; + mov word ptr cs:[EMS_Ctrl_tab+2],ax ;AN010; + mov word ptr cs:[EMS_state_buf+2],ax;AN010; + push di ;AN010;save di-> Buffinfo + add di, EMS_SEG_CNT ;AN010; + mov word ptr cs:[EMS_Ctrl_tab], di ;AN010; + pop di ;AN010; + add di, EMS_MAP_BUFF ;AN010; + mov word ptr cs:[EMS_state_Buf],di ;AN010; + clc ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN18 +$$IF18: + mov ax, cs:[Buffer_LineNum] ;AN000; Show error message. + push cs:[LineCount] ;AN017; Save current line count + mov cs:[LineCount], ax ;AN000; Now, we can change Linecount + call Error_Line ;AN000; since we are through with CONFIG.SYS file. + pop cs:[LineCount] ;AN017; Restore line count + stc ;AN000; +; $ENDIF +$$EN18: + pop bx ;AN010; + pop si ;AN010; + pop di ;AN000; + pop es ;AN000; + ret ;AN000; +DoEMS endp + +; +Set_Buffer proc near +;******************************************************************************* +;Function: Set buffers in the real memory. * +; For each hash table entry, set the pointer to the * +; corresponding hash bucket. * +; Lastly set the memhi, memlo for the next available free address. * +; ** At the request of IBMDOS, each hash bucket will start at the * +; ** new segment. * +; * +;Input: ds:bx -> BuffInfo. * +; [Memhi]:[MemLo = 0] = available space for the hash bucket. * +; BufferInfo.Hash_Ptr -> Hash table. * +; BufferBuckets = # of buckets to install. * +; SingleBufferSize = Buffer header size + Sector size * +; MaxNumBuff1 = Number of buffers in the first group of buckets * +; MaxNumBuff2 = Number of buffers in the second group of buckets * +; NthBuck = 1st thru Nth bucket are the first group * +; * +;Output: Buffers, hash buckets and Hash table entries established. * +; [Memhi]:[Memlo] = address of the next available free space. * +; * +; { For (every bucket) * +; { Set Hash table entry; * +; Next buffer ptr = buffer size; * +; For (every buffer in the bucket) * +; { Calll Set_Buffer_Info; /*Set link, id... */ * +; IF (last buffer in a bucket) THEN * +; {last buffer's next_ptr -> first buffer; * +; first buffer's prev_ptr -> last buffer; * +; }; * +; Next buffer ptr += buffer size; * +; }; * +; }; * +; MEMHI:MEMLO = Current Buffer_Bucket add + (# of odd * buffer size)* +; }; * +;******************************************************************************* + + assume ds:nothing ;AN000;to make sure. + lds bx, ds:[bx.HASH_PTR] ;AN000;now, ds:bx -> hash table + xor dx, dx ;AN026;To be used to count buckets +; $DO ;AN000;For each bucket +$$DO21: + inc dl ;AN026; Current bucket number + mov word ptr ds:[bx.BUFFER_BUCKET],0 ;AN000;Memlo is 0 after ROUND. + mov di, [MemHi] ;AN000; + mov word ptr ds:[bx.BUFFER_BUCKET+2], di ;AN000;Hash entry set. + mov word ptr ds:[bx.DIRTY_COUNT], 0 ;AN020;set DIRTY_COUNT, BUFFER_RESERVED to 0. + mov es, di ;AN000; + xor di, di ;AN000;es:di -> hash bucket + xor cx, cx ;AN000 + xor ax, ax ;AN000 +; $DO ;AN000;For each buffer in the bucket +$$DO22: + call Set_Buffer_Info ;AN000;Set buf_link, buf_id... + inc cx ;AN000;buffer number + cmp dl, [NthBuck] ;AN026;Current bucket number > NthBuck? +; $IF BE ;AN026; + JNBE $$IF23 + cmp cl, [MaxNumBuf1] ;AN026; last buffer of the 1st group? +; $ELSE ;AN026; + JMP SHORT $$EN23 +$$IF23: + cmp cl, [MaxNumBuf2] ;AN026; last buffer of the 2nd group? +; $ENDIF ;AN026; +$$EN23: + +; $IF E ;AN020;Yes, last buffer + JNE $$IF26 + mov word ptr es:[di.BUF_NEXT], 0 ;AN020;the last buffer's next -> the first buffer in bucket (Circular chain) + mov word ptr es:[BUF_PREV], di ;AN020;the first buffer's prev -> the last buffer +; $ENDIF ;AN020; +$$IF26: + mov di, ax ;AN000;adjust next buffer position +; $ENDDO E ;AN000;flag set already for testing last buffer. + JNE $$DO22 + add [Memlo], ax ;AN000;AX is the size of this bucket. + or [SetDevMarkFlag], FOR_DEVMARK ;AN005;Update DEVMARK_SIZE + call Round ;AN000;memhi:memlo adjusted for the next bucket. + add bx, size BUFFER_HASH_ENTRY ;AN000;ds:bx -> next hash entry. + dec [BufferBuckets] ;AN000; +; $ENDDO Z ;AN000; + JNZ $$DO21 + ret ;AN000; +Set_Buffer endp + +; +Set_EMS_Buffer proc near +;******************************************************************************* +;Function: Set buffers in the extended memory. * +; For each hash table entry, set the pointer to the corresponding * +; hash bucket. * +; * +;Input: ds:bx -> BuffInfo. * +; BuffINFO.Hash_Ptr -> Hash table. * +; BuffINFO.EMS_Handle = EMS handle * +; Buffers = tatal # of buffers to install. * +; Multiple of MAXBUFFINBUCKET*MAXBUCKETINPAGE. * +; Buffer_Pages = # of extended memory pages for buffers. * +; BufferBuckets = # of buckets to install. * +; SingleBufferSize = Buffer header size + Sector size. * +; * +;Output: Buffers, hash buckets and Hash table entries established. * +; * +; { For (each page) * +; { Map the page; /*Map the page into Page frame * +; For (each bucket) /*Each page has two buckets */ * +; { * +; Set EMS_Page; * +; Set Buffer_Bucket; * +; Next buffer ptr = buffer size; * +; For (every buffer) /*A bucket has 15 buffers */ * +; { Set Buf_link to Next buffer ptr; * +; Set Buffer_ID to free; * +; If (last buffer in this bucket) THEN * +; {Buf_link = -1; * +; Next buffer ptr = 0; * +; }; * +; Next buffer ptr += buffer size; * +; }; * +; }; * +; }; * +; }; * +;******************************************************************************* + + assume ds:nothing ;AN000;to make sure. + +IF BUFFERFLAG + + push ax + mov ax, offset ems_save_buf + mov word ptr cs:[ems_state_buf], ax + push cs + pop word ptr cs:[ems_state_buf+2] + pop ax + +ENDIF + + call Save_MAP_State ;AN010; + mov dx, es:[bx.EMS_Handle] ;AN000;save EMS_Handle + lds si, ds:[bx.HASH_PTR] ;AN000;now ds:si -> Hash table + xor bx, bx ;AN000;starting logical page number. +; $DO ;AN000;For each page, +$$DO30: + call Map_Page ;AN000;map it to IBM physical page 254. + mov di, cs:IBM_Frame_Seg ;AN000; + mov es, di ;AN000 + xor di, di ;AN000;es:di -> bucket + xor ax, ax ;AN000 + xor cx, cx ;AN000 +; $DO ;AN000;For each bucket, +$$DO31: + mov ds:[si.EMS_PAGE_NUM], bx ;AN000;set the logical page number in Hash table. + mov word ptr ds:[si.BUFFER_BUCKET], di ;AN000;set the offset in hash table for this bucket. + mov word ptr ds:[si.BUFFER_BUCKET+2], es ;AN000;set the segment value in hash table. + mov word ptr ds:[si.DIRTY_COUNT], 0 ;AN020;set DIRTY_COUNT, BUFFER_RESERVED to 0. + push cx ;AN000;save bucket number + xor cx, cx ;AN000; +; $DO ;AN000;For each buffer in a bucket, +$$DO32: + call Set_Buffer_Info ;AN000;AX adjusted for the next buffer. + inc cx ;AN000;inc number of buffers in this bucket. + cmp cx, 1 ;AN020;The first buffer in the bucket? +; $IF E ;AN020; + JNE $$IF33 + mov cs:[EMS_Buf_First], di ;AN020;then save the offset value +; $ENDIF ;AN020; +$$IF33: + cmp cx, MAXBUFFINBUCKET ;AN000; +; $IF E ;AN000 + JNE $$IF35 + push word ptr cs:[EMS_Buf_First] ;AN020; + pop word ptr es:[di.BUF_NEXT] ;AN020;the last buffer's next -> the first buffer in bucket (Circular chain) + push di ;AN020;save di + push di ;AN020;di-> last buffer + mov di, cs:[EMS_Buf_First] ;AN020;es:di-> first buffer + pop word ptr es:[di.BUF_PREV] ;AN020;the first buffer's prev -> the last buffer + pop di ;AN020;restore di +; $ENDIF ;AN000; +$$IF35: + mov di, ax ;AN000;advance di to the next buffer position. +; $ENDDO E ;AN000; + JNE $$DO32 + add si, size BUFFER_HASH_ENTRY ;AN000;ds:si -> next hash table entry + pop cx ;AN000;restore bucket number + inc cx ;AN000;next bucket + cmp cx, MAXBUCKETINPAGE ;AN000;2 buckets per page +; $ENDDO E ;AN000; + JNE $$DO31 + inc bx ;AN000;increse logical page number + cmp bx, cs:[Buffer_Pages] ;AN000;reached the maximum page number? +; $ENDDO E ;AN000; + JNE $$DO30 + call Restore_MAP_State ;AN010; + ret ;AN000; +Set_EMS_Buffer endp + + +Set_Buffer_Info proc +;Function: Set buf_link, buf_id, Buf_Sector +;In: ES:DI -> Buffer header to be set. +; AX = DI +;Out: +; Above entries set. + + + push [Buf_Prev_Off] ;AN020; + pop es:[di.BUF_PREV] ;AN020; + mov Buf_Prev_Off, ax ;AN020; + add ax, [SingleBufferSize] ;AN000;adjust ax + mov word ptr es:[di.BUF_NEXT], ax ;AN020; + mov word ptr es:[di.BUF_ID], 00FFh ;AN000;new buffer free + mov word ptr es:[di.BUF_SECTOR], 0 ;AN000;To compensate the MASM 3 bug + mov word ptr es:[di.BUF_SECTOR+2],0 ;AN000;To compensate the MASM 3 bug + ret ;AN000; +Set_Buffer_Info endp + +Check_IBM_PageID proc near +;Function: check if the physical page 255 exists. (Physical page 255 is only +; one we are intereseted in, and this will be used for BUFFER +; manipulation by IBMBIO, IBMDOS) +;In: nothing +;Out: Carry clear and IBM_Frame_Seg set if it exist. All registers saved. + push es ;AN000; + push ax ;AN000; + push bx ;AN000; + push cx ;AN000; + push dx ;AN000; + push di ;AN010; + +IF NOT BUFFERFLAG + + mov ax, 1B00h ;AN029;AN030;AN0 Check EMS int 2fh installed. + int 2fh ;AN029; + cmp al, 0ffh ;AN029; + jne Cp_IBM_Err ;AN029;If not installed, then no IBM page. + mov ax, 1B01h ;AN029;AN030;Then ask if IBM page exists. + mov di, IBM_PAGE_ID ;AN029;=255 + int 2fh ;AN029; + or ah, ah ;AN029; + jnz Cp_IBM_Err ;AN029;;No IBM Page + mov cs:IBM_Frame_Seg, es ;AN029;;Save Physical IBM page frame addr. + mov cs:Real_IBM_Page_Id, di ;AN029;;Real page number for it. + clc ;AN029; + jmp short Cp_ID_Ret ;AN029; + +ELSE + push cs ;AN000; + pop es ;AN000; + mov ah, GET_PAGE_FRAME ;AN010;=58h + mov al, GET_NUM_PAGEFRAME ;AN010;=01h How many page frames? + int EMS_INT ;AN010; + or ah, ah ;AN010; + jnz hkn_err ;AN010; + cmp cx, MAX_NUM_PAGEFRAME ;AN010; + ja hkn_err ;AN010; cannot handle this big number + push cx ;AN010; + mov ah, GET_PAGE_FRAME ;AN010; + mov al, GET_PAGEFRAME_TAB ;AN010; + mov di, offset Frame_info_Buffer ;AN010; + int EMS_INT ;AN010; + pop cx ;AN010; + or ah, ah ;AN010; + jnz cp_IBM_Err ;AN010; +Cp_IBM_ID: ;AN010; + +; mov dx, es:[di] +; mov cs:[FIRST_PAGE], dx +; mov dx, es:[di+2] +; mov cs:[FIRST_PAGE+2], dx + + xor dx, dx + +; int 3 +find_page: + cmp es:[di], 0a000h ; is current page above 640K + jb next ; NO - goto check_last + + inc dx ; count the no. of pages above 640K + + cmp dx, 1 + jne first_ok + + mov ax, es:[di] + mov cs:[FIRST_PAGE], ax + mov ax, es:[di+2] + mov cs:[FIRST_PAGE+2], ax + +first_ok: + mov ax, cs:[FIRST_PAGE] + cmp ax, es:[di] ; is this page less than the one we have in + ; FIRST_PAGE + jbe check_last ; NO - goto check_last + mov ax, es:[di] ; update FIRST_PAGE with this page segment + mov cs:[FIRST_PAGE], ax + mov ax, es:[di+2] + mov cs:[FIRST_PAGE+2], ax + jmp next + +hkn_err: jmp cp_ibm_err + +check_last: + mov ax, cs:[LAST_PAGE] ; + cmp ax, es:[di] ; is this page greater than the one we have in + ; LAST_PAGE? + ja next ; NO - goto next + mov ax, es:[di] ; update LAST_PAGE with this value. + mov cs:[LAST_PAGE], ax + mov ax, es:[di+2] + mov cs:[LAST_PAGE+2], ax + +next: + add di, 4 + loop find_page + + cmp dx, 3 ; there should be at least 3 pages + ; above 640K for the buffers to be + ; installed. + jb Cp_IBM_Err + + mov ax, cs:[LAST_PAGE] + mov cs:IBM_Frame_Seg, ax + mov ax, cs:[LAST_PAGE+2] + mov cs:Real_IBM_Page_Id, ax + mov cs:[NPA640], dx + clc + jmp short Cp_Id_Ret + +ENDIF + + +; cmp word ptr es:[di+2], IBM_PAGE_ID ;AN010; the second word is the id +; je Got_IBM_ID ;AN010; +; add di, 4 ;AN010; advance to the next row (4 bytes) +; loop Cp_IBM_ID ;AN010; + +Cp_IBM_Err: ;AN010;;AN029; + stc ;AN000;;AN029; + jmp short Cp_ID_Ret ;AN000;;AN029; + +;Got_IBM_ID: ;AN000; +; mov ax, word ptr es:[di] ;AN010;Physical seg. addr. +; mov cs:IBM_Frame_Seg, ax ;AN000; +; clc ;AN000; +Cp_ID_Ret: ;AN000; + pop di ;AN010; + pop dx ;AN000; + pop cx ;AN000; + pop bx ;AN000; + pop ax ;AN000; + pop es ;AN000; + ret ;AN000; +Check_IBM_PageID endp + +; +Save_Map_State proc ;AN010; +;Function: Save the map state. +;In) +; EMS_Ctrl_Tab = double word pointer to EMS_state control table address +; EMS_state_Buf = double word pointer to EMS_MAP_BUFF address +;Out) Map state saved + push ax ;AN010; + push ds ;AN010; + push si ;AN010; + push es ;AN010; + push di ;AN010; + lds si, cs:EMS_Ctrl_Tab ;AN010; + les di, cs:EMS_state_Buf ;AN010; + mov ah, EMAP_STATE ;AN010; =4Fh + mov al, GET_MAP_STATE ;AN010; =00h + int EMS_INT ;AN010; + pop di ;AN010; + pop es ;AN010; + pop si ;AN010; + pop ds ;AN010; + pop ax ;AN010; + ret ;AN010; +Save_Map_State endp +; +Restore_Map_State proc ;AN010; + push ax ;AN010; + push ds ;AN010; + push si ;AN010; + lds si, cs:EMS_state_Buf ;AN010; + mov ah, EMAP_STATE ;AN010; + mov al, SET_MAP_STATE ;AN010; + int EMS_INT ;AN010; + pop si ;AN010; + pop ds ;AN010; + pop ax ;AN010; + ret ;AN010; +Restore_Map_State endp +; +Map_Page proc near ;AN000; +;Function: Map the logical page in BX of handle in DX to the physical page 255 +;In) +; BX = logical page number +; DX = EMS handle +; EMS_Ctrl_Tab = double word pointer to EMS_state control table address +; EMS_state_Buf = double word pointer to EMS_MAP_BUFF address +;Out) Logical page mapped into first phsical page frame. +; AX saved. + + push ax ;AN000; + mov ah, EMAP_L_TO_P ;AN000; + mov al, byte ptr cs:Real_IBM_PAGE_ID ;AN029;= 255 + int EMS_INT ;AN000; + pop ax ;AN000; + ret ;AN000; +Map_Page endp ;AN000; +; + +Roundup proc +;In: DX;AX - operand +; CX - divisor +; Important: DX should be less than CX. +;out: AX - Quotient (Rounded up) + + div cx ;AN000; + or dx, dx ;AN000; + jz RU_ret ;AN000; + inc AX ;AN000; +RU_ret: ;AN000; + ret ;AN000; +Roundup endp +;------------------------------------------------------------------------------ +;J.K. 5/6/86. IBMSTACK initialization routine. + IF STACKSW +.SALL + +INCLUDE STKINIT.INC + +.XALL + ENDIF +;------------------------------------------------------------------------------ + public SetDevMark +SetDevMark proc +;Set the DEVMARK for MEM command. +;In: [MEMHI] - the address to place DEVMARK +; [MEMLO] = 0 +; AL = ID for DEVMARK_ID +;OUT: DEVMARK established. +; the address saved in cs:[DevMark_Addr] +; [MEMHI] increase by 1. + + push es ;AN005; + push cx ;AN005; + + mov cx, cs:[memhi] ;AN005; + mov cs:[DevMark_Addr],cx ;AN005; + mov es, cx ;AN005; + mov es:[DEVMARK_ID], al ;AN005; + inc cx ;AN007; + mov es:[DEVMARK_SEG], cx ;AN007; + + pop cx ;AN005; + pop es ;AN005; + inc cs:[memhi] ;AN005; + ret ;AN005; +SetDevMark endp + +;******************************************************************************* +;Function: Load SHARE.EXE, if Big_Media_Flag = 1 and SHARE.EXE has not been * +; loaded yet. * +; This routine will use the same path for SHELL= command. * +; If SHELL= command has not been entered, then default to the root * +; directory. * +; If load fails, then issue message "Warning: SHARE.EXE not loaded" * +; * +;Input: Big_Media_Flag, COMMND * +;Output: Share.exe loaded if necessary. * +; * +;******************************************************************************* +LoadShare proc near ;AN021; + cmp Big_Media_Flag, 1 ;AN021; + jne LShare_Ret ;AN021; +;Check if SHARE is already loaded. + mov ax, 1000h ;AN021;multShare installation check + int 2fh ;AN021; + cmp al, 0ffh ;AN021; + jz LShare_Ret ;AN021;Share already loaded! +;SHARE not loaded. + push cs ;AN021; + pop ds ;AN021; + push cs ;AN021; + pop es ;AN021; + mov si, offset COMMND ;AN021; + mov di, offset PathString ;AN021; +LShare_String: ;AN021; + movsb ;AN021; + cmp byte ptr [di-1], 0 ;AN021;reached to the end? + jne LShare_string ;AN021; + mov si, offset PathString ;AN021;SI= start of PathString +LShare_Tail: ;AN021; + dec di ;AN021; + cmp byte ptr [di], "\" ;AN021; + je LShare_Got_Tail ;AN021; + cmp byte ptr [di], ":" ;AN021; + je LShare_Got_Tail ;AN021; + cmp di, si ;AN021;No path case (e.g. SHELL=command.com) + je LShare_Got_Tail_0 ;AN021; + jmp LShare_Tail ;AN021; +LShare_Got_Tail: ;AN021;di -> "\" or ":" + inc di ;AN021; +LShare_Got_Tail_0: ;AN021; + mov si, offset LShare ;AN021; +LShare_Set_Filename: ;AN021; + movsb ;AN021;Tag "SHARE.EXE",0,0Ah to the path. + cmp byte ptr [di-1], 0Ah ;AN021;Line feed? + jne LShare_Set_Filename ;AN021; +;Now, we got a path,filename with no parameters for SHARE.EXE + mov si, offset PathString ;AN021; + or Install_Flag, SHARE_INSTALL ;AN021;Signals Do_Install_Exec that this is for SHARE.EXE. + call Do_Install_Exec ;AN021;execute it. + jnc LShare_Ret ;AN021;No problem +;Load/Exec failed. Show "Warning: SHARE should be loaded for large media" + push cs ;AN021; + pop ds ;AN021; + mov dx, offset ShareWarnMsg ;AN021;WARNING! SHARE should be loaded... + invoke Print ;AN021; +LShare_Ret: ;AN021; + ret ;AN021; +LoadShare endp ;AN021; + +SYSINITSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/SYSINIT2.ASM b/v4.0/src/BIOS/SYSINIT2.ASM new file mode 100644 index 0000000..ff8b8ae --- /dev/null +++ b/v4.0/src/BIOS/SYSINIT2.ASM @@ -0,0 +1,1624 @@ + PAGE ,132 ; +; SCCSID = @(#)sysinit2.asm 1.13 85/10/15 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSINIT2 + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; p132 Multiple character device installation problem. 6/27/87 J.K. +;AN002; d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; p29 Extra space character in parameters passed. +; (Modification on ORGANIZE routine for COMMENT= fixed this +; problem too) 6/29/87 J.K. +;AN004; d41 REM command in CONFIG.SYS 7/7/87 J.K. +;AN005; d184 Set DEVMARK for MEM command 8/25/87 J.K. +;AN006; p1820 New Message SKL file 10/20/87 J.K. +;AN007; p1821 Include the COPYRIGH.INC file 10/22/87 J.K. +;AN008; p2210 IBMDOS returns incorrect DBCS vector table length 11/02/87 J.K. +;AN009; p2667 ccMono_Ptr problem 11/30/87 J.K. +;AN010; p2792 Device?driver.sys /d:2 command should not work 12/09/87 J.K. +;AN011; p3120 REM followed by CR, LF causes problem 01/13/88 J.K. +;AN012; p3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN013; d479 New option to disable extended INT 16h function call 02/12/88 J.K. +;AN014; D486 SHARE installation for big media 02/23/88 J.K. +;AN015; D526 Add /NC parameter when installing SHARE.EXE 04/28/88 J.K. +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +LF equ 10 +CR equ 13 +TAB equ 9 + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE + + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include DEVMARK.inc +.list + + IF NOT IBM + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + ENDIF + +code segment public 'code' + extrn EC35_Flag: byte +code ends + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' BYTE + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE + EXTRN BADSIZ_PRE:BYTE,BADLD_PRE:BYTE +; EXTRN BADSIZ_POST:BYTE,BADLD_POST:BYTE + EXTRN SYSSIZE:BYTE,BADCOUNTRY:BYTE + + EXTRN dosinfo:dword,entry_point:dword, + EXTRN MEMORY_SIZE:WORD,fcbs:byte,keep:byte + EXTRN DEFAULT_DRIVE:BYTE,confbot:word,alloclim:word + EXTRN BUFFERS:WORD,zero:byte,sepchr:byte + EXTRN FILES:BYTE + EXTRN count:word,chrptr:word + EXTRN bufptr:byte,memlo:word,prmblk:byte,memhi:word + EXTRN ldoff:word,area:word,PACKET:BYTE,UNITCOUNT:BYTE, + EXTRN BREAK_ADDR:DWORD,BPB_ADDR:DWORD,drivenumber:byte + extrn COM_Level:byte, CMMT:byte, CMMT1:byte, CMMT2:byte + extrn Cmd_Indicator:byte + extrn DoNotShowNum:byte + extrn MultDeviceFlag:byte + extrn DevMark_Addr:word ;AN005; + extrn SetDevMarkFlag:byte ;AN005; + extrn Org_Count:word ;AN012; + + EXTRN Stall:near + EXTRN Error_Line:near + + PUBLIC Int24,Open_Dev,Organize,Mem_Err,Newline,CallDev,Badload + PUBLIC PrnDev,AuxDev,Config,Commnd,Condev,GetNum,BadFil,PrnErr + PUBLIC Round,Delim,Print,Set_Break + PUBLIC SetParms, ParseLine, DiddleBack + PUBLIC Skip_delim,SetDOSCountryInfo,Set_Country_Path,Move_Asciiz + PUBLIC Cntry_Drv,Cntry_Root,Cntry_Path + PUBLIC Delim + public PathString ;AN014; + public LShare ;AN014; + +; +; The following set of routines is used to parse the DRIVPARM = command in +; the CONFIG.SYS file to change the default drive parameters. +; +SetParms: + push ds + push ax + push bx + push cx + push dx + push cs + pop ds + ASSUME DS:SYSINITSEG + xor bx,bx + mov bl,byte ptr drive + inc bl ; get it correct for IOCTL call (1=A,2=B...) + mov dx,offset DeviceParameters + mov ah, IOCTL + mov al, GENERIC_IOCTL + mov ch, RAWIO + mov cl, SET_DEVICE_PARAMETERS + int 21H + test word ptr Switches, flagec35 + jz Not_EC35 + + mov cl, byte ptr drive ; which drive was this for? + mov ax, Code ; get Code segment + mov ds, ax ; set code segment + assume ds:code + mov al, 1 ; assume drive 0 + shl al, cl ; set proper bit depending on drive + or ds:EC35_Flag, al ; set the bit in the permanent flags + +Not_EC35: + pop dx ; fix up all the registers + pop cx + pop bx + pop ax + pop ds + assume ds:nothing + ret + +; +; Replace default values for further DRIVPARM commands +; +DiddleBack: + push ds + push cs + pop ds + assume ds:sysinitseg + mov word ptr DeviceParameters.DP_Cylinders,80 + mov byte ptr DeviceParameters.DP_DeviceType, DEV_3INCH720KB + mov word ptr DeviceParameters.DP_DeviceAttributes,0 + mov word ptr switches,0 ; zero all switches + pop ds + assume ds:nothing + ret + +; +; Entry point is ParseLine. AL contains the first character in command line. +; +ParseLine: ; don't get character first time + push ds + push cs + pop ds + ASSUME DS:SYSINITSEG +NextSwtch: + cmp al,CR ; carriage return? + jz done_line + cmp al,LF ; linefeed? + jz put_back ; put it back and done +; Anything less or equal to a space is ignored. + cmp al,' ' ; space? + jbe get_next ; skip over space + cmp al,'/' + jz getparm + stc ; mark error invalid-character-in-input + jmp short exitpl + +getparm: + call Check_Switch + mov word ptr Switches,BX ; save switches read so far + jc swterr +get_next: + invoke getchr + jc done_line + jmp NextSwtch +swterr: + jmp exitpl ; exit if error + +done_line: + test word ptr Switches,flagdrive ; see if drive specified + jnz okay + stc ; mark error no-drive-specified + jmp short exitpl + +okay: + mov ax,word ptr switches + and ax,0003H ; get flag bits for changeline and non-rem + mov word ptr DeviceParameters.DP_DeviceAttributes,ax + mov word ptr DeviceParameters.DP_TrackTableEntries, 0 + clc ; everything is fine + call SetDeviceParameters +exitpl: + pop ds + ret + +put_back: + inc count ; one more char to scan + dec chrptr ; back up over linefeed + jmp short done_line +; +; Processes a switch in the input. It ensures that the switch is valid, and +; gets the number, if any required, following the switch. The switch and the +; number *must* be separated by a colon. Carry is set if there is any kind of +; error. +; +Check_Switch: + invoke getchr + jc err_check + and al,0DFH ; convert it to upper case + cmp al,'A' + jb err_check + cmp al,'Z' + ja err_check + push es + push cs + pop es + mov cl,byte ptr switchlist ; get number of valid switches + mov ch,0 + mov di,1+offset switchlist ; point to string of valid switches + repne scasb + pop es + jnz err_check + mov ax,1 + shl ax,cl ; set bit to indicate switch + mov bx,word ptr switches ; get switches so far + or bx,ax ; save this with other switches + mov cx,ax + test ax, switchnum ; test against switches that require number to follow + jz done_swtch + invoke getchr + jc err_Swtch + cmp al,':' + jnz err_swtch + invoke getchr + push bx ; preserve switches + mov byte ptr cs:sepchr,' ' ; allow space separators + call GetNum + mov byte ptr cs:sepchr,0 + pop bx ; restore switches +; Because GetNum does not consider carriage-return or line-feed as OK, we do +; not check for carry set here. If there is an error, it will be detected +; further on (hopefully). + call Process_Num + +done_swtch: + clc + ret + +err_swtch: + xor bx,cx ; remove this switch from the records +err_check: + stc + ret + +; +; This routine takes the switch just input, and the number following (if any), +; and sets the value in the appropriate variable. If the number input is zero +; then it does nothing - it assumes the default value that is present in the +; variable at the beginning. Zero is OK for form factor and drive, however. +; +Process_Num: + test word ptr Switches,cx ; if this switch has been done before, + jnz done_ret ; ignore this one. + test cx,flagdrive + jz try_f + mov byte ptr drive,al + jmp short done_ret + +try_f: + test cx,flagff + jz try_t +; Ensure that we do not get bogus form factors that are not supported + ;cmp al,Max_Dev_Type + ;ja done_ret + mov byte ptr DeviceParameters.DP_DeviceType,al + jmp short done_ret + +try_t: + or ax,ax + jz done_ret ; if number entered was 0, assume default value + test cx,flagcyln + jz try_s + mov word ptr DeviceParameters.DP_Cylinders,ax + jmp short done_ret + +try_s: + test cx,flagseclim + jz try_h + mov word ptr slim,ax + jmp short done_ret +; +; Must be for number of heads +try_h: + mov word ptr hlim,ax + +done_ret: + clc + ret + +; +; SetDeviceParameters sets up the recommended BPB in each BDS in the +; system based on the form factor. It is assumed that the BPBs for the +; various form factors are present in the BPBTable. For hard files, +; the Recommended BPB is the same as the BPB on the drive. +; No attempt is made to preserve registers since we are going to jump to +; SYSINIT straight after this routine. +; +SetDeviceParameters: + push es + push cs + pop es +ASSUME ES:SYSINITSEG + xor bx,bx + mov bl,byte ptr DeviceParameters.DP_DeviceType + cmp bl,DEV_5INCH + jnz Got_80 + mov cx,40 ; 48tpi has 40 cylinders + mov word ptr DeviceParameters.DP_Cylinders,cx +Got_80: + shl bx,1 ; get index into BPB table + mov si,offset BPBTable + mov si,word ptr [si+bx] ; get address of BPB +Set_RecBPB: + mov di,offset DeviceParameters.DP_BPB ; es:di -> BPB + mov cx,size a_BPB + cld + repe movsb + pop es +ASSUME ES:NOTHING + test word ptr switches,flagseclim + jz see_heads + mov ax,word ptr slim + mov word ptr DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax +see_heads: + test word ptr switches,flagheads + jz Set_All_Done + mov ax,word ptr hlim + mov word ptr DeviceParameters.DP_BPB.BPB_Heads,ax +; +; We need to set the media byte and the total number of sectors to reflect the +; number of heads. We do this by multiplying the number of heads by the number +; of 'sectors per head'. This is not a fool-proof scheme!! +; + mov cx,ax ; cx has number of heads + dec cl ; get it 0-based + mov ax,DeviceParameters.DP_BPB.BPB_TotalSectors ; this is OK for two heads + sar ax,1 ; ax contains # of sectors/head + sal ax,cl + jc Set_All_Done ; We have too many sectors - overflow!! + mov DeviceParameters.DP_BPB.BPB_TotalSectors,ax +; Set up correct Media Descriptor Byte + cmp cl,1 + mov bl,0F0H + mov al,2 ; AL contains sectors/cluster + ja Got_Correct_Mediad + mov bl,byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor + je Got_Correct_Mediad +; We have one head - OK for 48tpi medium + mov al,1 ; AL contains sectors/cluster + mov ch,DeviceParameters.DP_DeviceType + cmp ch,DEV_5INCH + jz Dec_Mediad + mov bl,0F0H + jmp short Got_Correct_Mediad +Dec_Mediad: + dec bl ; adjust for one head +Got_Correct_Mediad: + mov byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor,bl + mov byte ptr DeviceParameters.DP_BPB.BPB_SectorsPerCluster,al + clc +Set_All_Done: + RET + +ASSUME DS:NOTHING, ES:NOTHING + +NOCHAR1: STC + return + +ORGANIZE: + MOV CX,[COUNT] + JCXZ NOCHAR1 + CALL MAPCASE + XOR SI,SI + MOV DI,SI + xor ax,ax + mov COM_Level, 0 + +;ORG1: CALL GET ;SKIP LEADING CONTROL CHARACTERS +; CMP AL,' ' +; JB ORG1 +Org1: + call Skip_Comment ;AN000; + jz End_Commd_Line ;AN000; found a comment string and skipped. + call Get2 ;AN000; Not a comment string. Then get a char. + cmp al, LF ;AN000; + je End_Commd_Line ;AN000; starts with a blank line. + cmp al, ' ' ;AN000; + jbe Org1 ;AN000; skip leading control characters + jmp Findit ;AN000; +End_Commd_Line: ;AN000; + stosb ;AN000; store line feed char in buffer for the LineCount. + mov COM_Level, 0 ;AN000; reset the command level. + jmp Org1 ;AN000; +Findit: ;AN000; + PUSH CX + PUSH SI + PUSH DI + MOV BP,SI + DEC BP + MOV SI,OFFSET COMTAB ;Prepare to search command table + MOV CH,0 +FINDCOM: + MOV DI,BP + MOV CL,[SI] + INC SI + JCXZ NOCOM + REPE CMPSB + LAHF + ADD SI,CX ;Bump to next position without affecting flags + SAHF + LODSB ;Get indicator letter + JNZ FINDCOM + cmp byte ptr es:[di], CR ;AN011;The next char might be CR,LF + je GotCom0 ;AN011; such as in "REM",CR,LF case. + cmp byte ptr es:[di], LF ;AN011; + je GotCom0 ;AN011; + push ax ;AN010; + mov al, byte ptr es:[di] ;AN010;Now the next char. should be a delim. + call delim ;AN010; + pop ax ;AN010; + jnz findcom ;AN010; +GotCom0: + POP DI + POP SI + POP CX + JMP SHORT GOTCOM + +NOCOM: + POP DI + POP SI + POP CX + MOV AL,'Z' + stosb ;AN000; save indicator char. +Skip_Line: ;AN000; + call Get2 ;AN000; + cmp al, LF ;AN000; skip this bad command line + jne Skip_Line ;AN000; + jmp End_Commd_Line ;AN000; handle next command line + +GOTCOM: STOSB ;SAVE INDICATOR CHAR IN BUFFER + mov Cmd_Indicator, al ;AN000; save it for the future use. + +ORG2: CALL GET2 ;SKIP the commad name UNTIL DELIMITER + cmp al, LF ;AN011; + je Org21 ;AN011; + cmp al, CR ;AN011; + je Org21 ;AN011; + CALL DELIM ; + JNZ ORG2 + jmp short Org3 ;AN011; +Org21: ;AN011;if CR or LF then + dec si ;AN011; undo SI, CX register + inc cx ;AN011; and continue + +;ORG4: CALL GET2 +; call Delim ;J.K. 5/30/86. To permit "device=filename/p..." stuff. +; jz ORG_EXT ;J.K. 5/30/86 +;Org4_Cont: +; STOSB +; CMP AL,' ' +; JA ORG4 +; CMP AL,10 +; JZ ORG1 +; +; MOV BYTE PTR ES:[DI-1],0 + +Org3: + cmp Cmd_Indicator, 'Y' ;AN000; Comment= command? + je Get_Cmt_Token ;AN000; + cmp Cmd_Indicator, 'I' ;AN000; Install= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'D' ;AN000; Device= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'J' ;AN000; IFS= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'S' ;AN000; Shell= is a special one!!! + je Org_file ;AN000; + cmp Cmd_Indicator, '1' ;AN013; SWITCHES= command? + je Org_Switch ;AN013; + jmp Org4 ;AN000; +Org_Switch: + call Skip_Comment ;AN013; + jz End_Commd_Line_Brdg ;AN013; + call Get2 ;AN013; + call Org_Delim ;AN013; + jz Org_Switch ;AN013; + stosb ;AN013; + jmp Org5 ;AN013; +Org_file: ;AN000; Get the filename and put 0 at end, + call Skip_Comment ;AN000; + jz Org_Put_Zero ;AN000; + call Get2 ;AN000; Not a comment + call Delim ;AN000; + jz Org_file ;AN000; Skip the possible delimeters + stosb ;AN000; copy the first non delim char found in buffer +Org_Copy_File: ;AN000; + call Skip_Comment ;AN000; comment char in the filename? + jz Org_Put_Zero ;AN000; then stop copying filename at that point + call Get2 ;AN000; + cmp al, '/' ;AN000; a switch char? (device=filename/xxx) + je End_File_slash ;AN000; this will be the special case. + stosb ;AN000; save the char. in buffer + call Delim ;AN000; + jz End_Copy_File ;AN000; + cmp al, ' ' ;AN000; + ja Org_Copy_File ;AN000; keep copying + jmp End_Copy_File ;AN000; otherwise, assume end of the filename. +Get_Cmt_token: ;AN000; get the token. Just max. 2 char. + call Get2 ;AN000; + cmp al, ' ' ;AN000; skip white spaces or "=" char. + je Get_Cmt_Token ;AN000; (we are allowing the other special + cmp al, TAB ;AN000; charaters can used for comment id. + je Get_Cmt_Token ;AN000; character.) + cmp al, '=' ;AN000; = is special in this case. + je Get_Cmt_Token ;AN000; + cmp al, CR ;AN000; + je Get_Cmt_End ;AN000; cannot accept the carridge return + cmp al, LF ;AN000; + je Get_Cmt_End ;AN000; + mov CMMT1, al ;AN000; store it + mov CMMT, 1 ;AN000; 1 char. so far. + call Get2 ;AN000; + cmp al, ' ' ;AN000; + je Get_Cmt_End ;AN000; + cmp al, TAB ;AN000; + je Get_Cmt_End ;AN000; + cmp al, CR ;AN000; + je Get_Cmt_End ;AN000; + cmp al, LF ;AN000; + je End_Commd_Line_Brdg ;AN000; + mov CMMT2, al ;AN000; + inc CMMT ;AN000; +Get_Cmt_End: ;AN000; + call Get2 ;AN000; + cmp al, LF ;AN000; + jne Get_Cmt_End ;AN000; skip it. +End_Commd_Line_Brdg: jmp End_Commd_Line ;AN000; else jmp to End_Commd_Line + +Org_Put_Zero: ;AN000; Make the filename in front of + mov byte ptr es:[di], 0 ;AN000; the comment string to be an asciiz. + inc di ;AN000; + jmp End_Commd_Line ;AN000; (Maybe null if device=/*) +End_file_slash: ;AN000; AL = "/" option char. + mov byte ptr es:[di],0 ;AN000; make a filename an asciiz + inc di ;AN000; and + stosb ;AN000; store "/" after that. + jmp Org5 ;AN000; continue with the rest of the line + +End_Copy_File: ;AN000; + mov byte ptr es:[di-1], 0 ;AN000; make it an asciiz and handle the next char. + cmp al, LF ;AN000; + je End_Commd_Line_brdg ;AN000; + jmp Org5 ;AN000; + +Org4: ;AN000; Org4 skips all delimiters after the command name except for '/' + call Skip_Comment ;AN000; + jz End_Commd_Line_brdg ;AN000; + call Get2 ;AN000; + call Org_Delim ;AN000; skip delimiters EXCEPT '/' (mrw 4/88) + jz Org4 ;AN000; + jmp Org51 ;AN000; +Org5: ;AN000; rest of the line + call Skip_Comment ;AN000; Comment? + jz End_Commd_Line_brdg ;AN000; + call Get2 ;AN000; Not a comment. +Org51: ;AN000; + stosb ;AN000; copy the character + cmp al, '"' ;AN000; a quote ? + je At_Quote ;AN000; + cmp al, ' ' ;AN000; + ja Org5 ;AN000; + cmp al, LF ;AN000; line feed? + je Org1_brdg ;AN000; handles the next command line. + jmp Org5 ;AN000; handles next char in this line. +Org1_brdg: jmp Org1 ;AN000; +At_Quote: ;AN000; + cmp COM_Level, 0 ;AN000; + je Up_Level ;AN000; + mov COM_Level, 0 ;AN000; reset it. + jmp Org5 ;AN000; +Up_Level: ;AN000; + inc COM_level ;AN000; set it. + jmp Org5 ;AN000; + + +;ORG5: CALL GET2 +; STOSB +; CMP AL,10 +; JNZ ORG5 +; JMP ORG1 +; +;ORG_EXT: +; cmp al,' ' ;space? +; je Org4_Cont ;then do not make an exception. Go back. +; cmp al,9 ;Tab? +; je Org4_Cont +; mov byte ptr es:[di], 0 ;put 0 at the current DI to make it an ASCIIZ +; inc DI ; +; stosb ;and copy the delimeter char. +; jmp short ORG5 ;and continue as usual. + + +GET2: + JCXZ NOGET + MOV AL,ES:[SI] + INC SI + DEC CX + return + +;GET: JCXZ NOGET +; MOV AL,ES:[SI] +; INC SI +; DEC CX +; CALL Org_DELIM +; JZ GET +; return + +Skip_Comment: +;J.K.Skip the commented string until LF, if current es:si-> a comment string. +;J.K.In) ES:SI-> sting +;J.K. CX -> length. +;J.K.Out) Zero flag not set if not found a comment string. +;J.K. Zero flag set if found a comment string and skipped it. AL will contain +;J.K. the line feed charater at this moment when return. +;J.K. AX register destroyed. +;J.K. If found, SI, CX register adjusted accordingly. + + jcxz NoGet ;AN000; Get out of the Organize routine. + cmp COM_Level, 0 ;AN000; only check it if parameter level is 0. + jne No_Commt ;AN000; (Not inside quotations) + + cmp CMMT, 1 ;AN000; + jb No_Commt ;AN000; + mov al, es:[si] ;AN000; + cmp CMMT1, al ;AN000; + jne No_Commt ;AN000; + cmp CMMT, 2 ;AN000; + jne Skip_Cmmt ;AN000; + mov al, es:[si+1] ;AN000; + cmp CMMT2, al ;AN000; + jne No_Commt ;AN000; +Skip_Cmmt: ;AN000; + jcxz NoGet ;AN000; get out of Organize routine. + mov al, es:[si] ;AN000; + inc si ;AN000; + dec cx ;AN000; + cmp al, LF ;AN000; line feed? + jne Skip_Cmmt ;AN000; +No_Commt: ;AN000; + ret ;AN000; + + +DELIM: + CMP AL,'/' ;J.K. 5/30/86. IBM will assume "/" as an delimeter. + retz + cmp al, 0 ;J.K. 5/23/86 Special case for sysinit!!! + retz +Org_Delim: ;AN000; Used by Organize routine except for getting + CMP AL,' ' ;the filename. + retz + CMP AL,9 + retz + CMP AL,'=' + retz + CMP AL,',' + retz + CMP AL,';' + return + + +NOGET: POP CX + MOV COUNT,DI + mov Org_Count, DI ;AN012; + XOR SI,SI + MOV CHRPTR,SI + return + +;Get3: jcxz NOGET ;J.K.do not consider '/',',' as a delim. +; mov al, es:[si] +; inc si +; dec cx +; call DELIM +; jnz Get3_ret +; cmp al,'/' +; je Get3_ret +; cmp al,',' +; jne Get3 +;Get3_ret: +; ret + + + +; +; NEWLINE RETURNS WITH FIRST CHARACTER OF NEXT LINE +; +NEWLINE:invoke GETCHR ;SKIP NON-CONTROL CHARACTERS + retc + CMP AL,LF ;LOOK FOR LINE FEED + JNZ NEWLINE + invoke GETCHR + return + +MAPCASE: + PUSH CX + PUSH SI + PUSH DS + PUSH ES + POP DS + XOR SI,SI +CONVLOOP: + LODSB + + IF KANJI + CALL TESTKANJ + JZ NORMCONV + INC SI ;Skip next char + DEC CX + JCXZ CONVDONE ;Just ignore 1/2 kanji error +;Fall through, know AL is not in 'a'-'z' range +NORMCONV: + ENDIF + + CMP AL,'a' + JB NOCONV + CMP AL,'z' + JA NOCONV + SUB AL,20H + MOV [SI-1],AL +NOCONV: + LOOP CONVLOOP +CONVDONE: + POP DS + POP SI + POP CX + return + + IF KANJI +TESTKANJ: + CMP AL,81H + JB NOTLEAD + CMP AL,9FH + JBE ISLEAD + CMP AL,0E0H + JB NOTLEAD + CMP AL,0FCH + JBE ISLEAD +NOTLEAD: + PUSH AX + XOR AX,AX ;Set zero + POP AX + return + +ISLEAD: + PUSH AX + XOR AX,AX ;Set zero + INC AX ;Reset zero + POP AX + return + ENDIF + +ASSUME DS:NOTHING + +Yes_Break_Failed: ;device driver Init failed and aborted. + stc + pop ax + return + +SET_BREAK: +;J.K. 8/14/86 For DOS 3.3, this routine is modified to take care of the +;Device driver's initialization error and abort. +;If [break_addr+2] == [memhi] && [break_addr] = 0 then assume +;that the device driver's initialization has an error and wanted to +;abort the device driver. In this case, this routine will set carry +;and return to the caller. +;J.K. 6/26/87 If MultDeviceFlag <> 0, then do not perform the check. +;This is to allow the multiple character device driver which uses +;the same ending address segment with the offset value 0 for each +;of the drives. + + PUSH AX + MOV AX,WORD PTR [BREAK_ADDR+2] ;REMOVE THE INIT CODE + cmp MultDeviceFlag, 0 ;AN001; + jne Set_Break_Continue ;AN001;Do not check it. + cmp ax, [MEMHI] + jne Set_Break_Continue ;if not same, then O.K. + + cmp word ptr [BREAK_ADDR],0 + je Yes_Break_failed ;[Break_addr+2]=[MEMHI] & [Break_addr]=0 + +Set_Break_Continue: + MOV [MEMHI],AX + MOV AX,WORD PTR [BREAK_ADDR] + MOV [MEMLO],AX + POP AX ; NOTE FALL THROUGH + or [SetDevMarkFlag], SETBRKDONE ;AN005; Signal the successful Set_break + +; +; Round the values in MEMLO and MEMHI to paragraph boundary. +; Perform bounds check. +; +ROUND: + PUSH AX + MOV AX,[MEMLO] + + invoke ParaRound ; para round up + + ADD [MEMHI],AX + MOV [MEMLO],0 + mov ax,memhi ; ax = new memhi + CMP AX,[ALLOCLIM] ; if new memhi >= alloclim, error + JAE MEM_ERR + test cs:[SetDevMarkFlag], FOR_DEVMARK ;AN005; + jz Skip_Set_DEVMARKSIZE ;AN005; + push es ;AN005; + push si ;AN005; + mov si, cs:[DevMark_Addr] ;AN005; + mov es, si ;AN005; + sub ax, si ;AN005; + dec ax ;AN005; + mov es:[DEVMARK_SIZE], ax ;AN005; Paragraph + and cs:[SetDevMarkFlag], NOT_FOR_DEVMARK ;AN005; + pop si ;AN005; + pop es ;AN005; +Skip_Set_DEVMARKSIZE: ;AN005; + POP AX + clc ;clear carry + return + +MEM_ERR: + MOV DX,OFFSET BADMEM + PUSH CS + POP DS + CALL PRINT + JMP STALL + +CALLDEV:MOV DS,WORD PTR CS:[ENTRY_POINT+2] + ADD BX,WORD PTR CS:[ENTRY_POINT] ;Do a little relocation + MOV AX,DS:[BX] + PUSH WORD PTR CS:[ENTRY_POINT] + MOV WORD PTR CS:[ENTRY_POINT],AX + MOV BX,OFFSET PACKET + CALL [ENTRY_POINT] + POP WORD PTR CS:[ENTRY_POINT] + return + +BADNUM: + MOV sepchr,0 + XOR AX,AX ; Set Zero flag, and AX = 0 + pop bx ; J.K. + stc ; AND carry set + return + +ToDigit: + SUB AL,'0' + JB NotDig + CMP AL,9 + JA NotDig + CLC + return +NotDig: STC + return + +; GetNum parses a decimal number. +; Returns it in AX, sets zero flag if AX = 0 (MAY BE considered an +; error), if number is BAD carry is set, zero is set, AX=0. +GETNUM: push bx ; J.K. + XOR BX,BX ; running count is zero +B2: CALL ToDigit ; do we have a digit + JC BadNum ; no, bomb + XCHG AX,BX ; put total in AX + PUSH BX ; save digit + MOV BX,10 ; base of arithmetic + MUL BX ; shift by one decimal di... + POP BX ; get back digit + ADD AL,BL ; get total + ADC AH,0 ; make that 16 bits + JC BADNUM ; too big a number + XCHG AX,BX ; stash total + + invoke GETCHR ;GET NEXT DIGIT + JC B1 ; no more characters + cmp al, ' ' ;J.K. 5/23/86 space? + jz B15 ;J.K. 5/23/86 then end of digits + cmp al, ',' ;J.K. 5/23/86 ',' is a seperator!!! + jz B15 ;J.K. 5/23/86 then end of digits. + cmp al, TAB ;J.K. 5/23/86 TAB + jz B15 ;J.K. + CMP AL,SepChr ; allow 0 or special separators + JZ b15 + cmp al,SWTCHR ; See if another switch follows + JZ b15 + cmp al,LF ; Line-feed? + jz b15 + cmp al,CR ; Carriage return? + jz b15 + OR AL,AL ; end of line separator? + JNZ B2 ; no, try as a valid char... +b15: INC COUNT ; one more character to s... + DEC CHRPTR ; back up over separator +B1: MOV AX,BX ; get proper count + OR AX,AX ; Clears carry, sets Zero accordingly + pop bx + return + +SKIP_DELIM proc near ;J.K. +;Skip the delimeters pointed by CHRPTR. AL will contain the first non delimeter +;character encountered and CHRPTR will point to the next character. +;This rouitne will assume the second "," found as a non delimiter character. So +;in case if the string is " , , ", this routine will stop at the second ",". At +;this time, Zero flag is set. +;If COUNT is exhausted, then carry will be set. +Skip_delim_char: + call getchr + jc Skip_delim_exit + cmp al, ',' ;the first comma? + je Skip_delim_next + call delim ;check the charater in AL. + jz Skip_delim_char + jmp short Skip_delim_exit ;found a non delim char +Skip_delim_next: + call getchr + jc Skip_delim_exit + cmp al, ',' ;the second comma? + je Skip_delim_exit ;done + call delim + jz Skip_delim_next +Skip_delim_exit: + return +SKIP_DELIM endp + +;J.K. 5/26/86 ***************************************************************** +SetDOSCountryInfo proc near +;Input: ES:DI -> pointer to DOS_COUNTRY_CDPG_INFO +; DS:0 -> buffer. +; SI = 0 +; AX = country id +; DX = code page id. (If 0, then use ccSysCodePage as a default.) +; BX = file handle +; This routine can handle maxium 72 COUNTRY_DATA entries. +;Output: DOS_country_cdpg_info set. +; Carry set if any file read failure or wrong information in the file. +; Carry set and CX = -1 if cannot find the matching COUNTRY_id, CODEPAGE +; _id in the file. + + push di + push ax + push dx + + xor cx,cx + xor dx,dx + mov ax, 512 ;read 512 bytes + call ReadInControlBuffer ;Read the file header + jc SetDOSData_fail + push es + push si + push cs + pop es + mov di, offset COUNTRY_FILE_SIGNATURE + mov cx, 8 ;length of the signature + repz cmpsb + pop si + pop es + jnz SetDOSData_fail ;signature mismatch + + add si, 18 ;SI -> county info type + cmp byte ptr ds:[si], 1 ;Only accept type 1 (Currently only 1 header type) + jne SetDOSData_fail ;cannot proceed. error return + inc si ;SI -> file offset + mov dx, word ptr ds:[si] ;Get the INFO file offset. + mov cx, word ptr ds:[si+2] + mov ax, 1024 ;read 1024 bytes. + call ReadInControlBuffer ;Read INFO + jc SetDOSData_fail + mov cx, word ptr ds:[si] ;get the # of country, codepage combination entries + cmp cx, 72 ;cannot handle more than 72 entries. + ja SetDOSData_fail + inc si + inc si ;SI -> entry information packet + pop dx ;restore code page id + pop ax ;restore country id + pop di + +SetDOSCntry_find: ;Search for desired country_id,codepage_id. + cmp ax, word ptr ds:[si+2] ;compare country_id + jne SetDOSCntry_next + cmp dx, 0 ;No user specified code page ? + je SetDOSCntry_any_codepage;then no need to match code page id. + cmp dx, word ptr ds:[si+4] ;compare code page id + je SetDOSCntry_got_it +SetDOSCntry_next: + add si, word ptr ds:[si] ;next entry + inc si + inc si ;take a word for size of entry itself + loop SetDOSCntry_find + mov cx, -1 ;signals that bad country id entered. +SetDOSCntry_fail: + stc + ret + +SetDOSData_fail: + pop si + pop cx + pop di + jmp short SetDOSCntry_fail + +SetDOSCntry_any_CodePage: ;use the code_page_id of the country_id found. + mov dx, word ptr ds:[si+4] +SetDOSCntry_got_it: ;found the matching entry + mov cs:CntryCodePage_Id, dx ;save code page ID for this country. + mov dx, word ptr ds:[si+10] ;get the file offset of country data + mov cx, word ptr ds:[si+12] + mov ax, 512 ;read 512 bytes + call ReadInControlBuffer + jc SetDOSCntry_fail + mov cx, word ptr ds:[si] ;get the number of entries to handle. + inc si + inc si ;SI -> first entry + +SetDOSCntry_data: + push di ;ES:DI -> DOS_COUNTRY_CDPG_INFO + push cx ;save # of entry left + push si ;si -> current entry in Control buffer + + mov al, byte ptr ds:[si+2] ;get data entry id + call GetCountryDestination ;get the address of destination in ES:DI + jc SetDOSCntry_data_next ;No matching data entry id in DOS + + + mov dx, word ptr ds:[si+4] ;get offset of data + mov cx, word ptr ds:[si+6] + mov ax, 4200h + stc + int 21h ;move pointer + jc SetDOSData_fail + mov dx, 512 ;start of data buffer +; mov cx, word ptr es:[di] ;length of the corresponding data in DOS. +; add cx, 10 ;Signature + A word for the length itself + mov cx, 20 ;read 20 bytes only. We only need to + mov ah, 3fh ;look at the length of the data in the file. + stc + int 21h ;read the country.sys data + jc SetDOSData_fail ;read failure + cmp ax, cx + jne SetDOSData_fail + + mov dx, word ptr ds:[si+4] ;AN008;get offset of data again. + mov cx, word ptr ds:[si+6] ;AN008; + mov ax, 4200h ;AN008; + stc ;AN008; + int 21h ;AN008;move pointer back again + jc SetDOSData_fail ;AN008; + + push si ;AN008; + mov si, (512+8) ;AN008;get length of the data from the file + mov cx, word ptr ds:[si] ;AN008; + pop si ;AN008; + mov dx, 512 ;AN008;start of data buffer + add cx, 10 ;AN008;Signature + A word for the length itself + mov ah, 3fh ;AN008;Read the data from the file. + stc ;AN008; + int 21h ;AN008; + jc SetDOSData_fail ;AN008; + cmp ax, cx ;AN008; + jne SetDOSData_fail ;AN008; + + mov al, byte ptr ds:[si+2] ;save Data id for future use. + mov si, (512+8) ;SI-> data buffer + id tag field + mov cx, word ptr ds:[si] ;get the length of the file + inc cx ;Take care of a word for lenght of tab + inc cx ;itself. + cmp cx, (2048 - 512 - 8) ;Fit into the buffer? + ja SetDOSData_fail + cmp al, SetCountryInfo ;is the data for SetCountryInfo table? + jne SetDOSCntry_Mov ;no, don't worry + push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009;Cannot destroy ccMono_ptr address. Save them. + push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;At this time DI -> ccCountryInfoLen + push di ;save DI + + push ax + mov ax,cs:CntryCodePage_Id ;Do not use the Code Page info in Country_Info + mov ds:[si+4], ax ;Use the saved one for this !!!! + pop ax + +SetDOSCntry_Mov: + rep movsb ;copy the table into DOS + cmp al, SetCountryInfo ;was the ccMono_ptr saved? + jne SetDOSCntry_data_next + pop di ;restore DI + pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;restore + pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009; + +SetDOSCntry_data_next: + pop si ;restore control buffer pointer + pop cx ;restore # of entries left + pop di ;restore pointer to DSO_COUNTRY_CDPG + add si, word ptr ds:[si] ;try to get the next entry + inc si + inc si ;take a word of entry length itself +; loop SetDOSCntry_data + dec cx ;AN008; + cmp cx,0 ;AN008; + je SetDOSCntry_OK ;AN008; + jmp SetDOSCntry_data ;AN008; +SetDOSCntry_OK: ;AN008; + ret +SetDOSCountryInfo endp +; + +GetCountryDestination proc near +;Get the destination address in the DOS country info table. +;Input: AL - Data ID +; ES:DI -> DOS_COUNTRY_CDPG_INFO +;On return: +; ES:DI -> Destination address of the matching data id +; carry set if no matching data id found in DOS. + + push cx + add di, ccNumber_of_entries ;skip the reserved area, syscodepage etc. + mov cx, word ptr es:[di] ;get the number of entries + inc di + inc di ;SI -> the first start entry id +GetCntryDest: + cmp byte ptr es:[di], al + je GetCntryDest_OK + cmp byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry? + je GetCntryDest_1 + add di, 5 ;next data id + jmp short GetCntryDest_loop +GetCntryDest_1: + add di, NEW_COUNTRY_SIZE + 3 ;next data id +GetCntryDest_loop: + loop GetCntryDest + stc + jmp short GetCntryDest_exit +GetCntryDest_OK: + cmp al, SetCountryInfo ;select country info? + jne GetCntryDest_OK1 + inc di ;now DI -> ccCountryInfoLen + jmp short GetCntryDest_exit +GetCntryDest_OK1: + les di, dword ptr es:[di+1] ;get the destination in ES:DI +GetCntryDest_Exit: + pop cx + ret +GetCountryDestination endp + +; +ReadInControlBuffer proc near +;Move file pointer to CX:DX +;Read AX bytes into the control buffer. (Should be less than 2 Kb) +;SI will be set to 0 hence DS:SI points to the control buffer. +;Entry: CX,DX offset from the start of the file where the read/write pointer +; be moved. +; AX - # of bytes to read +; BX - file handle +; DS - buffer seg. +;Return: The control data information is read into DS:0 - DS:0200. +; CX,DX value destroyed. +; Carry set if error in Reading file. +; + push ax ;# of bytes to read + mov ax, 4200h + stc + int 21h ;move pointer + pop cx ;# of bytes to read + jc RICB_exit + xor dx,dx ;ds:dx -> control buffer + xor si,si + mov ah,3fh ;read into the buffer + stc + int 21h ;should be less than 1024 bytes. +RICB_exit: + ret +ReadInControlBuffer endp + +; +SET_COUNTRY_PATH proc near +;In: DS - SYSINITSEG, ES - CONFBOT, SI -> start of the asciiz path string +; DOSINFO_EXT, CNTRY_DRV, CNTRY_ROOT, CNTRY_PATH +; Assumes current directory is the ROOT directory. +;Out: DS:DI -> full path (CNTRY_DRV). +; Set the CNTRY_DRV string from the COUNTRY=,,path command. +; DS, ES, SI value saved. + + push si + push ds ;switch ds, es + push es + pop ds + pop es ;now DS -> CONFBOT, ES -> SYSINITSEG + + call chk_drive_letter ;current DS:[SI] is a drive letter? + jc SCP_Default_drv ;no, use current default drive. + mov al, byte ptr DS:[SI] + inc si + inc si ;SI -> next char after ":" + jmp short SCP_SetDrv +SCP_Default_drv: + mov ah, 19h + int 21h + add al, "A" ;convert it to a character. +SCP_SetDrv: + mov cs:CNTRY_DRV, al ;set the drive letter. + mov di, offset CNTRY_PATH + mov al, byte ptr DS:[SI] + cmp al, "\" + je SCP_Root_Dir + cmp al, cs:SWTCHR ;let's accept "/" as an directory delim + je SCP_Root_Dir + jmp short SCP_Path +SCP_Root_Dir: + dec di ;DI -> CNTRY_ROOT +SCP_Path: + call MOVE_ASCIIZ ;copy it + mov di, offset CNTRY_DRV +SCPath_Exit: + push ds ;switch ds, es + push es + pop ds + pop es ;DS, ES value restored + pop si + RET +SET_COUNTRY_PATH endp + +; +CHK_DRIVE_LETTER proc near +;Check if DS:[SI] is a drive letter followed by ":". +;Assume that every alpha charater is already converted to UPPER CASE. +;Carry set if not. +; + push ax + cmp byte ptr ds:[si], "A" + jb CDLetter_NO + cmp byte ptr ds:[si], "Z" + ja CDLetter_NO + cmp byte ptr ds:[si+1], ":" + jne CDLetter_NO + jmp short CDLetter_exit +CDLetter_NO: + stc +CDLetter_exit: + pop ax + ret +CHK_DRIVE_LETTER endp + +; +MOVE_ASCIIZ proc near +;In: DS:SI -> source ES:DI -> target +;Out: copy the string until 0. +;Assumes there exists a 0. +MASCIIZ_loop: + movsb + cmp byte ptr DS:[SI-1], 0 ;Was it 0? + jne MASCIIZ_loop + ret +MOVE_ASCIIZ endp + +; +; DS:DX POINTS TO STRING TO OUTPUT (ASCIZ) +; +; PRINTS +; +; +; +BADFIL: + PUSH CS + POP ES + MOV SI,DX +BADLOAD: + MOV DX,OFFSET BADLD_PRE ;WANT TO PRINT CONFIG ERROR +; MOV BX,OFFSET BADLD_POST + mov bx, offset CRLFM ;AN006; +PRNERR: + PUSH CS + POP DS + call Print +PRN1: MOV DL,ES:[SI] + OR DL,DL + JZ PRN2 + MOV AH,STD_CON_OUTPUT + INT 21H + INC SI + JMP PRN1 +PRN2: MOV DX,BX + call Print + cmp DoNotShowNum, 1 ;AN000; suppress line number when handling COMMAND.COM + je Prnexit + call Error_Line +PRNEXIT: + return + +PRINT: MOV AH,STD_CON_STRING_OUTPUT + INT 21H + return + + + IF NOEXEC +; +; LOAD NON EXE FILE CALLED [DS:DX] AT MEMORY LOCATION ES:BX +; +LDFIL: + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DS + PUSH BX + XOR AX,AX ;OPEN THE FILE + MOV AH,OPEN + STC ;IN CASE OF INT 24 + INT 21H + POP DX ;Clean stack in case jump + JC LDRET + PUSH DX + MOV BX,AX ;Handle in BX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JC LDCLSP + OR DX,DX + JNZ LDERRP ; File >64K + POP DX + PUSH DX + MOV CX,ES ; CX:DX is xaddr + ADD DX,AX ; Add file size to Xaddr + JNC DOSIZE + ADD CX,1000H ; ripple carry +DOSIZE: + mov ax,dx + call ParaRound + mov dx,ax + + ADD CX,DX + CMP CX,[ALLOCLIM] + JB OKLD + JMP MEM_ERR + +OKLD: + XOR CX,CX + XOR DX,DX + MOV AX,LSEEK SHL 8 ;Reset pointer to beginning of file + STC ;IN CASE OF INT 24 + INT 21H + JC LDCLSP + POP DX + PUSH ES ;READ THE FILE IN + POP DS ;Trans addr is DS:DX + MOV CX,0FF00H ; .COM files arn't any bigger than + ; 64k-100H + MOV AH,READ + STC ;IN CASE OF INT 24 + INT 21H + JC LDCLS + MOV SI,DX ;CHECK FOR EXE FILE + CMP WORD PTR [SI],"ZM" + CLC ; Assume OK + JNZ LDCLS ; Only know how to do .COM files + STC + JMP SHORT LDCLS + +LDERRP: + STC +LDCLSP: + POP DX ;Clean stack +LDCLS: + PUSHF + MOV AH,CLOSE ;CLOSE THE FILE + STC + INT 21H + POPF + +LDRET: POP DS + POP SI + POP DX + POP CX + POP BX + POP AX + return + ENDIF + +; +; OPEN DEVICE POINTED TO BY DX, AL HAS ACCESS CODE +; IF UNABLE TO OPEN DO A DEVICE OPEN NULL DEVICE INSTEAD +; +OPEN_DEV: + CALL OPEN_FILE + JNC OPEN_DEV3 +OPEN_DEV1: + MOV DX,OFFSET NULDEV + CALL OPEN_FILE + return + +OPEN_DEV3: + MOV BX,AX ; Handle from open to BX + XOR AX,AX ; GET DEVICE INFO + MOV AH,IOCTL + INT 21H + TEST DL,10000000B + retnz + MOV AH,CLOSE + INT 21H + JMP OPEN_DEV1 + +OPEN_FILE: + MOV AH,OPEN + STC + INT 21H + return + +;J.K. TEST INT24. Return back to DOS with the fake user response of "FAIL" +INT24: + mov al, 3 ;AN000; Fail the system call + iret ;AN000; Return back to DOS. + + +;INT24: ADD SP,6 ;RESTORE MACHINE STATE +; POP AX +; POP BX +; POP CX +; POP DX +; POP SI +; POP DI +; POP BP +; POP DS +; POP ES +; PUSH AX +; MOV AH,GET_DEFAULT_DRIVE ;INITIALIZE DOS +; INT 21H +; POP AX +; IRET ;BACK TO USER + + IF ALTVECT +BOOTMES DB 13,10,"MS-DOS version " + DB MAJOR_VERSION + "0" + DB "." + DB (MINOR_VERSION / 10) + "0" + DB (MINOR_VERSION MOD 10) + "0" + DB 13,10 + DB "Copyright 1981,88 Microsoft Corp.",13,10,"$" + ENDIF + +include copyrigh.inc ;P1821; Copyright statement + +NULDEV DB "NUL",0 +CONDEV DB "CON",0 +AUXDEV DB "AUX",0 +PRNDEV DB "PRN",0 + +CONFIG DB "\CONFIG.SYS",0 + +CNTRY_DRV DB "A:" +CNTRY_ROOT DB "\" +CNTRY_PATH DB "COUNTRY.SYS",0 + DB 52 DUP (0) + +COUNTRY_FILE_SIGNATURE db 0FFh,'COUNTRY' + +CntryCodePage_Id DW ? + +COMMND DB "\COMMAND.COM",0 + DB 51 dup (0) + +PathString db 64 dup (0) ;AN014; +LShare db "SHARE.EXE",0,"/NC",0Dh,0Ah ;AN014;AN015;To be used by Load/exec. + ;/NC parm will disable file sharing check. + +COMTAB LABEL BYTE +;;;; DB 8,"AVAILDEV",'A' ; NO LONGER SUPPORTED + DB 7,"BUFFERS", 'B' + DB 5,"BREAK", 'C' + DB 6,"DEVICE", 'D' + DB 5,"FILES", 'F' + DB 4,"FCBS", 'X' + DB 9,"LASTDRIVE",'L' + db 10,"MULTITRACK", 'M' ;AN002; + DB 8,"DRIVPARM", 'P' ; RS for DOS 3.2 + IF STACKSW + DB 6,"STACKS", 'K' ; BAS for DOS 3.2 + ENDIF + DB 7,"COUNTRY", 'Q' + DB 5,"SHELL", 'S' + db 7,"INSTALL", 'I' ;AN000; + db 3,"IFS", 'J' ;AN000; + db 4,"CPSW", 'W' ;AN000; +;;;; DB 8,"SWITCHAR",'W' ; NO LONGER SUPPORTED + db 7,"COMMENT", 'Y' ;AN000; + db 3,"REM", '0' ;AN004; + db 8,"SWITCHES", '1' ;AN013; + DB 0 + +public DeviceParameters +DeviceParameters a_DeviceParameters <0,DEV_3INCH720KB,0,80> + +hlim dw 2 +slim dw 9 + +public drive +drive db ? + +public switches +Switches dw 0 + +; +; The following are the recommended BPBs for the media that we know of so +; far. + +; 48 tpi diskettes + +BPB48T DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 2*9*40 + DB 0FDH + DW 2 + DW 9 + DW 2 + DD 0 + DD 0 + +; 96tpi diskettes + +BPB96T DW 512 + DB 1 + DW 1 + DB 2 + DW 224 + DW 2*15*80 + DB 0F9H + DW 7 + DW 15 + DW 2 + DD 0 + DD 0 + +; 3 1/2 inch diskette BPB + +BPB35 DW 512 + DB 2 + DW 1 + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DD 0 + DD 0 + +BPB35H DW 0200H + DB 01H + DW 0001H + DB 02H + DW 0E0h + DW 0B40H + DB 0F0H + DW 0009H + DW 0012H + DW 0002H + DD 0 + DD 0 + +BPBTable dw BPB48T ; 48tpi drives + dw BPB96T ; 96tpi drives + dw BPB35 ; 3.5" drives +; The following are not supported, so default to 3.5" media layout + dw BPB35 ; Not used - 8" drives + dw BPB35 ; Not Used - 8" drives + dw BPB35 ; Not Used - hard files + dw BPB35 ; Not Used - tape drives + dw BPB35H ; 3-1/2" 1.44MB drive + +switchlist db 8,"FHSTDICN" ; Preserve the positions of N and C. + +; The following depend on the positions of the various letters in SwitchList + +switchnum equ 11111000B ; which switches require number + +flagec35 equ 00000100B ; electrically compatible 3.5 inch disk drive +flagdrive equ 00001000B +flagcyln equ 00010000B +flagseclim equ 00100000B +flagheads equ 01000000B +flagff equ 10000000B + +SWTCHR EQU "/" ; switch follows this character + +SYSINITSEG ENDS + END diff --git a/v4.0/src/BOOT/BOOT.SKL b/v4.0/src/BOOT/BOOT.SKL new file mode 100644 index 0000000..764febd --- /dev/null +++ b/v4.0/src/BOOT/BOOT.SKL @@ -0,0 +1,8 @@ +:class 1 +; MESSAGES FOR THE IBM BOOT SECTOR. NUL Terminated. +; At this time, for DOS 4.00, we only have maximum 11 bytes left +; for translation.!!!!!!!!!!!!!!!!!!!!! + +:use 001 BOOT SYSMSG + +:end diff --git a/v4.0/src/BOOT/MAKEFILE b/v4.0/src/BOOT/MAKEFILE new file mode 100644 index 0000000..12ac4d8 --- /dev/null +++ b/v4.0/src/BOOT/MAKEFILE @@ -0,0 +1,25 @@ +#******************** makefile for boot ***************************** + +msg =..\messages +dos =..\dos +inc =..\inc +hinc =..\h + +# +#################### dependencies begin here ############################ +# + +all: msboot.bin + +boot.cl1: boot.skl \ + $(msg)\$(COUNTRY).MSG \ + makefile + +msboot.obj: msboot.asm boot.cl1 + +msboot.bin: msboot.obj + link msboot; + exe2bin msboot.exe msboot.bin + dbof msboot.bin boot.inc 7c00 200 + copy boot.inc $(inc) + del boot.inc diff --git a/v4.0/src/BOOT/MSBOOT.ASM b/v4.0/src/BOOT/MSBOOT.ASM new file mode 100644 index 0000000..b2a4103 --- /dev/null +++ b/v4.0/src/BOOT/MSBOOT.ASM @@ -0,0 +1,530 @@ + Page 60,132 ; SCCSID = @(#)msboot.asm 1.1 85/05/13 +TITLE BOOT SECTOR 1 OF TRACK 0 - BOOT LOADER + +; Rev 1.0 ChrisP, AaronR and others. 2.0 format boot +; +; Rev 3.0 MarkZ PC/AT enhancements +; 2.50 in label +; Rev 3.1 MarkZ 3.1 in label due to vagaries of SYSing to IBM drive D's +; This resulted in the BPB being off by 1. So we now trust +; 2.0 and 3.1 boot sectors and disbelieve 3.0. +; +; Rev 3.2 LeeAc Modify layout of extended BPB for >32M support +; Move PHYDRV to 3rd byte from end of sector +; so that it won't have to be moved again +; FORMAT and SYS count on PHYDRV being in a known location +; +; Rev. 3.3 D.C. L. Changed Sec 9 EOT field from 15 to 18. May 29, 1986. +; +; Rev 3.31 MarkT The COUNT value has a bogus check (JBE????) to determine +; if we've loaded in all the sectors of IBMBIO. This will +; cause too big of a load if the sectors per track is high +; enough, causing either a stack overflow or the boot code +; to be overwritten. +; +; Rev 4.00 J. K. For DOS 4.00 Modified to handle the extended BPB, and +; 32 bit sector number calculation to enable the primary +; partition be started beyond 32 MB boundary. +; +; +; The ROM in the IBM PC starts the boot process by performing a hardware +; initialization and a verification of all external devices. If all goes +; well, it will then load from the boot drive the sector from track 0, head 0, +; sector 1. This sector is placed at physical address 07C00h. The initial +; registers are set up as follows: CS=DS=ES=SS=0. IP=7C00h, SP=0400H. +; +; The code in this sector is responsible for locating the MSDOS device drivers +; (IBMBIO) and for placing the directory sector with this information at +; physical address 00500h. After loading in this sector, it reads in the +; entirety of the BIOS at BIOSEG:0 and does a long jump to that point. +; +; If no BIOS/DOS pair is found an error message is displayed and the user is +; prompted to reinsert another disk. If there is a disk error during the +; process, a message is displayed and things are halted. +; +; At the beginning of the boot sector, there is a table which describes the +; MSDOS structure of the media. This is equivalent to the BPB with some +; additional information describing the physical layout of the driver (heads, +; tracks, sectors) +; +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; d52 Make the fixed positioned variable "CURHD" to be local. 7/6/87 J.K. +;AN002; d48 Change head settle at boot time. 7/7/87 J.K. +;AN003; P1820 New message SKL file 10/20/87 J.K. +;AN004; D304 New structrue of Boot record for OS2. 11/09/87 J.K. +;============================================================================== + +ORIGIN EQU 7C00H ; Origin of bootstrap LOADER +BIOSEG EQU 70H ; destingation segment of BIOS +BioOff EQU 700H ; offset of bios +cbSec EQU 512 +cbDirEnt EQU 32 +DirOff EQU 500h +IBMLOADSIZE equ 3 ;J.K. Size of IBMLOAD module in sectors +ROM_DISKRD equ 2 +include version.inc + +; +; Define the destination segment of the BIOS, including the initialization +; label +; +SEGBIOS SEGMENT AT BIOSEG +BIOS LABEL BYTE +SEGBIOS ENDS + +CODE SEGMENT + ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; ORG DirOff + 1Ch +;BiosFS LABEL WORD + + ORG ORIGIN + +DSKADR = 1EH*4 ;POINTER TO DRIVE PARAMETERS + +Public $START +$START: + JMP START +;---------------------------------------------------------- +; +; THE FOLLOWING DATA CONFIGURES THE BOOT PROGRAM +; FOR ANY TYPE OF DRIVE OR HARDFILE +; +;J.K. Extened_BPB + +if ibmcopyright + DB "IBM " +else + DB "MSDOS" +endif + DB "4.0" ;AN005; +ByteSec DW cbSec ; SIZE OF A PHYSICAL SECTOR + DB 8 ; SECTORS PER ALLOCATION UNIT +cSecRes DW 1 ; NUMBER OF RESERVED SECTORS +cFat DB 2 ; NUMBER OF FATS +DirNum DW 512 ; NUMBER OF DIREC ENTRIES +cTotSec DW 4*17*305-1 ; NUMBER OF SECTORS - NUMBER OF HIDDEN SECTORS + ; (0 when 32 bit sector number) +MEDIA DB 0F8H ; MEDIA BYTE +cSecFat DW 8 ; NUMBER OF FAT SECTORS +SECLIM DW 17 ; SECTORS PER TRACK +HDLIM DW 4 ; NUMBER OF SURFACES +Ext_cSecHid label dword +cSecHid_L DW 1 ;AN000; NUMBER OF HIDDEN SECTORS +cSecHid_H dw 0 ;AN000; high order word of Hiden Sectors +Ext_cTotSec label dword +ctotsec_L dw 0 ;AN000; 32 bit version of NUMBER OF SECTORS +ctotsec_H dw 0 ;AN000; (when 16 bit version is zero) +; +Phydrv db 80h ;AN004; +Curhd db 0h ;AN004; Current Head +Ext_Boot_Sig db 41 ;AN000; +Boot_Serial dd 0 ;AN000; +Boot_Vol_Label db 'NO NAME ' ;AN000; +Boot_System_id db 'FAT12 ' ;AN000; + +;J.K. Danger!!! If not 32 bit sector number calculation, FORMAT should +;set the value of cSecHid_h and Ext_cTotSec to 0 !!! +; + +; +Public UDATA +UDATA LABEL byte +Sec9 equ byte ptr UDATA+0 ;11 byte diskette parm. table +BIOS$_L EQU WORD PTR UDATA+11 +BIOS$_H equ word ptr UDATA+13 ;AN000; +CURTRK EQU WORD PTR UDATA+15 +CURSEC EQU BYTE PTR UDATA+17 +DIR$_L EQU WORD PTR UDATA+18 +Dir$_H equ word ptr UDATA+20 ;AN000; +START: + +; +; First thing is to reset the stack to a better and more known place. The ROM +; may change, but we'd like to get the stack in the correct place. +; + CLI ;Stop interrupts till stack ok + XOR AX,AX + MOV SS,AX ;Work in stack just below this routine + ASSUME SS:CODE + MOV SP,ORIGIN + PUSH SS + POP ES + ASSUME ES:CODE +; +; We copy the disk parameter table into a local area. We scan the table above +; for non-zero parameters. Any we see get changed to their non-zero values. +; +;J.K. We copy the disk parameter table into a local area (overlayed into the +;code), and set the head settle time to 1, and End of Track to SECLIM given +;by FORMAT. + + MOV BX,DSKADR + LDS SI,DWORD PTR SS:[BX] ; get address of disk table + PUSH DS ; save original vector for possible + PUSH SI ; restore + PUSH SS + PUSH BX + MOV DI,offset Sec9 + MOV CX,11 + CLD +if $ le BIOS$_L + %OUT Don't destroy unexcuted code yet!!! +endif + repz movsb ;AN000; + push es ;AN000; + pop ds ;AN000; DS = ES = code = 0. + assume ds:code ;AN000; +; mov byte ptr [di-2], 1 ;AN000; Head settle time +;J.K. Change the head settle to 15 ms will slow the boot time quite a bit!!! + mov byte ptr [di-2], 0fh ;AN002; Head settle time + mov cx, SECLIM ;AN004; + mov byte ptr [di-7], cl ;AN000; End of Track +; +; Place in new disk parameter table vector. +; + MOV [BX+2],AX + MOV [BX],offset SEC9 +; +; We may now turn interrupts back on. Before this, there is a small window +; when a reboot command may come in when the disk parameter table is garbage +; + STI ;Interrupts OK now +; +; Reset the disk system just in case any thing funny has happened. +; + INT 13H ;Reset the system +; JC RERROR + jc CKErr ;AN000; +; +; The system is now prepared for us to begin reading. First, determine +; logical sector numbers of the start of the directory and the start of the +; data area. + + xor ax,ax ;AN000; + cmp cTotSec,ax ;AN000; 32 bit calculation? + je Dir_Cont ;AN000; + mov cx,cTotSec ;AN000; + mov cTotSec_L,cx ;AN000; cTotSec_L,cTotSec_H will be used for calculation +Dir_Cont: ;AN000; + MOV AL,cFat ;Determine sector dir starts on + MUL cSecFat ;DX;AX + ADD AX,cSecHid_L + adc DX,cSecHid_H ;AN000; + ADD AX,cSecRes + ADC DX,0 + MOV [DIR$_L],AX ; DX;AX = cFat*cSecFat + cSecRes + cSecHid + mov [DIR$_H],DX ;AN000; + MOV [BIOS$_L],AX + mov [BIOS$_H],DX ;AN000; +; +; Take into account size of directory (only know number of directory entries) +; + MOV AX,cbDirEnt ; bytes per directory entry + MUL DirNum ; convert to bytes in directory + MOV BX,ByteSec ; add in sector size + ADD AX,BX + DEC AX ; decrement so that we round up + DIV BX ; convert to sector number + ADD [BIOS$_L],AX ; Start sector # of Data area + adc [BIOS$_H],0 ;AN000; + +; +; We load in the first directory sector and examine it to make sure the the +; BIOS and DOS are the first two directory entries. If they are not found, +; the user is prompted to insert a new disk. The directory sector is loaded +; into 00500h +; + MOV BX,DirOff ; sector to go in at 00500h + mov dx,[DIR$_H] ;AN000; + MOV AX,[DIR$_L] ; logical sector of directory + CALL DODIV ; convert to sector, track, head + jc CKErr ;AN000; Overflow? BPB must be wrong!! +; MOV AX,0201H ; disk read 1 sector + mov al, 1 ;AN000; disk read 1 sector + CALL DOCALL ; do the disk read + JB CKERR ; if errors try to recover +; +; Now we scan for the presence of IBMBIO COM and IBMDOS COM. Check the +; first directory entry. +; + MOV DI,BX + MOV CX,11 + MOV SI,OFFSET BIO ; point to "ibmbio com" + REPZ CMPSB ; see if the same + JNZ CKERR ; if not there advise the user +; +; Found the BIOS. Check the second directory entry. +; + LEA DI,[BX+20h] + MOV SI,OFFSET DOS ; point to "ibmdos com" + MOV CX,11 + REPZ CMPSB + JZ DoLoad + +; +; There has been some recoverable error. Display a message and wait for a +; keystroke. +; +CKERR: MOV SI,OFFSET SYSMSG ; point to no system message +ErrOut: CALL WRITE ; and write on the screen + XOR AH,AH ; wait for response + INT 16H ; get character from keyboard + POP SI ; reset disk parameter table back to + POP DS ; rom + POP [SI] + POP [SI+2] + INT 19h ; Continue in loop till good disk + +Load_Failure: + pop ax ;adjust the stack + pop ax + pop ax + jmp short Ckerr ;display message and reboot. + +;J.K. We don't have the following error message any more!!! +;J.K. Sysmsg is fine. This will save space by eliminating DMSSG message. +;RERROR: MOV SI,OFFSET DMSSG ; DISK ERROR MESSAGE +; JMP ErrOut + +; +; We now begin to load the BIOS in. Compute the number of sectors needed. +; J.K. All we have to do is just read in sectors contiguously IBMLOADSIZE +; J.K. times. We here assume that IBMLOAD module is contiguous. Currently +; J.K. we estimate that IBMLOAD module will not be more than 3 sectors. + +DoLoad: + mov BX,BioOff ;offset of ibmbio(IBMLOAD) to be loaded. + mov CX,IBMLOADSIZE ;# of sectors to read. + mov AX, [BIOS$_L] ;Sector number to read. + mov DX, [BIOS$_H] ;AN000; +Do_While: ;AN000; + push AX ;AN000; + push DX ;AN000; + push CX ;AN000; + call DODIV ;AN000; DX;AX = sector number. + jc Load_Failure ;AN000; Adjust stack. Show error message + mov al, 1 ;AN000; Read 1 sector at a time. + ;This is to handle a case of media + ;when the first sector of IBMLOAD is the + ;the last sector in a track. + call DOCALL ;AN000; Read the sector. + pop CX ;AN000; + pop DX ;AN000; + pop AX ;AN000; + jc CkErr ;AN000; Read error? + add AX,1 ;AN000; Next sector number. + adc DX,0 ;AN000; + add BX,ByteSec ;AN000; adjust buffer address. + loop Do_While ;AN000; + + +; MOV AX,BiosFS ; get file size +; XOR DX,DX ; presume < 64K +; DIV ByteSec ; convert to sectors +; INC AL ; reading in one more can't hurt +; MOV COUNT,AL ; Store running count +; MOV AX,BIOS$ ; get logical sector of beginning of BIOS +; MOV BIOSAV,AX ; store away for real bios later +; MOV BX,BioOff ; Load address from BIOSSEG +; +; Main read-in loop. +; ES:BX points to area to read. +; Count is the number of sectors remaining. +; BIOS$ is the next logical sector number to read +; +;LOOPRD: +; MOV AX,BIOS$ ; Starting sector +; CALL DODIV +; +; CurHD is the head for this next disk request +; CurTrk is the track for this next request +; CurSec is the beginning sector number for this request +; +; Compute the number of sectors that we may be able to read in a single ROM +; request. +; +; MOV AX,SECLIM +; SUB AL,CURSEC +; INC AX +; +; AX is the number of sectors that we may read. +; + +; +;New code for Rev 3.31 +;***************************************************************************** + +; CMP COUNT,AL ;Is sectors we can read more than we need? +; JAE GOT_SECTORS ;No, it is okay +; MOV AL,COUNT ;Yes, only read in what is left + +;GOT_SECTORS: + +;***************************************************************************** +;End of change +; + + +; PUSH AX +; CALL DOCALL +; POP AX +; JB RERROR ; If errors report and go to ROM BASIC +; SUB COUNT,AL ; Are we finished? +; +;Old code replaced by Rev 3.3 +;******************************************************************** +; JBE DISKOK ; Yes -- transfer control to the DOS +;******************************************************************** +;New code for Rev 3.3 +; + +; JZ DISKOK ; Yes -- transfer control to the DOS + +;******************************************************************** +;End of change +; +; ADD BIOS$,AX ; increment logical sector position +; MUL ByteSec ; determine next offset for read +; ADD BX,AX ; (BX)=(BX)+(SI)*(Bytes per sector) +; JMP LOOPRD ; Get next track +; +; IBMINIT requires the following input conditions: +; +; DL = INT 13 drive number we booted from +; CH = media byte +;J.K.I1. BX was the First data sector on disk (0-based) +;J.K.I1. IBMBIO init routine should check if the boot record is the +;J.K.I1. extended one by looking at the extended_boot_signature. +;J.K.I1. If it is, then should us AX;BX for the starting data sector number. + +DISKOK: + MOV CH,Media + MOV DL,PhyDrv + MOV bx,[BIOS$_L] ;AN000; J.K.I1.Get bios sector in bx + mov ax,[BIOS$_H] ;AN000; J.K.I1. + JMP FAR PTR BIOS ;CRANK UP THE DOS + +WRITE: LODSB ;GET NEXT CHARACTER + OR AL,AL ;clear the high bit + JZ ENDWR ;ERROR MESSAGE UP, JUMP TO BASIC + MOV AH,14 ;WILL WRITE CHARACTER & ATTRIBUTE + MOV BX,7 ;ATTRIBUTE + INT 10H ;PRINT THE CHARACTER + JMP WRITE + +; convert a logical sector into Track/sector/head. AX has the logical +; sector number +; J.K. DX;AX has the sector number. Because of not enough space, we are +; going to use Simple 32 bit division here. +; Carry set if DX;AX is too big to handle. +; + +DODIV: + cmp dx,Seclim ;AN000; To prevent overflow!!! + jae DivOverFlow ;AN000; Compare high word with the divisor. + DIV SECLIM ;AX = Total tracks, DX = sector number + INC DL ;Since we assume SecLim < 255 (a byte), DH =0. + ;Cursec is 1-based. + MOV CURSEC, DL ;save it + XOR DX,DX + DIV HDLIM + MOV CURHD,DL ;Also, Hdlim < 255. + MOV CURTRK,AX + clc ;AN000; + ret ;AN000; +DivOverFlow: ;AN000; + stc ;AN000; +EndWR: + ret + +; +;J.K.We don't have space for the following full 32 bit division. +; convert a logical sector into Track/sector/head. AX has the logical +; sector number +; J.K. DX;AX has the sector number. +;DODIV: +; push ax +; mov ax,dx +; xor dx,dx +; div SecLim +; mov Temp_H,ax +; pop ax +; div SecLim ;J.K.Temp_H;AX = total tracks, DX=sector +; INC DL ;Since we assume SecLim < 255 (a byte), DH =0. +; ;Cursec is 1-based. +; MOV CURSEC, DL ;save it +; push ax +; mov ax,Temp_H +; XOR DX,DX +; DIV HDLIM +; mov Temp_H,ax +; pop ax +; div HdLim ;J.K.Temp_H;AX=total cyliners,DX=head +; MOV CURHD,DL ;Also, Hdlim < 255. +; cmp Temp_H,0 +; ja TooBigToHandle +; cmp ax, 1024 +; ja TooBigToHandle +; MOV CURTRK,AX +;ENDWR: RET +;TooBigToHandle: +; stc +; ret + +; +; Issue one read request. ES:BX have the transfer address, AL is the number +; of sectors. +; +DOCALL: MOV AH,ROM_DISKRD ;AC000;=2 + MOV DX,CURTRK + MOV CL,6 + SHL DH,CL + OR DH,CURSEC + MOV CX,DX + XCHG CH,CL + MOV DL, PHYDRV + mov dh, curhd + INT 13H + RET + +; include ibmbtmes.inc + include boot.cl1 ;AN003; + + + IF IBMCOPYRIGHT +BIO DB "IBMBIO COM" +DOS DB "IBMDOS COM" + ELSE +BIO DB "IO SYS" +DOS DB "MSDOS SYS" + ENDIF + +Free EQU (cbSec - 4) - ($-$start) ;AC000; +;Free EQU (cbSec - 5) - ($-$start) +if Free LT 0 + %out FATAL PROBLEM:boot sector is too large +endif + + org origin + (cbSec - 2) ;AN004; +; org origin + (cbSec - 5) + +;Warning!! Do not change the position of following unless +;Warning!! you change BOOTFORM.INC (in COMMON subdirectory) file. +;Format should set this EOT value for IBMBOOT. +;FEOT db 12h ;AN000; set by FORMAT. AN004;Use SecLim in BPB instead. +; FORMAT and SYS count on CURHD,PHYDRV being right here +;J.K. CURHD has been deleted since it is not being used by anybody. +;CURHD DB ? ;AN001;Unitialized (J.K. Maybe don't need this). +;PHYDRV db 0 ;AN000;moved into the header part. +; Boot sector signature + db 55h,0aah + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/APPEND/APPEND.ASM b/v4.0/src/CMD/APPEND/APPEND.ASM new file mode 100644 index 0000000..5ca2b70 --- /dev/null +++ b/v4.0/src/CMD/APPEND/APPEND.ASM @@ -0,0 +1,3462 @@ +page 60,120 +; +.sall +title APPEND +include sysmsg.inc +msg_utilname +;----------------------------------------------------------------------------- +; +; Title: APPEND +; +; Author: G. G. A. Network version +; B. A. F.` DOS changes +; +; Syntax: From the DOS command line: +; +; APPEND [d:]path[[;[d:]path]...] +; - Used to specify the directories to be +; searched after the working directory. +; +; APPEND ; +; - Used to release all appended directories. +; +; APPEND +; - Used to show appended directories. +; +; First time only: +; +; APPEND [[d:]path | | /X | /E | /X /E] +; - [d:]path Normal support and Set path +; - Normal support +; - /X Extended support, SEARCH, FIND and EXEC +; - /E Use DOS Environment for path(s) +; +; Revision History: +; @@01 07/11/86 Fix hang in TopView start PTM P00000?? +; @@02 07/28/86 Fix APPEND size problem PTM P0000045 +; @@03 07/29/86 Fix APPEND status with /E problem PTM P00000?? +; @@04 07/30/86 Fix second APPEND hang PTM P0000053 +; @@05 08/13/86 Fix parameter error PTM P0000125 +; @@06 08/20/86 Fix APPEND xxx fails in TopView PTM P0000217 +; @@07 08/21/86 Resurrect APPEND version message PTM P0000252 +; @@08 08/21/86 APPEND=path first time hangs PTM P0000254 +; @@09 08/22/86 APPEND gets wrong path under nested COMMAND PTM P0000276 +; @@10 08/28/86 Change message for @@05 PTM P0000291 +; @@11 09/10/86 Support message profile and make +; msg length variable. R.G. PTM P0000479 +; @@12 09/25/86 Allow second external append call. (RG) PTM P0000515 +; @@13 09/30/86 APPEND gets wrong path under nested COMMAND PTM P0000600 +; Again. Fix in COMMAND now, so remove @@09 changes +; @@14 10/01/86 Lower case drive in path files PTM P0000600 +; @@15 10/06/86 Include "," and "=" in skip leading of +; argument area parsing. PTM P0000677 +; @@16 10/06/86 Fix not using full APPEND path PTM P0000794 +; @@17 12/03/86 When searching for "APPEND=" string in +; environment, make sure delimiter precedes.(RG) PTM P0000893 +; +;------------------------------------------------------------------- +; +; AN000 3.30 changes, GGA 6/87 new code. P000 +; AN001 Support DRIVE and PATH modes D043 +; AN002 Add truename function P1276 +; AN003 Add extended handle open function D250 +; AN005 +; AN006 Add DBCS support +; AN007 Release Environmental Vector space P2666 +; AN008 Allow equal symbol with append - APPEND=A:/1; P2901 +; AN009 Release Environmental Vector on only the P3333 +; first invocation of APPEND +; AN010 display invalid parm from command line P3908 +; +; +;----------------------------------------------------------------------------- +;Date Rev Comments +;----------------------------------------------------------------------------- +;06-02-86 0.0 Begin conversion to PC/DOS version +;06-20-86 0.0 End conversion to PC/DOS version +; +page + +cseg segment public para 'CODE' + assume cs:cseg + assume ds:nothing,es:nothing + +;----------------------------------------------------------------------------- +; Equates +;----------------------------------------------------------------------------- + +.xlist +;include fsi.lib +NETSYSUTIL EQU 0C2H ; SYSTEM UTILITIES +NETENQ EQU 07H ; ENQ RESOURCE +NETDEQ EQU 08H ; DEQ RESOURCE +;include task.lib +TCBR_APPEND EQU 001H ; APPEND ACTIVE +;include DOS.lib +DOSSERVER EQU 5DH ; SERVER OPERATION +DOSSETERROR EQU 0AH ; SET EXTENDED ERROR +;include server.lib +DPL STRUC +DPL_AX DW 0 ;AX REG +DPL_BX DW 0 ;BX REG +DPL_CX DW 0 ;CX REG +DPL_DX DW 0 ;DX REG +DPL_SI DW 0 ;SI REG +DPL_DI DW 0 ;DI REG +DPL_DS DW 0 ;DS REG +DPL_ES DW 0 ;ES REG +DPL_XID DW 0 ;RESERVED +DPL_UID DW 0 ;SERVER USER ID +DPL_PID DW 0 ;REDIRECTOR PROCESS ID +DPL ENDS +include sysmac.lib +include versiona.inc +include appendp.inc ; parseing stuff for append ;AN004; +.list +; extrn end_address:near ; end of stay resident stuff + +; extrn bad_append_msg:byte ; messages +; extrn path_error_msg:byte +; extrn parm_error_msg:byte +; extrn path_parm_error_msg:byte +; extrn no_append_msg:byte ; @@05 +; extrn append_assign_msg:byte +; extrn append_TV_msg:byte ; @@01 +; extrn bad_DOS_msg:byte +; extrn second_APPEND_msg:byte ; @@04 + +; extrn len_bad_append_msg:word ;@@11 +; extrn len_path_error_msg:word ;@@11 +; extrn len_parm_error_msg:word ;@@11 +; extrn len_path_parm_error_msg:word ;@@11 +; extrn len_no_append_msg:word ;@@11 +; extrn len_append_assign_msg:word ;@@11 +; extrn len_append_TV_msg:word ;@@11 +; extrn len_bad_DOS_msg:word ;@@11 +; extrn len_second_APPEND_msg:word ;@@11 + +; Environmental Vector + +PSP_Env equ 2ch ;Environmental vector segment in PSP ;an007; dms; + +; Interrupts + +DOS_function equ 21h ; DOS function call interrupt +int_function equ 2fh ; DOS internal function interrupt, used + ; to verify APPEND presence +termpgm equ 20h ; @@05 +resident equ 27h + +; Function calls + +get_vector equ 3521h ; DOS function call to get INT 21 vector +set_vector equ 2521h ; DOS function call to set INT 21 vector +get_intfcn equ 352fh ; DOS function call to get INT 2f vector +set_intfcn equ 252fh ; DOS function call to set INT 2f vector +get_version equ 30h ; DOS function call to get DOS version number +get_DTA equ 2fh ; DOS function get DTA +set_DTA equ 1ah ; DOS function set DTA +get_crit_err equ 3524h ; DOS function call to get INT 24 vector +set_crit_err equ 2524h ; DOS function call to set INT 24 vector +get_PSP equ 62h ; DOS function call to get PSP address +Free_Alloc_Mem equ 49h ; DOS function call to free alloc. mem. ;an007; dms; + +print_string equ 09h ; DOS function call to get print a string +ctrl_break equ 33h ; DOS function call to get/set ctrl-break + +awrite equ 40h ; write function +get_dir equ 47h ; get current dir +change_dir equ 3bh ; change dir +get_disk equ 19h ; get current disk +change_disk equ 0eh ; change disk +term_stay equ 31h ; terminate a process and stay resident +term_proc equ 4ch ; terminate a process + +redir_flag equ 0000000000001000B ; redir flag for net installation check + +; DOS INT 2f function for APPEND presence + +append_2f equ 0b7h ; int 2f function code for append +applic_2f equ 0aeh ; int 2f function code for applications +COMMAND_2f equ -1 ; int 2f subfunction code for COMMAND call +append_inst equ 0ffh ; flag means append is there + +; INT 2f sub-function codes ;AN000; + +are_you_there equ 0 ; function code for presence check +old_dir_ptr equ 1 ; means APPEND 1.0 is trying to run +get_app_version equ 2 ; fun code for get ver request +tv_vector equ 3 ; fun code for set TV vector +dir_ptr equ 4 ; function code to return dirlist ptr +get_state equ 6 ; function code to return append ;AN001; + ; state ;AN001; +set_state equ 7 ; function code to set append ;AN001; + ; state ;AN001; + +DOS_version equ 10h ; function call to get DOS version +true_name equ 11h ; one-shot truename fcn for ASCIIZ ops ;AN002; + +; DOS INT 21 function calls that APPEND traps + +FCB_opn equ 0fh +file_sz equ 23h +handle_opn equ 3dh +dat_tim equ 57h +FCB_sch1 equ 11h +handle_fnd1 equ 4eh +exec_proc equ 4bh +ext_handle_opn equ 6ch ;AN003; + +break macro ; this is a dummy break macro so PDB.INC + endm ; won't blow up in the build + +; define some things for PDB (PSP) ;AN002; + ;AN002; +include pdb.inc ;AN002; + ;AN002; +true_name_flag equ 01h ; flag for true name function ;AN002; +eo_create equ 00f0h ; mask to check extended opens for create ;AN003; + +; Error codes that don't mean stop looking + +FCB_failed equ 0ffh ; FCB open failed +FCB_file_not_found equ 2 ; file not found on FCB open +handle_file_not_found equ 2 ; file not found on handle open +handle_path_not_found equ 3 ; path not found on handle open +FCB_no_more_files equ 18 ; no more matching files +handle_no_more_files equ 18 ; no more matching files + +; Equates for TOPVIEW barrier +TV_TRUE equ -1 ; this was changed from TRUE ;AN000; + ; because 3.30 parser uses TRUE ;AN000; +false equ 0 ; + +; Message equates + +tab_char equ 9 +cr equ 13 +lf equ 10 +beep equ 7 +STDOUT equ 0001h ; standard output file +STDERR equ 0002h ; standard error file +null equ 0 + +page + +;----------------------------------------------------------------------------- +; Resident data area +;----------------------------------------------------------------------------- + +version_loc: ; version number + db major_version,minor_version +; dw message_list ; pointer to message table + + even +vector_offset dw 0 ; save pointer to old int 21 here +vector_segment dw 0 +crit_vector_offset dw 0 ; save pointer to old int 24 here +crit_vector_segment dw 0 +intfcn_offset dw 0 ; save pointer to old int 2f here +intfcn_segment dw 0 +dirlst_offset dw 0 ; save pointer to dir list here +dirlst_segment dw 0 +tv_vec_off dw 0 ; save TV vector here +tv_vec_seg dw 0 + +pars_off dd cseg: SysParse ; save pointer to parser here +;pars_off dw offset SysParse ; save pointer to parser here +;pars_seg dw 0 + +app_dirs_seg dw 0 ; save ES here during FCB + +FCB_ptr dd 0 ; save pointer to FCB here +handle_ptr dd 0 ; save pointer to ASCIIZ string here + +stack_offset dw 0 +stack_segment dw 0 ; Calling process stack + +incoming_AX dw 0 ; AX saved at entry to interrupt handler +incoming_CX dw 0 ; CX saved at entry to interrupt handler +; must be together +incoming_BX dw 0 ; BX saved at entry to interrupt handler +incoming_ES dw 0 ; ES saved at entry to interrupt handler +; must be together +ax_after_21 dw 0 ; AX saved after call to real INT 21 +; temp_DS_save dw 0 ; DS saved during stack ops +temp_CS_save dw 0 ; CS saved during stack ops (set_return_flags) +temp_IP_save dw 0 ; IP saved during stack ops (set_return_flags) +FCB_drive_id db 0 ; save the drive id for FCB opens here + +;------------------------ +; DBCS stuff here ;AN006; + ;AN006; +DBCSEV_OFF DW 0 ; OFFSET OF DBCS EV ;AN006; +DBCSEV_SEG DW 0 ; SEGMENT OF DBCS EV ;AN006; + ;AN006; +;DEFAULT DBCS ENVIRONMENTAL VECTOR ;AN006; +EVEV DB 00H,00H ;AN006; + DB 00H,00H ;AN006; + DB 00H,00H ;AN006; + ;AN006; +dbcs_fb dw 0 ; offset of DBCS first byte chars found +;------------------------ + +initial_pass dw 0 ; flag used to indicate inital APPEND ;AN007; + +incoming_DX dw 0 ; used for saves for extended open ;AN003; +incoming_SI dw 0 ; used for saves for extended open ;AN003; +incoming_DI dw 0 ; used for saves for extended open ;AN003; +incoming_DS dw 0 ; used for saves for extended open ;AN003; +true_name_count dw 0 ; used to save number of chars in true_name dir ;AN003; + +int_save_ip dw 0 ; save registers here during critical +int_save_cs dw 0 ; error handler stack ops + +work_disk db "?:\" ; user's working disk +work_dir db 64 dup(" ") ; user's working dir +app_disk db "?:\" ; user's working disk +app_dir db 64 dup(" ") ; user's append disk's working dir +ctrl_break_state db 0 ; save the old ctrl-break state here + +end_search db 0 ; end search flag +try_dir db 128 dup (0) ; try this dir +fname db 15 dup (0) ; 8.3 filename stripped from original + ; ASCIIZ string +app_dirs_ptr dw 0 ; pointer to appended dir to try + +set_name db "SET " ; SET command +; must be together +setappend_name db "SET " ; SET command +append_id db "APPEND=" ; display from here for user +; must be together +app_dirs db ";" + db 128 dup (0) ; area for storing appended dirs + db 0 ; just to insure that the last dir is null terminated +semicolon db ";",0 ; null list + +; Flags / barriers added for TopView + +tv_flag db 0 ; flag to indicate re-entr from TopView + +parse_flag db 0 ; flag used by APPEND parsing + +FCB_ext_err db 0 ; flag used to indicate that FCB + ; open failed and ext err was done +crit_err_flag db 0 ; flag used to indicate that a critical + ; error happened +ext_err_flag db 0 ; flag used to indicate that ext err + ; must be set 0 = don't set, 1 = do set +in_middle db 0 ; flag used to tell if we made it to + ; middle of string before finding a space +equal_found db 0 ; multiple = check +;crit_sect_flag db 0 ; critical section flag + +stack_area dw 99 dup(0) ; stack area for append +append_stack dw 0 + +net_config dw 0 ; flag word for what (if any) network + ; config we are running under + ; as long as this word is zero, a clear determination + ; has not been made about the configuration + + even +ext_err_dpl DPL <> ; reserve a DPL for get/set extended error code + + +save_ext_err DPL <> ; reserve a DPL for first extended + ; error code + +;------------------------------------------------------------------- ;AN001; +; ;AN001; +; mode_flags This status word is used to control the various ;AN001; +; APPEND functions and modes. ;AN001; +; ;AN001; +;------------------------------------------------------------------- ;AN001; +mode_flags dw Path_mode + Drive_mode + Enabled ;AN001; + ; mode control flags ;AN001; + ; initially - path, drive and ;AN001; + ; enabled ;AN001; + +; equates for mode_flags follow: ;AN001; + +X_mode equ 8000h ; in /X mode +E_mode equ 4000h ; in /E mode +Path_mode equ 2000h ; PATH in string OK ;AN001; +Drive_mode equ 1000h ; DRIVE in string OK ;AN001; +Enabled equ 0001h ; APPEND enabled ;AN001; + +;------------------------------------------------------------------- + +cmd_name@ dd ? ; internal name string + +expected_error dw ? ; error to do append scan +expected_ext_error dw ? ; error to do append scan + +cmd_env dw ? ; pointer to COMMANDs environment +cmd_buf dw ? ; CMDBUF offset (in SS) + +incoming_DTA dd ? ; user's DTA (on EXEC) +exec_DTA db 21+1+2+2+2+2+13 dup(0) ; find DTA for exec emulation + +old_syntax db 0 ; using network syntax + +res_append db 0 ; resident append call ; @@05 + +abort_sp dw ? ; sp to restore on errors ; @@05 + +crlf label byte + db CR,LF +crlf_len equ $ - crlf + +;******************************************************************* ;an010;bgb +; parser message display area ;an010;bgb +;******************************************************************* ;an010;bgb +inv_parm db 0bh ;length ;an010;bgb + db 0 ;reserved ;an010;bgb +si_off dw 0 ;put offset of command line here ;an010;bgb +si_seg dw 0 ;put segment of command line here ;an010;bgb + db 0 ;use percent zero ;an010;bgb + db Left_Align+Char_Field_ASCIIZ ;type of data ;an010;bgb + db 128 ;max width ;an010;bgb + db 1 ;min width ;an010;bgb + db ' ' ;pad char ;an010;bgb + +;------------------------------------------------------------------- +; +; resident message area +; +;------------------------------------------------------------------- + +MSG_SERVICES +MSG_SERVICES ;an010;bgb +MSG_SERVICES + +.xlist +;----------------------------------------------------------------------------- +; macros +;----------------------------------------------------------------------------- + +;----------------------------- +; save and restore register macros +save_regs macro + push bx + push cx + push dx + + push di + push si + push ds + push es + endm + +restore_regs macro + pop es + pop ds + pop si + pop di + + pop dx + pop cx + pop bx + endm + +;----------------------------- +; this macro is used instead of the normal POPF instruction to help +; prevent a 286 bug from occurring +popff macro + local myret + jmp $+3 +myret label near + iret + push cs + call myret + endm + +;----------------------------- ; @@12 +; check character ; @@12 +; ; @@12 +chkchar macro char ; @@12 + lodsb ; @@12 + and al,0dfh ; @@12 + cmp al,char ; @@12 + jne ccn_ret ; @@12 + endm ; @@12 +.list + +page +;----------------------------------------------------------------------------- +; resident routine - control transferred here on INT 21 +; check to see if this call has a function code we are interested in +;----------------------------------------------------------------------------- + + +tv_entry: + pushf ; @@01 + jmp check_fcb_open ; @@01 + +interrupt_hook: +resident_routine: + pushf ; save the user's flags (old stack) + + cmp tv_flag,TV_TRUE ; see if in TV ;AN000; + je use_old ; yes, old_vect + +check_fcb_open: ; @@01 + +;------------------------------------------------------------------- ;AN001; +; first, check to see if APPEND disabled, if so, skip everything ;AN001; +; and go to real INT 21 handler ;AN001; +;------------------------------------------------------------------- ;AN001; + test mode_flags,Enabled ; APPEND disabled? ;AN001; + jz real_jump ; yes, skip all other checks ;AN001; + + cmp ah,FCB_opn ; FCB open? + jump E,FCB_open ; yes, do the APPEND + + cmp ah,handle_opn ; handle open? + jump E,handle_open ; yes, do the APPEND + + cmp ah,ext_handle_opn ; extended handle open? ;AN003; + jump E,ext_handle_open ; yes, do the APPEND ;AN003; + ;AN003; + cmp ah,file_sz ; file size? + jump E,FCB_open ; yes, do the APPEND + + + test mode_flags,X_mode ; /X mode not selected + jz real_jump + + cmp ah,FCB_sch1 ; search? + jump E,FCB_search1 ; yes, do the APPEND + + cmp ah,handle_fnd1 ; find? + jump E,handle_find1 ; yes, do the APPEND + + cmp tv_flag,TV_TRUE ; cant do in TopView ;AN000; + je skip_exec + cmp ax,exec_proc*256+0 ; EXEC? + jump E,exec_pgm ; yes, do the APPEND +skip_exec: + cmp ax,exec_proc*256+3 ; EXEC? + jump E,exec_pgm ; yes, do the APPEND + + page +;----------------------------------------------------------------------------- +; By here, we know that the call was not one we are interested in, +; pass through to old INT 21. +; Since this is done with a jmp, control will pass back to original caller +; after DOS is finished. +;----------------------------------------------------------------------------- + +real_jump: + cmp tv_flag,TV_TRUE ; see if called by TV ;AN000; + jne use_old ; yes, use old vect + + popff ; restore user's flags + jmp dword ptr tv_vec_off ; pass through to TV + +use_old: + popff ; restore user's flags (old stack) + jmp dword ptr Vector_Offset ; jump to old INT 21 + +page +;----------------------------------------------------------------------------- +; FCB_search1 - this routine handles FCB search first calls +;----------------------------------------------------------------------------- + +FCB_search1: + mov expected_ext_error,fcb_no_more_files + jmp short FCB_openx1 + +;----------------------------------------------------------------------------- +; FCB_open - this routine handles FCB open calls +;----------------------------------------------------------------------------- + +FCB_open: + mov expected_ext_error,fcb_file_not_found +FCB_openx1: + call check_config ; check the config flags + call crit_sect_set ; set critical section flag + + call tv_barrier + + mov incoming_AX,ax ; save user's AX + mov word ptr FCB_ptr+0,dx ; save FCB pointer + mov word ptr FCB_ptr+2,ds + + popff ; restore user's flags + call int_21 ; try the open + + cli + mov AX_after_21,ax ; save AX as it came back from INT + pushf ; save flags from operation + cmp al,FCB_failed ; open failed ? + je check_error ; yes, lets check extended error + jmp set_return_flags ; no, fix the stack, then ret to caller + +check_error: + call get_ext_err_code ; get the extended error code + mov FCB_ext_err,1 ; set FCB ext error + call save_first_ext_err ; save first extended error code + mov ax,ext_err_dpl.DPL_AX ; get error in ax + cmp ax,expected_ext_error ; file not found? + je FCB_openx2 ; yes, lets look around for file + lea dx,save_ext_err ; + call set_ext_err_code ; set the extended error code + jmp set_return_flags ; no, fix the stack, then return + +FCB_openx2: + +; set up APPEND's stack + + popff ; get rid of the flags from the + ; real operation +; mov temp_DS_save,ds ; Save DS reg + mov stack_segment,ss ; Save it + mov stack_offset,sp ; Save it + mov ax,cs ; Get current segment + mov ss,ax ; and point stack seg here + lea sp,append_stack ; set up new stack + + save_regs ; save registers + + push cs ; establish addressability + pop ds + + call ctrl_break_set ; set ctrl-break handler + call crit_err_set ; set crit err handler + + mov ext_err_flag,1 ; flag for setting critical error + +; fix FCB drive spec + + les bx,dword ptr FCB_ptr ; ES:BX points to FCB + mov ah,ES:byte ptr [bx] ; get FCB drive spec + cmp ah,-1 ; extended FCB? + jne not_ext_FCB1 + add bx,1+5+1 ; point to real drive letter + mov ah,ES:byte ptr [bx] ; get FCB drive spec + +not_ext_FCB1: + mov FCB_drive_id,ah ; save it for later + mov ES:byte ptr [bx],0 ; zero the drive field out to + ; use default drive + + mov ah,get_disk ; get disk + call int_21 ; call DOS INT 21 handler + + add al,"A" ; make it a character + mov work_disk,al ; save it + + mov ah,get_dir ; get directory + xor dx,dx ; default drive + lea si,work_dir ; save area + call int_21 ; call DOS INT 21 handler + + call address_path ; get address of path + cmp es: byte ptr [di],";" ; is the append list null? + jump E,null_list ; exit append + mov app_dirs_seg,es ; save app dirs segment + mov si,di ; source + +try_another1: + lea di,try_dir ; destination + call get_app_dir ; copy dir to try into try_dir + mov app_dirs_ptr,si ; save updated pointer + + +;----------------------------- +try_app_dir1: + mov app_disk,0 ; zero for current dir + cmp try_dir+1,":" ; see if we have a drive + jne no_drive ; char should be a colon + +; yes, there was a drive specified, must do the change disk function call + + mov ah,change_disk ; change disk + mov dl,try_dir ; get the char representation of the drive + mov app_disk,dl ; save it away for later use + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler +; jc check_end_dir_list ; there was an error, see if there is + ; another to try + + cmp crit_err_flag,0 ; did we experience a critical error + jne set_err_code ; yes, fake a file_not_found + +no_drive: + mov ah,get_dir ; get directory + xor dx,dx ; default drive + lea si,app_dir ; save area + call int_21 ; call DOS INT 21 handler + +; check to see if there was a critical error + + cmp crit_err_flag,0 ; did we experience a critical error + je cd_worked ; no, the cd worked + jmp short set_err_code + +save_regs_and_set: + pushf ; save everything again + save_regs + push cs ; re-establish addressability + pop ds ; ds = cs + +set_err_code: + xor ah,ah ; make ax look like open failed + mov al,FCB_failed + mov ax_after_21,ax ; save it away so we can restore it below + + jmp no_more_to_try + +cd_worked: + lea dx,try_dir ; point dx to dir to try + mov ah,change_dir ; change dir to appended directory + call int_21 ; call DOS INT 21 handler + +; try the open in this dir + + restore_regs ; make regs look like when user + mov ax,incoming_AX ; called us + + call int_21 ; call DOS INT 21 handler + mov ax_after_21,ax ; save AX + cmp crit_err_flag,0 ; did we get critical error? + jne save_regs_and_set ; yes, fake a file_not_found + cmp al,FCB_failed ; did open work? + jne open_ok + call get_ext_err_code ; get the extended error code + +open_ok: + pushf ; save everything again + save_regs + + push cs ; re-establish addressability + pop ds ; ds = cs + +; restore user's working disk and restore the dir on the appended drive + + mov ah,change_disk ; change disk back to our original + mov dl,work_disk + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler + + mov ah,change_dir ; change dir + lea dx,app_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + +; this is for ..\dirname ptr + + mov ah,change_dir ; change dir + lea dx,work_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + + mov ax,ax_after_21 ; restore AX + cmp al,FCB_failed ; did open work? + jne FCB_open_worked + mov ax,ext_err_dpl.DPL_AX + cmp ax,expected_ext_error + jne no_more_to_try ; not file not found + +check_end_dir_list: + mov es,app_dirs_seg ; restore es + mov si,app_dirs_ptr + cmp si,null ; should we try again? + je no_more_to_try ; no + jmp try_another1 ; yes + +FCB_open_worked: + mov byte ptr ext_err_flag,0 ; the open worked, no need to set ext err code + jmp short set_disk + +no_more_to_try: +; restore user's working disk and dir + +; The following code up to label "null_list" which +; restores the user's drive and path was moved in front +; of the code to restore the drive spec in FCB. +; + mov ah,change_disk ; change disk + mov dl,work_disk + call cap_dl + sub dl,"A" ; convert from char to drive spec + call int_21 ; call DOS INT 21 handler + + mov ah,change_dir ; change dir + lea dx,work_disk ; save area (this time include drive) + call int_21 ; call DOS INT 21 handler + +null_list: + mov ah,FCB_drive_id ; get FCB drive spec +; cmp ah,0 ; did they ask for default drive? +; je fix_drive_spec ; yes, leave it alone + jmp short fix_drive_spec + +set_disk: ; set drive number in FCB + mov ah,work_disk ; no, give them the found drive spec + sub ah,"A"-1 ; convert from char to drive spec + +; ah has proper drive spec to put into FCB, do it + +fix_drive_spec: + les bx,dword ptr FCB_ptr ; ES:BX points to FCB + cmp ES:byte ptr[bx],-1 ; extended FCB + jne not_ext_FCB2 ; put in the proper drive spec + add bx,1+5+1 ; point to real drive letter + +not_ext_FCB2: + mov ES:byte ptr [bx],ah + + + call ctrl_break_restore + call crit_err_restore + +; find out if there is a need to set the extended error code + + cmp ext_err_flag,0 ; do we need to set the extended error code? + je no_ext_err ; no, finish up + lea dx,ext_err_dpl + cmp FCB_ext_err,0 + je handle_ext_err + lea dx,save_ext_err + +handle_ext_err: + call set_ext_err_code ; yes, go set the ext error info + +; all done with append, clean things back up for the user + +no_ext_err: + restore_regs ; restore registers + + jmp reset_stack ; fix stack, ret to caller +page + +;----------------------------------------------------------------------------- +; handle_find - APPEND handle find function +;----------------------------------------------------------------------------- + +handle_find1: + mov incoming_CX,cx ; save user's CX + mov expected_error,handle_no_more_files +; mov expected_ext_error,handle_no_more_files + jmp short handle_openx + +;----------------------------------------------------------------------------- +; exec_pgm - APPEND exec program function +;----------------------------------------------------------------------------- + +exec_pgm: + mov incoming_BX,bx ; save user's ES:BX + mov incoming_ES,es + mov expected_error,handle_file_not_found +; mov expected_ext_error,handle_no_more_files + jmp short handle_openx + +;----------------------------------------------------------------------------- ;AN003; +; ext_handle_open - APPEND extended handle open function ;AN003; +;----------------------------------------------------------------------------- ;AN003; +ext_handle_open: ;AN003; + test dx,eo_create ; does this call specify create? ;AN003; + jz no_eo_create ; no, we can continue ;AN003; + ;AN003; + jmp real_jump ; yes, do nothing but pass on to real ;AN003; + ; INT 21 handler ;AN003; + ;AN003; +; getting here means the caller did not specify the create option ;AN003; + ;AN003; +no_eo_create: ;AN003; + ;AN003; + mov incoming_BX,bx ; save user's registers ;AN003; + mov incoming_CX,cx ; extended open sure does use a lot ;AN003; + mov incoming_DX,dx ; of registers ;AN003; + mov incoming_SI,si ;AN003; + mov incoming_DI,di ;AN003; + mov incoming_ES,es ;AN003; + mov incoming_DS,ds ;AN003; + ;AN003; + mov expected_error,handle_file_not_found ;AN003; + jmp short handle_openx ; for now ... ;AN003; + ;AN003; +;----------------------------------------------------------------------------- +; handle_open - APPEND handle open function +;----------------------------------------------------------------------------- + +handle_open: + mov expected_error,handle_file_not_found +; mov expected_ext_error,handle_file_not_found + +handle_openx: + call check_config ; check the config flags + call crit_sect_set ; set critical section flag + + call tv_barrier ; no op on exec + + mov incoming_AX,ax ; save user's AX + mov word ptr handle_ptr+0,dx ; save path pointer + mov word ptr handle_ptr+2,ds + + popff ; restore user's flags + call int_21 ; try the open + + cli + mov AX_after_21,ax ; save AX as it came back from INT + pushf ; save flags from operation + +; find out if we had an error, and if so was it the one we were +; looking for + + jc what_happened ; yes, lets find out what happened + mov incoming_AX,-1 ; insure no exec done later + jmp set_return_flags ; no, fix the stack, then ret to caller + ; this means that the real call worked, + ; APPEND does not need to do anything + +what_happened: +; cmp ax,handle_path_not_found ; normal errors +; je handle_search ; yes, look for the file + cmp ax,expected_error ; was the error file not found? + je handle_search ; yes, look for the file + jmp set_return_flags ; no, fix the stack, then ret to caller + + +handle_search: + call get_ext_err_code ; get the extended error code information + +; set up APPEND's stack + popff ; get rid of the flags from the + ; real operation +; mov temp_DS_save,ds ; Save DS reg + mov stack_segment,ss ; Save it + mov stack_offset,sp ; Save it + mov ax,cs ; Get current segment + mov ss,ax ; and point stack seg here + lea sp,append_stack ; set up new stack + + save_regs ; save registers + pushf ; + push cs ; establish addressability + pop ds + + call crit_err_set + + call ctrl_break_set + +; all done with the prep stuff, let's get down to business + +;------------------------------------------------------------------- ;AN001; +; ;AN001; +; before doing anything else, check DRIVE and PATH modes ;AN001; +; ;AN001; +;------------------------------------------------------------------- ;AN001; +; ;AN001; + + pushf ; save flags ;AN001; + push ax ; save AX ;AN001; + ;AN001; + cmp incoming_AX,exec_proc*256 ; is this call an exec? + je drive_and_path_ok + + +;------------------------------------------------------------------- +; Set up ES:SI to point to incoming string +;------------------------------------------------------------------- + + cmp incoming_AX,ext_handle_opn*256+0 ;is this call an ext open? ;AN003; + jne no_eo13 ;AN003; + mov si,incoming_SI ; DS:SI points to original name for ex open ;AN003; + mov es,incoming_DS ; but this code wants ES:SI to point to it ;AN003; + lea di,fname ; DS:DI points to fname area ;AN003; + jmp eo_skip3 ; skip the old stuff ;AN003; + ;AN003; +no_eo13: ;AN003; + les si,dword ptr handle_ptr ; ES:SI points to original handle + lea di,fname ; DS:DI points to fname area +eo_skip3: +;------------------------------------------------------------------- + + test mode_flags,Drive_mode ; Drive_mode enabled? + jnz check_path_mode ; yes, go check path mode + + call check_for_drive ; no, find out if there is a drive + ; specified + cmp ax,0 ; was there a drive letter? + je check_path_mode ; no, go check path mode + +;------------------------------------------------------------------- +; getting here means that Drive_mode is disabled and that a drive letter +; was found. This means we give up on this APPEND operation + + jmp drive_or_path_conflict + + +check_path_mode: + test mode_flags,Path_mode ; Path_mode enabled? + jnz drive_and_path_ok ; yes, go do the APPEND function + + call check_for_path ; no, find out if there is a path + ; specified + + cmp ax,0 ; was there a path? + jne drive_or_path_conflict ; no, go do the APPEND function + + + call check_for_drive ; no, find out if there is a drive + ; specified + cmp ax,0 ; was there a drive letter? + je drive_and_path_ok ; no, everything is OK + ; yes, fall through and exit w/error + +;------------------------------------------------------------------- ;AN001; +; getting here means that Drive_mode is disabled and that a drive ;AN001; +; letter was found. This means we give up on this APPEND operatio ;AN001; n + +drive_or_path_conflict: + + pop ax ; clean up stack + popff + +; restore_regs ; restore some regs ;AN002; +; pop ax + + mov ext_err_flag,1 ; we need to set extended error info + mov ax,expected_error ; make ax look like we got file not found + mov ax_after_21,ax ; save it away so we can restore it below + popff ; get flags from stack + stc ; set the carry flag + pushf ; put 'em back + + jmp no_more_to_try2 + + +drive_and_path_ok: ;AN001; + pop ax ; restore AX ;AN001; + popff ; restore flags ;AN001; + ;AN001; +;------------------------------------------------------------------- ;AN001; +; end of code to check DRIVE and PATH modes ;AN001; +;------------------------------------------------------------------- ;AN001; + + cmp incoming_AX,ext_handle_opn*256+0 ;is this call an ext open? ;AN003; + jne no_eo1 ;AN003; + mov si,incoming_SI ; DS:SI points to original name for ex open ;AN003; + mov es,incoming_DS ; but this code wants ES:SI to point to it ;AN003; + lea di,fname ; DS:DI points to fname area ;AN003; + jmp eo_skip1 ; skip the old stuff ;AN003; + ;AN003; +no_eo1: ;AN003; + les si,dword ptr handle_ptr ; ES:SI points to original handle + lea di,fname ; DS:DI points to fname area +eo_skip1: ;AN003; + call get_fname ; strip just the 8.3 filename from + ; the original ASCIIZ string + call address_path ; address the path + cmp es: byte ptr [di],";" ; is append list null ? + jump E,no_more_to_try2 ; exit append + popff ; + mov si,di ; pointer to list of appended directories + pushf ; push flags onto stack just for the + ; popff below + +try_another2: + popff + lea di,try_dir ; buffer to be filled with dir name + ; to try + push cx ; save CX + call get_app_dir ; this routine will return with a dir + ; to try in try_dir + mov true_name_count,cx ; save number of chars for later us ;AN003; + pop cx + mov app_dirs_ptr,si ; save updated pointer + + +;----------------------------- +try_app_dir2: + + call append_fname ; glue the filename onto the end of the dir to try + + +; we now have an ASCIIZ string that includes the original 8.3 filename +; and one of the appended dir paths + + mov ax,incoming_AX + mov cx,incoming_CX + lea dx,try_dir ; point to new ASCIIZ string + + cmp incoming_AX,ext_handle_opn*256+0 ; extended open? ;AN003; + jne not_eo1 ;AN003; + ;AN003; +; this is an extended open call ;AN003; + ;AN003; + save_regs ;AN003; + ;AN003; + mov si,dx ; ext open wants DS:SI -> filename ;AN003; + push cs ;AN003; + pop ds ;AN003; + ;AN003; + mov ax,incoming_AX ; function code ;AN003; + mov bx,incoming_BX ; mode word ;AN003; + mov cx,incoming_CX ; attributes ;AN003; + mov dx,incoming_DX ; flags ;AN003; + mov es,incoming_ES ; ES:DI parm_list pointer ;AN003; + mov di,incoming_DI ;AN003; + ;AN003; + call int_21 ; try the extended open ;AN003; + ;AN003; + restore_regs ;AN003; + pushf ; save flags ;AN003; +; mov es,incoming_ES ; restore es as it was ;AN003; + jmp not_exec2 ; go find out what happened ;AN003; + ;AN003; + ;AN003; +not_eo1: ;AN003; + cmp incoming_AX,exec_proc*256+0 ; exec pgm call + jne not_exec1 + +; this is an exec call ;AN003; + + push es + push bx + mov ah,get_DTA + call int_21 + mov word ptr incoming_DTA+0,bx ; save callers DTA + mov word ptr incoming_DTA+2,es + pop bx + pop es + push ds + push dx + mov ah,set_DTA + lea dx,exec_DTA ; set for fake exec search + push cs + pop ds + call int_21 + pop dx + pop ds + mov ah,handle_fnd1 ; precess search by finds + mov expected_error,handle_no_more_files + +not_exec1: + + push es ; save append's ES + push bx ; save append's BX + mov es,incoming_ES ; must restore ES before doing the call ; fix for P37, GGA 9/10/87 + mov bx,incoming_BX ; must resatore user's ES:BX + + call int_21 ; try the open + + pop bx ; restore append's BX + pop es ; restore append's es + pushf ; save flags + cmp incoming_AX,exec_proc*256+0 ; exec pgm call + jne not_exec2 + push ds + push dx + push ax + mov ah,set_DTA + mov dx,word ptr incoming_DTA+0 ; restore callers DTA + mov ds,word ptr incoming_DTA+2 + call int_21 + pop ax + pop dx + pop ds +not_exec2: + popff + pushf + jnc found_it_remote ; all done + + cmp crit_err_flag,0 ; process critical errors + jne check_crit_err + + cmp ax,handle_path_not_found ; normal errors + je should_we_look_more + + cmp ax,expected_error ; was the error we found file not found? + je should_we_look_more ; yes, look some more + jmp no_more_to_try2 ; no, any other error, we pack it in + +should_we_look_more: + mov si,app_dirs_ptr ; yes, see if we should look more + cmp si,null ; should we try again? + je no_more_to_tryx + jmp try_another2 ; yes +no_more_to_tryx: + jmp no_more_to_try2 + +check_crit_err: + mov ext_err_flag,1 ; we need to set extended error info + mov ax,expected_error ; make ax look like we got file not found + mov ax_after_21,ax ; save it away so we can restore it below + popff ; get clags from stack + stc ; set the carry flag + pushf ; put 'em back + + jmp no_more_to_try2 + +found_it_remote: ; come here only if the file was found in + ; an appended directory + mov ax_after_21,ax ; save AX + + +; ;AN002; +; Find out if this process has the true_name flag set in thier PSP. ;AN002; +; At this point, DS:DX points to the true name of the found file ;AN002; +; ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + save_regs + ;AN002; + mov ah,get_PSP ; function code for get PSP operation ;AN002; + call int_21 ; get the PSP, segment returned in BX ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is true name flag armed? ;AN002; + jz no_true_name ; no, don't copy true name ;AN002; + ;AN002; + sub ax,true_name_flag ; clear true name flag ;AN002; + mov es:[di],ax ; save it in PSP ;AN002; + ;AN002; + mov di,word ptr handle_ptr+0 ; get user's buffer pointer ES:DI ;AN002; + mov es,word ptr handle_ptr+2 ;AN002; + +; find out if this is a handle find or an open or an exec + + cmp incoming_AX,exec_proc*256+0 ; exec? + je no_true_name ; yes, do nothing with true name + ;AN002; + cmp incoming_AX,handle_fnd1*256+0 ; handle find? + jne not_hf ; no, go do the easy stuff + ;AN002; +; function we are doing is a handle find, must get part of true_name +; string from append path, part from DTA. Messy! + + lea si,try_dir ; buffer that has last APPEND path tried + + mov cx,true_name_count ; get number of chars in true_name dir ;AN002; + +copy_true_name_loop2: + mov ah,ds:[si] ; get byte of append dir path ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + inc si ; in this loop, the null is not copied ;AN002; + inc di ;AN002; + loop copy_true_name_loop2 ;AN002; + +; put in the "\" + + mov ah,"\" ; get a \ + mov es:[di],ah ; copy it + inc di ; increment pointer + +; we have copied the first part of the string, now get the real filename +; from the DTA + + push es + push bx + + mov ah,get_DTA + call int_21 + push es + pop ds + mov si,bx + + pop bx + pop es + +copy_true_name_loop3: + mov ah,ds:[si+30] ; get byte of actual filename ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + cmp ah,null ; is it a null? ;AN002; + je true_name_copied ; yes, all done ;AN002; + inc si ; in this loop the null is copied ;AN002; + inc di ;AN002; + jmp copy_true_name_loop3 ;AN002; + +not_hf: + mov si,dx ; make DS:SI point to true name + +copy_true_name_loop: ;AN002; + mov ah,ds:[si] ; get byte of true name ;AN002; + mov es:[di],ah ; copy it to user's buffer ;AN002; + cmp ah,null ; is it a null? ;AN002; + je true_name_copied ; yes, all done ;AN002; + inc si ;AN002; + inc di ;AN002; + jmp copy_true_name_loop ;AN002; + ;AN002; +true_name_copied: ;AN002; + ;AN002; +no_true_name: ;AN002; + restore_regs ; restore some regs ;AN002; + pop ax + ;AN002; + ;AN002; +no_more_to_try2: + + call ctrl_break_restore ; restore normal control break address + call crit_err_restore ; restore normal critical error address + +; find out if there is a need to set the extended error code + + cmp ext_err_flag,0 ; do we need to set the extended error code? + je no_ext_err2 ; no, finish up + lea dx,ext_err_dpl + call set_ext_err_code ; yes, go set the ext error info + +; reset flags, and pack it in + +no_ext_err2: + popff + restore_regs ; restore registers + pushf ; put the real flags on the stack + + jmp reset_stack ; fix stack, ret to caller + +page +;------------------------------------------------------------------- +; +; support routines for drive and path mode checking +; +; +;------------------------------------------------------------------- + + +check_for_drive: ; input: ES:SI -> original string + ; output: AX = 0 no drive present + ; output: AX = -1 drive present + + xor ax,ax ; assume no drive letter present + + cmp es: byte ptr [si+1],':' ; is the second char a ":"? + jne exit_check_for_drive ; no, skip setting the flag + + mov ax,-1 ; yes, set the flag + +exit_check_for_drive: + + ret + +;------------------------------------------------------------------- + +check_for_path: ; input: ES:SI -> original string + ; output: AX = 0 no path present + ; output: AX = -1 path present + + push si ; save pointer + + xor ax,ax ; assume no path present + + +; walk the string and look for "/", or "\". Any of these mean that a +; path is present + +walk_handle_string: + + push ax ;AN006; + mov al,es: byte ptr [si] ; is this a dbcs char? ;AN006; + call Chk_DBCS ;AN006; + pop ax ;AN006; + ;AN006; + jnc no_dbcs1 ; no, keep looking ;AN006; + + add si,2 ; yes, skip it and the next char ;AN006; + jmp walk_handle_string ; the next char could be a "\", but ;AN006; + ; would not mean a path was found ;AN006; + ;AN006; +no_dbcs1: ;AN006; + cmp es: byte ptr [si],"\" ; is the char a "\"? + je found_path ; yes, set flag and return + cmp es: byte ptr [si],"/" ; is the char a "/"? + je found_path ; yes, set flag and return + cmp es: byte ptr [si],0 ; is the char a null + je exit_check_for_path ; yes, got to the end of the + ; handle string + + inc si ; point to next char + jmp walk_handle_string ; and look again + +found_path: + mov ax,-1 ; yes, set the flag + +exit_check_for_path: + pop si ; restore si + ret + +page +;----------------------------------------------------------------------------- +; Entry point for interrupt 2f handler +;----------------------------------------------------------------------------- + +intfcn_hook: + cmp ah,append_2f ; is this function call for append? +;;;;;; je do_appends ; @@12 + jne ih_10 ; @@12 + jmp do_appends ; @@12 +ih_10: ; @@12 + cmp ah,applic_2f ; is this function call for applications + je do_applic + jmp pass_it_on + +do_applic: + cmp dx,-1 ; not COMMAND call + jump NE,pass_it_on + cmp al,0 ; match name request + jne ck01 + + mov cmd_buf,bx ; save CMDBUF offset + call check_cmd_name + jne no_internal1 + mov al,append_inst ; inidicate I want this command +no_internal1: + iret + +ck01: + cmp al,1 ; match name request + jne ck02 + +; save pointer to parser + + mov word ptr pars_off+0,di ; ES:DI points to COMMAND.COM's parser + mov word ptr pars_off+2,es ; save it for later + + mov cmd_env,bx ; save env pointer address + call check_cmd_name + jne no_internal2 + call COMMAND_begin ; process internal command +no_internal2: + iret + +ck02: +; cmp al,2 ; set COMMAND active ; @@13; @@09 +; jne ck03 ; @@13; @@09 +; mov cmd_active,1 ; @@13; @@09 +; iret ; @@13; @@09 +ck03: ; @@13; @@09 +; cmp al,3 ; set COMMAND in active ; @@13; @@09 +; jne ck04 ; @@13; @@09 +; mov cmd_active,0 ; @@13; @@09 +; iret ; @@13; @@09 +ck04: ; @@13; @@09 + jmp pass_it_on + +;******************************************************************************* +; The following old code is commented out. @@12 +;******************************************************************************* +;check_cmd_name: ; see if internal APPEND +; push es +; push cs +; pop es +; push di +; push cx +; push si +; cmp ds:byte ptr[si],6 ; length must match +; jne skip_comp +; comp append_id,6,[si+1] ; see if APPEND is command +;skip_comp: +; pop si +; pop cx +; pop di +; pop es +; ret +;********************************************************************* +check_cmd_name: ; See if APPEND @@12 + push ax ; @@12 + push si ; @@12 + push cx ; @@12 + push di ; @@12 + push es ; @@12 + mov si,cmd_buf ; DS:SI -> cmd buf ended with cr @@12 + add si,2 ; 1st 2 bytes garbage @@12 + ; @@12 +ccn_skip_leading: ; @@12 + lodsb ; skip leading stuff @@12 + + call Chk_DBCS ; find out if this is DBCS ;AN006; + jnc no_dbcs2 ; no, keep looking ;AN006; + lodsb ; yes, skip it and the next byte ;AN006; + jmp ccn_skip_leading ; the second byte will be skipper when ;AN006; + ; we go back through ;AN006; + +no_dbcs2: ;AN006; + cmp al," " ; blank @@12 + je ccn_skip_leading ; @@12 + cmp al,tab_char ; tab @@12 + je ccn_skip_leading ; @@12 + cmp al,"," ; comma @@12 + je ccn_skip_leading ; @@12 + cmp al,"=" ; equal @@12 + je ccn_skip_leading ; @@12 + cmp al,";" ; semi-colon @@12 + je ccn_skip_leading ; @@12 + cmp al,"\" ; back slash @@12 + je ccn_skip_leading ; @@12 + cmp al,cr ; bad ret for early terminate @@12 + jne ccn_02 ; @@12 + cmp al,0 ; reset z for no match @@12 + jmp ccn_ret ; @@12 +ccn_02: ; @@12 + mov di,si ; di -> beginning of possible @@12 + dec di ; "APPEND " string @@12 + lodsb ; @@12 + cmp al,":" ; @@12 + jne ccn_cont ; @@12 + mov di,si ; @@12 + lodsb ; @@12 +ccn_cont: ; @@12 + call Chk_DBCS ;AN006; + jnc no_dbcs3 ; no, carry on ;AN006; + add si,2 ; yes, skip it and the next byte ;AN006; + jmp ccn_20 ;AN006; + ;AN006; +no_dbcs3: ;AN006; + cmp al,"\" ; move di up upon "\" @@12 + jne ccn_20 ; @@12 + mov di,si ; @@12 +ccn_10: ; @@12 + lodsb ; @@12 + jmp ccn_cont ; @@12 +ccn_20: ; @@12 + cmp al," " ; look for separator @@12 + je ccn_30 ; if found, then have command @@12 + cmp al,"=" ; @@12 + je ccn_30 ; @@12 + cmp al,cr ; @@12 + je ccn_30 ; @@12 + cmp al,tab_char ; @@12 + je ccn_30 ; @@12 + cmp al,"," ; @@12 + je ccn_30 ; @@12 + cmp al,";" ; @@12 + jne ccn_10 ; @@12 + +ccn_30: ; @@12 + sub si,di ; @@12 + cmp si,7 ; @@12 + jne ccn_ret ; no match @@12 + ; @@12 + mov si,di ; @@12 + chkchar "A" ; look for "APPEND" string @@12 + chkchar "P" ; @@12 + chkchar "P" ; @@12 + chkchar "E" ; @@12 + chkchar "N" ; @@12 + chkchar "D" ; @@12 + ; exit with z set for match @@12 +ccn_ret: ; @@12 + pop es ; @@12 + pop di ; @@12 + pop cx ; @@12 + pop si ; @@12 + pop ax ; @@12 + ret ; @@12 + +page +;------------------------------------------------------------------- ;AN000; +; ;AN000; +; do_appends ;AN000; +; ;AN000; +; This is the INT 2F handler for the APPEND ;AN000; +; subfunction ;AN000; +; ;AN000; +; New functions added for 3.30: ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; +; Get /X status ;AN000; +; ;AN000; +; Input: AX = B706 ;AN000; +; ;AN000; +; Output: BX = 0000 /X not active ;AN000; +; = 0001 /X active ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; +; Set /X status ;AN000; +; ;AN000; +; Input: AX = B707 ;AN000; +; ;AN000; +; BX = 0000 turn /X off ;AN000; +; BX = 0001 turn /X on (active) ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +; +do_appends: + cmp al,are_you_there ; is the function request for presence? + jne ck1 + + mov al,-1 ; set flag to indicate we are here + iret ; return to user + +ck1: + cmp al,dir_ptr ; is the function request for pointer? + jne ck2 + + les di,dword ptr dirlst_offset ; return dirlist pointer to caller + iret + +ck2: + cmp al,get_app_version ; is the function request for version? + jne ck3 ; no, check for next function + + mov ax,-1 ; yes, set NOT NETWORK version + iret + +ck3: + cmp al,tv_vector ; is the function request for TV vector? + jne ck4 ; no, check for old dir ptr + + mov tv_vec_seg,es ; yes, save the TV vector + mov tv_vec_off,di + + push cs ; set ES:DI to tv ent pnt + pop es ; + lea di,tv_entry + + xor byte ptr tv_flag,TV_TRUE ; set flag ;AN000; + iret + +ck4: ; + cmp al,old_dir_ptr ; is it the old dir ptr + jne ck5 ; no, pass it on + + push ds + push cs + pop ds + + call sysloadmsg ;AN000; + ;AN000; + mov ax,1 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + pop ds + mov al,1 + call terminate ; exit to DOS ; @@05 + +ck5: ; + cmp al,DOS_version ; is it the new version check + jne ck6 ; no, pass it on + + mov ax,mode_flags ; set mode bits + xor bx,bx ; destroy registers + xor cx,cx + mov dl,byte ptr version_loc ; major version num + mov dh,byte ptr version_loc+1 ; minor version num + iret + +ck6: ;AN000; + cmp al,get_state ; is it get state call? ;AN001; + jne ck7 ; no, look some more ;AN000; + ;AN000; + mov bx,mode_flags ; get mode bits ;AN000; + iret ; return to user ;AN000; + ;AN000; +ck7: ;AN000; + cmp al,set_state ; is it set state call? ;AN001; + jne ck8 ; no, look some more ;AN000; + ;AN000; + mov mode_flags,bx ; save the new state ;AN001; + iret ;AN000; + ;AN000; +ck8: ;AN000; + + cmp al,true_name ; is it the set true name function? ;AN002; + jne ck9 ; no, look some more ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + push bx ;AN002; + push es ;AN002; + push di ;AN002; + ;AN002; + ;AN002; +; get the PSP and then get the APPEND flags byte + + mov ah,get_PSP ; function code to get PSP address ;AN002; + call int_21 ; get the PSP address ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; +; is the flag already set? + + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is it set? ;AN002; + jnz no_set_true_name ; yes, do nothing ;AN002; + ;AN002; +; set the true_name flag + +set_true_name: ;AN002; + add ax,true_name_flag ; set true name flag ;AN002; + mov es:[di],ax ; save in PSP ;AN002; + ;AN002; +no_set_true_name: + pop di ; restore some regs ;AN002; + pop es ;AN002; + pop bx ;AN002; + pop ax ;AN002; + ;AN002; + iret ; return ;AN002; + ;AN002; +ck9: ;AN002; + +;------------------------------------------------------------------- +; fill in additional 2F functions here +;------------------------------------------------------------------- + +pass_it_on: ; the function call (ah) was not for append + jmp dword ptr intfcn_Offset ; jump to old INT 2f + +page +;----------------------------------------------------------------------------- +; Entry point for interrupt 24 handler +;----------------------------------------------------------------------------- + +crit_err_handler: + + mov crit_err_flag,0ffh ; set critical error flag + mov al,3 ; fail int 21h + iret + +page +;----------------------------------------------------------------------------- +; miscellaneous routines +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; tv_barrier +;----------------------------------------------------------------------------- + +tv_barrier: + + cmp tv_flag,TV_TRUE ; in Topview ;AN000; + jne no_barrier + + push ax + mov ax,2002h ; wait on DOS barrier + int 2Ah + pop ax +no_barrier: + ret + +;----------------------------- +; check_config - this routine is called by both the FCB and handle open +; code. I checks the net_config flag to see if it is zero, if so it +; does an installation check. If it is non-zero, nothing is done. + +check_config: + + push ax ; save a few registers + push bx + +; examine the config flag to see if we already know what config we have + + cmp net_config,0 + jne do_not_look ; we know config already + +; the flag word has not been set before, go find out what config we have + + mov ax,0b800h ; installation code function code + int 2fh ; do the installation check + + mov net_config,bx ; save flag word for later + +do_not_look: + pop bx ;restore regs and leave + pop ax + ret + +;*( Chk_DBCS ) ************************************************************* +;* * +;* Function: Check if a specified byte is in ranges of the DBCS lead bytes* +;* Attention: If your code is resident, comment out the lines marked * +;* ;** . * +;* * +;* Input: * +;* AL = Code to be examined * +;* * +;* * +;* Output: * +;* If CF is on then a lead byte of DBCS * +;* * +;* Register: * +;* FL is used for the output, others are unchanged. * +;* * +;*************************************************************************** +Chk_DBCS PROC + PUSH DS + PUSH SI +; CMP CS:DBCSEV_SEG,0 ; ALREADY SET ? ;** +; JNE DBCS00 ;** + MOV SI,OFFSET EVEV ; SET DEFAULT OFFSET ;** + PUSH CS ;** + POP DS ; SET DEFAULT SEGMENT ;** + PUSH AX + MOV AX,6300H ; GET DBCS EV CALL + INT 21H + MOV CS:DBCSEV_OFF,SI ;** + MOV CS:DBCSEV_SEG,DS ;** + POP AX +DBCS00: + MOV SI,CS:DBCSEV_OFF ;** + MOV DS,CS:DBCSEV_SEG ;** +DBCS_LOOP: + CMP WORD PTR [SI],0 + JE NON_DBCS + CMP AL,[SI] + JB DBCS01 + CMP AL,[SI+1] + JA DBCS01 + STC + JMP DBCS_EXIT +DBCS01: + ADD SI,2 + JMP DBCS_LOOP +NON_DBCS: + CLC +DBCS_EXIT: + POP SI + POP DS + RET +Chk_DBCS ENDP + + +;----------------------------- +; append_fname - glues the fname onto the end of the dir to try + +append_fname: + push es + push ds + pop es + lea di,try_dir ; destination, sort of (dir name) + lea si,fname ; source (filename) + +; find the end of the dir name + + mov dbcs_fb,-1 ; set flag for no dbcs first byte chars ;AN006; + +walk_dir_name: + mov al,byte ptr [di] ; get a char from dir name + cmp al,null ; are we at the end? + je end_of_dir ; yes, add on the fname + + call Chk_DBCS ; char is in al ;AN006; + jnc no_dbcs4 ; no, keep looking ;AN006; + mov dbcs_fb,di ; save offset ;AN006; + inc di ; skip second byte + +no_dbcs4: + inc di ; no, keep stepping + jmp walk_dir_name + +; now it is time to append the filename + +end_of_dir: + mov al,byte ptr [di-1] ; get last char of dir name + cmp al,"\" ; is it a dir seperator? + jne check_next_dir_sep ; no, check the next dir sep char ;AN006; + ;AN006; + sub di,2 ; yes, must find out if real dir sep ;AN006; + ; or DBCS second byte ;AN006; + cmp dbcs_fb,di ; is the char before our dir sep a DBCS ;AN006; + ; first byte? ;AN006; + jne no_dbcs4a ; no, must check for the next dir sep ;AN006; + ; yes, this means we must put in a dir sep ;AN006; + add di,2 ; restore di ;AN006; + jmp put_in_dir_sep ; put int the dir sep char ;AN006; + ;AN006; +no_dbcs4a: ;AN006; + add di,1 ; restore di, then check next dir sep ;AN006; + +check_next_dir_sep: + cmp al,"/" ; is it the other dir seperator? + je add_fname ; yes, no need to add one +put_in_dir_sep: ;AN006; + mov al,"\" ; get dir seperator + stosb ; add to end of dir + +add_fname: + lodsb ; get a char from fname + stosb ; copy the char + cmp al,null ; are we at the and of the filename? + je eo_name ; yes, all done! + jmp add_fname + + + + + + + +eo_name: + pop es + ret + + +;----------------------------- +; get_fname strips out the 8.3 filename from the original ASCIIZ string +; +; INPUT: ES:SI points to original string +; DS:DI points to area for filename + +get_fname: + + mov bx,si ; save the pointer + mov dbcs_fb,-1 ; set the dbcs flag off ;AN006; + +gfn1: + mov ah,ES:byte ptr [si] ; get a char from the source + cmp ah,null ; is it a null? + je got_the_end ; yes, we found the end + + call chk_dbcs ; is this char a DBCS first byte? ;AN006; + jnc no_dbcs5 ; no, carry on + mov dbcs_fb,si ; yes, save pointer + inc si ; skip second byte + +no_dbcs5: + inc si ; no, point to next char + jmp gfn1 ; loop till end found + +got_the_end: + mov ah,ES:byte ptr [si] ; get a char + cmp ah,"/" ; did we find a / + je went_too_far ; yes, we found the start + cmp ah,"\" ; did we find a \ + je found_bslash ; yes, we found the start ;AN006; + cmp ah,":" ; did we find a : + je went_too_far ; yes, we found the start + cmp si,bx ; are we back to the original start? + je got_the_beg ; yes, we found the start of the fname + dec si ; step back a char, then look some more + jmp got_the_end + +found_bslash: ; found a backslash, must figure out if ;AN006; + ; is second byte of DBCS ;AN006; + dec si ; point to next char ;AN006; + cmp si,dbcs_fb ; do they match? + jne no_dbcs5a ; no, fix up si and carry on ;AN006; + dec si ; skip dbcs byte and loop some more ;AN006; + jmp got_the_end ;AN006; + +no_dbcs5a: ;AN006; + inc si ; went too far by one extra ;AN006; + ;AN006; +went_too_far: + inc si ; went one char too far back + +; ES:SI now points to the beginning of the filename + +got_the_beg: + mov ah,ES:byte ptr [si] ; get a char from the source + mov byte ptr [di],ah ; copy to dest + cmp ah,null ; did we just copy the end? + je done_with_fname ; yes, all done + inc si ; no, get the next char + inc di + cmp di,offset app_dirs_ptr ; make sure we dont try to copy past the + je done_with_fname ; area + jmp got_the_beg + +done_with_fname: + ret + +;----------------------------- +; this code executed to return to caller after APPEND's stack has been +; initialized + +reset_stack: + +; reset the stack ;AN002; + + popff ; restore flags from real open + mov ss,Stack_Segment ; Get original stack segment + mov sp,Stack_Offset ; Get original stack pointer + pushf ; put the flags on the old stack + + +;----------------------------- +; before jumping to this routine, SS:SP must point to the caller's stack, +; and the flags from the real INT 21 operation must have been pushed + +set_return_flags: + +; must be sure to clear the true_name flag before leaving ;AN002; + ;AN002; + push ax ; save some regs ;AN002; + push bx ;AN002; + push es ;AN002; + push di ;AN002; + ;AN002; + mov ah,get_PSP ; function code for get PSP operation ;AN002; + call int_21 ; get the PSP, segment returned in BX ;AN002; + mov es,bx ; need to use it as a segment ;AN002; + mov di,PDB_Append ; get pointer to APPEND flag in PDB ;AN002; + ;AN002; + mov ax,es:[di] ; get APPEND flag into AX ;AN002; + test ax,true_name_flag ; is true name flag armed? ;AN002; + jz reset_stack2 ; no, don't copy true name ;AN002; + ;AN002; + sub ax,true_name_flag ; clear true name flag ;AN002; + mov es:[di],ax ; save it in PSP ;AN002; + ;AN002; + ;AN002; +reset_stack2: ;AN002; + ;AN002; + pop di ; restore ;AN002; + pop es ;AN002; + pop bx ;AN002; + pop ax ;AN002; + ;AN002; + cmp tv_flag,TV_TRUE ;AN000; + jne tv_flag_not_set + + mov ax,2003h ; clear open barrier + int 2Ah + + +; pop down to the old flags on the user's stack + +tv_flag_not_set: + + cmp incoming_AX,exec_proc*256+0 ; need to do exec + jne not_exec3 + popff ; discard bad flags + mov ax,incoming_AX ; set exec parms + + push ds ; save DS, this must be done ;an005; + ; to pervent DS from being trashed on return to caller ;an005; + + push cs + pop ds + lea dx,try_dir + mov bx,incoming_BX + mov es,incoming_ES + call int_21 ; issue the exec + + pop ds ; restore DS ; an005; + + pushf + +not_exec3: + popff ; get flags from real int 21 (old stack) + pop temp_IP_save ; save IP, CS + pop temp_CS_save + lahf ; save flags in AH + popff ; pop old flags off stack + sahf ; replace old with new + +; push the new flags onto the stack, then fix CS and IP on stack + + pushf ; push new flags onto stack + push temp_CS_save ; restore IP, CS + push temp_IP_save + mov ax,AX_after_21 ; Set AX as it was after open + + call crit_sect_reset ; clear the critical section flag + iret ; return to the calling routine + + +;----------------------------- +; This routine is used to extract an appended dir from the dir list +; On entry, DS:DI points to an area for the appended dir +; and ES:SI points to the source string + +get_app_dir: + + xor cx,cx ; keep a count of chars in cx ;AN003; +copy_dir: + mov ah,es:byte ptr [si] ; get the char, and copy it into dest + cmp ah,null ; find a null? + je no_more_dirs ; yes, inform caller that this is the last one + + cmp ah,";" ; check to see if we are at the end of a dir + je update_pointer ; yes, + + mov byte ptr [di],ah ; if not null or semi-colon, then copy it + inc si ; increment both pointers + inc di + inc cx ; count of chars ;AN003; + jmp copy_dir ; do it some more + +update_pointer: + inc si ; point to next char + mov ah,es:byte ptr [si] ; get char ; @@16 + cmp ah,null ; did we reach the end of the dir list? + je no_more_dirs ; + + cmp ah,";" ; is is a semi-colon + je update_pointer + jmp all_done + + +no_more_dirs: + xor si,si ; set end search flag + +all_done: + mov byte ptr [di],null ; null terminate destination + ret ; return to caller + +;----------------------------- +; set ctrl-break check off +; first, save the old state so we can restore it later, +; then turn ctrl-break checking off + +ctrl_break_set: + + mov ah,ctrl_break ; function code for ctrl-break check + xor al,al ; 0 = get current state + call int_21 ; call DOS INT 21 handler + + mov ctrl_break_state,dl ; save the old ctrl-break state + + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + xor dl,dl ; 0 = off + call int_21 ; call DOS INT 21 handler + ret + + +;----------------------------- +; restore ctrl-break checking flag to the way it was +ctrl_break_restore: + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + mov dl,ctrl_break_state ; get the way is was before we messed with it + call int_21 ; call DOS INT 21 handler + ret + +;----------------------------- +; restore ctrl-break checking flag to the way it was +ctrl_break_rest: + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + mov dl,ctrl_break_state ; get the way is was before we messed with it + call int_21 + ret + +;----------------------------- +; +crit_err_set: + mov crit_err_flag,0 ; clear the critical error flag + + mov ax,get_crit_err ; Get INT 24h vector + call int_21 ; call DOS INT 21 handler + + mov crit_vector_offset,bx ; Save it + mov ax,es ; es hase segment for resident code + mov crit_vector_segment,ax + + lea dx,crit_err_handler ; DS:DX = New INT 21h vector + mov ax,set_crit_err ; function code for setting critical error vector + call int_21 ; call DOS INT 21 handler + ret ; go back to the caller + + +;----------------------------- +; +crit_err_restore: + push ds ; save ds for this function + mov ax,set_crit_err ; function code for setting critical error vector + mov dx,crit_vector_offset ; get old int 24 offset + mov ds,crit_vector_segment ; get old int 24 segment + call int_21 ; call INT 21 + pop ds + ret + +;----------------------------- +; crit_sect_set - issues an enque request to the server to protect +; against reentry. This request is issued only if the network is started, +; and then, only for RCV, MSG, and SRV configurations +crit_sect_set: + push ax + push bx + push di + push es + + mov ax,net_config ; check the server config flag + cmp ax,0 ; is it zero? + je dont_set_crit_sect ; yes, skip it + + cmp ax,redir_flag ; is it a redir? + je dont_set_crit_sect ; yes, skip it + ; otherwise, issue the request + +; the config flag was not zero or redir, so set crit section + + mov ah,NETSYSUTIL + mov al,NETENQ + mov bx,TCBR_APPEND + int 2Ah + +dont_set_crit_sect: ; because of the config we don't want + pop es ; to set critical section + pop di + pop bx + pop ax + ret + +;----------------------------- +; +crit_sect_reset: + push ax + push bx + + mov ax,net_config ; check the server config flag + cmp ax,0 ; is it zero? + je not_set ; yes, skip it + + cmp ax,redir_flag ; is it a redir? + je not_set ; yes, skip it + + mov ah,NETSYSUTIL ; turn critical section off + mov al,NETDEQ + mov bx,TCBR_APPEND + int 2Ah + +not_set: + pop bx + pop ax + ret + + +;----------------------------- +; save_first_ext_err - this routine is used to save the extended +; error info after the first FCB open. +save_first_ext_err: + + push ax + + mov ax,ext_err_dpl.DPL_AX ; copy all registers + mov save_ext_err.DPL_AX,ax + mov ax,ext_err_dpl.DPL_BX + mov save_ext_err.DPL_BX,ax + mov ax,ext_err_dpl.DPL_CX + mov save_ext_err.DPL_CX,ax + mov ax,ext_err_dpl.DPL_DX + mov save_ext_err.DPL_DX,ax + mov ax,ext_err_dpl.DPL_SI + mov save_ext_err.DPL_SI,ax + mov ax,ext_err_dpl.DPL_DI + mov save_ext_err.DPL_DI,ax + mov ax,ext_err_dpl.DPL_DS + mov save_ext_err.DPL_DS,ax + mov ax,ext_err_dpl.DPL_ES + mov save_ext_err.DPL_ES,ax + + pop ax + ret + +;----------------------------- +; get_ext_err_code - this routine is used to get the extended error +; info for the error that cause append to start its search + +get_ext_err_code: + push ax ; save register that are changed by this + push bx ; DOS function + push cx + push di + push si + push es + push ds + +; get the extended error information + + mov ah,59h ; function code for get extended error + xor bx,bx ; version number + call int_21 ; get the extended error + +; save it away in a DPL for set_ext_error_code +; all fields in the DPL will be filled in except the last three, +; which will be left at zero + + mov ext_err_dpl.DPL_AX,ax + mov ext_err_dpl.DPL_BX,bx + mov ext_err_dpl.DPL_CX,cx + mov ext_err_dpl.DPL_DX,dx + mov ext_err_dpl.DPL_SI,si + mov ext_err_dpl.DPL_DI,di + mov ext_err_dpl.DPL_DS,ds + mov ext_err_dpl.DPL_ES,es + + +; restore regs and return + + pop ds + pop es ; restore registers + pop si + pop di + pop cx + pop bx + pop ax + ret + +;----------------------------- +; set_ext_err_code - this routine is used to get the extended error +; info for the error that cause append to start its search +; CS:DX points to return list +set_ext_err_code: + push ax ; save register that are changed by this + push ds ; DOS function + +; get the extended error information + + mov ah,DOSSERVER ; function code for DOSSERVER call + mov al,DOSSETERROR ; sub-function code for set extended error + push cs + pop ds + call int_21 ; set the extended error + +; restore regs and return + + pop ds ; restore registers + pop ax + ret +page +;----------------------------- +; This routine is used to initiate DOS calls from within the APPEND interrupt +; handlers. An INT instruction can not be used because it would cause APPEND +; to be re-entered. +; +; SS, SP saved incase call is EXEC which blows them away +int_21: ; + cmp tv_flag,TV_TRUE ; see if being re-entered ;AN000; + jne use_old_vec ; yes, pass through to DOS + + pushf ; to comp for iret pops + call dword ptr tv_vec_off ; Call INT 21h + ret ; + +use_old_vec: + cmp vector_segment,0 ; not installed yet + je use_int + + pushf ; to comp for iret pops + call dword ptr vector_offset ; Call INT 21h + ret ; + +use_int: + int DOS_function + ret +page +;----------------------------- +; This routine is used to locate the current APPEND path string +; result to ES:DI + +address_path: +address_status: ; @@13 + test mode_flags,E_mode + jnz get_env_mode + +address_pathx: + mov ax,append_2f*256+dir_ptr ; get from buffer + int int_function + clc + ret + +get_env_mode: ; get from environment +; cmp cmd_active,0 ; different logic ; @@13; @@09 +; jne use_cmd_env ; if in COMMAND ; @@13; @@09 + push bx + mov ah,get_PSP + call int_21 ; get the PSP + mov es,bx + mov bx,002ch ; address environment + mov ax,es:word ptr[bx] + mov es,ax + pop bx + cmp ax,0 ; PSP pointer is set + je address_pathx ; @@13 +use_cmd_env: ; @@13 +; cmp cmd_env,0 ; have not set my pointer yet +; je address_pathx ; @@13 +; mov es,cmd_env ; @@13 +env_mode1: + mov di,0 ; start at start + cmp es:byte ptr[di],0 ; no environment + je no_appendeq +find_append: + cmp es:word ptr[di],0 ; at environment end + je no_appendeq + push di + push si + push cx + push ds + push cs + pop ds + comp ,6+1,append_id ; string = "APPEND=" + pop ds + pop cx + pop si + pop di + je at_appendeq + inc di + jmp find_append +at_appendeq: ; must insure this is @@17 + cmp di,0 ; genuine "APPEND=" string @@17 + je at_appendeq_genuine ; if start of environ ok @@17 + dec di ; else check that 0 @@17 + cmp es:byte ptr[di],0 ; precedes string @@17 + je at_appendeq_10 ; jmp if ok @@17 + add di,8 ; else cont.search after @@17 + jmp find_append ; "=" @@17 +at_appendeq_10: ; @@17 + inc di ; @@17 +at_appendeq_genuine: ; @@17 + add di,6+1 ; skip APPEND= + cmp es:byte ptr[di],0 ; null value + je no_appendeq ; treat as not found + cmp es:byte ptr[di]," " + je no_appendeq + cmp es:byte ptr[di],";" + je no_appendeq + clc ; set ok + ret + +no_appendeq: ; not found, use default + lea di,semicolon ; null list + push cs + pop es + stc ; set error + ret + +;----------------------------- ; @@03 +; This routine is used to locate the current APPEND path string ; @@03 +; result to ES:DI. Used by APPEND status. ; @@03 + +;address_status: ; @@13; @@03 +; test mode_flags,E_mode ; @@13; @@03 +; jump Z,address_pathx ; @@13; @@03 +; jmp use_cmd_env ; @@13; @@03 + +cap_dl: ; convert dl to uppercase + cmp dl,"a" ; find out if we have a lower case; @@14 + jb cap_dlx ; char ; @@14 + cmp dl,"z" ; @@14 + ja cap_dlx ; @@14 + sub dl,"a"-"A" ; convert char to upper case ; @@14 +cap_dlx: + ret + +; end_address: ; this is the end of the TSR stuff ;AN002; + +page +;----------------------------------------------------------------------------- +; Main routine. Used to determine if APPEND has been loaded +; before. If not, load resident portion of APPEND. Then handle setting +; or displaying appended directory list. +;----------------------------------------------------------------------------- + +main_begin: ; DOS entry point + + mov ax,seg mystack ; set up stack + mov ss,ax + lea sp,mystack + + cld + + mov res_append,0 ; set external copy ; @@05 + + push cs ; make DS point to CS + pop ds + + push cs ; make ES point to CS + pop es + + +; find out if append has been loaded ; @@04 + ; @@04 + mov ah,append_2f ; int 2f function code for append ; @@04 + mov al,are_you_there ; function code to ask if append ; @@04 + ; has been loaded ; @@04 + int int_function ; @@04 + ; @@04 + cmp al,append_inst ; is append there? ; @@04 + jne not_there_yet ; no ; @@04 + + mov dx,0 ; set for network version ; @@07 + mov ah,append_2f ; int 2F function code for append ; @@07 + mov al,DOS_version ; function code for get version ; @@07 + int int_function ; @@07 + cmp dx,word ptr version_loc ; does the version match? ; @@07 + jne bad_append_ver ; no, cough up an error messsage ; @@07 + + + call sysloadmsg ;AN000; + ;AN000; + mov ax,9 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; +; mov cx,len_second_APPEND_msg; length of string ;AN000; ; @@04 +; lea dx,second_APPEND_msg ; second load message ;AN000; ; @@04 +; call print_STDERR ; display error message ;AN000; ; @@04 +; lea dx,crlf ; carriage return, line feed ; @@04 +; mov cx,crlf_len ; length of string ; @@04 +; call print_STDERR ; @@04 + ; @@04 + mov al,0fch ; second load ; @@05 + call terminate ; exit to DOS ; @@05 + +bad_append_ver: ; append version mismatch ; @@07 + call sysloadmsg ;AN000; + ;AN000; + mov ax,1 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; +; mov cx,len_bad_append_msg ;AN000; ; @@07 +; lea dx,bad_append_msg ; bad app message ;AN000; ; @@07 +; call print_STDERR ;AN000; ; @@07 +; lea dx,crlf ; carriage return, line feed ; @@07 +; mov cx,crlf_len ; length of string ; @@07 +; call print_STDERR ; @@07 + mov ax,0feh ; bad APPEND version ; @@05 + call terminate ; exit to DOS ; @@05 + +not_there_yet: ; @@04 + + mov cs:initial_pass,-1 ; set a flag for initial pass ;AN007; + call do_command ; do actual APPEND + + mov bx,4 ; close all standard files +do_closes: + mov ah,3eh ; close file handle + call int_21 + dec bx + jns do_closes + + call set_vectors ; set append vectors on success ; @@05 + + call Release_Environment ; release the environmental vector space ;an007; dms; + + lea dx,end_address+15 ; normal end + mov cl,4 ; calc end address in paragraphs + shr dx,cl + mov ah,get_PSP ; calc space from PSP to my code ; @@02 + call int_21 ; @@02 + mov ax,cs ; @@02 + sub ax,bx ; @@02 + add dx,ax ; calc length to keep ; @@02 + mov al,0 ; exit with no error + mov ah,term_stay + call int_21 + +page + +COMMAND_begin: ; COMMAND entry point + save_regs + mov word ptr cmd_name@+0,si ; save internal command buffer @ + mov word ptr cmd_name@+2,ds + cld + + mov abort_sp,sp ; save sp for aborts ; @@05 + mov res_append,1 ; set resident copy ; @@05 + call do_command ; do actual APPEND +abort_exit: ; exit to abort append ; @@05 + mov sp,abort_sp ; @@05 + + push es + push di + les di,cmd_name@ + mov es:byte ptr[di],0 ; set no command now + pop di + pop es + + cmp ax,0 ; error + jne no_E_mode + test mode_flags,E_mode ; no /E processing + jz no_E_mode + + mov ax,append_2f*256+dir_ptr; int 2f function code for append + int int_function + push es + pop ds + mov si,di + +; mov ah,get_PSP ; set new command +; call int_21 + mov bx,ss + mov es,bx + mov bx,cmd_buf ; command line iput buffer + inc bx ; skip max length + mov es:byte ptr[bx],3+1+6+1 + mov di,bx ; address command line buffer + inc di ; skip current length + push ds + push si + push cs + pop ds + move ,3+1+6+1,setappend_name ; set in "SET APPEND=" + pop si + pop ds + cmp ds:byte ptr[si],";" ; null list is special case + jne copy_path + mov al," " + stosb + inc es:byte ptr[bx] + jmp short copy_path_done +copy_path: + lodsb + cmp al,0 + je copy_path_done + stosb + inc es:byte ptr[bx] + jmp copy_path +copy_path_done: + mov es:byte ptr[di],cr ; set end delimiter + + les di,cmd_name@ + mov al,3 ; SET length + stosb + push cs ; @@06 + pop ds ; @@06 + move ,8,set_name ; set up "SET" command + + mov ax,0 ; set to do SET +no_E_mode: + + restore_regs + ret + +page + +do_command: ; APPEND process + +; set ctrl-break check off +; first, save the old state so we can restore it later, +; then turn ctrl-break checking off + + mov ah,ctrl_break ; function code for ctrl-break check + xor al,al ; 0 = get current state + call int_21 + + mov ctrl_break_state,dl ; save the old ctrl-break state + + mov ah,ctrl_break ; function code for ctrl-break check + mov al,01 ; set current state + xor dl,dl ; 0 = off + call int_21 + +; find out if append has been loaded + + mov ah,append_2f ; int 2f function code for append + mov al,are_you_there ; function code to ask if append + ; has been loaded + int int_function + + cmp al,append_inst ; is append there? + jne not_already_there ; yes, don't try to put it + jmp already_there ; yes, don't try to put it + ; there again + +; get DOS version and decide if it is in the allowed range for +; APPEND + +not_already_there: + mov ah,get_version ; lets find out if we should do it + call int_21 ; try the open + cmp ax,expected_version ; compare with DOS version + jne bad_DOS + + jmp check_assign ; valid range + ; lets see if assign has been loaded + +; Break it to the user that he's trying to do an APPEND with +; the wrong DOS version + +bad_DOS: + cmp al,01 ; DOS 1x or below has no handle fcns ; fixed P134 9/10/87 - gga + ja use_STDERR +; lea dx,bad_DOS_msg ; bad DOS message ;AN000; +; mov ah,print_string ;AN000; +; call int_21 ;AN000; + call sysloadmsg ;AN000; + ;AN000; + mov ax,8 ; message number ;AN000; + mov bx,NO_HANDLE ; no handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + + call ctrl_break_rest + int termpgm ; return to DOS ; @@05 + +use_STDERR: + ;AN000; + call sysloadmsg ;AN000; + ;AN000; + mov ax,8 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; mov cx,len_bad_DOS_msg ; length of string ;AN000; +; lea dx,bad_DOS_msg ; bad DOS message ;AN000; +; call print_STDERR ; display error message ;AN000; + + call ctrl_break_rest + mov al,0ffh ; bad DOS version ; @@05 + call terminate ; exit to DOS ; @@05 + +check_assign: + mov ax,0600h + int 2fh + or al,al + jnz assign_there + jmp check_TopView ; ASSIGN has not been loaded, ; @@01 + +; ASSIGN has been loaded before APPEND, bad news! + +assign_there: + call sysloadmsg ;AN000; + ;AN000; + mov ax,6 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; mov cx,len_append_assign_msg; length of string +; lea dx,append_assign_msg +; call print_STDERR ; display error message + jmp conflict_exit ; @@01 + ; @@01 +check_Topview: ; @@01 + mov bx,0 ; incase not there ; @@01 + mov ax,10h*256+34 ; TopView version check ; @@01 + int 15h ; @@01 + cmp bx,0 ; @@01 + jnz TopView_there ; @@01 + jmp replace_vector ; TopView has not been loaded, ; @@01 + ; @@01 +; TopView has been loaded before APPEND, bad news! ; @@01 + ; @@01 +TopView_there: ; @@01 +; mov cx,len_append_TV_msg ; length of string ; @@01 +; lea dx,append_TV_msg ; @@01 +; call print_STDERR ; display error message ; @@01 + call sysloadmsg ;AN000; + ;AN000; + mov ax,7 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + + ; @@01 +conflict_exit: ; @@01 + call ctrl_break_rest + mov al,0fdh ; @@05 + call terminate ; exit to DOS ; @@05 + +; get pointer to dir list, on return ES:DI points to buffer + +already_there: + +; This code has been moved to main_begin ; @@07 +; ; @@07 +; make sure the right version of APPEND has been loaded ; @@07 +; + +; mov dx,0 ; set for network version ; @@07 +; mov ah,append_2f ; int 2F function code for append ; @@07 +; mov al,DOS_version ; function code for get version ; @@07 +; int int_function ; @@07 +; cmp dx,word ptr version_loc ; does the version match? ; @@07 +; jump NE,bad_append_ver ; no, cough up an error messsage ; @@07 + +process_args: ; process all arguments + +;------------------------------------------------------------------- + mov si,0081h ; DS:SI points to argument area + mov cs:byte ptr e_switch+9,0 ; turn /E switch off + +process_argsx: ; process all arguments +; + + +; make sure that the /PATH and /X switches are re-enabled, and +; various flags are cleared + + mov ah,"/" + mov cs:byte ptr x_switch+9,ah ; re-enable /X switch + mov cs:byte ptr path_switch+9,ah ; re-enable /PATH switch + mov cs:byte ptr x_result.$P_Type,0 ; clear flag + mov cs:byte ptr path_result.$P_Type,0 ; clear flag + mov cs:byte ptr dirs_result.$P_Type,0 ; clear flag + mov cs:parse_flag,0 ; clear parse flag + +; set up things to call PARSER + + push cs ; make sure ES points to segment where + pop es ; parm block info is + lea di,cs:p_block2 ; ES:DI points to parm block, for secondary parsing + + + xor cx,cx ; ordinal value, must start as 0 + xor dx,dx ; must be 0 + + call Scan_For_Equal ; yes - let's see if we have "=" symbol ;an008; dms; + ; parse past it if we do + +get_pars_info: + call dword ptr pars_off ; call to COMMAND.COM's parser + + cmp ax,-1 ; end of line? + jne not_end_of_line ; no, carry on + jmp end_of_line_reached ; yes, go figure out what we got + +not_end_of_line: + + cmp ax,0 ; no, find out if there an error + je not_parse_error ; no, carry on + jmp parse_error ; yes, go display the error message + +; got here without any errors, set the proper bits in mode_flags + +not_parse_error: + mov cs: parse_flag,0ffh ; set parse flag + + +check_e: + cmp e_result.$P_Type,3 ; was there a /E in this pass? + jne check_x ; no, look for an X + + mov byte ptr e_switch+9,0 ; turn this off so we don't allow another + mov e_result.$P_Type,0 ; clear this so we don't get fooled later + + or mode_flags,E_mode ; set E mode on + + jmp get_pars_info ; go get another argument + +check_x: + cmp x_result.$P_Type,3 ; was there a /X on this pass? list index + je set_x ; yes, and it was /X w/o ON or OFF + + cmp x_result.$P_Type,2 ; was there a /X on this pass? list index + jne check_path + + mov byte ptr x_switch+9,0 ; turn this off so we don't allow another + mov x_result.$P_Type,0 ; clear this so we don't get fooled later + + cmp x_result.$P_Item_Tag,1 ; was /X or /X:ON specified? + je set_x ; yes, set X mode on + and mode_flags,NOT x_mode ; no, clear it + jmp get_pars_info + +set_x: + or mode_flags,x_mode + jmp get_pars_info + +check_path: + cmp path_result.$P_Type,2 ; was there a /path on this pass? list index + jne check_dirs + + xor ah,ah ; turn this off so we don't allow + mov byte ptr path_switch+9,ah ; another + mov path_result.$P_Type,0 ; clear this so we don't get fooled later + + + cmp path_result.$P_Item_Tag,1 ; was /PATH:ON specified? + je set_path ; yes, set PATH mode + and mode_flags,NOT path_mode ; no, clear it + jmp get_pars_info + +set_path: + or mode_flags,path_mode ; set PATH mode on + jmp get_pars_info + +; find out if dirs specified + +check_dirs: + cmp dirs_result.$P_Type,3 ; was a simple string returned? + je check_dirs2 ; yes, carry on + jmp get_pars_info ; no, all done for now + +; set up stuff to do the dirs copy + +check_dirs2: + push es + push ds + push si + push di + + lds si,dword ptr dirs_result.$P_Picked_Val ; get pointer to dirs string + mov dirs_result.$P_Type,0 ; clear this so we don't get fooled later + + mov di,0 ; set incase int 2f not installed ; @@08 + mov es,di ; @@08 + mov ax,append_2f*256+dir_ptr ; es:di -> internal result area ; @@08 + int int_function ; @@08 + mov ax,es ; see if active yet ; @@08 + or ax,di ; @@08 + jnz copy_dirs_loop ; ok, do the copy ; @@08 + push cs ; not active, set myself ; @@08 + pop es ; @@08 + lea di,app_dirs ; @@08 + +copy_dirs_loop: + movs es: byte ptr[di],ds:[si]; copy char + + cmp byte ptr ds:[si-1],0 ; is char a null + je done_copy_dirs + + jmp copy_dirs_loop + +done_copy_dirs: + + pop di + pop si + pop ds + pop es + + jmp get_pars_info ; no error yet, loop till done + +end_of_line_reached: + mov old_syntax,0 ; process old format operands + + cmp cs:initial_pass,-1 ; is this the first APPEND ;AN006; + je first_one ; yes, clear flag and exit ;AN006; + + cmp cs:parse_flag,0 ; if this flag is off, means null command line + ; was nothing on the command line + je display_dirs ; go display the dirs + +first_one: ;AN006; + mov cs:initial_pass,0 ; clear first pass flag ;AN006; + +done_for_now: +normal_exit: + call ctrl_break_rest ; reset control break checking + mov ax,0 ; set string + ret ; exit to COMMAND + + +parse_error: + push ax ;save parser error code ;an010;bgb + call sysloadmsg ;AN000; + pop ax ;restore parser error coed ;an010;bgb + call do_parse_err ;an010;bgb + jmp bad_parmx ; display message and get out + +;------------------------------------------------------------------- + +; mov si,0081h ; point si to argument area +; mov bx,ss +; mov ds,bx +; +;process_argsx: ; process all arguments +; mov di,0 ; set incase int 2f not installed ; @@08 +; mov es,di ; @@08 +; mov ax,append_2f*256+dir_ptr ; es:di -> internal result area ; @@08 +; int int_function ; @@08 +; mov ax,es ; see if active yet ; @@08 +; or ax,di ; @@08 +; jnz have_ptr ; @@08 +; push cs ; not active, set myself ; @@08 +; pop es ; @@08 +; lea di,app_dirs ; @@08 +;have_ptr: ; @@08 +; +;; step through the DOS command line argument area, and copy the new dir +;; list to the proper place in APPEND. This requires some parsing for +;; spaces, tabs chars, equal signs, as well as conversion to upper case +; +; cmp byte ptr[si],"=" ; APPEND=path is OK syntax +; jne skip_leading +; inc si +;skip_leading: ; skip leading spaces +; lodsb +; cmp al," " +; je skip_leading +; cmp al,tab_char +; je skip_leading +; cmp al,"," ; @@15 +; je skip_leading ; @@15 +; cmp al,"=" ; @@15 +; je skip_leading ; @@15 +; cmp al,cr ; did we have command line arguments? +; jump E,display_dirs ; no, display the dirs currently appended +; cmp al,"/" ; is it a parm starter? ; @@05 +; jump E,bad_path_parm ; yes, it's an error ; @@05 +; dec si +; +;copy_args: +; lodsb ; get char from command line area +; cmp al,cr ; are we at the end? +; jump E,found_end ; yes, display the currently appended dirs +; cmp al," " ; is it a space? +; je found_space ; yes, at end +; cmp al,tab_char ; is it a tab? +; je found_space ; yes, treat it like a space +; cmp al,"/" ; is it a parm starter? +; je bad_path_parm ; yes, it's an error ; @@05 +; cmp al,"a" ; find out if we have a lower case char +; jb copy_char ; @@14 +; cmp al,"z" +; ja copy_char ; @@14 +; sub al,"a"-"A" ; convert char to upper case ; @@14 +; +;copy_char: +; mov in_middle,-1 ; say that we made it to the middle +; stosb ; no, copy char into resident storage area +; jmp copy_args ; do it some more +; +;found_space: +; cmp in_middle,0 ; set the space flag then go through +; jump E,copy_args ; loop some more +; +;found_end: +; cmp in_middle,0 ; if I found the end of string but not +; jump E,display_dirs ; in the middle, go display some dirs +; +; mov es:byte ptr [di],0 ; null terminate the string +; mov in_middle,0 +; cmp al,cr +; je past_trailing +; +;skip_trailing: ; skip end spaces +; lodsb +; cmp al," " +; je skip_trailing +; cmp al,tab_char +; je skip_trailing +; cmp al,"/" ; path and parm not together ; @@05 +; je bad_path_parm ; @@05 +; cmp al,cr ; only white space allowed at end +; jne bad_path +;past_trailing: +; +; cmp old_syntax,0 ; go back to normal mode +; je normal_exit +; jmp exit_append2 +;normal_exit: +; call ctrl_break_rest ; reset control break checking +; mov ax,0 ; set string +; ret ; exit to COMMAND + +bad_path: ; bad paath operand +; mov cx,len_path_error_msg ; length of string +; lea dx,path_error_msg + call sysloadmsg ;AN000; + ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; +;gga call sysdispmsg ;AN000; + + jmp short bad_parmx + +bad_path_parm: ; bad parameter ; @@05 +; mov cx,len_path_parm_error_msg ; length of string ; @@05 +; lea dx,path_parm_error_msg ; @@05 + call sysloadmsg ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; standard error ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + jmp short bad_parmx ; @@05 +bad_parm: ; bad parameter +; mov cx,len_parm_error_msg ; length of string +; lea dx,parm_error_msg + call sysloadmsg ;AN000; + ;AN000; + mov ax,3 ; message number ;AN000; + mov bx,STDERR ; standard error ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + +bad_parmx: ; bad parameter + push ds + push cs + pop ds +; call print_STDERR ; display error message + lea si,inv_parm ; point to msg parm ;an010;bgb + call sysdispmsg ;AN000; + pop ds + call ctrl_break_rest + mov al,1 ; @@05 + call terminate ; exit to DOS ; @@05 + +; This code has been moved to main_begin ; @@07 +;bad_append_ver: ; append version mismatch ; @@07 +; push ds ; @@07 +; push cs ; @@07 +; pop ds ; @@07 +; mov cx,len_bad_append_msg ; @@07 +; lea dx,bad_append_msg ; bad app message ; @@07 +; call print_STDERR ; @@07 +; lea dx,crlf ; carriage return, line feed ; @@07 +; mov cx,crlf_len ; length of string ; @@07 +; call print_STDERR ; @@07 +; pop ds ; @@07 +; call ctrl_break_rest ; @@07 +; mov ax,0feh ; bad APPEND version ; @@05 +; call terminate ; exit to DOS ; @@05 + +; Display currently appended directories + +display_dirs: + call address_status ; get working path ; @@03 + push ds + push es + pop ds + + cmp es:byte ptr[di],";" ; no append now + je no_dirs_appended + +; count the chars in the dir list, cx will hold the count + + mov si,di + sub si,6+1 ; move pointer to APPEND + mov dx,si ; save pointer to string + xor cx,cx + +scanit: + lodsb ; get character + cmp al,null ; are we at end? + je print_it ; yes, print it + inc cx ; look at the next character + jmp scanit ; loop till we find the end + +print_it: + call print_STDOUT ; display appended dirs + push cs + pop ds + lea dx,crlf ; carriage return, line feed + mov cx,crlf_len ; length of string + call print_STDOUT + pop ds + +exit_append: + cmp old_syntax,0 ; process old format operands + je exit_append2 + mov si,0081h ; set up rescan + mov ah,get_PSP + call int_21 + mov ds,bx + jmp process_argsx + +exit_append2: + mov old_syntax,0 ; after first time this must be off + call ctrl_break_rest ; reset control break checking + mov ax,-1 ; no action + ret ; exit to COMMAND + +no_dirs_appended: + push cs + pop ds + + call sysloadmsg ;AN000; + ;AN000; + mov ax,5 ; message number ;AN000; + mov bx,STDERR ; handle ;AN000; + xor cx,cx ; sub count ;AN000; + xor dl,dl ; no input ;AN000; + mov dh,-1 ; message class ;AN000; + call sysdispmsg ;AN000; + +; lea dx,no_append_msg ; no dirs message ;AN000; +; mov cx,len_no_append_msg ; length of string ;AN000; +; call print_STDOUT ;AN000; + pop ds + jmp exit_append2 ; APPEND = = fix ;GGA + +page +;------------------------------------------------------------------- +; Getting here means that APPEND has not been loaded yet. Get the +; old vector, save it, and point the vector to the new routine. +;------------------------------------------------------------------- + +replace_vector: + + push ds + mov si,0081h ; point si to argument area + mov ah,get_PSP + call int_21 + mov ds,bx + +; Process /X and /E parameters + +skip_leading2: ; skip leading spaces +; lodsb +; cmp al," " +; je skip_leading2 +; cmp al,tab_char +; je skip_leading2 +; cmp al,cr ; at end +; jump E,parms_done +; cmp al,"/" +; jne set_old_syntax + +found_slash: +; lodsb +; cmp al,"e" +; je slash_E +; cmp al,"E" +; je slash_E +; cmp al,"x" +; je slash_X +; cmp al,"X" +; je slash_X +bad_parmy: +; pop ds +; jmp bad_parm +bad_path_parmy: +; pop ds +; jmp bad_path_parm + +slash_X: +; test mode_flags,X_mode ; no duplicates allowed +; jnz bad_parmy +; or mode_flags,X_mode +; jmp short slashx + +slash_E: +; test mode_flags,E_mode ; no duplicates allowed +; jnz bad_parmy +; or mode_flags,E_mode +slashx: +; jmp skip_leading2 ; loop some more +set_old_syntax: +;; test mode_flags,0 ; no /? switches on old mode +;; jne bad_path_parmy + mov old_syntax,1 +parms_done: + pop ds + jmp exit_append +page + +set_vectors: ; set append hooks ; @@05 + push es + +; Get INT 2f vector. Save to call older 2f handlers + + mov ax,get_intfcn ; Get INT 2fh vector + call int_21 + mov intfcn_offset,bx ; Save it + mov intfcn_segment,es + +; get int 21 vector + + mov ax,get_vector ; Get INT 21h vector + call int_21 + mov vector_offset,bx ; Save it + mov vector_segment,es + pop es + + push ds ; @@08 + push cs ; @@08 + pop ds ; @@08 + lea dx,intfcn_hook ; DS:DX = New INT 2fh vector + mov ax,set_intfcn ; Hook the interrupt + call int_21 + + lea dx,interrupt_hook ; DS:DX = New INT 21h vector + mov ax,set_vector ; Hook the interrupt + call int_21 + + mov dirlst_segment,cs ; save the address of the dirlist + lea dx,app_dirs + mov dirlst_offset,dx + pop ds ; @@08 + + ret ; @@05 + +terminate: ; terminate to dos or return ; @@05 + cmp res_append,0 ; @@05 + jne is_res ; @@05 + call Release_Environment ; release environmental vector ;ac009; dms; + mov ah,term_proc ; return to DOS on first time ; @@05 + call int_21 ; @@05 +is_res: ; @@05 + mov ax,-1 ; set abort requested ; @@05 + jmp abort_exit ; must go back to COMMAND ; @@05 + + +print_STDOUT: + mov bx,STDOUT ; Standard output device handle + mov ah,awrite ; function code for write + call int_21 + ret + +print_STDERR: + mov bx,STDERR ; Standard output device handle + mov ah,awrite + call int_21 + ret + +Release_Environment: ;an007; dms; + + push ax ;save regs ;an007; dms; + push bx ; ;an007; dms; + push es ; ;an007; dms; + mov ah,Get_PSP ; get the PSP segment ;an007; dms; + call int_21 ; invoke INT 21h ;an007; dms; + mov es,bx ; BX contains PSP segment - put in ES ;an007; dms; + mov bx,word ptr es:[PSP_Env]; get segment of environmental vector ;an007; dms; + mov es,bx ; place segment in ES for Free Memory ;an007; dms; + mov ah,Free_Alloc_Mem ; Free Allocated Memory ;an007; dms; + int 21h ; invoke INT 21h ;an007; dms; + pop es ; restore regs ;an007; dms; + pop bx ; ;an007; dms; + pop ax ; ;an007; dms; + + ret ; return to caller ;an007; dms; + +;========================================================================= +; Scan_For_Equal : This routine scans the command line from the +; beginning until it encounters anything other +; than the equal, tab, or space characters. +; Register SI is sent back to the caller pointing +; to the character that does not meet the match +; criteria. +; +; Inputs : DS:SI - pointer to next parm +; +; Outputs : SI - adjusted to byte not matching the following: +; "=" +; " " +; TAB +; +; Author : DS +; Date : 1/27/88 +; Version : DOS 3.4 +;========================================================================= + +Scan_For_Equal: + + push ax ; save regs ;an008; dms; + push cx ; ;an008; dms; + + xor cx,cx ; clear cx ;an008; dms; + mov cl,byte ptr ds:[80h] ; get length of command line ;an008; dms; + +Scan_For_Equal_Loop: + + cmp cx,0 ; at end? ;an008; dms; + jbe Scan_For_Equal_Exit ; exit loop ;an008; dms; + mov al,byte ptr ds:[si] ; get 1st. character ;an008; dms; + call Chk_DBCS ; DBCS lead byte? ;an008; dms; + jnc Scan_For_Equal_No_DBCS ; no ;an008; dms; + cmp byte ptr ds:[si],81h ; blank lead byte ;an008; dms; + jne Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + cmp byte ptr ds:[si+1],40h ; DBCS blank ;an008; dms; + jne Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + + add si,2 ; yes - DBCS lead byte ;an008; dms; + sub dx,2 ; decrease counter ;an008; dms; + jmp Scan_For_Equal_Loop + +Scan_For_Equal_No_DBCS: + + cmp al,"=" ; = found? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + cmp al,20h ; space? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + cmp al,09h ; tab? ;an008; dms; + je Scan_For_Equal_Next ; next character ;an008; dms; + jmp Scan_For_Equal_Exit ; exit with adjusted SI ;an008; dms; + +Scan_For_Equal_Next: + + inc si ; adjust ptr ;an008; dms; + dec cx ; decrease counter ;an008; dms; + jmp Scan_For_Equal_Loop ; continue loop ;an008; dms; + +Scan_For_Equal_Exit: + + pop cx ; ;an008; dms; + pop ax ; ;an008; dms; + + ret ; return to caller ;an008; dms; + + + +;========================================================================= ;an010;bgb +; do_parse_err : This routine sets up for the display of a parse ;an010;bgb +; error, and displays the offending parameter. ;an010;bgb +; ;an010;bgb +; Inputs : DS:SI - points just past offending parm in command line ;an010;bgb +; ;an010;bgb +; Outputs : si_off- parm for msg ret. ;an010;bgb +; si_seg- parm for msg ret. ;an010;bgb +; command line - hex zero at end of offending parm ;an010;bgb +; ;an010;bgb +; Date : 3/29/88 ;an010;bgb +; Version : DOS 4.0 (wow!) ;an010;bgb +;========================================================================= ;an010;bgb +do_parse_err PROC ;an010;bgb +;;;;;;;;mov ax,3 ;removed- parser handles this ;an010;bgb + mov bx,STDERR ; handle ;an010;bgb +;;;;;;;;xor cx,cx ; sub count ;an010;bgb + mov cx,1 ;display invalid parm ;an010;bgb + xor dl,dl ; no input ;an010;bgb + mov dh,02 ; message class of parse error ;an010;bgb +;;;;;;;;mov cs:si_off,81h ;initialize pointer ;an010;bgb + ;an010;bgb + dec si ;point to last byte of invalid parm ;an010;bgb +public decsi ;an010;bgb +decsi: cmp byte ptr [si],' ' ;are we pointing to a space? ;an010;bgb +; $IF E,OR ;if so, we dont want to do that ;an010;bgb + JE $$LL1 + cmp byte ptr [si],0dh ;are we pointing to CR? ;an010;bgb +; $IF E ;if so, we dont want to do that ;an010;bgb + JNE $$IF1 +$$LL1: + dec si ;find the last byte of parm ;an010;bgb + jmp decsi ;an010;bgb +; $ENDIF ;an010;bgb +$$IF1: + mov byte ptr [si+1],00 ;zero terminate display string ;an010;bgb +nextsi: ;an010;bgb +public nextsi ;an010;bgb + dec si ;look at previous char ;an010;bgb + cmp byte ptr [si],' ' ;find parm separator ;an010;bgb + jnz nextsi ;loop until begin of parm found ;an010;bgb + ;an010;bgb + mov cs:si_off,si ;mov si into display parms ;an010;bgb + mov cs:si_seg,ds ;initialize pointer ;an010;bgb + ret ; return to caller ;an010;bgb +do_parse_err ENDP ;an010;bgb + + +;------------------------------------------------------------------- +; +;------------------------------------------------------------------- + +MSG_SERVICES +MSG_SERVICES + +end_address: ; this is the end of the TSR stuff ;AN004; + +include parse.asm ; include the parser code +include msgdcl.inc + +cseg ends +sseg segment para stack 'STACK' + assume ss:sseg + dw 512 dup(0) +mystack dw 0 +sseg ends + + + + end main_begin + \ No newline at end of file diff --git a/v4.0/src/CMD/APPEND/APPEND.SKL b/v4.0/src/CMD/APPEND/APPEND.SKL new file mode 100644 index 0000000..3fc30ef --- /dev/null +++ b/v4.0/src/CMD/APPEND/APPEND.SKL @@ -0,0 +1,24 @@ + +;------------------------------------------------------------------- +; message retriever skeleton file for APPEND +;------------------------------------------------------------------- +:util APPEND + +:class a +;:use 1 COMMON1 +:def 1 "Incorrect APPEND version",CR,LF +:def 2 "Invalid path",CR,LF +:def 3 "Invalid parameter",CR,LF +:def 4 "Invalid combination of parameters",CR,LF +:def 5 "No Append",CR,LF + +:class b +:def 6 "APPEND / ASSIGN Conflict",CR,LF +:def 7 "APPEND / TopView Conflict",CR,LF +:def 8 "Incorrect DOS Version",CR,LF +:def 9 "APPEND already installed",CR,LF +;:use 8 COMMON1 ;"Incorrect DOS Version" +;:use 9 COMMON1 ;"APPEND already installed" + +:end + \ No newline at end of file diff --git a/v4.0/src/CMD/APPEND/APPENDM.ASM b/v4.0/src/CMD/APPEND/APPENDM.ASM new file mode 100644 index 0000000..5cd3f69 --- /dev/null +++ b/v4.0/src/CMD/APPEND/APPENDM.ASM @@ -0,0 +1,36 @@ +page 60,120 +; @@04 07/30/86 Fix second APPEND hang PTM P0000053 +; @@05 08/13/86 Fix bad parm message PTM P0000125 +; @@10 08/28/86 Change message for @@05 PTM P0000291 +; @@11 09/10/86 Support message profile and make +; msg length variable. R.G. PTM P0000479 +cseg segment public para 'CODE' + assume cs:cseg + + public bad_append_msg ;@@11 + public path_error_msg ;@@11 + public parm_error_msg ;@@11 + public path_parm_error_msg ;@@11 + public no_append_msg ;@@11 + public append_assign_msg ;@@11 + public append_tv_msg ;@@11 + public bad_DOS_msg ;@@11 + public second_append_msg ;@@11 + + public len_bad_append_msg ;@@11 + public len_path_error_msg ;@@11 + public len_parm_error_msg ;@@11 + public len_path_parm_error_msg ;@@11 + public len_no_append_msg ;@@11 + public len_append_assign_msg ;@@11 + public len_append_tv_msg ;@@11 + public len_bad_DOS_msg ;@@11 + public len_second_append_msg ;@@11 + +cr equ 13 +lf equ 10 + +include appendm.inc + +cseg ends + end diff --git a/v4.0/src/CMD/APPEND/APPENDP.INC b/v4.0/src/CMD/APPEND/APPENDP.INC new file mode 100644 index 0000000..432d4ec --- /dev/null +++ b/v4.0/src/CMD/APPEND/APPENDP.INC @@ -0,0 +1,147 @@ + +INCSW EQU 0 ;INCLUDE PSDATA.INC ;AN000; +FARSW EQU 1 ;CALL THE PARSER BY NEAR CALL +DATESW EQU 0 ;SUPPRESS DATE CHECKING ;AN000; +TIMESW EQU 0 ;SUPPRESS TIME CHECKING ;AN000; +FILESW EQU 0 ;SUPPRESS CHECKING FILE SPECIFICATION ;AN000; +CAPSW EQU 0 ;SUPPRESS FILE TABLE CAPS ;AN000; +CMPXSW EQU 1 ;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 1 ;SUPPRESS SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT ;AN000; +NUMSW EQU 1 ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT ;AN000; +SWSW EQU 1 ;DO SUPPORT SWITCHES ;AN000; +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 ;AN000; +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 ;AN000; +VAL3SW EQU 1 ;DO SUPPORT VALUE DEFINITION 3 + +include psdata.inc +;*********************************************************************** + +;------------------------------------------------------------------- +; +; parser stuff for APPEND +; +;------------------------------------------------------------------- + + + +p_block1 $P_PARMS_Blk ; parm block +p_block2 $P_PARMS_Blk ; parm block + +;------------------------ +; extended parameter block for APPEND first load + +px_block1: + db 0 ; min number positional operands + db 0 ; max number positional operands +; dw 0 ; offset into control block for positionals + + db 3 ; APPEND has two switches /E, /X, /PATH + dw offset e_switch ; control block for /E switch + dw offset x_switch ; control block for /X switch + dw offset path_switch ; control block for /PATH switch + + db 0 ; max number of keywords + dw 0 ; offset of keyword control block + +;------------------------ +; extended parameter block for 2nd, 3rd, ... APPEND invocations + +px_block2: + db 0 ; min number positional operands + db 1 ; max number positional operands + dw offset dirs_control ; pointer to dirs control block + +; db 2 ; APPEND after first load has two switches /X, /PATH + db 3 ; APPEND has two switches /E, /X, /PATH + dw offset e_switch ; control block for /E switch + dw offset x_switch ; control block for /X switch + dw offset path_switch ; control block for /PATH switch + + db 0 ; max number of keywords + +;------------------------ +dirs_control: + dw $P_Simple_S+$P_Optional ; complex, optional string + dw $P_CAP_File ; cap by file table + dw offset dirs_result ; dirs result buffer + dw offset dirs_values ; pointer to null value list + db 0 ; no synonyms + +dirs_values: + db 0 ; null value list for dirs + + + +;------------------------ +x_switch: + dw $P_Simple_s+$P_Optional ; /X, /X:ON, /X:OFF simple, optional string + dw $P_CAP_Char ; cap by char table + dw offset x_result ; pointer to result block + dw offset x_values ; pointer to values block + db 1 ; number of switches and synonyms + db "/X",0 ; only /X is valid + +x_values: + db 3 ; string values + db 0 ; zeroes here for ranges and + db 0 ; values + db 2 ; 2 possible string values + db 0 ; /X:OFF = 0 + dw offset off_string ; pointer to "OFF" + db 1 ; /X:ON = 1 + dw offset on_string +;------------------------ + +e_switch: + dw 0 ; /E + dw $P_CAP_Char ; cap by char table + dw offset e_result ; pointer to result block + dw offset e_values ; pointer to values block, none + db 1 ; number of switches and synonyms + db "/E",0 ; only /E is valid + +e_values: + db 0 ; null value list for /E + + +;------------------------ +path_switch: + dw $P_Simple_s ; /PATH:ON, /PATH:OFF simple string + dw $P_CAP_Char ; cap by char table + dw offset path_result ; pointer to result block + dw offset path_values ; pointer to values block + db 1 ; number of switches and synonyms + db "/PATH",0 ; only /PATH is valid + + +path_values: + db 3 ; string values + db 0 ; zeroes here for ranges and + db 0 ; values + db 2 ; 2 possible string values + db 0 ; /PATH:OFF = 0 + dw offset off_string ; pointer to "OFF" + db 1 ; /PATH:ON = 1 + dw offset on_string + + +;------------------------ + +off_string: + db "OFF",0 ; off string + +on_string: + db "ON",0 ; on string + + +;------------------------ + +x_result $P_Result_Blk <> ; /X result block +e_result $P_Result_Blk <> ; /E result block +path_result $P_Result_Blk <> ; /PATH result block +dirs_result $P_Result_Blk <> ; dirs result block + + + \ No newline at end of file diff --git a/v4.0/src/CMD/APPEND/MAKEFILE b/v4.0/src/CMD/APPEND/MAKEFILE new file mode 100644 index 0000000..73f7dd7 --- /dev/null +++ b/v4.0/src/CMD/APPEND/MAKEFILE @@ -0,0 +1,20 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: append.exe + +append.ctl: append.skl $(msg)\$(COUNTRY).msg + +append.obj: append.asm appendp.inc $(inc)\parse.asm append.ctl + +append.exe: append.obj + link append; + diff --git a/v4.0/src/CMD/APPEND/SYSMAC.LIB b/v4.0/src/CMD/APPEND/SYSMAC.LIB new file mode 100644 index 0000000..7a38a59 --- /dev/null +++ b/v4.0/src/CMD/APPEND/SYSMAC.LIB @@ -0,0 +1,361 @@ +; +; SYSTEM MACROS +; +; DISPLAY TEXT ON SCREEN +; +DISP MACRO TEXT,SEGM + IFNB + IFDIF , + PUSH DS + MOV AX,SEGM + MOV DS,AX + ENDIF + ENDIF + IFNB + LEA DX,TEXT + ENDIF + DOS DSTR + IFNB + IFDIF , + POP DS + ENDIF + ENDIF + ENDM +; +DMSG MACRO MSG + IFNB + LEA DX,MSG + ENDIF + DISP + ENDM +; +DCHAR MACRO CHAR + PUSH DX + IFNB + MOV DL,CHAR ; SET CHARACTER + ELSE + MOV DL,AL + ENDIF + DOS DO + POP DX + ENDM +; +; CLEAR SCREEN +; +CLEAR MACRO + MOV CX,00H*256+00H ; ROW=00, COL=00 + MOV DX,24H*256+79H ; ROW=24, COL=79 + MOV BH,07H ; NORMAL ATTRIBUTE + MOV AX,06H*256+00H ; CLEAR WHOLE SCREEN + INT 10H + ENDM +; +POS MACRO ROW,COL,PAGE + IFNB + MOV DX,ROW*256+COL ; SET ROW AND COLUMN + ENDIF + IFNB + MOV BH,PAGE ; SET PAGE + ELSE + MOV BH,0 + ENDIF + MOV AH,02H ; POSTIION CURSOR + INT 10H + ENDM +; +DEFMSG MACRO ID,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 + IFNB +ID LABEL BYTE ; DEFINE ESSAGE + ENDIF + IFNB + DB T1 + ENDIF + IFNB + DB T2 + ENDIF + IFNB + DB T3 + ENDIF + IFNB + DB T4 + ENDIF + IFNB + DB T5 + ENDIF + IFNB + DB T6 + ENDIF + IFNB + DB T7 + ENDIF + IFNB + DB T8 + ENDIF + IFNB + DB T9 + ENDIF + IFNB + DB T10 + ENDIF + DB '$' + ENDM +; +MOVE MACRO TO,LEN,FROM + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + MOV CX,LEN ; SET LENGTH + ENDIF + IFNB + LEA SI,FROM ; SET SOURCE + ENDIF + REP MOVS BYTE PTR[DI],BYTE PTR[SI] + ENDM +MOVEZ MACRO TO,FROM + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + LEA SI,FROM ; SET SOURCE + ENDIF + CALL MOVZ$ + ENDM +; +SCAN MACRO TO,LEN,VALUE,TYPE + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + MOV CX,LEN ; SET LENGTH + ENDIF + IFNB + MOV AL,VALUE ; SET SOURCE + ENDIF + IFB + REPZ SCASB + ENDIF + IFIDN , + REPZ SCASB + ENDIF + IFIDN , + REPZ SCASB + ENDIF + IFIDN , + REPNZ SCASB + ENDIF + IFIDN , + REPNZ SCASB + ENDIF + ENDM +; +FILL MACRO TO,LEN,VALUE + PUSH DI + PUSH CX + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + MOV CX,LEN ; SET LENGTH + ENDIF + IFNB + MOV AL,VALUE ; SET SOURCE + ENDIF + REP STOS BYTE PTR[DI] + POP CX + POP DI + ENDM +; +COMP MACRO TO,LEN,FROM + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + MOV CX,LEN ; SET LENGTH + ENDIF + IFNB + LEA SI,FROM ; SET SOURCE + ENDIF + REPE CMPS BYTE PTR[DI],BYTE PTR[SI] + ENDM +COMPZ MACRO TO,FROM + IFNB + LEA DI,TO ; SET DESTINATION + ENDIF + IFNB + LEA SI,FROM ; SET SOURCE + ENDIF + CALL CMPZ$ + ENDM +; +XCHGS MACRO O1,O2 + PUSH O1 + PUSH O2 + POP O1 + POP O2 + ENDM +; +JUMP MACRO COND,TARGET + LOCAL LAB + IFB + JMP TARGET + ENDIF + IFIDN , + JNA LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JBE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNAE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JB LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNB LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JAE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNC LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNBE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JA LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + OR CX,CX + JNZ LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNZ LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNG LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JLE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNGE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JL LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNL LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JGE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNLE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JG LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JC LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JZ LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JO LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JP LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JPE LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JS LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNO LAB + JMP TARGET +LAB: + ENDIF + IFIDN ,

+ JNP LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JPO LAB + JMP TARGET +LAB: + ENDIF + IFIDN , + JNS LAB + JMP TARGET +LAB: + ENDIF + ENDM +; + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM b/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM new file mode 100644 index 0000000..5561366 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGMAIN.ASM @@ -0,0 +1,1771 @@ + + + PAGE 90,132 ; + TITLE ASSGMAIN.SAL - ASSIGN MAIN PROGRAM +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: ASSGMAIN.SAL +; +; DESCRIPTIVE NAME: Reassigns drive specifications. +; +;FUNCTION: This program reassigns the specified drives to a new drive +; identifier. +; +; ENTRY POINT: ENTRY_POINT +; +; INPUT: +; +; ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW] +; where DRIVE = optional colon +; where DELIMITER = +;=TAB LF SPACE +; where SW = /STATUS or /STA +; +; where: +; /STATUS - reports back to the user +; the currently changed +; drive assignments and the +; new assignment drive +; +; Note: +; If a drive value has not been +; ASSIGN will report back nothing. +; +; UTILITY FUNCTION: +; Instructs DOS to route disk I/O +; for one drive into disk I/O to another +; drive. eg. +; a=c sets a: to c: +; +; EXIT-NORMAL: Assigned drives or reassigned drives +; +; EXIT-ERROR: Any one of the possible parse errors +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL) +; SYSLOADMSG +; SYSDISPMSG +; +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT ASSPARM,NUL; +; +; To assemble these modules, the sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; ASSIGN.SAL +; +; REVISION HISTORY: AN000 - Version 4.00: PARSER, System Message Handler, +; Status report +; +; COPYRIGHT: "Microsoft DOS ASSIGN Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft" +; "Licensed Material - Program Property of Microsoft" +; +; +; AN000 -> New Code +; +; AN001 -> PTM P3954 Release the environmental vector and close +; all handles. +; +; AN002 -> PTM P3918 Parse error messages must conform to spec. +; All parse error messages should display +; the offending parameters. +; +; +;****************** END OF SPECIFICATIONS ***************************** + +;********************************************* +;* * +;* UTILITY NAME: ASSIGN.COM * +;* * +;* SOURCE FILE NAME: ASSIGN.SAL * +;* * +;* STATUS: ASSIGN utility * +;* PC-DOS Version 3.40 * +;* * +;* SYNTAX (Command line) * +;* * +;* ASSIGN [DRIVE] [DELIMITER] [DRIVE] [SW] * +;* where DRIVE = optional colon * +;* where DELIMITER = +;=TAB LF SPACE * +;* where SW = /STATUS or /STA * +;* * +;* where: * +;* /STATUS - reports back to the user * +;* the currently changed * +;* drive assignments and the * +;* new assignment drive * +;* Note: * +;* If a drive value has not been * +;* ASSIGN will report back nothing. * +;* * +;* UTILITY FUNCTION: * +;* Instructs DOS to route disk I/O * +;* for one drive into disk I/O to another * +;* drive. eg. * +;* a=c sets a: to c: * +;********************************************* + +page +DEBUG = 0 + +.xlist + INCLUDE SYSMSG.INC ;AN000; + INCLUDE SYSVAR.INC + INCLUDE CURDIR.INC + INCLUDE MULT.INC + INCLUDE PDB.INC + +MSG_UTILNAME + +.list + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + BREAK +BREAK MACRO subtitle +.XLIST + SUBTTL subtitle +.LIST + PAGE + ENDM +.xcref break +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +CallOperRange macro low,high,routine ;;NS-macro to call subroutines +?call = low ;;NS-in the given call range + ;;NS-starting call value = low # +rept (high-low)+1 ;;NS-calculate the entry point + CallOper ?call,routine ;;NS-into the table then execute + ?call = ?call + 1 ;;NS-increment call value to next +endm + endm +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +CallOper macro call,routine ;;NS-macro that calls a single + ;;NS-subroutine that is used in + ;;NS-the above macro loop CallOperange + ORG (SysTab-ASSIGN_BASE)+(call*2) ;;NS-Calculate entry point into + DW OFFSET CODE:routine ;;NS-code where SysTab is the + ENDM ;;NS-entry point to the tables + ;;NS-ASSIGN_BASE is at 0:0000 + ;;NS-the (call*2) is calculated + ;;NS-to take into account two bytes + ;;NS-and final OFFSET statement points + ;;NS-code to be executed at the given + ;;NS-label +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; $SALUT (0,36,40,48) +MyINT21 macro ;;NS-macro used to save + pushf ;;NS-the flags to maintain + call system ;;NS-DOS environment + endm +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +SaveReg MACRO reglist ;; push those registers +IRP reg, + ?stackdepth = ?stackdepth + 1 + PUSH reg +ENDM +ENDM +.xcref SaveReg +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +RestoreReg MACRO reglist ;; pop those registers +IRP reg, + ?stackdepth = ?stackdepth - 1 + POP reg +ENDM +ENDM +.xcref RestoreReg + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +page + BREAK +; $SALUT (0,23,28,41) +; DOS FUNCTIONS USED +; (DEC) (HEX) +NO_ERROR equ 0 ;return code zero from the parser + ;********** CNS ***************** +;Std_Con_String_Output EQU 9 ; 9 +PSP_Env equ 2ch ;Environmental vector segment in PSP ;an001; dms; +Get_PSP equ 62h ; DOS function call to get PSP address ;an001; dms; +Handle_Close equ 3eh ;close handle ;an001; dms; + +Set_Default_Drive EQU 14 ; E +Get_Default_Drive EQU 25 ; 19 +Set_Interrupt_Vector EQU 37 ; 25 +Get_Version EQU 48 ; 30 +Keep_Process EQU 49 ; 31 +Get_Interrupt_Vector EQU 53 ; 35 +Get_Drive_Freespace EQU 54 ; 36 +Exit EQU 76 ; 4C +Dealloc EQU 73 ; 49 +Get_In_Vars EQU 82 ; 52 +Get_Set_Media_ID equ 69h ; 69h + +IOCTL_READ_BLOCK EQU 4404H ;READ FROM BLOCK DEVICE +IOCTL_WRITE_BLOCK EQU 4405H ;WRITE TO A BLOCK DEVICE +IOCTL_BLOCK_CHANGE EQU 4408H ;BLOCK DEVICE CHANGEABLE +IOCTL_BLOCK_REMOTE EQU 4409H ;BLOCK DEVICE REMOTE + +; VECTORS REFERENCED +PGM_TERM EQU 20H +DOS_CALL EQU 21H +CTL_BREAK EQU 23H +CRIT_ERR EQU 24H +ABS_DISK_READ EQU 25H +ABS_DISK_WRITE EQU 26H +stay equ 27h ;NS stay interrupt value +int_IBM EQU 2AH ;critical section maintenance +MULTIPLEXOR EQU 2FH ;MULTIPLEXOR INTERRUPT VECTOR NUMBER + +; CONSTANTS USED ACROSS THE MULTIPLEXOR INTERFACE +MPLEX_ID EQU 06H ;ID OF ASSIGN IN MPLEX CHAIN +MPLEX_R_U_THERE EQU 0 ;MPLEX FUNCTION: ARE YOU THERE? +MPLEX_GET_SEG EQU 1 ;MPLEX FUNCTION: GET SEG OF INSTALLED ASSIGN +MPLEX_INSTALLED EQU 0FFH ;"I AM HERE" RETURN VALUE + +; OTHER EQUATES +cr equ 0dh ;CARRIAGE RETURN +LF EQU 0AH ;LINE FEED +f_Interrupt EQU 0000001000000000B ;NS - mask used for interrupt + ;NS value + BREAK +; $SALUT (4,15,21,41) + +code segment para public ;NS code all in one segment +assume cs:code + ; one segment + +page + +ASSIGN_BASE: ;NS- starting point of loaded file + org 100h + +ENTRY_POINT: + jmp INITIALIZATION ;JUMP TO INITIALIZATION +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + BREAK +drives db 1,2,3,4,5,6,7,8,9 ;drive values used in comparison + db 10,11,12,13,14,15,16,17,18,19 ;against default or found drive + db 20,21,22,23,24,25,26 +default_drive db ? +drive_save db ? ; saved drive byte +drive_address dw ? ; location (from DS) of drive byte +drive_save2 db ? ; second saved drive byte +;****************************************************************************** +;****************************************************************************** + +system dd ? +int25_vec dd ? ;NS - Hooks for the Int 2f handler preparation +int26_vec dd ? ;NS - Hooks for the Int 2f handler preparation +int2F_vec dd ? ;NS - Area to be hooked in and remain resident +user_ret dd ? ; ??????????????????????????????????????? +saveIntF dw ? ; ??????????????????????????????????????? +I21_Func db ? ; Save area for INT21 function requested -->RW + + +; $SALUT (4,9,23,41) + EVEN +SysTab label word ;NS-Beginning of the call,subroutine table + CallOper 00h,DoReset + CallOperRange 01h,0Ch,DoNothing ; done ???????????????????????? + CallOper 0Dh,DoReset ; done ???????????????????????? + CallOper 0Eh,DoSetDefault + CallOperRange 0Fh,17h,DoFCB ; done ???????????????????????? + CallOper 18h,DoReset ; done ???????????????????????? + CallOper 19h,DoGetDefault ; ???????????????????????? + CallOperRange 1Ah,1Bh,DoReset ; done ???????????????????????? + CallOper 1Ch,DoDL ; done ???????????????????????? + CallOperRange 1Dh,20h,DoReset ; done ???????????????????????? + CallOperRange 21h,24h,DoFCB ; done ???????????????????????? + CallOperRange 25h,26h,DoReset ; done ???????????????????????? + CallOperRange 27h,28h,DoFCB ; done ???????????????????????? + CallOperRange 29h,31h,DoReset ; done ???????????????????????? + CallOper 32h,DoDL ; done ???????????????????????? + CallOperRange 33h,35h,DoReset ; done ???????????????????????? + CallOper 36h,DoDL ; done ???????????????????????? + CallOperRange 37h,38h,DoReset ; done ???????????????????????? + CallOperRange 39h,3Dh,DoAscii ; done ???????????????????????? + CallOperRange 3Eh,40h,DoReset ; done ???????????????????????? + CallOper 41h,DoAscii ; done ???????????????????????? + CallOper 42h,DoReset ; done ???????????????????????? + CallOper 43h,DoAscii ; done ???????????????????????? + CallOper 44h,DoIOCTL ; done ???????????????????????? + CallOperRange 45h,46h,DoReset ; done ???????????????????????? + CallOper 47h,DoDL ; done ???????????????????????? + CallOperRange 48h,4Ah,DoReset ; done ???????????????????????? + CallOper 4Bh,DoExec ; done ???????????????????????? + CallOperRange 4Ch,4Dh,DoReset ; done ???????????????????????? + CallOper 4Eh,DoAscii ; done ???????????????????????? + CallOperRange 4Fh,55h,DoReset ; done ???????????????????????? + CallOper 56h,DoRename ; done ???????????????????????? + CallOperRange 57h,59h,DoReset ; done ???????????????????????? + CallOperRange 5Ah,5Bh,DoAscii ; done ???????????????????????? + CallOperRange 5Ch,5Fh,DoReset ; done ???????????????????????? + CallOper 60h,DoTranslate ; done ???????????????????????? + CallOperRange 61h,63h,DoReset ; done ???????????????????????? + CallOperRange 64h,69h,DoSetGetMedia ;done ???????????????????????? + CallOperRange 6ah,6bh,DoNothing ;done ???????????????????????? + CallOper 6ch,DoAscii_DS_SI ;done ????????????????????????? + ; ???????????????????????? +page +; $SALUT (4,5,11,36) +MAXCLL EQU 6CH ; High bound of table + + org (systab-ASSIGN_BASE) + (2 * (MAXCLL + 1)) ;NS - Beginning of code starts at + ;NS - Beginning of table + 128 bytes + BREAK +ASSIGN_HANDLER: + mov SaveIntf,f_interrupt ;NS- Move in the mask into a saved area + SaveReg ;NS- ?????????????????????????????????? + cmp ah,MAXCLL ; Do a high bound check on the call + ; so we don't index past the end of + ja DoNothing ; the table on a bogus call + + mov al,ah ;NS- Call must be in the 0 - 63h range + cbw ;NS- zero out the high byte now + ;NS- AX has 0 & call number + shl ax,1 ;NS- Double the value in AX + mov bx,ax ;NS- Move the value into BX to + jmp systab[bx] ;NS- access the call number & subroutine + ;NS- bx bytes into the tbl +;*********************************************************************************** + +EnterAssign: ;NS- make sure system intact by doing + call LeaveAllAssign ;NS- error recovery check + + push ax ;NS- before making code + mov ax,8000h + critAssign ;NS- non- reentrant if unable + INT INT_IBM ;(2AH) NS- to screen out successfully + + POP AX ;NS- LeaveAllAssign will be executed + RET ;return NS- and the critical section will be reset +;************************************************************************************ +LeaveAssign: ;NS- restore re-entrancy to + push ax ;NS- the code after & only + mov ax,8100h + critAssign ;NS- after this call has been + INT INT_IBM ;(2AH) NS- made or the error recovery + + POP AX ;NS- call has been made + RET ;return NS- + +;************************************************************************************ +LeaveAllAssign: ;NS- Error recovery call + push ax ;NS- to restore the Assigns + mov ax,8908h ;NS- critical section + int INT_IBM ;(2AH) NS- if ASSIGN has encountered + + pop ax ;NS- a problem on entrance or departure + RET ;return NS- +;************************************************************************************ +; +; Reset the exclusion flag ;NS- Reset to Assign +; ;NS- critical section state +DoReset: ;NS- + call LeaveAllAssign ;NS- + ;NS- +;**************************************************************************************** +; +; The system call needed no special processing. Go do it directly. +; +DoNothing: ;NS-System registers and flags still + RestoreReg ;NS-intact it has not been clobbered + jmp system ;NS-by ASSIGN code + +page +;************************************************************************************ +; +; Munge the drive byte in an FCB pointed to by DS:DX. +; "MUNGE" ? (Webster will turn over in his gravy...) +; +DoFCB: + mov bx,dx ; indexable pointer + mov al,[bx] ; get drive + cmp al,0ffh ; extended fcb? + jnz DoMapDrive ; no + + add bx,7 ; yes, advance past it + mov al,[bx] ; get read drive byte +DoMapDrive: + or al,al ; default drive? +; $IF Z ;YES + JNZ $$IF1 + mov al,default_drive ; get default drive +; +; DS:BX points to the drive byte being munged. AL is the old value. Save +; it away. +; +; $ENDIF ;AC000; +$$IF1: + ;SaveFCB: + call EnterAssign ; NS-Enter Assign's critical section + + mov drive_save,al ; NS-save the drive assignment + call mapdrv1 ; NS-now let's map it to the + + mov [bx],al ; NS-numeric drive associated in + ; NS-in drive range 1 to 26 +;****************************************************************************** +; The FCB has been converted. Now let's POP off the user's info and do the +; system call. Note that we are no longer reentrant! +; + mov drive_address,bx ; NS- location of drive value + RestoreReg ; get back original registers + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI ; NS- Clear out old interrupts + ; NS- before an IRET is issued + ; NS- update the current + call system ; flags saved => this is a system call + + pushf ; NS- re-adjust the stack + call RestInt ; NS- and setup the environment + + SaveReg ; NS- with drive and the drive address + mov bx,drive_address ; NS- before leaving the Assign critical + mov al,drive_save ; NS- section + mov [bx],al + RestoreReg + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign + + iret ; back to user + +page +;************************************************************************************ +; +; Munge the user's ASCIZ string at DS:DX. +; +DoAscii: + mov bx,dx ; point to area + cmp byte ptr [bx+1],':' ; drive letter present? + jnz DoNothing ; nope, ignore this +; +; There is a drive leter present. Grab it and convert it +; + mov al,[bx] ; get drive letter + call EnterAssign ; NS- Re-enter ASSIGN crit section + + mov drive_save,al ; remember previous contents + call maplet ; convert to real drive letter + + mov [bx],al ; place in new drive letter + mov drive_address,bx + RestoreReg ; get back original registers + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI ; clean up stack + + call system ; flags saved => this is a system call + + pushf ; save all drive info + call RestInt ; NS- clean up environment before + + SaveReg ; NS- returning to the user's environment + mov bx,drive_address ; NS- to ask on the next ASSIGN entrance + mov al,drive_save + mov [bx],al + RestoreReg + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign ; NS- exit ASSIGN crit. section + + iret ; back to user + + +;************************************************************************************ +; +; Munge the user's ASCIZ string at DS:SI. +; +DoAscii_DS_SI: + mov bx,si ; point to area + cmp byte ptr [bx+1],':' ; drive letter present? +; $if ne ; drive letter not present + JE $$IF3 + jmp DoNothing ; nope, ignore this +; $endif ; +$$IF3: +; +; There is a drive leter present. Grab it and convert it +; + mov al,[bx] ; get drive letter + call EnterAssign ; NS- Re-enter ASSIGN crit section + + mov drive_save,al ; remember previous contents + call maplet ; convert to real drive letter + + mov [bx],al ; place in new drive letter + mov drive_address,bx + RestoreReg ; get back original registers + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI ; clean up stack + + call system ; flags saved => this is a system call + + pushf ; save all drive info + call RestInt ; NS- clean up environment before + + SaveReg ; NS- returning to the user's environment + mov bx,drive_address ; NS- to ask on the next ASSIGN entrance + mov al,drive_save + mov [bx],al + RestoreReg + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign ; NS- exit ASSIGN crit. section + + iret ; back to user + +page +;************************************************************************************ + +; +; DoDL - the drive to map is in DL. +; +DoDL: + or dl,dl ; NS- check for drive mapping +; $IF Z ;AC000;;USE DEFAULT DRIVE + JNZ $$IF5 + +DNJ1: + jmp DoNothing ; NS- default drive was requested + ; NS- thus no mapping needed +; $ENDIF ;AC000; +$$IF5: + mov al,dl ; NS- not default case so no need doctor + call EnterAssign ; NS- so enter ASSIGN crit. section again + + mov drive_save,al ; preserve old drive + call mapdrv1 + + mov dl,al ; drive is mapped + RestoreReg ; get back registers + mov I21_Func,ah ; Save requested function call -->RW + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI + + call system ; flags saved => this is a system call + + pushf ; + call RestInt + + cmp I21_Func,GET_DRIVE_FREESPACE ;(36h) If call returns info in DX, -->RW + ; NS- DL in both cases Func 36 + ; NS- Func 1Ch are both used for + ; NS- drive input we don't want to + ; NS- the old drives so they should not + ; restored as the old value - use ASSIGN's + je Dont_Restore_DL ;AC000;;THEN DO CHANGE IT + + cmp I21_Func,1ch ; If call returns info in DX, -->RW + ;(NOTE 1CH IS NOT DEFINED IN SYSCALL.INC. EK) + je Dont_Restore_DL ;AC000;;THEN DO CHANGE IT + + mov dl,drive_save ; restore his dl + ;DONT_RESTORE_DL: +Dont_Restore_DL: + + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign + + iret ; back to user +;************************************************************************************ + +; Map the IOCTL drives in BX ; NS- this section handles + ; NS- INT21 calls to get drive info +DoIOCTL: + RestoreReg + SaveReg + cmp ax,IOCTL_READ_BLOCK ;(4404h) IOCTL read string from block dev + jz DoMapBX ;AC000; + ; jz DoMapBX + cmp ax,IOCTL_WRITE_BLOCK ;(4405h) IOCTL write string from block dev + jz DoMapBX ;AC000; + ; jz DoMapBX + cmp ax,IOCTL_BLOCK_CHANGE ;(4408h) IOCTL is removable + jz DoMapBX ;AC000; + ; jz DoMapBX + cmp ax,IOCTL_BLOCK_REMOTE ;(4409h) IOCTL block dev redir (network) + jnz DNJ2 ;AC000;;NORMAL CALL + ;DoMapBX: +DoMapBX: + + or bx,bx ; NS- drive letter associated in BL + jz DNJ2 + + mov al,bl ; not the default case + call EnterAssign + + mov drive_save,al ; remember drive + call mapdrv1 ; NS- time to map drive to new assoc. + + mov bl,al ; drive is mapped + RestoreReg ; get back registers (throw away BX) + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI + + call system ; flags saved => this is a system call + + pushf + call RestInt + + mov bl,drive_save ; restore his dl + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign + + iret ; back to user + +DNJ2: + + jmp DoNothing + +DoSetGetMedia: + RestoreReg ;an000; dms;restore regs + SaveReg ;an000; dms;save regs + cmp ah,Get_Set_Media_ID ;an000; dms;trap on get/set media id +; $if z ;an000; dms;found + JNZ $$IF7 + or bl,bl ;an000; dms;drive letter entered +; $if nz ;an000; dms;yes + JZ $$IF8 + mov al,bl ; not the default case + call EnterAssign + + mov drive_save,al ; remember drive + call mapdrv1 ; NS- time to map drive to new assoc. + + mov bl,al ; drive is mapped + RestoreReg ; get back registers (throw away BX) + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI + + call system ; flags saved => this is a system call + + pushf + call RestInt + + mov bl,drive_save ; restore his dl + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign +; $else ;an000; dms;not valid function 69h + JMP SHORT $$EN8 +$$IF8: + jmp DoNothing ;an000; dms;pass to interrupt +; $endif ;an000; dms; +$$EN8: +; $else ;an000; dms; + JMP SHORT $$EN7 +$$IF7: + jmp DoNothing ;an000; dms;pass to interrupt +; $endif ;an000; dms; +$$EN7: + + iret ; back to user +page +;************************************************************************************ +; +; Map the drive letter and forget about it. EXEC never returns. +; +DoExec: + RestoreReg + SaveReg + or al,al +; $IF Z ;AC000;;IS LOAD GO, NOT USE NORMAL STUFF + JNZ $$IF13 + + mov bx,dx ; point to area +DoOnce: + cmp byte ptr [bx+1],':' ; drive letter present? +; $IF Z ;AC000;;YES + JNZ $$IF14 +; +; There is a drive leter present. Grab it and convert it +; + mov al,[bx] ; get drive letter + call maplet ; convert to real drive letter + + mov [bx],al ; place in new drive letter +; $ENDIF ;AC000; +$$IF14: +DNJ3: + jmp DoNothing ; restore and go on! + +; $ENDIF +$$IF13: + ;DAJ: + jmp DoAscii + +;************************************************************************************ +; +; Map the drive letter at DS:SI. We need to un-map it at the end. +; +DoTranslate: + mov bx,SI ; point to area + cmp byte ptr [bx+1],':' ; drive letter present? + jnz DNJ3 ; nope, ignore this +; +; There is a drive leter present. Grab it and convert it +; + mov al,[bx] ; get drive letter + call EnterAssign + + mov drive_save,al ; remember previous contents + call maplet ; convert to real drive letter + + mov [bx],al ; place in new drive letter + mov drive_address,bx + RestoreReg ; get back original registers + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI + + call system ; flags saved => this is a system call + + pushf + call RestInt + + SaveReg + mov bx,drive_address + mov al,drive_save + mov [bx],al + RestoreReg + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign + + iret ; back to user + +page +;************************************************************************************ +; +; Munge the user's ASCIZ string at DS:DX and es:di +; +DoRename: + mov bx,dx ; point to area + mov ax,[bx] + call EnterAssign + + mov drive_save,al + mov drive_address,bx + cmp ah,':' ; drive letter present? +; $IF Z ;AC000; + JNZ $$IF17 + + call maplet ; convert to real drive letter + + mov [bx],al ; place in new drive letter +; $ENDIF ;AC000; +$$IF17: + ;DoES: + mov ax,es:[di] ;NS- Get the 2nd drive from the command linepSOP + mov drive_save2,al ;NS- Save possible drive + cmp ah,':' ;NS- exclude if no colon present +; $IF Z ;AC000; + JNZ $$IF19 + + call maplet ;NS- go convert letter to actual drive # + + mov es:[di],al ;NS- new drive value +; $ENDIF ;AC000; +$$IF19: + ;DoIt: + RestoreReg ; get back original registers + pop word ptr user_ret ; restore his IP + pop word ptr user_ret+2 ; restore his CS + call GotoCLI + + call system ; flags saved => this is a system call + + pushf + call RestInt + + SaveReg + mov al,drive_save2 ; NS- get the second drive update + mov es:[di],al ; NS- on the command line + mov bx,drive_address ; + mov al,drive_save ; + mov [bx],al ; + RestoreReg ; + push word ptr user_ret+2 ; push back user's cs + push word ptr user_ret ; push back user's ip + Call LeaveAssign + + iret ; back to user + +;************************************************************************************ +; +; DoGetDefault - return our idea of the current drive... +; +DoGetDefault: + call Assign_Check + +; $IF Z ;AC000; + JNZ $$IF21 + ;DNJ4: + jmp DoNothing + +; $ENDIF ;AC000; +$$IF21: + RestoreReg + mov al,default_drive + dec al + iret + +page +;************************************************************************************ +; +; DoSetDefault - try to set to the mapped current drive. If we can do it, +; then OK, else oops! +; +DoSetDefault: + RestoreReg + mov al,dl ; get new drive + inc al ; convert it to 1-based + call EnterAssign + + mov drive_save,al ; remember what we're doing + call mapdrv1 ; convert drive + + dec al ; convert back to 0-based + mov dl,al ; stick back in correct register + mov drive_save2,al ; remember more of what we're doing + MyInt21 ; try the set + + push ax ; save return info from set + mov ah,Get_Default_Drive ;(29h) + MyInt21 + + mov dl,drive_save + dec dl ; Restore users original value + cmp al,drive_save2 ; Did the set work? +; $IF Z ;AC000;;YES! + JNZ $$IF23 + + mov al,drive_save + mov default_drive,al ; Set ours too, it's valid! +; $ENDIF ;AC000; +$$IF23: + ;BadDrive: + pop ax ; Set return info + call LeaveAssign + + iret + +;************************************************************************************ +; +; Maintain the CLI state upon the next IRET. Flags for the IRET are on the +; stack just under the return address. This means saving the current state +; of the int flag and then turning off the saved version. +; +GotoCLI: + push ax + push bp + mov bp,sp +; bp ax ret f + mov ax,[bp + 2 + 2 + 2] + and SaveIntf,ax ; save those interrupts + and word ptr [bp + 2 + 2 + 2],not f_interrupt + pop bp + pop ax + ret +; +;************************************************************************************ +; Restore he saved interrupt flag for the user. His flags are on the stack +; just above the RET. +; +RestInt: + push ax + push bp + mov bp,sp + mov ax,SaveIntf +; bp ax ret f + or [bp + 2 + 2 + 2],ax + pop bp + pop ax + ret + +;************************************************************************************ +mapdrv0: ;a = 0 , b = 1 + inc al +; $IF NZ ;AC000; + JZ $$IF25 + + call mapdrv1 + +; $ENDIF ;AC000; +$$IF25: + ;Wrap0: + dec al + ret + +;************************************************************************************ +mapdrv1: + cmp al,26 +; $IF NA ;AC000; + JA $$IF27 + + cmp al,0 ; check for default +; $IF Z ;AC000; + JNZ $$IF28 + + mov al,default_drive + mov drive_save,al +; $ENDIF ;AC000; +$$IF28: + + push bx ;a = 1, b = 2 + push cx + mov ch,ah + cbw + mov bx,offset drives-1 + add bx,ax + mov al,cs:[bx] + mov ah,ch + pop cx + pop bx +; $ENDIF ;AC000; +$$IF27: + ret + +;************************************************************************************ +maplet: + cmp al,'A' + jb LetDone + + cmp al,'Z' + jbe DoMapLet + + cmp al,'a' + jb LetDone + + cmp al,'z' + ja LetDone + +DoMapLet: + or al,20h + sub al,"a"-1 + call mapdrv1 + + add al,40h +LetDone: + ret + +page +;************************************************************************************ +int25: + call mapdrv0 + + jmp int25_vec + +int26: + call mapdrv0 + + jmp int26_vec + +int2F: + CMP AH,mplex_id ;(06h) is this our multiplex? +; $IF NE ;AC000;;NO + JE $$IF31 + + jmp int2F_vec ; No, Chain to next guy + +; $ENDIF ;AC000; +$$IF31: + ;MINE: + CMP AL,mplex_get_seg ;(01h) + ;0 AND 1 ARE THE ONLY ALLOWED FUNCTIONS +; $IF NA ;AC000;;IF NOT SOME OTHER NUMBER, + JA $$IF33 +; $IF E ;AC000;;IF FUNCTION REQUEST IS 01 + JNE $$IF34 + ;RETURN THE SEGID IN ES + PUSH CS + POP ES ; Call 1 gets our segment in ES +; $ENDIF ;AC000; +$$IF34: + ;QUER: + MOV AL,MPLEX_INSTALLED ;(0FFh) I AM here +; $ENDIF +$$IF33: + ;RESERVED_RET: + IRET + +;************************************************************************************ +assign_check: + push si + push ax + push cx + xor ax,ax + mov si,ax + mov cx,26 +; $SEARCH ;AC000; +$$DO37: + ;scn: + mov al,drives[si] + INC SI + cmp ax,si +; $EXITIF NZ,NUL ;AC000; + JNZ $$SR37 + +; $ENDLOOP LOOP ;AC000; + LOOP $$DO37 + + xor ax,ax ; reset z flag +; $ENDSRCH ;AC000; +$$SR37: + ;scndone: + pop cx + pop ax + pop si + ret + +prog_size = ($-ASSIGN_BASE+15)/16 + +page +;************************************************************************************ +; TRANSIENT CODE +;************************************************************************************ +;********************************************* +;* * +;* Subroutine name: Initialization * +;* * +;* Purpose: Process the command line. * +;* If there are no errors update * +;* the drive table according to * +;* the drive assignments, terminate * +;* and stay resident. If status switch * +;* set and the drive values have been * +;* altered display drive is set to * +;* 2nd drive. * +;* * +;* Input: Command line (described in header) * +;* * +;* Output: Table will be updated and resident* +;* code will be hooked in. * +;* * +;* Normal Exit: Valid drives, sufficient * +;* memory. * +;* Error Conditions: * +;* Incorrect DOS Version * +;* Invalid Parameter * +;* Invalid switch * +;*Externals: * +;* PROCESS_PATH * +;* REPORT_STATUS * +;* EXIT_PROG * +;* * +;********************************************* +; ***************************************** +; * INITIALIZATION * +; ***************************************** +; * * +; * CALL SYSLOADMSG * +; * Do DOS Versinon Check * +; * CALL SYSDISPMSG * +; * IF <> X.X then * +; * Display message * +; * Message number 1 * +; * (001 - Incorrect DOS Version) * +; * exit * +; * .ENDIF * +; * Continue * +; * * +; * Establish address of the * +; * PDB environment * +; * (Process Data Block ) * +; * .IF NO SPACE free de-allocate (49)* +; * memory at the environment * +; * address * +; * .ENDIF * +; ***************************************** +;******************************************************************************* + + + BREAK + + EXTRN SYSPARSE:NEAR ;AN000; + +ODDX equ 01H ;AN000; +EVENX equ 00H ;AN000; +PAD_CHAR equ ' ' ;AN000; +SEMICOLON equ ';' ;AN000; +SPACE equ ' ' ;AN000; +EQUAL equ '=' ;AN000; +PLUS equ '+' ;AN000; +good_parse_finish equ 0ffffh ;an000; +;****************************************************************************** +STATUS_ONLY db 0 ;AN000; +STRING_CTR db 0 ;AN000; +STATUS_FLAG db 0 ;AN000; +ERR_CODE db 0 ;AN000; +POS_FLAG db 'n' ;AN000; +PARMS_AVAIL db 'n' ;AN000; +PAR_RETC dw 0 ;AN000; used for the return code +DRV_X db 0 ;AN000; from the parser +save_dr_tbl_ptr dw ? ;an000;drive table pointer +curr_es_seg dw ? +Parm_Ptr1 dw ? ;an002;ptr to parse parm +Parm_Ptr2 dw ? ;an002;ptr to parse parm + +inv dd ? +STring dd ? ;AN000;string holder + + +INCLUDE ASSGPARM.INC ;AN000; +INCLUDE ASSGMSG.INC ;AN000; + + +assume cs:code, ds:code, ss:code, es:code + +INITIALIZATION: + + push ax ;an000; save ax + mov ax,ds ;an000; get the current ds + mov SEG_1,ax ;an000; set sublist table + mov SEG_2,ax ;an000; set sublist table + pop ax ;an000; restore ax + + call SYSLOADMSG ;AN000; ;does DOS version check +; $IF C ;AN000; + JNC $$IF41 + ;remainder of info given + call SYSDISPMSG ;AN000; ;by the msg retriever + ;message and exit + + call EXIT_PROG ;AC000; ;(4CH) Terminate function + +; $ENDIF +$$IF41: + + +page +;************************************* CNS ************************************ +; ***************************************** +; * INITIALIZATION * +; ***************************************** +; * * +; * Make internal DOS function call (52h)* +; * to process the data block * +; * information after mem is available * +; ****************************************** +;************************************* CNS ************************************ + ;OKDOS: + mov ax,ds:[pdb_environ] ;get your Process Data Block Address + or ax,ax ;check to see if space available +; $IF NZ ;AC000; + JZ $$IF43 + ; jz nofree + push es ; save code segment value + mov es,ax ; de-allocate memory + mov ah,dealloc ;(49H) + int DOS_CALL + + pop es ;restore code segment value + +; $ENDIF ;ACx00; +$$IF43: + ;nofree: + + push es ;an000; save es + mov ah,Get_In_Vars ;(52H) + int DOS_CALL + + mov Word ptr inv,bx + mov Word ptr inv+2,es + pop es ;an000; restore es + +;****************************************************************************** +; +; ***************************************** +; * Establish addressability * +; * to command line parms (DS:SI) * +; * Establish addressability to PARM * +; * control block (ES:DI) * +; * * +; ***************************************** +;******************************************************************************* + ;parser es & ds now points at the command line + cld ;clear the directional flag + ;decrement mode - maintanis pointer without + ;advancement + + mov di,offset ASS_PARMS ;AC000; ;set index to the location of your PARAMETER + ;PARSER control block + mov si,81h ;AC000; ;set index to the beginning of the commandline + ;at 81h to the first 128 bytes +page +;****************************************************************************** +;* PROCESS PATH +;****************************************************************************** +;********************************************* +;* * +;* Subroutine : Process_path * +;* Function : Process command line. * +;* Repeat searching for drive * +;* spec. If valid update * +;* drive table. * +;* * +;* Normal exit: End of line * +;* Parse error * +;* * +;* Abort exit: Invalid drive * +;* * +;********************************************* +; ***************************************** +; * * +; * WHILE PAR_RETC eq NO_ERROR (0) * +; * CALL SYSPARSE * +; * Case: * +; * .IF (POSITIONAL) * +; * Result is positional & Ctr even * +; * INC CTR * +; * CHECK_STRING * +; * .IF the string is valid * +; * valid drive * +; * calculate table drv posit. * +; * based on the ascii value * +; * .ELSE * +; * * +; * PARSE ERROR * +; * .ENDIF * +; * Result is positional & CTR odd * +; * save the ascii_value * +; * Check the String * +; * .IF the string is valid * +; * valid drive * +; * update the drive table * +; * .ELSE * +; * * +; * PARSE ERROR * +; * .ENDIF * +; * .ENDIF * +; * INC CTR * +; ***************************************** + +;****************************************************************************** + xor cx,cx ;an000; set cx to 0 for parse + xor dx,dx ;an000; set dx to 0 for parse + + mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm + mov Parm_Ptr2,si ;an002; dms;ptr to 1st. parm + call SYSPARSE ;AN000; dms;priming parse + mov par_retc,ax ;AN000; dms;set flag + +; $DO +$$DO45: + CMP ax,no_error ;AN000;Is compare the return +; $LEAVE NE ;AN000;code 0 no error keep + JNE $$EN45 + ;AN000;parsing + call CHK_PARSER ;AN000; + + mov Parm_Ptr2,si ;an002; dms;ptr to 1st. parm + call SYSPARSE ;AN000;go parse the command line + mov par_retc,ax ;AN000; dms;set flag + ;AN000;restore the parm return code + +; $ENDDO ;AN000; + JMP SHORT $$DO45 +$$EN45: + + cmp ax,good_parse_finish ;an000; dms;see if a parse error +; $if ne ;an000; dms;if a parse error + JE $$IF48 + push ax ;an002; dms save ax + mov ax,Parm_Ptr2 ;an002; dms;get original parm ptr + mov Parm_Ptr1,ax ;an002; dms;place in variable + pop ax ;an002; dms;restore ax + call PARSE_ERR ;an000; dms;display error & exit +; $endif ;an000; dms; +$$IF48: + + cmp PARMS_AVAIL,'y' ;AN000; +; $IF E ;AN000; If there are parms available + JNE $$IF50 + cmp ax,0 ;AN000; see if the return code was no error +; $IF G ;AN000; if greater than 0 + JNG $$IF51 + mov ax,parse10 + call PARSE_ERR ;AN000; you got a parser error + ;AN000; so report & exit +; $ENDIF ;AN000; you also get an error +$$IF51: + + xor ax,ax ;AN000; + mov al,String_ctr ;AN000; + mov bx,0002h + div bl ;AN000; + + cmp ah,EVENX +; $IF NE ;AN000; if the drives did not pair off + JE $$IF53 + mov ax,parse10 + call PARSE_ERR +; $ENDIF ;AN000; +$$IF53: + + cmp POS_FLAG,'n' ;AN000;has a drive been specified +; $IF E,AND ;AN000;and has a switch also been + JNE $$IF55 + cmp STATUS_FLAG,1 ;AN000;specified if so hook in code +; $IF E ;AN000;and then report status + JNE $$IF55 + mov STATUS_ONLY,1 ;AN000;set flag specifing user input full +; $ENDIF ;AN000;command line +$$IF55: + ;AN000; hook in the code +; $ENDIF ;AN000; +$$IF50: + +page + + cmp STATUS_ONLY,0 ;AN000; +; $IF E ;AN000; + JNE $$IF58 + + call Get_Vectors ;get current vectors ;an001; dms; + call Set_Vectors ;set new vectors ;an001; dms; + +; $ELSE ;AN000;END of HOOK-IN + JMP SHORT $$EN58 +$$IF58: + + call REPORT_STATUS ;AN000; + call EXIT_PROG ;AN000; + +; $ENDIF +$$EN58: +page +;*********************************** CNS *************************************** + RELOAD_CURDIR PROC NEAR + +;***************************************************************************** +; +; We have an interesting problem here. What if the user is assigning away +; his current drive? Here's the solution: +; +; o We get the current drive here. +; o We reload the mapping table. +; o We set the current drive. +; + MOV AH,Get_Default_Drive ;(19H) + INT DOS_CALL + + PUSH AX ; save away the table + + MOV AX,(MPLEX_ID SHL 8)+MPLEX_GET_SEG ;(0601H) Get the SEG of the installed ASSIGN + INT MULTIPLEXOR ;(2FH) in ES + + mov si,offset drives ;move in the new drive table + mov di,si + mov cx,26 ; move a-z + CLI + rep movsb ; + STI + + POP DX ; restore the old current drive + MOV AH,Set_Default_Drive ;(0EH) + INT DOS_CALL + + call EXIT_PROG ;go_home: + + INT PGM_TERM ;(20H) Exit SHOULD not return, but be safe + + ret + + RELOAD_CURDIR ENDP +;*********************************** CNS *************************************** +;Input: Parser control block +;Output: Result Parser control block +;Register usage: AX,BX,CX,DX,ES,DS,SI,DI +; +; +;*********************************** CNS *************************************** + + CHK_PARSER PROC NEAR + + xor cx,cx ;an000; clear out cx + xor ax,ax ;AN000; clear out ax + mov al,String_ctr ;AN000; grab current assign ctr + mov bx,0002h ;an000; set bx to 2 + div bl ;AN000; divide so we get rem. + cmp RES_TYPE,2 ;an000; check for 1st drive +; $IF E,AND ;AN000; drive letter? + JNE $$IF61 + cmp ah,EVENX ;AN000; and no remainder? +; $IF E ;AN000; + JNE $$IF61 + inc STRING_CTR ;AN000; increment counter + mov PARMS_AVAIL,'y' ;AN000; signal parms entered + push ax ;AN000; save ax + mov al,res_itag ;AN000; grab parm entered + mov drv_x,al ;AN000; save it for later use + call drvchk ;AC000; check for valid drive + cbw ;AC000; convert drive byte found to a word + mov bx,offset drives-1 ;AC000; get the drive table + add bx,ax ;AC000; get the drive address + mov save_dr_tbl_ptr,bx ;an000; save the drive table pointer + pop ax ;an000; restore ax +; $ENDIF ;AN000; +$$IF61: + + cmp RES_TYPE,2 ;AN000; check for 2nd drive +; $IF E,AND ;AN000; drive entered? + JNE $$IF63 + cmp ah,EVENX ;AN000; and not first? +; $IF NE ;AN000; + JE $$IF63 + inc STRING_CTR ;AN000; increment counter + mov PARMS_AVAIL,'y' ;AN000; signal parms entered + push ax ;AN000; save ax + mov al,res_itag ;AN000; grab parm entered + mov drv_x,al ;AN000; save it for later use + call drvchk ;AC000; if so see if it was valid + mov bx,save_dr_tbl_ptr ;an000; set bx to drive table + mov [bx],al ;AC000; if valid update the table + mov POS_FLAG,'y' ;AN000; yes you have valid positionals + pop ax ;an000; restore ax + mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm +; $ENDIF ;AN000; +$$IF63: + + cmp RES_SYN,0 ;AN000; See if a switch was specified +; $IF NE ;AN000; If so, + JE $$IF65 + mov STATUS_flag,1 ;AN000; set the status flag on + mov PARMS_AVAIL,'y' ;AN000; and report that a valid parameter + mov byte ptr SW_Syn1,20h ;an000; remove switch from list + mov byte ptr SW_Syn2,20h ;an000; remove switch from list + mov Parm_Ptr1,si ;an002; dms;ptr to 1st. parm +; $ENDIF ;AN000; was on the command line +$$IF65: + + ret ;AN000; + + + CHK_PARSER ENDP + +page +;*********************************** CNS *************************************** +; +; check drive validity +; +drvchk: + + sub al,"A" ; NS- error checking +; $IF NB ;AN000; ;if alphabetic, + JB $$IF67 + + push es + push bx + push ax + + les bx,inv + cmp al,es:[bx].sysi_ncds ;AN000; ;NS- check in case current directory +; $IF NAE ;AN000; ;NS- has been altered + JAE $$IF68 + + + les bx,es:[bx].sysi_cds + push bx + mov bl,size curdir_list + mul bl + pop bx + add bx,ax + test es:[bx].curdir_flags,curdir_inuse +; $IF NZ ;AC000; + JZ $$IF69 + + pop ax + pop bx + pop es + inc al + + ret + +; $ENDIF ;AC000; curdir in use? +$$IF69: +; $ENDIF ;AC000; curdir been altered? +$$IF68: +; $ENDIF ;AC000; alphabetic? +$$IF67: + + mov ax,parse10 ;AN000; Invalid parameter + call PARSE_ERR ;an000; display the error & end + +;******************************* CNS ******************************************* +;Purpose: Print the mapping status of the drive table. +;Input : Drive table +;Registers affected: BX,CX,DX,AX +; +;Output : Display of all drive values stored not equal to their sequential +; storage address +; +;******************************* CNS ******************************************* +REPORT_STATUS PROC NEAR + + push es ;an000; save es + push es ;an000; swap es with + pop ax ;an000; ax + mov curr_es_seg,ax ;an000; save es in curr_es_seg + + mov ax,0601h ;an000; our int 2fh + int 2fh ;an000; returns segment of drive vector + assume es:nothing ;an000; tell the linker + + mov cl,01 ;AN000; ;initialize the counter + ;AN000; advance to next drive + mov bx,offset drives ;AN000; load drive table +; $DO +$$DO73: + cmp cl,26 ;AN000; see if we scanned all drives + +; $LEAVE A ;AN000; exit loop if we have + JA $$EN73 + + cmp cl,es:[bx] ;AN000; ;compare the table value + ;to the table contents +; $IF NE ;AN000; + JE $$IF75 + push bx ;an000; save bx - we stomp it + push cx ;an000; save cx - we stomp it + mov al,es:[bx] ;AN000; get the table contents to convert + push es ;an000; save es for print + mov bx,curr_es_seg ;an000; get the current segment + mov es,bx ;an000; get the segment into es + assume es:code ;an000; tell linker it is code + + add cl,40H ;AN000; convert to ascii representation + add al,40h ;an000; convert to ascii + mov OLD_DRV,cl ;AN000; place in parms for printing + mov NEW_DRV,al ;AN000; by message retriever + + mov ax,0002h ;an000; message #2 + mov bx,stdout ;an000; print to standard out + mov cx,0002h ;an000; two replaceable parms + mov si,offset sublist1 ;an000; offset of sublist + mov di,0000h ;an000; no buffer for user input + mov dl,no_input ;AN000; no user input to mes. ret. + mov dh,utility_msg_class ;an000; utility messages only + + call SYSDISPMSG ;AN000; ;go to message retriever + pop es ;an000; restore es + assume es:nothing ;an000; tell the linker + pop cx ;an000; restore cx + pop bx ;an000; restore bx + +; $ENDIF ;AN000; +$$IF75: + + inc bx ;an000; next drive in vector + inc cl ;AN000; next letter to address + +; $ENDDO ;AN000; + JMP SHORT $$DO73 +$$EN73: + pop es ;an000; restore es + assume es:code ;an000; tell the linker + + ret ;AN000; + +REPORT_STATUS ENDP +page +;******************************* CNS ******************************************* +; Purpose: Exit program +; Input : Error code AL +; Output : Error code AL +; +;******************************* CNS ******************************************* +EXIT_PROG PROC NEAR + + + + mov ah,EXIT ;AC000;(4ch) RETURN TO DOS WITH ERRORLEVEL + int DOS_CALL ;AC000; + + + ret ;AC000; + +EXIT_PROG ENDP +;******************************* CNS ******************************************* + +;========================================================================= +; PARSE_ERR : This routine prints out the applicable parse +; error that is returned in AX by SYSPARSE. +; +; Inputs : AX - Parse error number to be printed +; Outputs : Applicable parse error +;========================================================================= + + +PARSE_ERR proc near ;an000; dms;report an error + + push ax ;an000;save ax + mov byte ptr ds:[si],0 ;an002;null terminate string + mov dx,Parm_Ptr1 ;an002;move ptr to sublist + mov Parse_Sub_Off,dx ;an002; + mov Parse_Sub_Seg,ds ;an002; + + mov bx,STDERR ;an000;print to standard out + mov cx,1 ;an002;1 replaceable parm + mov si,offset Parse_Sublist ;an002;sublist for replaceable parm + mov dl,NO_INPUT ;AN000;no input to message retriever + mov dh,PARSE_ERR_CLASS ;AN000;display parse errors + call SYSDISPMSG ;AN000;display error + + pop ax ;AN000;restore errcode + call EXIT_PROG ;AN000;exit ASSIGN due to error + + +PARSE_ERR endp ;an000; dms; + +Release_Environment proc near ;an001; dms; + + push ax ;save regs ;an001; dms; + push bx ; ;an001; dms; + push es ; ;an001; dms; + mov ah,Get_PSP ; get the PSP segment ;an001; dms; + int 21h ; invoke INT 21h ;an001; dms; + mov es,bx ; BX contains PSP segment - put in ES ;an001; dms; + mov bx,word ptr es:[PSP_Env]; get segment of environmental vector ;an001; dms; + mov es,bx ; place segment in ES for Free Memory ;an001; dms; + mov ah,Dealloc ; Free Allocated Memory ;an001; dms; + int 21h ; invoke INT 21h ;an001; dms; + pop es ; restore regs ;an001; dms; + pop bx ; ;an001; dms; + pop ax ; ;an001; dms; + + ret ; return to caller ;an001; dms; + +Release_Environment endp + +Close_Handles proc near ;close handles 0-4 ;an001; dms; + + push bx ;save regs ;an001; dms; + mov bx,4 ;close all standard files ;an001; dms; + +Close_Handle_Loop: + + mov ah,Handle_Close ;close file handle ;an001; dms; + int 21h ; ;an001; dms; + dec bx ;next handle ;an001; dms; + jns Close_Handle_Loop ;continue ;an001; dms; + + pop bx ;restore regs ;an001; dms; + ret ; ;an001; dms; + +Close_Handles endp ; ;an001; dms; + +Get_Vectors proc near ;get original vectors ;an001; dms; + + mov ax,(GET_INTERRUPT_VECTOR SHL 8)+ABS_DISK_READ ;(3525h) get the int 25 vector + int DOS_CALL + + mov word ptr [int25_vec],bx + mov word ptr [int25_vec+2],es + + mov ax,(GET_INTERRUPT_VECTOR SHL 8)+ABS_DISK_WRITE ;(3526H) get the int 26 vector + int DOS_CALL + + mov word ptr [int26_vec],bx + mov word ptr [int26_vec+2],es + + mov ax,(GET_INTERRUPT_VECTOR SHL 8)+MULTIPLEXOR ;(352FH) get the int 2F vector + int DOS_CALL + + mov word ptr [int2F_vec],bx + mov word ptr [int2F_vec+2],es + + mov ax,(Get_Interrupt_Vector SHL 8)+DOS_CALL ;(3521H) + int DOS_CALL + + mov word ptr cs:[system],bx + mov word ptr cs:[system+2],es + + MOV AX,(MPLEX_ID SHL 8)+MPLEX_R_U_THERE ;(0600H) See if we are in system already + INT MULTIPLEXOR ;(2FH) + + OR AL,AL +; $IF NZ ;AC000; NOT INSTALLED + JZ $$IF78 + + call RELOAD_CURDIR ;AC000; + +; $ENDIF +$$IF78: + + ret ; ;an001; dms; + +Get_Vectors endp ; ;an001; dms; + + +Set_Vectors proc near ;set to new vectors ;an001; dms; + + mov ah,Get_Default_Drive ;(19H) + int DOS_CALL + + inc al + mov [default_drive],al ;NS- add one to the value to get the + call mapdrv1 ;NS- actual drive value before mapping + + dec al ;NS- dec one to setup for select function + mov dl,al ;select its replacement + mov ah,Set_Default_Drive ;(0EH) + int DOS_CALL + ;NS- Set up hooks + mov dx,offset int25 ;set int 25 vector + mov ax,(SET_INTERRUPT_VECTOR SHL 8) + ABS_DISK_READ ;(2525H) + int DOS_CALL + ;NS- setup new seg + mov dx,offset int26 ;set int 26 vector + mov ax,(SET_INTERRUPT_VECTOR SHL 8) + ABS_DISK_WRITE ;(2526H) + int DOS_CALL + ;NS- Hook in resident portion + mov dx,offset int2F ;set int 2F vector + mov ax,(SET_INTERRUPT_VECTOR SHL 8) + MULTIPLEXOR ;(252FH) + int DOS_CALL + + mov dx,offset ASSIGN_HANDLER ;set the system int vector + mov ax,(SET_INTERRUPT_VECTOR SHL 8) + DOS_CALL ;(2521H) + int DOS_CALL + + call Close_Handles ;close handles 0-4 ;an001; dms; + call Release_Environment ;release the environmental vector ;an001; dms; + + mov dx,prog_size ;end but stay resident + mov ah,KEEP_PROCESS ;(31h) NS- ASSIGN loaded in mem + int DOS_CALL + + ret ; ;an001; dms; + +Set_Vectors endp ; ;an001; dms; + + + +.xlist +MSG_SERVICES +msg_services +msg_services +msg_services +msg_services +msg_services +.list + +include msgdcl.inc + +code ends + end ENTRY_POINT + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGMSG.INC b/v4.0/src/CMD/ASSIGN/ASSGMSG.INC new file mode 100644 index 0000000..65b7d72 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGMSG.INC @@ -0,0 +1,74 @@ +BADDOS equ 1 +STAT equ 2 +PARSE01 equ 01 +PARSE02 equ 02 +PARSE03 equ 03 +PARSE04 equ 04 +PARSE05 equ 05 +PARSE06 equ 06 +PARSE07 equ 07 +PARSE08 equ 08 +PARSE09 equ 09 +PARSE10 equ 10 + +OLD_DRV db 0,0 +NEW_DRV db 0,0 + +FLAG1 equ LEFT_ALIGN+CHAR_FIELD_ASCIIZ + +;****************************************************************************** +; VALUES FOR THE MSG_DESC CONTROL BLOCK +ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE +TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE +THREE_SUBS EQU 3 ;THREE VARIABLE FIELDS IN MESSAGE +CLASS_1 EQU EXT_ERR_CLASS ;CLASS 1 (DOS EXTENDED ERRORS) +CLASS_2 EQU PARSE_ERR_CLASS ;CLASS 2 (PARSE ERRORS) +CLASS_A EQU UTILITY_MSG_CLASS ;CLASS A TYPE MESSAGE + +;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, +;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN +;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. + +MSG_DESC STRUC +MSG_NUM DW 0 ;MESSAGE NUMBER (TO AX) +MSG_HAND DW 0 ;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW 0 ;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW 0 ;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DB 0 ;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) +MSG_DESC ENDS +; VALUES FOR THE SUBLIST CONTROL BLOCK +PC_ID_0 EQU 0 ;ID OF " - " TRAILER TO MESSAGE +PC_ID_1 EQU 1 ;ID OF PERCENT VARIABLE FIELD +PC_ID_2 EQU 2 ;ID OF PERCENT VARIABLE FIELD +PC_ID_3 EQU 3 ;ID OF PERCENT VARIABLE FIELD +MAX_0 EQU 0 ;MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT) +MIN_1 EQU 1 ;MINIMUM WIDTH OF STRING FIELD +;Message SUB-LIST + SUBLIST1 LABEL DWORD ;PARM LIST + ;(Original %1: set to %2:) + DB 11 ;PARMLIST size + DB 0 ;reserved + DW OLD_DRV ;; ptr to data +SEG_1 DW ? + DB 1 ;; n of %n + DB FLAG1 ;; data type + DB max_0 ;;max width + DB min_1 ;;min width + DB PAD_CHAR ;;char defined to be space + +DRV_LETS LABEL WORD +;Message SUB-LIST2 + SUBLIST2 LABEL DWORD ;PARM LIST + ;(File not found - 'PATH_SPEC') + DB 11 ;PARMLIST size + DB 0 ;reserved + DW NEW_DRV ;; ptr to data - offset +SEG_2 DW ? ;; ptr to data + DB 2 ;; n of %n + DB FLAG1 ;; data type + DB max_0 ;;max width + DB min_1 ;;min width + DB PAD_CHAR ;;char defined to be space + + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM b/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM new file mode 100644 index 0000000..74067bf --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGPARM.ASM @@ -0,0 +1,141 @@ + + PAGE ,132 ; + TITLE ASSPARM.SAL - ASSIGN SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: ASSGPARM.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of ASSIGN. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .EXE. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.SAL statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.SAL statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the ASMUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT ASSPARM,NUL; +; +; To assemble these modules, the sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; ASSIGN.SAL +; +; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, +; +; COPYRIGHT: "Microsoft DOS ASSIGN Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft Corp" +; "Licensed Material - Program Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=ASSIGN, MODULE=ASSPARM.SAL... + ENDIF +; = = = = = = = = = = = = + HEADER +; = = = = = = = = = = = = + +HEADER MACRO TEXT +.XLIST + SUBTTL TEXT +.LIST + PAGE + ENDM + +; = = = = = = = = = = = = + HEADER ; ;AN000; +CODE SEGMENT PARA PUBLIC ; ;AN000; + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE ; ;AN000; + + PUBLIC SYSPARSE ;SUBROUTINE ENTRY POINT ;AN000; + +CAPSW EQU 1 ;SUPPORT FILENAME TBL CAPS +FARSW EQU 0 ;PARSER CALL NEAR +FILESW EQU 0 ;CHECK FOR FILESPEC +DATESW EQU 0 ;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;SUPPRESS TIME CHECKING +CMPXSW EQU 0 ;SUPPRESS CHECKING COMPLEX LIST +NUMSW EQU 0 ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 1 ;SUPPORT OF VALUE DEFINITION 3 +DRVSW EQU 0 ;SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT + + IF1 ; ;AN000; + %OUT COMPONENT=ASSIGN, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM... + %OUT COMPONENT=ASSIGN, SUBCOMPONENT=PARSE, MODULE=PSDATA.INC... + ENDIF ; ;AN000; + + ;PARSE WORK AREA & EQUATES + +.xlist + INCLUDE PARSE.ASM +.list + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/ASSGPARM.INC b/v4.0/src/CMD/ASSIGN/ASSGPARM.INC new file mode 100644 index 0000000..933d3cb --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSGPARM.INC @@ -0,0 +1,242 @@ + + ASS_PARMS label dword + dw ASS_PARMSX + db 1 ;list of extra delimiters + db 3 ;0 length + db ";+=" + + ASS_PARMSX label byte + db 0,1 + +;Min 0 - no drive or switch specified +;Max 1 - maximal allowance of drive letters +;repeats + + dw ASS_POS1 ;positional ctl ptr + db 1 ;# of switches + dw ASS_SW1 ;switch ptr + + ASS_POS1 label word + dw 2010h ;Simple string, + ;ignore colon, & + ;repeat + ;allowed + dw 0002h ;Cap result by + ; character table + dw Result_Val ;tbl + dw Res_CTLVAL ;value list + db 0 ;no switch or + ;keyword synonyms + db 0 ;alternative keyword + + ASS_SW1 label word + dw 0 ;20010h ;Simple string, + ;ignore colon & repeat + ;allowed + dw 0002h ;Cap result by + ;character table + dw Result_Valsw ;tbl + dw 0 ; ;value list + db 2 ;switch or + ;keyword synonyms + SW_Syn1 db "/STATUS",0 ;alternate keyword + SW_Syn2 db "/STA",0 ;alternate keyword + + + Res_CTLVAL label word + db 3 ;List of simple strings + db 0 ;not in range defn. + db 0 ;not in numeric defn. + db 26 ;# of strings defined + db "A" ;item tag + ;value returned + dw DRVA_PTR ;string ptr + db "B" ;item tag + ;value returned + dw DRVB_PTR ;string ptr + db "C" ;item tag + ;value returned + dw DRVC_PTR ;string ptr + db "D" ;item tag + ;value returned + dw DRVD_PTR ;string ptr + db "E" ;item tag + ;value returned + dw DRVE_PTR ;string ptr + db "F" ;item tag + ;value returned + dw DRVF_PTR ;string ptr + db "G" ;item tag + ;value returned + dw DRVG_PTR ;string ptr + db "H" ;item tag + ;value returned + dw DRVH_PTR ;string ptr + db "I" ;item tag + ;value returned + dw DRVI_PTR ;string ptr + db "J" ;item tag + ;value returned + dw DRVJ_PTR ;string ptr + db "K" ;item tag + ;value returned + dw DRVK_PTR ;string ptr + db "L" ;item tag + ;value returned + dw DRVL_PTR ;string ptr + db "M" ;item tag + ;value returned + dw DRVM_PTR ;string ptr + db "N" ;item tag + ;value returned + dw DRVN_PTR ;string ptr + db "O" ;item tag + ;value returned + dw DRVO_PTR ;string ptr + db "P" ;item tag + ;value returned + dw DRVP_PTR ;string ptr + db "Q" ;item tag + ;value returned + dw DRVQ_PTR ;string ptr + db "R" ;item tag + ;value returned + dw DRVR_PTR ;string ptr + db "S" ;item tag + ;value returned + dw DRVS_PTR ;string ptr + db "T" ;item tag + ;value returned + dw DRVT_PTR ;string ptr + db "U" ;item tag + ;value returned + dw DRVU_PTR ;string ptr + db "V" ;item tag + ;value returned + dw DRVV_PTR ;string ptr + db "W" ;item tag + ;value returned + dw DRVW_PTR ;string ptr + db "X" ;item tag + ;value returned + dw DRVX_PTR ;string ptr + db "Y" ;item tag + ;value returned + dw DRVY_PTR ;string ptr + db "Z" ;item tag + ;value returned + dw DRVZ_PTR ;string ptr + + DRVA_PTR LABEL word + db "A",0 + + DRVB_PTR LABEL word + db "B",0 + + DRVC_PTR LABEL word + db "C",0 + + DRVD_PTR LABEL word + db "D",0 + + DRVE_PTR LABEL word + db "E",0 + + DRVF_PTR LABEL word + db "F",0 + + DRVG_PTR LABEL word + db "G",0 + + DRVH_PTR LABEL word + db "H",0 + + DRVI_PTR LABEL word + db "I",0 + + DRVJ_PTR LABEL word + db "J",0 + + DRVK_PTR LABEL word + db "K",0 + + DRVL_PTR LABEL word + db "L",0 + + DRVM_PTR LABEL word + db "M",0 + + DRVN_PTR LABEL word + db "N",0 + + DRVO_PTR LABEL word + db "O",0 + + DRVP_PTR LABEL word + db "P",0 + + DRVQ_PTR LABEL word + db "Q",0 + + DRVR_PTR LABEL word + db "R",0 + + DRVS_PTR LABEL word + db "S",0 + + DRVT_PTR LABEL word + db "T",0 + + DRVU_PTR LABEL word + db "U",0 + + DRVV_PTR LABEL word + db "V",0 + + DRVW_PTR LABEL word + db "W",0 + + DRVX_PTR LABEL word + db "X",0 + + DRVY_PTR LABEL word + db "Y",0 + + DRVZ_PTR LABEL word + db "Z",0 + + RESULT_VAL label word + RESULT_VALSW label word + + RES_TYPE db 0 ;Result_type + RES_ITAG db 0 ;Matched + ;item tag + RES_SYN dw 0 ;synonym + ;returned + RES_SOFF dw 0 ;drive type + ;or beginning + ;of string + ;may be string + RES_SEG dw 0 ;string offset + ;if type specified + + +;========================================================================= +; Sublist Definition Area +;========================================================================= + +Parse_Sublist label word + + db Sublist_Length ;sublist length ;an002; dms; + db Reserved ;reserved for future growth ;an002; dms; +Parse_Sub_Off dw ? ;offset of replaceable parm ;an002; dms; +Parse_Sub_Seg dw ? ;segment of replaceable parm ;an002; dms; + db 0 ;replaceable parm 0 ;an002; dms; + db Left_Align+Char_Field_ASCIIZ ; ;an002; dms; + db 40 ;max width ;an002; dms; + db 1 ;min width ;an002; dms; + db 20h ;blank fill ;an002; dms; + + + + diff --git a/v4.0/src/CMD/ASSIGN/ASSIGN.SKL b/v4.0/src/CMD/ASSIGN/ASSIGN.SKL new file mode 100644 index 0000000..5233c46 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/ASSIGN.SKL @@ -0,0 +1,9 @@ +:util ASSIGN +:class 2 ;parse errors: + +:class A ;"Original %1: set to %2:" +:use 1 COMMON1 ;MSG 1 is always + ;"Incorrect DOS version" +:def 2 "Original %1: set to %2:",cr,lf +:end + \ No newline at end of file diff --git a/v4.0/src/CMD/ASSIGN/MAKEFILE b/v4.0/src/CMD/ASSIGN/MAKEFILE new file mode 100644 index 0000000..1974c33 --- /dev/null +++ b/v4.0/src/CMD/ASSIGN/MAKEFILE @@ -0,0 +1,43 @@ +#************************** makefile for cmd\assign *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: assign.com + +assign.ctl: assign.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +assgparm.obj: assgparm.asm \ + $(inc)\psdata.inc \ + $(inc)\parse.asm \ + makefile + +assgmain.obj: assgmain.asm \ + $(inc)\dosmac.inc \ + $(inc)\sysvar.inc \ + $(inc)\mult.inc \ + $(inc)\pdb.inc \ + $(inc)\syscall.inc \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc \ + assgparm.inc \ + assgmsg.inc \ + assign.ctl \ + assign.cla \ + assign.cl1 \ + assign.cl2 \ + $(inc)\curdir.inc \ + makefile + +assign.com: assgmain.obj assgparm.obj + link assgmain.obj+assgparm.obj,assign,,; + exe2bin assign.exe assign.com + del assign.exe diff --git a/v4.0/src/CMD/ATTRIB/ATTRIB.C b/v4.0/src/CMD/ATTRIB/ATTRIB.C new file mode 100644 index 0000000..b12a470 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIB.C @@ -0,0 +1,2685 @@ +/* 0 */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Utility Name: ATTRIB.EXE */ +/* */ +/* Source File Name: ATTRIB.C */ +/* */ +/* Utility Function: */ +/* */ +/* Allows you to set or reset the Archive bit, the Read-Only bit and */ +/* the Extended Attributes. Also allows you to display the current */ +/* setting of those attributes. */ +/* */ +/* Status: ATTRIB Utility, DOS Version 4.0 */ +/* */ +/* Entry Point: inmain(line) */ +/* */ +/* Input: line = DOS command line parameters */ +/* */ +/* Exit-normal: attribute set, or attribute printed to output device */ +/* */ +/* Exit-error: error message written to standard error device */ +/* */ +/* Internal References: */ +/* */ +/* Routines: */ +/* */ +/* External References: */ +/* */ +/* Routines: */ +/* parse() module=_parse.sal */ +/* sysloadmsg() module=_msgret.sal */ +/* sysdispmsg() module=_msgret.sal */ +/* getpspbyte() module=new_c.sal */ +/* putpspbyte() module=new_c.sal */ +/* segread() module=dos.h(C library) */ +/* intdosx() module=dos.h(C library) */ +/* intdos() module=dos.h(C library) */ +/* */ +/* Notes: */ +/* Syntax (Command Line) */ +/* */ +/* ATTRIB [+R|-R] [+A|-A] [d:][path]filename[.ext] [[id]|[id=value]] [/S] */ +/* */ +/* where: */ +/* */ +/* +R = Make file ReadOnly by setting READONLY bit */ +/* -R = Reset READONLY bit */ +/* +A = Set ARCHIVE bit */ +/* -A = Reset ARCHIVE bit */ +/* */ +/* id = Set or display the extended attribute named by id. */ +/* Only one id processed per invocation. id can be *. */ +/* */ +/* /S = Process subdirectories also */ +/* */ +/* Copyright 1988 Microsoft Corporation */ +/* */ +/* Revision History: */ +/* */ +/* Modified 6/22/87 v. 4.0 */ +/* Rewritten 9/28/87 v. 4.0 - AN000 */ +/* - fixed check for "." & ".." - AN001 */ +/* PTM 3195 - changed Extended attribute MSGs - AN002 */ +/* PTM 3588 - Do C exit not DOS exit. - AN003 */ +/* PTM 3783 - Fix for hang problem. - AN004 */ +/* */ +/* NOTE: */ +/* When extended attributes are added back in, make sure you change the */ +/* attrib.skl file back to the original DOS 4.0 ext. attr. error msgs. */ +/* */ +/* Also, this C program requires a special lib when linking to take care */ +/* of the fact that the c lib saves the DOS environment on the heap and */ +/* if the environment is > 32k, STACK OVERFLOW will occur. */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +#include /*;AN000;*/ +#include /*;AN000;*/ +#include /*;AN000;*/ +#include /*;AN000;*/ +#include "parse.h" /*;AN000;*/ +#include "msgret.h" /*;AN000;*/ +#include "attrib.h" /*;AN000;*/ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* Beginning of code (variables declared in attrib.h) */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +/* + * inmain() - This routine receives control from an assembler routine and from + * here, main is called. This routine first parses the command line + * and then does the appropriate action. + */ +inmain(line) /*;AN000;*/ + char *line; /*;AN000;*/ +{ /*;AN000;*/ + main(line); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: main() */ +/* */ +/* Subroutine Function: */ +/* Parse the command line, makes a full path-filename, does the */ +/* appropriate function */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +main(line) /*;AN000;*/ + char *line; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + + WORD Parse_it(); /* forward declaration */ /*;AN000;*/ + WORD Make_fspec(); /* " " */ /*;AN000;*/ + WORD Do_dir(); /* " " */ /*;AN000;*/ + void Error_exit(); /* " " */ /*;AN000;*/ + void Parse_err(); /* " " */ /*;AN000;*/ + + /* initialize control variables */ + status = NOERROR; /*;AN000;*/ + descending = FALSE; /*;AN000;*/ + set_reg_attr = FALSE; /*;AN000;*/ + pmask = mmask = 0x0; /*;AN000;*/ + ext_attr[0] = BLANK; /*;AN000;*/ + file[0] = '\0'; /*;AN000;*/ + error_file_name[0] = '\0'; /*;AN000;*/ + + /* load messages */ + sysloadmsg(&inregs,&outregs); /*;AN000;*/ + if (outregs.x.cflag & CARRY) { /*;AN000;*/ + sysdispmsg(&outregs,&outregs); /*;AN000;*/ + Dexit(11); /*;AN000;*/ + } + + Check_appendx(); /* check APPEND /X status */ /*;AN000;*/ + Get_DBCS_vector(); /* get double byte table */ /*;AN000;*/ + + /* parse command line */ + status = Parse_it(line); /*;AN000;*/ + if (status != NOERROR) { /*;AN000;*/ + Parse_err(status); /*;AN000;*/ + } /*;AN000;*/ + + /* Do extended attribute translations here */ + Ext_translation(); /*;AN000;*/ + + + /* Initialize any variables need for next phase of program */ + segread(&segregs); /* init segment registers for DOS calls */ /*;AN000;*/ + + /* make full filespec (drive + full path + filename) */ + strcpy(error_file_name,fspec); /*;AN000;*/ + status = Make_fspec(fspec); /*;AN000;*/ + if (status == NOERROR) { /*;AN000;*/ + + /* now do the work! */ + did_attrib_ok = FALSE; /* needed if file not found and no */ /*;AN000;*/ + /* error detected in Attrib(). */ + status = Do_dir(fspec,file); /*;AN000;*/ + if (status == NOERROR && did_attrib_ok == FALSE) /*;AN000;*/ + status = FILENOTFOUND; /*;AN000;*/ + } /*;AN000;*/ + + /* determine if there was an error after attempt to do attrib function */ + /* NOTE: for ext. attr. calls, add 200 to the return code to get the */ + /* ---- error code for this switch. */ + switch(status) { /* Extended error codes */ /*;AN000;*/ + case 0: /*;AN000;*/ + break; /*;AN000;*/ + case 2: /* File not found */ /*;AN000;*/ + Error_exit(ERR_EXTENDED,2,ONEPARM); /*;AN000;*/ + break; /*;AN000;*/ + case 3: /* Path not found */ /*;AN000;*/ + Error_exit(ERR_EXTENDED,3,ONEPARM); /*;AN000;*/ + break; /*;AN000;*/ + case 5: /* Access Denied */ /*;AN000;*/ + Error_exit(ERR_EXTENDED,5,ONEPARM); /*;AN000;*/ + break; /*;AN000;*/ + case 15: /* Invalid drive specification */ /*;AN000;*/ + Error_exit(ERR_EXTENDED,15,ONEPARM); /*;AN000;*/ + break; /*;AN000;*/ + case 199: /* EA error: undetermined cause */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(199,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 201: /* EA error: name not found */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(201,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 202: /* EA error: no space to hold name or value */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(202,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 203: /* EA error: name can't be set on this function */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(204,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 204: /* EA error: name can't be set */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(204,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 205: /* EA error: name known to this FS but not supported */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(205,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 206: /* EA error: EA definition bad (type, length, etc.) */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(206,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case 208: /* EA error: EA value not supported */ /*;AN000;*/ + strcpy(error_file_name,ext_attr); /*;AN000;*/ + Error_exit(ERR_EXTENDED,87,ONEPARM); /*;AN000;*/ + /* Display_msg(208,STDERR,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + default: /* Access Denied */ /*;AN000;*/ + Error_exit(ERR_EXTENDED,5,ONEPARM); /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + Reset_appendx(); /*;AN000;*/ + + + +} /* end of inmain */ /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Display_msg */ +/* */ +/* Subroutine Function: */ +/* Display the requested message to a given output device */ +/* */ +/* Input: */ +/* (1) Number of the message to be displayed (see ATTRIB.SKL) */ +/* (2) Output device handle */ +/* (3) Number of substitution parameters (%1,%2) */ +/* (4) Offset of sublist control block */ +/* (5) Message Class, 0=no input, 1=input via INT 21 AH=1 */ +/* */ +/* Output: */ +/* The message is written to the given output device. If input */ +/* was requested, the character code of the key pressed is returned */ +/* in outregs.x.ax. */ +/* */ +/* Normal exit: Message written to handle */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* Sysdispmsg (module _msgret.sal) */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Display_msg(msgnum,msghan,msgparms,msgsub,msginput) /*;AN000;*/ + int msgnum; /*;AN000;*/ + int msghan; /*;AN000;*/ + int msgparms; /*;AN000;*/ + int *msgsub; /*;AN000;*/ + char msginput; /*;AN000;*/ +{ + inregs.x.ax = msgnum; /*;AN000;*/ + inregs.x.bx = msghan; /*;AN000;*/ + inregs.x.cx = msgparms; /*;AN000;*/ + inregs.h.dh = utility_msg_class; /*;AN000;*/ + inregs.h.dl = msginput; /*;AN000;*/ + inregs.x.si = (WORD)msgsub; /*;AN000;*/ + sysdispmsg(&inregs,&outregs); /*;AN000;*/ + + /* check for error printing message */ + if (outregs.x.cflag & CARRY) { /*;AN000;*/ + outregs.x.bx = (WORD) STDERR; /*;AN000;*/ + outregs.x.si = NOSUBPTR; /*;AN000;*/ + outregs.x.cx = NOSUBCNT; /*;AN000;*/ + outregs.h.dl = exterr_msg_class; /*;AN000;*/ + sysdispmsg(&outregs,&outregs); /*;AN000;*/ + } /*;AN000;*/ +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Ext_translation() */ +/* */ +/* Subroutine Function: */ +/* This routine does all translation of extended attribute names to */ +/* the form that will be returned by Get_ext_attr_names(). For */ +/* example, "CODEPAGE" would be translated to "CP". */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Ext_translation() /*;AN000;*/ +{ /*;AN000;*/ + if (strcmp(ext_attr,"CODEPAGE") == 0) { /*;AN000;*/ + strcpy(ext_attr,"CP"); /*;AN000;*/ + } /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_far_str() */ +/* */ +/* Subroutine Function: */ +/* copies a filename from source to the target. The source is offset */ +/* from the code segment instead of the data segment. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Get_far_str(target,source,length) /*;AN000;*/ + char *target; /*;AN000;*/ + DWORD *source; /* segment = cs register */ /*;AN000;*/ + WORD length; /*;AN000;*/ +{ /*;AN000;*/ + char far *fptr; /*;AN000;*/ + WORD i; /*;AN000;*/ + + if (length == 0) { /*;AN000;*/ + + /* copy string in data segment */ + for (fptr = (char far *) *((DWORD *)source);(char)*fptr != NUL;) /*;AN000;*/ + *target++ = (char) *fptr++; /*;AN000;*/ + *target = *fptr; /*EOS character */ /*;AN000;*/ + } /*;AN000;*/ + else { + + /* copy string in data segment */ + for (fptr = (char far *) *((DWORD *)source),i=0;i < length;i++) /*;AN000;*/ + *target++ = (char) *fptr++; /*;AN000;*/ + *target = 0x0; /*EOS character */ /*;AN000;*/ + } + strcpy(fix_es_reg,NUL); /* fix for es reg. after using far ptr */ /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Dexit() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS terminate. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Dexit(s) /*;AN000;*/ + WORD s; /*;AN000;*/ +{ /*;AN000;*/ + Reset_appendx(); /* Reset APPEND /X status */ /*;AN000;*/ + +/* inregs.h.ah = (BYTE)0x4c; /*;AN003; ;AN000;*/ +/* inregs.h.al = (BYTE)s; /*;AN003; ;AN000;*/ +/* intdos(&inregs,&outregs); /*terminate*/ /*;AN003; ;AN000;*/ + + /* if it didn't work - kill it */ + exit(); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Dallocate() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS allocate of length (in paragraphs). */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD *Dallocate(s) /*;AN000;*/ + WORD s; /* length in bytes */ /*;AN000;*/ +{ /*;AN000;*/ + WORD length; /*length in paragraphs */ /*;AN000;*/ + + length = (s / 16 + 1); /*;AN000;*/ + inregs.x.bx = length; /*;AN000;*/ + inregs.x.ax = 0x4800; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + if (outregs.x.cflag & CARRY) { /*;AN000;*/ + Error_exit(ERR_EXTENDED,8,NOSUBCNT); /*;AN000;*/ + } /*;AN000;*/ + return((WORD *)outregs.x.ax); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Dfree() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS de-allocate. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Dfree(segment) /*;AN000;*/ + WORD segment; /*;AN000;*/ +{ /*;AN000;*/ + segregs.es = segment; /*;AN000;*/ + inregs.x.ax = 0x4900; /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + if (outregs.x.cflag & CARRY) { /*;AN000;*/ + Error_exit(ERR_EXTENDED,8,NOSUBCNT); /*;AN000;*/ + } /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* fix for es reg. after using far ptr */ /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Copy_far_ptr() */ +/* */ +/* Subroutine Function: */ +/* Copies a far ptr declared in any form to a real far ptr variable. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: status = NOERROR */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Copy_far_ptr(p1_addr, p2_addr) /*;AN000;*/ + DWORD *p1_addr; /*;AN000;*/ + WORD *p2_addr; /*;AN000;*/ +{ /*;AN000;*/ + WORD *dptr, *tptr; /*;AN000;*/ + + dptr = (WORD *)p2_addr; /*;AN000;*/ + tptr = (WORD *)p1_addr; /*;AN000;*/ + + *tptr++ = *dptr++; /*;AN000;*/ + *tptr = *dptr; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* fix ES register */ /*;AN000;*/ +} /*;AN000;*/ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Parse_it() */ +/* */ +/* Subroutine Function: */ +/* Parses the command line and returns error status. */ +/* */ +/* Input: line */ +/* */ +/* Output: various control variables are set */ +/* */ +/* Normal exit: status = NOERROR */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Parse_it(line) /*;AN000;*/ + char *line; /*;AN000;*/ +{ /*;AN000;*/ + WORD i; /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD no_value; /*;AN000;*/ + WORD got_fn; /* got filename - required parameter */ /*;AN000;*/ + WORD pa, /*;AN000;*/ + ma, /*;AN000;*/ + pr, /*;AN000;*/ + mr; /*;AN000;*/ + char far *cptr; /*;AN000;*/ + char *ptr; /*;AN000;*/ + BYTE p_mask[4], /*;AN000;*/ + m_mask[4]; /*;AN000;*/ + char string[129]; /*;AN000;*/ + + /* do setup for parser */ + for (i=0; i<4; i++) { /*;AN000;*/ + p_mask[i] = m_mask[i] = 0; /*;AN000;*/ + } /*;AN000;*/ + do_reg_attr = TRUE; /*;AN000;*/ + do_ext_attr = FALSE; /*;AN000;*/ + set_reg_attr = FALSE; /*;AN000;*/ + set_ext_attr = FALSE; /*;AN000;*/ + no_value = TRUE; /* no value found for keyword */ /*;AN000;*/ + got_fn = FALSE; /* no filename yet */ /*;AN000;*/ + + inregs.x.si = (WORD)line; /* Make DS:SI point to source */ /*;AN000;*/ + inregs.x.cx = 0; /* Operand ordinal */ /*;AN000;*/ + inregs.x.di = (WORD)&p_p1; /* Address of parm list */ /*;AN000;*/ + status = p_no_error; /* Init no error condition */ /*;AN000;*/ + + /* loop until error or end_of_line */ + while (status == p_no_error) { /*;AN000;*/ + parse(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /* get error status */ /*;AN000;*/ + + /* check for errors, continue if none */ + if (status == p_no_error) { /*;AN000;*/ + + /* check if first positional */ + if (outregs.x.dx == (WORD)&pos1_buff) { /*;AN000;*/ + if (*(char *)pos1_buff.p_result_buff[0] == '+') { /*;AN000;*/ + p_mask[0] |= pos1_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + m_mask[0] |= pos1_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + set_reg_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if second positional */ + if (outregs.x.dx == (WORD)&pos2_buff) { /*;AN000;*/ + if (*(char *)pos2_buff.p_result_buff[0] == '+') { /*;AN000;*/ + p_mask[1] |= pos2_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + m_mask[1] |= pos2_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + set_reg_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if third positional */ + if (outregs.x.dx == (WORD)&pos3_buff) { /*;AN000;*/ + + /* copy filename from far string to data segment string */ + Get_far_str(fspec,pos3_buff.p_result_buff,0); /*;AN000;*/ + got_fn = TRUE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if fourth positional */ + if (outregs.x.dx == (WORD)&pos4_buff) { /*;AN000;*/ + if (*(char *)pos4_buff.p_result_buff[0] == '+') { /*;AN000;*/ + p_mask[2] |= pos4_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + m_mask[2] |= pos4_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + set_reg_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if fifth positional */ + if (outregs.x.dx == (WORD)&pos5_buff) { /*;AN000;*/ + if (*(char *)pos5_buff.p_result_buff[0] == '+') { /*;AN000;*/ + p_mask[3] |= pos5_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + m_mask[3] |= pos5_buff.p_item_tag; /*;AN000;*/ + } /*;AN000;*/ + set_reg_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if sixth positional */ + if (outregs.x.dx == (WORD)&pos6_buff) { /*;AN000;*/ + + /* copy attribute name from far string to data segment string */ + Get_far_str(ext_attr,pos6_buff.p_result_buff,0); /*;AN000;*/ + do_ext_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + } /*;AN000;*/ + + /* check if value of sixth positional */ + if (outregs.x.dx == (WORD)&pos6b_buff) { /*;AN000;*/ + + /* parse a value that is complex (in parenthesis). */ + if (pos6b_buff.p_type == p_complex) { /*;AN000;*/ + + /* Parse the complex and concatenate it together */ + inregs.x.cx = 0; /* reset ordinal count */ /*;AN000;*/ + status = p_no_error; /*;AN000;*/ + while (status != p_rc_eol) { /*;AN000;*/ + parse(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /* get error status */ /*;AN000;*/ + if (status != p_no_error) { /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + Get_far_str(string,pos6b_buff.p_result_buff,0); /*;AN000;*/ + strcat(ext_attr_value.ea_ascii,string); /*;AN000;*/ + inregs.x.si = outregs.x.si; /* update SI for parser */ /*;AN000;*/ + } /*;AN000;*/ + status = p_no_error; /*;AN000;*/ + ext_attr_value_type = EAISASCII; /*;AN000;*/ + } /*;AN000;*/ + else /*;AN000;*/ + Determine_type((WORD)pos6b_buff.p_type,pos6b_buff.p_result_buff); /*;AN000;*/ + set_ext_attr = TRUE; /*;AN000;*/ + do_reg_attr = FALSE; /*;AN000;*/ + do_ext_attr = FALSE; /*;AN000;*/ + no_value = TRUE; /* found a value for keyword */ /*;AN000;*/ + } /*;AN000;*/ + + /* check for '/S' switch */ + if (outregs.x.dx == (WORD)&sw_buff) { /*;AN000;*/ + + /* check if duplicate switch */ + if (descending == TRUE) { /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + } /*;AN000;*/ + descending = TRUE; /*;AN000;*/ + } /*;AN000;*/ + } /* if no error */ /*;AN000;*/ + + /* error, check if this is first positional, if so try again */ + /* using the second positional beacause they are optional */ + else if (inregs.x.cx == 0 || inregs.x.cx == 1 || /*;AN000;*/ + inregs.x.cx == 3 || inregs.x.cx == 4) { /*;AN000;*/ + inregs.x.cx++; /* try next positional */ /*;AN000;*/ + + /* Check for a filename beginning with '+' because parser will drop */ + /* the plus sign anyways, and we need to flag it as an error */ + for(ptr=(char *)inregs.x.si; *ptr == ' '; ptr++) /*;AN000;*/ + /* NULL statement */ ; /*;AN000;*/ + if (*ptr == '+') /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + else /*;AN000;*/ + status = p_no_error; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + + continue; /* go back up to while loop */ /*;AN000;*/ + } /*;AN000;*/ + + /* Check for keyword (an attribute name - fourth positional) */ + else if (status == p_not_in_key) { /*;AN000;*/ + inregs.x.di = (WORD)&p_p2; /* change control blocks to */ /*;AN000;*/ + /* be able to parse the keyword */ + inregs.x.cx = 0; /* reset ordinal count */ /*;AN000;*/ + status = p_no_error; /*;AN000;*/ + no_value = FALSE; /* got keyword and equal sign */ /*;AN000;*/ + continue; /*;AN000;*/ + } /*;AN000;*/ + + if (status == p_no_error) { /*;AN000;*/ + inregs.x.cx = outregs.x.cx; /* update CX for parser */ /*;AN000;*/ + inregs.x.si = outregs.x.si; /* update SI for parser */ /*;AN000;*/ + } /*;AN000;*/ + } /* while loop */ /*;AN000;*/ + + /* check error status and if at end of line */ + if (status == p_rc_eol) { /*;AN000;*/ + status = p_no_error; /*;AN000;*/ + } /*;AN000;*/ + + /* Check for filename on command line */ + if (!got_fn && status == p_no_error) { /*;AN000;*/ + status = p_op_missing; /*;AN000;*/ + } /*;AN000;*/ + + /* Check for keyword and equal sign but no value */ + if (!no_value) { /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + } /*;AN000;*/ + + /* check for duplicate +R +R or +A +A or -A -A or -R -R */ + for (pr=0,mr=0,pa=0,ma=0,i=0; i<4; i++) { /*;AN000;*/ + if (p_mask[i] & READONLY) /*;AN000;*/ + pr++; /*;AN000;*/ + if (m_mask[i] & READONLY) /*;AN000;*/ + mr++; /*;AN000;*/ + if (p_mask[i] & ARCHIVE) /*;AN000;*/ + pa++; /*;AN000;*/ + if (m_mask[i] & ARCHIVE) /*;AN000;*/ + ma++; /*;AN000;*/ + } /*;AN000;*/ + if ((pr > 1) || (mr > 1) || (pa > 1) || (ma > 1)) { /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + for (pmask=0,mmask=0,i=0; i<4; i++) { /*;AN000;*/ + pmask |= p_mask[i]; /* combine masks */ /*;AN000;*/ + mmask |= m_mask[i]; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* check for duplicate -R +R or -A +A */ + if ((pmask & mmask & READONLY) || (pmask & mmask & ARCHIVE)) { /*;AN000;*/ + status = p_syntax; /*;AN000;*/ + } /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Determine_type() */ +/* */ +/* Subroutine Function: */ +/* Determines the type of the new value of an attribute being set by */ +/* the user in terms of extended attribute types. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Determine_type(parser_type,result_ptr) /*;AN000;*/ + WORD parser_type; /*;AN000;*/ + WORD *result_ptr; /*;AN000;*/ +{ /*;AN000;*/ + DWORD number; /*;AN000;*/ + char string[129]; /*;AN000;*/ + + switch(parser_type) { /*;AN000;*/ + case p_number: /*;AN000;*/ + ext_attr_value_type = EAISBINARY; /*;AN000;*/ + number = (DWORD)*(DWORD *)result_ptr; /*;AN000;*/ + if (number > 0xffff) { /*;AN000;*/ + ext_attr_value.ea_bin.length = 4; /*;AN000;*/ + ext_attr_value.ea_bin.dword = number; /*;AN000;*/ + } /*;AN000;*/ + else if (number > 0xff) { /*;AN000;*/ + ext_attr_value.ea_bin.length = 2; /*;AN000;*/ + ext_attr_value.ea_bin.dword = number; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + ext_attr_value.ea_bin.length = 1; /*;AN000;*/ + ext_attr_value.ea_bin.dword = number; /*;AN000;*/ + } /*;AN000;*/ + break; /*;AN000;*/ + + case p_complex: /*;AN000;*/ + + /* Taken care of in Parse_it() */ + break; /*;AN000;*/ + + case p_string: /*;AN000;*/ + case p_quoted_string: /*;AN000;*/ + Get_far_str(string,result_ptr,0); /*;AN000;*/ + + /* is the type EAISLOGICAL or EAISASCII */ + if (strcmp(string,"ON") == 0) { /*;AN000;*/ + ext_attr_value.ea_logical = TRUE; /*;AN000;*/ + ext_attr_value_type = EAISLOGICAL; /*;AN000;*/ + } /*;AN000;*/ + else if (strcmp(string,"OFF") == 0) { /*;AN000;*/ + ext_attr_value.ea_logical = FALSE; /*;AN000;*/ + ext_attr_value_type = EAISLOGICAL; /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + strcpy(ext_attr_value.ea_ascii,string); /*;AN000;*/ + ext_attr_value_type = EAISASCII; /*;AN000;*/ + } /*;AN000;*/ + break; /*;AN000;*/ + + default: /*;AN000;*/ + ext_attr_value_type = EAISUNDEF; /*;AN000;*/ + ext_attr_value.ea_undef = TRUE; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Make_fspec() */ +/* */ +/* Subroutine Function: */ +/* Makes a full path-filename from the filename & current directory */ +/* information. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Make_fspec(fspec) /*;AN000;*/ + char *fspec; /*;AN000;*/ +{ /*;AN000;*/ + WORD Check_DBCS(); /* forward declaration */ /*;AN000;*/ + + char path[256]; /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD i,j; /*;AN000;*/ + + status = NOERROR; /*;AN000;*/ + + strcpy(path,fspec); /*;AN000;*/ + + /* Check if user did not enter a drive letter */ + if (fspec[1] != ':') { /*;AN000;*/ + inregs.x.ax = 0x1900; /* Get current drive */ /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + fspec[0] = 'A' + (outregs.x.ax & 0xff); /*;AN000;*/ + fspec[1] = ':'; /*;AN000;*/ + fspec[2] = NUL; /*;AN000;*/ + strcat(fspec,path); /*;AN000;*/ + } /*;AN000;*/ + + /* Check if user didn't enter a path in filename */ + if (!Check_DBCS(fspec,2,'\\')) { /*;AN000;*/ + strcpy(path,&fspec[2]); /*;AN000;*/ + fspec[2] = '\\'; /*;AN000;*/ + inregs.x.ax = 0x4700; /* Get current directory */ /*;AN000;*/ + inregs.x.si = (WORD)(&fspec[3]); /*;AN000;*/ + inregs.h.dl = fspec[0] - 'A' +1; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + if (!Check_DBCS(fspec,strlen(fspec)-1,'\\')) /*;AN000;*/ + strcat(fspec,"\\"); /*;AN000;*/ + strcat(fspec,path); /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* seperate the file specification into path and filename */ + for (i=strlen(fspec);(i>=0) && (!Check_DBCS(fspec,i,'\\')); i--) /*;AN000;*/ + /* null statement */ ; /*;AN000;*/ + i++; /*;AN000;*/ + j = 0; /*;AN000;*/ + while (fspec[i+j] != '\0') { /*;AN000;*/ + file[j] = fspec[i+j]; /*;AN000;*/ + fspec[i+j] = '\0'; /*;AN000;*/ + j++; /*;AN000;*/ + } /*;AN000;*/ + file[j] = '\0'; /*;AN000;*/ + + /* Check for filenames of: . (current dir) .. (parent dir) */ + if (strcmp(file,".") == 0) /*;AN001;*/ + strcpy(file,"*.*"); /*;AN001;*/ + else if (strcmp(file,"..") == 0) { /*;AN001;*/ + strcat(fspec,"..\\"); /*;AN001;*/ + strcpy(file,"*.*"); /*;AN001;*/ + } + + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Dta_save() */ +/* */ +/* Subroutine Function: */ +/* saves an area in the PSP, but who knows. */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Dta_save(t,l) + char *t; + unsigned l; +{ + unsigned i; + + for (i = 0; i < l; i++) *(t+i) = getpspbyte(0x80+i) + /* null statement */ ; + } + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Dta_restore() */ +/* */ +/* Subroutine Function: */ +/* Restores the data that was saved in Dta_save(). */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Dta_restore(t,l) + char *t; + unsigned l; +{ + unsigned i; + + for (i = 0; i < l; i++) putpspbyte(0x80+i,*(t+i)) + /* null statement */ ; +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Find_first() */ +/* */ +/* Subroutine Function: */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Find_first(s,f,a) + char *s; + char *f; + WORD *a; +{ + WORD status; + WORD i; + WORD o; + char *t; + + t = f; + *f = '\0'; + + inregs.x.ax = 0x4e00; /* DOS find first */ + inregs.x.cx = (*a & 0x00ff ); + inregs.x.dx = (WORD)s; + intdos(&inregs,&outregs); + status = outregs.x.ax; + + /* Check for no errors */ + if (!(outregs.x.cflag & CARRY)) { + for (i = 0; i < 14; i++) + *f++ = getpspbyte(0x80+30+i); + *a = getpspbyte(0x80+21); + status = NOERROR; + } + return(status); +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Find_next() */ +/* */ +/* Subroutine Function: */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Find_next(f,a) + char *f; + WORD *a; +{ + WORD status; + WORD i; + WORD o; + char *t; + + t = f; + *f = '\0'; + + inregs.x.ax = 0x4f00; /* DOS find next */ + intdos(&inregs,&outregs); + status = outregs.x.ax; + + if (!(outregs.x.cflag & CARRY)) { + for (i = 0; i < 14; i++) + *f++ = getpspbyte(0x80+30+i); + *a = getpspbyte(0x80+21); + status = NOERROR; + } + return(status); +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_reg_attrib() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS get attribute byte. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: return = 0 */ +/* */ +/* Error exit: return = error code */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Get_reg_attrib(fspec,attr_byte) /*;AN000;*/ + char *fspec; /*;AN000;*/ + BYTE *attr_byte; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + + inregs.x.ax = (WORD)0x4300; /*;AN000;*/ + inregs.x.dx = (WORD)fspec; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + /* Check for error */ /*;AN000;*/ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + *attr_byte = (BYTE)outregs.h.cl; /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + } /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Ext_open() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS extended open of a filename and returns a file handle.*/ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: handle = file handle, return = 0 */ +/* */ +/* Error exit: handle = ?; return = error code */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Ext_open(fspec,handle) /*;AN000;*/ + char *fspec; /*;AN000;*/ + WORD *handle; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + + inregs.x.ax = (WORD)0x6c00; /*;AN000;*/ + inregs.x.bx = (WORD)0x80; /*;AN000;*/ + inregs.x.cx = (WORD)0x0; /*;AN000;*/ + inregs.x.dx = (WORD)0x0101; /*;AN000;*/ + inregs.x.si = (WORD)fspec; /*;AN000;*/ + inregs.x.di = (WORD)&plist; /*;AN000;*//*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + /* Check for error */ /*;AN000;*/ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + *handle = outregs.x.ax; /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + } /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_ext_attrib() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS Get extended attributes and returns far ptr to list. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: handle = file handle, return = 0 */ +/* */ +/* Error exit: handle = ?; return = error code */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Get_ext_attrib(handle,list_ptr,qlist_ptr) /*;AN000;*/ + WORD handle; /*;AN000;*/ + WORD far **list_ptr; /* ptr to far ptr to list returned */ /*;AN000;*/ + WORD *qlist_ptr; /* query list */ /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD attr_size; /*;AN000;*/ + WORD *list_seg; /*;AN000;*/ + WORD *ptr; /*;AN000;*/ + + /* get size of attribute list */ /*;AN000;*/ + inregs.x.bx = handle; /*;AN000;*/ + inregs.x.ax = 0x5702; /* Get extended attributes*/ /*;AN000;*/ + inregs.x.si = (WORD)qlist_ptr; /* query one attribute */ /*;AN000;*/ + inregs.x.cx = (WORD)0; /* just get size of return buffer */ /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + /* if no errors then get extended attributes */ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + attr_size = outregs.x.cx; /*;AN000;*/ + + /* allocate buffer space for extended attr. list */ + /* uses MAX_ATTR_SIZE if possible so that buffer can be used */ + /* to set the largest attribute possible */ + if (attr_size > MAX_ATTR_SIZE) /*;AN000;*/ + list_seg = Dallocate(attr_size); /*;AN000;*/ + else /*;AN000;*/ + list_seg = Dallocate(MAX_ATTR_SIZE); /*;AN000;*/ + + /* get extended attributes */ + inregs.x.bx = handle; /*;AN000;*/ + inregs.x.ax = 0x5702; /* Get extended attributes */ /*;AN000;*/ + inregs.x.si = (WORD)qlist_ptr; /* query one attribute */ /*;AN000;*/ + inregs.x.di = (WORD)0x0; /* return buffer offset */ /*;AN000;*/ + inregs.x.cx = attr_size; /* size to get all attributes */ /*;AN000;*/ + segregs.es = (WORD)list_seg; /* segment of ea list to return */ /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* restores original ES reg. value */ /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + /* if no errors then fix up far pointer to list */ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + + /* convert segment returned from Dallocate to far ptr */ + *list_ptr = 0; /*;AN000;*/ + ptr = (WORD *)list_ptr; /*;AN000;*/ + ptr++; /*;AN000;*/ + *ptr = (WORD)list_seg; /*;AN000;*/ + (*list_ptr)++; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* restores ES register value */ /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_ext_attr_names() */ +/* */ +/* Subroutine Function: */ +/* Does a DOS Get extended attribute names and return a far ptr to */ +/* the querylist of names. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: handle = file handle, return = 0 */ +/* */ +/* Error exit: handle = ?; return = error code */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Get_ext_attr_names(handle,list_ptr,num_entries) /*;AN000;*/ + WORD handle; /*;AN000;*/ + WORD far **list_ptr; /* ptr to far ptr to list returned */ /*;AN000;*/ + WORD *num_entries; /* number of entries in list */ /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD attr_size; /*;AN000;*/ + WORD *list_seg; /*;AN000;*/ + WORD *ptr; /*;AN000;*/ + + /* get size of attribute name list */ /*;AN000;*/ + inregs.x.bx = handle; /*;AN000;*/ + inregs.x.ax = 0x5703; /* Get extended attribute names */ /*;AN000;*/ + inregs.x.cx = (WORD)0; /* just get size of return buffer */ /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + + /* if no errors then get extended attribute names */ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + attr_size = outregs.x.cx; /*;AN000;*/ + + /* allocate buffer space for extended attr. list */ + list_seg = Dallocate(attr_size); /*;AN000;*/ + + /* get extended attributes */ + inregs.x.bx = handle; /*;AN000;*/ + inregs.x.ax = 0x5703; /* Get extended attributes */ /*;AN000;*/ + inregs.x.di = (WORD)0x0; /* return buffer offset */ /*;AN000;*/ + inregs.x.cx = attr_size; /* size to get all names */ /*;AN000;*/ + segregs.es = (WORD)list_seg; /* segment of ea list to return */ /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* restores original ES reg. value */ /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + *num_entries = 0; /*;AN000;*/ + + /* if no errors then fix up far pointer to list */ + if (!(outregs.x.cflag & CARRY)) { /*;AN000;*/ + + /* convert segment returned from Dallocate to far ptr */ + *list_ptr = 0; /*;AN000;*/ + ptr = (WORD *)list_ptr; /*;AN000;*/ + ptr++; /*;AN000;*/ + *ptr = (WORD)list_seg; /*;AN000;*/ + *num_entries = (WORD)*(WORD far *)*list_ptr; /*;AN000;*/ + (*list_ptr)++; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* restores ES register value */ /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Set_reg_attrib() */ +/* */ +/* Subroutine Function: */ +/* Sets the attribute byte of a file (not extended attributes). */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Set_reg_attrib(fspec,attr_byte) /*;AN000;*/ + char *fspec; /*;AN000;*/ + BYTE attr_byte; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + + /* set attribute byte (archive & read-only bits) */ + inregs.x.ax = 0x4301; /* do DOS chmod call */ /*;AN000;*/ + inregs.x.dx = (WORD)fspec; /*;AN000;*/ + inregs.h.ch = 0x0; /*;AN000;*/ + inregs.h.cl = (BYTE)attr_byte; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + /*;AN000;*/ + /* Check for error */ + if (!(outregs.x.cflag & CARRY)) + status = NOERROR; /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Set_ext_attrib() */ +/* */ +/* Subroutine Function: */ +/* Set an extended attribute for a file. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Set_ext_attrib(handle,list_ptr) /*;AN000;*/ + WORD handle; /*;AN000;*/ + WORD far *list_ptr; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + + /* set extended attribute */ + inregs.x.ax = 0x5704; /* DOS set ext. attr. */ /*;AN000;*/ + inregs.x.bx = handle; /*;AN000;*/ + inregs.x.di = 0x0; /* list offset */ /*;AN000;*/ + segregs.es = (WORD)FP_SEG(list_ptr); /* list segment */ /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + /*;AN000;*/ + /* Check for error */ + if (!(outregs.x.cflag & CARRY)) /*;AN000;*/ + status = NOERROR; /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: CheckYN() */ +/* */ +/* Subroutine Function: */ +/* Check for a valid Yes/No answer. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD CheckYN(fspec) /*;AN000;*/ + char *fspec; /*;AN000;*/ +{ /*;AN000;*/ + WORD answer; /*;AN000;*/ + WORD key; /*;AN000;*/ + + while (TRUE) { /*;AN000;*/ + msg_str2.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str2.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(11,STDOUT,ONEPARM,&msg_str2,INPUT); /*;AN000;*/ + key = outregs.x.ax; /* get key from AX */ /*;AN000;*/ + inregs.x.dx = key; /* put key in DX */ /*;AN000;*/ + inregs.x.ax = 0x6523; /* check Y/N */ /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + answer = outregs.x.ax; /*;AN000;*/ + Display_msg(14,STDOUT,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + + if (answer == YES || answer == NO) /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + return(answer); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Find_ext_attrib() */ +/* */ +/* Subroutine Function: */ +/* Given an extended attribute name, search the list of attributes */ +/* for a file to find this attribute. Return either TRUE for found */ +/* or FALSE for not found. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Find_ext_attrib(lptr,attribute,num,addr) /*;AN000;*/ + WORD far *lptr; /*;AN000;*/ + char *attribute; /*;AN000;*/ + WORD num; /*;AN000;*/ + struct name_list far **addr; /*;AN000;*/ +{ /*;AN000;*/ + struct name_list far *ptr; /*;AN000;*/ + WORD i,j; /*;AN000;*/ + WORD length; /*;AN000;*/ + WORD found; /*;AN000;*/ + WORD match; /*;AN000;*/ + + found = FALSE; /*;AN000;*/ + + /* loop thru return list structure for the ext. attr. we want */ + for (ptr = (struct name_list far *)lptr,i=0;i < num; i++) { /*;AN000;*/ + + /* compare attribute name to see if this is it */ + if (ptr->nl_name_len == (length = strlen(attribute))) { /*;AN000;*/ + match = TRUE; /*;AN000;*/ + for (j=0;jnl_name[j] != attribute[j]) { /*;AN000;*/ + match = FALSE; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + if (match) { /*;AN000;*/ + found = TRUE; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* advance ptr to next extended attr. structure */ + length = NAME_SIZE + ptr->nl_name_len; /*;AN000;*/ + ptr = (struct name_list far *)((BYTE far *)ptr + length); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + } /*;AN000;*/ + + /* found the extended attribute wanted, pass addr back */ + if (found) { /*;AN000;*/ + *addr = ptr; /*;AN000;*/ + } /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + return(found); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Print_ext_attrib() */ +/* */ +/* Subroutine Function: */ +/* Given an extended attribute name, search the list of attributes */ +/* for a file to find this attribute. Return either TRUE for found */ +/* or FALSE for not found. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: target = source */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Print_ext_attrib(fspec,type,name_ptr,num,attr_ptr) /*;AN000;*/ + char *fspec; /*;AN000;*/ + WORD type; /*;AN000;*/ + struct name_list far *name_ptr; /*;AN000;*/ + WORD num; /*;AN000;*/ + struct attr_list far *attr_ptr; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD i; /*;AN000;*/ + WORD length; /*;AN000;*/ + WORD value; /*;AN000;*/ + BYTE far *value_ptr; /*;AN000;*/ + char string[129]; /*;AN000;*/ + char far *cptr; /*;AN000;*/ + struct name_list far *ptr; /*;AN000;*/ + + /* find value field in attribute list */ + length = ATTR_SIZE + attr_ptr->at_name_len; /*;AN000;*/ + value_ptr = (BYTE far *)((BYTE far *)attr_ptr + length); /*;AN000;*/ + length = attr_ptr->at_value_len; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + + status = NOERROR; /*;AN000;*/ + switch (type) { /*;AN000;*/ + case EAISUNDEF: /*;AN000;*/ + msg_str2.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str2.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(12,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EAISLOGICAL: /*;AN000;*/ + msg_str.sub_value_seg = segregs.ds; /*;AN000;*/ + if ((BYTE)*(BYTE far *)value_ptr == 0) /*;AN000;*/ + msg_str.sub_value = (WORD)str_off; /*;AN000;*/ + else /*;AN000;*/ + msg_str.sub_value = (WORD)str_on; /*;AN000;*/ + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_str,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EAISBINARY: /*;AN000;*/ + if (length == 1) { /*;AN000;*/ + msg_num.sub_flags = sf_unsbin2d | sf_byte | sf_right; /*;AN000;*/ + value = (BYTE)*(BYTE far *)value_ptr; /*;AN000;*/ + } /*;AN000;*/ + else if (length == 2) { /*;AN000;*/ + msg_num.sub_flags = sf_unsbin2d | sf_word | sf_right; /*;AN000;*/ + value = (WORD)*(WORD far *)value_ptr; /*;AN000;*/ + } /*;AN000;*/ + else if (length == 4) { /*;AN000;*/ + msg_num.sub_flags = sf_unsbin2d | sf_dword | sf_right; /*;AN000;*/ + value = (DWORD)*(DWORD far *)value_ptr; /*;AN000;*/ + } /*;AN000;*/ + msg_num.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_num.sub_value = (WORD)&value; /*;AN000;*/ + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_num,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EAISASCII: /*;AN000;*/ + msg_str2.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str2.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(12,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + Get_far_str(string,&value_ptr,length); /*;AN000;*/ + msg_str2.sub_value = (WORD)string; /*;AN000;*/ + Display_msg(8,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EAISDATE: /*;AN000;*/ + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + value = (WORD)*(WORD far *)value_ptr; /*;AN000;*/ + Convert_date(value,&msg_date.sub_value,&msg_date.sub_value_seg); /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_date,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EAISTIME: /*;AN000;*/ + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + value = (WORD)*(WORD far *)value_ptr; /*;AN000;*/ + Convert_time(value,&msg_time.sub_value,&msg_time.sub_value_seg); /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_time,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + case EANAMES: /*;AN000;*/ + msg_str2.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str2.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(12,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + + /* display special attribute names */ + for (i=0; i < MAX_SPL; i++) { /*;AN000;*/ + msg_str2.sub_value = (WORD)specials[i].name; /*;AN000;*/ + Display_msg(8,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + } /*;AN000;*/ + + /* display each attribute name */ + for (ptr = name_ptr,i=0; inl_name_len); /*;AN000;*/ + + msg_str2.sub_value = (WORD)string; /*;AN000;*/ + Display_msg(8,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + + /* advance ptr to next extended attr. structure */ + length = NAME_SIZE + ptr->nl_name_len; /*;AN000;*/ + ptr = (struct name_list far *)((BYTE far *)ptr + length); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + } /*;AN000;*/ + Display_msg(14,STDOUT,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + Display_msg(14,STDOUT,NOSUBPTR,NOSUBCNT,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + default: /*;AN000;*/ + msg_str2.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str2.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(12,STDOUT,ONEPARM,&msg_str2,NOINPUT); /*;AN000;*/ + break; /*;AN000;*/ + } /* endswitch */ /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Convert_date */ +/* */ +/* Subroutine Function: */ +/* Convert date word returned by DOS to the form required by the */ +/* message retriever. */ +/* */ +/* DOS returns: yyyyyyym mmmddddd */ +/* */ +/* y = 0-119 (1980-2099) */ +/* m = 1-12 */ +/* d = 1-31 */ +/* */ +/* Message retriever requires: yyyyyyyy yyyyyyyy mmmmmmmm dddddddd */ +/* */ +/* Input: */ +/* (1) Date word in form given by DOS */ +/* (2) Address of first word to place result (yyyyyyyy yyyyyyyy) */ +/* (3) Address of second word to place result (mmmmmmmm dddddddd) */ +/* */ +/* Output: */ +/* Double word result updated with date in form required by */ +/* message retriever. */ +/* */ +/* Normal exit: Result word updated */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Convert_date(dosdate,msgdate1,msgdate2) + WORD dosdate; + WORD *msgdate1; + WORD *msgdate2; +{ + WORD day,month,year; + + year = dosdate; + year = ((year >> 1) & 0x7f00) + 80*256; /* DOS year + 80 */ + year = (year >> 8) & 0x007f; /*;AN000;*/ + day = dosdate; + day = (day << 8) & 0x1f00; + month = dosdate; + month = (month >> 5) & 0x000f; + *msgdate1 = year; + *msgdate2 = month | day; +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Convert_time */ +/* */ +/* Subroutine Function: */ +/* Convert time word returned by DOS to the form required by the */ +/* message retriever. */ +/* */ +/* DOS returns: hhhhhmmm mmmsssss */ +/* */ +/* h = hours (0-23) */ +/* m = minutes (0-59) */ +/* s = seconds/2 */ +/* */ +/* Message retriever requires: hhhhhhhh mmmmmmmm ssssssss hhhhhhhh */ +/* */ +/* Input: */ +/* (1) Time word in form given by DOS */ +/* (2) Address of first word to place result (hhhhhhhh hhhhhhhh) */ +/* (3) Address of second word to place result (ssssssss 00000000) */ +/* */ +/* Output: */ +/* Double word result updated with time in form required by */ +/* message retriever. */ +/* */ +/* Normal exit: Result word updated */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Convert_time(dostime,msgtime1,msgtime2) + WORD dostime; + WORD *msgtime1; + WORD *msgtime2; +{ + WORD hours,minutes,seconds; + + hours = dostime; + hours = hours >> 11 & 0x001f; + seconds = dostime; + seconds = seconds & 0x001f * 2; /* seconds * 2 */ + minutes = dostime; + minutes = minutes << 3 & 0x3f00; + *msgtime1 = hours | minutes; + *msgtime2 = seconds; +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Regular_attrib() */ +/* */ +/* Subroutine Function: */ +/* Handles all function for archive bit and read-only bit. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Regular_attrib(fspec) /*;AN000;*/ + char *fspec; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD i; /*;AN000;*/ + char string[16]; /*;AN000;*/ + + /* get attributes */ + if ((status = Get_reg_attrib(fspec,&attr)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + + /* Check whether to display values or set new ones */ + if (set_reg_attr) { /*;AN000;*/ + attr = (attr & (~mmask)) | pmask; /*;AN000;*/ + status = Set_reg_attrib(fspec,attr); /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + for (i = 0; i < 8; i++) /*;AN000;*/ + if ((attr & bits[i]) != 0 ) /*;AN000;*/ + string[i] = as[i]; /*;AN000;*/ + else /*;AN000;*/ + string[i] = ' '; /*;AN000;*/ + for (i=8; i < 16; i++) /*;AN000;*/ + string[i] = ' '; /*;AN000;*/ + string[16] = '\0'; /*;AN000;*/ + + msg_str.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str.sub_value = (WORD)string; /*;AN000;*/ + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_str,NOINPUT); /*;AN000;*/ + } /*;AN000;*/ + + did_attrib_ok = TRUE; /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Special_attrib() */ +/* */ +/* Subroutine Function: */ +/* Handles all function for special attributes. For example, "DATE" */ +/* is a special attribute because it is not an extended attribute, */ +/* but ATTRIB does support its function. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Special_attrib(handle,fspec,id) /*;AN000;*/ + WORD handle; /*;AN000;*/ + char *fspec; /*;AN000;*/ + WORD id; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + DWORD filesize; /*;AN000;*/ + long size; /*;AN000;*/ + long filelength(); /*;AN000;*/ + + msg_str1.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_str1.sub_value = (WORD)fspec; /*;AN000;*/ + + /* check to set if user is trying to set a special attribute, if so */ + /* then return error. */ + if (set_ext_attr) /*;AN000;*/ + return(EARCNOTEVER+200); /*;AN000;*/ + + /* determine which info to get by using ID */ + if (id == A_FILESIZE) { /* get filesize */ /*;AN000;*/ + + /* get file size, if error return error code */ + if ((size = filelength(handle)) == (long)-1) { /*;AN000;*/ + return(FILENOTFOUND); /*;AN000;*/ + } /*;AN000;*/ + filesize = (DWORD)size; /*;AN000;*/ + msg_dword.sub_value = (WORD)&filesize; /*;AN000;*/ + msg_dword.sub_value_seg = (WORD)segregs.ds; /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_dword,NOINPUT); /*;AN000;*/ + } /*;AN000;*/ + + else if (id == A_DATE) { /*;AN000;*/ + inregs.x.ax = 0x5700; /* get date */ /*;AN000;*/ + inregs.x.bx = handle; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + if (outregs.x.cflag & CARRY) /*;AN000;*/ + return(status); /*;AN000;*/ + + Convert_date(outregs.x.dx,&msg_date.sub_value,&msg_date.sub_value_seg); /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_date,NOINPUT); /*;AN000;*/ + } /*;AN000;*/ + + else if (id == A_TIME) { /*;AN000;*/ + inregs.x.ax = 0x5700; /* get time */ /*;AN000;*/ + inregs.x.bx = handle; /*;AN000;*/ + intdos(&inregs,&outregs); /*;AN000;*/ + status = outregs.x.ax; /*;AN000;*/ + if (outregs.x.cflag & CARRY) /*;AN000;*/ + return(status); /*;AN000;*/ + + Convert_time(outregs.x.cx,&msg_time.sub_value,&msg_time.sub_value_seg); /*;AN000;*/ + Display_msg(9,STDOUT,TWOPARM,&msg_time,NOINPUT); /*;AN000;*/ + } /*;AN000;*/ + + did_attrib_ok = TRUE; /*;AN000;*/ + return(NOERROR); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Extended_attrib() */ +/* */ +/* Subroutine Function: */ +/* Determine what functions the user wants and then gets the */ +/* extended attributes and regular attributes and then checks */ +/* the attributes against what the user wanted and either do it or */ +/* return error. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Extended_attrib(handle,fspec) /*;AN000;*/ + WORD handle; /*;AN000;*/ + char *fspec; /*;AN000;*/ +{ /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD num; /*;AN000;*/ + WORD type; /*;AN000;*/ + WORD length; /*;AN000;*/ + WORD i; /*;AN000;*/ + WORD far *name_ptr, /*;AN000;*/ + far *nptr; /*;AN000;*/ + WORD far *list_ptr; /*;AN000;*/ + BYTE far *value_ptr; /*;AN000;*/ + char far *cptr; /*;AN000;*/ + char *ptr; /*;AN000;*/ + struct query_list qlist; /*;AN000;*/ + + /* get extended attribute names, if error return with error code */ + if ((status = Get_ext_attr_names(handle,&name_ptr,&num)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + + /* Check for keyword "*", print all extended attribute names */ + /* ***** this is a special piece of code */ + if (strcmp(ext_attr,"*") == 0) { /*;AN000;*/ + do_ext_attr = TRUE; /*;AN000;*/ + set_ext_attr = FALSE; /*;AN000;*/ + nptr = name_ptr; /*;AN000;*/ + type = EANAMES; /*;AN000;*/ + status = Print_ext_attrib(fspec,type,name_ptr,num,list_ptr); /*;AN004;*/ + did_attrib_ok = TRUE; /*;AN004;*/ + return(status); /*;AN004;*/ + } /*;AN000;*/ + + /* find if extended attribute name is in list */ + else if (!Find_ext_attrib(name_ptr,ext_attr,num,&nptr)) { /*;AN000;*/ + return(EARCNOTFOUND+200); /*;AN000;*/ + } /*;AN000;*/ + else /*;AN000;*/ + type = ((struct name_list far *)nptr)->nl_type; /*;AN000;*/ + + /* Check if extended attribute is hidden , if so leave */ + if (((struct name_list far *)nptr)->nl_flags & EAHIDDEN) { /*;AN000;*/ + did_attrib_ok = TRUE; /*;AN000;*/ + return(NOERROR); /*;AN000;*/ + } /*;AN000;*/ + + /* Get the extended attribute value */ + qlist.ql_num = 1; /*;AN000;*/ + qlist.ql_type = ((struct name_list far *)nptr)->nl_type; /*;AN000;*/ + qlist.ql_flags = ((struct name_list far *)nptr)->nl_flags; /*;AN000;*/ + qlist.ql_name_len = ((struct name_list far *)nptr)->nl_name_len; /*;AN000;*/ + cptr = (char far *)((BYTE far *)nptr + 4); /*;AN000;*/ + Get_far_str(qlist.ql_name,&cptr,qlist.ql_name_len); /*;AN000;*/ + + if ((status = Get_ext_attrib(handle,&list_ptr,&qlist)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + + /* Check if doing a display or set, and go do it */ + if (do_ext_attr) { /*;AN000;*/ + status = Print_ext_attrib(fspec,type,name_ptr,num,list_ptr); /*;AN000;*/ + } /*;AN000;*/ + else { /*;AN000;*/ + + /* Check if extended attribute is read-only or create-only */ + /* or if the type is undefined. if true, display error */ + if ((qlist.ql_flags & (EAREADONLY | EACREATEONLY)) || /*;AN000;*/ + (qlist.ql_type & EAISUNDEF)) { /*;AN000;*/ + return(EARCNOTEVER+200); /* error will be displayed */ /*;AN000;*/ + } /*;AN000;*/ + + /* Check type of current attribute against the type the user */ + /* is trying to set the attribute to. If they differ, error. */ + if (qlist.ql_type != ext_attr_value_type) { /*;AN000;*/ + return(EARCDEFBAD+200); /* error will be displayed */ /*;AN000;*/ + } /*;AN000;*/ + + /* find value field in attribute list */ + length = ATTR_SIZE + qlist.ql_name_len; /*;AN000;*/ + value_ptr = (BYTE far *)((BYTE far *)list_ptr + length); /*;AN000;*/ + length = ((struct attr_list far *)list_ptr)->at_value_len; /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + + /* CODEPAGE attrbute only - display Y/N message if changing codepage */ + /* to a new value and cp != 0, ask for confirmation. */ + if (strcmp(qlist.ql_name,"CP") == 0 && /*;AN000;*/ + (WORD)*(WORD far *)value_ptr != 0 && /*;AN000;*/ + (WORD)*(WORD far *)value_ptr != (WORD)ext_attr_value.ea_bin.dword) { /*;AN000;*/ + if (CheckYN(fspec) == NO) { /*;AN000;*/ + did_attrib_ok = TRUE; /*;AN000;*/ + return(NOERROR); /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* Determine type of extended attribute and set the correct value */ + switch (ext_attr_value_type) { /*;AN000;*/ + case EAISLOGICAL: /*;AN000;*/ + *(BYTE far *)value_ptr = (BYTE)ext_attr_value.ea_logical; /*;AN000;*/ + break; /*;AN000;*/ + case EAISBINARY: /*;AN000;*/ + if (length == 1) /*;AN000;*/ + *(BYTE far *)value_ptr = (BYTE)ext_attr_value.ea_bin.dword; /*;AN000;*/ + else if (length == 2) /*;AN000;*/ + *(WORD far *)value_ptr = (WORD)ext_attr_value.ea_bin.dword; /*;AN000;*/ + else /*;AN000;*/ + *(DWORD far *)value_ptr = (DWORD)ext_attr_value.ea_bin.dword; /*;AN000;*/ + break; /*;AN000;*/ + case EAISASCII: /*;AN000;*/ + length = strlen(ext_attr_value.ea_ascii); /* get string length */ /*;AN000;*/ + ((struct attr_list far *)list_ptr)->at_value_len = length; /*;AN000;*/ + for (ptr=ext_attr_value.ea_ascii,i=0;i < length;i++) { /*;AN000;*/ + *(char far *)value_ptr = *ptr++; /*;AN000;*/ + ((char far *)value_ptr)++; /*;AN000;*/ + } /*;AN000;*/ + break; /*;AN000;*/ + case EAISDATE: /*;AN000;*/ + *(WORD far *)value_ptr = (WORD)ext_attr_value.ea_date; /*;AN000;*/ + break; /*;AN000;*/ + case EAISTIME: /*;AN000;*/ + *(WORD far *)value_ptr = (WORD)ext_attr_value.ea_time; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + + list_ptr--; /* make list_ptr point to num entries */ /*;AN000;*/ + *(WORD far *)list_ptr = 1; /* num entries = 1 */ /*;AN000;*/ + + if ((status = Set_ext_attrib(handle,list_ptr)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + did_attrib_ok = TRUE; /*;AN000;*/ + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Attrib() */ +/* */ +/* Subroutine Function: */ +/* Determine what functions the user wants and then gets the */ +/* extended attributes and regular attributes and then checks */ +/* the attributes against what the user wanted and either do it or */ +/* return error. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Attrib(path,file) /*;AN000;*/ + char *path, /*;AN000;*/ + *file; /*;AN000;*/ +{ /*;AN000;*/ + char fspec[128]; /*;AN000;*/ + WORD status; /*;AN000;*/ + WORD handle; /*;AN000;*/ + WORD i; /*;AN000;*/ + WORD found_spl; /* boolean */ /*;AN000;*/ + WORD id; /*;AN000;*/ + + strcpy(fspec,path); /* make full filename */ /*;AN000;*/ + strcat(fspec,file); /*;AN000;*/ + + /* Check for extended & special attributes */ + if (set_ext_attr || do_ext_attr) { /*;AN000;*/ + + /* Check for special attribute keywords */ + found_spl = FALSE; /*;AN000;*/ + for (i=0; i < MAX_SPL; i++) { /*;AN000;*/ + if (strcmp(ext_attr,specials[i].name) == 0) { /*;AN000;*/ + found_spl = TRUE; /*;AN000;*/ + id = specials[i].id; /*;AN000;*/ + break; /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* Do an extended open, if error return error code */ + if ((status = Ext_open(fspec,&handle)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + + /* Special attributes */ + if (found_spl) { /*;AN000;*/ + status = Special_attrib(handle,fspec,id); /*;AN000;*/ + } /*;AN000;*/ + + /* Extended attributes */ + else { /*;AN000;*/ + status = Extended_attrib(handle,fspec); /*;AN000;*/ + } /*;AN000;*/ + close(handle); /*;AN000;*/ + } /*;AN000;*/ + + /* Check if setting archive bit or readonly bit */ + if (set_reg_attr || do_reg_attr) { /*;AN000;*/ + if ((status = Regular_attrib(fspec)) != NOERROR) { /*;AN000;*/ + return(status); /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + return(status); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Do_dir() */ +/* */ +/* Subroutine Function: */ +/* Given the full path-filename, determine if descending option is */ +/* set and then recursively (if option set) find all files in this */ +/* directory and all files in any subdirectories (if option set). */ +/* For each directory call Attrib() which will process a file. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +WORD Do_dir(path,file) + char *path, + *file; +{ + char dta_area[128]; + char subdirectory[256]; + char next[32]; + WORD status; + WORD search_attrib; + + next[0] = '\0'; /*;AN000;*/ + Dta_save(dta_area,128); + status = NOERROR; /*;AN000;*/ + + /* first, but only if descending, scan for subdirectories */ + if (descending) { + strcpy(subdirectory,path); + strcat(subdirectory,"*.*"); + + search_attrib = SUBDIR; /* Find all except volume labels*/ /*;AN000;*/ + status = Find_first(subdirectory,next,&search_attrib); + + while (status == NOERROR) { + if ((next[0] != '.') && ((search_attrib & SUBDIR) != 0)) { + strcpy(subdirectory,path); + strcat(subdirectory,next); + strcat(subdirectory,"\\"); + status = Do_dir(subdirectory,file); + } + if (status == NOERROR) { + strcpy(subdirectory,path); + strcat(subdirectory,"*.*"); + + search_attrib = SUBDIR; /*;AN000;*/ + status = Find_next(next,&search_attrib); + } + } /* while */ + } /* if descending */ + + if (status == NOMOREFILES) + status = NOERROR; + + /* now, search this directory for files that match */ + if (status == NOERROR) { + strcpy(subdirectory,path); + strcat(subdirectory,file); + + search_attrib = SUBDIR; /*;AN000;*/ + status = Find_first(subdirectory,next,&search_attrib); + while(status == NOERROR) { + + /* Check that this file is not a directory, system file, */ + /* or a hidden file. */ + if ( (next[0] != '.') && + ((search_attrib & SUBDIR) == 0) && + ((search_attrib & SYSTEM) == 0) && + ((search_attrib & HIDDEN) == 0) ) { + status = Attrib(path,next); + } + + if (status == NOERROR) { + search_attrib = SUBDIR; /*;AN000;*/ + status = Find_next(next,&search_attrib); + } + } /* while */ + } + if (status == NOMOREFILES) + status = NOERROR; + + if (status != NOERROR) { /*;AN000;*/ + } + + Dta_restore(dta_area,128); + return(status); +} + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Check_appendx() */ +/* */ +/* Subroutine Function: */ +/* Check APPEND /X status. If it is not active, */ +/* do nothing. If it is active, then turn it off */ +/* and set flag indicating that fact. */ +/* */ +/* Input: none */ +/* */ +/* Output: append_active_flg */ +/* */ +/* Normal exit: flag set if /X active */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Check_appendx() /*;AN000;*/ +{ /*;AN000;*/ + void ctl_brk_handler(); /*;AN000;*/ + extern crit_err_handler(); /*;AN000;*/ + WORD *ptr; /*;AN000;*/ + + inregs.x.ax = 0xb700; /* Is appendx installed ? */ /*;AN000;*/ + int86(0x2f,&inregs,&outregs); /*;AN000;*/ + if (outregs.h.al) { /*;AN000;*/ + inregs.x.ax = 0xb702; /* Get version */ /*;AN000;*/ + int86(0x2f,&inregs,&outregs); /*;AN000;*/ + if (outregs.x.ax == 0xffff) { /*;AN000;*/ + inregs.x.ax = 0xb706; /* Get /X status */ /*;AN000;*/ + int86(0x2f,&inregs,&outregs); /*;AN000;*/ + append_x_status = outregs.x.bx; /* save status to restore */ /*;AN000;*/ + + /* turn off append /x */ + inregs.x.ax = 0xb707; /* Set /X status */ /*;AN000;*/ + inregs.x.bx = append_x_status & INACTIVE; /*;AN000;*/ + int86(0x2f,&inregs,&outregs); /*;AN000;*/ + } /*;AN000;*/ + } /*;AN000;*/ + + /* get critical error handler vector for later */ + inregs.x.ax = 0x3524; /* get critical error vector */ /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + ptr = (WORD *)&old_int24_off; /*;AN000;*/ + *ptr++ = (WORD)outregs.x.bx; /*;AN000;*/ + *ptr = (WORD)segregs.es; /*;AN000;*/ + + /* set crtl-c & critical error handler vector */ + segread(&segregs); + inregs.x.ax = 0x2523; /* crtl-c - int 23 */ /*;AN000;*/ + inregs.x.dx = (WORD) ctl_brk_handler; /*;AN000;*/ + segregs.ds = (WORD) segregs.cs; /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + + inregs.x.ax = 0x2524; /* critical err - int 24 */ /*;AN000;*/ + inregs.x.dx = (WORD) crit_err_handler; /*;AN000;*/ + segregs.ds = (WORD) segregs.cs; /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /* restore ES register */ /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Reset_appendx() */ +/* */ +/* Subroutine Function: */ +/* Reset APPEND /X status. If it is not active, */ +/* do nothing. If it is active, then turn it on */ +/* and set flag indicating that fact. */ +/* */ +/* Input: none */ +/* */ +/* Output: append_active_flg */ +/* */ +/* Normal exit: flag set if /X active */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +Reset_appendx() /*;AN000;*/ +{ /*;AN000;*/ + if (append_x_status != 0) { /*;AN000;*/ + inregs.x.ax = 0xb707; /*;AN000;*/ + inregs.x.bx = append_x_status; /*;AN000;*/ + int86(0x2f,&inregs,&outregs); /*;AN000;*/ + } /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Check_DBCS() */ +/* */ +/* Subroutine Function: */ +/* Given an array and a position in the array, check if the character */ +/* is a non-DBCS character. */ +/* */ +/* Input: array, character position, character */ +/* */ +/* Output: TRUE - if array[position-1] != DBCS character AND */ +/* array[position] == character. */ +/* FALSE - otherwise */ +/* Normal exit: none */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +WORD Check_DBCS(array,position,character) /*;AN000;*/ + char *array; /*;AN000;*/ + WORD position; /*;AN000;*/ + char character; /*;AN000;*/ +{ /*;AN000;*/ + BYTE far *ptr; /*;AN000;*/ + WORD i; /*;AN000;*/ + char c; /*;AN000;*/ + char darray[128]; /* DBCS array, put "D" in every position*/ /*;AN000;*/ + /* that corresponds to the first byte */ + /* of a DBCS character. */ + for (i=0;i<128;i++) /*;AN000;*/ + darray[i] = ' '; /*;AN000;*/ + + /* Check each character, starting with the first in string, for DBCS */ + /* characters and mark each with a "D" in the corresponding darray. */ + for (i=0;i= *ptr && c <= *(ptr+1)) { /*;AN000;*/ + darray[i] = 'D'; /*;AN000;*/ + i++; /* skip over second byte of DBCS */ /*;AN000;*/ + break; + } + } /*;AN000;*/ + } /*;AN000;*/ + + /* if character is not DBCS then check to see if it is == to character */ + if (darray[position-1] != 'D' && character == array[position]) { /*;AN000;*/ + return (TRUE); /*;AN000;*/ + } /*;AN000;*/ + else /*;AN000;*/ + return (FALSE); /*;AN000;*/ +} /*;AN000;*/ + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Get_DBCS_vector() */ +/* */ +/* Subroutine Function: */ +/* Gets the double-byte table vector. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: none */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +Get_DBCS_vector() /*;AN000;*/ +{ /*;AN000;*/ + WORD *ptr; /*;AN000;*/ + WORD *buffer; /*;AN000;*/ + DWORD far *addr_ptr; /*;AN000;*/ + + /* allocate a buffer for DBCS table vector */ + buffer = Dallocate(5); /* at least 5 bytes big */ /*;AN000;*/ + + inregs.x.ax = 0x6507; /* get extended country info */ /*;AN000;*/ + inregs.x.bx = -1; /* use active code page */ /*;AN000;*/ + inregs.x.cx = 5; /* 5 bytes of return data */ /*;AN000;*/ + inregs.x.dx = -1; /* use default country */ /*;AN000;*/ + inregs.x.di = 0; /* buffer offset */ /*;AN000;*/ + segregs.es = (WORD)buffer; /* buffer segment */ /*;AN000;*/ + intdosx(&inregs,&outregs,&segregs); /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ + + outregs.x.di++; /* skip over id byte */ /*;AN000;*/ + + /* make a far ptr from ES:[DI] */ + addr_ptr = 0; /*;AN000;*/ + ptr = (WORD *)&addr_ptr; /*;AN000;*/ + *ptr = (WORD)outregs.x.di; /* get offset */ /*;AN000;*/ + ptr++; /*;AN000;*/ + *ptr = (WORD)segregs.es; /* get segment */ /*;AN000;*/ + DBCS_ptr = (BYTE far *)*addr_ptr; /*;AN000;*/ + DBCS_ptr += 2; /* skip over table length */ /*;AN000;*/ + + /* DBCS_ptr points to DBCS table */ /*;AN000;*/ + strcpy(fix_es_reg,NUL); /*;AN000;*/ +} /*;AN000;*/ + + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Error_exit() */ +/* */ +/* Subroutine Function: */ +/* displays an extended error message with - filename */ +/* */ +/* Input: error_file_name[] must contain name of file, if needed for */ +/* message output. */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +void Error_exit(msg_class,ext_err_num,subcnt) /*;AN000;*/ + /*;AN000;*/ + int msg_class; /*;AN000;*/ + int ext_err_num; /*;AN000;*/ + int subcnt; /*;AN000;*/ +{ /*;AN000;*/ + segread(&segregs); /*;AN000;*/ + msg_error.sub_value_seg = segregs.ds; /*;AN000;*/ + msg_error.sub_value = (WORD)error_file_name; /*;AN000;*/ + inregs.x.ax = (WORD)ext_err_num; /*;AN000;*/ + inregs.x.bx = STDERR; /*;AN000;*/ + inregs.x.cx = subcnt; /*;AN000;*/ + inregs.h.dh = (WORD)msg_class; /*;AN000;*/ + inregs.h.dl = NOINPUT; /*;AN000;*/ + inregs.x.si = (WORD)&msg_error; /*;AN000;*/ + sysdispmsg(&inregs,&outregs); /*;AN000;*/ + + /* check for error printing message */ + if (outregs.x.cflag & CARRY) { /*;AN000;*/ + outregs.x.bx = (WORD) STDERR; /*;AN000;*/ + outregs.x.si = NOSUBPTR; /*;AN000;*/ + outregs.x.cx = NOSUBCNT; /*;AN000;*/ + outregs.h.dl = exterr_msg_class; /*;AN000;*/ + sysdispmsg(&outregs,&outregs); /*;AN000;*/ + } /*;AN000;*/ + + Reset_appendx(); /* Reset APPEND /X status */ /*;AN000;*/ + exit(1); /*;AN000;*/ +} /*;AN000;*/ + + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: Parse_err() */ +/* */ +/* Subroutine Function: */ +/* displays an parser error message with - filename */ +/* */ +/* Input: error_file_name[] must contain name of file, if needed for */ +/* message output. */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +void Parse_err(error_num) /*;AN000;*/ + + WORD error_num; /*;AN000;*/ +{ /*;AN000;*/ + char *cptr; /*;AN000;*/ + char *sptr; /*;AN000;*/ + + /* take out leading spaces, point to beginning of parameter */ + for (((int)sptr) = inregs.x.si; ((int)sptr) < outregs.x.si && *sptr == BLANK; sptr++) /*;AN000;*/ + /* null statement */ ; /*;AN000;*/ + + /* find end of this parameter in command line and put end-of-string there */ + for (cptr = sptr; ((int)cptr) < outregs.x.si && *cptr != BLANK; cptr++) /*;AN000;*/ + /* null statement */ ; /*;AN000;*/ + *cptr = NUL; /*;AN000;*/ + strcpy(error_file_name,sptr); /*;AN000;*/ + + /* check for messages with no parameter */ + if (error_num == p_op_missing) /*;AN000;*/ + Error_exit(ERR_PARSE,error_num,NOSUBCNT); /*;AN000;*/ + else /*;AN000;*/ + Error_exit(ERR_PARSE,error_num,ONEPARM); /*;AN000;*/ +} /*;AN000;*/ + + + + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* */ +/* Subroutine Name: ctl_brk_handler */ +/* */ +/* Subroutine Function: */ +/* Crtl-break interrupt handler. */ +/* */ +/* Input: none */ +/* */ +/* Output: none */ +/* */ +/* Normal exit: */ +/* */ +/* Error exit: None */ +/* */ +/* Internal References: */ +/* None */ +/* */ +/* External References: */ +/* None */ +/* */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +void ctl_brk_handler() +{ + Reset_appendx(); + exit(3); /*;AN000;*/ +/* inregs.x.ax = 0x4c03; /* DOS terminate int call */ /*;AN000;*/ +/* intdos(&inregs,&outregs); /*;AN000;*/ +} diff --git a/v4.0/src/CMD/ATTRIB/ATTRIB.H b/v4.0/src/CMD/ATTRIB/ATTRIB.H new file mode 100644 index 0000000..5297d11 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIB.H @@ -0,0 +1,443 @@ +/* Module ATTRIB.H */ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* All defines for attrib.c */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +#define FALSE 0 /*;AN000;*/ +#define TRUE !FALSE /*;AN000;*/ + +#ifndef BYTE +#define BYTE unsigned char /*;AN000;*/ +#define WORD unsigned short /*;AN000;*/ +#define DWORD unsigned long /*;AN000;*/ +#endif + +#define CARRY 0x0001 /*;AN000; carry flag */ + +#define YES 1 /*;AN000; Yes return from int 21h Y/N check */ +#define NO 0 /*;AN000; NO return from int 21h Y/N check */ + +#define NUL 0x0 /*;AN000;*/ +#define BLANK 0x20 /*;AN000;*/ +#define TAB 0x09 /*;AN000;*/ +#define CR 0x0d /*;AN000;*/ +#define LF 0x0a /*;AN000;*/ + +/* Error_exit() parameter values */ +#define ERR_EXTENDED 1 /*;AN000;*/ +#define ERR_PARSE 2 /*;AN000;*/ + + +/* standard file handles */ +#define STDIN 0x00 /*;AN000; Standard Input device handle */ +#define STDOUT 0x01 /*;AN000; Standard Output device handle */ +#define STDERR 0x02 /*;AN000; Standard Error Output device handle */ +#define STDAUX 0x03 /*;AN000; Standard Auxiliary device handle */ +#define STDPRN 0x04 /*;AN000; Standard Printer device handle */ + +/* attribute byte defines */ +#define AFILE 0x00 /*;AN000;*/ +#define READONLY 0x01 /*;AN000;*/ +#define HIDDEN 0x02 /*;AN000;*/ +#define SYSTEM 0x04 /*;AN000;*/ +#define LABEL 0x08 /*;AN000;*/ +#define SUBDIR 0x10 /*;AN000;*/ +#define ARCHIVE 0x20 /*;AN000;*/ + +/* extended attribute type defines */ +#define EAISUNDEF 0 /*;AN000; undefined type */ +#define EAISLOGICAL 1 /*;AN000; logical (0 or 1) */ +#define EAISBINARY 2 /*;AN000; binary integer */ +#define EAISASCII 3 /*;AN000; ASCII type */ +#define EAISDATE 4 /*;AN000; DOS file date format */ +#define EAISTIME 5 /*;AN000; DOS file time format */ + +#define EANAMES 6 /*;AN000; ext attr names ASCII */ + +/* extended attribute flag defines */ +#define EASYSTEM 0x8000 /*;AN000; EA is system defined */ +#define EAREADONLY 0x4000 /*;AN000; EA is read only */ +#define EAHIDDEN 0x2000 /*;AN000; EA is hidden */ +#define EACREATEONLY 0x1000 /*;AN000; EA is setable only at create time */ + +/* extended attribute failure return code defines */ +#define EARCNOERROR 0 /*;AN000; no error */ +#define EARCNOTFOUND 1 /*;AN000; name not found */ +#define EARCNOSPACE 2 /*;AN000; no space to hold name or value */ +#define EARCNOTNOW 3 /*;AN000; name can't be set on this function */ +#define EARCNOTEVER 4 /*;AN000; name can't be set */ +#define EARCUNDEF 5 /*;AN000; name known to this FS but not supported */ +#define EARCDEFBAD 6 /*;AN000; EA definition bad (TYPE,LENGTH, etc.) */ +#define EARCACCESS 7 /*;AN000; EA access denied */ +#define EARCVALBAD 8 /*;AN000; EA value not supported */ +#define EARCUNKNOWN -1 /*;AN000; undetermined cause */ + +/* message retriever interface defines */ +#define NOSUBPTR 0 /*;AN000; no sublist pointer */ +#define NOSUBCNT 0 /*;AN000; 0 substitution count */ +#define ONEPARM 1 /*;AN000; 1 substitution count */ +#define TWOPARM 2 /*;AN000; 2 substitution count */ +#define NOINPUT 0 /*;AN000; no user input */ +#define INPUT 1 /*;AN000; ask user for Y/N input */ + +/* misc. defines */ +#define A_FILESIZE 1 /* id of special attribute: filesize */ +#define A_DATE 2 /* id of special attribute: date */ +#define A_TIME 3 /* id of special attribute: time */ + +#define MAX_ATTR_SIZE 160 /*;AN000; max ext attribute buffer size */ +#define MAX_KEYWORD 128 /*;AN000; max size of extended attribute keyword */ +#define MAX_SPL 3 /*;AN000; max number of special attributes */ + +#define ATTR_SIZE 7 /*;AN000; size in bytes of attr struct */ +#define NAME_SIZE 4 /*;AN000; size in bytes of name struct */ + +#define NOERROR 0 /*;AN000;*/ +#define NOMOREFILES 18 /*;AN000;*/ +#define FILENOTFOUND 2 /*;AN000;*/ + +#define GET_DATE 1 /*;AN000;*/ +#define GET_TIME 2 /*;AN000;*/ + +#define INACTIVE 0x7fff /*;AN000;*/ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* All structures defined for attrib.c */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +struct p_null { /*;AN000; a null value list for parser */ + unsigned char null; /*;AN000;*/ + }; /*;AN000;*/ + +struct query_list { /*;AN000; Generic attribute overlay structure */ + WORD ql_num; + BYTE ql_type; /*;AN000; EA type */ + WORD ql_flags; /*;AN000; EA flags */ + BYTE ql_name_len; /*;AN000; name length */ + char ql_name[MAX_KEYWORD]; /*;AN000; name */ + }; /*;AN000;*/ + +struct name_list { /*;AN000; Generic attribute overlay structure */ + BYTE nl_type; /*;AN000; EA type */ + WORD nl_flags; /*;AN000; EA flags */ + BYTE nl_name_len; /*;AN000; name length */ + char nl_name[MAX_KEYWORD]; /*;AN000; name */ + }; /*;AN000;*/ + +struct attr_list { /*;AN000; Generic attribute overlay structure */ + BYTE at_type; /*;AN000; EA type */ + WORD at_flags; /*;AN000; EA flags */ + BYTE at_rc; /*;AN000; EA return code */ + BYTE at_name_len; /*;AN000; name length */ + WORD at_value_len; /*;AN000; value length */ + char at_name[MAX_KEYWORD]; /*;AN000; name */ + }; /*;AN000;*/ + +struct parm_list { /*;AN000; Parm list for extended open DOS call */ + DWORD pm_list; /*;AN000; extended attr. list */ + WORD pm_num_parms; /*;AN000; number of parameters */ + BYTE pm_id; /*;AN000; id */ + WORD pm_iomode; /*;AN000; iomode */ + }; /*;AN000;*/ + +struct spl_list { /*;AN000;*/ + char name[MAX_KEYWORD]; /*;AN000;*/ + WORD id; /*;AN000;*/ + }; /*;AN000;*/ + +struct bin_struct { /*;AN000;*/ + BYTE length; /*;AN000;*/ + DWORD dword; /*;AN000;*/ + }; /*;AN000;*/ + +union eav_union { /*;AN000;*/ + WORD ea_undef; /*;AN000;*/ + BYTE ea_logical; /*;AN000;*/ + struct bin_struct ea_bin; /*;AN000;*/ + char ea_ascii[129]; /*;AN000;*/ + DWORD ea_time; /*;AN000;*/ + DWORD ea_date; /*;AN000;*/ + }; /*;AN000;*/ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/* All global variables for attrib.c */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +struct spl_list specials[MAX_SPL] = { /*;AN000;*/ + "FILESIZE", A_FILESIZE, /*;AN000;*/ + "DATE", A_DATE, /*;AN000;*/ + "TIME", A_TIME }; /*;AN000;*/ + + +/* parser structure variables */ +union eav_union ext_attr_value; /*;AN000; result value union */ + +struct p_result_blk pos1_buff; /*;AN000; result buffer for -+A,-+R */ +struct p_result_blk pos2_buff; /*;AN000; result buffer for -+A,-+R */ +struct p_result_blk pos3_buff; /*;AN000; result buffer for filespec */ +struct p_result_blk pos4_buff; /*;AN000; result buffer for -+A,-+R */ +struct p_result_blk pos5_buff; /*;AN000; result buffer for -+A,-+R */ +struct p_result_blk pos6_buff; /*;AN000; result buffer for id */ +struct p_result_blk pos6b_buff; /*;AN000; result buffer for id */ +struct p_result_blk sw_buff; /*;AN000; result buffer for /S */ + +char nullword[] = " "; /*;AN000; used when no word attribute */ +char nulldword[] = " "; /*;AN000; used when no double word attribute */ +char nulldate[] = " "; /*;AN000; used when no date attribute */ +char nulltime[] = " "; /*;AN000; used when no time attribute */ + +char plusa[] = "+A"; /*;AN000; strings for match */ +char minusa[] = "-A"; /*;AN000;*/ +char plusr[] = "+R"; /*;AN000;*/ +char minusr[] = "-R"; /*;AN000;*/ + +struct p_null noval = /*;AN000; structure for no value list */ + { 0 }; /*;AN000;*/ + +struct ps_valist_blk vals1 = /*;AN000; +A-A+R-R value list */ + { p_nval_string, /*;AN000; string value list type */ + 0, /*;AN000; number of ranges */ + 0, /*;AN000; number of numbers */ + 4, /*;AN000; number of strings */ + 0x20, /*;AN000; item tag */ + (WORD)plusa, /*;AN000; address of string */ + 0x20, /*;AN000; item tag */ + (WORD)minusa, /*;AN000; address of string */ + 0x01, /*;AN000; item tag */ + (WORD)plusr, /*;AN000; address of string */ + 0x01, /*;AN000; item tag */ + (WORD)minusr }; /*;AN000; address of string */ + +struct p_control_blk p_con1 = /*;AN000; describes +-A or +-R */ + { 0x2001, /*;AN000; Simple string,optional */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos1_buff, /*;AN000;*/ + (WORD)&vals1, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con2 = /*;AN000; describes +-A or +-R (2nd occurrance) */ + { 0x2001, /*;AN000; Simple string,optional */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos2_buff, /*;AN000;*/ + (WORD)&vals1, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con3 = /*;AN000; describes filespec */ + { 0x0200, /*;AN000; File spec required */ + 0x0001, /*;AN000; Cap result by file table */ + (WORD)&pos3_buff, /*;AN000;*/ + (WORD)&noval, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con4 = /*;AN000; describes +-A or +-R */ + { 0x2001, /*;AN000; Simple string,optional */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos4_buff, /*;AN000;*/ + (WORD)&vals1, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con5 = /*;AN000; describes +-A or +-R (2nd occurrance) */ + { 0x2001, /*;AN000; Simple string,optional */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos5_buff, /*;AN000;*/ + (WORD)&vals1, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con6 = /*;AN000; describes id */ + { 0x2001, /*;AN000; Simple string,optional */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos6_buff, /*;AN000;*/ + (WORD)&noval, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con6a = /*;AN000; describes id */ + { 0x2000, /*;AN000; Simple string */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&pos6_buff, /*;AN000;*/ + (WORD)&noval, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_con6b = /*;AN000; describes id */ + { 0xe481, /*;AN000; Quoted string */ + 0x0002, /*;AN000;*/ + (WORD)&pos6b_buff, /*;AN000;*/ + (WORD)&noval, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_control_blk p_swi1 = /*;AN000; Switch control block */ + { 0x0001, /*;AN000; Optional (switch) */ + 0x0002, /*;AN000; Cap result by char table */ + (WORD)&sw_buff, /*;AN000;*/ + (WORD)&noval, /*;AN000;*/ + 1, /*;AN000; one switch allowed */ + "/S" }; /*;AN000; /S */ + +struct p_parmsx p_px1 = /*;AN000; Parser Control definition for Parm Block 1 */ + { 1, /*;AN000; positionals */ + 6, /*;AN000;*/ + &p_con1, /*;AN000;*/ + &p_con2, /*;AN000;*/ + &p_con3, /*;AN000;*/ + &p_con4, /*;AN000;*/ + &p_con5, /*;AN000;*/ + &p_con6, /*;AN000;*/ + 1, /*;AN000; switches */ + &p_swi1, /*;AN000;*/ + 0, /*;AN000; keywords*/ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_parms p_p1 = /*;AN000; Parms block for line */ + { &p_px1, /*;AN000; Address of extended parm list */ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_parmsx p_px2 = /*;AN000; Parser Control definition for Parm Block 1 */ + { 1, /*;AN000; positionals */ + 2, /*;AN000;*/ + &p_con6a, /*;AN000;*/ + &p_con6b, /*;AN000;*/ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 1, /*;AN000; switches */ + &p_swi1, /*;AN000;*/ + 0, /*;AN000; keywords*/ + 0, /*;AN000;*/ + 0, /*;AN000;*/ + 0 }; /*;AN000;*/ + +struct p_parms p_p2 = /*;AN000; Parms block for line */ + { &p_px2, /*;AN000; Address of extended parm list */ + 1, /*;AN000;*/ + 1, /*;AN000;*/ + "=" }; /*;AN000;*/ + +/* extended open structure variables */ +struct parm_list plist = /*;AN000; Extended open parm list */ + { -1, /*;AN000; ptr to attr. list */ + 1, /*;AN000; number of parms */ + 6, /*;AN000; id */ + 2 }; /*;AN000; iomode */ + +/* messgages */ +struct m_sublist msg_num = /*;AN000; describes substitutions */ + { 72, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_unsbin2d | sf_right, /*;AN000; unsigned binary to decimal*/ + 9, /*;AN000; */ + 9, /*;AN000; */ + 0 }; /*;AN000; */ +struct m_sublist msg_str2 = /*;AN000; describes substitutions */ + { 60, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_left | sf_char | sf_asciiz, /*;AN000; string */ + 0, /*;AN000; null string */ + 0, /*;AN000; */ + (BYTE)" " }; /*;AN000; */ +struct m_sublist msg_dword = /*;AN000; describes substitutions */ + { 48, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_unsbin2d | sf_dword | sf_right, /*;AN000; unsigned binary to decimal*/ + 10, /*;AN000; */ + 9, /*;AN000; */ + 0 }; /*;AN000; */ +struct m_sublist msg_date = /*;AN000; describes substitutions */ + { 36, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_date | sf_mdy2, /*;AN000; unsigned binary to decimal*/ + 9, /*;AN000; */ + 9, /*;AN000; */ + 0 }; /*;AN000; */ +struct m_sublist msg_time = /*;AN000; describes substitutions */ + { 24, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_time12 | sf_hhmm | sf_right, /*;AN000; unsigned binary to decimal*/ + 9, /*;AN000; NN-NN-NNa (9 characters) */ + 9, /*;AN000; */ + 0 }; /*;AN000; */ +struct m_sublist msg_str = /*;AN000; describes substitutions */ + { 12, /*;AN000; for parm one of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 1, /*;AN000; */ + sf_left | sf_char | sf_asciiz, /*;AN000; string */ + 9, /*;AN000; null string */ + 9, /*;AN000; */ + (BYTE)" " }; /*;AN000; */ +struct m_sublist msg_str1 = /*;AN000; describes substitutions */ + { 12, /*;AN000; for parm two of message */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 2, /*;AN000; */ + sf_left | sf_char | sf_asciiz, /*;AN000; string */ + 0, /*;AN000; null string */ + 0, /*;AN000; */ + (BYTE)" " }; /*;AN000; */ +struct m_sublist msg_error = /*;AN000; describes substitutions */ + { 12, /*;AN000; for extended error messages*/ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + 0, /*;AN000; */ + sf_left | sf_char | sf_asciiz, /*;AN000; string */ + 0, /*;AN000; null string */ + 0, /*;AN000; */ + (BYTE)" " }; /*;AN000; */ + +/* misc. variables */ +union REGS inregs, /*;AN000; Registers */ + outregs; /*;AN000;*/ +struct SREGS segregs; /*;AN000; Segment registers */ + +DWORD old_int24_off; /*;AN000;*/ + +WORD descending; /*;AN000;*/ +WORD append_x_status; /*;AN000;*/ +WORD did_attrib_ok; /*;AN000;*/ +WORD set_reg_attr, /*;AN000;*/ + set_ext_attr; /*;AN000;*/ +WORD do_reg_attr, /*;AN000;*/ + do_ext_attr; /*;AN000;*/ + +BYTE far *DBCS_ptr; /*;AN000;*/ +BYTE ext_attr_value_type; /*;AN000;*/ +BYTE attr; /*;AN000;*/ +BYTE bits[8] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; /*;AN000;*/ +BYTE pmask, /*;AN000;*/ + mmask; /*;AN000;*/ + +char as[8] = { ' ',' ','A',' ',' ',' ',' ','R' }; /*;AN000;*/ +char fix_es_reg[1]; /*;AN000;*/ +char ext_attr[MAX_KEYWORD]; /*;AN000;*/ +char error_file_name[256]; /*;AN005;*/ +char fspec[256]; /*;AN000;*/ +char file[256]; /*;AN000;*/ +char str_on[3] = {"ON"}; /*;AN000;*/ +char str_off[4] = {"OFF"}; /*;AN000;*/ diff --git a/v4.0/src/CMD/ATTRIB/ATTRIB.LNK b/v4.0/src/CMD/ATTRIB/ATTRIB.LNK new file mode 100644 index 0000000..89de3bf --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIB.LNK @@ -0,0 +1,7 @@ +attriba+ +attrib+ +_parse+ +_msgret +attrib +nul; + diff --git a/v4.0/src/CMD/ATTRIB/ATTRIB.SKL b/v4.0/src/CMD/ATTRIB/ATTRIB.SKL new file mode 100644 index 0000000..aab62fa --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIB.SKL @@ -0,0 +1,30 @@ +:util ATTRIB ;utility name ;AN000; + +:class 1 ;AN000; + +:class 2 ;AN000; + +:class A ;system messages ;AN000; +:use 1 COMMON1 ;"Incorrect DOS version" ;AN000; +:use 2 EXTEND8 ;"Insufficient memory" ;AN000; + +:class B ;AN000; +:def 8 " %1" ;AN000; +:def 9 "%1 %2",CR,LF ;AN000; +:def 10 "%1",CR,LF,"%2",CR,LF ;AN000; +:def 11 "Code page mismatch - %1",CR,LF,"Are you sure (Y/N)?" ;AN000; +:def 12 "%1",CR,LF ;AN000; +:def 14 CR,LF ;AN000; +:def 15 "Invalid file type value",CR,LF ;AN000; + +;;; Change these extended attribute error msgs back when adding ext. attr. +;;; function in DOS. +;;;:def 199 "Extended attribute error",CR,LF ;AN000; +;;;:def 201 "Extended attribute name not found",CR,LF ;AN000; +;;;:use 202 EXTEND8 ;"Insufficient memory" ;AN000; +;;;:def 204 "Extended attribute name can't be set",CR,LF ;AN000; +;;;:def 205 "Extended attribute name known to this filesystem but not supported",CR,LF ;AN000; +;;;:def 206 "Extended attribute type mismatch",CR,LF ;AN000; +;;;:def 208 "Extended attribute value not supported",CR,LF ;AN000; + +:end ;AN000; diff --git a/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM b/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM new file mode 100644 index 0000000..4f9c312 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM @@ -0,0 +1,480 @@ + page ,132 ; + title New_C.C - DOS entry to the KWC's 'C' programs + +; +; This module has been modified extensively for my personal +; use. +; +; name XCMAIN -- initiate execution of C program +; +; description This is the main module for a C program on the +; DOS implementation. It initializes the segment +; registers, sets up the stack, and calls the C main +; function _main with a pointer to the remainder of +; the command line. +; +; Also defined in this module is the exit entry point +; XCEXIT. +; +; $salut (4,12,18,41) +SETBLOCK EQU 4AH ;MODIFY ALLOCATED MEMORY BLOCKS + ;ES = SEGMENT OF THE BLOCK + ;BX = NEW REQUESTED BLOCK SIZE + ; IN PARAGRAPHS + ;OUTPUT: BX=MAX SIZE POSSIBLE IF CY SET + ;AX = ERROR CODE IF CY SET + +RET_CD_EXIT EQU 4CH ;EXIT TO DOS, PASSING RETURN CODE + ;AL=RETURN CODE + +RET_EXIT equ 4ch ;AN000; ;terminate +ABORT equ 2 ;AN000; ;if >=, retry +XABORT equ 1 ;AN000; ;errorlevel return in al + + + extrn _inmain:near ;AC000; + extrn _Reset_appendx:near ;AN000; + extrn _old_int24_off:dword ;AN000; + + +psp segment at 0 ;<--emk +psp_ret dw ? ;int 20h +psp_memsz dw ? ;memory size + org 2ch +psp_env dw ? ;segid of environment + org 80h +psp_parlen db ? ;length of DOS command line parms +psp_par db 127 dup(?) ;DOS command line parms +psp ends + page + +; +; The following segment serves only to force "pgroup" lower in +; memory. +; + +base segment PARA PUBLIC 'DATA' + + db 00dh,00ah + db "----------\x0d\x0a" + db " DOS ATTRIB function \x0d\x0a" + db "--------------------\x0d\x0a" + db 00dh,00ah,01ah + +base ends + + +; +; The data segment defines locations which contain the offsets +; of the base and top of the stack. +; + +_data segment PARA public 'DATA' + + irp name,<_top,_base,_cs,_ss,_psp,_env,_rax,_rbx,_rcx,_rdx,_rds,_rsi,_rbp,_res,_rdi> + public name +name dw 0 + endm + +_data ends + +; +; The stack segment is included to prevent the warning from the +; linker, and also to define the base (lowest address) of the stack. +; + +stack segment PARA stack 'data' + +SBase dw 128 dup (?) + +stack ends + +null segment para public 'BEGDATA' +null ends +const segment word public 'CONST' +const ends +_bss segment word public 'BSS' +_bss ends +pgroup group base,_text +dgroup group null, _data, const, _bss, stack + + page + +; +; The main program must set up the initial segment registers +; and the stack pointer, and set up a far return to the DOS +; exit point at ES:0. The command line bytes from the program +; segment prefix are moved onto the stack, and a pointer to +; them supplied to the C main module _main (which calls main). +; + +_text segment PARA public 'CODE' + + public XCMAIN + + assume cs:pgroup + assume ds:psp ;<--emk + assume es:psp ;<--emk + assume ss:stack ;<--emk + +XCMAIN proc far + + mov ax,dgroup + mov ds,ax ;initialize ds and ss + assume ds:dgroup + + mov bx,psp_memsz ;total memory size (paragraphs) + sub bx,ax + test bx,0f000h +; $IF Z ;branch if more than or equal 64K bytes + JNZ $$IF1 + + mov cl,4 + shl bx,cl ;highest available byte +; $ELSE + JMP SHORT $$EN1 +$$IF1: + mov bx,0fff0h +; $ENDIF +$$EN1: + cli ; disable interrupts while changing stack <---kwc + mov ss,ax ; set ss <---kwc + mov sp,bx ; set stack pointer <---kwc + sti ;enable interrupts + assume ss:DGroup ;<--emk + + mov _ss,ss + mov _cs,cs + mov _top,bx ;save top of stack + + mov ax,offset DGroup:SBase + mov _base,ax ;store ptr to bottom of stack + +; code added here to allow allocates and exec's in the c code +; we will have to calculate the size of the code that has been loaded + + mov bx,sp ; bx = length of the stack + shr bx,1 + shr bx,1 + shr bx,1 + shr bx,1 ; bx = number of paragraphs in stack, + add bx,1 ; (fudge factor!)<--emk ,was 10 + mov ax,ss + add bx,ax ; bx = paragraph a little past the stack + mov ax,es ; ax = paragraph of the psp + sub bx,ax ; bx = number of paragraphs in code + mov ah,setblock + int 021h + +; end of added code! + + mov _psp,es ; save pointer to psp for setblock <---kwc + mov cl,psp_parlen ;get number of bytes <--emk + xor ch,ch ;cx = number of bytes of parms! + mov si,offset psp_par ;point to DOS command line parms <--emk + +; more modified code, picking up argv[0] from the environment! + + mov ds,psp_env ;set ds to segid of environment from es:psp + assume ds:nothing + + mov _env,ds ;remember where environment is + + mov si,0 ;clear index to step thru env +;The env has a set of keyword=operand, each one ending with a single null byte. +;At the end of the last one is a double null. We are looking for the end of +;all these keywords, by looking for the double null. +; $DO COMPLEX + JMP SHORT $$SD4 +$$DO4: + inc si ;bump index to look at next byte in env +; $STRTDO +$$SD4: + cmp word ptr [si],0 ;is this a double null delimiter? +; $ENDDO E ;ifdouble null found, exit + JNE $$DO4 +;At end of env is the double null and a word counter + add si,4 ;step over this double null delimiter + ; and the following word counter + push si ;save pointer to next field in env +;This is the invocation statement, including the path name, even if not specified +;but supplied by PATH. + +;continue stepping thru env looking for one more null byte, which indicates +;the end of the invocation command. +; $DO +$$DO7: + lodsb ;get a byte from env to al + cmp al,0 ;is this a null byte? +; $ENDDO E ;quit if null is found + JNE $$DO7 + + mov bx,si ; bx -> asciiz zero + pop si ; si -> first byte of agrv[0], the invocation command + sub bx,si ; bx = length of argv[0] + mov dx,bx ; (save for the copy later) + dec dx + add bx,cx ; add in the length of the rest of the parms + inc bx ; add one for the asciiz zero! + and bx,0fffeh ;force even number of bytes + add bx,2 ;adjust for possible rounding error + sub sp,bx ;allocate space on stack + mov di,sp ; (es:di) -> where we will put the stuff + push es + mov ax,ss + mov es,ax + xchg cx,dx ; length of argv[0] to copy, save length of parms + rep movsb ; (ds:si) already point to argv[0] + pop es + mov ss:byte ptr [di],' ' ;store trailing blank! + inc di + mov _rdi,di ;AN000; save start of command parms + xchg cx,dx ; restore length of parms +; $IF NCXZ ;if some bytes to move, + JCXZ $$IF9 + + mov si,offset psp_par ;point to DOS command line parms in psp +; $DO +$$DO10: + mov al,es:[si] ;move bytes to stack + mov ss:[di],al + inc si + inc di +; $ENDDO LOOP + LOOP $$DO10 +; $ENDIF ;bytes to move? +$$IF9: + xor ax,ax + mov ss:[di],al ;store null byte + mov ax,ss + mov ds,ax ;es, ds, and ss are all equal + assume ds:DGroup + + mov es,ax ;es, ds, and ss are all equal + assume es:DGroup + + mov ax,_rdi ;AN000; restore offset of parms on stack + push ax ;ptr to command line + + call _inmain ;AC000; call C main + + mov ah,ret_cd_exit ;return to DOS + int 21h ;errorlevel ret code in al + +XCMAIN endp + + page + +; +; name XCEXIT -- terminate execution of C program +; +; description This function terminates execution of the current +; program by returning to DOS. The error code +; argument normally supplied to XCEXIT is ignored +; in this implementation. +; +; input - al = binary return code for dos/ERRORLEVEL +; + + assume cs:PGroup + assume ds:DGroup + assume es:DGroup + assume ss:DGroup + + public xcexit +XCEXIT proc far + + mov ah,ret_cd_exit ; <--- kwc + int 021h ; <--- kwc + +XCEXIT endp + +;-------------------------------------------------------------------------- + + PAGE + +CENTER MACRO NAMELIST + PUSH BP ; SAVE CURRENT BP + MOV BP,SP ; POINT AT STACK WITH BP +WORKOFS = 0 + IRP ANAME, ; FOR EACH WORKING VARIABLE + IFNB <&ANAME> +WORKOFS = WORKOFS-2 ; WE WILL ALLOCATE ONE + DOEQU &ANAME,%WORKOFS ; WORD ON THE STACK THAT + ENDIF + ENDM ; IS UNDER SS,BP + ADD SP,WORKOFS + ENDM + +DOEQU MACRO NAME,VALUE +&NAME EQU &VALUE + ENDM + +CEXIT MACRO VALUE + MOV SP,BP + POP BP + RET + ENDM + + PAGE + +; INPUT PARAMATERS PASSED ON STACK + +PARMS STRUC + +OLD_BP DW ? ; SAVED BP +RETADD DW ? ; RETURN ADDRESS +PARM_1 DW ? +PARM_2 DW ? +PARM_3 DW ? +PARM_4 DW ? +PARM_5 DW ? +PARM_6 DW ? +PARM_7 DW ? +PARM_8 DW ? + +PARMS ENDS + +SAVE_SS DW 0 +SAVE_SP DW 0 + + PAGE + +;************************************************************************ +; ; +; Subroutine Name: ; +; getpspbyte ; +; ; +; Subroutine Function: ; +; get a byte from PSP ; ; +; ; +; Input: ; +; SS:[BP]+PARM1 = offset in PSP ; +; ; +; Output: ; +; AL = byte from PSP:offset ; +; ; +; C calling convention: ; +; char = getpspbyte(offset); ; +; ; +;************************************************************************ + +MOFFSET EQU PARM_1 ;AN000; + + ASSUME CS:PGROUP ;AN000; + ASSUME DS:DGROUP ;AN000; + ASSUME ES:DGROUP ;AN000; + ASSUME SS:DGROUP ;AN000; + + PUBLIC _GETPSPBYTE ;AN000; +_GETPSPBYTE PROC NEAR ;AN000; + + CENTER ;AN000; + + PUSH DS ;AN000; + + MOV DS,_PSP ;AN000; get save PSP segment + MOV SI,[BP].MOFFSET ;AN000; get offset into PSP + LODSB ;AN000; get PSP byte + MOV AH,0 ;AN000; zero high byte + + POP DS ;AN000; + + CEXIT ;AN000; + +_GETPSPBYTE ENDP + + +;************************************************************************ +; ; +; Subroutine Name: ; +; putpspbyte ; +; ; +; Subroutine Function: ; +; put a byte into PSP ; ; +; ; +; Input: ; +; SS:[BP]+MVALUE = byte in AL ; +; SS:[BP]+MOFFSET = offset in PSP ; +; ; +; Output: ; +; none ; +; ; +; C calling convention: ; +; putpspbyte(offset,char); ; +; ; +;************************************************************************ + + +MVALUE EQU PARM_2 ;AN000; +MOFFSET EQU PARM_1 ;AN000; + + ASSUME CS:PGROUP ;AN000; + ASSUME DS:DGROUP ;AN000; + ASSUME ES:DGROUP ;AN000; + ASSUME SS:DGROUP ;AN000; + + PUBLIC _PUTPSPBYTE ;AN000; +_PUTPSPBYTE PROC NEAR ;AN000; + + CENTER ;AN000; + + PUSH ES ;AN000; + + MOV AX,[BP].MVALUE ;AN000; get byte to store in PSP + MOV ES,_PSP ;AN000; get saved PSP segment + MOV DI,[BP].MOFFSET ;AN000; get offset in PSP + STOSB ;AN000; store the byte + + POP ES ;AN000; + + CEXIT ;AN000; + +_PUTPSPBYTE ENDP + + +;------------------------------------------------------------------- +; +; MODULE: crit_err_handler() +; +; PURPOSE: Supplies assembler exit routines for +; critical error situations +; +; CALLING FORMAT: +; crit_err_handler; +;------------------------------------------------------------------- + public _crit_err_handler ;AN000; + public vector ;AN000; +vector dd 0 ;AN000; +; ;AN000; +_crit_err_handler proc near ;AN000; + pushf ;AN000; + push ax ; save registers ;AN000; + push ds ;AN000; + mov ax,dgroup ;get C data segment ;AN000; + mov ds,ax ;AN000; + mov ax,word ptr ds:_old_int24_off ;get int24 offset ;AN000; + mov word ptr cs:vector,ax ;AN000; + mov ax,word ptr ds:_old_int24_off+2 ;get int24 segment ;AN000; + mov word ptr cs:vector+2,ax ;AN000; + pop ds ;restore registers ;AN000; + pop ax ;AN000; +; ;AN000; + call dword ptr cs:vector ; invoke DOS err hndlr ;AN000; + cmp al,ABORT ; what was the user's response ;AN000; + jnge retry ; ;AN000; +; ;AN000; + mov ax,dgroup ;get C data segment ;AN000; + mov ds,ax ;AN000; + mov es,ax ;AN000; + call _Reset_appendx ; restore user's orig append/x ;AN000; +; ;AN000; + mov ax,(RET_EXIT shl 8)+XABORT ; return to DOS w/criterr error ;AN000; + int 21h ; ;AN000; +retry: ;AN000; + iret ;AN000; +; ;AN000; +_crit_err_handler endp ;AN000; +_text ends ;AN000; + end XCMAIN ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/ATTRIB/MAKEFILE b/v4.0/src/CMD/ATTRIB/MAKEFILE new file mode 100644 index 0000000..a9e670a --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/MAKEFILE @@ -0,0 +1,46 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: attrib.exe + +attrib.ctl: attrib.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +_parse.obj: _parse.asm \ + $(inc)\parse.asm \ + $(inc)\psdata.inc + +_msgret.obj: _msgret.asm \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc \ + $(inc)\copyrigh.inc \ + attrib.skl \ + attrib.ctl \ + attrib.cl1 \ + attrib.cl2 \ + attrib.cla \ + attrib.clb + +attriba.obj: attriba.asm + +attrib.obj: attrib.c \ + attrib.h \ + parse.h \ + msgret.h \ + makefile + +attrib.exe: attrib.obj \ + attriba.obj \ + _parse.obj \ + _msgret.obj \ + attrib.lnk + link @attrib.lnk diff --git a/v4.0/src/CMD/ATTRIB/MSGRET.H b/v4.0/src/CMD/ATTRIB/MSGRET.H new file mode 100644 index 0000000..0f00329 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/MSGRET.H @@ -0,0 +1,60 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the message retriever from a C program. | +| | +| | +| Date: 6-19-87 | +| | ++----------------------------------------------------------------------*/ + + +#define utility_msg_class 0xff /*;AN000; Utility message type */ +#define exterr_msg_class 0x01 /*;AN000;*/ + + +/* Sublist Flag Values */ + +/* Alignment Indicator */ +#define sf_left 0x00 /*;AN000; left align */ +#define sf_right 0x80 /*;AN000; right align */ + +/* Field Type */ +#define sf_char 0x00 /*;AN000; character */ +#define sf_unsbin2d 0x01 /*;AN000; unsigned binary to decimal */ +#define sf_sbin 0x02 /*;AN000; signed binary to decimal */ +#define sf_unsbin2h 0x03 /*;AN000; unsigned binary to hex */ +#define sf_date 0x04 /*;AN000; date */ +#define sf_time12 0x05 /*;AN000; time 12-hour */ +#define sf_time24 0x06 /*;AN000; time 24-hour */ + + +/* Data Variable Size */ + +#define sf_ch 0x00 /*;AN000; single character */ +#define sf_asciiz 0x10 /*;AN000; asciiz string */ +#define sf_byte 0x10 /*;AN000; byte */ +#define sf_word 0x20 /*;AN000; word */ +#define sf_dword 0x30 /*;AN000; double word */ + +#define sf_mdy2 0x20 /*;AN000; month,day,year (2 digits) */ +#define sf_mdy4 0x30 /*;AN000; month,day,year (4 digits) */ + +#define sf_hhmm 0x00 /*;AN000; hh:mm */ +#define sf_hhmmss 0x10 /*;AN000; hh:mm:ss */ +#define sf_hhmmsshh 0x20 /*;AN000; hh:mm:ss:hh */ + + +struct m_sublist /*;AN000; */ + { /*;AN000; */ + BYTE sub_size; /*;AN000; */ + BYTE sub_res; /*;AN000; */ + WORD sub_value; /*;AN000; */ + WORD sub_value_seg; /*;AN000; */ + BYTE sub_id; /*;AN000; */ + BYTE sub_flags; /*;AN000; */ + BYTE sub_max_width; /*;AN000; */ + BYTE sub_min_width; /*;AN000; */ + BYTE sub_pad_char; /*;AN000; */ + }; /*;AN000; */ diff --git a/v4.0/src/CMD/ATTRIB/PARSE.H b/v4.0/src/CMD/ATTRIB/PARSE.H new file mode 100644 index 0000000..2421481 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/PARSE.H @@ -0,0 +1,185 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the parser from a C program. | +| | +| | +| Date: 5-21-87 | +| | ++----------------------------------------------------------------------*/ + +#define BYTE unsigned char /*;AN000;*/ +#define WORD unsigned short /*;AN000;*/ +#define DWORD unsigned long /*;AN000;*/ + +#define p_len_parms 4 /* length of p_parms */ /*;AN000;*/ +#define p_i_use_default 0 /* no extra stuff specified */ /*;AN000;*/ +#define p_i_have_delim 1 /* extra delimiter specified */ /*;AN000;*/ +#define p_i_have_eol 2 /* extra EOL specified */ /*;AN000;*/ + +struct p_parms /*;AN000;*/ + { /*;AN000;*/ + struct p_parmsx *p_parmsx_address; /* address of p_parmsx */ /*;AN000;*/ + BYTE p_num_extra; /* number of extra stuff */ /*;AN000;*/ + BYTE p_len_extra_delim; /* length of extra delimiter */ /*;AN000;*/ + char p_extra_delim[30]; /* extra delimiters */ /*;AN000;*/ + }; /*;AN000;*/ + +struct p_parmsx /*;AN000;*/ + { /*;AN000;*/ + BYTE p_minp; /* Minimum positional number */ /*;AN000;*/ + BYTE p_maxp; /* Maximum positional number */ /*;AN000;*/ + struct p_control_blk *p_control1; /* Address of the 1st CONTROL block */ /*;AN000;*/ + struct p_control_blk *p_control2; /* Address of the 2nd CONTROL block */ /*;AN000;*/ + struct p_control_blk *p_control3; /* Address of the 3nd CONTROL block */ /*;AN000;*/ + struct p_control_blk *p_control4; /* Address of the 4th CONTROL block */ /*;AN000;*/ + struct p_control_blk *p_control5; /* Address of the 3nd CONTROL block */ /*;AN000;*/ + struct p_control_blk *p_control6; /* Address of the 4th CONTROL block */ /*;AN000;*/ + BYTE p_maxs; /*;AN000;*/ + struct p_control_blk *p_switch; /*;AN000;*/ + BYTE p_maxk; /*;AN000;*/ + struct p_control_blk *p_keyword1; /*;AN000;*/ + struct p_control_blk *p_keyword2; /*;AN000;*/ + struct p_control_blk *p_keyword3; /*;AN000;*/ + }; /*;AN000;*/ + +struct p_control_blk /*;AN000;*/ + { /*;AN000;*/ + WORD p_match_flag; /* Controls type matched */ /*;AN000;*/ + WORD p_function_flag; /* Function should be taken */ /*;AN000;*/ + WORD p_result_buf; /* Result buffer address */ /*;AN000;*/ + WORD p_value_list; /* Value list address */ /*;AN000;*/ + BYTE p_nid; /* # of keyword/SW synonyms */ /*;AN000;*/ + char p_keyorsw[20]; /* keyword or sw */ /*;AN000;*/ + }; /*;AN000;*/ + +/* Match_Flags */ /*;AN000;*/ +#define p_num_val 0x8000 /* Numeric Value */ /*;AN000;*/ +#define p_snum_val 0x4000 /* Signed numeric value */ /*;AN000;*/ +#define p_simple_s 0x2000 /* Simple string */ /*;AN000;*/ +#define p_date_s 0x1000 /* Date string */ /*;AN000;*/ +#define p_time_s 0x0800 /* Time string */ /*;AN000;*/ +#define p_cmpx_s 0x0400 /* Complex string */ /*;AN000;*/ +#define p_file_spc 0x0200 /* File Spec */ /*;AN000;*/ +#define p_drv_only 0x0100 /* Drive Only */ /*;AN000;*/ +#define p_qu_string 0x0080 /* Quoted string */ /*;AN000;*/ +#define p_ig_colon 0x0010 /* Ignore colon at end in match */ /*;AN000;*/ +#define p_repeat 0x0002 /* Repeat allowed */ /*;AN000;*/ +#define p_optional 0x0001 /* Optional */ /*;AN000;*/ + +/*----------------------------------------------------------------------+ +| | +| Function flags | +| | ++----------------------------------------------------------------------*/ + +#define p_cap_file 0x0001 /* CAP result by file table */ /*;AN000;*/ +#define p_cap_char 0x0002 /* CAP result by character table */ /*;AN000;*/ +#define p_rm_colon 0x0010 /* Remove ":" at the end */ /*;AN000;*/ + +#define p_nval_none 0 /* no value list ID */ /*;AN000;*/ +#define p_nval_range 1 /* range list ID */ /*;AN000;*/ +#define p_nval_value 2 /* value list ID */ /*;AN000;*/ +#define p_nval_string 3 /* string list ID */ /*;AN000;*/ +#define p_len_range 9 /* Length of a range choice(two DD plus one DB) */ /*;AN000;*/ +#define p_len_value 5 /* Length of a value choice(one DD plus one DB) */ /*;AN000;*/ +#define p_len_string 3 /* Length of a string choice(one DW plus one DB) */ /*;AN000;*/ + +/*----------------------------------------------------------------------+ +| | +| Result block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_result_blk /*;AN000;*/ + { /*;AN000;*/ + BYTE p_type; /* Type returned */ /*;AN000;*/ + BYTE p_item_tag; /* Matched item tag */ /*;AN000;*/ + WORD p_synonym_ptr; /* pointer to Synonym list returned */ /*;AN000;*/ + WORD p_result_buff[2]; /* result value */ /*;AN000;*/ + }; /*;AN000;*/ + +/*----------------------------------------------------------------------+ +| | +| type | +| | ++----------------------------------------------------------------------*/ + +#define p_eol 0 /* End of line */ /*;AN000;*/ +#define p_number 1 /* Number */ /*;AN000;*/ +#define p_list_idx 2 /* List Index */ /*;AN000;*/ +#define p_string 3 /* String */ /*;AN000;*/ +#define p_complex 4 /* Complex */ /*;AN000;*/ +#define p_file_spec 5 /* File Spec */ /*;AN000;*/ +#define p_drive 6 /* Drive */ /*;AN000;*/ +#define p_date_f 7 /* Date */ /*;AN000;*/ +#define p_time_f 8 /* Time */ /*;AN000;*/ +#define p_quoted_string 9 /* Quoted String */ /*;AN000;*/ + +#define p_no_tag 0x0FF /* No ITEM_TAG found */ /*;AN000;*/ + +/*----------------------------------------------------------------------+ +| | +| following return code will be returned in the AX register. | +| | ++----------------------------------------------------------------------*/ + +#define p_no_error 0 /* No error */ /*;AN000;*/ +#define p_too_many 1 /* Too many operands */ /*;AN000;*/ +#define p_op_missing 2 /* Required operand missing */ /*;AN000;*/ +#define p_not_in_sw 3 /* Not in switch list provided */ /*;AN000;*/ +#define p_not_in_key 4 /* Not in keyword list provided */ /*;AN000;*/ +#define p_out_of_range 6 /* Out of range specified */ /*;AN000;*/ +#define p_not_in_val 7 /* Not in value list provided */ /*;AN000;*/ +#define p_not_in_str 8 /* Not in string list provided */ /*;AN000;*/ +#define p_syntax 9 /* Syntax error */ /*;AN000;*/ +#define p_rc_eol 0x0ffff /* End of command line */ /*;AN000;*/ + +/*----------------------------------------------------------------------+ +| | +| String Value List Block Structure | +| | ++----------------------------------------------------------------------*/ + +struct ps_valist_blk /*;AN000;*/ + { /*;AN000;*/ + BYTE ps_val; /* Value type */ /*;AN000;*/ + BYTE ps_nrng; /* Number of ranges */ /*;AN000;*/ + BYTE ps_nnval; /* Number of numbers */ /*;AN000;*/ + BYTE ps_nstrval; /* Number of strings */ /*;AN000;*/ + BYTE ps_item_tag1; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings1; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag2; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings2; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag3; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings3; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag4; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings4; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag5; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings5; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag6; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings6; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag7; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings7; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag8; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings8; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag9; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings9; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag10; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings10; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag11; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings11; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag12; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings12; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag13; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings13; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag14; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings14; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag15; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings15; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag16; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings16; /* Address of strings */ /*;AN000;*/ + BYTE ps_item_tag17; /* Matched item tag */ /*;AN000;*/ + WORD ps_strings17; /* Address of strings */ /*;AN000;*/ + }; /*;AN000;*/ diff --git a/v4.0/src/CMD/ATTRIB/_MSGRET.ASM b/v4.0/src/CMD/ATTRIB/_MSGRET.ASM new file mode 100644 index 0000000..7acb51e --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/_MSGRET.ASM @@ -0,0 +1,233 @@ +page 60,132 ;AN000; +name _msgret ;AN000; +title C to Message Retriever ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; +; MODULE: _msgret ;AN000; +; ;AN000; +; PURPOSE: Supplies an interface between C programs and ;AN000; +; the DOS message retriever ;AN000; +; ;AN000; +; CALLING FORMAT: ;AN000; +; sysloadmsg(&inregs,&outregs); ;AN000; +; sysgetmsg(&inregs,&outregs); ;AN000; +; sysdispmsg(&inregs,&outregs); ;AN000; +; ;AN000; +; ;AN000; +; DATE: 5-21-87 ;AN000; +; Modified: 6/18/87 ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; +; ;AN000; + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; +; ;AN000; + .8087 ;AN000; +_TEXT SEGMENT BYTE PUBLIC 'CODE' ;AN000; +_TEXT ENDS ;AN000; +_DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; +_DATA ENDS ;AN000; +CONST SEGMENT WORD PUBLIC 'CONST' ;AN000; +CONST ENDS ;AN000; +_BSS SEGMENT WORD PUBLIC 'BSS' ;AN000; +_BSS ENDS ;AN000; +DGROUP GROUP CONST, _BSS, _DATA ;AN000; + ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP ;AN000; +; ;AN000; + public _sysloadmsg ;AN000; + public _sysgetmsg ;AN000; + public _sysdispmsg ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; +_DATA segment ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; +; MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; + MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; +.LIST ;AN000; +.CREF ;AN000; +_DATA ends ;AN000; +; ;AN000; +; ;AN000; +_TEXT segment ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + ;DEFAULT=CHECK DOS VERSION ;AN000; + ;DEFAULT=NEARmsg ;AN000; + ;DEFAULT=INPUTmsg ;AN000; + ;DEFAULT=NUMmsg ;AN000; + ;DEFAULT=NO TIMEmsg ;AN000; + ;DEFAULT=NO DATEmsg ;AN000; +; MSG_SERVICES ;AN000; +; MSG_SERVICES ;MSG TEXT ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; + MSG_SERVICES ;AN000; + MSG_SERVICES ;MSG TEXT ;AN000; +.LIST ;AN000; +.CREF ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +_sysloadmsg proc near ;AN000; + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; +; ;AN000; +; copy C inregs into proper registers ;AN000; +; ;AN000; + mov di,[bp+4] ; fix di (arg 0) ;AN000; +; ;AN000; + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack ;AN000; +; ;AN000; + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; +; ;AN000; + push bp ; save base pointer ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; + call sysloadmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack ;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; +; ;AN000; + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; +; ;AN000; + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; +; ;AN000; + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; +; ;AN000; + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; +_sysloadmsg endp ;AN000; +; ;AN000; +; ;AN000; +_sysgetmsg proc near ;AN000; + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; +; ;AN000; +; copy C inregs into proper registers ;AN000; +; ;AN000; + mov di,[bp+4] ; fix di (arg 0) ;AN000; +; ;AN000; + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack ;AN000; +; ;AN000; + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; +; ;AN000; + push bp ; save base pointer ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; + call sysgetmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack ;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; +; ;AN000; + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; +; ;AN000; + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; +; ;AN000; + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; +; ;AN000; + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; +_sysgetmsg endp ;AN000; +; ;AN000; +; ;AN000; +_sysdispmsg proc near ;AN000; + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; +; ;AN000; +; copy C inregs into proper registers ;AN000; +; ;AN000; + mov di,[bp+4] ; fix di (arg 0) ;AN000; +; ;AN000; + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack ;AN000; +; ;AN000; + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; +; ;AN000; + push bp ; save base pointer ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; + call sysdispmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack ;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; +; ;AN000; + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; +; ;AN000; + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; +; ;AN000; + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; +; ;AN000; + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; +_sysdispmsg endp ;AN000; +; ;AN000; +; ;AN000; +_TEXT ends ; end code segment ;AN000; + + include msgdcl.inc + + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/ATTRIB/_PARSE.ASM b/v4.0/src/CMD/ATTRIB/_PARSE.ASM new file mode 100644 index 0000000..9800c9e --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/_PARSE.ASM @@ -0,0 +1,107 @@ +page 60,132 ;AN000; +name _parse ;AN000; +title C to PARSER interface ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; +; MODULE: _parse ;AN000; +; ;AN000; +; PURPOSE: Supplies an interface between C programs and ;AN000; +; the DOS parser ;AN000; +; ;AN000; +; CALLING FORMAT: ;AN000; +; parse(&inregs,&outregs); ;AN000; +; ;AN000; +; DATE: 5-21-87 ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; +; extrn sysparse:far ;AN000; +; ;AN000; + public _parse ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; +FarSW equ 0 ; make sysparse be a NEAR proc ;AN000; +TimeSW equ 0 ; Check time format ;AN000; +FileSW equ 1 ; Check file specification ;AN000; +CAPSW equ 1 ; Perform CAPS if specified ;AN000; +CmpxSW equ 0 ; Check complex list ;AN000; +NumSW equ 1 ; Check numeric value ;AN000; +KeySW equ 1 ; Support keywords ;AN000; +SwSW equ 1 ; Support switches ;AN000; +Val1SW equ 1 ; Support value definition 1 ;AN000; +Val2SW equ 1 ; Support value definition 2 ;AN000; +Val3SW equ 1 ; Support value definition 3 ;AN000; +DrvSW equ 0 ; Support drive only format ;AN000; +QusSW equ 1 ; Support quoted string format ;AN000; +;------------------------------------------------------------------- ;AN000; +DGROUP GROUP _DATA +PGROUP GROUP _TEXT + +_DATA segment byte public 'DATA' ;AN000; +BASESW = 1 ;SPECIFY, PSDATA POINTED TO BY "DS" +INCSW = 0 ;PSDATA.INC IS ALREADY INCLUDED + INCLUDE PSDATA.INC ;PARSER'S WORK SPACE +_DATA ends ;AN000; + +_TEXT segment byte public 'CODE' ;AN000; + + ASSUME CS: PGROUP ;AN000; + ASSUME DS: DGROUP ;AN000; +;------------------------------------------------------------------- ;AN000; +.xlist ;AN000; +include parse.asm ; include the parser ;AN000; +.list ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; +_parse proc near ;AN000; + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; +; ;AN000; +; copy C inregs into proper registers ;AN000; +; ;AN000; + mov di,[bp+4] ; fix di (arg 0) ;AN000; +; ;AN000; + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack ;AN000; +; ;AN000; + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; +; ;AN000; + push bp ; save base pointer ;AN000; +; ;AN000; +;------------------------------------------------------------------- ;AN000; + call sysparse ; call the parser ;AN000; +;------------------------------------------------------------------- ;AN000; +; ;AN000; + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack ;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; +; ;AN000; + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; +; ;AN000; + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; +; ;AN000; + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; +; ;AN000; + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; +_parse endp ;AN000; +_TEXT ends ; end code segment ;AN000; + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/BACKUP/BACKPARS.H b/v4.0/src/CMD/BACKUP/BACKPARS.H new file mode 100644 index 0000000..e43ae0d --- /dev/null +++ b/v4.0/src/CMD/BACKUP/BACKPARS.H @@ -0,0 +1,223 @@ +/* 0 */ +/*-----------------------------------------------------------------------*/ +/*- -*/ +/*- FILE: BACKPARS.H -*/ +/*- -*/ +/*- PURPOSE: Defines structures and DEFINES for the DOS PARSE -*/ +/*- service routines. -*/ +/*- -*/ +/*- DATE: 6/5/87 -*/ +/*- -*/ +/*-----------------------------------------------------------------------*/ + + +/**********************************************************/ +/* STRUCTURE TO DEFINE ADDITIONAL COMMAND LINE DELIMITERS */ +/**********************************************************/ +struct p_parms /*;AN000;4*/ + { /*;AN000;4*/ + WORD parmsx_ptr; /* POINTER TO PARMS STRUCTURE *//*;AN000;4*/ + BYTE p_num_extra; /* 1 SAYS THAT A DELIMITER LIST FOLLOWS */ /*;AN000;4*/ + BYTE p_len_extra_delim; /* NUMBER OF ADDITIONAL DELIMITERS *//*;AN000;4*/ + BYTE p_extra_delim[2]; /* ADDITIONAL DELIMITERS */ /*;AN000;4*/ + }; /*;AN000;4*/ + +/**************************************************/ +/* STRUCTURE TO DEFINE BACKUP SYNTAX REQUIREMENTS */ +/**************************************************/ +struct p_parmsx /*;AN000;4*/ + { /*;AN000;4*/ + BYTE p_minpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/ + BYTE p_maxpos; /* THERE ARE 2 REQUIRED POSITIONAL PARMS*/ /*;AN000;4*/ + WORD pos1_ptr; /* POINTER TO SOURCE FILESPEC DEF AREA*/ /*;AN000;4*/ + WORD pos2_ptr; /* POINTER TO TARGET DRIVE DEF AREA*/ /*;AN000;4*/ + BYTE num_sw; /* THERE ARE 7 SWITCHES (/S, /F, /M, /A, /L:, /T:, /D:) */ /*;AN000;4*/ + WORD sw1_ptr; /* POINTER TO FIRST SWITCH DEFINITION AREA*//*;AN000;4*/ + WORD sw2_ptr; /* POINTER TO SECOND SWITCH DEFINITION AREA*//*;AN000;4*/ + WORD sw3_ptr; /* POINTER TO THIRD SWITCH DEFINITION AREA*//*;AN000;4*/ + WORD sw4_ptr; /* POINTER TO FOURTH SWITCH DEFINITION AREA*//*;AN000;4*/ + WORD sw5_ptr; /* POINTER TO FIFTH SWITCH DEFINITION AREA*//*;AN000;4*/ + WORD num_keywords; /* NUMBER OF KEYWORDS IN BACKUP SYNTAX*/ /*;AN000;4*/ + }; /*;AN000;4*/ + +/****************************************/ +/* STRUCTURE TO DEFINE POSITIONAL PARMS */ +/****************************************/ +struct p_pos_blk /*;AN000;4*/ + { /*;AN000;4*/ + WORD match_flag; /* Controls type matched */ /*;AN000;4*/ + WORD function_flag; /* Function should be taken */ /*;AN000;4*/ + WORD result_buf; /* Result buffer address */ /*;AN000;4*/ + WORD value_list; /* Value list address */ /*;AN000;4*/ + BYTE nid; /* # of keyword/SW synonyms (0) *//*;AN000;4*/ + }; /*;AN000;4*/ + +/********************************/ +/* STRUCTURE TO DEFINE SWITCHES */ +/********************************/ +struct p_sw_blk /*;AN000;4*/ + { /*;AN000;4*/ + WORD p_match_flag; /* Controls type matched */ /*;AN000;4*/ + WORD p_function_flag; /* Function should be taken */ /*;AN000;4*/ + WORD p_result_buf; /* Result buffer address */ /*;AN000;4*/ + WORD p_value_list; /* Value list address */ /*;AN000;4*/ + BYTE p_nid; /* # of switches */ /*;AN000;4*/ + BYTE switch1[3]; /* Save area for switch */ /*;AN000;4*/ + BYTE switch2[3]; /* Save area for switch */ /*;AN000;4*/ + BYTE switch3[3]; /* Save area for switch */ /*;AN000;4*/ + BYTE switch4[3]; /* Save area for switch */ /*;AN000;4*/ + }; /*;AN000;4*/ +/* */ +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/**************************/ +/* RETURN BUFFER FOR TIME */ +/**************************/ +struct timebuff /*;AN000;4*/ + { /*;AN000;4*/ + BYTE t_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE t_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/ + WORD t_synonym_ptr; /* pointer to Synonym list returned */ /*;AN000;4*/ + BYTE hours; /*;AN000;4*/ + BYTE minutes; /*;AN000;4*/ + BYTE seconds; /*;AN000;4*/ + BYTE hundreds; /*;AN000;4*/ + }; /*;AN000;4*/ + +/**************************/ +/* RETURN BUFFER FOR DATE */ +/**************************/ +struct datebuff + { /*;AN000;4*/ + BYTE d_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE d_item_tag; /* SPACE FOR ITEM TAG*/ /*;AN000;4*/ + WORD d_synonym_ptr; /* pointer to Synonym list returned */ /*;AN000;4*/ + WORD year; /*;AN000;4*/ + BYTE month; /*;AN000;4*/ + BYTE day; /*;AN000;4*/ + }; /*;AN000;4*/ + + +/*******************************************/ +/* RETURN BUFFER FOR POSITIONAL PARAMETERS */ +/*******************************************/ +struct p_result_blk /*;AN000;4*/ + { /*;AN000;4*/ + BYTE p_type; /* Type returned */ /*;AN000;4*/ + BYTE p_item_tag; /* Matched item tag */ /*;AN000;4*/ + WORD p_synonym_ptr; /* pointer to Synonym list returned *//*;AN000;4*/ + DWORD p_string_ptr; /* Pointer to string /*;AN000;4*/ + }; /*;AN000;4*/ + +/****************************************/ +/* RETURN BUFFER FOR SWITCH INFORMATION */ +/****************************************/ +struct switchbuff /*;AN000;4*/ + { /*;AN000;4*/ + BYTE sw_type; /* TYPE RETURNED*/ /*;AN000;4*/ + BYTE sw_item_tag; /* Matched item tag */ /*;AN000;4*/ + WORD sw_synonym_ptr; /* pointer to synonym */ /*;AN000;4*/ + DWORD sw_string_ptr; /* Pointer to string */ /*;AN000;4*/ + }; /*;AN000;4*/ + + +/********************************/ +/* VALUE LIST FOR /F: PARAMETER */ +/********************************/ +struct val_list_struct /*;AN000;pxxxx*/ + { /*;AN000;pxxxx*/ + BYTE nval; /*;AN000;pxxxx*/ + BYTE num_ranges; /*;AN000;pxxxx*/ + BYTE num_choices; /*;AN000;pxxxx*/ + BYTE num_strings; /*;AN000;pxxxx*/ + BYTE item_tag01; /*;AN000;pxxxx*/ + WORD val01; /*;AN000;pxxxx*/ + BYTE item_tag02; /*;AN000;pxxxx*/ + WORD val02; /*;AN000;pxxxx*/ + BYTE item_tag03; /*;AN000;pxxxx*/ + WORD val03; /*;AN000;pxxxx*/ + BYTE item_tag04; /*;AN000;pxxxx*/ + WORD val04; /*;AN000;pxxxx*/ + BYTE item_tag05; /*;AN000;pxxxx*/ + WORD val05; /*;AN000;pxxxx*/ + BYTE item_tag06; /*;AN000;pxxxx*/ + WORD val06; /*;AN000;pxxxx*/ + BYTE item_tag07; /*;AN000;pxxxx*/ + WORD val07; /*;AN000;pxxxx*/ + BYTE item_tag08; /*;AN000;pxxxx*/ + WORD val08; /*;AN000;pxxxx*/ + BYTE item_tag09; /*;AN000;pxxxx*/ + WORD val09; /*;AN000;pxxxx*/ + BYTE item_tag10; /*;AN000;pxxxx*/ + WORD val10; /*;AN000;pxxxx*/ + BYTE item_tag11; /*;AN000;pxxxx*/ + WORD val11; /*;AN000;pxxxx*/ + BYTE item_tag12; /*;AN000;pxxxx*/ + WORD val12; /*;AN000;pxxxx*/ + BYTE item_tag13; /*;AN000;pxxxx*/ + WORD val13; /*;AN000;pxxxx*/ + BYTE item_tag14; /*;AN000;pxxxx*/ + WORD val14; /*;AN000;pxxxx*/ + BYTE item_tag15; /*;AN000;pxxxx*/ + WORD val15; /*;AN000;pxxxx*/ + BYTE item_tag16; /*;AN000;pxxxx*/ + WORD val16; /*;AN000;pxxxx*/ + BYTE item_tag17; /*;AN000;pxxxx*/ + WORD val17; /*;AN000;pxxxx*/ + BYTE item_tag18; /*;AN000;pxxxx*/ + WORD val18; /*;AN000;pxxxx*/ + BYTE item_tag19; /*;AN000;pxxxx*/ + WORD val19; /*;AN000;pxxxx*/ + BYTE item_tag20; /*;AN000;pxxxx*/ + WORD val20; /*;AN000;pxxxx*/ + BYTE item_tag21; /*;AN000;pxxxx*/ + WORD val21; /*;AN000;pxxxx*/ + BYTE item_tag22; /*;AN000;pxxxx*/ + WORD val22; /*;AN000;pxxxx*/ + BYTE item_tag23; /*;AN000;pxxxx*/ + WORD val23; /*;AN000;pxxxx*/ + BYTE item_tag24; /*;AN000;pxxxx*/ + WORD val24; /*;AN000;pxxxx*/ + BYTE item_tag25; /*;AN000;pxxxx*/ + WORD val25; /*;AN000;pxxxx*/ + BYTE item_tag26; /*;AN000;pxxxx*/ + WORD val26; /*;AN000;pxxxx*/ + BYTE item_tag27; /*;AN000;pxxxx*/ + WORD val27; /*;AN000;pxxxx*/ + + }; /*;AN000;pxxxx*/ + +/*********************************/ +/* VALUE TABLE FOR /F: PARAMETER */ +/*********************************/ +struct val_table_struct /*;AN000;pxxxx*/ + { /*;AN000;pxxxx*/ + BYTE val01[7]; /*;AN000;pxxxx*/ + BYTE val02[7]; /*;AN000;pxxxx*/ + BYTE val03[7]; /*;AN000;pxxxx*/ + BYTE val04[7]; /*;AN000;pxxxx*/ + BYTE val05[7]; /*;AN000;pxxxx*/ + BYTE val06[7]; /*;AN000;pxxxx*/ + BYTE val07[7]; /*;AN000;pxxxx*/ + BYTE val08[7]; /*;AN000;pxxxx*/ + BYTE val09[7]; /*;AN000;pxxxx*/ + BYTE val10[7]; /*;AN000;pxxxx*/ + BYTE val11[7]; /*;AN000;pxxxx*/ + BYTE val12[7]; /*;AN000;pxxxx*/ + BYTE val13[7]; /*;AN000;pxxxx*/ + BYTE val14[7]; /*;AN000;pxxxx*/ + BYTE val15[7]; /*;AN000;pxxxx*/ + BYTE val16[7]; /*;AN000;pxxxx*/ + BYTE val17[7]; /*;AN000;pxxxx*/ + BYTE val18[7]; /*;AN000;pxxxx*/ + BYTE val19[7]; /*;AN000;pxxxx*/ + BYTE val20[7]; /*;AN000;pxxxx*/ + BYTE val21[7]; /*;AN000;pxxxx*/ + BYTE val22[7]; /*;AN000;pxxxx*/ + BYTE val23[7]; /*;AN000;pxxxx*/ + BYTE val24[7]; /*;AN000;pxxxx*/ + BYTE val25[7]; /*;AN000;pxxxx*/ + BYTE val26[7]; /*;AN000;pxxxx*/ + BYTE val27[7]; /*;AN000;pxxxx*/ + }; /*;AN000;pxxxx*/ diff --git a/v4.0/src/CMD/BACKUP/BACKUP.C b/v4.0/src/CMD/BACKUP/BACKUP.C new file mode 100644 index 0000000..2f2805a --- /dev/null +++ b/v4.0/src/CMD/BACKUP/BACKUP.C @@ -0,0 +1,4385 @@ +/* 0 */ + +/************************************************************ +/* +/* UTILITY NAME: BACKUP.COM +/* +/* SOURCE FILE NAME: BACKUP.C +/* +/* DESCRIPTIVE NAME: +/* DOS Backup Utility Program +/* +/* STATUS: BACKUP utility, DOS Version 4.00 +/* Written using the C programming language. +/* +/* +/* COMPILER/LINKER INVOCATION: +/* +/* cc /AS /Os /Zep /W3 /DLINT_ARGS /UDEBUG backup.c; +/* link backup,,,mapper+comsubs +/* +/* Note: You MUST(!) use the PACKED option (/Zp) to make sure data structures +/* are not aligned !!! +/* +/* FUNCTION: +/* BACKUP will back up files from one disk(ette) to another. Accepts +/* global characters, other parameters are defined to allow a more +/* restrictive BACKUP procedure. Compacts data into one large file and +/* a control file containing directory information. Allows FORMATTING +/* target diskette, intelligent error recovery, and proper handling of +/* file sharing and sharing errors. Optionally creates a log file for +/* tracking purposes. Sets errorlevels on termination to indicate +/* result. +/* +/* RESTRICTIONS: +/* The BACKUP Utility program will be version checked to run ONLY on +/* DOS version 4.00. BACKUP performs a file by file backup using the +/* DOS file system, ie. it is not an image type backup. +/* +/* +/* SYNTAX: +/* +/* BACKUP [d:][path] filename [.ext]] d: [/S] [/F[:size]] +/* [/L[:fn]] [/M] [/A] [T:hh:mm:ss] [/D:mm-dd-yy] +/* +/* [/F[:size]] undocumented +/* +/* SOURCE HISTORY: +/* +/* New for DOS 3.3 and OS/2 +/* +/* Modification History: +/* +/* ;AN000; Code added in DOS 4.0 +/* 6-05-87 RW +/* ;AN000;1 No BACKUP of SYSTEM files +/* ;AN000;2 Support for APPEND /X deactivation +/* ;AN000;3 Support for Extended Attributes +/* ;AN000;4 Support for PARSE service routines +/* ;AN000;5 Support for code page file tags +/* ;AN000;6 Support for MESSAGE retriever +/* ;AN000;7 Allow logfile to go on BACKUP target drive +/* ;AN000;8 Eliminate double prompting on single diskette drive systems +/* ;AN000;9 Put error message in logfile on share error +/* ;AN000;10 Make diskette formatting the default (DCR 177) +/* ;AN000;d178 DCR 178 Find FORMAT.COM before beginning +/* ;AN001; DCR 434 - Allow /F:size to specify format size +/* ;AN002; Don't use "C" routines to find PATH in environment +/* ;AN003; Make BACKUP handle UNC format returned from XLAT +/* ;AN004; Add CR, LF to end of command line (p3646) +/* ;AN005; Make sure no bogus BACKUP and CONTROL files are left in case of error exit +/* ;AN006; Make sure we don't try to BACKUP logfile +/* ;AN007; Make sure ABORT responses to critical errors are aborted +/* ;AN008; Make PARSE errors messages display the offending parameter +/* ;AN009; Fix parser +/* ;AN010; Don't find FORMAT.COM on target drive +/* ;AN011; Make BACKUP handle disk full properly on fixed disk +/***************************************************************** + + /* "C" supplied include files */ +#include +#include +#include /*;AN000;*/ +#include +#include +#include /*;AN000;d178*/ + +#include /* OS/2 Include file */ + +#include "backup.h" /* BACKUP structures, defines, ...*/ +#include "backpars.h" /* DEFINEs and STRUCTs for the DOS Parse service routines */ + +#include /* symbol defns to determine degree of compatibility */ + + /**********************************/ + /* DATA STRUCTURES */ + /**********************************/ + WORD rc; /* Return code from DOS calls */ + + unsigned selector; /* Kinda like a segment address */ + + struct node *curr_node; /* Pointer to "node" structure for the */ + /* directory currently being processed */ + + struct node *last_child; /* Pointer to "node" structure for the */ + /* last directory discovered in the */ + /* directory currently being processed */ + + struct subst_list sublist; /*;AN000;6 Message substitution list */ + + struct p_parms parms; /*;AN000;4 Parser data structure */ + struct p_parmsx parmsx; /*;AN000;4 Parser data structure */ + struct p_pos_blk pos1; /*;AN000;4 Parser data structure */ + struct p_pos_blk pos2; /*;AN000;4 Parser data structure */ + struct p_sw_blk sw1; /*;AN000;4 Parser data structure */ + struct p_sw_blk sw2; /*;AN000;4 Parser data structure */ + struct p_sw_blk sw3; /*;AN000;4 Parser data structure */ + struct p_sw_blk sw4; /*;AN000;4 Parser data structure */ + struct p_sw_blk sw5; /*;AN001;DCR 434 Parser data structure */ + + struct p_result_blk pos_buff; /*;AN000;4 Parsr data structure */ + struct switchbuff sw_buff; /*;AN000;4 Parsr data structure */ + struct timebuff time_buff; /*;AN000;4 Parsr data structure */ + struct datebuff date_buff; /*;AN000;4 Parsr data structure */ + struct val_list_struct value_list; /*;AN001;DCR 434*/ + struct val_table_struct value_table; /*;AN001;DCR 434*/ + char curr_parm[128]; /*;AN009; Current parameter being parsed*/ + + DWORD noval = 0; /*;AN000;4 Value list for PARSR */ + + struct FileFindBuf dta; /* Return area for Find First/Next*/ + struct FileFindBuf *dta_addr; /* Pointer to above */ + union REGS inregs, outregs; /*;AN000;2 Register set */ + + /**********************************/ + /* DATA AREAS */ + /**********************************/ + WORD dirhandle; /* Dirhandle field, for Find First, Find Next */ + BYTE dirhandles_open = FALSE; /* Flag indicating at least 1 open dirhandle */ + + WORD def_drive; /* Storage for default drive (1=A,2=B,...) */ + BYTE src_drive_letter; /* ASCII drive letter, source drive */ + BYTE tgt_drive_letter; /* ASCII drive letter, target drive */ + BYTE src_def_dir[PATHLEN+20]; /* default dir on source, drive letter omitted */ + + BYTE src_drive_path_fn[PATHLEN+20]; /* D:\path\fn - The fully qualified spec to be backed up*/ + BYTE src_drive_path[PATHLEN+20]; /* D:\path - Fully qualified drive and path to be backed up */ + BYTE src_fn[PATHLEN]; /* fn - File spec to be backed up. Set to *.* if no filespec entered. */ + BYTE ext[3]; /* Filename extension */ + + WORD files_backed_up = 0; /* Counter for number files backed up on current target */ + BYTE diskettes_complete = 0; /* Number of diskettes already filled and complete */ + DWORD curr_db_begin_offset; /* Offset within the control file of the current Directory Block */ + DWORD curr_fh_begin_offset; /* Offset within the control file of the current File Header */ + WORD handle_source = 0xffff; /* Handle for source file */ + WORD handle_target = 0xffff; /* Handle for target file */ + WORD handle_control = 0xffff; /* Handle for control file */ + WORD handle_logfile = 0xffff; /* Handle for log file */ + DWORD part_size; /* Number of bytes from a file on the disk (for files that span) */ + DWORD cumul_part_size; /* Number of bytes from all disks for a particular file */ + + BYTE logfile_path[PATHLEN+20]; /* D:\path\filename - drive,path, and name */ + BYTE format_path[PATHLEN+20]; /*;AN000;d178 Full path to FORMAT.COM */ + BYTE format_size[128]; /*;AN001;DCR 434 If user enters "/F:size" this will be "size" */ + + /**********************************/ + /* PROGRAM CONTROL FLAGS */ + /**********************************/ + BYTE do_subdirs = FALSE; /* User parameters, /S */ + BYTE do_add = FALSE; /* User parameters, /A */ + BYTE do_modified = FALSE; /* User parameters, /M */ + BYTE do_format_parms = FALSE; /* User parameters, /F ;AN000;d177 */ + BYTE do_logfile = FALSE; /* User parameters, /L */ + BYTE do_time = FALSE; /* User parameters, /T */ + BYTE do_date = FALSE; /* User parameters, /D */ + + BYTE buffers_allocated = FALSE; /* Indicates if file buffers were allocated */ + BYTE curr_dir_set = FALSE; /* Indicates if the current directory on source was changed */ + BYTE def_drive_set = FALSE; /* Indicates if the default drive was changed */ + + BYTE control_opened = FALSE; /* Indicates if file opened or not */ + BYTE logfile_opened = FALSE; /*;AN000;7 Indicates if logfile file is opened */ + BYTE source_opened = FALSE; /* Indicates if file opened or not */ + BYTE target_opened = FALSE; /* Indicates if file opened or not */ + + BYTE doing_first_target = TRUE; /* Indicates that first target is being processed */ + BYTE got_first_target = FALSE; /* Indicates that first target is being processed */ + + BYTE source_removable; /* Indicates if the source drive is removable */ + BYTE target_removable; /* Indicates if the target drive is removable */ + + BYTE file_spans_target; /* Indicates that first target is being processed */ + BYTE disk_full = FALSE; /* Flag indicating the disk is full */ + BYTE logfile_on_target = FALSE; /*;AN000;7 Flag telling if user wants logfile on target drive */ + BYTE got_path_validity = FALSE; /*;AN000;4 Flag indicating we have not verified input path*/ + BYTE checking_target = FALSE; /*;AN007; Indicates if we are checking target diskette to determine if it is formatted */ + + BYTE new_directory = TRUE; /* Indicates that file to be backed up is in a different directory */ + BYTE found_a_file = FALSE; /* Indicates if a file was found to be backed up */ + BYTE back_it_up = FALSE; /* Indicates if a file was found and conforms to specified parameters */ char author[45]=" Program Author: W. Russell Whitehead "; + /**********************************/ + /* EXTENDED ATTRIBUTES */ + /**********************************/ +/*EAEA BYTE ext_attrib_flg = FALSE; /*;AN000;3 Indicates there are extended attributes*/ +/*EAEA WORD ext_attrib_len; /*;AN000;3 Length of extended attributes*/ +/*EAEA BYTE ext_attrib_buff[EXTATTBUFLEN]; /*;AN000;3 Buffer for extended attributes*/ + BYTE ext_attrib_buff[3]; /*;AN000;3 Buffer for extended attributes*/ + struct parm_list ea_parmlist; /*;AN000;3 Parameter list for extended open*/ + + /**********************************/ + /* APPEND STUFF */ + /**********************************/ + BYTE append_indicator = 0xff; /*;AN000;2 Indicates if support for APPEND /X is active */ + WORD original_append_func; /*;AN000;2 APPEND functions on program entry, restored on program exit */ + + /**********************************/ + /* OTHER STUFF */ + /**********************************/ + BYTE span_seq_num; /* Counter indicating which part of a spanning file is on current target */ + + WORD data_file_alloc_size = 0xffff; /* Number of paragraphs to initially try to allocate for data file */ + + DWORD data_file_tot_len = 0; /* Storage area for data file current length */ + DWORD ctl_file_tot_len = 0; /* Storage area for control file current length on the disk */ + + WORD ctry_date_fmt; + BYTE ctry_time_fmt; + WORD ctry_date_sep; + WORD ctry_time_sep; + + WORD user_specified_time = 0; /* Time user entered in response to /T parameter */ + WORD user_specified_date = 0; /* Date user entered in response to /T parameter */ + + BYTE return_code = RETCODE_NO_ERROR; /* Save area for DOS ErrorLevel */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: main +/* +/* FUNCTION: +/* +/* Backs up files from source to target drive +/* +/***************************************************/ +main(argc,argv) +int argc; +char *argv[]; +{ + init(); /*;AN000;6 Mundane initializization of data structures, */ + /* check DOS version,preload messages */ + def_drive = get_current_drive(); /* Save default drive number*/ + check_drive_validity(argc,argv); /* Check for validity of input drive(s) */ + get_drive_types(); /* Find out if source and target are removable */ + get_country_info(); /* Get country dependent information */ + parser(argc,argv); /*;AN000;4 Parse input line, init switches and flags*/ + check_path_validity(argv); /*;AN000;4 Verify that the source filespec is valid */ + if (target_removable) /*;AN000;d178 If target drive is diskette */ + find_format(); /*;AN000;d178 Find FORMAT.COM and build path to it*/ + save_current_dirs(); /* Save default directories on def drive, source and target */ + alloc_buffer(); /* Allocate IO buffer */ + check_appendX(); /*;AN000;2 Check APPEND /X status, turn off if active */ + set_vectors(); /* Set vectors for Int 23h and 24h */ + do_backup(); /* Do the BACKUP */ + + return(0); +} /* end main */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: init +/* +/* FUNCTION: +/* Preload messages +/* Check DOS version +/* Mundane initializization of data structures +/* +/**************************************************/ +void init() /*;AN000;6*/ +{ /*;AN000;6*/ + + /**********************************/ + /** PRELOAD MESSAGES **/ + /**********************************/ + sysloadmsg(&inregs,&outregs); /*;AN000;6 Preload messages, check DOS version */ + + if (outregs.x.cflag & CARRY) /*;AN000;6 If there was an error */ + { /*;AN000;6*/ + sysdispmsg(&outregs,&outregs); /*;AN000;6 Display the error message (Use OUTREGS as input*/ + return_code = RETCODE_ERROR; /*;AN000;6 Set the return code */ + terminate(); /*;AN000;6 and terminate */ + } /*;AN000;6*/ + + /**********************************/ + /** SETUP MESSAGE SUBST LIST **/ + /**********************************/ + sublist.sl_size1= SUBLIST_SIZE; /*;AN000;6 Initialize subst list for message retriever*/ + sublist.sl_size2= SUBLIST_SIZE; /*;AN000;6*/ + sublist.one = 1; /*;AN000;6*/ + sublist.two = 2; /*;AN000;6*/ + sublist.zero1 = 0; /*;AN000;6*/ + sublist.zero2 = 0; /*;AN000;6*/ + + ext_attrib_buff[0] = 0; /*;AN000;3*/ + ext_attrib_buff[1] = 0; /*;AN000;3*/ + + date_buff.month = 0; /*;AN000;3*/ + date_buff.day = 0; /*;AN000;3*/ + date_buff.year = 0; /*;AN000;3*/ + + time_buff.hours = 0; /*;AN000;3*/ + time_buff.minutes = 0; /*;AN000;3*/ + time_buff.seconds = 0; /*;AN000;3*/ + time_buff.hundreds= 0; /*;AN000;3*/ + + dta_addr = (struct FileFindBuf *)&dta; /* Get address of FindFile buffer */ + + return; /*;AN000;6*/ +} /*;AN000;6*/ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: parser +/* +/* FUNCTION: +/* +/* Parse the command line +/* +/**************************************************/ +void parser(argc,argv) /*;AN000;4*/ +int argc; /*;AN000;4*/ +char *argv[]; /*;AN000;4*/ +{ /*;AN000;4*/ + char cmd_line[128]; /*;AN000;4*/ + char not_finished = TRUE; /*;AN000;4*/ + int x; /*;AN000;4*/ + + parse_init(); /* Initialize parser data structures*//*;AN000;4*/ + + /* Copy command line parameters to local area */ + cmd_line[0] = NUL; /*;AN000;4*/ + for (x=1; x<=argc; x++) /*;AN000;4*/ + { /*;AN000;4*/ + strcat(cmd_line,argv[x]); /*;AN000;4*/ + if (x != argc) strcat(cmd_line," "); /*;AN000;4*/ + } /*;AN000;4*/ + + strcat(cmd_line,"\r"); /*;AN004;*/ + + inregs.x.si = (WORD)&cmd_line[0]; /*DS:SI points to cmd line*//*;AN000;4*/ + + + + while (not_finished) /*;AN000;4 For all strings in command line */ + { /*;AN000;4*/ + inregs.x.dx = 0; /*;AN000;4 RESERVED */ + inregs.x.di = (WORD)&parms; /*ES:DI*/ /*;AN000;4 address of parm list */ + + parse(&inregs,&outregs); /*;AN000;4 Call DOS SYSPARSE service routines*/ + + x=0; /* Save the parsed parameter */ /*;AN009;*/ + for (inregs.x.si; inregs.x.si= 5) /*;AN000;p2592*/ + check_for_device_names(argv); /*;AN000;p2592*/ + + return; /*;AN000;4 Return to caller*/ +} /* end parser */ /*;AN000;4*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: parse_error +/* +/* FUNCTION: +/* +/* There was a parse error. Display appropriate +/* error message and terminate. +/* +/**************************************************/ +void parse_error(ax,dx) /*;AN000;4*/ +WORD ax; /*;AN000;4*/ +WORD dx; /*;AN000;4*/ +{ /*;AN000;4*/ + sublist.value1 = &curr_parm[0]; /*;AN008;*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN008;*/ + sublist.pad_char1 = ' '; /*;AN008;*/ + sublist.one = 0; /*;AN008;*/ + sublist.max_width1 = (BYTE)strlen(curr_parm); /*;AN008;*/ + sublist.min_width1 = sublist.max_width1; /*;AN008;*/ + + if (dx == (WORD)&time_buff) /*;AN000;4*/ + display_it(INV_TIME,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/ + else /*;AN000;4*/ + if (dx == (WORD)&date_buff) /*;AN000;4*/ + display_it(INV_DATE,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;4*/ + else /*;AN000;4*/ + display_it (ax,STDERR,1,NOWAIT,(BYTE)PARSEERROR); /*;AN000;6*/ + + return_code = RETCODE_ERROR; /*;AN000;4*/ + clean_up_and_exit(); /*;AN000;4*/ + + return; /*;AN000;4*/ +} /* end parse_error */ /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_date +/* +/* FUNCTION: +/* +/* A date parameter was entered. Validate it +/* +/**************************************************/ +void check_date(year,month,day) /*;AN000;4*/ +WORD year; /*;AN000;4*/ +BYTE month; /*;AN000;4*/ +BYTE day; /*;AN000;4*/ +{ /*;AN000;4*/ + if (year > 2099 || year < 1980) /*;AC000;4*/ + error_exit(INV_DATE); /*;AC000;4*/ + + if (month > 12 || month < 1) /*;AC000;4*/ + error_exit(INV_DATE); /*;AC000;4*/ + + if (day > 31 || day < 1) /*;AC000;4*/ + error_exit(INV_DATE); /*;AC000;4*/ + + /* Verify day not greater then 30 if Apr,Jun,Sep,Nov */ + if ((day>30) && (month==4 || month==6 || month==9 || month==11))/*;AC000;4*/ + error_exit(INV_DATE); /*;AC000;4*/ + + if (month == 2) /* Deal with February */ /*;AC000;4*/ + { /*;AC000;4*/ + if (day > 29) /* if Feb 30 or above */ /*;AC000;4*/ + error_exit(INV_DATE); /* then Bad Date */ /*;AC000;4*/ + + if ((year % 4) != 0) /* If not a leap year */ /*;AC000;4*/ + if (day > 28) /* if Feb 29 or above */ /*;AC000;4*/ + error_exit(INV_DATE); /* then Bad Date */ /*;AC000;4*/ + } /*;AC000;4*/ + + do_date = TRUE; /*;AN000;4*/ + + return; /*;AN000;4*/ +} /* end check_date */ /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_time +/* +/* FUNCTION: +/* +/* A time parameter was entered. Validate it +/* +/**************************************************/ +void check_time(hours,minutes,seconds,hundreds) /*;AN000;4*/ +BYTE hours; /*;AN000;4*/ +BYTE minutes; /*;AN000;4*/ +BYTE seconds; /*;AN000;4*/ +BYTE hundreds; /*;AN000;4*/ +{ /*;AN000;4*/ + if (hours > 23 || hours < 0) /*;AC000;4*/ + error_exit(INV_TIME); /*;AC000;4*/ + + if (minutes >= 60 || minutes < 0) /*;AC000;4*/ + error_exit(INV_TIME); /*;AC000;4*/ + + if (seconds >= 60 || seconds < 0) /*;AC000;4*/ + error_exit(INV_TIME); /*;AC000;4*/ + + if (hundreds > 99 || hundreds < 0) /*;AC000;4*/ + error_exit(INV_TIME); /*;AC000;4*/ + + do_time = TRUE; /*;AN000;4*/ + + return; /*;AN000;4*/ +} /* end check_time */ /*;AN000;4*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: parse_init +/* +/* FUNCTION: +/* +/* Initialize the parser data structures +/* +/**************************************************/ +void parse_init() /*;AN000;4*/ +{ /* Initialize PARMS data structure */ /*;AN000;4*/ + parms.parmsx_ptr = (WORD)&parmsx; /*;AN000;4*/ + parms.p_num_extra = 1; /*;AN000;4*/ + parms.p_len_extra_delim = 1; /*;AN000;4*/ + parms.p_extra_delim[0] = ';'; /*;AN000;4*/ + parms.p_extra_delim[1] = NUL; /*;AN000;4 */ + + /* Initialize PARMSX data structure */ + parmsx.p_minpos= 2; /*;AN000;4*/ + parmsx.p_maxpos= 2; /*;AN000;4*/ + parmsx.pos1_ptr= (WORD)&pos1; /*;AN000;4*/ + parmsx.pos2_ptr= (WORD)&pos2; /*;AN000;4*/ + parmsx.num_sw = 5; /*;AN000;4*/ + parmsx.sw1_ptr = (WORD)&sw1; /*;AN000;4*/ + parmsx.sw2_ptr = (WORD)&sw2; /*;AN000;4*/ + parmsx.sw3_ptr = (WORD)&sw3; /*;AN000;4*/ + parmsx.sw4_ptr = (WORD)&sw4; /*;AN000;4*/ + parmsx.sw5_ptr = (WORD)&sw5; /*;AN001;DCR 434*/ + parmsx.num_keywords = 0; /*;AN000;4*/ + + /* Initialize POS1 data structure */ + pos1.match_flag = FILESPEC; /*;AN000;4*/ + pos1.function_flag = 0; /*;AN000;4*/ + pos1.result_buf = (WORD)&pos_buff; /*;AN000;4*/ + pos1.value_list = (WORD)&noval; /*;AN000;4*/ + pos1.nid = 0; /*;AN000;4*/ + + /* Initialize POS2 data structure */ + pos2.match_flag = DRIVELETTER; /*;AN000;4*/ + pos2.function_flag = 0; /*;AN000;4*/ + pos2.result_buf = (WORD)&pos_buff; /*;AN000;4*/ + pos2.value_list = (WORD)&noval; /*;AN000;4*/ + pos2.nid = 0; /*;AN000;4*/ + + /* Initialize SW1 data structure */ + sw1.p_match_flag = 0; /*;AN000;4*/ + sw1.p_function_flag = 0; /*;AN000;4*/ + sw1.p_result_buf = (WORD)&sw_buff; /*;AN000;4*/ + sw1.p_value_list = (WORD)&noval; /*;AN000;4*/ + sw1.p_nid = 4; /*;AN000;4*/ + strcpy(sw1.switch1,"/S"); /*;AN000;4*/ + strcpy(sw1.switch2,"/M"); /*;AN000;4*/ + strcpy(sw1.switch3,"/A"); /*;AN000;4*/ + + /* Initialize SW2 data structure */ + sw2.p_match_flag = DATESTRING; /*;AN000;4*/ + sw2.p_function_flag = 0; /*;AN000;4*/ + sw2.p_result_buf = (WORD)&date_buff; /*;AN000;4*/ + sw2.p_value_list = (WORD)&noval; /*;AN000;4*/ + sw2.p_nid = 1; /*;AN000;4*/ + strcpy(sw2.switch1,"/D"); /*;AN000;4*/ + + /* Initialize SW3 data structure */ + sw3.p_match_flag = TIMESTRING; /*;AN000;4*/ + sw3.p_function_flag = 0; /*;AN000;4*/ + sw3.p_result_buf = (WORD)&time_buff; /*;AN000;4*/ + sw3.p_value_list = (WORD)&noval; /*;AN000;4*/ + sw3.p_nid = 1; /*;AN000;4*/ + strcpy(sw3.switch1,"/T"); /*;AN000;4*/ + + /* Initialize SW4 data structure */ + sw4.p_match_flag = SSTRING + OPTIONAL; /*;AN000;4*/ + sw4.p_function_flag = CAP_FILETABLE; /*;AN000;4*/ + sw4.p_result_buf = (WORD)&sw_buff; /*;AN000;4*/ + sw4.p_value_list = (WORD)&noval; /*;AN000;4*/ + sw4.p_nid = 1; /*;AN000;4*/ + strcpy(sw4.switch1,"/L"); /*;AN000;4*/ + + /* Initialize SW5 data structure */ + sw5.p_match_flag = SSTRING + OPTIONAL; /*;AN001;DCR 434*/ + sw5.p_function_flag = CAP_CHARTABLE; /*;AN001;DCR 434*/ + sw5.p_result_buf = (WORD)&sw_buff; /*;AN001;DCR 434*/ + sw5.p_value_list = (WORD)&value_list; /*;AN001;DCR 434*/ + sw5.p_nid = 1; /*;AN001;DCR 434*/ + strcpy(sw5.switch1,"/F"); /*;AN001;DCR 434*/ + + /* Initialize value list data structure */ + value_list.nval = 3; /*;AN001;DCR 434*/ + value_list.num_ranges = 0; /*;AN001;DCR 434*/ + value_list.num_choices = 0; /*;AN001;DCR 434*/ + value_list.num_strings = 27; /*;AN001;DCR 434*/ + value_list.val01 = (WORD)&value_table.val01[0]; /*;AN001;DCR 434*/ + value_list.val02 = (WORD)&value_table.val02[0]; /*;AN001;DCR 434*/ + value_list.val03 = (WORD)&value_table.val03[0]; /*;AN001;DCR 434*/ + value_list.val04 = (WORD)&value_table.val04[0]; /*;AN001;DCR 434*/ + value_list.val05 = (WORD)&value_table.val05[0]; /*;AN001;DCR 434*/ + value_list.val06 = (WORD)&value_table.val06[0]; /*;AN001;DCR 434*/ + value_list.val07 = (WORD)&value_table.val07[0]; /*;AN001;DCR 434*/ + value_list.val08 = (WORD)&value_table.val08[0]; /*;AN001;DCR 434*/ + value_list.val09 = (WORD)&value_table.val09[0]; /*;AN001;DCR 434*/ + value_list.val10 = (WORD)&value_table.val10[0]; /*;AN001;DCR 434*/ + value_list.val11 = (WORD)&value_table.val11[0]; /*;AN001;DCR 434*/ + value_list.val12 = (WORD)&value_table.val12[0]; /*;AN001;DCR 434*/ + value_list.val13 = (WORD)&value_table.val13[0]; /*;AN001;DCR 434*/ + value_list.val14 = (WORD)&value_table.val14[0]; /*;AN001;DCR 434*/ + value_list.val15 = (WORD)&value_table.val15[0]; /*;AN001;DCR 434*/ + value_list.val16 = (WORD)&value_table.val16[0]; /*;AN001;DCR 434*/ + value_list.val17 = (WORD)&value_table.val17[0]; /*;AN001;DCR 434*/ + value_list.val18 = (WORD)&value_table.val18[0]; /*;AN001;DCR 434*/ + value_list.val19 = (WORD)&value_table.val19[0]; /*;AN001;DCR 434*/ + value_list.val20 = (WORD)&value_table.val20[0]; /*;AN001;DCR 434*/ + value_list.val21 = (WORD)&value_table.val21[0]; /*;AN001;DCR 434*/ + value_list.val22 = (WORD)&value_table.val22[0]; /*;AN001;DCR 434*/ + value_list.val23 = (WORD)&value_table.val23[0]; /*;AN001;DCR 434*/ + value_list.val24 = (WORD)&value_table.val24[0]; /*;AN001;DCR 434*/ + value_list.val25 = (WORD)&value_table.val25[0]; /*;AN001;DCR 434*/ + value_list.val26 = (WORD)&value_table.val26[0]; /*;AN001;DCR 434*/ + value_list.val27 = (WORD)&value_table.val27[0]; /*;AN001;DCR 434*/ + + /* Initialize FORMAT value table */ + strcpy(value_table.val01,"160"); /*;AN001;DCR 434*/ + strcpy(value_table.val02,"160K"); /*;AN001;DCR 434*/ + strcpy(value_table.val03,"160KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val04,"180"); /*;AN001;DCR 434*/ + strcpy(value_table.val05,"180K"); /*;AN001;DCR 434*/ + strcpy(value_table.val06,"180KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val07,"320"); /*;AN001;DCR 434*/ + strcpy(value_table.val08,"320K"); /*;AN001;DCR 434*/ + strcpy(value_table.val09,"320KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val10,"360"); /*;AN001;DCR 434*/ + strcpy(value_table.val11,"360K"); /*;AN001;DCR 434*/ + strcpy(value_table.val12,"360KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val13,"720"); /*;AN001;DCR 434*/ + strcpy(value_table.val14,"720K"); /*;AN001;DCR 434*/ + strcpy(value_table.val15,"720KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val16,"1200"); /*;AN001;DCR 434*/ + strcpy(value_table.val17,"1200K"); /*;AN001;DCR 434*/ + strcpy(value_table.val18,"1200KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val19,"1.2"); /*;AN001;DCR 434*/ + strcpy(value_table.val20,"1.2M"); /*;AN001;DCR 434*/ + strcpy(value_table.val21,"1.2MB"); /*;AN001;DCR 434*/ + strcpy(value_table.val22,"1440"); /*;AN001;DCR 434*/ + strcpy(value_table.val23,"1440K"); /*;AN001;DCR 434*/ + strcpy(value_table.val24,"1440KB"); /*;AN001;DCR 434*/ + strcpy(value_table.val25,"1.44"); /*;AN001;DCR 434*/ + strcpy(value_table.val26,"1.44M"); /*;AN001;DCR 434*/ + strcpy(value_table.val27,"1.44MB"); /*;AN001;DCR 434*/ + + return; /*;AN000;4*/ +} /*;AN000;4*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: find_format +/* +/* FUNCTION: +/* +/* Search for the FORMAT utility. If found, then +/* build a full path to it from the root. If not +/* found, tell the user and terminate. +/* +/***************************************************/ +void find_format() /*;AN000;d178*/ +{ /*;AN000;d178*/ + BYTE found_it= FALSE; /*;AN000;d178*/ + BYTE no_more = FALSE; /*;AN000;d178*/ + int findex,pindex; /*;AN002;*/ + BYTE done = FALSE; /*;AN002;*/ + char path[130]; /*;AN002;*/ + + /*******************************/ + /* First try current directory */ + format_path[0] = '.'; /*;AN000;d178*/ + format_path[1] = NUL; /*;AN000;d178*/ + + /* Build full path */ + xlat(format_path,format_path); /*;AN000;d178*/ + + /* If at root, remove trailing backslash */ + if (strlen(format_path)==3 && format_path[1]==':') /*;AN000;p1900*/ + format_path[2] = NUL; /*;AN000;p1900*/ + + strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/ + + /* Now look for it */ + if (format_path[0] == tgt_drive_letter) /*;AN010;*/ + if (target_removable) /*;AN010;*/ + format_path[0] = NUL; /*;AN010;*/ + + if (exist(format_path)) /*;AN000;d178*/ + found_it = TRUE; /*;AN000;d178*/ + else /*;AN000;d178*/ + { + get_path(path); /*;AN002;*/ + + if (strlen(path)==0 || path[0]==NUL) /*;AN002;*/ + error_exit(CANT_FIND_FORMAT); /*;AN002;*/ + } + + pindex = 0; + while (!found_it && path[pindex] != NUL) + { + for (findex=0; path[pindex]!=NUL && path[pindex]!=';'; pindex++) /*;AN002;*/ + { /*;AN002;*/ + format_path[findex] = path[pindex]; /*;AN002;*/ + findex++; /*;AN002;*/ + } /*;AN002;*/ + + if (path[pindex]==';') + pindex++; + + format_path[findex] = NUL; /*;AN002;*/ + + xlat(format_path,format_path); /*;AN002;*/ + + if (strlen(format_path)==3 && format_path[1]==':') /*;AN000;p1900*/ + format_path[2] = NUL; /*;AN000;p1900*/ + + strcat(format_path,"\\FORMAT.COM"); /*;AN000;d178*/ + + if (format_path[0] == tgt_drive_letter) /*;AN010;*/ + if (target_removable) /*;AN010;*/ + format_path[0] = NUL; /*;AN010;*/ + + if (exist(format_path)) /*;AN000;d178*/ + found_it = TRUE; /*;AN000;d178*/ + } /*;AN000;d178*/ + + if (!found_it) /*;AN000;d178*/ + error_exit(CANT_FIND_FORMAT); /*;AN000;d178*/ + + return; /*;AN000;d178*/ +} /*;AN000;d178*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_path +/* +/* FUNCTION: +/* Finds the environment pointer in the PSP, and +/* searches the envirnment for a PATH statement. +/* If found, copies it to the buffer address passed in. +/* +/***************************************************/ +void get_path(p) /*;AN002;*/ +char *p; /*;AN002;*/ +{ /*;AN002;*/ + char far * env_ptr; /*;AN002;*/ + WORD env_seg; /*;AN002;*/ + BYTE got_path = FALSE; /*;AN002;*/ + BYTE done = FALSE; /*;AN002;*/ + union REGS xregs; /*;AN002;*/ + char path[130]; /*;AN002;*/ + + /* First find PSP */ + xregs.x.ax = 0x6200; /* Get PSP Address */ /*;AN002;*/ + intdos(&xregs,&xregs); /* Returned in BX */ /*;AN002;*/ + + /* Build pointer to env ptr from PSP+2c */ + env_ptr = far_ptr(xregs.x.bx,0x2c); /*;AN002;*/ + env_seg = *(WORD far *)env_ptr; /*;AN002;*/ + env_ptr = far_ptr(env_seg,0); /*;AN002;*/ + *p = NUL; /*;AN002;*/ + + /* Search for PATH in the environment */ + while (!done) /*;AN002;*/ + { /*;AN002;*/ + if /*;AN002;*/ + (*env_ptr == 'P' && /*;AN002;*/ + *(env_ptr+1) == 'A' && /*;AN002;*/ + *(env_ptr+2) == 'T' && /*;AN002;*/ + *(env_ptr+3) == 'H' && /*;AN002;*/ + *(env_ptr+4) == '=' /*;AN002;*/ + ) /*;AN002;*/ + { /*;AN002;*/ + done = TRUE; /*;AN002;*/ + got_path = TRUE; /*;AN002;*/ + } /*;AN002;*/ + else /*;AN002;*/ + if (*env_ptr == NUL && *(env_ptr+1) == NUL) /*;AN002;*/ + done = TRUE; /*;AN002;*/ + + if (!done) /*;AN002;*/ + env_ptr++; /*;AN002;*/ + } /*;AN002;*/ + + /* Copy path to desired buffer */ + if (got_path) /*;AN002;*/ + { /*;AN002;*/ + env_ptr += 5; /* Skip over "PATH=" */ /*;AN002;*/ + for (; *env_ptr!=NUL; env_ptr++) /*;AN002;*/ + { /*;AN002;*/ + *p = *env_ptr; /*;AN002;*/ + p++; /*;AN002;*/ + } /*;AN002;*/ + + *p = NUL; /*;AN002;*/ + } /*;AN002;*/ + + return; /*;AN002;*/ +} /*;AN002;*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: xlat +/* +/* FUNCTION: +/* +/* Performs name translate function. Calls DOS function +/* call 60h to build full path from root using the "src" +/* passed in, places resultant path at "tgt". +/* +/***************************************************/ +void xlat(tgt,src) /*;AN000;*/ +char * tgt; /*;AN000;*/ +char * src; /*;AN000;*/ +{ /*;AN000;*/ + union REGS xregs; + + xregs.x.ax = 0x6000; /* Name Xlat*/ /*;AN000;*/ + xregs.x.bx = 0; /* Drive*/ /*;AN000;*/ + xregs.x.si = (WORD)src; /* Source*/ /*;AN000;*/ + xregs.x.di = (WORD)tgt; /* Target*/ /*;AN000;*/ + intdos(&xregs,&xregs); /* Blammo!*/ /*;AN000;*/ + + return; /*;AN000;*/ +} /*;AN000;*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_drive_validity +/* +/* FUNCTION: +/* +/* Verify that at least the target drive letter is +/* is entered. Verify that they are valid drives. +/* +/***************************************************/ +void check_drive_validity(argc,argv) +int argc; +char *argv[]; +{ + char *t; + int i; + BYTE specified_drive; + + if (argc < 2) + error_exit(NO_SOURCE); + + /*********************/ + /* Verify the source */ + /*********************/ + *argv[1] = (BYTE)com_toupper(*argv[1]); + + + t = argv[1]; + t++; + if (*t == ':') /* Check specified source drive */ /*;AC000;p2671*/ + { /*;AN000;p2671*/ + if (*argv[1] < 'A') /*;AN000;p2671*/ + error_exit(INV_DRIVE); /*;AN000;p2671*/ + if (*argv[1] > 'Z') /*;AN000;p2671*/ + error_exit(INV_DRIVE); /*;AN000;p2671*/ + src_drive_letter = *argv[1]; /*;AN000;p2671*/ + } /* Use default drive for source */ /*;AN000;p2671*/ + else /*;AN000;p2671*/ + src_drive_letter = (BYTE)def_drive + 'A' - 1; /*;AN000;p2671*/ + + /*********************/ + /* Verify the target */ + /*********************/ + if (argc < 3 ) + error_exit(NO_TARGET); + + *argv[2] = (BYTE)com_toupper(*argv[2]); + + if (*argv[2] < 'A') + error_exit(INV_DRIVE); + if (*argv[2] > 'Z') + error_exit(INV_DRIVE); + + /* Verify drive letter followed by ":" */ + t = argv[2]; + t++; + if (*t != ':') + error_exit(NO_TARGET); + + /* Make sure drive letters are different */ + if (src_drive_letter == *argv[2]) /*;AN000;p2671*/ + error_exit(SRC_AND_TGT_SAME); + + /* Is source a valid drive? */ + specified_drive = src_drive_letter - 'A' + 1; + set_default_drive(specified_drive); + if (get_current_drive() != specified_drive) + error_exit(INV_DRIVE); + + /* Is target a valid drive? */ + specified_drive = *argv[2] - 'A' + 1; + set_default_drive(specified_drive); + if (get_current_drive() != specified_drive) + error_exit(INV_DRIVE); + + set_default_drive(def_drive); /* Reset default drive to original one */ + def_drive_set = FALSE; + + tgt_drive_letter = *argv[2]; + + return; +} /* end check_drive_validity */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_for_device_names +/* +/* FUNCTION: +/* +/* Make sure user not trying to restore a reserved device name +/* +/**************************************************/ +#define INVPARM 10 /*;AN000;4*/ +void check_for_device_names(argv) /*;AN000;p2592*/ +char *argv[]; /*;AN000;p2592*/ +{ /*;AN000;p2592*/ + union REGS qregs; /*;AN000;p2592*/ + char target[128]; /*;AN000;p2592*/ + char *t; /*;AN000;p2592*/ + +#define CAPITALIZE_STRING 0x6521 /*;AN000;p2592*/ + + qregs.x.ax = CAPITALIZE_STRING; /*;AN000;p2592*/ + qregs.x.dx = (WORD)argv[1]; /*;AN000;p2592*/ + strcpy(target,argv[1]); /*;AN000;p2592*/ + qregs.x.cx = strlen(target); /*;AN000;p2592*/ + intdos(&qregs,&qregs); /*;AN000;p2592*/ + strcpy(target,argv[1]); /*;AN000;p2592*/ + + for (t=&target[0]; *t!=NUL; t++) + if /*;AN000;p2592*/ + ( strcmp(t,"LPT1")==0 || /*;AN000;p2592*/ + strcmp(t,"LPT2")==0 || /*;AN000;p2592*/ + strcmp(t,"PRN")==0 || /*;AN000;p2592*/ + strcmp(t,"CON")==0 || /*;AN000;p2592*/ + strcmp(t,"NUL")==0 || /*;AN000;p2592*/ + strcmp(t,"AUX")==0 || /*;AN000;p2592*/ + strcmp(t,"LPT1:")==0 || /*;AN000;p2592*/ + strcmp(t,"LPT2:")==0 || /*;AN000;p2592*/ + strcmp(t,"PRN:")==0 || /*;AN000;p2592*/ + strcmp(t,"CON:")==0 || /*;AN000;p2592*/ + strcmp(t,"NUL:")==0 || /*;AN000;p2592*/ + strcmp(t,"AUX:")==0 /*;AN000;p2592*/ + ) /*;AN000;p2592*/ + { /*;AN000;p2592*/ + sublist.value1 = (char far *)t; /*;AN000;p2592*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;p2592*/ + sublist.one = 0; /*;AN000;p2592*/ + sublist.max_width1 = (BYTE)strlen(t); /*;AN000;p2592*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;p2592*/ + + display_it (INVPARM,STDERR,1,NOWAIT,(BYTE)PARSEERROR); /*;AN000;p2592*/ + return_code = RETCODE_ERROR; /*;AN000;4*/ + clean_up_and_exit(); /*;AN000;4*/ + } /*;AN000;p2592*/ + + + return; /*;AN000;p2592*/ +} /*;AN000;p2592*/ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_path_validity +/* +/* FUNCTION: +/* +/* Verify that the path entered by the user exists. +/* Build a full path from the root, place it in +/* src_drive_path. Extract filespec and place it +/* in user_filespec. +/* +/***************************************************/ +void check_path_validity(argv) +char *argv[]; +{ + WORD dhandle; + char temppath[PATHLEN+20]; + char temppath2[PATHLEN+20]; + char globals = FALSE; + int x; /*;AN000;p2943*/ + char *foo,*foo2; /*;AN003;*/ + union REGS qregs; /*;AC000;8*/ + + strcpy(src_drive_path_fn,argv[1]); /* Copy argv[1] to string area */ + + for (x=0; x 2) + *foo = NUL; + else + { /* foo must = 2 */ + foo++; + *foo = NUL; + } + + /************************/ + /* Build src_fn **/ + foo = com_strrchr(src_drive_path_fn,BACKSLASH); /*;AN000;p2341*/ + + if (foo == NUL) /*;AN000;p2341*/ + foo = &src_drive_path_fn[2]; /*;AN000;p2341*/ + else /*;AN000;p2341*/ + foo++; /* Skip over last non-DBCS char */ /*;AN000;p2341*/ + + strcpy(src_fn,foo); /*;AN003;*/ + + got_path_validity = TRUE; /*;AN000;4*/ + + return; +} /* end check_path_validity */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: alloc_buffers +/* +/* FUNCTION: +/* Attempt to allocate a (64k-1) buffer. If +/* fails, decrement buff size by 512 and keep +/* trying. If can't get at least a 2k buffer, +/* give up. +/* +/***************************************************/ +void alloc_buffer() +{ + alloc_seg(); + + while ((rc != NOERROR) && (data_file_alloc_size > 2048)) + { + data_file_alloc_size = data_file_alloc_size - 512; + alloc_seg(); + } + + if (rc == NOERROR && data_file_alloc_size > 2048) + buffers_allocated = TRUE; + else + error_exit(INSUFF_MEMORY); + + return; +} + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: process_switch +/* +/* FUNCTION: +/* +/* Identify the parameter and set program control +/* flags as appropriate. +/* +/***************************************************/ +void process_switch() /*;AN000;4*/ +{ /*;AN000;4*/ + char far * y; /*;AN000;4*/ + int i = 0; /*;AN000;4*/ + char temp_str[PATHLEN+20]; /*;AN000;7*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch1[0]) /* /S */ /*;AN000;4 /S */ + { /*;AN000;4*/ + do_subdirs=TRUE; /*;AN000;4*/ + } /*;AN000;4*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw5.switch1[0]) /* /F */ /*;AN001;DCR 434 /F */ + { /*;AN001;DCR 434*/ + if (!target_removable) /*;AN001;DCR 434*/ + error_exit(CANT_FORMAT_HARDFILE); /*;AN001;DCR 434*/ + + do_format_parms=TRUE; /*;AN001;DCR 434*/ + format_size[0] = ' '; /* Can't do STRCPY during PARSE */ /*;AN001;DCR 434*/ + format_size[1] = '/'; /*;AN001;DCR 434*/ + format_size[2] = 'F'; /*;AN001;DCR 434*/ + format_size[3] = ':'; /*;AN001;DCR 434*/ + format_size[4] = NUL; /*;AN001;DCR 434*/ + + i = 4; /* Copy size */ /*;AN001;DCR 434*/ + for (y=(char *)sw_buff.sw_string_ptr; *y!=NUL; y++) /*;AN001;DCR 434*/ + { /*;AN001;DCR 434*/ + format_size[i] = (BYTE)*y; /*;AN001;DCR 434*/ + i++; /*;AN001;DCR 434*/ + } /*;AN001;DCR 434*/ + + /* Handle case where user only enters /F */ + if ( + format_size[4] == NUL || /*;AN001;DCR 434*/ + format_size[4] < '0' || /*;AN001;DCR 434*/ + format_size[4] > '9' /*;AN001;DCR 434*/ + ) /*;AN001;DCR 434*/ + format_size[0] = NUL; /*;AN001;DCR 434*/ + + } /*;AN001;DCR 434*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch2[0]) /* /M */ /*;AN000;4 /M */ + { /*;AN000;4*/ + do_modified=TRUE; /*;AN000;4*/ + } /*;AN000;4*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw1.switch3[0]) /* /A */ /*;AN000;4 /A */ + { /*;AN000;4*/ + do_add=TRUE; /*;AN000;4*/ + } /*;AN000;4*/ + + if (sw_buff.sw_synonym_ptr == (WORD)&sw4.switch1[0]) /* /L */ /*;AN000;4 /L */ + { /*;AN000;4*/ + do_logfile = TRUE; /*;AN000;4*/ + i = 0; /* Copy filespec */ /*;AN000;4*/ + for (y=(char far *)sw_buff.sw_string_ptr; *y!=NUL; y++) /*;AN000;4*/ + { /*;AN000;4*/ + temp_str[i] = (BYTE)*y; /*;AN000;4*/ + i++; /*;AN000;4*/ + } /*;AN000;4*/ + + temp_str[i] = NUL; /*;AN000;4*/ + + if (strlen(temp_str) == 0) /* Use default logfile? */ /*;AN000;7 Is default logfile?*/ + sprintf(temp_str,"%c:\\BACKUP.LOG",src_drive_letter); /*;AN000;7*/ + + xlat(logfile_path,temp_str); /*;AN000;7*/ + + if ((BYTE)logfile_path[0] == tgt_drive_letter) /*;AN000;7*/ + logfile_on_target = TRUE; /*;AN000;7*/ + } /*;AN000;4*/ + + return; /*;AN000;4*/ +} /* end process_switch */ /*;AN000;4*/ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: save_current_dirs +/* +/* FUNCTION: +/* +/* Save the current directory on default drive. +/* Later when we terminate we must restore it. +/* +/***************************************************/ +void save_current_dirs() +{ + + src_def_dir[0] = BACKSLASH; + get_current_dir(src_drive_letter -'A'+1,&src_def_dir[1]); + + return; +} /* end save_current_dirs */ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: open_logfile +/* +/* FUNCTION: +/* User specified the /L parameter for a BACKUP +/* log file. First try to open it. If it doesn't +/* exist then create it. +/* +/***************************************************/ +void open_logfile() +{ + int x; /*;AN000;7*/ + + handle_logfile = /*;AN000;5*/ + extended_open /*;AN000;5*/ + (OPEN_IT, /* Flag;AN000;5*/ + 0, /* attr;AN000;5*/ + (char far *)logfile_path, /* path;AN000;5*/ + (WORD)(DENYWRITE+WRITEACCESS) /* mode;AN000;5*/ + ); /*;AN000;5*/ + + if (rc == NOERROR) + lseek(handle_logfile,EOFILE,(DWORD)0); + else /* If you didn't, create the file */ + handle_logfile = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( CREATE_IT, /*;AN000;5*/ + (WORD)ARCHIVE, /*;AN000;5*/ + (char far *)logfile_path, /*;AN000;5*/ + (WORD)(WRITEACCESS) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc != NOERROR) /* Terminate if can't open logfile */ + error_exit(CANT_OPEN_LOGFILE); + + display_msg(LOGGING); /* Tell user where we are logging */ + + datetime(); /* Put date and time of BACKUP in logfile */ + + logfile_opened = TRUE; /*;AN000;7 The logfile is open */ + + return; +} /* end open_logfile */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: set_vectors +/* +/* FUNCTION: +/* Hook control break and critical vector to +/* allow BACKUP to gracefully terminate. +/* +/***************************************************/ +void set_vectors() +{ + + setsignal(ACTIONHOOK,CTRLC); /* Handle CTRL_C */ + setsignal(ACTIONHOOK,CTRLBREAK); /* Handle CTRL_BREAK */ + set_int24_vector(); /*;AN000; Set Critical error vector (int 24h) */ + + return; +} /* end set_vectors */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_appendX +/* +/* FUNCTION: +/* Check APPEND /X status. If it is not active, +/* do nothing. If it is active, then turn it off +/* and set flag indicating that we must reset it later. +/* +/***************************************************/ +void check_appendX() /*;AN000;2*/ +{ /*;AN000;2*/ + union REGS gregs; /*;AN000;2 Register set */ + + gregs.x.ax = INSTALL_CHECK; /*;AN000;2 Get installed state*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + /*****************************************************/ + /* 1) See if append is active + /* 2) If so, figure out if DOS or PCNET version + /*****************************************************/ + if (gregs.h.al == 0) /*;AN000;2 Zero if not installed*/ + append_indicator = NOT_INSTALLED; /*;AN000;2 */ + else /*;AN000;2 See which APPEND it is*/ + { /*;AN000;2*/ + gregs.x.ax = GET_APPEND_VER; /*;AN000;2*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + if (gregs.h.al == (BYTE)-1) /*;AN000;2 -1 if DOS version*/ + append_indicator = DOS_APPEND; /*;AN000;2*/ + else /*;AN000;2*/ + append_indicator = NET_APPEND; /*;AN000;2*/ + } /*;AN000;2*/ + + /*****************************************************/ + /* If it is the DOS append + /* 1) Get the current append functions (returned in BX) + /* 2) Reset append with /X support off + /*****************************************************/ + if (append_indicator == DOS_APPEND) /*;AN000;2*/ + { /*;AN000;2*/ + gregs.x.ax = GET_STATE; /*;AN000;2 Get active APPEND functions*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + original_append_func = gregs.x.bx; /*;AN000;2*/ + + gregs.x.ax = SET_STATE; /*;AN000;2*/ + gregs.x.bx = gregs.x.bx & (!APPEND_X_BIT); /*;AN000;2*/ + int86(0x2f,&gregs,&gregs); /*;AN000;2*/ + + } /*;AN000;2*/ + + return; /*;AN000;2*/ +} /*;AN000;2*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_drive_types +/* +/* FUNCTION: +/* For the source and target drives, figure out +/* if they are removable or not. +/* +/***************************************************/ +void get_drive_types() /* Check if the source and target drive are removable*/ +{ +#define REMOVABLE 0 + + WORD drivehandle; + char drive_spec[3]; + + /* Check Source drive */ + drive_spec[0] = src_drive_letter; + drive_spec[1] = ':'; + drive_spec[2] = NUL; + + /* Device open, source drive */ + drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ; + + /* Now see if it is removable */ + if (ioctl(drivehandle) == REMOVABLE) + source_removable = TRUE; + else + source_removable = FALSE; + + close_file(drivehandle); + + /* Check Target drive */ + drive_spec[0] = tgt_drive_letter; + drive_spec[1] = ':'; + drive_spec[2] = NUL; + + drivehandle = handle_open(drive_spec,OPENDASD+DENYNONE) ; + + if (ioctl(drivehandle) == REMOVABLE) + target_removable = TRUE; + else + target_removable = FALSE; + + close_file(drivehandle); + + return; +} /* end get_drive_types */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: do_backup +/* +/* FUNCTION: +/* +/* BACKUP all files that should be backed up +/* +/***************************************************/ +void do_backup() +{ + set_default_dir(); /* Set default dir to one where source files are */ + + find_first_file(); /* Find first file to be backed up */ + if (back_it_up) /* If you found one.... */ + { /* then */ + get_first_target(); /* get the first diskette (or last if /A specified!) */ + do /* Repeat this */ + { + open_source_file(); /* Open the file we found */ + if (source_opened) /* If succeessful open of source */ + do_copy(); /* Copy it to the target drive. Handle files that span diskettes. */ + find_next_file(); /* Search for another file */ + } + while (back_it_up); /* While there are file to back up */ + display_msg(CRLF); + } + else /* otherwise */ + { + display_msg(NONEFNDMSG); + return_code = RETCODE_NO_FILES;/* there were no files to be backed up */ + } + + clean_up_and_exit(); + + return; +} /* end do_backup */ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: find_first_file +/* +/* FUNCTION: +/* +/* Find the first file conforming to user entered spec. +/* If necessary, look on other directory levels also. +/* +/***************************************************/ +void find_first_file() +{ + char loop_done = FALSE; + + back_it_up = FALSE; /* Havn't found a file yet ! */ + find_the_first(); /* Sets the "found_a_file" flag */ + + if (found_a_file) /* If you find a file, do this stuff */ + do + { + if (found_a_file) /* If you got one, then */ + see_if_it_should_be_backed_up(); /* Check it against user entered parameters */ + + if (!back_it_up) /* If it shouldn't be processed... */ + find_the_next(); /* then find another (sets the "found_a_file" flag) */ + else + loop_done = TRUE; /* Otherwise your done here */ + + if (!found_a_file) /* Don't remove this ! */ + loop_done = TRUE; /* This has gotta stay ! */ + } + while (!loop_done); + + return; +} /* end find_first_file */ + +/** *********************************************/ +/* +/* SUBROUTINE NAME: find_next_file +/* +/* FUNCTION: +/* +/* Find the next file conforming to user entered spec +/* +/************************************************/ +void find_next_file() +{ + char loop_done = FALSE; + + back_it_up = FALSE; + + do + { + find_the_next(); + if (found_a_file) + { + see_if_it_should_be_backed_up(); + if (back_it_up) + loop_done = TRUE; + } + else + loop_done = TRUE; + } + while (!loop_done); + + return; +} /* end find_next_file */ + +/** *********************************************/ +/* +/* SUBROUTINE NAME: find_the_first +/* +/* FUNCTION: +/* +/* Find the first file conforming to user entered spec. +/* Searches in current directory, if one not found then +/* goes to the next level and repeats. +/* +/************************************************/ +void find_the_first() +{ + char loop_done = FALSE; + char file_spec[PATHLEN]; + + found_a_file = FALSE; + sprintf(file_spec,"%c:%s",src_drive_letter,src_fn); + + do + { + find_first /* Find file conforming to user-entered file spec */ + ( + &file_spec[0], + &dirhandle, + dta_addr, + (SYSTEM + HIDDEN) + ); + + if (rc == NOERROR) + { /* If no error */ + found_a_file = TRUE; /* then we found a file */ + loop_done = TRUE; /* and we are done here */ + } + else /* If there was an error */ + if (do_subdirs) /* and if user said /S */ + { + change_levels(); /* Change DIR (Sets NewDirectory if level changed) */ + if (!new_directory) /* If there ain't none */ + loop_done = TRUE; /* then were done */ + } + else + loop_done = TRUE; + } + while (!loop_done); + + return; +} /* end find_the_first */ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: find_the_next +/* +/* FUNCTION: +/* +/* Find the next file conforming to user entered spec +/* +/***************************************************/ +void find_the_next() +{ + char loop_done = FALSE; + + found_a_file = FALSE; + + find_next(dirhandle,dta_addr); + + if (rc == NOERROR) + { + found_a_file = TRUE; + loop_done = TRUE; + } + else + do + { + if (do_subdirs) + { + change_levels(); /* Change DIR to next dir level */ + if (!new_directory) /* If we were successful */ + loop_done = TRUE; /* Then indicate that fact */ + else /* otherwise */ + { + find_the_first(); /* Look for first file at this level */ + loop_done = TRUE; + } + } + else + loop_done = TRUE; + } + while (!loop_done); + + return; +} /* end find_the_next */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: change_levels +/* +/* FUNCTION: +/* Change directory to next one in the linked list +/* of directories to be processed. +/* +/***************************************************/ +void change_levels() +{ + new_directory = FALSE; + remove_node(); + return; +} /* end change_levels */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: alloc_node +/* +/* FUNCTION: +/* Allocates a node for the linked list of subdirectories +/* to be processed. +/* +/***************************************************/ +struct node * alloc_node(path_len) +unsigned int path_len; +{ + struct node *pointer; + unsigned int malloc_size; + + malloc_size = (unsigned int) (sizeof(struct node far *) + path_len + 2); +#if defined(DEBUG) + printf("\nMALLOCING NODE, SIZE=%04Xh...",malloc_size); +#endif + + pointer = (struct node *)malloc(malloc_size); + +#if defined(DEBUG) + if (pointer != NUL) + printf("SUCCESSFUL, PTR=%u",(unsigned)pointer); + else + printf("ERROR, PTR=%u",(unsigned)pointer); +#endif + + if (pointer == NUL) + error_exit(INSUFF_MEMORY); + else + return(pointer); + +} /* end alloc_node */ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: alloc_first_node +/* +/* FUNCTION: +/* +/* Allocate the first node in the linked list. +/* +/***************************************************/ +void alloc_first_node() +{ +#if defined(DEBUG) +printf("\nINSERTING FIRST NODE=%s",src_drive_path); +#endif + + curr_node = alloc_node(strlen(src_drive_path+1)); + last_child = curr_node; + strcpy(curr_node->path,src_drive_path); + curr_node->np = NUL; + + return; +} /* end alloc_first_node */ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: insert_node +/* +/* FUNCTION: +/* +/* Insert next node in the linked list of subdirectories +/* to be processed. +/* +/***************************************************/ +void insert_node(path_addr) +char *path_addr; +{ + struct node *temp; /* temporary pointer to a node */ + struct node *newnode; /* same thing */ + +#if defined(DEBUG) +printf("\nINSERTING NODE=%s",*path_addr); +#endif + temp = last_child->np; + newnode = alloc_node(strlen(path_addr)); + last_child->np = newnode; + newnode->np = temp; + strcpy(newnode->path,path_addr); + last_child = newnode; + + return; +} /* end insert_node */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: remove_node +/* +/* FUNCTION: +/* CHDIR to the next level to be processed. +/* Release the node for that directory +/* +/***************************************************/ +void remove_node() +{ + struct node *temp; + + temp = curr_node; + last_child = curr_node->np; + if (curr_node->np != NUL) + { + rc = chdir(last_child->path); + if (rc == NOERROR) + { + new_directory = TRUE; + strcpy(src_drive_path,last_child->path); + +#if defined(DEBUG) + printf("\nFREE NODE %u",(unsigned)curr_node); +#endif + free((char *)curr_node); + curr_node = last_child; + + if (do_subdirs) /* Place all subdirs in linked list */ + find_all_subdirs(); + } + } + return; +} /* end remove_node */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: find_all_subdirs +/* +/* FUNCTION: +/* User entered "/S" parameter. Search for all +/* subdirectory entries at this level. Place +/* them all in the linked list of directories to +/* be processed. +/***************************************************/ +void find_all_subdirs() +{ + WORD dhandle; + char global[6]; + char full_path[PATHLEN+20]; + struct FileFindBuf tempdta; + + sprintf(global,"%c:*.*",src_drive_letter); + + find_first /* Find all subdirectory entries in current directory. */ + ( + &global[0], + &dhandle, + &tempdta, + (SUBDIR + SYSTEM + HIDDEN) + ); + + while (rc == NOERROR) + { + if ((tempdta.attributes & SUBDIR) == SUBDIR) /* If its a subdirectory */ + if (tempdta.file_name[0] != '.') /* But not "." or ".." */ + { + if (src_drive_path[strlen(src_drive_path)-1] != BACKSLASH) + sprintf(full_path,"%s\\%s",src_drive_path,tempdta.file_name); + else + sprintf(full_path,"%s%s", src_drive_path,tempdta.file_name); + + insert_node((char *)full_path); /* Save it in the linked list */ + } + + find_next(dhandle,&tempdta); + } + + return; +} + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_first_target +/* +/* FUNCTION: +/* We are ready for the target disk. If it is a +/* diskette, ask user to put one in. Remember +/* to correctly handle /A if user wants it. +/* +/***************************************************/ +void get_first_target() +{ + if (target_removable) + get_diskette(); + else + get_hardfile(); + + if (do_logfile) + open_logfile(); /*;AN000;7 Open or create logfile*/ + + if (!do_add) + put_disk_header(); + + return; +} /* end get_first_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_next_target +/* +/* FUNCTION: +/* We are ready for the next target diskette. +/* Ask user to insert it. Format if required. +/* Create files, reset variables. +/* +/***************************************************/ +void get_next_target() +{ + + doing_first_target = FALSE; + files_backed_up = 0; + display_msg(CRLF); + + get_diskette(); /* Get it */ + + disk_full = FALSE; + + if (do_logfile) + { + if (logfile_on_target) /*;AN000;7 and if logfile on the target drive*/ + open_logfile(); /*;AN000;7 Open or create it*/ + } + + if (file_spans_target) + show_path(); /* Display to stdout and logfile the full path from root */ + + put_disk_header(); + put_new_fh(); + + return; +} /* end get_next_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: see_if_it_should_be_backed_up +/* +/* FUNCTION: +/* We found a file, its directory information is +/* at the DTA structure. Don't backup a subdirectory +/* or volume label. If /M specified, only backup files +/* with archive bit set. Don't BACKUP 0 length files. +/* If /D: and/or /T: specified, only backup appropriate files. +/* +/***************************************************/ +void see_if_it_should_be_backed_up() +{ + BYTE temp[PATHLEN+20]; /*;AN006;*/ + + back_it_up = TRUE; + + if ((dta.attributes & SUBDIR) == SUBDIR) /* Is it a directory name ? */ + back_it_up = FALSE; /* Indicate that we don't want to back it up */ + + if ((dta.attributes & VOLLABEL) == VOLLABEL) /* Is it a volumelabel ? */ + back_it_up = FALSE; /* Indicate that we don't want to back it up */ + + if (do_modified) /* Check ARCHIVE bit */ + if ((dta.attributes & ARCHIVE) != ARCHIVE) + back_it_up = FALSE; + + if (do_time) /* Check TIME parameter */ + { + if (do_date) + { /* If user entered a date, only files modified */ + if (dta.write_date == user_specified_date) /* after specified time AND ON THE DATE ENTERED */ + if (dta.write_time < user_specified_time) /* will be processed. Files dated after that will */ + back_it_up = FALSE; /* ignore time parm */ + } + else /* If user entered time with NO DATE PARM, then */ + if (dta.write_time < user_specified_time) /* files modifed on or after specified time will be */ + back_it_up = FALSE; /* processed, regardless of date */ + } + + if (do_date) /* Check DATE parameter */ + { + if (dta.write_date < user_specified_date) + back_it_up = FALSE; + } + +#define SAME 0 + + if (strcmp(src_drive_path+2,"\\") == SAME) /*;AN000;1 If we are processing the root directory */ + if /*;AN000;1 and if we are looking at any of these files */ + (strcmp(dta.file_name,"IBMBIO.COM") == SAME || /*;AN000;1*/ + strcmp(dta.file_name,"IBMDOS.COM") == SAME || /*;AN000;1*/ +#if ! IBMCOPYRIGHT + strcmp(dta.file_name,"IO.SYS") == SAME || /*;AN000;1*/ + strcmp(dta.file_name,"MSDOS.SYS") == SAME || /*;AN000;1*/ +#endif + strcmp(dta.file_name,"COMMAND.COM") == SAME || /*;AN000;1*/ + strcmp(dta.file_name,"CMD.EXE") == SAME /*;AN000;1*/ + ) /*;AN000;1*/ + back_it_up = FALSE; /*;AN000;1 then do not back them up! */ + + + + if (do_logfile) /*;AN006;*/ + { /*;AN006;*/ + strcpy(temp,src_drive_path); /*;AN006;*/ + + if (strlen(temp) == 3) /*;AN006;*/ + temp[2] = NUL; /*;AN006;*/ + + sprintf(temp,"%s\\%s",temp,dta.file_name); /*;AN006;*/ + + if (strcmp(logfile_path,temp) == SAME)/*;AN006;*/ + back_it_up = FALSE; /*;AN006;*/ + } /*;AN006;*/ + + return; +} /* end see_if_it_should_be_backed_up */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_diskette +/* +/* FUNCTION: +/* Get the diskette from user. If unformatted +/* and user entered /F, then try to FORMAT it. +/* Create target files on root of diskette. +/**************************************************/ +void get_diskette() +{ + union REGS qregs; /*;AN000;8*/ + + if (!do_add) + { + display_msg(INSERTTARGET); + display_msg(ERASEMSG); + } + else + if (doing_first_target) + display_msg(LASTDISKMSG); + else + { + display_msg(INSERTTARGET); + display_msg(ERASEMSG); + } + + got_first_target = TRUE; /*;AN000;*/ + + /*wait_for_keystroke(); /* Let user "Strike any key when ready" */ + + /* If single drive system, eliminates double prompting */ + /* for user to "Insert diskette for drive %1" */ + qregs.x.ax = SETLOGICALDRIVE; /*;AN000;8*/ + qregs.h.bl = tgt_drive_letter - 'A' + 1; /*;AN000;8*/ + intdos(&qregs,&qregs); /*;AN000;8*/ + + if (target_removable) /*;AN000;d177*/ + format_target(); + + if (do_add) /* If we are adding files */ + if (doing_first_target) /* and if its the first target */ + check_last_target(); /* verify that its a valid one */ + + display_msg(BUDISKMSG); + display_msg(SEQUENCEMSG); + delete_files(ROOTDIR); /* Delete all files in the root dir of target drive */ + + create_target(); /* Create target files */ + + return; +} /* end get_diskette */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: get_hardfile +/* +/* FUNCTION: +/* Target is a hardfile. FORMATTING hardfile is +/* not allowed by BACKUP. Create target files +/* in BACKUP directory of disk. +/***************************************************/ +void get_hardfile() +{ + char dirname[15]; + + sprintf(dirname,"%c:\\BACKUP\\*.*",tgt_drive_letter); + if (exist(&dirname[0])) + { + if (!do_add) + { + display_msg(FERASEMSG); + /*wait_for_keystroke(); /* Let user "Strike any key when ready" */ + } + delete_files(BACKUPDIR); /* Delete \BACKUP\*.* of target drive if not do_add */ + } + else + { + sprintf(dirname,"%c:\\BACKUP",tgt_drive_letter); + mkdir(dirname); + } + + display_msg(BUDISKMSG); + create_target(); + + return; +} /* end get_hardfile */ + + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: check_last_target +/* +/* FUNCTION: +/* User entered /A parameter. Make sure that +/* we are not adding to a BACKUP diskette created +/* with the disgusting old BACKUP format. +/* Make sure there is a BACKUP.xxx and CONTROL.xxx +/* file out there. Make sure it was the last target +/* and get the sequence number. +/***************************************************/ +void check_last_target() +{ + WORD dhandle; + WORD bytes_read; + BYTE flag; + char path[25]; + char current_file[25]; + + struct FileFindBuf tempdta; + + if (target_removable) /* Make sure there is no old BACKUP on here */ + sprintf(path,"%c:\\BACKUPID.@@@",tgt_drive_letter); + else + sprintf(path,"%c:\\BACKUP\\BACKUPID.@@@",tgt_drive_letter); + + if (exist(path)) + error_exit(INVTARGET); + + if (target_removable) /* Build path to control file */ + sprintf(path,"%c:\\CONTROL.*",tgt_drive_letter); + else + sprintf(path,"%c:\\BACKUP\CONTROL.*",tgt_drive_letter); + + find_first /* Find the control file */ + ( + &path[0], + &dhandle, + &tempdta, + (SYSTEM + HIDDEN) + ); + + if (rc != NOERROR) /* If you got one, then close dirhandle */ + error_exit(NOTLASTMSG); + + findclose(dhandle); + + + /* Add drive letter to control file name */ + sprintf(path,"%c:%s",tgt_drive_letter,tempdta.file_name); + + handle_control = /* Open the control file;AN000;5*/ + extended_open /*;AN000;5*/ + (OPEN_IT, /*;AN000;5*/ + 0, /*;AN000;5*/ + (char far *)path, /*;AN000;5*/ + (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc != NOERROR) /* If can't open it, strange error */ + error_exit(NOTLASTMSG); + + /* Get diskette sequence number */ + lseek(handle_control,BOFILE,(DWORD)9); + bytes_read = handle_read(handle_control,1,(char far *)&diskettes_complete); + diskettes_complete--; /* This diskette is not longer "complete" */ + + /* Seek to DH_LastDisk and read that byte */ + lseek(handle_control,BOFILE,(DWORD)138); /* Check DH_LastDisk flag in control file */ + bytes_read = handle_read(handle_control,1,(char far *)&flag); + + if (flag != LAST_TARGET) /* If wasn't last target, terminate */ + error_exit(NOTLASTMSG); + + close_file(handle_control); /* Close the control file */ + control_opened = FALSE; /*;AN005; And say it isn't open */ + + return; +} /* end check_last_target */ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: format_target +/* +/* FUNCTION: +/* See if the target is formatted. If not, try +/* to format it. +/* +/***************************************************/ +void format_target() +{ +#define HOOK 0 +#define UNHOOK 1 + + WORD bfree; + char format_parms[35]; /*;AC000;8*/ + WORD temp_rc; /*;AN000;p2631 Return code from DOS calls */ + + if (do_add) + if (doing_first_target) + return; + + /**********************************/ + /* See if diskette is unformatted */ + /**********************************/ + do_dos_error(HOOK); /* Replace hard error handler */ + rc = NOERROR; /* Reset return code */ + checking_target = TRUE; /*;AN007;*/ + bfree = (WORD)disk_free_space();/* If this generates hard error, then format target */ + checking_target = FALSE; /*;AN007;*/ + + temp_rc = rc; /*;AN000;p2631*/ + do_dos_error(UNHOOK); /*;AN000;p2631 Unhook hard error handler */ + rc = temp_rc; /*;AN000;p2631*/ + + if (rc != NOERROR) /* If there was a hard error... */ + { /* Then FORMAT the target */ + display_msg(CRLF); + + sprintf(format_parms,"%c:",tgt_drive_letter); + + if (do_format_parms) /*;AN001;DCR 434*/ + if (format_size[0] != NUL) /*;AN001;DCR 434*/ + strcat(format_parms,format_size); /*;AN001;DCR 434*/ + + strcat(format_parms," /BACKUP /V:BACKUP"); /*;AN000;8*/ + + if (spawnlp(P_WAIT,format_path,"FORMAT",format_parms,NUL) == NOERROR) /*;AC000;d178*/ + { + display_msg(CRLF); /* Skip a line */ + } + else + { + display_msg(ERR_EXEC_FORMAT); /* Display "Error executing FORMAT" */ + display_msg(INSERTTARGET); /* And give another chance */ + display_msg(ERASEMSG); + /*wait_for_keystroke(); */ + } + + } + + return; +} /* end format_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: set_default_dir +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void set_default_dir() +{ + if (com_strchr(src_drive_path,BACKSLASH) != NUL) /* if there IS a backslash... */ + if (strlen(src_drive_path) >= 3) /* if length is greater than 3... */ + { + rc = chdir(src_drive_path); /* then change dir to there. */ + if (rc == NOERROR) + { + src_drive_path[2] = BACKSLASH; + get_current_dir(src_drive_letter-'A'+1,&src_drive_path[3]); + } + else + error_exit(INV_PATH); + } + + curr_dir_set = TRUE; + + if (do_subdirs) /* If we are processing subdirectories too, */ + { + alloc_first_node(); /* then put current level in linked list */ + find_all_subdirs(); /* And get all directory entries in that level */ + } + + return; +} /* end set_default_dir */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: label_target_drive +/* +/* FUNCTION: +/* Create volume label BACKUP.xxx on target +/* diskette drive. +/* +/***************************************************/ +void label_target_drive() /* Create Volume label BACKUP.XXX on target */ +{ + + char fsbuf[20]; + WORD handle; + + build_ext(diskettes_complete + 1); + + sprintf(fsbuf,"%c:BACKUP.%s",tgt_drive_letter,ext); + + replace_volume_label(&fsbuf[0]); + + return; +} /* end label_target_drive */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: build_ext +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void build_ext(num) +int num; +{ + if (num < 10) + sprintf(ext,"00%u",num); + else + if (num < 100) + sprintf(ext,"0%u",num); + else + sprintf(ext,"%u",num); + + return; +} /* end build_ext */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: create_target +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void create_target() +{ + char path[25]; + + if (do_add) + if (doing_first_target) + { + open_target(); + return; + } + + build_ext(diskettes_complete + 1); + + if (target_removable) + sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); + else + sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); + + handle_target = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( /*;AN000;5*/ + CREATE_IT, /*;AN000;5*/ + (WORD)ARCHIVE, /*;AN000;5*/ + (char far *)path, /*;AN000;5*/ + (WORD)(READWRITE) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc == NOERROR) + target_opened = TRUE; + else + error_exit(INVTARGET); + + if (target_removable) + sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); + else + sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); + + handle_control = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( /*;AN000;5*/ + CREATE_IT, /*;AN000;5*/ + (WORD)ARCHIVE, /*;AN000;5*/ + (char far *)path, /*;AN000;5*/ + (WORD)(READWRITE) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc == NOERROR) + control_opened = TRUE; + else + error_exit(INVTARGET); + + data_file_tot_len = (DWORD)0; + ctl_file_tot_len = (DWORD)0; + + return; +} /* end create_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: open_target +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void open_target() /* Done only if /A and it is the first target */ +{ + + char path[PATHLEN+20]; + + /* Open BACKUP.xxx File */ + build_ext(diskettes_complete+1); + + if (target_removable) + sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); + else + sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); + + /* Turn off readonly bit on BACKUP.xxx */ + set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF)); + /* Open it */ + handle_target = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( OPEN_IT, /*;AN000;5*/ + 0, /*;AN000;5*/ + (char far *)path, /*;AN000;5*/ + (WORD)(DENYALL+READWRITE) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc == NOERROR) + target_opened = TRUE; + else + error_exit(INVTARGET); + /* Open CONTROL.xxx File */ + if (target_removable) + sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); + else + sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); + + set_attribute(path,(WORD)(get_attribute(path) & (WORD)READONLYOFF)); + + handle_control = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( OPEN_IT, /*;AN000;5*/ + 0, /*;AN000;5*/ + (char far *)path, /*;AN000;5*/ + (WORD)(DENYALL+READWRITE) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc == NOERROR) + control_opened = TRUE; + else + error_exit(INVTARGET); + + data_file_tot_len = (DWORD)lseek(handle_target ,EOFILE,(DWORD)0); + ctl_file_tot_len = (DWORD)lseek(handle_control,EOFILE,(DWORD)0); + + return; +} /* end open_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: delete_files +/* +/* FUNCTION: +/* Delete all files in the root directory of target +/* diskette, or in the BACKUP directory of the target +/* hardfile. If error occurs deleting file, try to +/* reset the attribute to 0 and try it again. +/* +/* +/***************************************************/ +void delete_files(dirlevel) +char dirlevel; +{ + BYTE delete_path[25]; + struct FileFindBuf tempdta; + struct FileFindBuf *tempdta_addr; + WORD dhandle; + BYTE delete_it; /*;AN000;7*/ + + if (do_add) /* Don't delete files if we */ + if (doing_first_target) /* are adding files to an existing */ + return; /* BACKUP and this is the first target */ + + tempdta_addr = (struct FileFindBuf *)&tempdta; + + if (dirlevel == ROOTDIR) + sprintf(delete_path,"%c:\\*.*",tgt_drive_letter); + else + sprintf(delete_path,"%c:\\BACKUP\\*.*",tgt_drive_letter); + + find_first /* Find a file to delete */ + ( + (char *)&delete_path[0], + &dhandle, + tempdta_addr, + (SYSTEM + HIDDEN) + ); + + while (rc == NOERROR) + { + delete_it = TRUE; /*;AN000;7*/ + + if (dirlevel == ROOTDIR) + sprintf(delete_path,"%c:\\%s",tgt_drive_letter,tempdta.file_name); + else + sprintf(delete_path,"%c:\\BACKUP\\%s",tgt_drive_letter,tempdta.file_name); + + if (logfile_on_target) /*;AN000;7*/ + if (strcmp(delete_path,logfile_path) == SAME) /*;AN000;7*/ + delete_it = FALSE; /*;AN000;7*/ + + if (delete_it == TRUE) /*;AN000;7*/ + { /*;AN000;7*/ + delete(delete_path); + + if (rc != NOERROR) + { + set_attribute(delete_path,(WORD)0); + delete(delete_path); + } + } /*;AN000;7*/ + + find_next(dhandle,tempdta_addr); + } + + return; +} /* end delete_files */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: exist +/* +/* FUNCTION: +/* Does a FIND FIRST of the filespec passed at PATH_ADDR. +/* If so, returns TRUE, otherwise returns FALSE. +/* +/***************************************************/ +WORD exist(path_addr) /* Return TRUE if specified epath exists, FALSE other */ +char *path_addr; +{ + WORD dhandle; + WORD temprc; + struct FileFindBuf tempdta; + + find_first /* DOS Find First */ + ( + path_addr, + &dhandle, + &tempdta, + (SUBDIR + SYSTEM + HIDDEN) + ); + + temprc = rc; + if (rc == NOERROR) findclose(dhandle); + + if (temprc != NOERROR) + return(FALSE); + else + return(TRUE); + +} /* end exist */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: open_source_file +/* +/* FUNCTION: +/* Try to open the source file at the DTA structure. +/* If after MAX_RETRY_OPEN_COUNT attempts you cannot +/* open it, then display an appropriate message and +/* continue. If it was opened, then get the files +/* extended attributes. +/* +/***************************************************/ +void open_source_file() +{ + int num_attempts = 0; + char done = FALSE; + char file_to_be_backup[20]; + + source_opened = FALSE; /* Source is not opened yet */ + file_spans_target = FALSE; /* File does not spans diskettes */ + span_seq_num = 1; /* Indicate that this is the first diskette containing part of this file*/ + show_path(); /* Display to stdout/logfile the full path from root */ + sprintf(file_to_be_backup,"%c:%s",src_drive_letter,dta.file_name); + + do + { /*;AN000;5*/ /* Attempt open */ + handle_source = /*;AN000;5*/ + extended_open /*;AN000;5*/ + ( /*;AN000;5*/ + OPEN_IT, /*;AN000;5*/ + 0, /*;AN000;5*/ + (char far *)file_to_be_backup, /*;AN000;5*/ + (WORD)(DENYWRITE+READACCESS) /*;AN000;5*/ + ); /*;AN000;5*/ + + if (rc != NOERROR) /* Check for error */ + { /* Handle Share Errors */ + num_attempts++; /* Increment number of attempts */ + if (num_attempts == MAX_RETRY_OPEN_COUNT)/* Compare with max number of retries to perform */ + { + file_sharing_error(); /*;AN000;9 There was a share error opening the file*/ + done = TRUE; + } + } + else + { + source_opened = TRUE; /* Set flag indicating file is opened */ + done = TRUE; /* We are done in this loop */ + +/*EAEAEAEAEA get_extended_attributes(handle_source); /*;AN000;3 Get extended attributes for this file */ + + put_new_fh(); /* Write the file header to the control file */ + +/*EAEAEAEAE if (ext_attrib_flg) /*;AN000;3 If the file has extended attributes */ +/*EAEAEAEAE write_extended_attributes(); /*;AN000;3then write them to BACKUP file */ + } + } + while (!done); + + return; +} /* end open_source_file */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: file_sharing_error +/* +/* FUNCTION: +/* +/* Handle the file sharing error that just occurred +/* +/***************************************************/ +void file_sharing_error() /*;AN000;9*/ +{ /*;AN000;9*/ + union REGS reg; /*;AN000;9*/ + + display_msg(CRLF); + display_msg(CONFLICTMSG); /* Say "Last file not backed */ + return_code = RETCODE_SHARE_ERROR; /* Set errorlevel */ + + if (do_logfile) /*;AN000;9*/ + { /*;AN000;9*/ + reg.x.ax = LASTNOTBACKUP; /*;AN000;9*/ + reg.x.bx = handle_logfile; /*;AN000;9*/ +#define MSG_LEN 33 /*;AN000;9*/ + reg.x.cx = (WORD)MSG_LEN; /*;AN000;9*/ + update_logfile(®,®); /* In source file _msgret.sal /*;AN000;9*/ + } /*;AN000;9*/ + + return; /*;AN000;9*/ +} /*;AN000;9*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: far_ptr +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +char far *far_ptr(seg,off) +WORD seg; +WORD off; +{ + char far *p; + + PUT_SEG(p,seg); + PUT_OFF(p,off); + + return(p); +} + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: do_copy +/* +/* FUNCTION: +/* Copy the source file to the BACKUP.xxx file +/* If there are extended attributes, write them +/* to the BACKUP.xxx file. +/***************************************************/ +void do_copy() +{ + WORD bytes_read; + WORD bytes_to_read = data_file_alloc_size; /* Read size = buffer size */ + char done = FALSE; + char file_to_be_backup[20]; + + part_size = (DWORD)0; + cumul_part_size = (DWORD)0; + + if (source_opened) + { + do + { + bytes_read = + handle_read + ( + handle_source, + bytes_to_read, + far_ptr(selector,0) + ); + + if (bytes_read == 0) + done = TRUE; + else + write_to_target(bytes_read); + + if (bytes_read < bytes_to_read) + done = TRUE; + } + while (!done); + + close_file(handle_source); /* Close the source file handle */ + source_opened = FALSE; /* Indicate that the source is not opened */ + sprintf(file_to_be_backup,"%c:%s",src_drive_letter,dta.file_name); + reset_archive_bit(file_to_be_backup);/* Reset the archive bit on the source file */ + files_backed_up++; /* Increment number of files backed up */ + } + + return; +} /* end do_copy */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: write_extended_attributes +/* +/* FUNCTION: +/* There are extended attributes for the file +/* just backed up. Write the length of the +/* extended attributes to the BACKUP.xxx file, +/* then write the extended attributes the that file. +/* +/**************************************************/ +/*#define WRITE_LENGTH 2 +/* +/*void write_extended_attributes() /*;AN000;3*/ +/*{ /*;AN000;3*/ +/* WORD written; /*;AN000;3*/ +/* /*******************************************/ +/* /* Write the length of extended attributes */ +/* /*******************************************/ +/* written = +/* handle_write +/* ( +/* handle_target, +/* WRITE_LENGTH, +/* (char far *)&ext_attrib_len +/* ); /*;AN000;3*/ +/* +/* if (written == WRITE_LENGTH ) /*;AN000;3*/ +/* data_file_tot_len += WRITE_LENGTH; /*;AN000;3*/ +/* +/* /*********************************/ +/* /* Write the extended attributes */ +/* /*********************************/ +/* written = handle_write(handle_target,ext_attrib_len,(char far *)ext_attrib_buff); /*;AN000;3*/ +/* if (written == ext_attrib_len) /*;AN000;3*/ +/* data_file_tot_len += (DWORD)written; /*;AN000;3*/ +/* +/* ext_attrib_buff[0] = 0; /*;AN000;3*/ +/* ext_attrib_buff[1] = 0; /*;AN000;3*/ +/* return; /*;AN000;3*/ +/*} /*;AN000;3*/ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: show_path +/* +/* FUNCTION: +/* Display to stdout the full path from root. +/* If we are logging, put full path there too. +/* +/***************************************************/ +void show_path() +{ + char done_path[PATHLEN+20]; + char logfile_entry[PATHLEN+22]; + WORD written = 0; + + if (src_drive_path[strlen(src_drive_path) - 1] != BACKSLASH) + sprintf(done_path,"%s\\%s",src_drive_path,dta.file_name); + else + sprintf(done_path,"%s%s",src_drive_path,dta.file_name); + + done_path[0] = 0xd; + done_path[1] = 0xa; + /* Display logfile path on screen */ + handle_write(STDOUT,strlen(done_path),(char far *)&done_path[0]); + + if (do_logfile) + { + build_ext(diskettes_complete+1); + sprintf(logfile_entry,"\15\12%s %s",ext,&done_path[2]); + written = handle_write(handle_logfile,strlen(logfile_entry),(char far *)&logfile_entry[0]); + if (written != strlen(logfile_entry) || (rc != NOERROR) ) + { + display_msg(LOGFILE_TARGET_FULL); + /*wait_for_keystroke();*/ + do_logfile = FALSE; + } + } + + return; +} /* end show_path */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: reset_archive_bit +/* +/* FUNCTION: +/* Sets the attribute of the source file to what +/* it was before, except the archive bit is reset. +/* +/***************************************************/ +void reset_archive_bit(path_addr) +char *path_addr; +#define ARCHIVE_MASK 223 +{ + WORD attrib; + + attrib = get_attribute(path_addr); + attrib = attrib & (WORD)ARCHIVE_MASK; + set_attribute(path_addr,attrib); + + return; +} /* end reset_archive_bit */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: write_to_target +/* +/* FUNCTION: +/* Write a specified # of bytes to +/* target. Handle disk full conditions +/* and everything else. +/***************************************************/ +void write_to_target(bytes_to_write) +WORD bytes_to_write; +{ + WORD bytes_written; + WORD written; + + bytes_written = handle_write(handle_target,bytes_to_write,far_ptr(selector,0)); + written = bytes_written; + + if (bytes_written == bytes_to_write) /* If we wrote it all... */ + { + part_size += (DWORD)written; /* Update size of this part. */ + cumul_part_size += (DWORD)written; /* Update size of this part. */ + data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ + } + else + { + written = write_till_target_full(bytes_to_write,0); /* Fill up current target */ + bytes_written += written; /* Update # bytes written */ + part_size += (DWORD)written; /* Update size of this part. */ + cumul_part_size += (DWORD)written; /* Update size of this part. */ + data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ + close_out_current_target(); /* Update CONTROL.xxx file, close files */ + get_next_target(); /* Get next diskette from user * + /* Write rest of buffer */ + written = handle_write(handle_target,bytes_to_write-bytes_written,far_ptr(selector,bytes_written)); + bytes_written += written; /* Update # bytes written */ + part_size = (DWORD)written; /* Update size of this part. */ + cumul_part_size += (DWORD)written; /* Update size of this part. */ + data_file_tot_len += (DWORD)written; /* Update length of BACKUP.xxx file */ + } + + return; +} /* end write_to_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: write_till_target_full +/* +/* FUNCTION: +/* Find out how much space is left on the disk, +/* and use it all up. +/* +/***************************************************/ +WORD write_till_target_full(bytes_to_write,begin_offset) +WORD bytes_to_write; +WORD begin_offset; +{ + WORD written; + WORD bfree; + + bfree = (unsigned) disk_free_space(); + written = handle_write(handle_target,bfree,far_ptr(selector,begin_offset)); + + return(written); +} /* end write_till_target_full */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: close_out_current_target +/* +/* FUNCTION: +/* Update CONTROL.xxx file, close it, close BACKUP.xxx, +/* make files READONLY, die if backing up to hardfile. +/* +/***************************************************/ +void close_out_current_target() +{ + BYTE last = LAST_TARGET; /*;AN011;*/ + + disk_full = TRUE; /* Yes, the disk is full */ + + if (part_size != 0) /* If we wrote something...*/ + { + file_spans_target = TRUE; /* Say "Hey, this file spans diskettes !" */ + files_backed_up++; /* Increment number files backed up on this target */ + } + + if (files_backed_up > 0) /* If we backed up something */ + update_db_entries(files_backed_up); /* Increment Num_Entries field in directory block and NextDB field */ + + update_fh_entries(); /* Update the fields in file header */ + + if (!target_removable) /*;AN011;*/ + { /*;AN011;*/ + /* Update DH_LastDisk == LAST_DISK */ + lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); /*;AN011;*/ + handle_write(handle_control,1,(char far *)&last); /*;AN011;*/ + } /*;AN011;*/ + + if (control_opened) /* If the control file is open */ + { + close_file(handle_control); /* Close it */ + control_opened = FALSE; /* And say it isn't open */ + } + + if (target_opened) + close_file(handle_target); /* Close files */ + + target_opened = FALSE; /* Indicate that target is not opened */ + + if (file_spans_target) /* If file spans to another diskette */ + span_seq_num++; /* then increment the sequence number */ + + mark_files_read_only(); /* Set ReadOnly Attribute of BACKUP/CONTROL files */ + + if (logfile_on_target) /*;AN000;7 If logfile resides on target drive */ + { /*;AN000;7 */ + close_file(handle_logfile); /*;AN000;7 Then close it */ + logfile_opened = FALSE; /*;AN000;7 and set flag indicating that */ + } /*;AN000;7 */ + + if (!target_removable) /* If target is a hardfile */ + { + display_msg(LASTNOTBACKUP); /* Say "Last file not backed up */ + error_exit(FDISKFULLMSG); /* then give error message and quit */ + } + + diskettes_complete++; /* Increment number of diskettes complete */ + return; +} /* end close_out_current_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: mark_as_not_last_target +/* +/* FUNCTION: +/* Sets the field in the disk header indicating +/* this is not the last target +/* +/***************************************************/ +void mark_as_not_last_target() +{ + BYTE last = NOT_LAST_TARGET; + DWORD db_offset; + DWORD pointer; + + /* Update DH_LastDisk = NOT_LAST_TARGET */ + lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); + handle_write(handle_control,1,(char far *)&last); + + /* Get first DB_NextDB */ + pointer = lseek(handle_control,BOFILE,(DWORD)(DHLENGTH+66)); + handle_read(handle_control,4,(char far *)&db_offset); + + /* Get offset of last Dir Block */ + while (db_offset != (DWORD)LAST_DB) + { + pointer = lseek(handle_control,BOFILE,(DWORD)db_offset+66); + handle_read(handle_control,4,(char far *)&db_offset); + } + + /* Change DB_NextDB field to point to EOF */ + lseek(handle_control,BOFILE,(DWORD)pointer); + handle_write(handle_control,4,(char far *)&ctl_file_tot_len); + + lseek(handle_control,EOFILE,(DWORD)0); + return; +} /* end mark_as_not_last_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: mark_as_last_target +/* +/* FUNCTION: +/* Sets the field in the disk header indicating +/* this is the last target. Also updates the +/* directory block to indicate the number of +/* files that are backed up. +/* +/***************************************************/ +void mark_as_last_target() +{ + BYTE last = LAST_TARGET; + + /* Update DH_LastDisk == LAST_DISK */ + lseek(handle_control,BOFILE,(DWORD)(DHLENGTH - 1)); + handle_write(handle_control,1,(char far *)&last); + + /* Update DB_NumEntries == FILES_BACKED_UP */ + lseek(handle_control,BOFILE,(DWORD)(curr_db_begin_offset + 64)); + handle_write(handle_control,2,(char far *)&files_backed_up); + + /* Update FH Entries */ + update_fh_entries(); + + return; +} /* end mark_as_last_target */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: update_db_entries +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void update_db_entries(entries) +WORD entries; +{ + lseek(handle_control,BOFILE,(DWORD)(curr_db_begin_offset+64)); + + /* Update DB_num_entries */ + handle_write(handle_control,2,(char far *)&entries); + + if (!disk_full) /* Update DB_NextDB only if we are not at the end of a disk */ + handle_write(handle_control,4,(char far *)&ctl_file_tot_len); + + lseek(handle_control,EOFILE,(DWORD)0); + + return; +} /* end update_db_entries */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: update_fh_entries +/* +/* FUNCTION: +/* Update following fields in Current File Header: +/* +/* FH_Flags: Indicate file successfully processed. +/* Indicate if this is last part or not. +/* +/* FH_PartSize: Indicate number of bytes written +/* +/***************************************************/ +void update_fh_entries() +{ + BYTE flag; + + if (!file_spans_target) + flag = (BYTE)(LASTPART + SUCCESSFUL); + else + flag = (BYTE)(NOTLASTPART + SUCCESSFUL); + +/*EAEA if (ext_attrib_flg) /*;AN000;3 If there are extended attributes */ +/*EAEA if (span_seq_num == 1) /*;AN000;3 If its the first part of file */ +/*EAEA flag += EXT_ATTR; /*;AN000;3 set flag indicating extended attributes exist */ + + if (!target_removable) /*;AN011;*/ + if (disk_full) /*;AN011;*/ + { /*;AN011;*/ + flag = (BYTE)(LASTPART + NOTSUCCESSFUL); /*;AN011;*/ + } /*;AN011;*/ + + /* Go to FLAG field */ + lseek(handle_control,BOFILE,(DWORD)(curr_fh_begin_offset+13)); + /* Write the FLAG field to control file */ + handle_write(handle_control,1,(BYTE far *)&flag); + + /* Go to PARTSIZE field */ + lseek(handle_control,CURRPOS,(DWORD)10); + /* Write the PARTSIZE field to control file */ + handle_write(handle_control,4,(char far *)&part_size); + + lseek(handle_control,EOFILE,(DWORD)0); /* Go back to end-of-file */ + + return; +} /* end update_fh_entries */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: mark_files_read_only +/* +/* FUNCTION: +/* Set the READ-ONLY attribute on BACKUP.xxx and CONTROL.xx +/* +/* +/***************************************************/ +void mark_files_read_only() +{ + char path[25]; + + build_ext(diskettes_complete + 1); + + if (target_removable) + { + sprintf(path,"%c:\\CONTROL.%s",tgt_drive_letter,ext); + set_attribute(path,(WORD)(ARCHIVE + READONLY)); + sprintf(path,"%c:\\BACKUP.%s",tgt_drive_letter,ext); + set_attribute(path,(WORD)(ARCHIVE + READONLY)); + } + else + { + sprintf(path,"%c:\\BACKUP\\CONTROL.%s",tgt_drive_letter,ext); + set_attribute(path,(WORD)(ARCHIVE + READONLY)); + sprintf(path,"%c:\\BACKUP\\BACKUP.%s",tgt_drive_letter,ext); + set_attribute(path,(WORD)(ARCHIVE + READONLY)); + } + + if (target_removable) + label_target_drive(); + + return; +} + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: put_disk_header +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void put_disk_header() +{ + struct Disk_Header dh; + int i; + + dh.DH_Length = DHLENGTH; /* DH_Length */ + + strcpy(dh.DH_Identifier,"BACKUP "); /* DH_Identifier */ + dh.DH_Sequence = diskettes_complete + 1; /* DH_Sequence */ + for (i=0; i<=128; i++) dh.DH_reserved[i] = NUL; /* DH_Reserved */ + dh.DH_LastDisk = NOT_LAST_TARGET; /* DH_LastDisk - Assume NOT THE LAST TARGET */ + + write_to_control_file((char far *)&dh,DHLENGTH); + put_new_db(); + + return; +} /* end put_disk_header */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: put_new_db +/* +/* FUNCTION: +/* +/* +/* +/***************************************************/ +void put_new_db() +{ + struct Dir_Block db; + int i; + + if (files_backed_up > 0) + update_db_entries(files_backed_up); /* Update entries in previous db */ + + curr_db_begin_offset = ctl_file_tot_len; /* Save this for updating when done with current dir */ + + db.DB_Length = DBLENGTH; /* LENGTH, IN BYTES, OF DIR BLOCK */ + for (i=0; i<=63; i++) + db.DB_Path[i]=NUL; /* ASCII PATH OF THIS DIRECTORY, DRIVE OMITTED*/ + + strcpy(db.DB_Path,&src_drive_path[3]); + db.DB_NumEntries = 0; /* NUM OF FILENAMES CURRENTLY IN LIST */ + db.DB_NextDB = (DWORD)LAST_DB; /* OFFSET OF NEXT DIRECTORY BLOCK */ + + write_to_control_file((char far *)&db,DBLENGTH); + new_directory = FALSE; + files_backed_up = 0; + + return; +} /* end put_new_db */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: put_new_fh +/* +/* FUNCTION: +/* We are about to backup a file. Write the +/* file header to the control file. +/* +/***************************************************/ +void put_new_fh() +{ + struct File_Header fh; + int i; /*;AN000;3*/ + + if (do_add) /* If we are adding files */ + if (doing_first_target) /* and it is the last diskette from previous backup */ + if (files_backed_up == 0) /* and we have not backed up ANY yet */ + mark_as_not_last_target(); /* then mark this diskette as NOT the last */ + + if (new_directory) /* If this file resides in a different directory */ + put_new_db(); /* then create new directory block. */ + + curr_fh_begin_offset = ctl_file_tot_len; + + fh.FH_Length = FHLENGTH; /* LENGTH, IN BYTES, OF FILE HEADER */ + for (i=0; i<=11; i++) fh.FH_FName[i]=NUL; /*;AN000;3*/ + strcpy(fh.FH_FName,dta.file_name); /* ASCII FILE NAME */ + + fh.FH_FLength = (DWORD)dta.file_size; /* Length of file */ + fh.FH_FSequence = span_seq_num; /* Sequence #, for files that span */ + fh.FH_BeginOffset=data_file_tot_len; /* OFFSET WHERE THIS SEGMENT BEGINS */ + fh.FH_Attribute = dta.attributes; /* FILE ATTRIBUTE FROM DIRECTORY */ + fh.FH_FTime = dta.write_time; /* TIME WHEN FILE WAS LAST MODIFIED */ + fh.FH_FDate = dta.write_date; /* DATE WHEN FILE WAS LAST MODIFIED */ +/*EAEA fh.FH_EA_offset = 0; /*;AN000;3 Otherwise set to zero */ + fh.FH_Flags = LASTPART + SUCCESSFUL; + +/*EAEA if (ext_attrib_flg) /*;AN000;3 If there are extended attributes */ +/*EAEA if (!file_spans_target) /*;AN000;3*/ +/*EAEA if (span_seq_num == 1) /*;AN000;3 If its the first part of file */ +/*EAEA { /*;AN000;3*/ +/*EAEA fh.FH_Flags += EXT_ATTR; /*;AN000;3 set flag indicating extended attributes exist */ +/*EAEA fh.FH_EA_offset = data_file_tot_len; /*;AN000;3 OFFSET WHERE EXTENDED ATTRIBUTES BEGIN */ +/*EAEA fh.FH_BeginOffset += ext_attrib_len+2; /*;AN000;3*/ +/*EAEA } /*;AN000;3*/ + + if (file_spans_target) + { + fh.FH_PartSize = (DWORD)(dta.file_size - cumul_part_size); /*LENGTH OF THIS PART OF FILE */ + file_spans_target = FALSE; + } + else + fh.FH_PartSize = (DWORD)dta.file_size;/* LENGTH OF THIS PART OF FILE */ + + write_to_control_file((char far *)&fh,FHLENGTH); + + return; +} /* end put_new_fh */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: write_to_control_file +/* +/* FUNCTION: +/* Write to the control file and update +/* counters +/* +/***************************************************/ +void write_to_control_file(address,len) +char far * address; +unsigned short len; +{ + WORD written; + + written = handle_write(handle_control,len,address); + ctl_file_tot_len = ctl_file_tot_len + (DWORD)written; + + return; +} /* end write_to_control_file */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: control_break_handler +/* +/* FUNCTION: +/* Set errorlevel and call routines to +/* close files and terminate. +/* +/***************************************************/ +void control_break_handler() +{ + return_code = RETCODE_CTL_BREAK; + clean_up_and_exit(); + return; +} + + +/************************************************************/ +/* +/* SUBROUTINE NAME: display_it +/* +/* SUBROUTINE FUNCTION: +/* Display the requested message to the standard output device. +/* +/* INPUT: +/* 1) (WORD) Number of the message to be displayed. +/* 2) (WORD) Handle to be written to. +/* 3) (WORD) Substitution Count +/* 4) (WORD) Flag indicating user should "Strike any key..." +/* 5) (WORD) Num indicating message class +/* +/* OUTPUT: +/* The message corresponding to the requested msg number will +/* be written to the requested handle. If requested, substitution +/* text will be inserted as required. The Substitution List +/* is global and, if used, will be initialized by DISPLAY_MSG +/* before calling this routine. +/* +/* NORMAL EXIT: +/* Message will be successfully written to requested handle. +/* +/* ERROR EXIT: +/* None. Note that theoretically an error can be returned from +/* SYSDISPMSG, but there is nothing that the application can do. +/* +/* INTERNAL REFERENCES: +/* System Display Message service routine SYSDISPMSG +/* +/* EXTERNAL REFERENCES: +/* None +/* +/************************************************************/ +void display_it(msg_number,handle,subst_count,waitflag,class)/*;AN000;6*/ + +int msg_number; /*;AN000;6*/ +WORD handle; /*;AN000;6*/ +int subst_count; /*;AN000;6*/ +BYTE waitflag; /*;AN000;6*/ +BYTE class; /*;AN000;6 1=DOSerror, 2=PARSE,-1=Utility msg*/ +{ /*;AN000;6*/ + inregs.x.ax = msg_number; /*;AN000;6*/ + inregs.x.bx = handle; /*;AN000;6*/ + inregs.x.cx = subst_count; /*;AN000;6*/ + inregs.h.dh = class; /*;AN000;6*/ + inregs.h.dl = (BYTE)waitflag; /*;AN000;6*/ + inregs.x.si = (WORD)(char far *)&sublist; /*;AN000;6*/ + + sysdispmsg(&inregs,&outregs); /*;AN000;6*/ + + return; /*;AN000;6*/ +} /*;AN000;6*/ +/** ***********************************************/ +/* +/* SUBROUTINE NAME: display_msg +/* +/* FUNCTION: +/* Display the messages referenced by +/* variable MSG_NUM to either STDOUT or +/* STDERR. In some cases insert text into +/* the body of the message. +/* +/***************************************************/ + +void display_msg(msg_num) +int msg_num; +{ + + switch (msg_num) + { + case NONEFNDMSG : { display_it (msg_num,STDOUT,0,NOWAIT,(BYTE)UTIL_MSG); break; } /*;AN000;6*/ + + case INSUFF_MEMORY : /*;AN000;6*/ + case ERR_EXEC_FORMAT : /*;AN000;d178*/ + case INV_PATH : /*;AN000;6*/ + case INV_DATE : /*;AN000;6*/ + case INV_TIME : /*;AN000;6*/ + case NO_SOURCE : /*;AN000;6*/ + case NO_TARGET : /*;AN000;6*/ + case SRC_AND_TGT_SAME : /*;AN000;6*/ + case BAD_DOS_VER : /*;AN000;6*/ + case INV_DRIVE : /*;AN000;6*/ + case CANT_OPEN_LOGFILE: /*;AN000;6*/ + case INVTARGET : /*;AN000;6*/ + case NOTLASTMSG : /*;AN000;6*/ + case CONFLICTMSG : /*;AN000;6*/ + case CRLF : + case CANT_FIND_FORMAT : + case LASTNOTBACKUP :{ /*;AN000;6*/ + display_it (msg_num,STDERR,0,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; /*;AN000;6*/ + } /*;AN000;6*/ + + case LOGFILE_TARGET_FULL:{ + display_it (msg_num,STDERR,0,NOWAIT,(BYTE)UTIL_MSG);/*;AN000;6*/ + display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + case LOGGING : { + sublist.value1 = (char far *)&logfile_path[0]; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.max_width1 = (BYTE)strlen(logfile_path); /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + display_it (msg_num,STDOUT,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + case CANT_FORMAT_HARDFILE : + { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.max_width1 = 1; /*;AN000;6*/ + sublist.min_width1 = 1; /*;AN000;6*/ + display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + case BUDISKMSG : /*;AN000;6*/ + case FDISKFULLMSG : /*;AN000;6*/ + { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.max_width1 = 1; /*;AN000;6*/ + sublist.min_width1 = 1; /*;AN000;6*/ + display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + + case ERASEMSG : /*;AN000;6*/ + case FERASEMSG : /*;AN000;6*/ + case LASTDISKMSG : /*;AN000;6*/ + { sublist.value1 = (char far *)&tgt_drive_letter; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.max_width1 = 1; /*;AN000;6*/ + sublist.min_width1 = 1; /*;AN000;6*/ + display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + + case INSERTSOURCE : { + sublist.value1 = (char far *)&src_drive_letter; /*;AN000;6*/ + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.max_width1 = 1; /*;AN000;6*/ + sublist.min_width1 = 1; /*;AN000;6*/ + display_it (msg_num,STDERR,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + display_it (PRESS_ANY_KEY,STDERR,0,WAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + + case SEQUENCEMSG : { + build_ext(diskettes_complete+1); + if (diskettes_complete+1 < 100) + { + sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/ + sublist.max_width1 = 2; /*;AN000;6*/ + } + else + { + sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/ + sublist.max_width1 = 3; /*;AN000;6*/ + } + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + display_it (msg_num,STDOUT,1,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + + case INSERTTARGET : { + build_ext(diskettes_complete+1); + if (diskettes_complete+1 < 100) + { + sublist.value1 = (char far *)&ext[1]; /*;AN000;6*/ + sublist.max_width1 = 2; /*;AN000;6*/ + } + else + { + sublist.value1 = (char far *)&ext[0]; /*;AN000;6*/ + sublist.max_width1 = 3; /*;AN000;6*/ + } + + sublist.flags1 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char1 = ' '; /*;AN000;6*/ + sublist.min_width1 = sublist.max_width1; /*;AN000;6*/ + + sublist.value2 = (char far *)&tgt_drive_letter; /*;AN000;6*/ + sublist.flags2 = LEFT_ALIGN + CHAR_FIELD_ASCIIZ; /*;AN000;6*/ + sublist.pad_char2 = ' '; /*;AN000;6*/ + sublist.max_width2 = 1; /*;AN000;6*/ + sublist.min_width2 = 1; /*;AN000;6*/ + + display_it (msg_num,STDERR,2,NOWAIT,(BYTE)UTIL_MSG); /*;AN000;6*/ + break; + } + + } + + return; +} /* end display_msg */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: error_exit +/* +/* FUNCTION: +/* Display appropriate error message, set +/* the return code, and call clean_up_and_exit. +/* +/***************************************************/ +void error_exit(error_type) +int error_type; +{ + display_msg(error_type); + return_code = RETCODE_ERROR; + clean_up_and_exit(); + + return; +} /* end error_exit */ + +/** ***********************************************/ +/* +/* SUBROUTINE NAME: restore_default_directories +/* +/* FUNCTION: +/* Restore the original current directory on +/* the source drive. +/* +/***************************************************/ +void restore_default_directories() +{ + char path[PATHLEN+20]; + + sprintf(path,"%c:%s",src_drive_letter,src_def_dir); + chdir(path); + + return; +} /* end restore_default_directories */ + +/**************************************************/ +/* +/* SUBROUTINE NAME: clean_up_and_exit +/* +/* FUNCTION: +/* Update BACKUP and CONTROL files. +/* Close open files. +/* Mark BACKUP, CONTROL file read only +/* Restore default drive and directories +/* Deallocate buffers +/***************************************************/ +void clean_up_and_exit() +{ + char name[15]; /*;AN000;p2652*/ + + if (source_opened) + { + close_file(handle_source); + source_opened = FALSE; /* Indicate that source is not opened */ + } + + if (target_opened) + { + close_file(handle_target); + target_opened = FALSE; /* Indicate that target is not opened */ + } + + if (control_opened) + { + mark_as_last_target(); + close_file(handle_control); + control_opened = FALSE; /*;AN005;*/ + mark_files_read_only(); + } + + if (logfile_opened) + { + close_file(handle_logfile); + logfile_opened = FALSE; + } + + if (files_backed_up == 0 && !checking_target) /*;AN000;p2652*//*;AN007;*/ + { /*;AN005;*/ + if (!do_add) /*;AN000;p2652*/ + { /*;AN000;p2652*/ + if (target_removable && got_first_target) /*;AN000;p2652*/ + { /*;AN005;*/ + build_ext(diskettes_complete + 1); /*;AN005;*/ + sprintf(name,"%c:\\BACKUP.%s",tgt_drive_letter,ext); /*;AN005;*/ + set_attribute(name,(WORD)0); /*;AN005;*/ + delete(name); /*;AN005;*/ + /*;AN005;*/ + sprintf(name,"%c:\\CONTROL.%s",tgt_drive_letter,ext); /*;AN005;*/ + set_attribute(name,(WORD)0); /*;AN005;*/ + delete(name); /*;AN005;*/ + } /*;AN005;*/ + + if (!target_removable) + delete_files(BACKUPDIR); /*;AN000;p2652*/ + + } /*;AN000;p2652*/ + + if (!target_removable) /*;AN005;*/ + { /*;AN005;*/ + sprintf(name,"%c:\\BACKUP",tgt_drive_letter); /*;AN000;p2652*/ + rmdir(name); /*;AN000;p2652*/ + } /*;AN005;*/ + } /*;AN005;*/ + + if (def_drive_set) + { + set_default_drive(def_drive); + } + + if (curr_dir_set) + { + restore_default_directories(); + } + + if (buffers_allocated) + free_seg(selector); + + terminate(); + + return; +} /* end clean_up_and_exit */ + + + +/** ***********************************************/ +/* DOS FAMILY API CALLS */ +/**************************************************/ + +WORD handle_open(path_addr,mode) +char *path_addr; +WORD mode; +{ + WORD handle; + WORD action; + +#if defined(DEBUG) + printf("\nDOSOPEN FILE=%s, MODE=%04Xh...",path_addr,mode); +#endif + + rc = + DOSOPEN + ( + (char far *)path_addr, /* Path address */ + (unsigned far *)&handle, /* Return area for handle */ + (unsigned far *)&action, /* Return area for action performed */ + (DWORD)0, /* File Size */ + (WORD)0, /* File attribute */ + (WORD)1, /* Flag: Only open file if it exists */ + (WORD)mode, /* Mode */ + (DWORD)0 /* Reserved */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, HANDLE=%04Xh",handle); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(handle); +} /* end handle_open */ + + +/** ***********************************************/ +DWORD lseek(handle,method,distance) +WORD handle; +BYTE method; /* 0=BOF+Offset, 1=CurrPos+Offset, 2=EOF+Offset */ +DWORD distance; +{ + DWORD pointer; + +#if defined(DEBUG) + printf("\nDOSCHGFILEPTR HANDLE=%04Xh, METHOD=%02Xh, DIST=%08lXh...",handle,method,distance); +#endif + + rc = + DOSCHGFILEPTR + ( + handle, + distance, + method, + (DWORD far *)&pointer + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, POINTER=%08lXh",pointer); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return((DWORD)pointer); +} /* end lseek */ + +/** ***********************************************/ +WORD handle_read(handle,length,address) +WORD handle; +WORD length; +char far *address; +{ + WORD num_read; + +#if defined(DEBUG) + printf("\nDOSREAD HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address); +#endif + + rc = + DOSREAD + ( + handle, + address, + length, + (unsigned far *)&num_read + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("READ %04Xh",num_read); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(num_read); +} /* end handle_read */ +/** ***********************************************/ +WORD handle_write(handle,length,address) +WORD handle; +WORD length; +char far *address; +{ + WORD written; + +#if defined(DEBUG) + printf("\nDOSWRITE HANDLE=%04Xh, BYTES=%04Xh, ADDR(off:seg)=%04X:%04X...",handle,length,address); +#endif + + if (length != 0) + rc = + DOSWRITE + ( + handle, + address, + length, + (unsigned far *)&written + ); + else + { + written = 0; + rc = NOERROR; + } + +#if defined(DEBUG) + if (rc == NOERROR) + printf("WROTE %04Xh",written); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(written); +} /* end handle_write */ + +/** ***********************************************/ +void close_file(handle) /* Close the file handle specified. */ +WORD handle; +{ +#if defined(DEBUG) + printf("\nDOSCLOSE HANDLE=%04Xh...",handle); +#endif + + rc = DOSCLOSE(handle); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end close_file */ + +/** ***********************************************/ +WORD get_attribute(path_addr) +char *path_addr; +{ + WORD attribute; + +#if defined(DEBUG) + printf("\nDOSQFILEMODE %s...",path_addr); +#endif + + rc = DOSQFILEMODE((char far *)path_addr,(unsigned far *)&attribute,(DWORD)0); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, ATTRIB=%04Xh",attribute); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(attribute); +} + +/** ***********************************************/ +void set_attribute(path_addr,attribute) +char *path_addr; +WORD attribute; +{ +#if defined(DEBUG) + printf("\nDOSSETFILEMODE FILE=%s, ATTRIB=%04Xh...",path_addr,attribute); +#endif + + rc = DOSSETFILEMODE((char far *)path_addr,attribute,(DWORD)0); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} +/** ***********************************************/ +WORD get_current_drive() +{ + WORD drive; /* 1=a */ + DWORD drivemap; + +#if defined(DEBUG) + printf("\nDOSQCURDISK DRIVE (1=A)..."); +#endif + + rc = DOSQCURDISK + ( + (unsigned far *)&drive, + (DWORD far *)&drivemap + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, DRIVE=%04Xh",drive); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(drive); +} + +/** ***********************************************/ +void set_default_drive(drive) /* Change the current drive (1=A,2=B) */ +WORD drive; +{ +#if defined(DEBUG) + printf("\nDOSSELECTDISK (1=A) TO %04Xh...",drive); +#endif + + rc = DOSSELECTDISK(drive); + + if (rc == NOERROR) + def_drive_set = TRUE; + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end set_default_drive */ + +/** ***********************************************/ +void get_current_dir(drive,path_addr) +WORD drive; /* 0=default, 1=a, . . . */ +char *path_addr; /* Pointer to path buffer */ +{ + WORD path_buff_len = PATHLEN+20; + +#if defined(DEBUG) + printf("\nDOSQCURDIR DRIVE (0=def) %04Xh...",drive); +#endif + + rc = + DOSQCURDIR + ( + drive, + (char far *)path_addr, + (unsigned far *)&path_buff_len + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, CURRENT DIR IS = \\%s",path_addr); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end get_current_dir */ + +/** ***********************************************/ +void find_first(path_addr,dirhandle_addr,dta_address,attrib) +char *path_addr; +WORD *dirhandle_addr; +struct FileFindBuf *dta_address; +WORD attrib; +{ + WORD numentries = 1; + WORD temprc; + + *dirhandle_addr = 0xffff; + + +#if defined(DEBUG) + printf("\nDOSFINDFIRST DIRH=%04Xh, FILE=%s...",*dirhandle_addr,path_addr); +#endif + + rc = + DOSFINDFIRST + ( + (char far *)path_addr, + (unsigned far *)dirhandle_addr, + attrib, + (struct FileFindBuf far *)dta_address, + (WORD)(sizeof(struct FileFindBuf)), + (unsigned far *)&numentries, + (DWORD)0 + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, NAME=%s, ATTR=%04Xh, SIZE=%08lXh, DIRH=%04Xh",(*dta_address).file_name,(*dta_address).attributes,(*dta_address).file_size,*dirhandle_addr); + else + printf("ERROR, DIRH=%04Xh, RC=%04Xh",*dirhandle_addr,rc); +#endif + + if (rc != NOERROR) + { + temprc=rc; + findclose(*dirhandle_addr); + rc = temprc; + } + + return; +} /* end find_first */ + +/** ***********************************************/ +void find_next(dirhandle,dta_address) +WORD dirhandle; +struct FileFindBuf *dta_address; +{ + WORD temprc; + WORD numentries = 1; + +#if defined(DEBUG) + printf("\nDOSFINDNEXT, DIRH=%04Xh...",dirhandle); +#endif + + rc = + DOSFINDNEXT + ( + dirhandle, + (struct FileFindBuf far *)dta_address, + (WORD)(sizeof(struct FileFindBuf)+12), + (unsigned far *)&numentries + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, NAME=%s, DIRH=%04Xh",(*dta_address).file_name,dirhandle); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + if (rc != NOERROR) + { + temprc=rc; + findclose(dirhandle); + rc = temprc; + } + + return; +} /* end find_next */ +/** ***********************************************/ +void findclose(dirhandle) +WORD dirhandle; +{ + +#if defined(DEBUG) + printf("\nDOSFINDCLOSE DIRH=%04Xh...",dirhandle); +#endif + + rc = DOSFINDCLOSE(dirhandle); + + dirhandles_open = FALSE; + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end findclose */ +/** ***********************************************/ +void delete(path_addr) +char *path_addr; +{ +#if defined(DEBUG) + printf("\nDOSDELETE FILE %s...",path_addr); +#endif + + rc = DOSDELETE((char far *)path_addr,(DWORD)0); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end delete */ +/** ***********************************************/ +long disk_free_space() +{ + struct FSAllocate fsa; + +#if defined(DEBUG) + printf("\nDOSQFSINFO (0=def) DRIVE=%04Xh...",tgt_drive_letter-'A'+1); +#endif + + rc = + DOSQFSINFO + ( + (WORD)tgt_drive_letter - 'A' + 1, /* Drive 0=def, 1=a... */ + (WORD)1, /* Level */ + (char far *)&fsa, /* Return info */ + (WORD)(sizeof(struct FSAllocate)) /* Size of return info buffer */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, FREESPACE=%08lXh",fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return((DWORD)(fsa.sec_per_unit * fsa.avail_units * fsa.bytes_sec)); +} +/** ***********************************************/ +void replace_volume_label(label_addr) +char *label_addr; +{ +#if defined(DEBUG) + printf("\nDOSSETFSINFO (0=def) DRIVE=%04Xh, LEN=%04Xh...",tgt_drive_letter-'A'+1,label_addr[0]); +#endif + + rc = DOSSETFSINFO + ( + (WORD)tgt_drive_letter-'A'+1, /* Drive 0=def, 1=a... */ + (WORD)2, /* Level */ + (char far *)label_addr, /* Buffer */ + (WORD)LABELLEN+1 /* Buffer size */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end replace_volume_label */ + +/** ***********************************************/ +#define TERMINATE 0x4C00 +void terminate() /* Terminate process, return errorlevel to DOS */ +{ + + if (append_indicator == DOS_APPEND) /*;AN000;2 If append /x was reset*/ + { /*;AN000;2*/ +#if defined(DEBUG) +printf("\nINT2Fh,(SET APPEND) AX=%04Xh TO %04Xh...",SET_STATE,original_append_func); +#endif + inregs.x.ax = SET_STATE; /*;AN000;2*/ + inregs.x.bx = original_append_func; /*;AN000;2*/ + int86(0x2f,&inregs,&outregs); /*;AN000;2*/ + } /*;AN000;2*/ + + exit(return_code); /*;AN000;p972*/ + + return; +} /* end terminate */ +/** ***********************************************/ +WORD ioctl(devhandle) +WORD devhandle; +{ +#define ISDEVREMOVABL 0x20 +#define CATEGORY 8 /*1=serial,3=display,5=printer,8=disk*/ + + BYTE data_area; + +#if defined(DEBUG) + printf("\nDOSDEVIOCTL HANDLE=%04Xh...",devhandle); +#endif + + rc = + DOSDEVIOCTL + ( + (char far *)&data_area, /* Data Area */ + (char far *)&data_area, /* Parameter list */ + (WORD)ISDEVREMOVABL, /* Device Function = 20 hex */ + (WORD)CATEGORY, /* Device Category = 8 hex */ + (WORD)devhandle /* Device Handle */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, DATA_AREA(0=REMOVABLE) SET TO %02Xh",data_area); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return(data_area); +} /* end IOCTL */ + +/** ***********************************************/ +void alloc_seg() +{ +#if defined(DEBUG) + printf("\nDOSALLOCSEG SIZE=%04Xh...",data_file_alloc_size); +#endif + + rc = + DOSALLOCSEG + ( + (WORD)data_file_alloc_size, /* Bytes to allocate */ + (unsigned far *)&selector, /* Address of selector */ + (WORD)0 /* Share indicator, sez DON'T SHARE */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL, SELECTOR=%04Xh, SIZE=%04Xh",selector,data_file_alloc_size); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} + +/** ***********************************************/ +void free_seg(selector) +unsigned selector; +{ +#if defined(DEBUG) + printf("\nDOSFREESEG (%04Xh)...",selector); +#endif + + rc = DOSFREESEG(selector); /* Address of selector */ + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} + +/** ***********************************************/ +void setsignal(action,signum) +WORD action; +WORD signum; +{ + DWORD old_sig_handler; + WORD old_sig_action; + +#if defined(DEBUG) + printf("\nDOSSETSIGHANDLER ACTION=%04Xh,SIGNUM=%04Xh...",action,signum); +#endif + + rc = + DOSSETSIGHANDLER + ( + (void far *)control_break_handler, /* Signal handler address */ + (DWORD far *)&old_sig_handler, /* Address of previous handler */ + (unsigned far *)&old_sig_action, /* Address of previous action */ + action, /* Indicate request type (2=hook) */ + signum /* Signal number */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} /* end setsignal */ + +/** ***********************************************/ +void do_dos_error(flag) +WORD flag; +{ +#if defined(DEBUG) + printf("\nDOSERROR, FLAG=%04Xh...",flag); +#endif + + rc = DOSERROR(flag); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + return; +} +/** ***********************************************/ +void get_country_info() +{ +#define USACOUNTRY 1 +#define DEFAULT_COUNTRY 0 +#define DEFAULT_CODEPAGE 0 + + struct ctry_info_blk buff; + struct countrycode ctrystuff; /* Added for CPDOS 1.1 */ + WORD data_len; + + ctrystuff.country = (WORD)DEFAULT_COUNTRY; + ctrystuff.codepage= (WORD)DEFAULT_CODEPAGE; + +#if defined(DEBUG) + printf("\nDOSGETCTRYINFO COUNTRY=%04Xh...",ctrystuff.country); +#endif + + rc = + DOSGETCTRYINFO + ( + (unsigned)sizeof(struct ctry_info_blk), /* Length of return area */ + (struct countrycode far *)&ctrystuff, /* Country Code */ + (char far *)&buff, /* Return area */ + (unsigned far *)&data_len /* Len of returned area */ + ); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + if (rc == NOERROR) + { + ctry_date_fmt = buff.date_format; + ctry_time_fmt = buff.time_format; + ctry_date_sep = buff.date_separator; + ctry_time_sep = buff.time_separator; +#if defined(DEBUG) + printf("\nDATE SEPERATOR=%c",ctry_date_sep); + printf("\nTIME SEPERATOR=%c",ctry_time_sep); + printf("\nDATE FORMAT=%u",ctry_date_fmt); + printf("\nTIME FORMAT=%u",ctry_time_fmt); +#endif + } + + + return; +} /* end get_country_info */ + +/** ***********************************************/ +void datetime() /* Put date and time in logfile */ +{ + struct DateTime buff; + char date[12]; + char time[12]; + char datetimestring[25]; + WORD written = 0; + +#if defined(DEBUG) + printf("\nDOSGETDATETIME..."); +#endif + + rc = DOSGETDATETIME((struct DateTime far *)&buff); + +#if defined(DEBUG) + if (rc == NOERROR) + printf("SUCCESSFUL"); + else + printf("ERROR, RC=%04Xh",rc); +#endif + + /* Build time string */ + sprintf(time,"%u%c%02u%c%02u",buff.hour,ctry_time_sep,buff.minutes,ctry_time_sep,buff.seconds); + + /* Build date string */ + switch (ctry_date_fmt) + { + case USA: + sprintf(date,"%u%c%02u%c%04u",buff.month,ctry_date_sep,buff.day,ctry_date_sep,buff.year); + break; + + case EUR: + sprintf(date,"%u%c%02u%c%04u",buff.day,ctry_date_sep,buff.month,ctry_date_sep,buff.year); + break; + + case JAP: + sprintf(date,"%04u%c%02u%c%02u",buff.year,ctry_date_sep,buff.month,ctry_date_sep,buff.day); + break; + + default: + break; + } + + datetimestring[0] = 0x0d; + datetimestring[1] = 0x0a; + sprintf(datetimestring+2,"%s %s",date,time); + + written = handle_write(handle_logfile,strlen(datetimestring),(char far *)&datetimestring[0]); + if (written != strlen(datetimestring) || (rc != NOERROR) ) + { + display_msg(LOGFILE_TARGET_FULL); + /* wait_for_keystroke(); */ + do_logfile = FALSE; + } + + return; +} /* end datetime */ + + + + + + + + + + + + +/** ***********************************************/ +/*void get_extended_attributes(handle) /*;AN000;3*/ +/*WORD handle; /*;AN000;3*/ +/*{ /*;AN000;3*/ +/*#if defined(DEBUG) +/* printf("\nGET EXTENDED ATTRIBUTE LENGTH..."); +/*#endif +/* ext_attrib_flg = TRUE; /*Assume ext attrib exist*/ /*;AN000;3*/ +/* +/* /* GET EXTENDED ATTRIBUTE LENGTH */ +/* inregs.x.ax = 0x5702; /*;AN000;3*/ +/* inregs.x.bx = handle; /*;AN000;3*/ +/* inregs.x.cx = 0; /*;AN000;3*/ +/* inregs.x.si = 0xffff; /*;AN000;3*/ +/* intdos(&inregs,&outregs); /*;AN000;3*/ +/* +/*#if defined(DEBUG) +/* if (outregs.x.cflag & CARRY) +/* printf("ERROR, RC=%04Xh",outregs.x.ax); +/* else +/* printf("SUCCESSFUL, LEN=%04Xh",outregs.x.cx); +/*#endif +/* +/* if (!(outregs.x.cflag & CARRY)) /*;AN000;3*/ +/* ext_attrib_len = outregs.x.cx; /*;AN000;3*/ +/* else /*;AN000;3*/ +/* ext_attrib_flg = FALSE; /*;AN000;3 Set flag indicating no extended attributes*/ +/* +/* +/*#if defined(DEBUG) +/* printf("\nGET EXTENDED ATTRIBUTES..."); +/*#endif +/* +/* /* GET EXTENDED ATTRIBUTES */ +/* if (ext_attrib_flg) +/* { /*;AN000;3*/ +/* inregs.x.ax = 0x5702; /*;AN000;3*/ +/* inregs.x.bx = handle; /*;AN000;3*/ +/* inregs.x.cx = outregs.x.cx; /*;AN000;3*/ +/* inregs.x.di = (unsigned)&ext_attrib_buff[0]; /*;AN000;3*/ +/* inregs.x.si = 0xffff; /*;AN000;3*/ +/* intdos(&inregs,&outregs); /*;AN000;3*/ +/* +/* if (outregs.x.cflag & CARRY) /*;AN000;3*/ +/* ext_attrib_flg = FALSE; /*;AN000;3*/ +/* +/*#if defined(DEBUG) +/* if (outregs.x.cflag & CARRY) +/* printf("ERROR, RC=%04Xh",outregs.x.ax); +/* else +/* printf("SUCCESSFUL"); +/*#endif +/* } +/* +/* return; /*;AN000;3*/ +/*} /* end get_extended_attributes */ /*;AN000;3*/ +/** ************************************************/ +#define EXTENDEDOPEN 0x6c00 /*;AN000;3*/ + +WORD extended_open(flag,attr,path_addr,mode) /*;AN000;3*/ +WORD flag; /*;AN000;3*/ +WORD attr; /*;AN000;3*/ +char far *path_addr; /*;AN000;3*/ +WORD mode; /*;AN000;3*/ +{ /*;AN000;3*/ + union REGS inreg,outreg; /*;AN000;3*/ + + ea_parmlist.ext_attr_addr = (DWORD)(char far *)&ext_attrib_buff[0];/*;AN000;3*/ + ea_parmlist.num_additional = 0; /*;AN000;3*/ + +#if defined(DEBUG) + if (flag == CREATE_IT) printf("\nEXTENDED OPEN - CREATE, FILE %s...",path_addr); + else printf("\nEXTENDED OPEN - OPEN, FILE %s...",path_addr); +#endif + + rc = NOERROR; /*;AN000;3*/ + inreg.x.ax = EXTENDEDOPEN; /*;AN000;3*/ + inreg.x.bx = mode + NO_INHERIT; /*;AN000;3*/ + inreg.x.cx = attr; /*;AN000;3*/ + inreg.x.dx = flag + NO_CP_CHECK; /*;AN000;3*/ + inreg.x.si = (WORD)path_addr; /*;AN000;3*/ + + inreg.x.di = (WORD)&ea_parmlist; /*;AN000;3*/ + + intdos(&inreg,&outreg); /*;AN000;3*/ + if (outreg.x.cflag & CARRY) /* If there was an error /*;AN000;3*/ + rc = outreg.x.ax; /* then set return code /*;AN000;3*/ + +#if defined(DEBUG) + if (outreg.x.cflag & CARRY) + printf("ERROR, RC=%04Xh",outreg.x.ax); + else + printf("SUCCESSFUL, HANDLE=%04Xh",outreg.x.ax); +#endif + + return(outreg.x.ax); /*;AN000;3*/ +} /* end extended_open */ /*;AN000;3*/ + \ No newline at end of file diff --git a/v4.0/src/CMD/BACKUP/BACKUP.H b/v4.0/src/CMD/BACKUP/BACKUP.H new file mode 100644 index 0000000..61cc981 --- /dev/null +++ b/v4.0/src/CMD/BACKUP/BACKUP.H @@ -0,0 +1,502 @@ +/*0 */ +/*----------------------------------------------------------- +/*- +/*- FILE: BACKUP.H +/*- +/*- PURPOSE: For the BACKUP utility, this file has the required +/*- BACKUP defines, message numbers, structures, +/*- and subroutine declarations. +/*- +/*---------------------------------------------------------*/ + +/*---------------------- +/*- Utility #DEFINES... +/*----------------------*/ + +#define DHLENGTH 139 /* Length, in bytes, of a Disk Header */ +#define DBLENGTH 70 /* Length, in bytes, of a Directory Block */ +#define FHLENGTH 34 /* Length, in bytes, of a File Header */ + +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long + +#define NOERROR 0 +#define NUL 0 + +#define FALSE 0 +#define TRUE !FALSE + +#define BACKSLASH 0x5c + +#define READONLYOFF 254 /* bit mask, will be ANDed with current attribute to turn off readonly bit */ + +#define READONLY 0x01 /* File Attributes */ +#define HIDDEN 0x02 +#define SYSTEM 0x04 +#define VOLLABEL 0x08 +#define SUBDIR 0x10 +#define ARCHIVE 0x20 + +#define DENYALL 0x10 /* Sharing Mode */ +#define DENYWRITE 0x20 +#define DENYREAD 0x30 +#define DENYNONE 0x40 + +#define READACCESS 0x00 /* Access Modes */ +#define WRITEACCESS 0x01 +#define READWRITE 0x02 + + +#define NO_CP_CHECK 0x100 /*;AN000;5*/ + +#define SYNCHRONOUS 0x4000 /* OS/2 File Write-Through */ +#define NOTSYNCHRONOUS 0x0000 /* OS/2 File Write-Through */ +#define OPENDASD 0x8000 /* OS/2 Open a DASD device */ +#define OPEN_IT 0x01 /*;AN000;5*/ +#define CREATE_IT 0x12 /*;AN000;5*/ + +#define NO_INHERIT 0x80 /* Inheritance bit */ + +#define STDIN 0x00 /* Predefined handles */ +#define STDOUT 0x01 +#define STDERR 0x02 + +#define BOFILE 0 /* LSEEK move methods */ +#define CURRPOS 1 +#define EOFILE 2 + +#define GET 0 /* CHMOD functions */ +#define SET 1 + +#define SSTRING 0x2000 /*;AN000;4 Parser Match Flags */ +#define DATESTRING 0x1000 /*;AN000;4*/ +#define TIMESTRING 0x0800 /*;AN000;4*/ +#define FILESPEC 0x0200 /*;AN000;4*/ +#define DRIVELETTER 0x0100 /*;AN000;4*/ +#define OPTIONAL 0x0001 /*;AN000;4*/ + +#define CAP_FILETABLE 0x0001 /*;AN000;4 Parser Function flag*/ +#define CAP_CHARTABLE 0x0002 /*;AN000;4 Parser Function flag*/ + +#define LABELLEN 11 + +#define SETLOGICALDRIVE 0x440F /*;AN000;8 */ + + +/*--------APPEND FUNCTIONS-----------*/ +#define INSTALL_CHECK 0xB700 /*;AN000;2*/ +#define NOT_INSTALLED 0 /*;AN000;2*/ +#define GET_APPEND_VER 0xB702 /*;AN000;2*/ +#define NET_APPEND 1 /*;AN000;2*/ +#define DOS_APPEND 2 /*;AN000;2*/ +#define GET_STATE 0xB706 /*;AN000;2*/ +#define SET_STATE 0xB707 /*;AN000;2*/ + +#define APPEND_X_BIT 0x8000 /*;AN000;2*/ + + + +#define ACTIONHOOK 2 +#define CTRLC 1 +#define CTRLBREAK 4 + +#define EOL -1 /*;AN000;4*/ +#define QUOTED_STRING 9 /*;AN000;4*/ +#define RET_DATE 7 /*;AN000;4*/ +#define RET_TIME 8 /*;AN000;4*/ + +#define CPSW_ACTIVE 1 /*;AN000;3*/ +#define CPSW_NOTACTIVE 0 /*;AN000;3*/ +#define GET_CPSW 0x3303 /*;AN000;3*/ + +#define CARRY 0x0001 /*;AN000;*/ +/***********************************/ +/* Utility-specific definitions */ +/***********************************/ + +#define ROOTDIR 0 +#define BACKUPDIR 1 + +#define PUT_SEG(fp,seg) (*((unsigned *)&(fp)+1)) = (unsigned) seg +#define PUT_OFF(fp,off) (*((unsigned *)&(fp))) = (unsigned) off + +#define MAXMSGLEN 160 +#define PATHLEN 64 +#define MAX_RETRY_OPEN_COUNT 5 + +#define RETCODE_NO_ERROR 0 /* Errorlevels */ +#define RETCODE_NO_FILES 1 +#define RETCODE_SHARE_ERROR 2 +#define RETCODE_CTL_BREAK 3 +#define RETCODE_ERROR 4 + +/************************************************/ +/* NOTE FROM PARSER SUBROUTINE !!!!! */ +/************************************************/ +/* The SECONDS bits in the DOS Directory are in */ +/* 2-second increments. Therefore, div by 2, */ +/* take the integer portion and use in search. */ +/* Note that files can be backed up that were */ +/* modified 1 second before the time that a user*/ +/* enters, which is better than not backing up */ +/* a file that was modified at exactly that time*/ +/************************************************/ + +/*-------------------------------------------*/ +/*------ BACKUP messages --------*/ +/*-------------------------------------------*/ +#define BAD_DOS_VER 1 /*;AN000;6*/ +#define INSUFF_MEMORY 2 /*;AN000;6*/ + +#define INV_DRIVE 6 /*;AN000;6*/ +#define INV_DATE 7 /*;AN000;6*/ +#define INV_TIME 8 /*;AN000;6*/ + +#define INV_PATH 11 /*;AN000;6*/ +#define NO_SOURCE 12 /*;AN000;6*/ +#define NO_TARGET 13 /*;AN000;6*/ +#define SRC_AND_TGT_SAME 14 /*;AN000;6*/ +#define ERR_EXEC_FORMAT 15 /*;AN000;6*/ +#define CANT_FIND_FORMAT 16 /*;AN000;d178*/ +#define CANT_OPEN_LOGFILE 17 /*;AN000;6*/ +#define LOGGING 18 /*;AN000;6*/ +#define NOTLASTMSG 19 /*;AN000;6*/ +#define ERASEMSG 20 /*;AN000;6*/ +#define FERASEMSG 21 /*;AN000;6*/ +#define BUDISKMSG 22 /*;AN000;6*/ +#define SEQUENCEMSG 23 /*;AN000;6*/ +#define NONEFNDMSG 24 /*;AN000;6*/ +#define INSERTSOURCE 25 /*;AN000;6*/ +#define INSERTTARGET 26 /*;AN000;6*/ +#define CONFLICTMSG 27 /*;AN000;6*/ +#define LASTDISKMSG 28 /*;AN000;6*/ +#define INVTARGET 29 /*;AN000;6*/ +#define LASTNOTBACKUP 30 /*;AN000;6*/ +#define FDISKFULLMSG 31 /*;AN000;6*/ +#define LOGFILE_TARGET_FULL 32 /*;AN000;6*/ +#define PRESS_ANY_KEY 33 /*;AN000;6*/ +#define CRLF 34 /*;AN000;6*/ +#define CANT_FORMAT_HARDFILE 35 /*;AN000;/* + +/*------------------------------------*/ +/*- MESSAGE CLASSES -*/ +/*------------------------------------*/ +#define EXTENDED 1 /*;AN000;6*/ +#define PARSEERROR 2 /*;AN000;6*/ +#define UTIL_MSG -1 /*;AN000;6*/ + +#define NOWAIT 0 /*;AN000;6*/ +#define WAIT 0xc8 /*;AN000;6*/ + + +/*-------------------------------------------------------------*/ +/*- CONTROL BLOCK FOR EACH BACKUP DISKETTE */ +/*-------------------------------------------------------------*/ +/*- THIS STRUCTURE WILL MAKE UP THE FIRST DH_DHLength BYTES */ +/*- OF THE control.xxx FILE ON THE BACKUP TARGET. */ +/*- IT IDENTIFIES THE DISK AS BEING A BACKUP, AND INCLUDES */ +/*- DISKETTE SEQUENCE NUMBER AND A FLAG INDICATING IF THIS */ +/*- IS THE LAST TARGET. */ +/*-------------------------------------------------------------*/ + +#define LAST_TARGET 0xFF +#define NOT_LAST_TARGET 0x00 + +struct Disk_Header + { + BYTE DH_Length; /* Length, in bytes, of disk header */ + BYTE DH_Identifier[8]; /* Identifies disk as a backup */ + BYTE DH_Sequence; /* Backup diskette seq num (1-255) */ + BYTE DH_reserved [128]; /* Save area for nothing */ + BYTE DH_LastDisk; /* Indicates if this is last target */ + /* 0xFF if last target, 0 otherwise */ + }; + + +/*----------------------------------------------------------------------*/ +/*- DIRECTORY BLOCK */ +/*----------------------------------------------------------------------*/ +/*- THIS STRUCTURE IS WRITTEN TO THE control.xxx FILE AT LEAST ONCE */ +/*- FOR EACH SUBDIRECTORY, INCLUDING THE ROOT, BACKED UP. IT CONTAINS */ +/*- THE PATH TO THAT DIRECTORY, THE NUMBER OF FILES FROM THAT */ +/*- DIRECTORY THAT ARE BACKED UP ON CURRENT TARGET, AND THE OFFSET */ +/*- OF THE NEXT DIRECTORY BLOCK ON THAT DISKETTE, IF ONE EXISTS. */ +/*- IF THERE ARE NO OTHER DIRECTORY BLOCKS, IT EQUALS 0xffffffff. */ +/*----------------------------------------------------------------------*/ +#define LAST_DB 0xFFFFFFFF + +struct Dir_Block + { + BYTE DB_Length; /* Length, in bytes, of dir block */ + BYTE DB_Path[63]; + /* ASCII path of this directory, */ + /* drive letter omitted */ + WORD DB_NumEntries; /* Num of filenames currently in list*/ + DWORD DB_NextDB; /* Offset of next directory block */ + }; /* =0xffffffff if there are no more*/ + /* on current target */ + +/*--------------------------------------------------------------------*/ +/*- CONTROL BLOCK FOR EACH BACKED-UP FILE */ +/*--------------------------------------------------------------------*/ +/*- THIS STRUCTURE WILL BE REPEATED AFTER THE DIRECTORYBLOCK ONCE */ +/*- FOR EACH FILE BACKED UP FROM THAT DIRECTORY. IT CONTAINS THE */ +/*- FILENAME, DIRECTORY INFORMATION, AND OTHER NECESSARY INFORMATION. */ +/*--------------------------------------------------------------------*/ +#define NOTLASTPART 0 +#define LASTPART 1 + +#define NOTSUCCESSFUL 0 +#define SUCCESSFUL 2 + +#define EXT_ATTR 4 /*;AN000;3*/ + +struct File_Header + { + BYTE FH_Length; /* Length, in bytes, of file header */ + BYTE FH_FName[12]; /* ASCII file name (from directory)*/ + BYTE FH_Flags; /* bit 0=1 if last part of file */ + /* bit 1=1 if it is backed up successfully */ + /* bit 2=1 if Extended Attributes are backed up (New for DOS4.00) ;AN000;3*/ + DWORD FH_FLength; /* Total length of the file (from directory) */ + WORD FH_FSequence; /* Sequence #, for files that span */ + DWORD FH_BeginOffset; /* Offset in BACKUP.xxx where this segment begins */ + DWORD FH_PartSize; /* Length of part of file on current target */ + WORD FH_Attribute; /* File attribute (from directory) */ + WORD FH_FTime; /* Time when file was last modified (from directory)*/ + WORD FH_FDate; /* Date when file was last modified (from directory)*/ + }; + +/*--------------------------------------------------------------------*/ +/*- THIS IS THE STRUCTURE THAT IS USED IN THE LINKED LIST OF */ +/*- DIRECTORIES THAT NEED TO BE PROCESSED (if /S option specified) */ +/*--------------------------------------------------------------------*/ + struct node + { + struct node *np; + char path[PATHLEN+15]; + }; + + +/*--------------------------------------------------------------------*/ +/*- THIS IS THE STRUCTURE THAT IS USED BY THE DOS FUNCTION */ +/*- "RETURN COUNTRY INFORMATION" */ +/*--------------------------------------------------------------------*/ + struct ctry_info_blk + { + WORD country_code; + WORD code_page; + WORD date_format; +#define USA 0 +#define EUR 1 +#define JAP 2 + BYTE currency_symbol[5]; + WORD thousands_separator; + WORD decimal_Separator; + WORD date_separator; + WORD time_separator; + BYTE currency_format; + BYTE num_sig_dec_dig_in_currency; + BYTE time_format; + DWORD case_map_call; + WORD data_list_separator; + WORD reserved[5]; + }; + +/*------------------------------------------------------------------------*/ +/*- THIS STRUCTURE IS USED BY THE DOS MESSAGE HANDLER SERVICE ROUTINES -*/ +/*------------------------------------------------------------------------*/ + + /************************************************/ + /* Substitution List for Message Retriever */ + /************************************************/ +/*----------------------- +; SUBLIST Equates +;------------------------*/ +#define SUBLIST_SIZE 11 /*;AN000;6*/ + +#define LEFT_ALIGN 0x0 /*;AN000;600xxxxxx */ +#define RIGHT_ALIGN 0x80 /*;AN000;610xxxxxx */ + +#define CHAR_FIELD_CHAR 0x0 /*;AN000;6a0000000 */ +#define CHAR_FIELD_ASCIIZ 0x10 /*;AN000;6a0010000 */ + +#define UNSGN_BIN_BYTE 0x11 /*;AN000;6a0010001 - Unsigned BINary to Decimal CHARacter */ +#define UNSGN_BIN_WORD 0x21 /*;AN000;6a0100001 */ +#define UNSGN_BIN_DWORD 0x31 /*;AN000;6a0110001 */ + + +/*---------------------------------------------*/ +/*- Message substitution list structure -*/ +/*---------------------------------------------*/ + struct subst_list /*;AN000;6*/ + { /*;AN000;6*/ + BYTE sl_size1; /* Size of List */ /*;AN000;6*/ + BYTE zero1; /* Reserved */ /*;AN000;6*/ + char far *value1; /* Time, date, or ptr to data item*/ /*;AN000;6*/ + BYTE one; /* n of %n */ /*;AN000;6*/ + BYTE flags1; /* Data Type flags */ /*;AN000;6*/ + BYTE max_width1; /* Maximum FIELD width */ /*;AN000;6*/ + BYTE min_width1; /* Minimum FIELD width */ /*;AN000;6*/ + BYTE pad_char1; /* Character for pad FIELD */ /*;AN000;6*/ + + BYTE sl_size2; /* Size of List */ /*;AN000;6*/ + BYTE zero2; /* Reserved */ /*;AN000;6*/ + char far *value2; /* Time; date; or ptr to data item*/ /*;AN000;6*/ + BYTE two; /* n of %n */ /*;AN000;6*/ + BYTE flags2; /* Data Type flags */ /*;AN000;6*/ + BYTE max_width2; /* Maximum FIELD width */ /*;AN000;6*/ + BYTE min_width2; /* Minimum FIELD width */ /*;AN000;6*/ + BYTE pad_char2; /* Character for pad FIELD */ /*;AN000;6*/ + }; /*;AN000;6*/ + +/*----------------------------------*/ +/*- EXTENDED OPEN PARAMETER LIST -*/ +/*----------------------------------*/ +#define EXTATTBUFLEN 4086 /*;AN000;3*/ + struct parm_list /*;AN000;3*/ + { /*;AN000;3*/ + DWORD ext_attr_addr; /*;AN000;3*/ + WORD num_additional; /*;AN000;3*/ + BYTE id_io_mode; /*;AN000;3*/ + WORD io_mode; /*;AN000;3*/ + }; /*;AN000;3*/ + +/* */ +/*----------------------------------------------------*/ +/*- SUBROUTINE DECLARATIONS -*/ +/*----------------------------------------------------*/ + int cdecl sprintf(char *, char *, ...); + int cdecl printf(char *,...); + + void alloc_buffer(void); + void alloc_first_node(void); + struct node * alloc_node(unsigned int); + void check_appendX(void); /*;AN000;2*/ + void alloc_seg(void); + void build_ext(int); + void change_levels(void); + void check_date(WORD,BYTE,BYTE); /*;AN000;4*/ + void check_DOS_version(void); + void check_drive_validity(int,char * []); + void check_for_device_names(char * []); /*;AN000;p2592*/ + void check_last_target(void); + void check_path_validity(char * []); + void check_time(BYTE,BYTE,BYTE,BYTE); /*;AN000;4*/ + void clean_up_and_exit(void); + void close_file(WORD); + void close_out_current_target(void); + void control_break_handler(void); + void create_target(void); + void datetime(void); + void delete(char *); + void delete_files(char); + long disk_free_space(void); + void display_it(int,WORD,int,BYTE,BYTE); /*;AN000;6*/ + void display_msg(int); + void do_backup(void); + void do_copy(void); + void do_dos_error(WORD); + extern unsigned far pascal set_int24_vector(void); /*;AN000;*/ + void error_exit(int); + WORD exist(char *); + WORD extended_open(WORD,WORD,char far *,WORD); /*;AN000;5*/ + void file_sharing_error(void); /*;AN000;9*/ + char far * far_ptr(WORD,WORD); + void findclose(WORD); + void find_all_subdirs(void); + void find_first(char *,WORD *,struct FileFindBuf *,WORD); + void find_first_file(void); + void find_format(void); /*;AN000;d178*/ + void find_next(WORD,struct FileFindBuf *); + void find_next_file(void); + void find_the_first(void); + void find_the_next(void); + void format_target(void); + void free_seg(unsigned); + WORD get_attribute(char *); + void get_current_dir(WORD,char *); + WORD get_current_drive(void); + void get_country_info(void); + void get_diskette(void); + void get_drive_types(void); + void get_extended_attributes(WORD); /*;AN000;3 */ + void get_first_target(void); + void get_hardfile(void); + void get_next_target(void); + void get_path(char *); /*;AN002;*/ + WORD handle_open(char *,WORD); + WORD handle_read(WORD,WORD,char far *); + WORD handle_write(WORD,WORD,char far *); + void init(void); /*;AN000;6*/ + void insert_node(char *); + WORD ioctl(WORD); + void label_target_drive(void); + DWORD lseek(WORD,BYTE,DWORD); + int main(int, char * []); + void mark_as_last_target(void); + void mark_as_not_last_target(void); + void mark_files_read_only(void); + void open_logfile(void); + void open_source_file(void); + void open_target(void); + void parser(int,char * []); /*;AN000;4*/ + void parse_error(WORD,WORD); /*;AN000;4*//*;AN008;*/ + void parse_init(void); /*;AN000;4*/ + void process_switch(void); /*;AN000;4*//*;AN008;*/ + void put_disk_header(void); + void put_new_db(void); + void put_new_fh(void); + void remove_last_backslash_from_BDS(void); + void remove_node(void); + void replace_volume_label(char *); + void reset_archive_bit(char *); + void restore_default_directories(void); + void save_current_dirs(void); + void see_if_it_should_be_backed_up(void); + void set_attribute(char *,WORD); + void set_vectors(void); /*;AN000;*/ + void set_default_dir(void); + void set_default_drive(WORD); + void setsignal(WORD,WORD); + void show_path(void); + char *strcat(char *,const char *); /* */ + size_t strlen(const char *); /* */ + char *strcpy(char *, const char *); /* */ + char *strncpy(char *, const char *, unsigned int); /* */ + int strncmp(const char *,const char *,unsigned int);/* */ + int strcmp(const char *,const char *); /* */ + void terminate(void); + void update_db_entries(WORD); + void update_fh_entries(void); +/***** void write_extended_attributes(void); /*;AN000;3*/ + WORD write_till_target_full(WORD,WORD); + void write_to_control_file(char far *,WORD); + void write_to_target(WORD); + void xlat(char *,char *); /*;AN000;*/ + +extern void sysloadmsg(union REGS *, union REGS *); /*;AN000;6*/ +extern void update_logfile(union REGS *, union REGS *); /*;AN000;9*/ +extern void sysdispmsg(union REGS *, union REGS *); /*;AN000;6*/ +extern void parse (union REGS *, union REGS *); /*;AN000;4*/ + +/*-------------------------------*/ +/*- From COMSUB.H */ +/*-------------------------------*/ + +/* convert character to uppercase */ +extern int com_toupper( + unsigned char ); /* character to be converted to uppercase */ + + +/* search the first occurrence of a character in a string */ +extern char *com_strchr( + unsigned char *, /* a source string */ + unsigned char ); /* a character to be searched */ + +/* search the last charater occurrence in a string */ +extern unsigned char +*com_strrchr( + unsigned char *, /* source string */ + unsigned char ); /* target string */ diff --git a/v4.0/src/CMD/BACKUP/BACKUP.SKL b/v4.0/src/CMD/BACKUP/BACKUP.SKL new file mode 100644 index 0000000..c083c25 --- /dev/null +++ b/v4.0/src/CMD/BACKUP/BACKUP.SKL @@ -0,0 +1,52 @@ +;========================================================== + +:util BACKUP ;AN000; + +;--------- +:class A +;--------- +:use 1 COMMON1 ;AN000; ;For "Incorrect DOS version +:def 2 CR,LF,"Insufficient memory",CR,LF ;AN000; +:def 6 CR,LF,"Invalid drive specification",CR,LF ;AN000; +:use 7 COMMON23 ;AN000; ;For "Invalid date +:use 8 COMMON24 ;AN000; ;For "Invalid time + + +:use 11 COMMON25 ;AN000; ;For "Invalid path + +:use 12 COMMON26 ;AN000; ;For "No source drive specified +:use 13 COMMON27 ;AN000; ;For "No target drive specified +:def 14 CR,LF,"Source and target drives are the same",CR,LF ;AN000; +:def 15 CR,LF,"Error executing FORMAT",CR,LF ;AN000;d178 +:def 16 CR,LF,"Cannot find FORMAT.COM",CR,LF ;AN000;d178 +:def 17 CR,LF,"Error opening logfile",CR,LF ;AN000; +:def 18 CR,LF,"Logging to file %1",CR,LF ;AN000; +:def 19 CR,LF,"Last backup diskette not inserted",CR,LF ;AN000; + +:def 20 CR,LF,"Warning! Files in the target drive",CR,LF ;AN000; + "%1:\ root directory will be erased",CR,LF ;AN000; + +:def 21 CR,LF,"Warning! Files in the target drive",CR,LF ;AN000; + "%1:\BACKUP directory will be erased",CR,LF ;AN000; + +:def 22 CR,LF,"*** Backing up files to drive %1: ***",CR,LF ;AN000; +:def 23 "Diskette Number: %1",CR,LF ;AN000; +:def 24 CR,LF,"Warning! No files were found to back up",CR,LF ;AN000; +:def 25 CR,LF,"Insert backup source diskette in drive %1:",CR,LF ;AN000; + +:def 26 CR,LF,"Insert backup diskette %1 in drive %2:",CR,LF ;AN000; +:def 27 CR,LF,"*** Not able to backup file ***",CR,LF ;AN000; +:def 28 CR,LF,"Insert last backup diskette in drive %1:",CR,LF ;AN000; + +:def 29 CR,LF,"Target can not be used for backup",CR,LF ;AN000; +:def 30 CR,LF,"*** Last file not backed up ***",CR,LF ;AN000; +:def 31 CR,LF,"Fixed backup device %1: is full",CR,LF ;AN000; + +:def 32 CR,LF,"Disk full error writing to BACKUP Log File",CR,LF ;AN000; + ;AN000; +:use 33 COMMON28 ;AN000; ;For "Press any key to continue . . . +:def 34 CR,LF ;AN000; +:def 35 CR,LF,"Cannot FORMAT nonremovable drive %1:",CR,LF ;AN000; + +:end ;AN000; +;========================================================== diff --git a/v4.0/src/CMD/BACKUP/MAKEFILE b/v4.0/src/CMD/BACKUP/MAKEFILE new file mode 100644 index 0000000..4caece8 --- /dev/null +++ b/v4.0/src/CMD/BACKUP/MAKEFILE @@ -0,0 +1,45 @@ +#************************** makefile for cmd\backup *************************** + +cflags = -AS -Od -Zp $(extcsw) +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h +map =..\..\mapper +here =..\cmd\backup + +# +####################### dependencies begin here. ######################### +# + +all: backup.com + +$(map)\mapper.lib: + cd $(map) + nmake + cd $(here) + +_parse.obj: _parse.asm \ + $(inc)\parse.asm \ + $(inc)\psdata.inc \ + makefile + +backup.ctl: backup.skl \ + $(msg)\$(COUNTRY).MSG + +_msgret.obj: _msgret.asm \ + backup.ctl \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc \ + $(inc)\versiona.inc \ + $(inc)\copyrigh.inc \ + makefile + +backup.obj: backup.c backpars.h backup.h makefile \ + $(hinc)\doscalls.h + +backup.com: backup.obj _parse.obj _msgret.obj \ + $(map)\mapper.lib $(inc)\comsubs.lib + link /NOE backup + _parse + _msgret,,,$(map)\mapper + $(inc)\comsubs; + convert backup.exe backup.com + del backup.exe diff --git a/v4.0/src/CMD/BACKUP/_MSGRET.ASM b/v4.0/src/CMD/BACKUP/_MSGRET.ASM new file mode 100644 index 0000000..cf87f1e --- /dev/null +++ b/v4.0/src/CMD/BACKUP/_MSGRET.ASM @@ -0,0 +1,268 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.30 message retriever +; +; CALLING FORMAT: +; sysloadmsg(&inregs,&outregs); +; sysdispmsg(&inregs,&outregs); +; sysgetmsg(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; + + .8087 +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS +DGROUP GROUP CONST, _BSS, _DATA + ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP + + + public _sysloadmsg + public _sysdispmsg + public _update_logfile + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + +_DATA segment +.XLIST +.XCREF + MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; + +.LIST +.CREF +_DATA ends + + +_TEXT segment + +;------------------------------------------------------------------- + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg +.XLIST +.XCREF + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; +.LIST +.CREF +;------------------------------------------------------------------- + +_sysloadmsg proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + call sysloadmsg ; call the message retriever +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_sysloadmsg endp + + +;============================================================================ +;============================================================================ +;============================================================================ + + +_update_logfile proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + + mov di,[bp+4] ; fix di (arg 0) +;------------------------------------------------------------------- + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer +;------------------------------------------------------------------- + mov dh,-1 ; Message class, Utility message + mov cs:handle,bx ;AN000;9 Save logfile handle + mov cs:len,cx ;AN000;9 Save write length + push ds ;AN000;9 + pop cs:save_ds ;AN000;9 + call sysgetmsg ; call the message retriever +;------------------------------------------------------------------- + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + mov cs:offst,si ;AN000;9 + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + + mov ah,040h ;AN000;9 Write the message to logfile + mov bx,cs:handle ;AN000;9 + mov cx,cs:len ;AN000;9 + mov dx,cs:offst ;AN000;9 + int 021h ;AN000;9 + push cs:save_ds ;AN000;9 + pop ds ;AN000;9 + ret + + handle dw ? ;AN000;9 + len dw ? ;AN000;9 + offst dw ? ;AN000;9 + save_ds dw ? ;AN000;9 +_update_logfile endp + +;============================================================================ +;============================================================================ +;============================================================================ + + +_sysdispmsg proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) +;------------------------------------------------------------------- + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer +;------------------------------------------------------------------- + call sysdispmsg ; call the message retriever +;------------------------------------------------------------------- + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di +;------------------------------------------------------------------- + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_sysdispmsg endp + +;============================================================================ +;============================================================================ +;============================================================================ + +;============================================================================ +;============================================================================ +;============================================================================ + +include msgdcl.inc + + +_TEXT ends ; end code segment + end + + \ No newline at end of file diff --git a/v4.0/src/CMD/BACKUP/_PARSE.ASM b/v4.0/src/CMD/BACKUP/_PARSE.ASM new file mode 100644 index 0000000..0c13826 --- /dev/null +++ b/v4.0/src/CMD/BACKUP/_PARSE.ASM @@ -0,0 +1,121 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.30 parser +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse + + include version.inc + +;------------------------------------------------------------------- +FarSW equ 0 ; make sysparse be a NEAR proc +TimeSW equ 1 ; Check time format +FileSW equ 1 ; Check file specification +CAPSW equ 1 ; Perform CAPS if specified +CmpxSW equ 0 ; Check complex list +NumSW equ 0 ; Check numeric value +KeySW equ 0 ; Support keywords +SwSW equ 1 ; Support switches +Val1SW equ 0 ; Support value definition 1 +Val2SW equ 0 ; Support value definition 2 +if ibmcopyright +Val3SW equ 0 ; Support value definition 3 +else +Val3SW equ 1 ; Support value definition 3 +endif +DrvSW equ 1 ; Support drive only format +QusSW equ 0 ; Support quoted string format +IncSW equ 0 ; Dont include PSDATA, I just did it +BaseSW equ 1 ; DS points to data +;------------------------------------------------------------------- + +DGROUP GROUP _DATA +PGROUP GROUP _TEXT + +_DATA segment byte public 'DATA' +include psdata.inc +_DATA ends + +_TEXT segment byte public 'CODE' + + ASSUME CS: PGROUP + ASSUME DS: DGROUP + +;------------------------------------------------------------------- +.xlist +include parse.asm ; include the parser +.list +;------------------------------------------------------------------- + +_parse proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer +;------------------------------------------------------------------- + call sysparse ; call the parser +;------------------------------------------------------------------- + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_parse endp + +_TEXT ends ; end code segment + end + + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKCHNG.INC b/v4.0/src/CMD/CHKDSK/CHKCHNG.INC new file mode 100644 index 0000000..46f7991 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKCHNG.INC @@ -0,0 +1,288 @@ +.xlist +; +; + +; CHKDSK Version 2.0 +; Verifies and repairs MS-DOS disk directory. + + +;REV 1.1 ARR +; 05/21/82 Added rev number +;REV 1.5 NP ARR +; Mod by NANCYP to report on extents +; Mod by AARONR to report volume ID +;REV 2.0 ARR +; Total rewrite for directories +;REV 2.1 ARR +; Added ^C and INT 24H handlers +;REV 2.2 ARR +; INTERNATIONAL support +;REV 2.3 NP +; Mod by NANCYP to use 2.0 system calls +; and accept pathnames as parameters +;REV 2.4 NP +; PRINTF incorporated into CHKDSK +; Modified to run as .EXE file +;REV 3.0 ARR 8/30/83 +; Update for vers 2.5 of DOS +; 16 bit FATS +;REV 3.05 RS 10/11/84 +; Split into CHKDSK2.ASM for on-machine assembly. +;REV 3.20 RS 9/26/85 +; Allow 0F0H as a valid DOS media descriptor byte - used for non-standard +; media layouts. +; +;***************************************************************************** +;* * +;* Change list to CHKDSK modules * +;* * +;* Lines are tagged ANxxx for new, ACxxx for changed * +;* --------------------------------------------------------------------------* +;* 000 - DOS 4.00 Spec additions and DCR's thru unit/function test * +;* Date: 8/3/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 001 - DOS 4.00 PTM P265 - Give 'Can't chkdsk subst drive" when running * +;* hardfile. Using 1 based drive insted of 0 * +;* Date: 8/17/87 Developer: Mark T. * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 002 - DOS 4.00 PTM P251 - Hang when chkdsk default drive. Not setting up * +;* drive fields correctly on default drive * +;* Date: 8/14/87 Developer: Mark T. * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* * +;* * +;* * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 005 - DOS 4.00 DCR D166 - Enable 128k FAT * +;* Date: 8/21/87 Developer: Bruce B. * +;* general modifications are: reserve the rest of the program segment for the* +;* stack, put the fat-table next after the end of the program seg, then * +;* put the fatmap area next after the end of the fat-table. * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 006 - DOS 4.00 ptm p097 - change calculation of total disk space * +;* Date: 8/28/87 Developer: Bruce B. * +;* modules - chkinit.sal, chkdsk2.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 007 - DOS 4.00 ptm p816 - files with length zero * +;* Date: 8/21/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 008 - DOS 4.00 ptm p872 - incorrect media size reported * +;* Date: 9/10/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 009 - DOS 4.00 ptm p1151- incorrect date and time * +;* Date: 9/10/87 Developer: Bruce B. * +;* modules - chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 010 - DOS 4.00 ptm p1158- incorrect disk size when disk is full * +;* Date: 9/10/87 Developer: Bruce B. * +;* modules - chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 011 - DOS 4.00 ptm p817 - cant check files * +;* Date: 9/24/87 Developer: Bruce B. * +;* modules - chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 012 - DOS 4.00 ptm p1223- month and day reversed * +;* Date: 9/22/87 Developer: Bruce B. * +;* modules - chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 013 - DOS 4.00 ptm p1238- not detect filesize <> number of clusters * +;* Date: 9/25/87 Developer: Bruce B. * +;* modules - chkproc.sal, chkdisk.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - DOS 4.00 ptm p1239- hangs when file has invalid ??? * +;* Date: 9/25/87 Developer: Bruce B. * +;* modules - chkproc.sal, chkdisk.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 014 - DOS 4.00 ptm p1240- not detect crosslinked files * +;* Date: 9/25/87 Developer: Bruce B. * +;* modules - chkproc.sal, chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - DOS 4.00 ptm p1241- hangs when trying to fix lost subdir * +;* Date: 9/25/87 Developer: Bruce B. * +;* modules - chkproc.sal, chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - DOS 4.00 ptm p1242- hangs when lost subdir found * +;* Date: 9/25/87 Developer: Bruce B. * +;* modules - chkproc.sal, chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 015 - DOS 4.00 ptm p1176 - not working for vdisk drives * +;* Date: 10/1/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 016 - DOS 4.00 ptm p1436 - not working for full disk with system files * +;* Date: 10/2/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - DOS 4.00 ptm p1437 - not working on vdisk * +;* Date: 10/2/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* - DOS 4.00 ptm p1447 - chkdsk filenam --> invalid drive spec * +;* Date: 10/2/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 017 - DOS 4.00 ptm p1491 - invalid use of common msgs * +;* Date: 10/5/87 Developer: Bruce B. * +;* modules - chkdsk.skl chkmsg.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 018 - DOS 4.00 ptm p1507 - 'non_dos' instead of 'non-dos' * +;* Date: 10/6/87 Developer: Bruce B. * +;* modules - chkdsk.skl * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 019 - DOS 4.00 ptm p1506 - '0 bytes would be freed' * +;* Date: 10/6/87 Developer: Bruce B. * +;* modules - * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 020 - DOS 4.00 ptm p1556 - chkdsk allows 2 positional or keyword parms * +;* Date: 10/8/87 Developer: Bruce B. * +;* modules - chkparse.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 021 - DOS 4.00 ptm p1557 - displays invalid drive spec twice * +;* Date: 10/8/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 022 - DOS 4.00 ptm p1558 - divide overflow on invalid drive * +;* Date: 10/8/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 023 - DOS 4.00 ptm p1559 - abnormal results when int13 is bad * +;* Date: 10/8/87 Developer: Bruce B. * +;* modules - * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 024 - DOS 4.00 ptm p1606 - no display of volume serial number * +;* Date: 10/12/87 Developer: Bruce B. * +;* modules - chkdsk2.sal, chkmsg.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 025 - DOS 4.00 ptm p1761 - doesnt work on zerod out cluster for dir * +;* Date: 10/17/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 026 - DOS 4.00 ptm p1842 - chkdsk accepts 2 filespec parms * +;* Date: 10/20/87 Developer: Bruce B. * +;* modules - chkinit.sal, chkparse.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 027 - DOS 4.00 ptm p2007 - test case 7 - chkdsk a: /v (invalid subdirs) * +;* Date: 10/24/87 Developer: Bruce B. * +;* modules - chkproc.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 028 - DOS 4.00 ptm p2029 - chkdsk cant exec for afs * +;* Date: 10/26/87 Developer: Bruce B. * +;* modules - chkexec.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 029 - DOS 4.00 ptm p2104 - chkdsk goes to drive a: on ctl-break * +;* Date: 10/29/87 Developer: Bruce B. * +;* modules - chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 030 - DOS 4.00 ptm p2323 - low memory check, correct free memory report * +;* Date: 11/04/87 Developer: Bruce B. * +;* modules - chkfat.sal, chkdsk2.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 031 - DOS 4.00 ptm p2495 - incorrect message for drive not ready * +;* Date: 11/17/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 032 - DOS 4.00 ptm p2648 - unformatted disk displays "invalid device type" * +;* Date: 11/24/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 033 - DOS 4.00 ptm p2781 - divide overflow on unformatted diskette * +;* Date: 12/07/87 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 034 - DOS 4.00 ptm p2975 - get psp done three times * +;* Date: 12/20/87 Developer: Bruce B. * +;* modules - chkinit.sal, chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 035 - DOS 4.00 ptm p3007 - chkdsk reports incorrect memory * +;* Date: 12/28/87 Developer: Bruce B. * +;* modules - chkinit.sal, chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 036 - DOS 4.00 ptm p3028 - include pathgen into pgm * +;* Date: 01/12/88 Developer: Bruce B. * +;* modules - all * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 037 - DOS 4.00 ptm p3129 - chkdsk fails to build * +;* Date: 01/14/88 Developer: Bruce B. * +;* modules - chkdisp.asm * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 038 - DOS 4.00 ptm p3130 - remove AFS from code * +;* Date: 01/14/88 Developer: Bruce B. * +;* modules - chkinit.sal, chkequ.inc, chkexec.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 039 - DOS 4.00 ptm p3360 - correct addressing of ctl-break handling * +;* Date: 02/05/88 Developer: Bruce B. * +;* modules - chkproc2.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 040 - DOS 4.00 ptm p3573 - pathgen parser and msg ret. * +;* Date: 02/19/88 Developer: Bruce B * +;* modules - chkdisp.asm, chkparse.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 041 - DOS 4.00 dcr d490 - change get media id call for same as os/2 1.0 * +;* Date: 02/26/88 Developer: Bruce B * +;* modules - chkdata.inc, chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 042 - DOS 4.00 ptm p3735 - chkdsk prints files to stderr, not stdout * +;* Date: 03/04/88 Developer: Bruce B * +;* modules - chkmsg.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 043 - DOS 4.00 ptm p3708 - chkdsk prints wrong message for network drive * +;* Date: 03/07/88 Developer: Bruce B * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 044 - DOS 4.00 ptm p3840 - wrong message for newtork filename * +;* Date: 03/14/88 Developer: Bruce B * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 045 - DOS 4.00 ptm p3876 - hang when .. entry erased and /f parameter * +;* Date: 03/15/88 Developer: Bruce B * +;* modules - chkproc.sal, chkdsk2.sal, chkmsg.inc, chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 046 - DOS 4.00 ptm p3923?- display invalid parm names * +;* Date: 03/21/88 Developer: Bruce B * +;* modules - chkinit.sal, chkmsg.inc * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 047 - private build only- display lost cluster number * +;* Date: 03/24/88 Developer: Bruce B * +;* modules - chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 048 - DOS 4.00 PTM p4050 - wont recover . and .. entries * +;* Date: 04/12/88 Developer: Bruce B * +;* modules - many * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 049 - DOS 4.00 PTM p4125 - chkdsk prints incorrect user file bytes * +;* Date: 04/13/88 Developer: Bruce B. * +;* modules - many * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 050 - DOS 4.00 PTM p4571 - chkdsk and mem report diff ram under Windows * +;* Date: 05/02/88 Developer: Bruce B. * +;* modules - chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 051 - DOS 4.00 PTM p4571 - chkdsk does not recover lost clusters into files* +;* Date: 05/05/88 Developer: Bruce B. * +;* modules - chkfat.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 052 - DOS 4.00 PTM p4869 - handle MS ramdrive.sys * +;* Date: 05/16/88 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 053 - DOS 4.00 PTM p4924 - oops! do it right this time.... * +;* Date: 05/19/88 Developer: Bruce B. * +;* modules - chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 054 - DOS 4.00 PTM p4957 - both chkdsk & mem do avail mem incorrectly * +;* Date: 05/24/88 Developer: Bruce B. * +;* modules - chkdsk1.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 055 - DOS 4.00 PTM p5007 - wont handle '\' as 2nd byte of dbcs pair * +;* Date: 06/01/88 Developer: Bruce B * +;* modules - chkdsk1.sal, chkinit.sal * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* * +;***************************************************************************** +;* Note: This is file CHKCHNG.INC for updating purposes * +;***************************************************************************** diff --git a/v4.0/src/CMD/CHKDSK/CHKDATA.INC b/v4.0/src/CMD/CHKDSK/CHKDATA.INC new file mode 100644 index 0000000..aeb1ffe --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDATA.INC @@ -0,0 +1,244 @@ + +CONST SEGMENT PUBLIC PARA 'DATA' + EXTRN STACKMES:byte + EXTRN BADVER:byte, BADDRV_ARG:word, INVPATH_ARG:word + EXTRN FILE_ARG:word + EXTRN BADCD_ARG:word, BADSUBDIR:byte + EXTRN no_mem_arg:word ;an030;bgb + EXTRN BADRDMES:byte + EXTRN BADDRVM:byte + EXTRN BADIDBYT:byte + EXTRN OPNERR_ARG:word, NOEXT_ARG:word, EXTENT_ARG:word + EXTRN IDMES_ARG:WORD + EXTRN ORPH_ARG:WORD + EXTRN FILE_ARG1:WORD, FILE_ARG2:WORD + EXTRN badrw_num:word, BADRW_STR:WORD, BLOCK_NUM:WORD + EXTRN FATAL_ARG1:WORD, FATAL_ARG2:WORD + EXTRN FATmsg2:word ;an024;bgb + EXTRN BADSW_ARG:WORD, DSKSPC:WORD ;an049;bgb + EXTRN HIDMES:WORD, DIRMES:WORD, FILEMES:WORD, ORPHMES2:WORD + EXTRN ORPHMES3:WORD, BADSPC:WORD, FRESPC:WORD + EXTRN FREMEM:WORD, REPORT_ARG:WORD, CRLF_ARG:WORD + EXTRN RARG1:WORD, RARG3:WORD, ORPHCNT:WORD + EXTRN NO_NET_ARG:byte, MONTAB:BYTE, SubstErr:BYTE + EXTRN ExitStatus:Byte,Badr_Arg:Byte ;an000;bgb + EXTRN Sublist_msg_Idmes:word ;an000;bgb + extrn msgserialnumber:byte ;an000;bgb + extrn psp_segment:word ;an000;bgb;an034;bgb + ;an000;bgb + PUBLIC SWITCHAR + PUBLIC TCHAR + PUBLIC HECODE + PUBLIC conbuf + PUBLIC DOTMES + PUBLIC NOISY + PUBLIC DOTENT + PUBLIC HAVFIX + PUBLIC DOFIX + PUBLIC DIRBUF + PUBLIC PARSTR, DDOTENT, NUL, ERRSUB, SECONDPASS, ALLFILE + PUBLIC ORPHFCB, ORPHEXT, HIDCNT, HIDSIZ, FILCNT, FILSIZ, DIRCNT + PUBLIC DIRSIZ, DIRTYFAT, CROSSCNT, BADSIZ, ORPHSIZ, LCLUS + PUBLIC USERDIR, FRAGMENT, ALLDRV, FIXMFLG, DIRCHAR + PUBLIC BIGFAT, EOFVAL, BADVAL,CHAIN_END + PUBLIC fTrunc,Volnam + PUBLIC temp_dd ;an049;bgb + +DIRBUF LABEL BYTE ;Entry buffer for searches +VOLID DB -1,0,0,0,0,0,8 ;Volume ID FCB +VOLNAM DB 0,"???????????" + DB 25 DUP(0) + +ALLFILE DB -1 ;Extended FCB indicator + DB 0,0,0,0,0 ;reserved bytes + DB 1EH ;attribute byte 0001-1110 hidden, system, label, subdir +ALLDRV DB 0 ;default drive + DB "???????????" ;any file name + DB 25 DUP (?) + +ORPHFCB DB 0,"FILE0000" +ORPHEXT DB "CHK" + DB 25 DUP (?) + +fcb_copy db 32 dup (?) + +;Non-message data + +pFileName DW ? ; pointer +SWITCHAR DB "/" +ROOTSTR LABEL BYTE ;use this to change dir to the root +DIRCHAR DB "\" +NUL DB 0 +PARSTR DB "..",0 +DOTMES DB ".",0 +DOTENT DB ". " +DDOTENT DB ".. " +HECODE DB ? +FIXMFLG DB 0 ;Flag for printing fixmes +ERRSUB DW 0 ;Flag for bad subdir error +FRAGMENT DB 0 ;Flag for extent processing +DIR_FIX DB 0 ;Flag for changing dir back to users' +DIRTYFAT DB 0 ;Dirty flag for FAT +; +;note - all these fields that count allocation units can remain the same, +; because the total au's are always less than 64k (1 word). +; looks like the number of files and directories should change, though. +DIRCNT dd 0 ;# directories ;an049;bgb +DIRSIZ dw 0 ;# alloc units in dirs ;an049;bgb +FILCNT dd 0 ;# reg files +FILSIZ dw 0 ;# alloc units in reg files +HIDCNT dd 0 ;# hidden files +HIDSIZ dw 0 ;# alloc units in hid files +BADSIZ dw 0 ;# alloc units in bad sectors +ORPHSIZ dw 0 ;# alloc units in orphan files +LCLUS dw 0 ;# alloc units in lost clusters +DISPFLG DB 0 ;used by number routines +CROSSCNT dd 0 ;# crosslinked files (first pass) +;end of display fields +; +temp_dd dd 0 ;temporary double word field for orphcnt;an049;bgb +SECONDPASS DB 0 ;Pass flag +HAVFIX DB 0 ;non zero if any fixes +DOFIX DB 0 ;flag for F switch +NOISY DB 0 ;flag for V switch +BIGFAT DB 0 ;0=12 bit FAT, NZ=16bit FAT +EOFVAL DW 0FF8H ;0FF8 for 12 bit FAT,0FFF8 for 16 bit +CHAIN_END DW 0FFFH ;0FFF for 12 bit FAT,0FFFF for 16 bit ;AN000; +BADVAL DW 0FF7H ;0FF7 for 12 bit FAT,0FFF7 for 16 bit + +mon_name db 3 dup (?),0 +TCHAR DB 'a' +USERDIR DB "\",0 ;Users current dir for drive + DB (DIRSTRLEN-1) DUP (?) +CONBUF DB 15,0 ;Input buffer + DB 15 DUP (?) + +fTrunc DB FALSE ; TRUE => couldn't chdir, no freeing. + +badread db " File allocation table bad",0 +CONST ENDS + + + + + + + + +DATA SEGMENT PUBLIC PARA 'DATA' + PUBLIC THISDPB,DOTSNOGOOD,NUL_ARG,STACKLIM,ZEROTRUNC + PUBLIC NAMBUF,SRFCBPT,fatmap,ISCROSS,MCLUS,CSIZE,SSIZE + PUBLIC DSIZE,ARG1,ARG_BUF,ERRCNT,USERDEV,SECBUF + PUBLIC HARDCH,CONTCH,PATH_NAME,TMP_SPC,mem_size + public Read_Write_Relative,Transrc, fatcnt, fattbl_seg ;an000;bgb + public firstfat, fatsiz, secs_per_64k, paras_per_fat, sec_count ;an000;bgb + public firstsec ;an047;bgb + public dirsec ;an047;bgb + public root_entries ;an047;bgb + public paras_per_64k, save_drive ;an000;bgb + public sernum ;an000;bgb;an024;bgb +ifdef fsexec ;an038;bgb + public exec_path ;an038;bgb;an000;bgb;an027;bgb + public exec_block ;an038;bgb;an000;bgb;an027;bgb + public path_string ;an038;bgb;an000;bgb;an027;bgb +endif ;an038;bgb + public end_of_fatmap ;an000;bgb;an030;bgb + public DBCS_VECTOR ;an055;bgb + public DBCS_VECTOR_off ;an055;bgb + public DBCS_VECTOR_seg ;an055;bgb + +DBCS_VECTOR DB 0 +DBCS_VECTOR_off dw 0 +DBCS_VECTOR_seg dw 0 + +ifdef fsexec ;an038;bgb +Exec_Block Exec_Block_Parms <> ;an038;bgb;an027;bgb +EXEC_Path db 66 dup(0) ;an038;bgb;an027;bgb +;These next two should stay togather ;an027;bgb +; --------------------------------------- ;an027;bgb +Path_String db "PATH=" ; ;an027;bgb +Len_Path_String equ $ - Path_String ; ;an027;bgb;AN000; +;---------------------------------------- ;an027;bgb +endif ;an038;bgb + ;an038;bgb;an027;bgb + ;an027;bgb +;These should stay togather ;an027;bgb +; --------------------------------------- ;an027;bgb + ; ;an027;bgb +Search_Chkdsk db "KSDKHC" ; ;an027;bgb +Len_Search_Chkdsk equ $ - Search_Chkdsk ; ;an027;bgb +Search_Chkdsk_End equ $-1 ;an027;bgb + ; ;an027;bgb +;---------------------------------------- ;an027;bgb +save_drive db 0 ;determines whether drive specified is valid +firstfat dw 0 ;sector number of fat ;an005;bgb +firstsec dw 0 ;sector number of data area ;an047;bgb +dirsec dw 0 ;sector number of dir area ;an047;bgb +root_entries dw 0 ;number of entries in root dir ;an047;bgb +fattbl_seg dw 0 ;segment of the fat-table ;an005;bgb +sec_count dw 0 ;sectors / 64k +secs_per_64k dw 0 ;an005;bgb +paras_per_64k dw 0 ;an005;bgb +fatsiz dw 0 ;an005;bgb +paras_per_fat dw 0 ;an005;bgb +fatcnt db 2 ;number of fats on disk ;an005;bgb +HARDCH dd ? ;Pointer to real INT 24 handler +CONTCH DD ? ;Pointer to real INT 23 handler +THISDPB DD ? ;Pointer to drive DPB +USERDEV DB ? ;Users current device +CSIZE DB ? ;Sectors per cluster 1-256 +SSIZE DW ? ;bytes per sector 1-64k +DSIZE DW ? ;# alloc units on disk +MCLUS DW ? ;DSIZE + 1 +NAMBUF DB 14 DUP (?) ;Buffer +DOTSNOGOOD DB ? ;. or .. error flag +ZEROTRUNC DB ? ;Trimming flag +ISCROSS DB ? ;Crosslink flag +OLDCLUS DW ? +SRFCBPT DW ? +fatmap DW ? ;segment of fatmap table ;an005;bgb +end_of_fatmap dw ? ;last mem segment used ;an030;bgb +SECBUF DW ? ;Offset of sector buffer (in ram) +ERRCNT DB ? ;Used by FATread and write +PATH_NAME DB 128 DUP(0) +FNAME_LEN DW 128 +NUL_ARG DB ? +ARG1 DW ? +ARG2 DW ? +ARG3 DW ? + + +; +; The following is used as a PRINTF buffer and also as the source/destination +; for a name trans +; +ARG_BUF DB 256 DUP (?) +TMP_SPC DB 128 DUP (?) +mon dw ? +day dw ? +year dw ? +mem_size dw ? +;;;TRANSRC DB "A:CON",0,0 ; Device so we don't hit the drive +TRANSRC DB "A:\",0,0 ; Device so we don't hit the drive +Read_Write_Relative Relative_Sector_Buffer <> ; ;AN000; + +STACKLIM DW ? ;Stack growth limit +INTERNATVARS internat_block <> + DB (internat_block_max - ($ - INTERNATVARS)) DUP (?) + + +; Structure for Get_Media_Id ;an024;bgb +SerNumBuf Label Byte ;AN000;S GENERIC_IOCTL buffer ;an024;bgb + dw 0 ;AN000;S Info level (set on input) ;an024;bgb +SerNum dd 0 ;AN000;S Serial # ;an024;bgb + db 11 DUP(' ') ;AN000;S Volume label ;an024;bgb + db 8 DUP(' ') ;AN000;S File system type ;an024;bgb +DATA ENDS + + ;an000;bgb + ;an000;bgb +lastseg SEGMENT PUBLIC PARA 'LAST' ;an000;bgb + public fattbl ;an000;bgb +fattbl db 0 ;this is the last thing in the pgm ;an000;bgb;an005;bgb +lastseg ends ;this is where the fat is put in ram ;an000;bgb + diff --git a/v4.0/src/CMD/CHKDSK/CHKDISK.ASM b/v4.0/src/CMD/CHKDSK/CHKDISK.ASM new file mode 100644 index 0000000..c76be99 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDISK.ASM @@ -0,0 +1,328 @@ +TITLE CHKDISK - procedures that read or write to the disk +page ,132 ; + + .xlist + include chkseg.inc ;an005;bgb + INCLUDE CHKCHNG.INC + INCLUDE DOSSYM.INC + INCLUDE CHKEQU.INC + INCLUDE CHKMACRO.INC + include pathmac.inc + + +CONST SEGMENT PUBLIC PARA 'DATA' + EXTRN FIXMES_ARG:word + EXTRN BADW_ARG:word + EXTRN badrw_num:word,BADRW_STR:WORD,HAVFIX:byte + EXTRN DIRTYFAT:byte,DOFIX:byte,SECONDPASS:byte + EXTRN HECODE:byte,USERDIR:byte,FRAGMENT:byte + EXTRN ORPHEXT:byte,ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte + EXTRN EOFVAL:word,BADVAL:word + extrn fTrunc:BYTE +CONST ENDS + +DATA SEGMENT PUBLIC PARA 'DATA' + EXTRN THISDPB:dword,NUL_ARG:byte + EXTRN NAMBUF:byte,SRFCBPT:word,FATMAP:word + EXTRN USERDEV:byte,HARDCH:dword,CONTCH:dword + EXTRN ExitStatus:Byte,Read_Write_Relative:Byte + extrn bytes_per_sector:word ;an005;bgb + extrn sec_count:word, paras_per_64k:word, secs_per_64k:word ;an005;bgb + extrn fattbl_seg:word, paras_per_fat:word ;an005;bgb +DATA ENDS + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + EXTRN FCB_TO_ASCZ:NEAR + EXTRN EPRINT:NEAR + EXTRN PROMPTYN:NEAR,DIRPROC:NEAR + EXTRN DOCRLF:NEAR,UNPACK:NEAR,PACK:NEAR + EXTRN CHECKNOFMES:NEAR +public read_disk, Read_once, write_disk, Write_once ;an005;bgb +public ReadFt, seg_adj, calc_sp64k ;an005;bgb + .list + + + pathlabl chkdisk +;========================================================================= ;an005;bgb +; READ_DISK : This routine reads the logical sector count requested. ;an005;bgb +; It will read a maximum of 64k in one read. If more ;an005;bgb +; than 64k exists it will continue looping until ;an005;bgb +; all sectors have been read. ;an005;bgb +; ;an005;bgb +; Inputs : AL - Drive letter ;an005;bgb +; ES:BX - Segment:offset of transfer address ;an005;bgb +; CX - Sector count ;an005;bgb +; DX - 1st sector ;an005;bgb +; ;an005;bgb +; Outputs : Logical sectors read ;an005;bgb +; LOGIC ;an005;bgb +; ***** ;an005;bgb +; adjust es:bx to es:00 ;an005;bgb +; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?) +; DO while there are more sectors to read than sectors-per-64k ;an005;bgb +; set sector-count to sectors-per-64k ;an005;bgb +; perform the disk read ;an005;bgb +; bump the seg addr to the new addr ;an005;bgb +; dec the number of sectors to read by sectors-per-64k ;an005;bgb +; bump the starting sector number by the sectors-per-64k ;an005;bgb +; ENDDO ;an005;bgb +; perform a disk read for less than sectors-per-64k ;an005;bgb +;========================================================================= ;an005;bgb +procedure read_disk ;an005;bgb + savereg ;an005;bgb + call seg_adj ;an000;calc new seg:off ;an005;bgb + call calc_sp64k ;an000;secs/64k ;an005;bgb +; $DO ; do while more than 64k ;an005;bgb +$$DO1: + cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb +; $LEAVE LE ;an000;yes ;an005;bgb + JLE $$EN1 + mov sec_count,cx ;an000;save cx ;an005;bgb + mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb + call read_once ;an000;read it ;an005;bgb +; $LEAVE C ;an005;bgb + JC $$EN1 + mov cx,es ;an005;bgb + add cx,paras_per_64k ; adjust transfer area ;an005;bgb + mov es,cx ;an005;bgb + mov cx,sec_count ; restore sector count ;an005;bgb + sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb + add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb +; $ENDDO ;an005;bgb + JMP SHORT $$DO1 +$$EN1: + call read_once ;an000;read it ;an005;bgb + restorereg ;an005;bgb + ret ;an005;bgb +read_disk endp ;an005;bgb + ;an005;bgb + ;an005;bgb +;***************************************************************************** ;an005;bgb +;Routine name: Read_once ;an005;bgb +;***************************************************************************** ;an005;bgb +; ;an005;bgb +;description: Read in data using Generic IOCtl ;an005;bgb +; ;an005;bgb +;Called Procedures: None ;an005;bgb +; ;an005;bgb +; ;an005;bgb +;Change History: Created 5/13/87 MT ;an005;bgb +; ;an005;bgb +;Input: AL = Drive number (0=A) ;an005;bgb +; es:BX = Transfer address ;an005;bgb +; CX = Number of sectors ;an005;bgb +; Read_Write_Relative.Start_Sector_High = Number of sectors high ;an005;bgb +; DX = logical sector number low ;an005;bgb +; ;an005;bgb +;Output: CY if error ;an005;bgb +; AH = INT 25h error code ;an005;bgb +; ;an005;bgb +;Psuedocode ;an005;bgb +;---------- ;an005;bgb +; Save registers ;an005;bgb +; Setup structure for function call ;an005;bgb +; Read the disk (AX=440Dh, CL = 6Fh) ;an005;bgb +; Restore registers ;an005;bgb +; ret ;an005;bgb +;***************************************************************************** ;an005;bgb +Procedure Read_once ; ;an005;bgb + savereg ;Change it to Read relative sect;an005;bgb + mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;an005;bgb + mov bx,es ; ;AN005;bgb + mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;an005;bgb + mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to read ;an005;bgb + mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;an005;bgb + mov bx,offset Read_Write_Relative ; ;an005;bgb + mov cx,0FFFFh ;Read relative sector ;an005;bgb + INT 25h ;Do the read ;an005;bgb + pop dx ;Throw away flags on stack ;an005;bgb + restorereg ;an005;bgb + return ;an005;bgb + Read_once endp ;an005;bgb + ;an005;bgb + ;an005;bgb +;========================================================================= ;an005;bgb +; WRITE-DISK : This routine reads the logical sector count requested. ;an005;bgb +; It will read a maximum of 64k in one read. If more ;an005;bgb +; than 64k exists it will continue looping until ;an005;bgb +; all sectors have been read. ;an005;bgb +; ;an005;bgb +; Inputs : AL - Drive letter ;an005;bgb +; ES:BX - Segment:offset of transfer address ;an005;bgb +; CX - Sector count ;an005;bgb +; DX - 1st sector ;an005;bgb +; ;an005;bgb +; Outputs : Logical sectors read ;an005;bgb +; LOGIC ;an005;bgb +; ***** ;an005;bgb +; adjust es:bx to es:00 ;an005;bgb +; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?) +; DO while there are more sectors to read than sectors-per-64k ;an005;bgb +; set sector-count to sectors-per-64k ;an005;bgb +; perform the disk read ;an005;bgb +; bump the seg addr to the new addr ;an005;bgb +; dec the number of sectors to read by sectors-per-64k ;an005;bgb +; bump the starting sector number by the sectors-per-64k ;an005;bgb +; ENDDO ;an005;bgb +; perform a disk read for less than sectors-per-64k ;an005;bgb +;========================================================================= ;an005;bgb +procedure write_disk ;an005;bgb + savereg ;an013;bgb + call seg_adj ;an000;calc new seg:off ;an005;bgb +; $DO ; do while more than 64k ;an005;bgb +$$DO5: + cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb +; $LEAVE LE ;an000;yes ;an005;bgb + JLE $$EN5 + mov sec_count,cx ;an000;save cx ;an005;bgb + mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb + call write_once ;an000;read it ;an005;bgb +; $LEAVE C ;an005;bgb + JC $$EN5 + mov cx,es ;an005;bgb + add cx,paras_per_64k ; adjust transfer area ;an005;bgb + mov es,cx ;an005;bgb + mov cx,sec_count ; restore sector count ;an005;bgb + sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb + add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb +; $ENDDO ;an005;bgb + JMP SHORT $$DO5 +$$EN5: + call write_once ;an000;read it ;an005;bgb + restorereg ;an013;bgb + ret ;an005;bgb +write_disk endp ;an005;bgb + ;an005;bgb +;***************************************************************************** ;an005;bgb +;Routine name: Write_once ;an005;bgb +;***************************************************************************** ;an005;bgb +; ;an005;bgb +;description: Write Data using int 26 ;an005;bgb +; ;an005;bgb +;Called Procedures: None ;an005;bgb +; ;an005;bgb +; ;an005;bgb +;Change History: Created 5/13/87 MT ;an005;bgb +; ;an005;bgb +;Input: AL = Drive number (0=A) ;an005;bgb +; DS:BX = Transfer address ;an005;bgb +; CX = Number of sectors ;an005;bgb +; Read_Write_Relative.Start_Sector_High = already set up ;an048;bgb +; DX = logical sector number low ;an005;bgb +; ;an005;bgb +;Output: CY if error ;an005;bgb +; AH = INT 26h error code ;an005;bgb +; ;an005;bgb +;Psuedocode ;an005;bgb +;---------- ;an005;bgb +; Save registers ;an005;bgb +; Setup structure for function call ;an005;bgb +; Write to disk (AX=440Dh, CL = 4Fh) ;an005;bgb +; Restore registers ;an005;bgb +; ret ;an005;bgb +;***************************************************************************** ;an005;bgb +Procedure Write_once ; ;an005;bgb + savereg ;This is setup for INT 26h right;AN005;bgb + mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;AN005;bgb + mov bx,es ; ;AN005;bgb + mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;AN005;bgb + mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to write ;AN005;bgb + mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;AN005;bgb + mov cx,0FFFFh ;Write relative sector ;AN005;bgb + lea bx,read_write_relative ; ;an005;bgb + INT 026h ;Do the write ;AN005;bgb + pop dx ;flags is returned on the stack;AN005;bgb + restorereg ; ;AN005;bgb + ret ; ;AN005;bgb +Write_once endp ; ;AN005;bgb + ;an005;bgb +;========================================================================= ;an005;bgb +; SEG_ADJ : This routine adjusts the segment:offset to prevent ;an005;bgb +; address wrap. ;an005;bgb +; ;an005;bgb +; Inputs : bx - Offset to adjust segment with ;an005;bgb +; es - Segment to be adjusted ;an005;bgb +; ;an005;bgb +; Outputs : bx - New offset ;an005;bgb +; es - Adjusted segment ;an005;bgb +;========================================================================= ;an005;bgb +procedure seg_adj ;an005;bgb + savereg ;an005;bgb + mov ax,bx ;an000;get offset ;an005;bgb + mov bx,0010h ;divide by 16 ;an005;bgb + xor dx,dx ;an000;clear dx ;an005;bgb + div bx ;an000;get para count ;an022;bgb + mov bx,es ;an000;get seg ;an005;bgb + add bx,ax ;an000;adjust for paras ;an005;bgb + mov es,bx ;an000;save new seg ;an005;bgb + mov bx,dx ;an000;new offset ;an005;bgb + restorereg ;an005;bgb + ret ;an005;bgb +seg_adj endp ;an005;bgb + ;an005;bgb + ;an005;bgb +;========================================================================= ;an005;bgb +; CALC_SP64K : This routine calculates how many sectors, for this ;an005;bgb +; particular media, will fit into 64k. ;an005;bgb +; ;an005;bgb +; Inputs : DPB_SECTOR_SIZE - bytes/sector ;an005;bgb +; ;an005;bgb +; Outputs : SECS_PER_64K - Sectors / 64k ;an005;bgb +; PARAS_PER_64K - paragraphs per 64k ;an005;bgb +;========================================================================= ;an005;bgb +procedure calc_sp64k ;an005;bgb + savereg ;an005;bgb + mov ax,0ffffh ;an000;64k ;an005;bgb + mov bx,bytes_per_sector ;an000;get bytes/sector ;an005;bgb + xor dx,dx ;an000;clear dx ;an005;bgb + div bx ;an000;sector count ;an022;bgb;bgb + mov secs_per_64k,ax ;an000;save sector count ;an005;bgb + mov ax,bytes_per_sector ;an000;get bytes/sector ;an005;bgb + mov bx,010h ; divide by paras ;an005;bgb + xor dx,dx ;an000;clear dx ;an005;bgb + div bx ; paras per sector ;an022;bgb;bgb + mul secs_per_64k ; times sectors ;an005;bgb + mov paras_per_64k,ax ; = paras per 64k ;an005;bgb + restorereg ;an000;restore dx ;an005;bgb + ret ;an000; ;an005;bgb +calc_sp64k endp ;an000; ;an005;bgb + ;an005;bgb + ;an005;bgb + Break ;an005;bgb +;****************************************************************************** ;an005;bgb +; ReadFt - attempt to read in the fat. If there are errors, step to ;an005;bgb +; successive fats until no more. ;an005;bgb +; ;an005;bgb +; Inputs: none. ;an005;bgb +; Outputs: Fats are read until one succeeds. ;an005;bgb +; Carry set indicates no Fat could be read. ;an005;bgb +; Registers modified: all ;an005;bgb +; LOGIC ;an005;bgb +; ***** ;an005;bgb +; DO for each of the fats on the disk: ;an005;bgb +; read - all the sectors in the fat ;an005;bgb +; increase the starting sector by the number of sectors in each fat ;an005;bgb +; ;an005;bgb +; LARGE FAT SUPPORT - the big change here is in read disk. since the fat must ;an005;bgb +; be within the first 32M, then the starting sector number of 65535 is ok, ;an005;bgb +; as is a larger number of sectors to read/write. ;an005;bgb +;****************************************************************************** ;an005;bgb +Procedure ReadFt,NEAR ;an005;bgb + clc ;Clear CY so we will loop ;an005;bgb + mov Read_Write_Relative.Start_Sector_High,0 ; ;an005;bgb + call Read_Disk ; Read_Disk (); ;AC0;an005;bgb +; $IF C + JNC $$IF9 + add dx,cx ; fatstart += fatsize ;an005;bgb + call Read_Disk ; Read_Disk (); ;AC0;an005;bgb +; $ENDIF +$$IF9: +bad_read: ret ;an005;bgb +EndProc ReadFt ;an005;bgb + + + pathlabl chkdisk +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKDISP.ASM b/v4.0/src/CMD/CHKDSK/CHKDISP.ASM new file mode 100644 index 0000000..e4d6ebc --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDISP.ASM @@ -0,0 +1,139 @@ +page ,132 ; ;an000;bgb +;***************************************************************************** ;an000;bgb +;***************************************************************************** ;an000;bgb +;UTILITY NAME: FORMAT.COM ;an000;bgb +; ;an000;bgb +;MODULE NAME: DISPLAY.ASM ;an000;bgb +; ;an000;bgb +; ;an000;bgb +; Designed: Mark T. ;an000;bgb +; ;an000;bgb +; Change List: AN000 - New code DOS 3.3 spec additions ;an000;bgb +; AC000 - Changed code DOS 3.3 spec additions ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb + EXTRN command_line_buffer:byte ;an000;bgb;an005;bgb +;***************************************************************************** ;an000;bgb +; Include Files ;an000;bgb +;***************************************************************************** ;an000;bgb +.xlist ;an000;bgb +include pathmac.inc ;an040;bgb +include chkseg.inc ;an000;bgb +INCLUDE CPMFCB.INC ;an000;bgb +INCLUDE CHKEQU.INC ;an000;bgb +.list ;an000;bgb +INCLUDE CHKMSG.INC ;an000;bgb +.xlist ;an000;bgb +INCLUDE SYSMSG.INC ;an000;bgb +.list ;an000;bgb + ; ;an000;bgb +cstack segment para stack 'STACK' ;an000;bgb + db 62 dup ("-Stack!-") ; (362-80h) is the additional IBM ROM ;an000;bgb +cstack ends ;an000;bgb + ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +; Message Services ;an000;bgb +;***************************************************************************** ;an000;bgb +MSG_UTILNAME ;an000;bgb + ;an000;bgb +;.xlist ;an000;bgb +data segment public para 'DATA' ;an000;bgb +Msg_Services ;an000;bgb +data ends ;an000;bgb + ;an000;bgb +code segment public para 'CODE' ;an000;bgb +pathlabl msgret ;an040;bgb +Msg_Services ;an000;bgb +Msg_Services ;an000;bgb +Msg_Services ;an000;bgb +pathlabl msgret ;an040;bgb +Msg_Services ;an037;bgb +code ends ;an000;bgb +.list ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Public Declarations ;an000;bgb +;***************************************************************************** ;an000;bgb + Public SysLoadMsg ;an000;bgb + Public SysDispMsg ;an000;bgb + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;*************************************************************************** ;an000;bgb +; Message Structures ;an000;bgb +;*************************************************************************** ;an000;bgb +Message_Table struc ; ;an000;bgb;AN000; +Entry1 dw 0 ; ;an000;bgb;AN000; +Entry2 dw 0 ; ;an000;bgb;AN000; +Entry3 dw 0 ; ;an000;bgb;AN000; +Entry4 dw 0 ; ;an000;bgb;AN000; +Entry5 db 0 ; ;an000;bgb;AN000; +Entry6 db 0 ; ;an000;bgb;AN000; +Entry7 dw 0 ; ;an000;bgb;AN000; +Message_Table ends ; ;an000;bgb;AN000; + ;an000;bgb +code segment public para 'CODE' ; ;an000;bgb;AN000; +;***************************************************************************** ;an000;bgb +;Routine name&gml Display_Interface ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;DescriptioN&gml Save all registers, set up registers required for SysDispMsg ;an000;bgb +; routine. This information is contained in a message description ;an000;bgb +; table pointed to by the DX register. Call SysDispMsg, then ;an000;bgb +; restore registers. This routine assumes that the only time an ;an000;bgb +; error will be returned is if an extended error message was ;an000;bgb +; requested, so it will ignore error returns ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; ;an000;bgb +;Change History&gml Created 4/22/87 MT ;an000;bgb +; ;an000;bgb +;Input&gml ES&gmlDX = pointer to message description ;an000;bgb +; ;an000;bgb +;Output&gml None ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Save all registers ;an000;bgb +; Setup registers for SysDispMsg from Message Description Tables ;an000;bgb +; CALL SysDispMsg ;an000;bgb +; Restore registers ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Public Display_Interface ;an000;bgb +Display_Interface proc ; ;an000;bgb;AN000; + push ds ;an000;bgb + push ax ;an000;bgb + push bx ;an000;bgb + push cx ;an000;bgb + push dx ;an000;bgb + push si ;an000;bgb + push di ;an000;bgb + mov di,dx ;Change pointer to table ;an000;bgb;AN000; + mov dx,dg ;Point to group ;an000;bgb + mov ds,dx ; ;an000;bgb + mov ax,[di].Entry1 ;Message number ;an000;bgb;AN000; + mov bx,[di].Entry2 ;Handle ;an000;bgb;AN000; + mov si,[di].Entry3 ;Sublist ;an000;bgb;AN000; + mov cx,[di].Entry4 ;Count ;an000;bgb;AN000; + mov dh,[di].Entry5 ;Class ;an000;bgb;AN000; + mov dl,[di].Entry6 ;Function ;an000;bgb;AN000; + mov di,[di].Entry7 ;Input ;an000;bgb;AN000; + call SysDispMsg ;Display the message ;an000;bgb;AN000; + pop di ;an000;bgb + pop si ;an000;bgb + pop dx ;an000;bgb + pop cx ;an000;bgb + pop bx ;an000;bgb + pop ax ;an000;bgb + pop ds ;an000;bgb + ret ;All done ;an000;bgb;AN000; +Display_Interface endp ; ;an000;bgb;AN000; + ;an000;bgb +include msgdcl.inc + +code ends ;an000;bgb + end ;an000;bgb diff --git a/v4.0/src/CMD/CHKDSK/CHKDSK.FLS b/v4.0/src/CMD/CHKDSK/CHKDSK.FLS new file mode 100644 index 0000000..43e0841 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDSK.FLS @@ -0,0 +1,7 @@ +CHKDSK1.ASM +CHKMES.ASM +CHKPRMT.ASM +CHKPROC.ASM +CHKPROC2.ASM +CHKDSK2.ASM + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKDSK.LNK b/v4.0/src/CMD/CHKDSK/CHKDSK.LNK new file mode 100644 index 0000000..25d94f5 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDSK.LNK @@ -0,0 +1,12 @@ +chkdisk+ +chkdisp+ +CHKDSK1+ +CHKDSK2+ +chkfat+ +CHKINIT+ +CHKPRMT+ +CHKPROC2+ +CHKPROC +CHKDSK.EXE,CHKDSK.MAP ; +;chkexec+ ;an038;bgb + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKDSK.SKL b/v4.0/src/CMD/CHKDSK/CHKDSK.SKL new file mode 100644 index 0000000..cf2f149 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDSK.SKL @@ -0,0 +1,82 @@ +:util CHKDSK ;an000;bgb + ;an000;bgb +:class A ;an000;bgb +:use COMMON1 ;Incorrect DOS version ;an000;bgb +:use COMMON2 ;stackmes ;an000;bgb +:def 3 "Convert lost chains to files (Y/N)?" ;freemes ;an000;bgb +:def 4 "Unrecoverable error in directory" ;ptrandir ;an000;bgb +:def 5 "Convert directory to file (Y/N)?" ;ptrandir2 ;an000;bgb +:def 7 "%1 bytes total disk space" ;dskspc ;an000;bgb +:def 8 "%1 bytes in bad sectors" ;badspc ;an000;bgb +:def 9 "%1 bytes in %2 hidden files" ;hidmes ;an000;bgb +:def 10 "%1 bytes in %2 directories" ;dirmes ;an000;bgb +:def 11 "%1 bytes in %2 user files" ;filemes ;an000;bgb +:def 12 "%1 bytes in %2 recovered files" ;orphmes2 ;an000;bgb +:def 13 "%1 bytes would be in %2 recovered files" ;orphmes3 ;an000;bgb +:def 14 "%1 bytes available on disk" ;frespc ;an000;bgb +:def 15 "%1 total bytes memory" ;totmem ;an000;bgb +:def 16 "%1 bytes free" ;fremem ;an000;bgb +:def 17 "Cannot CHKDSK a network drive" ;no_net_arg ;an000;bgb +:def 18 "Cannot CHKDSK a SUBSTed or ASSIGNed drive" ;SubStErr ;an000;bgb +:def 19 "Probable non-DOS disk",CR,LF,"Continue (Y/N)?" ;badidbyt ;an018;bgb ;an000;bgb +:def 20 "Disk error reading FAT %1",CR,LF ;badr ;an000;bgb + ;an000;bgb +:class B ;an000;bgb +:def 21 "Directory %1" ;direc_arg ;an000;bgb +:def 22 "%1 Contains %2 non-contiguous blocks" ;extent_arg ;an000;bgb +:def 23 "All specified file(s) are contiguous" ;noext_arg ;an000;bgb +:def 24 "Errors found, F parameter not specified",CR,LF,"Corrections will not be written to disk" ;fixmes_arg;an000;bgb +:def 25 " Processing cannot continue %1%2" ;fatal_arg ;an000;bgb +:def 26 " File allocation table bad, drive %1" ;badrdmes ;an000;bgb +:use COMMON2 ;stackmes ;an000;bgb +:def 29 " CHDIR .. failed, trying alternate method" ;cdddmes ;an000;bgb +:def 30 " Has invalid cluster, file truncated" ;badchain ;an000;bgb +:def 31 " Invalid sub-directory entry" ;badsubdir ;an000;bgb +:def 32 " Does not exist" ;ndotmes ;an000;bgb +:def 33 " First cluster number is invalid, entry truncated" ;nulnz ;an000;bgb +:def 34 " Allocation error, size adjusted" ;badclus ;an000;bgb +:def 35 " Cannot recover .. entry, processing continued" ;norecdot ;an000;bgb +:def 36 " Directory is totally empty, no . or .." ;nuldmes ;an000;bgb +:def 37 " Directory is joined" ;joinmes ;an000;bgb +:def 38 " Cannot recover .. entry" ;norecddot ;an000;bgb +:def 39 " Entry has a bad link" ;norecddot1 ;an000;bgb +:def 40 " Entry has a bad attribute" ;norecddot2 ;an000;bgb + ;an000;bgb +:class C ;an000;bgb +:def 41 " Entry has a bad size" ;norecddot3 ;an000;bgb +:def 42 " Is cross linked on cluster %1" ;cross_arg ;an000;bgb +:def 43 " Cannot CHDIR to %1,",CR,LF,"tree past this point not processed" ;badtarg_ptr;an000;bgb +:def 44 " tree past this point not processed" ;badtarg2 ;an000;bgb +:def 45 "%1 bytes disk space freed" ;freebymes1 ;an000;bgb +:def 46 "%1 bytes disk space would be freed" ;freebymes2 ;an000;bgb +:def 47 "Volume %1 created %2 %3",CR,LF ;idmes_arg ;an000;bgb +:def 48 "%1 total allocation units on disk" ;idmes1 ;an000;bgb +:def 49 "%1 bytes in each allocation unit" ;idmes2 ;an000;bgb +;:def 50 "CHKDSK not available on drive %1" ;msgExecFailure ;an000;bgb +:def 51 " Extended Attributes has invalid clusters, attributes truncated" ;Inv_XA_Msg;an000;bgb +:def 52 " Extended Attributes allocation error , attributes truncated" ;Alloc_XA_Msg;an000;bgb +:def 53 "Invalid parameter" ;badsw_arg ;an000;bgb +:use 54 extend15 ;baddrv_arg "invalid drive spec" ;an017;bgb +:use 55 extend3 ;invpath_arg "path not found" ;an017;bgb +:use 56 extend2 ;opnerr_arg "file not found" ;an017;bgb +:def 58 " %1 lost clusters found in %2 chains." ;orph_arg ;an000;bgb +:def 59 CR,LF ;crlf_arg ;an000;bgb +:def 60 " Cannot CHDIR to root",CR,LF ;badcd_arg ;an000;bgb + ;an000;bgb +:class D ;an000;bgb +:def 61 " Disk error writing FAT %1" ;badw_arg ;an000;bgb +:def 62 " %1" ;noisy_arg ;an000;bgb +:def 63 "Invalid current directory" ;baddpbdir ;an000;bgb +:def 64 "%1",CR,LF ;file_arg ;an000;bgb +:def 65 " Insufficient room in root directory",CR,LF," Move files from root directory and repeat CHKDSK" ;creatmes;an000;bgb +:def 66 "%1 %2 %3" ;eup_arg ;an000;bgb +:def 67 "%1 %2, %3" ;usp_arg ;an000;bgb +:def 68 "%1%2%3%4%5" ;oth_arg ;an000;bgb +:def 69 "%1%2%3%4" ;time_arg ;an000;bgb +:def 70 "%1 available allocation units on disk" ;idmes2 ;an017;bgb +:use 71 COMMON36 ;Volume Serial Number is %1-%2 ;an024;bgb +:use 72 extend8 ;insufficent memory ;an030;bgb +:use 73 extend26 ;invalid media type ;an033;bgb +:use 74 extend29 ;write fault error ;an033;bgb + +:end diff --git a/v4.0/src/CMD/CHKDSK/CHKDSK1.ASM b/v4.0/src/CMD/CHKDSK/CHKDSK1.ASM new file mode 100644 index 0000000..6d85d42 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDSK1.ASM @@ -0,0 +1,682 @@ + TITLE CHKDSK - MS-DOS Disk consistancy checker ; +page ,132 ; + + .xlist + include chkseg.inc ;an005;bgb + INCLUDE CHKCHNG.INC + INCLUDE DOSSYM.INC + INCLUDE syscall.inc ;an041;bgb + INCLUDE ioctl.inc ;an041;bgb;an041;bgb + INCLUDE CHKEQU.INC + INCLUDE CHKMACRO.INC + include chkdata.inc ;an005;bgb + include pathmac.inc + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:NOTHING,ES:DG,SS:dg + EXTRN INT_23:NEAR, readft:near ;an005;bgb + EXTRN FATAL:NEAR, PROMPTYN:NEAR, GET_CURRDIR:NEAR + extrn calc_fatmap_seg:near, FINDCHAIN:NEAR, CHECKERR:NEAR, DIRPROC:NEAR + extrn CHKMAP:NEAR, Main_Init:Near ;an049;bgb + EXTRN CHKCROSS:NEAR, AMDONE:NEAR, UNPACK:NEAR, GET_THISEL2:NEAR + EXTRN PRINTF_CRLF:NEAR, DOCRLF:NEAR, REPORT:NEAR + extrn init_fatmap:near, CHKPRMT_END:near ;an005;bgb + extrn hook_interrupts:near + extrn CHECK_DBCS_CHARACTER:NEAR ;an055;bgb + +public SETSTACK, OkDrive, DRVISOK, Root_CD_Ok, NOTVOLID, fat16b, SMALLFAT +public BAD_STACK, RDLOOP, NORETRY1, RDOK, IDOK, ALLDONE, CHECKFILES, GotPath +public IS_ROOT_DIR, NOT_ROOT_DIR, VALID_PATH, ParseName, ScanFile, FRAGCHK +public EACHCLUS, LASTCLUS, NXTCHK, GETNXT, MSGCHK, FILSPOK, CDONE, CDONE1 +public PRINTID, FIGREC, Main_Routine, checkit + .list + + + pathlabl chkdsk1 +CHKDSK: +; find out if we have enough memory to do the job + mov cs:save_drive,al ;save drive validity +;;;;int 12h ;1k blocks (640k = 280h) ;an054;bgb;an050;bgb +;;;;mov bx,64 ;number of paragraphs ;an054;bgb;an050;bgb +;;;;mul bx ;640k = a000 ;an054;bgb;an050;bgb +;;;;mov cs:[mem_size],ax ;returns number of 1k blocks ;an054;bgb;an050;bgb + DOS_Call GetCurrentPSP ;Get PSP segment address ;Ac034;bgb + mov cs:psp_segment,bx ;ac034;bgb + mov ds,bx ;ds points to the psp ;Ac034;bgb + Assume DS:Nothing + MOV DX,DS:[2] ;High break + mov cs:[mem_size],dx ;move it into data area ;an054;bgb + MOV BX,0FFFFH ;need at least 64k bytes + MOV CX,CS ;get segment of where we are + SUB DX,CX ;top-of-mem - pgm = # para left in alloc block + CMP DX,0FFFH ; is the space available > 64K ? +; $IF B + JNB $$IF1 + MOV CX,4 ; Yes, set SP to BX (FFF0) + SHL DX,CL ; Convert remaining memory to bytes + MOV BX,DX +; $ENDIF +$$IF1: +SETSTACK: ;***Set_Memory********* + CLI + PUSH CS + POP SS +ASSUME SS:DG + MOV SP,BX + STI + PUSH AX + JMP Main_Init ;Go to init routines + + +;************************************************************************** +; MAIN-ROUTINE +; +; called by - main-init +; +; LOGIC +; ***** +; - get the dpb addr +; - set the default drive to here +; - save the directory we are on +; - set the directory to the root of the drive +; - print the volume name +; - get the dpb info +; - get the addr of the fatmap area +; - calculate the amount of stack space we have +;************************************************************************** +Main_Routine: + set_data_segment +OkDrive: +;get the dpb addr from this drive + mov dl,AllDrv ;Get drive number ;AN000; + DOS_Call Get_DPB ;func 32 ;Get DPB pointer ;AC000; + ASSUME DS:NOTHING,cs:DG + CMP AL,-1 ;is this a good drive? +; $IF Z + JNZ $$IF3 +;;;;;;;;JNZ DRVISOK ;Bad drive (should always be ok) + LEA DX,BADDRV_arg ;This should never happen ;AC000; + push cs + pop ds + call PRINTf_crlf ; ;AC000; + mov ExitStatus,Bad_Exit ;Get return code ;AC000; + ret ;Go back to Main_Init ;AC000; +; $ENDIF +$$IF3: + MOV WORD PTR CS:[THISDPB+2],DS ;get the dpb segment + set_data_segment ;reset ds to the pgm + MOV WORD PTR [THISDPB],BX ;get the dpb offset + +;**Set_Drive_Info************************************************************* +DRVISOK: + push dx + push es + call hook_interrupts + pop es + pop dx +; make this drive the default drive + DEC DL ;A=0 b=1 c=2 + DOS_Call Set_Default_Drive ;func 0e - no return ;AC000; + +;get the name of the current directory + INC DL ;drive number a=1 b=2 c=3 + LEA SI,USERDIR+1 ; ;AC000; + DOS_Call Current_Dir ; ;AC000; +;;;;PUSH CS +;;;;POP ES + +;change the current directory to the root + lea DX,rootstr ; ;an005;bgb + DOS_Call ChDir ; ;AC000; +; $IF C ;will this ever happen? + JNC $$IF5 +;;;;;;;;jnc Root_CD_Ok ; ;AN000; + MOV DX,OFFSET DG:BADCD_arg + call display_interface ; ;AC000; + mov ExitStatus,Bad_Exit ;Get return code ;AC000; + ret ;Go back to Main_Init ;AC000; +; $ENDIF +$$IF5: + +;get the dpb info + LDS BX,[THISDPB] ;ds:bx--> dpb area + ASSUME DS:NOTHING + MOV AX,[BX.dpb_sector_size] ;Bytes/sector + MOV [SSIZE],AX ;Sector size in bytes + MOV AL,[BX.dpb_cluster_mask] + INC AL + MOV [CSIZE],AL ;Sectors per cluster + MOV AX,[BX.dpb_max_cluster] ; number of clusters in the disk + MOV [MCLUS],AX ;Bound for FAT searching + DEC AX ;ax= max clusters - 1 ;an005;bgb + MOV [DSIZE],AX ;Total data clusters on disk ;an005;bgb + CMP AX,4096-8 ;Big or little FAT? +; $IF NB + JB $$IF7 +fat16b: INC es:[BIGFAT] ;set 16-bit fat flag to true + MOV es:[EOFVAL],0FFF8H ;set 16-bit compare fields for fat + MOV es:[CHAIN_END],0FFFFh ;Marker for end of chain ;AC000; + MOV es:[BADVAL],0FFF7H ;set 16-bit compare fields for fat +; $ENDIF +$$IF7: + mov ax,[bx.dpb_FAT_size] ;Sectors for one fat (DCR) ;an005;bgb + mov fatsiz,ax ;Sectors for one fat (DCR) ;an005;bgb + MOV CL,[BX.dpb_FAT_count] ;Number of FATs ;an005;bgb + mov fatcnt,cl ;an005;bgb + MOV DX,[BX.dpb_first_FAT] ;First sector of FAT ;an005;bgb + MOV firstfat,dx ;First sector of FAT ;an005;bgb + MOV DX,[BX.dpb_first_sector] ;First sector of data ;ac048;bgb + MOV firstsec,dx ;First sector of data ;ac048;bgb + MOV DX,[BX.dpb_dir_sector] ;First sector of dir ;ac048;bgb + MOV dirsec,dx ;First sector of dir ;ac048;bgb + MOV DX,[BX.dpb_root_entries] ;First sector of dir ;ac048;bgb + MOV root_entries,dx ;First sector of dir ;ac048;bgb + set_data_segment ;reset ds to point to data area + +;calc fatmap area +SMALLFAT: ;do this for both size fats + ;old calculation + ;;;;DEC AX ;ax= max clusters - 1 ;an005;bgb + ;;;;MOV [DSIZE],AX ;Total data clusters on disk ;an005;bgb + ;;;;MOV AX,[BX.dpb_FAT_size] ;Sectors for one fat (DCR) ;an005;bgb + ;;;;MOV CX,AX ;CX = Sectors/Fat ;an005;bgb + ;;;;MUL [SSIZE] ;times bytes/sector = bytes per fat ;an005;bgb + ;;;;ADD fatmap,AX ;Allocate FAT space ;an005;bgb + ;;;;MOV AX,fatmap ; get seg of fatmap ;an005;bgb + +Root_CD_Ok: ; ;AN000; +;set dta area----do i need to do this since we are using int 25? +;set it to fat table + call calc_fatmap_seg ;find the addr of where to put the fat map ;an005;bgb +;see if we still have enough memory + mov ax,mem_size ;get top of memory + cmp ax,end_of_fatmap ;mem_size must be greater or equal +; $IF B ; if not, display error msg + JNB $$IF9 + MOV DX,OFFSET DG:no_mem_arg + invoke printf_crlf + jmp alldone ;finished with pgm +; $ENDIF +$$IF9: + push ds ;save ds + mov ds,fattbl_seg ;get seg + xor dx,dx ;ds:dx--> dta area +;;;;mov fatmap,dx + DOS_Call Set_DMA ;function 1a ;AC000; + pop ds ;restore ds + +;look for volume entry in dir + lea DX,volid ;Look for VOL ID ;an005;bgb + DOS_Call Dir_Search_First ;function 11 ;AC000; + CMP AL,0 ;did we find it? +; $IF Z ;yes + JNZ $$IF11 +;;;;;;;;JZ NOTVOLID + CALL PRINTID ;print volume name, date, time +; $ENDIF +$$IF11: +NOTVOLID: + call get_serial_num ;print volume serial number ;an024;bgb +;;;;call hook_interrupts +; calculate the place where we run out of ram space ;an005;bgb +;;;;ADD AX,[MCLUS] ;5000 ;fatmap seg + num of clusters? ;an005;bgb +;;;;ADD AX,2 ;5002 ;Insurance ;an005;bgb +;;;;MOV [SECBUF],AX ;Allocate fatmap space ;an005;bgb + mov ax, offset dg:chkprmt_end ;this label must be the last thing in the code segment + mov [secbuf],AX ;location of read/write buffer for dir entries ;an005;bgb +;;;;ADD AX,[SSIZE] ;5202 ;an005;bgb +;;;;ADD AX,20 ;5216 ;Insurance ;an005;bgb + mov ax,0ffffh ;get end of segment + lea bx,fattbl ;get end of program + sub ax,bx ;this is the amount of stack space we have + MOV [STACKLIM],AX ;Limit on recursion ;an005;bgb +; see if we have already overrun the stack + MOV DI,SP ;where is the stack pointer now? ;an005;bgb + SUB DI,100H ; Want AT LEAST this much stack from ;an005;bgb + ; our current location ;an005;bgb + CMP DI,AX +; $IF B + JNB $$IF13 +;;;;;;;;JB BAD_STACK ; Already in trouble +BAD_STACK: + MOV BX,OFFSET DG:STACKMES ;Out of stack + PUSH CS + POP DS + JMP FATAL +; $ENDIF +$$IF13: + +; +;**Read in FAT***************************************************************** +;;;;MOV DI,fatsiz ;sectors per fat ;an005;bgb +;;;;MOV CL,[BX.dpb_FAT_count] ;Number of FATs +;;;;MOV DX,[BX.dpb_first_FAT] ;First sector of FAT + mov cx,fatsiz ;number of sectors to read ;an005;bgb + mov dx,firstfat ;starting sector number ;an005;bgb + mov es,fattbl_seg ;set up bx for read-disk ;an005;bgb + xor bx,bx ;an005;bgb + MOV AL,[ALLDRV] ;set up al with drive letter for read-disk + DEC AL ;zero based +;;;;MOV AH,1 +RDLOOP: +;;;;XCHG CX,DI ;DI has # of Fats + call readft ; readft (); ;AN005;bgb +; $IF C ; could the fat be read from disk? ;AN005;bgb + JNC $$IF15 + inc byte ptr [nul_arg] ;an005;bgb +;;;;;;;;mov [fatal_arg2],offset dg:baddrvm ;an005;bgb + mov [fatmsg2],offset dg:baddrvm ;an005;bgb + lea BX,badread ;an022;bgb + JMP FATAL ;Couldn't read any FAT, BARF ;an005;bgb +; $ENDIF ;fat could be read from disk ;AN005;bgb +$$IF15: + +; savereg ;an005;bgb +; mov Read_Write_Relative.Start_Sector_High,0 ; ;AN000; +; call Read_Disk ;Read in the FAT ;AC000; +; $IF C +;;;;;;;;JNC RDOK +;;;;;;;;mov [badrw_str],offset dg:reading +; POP AX ; Get fat# in ah +; PUSH AX ; Back on stack +; xchg al,ah ; Fat # to AL +; xor ah,ah ; Make it a word +; mov [badrw_num],ax +; mov dx,offset dg:badr_arg +; invoke printf_crlf +; restorereg ;an005;bgb +; INC AH +; ADD DX,DI +; LOOP RDLOOP ;Try next FAT +;;;;;;;;JMP NORETRY1 ;Couldn't read either ;AC000; +NORETRY1: +; inc byte ptr [nul_arg] +; mov [fatal_arg2],offset dg:baddrvm +; MOV BX,OFFSET DG:BADRDMES +; JMP FATAL ;Couldn't read any FAT, BARF +; $ENDIF +RDOK: ;**Check_for_FAT_ID********************************************** +;;;;restorereg ;Clean up ;an005;bgb + mov es,fattbl_seg ;segment of fat-table ;an005;bgb + xor si,si ;offset of first byte in fat-table ;an005;bgb +;;;;LODSB ;Check FAT ID byte + mov al,byte ptr es:[si] ;get first byte of fat table + CMP AL,0F8H ;is it the correct id byte? +; $IF B,AND + JNB $$IF17 +;;;;;;;;JAE IDOK + CMP AL,0F0H ;if not, Is it a "strange" medium? +; $IF NZ + JZ $$IF17 +;;;;;;;;jz IDOK ;neither fat nor strange + MOV DX,OFFSET DG:BADIDBYT ;FAT ID bad + CALL PROMPTYN ;Ask user to stop or not +; $IF NZ + JZ $$IF18 +;;;;;;;;;;;;JZ IDOK + JMP ALLDONE ;User said stop +; $ENDIF +$$IF18: +; $ENDIF +$$IF17: + +;initialize the fatmap area to all zeros +IDOK: + call init_fatmap + +;set the dta addr to here for all searches + MOV DX,OFFSET DG:DIRBUF ;FOR ALL SEARCHING + DOS_Call Set_DMA ; ;AC000; + XOR AX,AX ;zero out ax + PUSH AX ;I am root + PUSH AX ;Parent is root +; + set_data_segment +checkit: + CALL DIRPROC + CALL CHKMAP ;Look for badsectors, orphans + CALL CHKCROSS ;Check for second pass + INVOKE DOCRLF ;display new line + CALL REPORT ;finished, display data to screen + +;***************************************************************************** +ALLDONE: + CALL AMDONE +;;;;;MOV AH,EXIT +;;;;;;;;XOR AL,AL +;;;;;; ;mov ExitStatus,Bad_Exit ;Get return code ;AC000; +;;;;;;;;INT 21H + ret ;Ret to Main_Init for common exit ;AN000; + +ASSUME DS:DG +;**Extent_Check*************************************************************** +Break +; +; Search the directory for the files specified on the command line and report +; the number of fragmented allocation units found in each one. We examine the +; given path name for a directory. If it is found, we CHDIR to it. In any +; event, we move to the file name part and do a parseFCB call to convert it +; into an FCB for a dir_search_first. If the parse did NOT advance the +; pointer to the null byte terminating the string, then we have a bogus anme +; and we should report it. +; + +CHECKFILES: + set_data_segment +; see if there is a '\' in the path name + MOV DI,OFFSET DG:PATH_NAME + MOV SI,DI + MOV CX, FNAME_LEN ; ;an011;bgb + ADD DI,CX ; ES:DI points to char AFTER last char + DEC DI ; Point to last char +doagain: MOV AL,[DIRCHAR] ;try to find '\' in path name + STD + REPNE SCASB + CLD +; $IF Z ;a '\' was found in path ;an055;bgb + JNZ $$IF21 + mov al,[di] ;get byte preceding '\' ;an055;bgb + call check_dbcs_character ;see if dbcs leading char ;an055;bgb +; $IF C ;carry means dbcs leading char ;an055;bgb + JNC $$IF22 + jmp doagain ;so ignore ;an055;bgb +; $ELSE ;an055;bgb + JMP SHORT $$EN22 +$$IF22: + jmp GotPath ;found a '\' and not dbcs ;an055;bgb +; $ENDIF ;an055;bgb +$$EN22: +; $ENDIF ;an055;bgb +$$IF21: +;;;;;;;;;;;;;;;;;;;;;JZ GotPath ; found path char. ;an055;bgb +; No '\' was found. set up pointers for parse FCB call. + MOV DI,OFFSET DG:PATH_NAME + CMP BYTE PTR [DI+1],':' ;was a drive letter entered? + JNZ ParseName + ADD DI,2 + JMP SHORT ParseName + +;***************************************************************************** +; found a '\' in the path name +;Change directories and set up the appropriate FCB +GotPath: + INC DI ; DI points AT the path sep + PUSH WORD PTR [DI] ; Save two chars here + PUSH DI ; Save location + SUB SI,DI + JZ IS_ROOT_DIR ; SI=DI=First char which is a dirchar + NEG SI + CMP SI,2 + JNZ NOT_ROOT_DIR + CMP BYTE PTR [DI-1],':' ; d:\ root spec? + JNZ NOT_ROOT_DIR ; Nope +IS_ROOT_DIR: + INC DI ; Don't zap the path sep, zap NEXT char +NOT_ROOT_DIR: + MOV BYTE PTR [DI],0 + MOV DX,OFFSET DG:PATH_NAME + DOS_Call Chdir ; ;AC000; + POP DI ; Recall loc + POP WORD PTR [DI] ; recall chars + JNC VALID_PATH + INVOKE DOCRLF + MOV DX,OFFSET DG:INVPATH_arg + invoke printf_crlf + JMP CDONE1 + +;***************************************************************************** +VALID_PATH: + INC [DIR_FIX] + INC DI ; Point past path sep to first char of name +ParseName: +; parse the filename and get back a formatted fcb for it in es:di + MOV SI,DI ; DS:SI points to name + MOV DI,offset dg:FCB_copy ; ES:DI points to FCB + MOV AL,ALLDRV ; drive number + STOSB ; put it into fcb + DEC DI ; Back to start of FCB + MOV pFileName,SI ; save end of file name + MOV AL,00000010B ; tell parse to change drive letter if needed + DOS_Call Parse_File_Descriptor ; ;AC000; + CMP BYTE PTR [SI],0 ;ds:si should point past filename + JZ ScanFile +; +; Twiddle the file name to be truly bogus. Zorch the drive letter +; + MOV BYTE PTR es:[DI],-1 +ScanFile: + INVOKE DOCRLF +;set dma pointer to here + MOV DX,OFFSET DG:DIRBUF ;FOR ALL SEARCHING + MOV BP,DX + ADD BP,27 ;bp points to clus in the dir entry + DOS_Call Set_DMA ;set dma ptr here for dir search ;AC000; +;try to find the file specified + MOV AH,DIR_SEARCH_FIRST ;Look for the first file +FRAGCHK: + MOV DX,offset dg:FCB_copy + INT 21H + OR AL,AL ;Did we find it? + JNZ MSGCHK ;No -- we're done +; we found the file +; look for fragmentation + XOR AX,AX ;Initialize the fragment counter + MOV SI,[BP] ;Get the first cluster ;an005;bgb + CALL UNPACK ;see what that cluster points to + CMP DI,[EOFVAL] ;End-of-file? + JAE NXTCHK ;Yes -- go report the results + INC SI + CMP SI,DI + JZ EACHCLUS + INC AX +EACHCLUS: + MOV [OLDCLUS],DI ;Save the last cluster found + MOV SI,DI ;Get the next cluster + CALL UNPACK + INC [OLDCLUS] ;Bump the old cluster + CMP DI,[OLDCLUS] ;Are they the same? + JNZ LASTCLUS ;No -- check for end-of-file + JMP SHORT EACHCLUS ;Continue processing +LASTCLUS: + CMP DI,[EOFVAL] ;End-of-file? + JAE NXTCHK ;Yes -- go report the results + INC AX ;No -- found a fragement + JMP SHORT EACHCLUS ;Continue processing +NXTCHK: ;reached the end of a file + OR AX,AX ;did we find any fragmentation? + JZ GETNXT +;we found fragmentation + MOV [FRAGMENT],2 ;Signal that we output at least one file + inc ax ;bump by one for ends + mov [block_num],ax + mov word ptr rarg1,ax ; ;an011;bgb + mov word ptr rarg1+2,0 + mov si,offset dg:dirbuf ;point to filename ;an011;bgb + INC SI ;move pointer past drive letter +; get the full path name for this file + CALL get_THISEL2 +; print it out + mov dx,offset dg:extent_arg + invoke printf_crlf +GETNXT: + MOV AH,DIR_SEARCH_NEXT ;Look for the next file + JMP FRAGCHK +MSGCHK: + CMP AH,DIR_SEARCH_FIRST ;was this the first file searched for? + JNZ FILSPOK +; MOV SI,offset dg:FCB_copy + 1 ;File not found error +; CALL get_THISEL2 + MOV SI,pFileName + CALL get_currdir + mov dx,offset dg:OPNERR_arg + invoke printf_crlf ;bad file spec + jmp short cdone +FILSPOK: + CMP BYTE PTR [FRAGMENT],2 + JZ CDONE +; all files were ok + mov dx,offset dg:NOEXT_arg + invoke printf_crlf +CDONE: + CMP BYTE PTR [DIR_FIX],0 + JZ CDONE1 + MOV DX,OFFSET DG:USERDIR + DOS_Call ChDir ; ;AC000; +CDONE1: + RET + + + +; This is the old parameter passing scheme ;ac048;bgb +; inputs: AH - the sector number within the cluster ;ac048;bgb +; BX - cluster number ;ac048;bgb +; output: DX - absolute sector number ;ac048;bgb +;***************************************************************************** ;ac048;bgb +; FIGREC - This procedure calculates the absolute sector number of a logical ;ac048;bgb +; drive, given any cluster number and the sector within that cluster. ;ac048;bgb +; You can use this to find the sector number for a file. ;ac048;bgb +; ;ac048;bgb +; This procedure was entirely re-written for dos 4.0, since the ;ac048;bgb +; sector number can now be a DOUBLE word value. ;ac048;bgb +; ;ac048;bgb +; called by: getent in chkproc ;ac048;bgb +; ;ac048;bgb +; inputs: BX - cluster number ;ac048;bgb +; AH - sector number within cluster ;ac048;bgb +; csize - sectors per cluster (from dpb) ;ac048;bgb +; firstsec - starting sector number of the data area (from dpb) ;ac048;bgb +; ;ac048;bgb +;outputs: DX - absolute sector number (low order) ;ac048;bgb +; INT26.start_sector_high (hi order) ;ac048;bgb +; ;ac048;bgb +;regs changed: DX only ;ac048;bgb +; ;ac048;bgb +;formula: cluster (3-fff7) * secs/cluster (1-8) = (3-7ffb8) ;ac048;bgb +; + sector-offset (0-8) + first-sector (1-ffff) = (7ffb9-8ffbf) ;ac048;bgb +; ;ac048;bgb +; logic: 1. adjust the cluster number, since the 1st two clusters in the fat ;ac048;bgb +; are not used. cluster number can be from 3-fff7. ;ac048;bgb +; 2. get the sectors-per-cluster, and multiply it times cluster number ;ac048;bgb +; in AX. since this is a word multiply, the high order number goes ;ac048;bgb +; into DX. ;ac048;bgb +; 3. add in the sector-number-within-the-cluster. Each cluster ;ac048;bgb +; (usually) contains several sectors within a cluster. This sector ;ac048;bgb +; number is that number. It may be from zero to the max number of ;ac048;bgb +; sectors/cluster (which can be up to 8 so far on IBM systems). ;ac048;bgb +; Do an ADC in case there is a overflow of the word register. ;ac048;bgb +; 4. add in the starting cluster number of the data area. This now ;ac048;bgb +; gives you the logical sector number within that drive. ;ac048;bgb +;***************************************************************************** ;ac048;bgb +procedure figrec,NEAR ;ac048;bgb + push ax ;save registers ;ac048;bgb + push bx ;save registers ;ac048;bgb + push cx ;save registers ;ac048;bgb + ;ac048;bgb + xor ch,ch ;clear out hi byte of sector-offset ;ac048;bgb + mov cl,ah ;move sector-offset into cx ;ac048;bgb + mov ax,bx ;move cluster number into ax for mult ;ac048;bgb + ;ac048;bgb + xor bh,bh ;zero out bh ;ac048;bgb + mov bl,csize ;get sectors per cluster ;ac048;bgb + dec ax ; sub 2 for the 1st 2 unused clus in the fat ;ac048;bgb + dec ax ; ;ac048;bgb + mul bx ;ax=low word, dx=hi word ;ac048;bgb + ;ac048;bgb + add ax,cx ;add sector offset ;ac048;bgb + adc dx,0 ;inc hi word if overflow ;ac048;bgb + add ax,[firstsec] ;add first data sector ;ac048;bgb + adc dx,0 ;inc hi word if overflow ;ac048;bgb + ;ac048;bgb + mov Read_Write_Relative.Start_Sector_High,dx ;save hi value ;ac048;bgb + mov dx,ax ;convert to old format- dx=low ;ac048;bgb + ;ac048;bgb + pop cx ;ac048;bgb + pop bx ;ac048;bgb + pop ax ;ac048;bgb + RET ;ac048;bgb +endproc figrec ;ac048;bgb + + +;***************************************************************************** +SUBTTL PRINTID - Print Volume ID info +PAGE +PRINTID: +ASSUME DS:DG + call docrlf ; ;AN000; +;get volume name ;an012;bgb + xor si,si ;Point at DTA where find first just done;;an005;bgb + lea DI,arg_buf ;Where to put vol name for message ;AC000; + add si,DirNam ;Point at the vol label name ;AN000; +;;;;;;;;lea DI,arg_buf ;Point at vol label location in arg_Buf ;AC000; + MOV CX,11 ; Pack the name + push ds ;an005;bgb + mov ds,fattbl_seg ;an005;bgb + REP MOVSB ; Move all of it +;get the year ;an012;bgb + xor si,si ;Get back pointer to FCB ;an009;bgb + mov ax,ds:[si].DirDat ;yyyyyyym mmmddddd Put in SysDisp form ;AN009;bgb + and ax,Year_Mask ;yyyyyyy0 00000000 ;AN000; + shr ax,1 ;0yyyyyyy 00000000 ;AN000; + xchg al,ah ;00000000 0yyyyyyy ;AN000; + add ax,1980 ; ;AN000; + mov es:Sublist_msg_Idmes.Sublist_Offset+(size Sublist_Struc),ax ; ;AN009;bgb +;get the month ;an012;bgb + mov ax,ds:[si].DirDat ;yyyyyyym mmmddddd ;AN009;bgb + and ax,Month_Mask ;0000000m mmm00000 ;AN000; + mov cl,5 ; ;AN000; + shr ax,cl ;00000000 0000mmmm ;AN000; + mov cl,al ;0000mmmm ;AN000; +;get the day ;an012;bgb + mov ax,ds:[si].DirDat ;yyyyyyym mmmddddd ;AN009;bgb + and ax,Day_Mask ;00000000 000ddddd ;AN000; + mov ah,cl ;0000mmmm 000ddddd ;AN000; + xchg ah,al ;make it display correctly ;an012;bgb + mov es:Sublist_msg_Idmes.Sublist_Segment+(size Sublist_Struc),ax ; ;AN009;bgb +;get the time ;an012;bgb + mov ax,ds:[si].DirTim ;hhhhhmmm mmmsssss ;AN009;bgb + and ax,Hour_Mask ;hhhhh000 00000000 ;AN000; + mov cl,11 ; ;AN000; + shr ax,cl ;00000000 000hhhhh ;AN000; + mov ch,al ;000hhhhh ;AN000; + mov ax,ds:[si].DirTim ;hhhhhmmm mmmsssss ;AN009;bgb + and ax,Minute_Mask ;00000mmm mmm00000 ;AN000; + mov cl,3 ; ;AN000; + shl ax,cl ;00mmmmmm 00000000 ;AN000; + mov al,ch ;00mmmmmm 000hhhhh ;AN000; + mov es:Sublist_msg_Idmes.Sublist_Offset+(size Sublist_Struc)+(size Sublist_Struc),ax ;AN009;bgb + mov es:Sublist_msg_Idmes.Sublist_Segment+(size Sublist_Struc)+(size Sublist_Struc),0 ;AN009;bgb + pop ds ;an009;bgb + Message Idmes_Arg ; the parts out as needed ;AC000' +;;;;;;;;call doCRLF + ret ; + + + + +;***************************************************************************** ;an024;bgb +; Get the volume serial number ;an024;bgb +;***************************************************************************** ;an024;bgb +; Input: FCB_Drive ;an024;bgb +; Output: SerNum if no carry ;an024;bgb +; Notes: Only DOS Version 3.4 and above will contain serial numbers ;an024;bgb +;***************************************************************************** ;an024;bgb + PUBLIC GET_SERIAL_NUM ;an024;bgb +procedure Get_Serial_Num,NEAR ;AN000;S ;an024;bgb + mov al,GENERIC_IOCTL ;AN000;S ;an041;bgb;an024;bgb + xor bx,bx ;zero out bx ;an041;bgb;an024;bgb + mov bl,alldrv ;AN000;S Which drive to check ;an024;bgb + mov ch,rawio ;8 = disk io ;an041;bgb;an024;bgb + mov cl,Get_Media_Id ;66h = get media id ;an041;bgb;an024;bgb + LEA dx,SerNumBuf ;AN000;S Pt to the buffer ;an024;bgb + Dos_call ioctl ;AN000;S Make the call ;an041;bgb;an024;bgb +; $IF NC + JC $$IF26 + message msgserialnumber ;an024;bgb +; $ENDIF +$$IF26: + ret ;AN000;S ;an024;bgb +endproc Get_Serial_Num ;AN000;S ;an024;bgb + pathlabl chkdsk1 ;an024;bgb +CODE ENDS + END CHKDSK + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKDSK2.ASM b/v4.0/src/CMD/CHKDSK/CHKDSK2.ASM new file mode 100644 index 0000000..45838da --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKDSK2.ASM @@ -0,0 +1,449 @@ +TITLE CHKDSK - MS-DOS Disk consistancy checker +page ,132 ; + + .xlist + include chkseg.inc + INCLUDE CHKCHNG.INC + INCLUDE DOSSYM.INC + INCLUDE CHKEQU.INC + INCLUDE CHKMACRO.INC + include pathmac.inc + .list + +SUBTTL Initialized Data +PAGE +CONST SEGMENT PUBLIC PARA 'DATA' + EXTRN BADVER:byte,BADDRV_ARG:word,INVPATH_ARG:word + EXTRN FILE_ARG:word + EXTRN BADCD_ARG:word,BADSUBDIR:byte + EXTRN BADDRVM:byte + EXTRN BADIDBYT:byte + EXTRN OPNERR_ARG:word,NOEXT_ARG:word,EXTENT_ARG:word + EXTRN IDMES_ARG:WORD + EXTRN FILE_ARG1:WORD,FILE_ARG2:WORD + EXTRN badrw_num:word,BADRW_STR:WORD,BLOCK_NUM:WORD + EXTRN BADSW_ARG:WORD,DSKSPC:WORD + EXTRN HIDMES:WORD,DIRMES:WORD,FILEMES:WORD,ORPHMES2:WORD + EXTRN ORPHMES3:WORD,BADSPC:WORD,FRESPC:WORD + EXTRN TOTMEM:WORD,FREMEM:WORD,REPORT_ARG:WORD,CRLF_ARG:WORD + EXTRN RARG1:dWORD,RARG3:dWORD,ORPHCNT:dWORD ;an049;bgb + EXTRN SubstErr:BYTE + extrn tot_bytes_lo:word, tot_bytes_hi:word + + extrn SWITCHAR:byte,TCHAR:byte,HECODE:byte,CONBUF:byte + extrn DOTMES:byte,NOISY:byte,HAVFIX:byte + extrn DOFIX:byte,DIRBUF:near,PARSTR:byte + extrn NUL:byte,ERRSUB:word,ALLFILE:byte + extrn ORPHFCB:byte,ORPHEXT:byte,HIDCNT:dword + extrn HIDSIZ:word,FILCNT:dword,FILSIZ:word,DIRCNT:dword ;an049;bgb + extrn DIRSIZ:word,CROSSCNT:dword,BADSIZ:word ;an049;bgb + extrn ORPHSIZ:word ;an049;bgb + extrn LCLUS:word ;an049;bgb + extrn USERDIR:byte,FRAGMENT:byte + extrn ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte + extrn EOFVAL:word ;an050;bgb + extrn Idmes2:Byte,Idmes1:Byte,idmes3:byte ;an017;bgb +CONST ENDS + +SUBTTL Un-initialized Data +PAGE +DATA SEGMENT PUBLIC PARA 'DATA' + extrn THISDPB:dword,DOTSNOGOOD:byte,NUL_ARG:byte + extrn NAMBUF:byte,SRFCBPT:word + extrn ISCROSS:byte,MCLUS:word,CSIZE:byte,SSIZE:word + extrn DSIZE:word,ARG1:word,ARG_BUF:byte,ERRCNT:byte + extrn USERDEV:byte,HARDCH:dword,CONTCH:dword + extrn mem_size:word ;an055;bgb + extrn psp_segment:word ;an030;bgb + extrn write_fault:byte ;an045;bgb +DATA ENDS + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + EXTRN INT_23:NEAR + EXTRN PROMPTYN:NEAR,GET_CURRDIRERR:NEAR,GET_CURRDIR:NEAR + EXTRN FINDCHAIN:NEAR,CHECKERR:NEAR + EXTRN Write_Disk:Near, multiply_32_bits:near + + PUBLIC PRINTF_CRLF,DOCRLF,SUBERRP,FCB_TO_ASCZ,EPRINT + PUBLIC DOINT26,DOTCOMBMES,REPORT + public ramcarv + + +;EPRINT: +; CALL CHECKERR +; JNZ RET14 +; cmp byte ptr [nul_arg],0 +; jnz hav_eprint_arg +; mov [file_arg2],offset dg:nul +;hav_eprint_arg: +; mov [file_arg1],dx +; ;mov dx,offset dg:file_arg +; mov dx,file_arg ;Get offset of message ;AC000; +; call printf_crlf +; mov byte ptr [nul_arg],0 +;RET14: ret + + +EPrint: + call CheckErr ;See if we should display msg + pathlabl chkdsk2 +; $IF Z ;Yes if Z set ;AC000; + JNZ $$IF1 + push dx ;Save message ;AC000; + Message File_Arg ;Put out file in question ;AC000; + pop dx ;Get back message ;AC000; + call Printf_CRLF ;Print it + cmp byte ptr [nul_arg],0 ;Is there a second message? +; $IF NZ ;Yes if not nul ;AC000; + JZ $$IF2 + mov dx,File_Arg2 ;Display it ;AN000; + call Printf_CRLF ; ;AN000; +; $ENDIF ; ;AC000; +$$IF2: + mov byte ptr [nul_arg],0 ;Re-init this field +; $ENDIF +$$IF1: + ret ; + +DOTCOMBMES: + CMP [NOISY],0 + JZ SUBERRP + mov [file_arg2],dx + CALL get_currdirERR + ;MOV DX,OFFSET DG:CENTRY ;Centry got split into 3 msg's + ;inc byte ptr [nul_arg] ; + CALL EPRINT + RET + +SUBERRP: + MOV AL,1 ;found a subdir error + XCHG AL,BYTE PTR [ERRSUB] ;set error flag and get old flag + CMP AL,0 ;were any errors found before? +; $if z ;no errors found yet + JNZ $$IF5 + ;JNZ RET32 + MOV SI,OFFSET DG:NUL ;display error msgs + CALL get_currdirERR + MOV DX,OFFSET DG:BADSUBdir + CALL EPRINT +; $endif +$$IF5: +RET32: RET + +;**************************************************************************** +; called by: get_thisel2 +; inputs: DS:SI - pointer to file name +;**************************************************************************** +FCB_TO_ASCZ: ;Convert DS:SI to ASCIZ ES:DI + PUSH CX +;move filename from ds:si to es:di + MOV CX,8 ; Pack the name + REP MOVSB ; Move all of it +main_kill_tail: +; delete trailing spaces in name + CMP BYTE PTR ES:[DI-1]," " ;was the last char in name a space? + JNZ find_check_dot + DEC DI ; Back up over trailing space + INC CX + CMP CX,8 + JB main_kill_tail +find_check_dot: +; ??? + CMP WORD PTR [SI],(" " SHL 8) OR " " + JNZ got_ext ; Some chars in extension + CMP BYTE PTR [SI+2]," " + JZ find_done ; No extension +got_ext: +; move period for extension + MOV AL,"." + STOSB +; move 3 byte extension + MOV CX,3 + REP MOVSB +ext_kill_tail: +;delete trailing blanks + CMP BYTE PTR ES:[DI-1]," " ; + JNZ find_done ; + DEC DI ; Back up over trailing space + JMP ext_kill_tail ; +find_done: ; +; put hex zero at the end + XOR AL,AL ; + STOSB ; NUL terminate + POP CX + RET + + +DOINT26: +; PUSH CX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb +; PUSH DX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb +; PUSH BX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb + call Write_Disk ; ;an045;bgb;AC000; +; POP BX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb +; POP DX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb +; POP CX ;reg saves are handled in write_disk ;ac048;bgb;an045;bgb +; JNC RET23 ;ac048;bgb;an045;bgb + ;MOV SI,OFFSET DG:WRITING ;ac048;bgb;an045;bgb + ;CALL DSKERR ;ac048;bgb;an045;bgb +; $IF C ;ac048;bgb;an045;bgb + JNC $$IF7 + mov dx,offset dg:write_fault ;ac048;bgb;an045;bgb + invoke printf_crlf ;ac048;bgb;an045;bgb +; $ENDIF ;ac048;bgb;an045;bgb +$$IF7: +; ;ac048;bgb;ac048;bgb;an045;bgb +;Need to handle 'Fail' option of critical error here. ;ac048;bgb;an045;bgb +; ;ac048;bgb;an045;bgb + ;ac048;bgb;an045;bgb +; JZ DOINT26 ;ac048;bgb;an045;bgb +RET23: RET ;ac048;bgb;an045;bgb + + + +;************************************** +; Prints all reporting data +;************************************** + +REPORT: +;total disk space + mov bx,offset dg:dskspc + mov dx,tot_bytes_hi ;total bytes in disk ;AN006;bgb + mov ax,tot_bytes_lo ;total bytes in disk ;AN006;bgb + xor si,si ;no file count + xor di,di ;no file count + call Report_Mes_2 ; ;AN006;bgb +;hidden files + mov ax,hidsiz ;get cluster count ;an049;bgb + or ax,ax ;are there any hidden files? +; $IF NZ ;yes ;AC000; + JZ $$IF9 + mov si,word ptr hidcnt ;si=low file count ;an049;bgb + mov di,word ptr hidcnt+2 ;di=hi file count ;an049;bgb + mov bx,offset dg:hidmes ;bx=msg ; + call report_mes_1 ; +; $ENDIF ; ;AC000; +$$IF9: +;space in subdirectories + mov ax,dirsiz ;get cluster count + or ax,ax ;Are there any directories? ;an049;bgb +; $IF NZ ;yes ;AC000; + JZ $$IF11 + mov si,word ptr dircnt ;si=low file count ;an049;bgb + mov di,word ptr dircnt+2 ;di=hi file count ;an049;bgb + mov bx,offset dg:dirmes ;bx=msg + call report_mes_1 ;an049;bgb +; $ENDIF ; ;AC000; +$$IF11: +;user files + mov ax,filsiz ;get cluster count + or ax,ax ;Are there any user files? ;an049;bgb +; $IF NZ ;yes ;AC000; + JZ $$IF13 + mov si,word ptr filcnt ;si=lo file count ;an049;bgb + mov di,word ptr filcnt+2 ;di=hi file count ;an049;bgb + mov bx,offset dg:filemes ;bx=msg + call report_mes_1 +; $ENDIF ; ;AC000; +$$IF13: +;chains of lost clusters + mov ax,orphsiz ;get cluster count + or ax,ax ;Are there any lost clusters? ;an049;bgb +; $IF NZ ;yes ;AC000; + JZ $$IF15 + mov si,word ptr orphcnt ;si=lo file count + mov di,word ptr orphcnt+2 ;di=hi file count + cmp dofix,0 ;/F entered? +; $IF Z ;no ;AC000; + JNZ $$IF16 + mov bx,offset dg:orphmes3 ;bytes would be recovered +; $else + JMP SHORT $$EN16 +$$IF16: + mov bx,offset dg:orphmes2 ;bytes were recovered +; $ENDIF ; ;AC000; +$$EN16: + call report_mes_1 +; $ENDIF ; ;AC000; +$$IF15: +;clusters of bad spots + mov ax,badsiz ;get cluster count + or ax,ax ;Are there any bad spots on disk? +; $IF NZ ;if low word > zero, then yes ;AC000; + JZ $$IF20 + xor si,si ;no files to count + xor di,di ;no files to count + mov bx,offset dg:badspc ;Issue report + call report_mes_1 +; $ENDIF ; ;AC000; +$$IF20: +;bytes on disk left - free space + mov ax,[dsize] ;get total disk clusters + sub ax,[dirsiz] ; - dirs + sub ax,[filsiz] ; - files + sub ax,[hidsiz] ; - hidden files + sub ax,[badsiz] ; - bad spots + sub ax,[orphsiz] ; - lost clusters recovered + sub ax,[lclus] ; - lost clusters not recovered + xor si,si + xor di,di + mov bx,offset dg:frespc + call report_mes_1 ;Free space is whats left + call docrlf ; ;AN000; +;size of each allocation unit + xor dx,dx ;Figure out cluster size ;AN000; + xor ah,ah ; ;AN000; + mov cx,SSize ;Bytes/sector * ;AN000; + mov al,CSize ; Sectors/cluster ;AN000; + mul cx ; = Bytes/Cluster in AX ;AN000; + mov bx,offset dg:idmes2 ;Allocation size message ;AN000; + xor si,si + xor di,di + call Report_Mes_2 ; ;AN000; +;total clusters + mov ax,Mclus ;Allocation units available ;AN000; + dec ax ;MCLUS is # clusters+1 + xor dx,dx ; ;AN000; + mov bx,offset dg:idmes1 ; ;AN000; + xor si,si + xor di,di + call Report_Mes_2 ; ;AN000; +;;;;;;;;call docrlf ; ;an017;bgb +;avail clusters ;an017;bgb +public avail_clus +avail_clus: + mov ax,[dsize] ;total clusters on disk ;an017;bgb + sub ax,[dirsiz] ; - clusters in subdirs ;an017;bgb + sub ax,[filsiz] ; - user files ;an017;bgb + sub ax,[hidsiz] ; - hidden files ;an017;bgb + sub ax,[badsiz] ; - bad spots ;an017;bgb + sub ax,[orphsiz] ; - lost clusters recovered ;an017;bgb + sub ax,[lclus] ; - lost clusters not recovered ;an017;bgb + mov bx,offset dg:idmes3 ; ;an017;bgb + xor dx,dx ; ;AN017;bgb + xor si,si + xor di,di + call Report_Mes_2 ;dont convert to bytes! ;an017;bgb + call docrlf ;an017;bgb + + +;dcl Jan 8, 87 Compensate for RAM Carving - Start + +ramcarv: + push es ;AN000; + xor bx,bx ;AN000; + mov ah,0c1h ; return Ext'd Bios Data Seg Address ;AN000; + int 15h ;AN000; +; $IF NC ; ram carving exists if no carry ;AC000; ;AN000; + JC $$IF22 + xor ax,ax ; zero out ax + mov al,byte ptr es:[0] ; pointer to # of 1k blocks of RAM Carve;AN000; + mov dx,64 ; convert 1k blocks to paras ;AN000; + mul dx ;AN000; + mov bx,ax ; save value in BX ;AN000; +; $ENDIF ; ;AC000; ;AN000; +$$IF22: + pop es ;AN000; + +;dcl Jan 8, 87 Compensate for RAM Carving - End + + mov ax,[mem_size] ;Find out about memory + add ax,bx ; dcl Jan 8, 87 Compensate for RAM Carving + mov dx,16 ;Mul to convert kbytes to bytes + mul dx + mov bx,offset dg:totmem + call report_mes_2 + mov ax,[mem_size] +;;;;;;; mov dx,psp_segment ;an030;bgb + sub ax,psp_segment ;an030;bgb + mov dx,16 + mul dx + mov bx,offset dg:fremem + call report_mes_2 + ret + +;************************************************************* +; +; Print the message specified by the control string. +; +; REPORT_MES_1 +; On entry: +; BX contains the address of the control string. +; AX contains a cluster count for the %ld argument in the control string. +; CX contains a word count for the %d argument in the control string +; or is meaningless. +; +; REPORT_MES_2 +; On entry: +; BX contains the address of the control string. +; AX,DX contain a long integer. +; CX contains a word count for the %d argument in the control string +; or is meaningless. +; +;************************************************************* + +;***************************************************************************** +; REPORT_MES_1 - Print the report messages. Display the file count and +; translate the number of clusters into the number of bytes. +; +; WARNING!! NOTE!! --> +; +; called by - PROCEDURE NAME +; +; inputs: AX - cluster count (1-ffff) +; BX - offset of control string +; CX - +; DX - high word of cluster count is zero'd out here. +; SP - +; BP - +; SI - low word of file count +; DI - hi word of file count +; DS - segment of control string +; ES - +; +; output: DISPLAY OF DATA TO SCREEN +; +; Regs abused - ALL +; +;logic: 1. zero out hi word of cluster count, and multiply by sectors per +; cluster. This gives number of sectors, which is a double word. +; +; 2. multiply by bytes per sector to give number of bytes. +; +; 3. place values in diplay fields, and call the msg. retriever. +; +;***************************************************************************** +report_mes_1: + push bx ;save it + xor dx,dx ;zero out hi word for multiply + mov cl,csize ;get sectors per cluster + xor ch,ch ;zero out hi byte of word + mul cx ;Convert cluster count to sector count ax/dx + + mov bx,dx ;bx:ax is number to be mult;bgb + mov cx,ssize ;cx is number to mult with ;bgb + call multiply_32_bits ;bgb + mov dx,bx ;move hi value to dx + pop bx ;retore pointer;bgb + +report_mes_2: + mov word ptr rarg1,ax ;Lo word of bytes in ax + mov word ptr rarg1+2,dx ;Hi word of bytes in dx + mov word ptr rarg3,si ;lo word of file count in si + mov word ptr rarg3+2,di ;hi word of file count in di + mov report_arg,bx ;Store the offset of the ctrl string + mov dx,bx ;dx has ptr to msg for disp_interface ;AC000; + call printf_crlf ;print msg, then carraige return + ret + +PRINTF_CRLF: + call display_interface ; ;AC000; +DOCRLF: mov dx,offset dg:crlf_arg + call Display_Interface ;Replace old printf call with SysDispMsg;AN000; + ret ; ;AN000; + + + pathlabl chkdsk2 +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKEQU.INC b/v4.0/src/CMD/CHKDSK/CHKEQU.INC new file mode 100644 index 0000000..c2cbba5 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKEQU.INC @@ -0,0 +1,206 @@ +;fsexec equ true ; ; ;an038;bgb ; +FCB EQU 5CH + +String_Done equ 0 +No_Error equ 0 +chk_Error equ 1 +Stderr equ 2 + +FALSE EQU 0 +TRUE EQU NOT FALSE + +; NOTE WARNING DANGER. +; THIS EQU DEFINES AN OFFSET INTO THE SEARCH FCB OF THE LASTENT VALUE. +; ITS LOCATION MAY CHANGE FROM DOS VERSION TO DOS VERSION. +;2.0/2.1 value +;THISENT EQU 17H ;Relative entry number of current entry +;3.0 value +THISENT EQU 14H ;Relative entry number of current entry + + +;Attribute bits + +RDONLY EQU 1 +HIDDN EQU 2 +SYSTM EQU 4 +VOLIDA EQU 8 +ISDIR EQU 10H +DRVCHAR EQU ":" +; +;***************************************************************************** +; Equates +;***************************************************************************** +; + +Multiplex equ 2Fh ; ;AN000; +Set_Append_X equ 0B707h ; ;AN000;; +Append_X equ 0B706h ; ;AN000;; +Append_X_Set equ 1 ; ;AN000; +Append_Off equ 0 ; ;AN000; +Append_ON equ 1 ; ;AN000; + + +Disk_Error equ 80h ;INT 24h bit clear if disk error;AN000; + +NO equ 0 ;AN000; +YES equ not NO ;AN000; + +Year_Mask equ 0FE00h +Month_Mask equ 01E0h +Day_Mask equ 001Fh +Hour_Mask equ 0F800h +Minute_Mask equ 07E0h + +Not_Include equ 0 +Do_Include equ 1 + + +YES_Found equ 1 +NO_Found equ 0 + +ON equ 1 +OFF equ 0 + +No_Ext_Attrib equ 0 ;AN000; +No_Entry equ 0 +XA_Chain equ 84h ;Mark head of XA chain ;AN000; + +ifdef fsexec ;an038;bgb +Len_FS_String_Buffer equ 13 ;an038;bgb +FAT12_File_System equ 01h ;an038;bgb;AN000; +FAT16_File_System equ 04h ;an038;bgb;AN000; +New_File_System equ 06h ;an038;bgb;AN000; +endif + +Bad_Exit equ 0FFh ;Errorlevel = 0FFh ;AN000; + +Net_Check equ 1200h ;AN000; +Assign_Check equ 8000h ;AN000; + +Found_Yes equ 1 ;AN000; +Found_No equ 0 ;AN000; + +Asciiz_End equ 0 ;AN000; + +Dir_Attribute equ 10h +Vol_Attribute equ 08h + +Dir_Entries_Per_Sector equ 512/32 + + +Critical_Error_Fail equ 3 +Write_Protect equ 0 +Drive_Not_Ready equ 2 + +Blank equ " " ;AN000; + +Head_Mask equ 7Fh ;Mask to turn off head bit ;AN000; + + +;Limits +BIG_FAT_THRESHOLD equ 4086 ;AN000; + + + +;------------------------------------------------------------------------------- +; These are the data structures which we will need +;**************************************************************************** +; Structures +;**************************************************************************** +ifdef fsexec ;an038;bgb +Exec_Block_Parms struc ;an038;bgb +Segment_Env dw 0 ;an038;bgb +Offset_Command dw 0 ;an038;bgb +Segment_Command dw 0 ;an038;bgb +Offset_FCB1 dw 0 ;an038;bgb +Segment_FCB1 dw 0 ;an038;bgb +Offset_FCB2 dw 0 ;an038;bgb +Segment_FCB2 dw 0 ;an038;bgb +Exec_Block_Parms ends ;an038;bgb + +Media_ID struc ;AN000; +Media_ID_Info_Level dw 0 ;AN000; +Media_ID_Serial_Number dd 0 ;AN000; +Media_ID_Volume_Label db 11 dup(" ") ;AN000; +Media_ID_File_System db 8 dup(" ") ;AN000; +Media_ID ends ;AN000; +endif ;an038;bgb + +Sublist_Struc struc +Sublist_Size db ? ; ;AN000; +Sublist_Rsv db ? ; ;AN000; +Sublist_Offset dw ? ; ;AN000; +Sublist_Segment dw ? ; ;AN000; +Sublist_Number db ? ; ;AN000; +Sublist_Type db ? ; ;AN000; +Sublist_Max db ? ; ;AN000; +Sublist_Min db ? ; ;AN000; +Sublist_Char db ? ; ;AN000; +Sublist_Struc ends + +A_DeviceParameters struc + +SpecialFunctions db ? ;1 0 +DeviceType db ? ;1 1 +DeviceAttributes dw ? ;2 2 +NumberOfCylinders dw ? ;2 4 +MediaType db ? ;1 6 +BytePerSector dw ? ;2 7 +SectorsPerCluster db ? ; +ReservedSectors dw ? +NumberOfFATs db ? +RootEntries dw ? +TotalSectors dw ? +MediaDescriptor db ? +SectorsPerFAT dw ? +SectorsPerTrack dw ? +Heads dw ? +HiddenSectors dd ? +Ext_Total_Sectors dd ? +ReservedArea db 6 dup(?) + +A_DeviceParameters ends + + + + +Relative_Sector_Buffer struc ; ;AN000; + +Start_Sector_Low dw ? ;Low word of RBA sector ;AN000; +Start_Sector_High dw ? ;High word of RBA sector ;AN000; +Number_Sectors dw ? ;Number of sectors ;AN000; +Buffer_Offset dw ? ;Address of data buffer ;AN000; +Buffer_Segment dw ? ; ;AN000; + +Relative_Sector_Buffer ends ; ;AN000; + + +XAL struc ;AN000; + +XAL_Tsize dw ? ;AN000; +XAL_TCount dw ? ;AN000; +XAL_LSize dw ? ;AN000; +XAL_LCount dw ? ;AN000; +XAL_Data db 512-8 dup(?) ;AN000; + +XAL ends ;AN000; + +DIRENT STRUC + DB 7 DUP (?) ;Ext FCB junk + DB ? ;Drive +DIRNAM DB 11 DUP (?) ; +DIRATT DB ? ; +DIRCP DW ? ; ;AN000; +DIR_XA DW ? ; ;AN000; +DIRATT2 db ? ; ;AN000; +DIRRES DB 5 DUP (?) ; ;AC000; +DIRTIM DW ? ; +DIRDAT DW ? ; +DIRCLUS DW ? ; +DIRESIZ DD ? ; +DIRENT ENDS ; +ENTSIZ EQU SIZE DIRENT + +;------------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKFAT.ASM b/v4.0/src/CMD/CHKDSK/CHKFAT.ASM new file mode 100644 index 0000000..badd48c --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKFAT.ASM @@ -0,0 +1,1064 @@ +TITLE CHKFAT - procedures that acces the fat and/or fatmap +page ,132 ; + + .xlist + include chkseg.inc ;an005;bgb + INCLUDE CHKCHNG.inc + INCLUDE DOSSYM.inc + INCLUDE CHKEQU.inc + INCLUDE CHKMACRO.inc + include pathmac.inc + + +CONST SEGMENT PUBLIC PARA 'DATA' + EXTRN CREATMES:byte,FIXMES_ARG:word + EXTRN FREEMES:byte + EXTRN BADW_ARG:word,FATAL_END:word + EXTRN badrw_num:word,BADRW_STR:WORD,HAVFIX:byte + EXTRN FREEBYMES1:byte,FREEBYMES2:byte + EXTRN FREE_ARG1:WORD,FREE_ARG2:WORD,FREE_ARG3:WORD,ORPHCNT:dword + EXTRN DIRTYFAT:byte,CROSSCNT:dword,DOFIX:byte,SECONDPASS:byte + EXTRN BADSIZ:word,ORPHSIZ:word,LCLUS:word,ORPHFCB:byte + EXTRN HECODE:byte,USERDIR:byte,FRAGMENT:byte + EXTRN ORPHEXT:byte,ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte + EXTRN BIGFAT:byte,EOFVAL:word,BADVAL:word + extrn fTrunc:BYTE, rarg1:word ;an018;bgb + extrn temp_dd:dword ;an049;bgb +CONST ENDS + +DATA SEGMENT PUBLIC PARA 'DATA' + extrn fatcnt:byte ;an005;bgb + EXTRN THISDPB:dword,NUL_ARG:byte + EXTRN NAMBUF:byte,SRFCBPT:word,FATMAP:word + EXTRN MCLUS:word,CSIZE:byte,SSIZE:word + EXTRN DSIZE:word,ARG1:word,ARG_BUF:byte,ERRCNT:byte + EXTRN USERDEV:byte,HARDCH:dword,CONTCH:dword + EXTRN ExitStatus:Byte,Read_Write_Relative:Byte + extrn bytes_per_sector:word, fattbl:word ;an005;bgb + extrn sec_count:word, secs_per_64k:word, paras_per_64k:word ;an005;bgb + extrn fattbl_seg:word, fatsiz:word, paras_per_fat:word ;an005;bgb + extrn end_of_fatmap:word ;an030;bgb + extrn root_entries:word ;ac048;bgb;an047;bgb +DATA ENDS + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + EXTRN PRINTF_CRLF:NEAR,FCB_TO_ASCZ:NEAR, recover:near + EXTRN EPRINT:NEAR, makorphnam:near + EXTRN DOINT26:NEAR,PROMPTYN:NEAR,CHECKFILES:NEAR,DIRPROC:NEAR + EXTRN DOCRLF:NEAR, getfilsiz:near, fatal:near, write_disk:near + EXTRN GETENT:NEAR,CHECKNOFMES:NEAR, systime:near + EXTRN multiply_32_bits:near ;an049;bgb + +public calc_fatmap_seg, MARKMAP, CHKMAP, CHKMAPLP, ORPHAN, CONTLP, RET18 +public PromptRecover, NOCHAINREC, CHKMAPLP2, NEXTCLUS +public DISPFRB, FINDCHAIN, CHKMAPLP3, CHAINLP, INSERTEOF, FAT12_4, CHKCHHEAD +public ADDCHAIN, CHGOON, NEXTCLUS2, +public CHAINREC, MAKFILLP, GOTENT, OPAGAIN, GOTORPHNAM, ENTMADE, NEXTENT +public NXTORP, RET100, nextorph +public AMDONE, REWRITE, WRTLOOP +public WRTOK, NOWRITE, DONE, CROSSCHK, calc_fat_addr, pack, unpack + .list +PHONEY_STACK DW 5 DUP(0) ;ac048;bgb + + pathlabl chkfat +;***************************************************************************** ;an005;bgb +; CALC-FAT-ADDR - calculate the seg/off of the fat cell from the cell number ;an005;bgb +; ;an005;bgb +; Inputs: es - fat table segment +; si - cluster number +; +; Outputs: es - fat table segment + cluster seg +; di - cluster offset +; ;an005;bgb +; LARGE FAT SUPPORT ;an005;bgb +;******************* ;an005;bgb +; the offset into the fat table is cluster number times 2 (2 bytes per fat entry) ;an005;bgb +; This will result not only in the segment boundary being passed, but also in ;an005;bgb +; a single-word math overflow. So, we calculate the the address as follows: ;an005;bgb +; 0. start with cluster number (1-65535) ;an005;bgb +; 1. divide by 8 to get the number of paragraphs per fat-cell (0-8191) ;an005;bgb +; remainder = (0-7) ;an005;bgb +; 2. multiply the remainder by 2 to get offset in bytes (0-15) ;an005;bgb +; You now have a paragraph-offset number that you can use to calc the addr into ;an005;bgb +; the fat table. To get the physical addr you must add it to the offset of the ;an005;bgb +; table in memory. ;an005;bgb +; 3. add the paras to the segment register ;an005;bgb +; 4. add the offset to the offset register ;an005;bgb +;****************************************************************************** ;an005;bgb +Procedure calc_fat_addr,near ;an005;bgb + savereg ; ;an005;bgb + mov ax,si ;get cluster number from si + mov bx,0008h ; div by para (* 2 bytes per clus) ;an005;bgb + xor dx,dx ; zero dx for word divide ;an005;bgb + div bx ; do it ;an022;bgb;bgb + mov bx,es ; get fat table segment ;an005;bgb + add bx,ax ; add number of paras to the cluster ;an005;bgb + mov es,bx ; move it back ;an005;bgb + shl dx,1 ; remainder times 2 ;an005;bgb + mov di,dx ; offset = 00 + remainder ;an005;bgb + restorereg ;an005;bgb + return ;an005;bgb +EndProc calc_fat_addr ;an005;bgb + +;========================================================================= +; UNPACK : This routine calculates the position in the FAT +; where the cluster number resides and obtains +; its contents. +; +; Inputs : SI - Cluster number +; Outputs : DI - Cluster contents +; zero flag is set if fat cell = zero +; +; LOGIC +; - get addr of fat table +; - if 16-bit fat, +; then get the address of the cell (calc_fat_addr) +; mov it into di +; set the zero flag +; else multiply the cluster-number by 1.5 to get the byte-offset +; move the contents of the cluster into di +; if the cluster-number is odd, +; then shift it right by 1 nibble +; set the zero flag +; else (its already shifted right) +; set the zero flag +;========================================================================= +UNPACK proc near ;ac005; dms;unpack FAT + push es ;an005;bgb + mov es,fattbl_seg ;point to FAT in memory ;an005;bgb + mov DI,SI ;put cluster number in DI + cmp [BIGFAT],0 ;big fat? +; $IF nz ;yes + JZ $$IF1 + call calc_fat_addr ;calc addr of cluster ;an005;bgb + mov di,word ptr es:[di] ;es:bx points to fat cluster ;an005;bgb + or DI,DI ; Set zero +; $ELSE ;small fat + JMP SHORT $$EN1 +$$IF1: + SHR DI,1 + ADD DI,SI ; Mult by 1.5 + mov DI,word ptr es:[di] + TEST SI,1 ;is the cluster number odd? +; $IF nz ;last bit is non-zero; means it is odd + JZ $$IF3 + SHR DI,1 ;shift by 1 nibble + SHR DI,1 + SHR DI,1 + SHR DI,1 + and di,0fffh ;ac005; dms; +; $ELSE ;ac005; dms;even cluster bound. + JMP SHORT $$EN3 +$$IF3: + AND DI,0FFFH +; $ENDIF +$$EN3: +; $ENDIF +$$EN1: + pop es + return +UNPACK endp ;ac005; dms; + +;========================================================================= +; PACK : This routine puts data into the FAT. +; +; Inputs : SI - Cluster number to be packed +; dx - Data to be packed +; +; Outputs : Altered FAT +; LOGIC +; - set the fat-changed-flags +; - get the seg of the fat-table +; - if 16-bit fat, +; then get the address of the cell (calc_fat_addr) +; mov the new value into it +; else multiply the cluster-number by 1.5 to get the byte-offset +; move the contents of the cluster into di +; if the cluster-number is odd, +; then shift it right by 1 nibble +; set the zero flag +; else (its already shifted right) +; set the zero flag +;========================================================================= +PACK proc near ;ac005; dms; + savereg ;ac048;bgb + mov [DIRTYFAT],1 ;Set FAT dirty byte + mov [HAVFIX],1 ;Indicate a fix + mov es,fattbl_seg ; ;an005;bgb + mov DI,SI + cmp [BIGFAT],0 +; $IF nz ;ac005; dms;big fat? + JZ $$IF7 + call calc_fat_addr ;calc addr of cluster ;an005;bgb + mov es:[di],dx ;move dx into cluster ;an005;bgb +; $ELSE + JMP SHORT $$EN7 +$$IF7: + shr di,1 ;offset = clus-num * 1.5 + add di,si ;offset = clus-num * 1.5 + push di ;save cluster offset + mov DI,es:[di] ;get previous value, 4 nibbles + test si,1 ;is the cluster number odd? +; $IF nz ;last bit is non-zero; means it is odd + JZ $$IF9 + SHL dx,1 ;shift by 1 nibble + SHL dx,1 + SHL dx,1 + SHL dx,1 + AND DI,0FH ;zero out 1st 3 nibbles '000f' +; $ELSE ;even cluster number + JMP SHORT $$EN9 +$$IF9: + AND DI,0F000H ;zero out last 3 nibbles 'f000' +; $ENDIF +$$EN9: + or DI,dx ;put new value in with old + pop si ;get cluster offset + mov es:[SI],DI +; $ENDIF +$$EN7: + restorereg ;ac048;bgb + ret +PACK endp ;ac005; dms; + +;========================================================================= ;an005;bgb +; CROSSCHK : this proc gets the value of the fatmap entry that is pointed ;an005;bgb +; to by an orphan ;an005;bgb +; ;an005;bgb +; Inputs : si - cluster number of the orphan ;an005;bgb +; ;an005;bgb +; Outputs : ah - contents of the fatmap pointed to by di ;an005;bgb +; LOGIC ;an005;bgb +; ***** ;an005;bgb +;========================================================================= ;an005;bgb +procedure CROSSCHK ;an005;bgb + push es + mov es,fatmap ;an005;bgb + xor di,di ;an005;bgb + ADD DI,SI + mov ah,es:[di] ;an005;bgb + TEST AH,10H + pop es + ret +EndProc CROSSCHK ;an005;bgb + +;***************************************************************************** ;an005;bgb +; INIT_FATMAP ;an005;bgb +; description: initialize the fatmap area to all zeros ;an005;bgb +; ;an005;bgb +; called from: main-routine ;an005;bgb +; ;an005;bgb +;Change History: Created 8/31/87 bgb ;an005;bgb +; ;an005;bgb +;Input: segment addr of the fatmap ;an005;bgb +; number of clusters in the fat (1-65535) ;an005;bgb +; ;an005;bgb +;Output: fatmap ;an005;bgb +; ;an005;bgb +; LOGIC ;an005;bgb +;---------- ;an005;bgb +;***************************************************************************** ;an005;bgb +Procedure init_fatmap,Near ;AN000;bgb ;an005;bgb + savereg + mov es,fatmap ;get seg of the fatmap ;an005;bgb + xor di,di ;get off of the fatmap ;an005;bgb + mov cx,[MCLUS] ;do once for each cluster + xor AL,AL ;zero means free + REP STOSB ;Initialize fatmap to all free + mov byte ptr es:[di],al ; ;an010;bgb + restorereg + return +endproc init_fatmap ; ;AN000; +; +;***************************************************************************** ;an005;bgb +; CALC_FATMAP_SEG ;an005;bgb +; description: calculate the segment of the fatmap for addressing purposes ;an005;bgb +; ;an005;bgb +; called from: main-routine ;an005;bgb +; ;an005;bgb +;Change History: Created 8/31/87 bgb ;an005;bgb +; ;an005;bgb +;Input: bytes-per-sector ;an005;bgb +; fatsiz ;an005;bgb +; ;an005;bgb +;Output: ram-based fat table ;an005;bgb +; paras-per-fat - number of paragraphs of mem in the fat +; fattbl-seg - segment number of fat table +; fatmap - segment number of the fat map table +; ;an005;bgb +; LOGIC ;an005;bgb +;---------- ;an005;bgb +; - calc length fat-table (in paras) ;an005;bgb +; = bytes-per-sector / 16 * sectors-per-fat ;an005;bgb +; - calc segment of fat table in memory ;an005;bgb +; = es + 64k ;an005;bgb +; - calc segment of fatmap area in memory ;an005;bgb +; = es + 64k + length of fat-table ;an005;bgb +;***************************************************************************** ;an005;bgb +Procedure calc_fatmap_seg,Near ;AN000;bgb ;an005;bgb +; calc fat table length ;an005;bgb + push es + mov ax,bytes_per_sector ; bytes per sector ;an005;bgb + xor dx,dx ;an005;bgb + mov bx,16 ;an005;bgb + div bx ; paras per sector ;an022;bgb;bgb + mov cx,fatsiz ;2 ; get sectors per fat ;an005;bgb + xor dx,dx ;an005;bgb + mul cx ; paras per fat ;an005;bgb + mov paras_per_fat,ax ;an005;bgb +; calc fat table segment ;an005;bgb + mov bx,es ;get seg of fat-table ;an005;bgb + add bx,01000h ;add 64k for end of pgm seg ;an005;bgb + mov fattbl_seg,bx ;starting segment of fattbl ;an005;bgb +; calc fatmap segment :an005;bgb + add ax,bx ;seg of fatmap= seg of fattbl + size of fattbl ;an005;bgb + mov fatmap,ax ;this is the seg of the fatmap ;an005;bgb +; find segment number of end of fatmap ;an030;bgb +;ptm p5000 mov bx,paras_per_fat ;each fat cell is 2 bytes ;an030;bgb +;ptm p5000 shr bx,1 ;each fatmap cell is 1 byte = ;an030;bgb + mov bx, [MCLUS] ;P5000 INIT_FATMAP use [MCLUS] + shr bx, 1 ;P5000 convert it to para. + shr bx, 1 ;P5000 + shr bx, 1 ;P5000 + shr bx, 1 ;P5000 + add ax,bx ;add in fatmap seg = ;an030;bgb + inc ax ;P5000 + mov end_of_fatmap,ax ;last seg value ;an030;bgb + pop es + ret ; ;AN000; +endproc calc_fatmap_seg ; ;AN000; +; + ;ac048;bgb +;***************************************************************************** ;ac048;bgb +; FIX_ENTRY - fill in the dir entry with the lost cluster information, give it ;ac048;bgb +; unique filename, and write it back to disk. ;ac048;bgb +; ;ac048;bgb +; WARNING!! NOTE!! --> ;ac048;bgb +; ;ac048;bgb +; called by - CHAINREC ;ac048;bgb +; ;ac048;bgb +; inputs: AX - drive number ;ac048;bgb +; BX - ram offset of beginning of sector ;ac048;bgb +; CX - ;ac048;bgb +; DX - sector number low ;ac048;bgb +; SP - ;ac048;bgb +; BP - ;ac048;bgb +; SI - cluster number of first cluster in this lost chain ;ac048;bgb +; DI - points to entry in ram ;ac048;bgb +; ;ac048;bgb +; output: AX - ;ac048;bgb +; BX - ;ac048;bgb +; CX - ;ac048;bgb +; DX - ;ac048;bgb +; SP - ;ac048;bgb +; BP - ;ac048;bgb +; SI - ;ac048;bgb +; DI- ;ac048;bgb +; ;ac048;bgb +; Regs abused - di,si,cx ;ac048;bgb +; ;ac048;bgb +;logic: 1. save the starting cluster number ;ac048;bgb +; ;ac048;bgb +; 2. if the recovered file name already exists, then use the next one. ;ac048;bgb +; do this until the name is unique. ;ac048;bgb +; ;ac048;bgb +; 3. move all the pertinant info into the dir entry. ;ac048;bgb +; ;ac048;bgb +; 4. write the dir entry out to disk. ;ac048;bgb +;***************************************************************************** ;ac048;bgb +procedure fix_entry,near ;ac048;bgb + mov ds:[DI+26],SI ;move 1st clus num into dir entry ;ac048;bgb ;an005;bgb + savereg ;Save INT 26 data ;ac048;bgb +;make sure this name is unique ;ac048;bgb + DOS_Call Disk_Reset ;func 0d - flush buffers ;AC000;ac048;bgb; + mov dx,OFFSET DG:ORPHFCB ;point to filename file0000.chk ;ac048;bgb + mov AH,FCB_OPEN ;open the file just put into the dir ;ac048;bgb +OPAGAIN: ;ac048;bgb +; $do ;ac048;bgb +$$DO13: + INT 21H ;ac048;bgb + or AL,AL ;did the open fail? ;ac048;bgb +; $leave nz ;ac048;bgb + JNZ $$EN13 + call MAKORPHNAM ;Try next name ;ac048;bgb +; $enddo ;ac048;bgb + JMP SHORT $$DO13 +$$EN13: +GOTORPHNAM: ;di still points to entry ;ac048;bgb + mov SI,OFFSET DG:ORPHFCB + 1 ;ORPHFCB Now has good name ;ac048;bgb + mov cx,11 ;move filename, ext ;ac048;bgb + REP MOVSB ;ac048;bgb + call MAKORPHNAM ;Make next name ;ac048;bgb + xor ax,ax ;fill dir entry with zeros ;ac048;bgb + mov cx,11 ;ac048;bgb + REP STOSB ;ac048;bgb +; Add in time for orphan file - BAS July 17/85 ;ac048;bgb + push dx ;save starting sector number ;ac048;bgb;an045;bgb + call SYSTIME ;ac048;bgb + STOSW ; Time ;ac048;bgb + mov ax,dx ;ac048;bgb + STOSW ; Date ;ac048;bgb + pop dx ;restore starting sector number ;ac048;bgb ;an045;bgb + mov SI,ds:[DI] ;get starting cluster number ;ac048;bgb ;an005;bgb + inc DI ;skip firstclus in entry ;ac048;bgb + inc DI ;ac048;bgb + PUSH DI ;save it from getfilsiz ;ac048;bgb + call GETFILSIZ ;calc file size from number of clus ;ac048;bgb + POP DI ;restore di ;ac048;bgb + STOSW ;ax=file size low ;ac048;bgb + mov ax,dx ;dx=filesize high ;ac048;bgb + STOSW ; ;ac048;bgb + restorereg ;offset, sector num, drive num ;ac048;bgb + mov cx,1 ;number of sectors = 1 ;ac048;bgb + call DOINT26 ;write it out to disk ;ac048;bgb + ret ;ac048;bgb +endproc fix_entry ;ac048;bgb + ;ac048;bgb +;***************************************************************************** ;ac048;bgb;an047;bgb +; NEXTORPH - find the cluster number of the next orphan. This assumes that ;ac048;bgb;an047;bgb +; there is at least one lost cluster available. ;ac048;bgb;an047;bgb +; ;ac048;bgb;an047;bgb +; WARNING!! NOTE!! --> ;ac048;bgb;an047;bgb +; ;ac048;bgb;an047;bgb +; called by - PROCEDURE NAME ;ac048;bgb;an047;bgb +; ;ac048;bgb;an047;bgb +; inputs: AX - ;ac048;bgb;an047;bgb +; BX - ;ac048;bgb;an047;bgb +; CX - ;ac048;bgb;an047;bgb +; DX - ;a;ac048;bgbn047;bgb +; SP - ;;ac048;bgban047;bgb +; BP - ;a;ac048;bgbn047;bgb +; SI - cluster number of the previous orphan ;a;ac048;bgbn047;bgb +; DI - ;a;ac048;bgbn047;bgb +; DS - ;a;ac048;bgbn047;bgb +; ES - points to one byte map of the fat ;a;ac048;bgbn047;bgb +; ;a;ac048;bgbn047;bgb +; output: AX - ;;ac048;bgban047;bgb +; BX - ;a;ac048;bgbn047;bgb +; CX - ;;ac048;bgban047;bgb +; DX - ;a;ac048;bgbn047;bgb +; SP - ;a;ac048;bgbn047;bgb +; BP - ;a;ac048;bgbn047;bgb +; SI - cluster number of one past the orphan ;ac048;bgb;an047;bgb +; DI - cluster number of the orphan ;a;ac048;bgbn047;bgb +; DS - ;a;ac048;bgbn047;bgb +; ES - ;a;ac048;bgbn047;bgb +; ;a;ac048;bgbn047;bgb +; Regs abused - none ;ac048;bgb;an047;bgb +; ;;ac048;bgban047;bgb +;logic: 1. save ax & es, and point to fat map ;ac048;bgb;an047;bgb +; ;a;ac048;bgbn047;bgb +; 2. do until the head of a chain is found: ;ac048;bgb ;an047;bgb +; ;;ac048;bgban047;bgb +; 3. get the next cell ;ac048;bgb ;an047;bgb +; ;;ac048;bgban047;bgb +; 4. bump pointers into fat map ;ac048;bgb ;an047;bgb +; ;;ac048;bgban047;bgb +; 5. restore ax & es ;;ac048;bgban047;bgb +;*****************************************************************************;a;ac048;bgbn047;bgb +procedure NEXTORPH,near ;a;ac048;bgbn047;bgb + savereg ;save regs abused ;ac048;bgb + mov es,[FATMAP] ;point to fat map ;ac048;bgb +; $do ;ac048;bgb +$$DO16: +loopno: mov al,byte ptr es:[si] ;get the indicated fatmap entry ;ac048;bgb ;an005;bgb + inc si ;point to the next one ;ac048;bgb ;an005;bgb + inc di ;point to the next one ;ac048;bgb ;an005;bgb + cmp AL,89H ;stop when you find an 89 ;ac048;bgb +; $leave z ;this means head(80), found(1), and orphan(8) ;ac048;bgb + JZ $$EN16 +; $enddo ;ac048;bgb + JMP SHORT $$DO16 +$$EN16: + restorereg ;restore regs ;ac048;bgb +return ;ac048;bgb +endproc nextorph ;ac048;bgb + ;ac048;bgb + ;ac048;bgb + +;**************************************************************************** +; MARKMAP - make a mark in the fat map for every cluster encountered +; +; called by - markfat, +; +; inputs - AL - the mark +; DI - cluster number +; +; outputs - CY if crosslink found +; - AH - previous mark +; - crosscnt (count of number of crosslinks found) +; - fatmap marked +; +; LOGIC +;****** +; - point to fatmap with es +; - if that cell has been found before, +; then mark it crossed x'10' +; else mark it found al +;**************************************************************************** +markmap: savereg ;Save registers ;AN000; + xor si,si ;Get addr of map ;an005;bgb + mov es,[FATMAP] ;Get addr of map ;an005;bgb + mov ah,es:[di] ;Get entry at that spot ;an005;bgb + or ah,ah ;Is it zero? ; ; +; $IF NZ ;already found - mark crossed;If not, we got crosslink ;AC000; + JZ $$IF19 + add word ptr crosscnt,1 ;Count the crosslink ; ; + adc word ptr crosscnt+2,0 ;Count the crosslink ; ; + or byte ptr es:[di],10H ;Resets zero in map ;An005;bgb + stc ;Indicate crosslink on ret ; ; +; $ELSE ;not found - mark found ;No crosslink ; ; + JMP SHORT $$EN19 +$$IF19: + mov es:[di],al ;Set mark in map ;Ac005;bgb + clc ;Indicate things okay ; ; +; $ENDIF ; ;AN000; +$$EN19: + restorereg ; ;AN005;bgb + ret ; ; ; + + +;**************************************************************************** +; CHKMAP - Compare FAT and FATMAP looking for badsectors and orphans +; +; called by - +; +; inputs - fatmap +; - dsize - number of clusters on the disk +; +; outputs - badsiz - +; - +; - +; LOGIC +;****** +; - get addr of fatmap +; - get offset of 1st cluster in fatmap +; - do for all the clusters on the disk: +; - if the cluster has been found +; then get the next cluster in its chain +; if the cell was never pointed to by anyone (0) +; then get the contents of that cell from the fat +; (the contents of the fat cell should be zero, too) +; if the fat-cell is not zero +; then (it should only be a bad sector) +; if it is a bad sector, inc the bad-sector-counter +; otherwise, we have found an orphan sector +; end-of-loop +; - if there are any orphans, +; then recover them +;**************************************************************************** +CHKMAP: + push es ;an014;bgb + mov es,fatmap ;get segment of the fatmap ;an005;bgb + xor si,si ;get the offset of the fatmap ;an005;bgb + mov si,2 ;go past the first two (invalid) entries;an005;bgb +;do for all the clusters on the disk + mov cx,[DSIZE] ;loop for the number of clusters on the disk +CHKMAPLP: + mov al,es:[si] ;move a byte from the fatmap to al ;an005;bgb + or al,al ;is the cluster found already? +; $IF Z ;fatmap cell is zero + JNZ $$IF22 + call unpack ;get the contents of it +; $IF NZ ;is there something in the cell? + JZ $$IF23 + cmp di,[badval] ;is the fat cell pointing to a bad sector? fff7 +; $IF Z ; yes + JNZ $$IF24 + inc [badsiz] ;inc the bad sector counter + mov byte ptr es:[si],4 ;Flag the map ;an005;bgb +; $ELSE ; no, not a bad sector + JMP SHORT $$EN24 +$$IF24: +orphan: inc [orphsiz] ; then its an orphan + mov byte ptr es:[si],8 ;Flag it ;an005;bgb +; $ENDIF +$$EN24: +; $ENDIF +$$IF23: +; $ENDIF +$$IF22: +CONTLP: + inc si ;point si to next cluster + loop chkmaplp + cmp [orphsiz],0 ;an005;bgb +; $IF A ;if there are any orphans, go recover them ;an005;bgb + JNA $$IF29 + call recover +; $ENDIF +$$IF29: + pop es ;an014;bgb +RET18: ret + +;***************************************************************************** +; PROMPTRECOVER - do the actual recovering of files +; +; inputs: es - points to fatmap +; ax - +; bx - +; cx - +; dx - +; +; outputs: +; LOGIC +; - ask the user if he wants to convert the orphans to files +; - +; - +;*************************************************************************** +PromptRecover: + mov dx,OFFSET DG:FREEMES + call PROMPTYN ;Ask user +; $IF Z + JNZ $$IF31 + jmp CHAINREC +; $ENDIF +$$IF31: +NOCHAINREC: + mov es,[fatmap] ;Free all orphans ;an005;bgb + mov si,2 ;an005;bgb + mov cx,[dsize] + xor dx,dx ;dx is the new value (free) +CHKMAPLP2: + mov al,es:[si] ;get next byte from fatmap into al + TEST AL,8 ; is it an orphan? +; $IF NZ ;yes + JZ $$IF33 + call PACK ;si=cluster number dx=new value +; $ENDIF +$$IF33: +NEXTCLUS: + inc si + loop CHKMAPLP2 + xor ax,ax + XCHG ax,[ORPHSIZ] ;number of orphans = zero + mov cx,OFFSET DG:FREEBYMES1 ;print msg + cmp [DOFIX],0 +; $IF Z + JNZ $$IF35 + mov cx,OFFSET DG:FREEBYMES2 + mov [LCLUS],ax ;move number of lost clust would be ;an049;bgb +; $ENDIF +$$IF35: +DISPFRB: ;ax=lost clusters (1-fff6) + push bx ;save it ;an049;bgb + push cx ;save it ;an049;bgb + mov cl,[csize] ;get sectors per cluster (1-32) ;an049;bgb + xor ch,ch ;zero out high byte ;an049;bgb + xor dx,dx ;zero out hi word for word mult ;an049;bgb + mul cx ;cx*ax=dx:ax lost sectors (1-1ffec0);an049;bgb + mov bx,dx ;move high word for call ;an049;bgb + mov cx,ssize ;word to mult with ;an049;bgb + call multiply_32_bits ;bx:ax is result ;an049;bgb + mov word ptr rarg1,ax ;low word into low word ;an049;bgb + mov word ptr rarg1+2,bx ;hi word into hi word ;an049;bgb + mov [free_arg1],ax + mov [free_arg2],bx ;an049;bgb + mov [free_arg3],cx + pop cx + pop bx + mov dx,cx ;Point to right message;an049;bgb + call printf_crlf + ret + + + + +;***************************************************************************** +; FINDCHAIN - +; +; called by - recover +; +; inputs: +; +; outputs: +; LOGIC - search thru entire fatmap +; - +; - +;*************************************************************************** +lostdeb equ 0 ;set private build version on ;an047;bgb +lost_str db '00000' ;max size of cluster number +FINDCHAIN: +;Do chain recovery on orphans + mov es,[FATMAP] ; point to fatmap + mov SI,2 ; point to fatmap + mov dx,si ; point to fatmap + mov cx,[DSIZE] ;get total number of clusters on disk +CHKMAPLP3: + mov al,es:[si] ;get next fatmap entry + inc si ;point to next fatmap entry + ;has to be an orphan(08) + TEST AL,8 ;Orphan? + jz NEXTCLUS2 ;Nope + ;make sure its not a regular file entry + TEST AL,1 ;Seen before ? + jnz NEXTCLUS2 ;Yup +;recover this chain + savereg ;Save search environment + dec SI + or byte ptr es:[si],81H ;Mark as seen and head + + + IF LOSTDEB ;is this private build version? + call lostdisp ;display lost cluster numbers + ENDIF + + add word ptr orphcnt,1 ;Found a chain + adc word ptr orphcnt+2,0 ;Found a chain + mov SI,dx ;point to the next fatmap entry +CHAINLP: + call UNPACK ;si = fat cell + XCHG SI,DI ;si=contents, di=cell number + cmp SI,[EOFVAL] ;is this the end of the file? + JAE CHGOON ;yes, then we are done + PUSH DI ;no, not eof +;dont do this next part if any of two conditions: +; 1. invalid cluster number +; 2. points to itself + cmp SI,2 ;well, is it a valid cluster number? + JB INSERTEOF ;Bad cluster number + cmp SI,[dsize] + JA INSERTEOF ;Bad cluster number + cmp SI,DI ;how bout if it points to itself? + jz INSERTEOF ;Tight loop +; find out what it points TO + call CROSSCHK + TEST AH,8 ;Points to a non-orphan? + jnz CHKCHHEAD ;Nope + ;orphan points to nothing +INSERTEOF: +; you come here if: +; 1. invalid cluster number +; 2. points to itself +; 3. points to nothing + POP SI ;the previous cluster number + mov dx,0FFFH ;get eof value (12-bit) + cmp [BIGFAT],0 + jz FAT12_4 + mov dx,0FFFFH ;get eof value (16-bit) +FAT12_4: + call PACK ;stick it in! + jmp SHORT CHGOON ;and we are done +; orphan point to a head entry +CHKCHHEAD: + TEST AH,80H ;Previosly marked head? + jz ADDCHAIN ;Nope + AND BYTE PTR es:[DI],NOT 80H ;Turn off head bit + sub word ptr orphcnt,1 ;Wasn't really a head + sbb word ptr orphcnt+2,0 ;Wasn't really a head + POP DI ;Clean stack + jmp SHORT CHGOON +ADDCHAIN: + TEST AH,1 ;Previosly seen? + jnz INSERTEOF ;Yup, don't make a cross link + or BYTE PTR es:[DI],1 ;Mark as seen + POP DI ;Clean stack + jmp CHAINLP ;Follow chain +CHGOON: + POP dx ;Restore search + POP cx + POP SI +NEXTCLUS2: + inc dx + loop CHKMAPLP3 + ret + + + +;***************************************************************************** ;ac048;bgb +; CHAINREC - the user has requested us to recover the lost clusters ;ac048;bgb +; ;ac048;bgb +; inputs: ;ac048;bgb +; note: although called from PROMPTRECOVER, this routine returns control to ;ac048;bgb +; recover via the ret instruction. ;ac048;bgb +;***************************************************************************** ;ac048;bgb + ;ac048;bgb +;***************************************************************************** ;ac048;bgb +; CHAINREC - The user has requested us to recover the lost clusters ;ac048;bgb +; ;ac048;bgb +; WARNING!! NOTE!! --> the count of the number of lost cluster chains remains, +; for this proc, a single word. More than 64k chains +; will cause this proc to fail. +; ;ac048;bgb +; called by - PROCEDURE NAME ;ac048;bgb +; ;ac048;bgb +; inputs: AX - N/A ;ac048;bgb +; bx - ;ac048;bgb +; cx - N/A ;ac048;bgb +; dx - N/A ;ac048;bgb +; SP - ;ac048;bgb +; BP - N/A ;ac048;bgb +; SI - N/A ;ac048;bgb +; DI - N/A ;ac048;bgb +; data: root_entries ;ac048;bgb +; orphcnt ;ac048;bgb +; ;ac048;bgb +; output: AX - ;ac048;bgb +; bx - ;ac048;bgb +; cx - ;ac048;bgb +; dx - ;ac048;bgb +; SP - ;ac048;bgb +; BP - ;ac048;bgb +; SI - ;ac048;bgb +; DI- ;ac048;bgb +; ;ac048;bgb +; Regs abused - ;ac048;bgb +; ;ac048;bgb +;logic: 1. ;ac048;bgb +;***************************************************************************** ;ac048;bgb + CHAINREC: ;ac048;bgb + push es ;save es if it is used for anything ;ac048;bgb + push ds ;make es point to data ;ac048;bgb + pop es ;ac048;bgb +;find the cluster number of the orphan ;ac048;bgb + mov SI,2 ;start at first cluster ;an005;bgb ;ac048;bgb + mov DI,1 ;point to previous cluster? ;ac048;bgb + call NEXTORPH ;di points to orphan ;ac048;bgb +;init for loop ;ac048;bgb + savereg ;save orphan, orphan+1 ;ac048;bgb + mov SI,DI ;si point to orphan ;ac048;bgb + xor ax,ax ;set count of dir entries processed to zero;ac048;bgb + mov dx,word ptr orphcnt ;get low word of lost clusters ;ac048;bgb;an049;bgb + mov word ptr temp_dd,dx ;get low word of lost clusters ;an049;bgb + mov dx,word ptr orphcnt+2 ;get hi word of lost clusters ;an049;bgb + mov word ptr temp_dd+2,dx ;get hi word of lost clusters ;an049;bgb + mov BP,OFFSET DG:PHONEY_STACK ;Set BP to point to "root" ;ac048;bgb +;do for all dir entries: ;ac048;bgb +MAKFILLP: ;ac048;bgb +; $DO ;do for all root entries ;ac048;bgb +$$DO37: + savereg ;cnt of entries processed, num orphans ;ac048;bgb;an049;bgb + call GETENT ;DI points to entry ;ac048;bgb + cmp BYTE PTR ds:[DI],0E5H ;is this dir entry erased? ;an;ac048;bgb005;bgb +; $if z,or ;ac048;bgb + JZ $$LL38 + cmp BYTE PTR ds:[DI],0 ;is this dir entry empty? ;an;ac048;bgb005;bgb +; $if z ;ac048;bgb + JNZ $$IF38 +$$LL38: +GOTENT: mov [HAVFIX],1 ;Making a fix ;ac048;bgb + cmp [DOFIX],0 ;/f parameter specified? ;ac048;bgb +; $if NZ ;yes- do the fix ;ac048;bgb + JZ $$IF39 + call fix_entry ;ac048;bgb +; $endif ;ac048;bgb +$$IF39: +ENTMADE: restorereg ;ac048;bgb;an049;bgb + sub word ptr temp_dd,1 ;finished with one orphan ;ac048;bgb;an049;bgb + sbb word ptr temp_dd+2,0 ;finished with one orphan ;ac048;bgb;an049;bgb + cmp word ptr temp_dd,0 ;is that the last one? ;ac048;bgb;an049;bgb +; $IF Z,AND ;no, check the hi word ;an049;bgb + JNZ $$IF41 + cmp word ptr temp_dd+2,0;is that the last one? ;ac048;bgb;an049;bgb +; $IF Z ;neither are zero ;an049;bgb + JNZ $$IF41 + jmp RET100 ; yes,we are done ;ac048;bgb;an049;bgb +; $endif ;an049;bgb +$$IF41: + call NEXTORPH ;get the cluster of the next one ;ac048;bgb + savereg ;ac048;bgb + mov SI,DI ;ac048;bgb +; $else ;dir entry was not erased or zero ;ac048;bgb + JMP SHORT $$EN38 +$$IF38: +NEXTENT: restorereg ;ac048;bgb;an049;bgb +; $endif ;ac048;bgb +$$EN38: +NXTORP: inc ax ;ac048;bgb + cmp ax,root_entries ;do for 0 to (root_entries - 1) ;ac048;bgb +; $leave z ;ac048;bgb + JZ $$EN37 +; $ENDDO ;ac048;bgb + JMP SHORT $$DO37 +$$EN37: + restorereg ;Clean Stack from si,di ;ac048;bgb + sub word ptr orphcnt,dx ;Couldn't make them all ;ac048;bgb + sbb word ptr orphcnt+2,0 ;Couldn't make them all ;ac048;bgb + mov dx,OFFSET DG:CREATMES ;ac048;bgb + mov byte ptr [arg_buf],0 ;ac048;bgb + call EPRINT ;ac048;bgb +RET100: pop es ;restore es ;ac048;bgb + ret ;ac048;bgb + ;ac048;bgb + ;ac048;bgb + ;ac048;bgb + +;***************************************************************************** +;***************************************************************************** +SUBTTL AMDONE - Finish up routine +PAGE +Public AmDone +AMDONE: +ASSUME DS:NOTHING + cmp [DIRTYFAT],0 + jz NOWRITE ;FAT not dirty + cmp [DOFIX],0 + jz NOWRITE ;Not supposed to fix +REWRITE: + LDS bx,[THISDPB] +ASSUME DS:NOTHING + mov cx,[bx.dpb_FAT_size] ;Sectors for one fat (DCR) ;AC000; + mov DI,cx + mov CL,[bx.dpb_FAT_count] ;Number of FATs + mov dx,[bx.dpb_first_FAT] ;First sector of FAT + PUSH CS + POP DS +ASSUME DS:DG + mov [ERRCNT],0 +; set up to write to the disk + xor bx,bx ;offset of the fat-table ;an005;bgb + mov es,fattbl_seg ;segment of the fat-table ;an005;bgb + mov AL,[ALLDRV] + dec AL + mov AH,1 + PUSH cx +WRTLOOP: + XCHG cx,DI + PUSH dx + PUSH cx + PUSH DI + PUSH ax + + call Write_Disk ;Do relative sector write ;AC000; + + JNC WRTOK + inc [ERRCNT] + ;mov [badrw_str],offset dg:writing + POP ax ; Get fat # in AH + PUSH ax ; Back on stack + xchg al,ah ; Fat # to AL + xor ah,ah ; Make it a word + mov [badrw_num],ax + mov dx,offset dg:badw_arg + call PRINTf_crlf +WRTOK: + POP ax + POP cx + POP DI + POP dx + inc AH + ADD dx,DI + loop WRTLOOP ;Next FAT + POP cx ;Number of FATs + cmp CL,[ERRCNT] ;Error on all? +; $if e + JNE $$IF47 + jmp fatal +; $endif +$$IF47: +; make sure that the data fields are always adressable, because +;we can come here after a ctl - break has happened. so point to them w/ cs: +NOWRITE: + DOS_Call Disk_Reset ; ;AC000; + mov dx,OFFSET DG:USERDIR ;Recover users directory + DOS_Call ChDir ; ;AC000; + cmp BYTE PTR cs:[FRAGMENT],1 ;Check for any fragmented files? ;an029;bgb + jnz DONE ;No -- we're finished + call CHECKFILES ;Yes -- report any fragments +Public Done +DONE: +ASSUME DS:NOTHING + mov DL,cs:[USERDEV] ;Recover users drive ;an029;bgb + DOS_Call Set_Default_Drive ; ;AC000; + ret + + + + + + + + + + IF LOSTDEB ;is this private build version? +Procedure lostdisp,near ;an005;bgb + savereg ; ;an005;bgb + mov ax,dx ;save orig value + + mov cl,12 ;shift 3 nibbles + shr dx,cl ;remove al but last nibble + and dx,000fh + cmp dx,0ah +; $IF B + JNB $$IF49 + add dx,30h ;make it char +; $ELSE + JMP SHORT $$EN49 +$$IF49: + add dx,37h +; $ENDIF +$$EN49: + push ax + mov ah,2 + int 21h + pop ax + + mov dx,ax ;get orig value + mov cl,8 + shr dx,cl + and dx,000fh + cmp dx,0ah +; $IF B + JNB $$IF52 + add dx,30h ;make it char +; $ELSE + JMP SHORT $$EN52 +$$IF52: + add dx,37h +; $ENDIF +$$EN52: + push ax + mov ah,2 + int 21h + pop ax + + mov dx,ax ;get orig value + mov cl,4 + shr dx,cl + and dx,000fh + cmp dx,0ah +; $IF B + JNB $$IF55 + add dx,30h ;make it char +; $ELSE + JMP SHORT $$EN55 +$$IF55: + add dx,37h +; $ENDIF +$$EN55: + push ax + mov ah,2 + int 21h + pop ax + + mov dx,ax ;get orig value + and dx,000fh + cmp dx,0ah +; $IF B + JNB $$IF58 + add dx,30h ;make it char +; $ELSE + JMP SHORT $$EN58 +$$IF58: + add dx,37h +; $ENDIF +$$EN58: + mov ah,2 + int 21h + + mov dl,' ' ;space after last number + mov ah,2 + int 21h + + restorereg ;an005;bgb + return ;an005;bgb +EndProc lostdisp ;an005;bgb +ENDIF + + + pathlabl chkfat + + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKINIT.ASM b/v4.0/src/CMD/CHKDSK/CHKINIT.ASM new file mode 100644 index 0000000..d904553 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKINIT.ASM @@ -0,0 +1,1548 @@ +page ,132 ; +;***************************************************************************** +;***************************************************************************** +;UTILITY NAME: CHKOVER.COM +; +;MODULE NAME: CHKINIT.SAL +; +;ÚÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Main_Init ³ +;ÀÄÂÄÄÄÄÄÄÄÄÄÙ +; ³ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôInit_Input_OutputÃÄÄÄÄ´Preload_Messages³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ôParse_Drive_Letter ³ +; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ôParse_Command_Line ³ +;; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ À´Interpret_Parse³ +; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôValidate_Target_DriveôCheck_Target_Drive³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ôCheck_For_Network³ +; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ À´Check_Translate_Drive³ +; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôHook_Interrupts³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôClear_Append_X³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôCHKDSK_IFSôEXEC_FS_CHKDSK³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ À´Main_Routine³ +; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; À´Reset_Append_X³ +; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +;***************************************************************************** +;;an099;dcl for p3202 +;***************************************************************************** + +; +;***************************************************************************** +; Include files +;***************************************************************************** +.xlist ;an000;bgb +include chkseg.inc ;an005;bgb ;an000;bgb +include pathmac.inc ;an000;bgb +INCLUDE CHKEQU.INC ; ;an000;bgb;AN000; +INCLUDE CHKCHNG.INC ;List of changes ;an000;bgb +include dossym.inc ;an000;bgb +INCLUDE SYSCALL.INC ; ;an000;bgb;AN000; +INCLUDE CHKMACRO.INC ; ;an000;bgb;AN000; +INCLUDE CHKPARSE.INC ; ;an000;bgb;AN000; +INCLUDE IOCTL.INC ;an000;bgb +.list ;an000;bgb + ;an000;bgb + ;an000;bgb + ;an000;bgb +psp segment public para 'DUMMY' ;an000;bgb + org 05Ch ;an000;bgb +FCB1 label byte ;an000;bgb + org 06Ch ;an000;bgb +FCB2 label byte ;an000;bgb +psp ends ;an000;bgb + ;an000;bgb +; ;an000;bgb +DATA segment public para 'DATA' ;an000;bgb +;***************************************************************************** ;an000;bgb +; Data Area ;an000;bgb +;***************************************************************************** ;an000;bgb +old_drive db 0 ;an000;bgb + +include version.inc + +IF IBMCOPYRIGHT + +ELSE + +myramdisk db 'RDV 1.20' + +ENDIF + +myvdisk db 'VDISK' ;an000;bgb +bytes_per_sector dw 0 ;an005;bgb ;an000;bgb +BPB_Buffer A_DeviceParameters <> ; ;an000;bgb;AN000; + ;an000;bgb +Data_Start_Low dw ? ; ;an000;bgb;AN000; +Data_Start_High dw ? ; ;an000;bgb + ;an000;bgb +public command_line_buffer ;an046;bgb +Command_Line_Buffer db 128 dup(0) ; ;an000;bgb;AN000; +Command_Line_Length equ $ - Command_Line_Buffer ; ;an000;bgb;AN000; + ;an046;bgb +Fatal_Error db 0 ; ;an000;bgb;AN000; + ;an000;bgb +Command_Line db NO ; ;an000;bgb +Append db 0 ; ;an000;bgb + ;an000;bgb +ifdef fsexec ;an038;bgb + ;These should stay together ; ;an038;bgb + ; --------------------------------------- ; ; ;an038;bgb + FS_String_Buffer db 13 dup(" ") ; ;an038;bgb + FS_String_End db "CHK.EXE",0 ; ;an038;bgb + Len_FS_String_End equ $ - FS_String_End ; ;an038;bgb + ;---------------------------------------- ; ;an038;bgb + FS_Not_Fat db 0 ; ;an038;bgb + FAT12_String db "FAT12 " ; ;an038;bgb + FAT16_String db "FAT16 " ; ;an038;bgb + Len_FS_ID_String equ $ - FAT16_String ; ;an038;bgb + Media_ID_Buffer Media_ID <> ; ;an038;bgb +endif ;an038;bgb + +ExitStatus db 0 ; ;an000;bgb;AN000; + ;an000;bgb +PSP_Segment dw 0 ; ;an000;bgb;AN000; +tot_bytes_lo dw 0 ; low word of number of sectors in disk ;an000;bgb;an006;bgb +tot_bytes_hi dw 0 ;high word of number of sectors in disk ;an000;bgb;an006;bgb +fat_dir_secs dw 0 ;sectors in fat, directory and resvd ;an000;bgb;an006;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +; Public Data Declarations ;an000;bgb +;***************************************************************************** ;an000;bgb + public bpb_buffer ;an000;bgb;an006;bgb + public tot_bytes_lo ;an000;bgb;an006;bgb + public tot_bytes_hi ;an000;bgb;an006;bgb + public fat_dir_secs ;an000;bgb;an006;bgb + public bytes_per_sector ;an000;bgb;an005;bgb + Public Data_Start_Low ;an000;bgb + Public Data_Start_High ;an000;bgb + Public Fatal_Error ;an000;bgb + Public ExitStatus ;an000;bgb + Public PSP_Segment ;an000;bgb +ifdef fsexec ;an038;bgb + Public FS_String_Buffer ;an038;bgb +endif ;an038;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; External Data Declarations ;an000;bgb +;***************************************************************************** ;an000;bgb + EXTRN movsi:word ;move si pointer here for display of invalid parm ;an046;bgb;an000;bgb;an005;bgb + EXTRN fatcnt:Byte ;an000;bgb;an005;bgb + EXTRN AllDrv:Byte ;an000;bgb + EXTRN VolNam:Byte ;an000;bgb + EXTRN BadDrvM:Byte ;an000;bgb + EXTRN OrphFCB:Byte ;an000;bgb + EXTRN Arg_Buf:Byte ;an000;bgb + EXTRN Noisy:Byte ;an000;bgb + EXTRN DoFix:Byte ;an000;bgb + EXTRN SubstErr:Byte ;an000;bgb + EXTRN No_Net_Arg:Byte ;an000;bgb + EXTRN UserDev:Byte ;an000;bgb + EXTRN BadDrv_Arg:Byte ;an000;bgb + EXTRN TranSrc:Byte ;an000;bgb + EXTRN ContCh:Word ;an000;bgb + EXTRN HardCh:Word ;an000;bgb + EXTRN Fragment:Byte ;an000;bgb + EXTRN Parse_Error_Msg:Byte ;an000;bgb + EXTRN Chkprmt_End:Byte ;an000;bgb + extrn save_drive:byte ;an000;bgb + EXTRN Read_Write_Relative:Byte ;an000;bgb + EXTRN inval_media:byte ;an000;bgb;an033;bgb +data ends ;an000;bgb + ;an000;bgb + ;an000;bgb +code segment public para 'CODE' ;an000;bgb +;***************************************************************************** ;an000;bgb +; External Routine Declarations ;an000;bgb +;***************************************************************************** ;an000;bgb +ifdef fsexec ;an038;bgb + EXTRN Exec_FS_CHKDSK:Near ;an000;bgb +endif + EXTRN SysLoadMsg:Near ;an000;bgb + EXTRN SysDispMsg:Near ;an000;bgb + EXTRN Done:Near ;an000;bgb + EXTRN Main_Routine:Near ;an000;bgb + EXTRN INT_23:Near ;an000;bgb + EXTRN INT_24:Near ;an000;bgb + EXTRN Path_Name:Near ;an000;bgb + extrn read_once:near ;an000;bgb + + public p97, multiply_32_bits ;an000;bgb + public func60 ;an000;bgb + public hook_interrupts ;an000;bgb + public get_bpb ;an000;bgb + + pathlabl chkinit ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Main_Init ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Main control routine for init section ;an000;bgb +; ;an000;bgb +;Called Procedures: Check_DOS_Version ;an000;bgb +; Init_Input_Output ;an000;bgb +; Validate_Target_Drive ;an000;bgb +; Hook_Interrupts ;an000;bgb +; Clear_Append_X ;an000;bgb +; CHKDSK_IFS ;an000;bgb +; Reset_Append_X ;an000;bgb +; ;an000;bgb +;Input: None ;an000;bgb +; ;an000;bgb +;Output: None ;an000;bgb +; ;an000;bgb +;Change History: Created 5/8/87 MT ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Set segregs to DATA ;an000;bgb +; Get segment of PSP ;an000;bgb +; Fatal_Error = NO ;an000;bgb +; Flush all buffers (INT 21h AH=0Dh) ;an000;bgb +; Parse input and load messages (CALL Init_Input_Output) ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; Check target drive letter (CALL Validate_Target_Drive) ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; Set up Control Break (CALL Hook_Interrupts) ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; CALL Clear_Append_X ;an000;bgb +; CALL CHKDSK_IFS ;an000;bgb +; CALL Reset_Append_X ;an000;bgb +; ENDIF ;an000;bgb +; ENDIF ;an000;bgb +; ENDIF ;an000;bgb +; Exit program ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Main_Init ; ;an000;bgb;AN000; + Set_Data_Segment ;Setup addressibility ;an000;bgb;AN000; + call get_psp ;an000;bgb +;;;;;;;;DOS_Call GetCurrentPSP ;Get PSP segment address ;an000;bgb;ac034;bgb +;;;;;;;;mov PSP_Segment,bx ;Save it for later ;an000;bgb;ac034;bgb + mov Fatal_Error,No ;Init the error flag ;an000;bgb;AN000; + Dos_Call Disk_Reset ;Flush all buffers ;an000;bgb + call Init_IO ;Setup messages and parse ;an000;bgb;AN000; + cmp Fatal_Error,Yes ;Error occur? ;an000;bgb;AN000; +; $IF NE ;Nope, keep going ;an000;bgb;AN000; + JE $$IF1 + call Validate_Target_Drive ;Check drive letter ;an000;bgb;AN000; + cmp Fatal_Error,Yes ;Error occur? ;an000;bgb;AN000; +; $IF NE ;Nope, keep going ;an000;bgb;AN000; + JE $$IF2 +;;;;;;;;;;;;;;call Hook_Interrupts ;Set CNTRL -Break hook ;an000;bgb;AN000; + call Clear_Append_X ; ;an000;bgb;AN000; + call CHKDSK_IFS ;Chkdsk correct file system ;an000;bgb;AN000; + call Reset_Append_X ; ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF2: +; $ENDIF ; ;an000;bgb;AN000; +$$IF1: + mov al,ExitStatus ;Get Errorlevel ;an000;bgb;AN000; + DOS_Call Exit ;Exit program ;an000;bgb;AN000; + int 20h ;If other exit fails ;an000;bgb;AN000; +Main_Init endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: get_psp ;an000;bgb +;***************************************************************************** ;an000;bgb +;Description: get info from the psp area ;an000;bgb +; ;an000;bgb +;Called Procedures: get_drive ;an000;bgb +; ;an000;bgb +;Change History: Created 8/7/87 bgb ;an000;bgb +; ;an000;bgb +;Input: none ;an000;bgb +; ;an000;bgb +;Output: psp_segment ;an000;bgb +; command_line_buffer ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; get addr of psp ;an000;bgb +; move command line into data seg ;an000;bgb +; get drive number of target ;an000;bgb +; get addr of data seg ;an000;bgb +; call get_drive ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Procedure get_psp ;;AN000; ;an000;bgb +;;;;;;;;DOS_Call GetCurrentPSP ;Get PSP segment address :AN035;b;an000;bgbgb +;;;;;;;;mov PSP_Segment,bx ;Save it for later ;AN035;b;an000;bgbgb +; get command line from psp ;an000;bgb;AN000;bgb + mov cx,PSP_Segment ;point ds to data seg ;an000;bgb;AN000;bgb + mov ds,cx ; " " " " " ;an000;bgb;AN000;bgb + assume ds:NOTHING,es:dg ; " " " " " ;an000;bgb;AN000;bgb +; get the drive number of the target from the psp (0=default, a=1, b=2, c=3) ;AN;an000;bgb000;bgb + mov bl,ds:[FCB1] ;Get target drive from FCB -74 ;AN0;an000;bgb00; + Set_Data_Segment ;Set DS,ES to Data segment ;AN0;an000;bgb00;bgb + call get_drive ;an000;bgb + ret ;an000;bgb +get_psp endp ; ;AN000; ;an000;bgb + ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: get_drive ;an000;bgb +;***************************************************************************** ;an000;bgb +;Description: get drive letter from reg bl ;an000;bgb +; ;an000;bgb +;Change History: Created 8/7/87 bgb ;an000;bgb +; ;an000;bgb +;Input: bl = drive num (default=0) ;an000;bgb +; ;an000;bgb +;Output: driveletter ;an000;bgb +; user_drive ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; IF drive-num = default ;an000;bgb +; get default drive number (a=1) ;an000;bgb +; convert to letter ;an000;bgb +; ELSE ;an000;bgb +; convert to letter ;an000;bgb +; ENDIF ;an000;bgb +; move letter into data areas ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Procedure get_drive ;;AN000; ;an000;bgb +; convert drive number to drive letter ;an000;bgb + cmp bl,0 ;a=1 b=2 c=3 ;Is it default drive? 0=default ;AN000; ;an000;bgb +; $IF E ;Yes, turn it into drive letter ;AN000; ;an000;bgb + JNE $$IF5 +; get default drive number ;an000;bgb + DOS_Call Get_Default_Drive ;Get default drive num in al ;AN00;an000;bgb0; + ;a=0, b=1, c=2 ;an000;bgb +; $ELSE ;Not default, A=1 ;AN000; ;an000;bgb + JMP SHORT $$EN5 +$$IF5: +; bl already contains the correct drive number - save it ;an000;bgb + dec bl ;make it zero based ;an000;bgb + mov al,bl ;an000;bgb +; $ENDIF ; 74+40=b4 ;an000;bgb +$$EN5: + mov BadDrvm+1,al ; " " " " ;an000;bgb ;AN000; + inc al ;an000;bgb + mov byte ptr Buffer.drnum_stroff,al ; ;an000;bgb ; + mov AllDrv,al ; ;an000;bgb ;AC000; + mov VolNam,al ; ;an000;bgb ;AC000; + mov OrphFCB,al ; ;an000;bgb ;AC000; + dec al ;an000;bgb + add al,"A" ;convert it to letter ;AN000; ;an000;bgb + mov arg_buf,al ;set up prompt msg ;AN0;an000;bgb00;bgb + ret ;an000;bgb +get_drive endp ; ;AN000; ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Init_Input_Output ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;description: Initialize messages, Parse command line if FAT file system ;an000;bgb +; ;an000;bgb +;Called Procedures: Preload_Messages ;an000;bgb +; Parse_Command_Line ;an000;bgb +; ;an000;bgb +;Change History: Created 5/10/87 MT ;an000;bgb +; ;an000;bgb +;Input: PSP command line at 81h and length at 80h ;an000;bgb +; ;an000;bgb +;Output: FS_Not_FAT = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; FS_Not_FAT = NO ;an000;bgb +; Load messages (CALL Preload_Messages) ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; Get file system type (INT 21h AX=440Dh, CX=084Eh GET MEDIA_ID) ;an000;bgb +; IF CY (Old type diskette),OR ;an000;bgb +; IF "FAT_12 ",OR ;an000;bgb +; IF "FAT_16 " ;an000;bgb +; CALL Parse_Command_Line ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; Interpret_Parse ;an000;bgb +; ENDIF ;an000;bgb +; ELSE ;an000;bgb +; Get drive letter only (CALL Parse_Drive_Letter) ;an000;bgb +; FS_Not_FAT = YES ;an000;bgb +; ENDIF ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Init_IO ; ;AN000; ;an000;bgb + ;an000;bgb + call Preload_Messages ;Load up message retriever ;an000;bgb;AN000; +ifdef fsexec ;an038;bgb + mov FS_Not_FAT,No ;an038;bgb + cmp Fatal_Error,YES ;Quit? ;an038;bgb;AN000; +; $IF NE ;Nope, keep going ;an038;bgb;AN000; + JE $$IF8 + mov al,GENERIC_IOCTL ;Generic IOCtl call ;an038;bgb;AN000; + push ds ; ;an038;bgb;AN000; + mov bx,PSP_Segment ; ;an038;bgb;AN000; + mov ds,bx ; ;an038;bgb;AN000; + assume ds:nothing ; ;an038;bgb;AN000; + ;an038;bgb + mov bl,ds:FCB1 ;Get drive (A=1) ;an038;bgb;AN000; + ;an038;bgb + pop ds ; ;an038;bgb;AN000; + assume ds:dg ; ;an038;bgb;AN000; + xor bh,bh ;Set bh=0 ;an038;bgb;AN000; + mov ch,RawIO ;Get Media ID call ;an038;bgb;AN000; + mov cl,GET_MEDIA_ID ; ;an038;bgb;AN000; + lea dx,Media_ID_Buffer ;Point at buffer ;an038;bgb;AN000; + DOS_Call IOCtl ;Do function call ;an038;bgb;AN000; +; $IF C,OR ;Old style diskette, OR ;an038;bgb;AN000; + JC $$LL9 + lea si,FAT12_String ;Check for FAT_12 string ;an038;bgb;AN000; + lea di,Media_ID_Buffer.Media_ID_File_System ; ;AN000;;an038;bgb + mov cx,Len_FS_ID_String ;Length of compare ;an038;bgb;AN000; + repe cmpsb ;Find it? ;an038;bgb;AN000; +; $IF E,OR ;Nope, keep going ;an038;bgb;AN000; + JE $$LL9 + lea si,FAT16_String ;Check for FAT_16 string ;an038;bgb;AN000; + lea di,Media_ID_Buffer.Media_ID_File_System ; ;AN000;;an038;bgb + mov cx,Len_FS_ID_String ;Length of compare ;an038;bgb;AN000; + repe cmpsb ;Do compare ;an038;bgb;AN000; +; $IF E ;Find it? ;an038;bgb;AN000; + JNE $$IF9 +$$LL9: +endif ;an038;bgb + call Parse_Command_Line ;Parse in command line input ;an038;bgb;AN000; +ifdef fsexec ;an038;bgb +; $ELSE ;We got FS other than FAT ;an038;bgb;AN000; + JMP SHORT $$EN9 +$$IF9: +;;;;;;;;;;;;;;call Parse_Drive_Letter ;Only look for drive letter ;an038;bgb;AN000; + mov FS_Not_FAT,Yes ;Indicate exec file system ;an038;bgb;AN000; + mov cx,8 ;an038;bgb;an027;bgb + lea si,Media_ID_Buffer.Media_ID_File_System ;get file system;an038;bgb ;an027;bgb + lea di,fs_string_buffer ;put it here ;an038;bgb;an027;bgb + rep movsb ;an038;bgb;an027;bgb + lea di,fs_string_buffer ;point to beginning again ;an038;bgb;an027;bgb +; $DO COMPLEX ;search th string until eol found ;an038;bgb;an027;bgb + JMP SHORT $$SD11 +$$DO11: + inc di ;next char ;an038;bgb;an027;bgb +; $STRTDO ;start loop here ;an038;bgb;an027;bgb +$$SD11: + cmp byte ptr [di],' ' ;end of string ? ;an038;bgb;an027;bgb +; $ENDDO E ;end loop when eol found ;an038;bgb;an027;bgb + JNE $$DO11 + lea si,fs_string_end ;get end of string - rec.exe ;an038;bgb;an027;bgb + mov cx,8 ; 8 more chars ;an038;bgb;an027;bgb + rep movsb ;move it in ;an038;bgb;an027;bgb +; $ENDIF ; ;an038;bgb;AN000; +$$EN9: +; $ENDIF ; ;an038;bgb;AN000; +$$IF8: +endif ;an038;bgb + ret ; ;an000;bgb;AN000; + ;an000;bgb +Init_IO endp ; ;AN000; ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Preload_Messages ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Preload messages using common message retriever routines. ;an000;bgb +; ;an000;bgb +;Called Procedures: SysLoadMsg ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Fatal_Error = NO ;an000;bgb +; ;an000;bgb +;Output: Fatal_Error = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Preload All messages (Call SysLoadMsg) ;an000;bgb +; IF error ;an000;bgb +; Display SysLoadMsg error message ;an000;bgb +; Fatal_Error = YES ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Preload_Messages ; ;an000;bgb;AN000; + ; ;an000;bgb + call SysLoadMsg ;Preload the messages ;an000;bgb;AN000; +; $IF C ;Error? ;an000;bgb;AN000; + JNC $$IF16 + call SysDispMsg ;Display preload msg ;an000;bgb;AN000; + mov Fatal_Error, YES ;Indicate error exit ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF16: + ret ; ;an000;bgb;AN000; + ;an000;bgb +Preload_Messages endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Parse_Drive_Letter ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Copy the command line - then parse looking only for drive ;an000;bgb +; letter. Ignore errors, because this is only called to get ;an000;bgb +; the drive letter for non-FAT chkdsk ;an000;bgb +; ;an000;bgb +;Called Procedures: SysParse ;an000;bgb +; ;an000;bgb +;Change History: Created 5/12/87 MT ;an000;bgb +; ;an000;bgb +;Input: Command line input at 81h ;an000;bgb +; ;an000;bgb +;Output: None ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; Copy command line to buffer ;an000;bgb +; DO ;an000;bgb +; Parse buffer line (CALL SysParse) using drive letter only tables ;an000;bgb +; LEAVE end of parse ;an000;bgb +; ENDDO missing operand ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +;Procedure Parse_Drive_Letter ; ;an000;bgb;AN000; +; Set_Data_Segment ;Set DS,ES to Data segment ;an000;bgb;AN000; +; mov cx,PSP_Segment ;Get segment of PSP ;an000;bgb;AN000; +; mov ds,cx ; " " " " ;an000;bgb;AN000; +; assume ds:nothing ; ;an000;bgb;AN000; +; mov si,Command_Line_Parms ;Point to command line ;an000;bgb;AN000; +; lea di,Command_Line_Buffer ;Point to buffer to save to ;an000;bgb;AN000; +; mov cx,Command_Line_Length ;Number of bytes to move ;an000;bgb;AN000; +; rep movsb ;Copy the entire buffer ;an000;bgb;AN000; +; Set_Data_Segment ; ;an000;bgb;AN000; +; lea si,Command_Line_Buffer ;Pointer to parse line ;an000;bgb;AN000; +; lea di,input_table ;Pointer to control table ;an000;bgb;AN000; +; $DO ;Parse for drive letter ;an000;bgb;AN000; +; xor dx,dx ;Parse line @SI ;an000;bgb;AN000; +; xor cx,cx ;Parse table @DI ;an000;bgb;AN000; +; call SysParse ;Go parse ;an000;bgb;AN000; +; cmp ax,End_Of_Parse ;Check for end of parse ;an000;bgb;AN000; +; $LEAVE E ;In other words, no drive letter;an000;bgb;AN000; +; cmp ax,Operand_Missing ; exit if positional missing ;an000;bgb;AN000; +; $ENDDO E ;Ignore errors!!! ;an000;bgb;AN000; +; Set_Data_Segment ; ;an000;bgb;AN000; +; ret ; ;an000;bgb;AN000; +; ;an000;bgb +;Parse_Drive_Letter endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Parse_Command_Line ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Parse the command line. Check for errors, and display error and ;an000;bgb +; exit program if found. Use parse error messages except in case ;an000;bgb +; of no parameters, which has its own message ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; SysParse ;an000;bgb +; Interpret_Parse ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Fatal_Error = NO ;an000;bgb +; PSP_Segment ;an000;bgb +; ;an000;bgb +;Output: Fatal_Error = YES/NO ;an000;bgb +; Parse output buffers set up ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; SEARCH ;an000;bgb +; Parse command line (CALL SysParse) ;an000;bgb +; EXITIF end of parsing command line ;an000;bgb +; Figure out last thing parsed (Call Interpret_Parse) ;an000;bgb +; ORELSE ;an000;bgb +; See if parse error ;an000;bgb +; ENDLOOP parse error ;an000;bgb +; See what was parsed (Call Interpret_Parse) ;an000;bgb +; Fatal_Error = YES ;an000;bgb +; ENDSRCH ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Parse_Command_Line ; ;an000;bgb;AN000; + ;an000;bgb + push ds ;Save data segment ;an000;bgb;AN000; + Set_Data_Segment ; ;an000;bgb;AN000; + mov cx,PSP_Segment ;Get segment of PSP ;an000;bgb;AN000; + mov ds,cx ; " " " " ;an000;bgb;AN000; + ;an000;bgb + assume ds:nothing,es:dg ; ;an000;bgb;AN000; + ;an000;bgb + mov si,Command_Line_Parms ;Point at command line ;an000;bgb;AN000; + lea di,Command_Line_Buffer ;Where to put a copy of it ;an000;bgb;AN000; + mov cx,Command_Line_Length ;How long was input? ;an000;bgb;AN000; + repnz movsb ;Copy it ;an000;bgb;AN000; + lea Di,Command_Line_Buffer ; ;an046;bgb +public nextdi ;an046;bgb +nextdi: ;an046;bgb + mov al,0dh ;search for end of line ;an046;bgb + cmp al,ES:[Di] ;zero terminate string ;an046;bgb +; $IF NZ ;an046;bgb + JZ $$IF18 + inc di ;an046;bgb + jmp nextdi ;an046;bgb +; $ELSE ;an046;bgb + JMP SHORT $$EN18 +$$IF18: + mov byte ptr ES:[di+1],00 ;an046;bgb +; $ENDIF ;an046;bgb +$$EN18: + ;an046;bgb + Set_Data_Segment ;Set DS,ES to Data segment ;an000;bgb;AN000; + xor cx,cx ; ;an000;bgb;AN000; + xor dx,dx ;Required for SysParse call ;;an000;bgbAN000; + lea si,Command_Line_Buffer ;Pointer to parse line ;an000;bgb ;AN000; + lea di,input_table ;Pointer to control table ;an000;bgb ;AN000; +; $SEARCH ;Loop until all parsed ;an000;bgb;AN000; +$$DO21: + cmp Fatal_Error,Yes ;Interpret something bad? ;an000;bgb;AN000; +; $EXITIF E,OR ;If so, don't parse any more ;an000;bgb;AN000; + JE $$LL22 + call SysParse ;Go parse ;an000;bgb;AN000; + cmp ax,End_Of_Parse ;Check for end of parse ;an000;bgb;AN000; +; $EXITIF E ;Is it? ;an000;bgb;AN000; + JNE $$IF21 +$$LL22: + ;All done ;an000;bgb;AN000; +; $ORELSE ;Not end ;an000;bgb;AN000; + JMP SHORT $$SR21 +$$IF21: + cmp ax,0 ;Check for parse error ;an000;bgb;AN000; +; $LEAVE NE ;Stop if there was one ;an000;bgb;AN000; + JNE $$EN21 + call Interpret_Parse ;Go find what we parsed ;an000;bgb;AN000; +; $ENDLOOP ;Parse error, see what it was ;an000;bgb;AN000; + JMP SHORT $$DO21 +$$EN21: + + dec si ;point to last byte of invalid parm +public decsi +decsi: cmp byte ptr [si],' ' ;are we pointing to a space? ;an046;bgb +; $IF E,OR ;if so, we dont want to do that + JE $$LL26 + cmp byte ptr [si],0dh ;are we pointing to CR? ;an046;bgb +; $IF E ;if so, we dont want to do that + JNE $$IF26 +$$LL26: + dec si ;find the last byte of parm + jmp decsi +; $ENDIF +$$IF26: + mov byte ptr [si+1],00 ;zero terminate display string ;an046;bgb +nextsi: +public nextsi + dec si ;look at previous char ;an046;bgb + cmp byte ptr [si],' ' ;find parm separator ;an046;bgb + jnz nextsi ;loop until begin of parm found + mov movsi,si ;mov si into display parms ;an046;bgb + PARSE_MESSAGE ;Display parse error ;an000;bgb;AN000; + mov Fatal_Error,YES ;Indicate death! ;an000;bgb;AN000; +; $ENDSRCH ; ;an000;bgb;AN000; +$$SR21: + pop ds ; ;an000;bgb;AN000; + ret ; ;an000;bgb;AN000; + ;an000;bgb +Parse_Command_Line endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Interpret_Parse ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;description: Get any switches entered, and dr ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: DS:DrNum (FCB at 5Ch) ;an000;bgb +; ;an000;bgb +;Output: Noisy = ON/OFF ;an000;bgb +; DoFix = ON/OFF ;an000;bgb +; ALLDRV = Target drive, A=1 ;an000;bgb +; VOLNAM = Target drive, A=1 ;an000;bgb +; ORPHFCB = Target drive, A=1 ;an000;bgb +; BADDRVm+1 = Target drive, A=0 ;an000;bgb +; Arg_Buf = Target drive letter ;an000;bgb +; Fragment > 1 if filespec entered ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Noisy = OFF ;an000;bgb +; DoFix = OFF ;an000;bgb +; IF /V ;an000;bgb +; Noisy = ON ;an000;bgb +; ENDIF ;an000;bgb +; IF /F ;an000;bgb +; DoFix = ON ;an000;bgb +; ENDIF ;an000;bgb +; IF file spec entered ;an000;bgb +; Build filename ;an000;bgb +; Fragment = 1 ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Interpret_Parse ; ;an000;bgb;AN000; + ;an000;bgb + push ds ;Save segment ;an000;bgb;AN000; + push si ;Restore SI for parser ;an000;bgb;AN000; + push cx ; ;an000;bgb;AN000; + push di ; ;an000;bgb + Set_Data_Segment ; ;an000;bgb + cmp byte ptr Buffer.dfType,Type_Drive ;Have drive letter? ;AN000; ;an000;bgb +; $IF E ;Yes, save info ;an000;bgb;AN000; + JNE $$IF29 + and word ptr dfcontrol,filespec ;dont let another drive letter ;an000;bgb + mov al,byte ptr Buffer.Drnum_stroff ;Get drive entered ;;an000;bgbAN000; + mov AllDrv,al ; ;an000;bgb;AC000; + mov VolNam,al ; ;an000;bgb;AC000; + mov OrphFCB,al ; ;an000;bgb;AC000; + dec al ;Make it 0 based ;an000;bgb;AN000; + mov BadDrvm+1,al ; " " " " ;an000;bgb;AN000; + add al,'A' ;Make it a drive letter ;an000;bgb;AN000; + mov Arg_Buf,al ;Save it ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF29: + cmp SwBuffer.Switch_Pointer,offset Sw_v ;AN020;;an000;bgbbgb +; $IF E ; ;an000;bgb;AN000; + JNE $$IF31 + mov Noisy,ON ;Set flag ;an000;bgb;AC000; + mov byte ptr sw_v,blank ;an000;bgb;an020;bgb +; $ENDIF ; ;an000;bgb;AN000; +$$IF31: + cmp SwBuffer.Switch_Pointer,offset sw_f ;AN020;;an000;bgbbgb +; $IF E ; ;an000;bgb;AN000; + JNE $$IF33 + mov DoFix,ON ;Set flag ;an000;bgb;AC000; + mov byte ptr sw_f,blank ;;an000;bgban020;bgb +; $ENDIF ; ;an000;bgb;AN000; +$$IF33: +;;;;;;; cmp FileSpec_Buffer.FileSpec_Pointer,offset FileSpec_Control.Keyword;an000;bgb ;AN000; + cmp buffer.dftype, type_filespec ;an000;bgb +; $IF E ; ;an000;bgb;AN000; + JNE $$IF35 + mov word ptr dfcontrol,0 ;dont let another drive letter or filesp;an000;bgbec + mov si,Buffer.drnum_StrOff ; ;AN000; ;an000;bgb + lea di,Path_Name ;Point to where to build path ;an000;bgb;AN000; + cld ;SI-DI dir is up ;an000;bgb;AN000; +; $DO ;Move string one char at a time ;an000;bgb;AN000; +$$DO36: + cmp byte ptr [si],Asciiz_End ;Is it the end? ;an000;bgb;AN000; +; $LEAVE E ;You got it ;an000;bgb;AN000; + JE $$EN36 + movsb ;Nope, move the character ;an000;bgb;AN000; +; $ENDDO ;And keep crusin ;an000;bgb;AN000; + JMP SHORT $$DO36 +$$EN36: + inc fragment ;To be compat with old code ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF35: + pop di ;Restore parse regs ;an000;bgb;AN000; + pop cx ; ;an000;bgb;AN000; + pop si ; ;an000;bgb;AN000; + pop ds ; ;an000;bgb;AN000; + ret ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +Interpret_Parse endp ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Validate_Target_Drive ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Control routine for validating the specified format target drive. ;an000;bgb +; If any of the called routines find an error, they will print ;an000;bgb +; message and terminate program, without returning to this routine ;an000;bgb +; ;an000;bgb +;Called Procedures: Check_Target_Drive ;an000;bgb +; Check_For_Network ;an000;bgb +; Check_Translate_Drive ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Fatal_Error = NO ;an000;bgb +; ;an000;bgb +;Output: Fatal_Error = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; CALL Check_Target_Drive ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; CALL Check_For_Network ;an000;bgb +; IF !Fatal_Error ;an000;bgb +; CALL Check_Translate_Drive ;an000;bgb +; ENDIF ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Validate_Target_Drive ; ;an000;bgb;AN000; + call Check_For_Network ;See if Network drive letter ;an000;;an043;bgbbgb;AN000; + cmp Fatal_Error,YES ;Can we continue? ;an0;an043;bgb00;bgb;AN000; +; $IF NE ;Yep ;an0;an043;bgb00;bgb;AN000; + JE $$IF40 + call Check_Target_Drive ;See if valid drive letter ;an000;bgb;AN000; + cmp Fatal_Error,YES ;Can we continue? ;an000;bgb;AN000; +; $IF NE ;Yep ;an000;bgb;AN000; + JE $$IF41 + call Check_For_Network ;See if Network drive letter ;an000;bgb;AN000; + cmp Fatal_Error,YES ;Can we continue? ;an000;bgb;AN000; +; $IF NE ;Yep ;an000;bgb;AN000; + JE $$IF42 + call Check_Translate_Drive ;See if Subst, Assigned ;an000;bgb;AN000; +; $ENDIF ;- Fatal_Error passed back ;an000;bgb;AN000; +$$IF42: +; $ENDIF ; ;an000;bgb;AN000; +$$IF41: +; $ENDIF ;an000;bgb +$$IF40: + ret ; ;an000;bgb;AN000; + ;an000;bgb +Validate_Target_Drive endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Check_Target_Drive ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Check to see if valid DOS drive by checking if drive is ;an000;bgb +; removable. If error, the drive is invalid. Save default ;an000;bgb +; drive info. Also get target drive BPB information, and compute ;an000;bgb +; the start of the data area ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Fatal_Error = NO ;an000;bgb +; ;an000;bgb +;Output: BIOSFile = default drive letter ;an000;bgb +; DOSFile = default drive letter ;an000;bgb +; CommandFile = default drive letter ;an000;bgb +; Fatal_Error = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Get default drive (INT 21h, AH = 19h) ;an000;bgb +; Convert it to drive letter ;an000;bgb +; Save into BIOSFile,DOSFile,CommandFile ;an000;bgb +; See if drive removable (INT 21h, AX=4409h IOCtl) ;an000;bgb +; IF error - drive invalid ;an000;bgb +; Display Invalid drive message ;an000;bgb +; Fatal_Error= YES ;an000;bgb +; ENDIF ;an000;bgb +; Get BPB of target drive (Generic IOCtl Get Device parameters) ;an000;bgb +; Compute start of data area ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Procedure Check_Target_Drive ; ;an000;bgb;AN000; + call func60 ; ;an000;bgb + mov al,save_drive ;an000;bgb + cmp al,0ffh ;save drive spec ;an000;bgb +; $IF E ;an000;bgb + JNE $$IF46 + Message BadDrv_Arg ;Print message ;an000;bgb;AC000; + mov Fatal_Error,Yes ;Indicate error ;an000;bgb;AN000; + jmp Exit_Baddrv ;dont do rest of proc ;an000;bgb;an021;bgb;an099; +; $ENDIF ;an000;bgb +$$IF46: + DOS_Call Get_Default_Drive ;Find the current drive 19 ;an000;bgb;AC000; + mov UserDev,al ;Save it ;an000;bgb; ; + cmp AllDrv,0 ;Was drive entered? ;an000;bgb;AN002; +; $IF E ;No ;an000;bgb;AN002; + JNE $$IF48 + mov BadDrvm+1,al ;Save 0 based number ;an000;bgb;AN002; + inc al ;Make 1 based ;an000;bgb;AN002; + mov byte ptr Buffer.Drnum_stroff,al ; ;an000;bgb ; + mov AllDrv,al ;Use default drive for ;an000;bgb;AN002; + mov VolNam,al ;entries for drive fields ;an000;bgb;AN002; + mov OrphFCB,al ; ;an000;bgb;AN002; + add al,'A'-1 ;Make it a drive letter ;an000;bgb;AN002; + mov Arg_Buf,al ;Save it ;an000;bgb;AN002; +; $ENDIF ; ;an000;bgb;AN002; +$$IF48: + mov bl,alldrv ;Get drive number (A=1) ;AN00;an044;bgb;an000;bgb0; + mov al,09h ;See if drive is local ;an000;bgb;AC000; + DOS_Call IOCtl ;-this will fail if bad drive ;an000;bgb;AC000; +; $IF C ;CY means invalid drive ;an000;bgb;AC000; + JNC $$IF50 + Message BadDrv_Arg ;Print message ;an000;bgb;AC015;bgb + mov Fatal_Error,Yes ;Indicate error ;an000;bgb;AN015;bgb +; $ENDIF ; ;an000;bgb;AN000; +$$IF50: + cmp fatal_error,no ;an000;bgb +; $IF E ;an000;bgb + JNE $$IF52 +get_bpb: mov al,GENERIC_IOCTL ;Get BPB information ;an000;bgb ;AN000; + mov ch,RawIO ; " " " " ;an000;bgb ;AN000; + mov cl,GET_DEVICE_PARAMETERS ; ;an000;bgb ;AN000; + mov bl,AllDrv ; " " " " ;an000;bgb ;AN000; + lea dx,BPB_Buffer ; dx points to bpb area ;an000;bgb ;AN000; + mov byte ptr bpb_buffer, 0ffh ;turn bit 0 on to get bpb inf;an000;bgbo of disk ;an008;bgb + DOS_Call IOCtl ; " " " " ;an000;bgb ;AN000; + mov bx,dx ;use bx as the pointer to bpb;an000;bgb ;an015;bgb +; $IF C ;is ioct not supported or bad? ;an000;bgb ;an015;bgb + JNC $$IF53 + mov al,BadDrvm+1 ; drive number a=0 ;an000;bgb ;AN015;bgb + lea bx,chkprmt_end ; transfer address es:bx ;an000;bgb ;an015;bgb + ;warning! this label must be the last in the code segment ;an000;bgb + mov cx,1 ; 1 sector - boot record ;an000;bgb ;an015;bgb + mov dx,0 ; logical sector 0 ;an000;bgb ;an015;bgb + mov Read_Write_Relative.Start_Sector_High,0 ; ;an000;bgb ;an015;bgb + call read_once ;an000;bgb ;an015;bgb +; $IF C ;couldnt read the boot? ;an000;bgb ;an015;bgb + JNC $$IF54 + Message BadDrv_Arg ;Print message ;an000;bgb ;AC015;bgb + mov Fatal_Error,Yes ;Indicate error ;an000;bgb ;AN015;bgb +; $ELSE ;ioct not supported - is it vdisk ;an000;bgb ;an015;bgb + JMP SHORT $$EN54 +$$IF54: +; mov di,bx ;an000;bgb;an022;bgb +; add di,3 ;es:di --> to vdisk area in boot rcd ;an000;bgb;an022;bgb +; lea si,myvdisk ;ds:si --> proper vdisk string ;an000;bgb;an022;bgb +; mov cx,5 ; compare 5 bytes ;an000;bgb;an022;bgb +; repe cmpsb ;compare both strings ;an000;bgb;an022;bgb +IF IBMCOPYRIGHT +; $IF NE ;an000;bgb;an022;bgb +; jmp baddrv ;an000;bgb +; $ENDIF ;an000;bgb;an022;bgb +ELSE +; $IF NE + mov di,bx + add di,3 + lea si,myramdisk + mov cx,8 + repe cmpsb + +; $IF NE + JE $$IF56 + jmp baddrv +; $ENDIF +$$IF56: +; $ENDIF +ENDIF +; $ENDIF ;an000;bgb;an022;bgb +$$EN54: + add bx,4 ;boot-record-offset - device-paramete;an000;bgbr offset ;an015;bgb +; $ENDIF ;an000;bgb ;an015;bgb +$$IF53: +; $ENDIF ;an000;bgb +$$IF52: + cmp fatal_error,no ;an000;bgb +; $IF E ;an000;bgb + JNE $$IF61 + call get_boot_info ;an053;bgb + call calc_space ;an000;bgb +; $ENDIF ;an000;bgb +$$IF61: + cmp bytes_per_sector,0 ;an000;bgb;an033;bgb +; $IF E ;an000;bgb;an033;bgb + JNE $$IF63 +baddrv: mov fatal_error,yes ;an000;bgb;an033;bgb + mov dx,offset dg:inval_media ;an000;bgb;an033;bgb + invoke printf_crlf ;an000;bgb;an033;bgb +; $ENDIF ;an000;bgb;an033;bgb +$$IF63: +Exit_Baddrv: ;AN099; + ret ;And we're outa here ;an000;bgb;AN000; +Check_Target_Drive endp ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb + +;****************************************************************************** ;an053;bgb;an000;bgb +; get_boot_info ;an053;bgb +; ;an053;bgb +; ;an053;bgb;an000;bgb +; Inputs : none ;an053;bgb;an000;bgb +; ;an053;bgb;an000;bgb +; Outputs : ;an053;bgb +;****************************************************************************** ;an053;bgb;an000;bgb +Procedure get_boot_info ; ;an053;bgb;an000;bgb + mov cx,[bx].BytePerSector ; usually 512 ;an053;bgb;an000;bgb ;an015;bgb + cmp cx,512 ;vdisk sizes ;an053;bgb +; $IF NE,AND ;vdisk sizes ;an053;bgb + JE $$IF65 + cmp cx,256 ;vdisk sizes ;an053;bgb +; $IF NE,AND ;vdisk sizes ;an053;bgb + JE $$IF65 + cmp cx,128 ;vdisk sizes ;an053;bgb +; $IF NE ;vdisk sizes ;an053;bgb + JE $$IF65 + jmp baddrv ;an053;bgb +; $ENDIF ;an053;bgb +$$IF65: + mov bytes_per_sector,cx ; ; ;an053;bgb;an000;bgb ;an005;bgb + ;an053;bgb + xor cx,cx ;Find # sectors used by FA;an053;bgb;an000;bgbT's ;AN000; + mov cl,[bx].NumberOfFats ; " " " " ;an053;bgb;an000;bgb ;an015;bgb + cmp cx,2 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF67 + cmp cx,1 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE ;an053;bgb + JE $$IF67 + jmp baddrv ;must be 2 fats ;an053;bgb ;an032;bgb +; $ENDIF ;an053;bgb +$$IF67: + mov fatcnt,cl ;an053;bgb;an000;bgb ;an005;bgb + ;an053;bgb + ;an053;bgb + xor ax,ax ;an053;bgb + mov al,[bx].SectorsPerCluster ;get total sectors ;an053;bgb ;an000;bgb;an015;bgb + cmp ax,1 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,2 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,4 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,8 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,16 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,32 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,64 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE,AND ;an053;bgb + JE $$IF69 + cmp ax,128 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF NE ;an053;bgb + JE $$IF69 + jmp baddrv ;this is not! ;an053;bgb ;an032;bgb +; $ENDIF ;an053;bgb +$$IF69: + ;an053;bgb + mov ax,[bx].SectorsPerFAT ; " " " " ;an053;bgb;an000;bgb ;an015;bgb + cmp ax,0 ;make sure it is ok ;an053;bgb;an032;bgb + jz baddrv ;this is not! ;an053;bgb;an032;bgb + mul cx ; " " " " ;an053;bgb;an000;bgb ;AN000; + push bx ;save bpb pointer ;an053;bgb;an000;bgb ;an015;bgb + push dx ;Save results ;an053;bgb;an000;bgb ;AN000; + push ax ; " " ;an053;bgb;an000;bgb ;AN000; + ;an053;bgb + mov ax,[bx].RootEntries ;Find number of sectors in root ;an053;bgb;an000;bgb ;an015;bgb + cmp ax,2 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF B,OR ;this is not! ;an053;bgb;an032;bgb + JB $$LL71 + cmp ax,512 ;make sure it is ok ;an053;bgb;an032;bgb +; $IF A ;this is not! ;an053;bgb;an032;bgb + JNA $$IF71 +$$LL71: + jmp baddrv ;an053;bgb +; $ENDIF ;an053;bgb +$$IF71: + ;an053;bgb + mov cl,Dir_Entries_Per_Sector ; by dividing RootEntries ;an053;bgb;an000;bgb ;AN000; + cmp cl,0 ;an053;bgb;an000;bgb;an022;bgb +; $IF NE ;an053;bgb;an000;bgb;an022;bgb + JE $$IF73 + div cl ; by (512/32) ;an053;bgb;an000;bgb;an022;bgb;AN000; +; $ENDIF ;an053;bgb;an000;bgb;an022;bgb +$$IF73: + pop bx ;Get low sectors per FAT b;an053;bgb;an000;bgback ;AN000; + pop dx ;Get high part ;an053;bgb;an000;bgb ;AN000; + add ax,bx ;Add to get FAT+Dir sector;an053;bgb;an000;bgbs ;AN000; + adc dx,0 ;High part ;an053;bgb;an000;bgb ;AN000; + mov fat_dir_secs,ax ;save it ;an053;bgb;an000;bgb ;an006;bgb + inc fat_dir_secs ; 1 for reserved sector ;an053;bgb;an000;bgb ;an006;bgb + pop bx ;restore bpb pointer ;an053;bgb;an000;bgb ;an015;bgb + add ax,[bx].ReservedSectors ;Add in Boot record sectors ;an053;bgb;an000;bgb ;an015;bgb + adc dx,0 ;to get start of data (DX:;an053;bgb;an000;bgbAX) ;AN000; + mov Data_Start_Low,ax ;Save it ;an053;bgb;an000;bgb ;AN000; + mov Data_Start_High,dx ; ;an053;bgb;an000;bgb ;AN000; + ret ; ;an053;bgb;an000;bgb +get_boot_info endp ; ;an053;bgb;an000;bgb + + + + + + + +;****************************************************************************** ;an000;bgb +; Calc_Space : Calculate the total space that is ;an000;bgb +; addressible on the the disk by DOS. ;an000;bgb +; ;an000;bgb +; Inputs : none ;an000;bgb +; ;an000;bgb +; Outputs : Fdsksiz - Size in bytes of the disk ;an000;bgb +;****************************************************************************** ;an000;bgb +Procedure Calc_Space ; ;an000;bgb +; get the total number of clusters on the disk ;an000;bgb ;an006;bgb +p97: xor ax,ax ;clear ax ;an000;bgb + mov ah,36h ;Get disk free space ;an000;bgb + mov dl,alldrv ; 1 based drive number ;an000;bgb + push bx ;save bpb pointer ;an000;bgb;an015;bgb + int 21h ;bx = total space avail ;an000;bgb +;multiply by sectors per cluster ;an000;bgb +gtsecs: mov ax,dx ;get total clusters ;an000;bgb + xor cx,cx ;clear cx ;an000;bgb + pop bx ;restore bpb pointer ;an000;bgb;an015;bgb + mov cl,[bx].SectorsPerCluster ;get total sectors ;an000;bgb;an015;bgb + push bx ;save bpb pointer ;an000;bgb;an015;bgb + xor bx,bx ;clear bx ;an000;bgb + call Multiply_32_Bits ;multiply ;an000;bgb +;multiply by bytes per sector ;an000;bgb + mov dx,bx ;save bx ;an000;bgb;an015;bgb + pop bx ;get bpb addr ;an000;bgb;an015;bgb + mov cx,[bx].BytePerSector ;get total bytes ;an000;bgb;an015;bgb + mov bx,dx ;restore bx ;an000;bgb;an015;bgb + call Multiply_32_Bits ; multiply ;an000;bgb +;result is bytes on disk ;an000;bgb + mov tot_bytes_lo,ax ;save high word ;an000;bgb + mov tot_bytes_hi,bx ;save low word ;an000;bgb + ret ; ;an000;bgb +Calc_Space endp ; ;an000;bgb + + +;***************************************************************************** ;an000;bgb +;Routine name: Check_For_Network ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: See if target drive isn't local, or if it is a shared drive. If ;an000;bgb +; so, exit with error message. The IOCtl call is not checked for ;an000;bgb +; an error because it is called previously in another routine, and ;an000;bgb +; invalid drive is the only error it can generate. That condition ;an000;bgb +; would not get this far ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Drive_Letter_Buffer.Drive_Number ;an000;bgb +; Fatal_Error = NO ;an000;bgb +; ;an000;bgb +;Output: Fatal_Error = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; See if drive is local (INT 21h, AX=4409 IOCtl) ;an000;bgb +; IF not local ;an000;bgb +; Display network message ;an000;bgb +; Fatal_ERROR = YES ;an000;bgb +; ELSE ;an000;bgb +; IF 8000h bit set on return ;an000;bgb +; Display assign message ;an000;bgb +; Fatal_Error = YES ;an000;bgb +; ENDIF ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Check_For_Network ; ;an000;bgb;AN000; + ; ;an000;bgb + mov bl,alldrv ;Drive is 1=A, 2=B ;an000;bgb; ; + mov al,09h ;See if drive is local or remote;an000;bgb;AC000; + DOS_CALL IOCtl ;We will not check for error ;an000;bgb;AC000; + test dx,Net_Check ;if (x & 1200H)(redir or shared);an000;bgb; ; +; $IF NZ ;Found a net drive ;an000;bgb;AC000; + JZ $$IF75 + Message No_Net_Arg ;Tell 'em ;an000;bgb;AC000; + mov Fatal_Error,Yes ;Indicate bad stuff ;an000;bgb;AN000; +; $ELSE ;Local drive, now check assign ;an000;bgb;AN000; + JMP SHORT $$EN75 +$$IF75: + test dx,Assign_Check ;8000h bit is bad news ;an000;bgb; ; +; $IF NZ ;Found it ;an000;bgb;AC000; + JZ $$IF77 + Message SubstErr ;Tell error ;an000;bgb;AC000; + mov Fatal_Error,Yes ;Indicate bad stuff ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF77: +; $ENDIF ; ;an000;bgb;AN000; +$$EN75: + ret ; ;an000;bgb;AN000; + ;an000;bgb +Check_For_Network endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Check_Translate_Drive ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Do a name translate call on the drive letter to see if it is ;an000;bgb +; assigned by SUBST or ASSIGN ;an000;bgb +; ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; ;an000;bgb +;Change History: Created 5/1/87 MT ;an000;bgb +; ;an000;bgb +;Input: Drive_Letter_Buffer.Drive_Number ;an000;bgb +; Fatal_Error = NO ;an000;bgb +; ;an000;bgb +;Output: Fatal_Error = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; Put drive letter in ASCIIZ string "d:\",0 ;an000;bgb +; Do name translate call (INT 21) ;an000;bgb +; IF drive not same ;an000;bgb +; Display assigned message ;an000;bgb +; Fatal_Error = YES ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Procedure Check_Translate_Drive ; ;an000;bgb;AN000; + call func60 ; ;an000;bgb + mov bl,byte ptr [TranSrc] ;Get drive letter from path ;an000;bgb; ; + cmp bl,byte ptr [Chkprmt_End] ;Did drive letter change? ;an000;bgb; ; +; $IF NE ;If not the same, it be bad ;an000;bgb;AC000; + JE $$IF80 + Message SubstErr ;Tell user ;an000;bgb;AC000; + mov Fatal_Error,Yes ;Setup error flag ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF80: + ret ; ;an000;bgb;AN000; +Check_Translate_Drive endp ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +Procedure func60 ; ;an000;bgb;AN000; +; PUSH DS ;ICE ;an000;bgb +; push bx ;ICE ;an000;bgb +; push ax ;ICE ;an000;bgb +; ;an000;bgb +; mov bx,0140H ;ICE ;an000;bgb +; xor ax,ax ;ICE ;an000;bgb +; mov ds,ax ;ICE ;an000;bgb +; mov ax,word ptr ds:[bx] ;ICE ;an000;bgb +; mov word ptr ds:[bx],ax ;ICE ;an000;bgb +; ;an000;bgb +; pop ax ;ICE ;an000;bgb +; pop bx ;ICE ;an000;bgb +; POP DS ;ICE ;an000;bgb + ;an000;bgb + mov byte ptr [transrc],'A' ;an000;bgb + mov bl,alldrv ;Get drive ; ;an000;bgb ; + dec bl ;Make it 0 based ;an000;bgb;AN001; + add byte ptr [TranSrc],bl ;Make string "d:\" ;an000;bgb; ; + lea si,TranSrc ;Point to translate string ;an000;bgb; ; + push ds ;Set ES=DS (Data segment) ;an000;bgb; ; + pop es ; " " " " ;an000;bgb; ; + lea di,Chkprmt_End ;Point at output buffer ;an000;bgb; ; + DOS_Call xNameTrans ;Get real path ;an000;bgb;AC000; + ret ; ;an000;bgb;AN000; +func60 endp ; ;AN000; ;an000;bgb + ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Hook_Interrupts ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Change the interrupt handler for INT 13h to point to the ;an000;bgb +; ControlC_Handler routine ;an000;bgb +; ;an000;bgb +;Called Procedures: None ;an000;bgb +; ;an000;bgb +;Change History: Created 4/21/87 MT ;an000;bgb +; ;an000;bgb +;Input: None ;an000;bgb +; ;an000;bgb +;Output: None ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Point at ControlC_Handler routine ;an000;bgb +; Set interrupt handler (INT 21h, AX=2523h) ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +procedure Hook_Interrupts ; ;an000;bgb;AN000; + ; ;an000;bgb + mov al,23h ;an000;bgb + DOS_Call Get_Interrupt_Vector ;Get the INT 23h handler ;an000;bgb;AC000; + mov word ptr [CONTCH],bx ; ;an000;bgb + mov bx,es ; ;an000;bgb;AN000; + mov word ptr [CONTCH+2],bx ; ;an000;bgb + mov al,23h ;Specify CNTRL handler ;an000;bgb; ; + lea dx, INT_23 ;Point at it ;an000;bgb; ; + push ds ;Save data seg ;an000;bgb; ; + push cs ;Point to code segment ;an000;bgb; ; + pop ds ; ;an000;bgb; ; + DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;an000;bgb;AC000; + pop ds ;Get Data degment back ;an000;bgb; ; + mov al,24h ; ;an000;bgb + DOS_Call Get_Interrupt_Vector ;Get the INT 24h handler ;an000;bgb;AC000; + mov word ptr [HardCh],bx ;Save it ;an000;bgb + mov bx,es ; ;an000;bgb + mov word ptr [HardCh+2],bx ; ;an000;bgb + mov al,24h ;Specify handler ;an000;bgb ; ; + lea dx, INT_24 ;Point at it ;an000;bgb; ; + push ds ;Save data seg ;an000;bgb; ; + push cs ;Point to code segment ;an000;bgb; ; + pop ds ; ;an000;bgb; ; + DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;an000;bgb;AC000; + pop ds ;Get Data degment back ;an000;bgb; ; + ret ; ;an000;bgb;AN000; + ;an000;bgb +hook_Interrupts endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Clear_Append_X ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: Determine if Append /XA is turned on thru INT 2Fh, and shut ;an000;bgb +; off for life of CHKDSK if it is. ;an000;bgb +; ;an000;bgb +;Called Procedures: None ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Change History: Created 5/13/87 MT ;an000;bgb +; ;an000;bgb +;Input: None ;an000;bgb +; ;an000;bgb +;Output: APPEND = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Append = NO ;an000;bgb +; See if APPEND /X is present (INT 2Fh, AX=0B706h) ;an000;bgb +; IF present ;an000;bgb +; Turn append /X off (INT 2Fh, AX=B707h, BX = 0) ;an000;bgb +; Append = YES ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Clear_Append_X ; ;an000;bgb ;AN000; + ;an000;bgb + mov Append,NO ;Init the Append /X flag ;an000;bgb;AN000; + mov ax,Append_X ;Is Append /X there? ;an000;bgb;AN000; + int Multiplex ; " " " " ;an000;bgb;AN000; + cmp bx,Append_X_Set ;Was it turned on? ;an000;bgb;AN000; +; $IF E ;Yep ;an000;bgb;AN000; + JNE $$IF82 + mov Append,YES ;Indicate that it was on ;an000;bgb;AN000; + mov ax,Set_Append_X ;Turn Append /X off ;an000;bgb;AN000; + mov bx,Append_Off ; " " " " ;an000;bgb;AN000; + int Multiplex ; " " " " ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF82: + ret ; ;an000;bgb;AN000; + ;an000;bgb +Clear_Append_X endp ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: CHKDSK_IFS ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: ;an000;bgb +; ;an000;bgb +;Called Procedures: Main_Routine ;an000;bgb +; EXEC_FS_CHKDSK ;an000;bgb +; Done ;an000;bgb +; ;an000;bgb +;Change History: Created 5/8/87 MT ;an000;bgb +; ;an000;bgb +;Input: FS_Not_FAT = Yes/No ;an000;bgb +; ;an000;bgb +;Output: None ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; IF File system other than FAT ;an000;bgb +; Go call file system specific CHKDSK (CALL Exec_FS_CHKDSK) ;an000;bgb +; ELSE ;an000;bgb +; Do FAT based CHKDSK (CALL Main_Routine) ;an000;bgb +; ENDIF ;an000;bgb +; Restore current drive (CALL Done) ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb + ;an000;bgb +Procedure CHKDSK_IFS ; ;an000;bgb;AN000; + ;an000;bgb +ifdef fsexec ;an038;bgb + cmp FS_Not_Fat,YES ;Is the target FS a FAT? ;an038;bgb;AN000; +; $IF E ;No, so need to exec the ;an038;bgb;AN000; + JNE $$IF84 + call EXEC_FS_CHKDSK ; file system specific prog. ;an038;bgb;AN000; +; $ELSE ;It's a FAT ;an038;bgb;AN000; + JMP SHORT $$EN84 +$$IF84: +endif ;an038;bgb + call Main_Routine ;Use canned code! ;an038;bgb;AN000; +ifdef fsexec ;an038;bgb +; $ENDIF ; ;an038;bgb;AN000; +$$EN84: +endif ;an038;bgb + call Done ;Restore current drive ;an000;bgb;AN000; + ret ; ;an000;bgb;AN000; + ;an000;bgb +CHKDSK_IFS endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Reset_Append_X ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;description: If APPEND /XA was on originally, turn it back on ;an000;bgb +; ;an000;bgb +;Called Procedures: None ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Change History: Created 5/13/87 MT ;an000;bgb +; ;an000;bgb +;Input: None ;an000;bgb +; ;an000;bgb +;Output: APPEND = YES/NO ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; IF APPEND = YES ;an000;bgb +; Turn append /X on (INT 2Fh, AX=B707h, BX = 1) ;an000;bgb +; ENDIF ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Procedure Reset_Append_X ; ;an000;bgb;AN000; + ;an000;bgb + cmp Append,Yes ;Was Append /X on to start with?;an000;bgb;AN000; +; $IF E ;Yep ;an000;bgb;AN000; + JNE $$IF87 + mov ax,Set_Append_X ;Turn Append /X off ;an000;bgb;AN000; + mov bx,Append_On ; " " " " ;an000;bgb;AN000; + int Multiplex ; " " " " ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF87: + ret ; ;an000;bgb;AN000; + ;an000;bgb +Reset_Append_X endp ; ;an000;bgb;AN000; + ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name: Multiply_32_Bits ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding ;an000;bgb +; the 32 bit number to itself for each power of 2 contained in the ;an000;bgb +; 16 bit number. Whenever a bit that is set in the multiplier (CX) ;an000;bgb +; gets shifted to the bit 0 spot, it means that that amount has ;an000;bgb +; been multiplied so far, and it should be added into the total ;an000;bgb +; value. Take the example CX = 12 (1100). Using the associative ;an000;bgb +; rule, this is the same as CX = 8+4 (1000 + 0100). The ;an000;bgb +; multiply is done on this principle - whenever a bit that is set ;an000;bgb +; is shifted down to the bit 0 location, the value in BX:AX is ;an000;bgb +; added to the running total in DI:SI. The multiply is continued ;an000;bgb +; until CX = 0. The routine will exit with CY set if overflow ;an000;bgb +; occurs. ;an000;bgb +; ;an000;bgb +; ;an000;bgb +;Called Procedures: None ;an000;bgb +; ;an000;bgb +;Change History: Created 7/23/87 MT ;an000;bgb +; ;an000;bgb +;Input: BX:AX = 32 bit number to be multiplied ;an000;bgb +; CX = 16 bit number to be multiplied. (Must be even number) ;an000;bgb +; ;an000;bgb +;Output: BX:AX = output. ;an000;bgb +; CY set if overflow ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; Point at ControlC_Handler routine ;an000;bgb +; Set interrupt handler (INT 21h, AX=2523h) ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb + ;an000;bgb +Public Multiply_32_Bits ;an000;bgb +Multiply_32_Bits proc ; ;an000;bgb;AN000; + ;an000;bgb + push di ; ;an000;bgb;AN000; + push si ; ;an000;bgb;AN000; + xor di,di ;Init result to zero ;an000;bgb + xor si,si ; ;an000;bgb + cmp cx,0 ;Multiply by 0? ;an000;bgb;AN000; +; $IF NE ;Keep going if not ;an000;bgb;AN000; + JE $$IF89 +; $DO ;This works by adding the result;an000;bgb;AN000; +$$DO90: + test cx,1 ;Need to add in sum of this bit?;an000;bgb;AN000; +; $IF NZ ;Yes ;an000;bgb;AN000; + JZ $$IF91 + add si,ax ;Add in the total so far for ;an000;bgb;AN000; + adc di,bx ; this bit multiplier (CY oflow);an000;bgb;AN000; +; $ELSE ;Don't split multiplier ;an000;bgb;AN000; + JMP SHORT $$EN91 +$$IF91: + clc ;Force non exit ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$EN91: +; $LEAVE C ;Leave on overflow ;an000;bgb;AN000; + JC $$EN90 + shr cx,1 ;See if need to multiply value ;an000;bgb;AN000; + cmp cx,0 ;by 2 ;an000;bgb;AN000; +; $LEAVE E ;Done if cx shifted down to zero;an000;bgb;AN000; + JE $$EN90 + add ax,ax ;Each time cx is shifted, add ;an000;bgb;AN000; + adc bx,bx ;value to itself (Multiply * 2) ;an000;bgb;AN000; +; $ENDDO C ;CY set on overflow ;an000;bgb;AN000; + JNC $$DO90 +$$EN90: +; $IF NC ;If no overflow, add in DI:SI ;an000;bgb;AN000; + JC $$IF97 + mov ax,si ; which contains the original ;an000;bgb;AN000; + mov bx,di ; value if odd, 0 if even. This ;an000;bgb;AN000; + clc ;Set no overflow flag ;an000;bgb;AN000; +; $ENDIF ; ;an000;bgb;AN000; +$$IF97: +; $ELSE ; ;an000;bgb + JMP SHORT $$EN89 +$$IF89: + xor ax,ax ; ;an000;bgb + xor bx,bx ; ;an000;bgb +; $ENDIF ;Multiply by 0 ;an000;bgb;AN000; +$$EN89: + pop si ; ;an000;bgb;AN000; + pop di ; ;an000;bgb;AN000; + ret ; ;an000;bgb;AN000; + ;an000;bgb +Multiply_32_Bits endp ;an000;bgb + pathlabl chkinit ;an000;bgb +code ends ;an000;bgb + end ;an000;bgb + ;an000;bgb + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKMACRO.INC b/v4.0/src/CMD/CHKDSK/CHKMACRO.INC new file mode 100644 index 0000000..f6ba6ac --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKMACRO.INC @@ -0,0 +1,105 @@ + +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + + +; +;****************************************************************************** +; Message Macro Definitions +;****************************************************************************** +; + + EXTRN Display_Interface:near + + +;----------------------------------------------------------------------------- + +Message macro Message_Name ; ;AN000; + ; + mov dx,offset dg:Message_Name ; ;AN000; + call Display_Interface ; ;AN000; + ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Parse_Message macro ; ;AN000; + + ; + push ds + mov dx,dg + mov ds,dx + mov word ptr Parse_Error_Msg,ax ; ;AN000; + mov dx,offset dg:Parse_Error_Msg ; ;AN000; + call Display_Interface ; ;AN000; + pop ds ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Extended_Message macro ; ;AN000; + ; + + push ds + mov dx,dg + mov ds,dx + mov word ptr Extended_Error_Msg,ax ; ;AN000; + mov dx,offset dg:Extended_Error_Msg ; ;AN000; + call Display_Interface ; ;AN000; + pop ds + endm ; ;AN000; +; +;***************************************************************************** +; General Macro's +;***************************************************************************** +; + +Procedure macro Proc_Name,Seg_Name ; ;AN000; + ; +Public Proc_Name ; ;AN000; +Proc_Name proc ; ;AN000; + + endm ; ;AN000; +;----------------------------------------------------------------------------- + +DOS_Call macro Function ; ;AN000; + ; + mov ah,Function ; ;AN000; + int 21h ; ;AN000; + ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Popff macro + +Assume cs:DG + + jmp $+3 + iret + push cs + call $-2 + +Assume cs:code + + endm + +;----------------------------------------------------------------------------- + +Set_Data_Segment macro + + push ax + mov ax,dg ;Point to data segment + mov ds,ax ; + push ds + pop es + pop ax + + .LALL + assume ds:dg,es:dg + .XALL + endm + + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKMSG.INC b/v4.0/src/CMD/CHKDSK/CHKMSG.INC new file mode 100644 index 0000000..6b75dad --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKMSG.INC @@ -0,0 +1,1047 @@ + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Macro's ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + ;an000;bgb +Define_Msg macro Message_Name ; ;AN000; + ; ;an000;bgb +Create_Msg Message_Name,Message_Number,Handle,Sublist,Count,Class,Function,Input;AN000; + ; ;an000;bgb + endm ; ;AN000; + ;an000;bgb +;----------------------------------------------------------------------------- ;an000;bgb + ;an000;bgb +Create_Msg macro Parm1,Parm2,Parm3,Parm4,Parm5,Parm6,Parm7,Parm8; ;AN000; + ;an000;bgb +Public Parm1 ;an000;bgb +Parm1 label word ; ;AN000; + dw Parm2 ; ;AN000; + dw Parm3 ; ;AN000; + dw Parm4 ; ;AN000; + dw Parm5 ; ;AN000; + db Parm6 ; ;AN000; + db Parm7 ; ;AN000; + dw Parm8 ; ;AN000; + endm ; ;AN000; + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; External data declarations ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + Extrn Arg_Buf:Byte ;an000;bgb +ifdef fsexec ;an038;bgb + Extrn Drive_Letter_Msg:Byte ;an038;bgb;an000;bgb +endif ;an038;bgb + Extrn TChar:Byte ;an000;bgb + Extrn Cross_Clus:Byte ;an000;bgb + extrn sernum:word ;an024;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Public Data ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + Public Sublist_msg_Idmes ;an000;bgb + Public BadDrvm ;an000;bgb + Public YES_BYTE ;an000;bgb + Public NO_BYTE ;an000;bgb + Public yn_arg ;an000;bgb + Public orphcnt ;an000;bgb + Public report_arg ;an000;bgb + Public rarg1 ;an000;bgb + Public rarg3 ;an000;bgb + Public badrw_str ;an000;bgb + Public badrw_num ;an000;bgb + Public block_num ;an000;bgb + Public fatal_arg1 ;an000;bgb + Public fatal_arg2 ;an000;bgb + Public file_arg1 ;an000;bgb + Public file_arg2 ;an000;bgb + Public free_arg1 ;an000;bgb + Public free_arg2 ;an000;bgb + Public free_arg3 ;an000;bgb + Public Fatal_End ;an000;bgb + Public MonTab ;an000;bgb + public fatmsg1 ;an024;bgb ;an000;bgb + public fatmsg2 ;an024;bgb ;an000;bgb + extrn orphsiz:word ;an049;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Message Retriever equates ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + ;an000;bgb +Format_Msg equ 'C' ;an000;bgb + ;an000;bgb +N_A equ 0 ;an000;bgb +None equ 0 ;an000;bgb + ;an000;bgb +Blank equ " " ;an000;bgb +No_Function equ 0 ;an000;bgb + ;an000;bgb + ;an000;bgb + ;an000;bgb + ;an000;bgb +data segment public para 'data' ; AN000; ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Message Sublist Tables ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;The following control blocks are used for messages with ;an000;bgb +;replaceable paramters. These control blocks are used by the ;an000;bgb +;SysDispMsg routine. ;an000;bgb +; ;an000;bgb + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_msg_Orphmes2 label dword ; ;an000;bgb +Sublist_msg_Orphmes3 label dword ; ;an000;bgb +Sublist_msg_HidMes label dword ; ;an000;bgb +Sublist_msg_DirMes label dword ; ;an000;bgb +Sublist_msg_FileMes label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ;0bh ;an000;bgb;an049;bgb + db Reserved ;00h ;an000;bgb;an049;bgb + dw rarg1 ;offset of value ;an000;bgb;an049;bgb + dw dg ;segment of value ;an000;bgb;an049;bgb + db 1 ;the first parm ;an000;bgb;an049;bgb + db Right_Align+Unsgn_Bin_DWord ;type of data ;an000;bgb;an049;bgb + db 10 ;max length of data ;an000;bgb;an049;bgb + db 10 ;min length of data ;an000;bgb;an049;bgb + db Blank ;pad character ;an000;bgb;an049;bgb + db Sublist_Length ;0bh ;an000;bgb;an049;bgb + db Reserved ;00h ;an000;bgb;an049;bgb + dw rarg3 ;offset of value ;an000;bgb;an049;bgb + dw dg ;segment of value ;an000;bgb;an049;bgb + db 2 ;the second parm ;an000;bgb;an049;bgb + db Left_Align+Unsgn_Bin_DWord;type of data ;an000;bgb;an049;bgb + db 10 ;max length of data ;an000;bgb;an049;bgb + db 1 ;min length of data ;an000;bgb;an049;bgb + db Blank ;pad character ;an000;bgb;an049;bgb +;--------------------------- ; ;an000;bgb;an049;bgb +Sublist_msg_dskspc label dword ; ;an000;bgb;an049;bgb +Sublist_msg_badspc label dword ; ;an000;bgb;an049;bgb +Sublist_msg_frespc label dword ; ;an000;bgb;an049;bgb +Sublist_msg_totmem label dword ; ;an000;bgb;an049;bgb +Sublist_msg_fremem label dword ; ;an000;bgb;an049;bgb +Sublist_msg_Freebymes label dword ; ;an000;bgb;an049;bgb +Sublist_msg_alloc label dword ; ;an000;bgb;an049;bgb + ;an000;bgb;an049;bgb + db Sublist_Length ;0bh ;an000;bgb;an049;bgb + db Reserved ;00h ;an000;bgb;an049;bgb + dw dg:rarg1 ;offset of data ;an000;bgb;an049;bgb + dw dg ;segment of data ;an000;bgb;an049;bgb + db 1 ;1st parm ;an000;bgb;an049;bgb + db Right_Align+Unsgn_Bin_DWord ;type of data ;an000;bgb;an049;bgb + db 10 ;max length of data ;an000;bgb;an049;bgb + db 10 ;min length of data ;an000;bgb;an049;bgb + db Blank ;pad character ;an000;bgb;an049;bgb +;--------------------------- ; ;an000;bgb;an049;bgb +Sublist_msg_Extents label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb + db Reserved ; ;an000;bgb + dw dg:arg_buf ; ;an000;bgb + dw dg ; ;an000;bgb + db 1 ; ;an000;bgb + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb + db 64 ; ;an000;bgb + db 1 ; ;an000;bgb + db Blank ; ;an000;bgb + db Sublist_Length ; ;an000;bgb + db Reserved ; ;an000;bgb + dw dg:rarg1 ; ;an000;bgb + dw dg ; ;an000;bgb + db 2 ; ;an000;bgb + db Left_Align+Unsgn_Bin_Word ; ;;an000;bgb + db 5 ; ;an000;bgb + db 1 ; ;an000;bgb + db Blank ; ;an000;bgb + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_msg_Badr_arg label dword ; ;an000;bgb +Sublist_msg_Badw_arg label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb + db Reserved ; ;an000;bgb + dw dg:Badrw_Num ; ;an000;bgb + dw dg ; ;an000;bgb + db 1 ; ;an000;bgb + db Left_Align+Unsgn_Bin_Word ; ;;an000;bgb + db 5 ; ;an000;bgb + db 1 ; ;an000;bgb + db Blank ; ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_msg_Badrdmes label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw dg:Fatal_End ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 1 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; +;--------------------------- ; ;an000;bgb +Sublist_msg_Crossmes label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb + db Reserved ; ;an000;bgb + dw dg:Cross_Clus ; ;an000;bgb + dw dg ; ;an000;bgb + db 1 ; ;an000;bgb + db Left_Align+Unsgn_Bin_Word ; ;an000;bgb + db 5 ; ;an000;bgb + db 1 ; ;an000;bgb + db Blank ; ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_msg_BadTarg label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb + db Reserved ; ;an000;bgb + dw dg:arg_buf ; ;an000;bgb + dw dg ; ;an000;bgb + db 1 ; ;an000;bgb + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb + db 64 ; ;an000;bgb + db 1 ; ;an000;bgb + db Blank ; ;an000;bgb;AN000; +;--------------------------- ; ;an000;bgb +Sublist_msg_IDmes label dword ; ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw dg:arg_buf ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 11 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw 0 ;Date will be entered ;an000;bgb;AN000; + dw 0 ; by PrintID routine ;an000;bgb;AN000; + db 2 ; ;an000;bgb;AN000; + db Left_Align+Date_MDY_4 ; ;an000;bgb;AN000; + db 10 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw 0 ;Time will be entered ;an000;bgb;AN000; + dw 0 ; by PrintID routine ;an000;bgb;AN000; + db 3 ; ;an000;bgb;AN000; + db Left_Align+Time_HHMM_Cty; ;an000;bgb;AN000; + db 6 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_Msg_File_Arg label dword ;an000;dms ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw dg:arg_buf ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 64 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_Msg_Noisy label dword ;an000;dms ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw dg:arg_buf ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 64 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_Msg_Orphmes label dword ;an000;dms ;an000;bgb + ;an000;bgb + db Sublist_Length ;0bh ;an000;bgb;AN000; + db Reserved ;00h ;an000;bgb;AN000; + dw dg:orphsiz ;offset of data ;an000;bgb;AN000;;an049;bgb + dw dg ;segment ;an000;bgb;AN000; + db 1 ;1st of 2 replaceable parms ;an000;bgb;AN000; + db Left_Align+Unsgn_Bin_Word ;only 64k clusters ;an000;bgb ;AN000; + db 05 ;max length ;an000;bgb;AN000;;an049;bgb + db 1 ;min length ;an000;bgb;AN000; + db Blank ;pad ;an000;bgb;AN000; + ;an000;bgb + db Sublist_Length ;0b ;an000;bgb;AN000; + db Reserved ;00 ;an000;bgb;AN000; + dw dg:orphcnt ;offset ;an000;bgb;AN000; + dw dg ;seg ;an000;bgb;AN000; + db 2 ;2nd replaceable parm ;an000;bgb;AN000; + db Left_Align+Unsgn_Bin_dword ;double word ;an000;bgb;AN000;;an049;bgb + db 10 ;max len ;an000;bgb;AN000;;an049;bgb + db 1 ;min len ;an000;bgb;AN000; + db Blank ;pad char ;an000;bgb;AN000; +;--------------------------- ; ;an000;bgb +Sublist_Msg_Direcmes label dword ;an000;dms ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; + dw dg:arg_buf ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb;AN000; + db 64 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + ;an000;bgb +Sublist_Msg_Fatalmes label dword ;an000;dms ;an000;bgb + ;an000;bgb + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; +fatmsg1 dw dg:fatal_arg1 ; ;an000;bgb;AN024;bgb + dw dg ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 64 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; + db Sublist_Length ; ;an000;bgb;AN000; + db Reserved ; ;an000;bgb;AN000; +fatmsg2 dw dg:fatal_arg2 ; ;an000;bgb;AN000; + dw dg ; ;an000;bgb;AN000; + db 2 ;number 2 of 2 subs ;an000;bgb;AN022;bgb + db Left_Align+Char_Field_ASCIIZ ; ;an000;bgb ;AN000; + db 64 ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Blank ; ;an000;bgb;AN000; +;--------------------------- ; ;an000;bgb +ifdef fsexec ;an038;bgb +Sublist_msg_EXECFailure label dword ; ;an038;bgb;an000;bgb + db Sublist_Length ; ;an038;bgb;an000;bgb;AN000; + db Reserved ; ;an038;bgb;an000;bgb;AN000; + dw dg:Drive_Letter_Msg ; ;an038;bgb;an000;bgb;AN000; + dw dg ; ;an038;bgb;an000;bgb;AN000; + db 1 ; ;an038;bgb;an000;bgb;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;an038;bgb;an000;bgb ;AN000; + db 2 ; ;an038;bgb;an000;bgb;AN000; + db 2 ; ;an038;bgb;an000;bgb;AN000; + db Blank ; ;an038;bgb;an000;bgb;AN000; +endif ;an000;bgb + ;an000;bgb +;--------------------------- ; ;an000;bgb +Sublist_msgSerialNumber label dword ; ;an000;bgb;an024;bgb + db Sublist_Length ;0b ;an000;bgb;an024;bgb + db Reserved ;00 ;an000;bgb;an024;bgb + dw offset word ptr sernum+2 ;data field ;an000;bgb;an024;bgb + dw data ; ;an000;bgb;an024;bgb + db 1 ;#1 of 2 ;an000;bgb;an024;bgb + db Right_Align+Bin_Hex_Word ;format ;an000;bgb;an024;bgb + db 4 ;min len ;an000;bgb;an024;bgb + db 4 ;max len ;an000;bgb;an024;bgb + db '0' ;Display leading 0's ;an000;bgb;an024;bgb + ;an000;bgb;an024;bgb + db Sublist_Length ;0b ;an000;bgb;an024;bgb + db Reserved ;00 ;an000;bgb;an024;bgb + dw offset sernum ;data field ;an000;bgb;an024;bgb + dw data ; ;an000;bgb;an024;bgb + db 2 ;#2 of 2 ;an000;bgb;an024;bgb + db Right_Align+Bin_hex_Word ;format ;an000;bgb;an024;bgb + db 4 ;min len ;an000;bgb;an024;bgb + db 4 ;max len ;an000;bgb;an024;bgb + db '0' ;pad char ;an000;bgb;an024;bgb + ;an000;bgb +;--------------------------- ; ;an046;bgb +Sublist_msg_parserr label dword ; ;an046;bgb + ;an046;bgb + db Sublist_Length ;11 ;an046;bgb + db Reserved ;0 ;an046;bgb +public movsi +movsi dw dg:command_line_buffer ;off ;an046;bgb + dw dg ;seg ;an046;bgb + db 0 ;USE PERCENT ZERO ;an046;bgb + db Left_Align+Char_Field_ASCIIZ ;type of data ;an046;bgb + db 128 ;max width ;an046;bgb + db 1 ;min width ;an046;bgb + db Blank ;pad char ;an046;bgb +;--------------------------- ; ;an046;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Message Description Tables ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 1 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = EXT_ERR_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badver ; AN000;SM Incorrect DOS version;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 19 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = N_A ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badidbyt ; AN000;SM Probable non_DOS disk;an000;bgb (CRLF) Continue (Y/N)? +;---------------------- ; ;an000;bgb +Message_Number = 3 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = N_A ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg freemes ; AN000;SM Convert lost chains t;an000;bgbo files (Y/N)? +;---------------------- ; ;an000;bgb +Message_Number = 4 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = N_A ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg ptrandir ; AN000;SM Unrecoverable error i;an000;bgbn directory +;---------------------- ; ;an000;bgb +Message_Number = 5 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = N_A ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg ptrandir2 ; AN000;SM Convert directory to ;an000;bgbfile (Y/N)? +;---------------------- ; ;an000;bgb +Message_Number = 7 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_dskspc ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg dskspc ; AN000;SM %1 bytes total disk s;an000;bgbpace +;---------------------- ; ;an000;bgb +Message_Number = 8 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_badspc ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badspc ; AN000;SM %1 bytes in bad secto;an000;bgbrs +;---------------------- ; ;an000;bgb +Message_Number = 9 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_hidmes ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg hidmes ; AN000;SM %1 bytes in %2 hidden;an000;bgb files +;---------------------- ; ;an000;bgb +Message_Number = 10 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_dirmes ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg dirmes ; AN000;SM %1 bytes in %2 direct;an000;bgbories +;---------------------- ; ;an000;bgb +Message_Number = 11 ; message number 11 ;an000;bgb +Handle = STDOUT ; crt ;an000;bgb +Sublist = dg:Sublist_msg_filemes ; location of sublist ;an000;bgb +Count = 2 ; caontains 2 parameters ;an000;bgb +Class = UTILITY_MSG_CLASS ; type of msg ;an000;bgb +Function = NO_INPUT ; no input from user ;an000;bgb +Input = N_A ; not applicable ;an000;bgb + Define_Msg filemes ; AN000;SM %1 bytes in %2 user f;an000;bgbiles +;---------------------- ; ;an000;bgb +Message_Number = 12 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_orphmes2 ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg orphmes2 ; AN000;SM %1 bytes in %2 recove;an000;bgbred files +;---------------------- ; ;an000;bgb +Message_Number = 13 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_orphmes3 ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg orphmes3 ; AN000;SM %1 bytes would be in ;an000;bgb%2 recovered files +;---------------------- ; ;an000;bgb +Message_Number = 14 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_frespc ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg frespc ; AN000;SM %1 bytes available on;an000;bgb disk +;---------------------- ; ;an000;bgb +Message_Number = 15 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_totmem ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg totmem ; AN000;SM %1 bytes total memory;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 16 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_fremem ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg fremem ; AN000;SM %1 bytes free ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 17 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg no_net_arg ; AN000;SM Cannot CHKDSK a netwo;an000;bgbrk drive +;---------------------- ; ;an000;bgb +Message_Number = 18 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg SubstErr ; AN000;SM Cannot CHKDSK a SUBST;an000;bgbed or ASSIGNed drive +;---------------------- ; ;an000;bgb +Message_Number = 20 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_badr_arg ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badr_arg ; AN000;SM Disk error reading FA;an000;bgbT %2 +;---------------------- ; ;an000;bgb +Message_Number = 21 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_direcmes ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg direc_arg ; AN000;SM Directory %1 ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 22 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_extents ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg extent_arg ; AN000;SM %1 Contains %2 non-co;an000;bgbntiguous blocks +;---------------------- ; ;an000;bgb +Message_Number = 23 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg noext_arg ; AN000;SM All specified file(s);an000;bgb are contiguous +;---------------------- ; ;an000;bgb +Message_Number = 24 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg fixmes_arg ; AN000;SM Errors found, F param;an000;bgbeter not specified (CRLF) +;---------------------- ; Corrections will not ;an000;bgbbe written to disk +Message_Number = 25 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_fatalmes ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg fatal_arg ; AN000;SM Processing cannot con;an000;bgbtinue %1%2 +;---------------------- ; ;an000;bgb +Message_Number = 26 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_badrdmes ; AN000;SM ;an000;bgb +Count = 2 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badrdmes ; AN000;SM File allocation table;an000;bgb bad, drive %1 +;---------------------- ; ;an000;bgb +Message_Number = 2 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg stackmes ; AN000;SM Insufficient memory ;an000;bgb + Define_Msg stackmes1 ; AN000;SM Cannot make directory;an000;bgb entry %1 (CRLF) +;---------------------- ; Move files from root ;an000;bgbdirectory and repeat CHKDSK +Message_Number = 29 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg cdddmes ; AN000;SM CHDIR .. failed, tryi;an000;bgbng alternate method +;---------------------- ; ;an000;bgb +Message_Number = 30 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badchain ; AN000;SM Has invalid cluster, ;an000;bgbfile truncated +;---------------------- ; ;an000;bgb +Message_Number = 31 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badsubdir ; AN000;SM Invalid sub-directory;an000;bgb entry +;---------------------- ; ;an000;bgb +Message_Number = 32 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg ndotmes ; AN000;SM Does not exist ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 33 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg nulnz ; AN000;SM First cluster number ;an000;bgbis invalid, entry truncated +;---------------------- ; ;an000;bgb +Message_Number = 34 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badclus ; AN000;SM Allocation error, siz;an000;bgbe adjusted +;---------------------- ; ;an000;bgb +Message_Number = 35 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg norecdot ; AN000;SM Cannot recover .. ent;an000;bgbry, processing continued +;---------------------- ; ;an000;bgb +Message_Number = 36 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg nuldmes ; AN000;SM Directory is totally ;an000;bgbempty, no .. or .. +;---------------------- ; ;an000;bgb +Message_Number = 37 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg joinmes ; AN000;SM Directory is joined ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 38 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg norecddot ; AN000;SM Cannot recover .. ent;an000;bgbry +;---------------------- ; ;an000;bgb +Message_Number = 39 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg norecddot1 ; AN000;SM Entry has a bad link ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 40 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg norecddot2 ; AN000;SM Entry has a bad attri;an000;bgbbute +;---------------------- ; ;an000;bgb +Message_Number = 41 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg norecddot3 ; AN000;SM Entry has a bad size ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 42 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_crossmes ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg cross_arg ; AN000;SM Is cross linked on cl;an000;bgbuster %2 +;---------------------- ; ;an000;bgb +Message_Number = 43 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_badtarg ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badtarg_ptr ; AN000;SM Cannot CHDIR to %1, (;an000;bgbCRLF) +;---------------------- ; tree past this point ;an000;bgbnot processed +Message_Number = 44 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badtarg2 ; AN000;SM tree past this point ;an000;bgbnot processed +;---------------------- ; ;an000;bgb +Message_Number = 45 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_freebymes ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg freeBymes1 ; AN000;SM %1 bytes disk space f;an000;bgbreed +;---------------------- ; ;an000;bgb +Message_Number = 46 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_freebymes ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg freebymes2 ; AN000;SM %1 bytes disk space w;an000;bgbould be freed +;---------------------- ; ;an000;bgb +Message_Number = 47 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_idmes ; AN000;SM ;an000;bgb +Count = 3 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg idmes_arg ; AN000;SM Volume %1 created %2 ;an000;bgb%3 +;---------------------- ; ;an000;bgb +Message_Number = 48 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_alloc ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg idmes1 ; AN017;bgb %1 total allocation ;an000;bgbunits on disk +;---------------------- ; ;an000;bgb +Message_Number = 49 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = dg:Sublist_msg_alloc ; AN000;SM ;an000;bgb +Count = 1 ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg idmes2 ; AN000;SM %1 bytes in each allo;an000;bgbcation unit +;---------------------- ; ;an000;bgb +ifdef fsexec ;an038;bgb +Message_Number = 50 ; AN000;SM ;an038;bgb;an000;bgb +Handle = STDERR ; AN000;SM ;an038;bgb;an000;bgb +Sublist = dg:Sublist_msg_ExecFailure ; AN000;SM ;an038;bgb;an000;bgb +Count = 1 ; AN000;SM ;an038;bgb;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an038;bgb;an000;bgb +Function = NO_INPUT ; AN000;SM ;an038;bgb;an000;bgb +Input = N_A ; AN000;SM ;an038;bgb;an000;bgb + Define_Msg msgExecFailure ; AN000;SM CHKDSK not available ;an038;bgb;an000;bgbon drive %1 + endif ;an038;bgb +;---------------------- ; ;an000;bgb +Message_Number = 51 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg Inv_XA_Msg ; AN000;SM Extended Attributes h;an000;bgbas invalid clusters, +;---------------------- ; attributes truncated ;an000;bgb +Message_Number = 52 ; AN000;SM ;an000;bgb +Handle = STDOUT ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg Alloc_XA_Msg ; AN000;SM Extended Attributes l;an000;bgbocation .. , +;---------------------- ; attributes truncated ;an000;bgb +Message_Number = 53 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = dg:sublist_msg_parserr ; AN000;SM ;an046;bgb;an000;bgb +Count = 1 ; AN000;SM ;an046;bgb;an000;bgb +Class = PARSE_ERR_CLASS ; AN000;SM ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg badsw_arg ; AN000;SM Invalid parameter ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 54 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = utility_msg_class ; AN000;bgb ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg baddrv_arg ; AN000;SM Invalid drive specifi;an000;bgbcation +;---------------------- ; ;an000;bgb +Message_Number = 55 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = utility_msg_class ; AN017;bgb ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg invpath_arg ; AN000;SM Path not found ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 56 ; AN000;SM ;an000;bgb +Handle = STDERR ; AN000;SM ;an000;bgb +Sublist = None ; AN000;SM ;an000;bgb +Count = None ; AN000;SM ;an000;bgb +Class = utility_msg_class ; AN017;bgb ;an000;bgb +Function = NO_INPUT ; AN000;SM ;an000;bgb +Input = N_A ; AN000;SM ;an000;bgb + Define_Msg opnerr_arg ; AN000;SM File not found ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 0 ; ;an000;bgb;AN000; +Handle = STDERR ; ;an000;bgb;AN000; +Sublist = No_Replace ; ;AN;an000;bgb000; +Count = N_A ; ;an000;bgb;AN000; +Class = Ext_Err_Class ; ;an000;bgb;AN000; +Function = No_Function ; ;an000;bgb;AN000; +Input = N_A ; ;an000;bgb;AN000; + Define_Msg Extended_Error_Msg ; ;an000;bgb;AN000; +;----------------------- ;an000;bgb +Message_Number = 0 ; ;an000;bgb +Handle = STDERR ; ;an000;bgb;AN000; +Sublist = dg:sublist_msg_parserr ; ;an046;bgbbgb000; +Count = 1 ; ;an046;bgb;AN000; +Class = Parse_Err_Class ; ;an000;bgb;AN000; +Function = No_Function ; ;an000;bgb;AN000; +Input = N_A ; ;an000;bgb;AN000; + Define_Msg Parse_Error_Msg ; ;an000;bgb;AN000; +;----------------------- ;an000;bgb +Message_Number = 58 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = dg:Sublist_msg_orphmes ; AN000;dms ;an000;bgb +Count = 2 ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg orph_arg ; AN000;dms "%1 lost clusters fo;an000;bgbund in %2 chains.",0 +;---------------------- ; ;an000;bgb +Message_Number = 59 ; AN000;dms ;an000;bgb +Handle = STDout ; AN000;bgb ;an000;bgb +Sublist = none ; AN000;dms ;an000;bgb +Count = none ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg crlf_arg ; AN000;dms CR,LF ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 60 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = none ; AN000;dms ;an000;bgb +Count = none ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg badcd_arg ; AN000;dms "Cannot CHDIR to roo;an000;bgbt",cr,lf +;---------------------- ; ;an000;bgb +Message_Number = 61 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = dg:Sublist_Msg_Badw_arg ; AN000;dms ;an000;bgb +Count = 1 ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg badw_arg ; AN000;dms "Disk error writing ;an000;bgbFAT %1" +;---------------------- ; ;an000;bgb +Message_Number = 62 ; AN000;dms ;an000;bgb +Handle = STDOUT ; AN000;dms ;an042;bgb;an000;bgb +Sublist = dg:Sublist_Msg_Noisy ; AN000;dms ;an000;bgb +Count = 1 ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg noisy_arg ; AN000;dms " %1" ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 63 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = none ; AN000;dms ;an000;bgb +Count = none ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg baddpbdir ; AN000;dms "Invalid current dir;an000;bgbectory" +;---------------------- ; ;an000;bgb +Message_Number = 64 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = dg:Sublist_Msg_File_Arg ; AN000;dms ;an000;bgb +Count = 1 ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg file_arg ; AN000;dms "%1",cr,lf ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 65 ; AN000;dms ;an000;bgb +Handle = STDERR ; AN000;dms ;an000;bgb +Sublist = none ; AN000;dms ;an000;bgb +Count = none ; AN000;dms ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN000;dms ;an000;bgb +Function = NO_INPUT ; AN000;dms ;an000;bgb +Input = N_A ; AN000;dms ;an000;bgb + Define_Msg creatmes ; AN000;dms "Insufficient room i;an000;bgbn root directory" +;---------------------- ; ;an000;bgb +Message_Number = 70 ; AN017;bgb ;an000;bgb +Handle = STDOUT ; AN017;bgb ;an000;bgb +Sublist = dg:Sublist_msg_alloc ; AN017;bgb ;an000;bgb +Count = 1 ; AN017;bgb ;an000;bgb +Class = UTILITY_MSG_CLASS ; AN017;bgb ;an000;bgb +Function = NO_INPUT ; AN017;bgb ;an000;bgb +Input = N_A ; AN017;bgb ;an000;bgb + Define_Msg idmes3 ; AN017;bgb %1 allocation units ;an000;bgbavailable on disk +;---------------------- ; ;an000;bgb +Message_Number = 71 ; ;an000;bgb;an024;bgb +Handle = STDOUT ; ;an000;bgb;an024;bgb +Sublist = Sublist_msgSerialNumber ; ;an000;bgb;an024;bgb +Count = 2 ; ;an000;bgb;an024;bgb +Class = Utility_Msg_Class ; ;an000;bgb;an024;bgb +Function = No_Function ; ;an000;bgb;an024;bgb +Input = N_A ; ;an000;bgb;an024;bgb + Define_Msg msgSerialNumber ; ;an000;bgb;an024;bgb +;---------------------- ; ;an000;bgb +Message_Number = 72 ; AN030;bgb ;an000;bgb +Handle = STDERR ; AN030;bgb ;an000;bgb +Sublist = None ; AN030;bgb ;an000;bgb +Count = None ; AN030;bgb ;an000;bgb +Class = utility_msg_class ; AN030;bgb ;an000;bgb +Function = NO_INPUT ; AN030;bgb ;an000;bgb +Input = N_A ; AN030;bgb ;an000;bgb + Define_Msg no_mem_arg ; AN030;bgb insufficient memory ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 73 ; AN033;bgb ;an000;bgb +Handle = STDERR ; AN033;bgb ;an000;bgb +Sublist = None ; AN033;bgb ;an000;bgb +Count = None ; AN033;bgb ;an000;bgb +Class = utility_msg_class ; AN033;bgb ;an000;bgb +Function = NO_INPUT ; AN033;bgb ;an000;bgb +Input = N_A ; AN033;bgb ;an000;bgb + Define_Msg inval_media ; AN033;bgb invalid media type ;an000;bgb +;---------------------- ; ;an000;bgb +Message_Number = 74 ; AN045;bgb ;an000;bgb +Handle = STDERR ; AN045;bgb ;an000;bgb +Sublist = None ; AN045;bgb ;an000;bgb +Count = None ; AN045;bgb ;an000;bgb +Class = utility_msg_class ; AN045;bgb ;an000;bgb +Function = NO_INPUT ; AN045;bgb ;an000;bgb +Input = N_A ; AN045;bgb ;an000;bgb + Define_Msg write_fault ; AN045;bgb write fault error ;an000;bgb + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Message Data Area ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + ;an000;bgb +; THE FOLLOWING ONE BYTE CHARACTERS ARE THE PROMPT ANSWERS. ;an000;bgb +; THEY MUST BE LOWER CASE, AND THE UPPER TO LOWER, OR LOWER ;an000;bgb +; TO LOWER CONVERSION MUST BE DOABLE BY "OR AL,20h". ;an000;bgb +; Yes/No Answers ;an000;bgb +YES_BYTE DB "y" ;an000;bgb +NO_BYTE DB "n" ;an000;bgb + ;an000;bgb +;The following table is the list of abbreviated month names used to print ;an000;bgb +; out the volume ID. ;an000;bgb +; MUST BE THREE BYTES PER MONTH ;an000;bgb +MONTAB DB "JanFebMarAprMayJunJulAugSepOctNovDec" ;an000;bgb + ;an000;bgb + ;an000;bgb +yn_arg dw ? ;an000;bgb + ;an000;bgb +;orph_num dw ? ;from orphsiz; = number of lost clusters ;an000;bgb;an049;bgb +orphcnt dd ? ;number of chains of lost clusters ;an000;bgb + ;an000;bgb +report_arg dw ? ;an000;bgb +rarg1 dd ? ;changed to dword ;an000;bgb;an049;bgb +rarg3 dd ? ;changed to dword ;an000;bgb;an049;bgb + ;an000;bgb +baddrvm DB " A.",0 ;an000;bgb +badrw_str dw ? ;an000;bgb +badrw_num dw ? ;an000;bgb +block_num dw ? ;an000;bgb +fatal_arg1 dw ? ;an000;bgb +fatal_arg2 dw ? ;an000;bgb +file_arg1 dw ? ;an000;bgb +file_arg2 dw ? ;an000;bgb +free_arg1 dw ? ;an000;bgb +free_arg2 dw ? ;an000;bgb +free_arg3 dw ? ;an000;bgb +fatal_end db ".",0 ;an000;bgb + ;an000;bgb + ;an000;bgb +data ends ; AN000; ;an000;bgb diff --git a/v4.0/src/CMD/CHKDSK/CHKPARSE.INC b/v4.0/src/CMD/CHKDSK/CHKPARSE.INC new file mode 100644 index 0000000..ce76896 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKPARSE.INC @@ -0,0 +1,285 @@ + ;an000;bgb + ;an000;bgb + ;an000;bgb + ;an000;bgb +data segment public para 'DATA' ;an000;bgb ;AN000; + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Publics ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +; Public Drive_Letter_Buffer ;an000;bgb + Public SwBuffer ;an000;bgb + Public Switch_F_Buffer ;an000;bgb +; Public FileSpec_Buffer ;an000;bgb + public buffer ;an000;bgb + public sw_v, sw_f ;an000;bgb;an020;bgb + ;an000;bgb +; ;an000;bgb +;*************************************************************************** ;an000;bgb +; Equates ;an000;bgb +;*************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +;Match Flags ;an000;bgb + ;an000;bgb +Numeric_Value equ 8000h ; ;an000;bgb;AN000; +Signed_Numeric_Value equ 4000h ; ;an000;bgb;AN000; +Simple_String equ 2000h ; ;an000;bgb;AN000; +Date_String equ 1000h ; ;an000;bgb;AN000; +Time_String equ 0800h ; ;an000;bgb;AN000; +Complex_List equ 0400h ; ;an000;bgb;AN000; +Quoted_String equ 0080h ; ;an000;bgb;AN000; +Ignore_Colon equ 0010h ; ;an000;bgb;AN000; +Repeats_Allowed equ 0002h ; ;an000;bgb;AN000; +Optional equ 0001h ; ;an000;bgb;AN000; +Filespec equ 0200h ; ;an000;bgb;AN000; +Drive_Only equ 0100h ; ;an000;bgb;AN000; + ;an000;bgb +;Function_Flags ;an000;bgb + ;an000;bgb +File_Table_Capitalize equ 1 ; ;an000;bgb;AN000; +Char_Table_Capitalize equ 2 ; ;an000;bgb;AN000; +Remove_Colon equ 10h ; ;an000;bgb;AN000; + ;an000;bgb +;Extra delimeters and EOL ;an000;bgb + ;an000;bgb +Delimiters_Only equ 1 ; ;an000;bgb;AN000; +EOL_Or_Delimiters equ 2 ; ;an000;bgb;AN000; + ;an000;bgb +Semi_Colon equ ";" ; ;an000;bgb;AN000; +Tab equ 09h ; ;an000;bgb;AN000; +Colon equ ":" ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +;Parse Errors ;an000;bgb + ;an000;bgb +No_Error equ 0 ; ;an000;bgb;AN000; +Too_Many_Operands equ 1 ; ;an000;bgb;AN000; +Operand_Missing equ 2 ; ;an000;bgb;AN000; +Not_In_Switch_List equ 3 ; ;an000;bgb;AN000; +Not_In_Keyword_List equ 4 ; ;an000;bgb;AN000; +Out_Of_Range equ 6 ; ;an000;bgb;AN000; +Not_In_Value_List equ 7 ; ;an000;bgb;AN000; +Not_In_String_List equ 8 ; ;an000;bgb;AN000; +Syntax_Error equ 9 ; ;an000;bgb;AN000; +End_Of_Parse equ -1 ; ;an000;bgb;AN000; + ;an000;bgb +;Return types ;an000;bgb + ;an000;bgb +Type_Reserved equ 0 ; ;an000;bgb;AN000; +Type_Number equ 1 ; ;an000;bgb;AN000; +Type_List_Index equ 2 ; ;an000;bgb;AN000; +Type_String equ 3 ; ;an000;bgb;AN000; +Type_Complex equ 4 ; ;an000;bgb;AN000; +Type_Filespec equ 5 ; ;an000;bgb;AN000; +Type_Drive equ 6 ; ;an000;bgb;AN000; +Type_Date equ 7 ; ;an000;bgb;AN000; +Type_Time equ 8 ; ;an000;bgb;AN000; +Type_Quoted_String equ 9 ; ;an000;bgb;AN000; + ;an000;bgb +;Other ;an000;bgb + ;an000;bgb +None equ 0 ; ;an000;bgb;AN000; +No_Error equ 0 ; ;an000;bgb;AN000; +Switch_Found equ 0FFFFh ; ;an000;bgb;AN000; +Range_Ok equ 1 ; ;an000;bgb;AN000; +Command_Line_Parms equ 81h ; ;an000;bgb;AN000; + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Parse Structures ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +Control struc ;an000;bgb + ;an000;bgb +Match_Flags dw ? ;an000;bgb +Function_Flags dw ? ;an000;bgb +Result dw ? ;an000;bgb +Values dw ? ;an000;bgb +Num_Keywords db ? ;an000;bgb +Keyword db ? ;an000;bgb + ;an000;bgb +Control ends ;an000;bgb + ;an000;bgb +;Drive_Letter_Return struc ; ;an000;bgb ;AN000; +;Drive_Type db 0 ; ;an000;bgb ;AN000; +;Drive_Item_Tag db 0 ; ;an000;bgb ;AN000; +;Drive_Pointer dw 0 ; ;an000;bgb ;AN000; +;Drive_Number db 0 ;A=1, B=2, C=3 ;an000;bgb ;AN000; +;Drive_debug db 8 dup(0) ;an000;bgb +;Drive_Letter_Return ends ; ;an000;bgb ;AN000; +; ;an000;bgb +;Filespec_Return struc ;AN000;SM ;an000;bgb +;Filespec_Type db 0 ;AN000;SM ;an000;bgb +;FileSpec_Item db 0 ;AN000;SM ;an000;bgb +;FileSpec_Pointer dw 0 ;AN000;SM ;an000;bgb +;Filespec_String_Off dw 0 ;AN000;SM ;an000;bgb +;FileSpec_String_Seg dw 0 ;an000;bgb +;FileSpec_Return ends ;an000;bgb + ;an000;bgb +single_Return struc ;AN000;SM ;an000;bgb +dftype db 0 ;AN000;SM ;an000;bgb +Item db 0 ;AN000;SM ;an000;bgb +Pointer dw 0 ;AN000;SM ;an000;bgb +drnum_stroff dw 0 ;AN000;SM ;an000;bgb +return_strseg dw 0 ;an000;bgb +single_return ends ;an000;bgb + ;an000;bgb + ;an000;bgb +Switch_Return struc ; ;an000;bgb;AN000; +Switch_Type db 0 ; ;an000;bgb;AN000; +Switch_Item_Tag db 0 ; ;an000;bgb;AN000; +Switch_Pointer dw 0 ; ;an000;bgb;AN000; +Switch_Debug db 4 dup(0) ;an000;bgb +Switch_Return ends ; ;an000;bgb;AN000; + ;an000;bgb +Switch_Num_Return struc ; ;an000;bgb;AN000; +Switch_Num_Type db 0 ; ;an000;bgb ;AN000; +Switch_Num_Item_Tag db 0 ; ;an000;bgb ;AN000; +Switch_Num_Pointer dw 0 ; ;an000;bgb ;AN000; +Switch_Number_Low dw 0 ; ;AN0;an000;bgb00; +Switch_Number_High dw 0 ; ;AN0;an000;bgb00; +Switch_Num_Return ends ; ;an000;bgb;AN000; + ;an000;bgb +Switch_String_Return struc ; ;an000;bgb;AN000; +Switch_String_Type db 0 ; ;an000;bgb ;AN000; +Switch_String_Item_Tag db 0 ; ;an000;bgb ;AN000; +Switch_String_Pointer dw 0 ; ;an000;bgb ;AN000; +Switch_String_Off dw 0 ; ;an000;bgb;AN000; +Switch_String_Seg dw 0 ; ;an000;bgb;AN000; +Switch_String_Return ends ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;************************************************************************** ;an000;bgb +; Parse tables ;an000;bgb +;************************************************************************** ;an000;bgb +; ;an000;bgb +Public input_Table ;an000;bgb +input_Table label byte ; ;AN000;;an000;bgb + ;an000;bgb + dw offset dg:ext_table ;Point to next level ;A;an000;bgbN000; + db Delimiters_Only ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Semi_Colon ; ;an000;bgb;AN000; + ;an000;bgb +Drive_Table label byte ;an000;bgb;AN000; + ; ;an000;bgb + dw offset dg:Drive_Control_Definition ;Point to next level ;an000;bgb ;AN000; + db Delimiters_Only ; ;an000;bgb;AN000; + db 1 ; ;an000;bgb;AN000; + db Semi_Colon ; ;an000;bgb;AN000; + ;an000;bgb +; ;an000;bgb +;************************************************************************** ;an000;bgb +;Define Positionals, Switches and Keywords ;an000;bgb +;************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +Public ext_table ;an000;bgb +ext_table label byte ; ;an000;bgb;AN000; + ; ;an000;bgb + db 0,1 ;up to one parm, either drive or file ;an000;bgb;an026;bgb + dw dg:dfcontrol ;Pointer to control table ;an000;bgb ;AN000; + db 1 ;1 switch def ;an000;bgb;AN020;bgb + dw dg:SwControl ;switch control block ;an000;bgb;AN020;bgb + db None ;No Keywords (maxk) ;an000;bgb;AN000; + ; ;an000;bgb +Drive_Control_Definition label byte ; ;an000;bgb;AN000; + ; ;an000;bgb + db 0,1 ;Only drive letter positional ;an000;bgb;AN000; + dw dg:dfControl ;Pointer to control table ;AN0;an000;bgb00; + db None ;0 switches ;an000;bgb;AN000; + db None ;No Keywords (maxk) ;an000;bgb;AN000; + ; ;an000;bgb + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;************************************************************************** ;an000;bgb +; Define Positionals, Switches and Keywords ;an000;bgb +;************************************************************************** ;an000;bgb +; ;an000;bgb +;this is the new control block for both drive letters and filespecs ;an000;bgb +Public dfControl ;an000;bgb +dfControl label byte ; ;AN000;;an000;bgb + dw drive_only+FileSpec+Optional ; ;an000;bgb ;AN000; + dw None ; ;an000;bgb;AN000; + dw dg:Buffer ; ;AN000; ;an000;bgb + dw dg:No_Value ; ;an000;bgb;AN000; + db None ; ;an000;bgb;AN000; + ;an000;bgb +Public SwControl ;an02;an000;bgb0;bgb +SwControl label byte ; ;AN020;;an000;bgbbgb + dw None ; ;an000;bgb;AN000; + dw None ; ;an000;bgb;AN000; + dw dg:SwBuffer ; ;AN000;;an000;bgb + dw dg:No_Value ;an000;bgb ;AN000; + db 2 ; ;an000;bgb;AN020;bgb +sw_v db "/V",0 ; ;an000;bgb;AN020;bgb +sw_f db "/F",0 ; ;an000;bgb;AN020;bgb + ; ;an000;bgb + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; Value lists ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb +No_Value db 0 ; ;an000;bgb;AN000; + ;an000;bgb + ;an000;bgb +; ;an000;bgb +;************************************************************************ ;an000;bgb +; PARSE Return Buffers ;an000;bgb +;************************************************************************ ;an000;bgb +; ;an000;bgb +; these buffers were replaced by a single buffer due to the parser bug ;an000;bgb +;Drive_Letter_Buffer Drive_Letter_Return <> ;Example of structure ;an000;bgb ;AN000; +;FileSpec_Buffer FileSpec_Return <> ; ;an000;bgb +SwBuffer Switch_Return <> ; ;an000;bgb;AN000; +Switch_F_Buffer Switch_Return <> ; ;an000;bgb;AN000; +buffer single_return <> ; new results buffer ;an000;bgb +data ends ; ;an000;bgb;AN000; + ;an000;bgb +; ;an000;bgb +;***************************************************************************** ;an000;bgb +; SysParse Routines ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb + ;an000;bgb + ;an000;bgb +code segment public para 'CODE' ;an000;bgb + ;an000;bgb +FarSW equ Not_Include ; ;an000;bgb;AN000; ;AN000; +DateSW equ Not_Include ; ;an000;bgb;AN000; +TimeSW equ Not_Include ; ;an000;bgb;AN000; +FileSW equ Do_Include ; ;an000;bgb;AN000; +CAPSW equ Not_Include ; ;an000;bgb;AN000; +CmpxSW equ Not_Include ; ;an000;bgb;AN000; +NumSW equ Not_Include ; ;an000;bgb;AN000; +KeySW equ Not_Include ; ;an000;bgb;AN000; +SwSW equ Do_Include ; ;an000;bgb;AN000; +Val1SW equ Not_Include ; ;an000;bgb;AN000; +Val2SW equ Not_Include ; ;an000;bgb;AN000; +Val3SW equ Not_Include ; ;an000;bgb;AN000; +DrvSW equ Do_Include ; ;an000;bgb;AN000; +QusSW equ Not_Include ; ;an000;bgb;AN000; +basesw equ 1 ;use ds as the default register ;an025;bgb +incsw equ 0 ;include psdata myself ;an028;bgb +code ends ;an028;bgb + + +data segment PUBLIC para 'DATA' ;an028;bgb +include psdata.inc ;an028;bgb +data ends ;an028;bgb + +code segment PUBLIC para 'CODE' ;an028;bgb +pathlabl parser ;an028;bgb +INCLUDE PARSE.ASM ;AN000; ;an028;bgb +pathlabl parser ;an028;bgb +code ends ;an000;bgb diff --git a/v4.0/src/CMD/CHKDSK/CHKPRMT.ASM b/v4.0/src/CMD/CHKDSK/CHKPRMT.ASM new file mode 100644 index 0000000..48ec463 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKPRMT.ASM @@ -0,0 +1,93 @@ +TITLE CHKPRMT - Procedures called from chkdsk which prompt ;an000;bgb +page ,132 ; ;an000;bgb + ;an000;bgb + .xlist ;an000;bgb + include chkseg.inc ;an000;bgb + INCLUDE CHKCHNG.INC ;an000;bgb + INCLUDE SYSCALL.INC ;an000;bgb + INCLUDE CHKEQU.INC ;an000;bgb + INCLUDE CHKMACRO.INC ;an000;bgb + include pathmac.inc ;an000;bgb + .list ;an000;bgb + ;an000;bgb + ;an000;bgb +CONST SEGMENT PUBLIC PARA 'DATA' ;an000;bgb + EXTRN YES_BYTE:BYTE,NO_BYTE:BYTE ;an000;bgb + EXTRN YN_ARG:WORD ;an000;bgb + EXTRN HECODE:byte,CONBUF:byte ;an000;bgb +CONST ENDS ;an000;bgb + ;an000;bgb + ;an000;bgb +CODE SEGMENT PUBLIC PARA 'CODE' ;an000;bgb +ASSUME CS:DG,DS:DG,ES:DG,SS:DG ;an000;bgb + EXTRN PRINTF_CRLF:NEAR,DOCRLF:NEAR ;an000;bgb + ;an000;bgb + pathlabl chkprmt ;an000;bgb +;***************************************************************************** ;an000;bgb +;Routine name:PromptYN ;an000;bgb +;***************************************************************************** ;an000;bgb +; ;an000;bgb +;description: Validate that input is valid Y/N for the country dependent info ;an000;bgb +; Return Z flag if 'Y' entered ;an000;bgb +;Called Procedures: Message (macro) ;an000;bgb +; User_String ;an000;bgb +; ;an000;bgb +;Change History: Created 5/10/87 MT ;an000;bgb +; ;an000;bgb +;Input: DX = offset to message ;an000;bgb +; ;an000;bgb +;Output: Z flag if 'Y' entered ;an000;bgb +; ;an000;bgb +;Psuedocode ;an000;bgb +;---------- ;an000;bgb +; ;an000;bgb +; DO ;an000;bgb +; Display prompt and input character ;an000;bgb +; IF got character ;an000;bgb +; Check for country dependent Y/N (INT 21h, AX=6523h Get Ext Country;an000;bgb) +; IF NC (Yes or No) ;an000;bgb +; Set Z if Yes, NZ if No ;an000;bgb +; ENDIF ;an000;bgb +; ELSE (nothing entered) ;an000;bgb +; stc ;an000;bgb +; ENDIF ;an000;bgb +; ENDDO NC ;an000;bgb +; ret ;an000;bgb +;***************************************************************************** ;an000;bgb +Procedure PromptYN ; ;an000;bgb;AN000; + push si ;Save reg ;an000;bgb +; $DO ; ;an000;bgb;AC000; +$$DO1: + Call Display_Interface ;Display the message ;an000;bgb;AC000; + MOV DX,OFFSET DG:CONBUF ;Point at input buffer ;an000;bgb + DOS_Call Std_Con_String_Input ;Get input ;an000;bgb;AC000; + CALL DOCRLF ; ;an000;bgb + MOV SI,OFFSET DG:CONBUF+2 ;Point at contents of buffer ;an000;bgb + CMP BYTE PTR [SI-1],0 ;Was there input? ;an000;bgb +; $IF NE ;Yep ;an000;bgb;AC000; + JE $$IF2 + mov al,23h ;See if it is Y/N ;an000;bgb;AN000; + mov dl,[si] ;Get character ;an000;bgb;AN000; + DOS_Call GetExtCntry ;Get country info call ;an000;bgb;AN000; +; $IF NC ;Yes or No entered ;an000;bgb;AN000; + JC $$IF3 + cmp ax,Yes_Found ;Set Z if Yes, NZ if No ;an000;bgb;AN000; + clc ;CY=0 means Y/N found ;an000;bgb +; $ENDIF ;CY set if neither ;an000;bgb;AN000; +$$IF3: +; $ELSE ;No characters input ;an000;bgb + JMP SHORT $$EN2 +$$IF2: + stc ;CY means not Y/N ;an000;bgb +; $ENDIF ; ;an000;bgb +$$EN2: +; $ENDDO NC ; ;an000;bgb;AN000; + JC $$DO1 + pop si ; ;an000;bgb + ret ; ;an000;bgb +PromptYN endp ; ;an000;bgb;AN000; + pathlabl chkprmt ;an000;bgb + ;an000;bgb +CODE ENDS ;an000;bgb + END ;an000;bgb + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKPROC.ASM b/v4.0/src/CMD/CHKDSK/CHKPROC.ASM new file mode 100644 index 0000000..e76b78f --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKPROC.ASM @@ -0,0 +1,1892 @@ +TITLE CHKPROC - PART1 Procedures called from chkdsk +page ,132 ; + + .xlist + include chkseg.inc + INCLUDE CHKCHNG.INC + INCLUDE DOSSYM.INC + INCLUDE CHKEQU.INC + INCLUDE CHKMACRO.INC + include pathmac.inc + .list + + +DATA SEGMENT PUBLIC PARA 'DATA' + EXTRN FIXMES_ARG:word,DIREC_ARG:word + EXTRN NULDMES:byte,NULNZ:byte,BADCLUS:byte,NORECDOT:byte + EXTRN NoRecDDot:Byte + EXTRN BADCHAIN:byte,NDOTMES:byte,CDDDMES:byte + EXTRN NORECDDOT1:byte,NORECDDOT2:byte,NORECDDOT3:byte + EXTRN STACKMES:byte + EXTRN BADDPBDIR:byte, BadSubDir:byte + EXTRN BADTARG_PTR:byte,BADTARG2:byte,JOINMES:byte + EXTRN PTRANDIR:byte,PTRANDIR2:byte + EXTRN CROSS_ARG:word,NOISY_ARG:word + EXTRN FILE_ARG1:WORD,FILE_ARG2:WORD,FILE_ARG:word + EXTRN DOTMES:byte,NOISY:byte,DOTENT:byte,HAVFIX:byte + EXTRN DOFIX:byte,DIRBUF:byte,PARSTR:byte,DDOTENT:byte + EXTRN NUL:byte,ERRSUB:word,SECONDPASS:byte,ALLFILE:byte + EXTRN HIDCNT:dword,HIDSIZ:word,FILCNT:dword,FILSIZ:word ;an049;bgb + EXTRN DIRCNT:dword ;an049;bgb + EXTRN DIRSIZ:word ;an049;bgb + EXTRN DIRTYFAT:byte, + EXTRN HECODE:byte + EXTRN ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte + EXTRN BIGFAT:byte,EOFVAL:word,BADVAL:word + Extrn fTrunc:BYTE ;ac048;bgb + Extrn dirsec:word ;ac048;bgb + + EXTRN THISDPB:dword,DOTSNOGOOD:byte,NUL_ARG:byte,STACKLIM:word + EXTRN ZEROTRUNC:byte,NAMBUF:byte,SRFCBPT:word,FATMAP:word + EXTRN ISCROSS:byte,MCLUS:word,CSIZE:byte,SSIZE:word,fattbl:byte + EXTRN DSIZE:word,ARG1:word,ARG_BUF:byte,TMP_SPC:BYTE + EXTRN SECBUF:word + EXTRN Inv_XA_Msg:Byte,Alloc_XA_Msg:Byte + Extrn Data_Start_Low:Word,Data_Start_High:Word + EXTRN Read_Write_Relative:Byte + EXTRN MClus:Word,Chain_End:Word + +XA_Buffer XAL <> ;XA buffer space to read in 1st sector ;AN000; +Head_Mark db 0 ;Flag for MarkMap ;AN000; +BClus dw 0 ;Bytes/Cluster +public cross_clus +Cross_Clus dw 0 ;Cluster crosslink occurred on +Cluster_Count dw 0 ; ;AN000; +First_Cluster dw 0 ; ;AN000; +Previous_Cluster dw 0 ; ;AN000; +XA_Pass db 0 ; ;AN000; +File_Size_High dw 0 ; ;AN000; +File_Size_Low dw 0 ; ;AN000; +Chain_Size_Low dw 0 ; ;AN000; +Chain_Size_High dw 0 ; ;AN000; + + +public Head_Mark +public BClus +public Cluster_Count +public First_Cluster +public Previous_Cluster +public XA_Pass +public File_Size_High +public File_Size_Low +public Chain_Size_Low +public Chain_Size_High +DATA ENDS + + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:DG,ES:DG,SS:DG +;Structures used by DIRPROC +SRCHFCB STRUC + DB 44 DUP (?) +SRCHFCB ENDS +SFCBSIZ EQU SIZE SRCHFCB + EXTRN PRINTF_CRLF:NEAR,SUBERRP:NEAR,FCB_TO_ASCZ:NEAR + EXTRN FIGREC:NEAR,EPRINT:NEAR + EXTRN DOINT26:NEAR,PROMPTYN:NEAR + EXTRN DOTCOMBMES:NEAR,FATAL:NEAR,MARKMAP:NEAR,GETFILSIZ:NEAR + EXTRN SYSTIME:NEAR, Read_Disk:Near,DoCRLF:Near + extrn crosschk:near + extrn UNPACK:near, PACK:near +public DOTDOTHARDWAY, NODOT, DOEXTMES1, MESD1, CANTREC, DOTGOON, NODDOT +public DOEXTMES2, MESD2, NFIX, CANTREC2, NULLDIRERR, DOEXTMES3, DOTSBAD +public dotsbad2, DIRPROC, STACKISOK, NOPRINT, JOINERR +public NONULLDERr, DOTOK, DATTOK, DLINKOK, BADDSIZ, DSIZOK, CHKDOTDOT +public DOTDOTOK, DDATTOK, DDLINKOK, BADDDSIZ, DDSIZOK, ROOTDIR +public DODDH, DIRDONE, MOREDIR, FPROC1, NOPRINT2, HIDENFILE, NORMFILE, NEWDIR +public DPROC1, CONVDIR, DPROC2, CANTTARG, BogusDir, ASKCONV +public PRINTTRMES, CROSSLOOK, CHLP, CROSSLINK, CHAINDONE +public FIXENT2, RET20, FIXENT, GETENT, CLUSISOK +public SKIPLP, GOTCLUS, DOROOTDIR, RDRETRY, RDOK2, WANTROOT, CHECKNOFMES, ret14 +public CHECKERR, get_currdirERR, ok_pri_dir, get_thiselERR, ok_pri_el +public get_THISEL, get_THISEL2, get_currdir, GET_END, ERRLOOP, LPDONE +public CHECK_SPLICE, NT_SPLC, MarkFAT, Bad_Cluster, Check_Chain_Sizes +public print_filename ;ac048;bgb +public NOTROOT ;ac048;bgb +public FIXDOT ;ac048;bgb + + + pathlabl chkproc +SUBTTL DIRPROC -- Recursive directory processing +PAGE +;************************************************************************** +; DOTDOTHARDWAY - change dir to the previous directory using '..' +; +; called by - +; +; inputs - parse string '..' +; +; outputs - new default directory +; +;NOTE +; On versions of DOS < 2.50 "cd .." would fail if there was no ".." +; entry in the current directory. On versions >= 2.50 "cd .." +; is handled as a string manipulation and therefore should always +; work. On < 2.50 this routine didddled the current directory string +; INSIDE THE DOS DATA STRUCTURES. This is no longer desirable, or +; needed. +;************************************************************************** +procedure dotdothardway,near + MOV DX,OFFSET DG:PARSTR + DOS_Call ChDir ; ;AC000; + RET +endproc dotdothardway + + +;************************************************************************** ;ac048;bgb +; NODOT - come here if there is no . entry in the first entry of the sub- ;ac048;bgb +; directory. The . entry is a pointer to the subdirectory itself. ;ac048;bgb +; The entry from the search first did not find it, and the subdir is ;ac048;bgb +; not joined. So, try to put a new . entry into the first slot. ;ac048;bgb +; ;ac048;bgb +; called by - nonullderr ;ac048;bgb +; ;ac048;bgb +; inputs - SI - points to arg_buf, which is a filespec ;ac048;bgb +; DI - points to tmp_spc, which is a filespec ;ac048;bgb +; AX - return value from search first ;ac048;bgb +; ;ac048;bgb +; outputs - if the /f parm was entered, tries to replace the . entry ;ac048;bgb +; AX - saves the return value from search first ;ac048;bgb +; ;ac048;bgb +; logic: 1. go display error messages. Different messages are displayed, ;ac048;bgb +; depending on /f and /v parms. ;ac048;bgb +; ;ac048;bgb +; 2. go get the sector number and read it into ram ;ac048;bgb +; ;ac048;bgb +; 3. if the first entry is erased (begins with hex e5), then we can ;ac048;bgb +; fill it with the corrected . entry. Otherwise, go to #6. ;ac048;bgb +; ;ac048;bgb +; 4. So, fill entry with all the dir fields - name, ext, attr, date, ;ac048;bgb +; time, size, cluster #. ;ac048;bgb +; ;ac048;bgb +; 5. write it back to disk. ;ac048;bgb +; ;ac048;bgb +; 6. go check out the .. entry ;ac048;bgb +;************************************************************************** ;ac048;bgb +NODOT: ;No . ;ac048;bgb + PUSH AX ;save the return value from search 1st ;ac048;bgb +;display msgs ;;;;;;;;jnz doextmes1 ;ac048;bgb + CMP [NOISY],OFF ;was /v parm entered? ;ac048;bgb;AC000; +; $IF Z ;display no /v msgs ;ac048;bgb + JNZ $$IF1 + call suberrp ;ac048;bgb + ;;;;;;;;jmp short mesd1 ;ac048;bgb +; $ELSE ;display /v msgs ;ac048;bgb + JMP SHORT $$EN1 +$$IF1: +DOEXTMES1: mov si,offset dg:dotmes ;first find out where we are ;ac048;bgb + call get_currdirerr ;ac048;bgb + mov dx,offset dg:ndotmes ;print dir, dot, and 'not found' msg ;ac048;bgb + call eprint ;ac048;bgb +; $ENDIF ;ac048;bgb +$$EN1: + ;ac048;bgb +;go find the sector ;ac048;bgb +MESD1: XOR AX,AX ;set entry number to zero ;ac048;bgb + PUSH BX ;save ;ac048;bgb + PUSH BP ;save ;ac048;bgb + CALL GETENT ;get the sector number ;ac048;bgb + POP BP ;restore bp ;ac048;bgb + PUSH BP ;put it back ;ac048;bgb + CMP BYTE PTR [DI],0E5H ;is this 1st entry erased/open? ;ac048;bgb +; $if nz ;ac048;bgb + JZ $$IF4 +;cant fill . entry ;JNZ CANTREC ;ac048;bgb ;Nope +CANTREC: INC [DOTSNOGOOD] ;ac048;bgb + CMP [NOISY],OFF ; ;ac048;bgb ;AC000; +; $if nz ;ac048;bgb + JZ $$IF5 + ;JZ DOTGOON ;ac048;bgb + MOV DX,OFFSET DG:NORECDOT ;ac048;bgb + CALL EPRINT ;ac048;bgb +; $endif ;ac048;bgb +$$IF5: + jmp dotgoon ;ac048;bgb +; $endif ;ac048;bgb +$$IF4: + +;get filename +fixdot: MOV SI,OFFSET DG:DOTENT ;point to valid . entry + MOV CX,11 ;move filename and ext + REP MOVSB ;Name + PUSH AX ;save disk number +;move attr byte + MOV AL,ISDIR ;hex 10 + STOSB ;Attribute +; Add in time for directory - BAS July 17/85 + ADD DI,10 + push dx ;save starting sector number ;ac048;bgb + CALL SYSTIME + STOSW ; Time + MOV AX,DX + STOSW ; Date + MOV AX,[BP+6] + STOSW ;Alloc # + XOR AX,AX + STOSW + STOSW ;Size + pop dx ;restore starting sector number ;ac048;bgbb + POP AX ; +;write back to disk + MOV [HAVFIX],1 ;Have a fix + CMP [DOFIX],0 ; /f parm entered? +; $if nz ;ac048;bgb + JZ $$IF8 + ;JZ DOTGOON ;ac048;bgbif not F + MOV CX,1 ;ac048;bgb + CALL DOINT26 ;ac048;bgb + ;JMP SHORT DOTGOON ;ac048;bgb +; $endif ;ac048;bgb +$$IF8: +;go check out .. entry +DOTGOON: POP BP + POP BX + POP AX + MOV SI,OFFSET DG:DIRBUF + JMP CHKDOTDOT ;Go look for .. +;***************************************************************************** + + + + +NODDOT label far ;No .. + PUSH AX ;Return from SRCH + CMP [NOISY],OFF ; ;AC000; + JNZ DOEXTMES2 + CALL SUBERRP + JMP SHORT MESD2 +DOEXTMES2: + MOV SI,OFFSET DG:PARSTR + CALL get_currdirERR + MOV DX,OFFSET DG:NDOTMES + CALL EPRINT + +MESD2: + MOV AX,1 + PUSH BX + PUSH BP + CALL GETENT + POP BP + PUSH BP + CMP BYTE PTR [DI],0E5H ;Place to put it? + JNZ CANTREC2 ;Nope + MOV SI,OFFSET DG:DDOTENT + MOV CX,11 + REP MOVSB ;Name + PUSH AX + MOV AL,ISDIR + STOSB ;Attribute + ADD DI,10 +; +; Add in time for directory - BAS July 17/85 + push dx ;save starting sector number ;ac048;bgb + CALL SYSTIME + STOSW ; Time + MOV AX,DX + STOSW ; Date + MOV AX,[BP+4] + STOSW ;Alloc # + XOR AX,AX + STOSW + STOSW ;Size + pop dx ;restore starting sector number ;ac048;bgbb + POP AX + MOV [HAVFIX],1 ;Got a fix + CMP [DOFIX],0 + JZ NFIX ;No fix if no F, carry clear + MOV CX,1 + CALL DOINT26 +NFIX: + restorereg ;ac048;bgb + MOV SI,OFFSET DG:DIRBUF + JMP far ptr ROOTDIR ;Process files + +CANTREC2: + restorereg ;ac048;bgb + CMP [NOISY],OFF ; ;AC000; + JZ DOTSBAD2 + MOV DX,OFFSET DG:NORECDDOT + JMP DOTSBAD + +NULLDIRERR label far ;dir is empty + CMP [NOISY],OFF ; ;AC000; + JNZ DOEXTMES3 + CALL SUBERRP + JMP SHORT DOTSBAD2 +DOEXTMES3: + MOV SI,OFFSET DG:NUL + CALL get_currdirERR + MOV DX,OFFSET DG:NULDMES +DOTSBAD: ;Can't recover + mov [file_arg2],offset dg:badtarg2 + inc byte ptr [nul_arg] + MOV fTrunc,TRUE + CALL EPRINT +dotsbad2: + CALL DOTDOTHARDWAY + INC [DOTSNOGOOD] + MOV SP,BP ;Pop local vars + POP BP ;Restore frame + RET 4 ;Pop args + + + + +PAGE +;*************************************************************************** +; DIRPROC - recursive tree walker +; +; called by - main-routine in chkdsk1.sal +; +; inputs - ax=0 +; - two words of 0 on the stack +; +;Recursive tree walker +;dirproc(self,parent) +;**************************************************************************** +DIRPROC: + MOV [DOTSNOGOOD],0 ;Init to dots OK - set . or .. error flag to false + MOV [ERRSUB],0 ;No subdir errors yet + PUSH BP ;Save frame pointer - 0 + MOV BP,SP ;ffe2 - 2c = ffb6 + SUB SP,SFCBSIZ ;Only local var + +; are we at stack overflow ? + CMP SP,[STACKLIM] ; ffb6 vs. 5943 ;an005;bgb +; $IF NA + JA $$IF10 +;;;;;;;;JA STACKISOK + MOV BX,OFFSET DG:STACKMES ;Out of stack + JMP FATAL +; $ENDIF +$$IF10: + +STACKISOK: +;print the files as they are found + CMP [NOISY],off ; off= 0 ;AC000; +; $IF NZ ;if not noisy, dont print filenames + JZ $$IF12 +;;;;;;;;JZ NOPRINT + CMP [SECONDPASS],False ; ;AC000; +; $IF Z ;only print on the first pass + JNZ $$IF13 +;;;;;;;;;;;;JNZ NOPRINT ;Don't do it again on second pass + MOV SI,OFFSET DG:NUL + CALL get_CURRDIR + mov dx,offset dg:DIREC_arg ;Tell user where we are + CALL PRINTf_crlf +; $ENDIF +$$IF13: +; $ENDIF +$$IF12: + +; initialize search fcb +NOPRINT: + MOV SI,OFFSET DG:ALLFILE ;extended fcb + MOV DI,SP + PUSH DI + MOV CX,SFCBSIZ ;move 44dec bytes + REP MOVSB ;from allfile (ds:si) to es:di +; find this file + POP DX ; from push bp + MOV BX,DX ;BX points to SRCH FCB + DOS_Call Dir_Search_First ;search for any file ;AC000; +; + CMP WORD PTR [BP+6],0 ;attribute byte- root will = zero +; $if z + JNZ $$IF16 + jmp far ptr rootdir ;yes, we are at the root +; $endif +$$IF16: + OR AL,AL ;check return code from search first + JZ NONULLDERR + CALL CHECK_SPLICE ; See if dir is spliced +; $if c + JNC $$IF18 +;;;;;;;;;;;;JC nulldirerr ; Not spliced, error + jmp nulldirerr +; $endif +$$IF18: +JOINERR: + MOV SI,OFFSET DG:NUL + CALL get_currdir + mov fTrunc,TRUE + mov dx,offset dg:joinmes ; ;AC000; + call Printf_Crlf ; ;AC000; + mov dx,offset dg:badtarg2 ; ;AC000; + call Printf_CRLF ; ;AC000; + CALL DOTDOTHARDWAY + MOV SP,BP ;Pop local vars + POP BP ;Restore frame + RET 4 ;Pop args + + + +NONULLDERR: + MOV SI,OFFSET DG:DIRBUF + DIRNAM + MOV DI,OFFSET DG:DOTENT + MOV CX,11 + REP CMPSB + JZ DOTOK ;Got a . as first entry + push ax ;save return code from search first ;an045;bgb + CALL CHECK_SPLICE ; See if dir is spliced +; $IF C ;carry means no join on this dir ;an045;bgb + JNC $$IF20 + pop ax ;restore return code ;an045;bgb + jmp nodot ;goto no . entry code ;an045;bgb +; $ELSE ;no carry means dir is joined ;an045;bgb + JMP SHORT $$EN20 +$$IF20: + pop ax ;restore return code ;an045;bgb + jmp joinerr ;goto join error code ;an045;bgb +; $ENDIF ;no carry means dir is joined ;an045;bgb +$$EN20: +;;;;;;;;JNC JOINERR ; spliced, stop ;an045;bgb +;;;;;;;;JMP NODOT ;No . ;an045;bgb + +DOTOK: + MOV SI,OFFSET DG:DIRBUF + MOV AL,[SI.DIRATT] + TEST AL,ISDIR + JNZ DATTOK + PUSH SI ;. not a dir? + MOV SI,OFFSET DG:DOTMES + ;MOV DX,OFFSET DG:BADATT + mov dx,offset dg:norecddot2 ; ;AN000; + CALL DOTCOMBMES + POP SI + OR [SI.DIRATT],ISDIR + CALL FIXENT ;Fix it +DATTOK: + MOV AX,[SI.DIRCLUS] + CMP AX,[BP+6] ;. link = MYSELF? + JZ DLINKOK + PUSH SI ;Link messed up + MOV SI,OFFSET DG:DOTMES + ;MOV DX,OFFSET DG:CLUSBAD + mov dx,offset dg:norecddot1 ; ;AN000; + CALL DOTCOMBMES + POP SI + MOV AX,[BP+6] + MOV [SI.DIRCLUS],AX + CALL FIXENT ;Fix it +DLINKOK: + MOV AX,WORD PTR [SI.DIRESIZ] + OR AX,AX + JNZ BADDSIZ + MOV AX,WORD PTR [SI.DIRESIZ+2] + OR AX,AX + JZ DSIZOK +BADDSIZ: ;Size should be zero + PUSH SI + MOV SI,OFFSET DG:DOTMES + ;MOV DX,OFFSET DG:BADSIZM + mov dx,offset dg:norecddot3 ; ;AN000; + CALL DOTCOMBMES + POP SI + XOR AX,AX + MOV WORD PTR [SI.DIRESIZ],AX + MOV WORD PTR [SI.DIRESIZ+2],AX + CALL FIXENT ;Fix it +DSIZOK: ;Get next (should be ..) + MOV DX,BX + DOS_Call Dir_Search_Next ; ;AC000; +CHKDOTDOT: ;Come here after . failure + OR AL,AL + JZ DOTDOTOK + JMP NODDOT ;No .. +DOTDOTOK: + MOV SI,OFFSET DG:DIRBUF + DIRNAM + MOV DI,OFFSET DG:DDOTENT + MOV CX,11 + REP CMPSB +; $if nz + JZ $$IF23 + jmp noddot +;;; ;;;;;;;;JNZ NODDOT ;No .. +; $endif +$$IF23: + MOV SI,OFFSET DG:DIRBUF + MOV AL,[SI.DIRATT] + TEST AL,ISDIR + JNZ DDATTOK ;.. must be a dir + PUSH SI + MOV SI,OFFSET DG:PARSTR + ;MOV DX,OFFSET DG:BADATT + mov dx,offset dg:norecddot2 ; ;AN000; + CALL DOTCOMBMES + POP SI + OR [SI.DIRATT],ISDIR + CALL FIXENT ;Fix it +DDATTOK: + PUSH SI + MOV AX,[SI.DIRCLUS] + CMP AX,[BP+4] ;.. link must be PARENT + JZ DDLINKOK + MOV SI,OFFSET DG:PARSTR + ;MOV DX,OFFSET DG:CLUSBAD + mov dx,offset dg:norecddot1 ; ;AN000; + CALL DOTCOMBMES + POP SI + MOV AX,[BP+4] + MOV [SI.DIRCLUS],AX + CALL FIXENT ;Fix it +DDLINKOK: + MOV AX,WORD PTR [SI.DIRESIZ] + OR AX,AX + JNZ BADDDSIZ + MOV AX,WORD PTR [SI.DIRESIZ+2] + OR AX,AX +; $if z + JNZ $$IF25 + jmp DDSIZOK +; $endif +$$IF25: +BADDDSIZ: ;.. size should be 0 + PUSH SI + MOV SI,OFFSET DG:PARSTR + ;MOV DX,OFFSET DG:BADSIZM + mov dx,offset dg:norecddot3 ; ;AN000; + CALL DOTCOMBMES + POP SI + XOR AX,AX + MOV WORD PTR [SI.DIRESIZ],AX + MOV WORD PTR [SI.DIRESIZ+2],AX + CALL FIXENT ;Fix it + + +;*************************************************************************** +; DDSIZOK - search for the next file in this directory +;*************************************************************************** +DDSIZOK label far + MOV DX,BX ;search for Next entry + DOS_Call Dir_Search_Next ;func=12 ;AC000; + +ROOTDIR label far ;come here after search first .. failure also + OR AL,AL ; was a matching filename found? + JZ MOREDIR ;zero = yes ;More to go + CMP WORD PTR [BP+6],0 ;nz=no ;Am I the root? + JZ DIRDONE ;Yes, no chdir + MOV DX,OFFSET DG:PARSTR + DOS_Call ChDir ; ;AC000; + JNC DIRDONE ;Worked + +; NOTE************************************************ +; On DOS >= 2.50 "cd .." should ALWAYS work since it is +; a string manipulation. Should NEVER get to here. + + CMP [NOISY],OFF ; ;AC000; + JZ DODDH + MOV SI,OFFSET DG:NUL + CALL get_currdirERR + MOV DX,OFFSET DG:CDDDMES + CALL EPRINT +DODDH: + CALL DOTDOTHARDWAY ;Try again +DIRDONE: + MOV SP,BP ;Pop local vars + POP BP ;Restore frame + RET 4 ;Pop args + + + +;***************************************************************** +; found at least one file in this subdir! +;***************************************************************** +MOREDIR: + MOV SI,OFFSET DG:DIRBUF ;point to where ext fcb of found file is + TEST [SI.DIRATT],ISDIR ;attr 010h = sub-directory + JNZ NEWDIR ;Is a new directory? + CMP [SECONDPASS],False ;no, same dir ;AC000; + JZ FPROC1 ;2nd pass here + CALL CROSSLOOK ;Check for cross links + JMP DDSIZOK ;Next + +FPROC1: + CMP [NOISY],OFF ; ;AC000; +; $IF NZ ;print filenames? + JZ $$IF27 + call print_filename +; $ENDIF +$$IF27: +NOPRINT2: + mov Cluster_Count,0 ;No clusters for vol label ;AN000; + mov cx,0 ;setup cx for 0 size vol labels ;an016;bgb + TEST [SI.DIRATT],VOLIDA ;attr=08 ;Don't chase chains on labels ;AC000; +; $IF Z ;no, regular file + JNZ $$IF29 + MOV AL,81H ;Head of file + mov di,word ptr [si].DIRESIZ+0 ;Get file size + mov File_Size_Low,di ; + mov di,word ptr [si].DIRESIZ+2 ; + mov File_Size_High,di ; + mov di,[si].DirClus ;First cluster of file ;AN000; + CALL MARKFAT + MOV CX,Cluster_Count ;Get number of clusters +;;;;;;;;;;;;PUSH CX ;Save them +;;;;;;;;;;;;CALL Check_Extended_Attributes ;See if XA exist, and handle ;AN000; +;;;;;;;;;;;;POP CX ;Get File length clusters +;;;;;;;;;;;;ADD CX,Cluster_Count ;Add in XA clusters + TEST [SI.DIRATT],HIDDN ; + JZ NORMFILE ; +; $ENDIF +$$IF29: +hidenfile: + add word ptr hidcnt,1 ;found another hidden file ;an049;bgb + adc word ptr hidcnt+2,0 ;add high word if > 64k files ;an049;bgb + add hidsiz,cx ;it was this many bytes ;an049;bgb + JMP ddsizok ;Next +NORMFILE: + add word ptr filcnt,1 ;inc file counter ;an049;bgb + adc word ptr filcnt+2,0 ;add high word if >64k files ;an049;bgb + add filsiz,cx ;add in size of file ;an049;bgb + JMP ddsizok ;Next + + +;*************************************************************************** +; NEWDIR - come here whenever you find another directory entry +; inputs: SI - points to directory entry +;*************************************************************************** +NEWDIR: + CMP [SECONDPASS],False ;are we on 2nd pass? ;AC000; + JZ DPROC1 ;zero means no - skip next part + CALL CROSSLOOK ;2nd pass - Check for cross links + JMP SHORT DPROC2 ;goto dproc2 +DPROC1: ;1st pass + MOV AL,82H ;Head of dir + mov di,[si].DirClus ;get 1st clus num from dir entry ;AN000; + mov File_Size_Low,0 ; ;Set to zero, shouldn't ;AN000; + mov File_Size_High,0 ; be looked at for dir ;AN000; + CALL MARKFAT + add word ptr dircnt,1 ;add 1 to the dir counter ;an047;bgb + adc word ptr dircnt+2,0 ;add 1 to the high word if carry ;an047;bgb + MOV CX,Cluster_Count ;Add count of clusters in files ;AN000; + CMP [ZEROTRUNC],0 ;did we modify the file size? ;an026;bgb + JZ DPROC2 ;Dir not truncated +CONVDIR: ;yes, dir size truncated + AND [SI.DIRATT],NOT ISDIR ;Turn into file + CALL FIXENT + POP BX ;Get my SRCH FCB pointer back + POP [ERRSUB] ;restore from prev dir + JMP ddsizok ;Next +DPROC2: + add dirsiz,cx ;add in siz of clusters ;an049;bgb +; put 4 words on the stack - for next call to dirproc? + PUSH [ERRSUB] ;save the fcb ptr from prev dir + PUSH BX ;Save my srch FCB pointer + MOV AX,[SI].DirCLus ;get 1st cluster number + PUSH AX ; Give him his own first clus pointer + PUSH [BP+6] ; His PARENT is me +;copy fcb name to msg string name + ADD SI,DIRNAM ;point to name, +08 + MOV DI,OFFSET DG:NAMBUF + savereg ;copy to msg string + CALL FCB_TO_ASCZ + restorereg +;check out validity of dir + OR AX,AX ;does the 1st clus in dir point to zero? + JZ BogusDir ; no, it is bogus + mov dx,di + DOS_Call ChDir ; chdir to it ;AC000; + JC CANTTARG ; carry means bad dir +; go check out new dir + CALL DIRPROC + POP BX ;Get my SRCH FCB pointer back + POP [ERRSUB] ;restore from prev dir + CMP [DOTSNOGOOD],0 + JNZ ASKCONV + JMP ddsizok ;Next +;newdir error routines +CANTTARG: +;cant chdir + ADD SP,8 ; Clean stack + mov SI,dx ; Pointer to bad DIR + CALL get_currdirERR + MOV DX,OFFSET DG:BADTarg_PTR + mov fTrunc,TRUE + call printf_crlf + JMP ddsizok ;Next +BogusDir: +;bad dir entry + ADD SP,8 ; clean off stack + MOV SI,DX ; pointer to bad dir + CALL get_currdirERR ; output message with dir + MOV DX,OFFSET DG:BadSubDir ; real error message + CALL EPRINT ; to stderr... +ASKCONV: + CMP [SECONDPASS],False ; ;AC000; +; $if nz + JZ $$IF31 + jmp ddsizok +;;;;;;;;;;;;JNZ DDSIZOK ;Leave on second pass +; $endif +$$IF31: + cmp [NOISY],on ; /v entered ? ;An027;bgb +; $IF E ; no, skip next msg ;An027;bgb + JNE $$IF33 + MOV DX,OFFSET DG:PTRANDIR ;unrecoverable error in directory ;An027;bgb + call printf_crlf ;display msg ;An027;bgb +; $ENDIF +$$IF33: +PRINTTRMES: + MOV DX,OFFSET DG:PTRANDIR2 ;either case - "convert dir to file?" ;An027;bgb + CALL PROMPTYN ;Ask user what to do +; $if nz + JZ $$IF35 + jmp ddsizok +;;;;;;;;;;; JNZ DDSIZOK ;Leave on second pass +; $endif +$$IF35: + PUSH BP + PUSH BX + MOV AX,[BX+THISENT] ;Entry number + CALL GETENT ;Get the entry + MOV SI,DI + MOV DI,OFFSET DG:DIRBUF + PUSH DI + ADD DI,DIRNAM + MOV CX,32 + REP MOVSB ;Transfer entry to DIRBUF + POP SI + PUSH SI + MOV SI,[SI.DIRCLUS] ;First cluster + CALL GETFILSIZ + POP SI + POP BX + POP BP + MOV WORD PTR [SI.DIRESIZ],AX ;Fix entry + MOV WORD PTR [SI.DIRESIZ+2],DX + JMP CONVDIR ;convert directory +;***************************************************************************** +;end of newdir +;***************************************************************************** + + + +SUBTTL fat-Look routines +PAGE +;***************************************************************************** +; CROSSLOOK - look at the fat, check for cross linked files +; called by - +;**************************************************************************** +CROSSLOOK: +;Same as MRKFAT only simpler for pass 2 + MOV [SRFCBPT],BX ;an014;bgb + MOV BX,SI ;an014;bgb + MOV SI,[BX.DIRCLUS] ;an014;bgb + CALL CROSSCHK ;an014;bgb + JNZ CROSSLINK ;an014;bgb +;;;;;;;;mov XA_Pass,False ;an014;bgb ;an014;bgb + +CHLP: + PUSH BX ;an014;bgb + CALL UNPACK ;an014;bgb + POP BX ;an014;bgb + XCHG SI,DI ;an014;bgb + CMP SI,[EOFVAL] ;an014;bgb + jae chaindone ;an014;bgb ;an014;bgb +;;;;;;;;JAE Check_XA_Cross ;an014;bgb ;an014;bgb + CALL CROSSCHK ;an014;bgb + JZ CHLP ;an014;bgb + JMP SHORT CROSSLINK ;an014;bgb + ;an014;bgb +Check_XA_Cross: ; ;AN000; + +;;;;;;;;mov SI,[BX.DIR_XA] ;See if extended attribute ;an014;bgb ;AN000; +;;;;;;;;cmp si,0 ;Is there? ;an014;bgb ;AN000; +;;;;;;;;je ChainDoneJ ;No if zero ;an014;bgb ;AN000; +; CALL CROSSCHK ;Yes, see if crosslinked ;an014;bgb ;AN000; +; JNZ CROSSLINKJ ;NZ means yes ;an014;bgb ;AN000; +;A_Cross_Loop: ; ;an014;bgb ;AN000; +; PUSH BX ; ;an014;bgb ;AN000; +; CALL UNPACK ;Get next cluster ;an014;bgb ;AN000; +; POP BX ; ;an014;bgb ;AN000; +; XCHG SI,DI ; ;an014;bgb ;AN000; +; CMP SI,[EOFVAL] ;Reach the end? ;an014;bgb ;AN000; +; JAE ChainDoneJ ;Leave if so ;an014;bgb ;AN000; +; CALL CROSSCHK ;See if crosslink ;an014;bgb ;AN000; +; JZ XA_Cross_Loop ;Go check next cluster if not ;AN000; +; jmp CrossLink ;Go handle crosslink ;an014;bgb ;AN000; +; + +;NOCLUSTERSJ: JMP NOCLUSTERS + + + CHASELOOP: ;an014;bgb + PUSH BX ;an014;bgb + CALL UNPACK ;an014;bgb + POP BX ;an014;bgb + INC CX ;an014;bgb + XCHG SI,DI ;an014;bgb + CMP SI,[EOFVAL] ;an014;bgb + JAE CHAINDONE ;an014;bgb + CMP SI,2 ;an014;bgb + JB MRKBAD ;an014;bgb + CMP SI,[MCLUS] ;an014;bgb + JBE MRKOK ;an014;bgb + MRKBAD: ;Bad cluster # in chain + PUSH CX ;an014;bgb + PUSH DI ;an014;bgb + CALL get_THISELERR ;an014;bgb + MOV DX,OFFSET dg:BADCHAIN ;an014;bgb + CALL EPRINT ;an014;bgb + POP SI ;an014;bgb + MOV DX,0FFFH ;Insert EOF ;an014;bgb + CMP [BIGFAT],0 ;an014;bgb + JZ FAT12_1 ;an014;bgb + MOV DX,0FFFFH ;an014;bgb + FAT12_1: ;an014;bgb ;an014;bgb ;an014;bgb + PUSH BX ;an014;bgb + CALL PACK ;an014;bgb + POP BX ;an014;bgb + POP CX ;an014;bgb + JMP SHORT CHAINDONE ;an014;bgb + + MRKOK: + CALL MARKMAP ;an014;bgb + JZ CHASELOOP ;an014;bgb +Public CrossLink +CROSSLINK: ;File is cross linked + INC [ISCROSS] ;an014;bgb + CMP [SECONDPASS],False ; ;an014;bgb ;AC000; + JZ CHAINDONE ;Crosslinks only on second pass ;an014;bgb + mov [cross_clus],si ;Cluster number ;an014;bgb + CALL get_THISEL ;an014;bgb + Message File_Arg ;Print file out ;an014;bgb ;AN000; + MOV DX,OFFSET DG:CROSS_arg ;Print message out ;an014;bgb ;AC000; + CALL PRINTf_crlf ;an014;bgb +Public ChainDone +CHAINDONE: + TEST [BX.DIRATT],ISDIR + JNZ NOSIZE ;Don't size dirs + CMP [ISCROSS],0 + JNZ NOSIZE ;Don't size cross linked files;an014;bgb + CMP [SECONDPASS],False ; + JNZ NOSIZE ;Don't size on pass 2 (CX garbage) + MOV AL,[CSIZE] + XOR AH,AH + MUL [SSIZE] + PUSH AX ;Size in bytes of one alloc unit + MUL CX + MOV DI,DX ;Save allocation size + MOV SI,AX + SUB AX,WORD PTR [BX.DIRESIZ] + SBB DX,WORD PTR [BX.DIRESIZ+2] + JC BADFSIZ ;Size to big + OR DX,DX + JNZ BADFSIZ ;Size to small + POP DX + CMP AX,DX + JB NOSIZE ;Size within one Alloc unit + PUSH DX ;Size too small + PUBLIC BadFSiz + BADFSIZ: + POP DX + PUSH CX ;Save size of file + MOV WORD PTR [BX.DIRESIZ],SI + MOV WORD PTR [BX.DIRESIZ+2],DI + CALL FIXENT2 ;Fix it + CALL get_THISELERR + MOV DX,OFFSET DG:BADCLUS + CALL EPRINT + POP CX ;Restore size of file + NOSIZE: + MOV SI,BX + MOV BX,[SRFCBPT] + RET + + NOCLUSTERS: + ;File is zero length + OR SI,SI + JZ CHKSIZ ;Firclus is OK, Check size + MOV DX,OFFSET DG:NULNZ + ADJUST: + PUSH DX + CALL get_THISELERR + POP DX + CALL EPRINT + XOR SI,SI + MOV [BX.DIRCLUS],SI ;Set it to 0 + MOV WORD PTR [BX.DIRESIZ],SI ;Set size too + MOV WORD PTR [BX.DIRESIZ+2],SI + CALL FIXENT2 ;Fix it + INC [ZEROTRUNC] ;Indicate truncation + JMP CHAINDONE + + PUBLIC ChkSiz + CHKSIZ: + MOV DX,OFFSET DG:BADCLUS + CMP WORD PTR [BX.DIRESIZ],0 + JNZ ADJUST ;Size wrong + CMP WORD PTR [BX.DIRESIZ+2],0 + JNZ ADJUST ;Size wrong + JMP CHAINDONE ;Size OK + + +SUBTTL Routines for manipulating dir entries +PAGE + +FIXENT2: +;Same as FIXENT only [SRFCBPT] points to the search FCB, BX points to the entry + savereg + MOV SI,BX + MOV BX,[SRFCBPT] + CALL FIXENT + restorereg +RET20: RET + +FIXENT: +;BX Points to search FCB +;SI Points to Entry to fix + MOV [HAVFIX],1 ;Indicate a fix + CMP [DOFIX],0 ;did the user enter /f flag? + JZ fixret ;zero means no - dont fix it + savereg + MOV AX,[BX+THISENT] ;Entry number + CALL GETENT + POP SI ;Entry pointer + ADD SI,DIRNAM ;Point to start of entry + MOV CX,32 + REP MOVSB + INC CL + CALL DOINT26 + restorereg +fixret: RET + + + +;***************************************************************************** ;ac048;bgb +; GETENT - calculate, and read into ram, the sector of the directory entry ;ac048;bgb +; that is invalid. This entry can be in either the root directory, ;ac048;bgb +; or in a sub-directory. If it is in the root, it can be in the first ;ac048;bgb +; sector of the root dir, or in a subsequent sector. If it is in a ;ac048;bgb +; subdirectory, it can be in the first cluster of the subdir, or in ;ac048;bgb +; any subsequent cluster. It can also be in the first sector of the ;ac048;bgb +; cluster, or in any of the following sectors within that cluster. ;ac048;bgb +; ;ac048;bgb +; WARNING!! NOTE!! --> this procedure has a limit on the input value of 64k ;ac048;bgb +; entries. If the disk fails on an entry in a subdir ;ac048;bgb +; which has an invalid entry past this value, then the ;ac048;bgb +; calling procedure will probably wrap on this word value, ;ac048;bgb +; causing getent to calc the wrong sector, and then ;ac048;bgb +; corrupting the disk. Not likely, but poss. ;ac048;bgb +; ;ac048;bgb +; called by - nodot/mesd1 - no . entry found (always subdir) ;ac048;bgb +; - noddot/mesd2 - no .. entry found (always subdir) ;ac048;bgb +; - askconv/printtrmes - convert dir to file (can be in root) ;ac048;bgb +; - makfillp - find root entry in which to place lost clus ;ac048;bgb +; ;ac048;bgb +; inputs - AX - desired entry num (in curr dir, reffed off BP) ;ac048;bgb +; 0=. 1=.. 2=first entry ;ac048;bgb +; DX - number of lost clusters +; BP - ptr to extended fcb for this dir ;ac048;bgb +; BP+6 - 1st cluster number of this dir ;ac048;bgb +; ;ac048;bgb +; output - AX - contains number of the disk to use for int26 ;ac048;bgb +; DI - points to entry in subdir in ram ;ac048;bgb +; DX - low sector number of the dir ;ac048;bgb +; BX - ram offset of the sector ;ac048;bgb +; Read_Write_Relative.Start_Sector_Hi - hi sector number of the dir ;ac048;bgb +; ;ac048;bgb +; Regs abused - all of 'em !! (ok, well, maybe not bp...) ;ac048;bgb +; ;ac048;bgb +;logic: 1. make sure there will not be a problem with the cluster number. This ;ac048;bgb +; should not be a problem, since if the cluster number is invalid, it ;ac048;bgb +; should have been flagged by previous routines. ;ac048;bgb +; ;ac048;bgb +; 2. calc clus-num & offset ;ac048;bgb +; Entries * bytes/entry / BPS --> number of sectors from the beg of ;ac048;bgb +; the dir. There are 16 entries per sector (starting at zero). The ;ac048;bgb +; bytes/entry and bytes/sector are condensed, giving a div by 16, ;ac048;bgb +; instead of "* 32 / 512". Now we have the first cluster (0-fff7), ;ac048;bgb +; the sector-offset (0-fff), and the entry-offset (0-f). ;ac048;bgb +; ;ac048;bgb +; forumla: entry (0-ffff) / 16 = sector-offset (0-fff) ax ;ac048;bgb +; = entry-offset (0-f) dx ;ac048;bgb +; ;ac048;bgb +; 3. if we are in the root directory, then we have the correct sector ;ac048;bgb +; number, so just add it to the starting sector number of the ;ac048;bgb +; directory. ;ac048;bgb +; ;ac048;bgb +; 4. otherwise, we are in a subdirectory. Here, we need to get the ;ac048;bgb +; cluster-offset, since the sector-offset can be more than 1 cluster ;ac048;bgb +; in length. So, divide the sectors by (secs/clus) to get cluster- ;ac048;bgb +; offset. This value is now a power of 2, from 2 up to 16. ;ac048;bgb +; ;ac048;bgb +; / sectors/cluster (2-16) = cluster offset AL ;ac048;bgb +; = sector offset AH ;ac048;bgb +; ;ac048;bgb +; 5. If AL > 0, then we have to walk the fat chain to find the cluster ;ac048;bgb +; where this sector is. Fortunately, we have the starting cluster ;ac048;bgb +; number (BX), UNPACK will find the next cluster number, and we have ;ac048;bgb +; the number of clusters to jump (AL). So, move the appropriate ;ac048;bgb +; into the regs, and loop until completed. Now BX has the correct ;ac048;bgb +; cluster number. ;ac048;bgb +; ;ac048;bgb +; 6. Now we need to translate the cluster and sector numbers into an ;ac048;bgb +; absolute, double word, sector number. FIGREC will do this. ;ac048;bgb +; ;ac048;bgb +; 7. Now, from either root dir, or from subdir, we have the absolute ;ac048;bgb +; sector, so set up the regs, and call READ_DISK to read it into ram. ;ac048;bgb +; Now DX contains the sector number (low), and BX points to the ;ac048;bgb +; sector in ram. ;ac048;bgb +; ;ac048;bgb +; 8. Finally, get the entry-offset that we had stored on the stack, and ;ac048;bgb +; translate it into a byte-offset by multpying it times the number of ;ac048;bgb +; bytes per entry (32). Now DI points to the entry in ram. ;ac048;bgb +;***************************************************************************** ;ac048;bgb +GETENT: ;ac048;bgb + mov bx,[bp+6] ;Get 1st cluster of subdir ;ac048;bgb +;double check for invalid cluster ;ac048;bgb + cmp bx,[eofval] ;Last entry in cluster? ;ac048;bgb +; $IF NB ;ac048;bgb + JB $$IF37 + mov bx,offset dg:baddpbdir ;This should never happen ;ac048;bgb + jmp fatal ;Danger, warning Phil Robins;ac048;bgbon +; $ENDIF ;ac048;bgb +$$IF37: + ;ac048;bgb +CLUSISOK: ;ac048;bgb +;calc cluster number and offset ;ac048;bgb + mov cx,16 ;32 bytes/entry / 512 bytes/sec ;ac048;bgb + xor dx,dx ;zero out hi word for divide ;ac048;bgb + div cx ;NOW- bx=first clus, ax=sec-offset, dx=entry-offset ;ac048;bgb + ;NOTE: ax can be > 1 cluster ;ac048;bgb +;are we at the root? ;ac048;bgb + or bx,bx ;cluster zero? ;ac048;bgb +; $IF Z ;yes, then we are in root dir ;ac048;bgb + JNZ $$IF39 + ;;;;;;;;jz wantroot ;Cluster 0 means root dir ;ac048;bgb +WANTROOT: push dx ;restored as di- ptr to invalid entry ;ac048;bgb + mov dx,ax ;get sector offset ;ac048;bgb + add dx,[dirsec] ;add in first sector of dir ;ac048;bgb + mov Read_Write_Relative.Start_Sector_High,0 ;save hi value ;ac048;bgb + ;;;;;;;;;;;JMP DOROOTDIR ;now ready for int25 ;ac048;bgb + ;ac048;bgb +; $ELSE ;not in root dir ;ac048;bgb + JMP SHORT $$EN39 +$$IF39: +NOTROOT: div csize ;divide by sectors/cluster (2-16) ;ac048;bgb + ;AL=# cluster-offset (QUO), AH= sector-offset (REM);ac048;bgb + mov cl,al ;get cluster offset from al ;ac048;bgb + xor ch,ch ;zero out hi byte to make word value ;ac048;bgb + or cx,cx ;do we have more than one cluster worth to go yet? ;ac048;bgb +; $IF NZ ;yes - we have to walk the chain to find it ;ac048;bgb + JZ $$IF41 + ;;;;;;;;JCXZ GOTCLUS ;jump if cx reg = zero ;ac048;bgb + mov si,bx ;move the cluster num for input ;ac048;bgb +SKIPLP: call unpack ;find the next cluster number ;ac048;bgb + xchg si,di ;move it into input position ;ac048;bgb + loop skiplp ;do for number of cluster-offset ;ac048;bgb + mov bx,si ;now we have the cluster number ;ac048;bgb +; $ENDIF ;ac048;bgb +$$IF41: + ;ac048;bgb +;calculate the sector from the cluster & sec-offset ;ac048;bgb +GOTCLUS: push dx ;restored as di -> entry offset ;ac048;bgb + call figrec ;Convert to sector # - ax=low, dx=hi ;ac048;bgb +; $ENDIF ;are we in root dir? ;ac048;bgb +$$EN39: + ;ac048;bgb +DOROOTDIR: ;ac048;bgb + mov bx,[secbuf] ;get offset of ram area ;ac048;bgb + mov al,[alldrv] ;get drive number ;ac048;bgb + dec al ;adjust for int25 ;ac048;bgb +RDRETRY: mov cx,1 ;read 1 sector ;ac048;bgb + call Read_Disk ;do it ;ac048;bgb + jnc rdok2 ;was it good? ;ac048;bgb +;Need to handle 'Fail' option of critical error here ;ac048;bgb + JZ RDRETRY ;ac048;bgb + ;ac048;bgb +RDOK2: pop ax ;get byte-offset into sector ;ac048;bgb + mov cl,5 ;value of 32= bytes per entry ;ac048;bgb + shl ax,cl ;mul entry offset to get byte offset ;ac048;bgb + add ax,bx ;add in offset of dir in ram ;ac048;bgb + mov di,ax ;ac048;bgb + mov al,[alldrv] ;get drive number ;ac048;bgb + dec al ;adjust for int26 ;ac048;bgb + RET ;di now points to offending entry ;ac048;bgb +;***************************************************************************** ;ac048;bgb + + + + +CHECKNOFMES: + MOV AL,1 + XCHG AL,[FIXMFLG] + OR AL,AL + JNZ RET14 ;Don't print it more than once + CMP [DOFIX],0 + JNZ RET14 ;Don't print it if F switch specified + mov dx,offset dg:FIXMES_arg + CALL PRINTf_crlf + call DoCRLF ; ;AN000; +ret14: RET + +CHECKERR: + CALL CHECKNOFMES + CMP [SECONDPASS],False ; ;AC000; + RET + +get_currdirERR: + CALL CHECKERR + jz ok_pri_dir + mov byte ptr [arg_buf],0 + ret +ok_pri_dir: + CALL get_currdir + ret + +get_thiselERR: + CALL CHECKERR + jz ok_pri_el + mov byte ptr [arg_buf],0 +ok_pri_el: + CALL get_thisel + RET + +get_THISEL: + MOV SI,BX + ADD SI,DIRNAM +;***************************************************************************** +; called by: checkfiles +; inputs: AX - number of fragments +; SI +;***************************************************************************** +get_THISEL2: + MOV DI,OFFSET DG:NAMBUF + PUSH DI + CALL FCB_TO_ASCZ + POP SI +get_currdir: + PUSH SI +; get drive letter prefix (c:\) + mov di,offset dg:arg_buf + MOV al,[ALLDRV] + ADD al,'@' + stosb + MOV al,[DRVCHAR] + stosb + mov al,[DIRCHAR] + stosb + MOV SI,DI +; get the name of the current directory, and put it into es:di + MOV DL,[ALLDRV] + DOS_Call Current_Dir ; ;AC000; +GET_END: +;find the end of the string - it will be hex zero + LODSB + OR AL,AL + JNZ GET_END +; + DEC SI ; Point at NUL + MOV DI,SI + POP SI ;point to begin of string + CMP BYTE PTR [SI],0 + JZ LPDONE ;If tail string NUL, no '/' +; move '\' for between path and filename + MOV al,[DIRCHAR] + CMP BYTE PTR [DI - 1],AL + JZ ERRLOOP ; Don't double '/' if root + stosb +ERRLOOP: +; move filename from ds:si to es:di until find hex zero + LODSB + OR AL,AL + JZ LPDONE + stosb + JMP ERRLOOP +LPDONE: +; finish off string with hex zero for asciiz + mov al,0 + stosb + RET + +CHECK_SPLICE: +; Carry set if current directory is NOT spliced (joined) onto. +; Carry clear if current directory is spliced (joined) onto. + + MOV SI,OFFSET DG:NUL + CALL get_currdir ; Build ASCIZ text of current dir + ; at arg_buf + mov si,offset dg:arg_buf + mov di,offset dg:TMP_SPC + DOS_Call xNameTrans ; ;AC000; + JC NT_SPLC ; Say NOT spliced if error + CMP WORD PTR [TMP_SPC+1],"\" SHL 8 OR ":" + JNZ NT_SPLC + CMP BYTE PTR [TMP_SPC+3],0 + JNZ NT_SPLC + MOV AL,BYTE PTR [arg_buf] ; Source drive letter + CMP AL,BYTE PTR [TMP_SPC] ; Different from dest if spliced + JZ NT_SPLC ; Drive letter didn't change + CLC + RET + +NT_SPLC: + STC + RET + + +;***************************************************************************** +;Routine name: MarkFAT +;***************************************************************************** +; +;Description: Trace the fat chain for a single file, marking entries in FATMap, +; and handling errors - +; (crosslink, truncation, allocation error, invalid cluster entry) +; +; called by : moredir +; newdir +; +;Called Procedures: Unpack +; Bad_Cluster +; MarkMap +; Check_Chain_Sizes +; ThisEl +; Eprint +; +;Change History: Created 5/10/87 MT +; +;Input: BX = pointer to search FCB +; AL is head mark with app type =81h +; SI = points to dir entry +; DI = cluster entry of file or XA in directory +; File_Size_Low/High = bytes length directory or XA structure says +; the data area is +; SecondPass = TRUE/FALSE +; XA_Pass = TRUE/FALSE +; EOFVal = 0FF8h/0FFF8h +; +;Output: +; ZEROTRUNC is non zero if the file was trimmed to zero length +; ISCROSS is non zero if the file is cross linked +; BX,SI preserved +; Cluster_Count = number of clusters in chain +; carry flag is set if the clusters are ok +; fatmap entries - 81h = head of file, +; 01h = used cluster +; +;Psuedocode +;---------- +; +; ZeroTrunc,IsCross = FALSE, SRFCBPT = BX, Cluster_Count = 0 +; Get file cluster entry (CALL Unpack) +; IF cluster < 2 or > maximum cluster (MClus) +; Go handle invalid cluster (CALL Bad_Cluster) +; ELSE +; SEARCH +; Go mark cluster in FATMap (CALL MarkMAP) +; Turn off head bit on FATMap marker +; EXITIF Crosslink +; IsCross = TRUE +; IF SecondPass = FALSE +; Setup filename for message (CALL ThisEl) +; Display crosslink message (Call Eprint) +; ENDIF +; ORELSE (no crosslink) +; Get next cluster (CALL Unpack) +; IF Cluster >= EOFVAL [(0/F)FF8h] +; Verify file sizes (CALL Check_Chain_Sizes) +; clc (Force loop to end) +; ELSE +; IF cluster < 2 or > maximum cluster (MClus) +; Go handle invalid cluster (CALL Bad_Cluster) +; clc (Force loop to end) +; ELSE +; stc (Force loop to keep goining +; ENDIF +; ENDIF +; ENDLOOP clc +; ENDSRCH +; ENDIF +; ret +;***************************************************************************** +Procedure MarkFAT ; ;AN000; + push si ;AN000; + push bx ;AN000; + mov Head_Mark,al ;Save flag to put in map ;AN000; + mov ZeroTrunc,False ;Init values ; ; + mov IsCross,False ; ; ; + mov Cluster_Count,0 ;Init count of clusters ; ; + mov SrFCBPt,bx ;Pointer to search FCB ; ; + mov First_Cluster,di ; ;AN000; + mov Previous_Cluster,di ;Init pointer + cmp di,2 ;Cluster < 2? ;AC000; +; $IF B,OR ; or ;AC000; + JB $$LL44 + cmp di,MClus ;Cluster > total clusters? ;AC000; +; $IF A ; ;AC000; + JNA $$IF44 +$$LL44: + cmp word ptr [si].dirclus,0 ;if both cluster and size = 0, ;an025;bgb +; $IF NE,OR ;then its not an error, ;an025;bgb + JNE $$LL45 + cmp word ptr [si].diresiz,0 ;and dont print msg ;an025;bgb +; $IF NE ;an025;bgb + JE $$IF45 +$$LL45: + call Bad_Cluster ;Yes, go indicate bad stuff ;AN000; +; $ENDIF +$$IF45: +; $ELSE ;Cluster in valid range ;AN000; + JMP SHORT $$EN44 +$$IF44: +; $SEARCH ;Chase the cluster chain ;AN000; +$$DO48: + mov al,Head_Mark ;Get flag for map 01 ;AC000; + call MarkMap ;Mark the cluster (SI) ;AC000; + push ax ;Save head mark ;AN000; + lahf ;Save CY status + and Head_Mark,Head_Mask ;Turn off head bit of map flag ;AC000; + sahf ;Get CY flags back + pop ax ;Get haed mark back ;AN000; +; $EXITIF C ;Quit if crosslink ;AC000; + JNC $$IF48 + mov IsCross,True ;Set crosslink flag ;AC000; + cmp SecondPass,True ;Handle crosslink 2nd pass only ;AC000; +; $IF E ;This is first pass ;AC000; + JNE $$IF50 + mov Cross_Clus,di ;Put cluster in message ;AN000; + push bx ;Get dir pointer into bx ;AN000; + push si ; ;AN000; + mov bx,si ; for the call ;AN000; + call Get_ThisELErr ; ;AC000; + mov dx,offset DG:Cross_arg ;Specify error message ;AC000; + call EPrint ;Go print file and error ;AC000; + pop si ; ;AN000; + pop bx ; ;AN000; + Message Cross_Arg ; ;AC000; +; $ENDIF ; ;AN000; +$$IF50: +; $ORELSE ;No crosslink found ;AN000; + JMP SHORT $$SR48 +$$IF48: + push si ;Save dir pointer + mov si,di ;Provide current cluster + mov Previous_Cluster,di ;Save current cluster + call UnPack ;Get next cluster entry (di) ;AC000; + inc Cluster_Count ;Got a cluster ;AN000; + pop si ;Get dir pointer back + cmp di,EOFVal ;Is it the last clus in file? ;AC000; +; $IF AE ;Yes - good chain so far ;AN000; + JNAE $$IF53 + call Check_Chain_Sizes ;Go verify file sizes ;AN000; + clc ;Clear CY to force exit ;AN000; +; $ELSE ;Not end of chain + JMP SHORT $$EN53 +$$IF53: + cmp di,2 ;Cluster < 2? ;AC000; +; $IF B,OR ; or ;AC000; + JB $$LL55 + cmp di,MClus ;Cluster > total clusters? ;AC000; +; $IF A ;Yep ;AN000; + JNA $$IF55 +$$LL55: + call Bad_Cluster ;Yes, go indicate bad stuff ;AN000; + clc ;Clear CY to force loop exit ;AN000; +; $ELSE ;No, more clusters to go ;AN000; + JMP SHORT $$EN55 +$$IF55: + stc ;Set CY to keep going ;AN000; +; $ENDIF ; ;AN000; +$$EN55: +; $ENDIF ; +$$EN53: +; $ENDLOOP NC ;Exit if done with chain ;AN000; + JC $$DO48 +; $ENDSRCH ;End of chain chase loop ;AN000; +$$SR48: +; $ENDIF ; +$$EN44: + pop bx ;Restore registers ;AN000; + pop si ; ;AN000; + ret ; ;AN000; +MarkFAT endp ; ;AN000; + +;***************************************************************************** +;Routine name: Bad_Cluster +;***************************************************************************** +; +;description: IF first cluster =0, truncate file or XA to zero length. +; If bad cluster elsewhere, put in EOFVal. +; +;Called Procedures: Get_ThisElErr +; Eprint +; FixENT2 +; +;Change History: Created 5/10/87 MT +; +;Input: First_Cluster +; Chain_End +; XA_PASS = TRUE/FALSE +; DI = Cluster entry +; SI = dir block pointer +; First_Cluster = first cluster or extended XA +; Previous_Cluster = last good cluster number +; +;Output: ZeroTrunc = TRUE/FALSE +; +;Psuedocode +;---------- +; +; Setup filename for any messages (Call Get_ThisELErr) +; IF cluster = First_Cluster +; IF XA_PASS = FALSE +; Zero out file length in DIR +; Setup message (CALL Get_ThisElErr) +; Display message (Call Eprint) +; ELSE (XA pass) +; Zero out XA pointer +; Setup message (CALL Get_ThisElErr) +; Display message (Call Eprint) +; ENDIF +; Write out corrected directory (CALL FixENT2) +; ELSE (cluster other than first in chain) +; IF XA_Pass = TRUE +; Display Bad XA cluster message +; ELSE (!XA_Pass) +; Display bad file chain message +; ENDIF +; Move EOF into bad cluster (CALL PACK - Chain_End) +; ENDIF +; ret +;***************************************************************************** +Procedure Bad_Cluster ; ;AN000; + savereg ;Preserve registers ;AN000; + mov bx,si ; for the call ;AN000; + call Get_ThisElErr ;Setup message ;AC000; + restorereg + cmp di,First_Cluster ;does 1st clus point to itself? ;Need to change the directory ;AC000; +; $IF E,OR ;yes ; pointer if the dir cluster or ;AC000; + JE $$LL62 + push di ;if not, try this next test ; XA is bad, or the last good ;AN000; + mov di,Previous_Cluster ;get prev cluster ; entry was the dir cluster or ;AN000; + cmp di,First_Cluster ;does prev clus = 1st clus? ; XA cluster. ;AN000; + pop di ;means the 1st cluster is bad +; $IF E ;yes ; ;AN000; + JNE $$IF62 +$$LL62: + cmp word ptr [si].dirclus,0 ;is cluster num already 0? ;an025;bgb +; $IF NE ;no, its bad ;an025;bgb + JE $$IF63 + mov dx,offset DG:NulNZ ;1st cluster number is invalid;an025;bgb + call EPrint ;Go print file and error ;an025;bgb + mov word ptr [si].dirclus,0 ;set cluster number to 0 ;an025;bgb + mov zerotrunc,true ;modified the file size ;an026;bgb +; $ENDIF ;already set to 0, dont print err msg ;an025;bgb +$$IF63: + mov word ptr [si].DIRESIZ,0 ;set file size to 0 ;Kill the file size ;AC000; + mov word ptr [si].DIRESIZ+2,0 ;Kill the file size ;AC000;0; + mov bx,si ;Get pointer to directory ;AN000; + call FixEnt2 ;Write out updated directory ;AC000; +; $ELSE ;Not first cluster in chain ;AN000; + JMP SHORT $$EN62 +$$IF62: + mov dx,offset dg:Badchain ;Tell user file and error ;AN000; + call EPrint ;AN000; + mov dx,Chain_End ;Terminate chain at bad spot ;AC000; + mov si,Previous_Cluster ;Change the last good cluster ;AC000; + call Pack ;Go fix it ;AC000; +; $ENDIF ; ;AN000; +$$EN62: + restorereg + ret ; +Bad_Cluster endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_Chain_Sizes +;***************************************************************************** +; +;description: See if length of chain as listed in dir or XA matches up +; with the number of clusters allocated. Don't check if crosslink +; error, or chasing directory chain. +; +;Called Procedures: FixEnt +; Bad_Chain_Size +; +; +;Change History: Created 5/10/87 MT +; +;Input: CSIZE = sectors per cluster +; SSIZE = bytes per sector +; Cluster_Count = number of clusters in chain +; File_Size_Low/High = bytes dir or XA says is in chain +; SI = Pointer to Dir entry +; +;Output: Cluster_Count = Size of chain in clusters +; SI = Pointer to dir entry +; BX = SRFCBPT +; +;Psuedocode +;---------- +; +; IF !Directory attribute,AND +; IF !Crosslinked (ISCROSS = FALSE),AND +; IF !Second pass (SecondPass = FALSE) +; Compute bytes/cluster +; Compute bytes/chain +; IF size > File_Size_High/Low +; Fix the size (CALL Bad_Chain_Size) +; ELSE +; Subtract file size from chain length +; IF Difference in Chain_Length and Size >= bytes/cluster +; Fix the size (CALL Bad_Chain_Size) +; ENDIF +; ENDIF +; ENDIF +; ENDIF +; CX = Cluster_Count (kept for compatibility with old code) +; BX = SRFCPT (kept for compatibility with old code) +; ret +;***************************************************************************** +Procedure Check_Chain_Sizes ;AN000; + push si ; ;AN000; + push ax ; ;AN000; + test [si].DirAtt,Dir_Attribute ;Is this a directory? ;AC000; +; $IF Z,AND ;No ;AC000; + JNZ $$IF67 + cmp IsCross,False ; and,is it crosslinked? ;AC000; +; $IF E,AND ;No ;AC000; + JNE $$IF67 + cmp SecondPass,False ;and, is this the first pass? ;AC000; +; $IF E ;Yes, ;AC000; + JNE $$IF67 + xor ax,ax ;AX =0 ;AC000; + mov ax,SSize ;Get (bytes/sector) * ;AC000; + mov cl,CSize ; (Sectors/cluster) ;AC000; + mul cx ;AX=Bytes/cluster (< 64k) ;AC000; + mov BClus,ax ;Save Bytes/cluster ;AN000; + mov cx,Cluster_Count ;Number of clusters in chain ;AC000; + mul cx ;DX:AX = bytes/chain ;AC000; + mov Chain_Size_Low,ax ;Save allocation size in bytes ;AN000; + mov Chain_Size_High,dx ; ;AN000; + cmp dx,File_Size_High ;See if file size if greater ;AN000; +; $IF E,AND ; than chain length - if ;AN000; + JNE $$IF68 + cmp ax,File_Size_Low ; so, than there is an ;AC000; +; $IF B ; allocation error. ;AC000; + JNB $$IF68 + call Bad_Chain_Size ;Fix it! ;AC013;bgb +; $ELSE ;Chain larger than file ;AC000; + JMP SHORT $$EN68 +$$IF68: + cmp dx,File_Size_High ;See if high part lower ;AN000; +; $IF B ;Chain < filsize if so ;AN000; + JNB $$IF70 + call Bad_Chain_Size ;Fix it! ;AC013;bgb +; $ELSE ;Chain > filesize ;AN000; + JMP SHORT $$EN70 +$$IF70: + mov cx,File_Size_Low ;See if within 1 cluster ;AN000; + mov bx,File_Size_High ; ;AN000; + sub ax,cx ;Subtract file size from ;AC000; + sbb dx,bx ; the chain size ;AN000; + cmp dx,0 ;See if within 1 cluster ;AN000; +; $IF NE,OR ;Not if high size set,or ;AN000; + JNE $$LL72 + cmp ax,BClus ;Within (bytes/cluster -1)? ;AC000; +; $IF AE ;Nope, allocation error ;AC000; + JNAE $$IF72 +$$LL72: + call Bad_Chain_Size ;Go fix the chain ;AN013;bgb +; $ENDIF ; ;AN000; +$$IF72: +; $ENDIF ; ;AN000; +$$EN70: +; $ENDIF ; ;AN000; +$$EN68: +; $ENDIF ; ;AN000; +$$IF67: + mov bx,SrFCBPt ; Needed for compat ;AC000; + pop ax ;Restore used regs ;AN000; + pop si ;SI = Dir pointer ;AN000; + ret ; ; ; +check_chain_sizes endp ; ;AN000; + + + +Procedure print_filename ;AN000; + PUSH BX + MOV BX,SI + CALL get_THISEL + mov dx,offset dg:noisy_arg + call printf_crlf + MOV SI,BX + POP BX + return +print_filename endp ; ;AN000; + +;these procedures were for the extended attribute support, which was removed ;an006;bgb + +;***************************************************************************** +;Routine name: Bad_Chain_Size +;***************************************************************************** +; +;Description: adjust +; filesize to allocation length. +; +;Called Procedures: Truncate_XA +; FixEnt2 +; Get_ThisElErr +; Eprint +; +;Change History: Created 5/11/87 MT +; +;Input: XA_Pass = TRUE/FALSE +; Chain_Size_High/Low +; SI = Dir pointer +; Chain_Size_Low/High = length in bytes of allocation chain +; +;Output: None +; +;Psuedocode +;---------- +; +; IF XA_Pass +; Delete XA chain (CALL Truncate_XA) +; ELSE +; Set directory entry to length = Total allocation size +; Go write out (CALL FixEnt2) +; Setup message (CALL Get_Thiselerr) +; Display it (Call Eprint) +; ENDIF +; ret +;***************************************************************************** +Procedure Bad_Chain_Size ; ;AN000; + push es + push ax ;Save register ;AN000; + + push ds ;make es point to dg + pop es +;;;;;; cmp XA_Pass,True ;Are we handling XA's? ;AN013;bgb +;;;;;;;;$IF E ;Yes ;AN013;bgb +;;;;;;;;;;;call Truncate_XA ;Go truncate the chain ;AN013;bgb +;;;;;;;;$ELSE ;Normal file chain ;AN013;bgb + mov ax,Chain_Size_Low ;Get length of allocation ;AN000; + mov dx,Chain_Size_High ; chain for filesize ;AN000; + mov word ptr [si].DirESiz,ax ;Put it in the directory ;AC000; + mov word ptr [si+2].DirESiz,dx ; " " " " ;AC000; + push bx ; ;AN000; + push si ; ;AN000; + mov bx,si ;Get pointer to directory ;AN000; + call FixENT2 ;Write dir to disk ;AC000; + call Get_ThisElErr ;Setup message ;AC000; + mov dx,offset DG:BadClus ;Specify error message ;AC000; + call EPrint ;Go print file and error ;AC000; + pop si ; ;AN000; + pop bx ; ;AN000; +;;;;;;;;$ENDIF ; ;AN013;bgb + pop ax ;Restore registers ;AN000; + pop es + ret ; + +Bad_Chain_Size endp ; ;AN000; + +;***************************************************************************** +;Routine name: Truncate_XA +;***************************************************************************** +; +;Description: If /F entered, than truncate XA chain and remove pointer. +; If XA allocation error, than deallocate all of XA chain. +; +;Called Procedures: Get_ThisElErr +; Eprint +; MarkMap +; Unpack +; Pack +; +;Change History: Created 5/11/87 MT +; +;Input: First_Cluster +; Chain_End +; SI = directory entry pointer +; +; +;Output: FATMap entries for XA chain zero'd out +; +;Psuedocode +;---------- +; +; Set XA pointer in dir to 0 +; Write it out (CALL FixEnt2) +; Setup message (Call get_ThisElErr +; Display message (Call Eprint) +; Get first cluster number (First_Cluster) +; DO +; Get first cluster entry (Call Unpack) +; Go mark cluster in FATMap with "Open" (CALL MarkMAP) +; Set cluster entry with 0000 (Call Pack) +; ENDDO cluster value >= EOFVal +; ret +;***************************************************************************** + +;rocedure Truncate_XA ; ;AN000; +; +; push si ;Save dir pointer ;AN000; +; push bx ; ;AN000; +; push si ; ;AN000; +; mov bx,si ;Get directory pointer ;AN000; +; call Get_ThisEl ;Setup message ;AN000; +; mov dx,offset DG:Alloc_XA_Msg ;Specify error message ;AC000; +; call EPrint ;Go print file and error ;AC000; +; pop si ; ;AN000; +; mov word ptr [si].DIR_XA,No_Ext_Attrib ;Erase XA pointer ;AN000; +; call FixENT2 ;Write dir entry out ;AN000; +; pop bx ; ;AN000; +; mov si,First_Cluster ;Get first cluster ;AN000; +; $DO ;Chase and erase XA chain ;AN000; +; call Unpack ;Get next cluster ;AN000; +; push di ;Save it- DI next, SI current ;AN000; +; mov al,No_Entry ;Free entry in map ;AN000; +; call MarkMap ; " " " " ;AN000; +; mov dx,No_Entry ;Free up cluster in Fat ;AN000; +; call Pack ; " " " " ;AN000; +; pop si ;Get back next cluster ;AN000; +; cmp si,[EOFVal] ;Reached end of chain? ;AN000; +; $ENDDO AE ;Keep looping if not ;AN000; +; pop si ;Restore Dir pointer ;AN000; +; ret ; ;AN000; +; +;runcate_XA endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_Extended_Attributes +;***************************************************************************** +; +;Description: Get the first cluster of XA chain, if it is zero, than erase +; extended attribute pointer (/F only). Otherwise, map the +; cluster in the FATMAP. If crosslink found on first cluster, +; no more processing is done. If value other than EOF mark +; found in first cluster +; +;Called Procedures: Load_XA +; Fix_Bad_XA +; Check_XA_Structure +; MarkFAT +; +;Change History: Created 5/10/87 MT +; +;Input: SI = pointer to directory entry +; +;Output: FATMap marked with XA_Cluster for each XA cluster found +; XA_PASS = NO +; +;Psuedocode +;---------- +; +; IF (XA exists for file) +; XA_PASS = YES +; DI = XA entry cluster in dir +; Load in first sector of XA (CALL Load_XA) +; IF !error +; File_Size_Low/High = length of XA's in bytes +; AL = chain head mark (XA_Chain) +; Trace chain and map it (CALL MarkFAT) +; ELSE +; call Bad_Cluster +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +;rocedure Check_Extended_Attributes ; ;AN000; +; +; push ax ;Save register ;AN000; +; push cx ; ;AN000; +; push dx ; ;AN000; +; push di ; ;AN000; +; mov ax,[si].DIR_XA ;Get first cluster of XA's ;AN000; +; cmp ax,No_Ext_Attrib ;Are there extended attrib's ;AN000; +; $IF NE ;Quit if no ;AN000; +; mov di,ax ;Pointer to current cluster ;AN000; +; mov First_Cluster,di ;Remember first cluster ;AN000; +; mov XA_Pass,Yes ;Indicate processing XA's ;AN000; +; call Load_XA ;Go load sector ;AN000; +; $IF NC ;CY means load error ;AN000; +; mov ax,XA_Buffer.XAL_TSIZE ;Get bytes in XA chain ;AN000; +; mov File_Size_High,0 ;Save it ;AN000; +; mov File_Size_Low,ax ; ;AN000; +; mov al,XA_Chain ;Set up mark for map ;AN000; +; call MarkFAT ;Go map out chain ;AN000; +; $ELSE ;Error on read of XA ;AN000; +; call Bad_Cluster ;Delete extended attribs ;AN000; +;; $ENDIF ; ;AN000; +; $ENDIF +; pop di ;Restore registers +; pop dx ; ;AN000; +; pop cx ; ;AN000; +; pop ax ; ;AN000; +; ret ; ;AN000; +; +;heck_Extended_Attributes endp ; ;AN000; + + +;***************************************************************************** +;Routine name: Load_XA +;***************************************************************************** +; +;description: Read in the first XA cluster +; +;Called Procedures: Read_Disk +; +; +;Change History: Created 5/13/87 MT +; +;Input: AX has start cluster of XA chain +; SI = dir pointer +;Output: CY if read failed +; +;Psuedocode +;---------- +; +; Get start of data area +; Get start cluster +; Compute XA location from starting cluster +; Read it in (CALL Read_Disk) +; IF error +; stc +; ENDIF (NC if didn't take IF) +; ret +;***************************************************************************** + +;rocedure Load_XA ; ;AN000; +; +; push si ;Save used registers ;AN000; +; push cx ; ;AN000; +; push dx ; ;AN000; +; push bx ; ;AN000; +; sub ax,2 ;Make cluster 0 based ;AN000; +; mov cl,CSize ;Get sectors/cluster ;AN000; +; mul cl ;Offset sec in data area ;AN000; +; add ax,Data_Start_Low ;Get actual sector in partition ;AN000; +; adc dx,Data_Start_High ; " " " " ;AN000; +; mov Read_Write_Relative.Start_Sector_High,dx ;Setup high sector addr;AN000; +; mov bx,offset dg:XA_Buffer ;Read into buffer ;AN000; +; mov cx,1 ;Get just first sector ;AN000; +; mov dx,ax ;Get logical sector low ;AN000; +; mov al,AllDrv ;Get drive number 1=A,2=B ;AN000; +; dec al ;Make 0 based drive 0=A ;AN000; +; call Read_Disk ;Read in sector ;AN000; +; $IF C ;Problem? ;AN000; +; stc ; ;AN000; +; $ENDIF ; ;AN000; +; pop bx ;Restore registers ;AN000; +; pop dx ; ;AN000; +; pop cx ; ;AN000; +; pop si ; ;AN000; +; ret ; ;AN000; +; +;oad_XA endp ; ;AN000; + +;**************************************************************************** +;WARNING!!! this must be the last label in the code section +; any changes to chkdsk.arf must take into account this area. +; it is used for reading things from disk into memory, such as dir +Public CHKPRMT_End +Chkprmt_End label byte +;**************************************************************************** + pathlabl chkproc +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKPROC2.ASM b/v4.0/src/CMD/CHKDSK/CHKPROC2.ASM new file mode 100644 index 0000000..8a3bde8 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKPROC2.ASM @@ -0,0 +1,479 @@ +TITLE CHKPROC2 - PART2 Procedures called from chkdsk +page ,132 ; + + .xlist + include chkseg.inc ;an005;bgb + INCLUDE CHKCHNG.INC + INCLUDE DOSSYM.INC + INCLUDE CHKEQU.INC + INCLUDE CHKMACRO.INC + include pathmac.inc + +CONST SEGMENT PUBLIC PARA 'DATA' + EXTRN FIXMES_ARG:word ;an049;bgb + EXTRN FATAL_ARG:word + EXTRN BADW_ARG:word,FATAL_END:word + EXTRN badrw_num:word,BADRW_STR:WORD,HAVFIX:byte + EXTRN DIRTYFAT:byte,CROSSCNT:dword,DOFIX:byte,SECONDPASS:byte + EXTRN BADSIZ:word,ORPHSIZ:word,ORPHFCB:byte + EXTRN HECODE:byte,USERDIR:byte,FRAGMENT:byte + EXTRN ORPHEXT:byte,ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte + EXTRN EOFVAL:word,BADVAL:word + extrn fTrunc:BYTE +CONST ENDS + +DATA SEGMENT PUBLIC PARA 'DATA' + extrn fatcnt:byte, orph_arg:word ;an005;bgb;an049;bgb + EXTRN THISDPB:dword,NUL_ARG:byte + EXTRN NAMBUF:byte,SRFCBPT:word,FATMAP:word + EXTRN MCLUS:word,CSIZE:byte,SSIZE:word + EXTRN DSIZE:word,ARG_BUF:byte,ERRCNT:byte + EXTRN USERDEV:byte,HARDCH:dword,CONTCH:dword + EXTRN ExitStatus:Byte,Read_Write_Relative:Byte + extrn bytes_per_sector:word ;an005;bgb + extrn fattbl_seg:word, fatsiz:word, paras_per_fat:word ;an005;bgb + extrn fatmsg1:word ;an024;bgb + extrn fatmsg2:word ;an024;bgb + EXTRN dbcs_vector:byte ;an055;bgb + EXTRN dbcs_vector_off:word ;an055;bgb + EXTRN dbcs_vector_seg:word ;an055;bgb +DATA ENDS + +CODE SEGMENT PUBLIC PARA 'CODE' +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + EXTRN PRINTF_CRLF:NEAR,FCB_TO_ASCZ:NEAR + EXTRN PROMPTYN:NEAR,DIRPROC:NEAR + EXTRN DOCRLF:NEAR,UNPACK:NEAR,PACK:NEAR + EXTRN CHECKNOFMES:NEAR + EXTRN multiply_32_bits:near ;an047;bgb + extrn nowrite:near, done:near, pack:near, unpack:near + extrn promptrecover:near, findchain:near +public RECOVER, DoAsk +public MAKORPHNAM, NAM0, NAMMADE +public GETFILSIZ, NCLUS, GOTEOF, CHKCROSS, RET8 +public FATAL, hav_fatal_arg, INT_23, RDONE +public Systime ;an005;bgb +public int_24 ;an005;bgb +public CHECK_DBCS_CHARACTER ;an055;bgb + .list + + + + pathlabl chkproc2 +;***************************************************************************** +; RECOVER - +; free orphans or do chain recovery. Note that if we have NOT been able to +; process the entire tree (due to inability to CHDIR), we temporarily set +; DoFix to FALSE, do the operation, and then reset it. +; +; inputs: si - total number of clusters +; es - points to fatmap +; +; outputs: orphaned clusters are converted to files +; LOGIC +; - display dont fix msg if appropriate +; - display number of lost clusters +; - ask the user if he wants the chains converted to files +;*************************************************************************** +RECOVER: + mov al,1 + xchg al,[fixmflg] + or al,al +; $IF Z ; where there any errors found? + JNZ $$IF1 + cmp [dofix],0 ; yes - is the /f flag off? +; $IF Z ; yes - display the dont fix msg + JNZ $$IF2 + mov dx,offset dg:FIXMES_arg + CALL PRINTf_crlf + call DoCRLF ; ;AN000; +; $ENDIF +$$IF2: +; $ENDIF +$$IF1: + CALL DOCRLF +CHAINREPORT: +;;;;mov si,orphsiz ;get number of bad clusters found (recover) ;an005;bgb;an049;bgb +;;;;mov [orph_num],si ; Prints "XXX lost clusters found in YYY chains.";an049;bgb + call findchain ; On entry SI is the XXX value and the YYY value is + mov dx,offset dg:orph_arg ; in orphan-count. + call printf_crlf + TEST fTrunc,-1 +; $IF NZ + JZ $$IF5 + XOR AX,AX ; We have truncated the scan. Set DoFix to FALSE, + XCHG AL,DoFix ; do the operation and then restore things. + PUSH AX + CALL PromptRecover + POP AX + MOV DoFix,AL +DoAsk: +; $ELSE + JMP SHORT $$EN5 +$$IF5: + CALL PromptRecover +; $ENDIF +$$EN5: + return + + + + + + + + +;***************************************************************************** +;***************************************************************************** +MAKORPHNAM: + PUSH SI + MOV SI,OFFSET DG:ORPHEXT - 1 +NAM0: + INC BYTE PTR [SI] + CMP BYTE PTR [SI],'9' + JLE NAMMADE + MOV BYTE PTR [SI],'0' + DEC SI + JMP NAM0 + +NAMMADE: + POP SI + RET + + + + +;***************************************************************************** +; GETFILSIZ - calculate the file size based on the number of clusters. +; +; WARNING!! NOTE!! --> +; +; called by - PROCEDURE NAME +; +; inputs: AX - +; BX - +; CX - +; DX - +; SP - +; BP - +; SI - conatins the starting cluster number +; DI - +; DS - +; ES - +; +; output: AX - low word of the file size +; BX - +; CX - +; DX - hi word of the file size +; SP - +; BP - +; SI - +; DI - +; DS - +; ES - +; +; Regs abused - none +; +;logic: 1. save bx & cx for 32 bit mul +; +; 2. zero out file size results +; +; 3. do for all clusters: +; +; 4. get the next one and inc cluster counter +; +; 5. multiply clusters times sectors per cluster to give +; number of sectors in file. This can be a 2 word value - DX:AX. +; +; 6. multiply the sectors times the number of bytes per sector. This +; yields the number of bytes in the file. +;***************************************************************************** +;SI is start cluster, returns filesize as DX:AX +Procedure getfilsiz,near + savereg + XOR AX,AX ;zero out low word + XOR DX,DX ;zero out high word + OR SI,SI ;did we get a zero cluster? +; $if NZ + JZ $$IF8 +; $DO ;do for all clusters +$$DO9: +NCLUS: CALL UNPACK ;find the next cluster + XCHG SI,DI ;put output into input for unpack + INC AX ;found another cluster + CMP SI,[EOFVAL] ;did we find last cluster? +; $leave ae ;yes, so exit loop + JAE $$EN9 + ;;;;;;;CMP SI,2 + ;;;;;;;JAE NCLUS +; $enddo + JMP SHORT $$DO9 +$$EN9: +GOTEOF: + MOV BL,[CSIZE] ;get sectors per cluster + XOR BH,BH + MUL BX ;clusters * secs/cluster = sectors + mov bx,dx ;get high num for 32bit mult + mov cx,ssize ;cx = word to mult with + call multiply_32_bits ;mul bx:ax * cx + mov dx,bx ;save high word +; $endif +$$IF8: + restorereg + return +EndProc getfilsiz + + + +;***************************************************************************** +;***************************************************************************** +Public Chkcross +CHKCROSS: +;Check for Crosslinks, do second pass if any to find pairs + MOV SI,word ptr CROSSCNT + cmp word ptr crosscnt,0 ;if there is at least one crossed +; $if nz,or + JNZ $$LL13 + cmp word ptr crosscnt+2,0 +; $if nz + JZ $$IF13 +$$LL13: + CALL DOCRLF ;display another line + MOV SecondPass,True ; ; ;AC000; + XOR AX,AX ; + PUSH AX + PUSH AX + CALL DIRPROC ;Do it again +; $endif +$$IF13: +RET8: RET + + + +;***************************************************************************** +;***************************************************************************** +FATAL: +;Unrecoverable error + mov dx,offset dg:FATAL_arg + mov [fatmsg1],bx ;an024;bgb + cmp byte ptr [nul_arg],0 + jnz hav_fatal_arg + mov [fatmsg2],offset dg:fatal_end +hav_fatal_arg: + CALL PRINTf_crlf + MOV DL,[USERDEV] ;At least leave on same drive + DOS_Call Set_Default_Drive ; ;AC000; + ;MOV AH,EXIT + mov ExitStatus,Bad_Exit ;Get return code ;AC000; + ;INT 21H + ret ;Ret Main_Init for common exit + + + + +;***************************************************************************** +;***************************************************************************** +iNT_24 PROC FAR +aSSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSHF + push ax ;Save AX register ;AN000; + test al,Disk_Error ;Is it a disk critical err? +; $IF Z ;Yes + JNZ $$IF15 + mov ax,di ;Get error (DI low) ;AN000; + cmp al,Write_Protect ;Special case errors ;AN000; +; $IF E,OR ;If write protect or ;AN000; + JE $$LL16 + cmp al,Drive_Not_Ready ; if drive not ready ;AN000; + pop ax ;Balance stack again ;AN000; +; $IF E ; ;AN000; + JNE $$IF16 +$$LL16: + CALL dword ptr HardCh ; let parent's handler decide what to do +; $ELSE ;Other error ;AN000; + JMP SHORT $$EN16 +$$IF16: + pop ax ;balance stack ;AN000; + mov al,Critical_Error_Fail ;Fail the operation ;AN000; +; $ENDIF ; ;AN000; +$$EN16: +; $ELSE ;Not disk error + JMP SHORT $$EN15 +$$IF15: + CALL dword ptr HardCh ; let parent's handler decide what to do +; $ENDIF +$$EN15: + CMP AL,2 ;Abort? ;AC000; +; $IF E ;Yes ;AC000; + JNE $$IF21 + STI ;Turn off Interrupts + CALL DONE ;Forget about directory, restore users drive + mov ExitStatus,Bad_Exit ;Get return code ;AN000; +; $ENDIF ;AN000; +$$IF21: + IRET +iNT_24 ENDP + + + + +;***************************************************************************** +;***************************************************************************** +INT_23 proc far + STI + LDS DX,[HARDCH] + mov al,24h ; ;AC000; + DOS_Call Set_Interrupt_Vector ; ;AC000; + LDS DX,cs:[CONTCH] ;ac039;bgb + mov al,23h ; ;AC000; + DOS_Call Set_Interrupt_Vector ; ;AC000; + PUSH CS + POP DS +ASSUME DS:DG + MOV [FRAGMENT],0 +RDONE: + CALL NOWRITE ;Restore users drive and directory + ;MOV AH,EXIT + ;MOV AL,0FFH + ;INT 21H + mov ExitStatus,Bad_Exit ;Get return code ;AC000; + stc + ret ;Ret for common exit ;AN000; +int_23 endp + + + + + +;***************************************************************************** +;***************************************************************************** +; +; Systime returns the current date in AX, current time in DX +; AX - HHHHHMMMMMMSSSSS hours minutes seconds/2 +; DX - YYYYYYYMMMMDDDDD years months days +; +public Systime +Systime: + DOS_Call Get_Time ; ;AC000; + SHL CL,1 ;Minutes to left part of byte + SHL CL,1 + SHL CX,1 ;Push hours and minutes to left end + SHL CX,1 + SHL CX,1 + SHR DH,1 ;Count every two seconds + OR CL,DH ;Combine seconds with hours and minutes + MOV DX,CX + PUSH DX ; Save time +; +; WARNING! MONTH and YEAR must be adjacently allocated +; + DOS_Call Get_Date ; ;AC000; + SUB CX, 1980 + MOV AX, CX + MOV CL, 4 + SHL AL, CL ; Push year to left for month + OR AL, DH ; move in month + MOV CL,4 + SHL AX,CL ;Push month to left to make room for day + SHL AX,1 + OR AL, DL + POP DX ; Restore time + XCHG AX, DX ; Switch time and day + return + + +;***************************************************************************** ;an055;bgb +;Routine name: Check_DBCS_CharACter ;an055;bgb +;***************************************************************************** ;an055;bgb +; ;an055;bgb +;Description: Check if specified byte is in rANges of DBCS vectors ;an055;bgb +; ;an055;bgb +;Called Procedures: None ;an055;bgb +; ;an055;bgb +;ChANge History: Created 6/12/87 MT ;an055;bgb +; ;an055;bgb +;Input: AL = CharACter to check for DBCS lead charACter ;an055;bgb +; DBCS_Vector = YES/NO ;an055;bgb +; ;an055;bgb +;Output: CY set if DBCS charACter ;an055;bgb +; DBCS_VECTOR = YES ;an055;bgb +; ;an055;bgb +; ;an055;bgb +;Psuedocode ;an055;bgb +;---------- ;an055;bgb +; Save registers ;an055;bgb +; IF DBCS vector not found ;an055;bgb +; Get DBCS environmental vector (INT 21h ;an055;bgb +; Point at first set of vectors ;an055;bgb +; ENDIF ;an055;bgb +; SEARCH ;an055;bgb +; LEAVE End of DBCS vectors ;an055;bgb +; EXITIF CharACter > X1,AND (X1,Y1) are environment vectors ;an055;bgb +; EXITIF CharACter < Y1 ;an055;bgb +; STC (DBCS charACter) ;an055;bgb +; ORELSE ;an055;bgb +; Inc pointer to next set of vectors ;an055;bgb +; ENDLOOP ;an055;bgb +; CLC (Not DBCS charACter) ;an055;bgb +; ENDSRCH ;an055;bgb +; Restore registers ;an055;bgb +; ret ;an055;bgb +;***************************************************************************** ;an055;bgb +DBCS_Vector_Size equ 2 ;an055;bgb +end_of_vector equ 0 ;an055;bgb +Procedure Check_DBCS_Character ; ;an055;bgb + push ds ;Save registers ;an055;bgb + push si ; " " " " ;an055;bgb + push ax ; " " " " ;an055;bgb +;;;;;;;;push ds ; " " " " ;an055;bgb +;;;;;;;;pop es ;Establish addressability ;an055;bgb + cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;an055;bgb +; $IF NE ;Nope ;an055;bgb + JE $$IF23 + push ax ;Save input charACter ;an055;bgb + mov al,0 ;Get DBCS environment vectors ;an055;bgb + DOS_Call Hongeul ; " " " " ;an055;bgb + mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector ;an055;bgb + mov es:DBCS_Vector_Off,si ;Save the vector ;an055;bgb + mov ax,ds ; ;an055;bgb + mov es:DBCS_Vector_Seg,ax ; ;an055;bgb + pop ax ;Restore input charACter ;an055;bgb +; $ENDIF ; for next time in ;an055;bgb +$$IF23: + mov si,es:DBCS_Vector_Seg ;Get saved vector pointer ;an055;bgb + mov ds,si ; ;an055;bgb + mov si,es:DBCS_Vector_Off ; ;an055;bgb +; $SEARCH ;Check all the vectors ;an055;bgb +$$DO25: + cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;an055;bgb +; $LEAVE E ;Yes, done ;an055;bgb + JE $$EN25 + cmp al,ds:[si] ;See if char is in vector ;an055;bgb +; $EXITIF AE,AND ;If >= to lower, ANd ;an055;bgb + JNAE $$IF25 + cmp al,ds:[si+1] ; =< thAN higher rANge ;an055;bgb +; $EXITIF BE ; then DBCS charACter ;an055;bgb + JNBE $$IF25 + stc ;Set CY to indicate DBCS ;an055;bgb +; $ORELSE ;Not in rANge, check next ;an055;bgb + JMP SHORT $$SR25 +$$IF25: + add si,DBCS_Vector_Size ;Get next DBCS vector ;an055;bgb +; $ENDLOOP ;We didn't find DBCS char ;an055;bgb + JMP SHORT $$DO25 +$$EN25: + clc ;Clear CY for exit ;an055;bgb +; $ENDSRCH ; ;an055;bgb +$$SR25: + pop ax ;Restore registers ;an055;bgb + pop si ; " " " " ;an055;bgb + pop ds ;Restore data segment ;an055;bgb + ret ; ;an055;bgb +Check_DBCS_CharACter endp ; ;an055;bgb + + + + pathlabl chkproc2 +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/CHKSEG.INC b/v4.0/src/CMD/CHKDSK/CHKSEG.INC new file mode 100644 index 0000000..d33099d --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/CHKSEG.INC @@ -0,0 +1,21 @@ +PSP segment public para 'DUMMY' ;an000;bgb +PSP ends ;an000;bgb + ;an000;bgb +data segment public para 'DATA' ;an000;bgb +data ends ;an000;bgb + ;an000;bgb +CONST SEGMENT PUBLIC para 'DATA' ;an000;bgb +CONST ENDS ;an000;bgb + ;an000;bgb +code segment public para 'CODE' ;an000;bgb +code ends ;an000;bgb + ;an000;bgb +cstack segment para stack 'STACK' ;an000;bgb +cstack ends ;an000;bgb + ;an000;bgb +lastseg segment public para 'LAST' ;an000;bgb;AN000;bgb +lastseg ends ;this is a pointer to the end of the pgm ;A;an000;bgbN000;bgb + ;an000;bgb;AN000;bgb +DG GROUP data,const,code,CSTACK,lastseg ;an000;bgb +assume cs:dg,ds:dg,ss:dg,es:dg ;an000;bgb + \ No newline at end of file diff --git a/v4.0/src/CMD/CHKDSK/MAKEFILE b/v4.0/src/CMD/CHKDSK/MAKEFILE new file mode 100644 index 0000000..f9859b8 --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/MAKEFILE @@ -0,0 +1,94 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: chkdsk.com + +chkdsk.ctl: chkdsk.skl \ + makefile \ + $(msg)\$(COUNTRY).msg + +chkinit.obj: chkinit.asm \ + chkequ.inc chkmacro.inc chkparse.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\ioctl.inc + +chkdsk1.obj: chkdsk1.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc chkdata.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkdsk2.obj: chkdsk2.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkproc.obj: chkproc.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkproc2.obj: chkproc2.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkdisk.obj: chkdisk.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkfat.obj: chkfat.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +chkprmt.obj: chkprmt.asm \ + chkequ.inc chkmacro.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + +#chkexec.obj: chkexec.asm \ ;an038;bgb #commented out when received from IBM (mrw) +# chkequ.inc chkmacro.inc chkchng.inc \ ;an038;bgb +# makefile chkseg.inc \ ;an038;bgb +# $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ ;an038;bgb +# $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ ;an038;bgb +# $(inc)\syscall.inc ;an038;bgb + +chkdisp.obj: chkdisp.asm \ + chkdsk.ctl \ + chkdsk.cla chkdsk.clb chkdsk.clc chkdsk.cld chkdsk.cl1 chkdsk.cl2 \ + chkequ.inc chkmacro.inc chkparse.inc chkmsg.inc chkchng.inc \ + makefile chkseg.inc \ + $(inc)\dossym.inc $(inc)\sysmsg.inc $(inc)\devsym.inc \ + $(inc)\cpmfcb.inc $(inc)\dosmac.inc $(inc)\ioctl.inc \ + $(inc)\syscall.inc + + +chkdsk.com: chkdsk1.obj chkdsk2.obj chkproc.obj chkproc2.obj chkprmt.obj \ + chkdisk.obj chkfat.obj \ + chkinit.obj chkdisp.obj \ + chkdsk.lnk makefile + link @chkdsk.lnk + convert chkdsk.exe diff --git a/v4.0/src/CMD/CHKDSK/PATHMAC.INC b/v4.0/src/CMD/CHKDSK/PATHMAC.INC new file mode 100644 index 0000000..17d8aea --- /dev/null +++ b/v4.0/src/CMD/CHKDSK/PATHMAC.INC @@ -0,0 +1,32 @@ + +;*********************************************************************** +; NAME: pathlabl +; DESC: creates a public label at the spot it is placed, using the name +; given. +; INPUT: either module name or procedure name +; OUTPUT: public label +; LOGIC: if masm is in pass1 (pass2 will gen dup labels) +; if this label has not been gen before +; then create the label +; - $$A to place at begin of map +; - start means first occurence +; - use module/proc name last +; define this label for creation of 'stop' label +; else create stop label +; - same as start except name +;*********************************************************************** +.LALL +pathlabl MACRO pnam +IF1 ;if pass 1 + IFNDEF LBL_&pnam ;switch not defined if first creation + $$A_START_&pnam: ;create label + PUBLIC $$A_START_&pnam ;make it public + LBL_&pnam = 1 ;set switch + ELSE ;start label already created + $$A_STOP_&pnam: ;create stop label + PUBLIC $$A_STOP_&pnam ;make it public + ENDIF +ENDIF +ENDM + + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COMEQU.ASM b/v4.0/src/CMD/COMMAND/COMEQU.ASM new file mode 100644 index 0000000..40273e3 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMEQU.ASM @@ -0,0 +1,241 @@ +; SCCSID = @(#)comequ.asm 1.1 85/05/14 +; SCCSID = @(#)comequ.asm 1.1 85/05/14 +;************************************* +; COMMAND EQUs which are not switch dependant + +EMGDEBUG = FALSE + +SYM EQU ">" + +LINESPERPAGE EQU 25 ;AC000; default lines per page +NORMPERLIN EQU 1 +WIDEPERLIN EQU 5 +COMBUFLEN EQU 128 ; Length of commmand buffer +BatLen EQU 32 ; buffer for batch files +YES_ECHO EQU 1 ; echo line +NO_ECHO EQU 0 ; don't echo line +No_Echo_Char EQU "@" ; don't echo line if this is first char +call_in_progress EQU 1 ; indicate we're in the CALL command +length_call EQU 4 ; length of CALL +max_nest EQU 10 ; max # levels of batch nesting allowed +fail_allowed EQU 00001000b ; critical error +retry_allowed EQU 00010000b ; critical error +Ignore_allowed EQU 00100000b ; critical error +nullcommand EQU 1 ; no command on command line +end_of_line EQU -1 ;AN000; end of line return from parser +end_of_line_out EQU 0 ;AN000; end of line for output +end_of_line_in EQU 0dh ;AN000; end of line for input +result_number EQU 1 ;AN000; number returned from parser +result_string EQU 3 ;AN000; string returned from parser +result_filespec EQU 5 ;AN000; filespec returned from parser +result_drive EQU 6 ;AN000; drive returned from parser +result_date EQU 7 ;AN000; date returned from parser +result_time EQU 8 ;AN000; time returned from parser +result_no_error EQU 0 ;AN000; no error returned from parser +no_cont_flag EQU 0 ;AN000; no control flags for message +util_msg_class EQU -1 ;AN000; message class for utility +ext_msg_class EQU 1 ;AN000; message class for extended error +parse_msg_class EQU 2 ;AN000; message class for parse error +crit_msg_class EQU 3 ;AN000; message class for critical error +ext_crlf_class EQU 081h ;AN054; message class for extended error with no CRLF +colon_char EQU ":" ;AN000; colon character +crt_ioctl_ln EQU 14 ;AN000; default length of data for display ioctl +text_mode EQU 1 ;AN000; text mode return from ioctl +get_generic EQU 07Fh ;AN000; generic ioctl - get device info +set_crit_dev EQU 0100H ;AN000; device attribute for critical error on I/0 +mult_ansi EQU 01Ah ;AC064; multiplex for ansi.sys +mult_shell_get EQU 01902h ;AC065; multiplex for Shell - get next command +mult_shell_brk EQU 01903h ;AN000; multiplex for Shell - ^C batch check +shell_action equ 0ffh ;AN000; SHELL - return for taking SHELL specific action +bat_not_open EQU -1 ;AN000; batch handle will be set to this if not open +bat_open_handle EQU 19 ;AN000; handle will be in this position in JFN table +Ptr_seg_pos equ 7 ;AN000; Offset from start of message block for subst segment +Ptr_off_pos equ 5 ;AN000; Offset from start of message block for subst offset +Parm_off_pos equ word ptr 2 ;AN000; Offset from start of subst list for subst offset +parm_block_size equ 11 ;AN000; size of message subst block +blank equ " " ;AN000; blank character +no_subst equ 0 ;AN000; no substitutions for messages +one_subst equ 1 ;AN000; one substitution for messages +no_handle_out equ -1 ;AN000; use function 1 thru 12 for message retriever +res_subst equ 2 ;AN000; offset from start of message definition to number of subst +read_open_mode equ 0000000000000000b ;AN024; extended open mode for read +read_open_flag equ 0000000100000001b ;AN000; extended open flags for read +write_open_mode equ 0000000000000001b ;AN024; extended open mode for read +write_open_flag equ 0000000100000001b ;AN000; extended open flags for read +creat_open_flag equ 0000000100010010b ;AN000; extended open flags for read +get_CPSW equ 3 ;AN000; minor function for get CPSW status +CPSW_off equ 0 ;AN000; CPSW return from function - OFF +Get_XA equ 2 ;AN030; minor function for get extended attributes +Set_XA equ 4 ;AN000; minor function for set extended attributes +file_no_cpage equ 0 ;AN000; file has no code page tag +file_inv_cpage equ -1 ;AN000; file has invalid code page tag +do_xa equ -1 ;AN000; flag to get extended attributes +inv_cp_tag equ 0 ;AC039; tag for invalid code page +no_xa_seg equ -1 ;AN000; no segment for extended attributes - COPY +capital_A equ 'A' ;AC000; +vbar equ '|' ;AC000; +labracket equ '<' ;AC000; +rabracket equ '>' ;AC000; +dollar equ '$' ;AC000; +lparen equ '(' ;AC000; +rparen equ ')' ;AC000; +nullrparen equ 29h ;AC000; +in_word equ 4e49h ;AC000; 'NI' ('IN' backwards) +do_word equ 4f44h ;AC000; 'OD' ('DO' backwards) +star equ '*' ;AC000; +plus_chr equ '+' ;AC000; +small_a equ 'a' ;AC000; +small_z equ 'z' ;AC000; +dot_chr equ '.' ;AC000; +tab_chr equ 9 ;AN032; +equal_chr equ '=' ;AN032; +semicolon equ ';' ;AN049; +dot_qmark equ 2e3fh ;AC000; '.?' +dot_colon equ 2e3ah ;AC000; '.:' +capital_n equ 0 ;AC000; result from Y/N call if N entered +capital_y equ 1 ;AC000; result from Y/N call if Y entered +AppendInstall equ 0B700H ;AN020; append install check +AppendDOS equ 0B702H ;AN020; append DOS version check +AppendGetState equ 0B706H ;AN020; append get current state +AppendSetState equ 0B707H ;AN020; append set current state +AppendTruename equ 0B711H ;AN042; Get file's real location for Batch +search_attr equ attr_read_only+attr_hidden+attr_directory ;AC042; + +;************************************* +;* PARSE ERROR MESSAGES +;************************************* + +MoreArgs_Ptr equ 1 ;AN000;"Too many parameters" message number +LessArgs_Ptr equ 2 ;AN000;"Required parameter missing" message number +BadSwt_Ptr equ 3 ;AN000;"Invalid switch" message number +BadParm_Ptr equ 10 ;AN000;"Invalid parameter" message number + +;************************************* +;* EQUATES FOR MESSAGE RETRIEVER +;************************************* + +GET_EXTENDED_MSG EQU 0 ;AN000; get extended message address +SET_EXTENDED_MSG EQU 1 ;AN000; set extended message address +GET_PARSE_MSG EQU 2 ;AN000; get parse message address +SET_PARSE_MSG EQU 3 ;AN000; set parse message address +GET_CRITICAL_MSG EQU 4 ;AN000; get critical message address +SET_CRITICAL_MSG EQU 5 ;AN000; set critical message address +MESSAGE_2F EQU 46 ;AN000; minor code for message retriever + +;********************************* +;* EQUATES FOR INT 10H +;********************************* + +VIDEO_IO_INT EQU 10H ;AN000; equate for int 10h +SET_VIDEO_MODE EQU 0 ;AN000; set video mode +SET_CURSOR_POSITION EQU 2 ;AN000; set new cursor position +SCROLL_VIDEO_PAGE EQU 6 ;AN000; scroll active page up +VIDEO_ATTRIBUTE EQU 7 ;AN000; attribute to be used on blank line +SET_COLOR_PALETTE EQU 11 ;AN000; set color for video +GET_VIDEO_STATE EQU 15 ;AN000; get current video state +VIDEO_ALPHA EQU 3 ;AN000; alpha video is 3 or below +VIDEO_BW EQU 7 ;AN000; mode for 80X25 black & white + +AltPipeChr equ "|" ; alternate pipe character + +FCB EQU 5CH + +VARSTRUC STRUC +ISDIR DB ? +SIZ DB ? +TTAIL DW ? +INFO DB ? +BUF DB DIRSTRLEN + 20 DUP (?) +VARSTRUC ENDS + +fCheckDrive equ 00000001b +fSwitchAllowed equ 00000010b + +; +; Test switches +; +fParse EQU 0001h ; display results of parseline + +; +; Batch segment structure +; +; BYTE type of segment +; BYTE echo state of parent on entry to batch file +; WORD segment of last batch file +; WORD segment for FOR command +; BYTE FOR flag state on entry to batch file +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; + +BatchType equ 0 + +BatchSegment struc +BatType DB BatchType ; signature +Batechoflag DB 0 ; G state of echo +Batlast DW 0 ; G segment of last batch file +Batforptr DW 0 ; G segment for FOR command +Batforflag DB 0 ; G state of FOR +BatSeek DD ? ; lseek position of next char +BatParm DW 10 dup (?) ; pointers to parameters +BatFile DB ? ; beginning of batch file name +BatchSegment ends + +ANULL equ 0 ; terminates an argv string +ARGMAX equ 64 ; max args on a command line +ARGBLEN equ 2*128 ; 1char each plus term NUL +tplen equ 64 ; max size of one argument +arg_cnt_error equ 1 ; number of args > MAXARG +arg_buf_ovflow equ 2 ; overflowed argbuffer + +argv_ele STRUC ; elements in the argv array + argpointer DW (?) ; pointer to the argstring + argflags DB (?) ; cparse flags for this argstring + argstartel DW (?) ; the result of cparse's [STARTEL] + arglen DW (?) ; cparse's char count + one (for null) + argsw_word DW (?) ; any switches after this? what kinds? + arg_ocomptr DW (?) ; pointer into original command string +argv_ele ENDS + +arg_unit STRUC + argv DB (ARGMAX * SIZE argv_ele) DUP (?) + argvcnt DW (?) ; number of arguments + argswinfo DW (?) ; Switch information for entire line + argbuf DW ARGBLEN DUP (?) ; storage for argv strings + argforcombuf db COMBUFLEN DUP (?) ; Original for loop command string +arg_unit ENDS + +parseflags RECORD special_delim:1, unused:4, path_sep:1, wildcard:1, sw_flag:1 + +SwitchV EQU 10h +SwitchB EQU 08h +SwitchA EQU 04h +SwitchP EQU 02h +SwitchW EQU 01h +fSwitch EQU 8000h +fBadSwitch EQU 4000h + +SwitchDir EQU SwitchP + SwitchW + fSwitch +SwitchCopy EQU SwitchV + SwitchA + SwitchB + fSwitch + +break +; TRAP snares the operating system for a service call +; AX, as well as any other registers MS-DOS takes a fancy to, will be crunched. +trap MACRO dos_function,dos_info + ifnb + mov AX, (dos_function SHL 8) + dos_info + else + mov AX, (dos_function SHL 8) + endif + int int_command +ENDM + +; +; Equates for initialization +; +initInit equ 01h ; initialization in progress +initSpecial equ 02h ; in initialization time/date routine +initCtrlC equ 04h ; already in ^C handler diff --git a/v4.0/src/CMD/COMMAND/COMMAND.LNK b/v4.0/src/CMD/COMMAND/COMMAND.LNK new file mode 100644 index 0000000..29a639a --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND.LNK @@ -0,0 +1,6 @@ +/map COMMAND1.OBJ COMMAND2.OBJ RUCODE.OBJ RDATA.OBJ INIT.OBJ IPARSE.OBJ + +UINIT.OBJ TCODE.OBJ TBATCH.OBJ TBATCH2.OBJ TFOR.OBJ TCMD1A.OBJ TCMD1B.OBJ + +TCMD2A.OBJ TCMD2B.OBJ TENV.OBJ TENV2.OBJ TMISC1.OBJ TMISC2.OBJ TPIPE.OBJ + +PARSE2.OBJ PATH1.OBJ PATH2.OBJ TUCODE.OBJ COPY.OBJ COPYPR1.OBJ COPYPR2.OBJ + +CPARSE.OBJ TPARSE.OBJ TPRINTF.OBJ TDATA.OBJ TSPC.OBJ,COMMAND.EXE,,; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COMMAND.SKL b/v4.0/src/CMD/COMMAND/COMMAND.SKL new file mode 100644 index 0000000..44b1eef --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND.SKL @@ -0,0 +1,213 @@ + +;************************* +;* MESSAGE SKELETON FILE * +;************************* + +:util COMMAND ;AC000; + +:class 1 ;AC000; Transient extended errors + +:use EXTEND2 ;AC000; "File not found" +:use EXTEND3 ;AC000; "Path not found" +:use EXTEND8 ;AC000; "Insufficient memory" + +:class 2 ;AC000; Transient parse errors + +:class 3 ;AC000; Resident extended errors +:use -1 EXTEND999 ;AN000; "Extended error #" + +:class 4 ;AC000; Resident parse errors +:use -1 PARSE999 ;AN000; "Parse error #" + +:class A ;AC000; resident messages + +:use 220 COMMON17 ;AC000; "File allocation table bad, drive %1" +:use 223 COMMON28 ;AC000; "Press any key to continue" +:def 201 "A" ;AC000; +:def 202 "R" ;AC000; +:def 203 "I" ;AC000; +:def 204 "F" ;AC000; +:def 205 "Y" ;AC000; +:def 206 "N" ;AC000; +:def 210 "Abort" ;AC000; +:def 211 ", Retry" ;AC000; +:def 212 ", Ignore" ;AC000; +:def 213 ", Fail" ;AC000; +:def 214 "?" ;AC000; +:def 215 "reading",0 ;AC000; +:def 216 "writing",0 ;AC000; +:def 217 " %1 drive %2",CR,LF ;AC000; +:def 218 " %1 device %2",CR,LF ;AC000; +:def 219 "Please insert volume %1 serial %2-%3",CR,LF ;AC009; +:def 221 "Invalid COMMAND.COM",CR,LF ;AC000; +:def 222 "Insert disk with %1 in drive %2",CR,LF ;AC000; +:def 224 CR,LF,"Terminate batch job (Y/N)?" ;AC000; +:def 225 "Cannot execute %1",CR,LF ;AC000; +:def 226 "Error in EXE file",CR,LF ;AC000; +:def 227 "Program too big to fit in memory",CR,LF ;AC000; +:def 228 CR,LF,"No free file handles" ;AC000; +:def 229 "Bad Command or file name",CR,LF ;AC000; +:use 230 EXTEND5 ;AC000; +:def 231 CR,LF,"Memory allocation error" ;AC000; +:def 232 CR,LF,"Cannot load COMMAND, system halted",CR,LF;AC000; +:def 233 CR,LF,"Cannot start COMMAND, exiting",CR,LF ;AC000; +:def 234 CR,LF,"Top level process aborted, cannot continue",CR,LF;AC000; +:def 235 CR,LF ;AC000; + + +:class B ;AC000; Initialization messages + +:use 461 COMMON1 ;AC000; "Incorrect DOS version" +:def 463 "Out of environment space",CR,LF ;AC000; +:def 464 CR,LF,CR,LF,"MS DOS ",CR,LF + "Version 4.00 (C)Copyright International Business Machines Corp 1981,1988",CR,LF + " (C)Copyright Microsoft Corp 1981, 1988",CR,LF ;AC000; +:def 465 "Specified COMMAND search directory bad",CR,LF ;AC025; +:def 466 "Specified COMMAND search directory bad access denied",CR,LF ;AC025; + +:class C ;AC000; Parse messages + +:use PARSE1 ;AC000; "Too many parameters" +:use PARSE2 ;AC000; "Required parameter missing" +:use PARSE3 ;AC000; "Invalid switch" +:use PARSE4 ;AC000; "Invalid keyword" +:use PARSE6 ;AC000; "Parameter value not in allowed range" +:use PARSE7 ;AC000; "Parameter value not allowed" +:use PARSE8 ;AC000; "Parameter value not allowed" +:use PARSE9 ;AC000; "Parameter format not correct" +:use PARSE10 ;AC000; "Invalid parameter" +:use PARSE11 ;AC000; "Invalid parameter combination" + +:class D ;AC000; Extended errors - critical + +:use EXTEND19 ;AC000; "Write protect" +:use EXTEND20 ;AC000; "Invalid unit" +:use EXTEND21 ;AC000; "Drive not ready" +:use EXTEND22 ;AC000; "Invalid device request" +:use EXTEND23 ;AC000; "Data error" +:use EXTEND24 ;AC000; "Invalid device request parameters" +:use EXTEND25 ;AC000; "Seek error" +:use EXTEND26 ;AC000; "Invalid media type" +:use EXTEND27 ;AC000; "Sector not found" +:use EXTEND28 ;AC000; "Printer out of paper" +:use EXTEND29 ;AC000; "Write fault error" +:use EXTEND30 ;AC000; "Read fault error" +:use EXTEND31 ;AC000; "General Failure" +:use EXTEND32 ;AC000; "Sharing Violation" +:use EXTEND33 ;AC000; "Lock Violation" +:use EXTEND34 ;AC000; "Invalid Disk Change" +:use EXTEND35 ;AC000; "FCB unavailable" +:use EXTEND36 ;AC000; "System resource exhausted" +:use EXTEND37 ;AC000; "Code page mismatch" +:use EXTEND38 ;AC026; "Out of input" +:use EXTEND39 ;AC026; "Insufficient disk space" + +:class E ;AC000; extended errors + +:use EXTEND1 ;AC000; "Invalid Function" +:use EXTEND2 ;AC000; "File not found" +:use EXTEND3 ;AC000; "Path not found" +:use EXTEND4 ;AC000; "Too many open files" +:use EXTEND5 ;AC000; "Access denied" +:use EXTEND6 ;AC000; "Invalid handle" +:use EXTEND7 ;AC000; "Memory control blocks destroyed" +:use EXTEND8 ;AC000; "Insufficient memory" +:use EXTEND9 ;AC000; "Invalid memory block address" +:use EXTEND10 ;AC000; "Invalid Environment" +:use EXTEND11 ;AC000; "Invalid format" +:use EXTEND12 ;AC000; "Invalid function parameter" +:use EXTEND13 ;AC000; "Invalid data" +:use EXTEND15 ;AC000; "Invalid drive specification" +:use EXTEND16 ;AC000; "Attempt to remove current directory" +:use EXTEND17 ;AC000; "Not same device" +:use EXTEND18 ;AC000; "No more files" +:use EXTEND80 ;AC000; "File already exists" +:use EXTEND82 ;AC000; "Can not make directory entry" +:use EXTEND83 ;AC000; "Fail requested to Critical Error" +:use EXTEND84 ;AC000; "Too many attaches" +:use EXTEND85 ;AC000; "Device or file already attached" +:use EXTEND86 ;AC000; "Invalid password" +:use EXTEND87 ;AC000; "Invalid parameter" +:use EXTEND88 ;AC000; "File system data fault" +:use EXTEND89 ;AC000; "Function not supported by file system" +:use EXTEND90 ;AC000; + + +:class F ;AC000; Transient messages + +:use 1020 COMMON4 ;AC000; "%1 bytes free",CR,LF +:use 1015 COMMON18 ;AC000; "File cannot be copied onto itself",CR,LF +:use 1004 COMMON20 ;AC000; "Insufficient disk space",CR,LF +:use 1026 COMMON22 ;AC000; "Invalid code page",CR,LF +:use 1031 COMMON23 ;AC000; "Invalid date" +:use 1035 COMMON24 ;AC000; "Invalid time" +:use 1062 COMMON25 ;AC000; "Invalid path" +:use 1028 COMMON28 ;AC000; "Press any key to continue" +:use 1045 COMMON32 ;AC000; "Unable to create directory",CR,LF +:use 1041 COMMON33 ;AC000; "Volume in drive %1 has no label" +:use 1042 COMMON34 ;AC000; "Volume in drive %1 is %2" +:use 1043 COMMON36 ;AC000; "Volume Serial Number is %1" +:def 1002 "Duplicate file name or file not found",CR,LF ;AC000; +:def 1003 "Invalid path or file name",CR,LF ;AC000; +:def 1007 "Out of environment space",CR,LF ;AC000; +:def 1008 "File creation error",CR,LF ;AC000; +:def 1009 "Batch file missing",CR,LF ;AC000; +:def 1010 CR,LF,"Insert disk with batch file",CR,LF ;AC000; +:def 1011 "Bad command or file name",CR,LF ;AC000; +:use 1014 EXTEND5 ;AC000; +:def 1016 "Content of destination lost before copy",CR,LF ;AC000; +:def 1017 "Invalid filename or file not found",CR,LF ;AC000; +:def 1018 "%1 File(s) copied",CR,LF ;AC000; +:def 1019 "%1 File(s) " ;AC000; +:use 1021 EXTEND15 ;AC000; +:def 1022 "Code page %1 not prepared for system",CR,LF ;AC000; +:def 1023 "Code page %1 not prepared for all devices",CR,LF ;AC000; +:def 1024 "Active code page: %1",CR,LF ;AC000; +:def 1025 "NLSFUNC not installed",CR,LF ;AC000; +:def 1027 "Current drive is no longer valid" ;AC000; +:def 1029 "Label not found",CR,LF ;AC000; +:def 1030 "Syntax error",CR,LF ;AC000; +:def 1032 "Current date is %1 %2",CR,LF ;AC000; +:def 1033 "SunMonTueWedThuFriSat" ;AC000; +:def 1034 "Enter new date (%1): " ;AC031; +:def 1036 "Current time is %1",CR,LF ;AC000; +:def 1037 "Enter new time: " ;AC031; +:def 1038 ", Delete (Y/N)?" ;AC000; +:def 1039 "All files in directory will be deleted!",CR,LF + "Are you sure (Y/N)?" ;AC000; +:def 1040 "Microsoft DOS Version %1.%2",CR,LF ;AC000; +:def 1044 "Invalid directory",CR,LF ;AC000; +:def 1046 "Invalid path, not directory,",CR,LF,"or directory not empty",CR,LF ;AC000; +:def 1047 "Must specify ON or OFF",CR,LF ;AC000; +:def 1048 "Directory of %1",CR,LF ;AC000; +:def 1049 "No Path",CR,LF ;AC000; +:def 1050 "Invalid drive in search path",CR,LF ;AC000; +:def 1051 "Invalid device",CR,LF ;AC000; +:def 1052 "FOR cannot be nested",CR,LF ;AC000; +:def 1053 "Intermediate file error during pipe",CR,LF ;AC000; +:def 1054 "Cannot do binary reads from a device",CR,LF ;AC000; +:def 1055 "BREAK is %1",CR,LF ;AC000; +:def 1056 "VERIFY is %1",CR,LF ;AC000; +:def 1057 "ECHO is %1",CR,LF ;AC000; +:def 1059 "off",0 ;AC000; +:def 1060 "on",0 ;AC000; +:def 1061 "Error writing to device",CR,LF ;AC000; +:def 1063 "%1" ;AC000; +:def 1064 "%1" ;AC000; +:def 1065 "%1" ;AC000; +:def 1066 "%1" ;AC000; +:def 1067 9 ;AC000; +:def 1068 "

" ;AC000; +:def 1069 8," ",8 ;AC000; +:def 1070 CR,LF ;AC000; +:def 1071 "%1" ;AC000; +:def 1072 "mm-dd-yy" ;AC000; +:def 1073 "dd-mm-yy" ;AC000; +:def 1074 "yy-mm-dd" ;AC000; +:def 1075 "%1 %2" ;AC000; +:def 1076 "%1" ;AC000; +:def 1077 " %1 %2" ;AC053; +:def 1078 "Directory already exists",CR,LF ;AC000; + +:end ;AC000; + diff --git a/v4.0/src/CMD/COMMAND/COMMAND1.ASM b/v4.0/src/CMD/COMMAND/COMMAND1.ASM new file mode 100644 index 0000000..3ee909a --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND1.ASM @@ -0,0 +1,638 @@ + page 80,132 +; SCCSID = @(#)command1.asm 1.1 85/05/14 +; SCCSID = @(#)command1.asm 1.1 85/05/14 +TITLE COMMAND - resident code for COMMAND.COM +NAME COMMAND + +;***************************************************************************** +; +; MODULE: COMMAND.COM +; +; DESCRIPTIVE NAME: Default DOS command interpreter +; +; FUNCTION: This version of COMMAND is divided into three distinct +; parts. First is the resident portion, which includes +; handlers for interrupts 23H (Cntrl-C), 24H (fatal +; error), and 2EH (command line execute); it also has +; code to test and, if necessary, reload the transient +; portion. Following the resident is the init code, which +; is overwritten after use. Then comes the transient +; portion, which includes all command processing (whether +; internal or external). The transient portion loads at +; the end of physical memory, and it may be overlayed by +; programs that need as much memory as possible. When the +; resident portion of command regains control from a user +; program, a check sum is performed on the transient +; portion to see if it must be reloaded. Thus programs +; which do not need maximum memory will save the time +; required to reload COMMAND when they terminate. +; +; ENTRY POINT: PROGSTART +; +; INPUT: command line at offset 81H +; +; EXIT_NORMAL: No exit from root level command processor. Can exit +; from a secondary command processor via the EXIT +; internal command. +; +; EXIT_ERROR: Exit to prior command processor if possible, otherwise +; hang the system. +; +; INTERNAL REFERENCES: +; +; ROUTINES: See the COMMAND Subroutine Description Document +; (COMMAND.DOC) +; +; DATA AREAS: See the COMMAND Subroutine Description Document +; (COMMAND.DOC) +; +; EXTERNAL REFERENCES: +; +; ROUTINES: none +; +; DATA AREAS: none +; +;***************************************************************************** +; +; REVISION HISTORY +; ---------------- +; +; DOS 1.00 to DOS 3.30 +; -------------------------- +; SEE REVISION LOG IN COPY.ASM ALSO +; +; REV 1.17 +; 05/19/82 Fixed bug in BADEXE error (relocation error must return to +; resident since the EXELOAD may have overwritten the transient. +; +; REV 1.18 +; 05/21/82 IBM version always looks on drive A +; MSVER always looks on default drive +; +; REV 1.19 +; 06/03/82 Drive spec now entered in command line +; 06/07/82 Added VER command (print DOS version number) and VOL command +; (print volume label) +; +; REV 1.20 +; 06/09/82 Prints "directory" after directories +; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added +; +; REV 1.50 +; Some code for new 2.0 DOS, sort of HACKey. Not enough time to +; do it right. +; +; REV 1.70 +; EXEC used to fork off new processes +; +; REV 1.80 +; C switch for single command execution +; +; REV 1.90 +; Batch uses XENIX +; +; Rev 2.00 +; Lots of neato stuff +; IBM 2.00 level +; +; Rev 2.01 +; 'D' switch for date time suppression +; +; Rev 2.02 +; Default userpath is NUL rather than BIN +; same as IBM +; COMMAND split into pieces +; +; Rev 2.10 +; INTERNATIONAL SUPPORT +; +; Rev 2.50 +; all the 2.x new stuff -MU +; +; Rev 3.30 (Ellen G) +; CALL internal command (TBATCH2.ASM) +; CHCP internal command (TCMD2B.ASM) +; INT 24H support of abort, retry, ignore, and fail prompt +; @ sign suppression of batch file line +; Replaceable environment value support in batch files +; INT 2FH calls for APPEND +; Lots of PTR fixes! +; +; Beyond 3.30 to forever (Ellen G) +; ---------------------- +; +; A000 DOS 4.00 - Use SYSPARSE for internal commands +; Use Message Retriever services +; /MSG switch for resident extended error msg +; Convert to new capitalization support +; Better error recovery on CHCP command +; Code page file tag support +; TRUENAME internal command +; Extended screen line support +; /P switch on DEL/ERASE command +; Improved file redirection error recovery +; (removed) Improved batch file performance +; Unconditional DBCS support +; Volume serial number support +; (removed) COMMENT=?? support +; +; A001 PTM P20 Move system_cpage from TDATA to TSPC +; +; A002 PTM P74 Fix PRESCAN so that redirection symbols do not +; require delimiters. +; +; A003 PTM P5,P9,P111 Included in A000 development +; +; A004 PTM P86 Fix IF command to turn off piping before +; executing +; +; A005 DCR D17 If user specifies an extension on the command +; line search for that extension only. +; +; A006 DCR D15 New message for MkDir - "Directory already +; exists" +; +; A007 DCR D2 Change CTTY so that a write is done before XDUP +; +; A008 PTM P182 Change COPY to set default if invalid function +; returned from code page call. +; +; A009 PTM P179 Add CRLF to invalid disk change message +; +; A010 DCR D43 Allow APPEND to do a far call to SYSPARSE in +; transient COMMAND. +; +; A011 DCR D130 Change redirection to overwrite an EOF mark +; before appending to a file. +; +; A012 PTM P189 Fix redirection error recovery. +; +; A013 PTM P330 Change date format +; +; A014 PTM P455 Fix echo parsing +; +; A015 PTM P517 Fix DIR problem with * vs *. +; +; A016 PTM P354 Fix extended error message addressing +; +; A017 PTM P448 Fix appending to 0 length files +; +; A018 PTM P566,P3903 Fix parse error messages to print out parameter +; the parser fails on. Fail on duplicate switches. +; +; A019 PTM P542 Fix device name to be printed correctly during +; critical error +; +; A020 DCR D43 Set append state off while in DIR +; +; A021 PTM P709 Fix CTTY printing ascii characters. +; +; A022 DCR D209 Enhanced error recovery +; +; A023 PTM P911 Fix ANSI.SYS IOCTL structure. +; +; A024 PTM P899 Fix EXTOPEN open modes. +; +; A025 PTM P922 Fix messages and optimize PARSE switches +; +; A026 DCR D191 Change redirection error recovery support. +; +; A027 PTM P991 Fix so that KAUTOBAT & AUTOEXEC are terminated +; with a carriage return. +; +; A028 PTM P1076 Print a blank line before printing invalid +; date and invalid time messages. +; +; A029 PTM P1084 Eliminate calls to parse_check_eol in DATE +; and TIME. +; +; A030 DCR D201 New extended attribute format. +; +; A031 PTM P1149 Fix DATE/TIME add blank before prompt. +; +; A032 PTM P931 Fix =ON, =OFF for BREAK, VERIFY, ECHO +; +; A033 PTM P1298 Fix problem with system crashes on ECHO >"" +; +; A034 PTM P1387 Fix COPY D:fname+,, to work +; +; A035 PTM P1407 Fix so that >> (appending) to a device does +; do a read to determine eof. +; +; A036 PTM P1406 Use 69h instead of 44h to get volume serial +; so that ASSIGN works correctly. +; +; A037 PTM P1335 Fix COMMAND /C with FOR +; +; A038 PTM P1635 Fix COPY so that it doesn't accept /V /V +; +; A039 DCR D284 Change invalid code page tag from -1 to 0. +; +; A040 PTM P1787 Fix redirection to cause error when no file is +; specified. +; +; A041 PTM P1705 Close redirected files after internal APPEND +; executes. +; +; A042 PTM P1276 Fix problem of APPEND paths changes in batch +; files causing loss of batch file. +; +; A043 PTM P2208 Make sure redirection is not set up twice for +; CALL'ed batch files. +; +; A044 PTM P2315 Set switch on PARSE so that 0ah is not used +; as an end of line character +; +; A045 PTM P2560 Make sure we don't lose parse, critical error, +; and extended message pointers when we EXIT if +; COMMAND /P is the top level process. +; +; A046 PTM P2690 Change COPY message "fn File not found" to +; "File not found - fn" +; +; A047 PTM P2819 Fix transient reload prompt message +; +; A048 PTM P2824 Fix COPY path to be upper cased. This was broken +; when DBCS code was added. +; +; A049 PTM P2891 Fix PATH so that it doesn't accept extra characters +; on line. +; +; A050 PTM P3030 Fix TYPE to work properly on files > 64K +; +; A051 PTM P3011 Fix DIR header to be compatible with prior releases. +; +; A052 PTM P3063,P3228 Fix COPY message for invalid filename on target. +; +; A053 PTM P2865 Fix DIR to work in 40 column mode. +; +; A054 PTM P3407 Code reduction and critical error on single line +; PTM P3672 (Change to single parser exported under P3407) +; +; A055 PTM P3282 Reset message service variables in INT 23h to fix +; problems with breaking out of INT 24h +; +; A056 PTM P3389 Fix problem of environment overlaying transient. +; +; A057 PTM P3384 Fix COMMAND /C so that it works if there is no space +; before the "string". EX: COMMAND /CDIR +; +; A058 PTM P3493 Fix DBCS so that CPARSE eats second character of +; DBCS switch. +; +; A059 PTM P3394 Change the TIME command to right align the display of +; the time. +; +; A060 PTM P3672 Code reduction - change PARSE and EXTENDED ERROR +; messages to be disk based. Only keep them if /MSG +; is used. +; +; A061 PTM P3928 Fix so that transient doesn't reload when breaking +; out of internal commands, due to substitution blocks +; not being reset. +; +; A062 PTM P4079 Fix segment override for fetching address of environment +; of parent copy of COMMAND when no COMSPEC exists in +; secondary copy of environment. Change default slash in +; default comspec string to backslash. + +; A063 PTM P4140 REDIRECTOR and IFSFUNC changed interface for getting +; text for critical error messages. + +; A064 PTM P4934 Multiplex number for ANSI.SYS changed due to conflict +; 5/20/88 with Microsoft product already shipped. + +; A065 PTM P4935 Multiplex number for SHELL changed due to conflict with +; 5/20/88 with Microsoft product already shipped. + +; A066 PTM P4961 DIR /W /P scrolled first line off the screen in some +; 5/24/88 cases; where the listing would barely fit without the +; header and space remaining. + +; A067 PTM P5011 For /E: values of 993 to 1024 the COMSPEC was getting +; 6/6/88 trashed. Turns out that the SETBLOCK for the new +; environment was putting a "Z block" marker in the old +; environment. The fix is to move to the old environment +; to the new environment before doing the SETBLOCK. +;*********************************************************************************** + +.XCREF +.XLIST + INCLUDE DOSSYM.INC + INCLUDE comsw.asm + INCLUDE comequ.asm + INCLUDE resmsg.equ ;AN000; +.LIST +.CREF + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE + EXTRN BATCH:WORD + EXTRN ECHOFLAG:BYTE + EXTRN disp_class:byte ;AN055; + EXTRN execemes_block:byte ;AC000; + EXTRN execemes_off:word ;AC000; + EXTRN execemes_subst:byte ;AC000; + EXTRN execemes_seg:word ;AC000; + EXTRN EXTCOM:BYTE + EXTRN FORFLAG:BYTE + EXTRN IFFlag:BYTE + EXTRN InitFlag:BYTE + EXTRN NEST:WORD + EXTRN number_subst:byte ;AC000; + EXTRN PIPEFLAG:BYTE + EXTRN RETCODE:WORD + EXTRN SINGLECOM:WORD +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA + EXTRN CONPROC:NEAR + EXTRN init_contc_specialcase:near +INIT ENDS + +TAIL SEGMENT PUBLIC PARA +TAIL ENDS + +TRANCODE SEGMENT PUBLIC PARA +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + + INCLUDE envdata.asm + +; START OF RESIDENT PORTION + +CODERES SEGMENT PUBLIC BYTE ;AC000; + + + PUBLIC EXT_EXEC + PUBLIC CONTC + PUBLIC Exec_Wait + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN lodcom:near + EXTRN LODCOM1:near + + ORG 0 +ZERO = $ + + ORG 80h-1 + PUBLIC RESCOM +RESCOM LABEL BYTE + + ORG 100H + +PROGSTART: + JMP RESGROUP:CONPROC + +; +; COMMAND has issued an EXEC system call and it has returned an error. We +; examine the error code and select an appropriate message. +; +EXEC_ERR: + push ds ;AC000; get transient segment + pop es ;AC000; into ES + push cs ;AC000; get resident segment + pop ds ;AC000; into DS +ASSUME DS:RESGROUP ;AN000; + MOV BX,RBADNAM ;AC000; Get message number for Bad command + CMP AX,error_file_not_found + JZ GOTEXECEMES + MOV BX,TOOBIG ;AC000; Get message number for file not found + CMP AX,error_not_enough_memory + JZ GOTEXECEMES + MOV BX,EXEBAD ;AC000; Get message number for bad exe file + CMP AX,error_bad_format + JZ GOTEXECEMES + MOV BX,AccDen ;AC000; Get message number for access denied + CMP AX,error_access_denied + JZ GOTEXECEMES ;AC000; go print message + +DEFAULT_MESSAGE: + MOV BX,EXECEMES ;AC000; Get message number for default message + MOV EXECEMES_OFF,DX ;AN000; put offset of EXEC string in subst block + MOV EXECEMES_SEG,ES ;AN000; put segment of EXEC string in subst block + MOV AL,EXECEMES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:EXECEMES_BLOCK ;AN000; get address of subst block +GOTEXECEMES: + PUSH CS + POP ES ;AC000; get resident segment into ES +ASSUME ES:RESGROUP ;AN000; + MOV DX,BX ;AN000; get message number in DX + INVOKE RPRINT + JMP SHORT NOEXEC +; +; The transient has set up everything for an EXEC system call. For +; cleanliness, we issue the EXEC here in the resident so that we may be able +; to recover cleanly upon success. +; +EXT_EXEC: + push dx ;AN000; save the command name offset + INT int_command ; Do the EXEC + pop dx ;AN000; restore the command name offset + JC EXEC_ERR ; EXEC failed +; +; The exec has completed. Retrieve the exit code. +; +EXEC_WAIT: + push cs ;AC000; get resident segment + pop ds ;AC000; into DS + MOV AH,WAITPROCESS ;AC000; Get errorlevel + INT int_command ; Get the return code + MOV [RETCODE],AX +; +; We need to test to see if we can reload the transient. THe external command +; may have overwritten part of the transient. +; +NOEXEC: + JMP LODCOM +; +; This is the default system INT 23 handler. All processes (including +; COMMAND) get it by default. There are some games that are played: We +; ignore ^C during most of the INIT code. This is because we may perform an +; ALLOC and diddle the header! Also, if we are prompting for date/time in the +; init code, we are to treat ^C as empty responses. +; +CONTC PROC FAR + ASSUME CS:ResGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + test InitFlag,initINIT ; in initialization? + jz NotAtInit ; no + test InitFlag,initSpecial ; doing special stuff? + jz CmdIRet ; no, ignore ^C + jmp resgroup:init_contc_specialcase ; Yes, go handle it +CmdIret: + iret ; yes, ignore the ^C +NotAtInit: + test InitFlag,initCtrlC ; are we already in a ^C? + jz NotInit ; nope too. +; +; We are interrupting ourselves in this ^C handler. We need to set carry +; and return to the user sans flags only if the system call was a 1-12 one. +; Otherwise, we ignore the ^C. +; + cmp ah,1 + jb CmdIRet + cmp ah,12 + ja CmdIRet + add sp,6 ; remove int frame + stc + ret 2 ; remove those flags... +; +; We have now received a ^C for some process (maybe ourselves but not at INIT). +; +; Note that we are running on the user's stack!!! Bad news if any of the +; system calls below go and issue another INT 24... Massive stack overflow! +; Another bad point is that SavHand will save an already saved handle, thus +; losing a possible redirection... +; +; All we need to do is set the flag to indicate nested ^C. The above code +; will correctly flag the ^C diring the message output and prompting while +; ignoring the ^C the rest of the time. +; +; Clean up: flush disk. If we are in the middle of a batch file, we ask if +; he wants to terminate it. If he does, then we turn off all internal flags +; and let the DOS abort. +; +NotInit: + or InitFlag,initCtrlC ; nested ^c is on + STI + PUSH CS ; El Yucko! Change the user's DS!! + POP DS +ASSUME DS:RESGROUP + MOV DISP_CLASS,UTIL_MSG_CLASS ;AN055; reset display class + MOV NUMBER_SUBST,NO_SUBST ;AN055; reset number of substitutions + MOV AX,SingleCom + OR AX,AX + JNZ NoReset + PUSH AX + MOV AH,DISK_RESET + INT int_command ; Reset disks in case files were open + POP AX +NoReset: +; +; In the generalized version of FOR, PIPE and BATCH, we would walk the entire +; active list and free each segment. Here, we just free the single batch +; segment. +; + TEST Batch,-1 + JZ CONTCTERM + OR AX,AX + JNZ Contcterm + invoke SavHand + invoke ASKEND ; See if user wants to terminate batch +; +; If the carry flag is clear, we do NOT free up the batch file +; + JNC ContBatch + mov cl,echoflag ;AN000; get current echo flag + PUSH BX ;G + +ClearBatch: + MOV ES,[BATCH] ; get batch segment + mov di,batfile ;AN000; get offset of batch file name + mov ax,mult_shell_brk ;AN000; does the SHELL want this terminated? + int 2fh ;AN000; call the SHELL + cmp al,shell_action ;AN000; does shell want this batch? + jz shell_bat_cont ;AN000; yes - keep it + + MOV BX,ES:[BATFORPTR] ;G get old FOR segment + cmp bx,0 ;G is a FOR in progress + jz no_bat_for ;G no - don't deallocate + push es ;G + mov es,bx ;G yes - free it up... + MOV AH,DEALLOC ;G + INT 21H ;G + pop es ;G restore to batch segment + +no_bat_for: + mov cl,ES:[batechoflag] ;G get old echo flag + MOV BX,ES:[BATLAST] ;G get old batch segment + MOV AH,DEALLOC ; free it up... + INT 21H + MOV [BATCH],BX ;G get ready to deallocate next batch + DEC NEST ;G Is there another batch file? + JNZ CLEARBATCH ;G Keep going until no batch file + +; +; We are terminating a batch file; restore the echo status +; + +shell_bat_cont: ;AN000; continue batch for SHELL + + POP BX ;G + MOV ECHOFLAG,CL ;G reset echo status + MOV PIPEFLAG,0 ;G turn off pipeflag +ContBatch: + invoke CRLF ;G print out crlf before returning + invoke RestHand +; +; Yes, we are terminating. Turn off flags and allow the DOS to abort. +; +CONTCTERM: + XOR AX,AX ; Indicate no read + MOV BP,AX +; +; The following resetting of the state flags is good for the generalized batch +; processing. +; + MOV IfFlag,AL ; turn off iffing + MOV [FORFLAG],AL ; Turn off for processing + call ResPipeOff + CMP [SINGLECOM],AX ; See if we need to set SINGLECOM + JZ NOSETSING + MOV [SINGLECOM],-1 ; Cause termination on pipe, batch, for +NOSETSING: +; +; If we are doing an internal command, go through the reload process. If we +; are doing an external, let DOS abort the process. In both cases, we are +; now done with the ^C processing. +; + AND InitFlag,NOT initCtrlC + CMP [EXTCOM],AL + JNZ DODAB ; Internal ^C + JMP LODCOM1 +DODAB: + STC ; Tell DOS to abort + RET ; Leave flags on stack +ContC ENDP + +public ResPipeOff + assume ds:nothing,es:nothing +ResPipeOff: + SaveReg + xor ax,ax + xchg PipeFlag,al + or al,al + jz NoPipePop + shr EchoFlag,1 +NoPipePop: + RestoreReg + return +CODERES ENDS + END PROGSTART diff --git a/v4.0/src/CMD/COMMAND/COMMAND2.ASM b/v4.0/src/CMD/COMMAND/COMMAND2.ASM new file mode 100644 index 0000000..0f6c5b5 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND2.ASM @@ -0,0 +1,619 @@ + page 80,132 +; SCCSID = @(#)command2.asm 4.3 85/10/16 +; SCCSID = @(#)command2.asm 4.3 85/10/16 +TITLE COMMAND2 - resident code for COMMAND.COM part II +NAME COMMAND2 +.XCREF +.XLIST + INCLUDE DOSSYM.INC + INCLUDE comsw.asm + INCLUDE comequ.asm + INCLUDE resmsg.equ ;AN000; +.LIST +.CREF + +tokenized = FALSE + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE + EXTRN append_state:word ;AN020; + EXTRN append_flag:byte ;AN020; + EXTRN COMDRV:BYTE + EXTRN comprmt1_block:byte ;AN000; + EXTRN comprmt1_subst:byte ;AN000; + EXTRN COMSPEC:BYTE + EXTRN cpdrv:byte + EXTRN envirseg:word + EXTRN EXTCOM:BYTE + EXTRN HANDLE01:WORD + EXTRN InitFlag:BYTE + EXTRN INT_2E_RET:DWORD ;AC000; + EXTRN IO_SAVE:WORD + EXTRN LOADING:BYTE + EXTRN LTPA:WORD + EXTRN MEMSIZ:WORD + EXTRN number_subst:byte ;AN000; + EXTRN OldTerm:DWORD ;AC000; + EXTRN PARENT:WORD ;AC000; + EXTRN PERMCOM:BYTE + EXTRN RDIRCHAR:BYTE + EXTRN RES_TPA:WORD + EXTRN RETCODE:WORD + EXTRN rsrc_xa_seg:word ;AN030; + EXTRN RSWITCHAR:BYTE + EXTRN SAVE_PDB:WORD + EXTRN SINGLECOM:WORD + EXTRN SUM:WORD + EXTRN TRANS:WORD + EXTRN TranVarEnd:BYTE + EXTRN TRANVARS:BYTE + EXTRN TRNSEG:WORD + EXTRN VERVAL:WORD +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA + EXTRN envsiz:word + EXTRN oldenv:word + EXTRN resetenv:byte + EXTRN usedenv:word +INIT ENDS + +TAIL SEGMENT PUBLIC PARA +TAIL ENDS + +TRANCODE SEGMENT PUBLIC PARA +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE + EXTRN TRANDATAEND:BYTE +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE + EXTRN TRANSPACEEND:BYTE + EXTRN HEADCALL:DWORD +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + +; START OF RESIDENT PORTION + +CODERES SEGMENT PUBLIC BYTE ;AC000; + + PUBLIC CHKSUM + PUBLIC endinit + PUBLIC GETCOMDSK2 + PUBLIC INT_2E + PUBLIC LOADCOM + PUBLIC LODCOM + PUBLIC LODCOM1 + PUBLIC RESTHAND + PUBLIC SAVHAND + PUBLIC SETVECT + PUBLIC THEADFIX + PUBLIC TREMCHECK + PUBLIC tjmp + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN contc:near + EXTRN DSKERR:NEAR + EXTRN rstack:word +; +; If we cannot allocate enough memory for the transient or there was some +; other allocation error, we display a message and then die. +; +BADMEMERR: ; Allocation error loading transient + MOV DX,BMEMMES ;AC000; get message number +FATALC: + PUSH CS + POP DS + ASSUME DS:ResGroup + invoke RPRINT +; +; If this is NOT a permanent (top-level) COMMAND, then we exit; we can't do +; anything else! +; + CMP PERMCOM,0 + JZ FATALRET +; +; We are a permanent command. If we are in the process of the magic interrupt +; (Singlecom) then exit too. +; + CMP SINGLECOM,0 ; If PERMCOM and SINGLECOM + JNZ FATALRET ; Must take INT_2E exit +; +; Permanent command. We can't do ANYthing except halt. +; + MOV DX,HALTMES ;AC000; get message number + invoke RPRINT + STI +STALL: + JMP STALL ; Crash the system nicely + +FATALRET: + MOV DX,FRETMES ;AC000; get message number + invoke RPRINT +FATALRET2: + CMP [PERMCOM],0 ; If we get here and PERMCOM, + JNZ RET_2E ; must be INT_2E + invoke reset_msg_pointers ;AN000; reset critical & parse error messages + MOV AX,[PARENT] + MOV WORD PTR CS:[PDB_Parent_PID],AX + MOV AX,WORD PTR OldTerm + MOV WORD PTR CS:[PDB_Exit],AX + MOV AX,WORD PTR OldTerm+2 + MOV WORD PTR CS:[PDB_Exit+2],AX + MOV AX,(EXIT SHL 8) ; Return to lower level + INT int_command + +RET_2E: + PUSH CS + POP DS +ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING + MOV [SINGLECOM],0 ; Turn off singlecom + MOV ES,[RES_TPA] + MOV AH,DEALLOC + INT int_command ; Free up space used by transient + MOV BX,[SAVE_PDB] + MOV AH,SET_CURRENT_PDB + INT int_command ; Current process is user + MOV AX,[RETCODE] + CMP [EXTCOM],0 + JNZ GOTECODE + XOR AX,AX ; Internals always return 0 +GOTECODE: + MOV [EXTCOM],1 ; Force external + JMP [INT_2E_RET] ;"IRET" + +INT_2E: ; Magic command executer +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + POP WORD PTR [INT_2E_RET] + POP WORD PTR [INT_2E_RET+2] ;Get return address + POP AX ;Chuck flags + PUSH CS + POP ES + MOV DI,80H + MOV CX,64 + REP MOVSW + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV [SAVE_PDB],BX + MOV AH,SET_CURRENT_PDB + MOV BX,CS + INT int_command ; Current process is me + MOV [SINGLECOM],81H + MOV [EXTCOM],1 ; Make sure this case forced + +LODCOM: ; Termination handler + CMP [EXTCOM],0 + jz lodcom1 ; if internal, memory already allocated + mov bx,0ffffh + MOV AH,ALLOC + INT int_command + CALL SetSize + ADD AX,20H + CMP BX,AX ; Is less than 512 byte buffer worth it? + JNC MEMOK +BADMEMERRJ: + JMP BADMEMERR ; Not enough memory + +; SetSize - get transient size in paragraphs +Procedure SetSize,NEAR + MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15 + MOV CL,4 + SHR AX,CL + return +EndProc SetSize + +MEMOK: + MOV AH,ALLOC + INT int_command + JC BADMEMERRJ ; Memory arenas probably trashed + MOV [EXTCOM],0 ; Flag not to ALLOC again + MOV [RES_TPA], AX ; Save current TPA segment + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JC BAD_TPA ; Memory wrap if carry set +; Make sure that new boundary is within allocated range + MOV DX, [RES_TPA] + ADD DX, BX ; Compute maximum address + CMP DX, AX ; Is 64K address out of range? + JBE BAD_TPA +; Must have 64K of usable space. + SUB DX, AX ; Compute the usable space + CMP DX, 01000H ; Is space >= 64K ? + JAE LTPASET +BAD_TPA: + MOV AX, [RES_TPA] +LTPASET: + MOV [LTPA],AX ; Usable TPA is 64k buffer aligned + MOV AX, [RES_TPA] ; Actual TPA is buffer allocated + ADD BX,AX + MOV [MEMSIZ],BX + CALL SetSize + SUB BX,AX + MOV [TRNSEG],BX ; Transient starts here +LODCOM1: + MOV AX,CS + MOV SS,AX +ASSUME SS:RESGROUP + MOV SP,OFFSET RESGROUP:RSTACK + MOV DS,AX +ASSUME DS:RESGROUP + CALL HEADFIX ; Make sure files closed stdin and stdout restored + XOR BP,BP ; Flag command ok + MOV AX,-1 + XCHG AX,[VERVAL] + CMP AX,-1 + JZ NOSETVER + MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value + INT int_command +NOSETVER: + CMP [SINGLECOM],-1 + JNZ NOSNG + JMP FATALRET2 ; We have finished the single command +NOSNG: + CALL CHKSUM ; Check the transient + CMP DX,[SUM] + JZ HAVCOM ; Transient OK +BOGUS_COM: + MOV [LOADING],1 ; Flag DSKERR routine + CALL LOADCOM +CHKSAME: + + CALL CHKSUM + CMP DX,[SUM] + JZ HAVCOM ; Same COMMAND +ALSO_BOGUS: + CALL WRONGCOM + JMP SHORT CHKSAME +HAVCOM: + MOV AX,CHAR_OPER SHL 8 + INT int_command + MOV [RSWITCHAR],DL + CMP DL,'/' + JNZ USESLASH + mov cl,'\' + MOV [RDIRCHAR],cl ; Select alt path separator +USESLASH: + MOV [LOADING],0 ; Flag to DSKERR + MOV SI,OFFSET RESGROUP:TRANVARS + MOV DI,OFFSET TRANGROUP:HEADCALL + MOV ES,[TRNSEG] + CLD + MOV CX,OFFSET ResGroup:TranVarEnd + SUB CX,SI + REP MOVSB ; Transfer INFO to transient + MOV AX,[MEMSIZ] + MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header + +; Just a public label so this spot can be found easily. +tjmp: + JMP DWORD PTR [TRANS] + +; Far call to REMCHECK for TRANSIENT +TREMCHECK PROC FAR + CALL REMCHECK + RET +TREMCHECK ENDP + +REMCHECK: +;All registers preserved. Returns ZF set if media removable, NZ if fixed +; AL is drive (0=DEF, 1=A,...). + SaveReg + MOV BX,AX + MOV AX,(IOCTL SHL 8) + 8 + INT 21h + jnc RCcont ; If an error occurred, assume the media + or ax,ax ; is NON-removable. + ; AX contains the non-zero error code + ; from the INT 21, so the OR AX,AX sets + ; Non-zero. This behavior makes Network + ; drives appear to be non-removable. + jmp SHORT ResRegs +RCcont: + AND AX,1 + NOT AX +ResRegs: + RestoreReg + return + +; Far call to HEADFIX for TRANSIENT +THEADFIX PROC FAR + CALL HEADFIX + RET +THEADFIX ENDP + +HEADFIX: + CALL SETVECT + XOR BX,BX ; Clean up header + MOV CX,[IO_SAVE] + MOV DX,WORD PTR DS:[PDB_JFN_Table] + CMP CL,DL + JZ CHK1 ; Stdin matches + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table],CL ; Restore stdin +CHK1: + INC BX + CMP CH,DH ; Stdout matches + JZ CHKOTHERHAND + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout +CHKOTHERHAND: + ADD BX,4 ; Skip 2,3,4 + MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4 +CLOSELOOP: + MOV AH,CLOSE + INT int_command + INC BX + LOOP CLOSELOOP + push ds ;AN020; save data segment + push cs ;AN020; Get local segment into DS + pop ds ;AN020; + cmp append_flag,-1 ;AN020; Do we need to reset APPEND? + jnz append_fix_end ;AN030; no - just exit + mov ax,AppendSetState ;AN020; Set the state of Append + mov bx,Append_state ;AN020; back to the original state + int 2fh ;AN020; + mov append_flag,0 ;AN020; Set append flag to invalid +append_fix_end: ;AN030; + cmp [rsrc_xa_seg],no_xa_seg ;AN030; Is there any active XA segment? + jz xa_fix_end ;AN030; no - exit + push es ;AN030; Yes - deallocate it + mov es,rsrc_xa_seg ;AN030; + mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call + int int_command ;AN030; + pop es ;AN030; + mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment +xa_fix_end: + pop ds ;AN020; get data segment back + return + +SAVHAND: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH DS + PUSH BX ; Set stdin to sterr, stdout to stderr + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV DS,BX + LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table... + MOV AX,WORD PTR DS:[BX] + MOV [HANDLE01],AX ; Save user's stdin, stdout + MOV AL,CS:[PDB_JFN_Table+2] ; get COMMAND stderr + MOV AH,AL + MOV WORD PTR DS:[BX],AX ; Dup stderr + POP AX + POP BX + POP DS + return + +ASSUME DS:RESGROUP +GETCOMDSK2: + CALL GETCOMDSK + JMP LODCOM1 ; Memory already allocated + +RESTHAND: + PUSH DS + PUSH BX ; Restore stdin, stdout to user + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Point to user's header + MOV AX,[HANDLE01] + MOV DS,BX +ASSUME DS:NOTHING + LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table... + MOV WORD PTR DS:[BX],AX ; Stuff his old 0 and 1 + POP AX + POP BX + POP DS + return +ASSUME DS:RESGROUP,SS:RESGROUP + +HOPELESS: + MOV DX,COMBAD ;AC000; + JMP FATALC + +GETCOMDSK: + mov al,[comdrv] + CALL REMCHECK + jNZ HOPELESS ;Non-removable media +getcomdsk3: + cmp dx,combad ;AC000; + jnz getcomdsk4 + mov dx,combad ;AN000; get message number + invoke RPRINT ; Say command is invalid +getcomdsk4: + cmp [cpdrv],0 ;g is there a drive in the comspec? + jnz users_drive ;g yes - use it + mov ah,Get_default_drive ;g use default drive + int 21h ;g + add al,"A" ;g convert to ascii + mov [cpdrv],al ;g put in message to print out + +users_drive: ;g + mov dx,comprmt1 ;AC000; Prompt for diskette containing command +IF tokenized + or byte ptr [si],80h +endif + MOV AL,COMPRMT1_SUBST ;AN000; get number of substitutions + MOV SI,OFFSET RESGROUP:COMPRMT1_BLOCK ;AN000; get address of subst block + MOV NUMBER_SUBST,AL ;AN000; + invoke rprint +if tokenized + and byte ptr [si],NOT 80h +endif + mov dx,prompt ;AN047; Tell the user to strike a key + invoke rprint ;AN047; + CALL GetRawFlushedByte + return + +; flush world and get raw input +GetRawFlushedByte: + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT + INT int_command ; Get char without testing or echo + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT int_command + return + +LOADCOM: ; Load in transient + INC BP ; Flag command read + MOV DX,OFFSET RESGROUP:COMSPEC + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + JNC READCOM + CMP AX,error_too_many_open_files + JNZ TRYDOOPEN + MOV DX,NOHANDMES ;AC000; + JMP FATALC ; Fatal, will never find a handle + +TRYDOOPEN: + CALL GETCOMDSK + JMP LOADCOM + +READCOM: + MOV BX,AX ; Handle + MOV DX,OFFSET RESGROUP:TRANSTART + XOR CX,CX ; Seek loc + MOV AX,LSEEK SHL 8 + INT int_command + JC WRONGCOM1 + MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H + + PUSH DS + MOV DS,[TRNSEG] +ASSUME DS:NOTHING + MOV DX,100H + MOV AH,READ + INT int_command + POP DS +ASSUME DS:RESGROUP +WRONGCOM1: + PUSHF + PUSH AX + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + POP AX + POPF + JC WRONGCOM ; If error on READ + CMP AX,CX + retz ; Size matched +WRONGCOM: + MOV DX,COMBAD ;AC000; + CALL GETCOMDSK + JMP LOADCOM ; Try again + +CHKSUM: ; Compute transient checksum + PUSH DS + MOV DS,[TRNSEG] + MOV SI,100H + MOV CX,OFFSET TRANGROUP:TranDataEnd - 100H + +CHECK_SUM: + CLD + SHR CX,1 + XOR DX,DX +CHK: + LODSW + ADD DX,AX + ADC DX,0 + LOOP CHK + POP DS + return + +SETVECT: ; Set useful vectors + MOV DX,OFFSET RESGROUP:LODCOM + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H + MOV WORD PTR DS:[PDB_EXIT],DX + MOV WORD PTR DS:[PDB_EXIT+2],DS + INT int_command + MOV DX,OFFSET RESGROUP:CONTC + INC AL + INT int_command + MOV DX,OFFSET RESGROUP:DSKERR + INC AL + INT int_command + return + + +; +; This routine moves the environment to a newly allocated segment +; at the end of initialization +; + +ENDINIT: + push ds ;g save segments + push es ;g + push cs ;g get resident segment to DS + pop ds ;g + ASSUME DS:RESGROUP + mov cx,usedenv ;g get number of bytes to move + mov es,envirseg ;g get target environment segment + + ASSUME ES:NOTHING + mov DS:[PDB_environ],es ;g put new environment in my header ;AM067; + mov ds,oldenv ;g source environment segment ;AM067; + ASSUME DS:NOTHING ;AM067; + xor si,si ;g set up offsets to start of segments ;AM067; + xor di,di ;g ;AM067; + cld ;g make sure we move the right way! ;AM067; + rep movsb ;g move it ;AM067; + xor ax,ax ;g ;AM067; + stosb ;g make sure there are double 0 at end ;AM067; + + cmp resetenv,1 ;eg Do we need to setblock to env end? + jnz noreset ;eg no - we already did it + mov bx,envsiz ;eg get size of environment in paragraphs + push es ;eg save environment - just to make sure + mov ah,SETBLOCK ;eg + int int_command ;eg + pop es ;eg + +noreset: + mov InitFlag,FALSE ;AC042; Turn off init flag + pop es ;g + pop ds ;g + jmp lodcom ;g allocate transient + +CODERES ENDS + +; This TAIL segment is used to produce a PARA aligned label in the resident +; group which is the location where the transient segments will be loaded +; initial. + +TAIL SEGMENT PUBLIC PARA + ORG 0 + PUBLIC TranStart +TRANSTART LABEL WORD +TAIL ENDS + +; This TAIL segment is used to produce a PARA aligned label in the transient +; group which is the location where the exec segments will be loaded +; initial. + +TRANTAIL SEGMENT PUBLIC PARA + ORG 0 +EXECSTART LABEL WORD +TRANTAIL ENDS + + END diff --git a/v4.0/src/CMD/COMMAND/COMSEG.ASM b/v4.0/src/CMD/COMMAND/COMSEG.ASM new file mode 100644 index 0000000..81cfa30 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMSEG.ASM @@ -0,0 +1,43 @@ +; SCCSID = @(#)comseg.asm 1.1 85/05/14 +; SCCSID = @(#)comseg.asm 1.1 85/05/14 +; The following are all of the segments used in the load order + +CODERES SEGMENT PUBLIC BYTE ;AC000; resident code +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; resident data +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; AUTOEXEC batch segment +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ;AC000; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA ;AC000; Initialization code +INIT ENDS + +TAIL SEGMENT PUBLIC PARA ;AC000; End of Init - start of Transient +TAIL ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; Transient code +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; Transient data area +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; Transient modifiable data area +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA ;AC000; End of Transient +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COMSW.ASM b/v4.0/src/CMD/COMMAND/COMSW.ASM new file mode 100644 index 0000000..dbad747 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMSW.ASM @@ -0,0 +1,6 @@ +; SCCSID = @(#)comsw.asm 1.1 85/05/14 +; SCCSID = @(#)comsw.asm 1.1 85/05/14 + +include version.inc + + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPY.ASM b/v4.0/src/CMD/COMMAND/COPY.ASM new file mode 100644 index 0000000..37bb886 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPY.ASM @@ -0,0 +1,1001 @@ + page 80,132 +; SCCSID = @(#)copy.asm 1.1 85/05/14 +; SCCSID = @(#)copy.asm 1.1 85/05/14 +TITLE COMMAND COPY routines. + +; MODIFICATION HISTORY +; +; 11/01/83 EE Added a few lines at the end of SCANSRC2 to get multiple +; file concatenations (eg copy a.*+b.*+c.*) to work properly. +; 11/02/83 EE Commented out the code in CPARSE which added drive designators +; to tokens which begin with path characters so that PARSELINE +; will work correctly. +; 11/04/83 EE Commented out the code in CPARSE that considered paren's to be +; individual tokens. That distinction is no longer needed for +; FOR loop processing. +; 11/17/83 EE CPARSE upper case conversion is now flag dependent. Flag is +; 1 when Cparse is called from COPY. +; 11/17/83 EE Took out the comment chars around code described in 11/04/83 +; mod. It now is conditional on flag like previous mod. +; 11/21/83 NP Added printf +; 12/09/83 EE CPARSE changed to use CPYFLAG to determine when a colon should +; be added to a token. +; 05/30/84 MZ Initialize all copy variables. Fix confusion with destclosed +; NOTE: DestHand is the destination handle. There are two +; special values: -1 meaning destination was never opened and +; 0 which means that the destination has been openned and +; closed. +; 06/01/84 MZ Above reasoning totally specious. Returned things to normal +; 06/06/86 EG Change to fix problem of source switches /a and /b getting +; lost on large and multiple file (wildcard) copies. +; 06/09/86 EG Change to use xnametrans call to verify that source and +; destination are not equal. + + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN VERVAL:WORD + EXTRN RSRC_XA_SEG:WORD ;AN030; +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADCD_ptr:word + EXTRN COPIED_ptr:word + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN file_name_ptr:word + EXTRN INBDEV_ptr:word ;AC000; + EXTRN msg_disp_class:byte ;AN000; + EXTRN overwr_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN ALLSWITCH:WORD + EXTRN ARGC:BYTE + EXTRN ASCII:BYTE + EXTRN BINARY:BYTE + EXTRN BYTCNT:WORD + EXTRN CFLAG:BYTE + EXTRN comma:byte + EXTRN CONCAT:BYTE + EXTRN concat_xa:byte ;AN000; + EXTRN copy_num:word ;AC000; + EXTRN CPDATE:WORD + EXTRN CPTIME:WORD + EXTRN cpyflag:byte ;AC000; + EXTRN CURDRV:BYTE + EXTRN DESTBUF:BYTE + EXTRN DestClosed:BYTE + EXTRN DESTFCB:BYTE + EXTRN DESTFCB2:BYTE + EXTRN DESTHAND:WORD + EXTRN DESTINFO:BYTE + EXTRN DESTISDIR:BYTE + EXTRN DESTSIZ:BYTE + EXTRN DESTSWITCH:WORD + EXTRN DESTTAIL:WORD + EXTRN DESTVARS:BYTE + EXTRN DIRBUF:BYTE + EXTRN expand_star:byte + EXTRN FILECNT:WORD + EXTRN FIRSTDEST:BYTE + EXTRN FRSTSRCH:BYTE + EXTRN INEXACT:BYTE + EXTRN MELCOPY:BYTE + EXTRN MELSTART:WORD + EXTRN msg_flag:byte ;AN022; + EXTRN NOWRITE:BYTE + EXTRN NXTADD:WORD + EXTRN objcnt:byte + EXTRN one_char_val:byte ;AN000; + EXTRN parse_last:word ;AN018; + EXTRN PLUS:BYTE + EXTRN plus_comma:byte + EXTRN RDEOF:BYTE + EXTRN RESSEG:WORD + EXTRN SCANBUF:BYTE + EXTRN SDIRBUF:BYTE + EXTRN src_xa_size:word ;AN000; + EXTRN src_xa_seg:word ;AN000; + EXTRN SRCBUF:BYTE + EXTRN SRCHAND:WORD + EXTRN SRCINFO:BYTE + EXTRN SRCISDEV:BYTE + EXTRN SRCPT:WORD + EXTRN SRCSIZ:BYTE + EXTRN SRCTAIL:WORD + EXTRN SRCVARS:BYTE + EXTRN srcxname:byte + EXTRN STARTEL:WORD + EXTRN string_ptr_2:word + EXTRN TERMREAD:BYTE + EXTRN TPA:WORD + EXTRN USERDIR1:BYTE + EXTRN WRITTEN:WORD + EXTRN xa_cp_out:byte ;AN030; + EXTRN xa_list_attr:word ;AC030; +TRANSPACE ENDS + + +; ****************************************** +; COPY CODE +; + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN CERROR:NEAR + EXTRN COPERR:NEAR + EXTRN TCOMMAND:NEAR + + PUBLIC COPY + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + break Copy +assume ds:trangroup,es:trangroup + +COPY: +; First order of buisness is to find out about the destination +; +; initialize all internal variables +; + xor ax,ax + mov copy_num,ax + mov SrcPt,AX + mov SrcTail,AX + mov CFlag,AL + mov NxtAdd,AX + mov DestSwitch,AX + mov StartEl,AX + mov DestTail,AX + mov DestClosed,AL + mov DestSiz,AL + mov SrcSiz,AL + mov DestInfo,AL + mov SrcInfo,AL + mov InExact,AL + mov DestVars,AL + mov SrcVars,AL + mov UserDir1,AL + mov NoWrite,AL + mov RdEOF,AL + mov SrcHand,AX + mov CpDate,AX + mov CpTime,AX + mov xa_list_attr,ax ;AN030; initialize code page to none + mov SrcIsDev,AL + mov TermRead,AL + mov comma,al ;g + mov plus_comma,al ;g + mov msg_flag,al ;AN022; + mov [ALLSWITCH],AX ; no switches + mov [ARGC],al ; no arguments + mov [PLUS],al ; no concatenation + mov [BINARY],al ; Binary not specifically specified + mov [ASCII],al ; ASCII not specifically specified + mov [FILECNT],ax ; No files yet + mov [WRITTEN],ax ; Nothing written yet + mov [CONCAT],al ; No concatenation + mov [MELCOPY],al ; Not a Mel Hallerman copy + mov [concat_xa],al ;AN000; initialize flag for concatenation XA + mov MelStart,ax ; Not a Mel Hallerman copy + mov word ptr [SCANBUF],ax ; Init buffer + mov word ptr [DESTBUF],ax ; Init buffer + mov word ptr [SRCBUF],ax ; Init buffer + mov word ptr [SDIRBUF],ax ; Init buffer + mov word ptr [DIRBUF],ax ; Init buffer + mov word ptr [DESTFCB],ax ; Init buffer + mov objcnt,al ; Init command line object count + dec ax + mov DestHand,AX ; destination has never been opened + mov [FRSTSRCH],al ; First search call + mov [FIRSTDEST],al ; First time + mov [DESTISDIR],al ; Don't know about dest + mov src_xa_seg,ax ;AN000; initialize attribute segment to -1 + mov si,81H + mov bl,plus_chr ; include '+' as a delimiter + inc byte ptr [expand_star] ; want to include * expansion in cparse + mov cpyflag,1 ; Turn "CPARSE called from COPY flag" on + +DESTSCAN: + xor bp,bp ; no switches + mov di,offset trangroup:SCANBUF + mov parse_last,si ;AN018; save start of parsed string + invoke CPARSE + PUSHF ; save flags + inc objcnt + test bh,80H ; A '+' argument? + jz NOPLUS ; no + mov [PLUS],1 ; yes +NOPLUS: + test bh,1 ; Switch? + jz TESTP2 ; no + + test bp,SwitchV ;AN038; Verify requested? + jz not_slashv ;AN038; No - set the switch + test [allswitch],SwitchV ;AN038; Verify already entered? + jz not_slashv ;AN038; No - set the switch +;AD018; or [allswitch],FBadSwitch ;AN038; Set up bad switch + or BP,FBadSwitch ;AN018; Set up bad switch + +not_slashv: ;AN038; + or [DESTSWITCH],BP ; Yes, assume destination + or [ALLSWITCH],BP ; keep tabs on all switches + + test BP,NOT SwitchCopy ;AN018; Bad switch? + jz NOT_BAD_SWITCH ;AN018; Switches are okay + popf ;AN018; fix up stack + mov ax,BadSwt_ptr ;AN018; get "Invalid switch" message number + invoke Setup_parse_error_msg ;AN018; setup to print the message + jmp CERROR ;AC018; exit + +NOT_BAD_SWITCH: ;AN018; switch okay + POPF ; get flags back + jc CHECKDONE ; Hit CR? + jmp short DESTSCAN + +TESTP2: + POPF ; get flags back + jc CHECKDONE ; Hit CR? + test bh,80H ; Plus? + jnz GOTPLUS ; Yes, not a separate arg + inc [ARGC] ; found a real arg +GOTPLUS: + push SI + mov ax,[STARTEL] + mov SI,offset trangroup:SCANBUF ; Adjust to copy + sub ax,SI + mov DI,offset trangroup:DESTBUF + add ax,DI + mov [DESTTAIL],AX + mov [DESTSIZ],cl ; Save its size + inc cx ; Include the nul + rep movsb ; Save potential destination + mov [DESTINFO],bh ; Save info about it + mov [DESTSWITCH],0 ; reset switches + pop SI + jmp DESTSCAN ;AC018; keep going + +CHECKDONE: + cmp plus,1 ; If a statement like "copy file+" is + jnz cdcont ; entered, complain about it. + cmp argc,1 + jnz cdcont + cmp objcnt,2 + jnz cdcont + mov dx,offset trangroup:overwr_ptr + jmp coperr +cdcont: + mov al,[PLUS] + mov [CONCAT],al ; PLUS -> Concatination + shl al,1 + shl al,1 + mov [INEXACT],al ; CONCAT -> inexact copy + mov al,[ARGC] + or al,al ; Good number of args? + jnz TRY_TOO_MANY ;AC000; there are args, see if too many + MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,LessArgs_ptr ;AN000; get "Required parameters missing" message number + jmp short cerror_parsej ;AN000; exit + +TRY_TOO_MANY: + cmp al,2 + jbe ACOUNTOK + MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,MoreArgs_ptr ;AN000; get "Too many parameters" message number + +CERROR_PARSEJ: + mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class +CERROR4J: + jmp CERROR ; no, too many + +ACOUNTOK: + mov bp,offset trangroup:DESTVARS + cmp al,1 + jnz GOT2ARGS + mov al,[CURDRV] ; Dest is default drive:*.* + add al,capital_A + mov ah,':' + mov [bp.SIZ],2 + mov di,offset trangroup:DESTBUF + stosw + mov [DESTSWITCH],0 ; no switches on dest + mov [bp.INFO],2 ; Flag dest is ambig + mov [bp.ISDIR],0 ; Know destination specs file + invoke SETSTARS +GOT2ARGS: + cmp [bp.SIZ],2 + jnz NOTSHORTDEST + mov al,':' + cmp [DESTBUF+1],al + jnz NOTSHORTDEST ; Two char file name + or [bp.INFO],2 ; Know dest is d: + mov di,offset trangroup:DESTBUF + 2 + mov [bp.ISDIR],0 ; Know destination specs file + invoke SETSTARS +NOTSHORTDEST: + mov di,[bp.TTAIL] + cmp byte ptr [DI],0 + jnz CHKSWTCHES + mov dx,offset trangroup:BADCD_ptr + mov al,':' + cmp byte ptr [DI-2],al + jnz CERROR4J ; Trailing '/' error + mov [bp.ISDIR],2 ; Know destination is d:/ + or [bp.INFO],6 + invoke SETSTARS +CHKSWTCHES: +;AD018; mov ax,[ALLSWITCH] +;AD018; test ax,NOT SwitchCopy +;AD018; jz NOT_BAD_SWITCH ;AN000; Switches are okay +;AD018; MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer +;AD018; mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number +;AD018; jmp short CERROR_PARSEJ ;AC000; Switch specified which is not known + +; Now know most of the information needed about the destination + +;AD018; NOT_BAD_SWITCH: +if not ibmcopyright + mov ax, [allswitch] ; Which switches were requested? Hmmm? +endif + TEST AX,SwitchV ; Verify requested? + JZ NOVERIF ; No + MOV AH,GET_VERIFY_ON_WRITE + INT int_command ; Get current setting + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + XOR AH,AH + MOV [VERVAL],AX ; Save current setting + POP DS +ASSUME DS:TRANGROUP + MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 ; Set verify + INT int_command +NOVERIF: + xor bp,bp ; no switches + mov si,81H + mov bl,plus_chr ; include '+' as a delimiter +SCANFSRC: + mov di,offset trangroup:SCANBUF + invoke CPARSE ; Parse first source name + test bh,1 ; Switch? + jnz SCANFSRC ; Yes, try again + or [DESTSWITCH],bp ; Include copy wide switches on dest + test bp,SwitchB + jnz NOSETCASC ; Binary explicit + cmp [CONCAT],0 + JZ NOSETCASC ; Not Concat + mov [ASCII],SwitchA ; Concat -> ASCII copy if no B switch + mov [concat_xa],do_xa ;AN000; set up to do XA only on first file +NOSETCASC: + call source_set + call FRSTSRC + jmp FIRSTENT + +PUBLIC EndCopy +ENDCOPY: + CALL CLOSEDEST +ENDCOPY2: + call deallocate_src_xa ;AN030; deallocate xa segment + invoke free_tpa ;AN000; Make sure work area + invoke alloc_tpa ;AN000; is reset properly + MOV DX,OFFSET TRANGROUP:COPIED_ptr + MOV SI,[FILECNT] + mov copy_num,si + invoke std_printf + JMP TCOMMAND ; Stack could be messed up + +SRCNONEXIST: + cmp [CONCAT],0 + jnz NEXTSRC ; If in concat mode, ignore error + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block + mov string_ptr_2,offset trangroup:srcbuf ;AC046; get address of failed string + mov Extend_buf_sub,one_subst ;AC046; put number of subst in control block + jmp COPERR + +SOURCEPROC: + call source_set + cmp [CONCAT],0 + jnz LEAVECFLAG ; Leave CFLAG if concatination +FRSTSRC: + xor ax,ax + mov [CFLAG],al ; Flag destination not created + mov [NXTADD],ax ; Zero out buffer + mov DestClosed,AL +LEAVECFLAG: + mov [SRCPT],SI ; remember where we are + mov di,offset trangroup:USERDIR1 + mov bp,offset trangroup:SRCVARS + invoke BUILDPATH ; Figure out everything about the source + mov si,[SRCTAIL] ; Create the search FCB + return + +NEXTSRC: + cmp [PLUS],0 + jnz MORECP +ENDCOPYJ2: + jmp ENDCOPY ; Done +MORECP: + xor bp,bp ; no switches + mov si,[SRCPT] + mov bl,plus_chr ; include '+' as a delimiter +SCANSRC: + mov di,offset trangroup:SCANBUF + invoke CPARSE ; Parse first source name + JC EndCopyJ2 ; if error, then end (trailing + case) + test bh,80H + jz ENDCOPYJ2 ; If no '+' we're done + test bh,1 ; Switch? + jnz SCANSRC ; Yes, try again + call SOURCEPROC + cmp comma,1 ;g was +,, found last time? + jnz nostamp ;g no - try for a file + mov plus_comma,1 ;g yes - set flag + jmp srcnonexist ;g we know we won't find it +nostamp: ;g + mov plus_comma,0 ;g reset +,, flag +FIRSTENT: + mov di,FCB + mov ax,PARSE_FILE_DESCRIPTOR SHL 8 + INT int_command + CMP BYTE PTR [SI],0 ; parse everything? + JNZ SrchDone ; no, error, simulate no more search + mov ax,word ptr [SRCBUF] ; Get drive + cmp ah,':' + jz DRVSPEC1 + mov al,'@' +DRVSPEC1: + or al,20h + sub al,60h + mov ds:[FCB],al + mov ah,DIR_SEARCH_FIRST + call SEARCH +SrchDone: + pushf ; Save result of search + invoke RESTUDIR1 ; Restore users dir + popf + jz NEXTAMBIG0 + jmp SRCNONEXIST ; Failed +NEXTAMBIG0: + xor al,al + xchg al,[FRSTSRCH] + or al,al + jz NEXTAMBIG +SETNMEL: + mov cx,12 + mov di,OFFSET TRANGROUP:SDIRBUF + mov si,OFFSET TRANGROUP:DIRBUF + rep movsb ; Save very first source name +NEXTAMBIG: + xor al,al + mov [NOWRITE],al ; Turn off NOWRITE + mov di,[SRCTAIL] + mov si,offset trangroup:DIRBUF + 1 + invoke FCB_TO_ASCZ ; SRCBUF has complete name +MELDO: + cmp [CONCAT],0 + jnz SHOWCPNAM ; Show name if concat + test [SRCINFO],2 ; Show name if multi + jz DOREAD +SHOWCPNAM: + mov dx,offset trangroup:file_name_ptr + invoke std_printf + invoke CRLF2 +DOREAD: + call DOCOPY + cmp [CONCAT],0 + jnz NODCLOSE ; If concat, do not close + call CLOSEDEST ; else close current destination + jc NODCLOSE ; Concat flag got set, close didn't really happen + mov [CFLAG],0 ; Flag destination not created +NODCLOSE: + cmp [CONCAT],0 ; Check CONCAT again + jz NOFLUSH + invoke FLSHFIL ; Flush output between source files on + ; CONCAT so LOSTERR stuff works + ; correctly + TEST [MELCOPY],0FFH + jz NOFLUSH + jmp SHORT DOMELCOPY + +NOFLUSH: + call SEARCHNEXT ; Try next match + jnz NEXTSRCJ ; Finished with this source spec + mov [DESTCLOSED],0 ; Not created or concat ->... + jmp NEXTAMBIG ; Do next ambig + +DOMELCOPY: + cmp [MELCOPY],0FFH + jz CONTMEL + mov SI,[SRCPT] + mov [MELSTART],si + mov [MELCOPY],0FFH +CONTMEL: + xor BP,BP + mov si,[SRCPT] + mov bl,plus_chr +SCANSRC2: + mov di,OFFSET TRANGROUP:SCANBUF + invoke CPARSE + test bh,80H + jz NEXTMEL ; Go back to start + test bh,1 ; Switch ? + jnz SCANSRC2 ; Yes + call SOURCEPROC + invoke RESTUDIR1 + mov di,OFFSET TRANGROUP:DESTFCB2 + mov ax,PARSE_FILE_DESCRIPTOR SHL 8 + INT int_command + mov bx,OFFSET TRANGROUP:SDIRBUF + 1 + mov si,OFFSET TRANGROUP:DESTFCB2 + 1 + mov di,[SRCTAIL] + invoke BUILDNAME + cmp [CONCAT],0 ; Are we concatenating? + jz meldoj ; No, continue. +; +; Yes, turn off nowrite because this part of the code is only reached after +; the first file has been dealt with. +; + mov [NOWRITE],0 +meldoj: + jmp MELDO + +NEXTSRCJ: + jmp NEXTSRC + +NEXTMEL: + call CLOSEDEST + xor ax,ax + mov [CFLAG],al + mov [NXTADD],ax + mov [DESTCLOSED],al + mov si,[MELSTART] + mov [SRCPT],si + call SEARCHNEXT + jz SETNMELJ + jmp ENDCOPY2 +SETNMELJ: + jmp SETNMEL + +SEARCHNEXT: + MOV AH,DIR_SEARCH_NEXT + TEST [SRCINFO],2 + JNZ SEARCH ; Do search-next if ambig + OR AH,AH ; Reset zero flag + return +SEARCH: + PUSH AX + MOV AH,SET_DMA + MOV DX,OFFSET TRANGROUP:DIRBUF + INT int_command ; Put result of search in DIRBUF + POP AX ; Restore search first/next command + MOV DX,FCB + INT int_command ; Do the search + OR AL,AL + return + +DOCOPY: + mov si,offset trangroup:SRCBUF ;g do name translate of source + mov di,offset trangroup:SRCXNAME ;g save for name comparison + mov ah,xnametrans ;g + int int_command ;g + + mov [RDEOF],0 ; No EOF yet + + MOV AX,EXTOPEN SHL 8 ;AC000; open the file + mov bx,read_open_mode ;AN000; get open mode for COPY + xor cx,cx ;AN000; no special files + mov dx,read_open_flag ;AN000; set up open flags + mov di,-1 ;AN030; no parameter list + INT int_command + + jnc OpenOK +; +; Bogosity: IBM wants us to issue Access denied in this case. THey asked +; for it... +; + jmp error_on_source ;AC022; clean up and exit + +OpenOK: + mov bx,ax ; Save handle + mov [SRCHAND],bx ; Save handle + mov ax,(FILE_TIMES SHL 8) + INT int_command + jc src_cp_error ;AN022; If error, exit + mov [CPDATE],dx ; Save DATE + mov [CPTIME],cx ; Save TIME + + mov cx,xa_list_attr ;AN000; get old code page in cx + push cx ;AN000; save old attribute + mov xa_list_attr,0 ;AN000; initialize code page + + mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attribute size + mov si,-1 ;AN030; no querylist + xor cx,cx ;AN030; indicate we want size + int int_command ;AC000; + jc src_cp_error ;AN022; If error, exit + mov src_xa_size,cx ;AN000; save size + cmp cx,0 ;AN000; are there any? + pop cx ;AN000; get old attribute + jz no_cp_get ;AN030; no - don't get attributes + + push cx ;AN030; save old code page + invoke get_file_code_page_tag ;AN000; get file's code page + pop cx ;AN030 retrieve old code page + jnc no_cp_get ;AN000; no error - continue +src_cp_error: ;AN022; + jmp error_on_source ;AC022; and exit + +no_cp_get: + cmp [concat],0 ;AN000; are we doing concatenation + jz get_src_xa ;AN000; no get source extended attrib + cmp [concat_xa],do_xa ;AN000; is this the first file? + jz get_src_xa ;AN000; yes - get extended attributes + cmp cx,xa_list_attr ;AN000; no - see if code pages match + jz no_copy_xa_jmp ;AN000; code pages match - continue + mov xa_list_attr,inv_cp_tag ;AN000; set invalid code page tag +no_copy_xa_jmp: ;AC022; + jmp no_copy_xa ;AN000; don't get extended attributes + +get_src_xa: + call deallocate_src_xa ;AN030; deallocate any existing XA segment + cmp src_xa_size,0 ;AN000; are there any extended attributes? + jz no_copy_xa_jmp ;AC022; nothing there - don't allocate memory + push bx ;AN000; save handle + invoke free_tpa ;AN000; need to make free memory, first + mov bx,src_xa_size ;AN000; get bytes (size of XA) into bx + mov cl,4 ;AN000; divide bytes by 16 to convert + shr bx,cl ;AN000; to paragraphs + inc bx ;AN000; round up + mov ax,(alloc SHL 8) ;AN000; allocate memory for XA + int int_command ;AN000; + pushf ;AN000; save flags + mov [src_xa_seg], AX ;AN000; save new segment + push ds ;AN030; get resident segment + mov ds,[resseg] ;AN030; and save copy of xa + assume ds:resgroup ;AN030; segment in resident + mov [rsrc_xa_seg],ax ;AN030; in case user breaks + pop ds ;AN030; out or has critical + assume ds:trangroup ;AN030; error + invoke alloc_tpa ;AN000; reallocate the work area + popf ;AN000; restore flags + pop bx ;AN000; restore handle + jnc Alloc_for_xa_okay ;AN000; no carry - everything okay + call closesrc ;AN000; close the source file + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block + jmp cerror ;AN000; exit + +Alloc_for_xa_okay: + + mov ax,(file_times SHL 8)+get_XA ;AN000; get extended attributes + push es ;AN000; save es + mov es,[src_xa_seg] ;AN000; get segment for XA list + xor di,di ;AN000; offset of return list + mov si,-1 ;AN030; get all attributes + mov cx,[src_xa_size] ;AN000; get size of list + int int_command ;AN000; get all the attributes + pop es ;AN000; restore es + jnc no_copy_xa ;AC022; no error - continue + +error_on_source: ;AN022; we have a BAD error + invoke set_ext_error_msg ;AN022; set up the error message + mov string_ptr_2,offset trangroup:srcbuf ;AN022; get address of failed string + mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block + invoke std_Eprintf ;AN022; print it + cmp [srchand],0 ;AN022; did we open the file? + jz no_close_src ;AN022; no - don't close + call closesrc ;AN022; clean up +no_close_src: ;AN022; + cmp [cflag],0 ;AN022; was destination created? + jz endcopyj3 ;AN022; no - just cleanup and exit + jmp endcopy ;AN022; clean up concatenation and exit +endcopyj3: ;AN022; + jmp endcopy2 ;AN022; +no_copy_xa: + mov bx,[srchand] ;AN022; get handle back + mov ax,(IOCTL SHL 8) + INT int_command ; Get device stuff + and dl,devid_ISDEV + mov [SRCISDEV],dl ; Set source info + jz COPYLP ; Source not a device + cmp [BINARY],0 + jz COPYLP ; ASCII device OK + mov dx,offset trangroup:INBDEV_ptr ; Cannot do binary input + jmp COPERR + +COPYLP: + mov bx,[SRCHAND] + mov cx,[BYTCNT] + mov dx,[NXTADD] + sub cx,dx ; Compute available space + jnz GOTROOM + invoke FLSHFIL + CMP [TERMREAD],0 + JNZ CLOSESRC ; Give up + mov cx,[BYTCNT] +GOTROOM: + push ds + mov ds,[TPA] +ASSUME DS:NOTHING + mov ah,READ + INT int_command + pop ds +ASSUME DS:TRANGROUP + jc error_on_source ;AC022; Give up if error + mov cx,ax ; Get count + jcxz CLOSESRC ; No more to read + cmp [SRCISDEV],0 + jnz NOTESTA ; Is a device, ASCII mode + cmp [ASCII],0 + jz BINREAD +NOTESTA: + MOV DX,CX + MOV DI,[NXTADD] + MOV AL,1AH + PUSH ES + MOV ES,[TPA] + REPNE SCASB ; Scan for EOF + POP ES + JNZ USEALL + INC [RDEOF] + INC CX +USEALL: + SUB DX,CX + MOV CX,DX +BINREAD: + ADD CX,[NXTADD] + MOV [NXTADD],CX + CMP CX,[BYTCNT] ; Is buffer full? + JB TESTDEV ; If not, we may have found EOF + invoke FLSHFIL + CMP [TERMREAD],0 + JNZ CLOSESRC ; Give up + JMP SHORT COPYLP + +TESTDEV: + cmp [SRCISDEV],0 + JZ CLOSESRC ; If file then EOF + CMP [RDEOF],0 + JZ COPYLP ; On device, go till ^Z +CLOSESRC: + mov bx,[SRCHAND] + mov ah,CLOSE + INT int_command + return + +; +; We are called to close the destination. We need to note whether or not +; there is any internal data left to be flushed out. +; +CLOSEDEST: + cmp [DESTCLOSED],0 + retnz ; Don't double close + MOV AL,BYTE PTR [DESTSWITCH] + invoke SETASC ; Check for B or A switch on destination + JZ BINCLOS + MOV BX,[NXTADD] + CMP BX,[BYTCNT] ; Is memory full? + JNZ PUTZ + invoke TRYFLUSH ; Make room for one lousy byte + jz NOCONC +CONCHNG: ; Concat flag changed on us + stc + return +NOCONC: + XOR BX,BX +PUTZ: + PUSH DS + MOV DS,[TPA] + MOV WORD PTR [BX],1AH ; Add End-of-file mark (Ctrl-Z) + POP DS + INC [NXTADD] + MOV [NOWRITE],0 ; Make sure our ^Z gets written + MOV AX,[WRITTEN] + ADD AX,[NXTADD] + JC BINCLOS ; > 1 + CMP AX,1 + JZ FORGETITJ ; WRITTEN = 0 NXTADD = 1 (the ^Z) +BINCLOS: + invoke TRYFLUSH + jnz CONCHNG + cmp [WRITTEN],0 +ForgetItJ: + jnz no_forget ;AC000; Wrote something + jmp FORGETIT ;AC000; Never wrote nothing +no_forget: + MOV BX,[DESTHAND] + MOV CX,[CPTIME] + MOV DX,[CPDATE] + CMP [INEXACT],0 ; Copy not exact? + JZ DODCLOSE ; If no, copy date & time + MOV AH,GET_TIME + INT int_command + SHL CL,1 + SHL CL,1 ; Left justify min in CL + SHL CX,1 + SHL CX,1 + SHL CX,1 ; hours to high 5 bits, min to 5-10 + SHR DH,1 ; Divide seconds by 2 (now 5 bits) + OR CL,DH ; And stick into low 5 bits of CX + PUSH CX ; Save packed time + MOV AH,GET_DATE + INT int_command + SUB CX,1980 + XCHG CH,CL + SHL CX,1 ; Year to high 7 bits + SHL DH,1 ; Month to high 3 bits + SHL DH,1 + SHL DH,1 + SHL DH,1 + SHL DH,1 ; Most sig bit of month in carry + ADC CH,0 ; Put that bit next to year + OR DL,DH ; Or low three of month into day + MOV DH,CH ; Get year and high bit of month + POP CX ; Get time back +DODCLOSE: + CMP BX,0 + JLE CloseDone + MOV AX,(FILE_TIMES SHL 8) OR 1 + INT int_command ; Set date and time + jc xa_cleanup_err ;AN022; handle error + + mov ax,(file_times SHL 8)+set_XA ;AN000; set code page + mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list + int int_command ;AN000; + jc xa_cleanup_err ;AN030; exit if error + +; +; See if the destination has *anything* in it. If not, just close and delete +; it. +; +no_xa_cleanup_err: + mov ax,(lseek shl 8) + 2 ; seek to EOF + xor dx,dx + mov cx,dx + int 21h +; +; DX:AX is file size +; + or dx,ax + pushf + mov ax,(IOCTL SHL 8) + 0 ; get the destination attributes + int 21h + push dx ; save them away + MOV AH,CLOSE + INT int_command + pop dx + jnc close_cont ;AN022; handle error on close + popf ;AN022; get the flags back +xa_cleanup_err: ;AN022; + call cleanuperr ;AN022; attempt to delete the target + call DestDelete ;AN022; attempt to delete the target + jmp short fileclosed ;AN022; close the file +close_cont: ;AN022; no error - continue + popf + jnz CloseDone + test dx,80h ; is the destination a device? + jnz CloseDone ; yes, copy succeeded + call DestDelete + jmp short FileClosed +CloseDone: + INC [FILECNT] +FileClosed: + INC [DESTCLOSED] +RET50: + CLC + return + + +FORGETIT: + MOV BX,[DESTHAND] + CALL DODCLOSE ; Close the dest + call DestDelete + MOV [FILECNT],0 ; No files transferred + JMP RET50 + +DestDelete: + MOV DX,OFFSET TRANGROUP:DESTBUF + MOV AH,UNLINK + INT int_command ; And delete it + return + +source_set proc near + + push SI + mov ax,[STARTEL] + mov SI,offset trangroup:SCANBUF ; Adjust to copy + sub ax,SI + mov DI,offset trangroup:SRCBUF + add ax,DI + mov [SRCTAIL],AX + mov [SRCSIZ],cl ; Save its size + inc cx ; Include the nul + rep movsb ; Save this source + mov [SRCINFO],bh ; Save info about it + pop SI + mov ax,bp ; Switches so far + invoke SETASC ; Set A,B switches accordingly + invoke SWITCH ; Get any more switches on this arg + invoke SETASC ; Set + return + +source_set endp + + +;**************************************************************** +;* +;* ROUTINE: Cleanuperr +;* +;* FUNCTION: Issues extended error message for destination +;* if not alreay issued +;* +;* INPUT: return from INT 21 +;* +;* OUTPUT: none +;* +;**************************************************************** + +cleanuperr proc near ;AN022; + + cmp msg_flag,0 ;AN022; have we already issued a message? + jnz cleanuperr_cont ;AN022; yes - don't issue duplicate error + invoke set_ext_error_msg ;AN022; set up error message + mov string_ptr_2,offset trangroup:destbuf ;AN022; get address of failed string + mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block + invoke std_eprintf ;AN022; issue the error message +cleanuperr_cont: ;AN022; + + ret ;AN022; return to caller +cleanuperr endp ;AN022; + +;**************************************************************** +;* +;* ROUTINE: Deallocate_Src_XA +;* +;* FUNCTION: Deallocates source extended attribute segment +;* and resets both resident and transient variables. +;* +;* +;* INPUT: none +;* +;* OUTPUT: none +;* +;**************************************************************** + +Deallocate_Src_XA proc near ;AN030; + + cmp [src_xa_seg],no_xa_seg ;AN030; has any XA segment been allocated + jz no_src_xa ;AN030; no - continue + push es ;AN030; + mov es,src_xa_seg ;AN030; yes - free it + mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call + int int_command ;AN030; + pop es ;AN030; + mov [src_xa_seg],no_xa_seg ;AN030; reset to no segment + push ds ;AN030; reinitialize resident + mov ds,[resseg] ;AN030; copy of xa segment + assume ds:resgroup ;AN030; + mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment + pop ds ;AN030; + assume ds:trangroup ;AN030; +no_src_xa: ;AN030; + + ret ;AN030; return to caller +Deallocate_Src_XA endp ;AN030; + + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPYPR1.ASM b/v4.0/src/CMD/COMMAND/COPYPR1.ASM new file mode 100644 index 0000000..e727910 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPYPR1.ASM @@ -0,0 +1,276 @@ + page 80,132 +; SCCSID = @(#)copypr1.asm 1.1 85/05/14 +; SCCSID = @(#)copypr1.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC +; INCLUDE DEVSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN DEVWMES_ptr:word + EXTRN ext_open_parms:byte ;AN000; + EXTRN ext_open_seg:word ;AN000; + EXTRN ext_open_off:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN LOSTERR_ptr:word + EXTRN NOSPACE_ptr:word + EXTRN OVERWR_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN ASCII:BYTE + EXTRN BINARY:BYTE + EXTRN CFLAG:BYTE + EXTRN CONCAT:BYTE + EXTRN concat_xa:byte ;AC000; + EXTRN DESTBUF:BYTE + EXTRN DESTCLOSED:BYTE + EXTRN DESTHAND:WORD + EXTRN DESTISDEV:BYTE + EXTRN DESTSWITCH:WORD + EXTRN INEXACT:BYTE + EXTRN NOWRITE:BYTE + EXTRN NXTADD:WORD + EXTRN plus_comma:byte ;AN000; + EXTRN RDEOF:BYTE + EXTRN src_xa_seg:word ;AN000; + EXTRN SRCISDEV:BYTE + EXTRN string_ptr_2:word ;AN000; + EXTRN TERMREAD:BYTE + EXTRN TPA:WORD + EXTRN WRITTEN:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN ENDCOPY:NEAR + + PUBLIC FLSHFIL + PUBLIC TRYFLUSH + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +TRYFLUSH: + mov al,[CONCAT] + push ax + call FLSHFIL + pop ax + cmp al,[CONCAT] + return + +FLSHFIL: +; +; Write out any data remaining in memory. +; Inputs: +; [NXTADD] = No. of bytes to write +; [CFLAG] <> 0 if file has been created +; Outputs: +; [NXTADD] = 0 +; + MOV [TERMREAD],0 + cmp [CFLAG],0 + JZ NOTEXISTS + JMP EXISTS + +NOTEXISTS: + invoke BUILDDEST ; Find out all about the destination + invoke COMPNAME ; Source and dest. the same? + JNZ PROCDEST ; If not, go ahead + CMP [SRCISDEV],0 + JNZ PROCDEST ; Same name on device OK + CMP [CONCAT],0 ; Concatenation? + MOV DX,OFFSET TRANGROUP:OVERWR_ptr + JNZ NO_CONCAT_ERR ;AC000; If not, overwrite error + JMP COPERR ;AC000; + +NO_CONCAT_ERR: ;AC000; + MOV [NOWRITE],1 ; Flag not writting (just seeking) + +PROCDEST: + MOV AX,EXTOPEN SHL 8 ;AC000; open the file + mov si,offset trangroup:destbuf ;AN030; get file name + mov di,-1 ;AN030; indicate no parameters + cmp src_xa_seg,no_xa_seg ;AN030; is there an XA segment? + jz cont_no_xa ;AN030; no - no parameters + mov di,offset trangroup:Ext_open_parms ;AN030; get parameters + mov bx,src_xa_seg ;AN030; get extended attribute segment + mov ext_open_seg,bx ;AN030; put it in parameter list + mov ext_open_off,0 ;AN030; offset is 0 + +cont_no_xa: ;AN030; + mov bx,write_open_mode ;AN000; get open mode for COPY + xor cx,cx ;AN000; no special files + mov dx,write_open_flag ;AN000; set up open flags + + CMP [NOWRITE],0 + JNZ DODESTOPEN ; Don't actually create if NOWRITE set + mov dx,creat_open_flag ;AC000; set up create flags + +DODESTOPEN: + INT int_command +; +; We assume that the error is normal. TriageError will correct the DX value +; appropriately. +; + JNC dest_open_okay ;AC030; + +xa_set_error: ;AN030; error occurred on XA + invoke set_ext_error_msg ;AN030; get extended error + +ext_err_set: ;AN030; + mov string_ptr_2,offset trangroup:destbuf ;AN000; get address of failed string + mov Extend_buf_sub,one_subst ;AN030; put number of subst in control block + +COPERRJ2: ;AN030; + jmp COPERR ;AN030; go issue message + +dest_open_okay: ;AC030 + mov [DESTHAND],ax ; Save handle + mov [CFLAG],1 ; Destination now exists + mov bx,ax + mov cx,bx ;AN030; get handle into CX + invoke set_file_code_page ;AN030; set the code page for the target + jc ext_err_set ;AN030; if no error, continue + + mov [concat_xa],0 ;AN000; set first file flag off + mov ax,(IOCTL SHL 8) + INT int_command ; Get device stuff + mov [DESTISDEV],dl ; Set dest info + test dl,devid_ISDEV + jz exists ;AC030; Dest a device + + mov al,BYTE PTR [DESTSWITCH] + AND AL,SwitchA+SwitchB + JNZ TESTBOTH + MOV AL,[ASCII] ; Neither set, use current setting + OR AL,[BINARY] + JZ EXSETA ; Neither set, default to ASCII + +TESTBOTH: + JPE EXISTS ; Both are set, ignore + test AL,SwitchB + jz EXISTS ; Leave in cooked mode + mov ax,(IOCTL SHL 8) OR 1 + xor dh,dh + or dl,devid_RAW + mov [DESTISDEV],dl ; New value + INT int_command ; Set device to RAW mode + jmp short EXISTS + +COPERRJ: + jmp SHORT COPERR + +EXSETA: +; +; What we read in may have been in binary mode, flag zapped write OK +; + mov [ASCII],SwitchA ; Set ASCII mode + or [INEXACT],SwitchA ; ASCII -> INEXACT + +EXISTS: + cmp [NOWRITE],0 + jnz NOCHECKING ; If nowrite don't bother with name check + cmp plus_comma,1 ;g don't check if just doing +,, + jz NOCHECKING ;g + invoke COMPNAME ; Source and dest. the same? + JNZ NOCHECKING ; If not, go ahead + CMP [SRCISDEV],0 + JNZ NOCHECKING ; Same name on device OK +; +; At this point we know in append (would have gotten overwrite error on first +; destination create otherwise), and user trying to specify destination which +; has been scribbled already (if dest had been named first, NOWRITE would +; be set). +; + MOV DX,OFFSET TRANGROUP:LOSTERR_ptr ; Tell him he's not going to get it + invoke std_Eprintf ;AC022; + MOV [NXTADD],0 ; Set return + INC [TERMREAD] ; Tell Read to give up + +RET60: + return + +NOCHECKING: + mov bx,[DESTHAND] ; Get handle + XOR CX,CX + XCHG CX,[NXTADD] + JCXZ RET60 ; If Nothing to write, forget it + INC [WRITTEN] ; Flag that we wrote something + CMP [NOWRITE],0 ; If NOWRITE set, just seek CX bytes + JNZ SEEKEND + XOR DX,DX + PUSH DS + MOV DS,[TPA] +ASSUME DS:NOTHING + MOV AH,WRITE + INT int_command + POP DS +ASSUME DS:TRANGROUP + MOV DX,OFFSET TRANGROUP:NOSPACE_ptr + JC xa_set_error_Jmp ;AC022; Failure + sub cx,ax + retz ; Wrote all supposed to + test [DESTISDEV],devid_ISDEV + jz COPERR ; Is a file, error + test [DESTISDEV],devid_RAW + jnz DEVWRTERR ; Is a raw device, error + cmp [INEXACT],0 + retnz ; INEXACT so OK + dec cx + retz ; Wrote one byte less (the ^Z) + +DEVWRTERR: + MOV DX,OFFSET TRANGROUP:DEVWMES_ptr + +PUBLIC COPERR +COPERR: + INVOKE std_Eprintf ;AC022; + +COPERRP: + inc [DESTCLOSED] + cmp [CFLAG],0 + jz ENDCOPYJ ; Never actually got it open + MOV bx,[DESTHAND] + CMP BX,0 + JLE NoClose + MOV AH,CLOSE ; Close the file + INT int_command + +NoClose: + MOV DX,OFFSET TRANGROUP:DESTBUF + MOV AH,UNLINK + INT int_command ; And delete it + MOV [CFLAG],0 + +ENDCOPYJ: + JMP ENDCOPY + +XA_SET_ERROR_JMP: ;AN022; Go set up error message + jmp xa_set_error ;AN022; + +SEEKEND: + xor dx,dx ; Zero high half of offset + xchg dx,cx ; cx:dx is seek location + mov ax,(LSEEK SHL 8) OR 1 + INT int_command ; Seek ahead in the file + cmp [RDEOF],0 + retz +; +; If a ^Z has been read we must set the file size to the current +; file pointer location +; + MOV AH,WRITE + INT int_command ; CX is zero, truncates file + jc xa_set_error_Jmp ;AC022; Failure + return + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPYPR2.ASM b/v4.0/src/CMD/COMMAND/COPYPR2.ASM new file mode 100644 index 0000000..2913cab --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPYPR2.ASM @@ -0,0 +1,450 @@ + page 80,132 +; SCCSID = @(#)copypr2.asm 1.1 85/05/14 +; SCCSID = @(#)copypr2.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN FulDir_ptr:word ;AN052; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN ASCII:BYTE + EXTRN BINARY:BYTE + EXTRN CONCAT:BYTE + EXTRN DESTBUF:BYTE + EXTRN DESTFCB:BYTE + EXTRN DESTINFO:BYTE + EXTRN DESTISDIR:BYTE + EXTRN DESTTAIL:WORD + EXTRN DESTVARS:BYTE + EXTRN DIRBUF:BYTE + EXTRN DIRCHAR:BYTE + EXTRN FIRSTDEST:BYTE + EXTRN INEXACT:BYTE + EXTRN MELCOPY:BYTE + EXTRN NXTADD:WORD + EXTRN PLUS:BYTE + EXTRN SDIRBUF:BYTE + EXTRN SRCINFO:BYTE + EXTRN srcxname:byte + EXTRN TPA:WORD + EXTRN trgxname:byte + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN BADPATH_ERR:NEAR ;AN022; + EXTRN COPERR:NEAR ;AN052; + EXTRN EXTEND_SETUP:NEAR ;AN022; + + PUBLIC BUILDPATH + PUBLIC SETSTARS + PUBLIC SETASC + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +SETASC: +; +; Given switch vector in AX, +; Set ASCII switch if A is set +; Clear ASCII switch if B is set +; BINARY set if B specified +; Leave ASCII unchanged if neither or both are set +; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set +; + AND AL,SwitchA+SwitchB + JPE LOADSW ; PE means both or neither are set + PUSH AX + AND AL,SwitchB + MOV [BINARY],AL + POP AX + AND AL,SwitchA + MOV [ASCII],AL + OR [INEXACT],AL + +LOADSW: + MOV AL,[ASCII] + OR AL,AL + return + +public builddest +BUILDDEST: + cmp [DESTISDIR],-1 + jnz KNOWABOUTDEST ; Already done the figuring + MOV DI,OFFSET TRANGROUP:USERDIR1 + mov bp,offset trangroup:DESTVARS + call BUILDPATH + invoke RESTUDIR1 + +; Now know all about the destination + +KNOWABOUTDEST: + xor al,al + xchg al,[FIRSTDEST] + or al,al + jnz FIRSTDST + jmp NOTFIRSTDEST + +FIRSTDST: + mov si,[DESTTAIL] ; Create an FCB of the original DEST + mov di,offset trangroup:DESTFCB + mov ax,PARSE_FILE_DESCRIPTOR SHL 8 + INT int_command + CMP BYTE PTR [SI],0 + JZ GoodParse +;AD052; MOV BYTE PTR [DI+1],"|" ; must be illegal file name character + mov dx,offset trangroup:fuldir_ptr ;AN052; Issue "File creation error" + jmp coperr ;AN052; + +GoodParse: + mov ax,word ptr [DESTBUF] ; Get drive + cmp ah,':' + jz DRVSPEC4 + mov al,'@' + +DRVSPEC4: + MOV CL,[ASCII] ; Save current ASCII setting + or al,20h + sub al,60h + mov [DESTFCB],al + mov al,[DESTINFO] + mov ah,[SRCINFO] + and ax,0202H + or al,al + jz NOTMELCOPY + cmp al,ah + jnz NOTMELCOPY + cmp [PLUS],0 + jz NOTMELCOPY + inc [MELCOPY] ; ambig source, ambig dest, and pluses + xor al,al + jmp short SETCONC + +NOTMELCOPY: + xor al,2 ; al=2 if unambig dest, =0 if ambig dest + and al,ah + shr al,1 ; al=1 if unambig dest AND ambig sorce + ; Implies concatenation +SETCONC: + or al,[PLUS] ; al=1 if concat + mov [CONCAT],al + shl al,1 + shl al,1 + mov [INEXACT],al ; Concat -> inexact copy + cmp [BINARY],0 + jnz NOTFIRSTDEST ; Binary explicitly given, all OK + mov [ASCII],al ; Concat -> ASCII + or cl,cl + jnz NOTFIRSTDEST ; ASCII flag set before, DATA read correctly + or al,al + JZ NOTFIRSTDEST ; ASCII flag did not change states +; +; At this point there may already be binary read data in the read buffer. +; We need to find the first ^Z (if there is one) and trim the amount +; of data in the buffer correctly. +; + MOV CX,[NXTADD] + JCXZ NOTFIRSTDEST ; No data, everything OK + MOV AL,1AH + PUSH ES + XOR DI,DI + MOV ES,[TPA] + REPNE SCASB ; Scan for EOF + POP ES + JNZ NOTFIRSTDEST ; No ^Z in buffer, everything OK + DEC DI ; Point at ^Z + MOV [NXTADD],DI ; New buffer + +NOTFIRSTDEST: + mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars + cmp [CONCAT],0 + jz GOTCHRSRC ; Not a concat + mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars + +GOTCHRSRC: + mov si,offset trangroup:DESTFCB+1 ; Original dest name + mov di,[DESTTAIL] ; Where to put result + +public buildname +BUILDNAME: + mov cx,8 + +BUILDMAIN: + lodsb + cmp al,'?' + jnz NOTAMBIG + mov al,byte ptr [BX] + +NOTAMBIG: + cmp al,' ' + jz NOSTORE + stosb + +NOSTORE: + inc bx + loop BUILDMAIN + mov cl,3 + mov al,' ' + cmp byte ptr [SI],al + jz ENDDEST ; No extension + mov al,dot_chr + stosb + +BUILDEXT: + lodsb + cmp al,'?' + jnz NOTAMBIGE + mov al,byte ptr [BX] + +NOTAMBIGE: + cmp al,' ' + jz NOSTOREE + stosb + +NOSTOREE: + inc bx + loop BUILDEXT +ENDDEST: + xor al,al + stosb ; NUL terminate + return + +BUILDPATH: + test [BP.INFO],2 + jnz NOTPFILE ; If ambig don't bother with open + mov dx,bp + add dx,BUF ; Set DX to spec + + push di ;AN000; + MOV AX,EXTOPEN SHL 8 ;AC000; open the file + mov bx,read_open_mode ;AN000; get open mode for COPY + xor cx,cx ;AN000; no special files + mov si,dx ;AN030; get file name offset + mov di,-1 ;AN030; no parm list + mov dx,read_open_flag ;AN000; set up open flags + INT int_command + pop di ;AN000; + jnc pure_file ;AN022; is pure file + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_file_not_found ;AN022; if file not found - okay + jz notpfile ;AN022; + cmp ax,error_path_not_found ;AN022; if path not found - okay + jz notpfile ;AN022; + cmp ax,error_access_denied ;AN022; if access denied - okay + jz notpfile ;AN022; + jmp extend_setup ;AN022; exit with error + +pure_file: + mov bx,ax ; Is pure file + mov ax,IOCTL SHL 8 + INT int_command + mov ah,CLOSE + INT int_command + test dl,devid_ISDEV + jnz ISADEV ; If device, done + test [BP.INFO],4 + jz ISSIMPFILE ; If no path seps, done + +NOTPFILE: + mov dx,word ptr [BP.BUF] + cmp dl,0 ;AN034; If no drive specified, get + jz set_drive_spec ;AN034; default drive dir + cmp dh,':' + jz DRVSPEC5 + +set_drive_spec: ;AN034; + mov dl,'@' + +DRVSPEC5: + or dl,20h + sub dl,60h ; A = 1 + invoke SAVUDIR1 + jnc curdir_ok ;AN022; if error - exit + invoke get_ext_error_number ;AN022; get the extended error + jmp extend_setup ;AN022; exit with error + +curdir_ok: ;AN022; + mov dx,bp + add dx,BUF ; Set DX for upcomming CHDIRs + mov bh,[BP.INFO] + and bh,6 + cmp bh,6 ; Ambig and path ? + jnz CHECKAMB ; jmp if no + mov si,[BP.TTAIL] + mov bl,':' + cmp byte ptr [si-2],bl + jnz KNOWNOTSPEC + mov [BP.ISDIR],2 ; Know is d:/file + jmp short DOPCDJ + +KNOWNOTSPEC: + mov [BP.ISDIR],1 ; Know is path/file + dec si ; Point to the / + +DOPCDJ: + jmp DOPCD ;AC022; need long jump + +CHECKAMB: + cmp bh,2 + jnz CHECKCD + +ISSIMPFILE: +ISADEV: + mov [BP.ISDIR],0 ; Know is file since ambig but no path + return + +CHECKCD: + invoke SETREST1 + mov ah,CHDIR + INT int_command + jc NOTPDIR + mov di,dx + xor ax,ax + mov cx,ax + dec cx + +Kloop: ;AN000; 3/3/KK + MOV AL,ES:[DI] ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + OR AL,AL ;AN000; 3/3/KK + JZ Done ;AN000; 3/3/KK + xor ah,ah ;AN000; 3/3/KK + invoke Testkanj ;AN000; 3/3/KK + JZ Kloop ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + INC AH ;AN000; 3/3/KK + jmp Kloop ;AN000; 3/3/KK + +Done: ;AN000; 3/3/KK + dec di + mov al,[DIRCHAR] + mov [bp.ISDIR],2 ; assume d:/file + OR AH, AH ;AN000; 3/3/KK + JNZ Store_pchar ;AN000; 3/3/KK this is the trailing byte of ECS code + cmp al,[di-1] + jz GOTSRCSLSH + +Store_pchar: ;AN000; 3/3/KK + stosb + mov [bp.ISDIR],1 ; know path/file + +GOTSRCSLSH: + or [bp.INFO],6 + call SETSTARS + return + + +NOTPDIR: + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; if path not found - okay + jz notpdir_try ;AN022; + cmp ax,error_access_denied ;AN022; if access denied - okay + jnz extend_setupj ;AN022; otherwise - exit error + +notpdir_try: ;AN022; + mov [bp.ISDIR],0 ; assume pure file + mov bh,[bp.INFO] + test bh,4 + retz ; Know pure file, no path seps + mov [bp.ISDIR],2 ; assume d:/file + mov si,[bp.TTAIL] + cmp byte ptr [si],0 + jz BADCDERRJ2 ; Trailing '/' + mov bl,dot_chr + cmp byte ptr [si],bl + jz BADCDERRJ2 ; If . or .. pure cd should have worked + mov bl,':' + cmp byte ptr [si-2],bl + jz DOPCD ; Know d:/file + mov [bp.ISDIR],1 ; Know path/file + dec si ; Point at last '/' + +DOPCD: + xor bl,bl + xchg bl,[SI] ; Stick in a NUL + invoke SETREST1 + CMP DX,SI ;AN000; 3/3/KK + JAE LookBack ;AN000; 3/3/KK + PUSH SI ;AN000; 3/3/KK + PUSH CX ;AN000; 3/3/KK + MOV CX,SI ;AN000; 3/3/KK + MOV SI,DX ;AN000; 3/3/KK + +Kloop2: ;AN000; 3/3/KK + LODSB ;AN000; 3/3/KK + invoke TestKanj ;AN000; 3/3/KK + jz NotKanj4 ;AN000; 3/3/KK + LODSB ;AN000; 3/3/KK + CMP SI,CX ;AN000; 3/3/KK + JB Kloop2 ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + POP SI ;AN000; 3/3/KK + JMP SHORT DoCdr ;AN000; 3/3/KK Last char is ECS code, don't check for + ; trailing path sep +NotKanj4: ;AN000; 3/3/KK + CMP SI,CX ;AN000; 3/3/KK + JB Kloop2 ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + POP SI ;AN000; 3/3/KK + +LookBack: ;AN000; 3/3/KK + CMP BL,[SI-1] ; if double slash, then complain. + JZ BadCDErrJ2 + +DoCdr: ;AN000; 3/3/KK + mov ah,CHDIR + INT int_command + xchg bl,[SI] + retnc + invoke get_ext_error_number ;AN022; get the extended error + +EXTEND_SETUPJ: ;AN022; + JMP EXTEND_SETUP ;AN022; go issue the error message + +BADCDERRJ2: + jmp badpath_err ;AC022; go issue path not found message + +SETSTARS: + mov [bp.TTAIL],DI + add [bp.SIZ],12 + mov ax,dot_qmark + mov cx,8 + rep stosb + xchg al,ah + stosb + xchg al,ah + mov cl,3 + rep stosb + xor al,al + stosb + return + +PUBLIC CompName +COMPNAME: + + mov si,offset trangroup:DESTBUF ;g do name translate of target + mov di,offset trangroup:TRGXNAME ;g save for name comparison + mov ah,xnametrans ;g + int int_command ;g + + MOV si,offset trangroup:SRCXNAME ;g get name translate of source + MOV di,offset trangroup:TRGXNAME ;g get name translate of target + + + invoke STRCOMP + + return + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/CPARSE.ASM b/v4.0/src/CMD/COMMAND/CPARSE.ASM new file mode 100644 index 0000000..f751086 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/CPARSE.ASM @@ -0,0 +1,417 @@ + page 80,132 +; SCCSID = @(#)cparse.asm 1.1 85/05/14 +; SCCSID = @(#)cparse.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADCD_PTR:WORD ;AC022; + EXTRN BADCPMES_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN comma:byte + EXTRN cpyflag:byte + EXTRN CURDRV:BYTE + EXTRN ELCNT:BYTE + EXTRN ELPOS:BYTE + EXTRN EXPAND_STAR:BYTE + EXTRN SKPDEL:BYTE + EXTRN STARTEL:WORD + EXTRN SWITCHAR:BYTE + EXTRN switch_list:byte + EXTRN TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + + EXTRN CERROR:NEAR + + PUBLIC BADCDERR ;AC022; + PUBLIC CPARSE + +SWCOUNT EQU 5 ; Must agree with length of switch_list + +;-----------------------------------------------------------------------; +; ENTRY: ; +; DS:SI Points input buffer ; +; ES:DI Points to the token buffer ; +; BL Special delimiter for this call ; +; Always checked last ; +; set it to space if there is no special delimiter ; +; EXIT: ; +; DS:SI Points to next char in the input buffer ; +; ES:DI Points to the token buffer ; +; [STARTEL] Points to start of last element of path in token ; +; points to a NUL for no element strings 'd:' 'd:/' ; +; CX Character count ; +; BH Condition Code ; +; Bit 1H of BH set if switch character ; +; Token buffer contains char after ; +; switch character ; +; BP has switch bits set (ORing only) ; +; Bit 2H of BH set if ? or * in token ; +; if * found element ? filled ; +; Bit 4H of BH set if path sep in token ; +; Bit 80H of BH set if the special delimiter ; +; was skipped at the start of this token ; +; Token buffer always starts d: for non switch tokens ; +; CARRY SET ; +; if CR on input ; +; token buffer not altered ; +; ; +; DOES NOT RETURN ON BAD PATH, OR TRAILING SWITCH CHAR ERROR ; +; MODIFIES: ; +; CX, SI, AX, BH, DX and the Carry Flag ; ; +; ; +; -----------------------------------------------------------------------; +;--------------- +; Modifications to cparse: recognition of right and left parentheses +; as integral tokens, and removal of automatic upper-case conversion code. +; +; Both modifications were installed in the course of adding a coherent +; command-line parser to COMMAND.COM which builds a UNIX-style argv[]/argc +; structure for command-line arguments. This parser relies on cparse to +; recognize individual tokens. +; +; To process for-loops correctly, parentheses must therefore be +; recognized as tokens. The upper-case conversion code was removed so +; that commands (such as for and echo) would be able to use the "original" +; text of the command line. +; +; Note also the modification to prevent the automatic conversion of colons +; into spaces WITHIN THE SOURCE TEXT! +; +; Also note that BP is also clobbered if cparse recognizes any switches +; on the command line. +; +; Alan L, OS/MSDOS 14 August 1983 +;--------------- + +CPARSE: +ASSUME DS:TRANGROUP,ES:TRANGROUP + + xor ax,ax + mov [STARTEL],DI ; No path element (Is DI correct?) + mov [ELPOS],al ; Start in 8 char prefix + mov [SKPDEL],al ; No skip delimiter yet + mov bh,al ; Init nothing + pushf ; save flags + push di ; save the token buffer addrss + xor cx,cx ; no chars in token buffer + mov comma,cl ;g reset comma flag +moredelim: + LODSB + INVOKE DELIM + JNZ SCANCDONE + CMP AL,' ' + JZ moredelim + CMP AL,9 + JZ moredelim + xchg al,[SKPDEL] + or al,al + jz moredelim ; One non space/tab delimiter allowed + test bh,080h ;g has a special char been found? + jz no_comma ;g no - just exit + mov comma,1 ;g set comma flag +no_comma: + JMP x_done ; Nul argument + +SCANCDONE: + +;;;; IF NOT KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. +; cmp cpyflag,1 3/3/KK +; jnz cpcont1 3/3/KK +; invoke UPCONV 3/3/KK +cpcont1: +;--------------- +;;;; ENDIF 3/3/KK + + cmp al,bl ; Special delimiter? + jnz nospec + or bh,80H + jmp short moredelim + +nospec: + cmp al,0DH ; a CR? + jne ncperror + jmp cperror + +ncperror: + cmp al,[SWITCHAR] ; is the char the switch char? + jne na_switch ; yes, process... + jmp a_switch + +na_switch: + mov dl,':' + cmp byte ptr [si],dl + jne anum_chard ; Drive not specified + +;;;; IF KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. + cmp cpyflag,1 + jnz cpcont2 + invoke UPCONV +cpcont2: +;--------------- +;;;; ENDIF 3/3/KK + + call move_char + lodsb ; Get the ':' + call move_char + mov [STARTEL],di + mov [ELCNT],0 + jmp anum_test + +anum_chard: + mov [STARTEL],di + mov [ELCNT],0 ; Store of this char sets it to one + cmp cpyflag,1 ; Was CPARSE called from COPY? + jnz anum_char ; No, don't add drive spec. + invoke PATHCHRCMP ; Starts with a pathchar? + jnz anum_char ; no + push ax + mov al,[CURDRV] ; Insert drive spec + add al,capital_A + call move_char + mov al,':' + call move_char + pop ax + mov [STARTEL],di + mov [ELCNT],0 + +anum_char: + +;;;; IF KANJI 3/3/KK + invoke TESTKANJ + jz NOTKANJ ;AC048; + call move_char + lodsb + jmp short notspecial + +NOTKANJ: ;AN048; If not kanji + cmp cpyflag,1 ;AN048; and if we're in COPY + jnz testdot ;AN048; + invoke upconv ;AN048; upper case the char + +TESTDOT: +;;;; ENDIF 3/3/KK + + cmp al,dot_chr + jnz testquest + inc [ELPOS] ; flag in extension + mov [ELCNT],0FFH ; Store of the '.' resets it to 0 + +testquest: + cmp al,'?' + jnz testsplat + or bh,2 + +testsplat: + cmp al,star + jnz testpath + or bh,2 + cmp byte ptr [expand_star],0 + jnz expand_filename + jmp SHORT testpath + +badperr2j: + jmp badperr2 + +expand_filename: + mov ah,7 + cmp [ELPOS],0 + jz gotelcnt + mov ah,2 + +gotelcnt: + mov al,'?' + sub ah,[ELCNT] + jc badperr2j + xchg ah,cl + jcxz testpathx + +qmove: + xchg ah,cl + call move_char + xchg ah,cl + loop qmove + +testpathx: + xchg ah,cl + +testpath: + invoke PATHCHRCMP + jnz notspecial + or bh,4 + cmp byte ptr [expand_star],0 + jz no_err_check + test bh,2 ; If just hit a '/', cannot have ? or * yet + jnz badperr + +no_err_check: + mov [STARTEL],di ; New element + INC [STARTEL] ; Point to char after / + mov [ELCNT],0FFH ; Store of '/' sets it to 0 + mov [ELPOS],0 + +notspecial: + call move_char ; just an alphanum string +anum_test: + + lodsb + +;;;; IF NOT KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. +; cmp cpyflag,1 3/3/KK +; jnz cpcont3 3/3/KK +; invoke UPCONV 3/3/KK +cpcont3: +;--------------- +;;;; ENDIF 3/3/KK + + INVOKE DELIM + je x_done + + cmp al,0DH + je x_done + cmp al,[SWITCHAR] + je x_done + cmp al,bl + je x_done + cmp al,':' ; ':' allowed as trailer because + ; of devices +;;;; IF KANJI 3/3/KK + je FOO15 + jmp anum_char +FOO15: +;;; ELSE 3/3/KK +;;; jne anum_charj 3/3/KK +;;; ENDIF 3/3/KK + +;--------------- +; Modification made for parseline. +; Why would it be necessary to change colons to spaces? In this +; case, EVERY colon is changed to a space; e.g., 'f:' yields 'f ', +; but so does 'echo foo:bar' yield 'echo foo bar'. +;--------------- + cmp cpyflag,2 ; Is CPARSE parsing the 1st token from + ; from PARSELINE? + jnz cpcont4 ; No, continue + call move_char ; Yes, save the ':' and go get another + jmp anum_test ; character. + +cpcont4: + inc si ;Skip the ':' + jmp short x_done + +anum_charj: + jmp anum_char + +badperr2: + mov dx,offset trangroup:BADCPMES_ptr + jmp CERROR + +badperr: +BADCDERR: ;AC022; Issue "Invalid Directory" + MOV DX,OFFSET TRANGROUP:BADCD_ptr ;AC022; message + JMP CERROR ;AC022; + +cperror: + dec si ; adjust the pointer + pop di ; retrive token buffer address + popf ; restore flags + stc ; set the carry bit + return + +x_done: + dec si ; adjust for next round +;--------------- +; Mod to recognize right and left parens as integral tokens. +x_done2: +;--------------- + jmp short out_token + +a_switch: + OR BH,1 ; Indicate switch + OR BP,fSwitch + INVOKE SCANOFF + INC SI + invoke testkanj ;AN057; See if DBCS lead byte + jz a_switch_notkanj ;AN057; no - continue processing + call move_char ;AN057; DBCS - store first byte + lodsb ;AN057; get second byte + call move_char ;AN057; store second byte + or bp,fBadSwitch ;AN057; DBCS switch is invalid + jmp short out_token ;AN057; don't bother checking switch +a_switch_notkanj: ;AN057; + cmp al,0DH + jne Store_swt + mov al,0 + stosb ; null at the end + OR BP,fBadSwitch + jmp cperror ; Trailing switch character error + ; BP = fSwitch but no switch + ; bit is set (unknown switch) +Store_swt: + call move_char ; store the character +; +;--------------- +; This upconv call must stay. It is used to identify copy-switches +; on the command line, and won't store anything into the output buffer. + invoke UPCONV +;--------------- +; + PUSH ES + PUSH DI + PUSH CX + PUSH CS + POP ES +ASSUME ES:TRANGROUP + MOV DI,OFFSET TRANGROUP:switch_list + MOV CX,SWCOUNT + OR BP,fBadSwitch + REPNE SCASB + JNZ out_tokenp + AND BP,NOT fBadSwitch + MOV AX,1 + SHL AX,CL + OR BP,AX + +out_tokenp: + POP CX + POP DI + POP ES + +ASSUME ES:NOTHING +out_token: + mov al,0 + stosb ; null at the end + pop di ; restore token buffer pointer + popf + clc ; clear carry flag + return + +move_char: + stosb ; store char in token buffer + inc cx ; increment char count + inc [ELCNT] ; increment element count for * substi + return + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/ENVDATA.ASM b/v4.0/src/CMD/COMMAND/ENVDATA.ASM new file mode 100644 index 0000000..ed4cd9e --- /dev/null +++ b/v4.0/src/CMD/COMMAND/ENVDATA.ASM @@ -0,0 +1,28 @@ +; SCCSID = @(#)envdata.asm 1.1 85/05/14 +; SCCSID = @(#)envdata.asm 1.1 85/05/14 +; This file is included by command.asm and is used as the default command +; environment. + +ENVARENA SEGMENT PUBLIC PARA + ORG 0 + DB 10h DUP (?) ;Pad for memory allocation addr mark +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment + + PUBLIC ECOMSPEC,ENVIREND,PATHSTRING + + ORG 0 +PATHSTRING DB "PATH=" +USERPATH LABEL BYTE + + DB 0 ; Null path + DB "COMSPEC=" +ECOMSPEC DB "\COMMAND.COM" ;AC062 + DB 134 DUP (0) + +ENVIREND LABEL BYTE + +ENVIRONSIZ EQU $-PATHSTRING +ENVIRONSIZ2 EQU $-ECOMSPEC +ENVIRONMENT ENDS diff --git a/v4.0/src/CMD/COMMAND/FORDATA.ASM b/v4.0/src/CMD/COMMAND/FORDATA.ASM new file mode 100644 index 0000000..b46ba3d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/FORDATA.ASM @@ -0,0 +1,19 @@ +; SCCSID = @(#)fordata.asm 1.1 85/05/14 +; SCCSID = @(#)fordata.asm 1.1 85/05/14 +; Data structure definitions included by tfor.asm + +for_info STRUC + for_args DB (SIZE arg_unit) DUP (?) ; argv[] structure + FOR_COM_START DB (?) ; beginning of + FOR_EXPAND DW (?) ; * or ? item in ? + FOR_MINARG DW (?) ; beginning of + FOR_MAXARG DW (?) ; end of + forbuf DW 64 DUP (?) ; temporary buffer + fordma DW 64 DUP (?) ; FindFirst/Next buffer + FOR_VAR DB (?) ; loop control variable +for_info ENDS + +; empty segment done for bogus addressing +for_segment segment +f LABEL BYTE +for_segment ends diff --git a/v4.0/src/CMD/COMMAND/IFEQU.ASM b/v4.0/src/CMD/COMMAND/IFEQU.ASM new file mode 100644 index 0000000..9c0ee29 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/IFEQU.ASM @@ -0,0 +1,18 @@ +; SCCSID = @(#)ifequ.asm 1.1 85/05/14 +; SCCSID = @(#)ifequ.asm 1.1 85/05/14 +;************************************* +; COMMAND EQUs which are switch dependant + +IF1 + IF IBM + %OUT DBCS Enabled IBM version + ELSE + %OUT Normal version + ENDIF + +;; IF KANJI 3/3/KK +;; %OUT Kanji version 3/3/KK +;; ENDIF 3/3/KK + +ENDIF + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/INIT.ASM b/v4.0/src/CMD/COMMAND/INIT.ASM new file mode 100644 index 0000000..3ac84b6 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/INIT.ASM @@ -0,0 +1,1685 @@ + page 80,132 +; SCCSID = @(#)init.asm 4.13 85/11/03 +; SCCSID = @(#)init.asm 4.13 85/11/03 +TITLE COMMAND Initialization + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + include doscntry.inc ;AC000; + INCLUDE comseg.asm + INCLUDE comequ.asm + include resmsg.equ ;AN000; +.list +.cref + + +ENVIRONSIZ EQU 0A0H ;Must agree with values in EVIRONMENT segment +ENVIRONSIZ2 EQU 092H + +ENVBIG EQU 32768 +ENVSML EQU 160 +KOREA_COUNTRY_CODE EQU 82 + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN CONTC:NEAR + EXTRN DskErr:NEAR + EXTRN endinit:near + EXTRN INT_2E:NEAR + EXTRN LODCOM:NEAR + EXTRN RSTACK:WORD +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN abort_char:byte ;AN000; + EXTRN append_state:word ;AN042; + EXTRN BADFAT_OP_SEG:WORD ;AN000; + EXTRN BATCH:WORD + EXTRN COM_FCB1:DWORD + EXTRN COM_FCB2:DWORD + EXTRN COM_PTR:DWORD + EXTRN com_xlat_addr:word + EXTRN COMDRV:BYTE + EXTRN COMPRMT1_SEG:WORD ;AN000; + EXTRN COMPRMT1_SEG2:WORD ;AN000; + EXTRN COMSPEC:BYTE + EXTRN comspec_print:word + EXTRN comspec_end:word + EXTRN cpdrv:byte + EXTRN crit_msg_off:word ;AN000; + EXTRN crit_msg_seg:word ;AN000; + EXTRN critical_msg_start:byte ;AN000; + EXTRN DATARESEND:BYTE ;AC000; + EXTRN dbcs_vector_addr:word ;AN000; + EXTRN DEVE_OP_SEG:WORD ;AN000; + EXTRN DEVE_OP_SEG2:WORD ;AN000; + EXTRN disp_class:byte ;AN000; + EXTRN DRVNUM_OP_SEG:WORD ;AN000; + EXTRN DRVNUM_OP_SEG2:WORD ;AN000; + EXTRN EchoFlag:BYTE + EXTRN ENVIRSEG:WORD + EXTRN ERR15_OP_SEG:WORD ;AN000; + EXTRN ERR15_OP_SEG2:WORD ;AN000; + EXTRN ERR15_OP_SEG3:WORD ;AN000; + EXTRN extended_msg_start:byte ;AN000; + EXTRN extmsgend:byte ;AN000; + EXTRN fFail:BYTE + EXTRN fucase_addr:word ;AN000; + EXTRN InitFlag:BYTE + EXTRN IO_SAVE:WORD + EXTRN LTPA:WORD ;AC000; + EXTRN MEMSIZ:WORD + EXTRN MYSEG:WORD ;AC000; + EXTRN MYSEG1:WORD + EXTRN MYSEG2:WORD + EXTRN nest:word + EXTRN number_subst:byte ;AN000; + EXTRN OldTerm:DWORD + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AN000; +;AD060; EXTRN pars_msg_seg:word ;AN000; + EXTRN parse_msg_start:byte ;AN000; + EXTRN parsemes_ptr:word ;AN000; + EXTRN PERMCOM:BYTE + EXTRN RES_TPA:WORD + EXTRN resmsgend:word ;AN000; + EXTRN RSWITCHAR:BYTE + EXTRN SINGLECOM:WORD + EXTRN SUM:WORD + EXTRN TRNSEG:WORD + EXTRN TrnMvFlg:BYTE +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment + EXTRN ECOMSPEC:BYTE + EXTRN ENVIREND:BYTE + EXTRN PATHSTRING:BYTE +ENVIRONMENT ENDS + +TAIL SEGMENT PUBLIC PARA + EXTRN TRANSTART:WORD +TAIL ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN DATINIT:FAR + EXTRN printf_init:far +TRANCODE ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN TRANSPACEEND:BYTE +TRANSPACE ENDS + +; This is the area used for the autoexec.bat file. BATARENA is a pad for the +; the address mark placed by DOS. + +BATARENA SEGMENT PUBLIC PARA + + ORG 0 + DB 10h DUP (?) ;Pad for memory allocation addr mark + +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;Autoexec.bat segment + + ORG 0 + initbat batchsegment <> ;batch segment + DB 31 DUP (0) ;reserve area for batch file name & pad + +BATSEG ENDS + +; ******************************************************************* +; START OF INIT PORTION +; This code is overlayed the first time the TPA is used. + +INIT SEGMENT PUBLIC PARA + + EXTRN AUTOBAT:byte + EXTRN BADCSPFL:byte + EXTRN bslash:byte + EXTRN CHUCKENV:byte + EXTRN command_c_syn:byte ;AN000; + EXTRN command_d_syn:byte ;AN000; + EXTRN command_e_syn:byte ;AN000; + EXTRN command_f_syn:byte ;AN000; + EXTRN command_m_syn:byte ;AN000; + EXTRN command_p_syn:byte ;AN000; + EXTRN comnd1_syn:word ;AN000; + EXTRN comnd1_addr:dword ;AN000; + EXTRN COMSPECT:byte + EXTRN comspstring:byte + EXTRN dswitch:byte ;AN018; + EXTRN ECOMLOC:word + EXTRN EnvMax:WORD + EXTRN EnvSiz:WORD + EXTRN equalsign:byte + EXTRN eswitch:byte ;AN018; + EXTRN ext_msg:byte ;AN000; + EXTRN fslash:byte + EXTRN INITADD:dword + EXTRN initend:word + EXTRN init_parse:dword ;AN054; + EXTRN INTERNAT_INFO:BYTE ;AN000; 3/3/KK + EXTRN KAUTOBAT:byte ;AN000; 3/3/KK + EXTRN lcasea:byte + EXTRN lcasez:byte + EXTRN num_positionals:word ;AN000; + EXTRN oldenv:word + EXTRN old_parse_ptr:word ;AN057; + EXTRN parse_command:byte ;AN000; + EXTRN pars_msg_off:word ;AN060; + EXTRN pars_msg_seg:word ;AN060; + EXTRN PRDATTM:byte + EXTRN resetenv:word ;AC000; + EXTRN scswitch:byte + EXTRN space:byte + EXTRN triage_add:dword ;AC000; + EXTRN trnsize:word + EXTRN ucasea:byte + EXTRN usedenv:word + + +;AD054; EXTRN SYSPARSE:NEAR + + PUBLIC CONPROC + PUBLIC init_contc_specialcase + +ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP + + ORG 0 +ZERO = $ + + +CONPROC: + MOV SP,OFFSET RESGROUP:RSTACK ; MUST be first instruction + + CALL SYSLOADMSG ;AN000; check dos version + JNC OKDOS ;AN000; if no problem - continue + + mov ax,badver ;AN000; set DOS version + invoke sysdispmsg ;AN000; must be incorrect version + mov ax,es + cmp es:[PDB_Parent_PID],AX ; If command is its own parent, +here: ; loop forever. + Jz here + int 20h ; Otherwise, exit. + +; +; Turn APPEND off during initialization processing +; +okdos: + mov ax,AppendInstall ;AN042; see if append installed + int 2fh ;AN042; + cmp al,0 ;AN042; append installed? + je set_msg_addr ;AN042; no - continue + mov ax,AppendDOS ;AN042; see if append DOS version right + int 2fh ;AN042; + cmp ax,-1 ;AN042; append version correct? + jne set_msg_addr ;AN042; no - continue + mov ax,AppendGetState ;AN042; Get the state of Append + int 2fh ;AN042; + mov append_state,bx ;AN042; save append state + xor bx,bx ;AN042; clear out state + mov ax,AppendSetState ;AN042; Set the state of Append + int 2fh ;AN042; set everything off + +set_msg_addr: +; +; Get addresses of old critical and parse errors and save so they can +; be reset if COMMAND needs to exit +; + + push es ;AN000; SAVE ES DESTROYED BY INT 2FH +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_parse_msg ;AN000; get parse message address + int 2fh ;AN000; + mov cs:pars_msg_seg,es ;AN000; save returned segment + mov cs:pars_msg_off,di ;AN000; save returned offset + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_critical_msg ;AN000; get critical error message address + int 2fh ;AN000; + mov cs:crit_msg_seg,es ;AN000; save returned segment + mov cs:crit_msg_off,di ;AN000; save returned offset + pop es ;AN000; RESTORE ES DESTROYED BY INT 2FH + +; +; Set addresses of critical and parse errors in this level of COMMAND +; + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address + mov di,offset resgroup:parse_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; + call set_parse_2f ;AN060; set parse error address + + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,offset resgroup:critical_msg_start ;AN000; start address + int 2fh ;AN000; + + mov di,offset resgroup:dataresend+15 ;AN000; get address of resident end + mov [resmsgend],di ;AN000; save it + call sysloadmsg ;AN000; load message addresses + call get_msg_ptr ;AN000; set up pointers to some translated chars + mov ah,GetExtCntry ;g get extended country information + mov al,2 ;g minor function - ucase table + mov dx,-1 ;g + mov bx,-1 ;g + mov cx,5 ;g number of bytes we want + mov di,offset resgroup:com_xlat_addr ;g buffer to put address in + int int_command ;g + + mov ah,GetExtCntry ;AN000; get extended country info + mov al,4 ;AN000; get file ucase table + mov dx,-1 ;AN000; + mov bx,-1 ;AN000; + mov cx,5 ;AN000; number of bytes we want + mov di,offset resgroup:fucase_addr ;AN000; buffer for address + int int_command ;AN000; + + mov dx,offset resgroup:transtart+15 ;eg get end of init code + mov cl,4 ;eg change to paragraphs + shr dx,cl ;eg + mov ax,cs ;eg get current segment + add ax,dx ;eg calculate segment of end of init + mov [initend],ax ;eg save this + + push ds ;AN000; + mov ax, (ECS_call SHL 8) OR GetLeadBTbl ;AN000; get dbcs vector + int int_command ;AN000; + mov bx,ds ;AN000; get segment to bx + pop ds ;AN000; + mov dbcs_vector_addr,si ;AN000; save address of + mov dbcs_vector_addr+2,bx ;AN000; dbcs vector + + + mov ax,word ptr ds:[PDB_Parent_PID] ; Init PARENT so we can exit + mov [PARENT],ax ; correctly. + MOV AX,WORD PTR DS:[PDB_Exit] + MOV WORD PTR OldTerm,AX + MOV AX,WORD PTR DS:[PDB_Exit+2] + MOV WORD PTR OldTerm+2,AX + + MOV AX,OFFSET RESGROUP:ENVIREND + 15 + MOV CL,4 ; ax = size of resident part of + SHR AX,CL ; command in paragraphs. Add + MOV CX,CS ; this to CS and you get the + ADD AX,CX ; segment of the TPA. + + MOV [RES_TPA], AX ; Temporarily save the TPA segment + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JNC TPASET ; Memory wrap if carry set + MOV AX, [RES_TPA] +TPASET: + MOV [LTPA],AX ; Good enough for the moment + MOV AX,WORD PTR DS:[PDB_block_len] ; ax = # of paras given to command + + MOV [MYSEG1],DS ; These 3 variables are used as part of + MOV [MYSEG2],DS ; 3 long ptrs that the transient will + MOV [MYSEG],DS ; use to call resident routines. + MOV [MEMSIZ],AX ; Needed for execing other programs +; +; Compute maximum size of environment +; + MOV EnvMax,(Environsiz + 15) / 16 + (EnvMaximum-zero + 15)/16 - 1 +; +; Compute minimum size of environment +; + + MOV EnvSiz, ENVSML / 16 + + MOV DX,OFFSET TRANGROUP:TRANSPACEEND + 15 ; dx = size of transient + MOV CL,4 ; in paragraphs. + SHR DX,CL + mov [trnsize],dx ;eg save size of transient in paragraphs + + SUB AX,DX ; max seg addr - # para's needed for transient + MOV [TRNSEG],AX ; = seg addr to load the transient at. + MOV AX,DS:[PDB_environ] ; ax = environment segment + OR AX,AX ; If there is no environment segment, + JZ BUILDENV ; go compute one. + INC BYTE PTR [CHUCKENV] ; Flag no new ENVIRONSEG to set up + JMP SHORT ENVIRONPASSED ; Otherwise one was passed to us. + +BUILDENV: ; (this label isn't very accurate) + MOV AX,OFFSET RESGROUP:PATHSTRING ; Compute the segment of the + MOV CL,4 ; environment and put it in + SHR AX,CL ; ax. + MOV DX,DS + ADD AX,DX + +ENVIRONPASSED: + MOV [ENVIRSEG],AX ; Save the environment's segment and + MOV ES,AX ; load into es. +ASSUME ES:ENVIRONMENT + +GOTTHEENVIR: + MOV AX,CHAR_OPER SHL 8 ; Get the switch character and store it + INT int_command ; in RSWITCHAR. + MOV [RSWITCHAR],DL + + CMP DL,fslash ; If backslashes are being used as the + JNZ IUSESLASH ; path separator, change the forward + mov al,bslash ; slash in COMSPECT and ECOMSPEC (if + MOV [COMSPECT],al ; there is a new ENVIRONSEG) to + CMP BYTE PTR [CHUCKENV],0 ; backslash. + JNZ IUSESLASH + MOV ES:[ECOMSPEC],al ;eg + +IUSESLASH: +; +; Initialize the command drive +; + MOV AH,Get_Default_Drive + INT 21h + INC AL + MOV ComDrv,AL + + MOV AL,BYTE PTR DS:[FCB] ; al = default drive number for command + OR AL,AL + JZ NoComDrv ; no drive specified + + MOV AH,':' + MOV [COMDRV],AL + ADD AL,40H ; Convert number to uppercase character + + STD + CMP BYTE PTR [CHUCKENV],0 ; If a new environment is being built, + JNZ NOTWIDENV ; move the default comspec string in it + PUSH DS ; 2 bytes to make room for a drivespec. + PUSH ES ; The drivespec is in ax and is copied + POP DS ; on to the front of the string. + MOV DI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 1 ;eg + MOV SI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 3 ;eg + + MOV CX,ENVIRONSIZ2 - 2 + REP MOVSB + POP DS + MOV WORD PTR ES:[ECOMSPEC],AX + +NOTWIDENV: + CLD ; Add the drivespec to the string + MOV WORD PTR [AUTOBAT],AX ; used to reference autoexec.bat + MOV WORD PTR [KAUTOBAT],AX ;AN000; used to reference kautoexe.bat 3/3/KK + +NOCOMDRV: + INVOKE SETVECT ; Set interrupt vectors 22h, 23h, & 24h + +;********************************* +; PARSING STARTS HERE +;********************************* + + push cs ;AN000; get local segment + push cs ;AN000; into DS,ES + pop ds ;AN000; + pop es ;AN000; + +ASSUME DS:RESGROUP,ES:RESGROUP ;AN000; + + MOV SI,80H ;AC000; get command line + LODSB ;AC000; get length of line + MOV DI,SI ;AN000; get line position in DI + XOR AH,AH ;AC000; ax = length of command line +; +; Insure that the command line correctly ends with a CR +; + ADD DI,AX ;AC000; go to end of command line + MOV BYTE PTR [DI],0Dh ;AC000; insert a carriage return + xor cx,cx ;AC000; clear cx + mov num_positionals,cx ;AC000; initialize positionals +; +; Scan the command line looking for the parameters +; + +parse_command_line: + mov di,offset resgroup:parse_command;AN000; Get address of parse_command + mov cx,num_positionals ;AN000; Get number of positionals + xor dx,dx ;AN000; clear dx + mov old_parse_ptr,si ;AN057; save position before calling parser + call init_parse ;AN054; call parser + mov num_positionals,cx ;AN000; Save number of positionals + cmp ax,end_of_line ;AC000; are we at end of line? + jz ArgsDoneJ3 ;AC000; yes - exit + cmp ax,result_no_error ;AN000; did an error occur + jz parse_cont ;AN000; no - continue + +; +; Before issuing error message - make sure switch is not /C +; + +parse_line_error: + push si ;AN057; save line position + push ax ;AN057; save error number + cmp ax,BadSwt_Ptr ;AN057; Was error invalid switch? + jnz parse_line_error_disp ;AN057; No - just issue message + mov di,si ;AN057; Get terminating pointer in DI + mov si,old_parse_ptr ;AN057; Get starting pointer in SI + +init_chk_delim: + cmp si,di ;AN057; at end of parsed parameter? + jz parse_line_error_disp ;AN057; Yes - just display message + lodsb ;AN057; + cmp al,space ;AN057; Skip blank spaces + jz init_chk_delim ;AN057; + cmp al,tab_chr ;AN057; Skip tab characters + jz init_chk_delim ;AN057; + + cmp al,[rswitchar] ;AN057; Switch? + jnz parse_line_error_disp ;AN057; No - just issue message + lodsb ;AN057; Get the char after the switch + invoke itestkanj ;AN057; Is it DBCS? + jnz parse_line_error_disp ;AN057; Yes - can't be /C + invoke iupconv ;AN057; upper case it + cmp al,scswitch ;AN057; it is /C? + jnz parse_line_error_disp ;AN057; + pop dx ;AN057; even up stack + pop dx ;AN057; even up stack + jmp setSSwitch ;AN057; Yes - go set COMMAND /C + +parse_line_error_disp: + pop ax ;AN057; restore error number + pop si ;AN057; restore line position + mov disp_class,parse_msg_class ;AN000; set up parse error msg class + mov dx,ax ;AN000; get message number + call print_message ;AN000; issue error message + jmp short parse_command_line ;AN000; continue parsing + +parse_cont: +; +; See if a switch was entered +; + + cmp comnd1_syn,offset resgroup:command_f_syn ;AC000; was /F entered? + jz SetFSwitch ;AC000; yes go set fail switch + cmp comnd1_syn,offset resgroup:command_p_syn ;AC000; was /P entered? + Jz SetPSwitch ;AC000; yes go set up PERMCOM + cmp comnd1_syn,offset resgroup:command_d_syn ;AC000; was /D entered? + jz SetDSwitch ;AC000; yes go set date switch + cmp comnd1_syn,offset resgroup:command_c_syn ;AC000; was /C entered? + jz SetSSwitch ;AC000; yes go set up SINGLECOM + cmp comnd1_syn,offset resgroup:command_e_syn ;AC000; was /E entered? + jz SetESwitch ;AC000; yes go set up environment + cmp comnd1_syn,offset resgroup:command_m_syn ;AN000; was /MSG entered? + jz SetMSwitchjmp ;AN000; yes go set up message flag + jmp chkotherargs ;AC000; Must be something else + +SetMSwitchjmp: ;AN018; long jump needed + jmp SetMswitch ;AN018; + +ArgsdoneJ3: ;AN018; long jump needed + jmp ArgsDone ;AN018; + +SetFSwitch: + cmp fFail,-1 ;AN018; has fail switch been set? + jnz failok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +failok: + MOV fFail,-1 ;AC000; fail all INT 24s. + JMP parse_command_line ;AC000; + +SetPSwitch: +; +; We have a permanent COMMAND switch /P. Flag this and stash the +; termination address. +; + cmp [permcom],0 ;AN018; has /p switch been set? + jz permcomok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +permcomok: + INC [PERMCOM] + MOV WORD PTR [oldTerm],OFFSET RESGROUP:LODCOM + MOV WORD PTR [oldTerm+2],DS +; +; Make sure that we display the date and time. If the flag was not +; initialized, set it to indicate yes, do prompt. +; + CMP BYTE PTR [PRDATTM],-1 + JNZ parse_command_line_jmp ;AC018; keep parsing + MOV BYTE PTR [PRDATTM],0 ; If not set explicit, set to prompt + +Parse_command_line_jmp: ;AN018; + JMP parse_command_line ;AC000; keep parsing + +ArgsDoneJump: + JMP ArgsDone + +SetDSwitch: +; +; Flag no date/time prompting. +; + cmp dswitch,0 ;AN018; has /D switch been set? + jz setdateok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +setdateok: + inc dswitch ;AN018; indicate /D entered + MOV BYTE PTR [PRDATTM],1 ; User explicitly says no date time + JMP parse_command_line ;AC000; continue parsing + +SetSSwitch: +; +; Set up pointer to command line, flag no date/time and turn off singlecom. +; + MOV [SINGLECOM],SI ; Point to the rest of the command line + MOV [PERMCOM],0 ; A SINGLECOM must not be a PERMCOM + MOV BYTE PTR [PRDATTM],1 ; No date or time either, explicit + JMP ArgsDone +; +; Look for environment-size setting switch +; +; The environment size is represented in decimal bytes and is +; converted into pargraphs (rounded up to the next paragraph). +; + +SetESwitch: + cmp eswitch,0 ;AN018; has fail switch been set? + jz eswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +eswitchok: + inc eswitch ;AN018; indicate /E entered + mov di,offset resgroup:comnd1_addr ;AN000; get number returned + mov bx,word ptr [di] ;AN000; into bx + + ADD BX, 0FH ; Round up to next paragraph + mov cl,4 ;AC000; convert to pargraphs + SHR BX, cl ;AC000; by right 4 + + MOV EnvSiz,BX ; EnvSiz is in paragraphs + JMP parse_command_line ;AC000; continue parsing command line + +SetMSwitch: + cmp ext_msg,set_extended_msg ;AN018; has /MSG switch been set? + jnz setMswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message +setMswitchok: + MOV Ext_msg,set_extended_msg ;AN000; set /MSG switch + JMP parse_command_line ;AN000; keep parsing + +ARGSDONEJ: + JMP ARGSDONE + +; +; We have a non-switch character here. +; +CHKOTHERARGS: + push ds ;AN054; + push si ;AC000; save place in command line + lds si,comnd1_addr ;AN000; get address of filespec + assume ds:nothing ;AN054; + + mov dx,si ;AN000; put in dx also + MOV AX,(OPEN SHL 8) OR 2 ; Read and write + INT int_command + JC CHKSRCHSPEC ; Wasn't a file + MOV BX,AX + MOV AX,IOCTL SHL 8 + INT int_command + TEST DL,80H + JNZ ISADEVICE + +BADSETCON: ;AN022; + MOV AH,CLOSE ; Close initial handle, wasn't a device + INT int_command + JMP CHKSRCHSPEC + +ISADEVICE: + XOR DH,DH + OR DL,3 ; Make sure has CON attributes + MOV AX,(IOCTL SHL 8) OR 1 + INT int_command + JC BADSETCON ;AN022; Can't set attributes - quit + MOV DX,BX ; Save new handle +;eg POP BX ; Throw away saved SI +;eg POP BX ; Throw away saved CX + PUSH CX + MOV CX,3 + XOR BX,BX + +RCCLLOOP: ; Close 0,1 and 2 + MOV AH,CLOSE + INT int_command + INC BX + LOOP RCCLLOOP + MOV BX,DX ; New device handle + MOV AH,XDUP + INT int_command ; Dup to 0 + MOV AH,XDUP + INT int_command ; Dup to 1 + MOV AH,XDUP + INT int_command ; Dup to 2 + MOV AH,CLOSE + INT int_command ; Close initial handle + POP CX + pop si ;AN000; restore position of command line + pop ds ;AN054; + JMP parse_command_line ;AC000; continue parsing + +CHKSRCHSPEC: ; Not a device, so must be directory spec + + MOV BYTE PTR [CHUCKENV],0 ; If search specified -- no inheritance + MOV AX,OFFSET RESGROUP:PATHSTRING ; Figure environment pointer + MOV CL,4 + SHR AX,CL +;AD054; MOV DX,DS + MOV DX,CS ;AC054; + ADD AX,DX + MOV [ENVIRSEG],AX + + MOV ES,AX + push si ;AN000; remember location of file + xor cx,cx ;AN000; clear cx for counting + +countloop: + lodsb ;AN000; get a character + inc cx ;AN000; increment counter + cmp al,end_of_line_out ;AN000; are we at end of line? + jnz countloop ;AN000; no - keep counting + + mov al,space + dec si ;AN000; move back one + MOV BYTE PTR [SI],al ;AN000; put a space at end of line + pop si ;AC000; get location back + + MOV DI,[ECOMLOC] + +COMTRLOOP: + LODSB + DEC CX + CMP AL,space + JZ SETCOMSR + STOSB + +;;; IF KANJI 3/3/KK + XOR AH,AH +;;; ENDIF 3/3/KK + + JCXZ SETCOMSR + +;;;; IF KANJI 3/3/KK + PUSH DS ;AN054; Make sure we have + PUSH CS ;AN054; local DS for + POP DS ;AN054; ITESTKANJ + INVOKE ITESTKANJ + POP DS ;AN054; restore PARSER DS + JZ COMTRLOOP + DEC CX + MOVSB + INC AH + JCXZ SETCOMSR +;;;; ENDIF 3/3/KK + + JMP SHORT COMTRLOOP + +SETCOMSR: + PUSH CX + + PUSH CS ;AN054; Get local segment + POP DS ;AN054; + assume ds:resgroup ;AN054; + + PUSH DS + MOV SI,OFFSET RESGROUP:COMSPECT + MOV CX,14 + + MOV AL,ES:[DI-1] + +;;;; IF KANJI 3/3/KK + OR AH,AH + JNZ INOTROOT ; Last char was KANJI second byte, might be '\' +;;;; ENDIF 3/3/KK + + CALL PATHCHRCMPR + JNZ INOTROOT + INC SI ; Don't make a double / + DEC CX + +INOTROOT: + REP MOVSB + + MOV DX,[ECOMLOC] ; Now lets make sure its good! + PUSH ES + POP DS + + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + POP DS + JC SETCOMSRBAD ; No COMMAND.COM here + MOV BX,AX ; Handle + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + +SETCOMSRRET: + POP CX + POP SI + POP DS ;AN054; + assume ds:resgroup ;AN054; + +ARGSDONEJ2: + PUSH CS ;AN000; Make sure local ES is + POP ES ;AN000; restored + JMP parse_command_line ;AC000; continue parsing command line + +SETCOMSRBAD: + MOV DX,BADCOMLKMES_ptr ;AC000; get message number + invoke triageError + cmp ax, 65 + jnz doprt + mov dx,BADCOMACCMES_ptr ;AC000; get error message number +doprt: + call print_message + MOV SI,OFFSET RESGROUP:COMSPECT + MOV DI,[ECOMLOC] + MOV CX,14 + REP MOVSB ; Get my default back + + JMP SHORT SETCOMSRRET + +;********************************* +; PARSING ENDS HERE +;********************************* + +ARGSDONE: + mov es,[envirseg] ;AC000; get environment back + ASSUME ES:ENVIRONMENT ;AN000; +;AD060; cmp ext_msg,set_extended_msg ;AN000; was /msg specified? +;AD060; jnz check_permcom ;AN000; No, go check permcom +;AD060; cmp [permcom],0 ;AN000; Yes - was permcom set? +;AD060; jz permcom_error ;AN000; No - error cannot have /MSG without /P + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_extended_msg ;AN000; set up extended error message address +;AD060; push es ;AN016; save environment segment +;AD060; push cs ;AN016; get local segment to ES +;AD060; pop es ;AN016; +;AD060; mov di,offset resgroup:extended_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; +;AD060; pop es ;AN016; restore environment segment +;AD060; mov di,offset resgroup:extmsgend+15 ;AN000; get address of resident end +;AD060; mov [resmsgend],di ;AN000; save it +;AD060; call sysloadmsg ;AN000; load message addresses +;AD060; jmp short process_permcom ;AN000; now go process /P switch + +;AD060;permcom_error: +;AD060; mov disp_class,parse_msg_class ;AN000; set up parse error msg class +;AD060; mov dx,LessArgs_Ptr ;AN000; get message number for "Required parameter missing" +;AD060; call print_message ;AN000; issue error message +;AD060; jmp short comreturns ;AN000; we already know /P wasn't entered + +;AD060;check_permcom: + CMP [PERMCOM],0 + JZ COMRETURNS + +;AD060;process_permcom: + PUSH ES ; Save environment pointer + MOV AH,SET_CURRENT_PDB + MOV BX,DS + MOV ES,BX + INT int_command ; Current process is me + MOV DI,PDB_Exit ; Diddle the addresses in my header + MOV AX,OFFSET RESGROUP:LODCOM + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:CONTC + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:DskErr + STOSW + MOV AX,DS + STOSW + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me forever + + MOV DX,OFFSET RESGROUP:INT_2E + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 02EH + INT int_command ;Set magic interrupt + POP ES ;Remember environment + +COMRETURNS: + MOV AX,WORD PTR DS:[PDB_Parent_PID] + MOV [PARENT],AX ; Save parent + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me + MOV AX,WORD PTR DS:[PDB_JFN_Table] + MOV [IO_SAVE],AX ; Get the default stdin and out + MOV WORD PTR [COM_PTR+2],DS ; Set all these to resident + MOV WORD PTR [COM_FCB1+2],DS + MOV WORD PTR [COM_FCB2+2],DS + MOV DI,OFFSET RESGROUP:COMSPEC + + MOV SI,[ECOMLOC] + CMP BYTE PTR [CHUCKENV],0 + + MOV AX,DS ; XCHG ES,DS + PUSH ES + POP DS + MOV ES,AX + + JZ COPYCOMSP ; All set up for copy + + PUSH CS + POP DS + + MOV SI,OFFSET RESGROUP:COMSPSTRING + PUSH ES + PUSH DI + CALL IFINDE + MOV SI,DI + PUSH ES + POP DS + POP DI + POP ES + JNC COPYCOMSP + +COMSPECNOFND: + MOV SI,CS:[ECOMLOC] ;AC062 + ADD SI,OFFSET RESGROUP:PATHSTRING + PUSH CS + POP DS + +assume es:resgroup +COPYCOMSP: + mov es:comspec_print,di ; Save ptr to beginning of comspec path + cmp byte ptr [si+1],':' ; Is there a drive specifier in comspec + jnz COPYCOMSPLOOP ; If not, do not skip over first 2 bytes + add es:comspec_print,2 + +COPYCOMSPLOOP: + LODSB + STOSB + OR AL,AL + JNZ COPYCOMSPLOOP + mov es:comspec_end,di ; Save ptr to end of comspec path + dec es:comspec_end + mov ah,es:comdrv + add ah,'A'-1 + mov es:cpdrv,ah ; Load drive letter in comprmt2 +assume es:environment + + call setup_for_messages ;AN060; set up parse and extended error messages + PUSH CS + POP DS + MOV BX,[RESMSGEND] ;AC000; get end of resident + MOV CL,4 + SHR BX,CL +Public EnvMaximum +EnvMaximum: +; +; NOTE: The transient has to loaded directly after shrinking to the +; resident size. +; There is an assumption made when loading the transient that it +; still intact after the resident portion. +; If any other ALLOC/DEALLOC/SETBLOCK operations are performed +; inbetween, then there is a real good chance that the non-resident +; portion will be overwritten by arena information. +; + MOV AH,SETBLOCK + INT int_command ; Shrink me to the resident only +; +; Load in the transient and compute the checksum. We may do this in one of +; two ways: First, cheat and use the transient loading code that exists in +; the resident piece. This may be OK except that it will hit the disk. +; +; But we do not need to hit the disk! The transient is already loaded but is +; in the wrong place. We need to block transfer it up to the correct spot. +; +GOTENVIR: + MOV TrnMvFlg, 1 ; Indicate that transient has been moved + PUSH ES + MOV SI,OFFSET RESGroup:TranStart + MOV DI,0 + mov ES,Trnseg + MOV CX,OFFSET TRANGROUP:TRANSPACEEND +; +; We need to ensure that we do not have the potential of overwriting our +; existing code in this move +; It is OK to move if (SI+CX+Segment of Transient < TrnSeg). +; + push cx + mov ax,cx ; Get size of transient in bytes + add ax,si ; Calculate end of transient section + mov cl,4 + shr ax,cl ; Convert to paragraphs + inc ax ; Round up (for partial paragraph) + mov cx,ds + add ax,cx ; Add in current segment + cmp ax,Trnseg ; See if there is overlap + pop cx +; If we are too close to be safe, call LOADCOM instead of moving the code. + jb Ok_To_Move + invoke LOADCOM + jmp short Trans_Loaded +Ok_To_Move: +; +; Everything is set for an upward move. WRONG! We must move downward. +; + ADD SI,CX + DEC SI + ADD DI,CX + DEC DI + STD + REP MOVSB + CLD + +Trans_Loaded: + POP ES + + INVOKE CHKSUM ; Compute the checksum + MOV [SUM],DX ; Save it + + CMP BYTE PTR [PRDATTM],0 ;eg + JNZ NOBATCHSEG ;eg Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; + MOV BX,((SIZE BatchSegment) + 15 + 1 + 0Fh)/16 ;eg + MOV AH,ALLOC ;eg + INT int_command ;eg + JC NOBATCHSEG ;eg didn't allocate - pretend no batch + MOV BATCH,AX ;eg save batch segment + +NOBATCHSEG: + MOV BX, 0FFFFH ; Get size of largest block for env + MOV AH, ALLOC + INT int_command + +; Only allocate maximum 64K worth of environment + + SUB BX,TRNSIZE ;eg subtract # of transient paragraphs + SUB BX,128 ;eg make sure we have 2K left + MOV EnvMax, BX + CMP BX, 4096 ; 64K = 4096 paragraphs + JB MAXOK + MOV BX, 4096-1 + MOV EnvMax, BX +MAXOK: + + MOV AH, ALLOC ; Get max size + INT int_command + + mov bx,[envirseg] ;g get old environment segment + mov oldenv,bx ;g save it + mov usedenv,0 ;g initialize env size counter + MOV DS,bx + ASSUME DS:NOTHING + MOV [ENVIRSEG],AX + MOV ES,AX + XOR SI,SI + MOV DI,SI + MOV BX,EnvMax ; Copy over as much of the environment + ; as possible + SHL BX,1 + SHL BX,1 + SHL BX,1 + SHL BX,1 + MOV EnvMax, BX ; Convert EnvMax to bytes + DEC BX ; Dec by one to leave room for double 0 + XOR DX,DX ; Use DX to indicate that there was + ; no environment size error. +Public Nxtstr +Nxtstr: + CALL GetStrLen ; Get the size of the current env string + push ds ;g get addressability to environment + push cs ;g counter + pop ds ;g + ASSUME DS:RESGROUP + add usedenv,cx ;g add the string length to env size + pop ds ;g + ASSUME DS:NOTHING + CMP CX,1 ; End of environment was encountered. + JZ EnvExit + SUB BX,CX + JAE OKCpyStr ; Can't fit in all of enviroment. + INC DX ; Out of env space msg must be displayed + JMP EnvExit +OKCpyStr: + JMP Nxtstr +EnvExit: + + PUSH CS + POP DS + ASSUME DS:RESGroup + OR DX,DX ; DX will be non-zero if error + JZ EnvNoErr + MOV DX,OUTENVERR_ptr ;AC000; get message number + call print_message + +EnvNoErr: + ; BX now has the left over size of the maximum environment + ; We want to shrink the environment down to the minimum size + ; Set the environment size to max(Envsiz,Env used) + + MOV CX, EnvMax + SUB CX, BX ; CX now has the environment used + ADD CX, 16 ; Round up to next paragraph + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + CMP CX, Envsiz ; Is environment used > Envsiz + JB EnvSet + MOV Envsiz, CX +EnvSet: + MOV BX, Envsiz ; Set environment to size needed + mov ax,es ;eg get environment segment + add ax,bx ;eg add number of environment paragraphs + cmp ax,initend ;eg does this go past end of init? + ja envsetok ;eg yes - do the setblock + mov ax,es ;eg no - get back the environment segment + mov bx,initend ;eg get the segment at end of init + sub bx,ax ;eg setblock envir segment to end of init code + mov resetenv,1 ;eg set flag so we know to set envir later + +envsetok: + MOV AH, SETBLOCK + INT int_command + + IF MSVER + CMP [SINGLECOM],0 + JNZ NOPHEAD ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message +NOPHEAD: + ENDIF + + CMP [BATCH],0 ;eg did we set up a batch segment? + JNZ dodate ;eg yes - go initialize it + JMP NODTTM ; Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; +dodate: + MOV AX,BATCH ;eg get batch segment + MOV EchoFlag,3 ; set batch echo + MOV NEST,1 ; g set nest flag to 1 batch + MOV ES,AX +; +; Initialize the segment +; + XOR DI,DI + MOV AL,BatchType + STOSB + MOV AL,1 ; G initialize echo for batch exit + STOSB ; G + XOR AX,AX ; initialize to zero + STOSW ; G batch segment of last job - batlast + STOSW ; G segment for FOR + STOSB ; G FOR flag + STOSW ; position in file - batseek + STOSW +; +; Clean out the parameters +; + MOV AX,-1 ; initialize to no parameters + MOV CX,10 + REP STOSW +; +; Decide whether we should grab the default drive +; + CMP BYTE PTR [AUTOBAT],0 + + JNZ NOAUTSET + MOV AH,GET_DEFAULT_DRIVE + INT int_command + ADD AL,ucasea + + MOV [AUTOBAT],AL + MOV [KAUTOBAT],AL ;AN000; 3/3/KK + +NOAUTSET: +; +; Copy in the batch file name (including NUL) +; + MOV SI,OFFSET RESGROUP:AUTOBAT + MOV CX,8 + REP MOVSW + MOVSB ;AN027; move in carraige return to terminate string + + MOV DX,OFFSET RESGROUP:AUTOBAT + MOV AX,OPEN SHL 8 + INT int_command ; See if AUTOEXEC.BAT exists + JC NOABAT + MOV BX,AX + MOV AH,CLOSE + INT int_command + JMP DRV0 ;AC000; go process autoexec + +NOABAT: + push ax + call setup_seg + mov word ptr [triage_add+2],ax + pop ax + call triage_add + cmp ax, 65 + jz AccDenErr ;AN000; was network access denied + + +; If AUTOEXEC.BAT is not found, then check for KAUTOEXE.BAT. Changed +; by Ellen to check only when in Korea. The country information +; returned will overlay the old parse data area, but we don't care +; since we won't need the parse information or country information. +; We only care about the country code returned in BX. + + MOV DX,OFFSET RESGROUP:INTERNAT_INFO ;AN000; Set up internat vars + MOV AX,INTERNATIONAL SHL 8 ;AN000; get country dependent info + INT 21H ;AN000; + JC NOKABAT ;AN000; Error - don't bother with it + CMP BX,KOREA_COUNTRY_CODE ;AN000; Are we speaking Korean? + JNZ OPENERR ;AN000; No, don't check for KAUTOEXE + + MOV DI, OFFSET BatFile ;AN000; 3/3/KK + MOV SI,OFFSET RESGROUP:KAUTOBAT ;AN000; Another trial to do 3/3/KK + MOV CX,8 ;AN000; auto execution for the 3/3/KK + REP MOVSW ;AN000; non-English country 3/3/KK + MOVSB ;AN027; move in carraige return to terminate string + MOV DX,OFFSET RESGROUP:KAUTOBAT ;AN000; 3/3/KK + MOV AX,OPEN SHL 8 ;AN000; 3/3/KK + INT int_command ;AN000; See if KAUTOEXE.BAT exists 3/3/KK + JC NOKABAT ;AN000; 3/3/KK + MOV BX,AX ;AN000; 3/3/KK + MOV AH,CLOSE ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + JMP SHORT DRV0 ;AN000; 3/3/KK + +NOKABAT: ;AN000; 3/3/KK + call triage_add ;AN000; get extended error + cmp ax, 65 ;AN000; network access denied? + jnz openerr ;AN000; no - go deallocate batch + +AccDenErr: ;AN000; yes - put out message + mov DX,ACCDEN ;AC000; get message number + call print_message + +openerr: + MOV ES,[BATCH] ; Not found--turn off batch job + MOV AH,DEALLOC + INT int_command + MOV [BATCH],0 ; AFTER DEALLOC in case of ^C + MOV EchoFlag,1 + mov nest,0 ;g indicate no batch in progress + +DODTTM: + MOV AX,OFFSET TRANGROUP:DATINIT + MOV WORD PTR[INITADD],AX + MOV AX,[TRNSEG] + MOV WORD PTR[INITADD+2],AX + CALL DWORD PTR [INITADD] + +NODTTM: + + IF IBMVER + CMP [SINGLECOM],0 + JNZ DRV0 ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message + ENDIF + +DRV0: ; Reset APPEND state + push ds ;AN042; save data segment + push cs ;AN042; Get local segment into DS + pop ds ;AN042; + mov ax,AppendSetState ;AN042; Set the state of Append + mov bx,Append_state ;AN042; back to the original state + int 2fh ;AN042; + pop ds ;AN042; get data segment back + JMP ENDINIT ;G Finish initializing + +; +; Get length of string pointed to by DS:SI. Length includes NULL. +; Length is returned in CX +; +GetStrLen: + xor cx,cx +NxtChar: + lodsb + inc cx + or al,al + jnz NxtChar + ret +; +; If the transient has been loaded in TranSeg, then we need to use that +; segment for calls to routines in the transient area. Otherwise, the current +; code segment is used +; Segment returned in AX. +; +setup_seg: + mov ax,[trnseg] + cmp TrnMvFlg, 1 ; Has transient portion been moved + jz setup_end + push bx + mov bx,cs + mov ax,OFFSET RESGroup:TranStart + shr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + add ax,bx + pop bx +setup_end: + ret + +print_message: + push ax + PUSH DS ;AN000; save data and extra segment + PUSH ES ;AN000; registers + MOV AX,CS ;AN000; get local segment + MOV ES,AX ;AN000; set ES and DS to point to it + MOV DS,AX ;AN000; +;AD054; PUSH BX ;AC000; save BX register +;AD054; PUSH CX ;AC000; save CX register +;AD054; PUSH DX ;AC000; save DX register +;AD054; MOV AX,DX ;AC000; get message number +;AD054; MOV DH,DISP_CLASS ;AC000; get display class +;AD054; MOV DL,NO_CONT_FLAG ;AN000; set control flags off +;AD054; MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12 +;AD054; XOR CH,CH ;AC000; clear upper part of cx +;AD054; MOV CL,NUMBER_SUBST ;AC000; set number of substitutions +;AD054; invoke SYSDISPMSG ;AC000; display the message +;AD054; MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class +;AD054; MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions +;AD054; POP DX ;AC000; restore registers +;AD054; POP CX ;AC000; +;AD054; POP BX ;AC000; + invoke rprint ;AC054; + + POP ES ;AN000; + POP DS ;AN000; + pop ax + ret + +PATHCHRCMPR: + push dx + mov dl,fslash + CMP [RSWITCHAR],dl + JZ RNOSLASHT + CMP AL,dl + JZ RET41 +RNOSLASHT: + CMP AL,bslash +RET41: + pop dx + RET + + +IFINDE: + CALL IFIND ; FIND THE NAME + JC IFIND2 ; CARRY MEANS NOT FOUND + JMP ISCASB1 ; SCAN FOR = SIGN +; +; On return of FIND1, ES:DI points to beginning of name +; +IFIND: + CLD + CALL ICOUNT0 ; CX = LENGTH OF NAME + MOV ES,[ENVIRSEG] + XOR DI,DI + +IFIND1: + PUSH CX + PUSH SI + PUSH DI + +IFIND11: + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE ITESTKANJ + JZ NOTKANJ4 + DEC SI + LODSW + INC DI + INC DI + CMP AX,ES:[DI-2] + JNZ IFIND12 + DEC CX + LOOP IFIND11 + JMP SHORT IFIND12 + +NOTKANJ4: +;;;; ENDIF 3/3/KK + + CALL IUPCONV + INC DI + CMP AL,ES:[DI-1] + JNZ IFIND12 + LOOP IFIND11 + +IFIND12: + POP DI + POP SI + POP CX + JZ IFIND2 + PUSH CX + CALL ISCASB2 ; SCAN FOR A NUL + POP CX + CMP BYTE PTR ES:[DI],0 + JNZ IFIND1 + STC ; INDICATE NOT FOUND + +IFIND2: + RET + +ICOUNT0: + PUSH DS + POP ES + MOV DI,SI + + PUSH DI ; COUNT NUMBER OF CHARS UNTIL "=" + CALL ISCASB1 + JMP SHORT ICOUNTX + PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL + CALL ISCASB2 + +ICOUNTX: + POP CX + SUB DI,CX + XCHG DI,CX + RET + +ISCASB1: + MOV AL,equalsign ; SCAN FOR AN = + JMP SHORT ISCASBX + +ISCASB2: + XOR AL,AL ; SCAN FOR A NUL + +ISCASBX: + MOV CX,100H + REPNZ SCASB + RET + + +; **************************************************************** +; * +; * ROUTINE: IUPCONV (ADDED BY EMG 4.00) +; * +; * FUNCTION: This routine returns the upper case equivalent of +; * the character in AL from the file upper case table +; * in DOS if character if above ascii 128, else +; * subtracts 20H if between "a" and "z". +; * +; * INPUT: DS set to resident +; * AL char to be upper cased +; * FUCASE_ADDR set to the file upper case table +; * +; * OUTPUT: AL upper cased character +; * +; **************************************************************** + +assume ds:resgroup ;AN000; + +iupconv proc near ;AN000; + + cmp al,80h ;AN000; see if char is > ascii 128 + jb other_fucase ;AN000; no - upper case math + sub al,80h ;AN000; only upper 128 chars in table + push ds ;AN000; + push bx ;AN000; + lds bx,dword ptr fucase_addr+1 ;AN000; get table address + add bx,2 ;AN000; skip over first word + xlat ds:byte ptr [bx] ;AN000; convert to upper case + pop bx ;AN000; + pop ds ;AN000; + jmp short iupconv_end ;AN000; we finished - exit + +other_fucase: ;AN000; + cmp al,lcasea ;AC000; if between "a" and "z", + jb iupconv_end ;AC000; subtract 20h to get + cmp al,lcasez ;AC000; upper case equivalent. + ja iupconv_end ;AC000; + sub al,20h ;AC000; Change lower-case to upper + +iupconv_end: ;AN000; + ret + +iupconv endp ;AN000; + +init_contc_specialcase: + ; This routine is called if control-C + add sp,6 ; is type during the date/time prompt + push si ; at initialization time. The desired + mov si,dx ; response is to make it look like the + mov word ptr [si+1],0d00h ; user typed by "popping" the + pop si ; INT 21h stuff off the stack, putting + iret ; a in the user's buffer, and + ; returning directly to the user. + ; In this case the user is TCODE. + +; **************************************************************** +; * +; * ROUTINE: GET_MSG_PTR +; * +; * FUNCTION: Fill in translatable char table starting at +; * at Abort_char with translated characters. +; Set segments of resident messages. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +CHAR_START EQU 201 ;AN000; first character translate is 1 +CHAR_END EQU 207 ;AN000; last is 6 + +GET_MSG_PTR PROC NEAR ;AN000; + + MOV AX,CHAR_START ;AN000; get first char translation + MOV BX,OFFSET RESGROUP:ABORT_CHAR ;AN000; get first char offset +MOVEMES: ;AN000; + MOV DH,-1 ;AN000; utility message + INVOKE SYSGETMSG ;AN000; get the offset of the char + MOV CL,BYTE PTR [SI] ;AN000; get the character in CL + MOV BYTE PTR [BX],CL ;AN000; put the character in the table + INC BX ;AN000; point to next position in table + INC AX ;AN000; increment message number + CMP AX,CHAR_END ;AN000; are we at the end? + JNZ MOVEMES ;AN000; no - keep loading + + MOV AX,DS ;AN000; get data segment + MOV DRVNUM_OP_SEG,AX ;AN000; set up segments for + MOV DRVNUM_OP_SEG2,AX ;AN000; message substitutions + MOV DEVE_OP_SEG,AX ;AN000; used in the resident + MOV DEVE_OP_SEG2,AX ;AN000; portion of command + MOV ERR15_OP_SEG,AX ;AN000; during initialization + MOV ERR15_OP_SEG2,AX ;AN000; to save resident + MOV ERR15_OP_SEG3,AX ;AN000; space. + MOV BADFAT_OP_SEG,AX ;AN000; + MOV COMPRMT1_SEG,AX ;AN000; + MOV COMPRMT1_SEG2,AX ;AN000; + + RET ;AN000; + +GET_MSG_PTR ENDP ;AN000; + + +; **************************************************************** +; * +; * ROUTINE: Setup_for_messages +; * +; * FUNCTION: Sets up system for PARSE and EXTENDED ERROR +; * messages as follows: +; * +; * IF /P and /MSG are entered +; * keep PARSE and EXTENDED ERRORS in memory +; * ELSE IF /P is entered +; * use PARSE and EXTENDED ERRORS on disk +; * remove PARSE ERRORS from memory +; * ELSE +; * remove PARSE ERRORS from memory +; * ENDIF +; * +; * INPUT: PERMCOM Set up with user input +; * EXT_MSG Set up with user input +; * System set up to retain PARSE ERRORS +; * +; * OUTPUT: registers unchanged +; * +; **************************************************************** + + +setup_for_messages proc near ;AN060; + + push ds ;AN060; save data segment + push es ;AN060; save environment segment + push ax ;AN060; + push dx ;AN060; + push di ;AN060; + mov ax,cs ;AN060; get local segment to ES and DS + mov ds,ax ;AN060; + mov es,ax ;AN060; + + cmp [permcom],0 ;AN060; was permcom set? + jz no_permcom ;AN060; No - don't worry about messages + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jz permcom_slash_msg ;AN060; Yes - go process it + push es ;AN060; + mov ax,1 ;AN060; Set ES to 1 as a flag to the message + mov es,ax ;AN060; services that messages are on disk + mov di,offset resgroup:extended_msg_start-100h ;AN060; start address + call set_ext_2f ;AN060; set extended error address + mov di,offset resgroup:parse_msg_start-0100h ;AN060; start address + call set_parse_2f ;AN060; set parse error address + pop es ;AN060; + IF2 ;AN060;; + IFNDEF READ_DISK_INFO ;AN060;; + Extrn READ_DISK_PROC:Far ;AN060;; + ENDIF ;AN060;; + ENDIF ;AN060;; + MOV AX,DOS_GET_EXT_PARSE_ADD ;AN060;; 2FH Interface + MOV DL,DOS_SET_ADDR ;AN060;; Set the READ_DISK_PROC address + LEA DI,READ_DISK_PROC ;AN060;; + INT 2FH ;AN060;; Private interface + jmp short permcom_end ;AN060; and exit + +permcom_slash_msg: ;AN060; Keep messages in memory + mov di,offset resgroup:extended_msg_start ;AN060; start address + call set_ext_2f ;AN060; set the extended message address + mov di,offset resgroup:extmsgend+15 ;AN060; get address of resident end + mov [resmsgend],di ;AN060; save it + jmp short permcom_end ;AN060; exit + +no_permcom: ;AN060; + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jnz no_slash_msg ;AN060; no - no error + mov disp_class,parse_msg_class ;AN060; set up parse error msg class + mov dx,LessArgs_Ptr ;AN060; get message number for "Required parameter missing" + call print_message ;AN060; issue error message + +no_slash_msg: + mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers + mov dl,set_parse_msg ;AN060; set up parse message address + mov di,pars_msg_off ;AN060; old offset of parse messages + mov es,pars_msg_seg ;AN060; old segment of parse messages + int 2fh ;AN060; go set it + +permcom_end: + call sysloadmsg ;AN060; load message addresses + pop di ;AN060; + pop dx ;AN060; + pop ax ;AN060; + pop es ;AN060; get environment back + pop ds ;AN060; + + ret ;AN060; + +setup_for_messages endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_parse_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the PARSE +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_parse_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_parse_msg ;AN060; set up parse message address + int 2fh ;AN060; + + ret ;AN060; + +Set_parse_2f endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_ext_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the EXTENDED +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_ext_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_extended_msg ;AN060; set up extended error message address + int 2fh ;AN060; + + ret ;AN060; + +Set_ext_2f endp ;AN060; + + +ASSUME DS:RESGROUP, ES:RESGROUP + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AC026; include message services macro + +include msgdcl.inc + +INIT ENDS + + END diff --git a/v4.0/src/CMD/COMMAND/IPARSE.ASM b/v4.0/src/CMD/COMMAND/IPARSE.ASM new file mode 100644 index 0000000..5205fe9 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/IPARSE.ASM @@ -0,0 +1,38 @@ + page 80,132 +; SCCSID = @(#)iparse.asm 4.1 87/04/28 +; SCCSID = @(#)iparse.asm 4.1 87/04/28 +TITLE COMMAND interface to SYSPARSE + +.xlist +.xcref + INCLUDE comseg.asm ;AN000; +.list +.cref + + +INIT SEGMENT PUBLIC PARA ;AN000; + +ASSUME CS:RESGROUP,DS:RESGROUP,ES:NOTHING,SS:NOTHING ;AN000; + + +;AD054; public SYSPARSE ;AN000; + + DateSW equ 0 ;AN000; do not Check date format + TimeSW equ 0 ;AN000; do not Check time format + CmpxSW equ 0 ;AN000; do not check complex list + KeySW equ 0 ;AN025; do not support keywords + Val2SW equ 0 ;AN025; do not Support value definition 2 + Val3SW equ 0 ;AN000; do not Support value definition 3 + QusSW equ 0 ;AN025; do not include quoted string + DrvSW equ 0 ;AN025; do not include drive only + +.xlist +.xcref +;AD054; INCLUDE parse.asm ;AN000; +.list +.cref + + +INIT ends ;AN000; + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/MAKEFILE b/v4.0/src/CMD/COMMAND/MAKEFILE new file mode 100644 index 0000000..707fb00 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/MAKEFILE @@ -0,0 +1,134 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: command.com + +$(inc)\dossym.inc: $(inc)\dosmac.inc $(inc)\bpb.inc \ + $(inc)\buffer.inc $(inc)\sysvar.inc $(inc)\vector.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\cpmfcb.inc $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \ + $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\filemode.inc $(inc)\error.inc $(inc)\syscall.inc + echo "touch $(inc)\dossym.inc" + +command.ctl: command.skl $(msg)\$(COUNTRY).msg makefile + +command1.obj: command1.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \ + envdata.asm + +command2.obj: command2.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \ + envdata.asm + +copy.obj: copy.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +copypr1.obj: copypr1.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +copypr2.obj: copypr2.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +cparse.obj: cparse.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +init.obj: init.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comsw.asm comseg.asm comequ.asm resmsg.equ $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm command.ctl + +iparse.obj: iparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc + +parse2.obj: parse2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +path1.obj: path1.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +path2.obj: path2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +rdata.obj: rdata.asm comsw.asm comseg.asm $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm command.cla command.cl3 command.cl4 \ + command.cld command.clc command.cle command.ctl + +rucode.obj: rucode.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + $(inc)\doscntry.inc resmsg.equ $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm comsw.asm comseg.asm comequ.asm command.ctl + +tbatch.obj: tbatch.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tbatch2.obj: tbatch2.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd1a.obj: tcmd1a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd1b.obj: tcmd1b.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm $(inc)\ea.inc + +tcmd2a.obj: tcmd2a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd2b.obj: tcmd2b.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcode.obj: tcode.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm \ + $(inc)\mshalo.asm + +tdata.obj: tdata.asm comsw.asm comseg.asm $(inc)\curdir.inc \ + $(inc)\error.inc ifequ.asm comequ.asm $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm tranmsg.asm command.clf command.cl1 command.cl2 \ + command.ctl $(inc)\ea.inc + +tenv.obj: tenv.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm $(inc)\doscntry.inc + +tenv2.obj: tenv2.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm + +tfor.obj: tfor.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm fordata.asm + +tmisc1.obj: tmisc1.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tmisc2.obj: tmisc2.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tparse.obj: tparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc + +tpipe.obj: tpipe.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tprintf.obj: tprintf.asm comsw.asm $(inc)\dosmac.inc \ + comseg.asm comequ.asm $(inc)\sysmsg.inc $(inc)\msgserv.asm \ + command.ctl + +tspc.obj: tspc.asm comsw.asm $(inc)\dossym.inc comequ.asm \ + ifequ.asm comseg.asm $(inc)\ea.inc + +tucode.obj: tucode.asm $(inc)\dosmac.inc $(inc)\dossym.inc \ + comsw.asm comseg.asm comequ.asm ifequ.asm + +uinit.obj: uinit.asm comsw.asm comseg.asm ifequ.asm command.clb \ + $(inc)\sysmsg.inc $(inc)\msgserv.asm command.ctl + +command.com: command1.obj command2.obj rucode.obj rdata.obj init.obj iparse.obj \ + uinit.obj tcode.obj tbatch.obj tbatch2.obj tfor.obj tcmd1a.obj tcmd1b.obj \ + tcmd2a.obj tcmd2b.obj tenv.obj tenv2.obj tmisc1.obj tmisc2.obj tpipe.obj \ + parse2.obj path1.obj path2.obj tucode.obj copy.obj copypr1.obj copypr2.obj \ + cparse.obj tparse.obj tprintf.obj tdata.obj tspc.obj + link @command.lnk + exe2bin command.exe command.com + del command.exe diff --git a/v4.0/src/CMD/COMMAND/PARSE2.ASM b/v4.0/src/CMD/COMMAND/PARSE2.ASM new file mode 100644 index 0000000..2695927 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PARSE2.ASM @@ -0,0 +1,422 @@ + page 80,132 +; SCCSID = @(#)parse.asm 1.1 85/05/14 +; SCCSID = @(#)parse.asm 1.1 85/05/14 +.sall +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + + +break +;---------------------------------------------------------------------------- +; PARSE.ASM contains the routines to perform command line parsing. +; Parse and Path share a buffer and argv[] definitions. +; Invoking maps the unparsed command line in COMBUF into an +; array of pointers to the parsed tokens. The resulting array, argv[], +; also contains extra information provided by cparse about each token +; should be executed prior to +; +; Alan L, OS/MSDOS August 15, 1983 +; +; +; ENTRY: +; : command line in COMTAB. +; EXIT: +; : success flag, argcnt (number of args), argv[]. +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +DATARES SEGMENT PUBLIC BYTE + EXTRN FORFLAG:BYTE +DATARES ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN combuf:byte + EXTRN cpyflag:byte + EXTRN expand_star:byte + EXTRN RESSEG:word + EXTRN STARTEL:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + PUBLIC argv_calc ; convert array index into address + PUBLIC parseline + + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + + +break +;---------------------------------------------------------------------------- +; PARSELINE takes an MSDOS command line and maps it into a UNIX-style +; argv[argvcnt] array. The most important difference between this array and +; the tradition UNIX format is the extra cparse information included with +; each argument element. +;--------------- +; ENTRY: +; (BL special delimiter for cparse -- not implemented) +;--------------- +; EXIT: +; CF set if error +; AL error code (carry set). Note AH clobbered in any event. +; argv[] array of cparse flags and pointers to arguments +; argvcnt argument count +;--------------- +; NOTE(S): +; * BL (special delimiter) is ignored, for now (set to space). +; * Parseflags record contains cparse flags, as follows: +; sw_flag -- was this arg a switch? +; wildcard -- whether or not it contained a * or ? +; path_sep -- maybe it was a pathname +; unused -- for future expansion +; special_delim -- was there an initial special delimiter? +; * argv[] and argvcnt are undefined if CF/AL indicates an error. +; * Relationship between input, cparse output, and comtail can be +; found in the following chart. Despite the claim of the cparse +; documentation that, "Token buffer always starts d: for non switch +; tokens", such is not the case (see column two, row two). +; Similarly, [STARTEL] is not null when the command line is one of +; the forms, "d:", "d:\", or "d:/". In fact, *STARTEL (i.e., what +; STARTEL addresses) will be null. This is clearly just a +; documentation error. +; * cparse also returns a switch code in BP for each switch it +; recognizes on the command line. +; * arglen for each token does NOT include the terminating null. +; * Finally, note that interesting constructions like 'foodir/*.exe' +; parse as three separate tokens, and the asterisk is NOT a wildcard. +; For example, 'for %i in (foodir/*.exe) do echo %i' will first +; echo 'foodir', then '*', then '.exe'. Using cparse for command- +; line parsing may result in slightly different behavior than +; previously observed with the old COMMAND.COM command-line parser. +; +; Input Cparse Command Line (80H) +; \alan\foo.bat c:\alan\foo.bat \alan\foo.bat +; alan\foo.bat alan\foo.bat alan\foo.bat +; foo.bat foo.bat foo.bat +; c:\alan\foo.bat c:\alan\foo.bat c:\alan\foo.bat +; c:alan\foo.bat c:alan\foo.bat c:alan\foo.bat +; c:foo.bat c:foo.bat c:foo.bat +;--------------- +; CONSTANTS: +;--------------- +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN argbufptr:word + EXTRN comptr:word + EXTRN last_arg:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +;--------------- +parseline: +;--------------- + + push AX ; most of these are clobbered + push BX ; by cparse... + push CX + push DX + push DI + push SI + pushf + mov cpyflag,0 ; Turn "CPARSE called from COPY flag" off + + mov [LAST_ARG], -1 ; last argument at which to accumulate + xor ax,ax + mov cx,SIZE arg_unit + mov di,offset trangroup:arg + rep stosb + mov argbufptr,offset trangroup:arg.argbuf + mov arg.argswinfo, 0 ; switch information, and info to date + mov arg.argvcnt, 0 ; initialize argvcnt/argv[] + mov SI, OFFSET TRANGROUP:combuf+2 ; prescan leaves cooked input in combuf + +; This next section of code (up to pcont:) makes sure that si is set up for +; parsing. It should point at COMBUF if FORFLAG is set and arg.argforcombuf +; otherwise. This is done so that commands can get arg pointers into their +; original command line (or an exact copy of it) in arg_ocomptr. +; Arg.argforcombuf is used so that the for loop processor will always be able +; to get a hold of its original command line; even after COMBUF is blasted by +; the command to be repeated or the transient part of command has been +; reloaded. + + push ds + mov ds,[RESSEG] + assume ds:resgroup + cmp FORFLAG,0 + pop ds + assume ds:trangroup + jnz pcont + mov di,OFFSET TRANGROUP:arg.argforcombuf + xor ch,ch + mov cl,[COMBUF+1] + inc cl + rep movsb + mov si,OFFSET TRANGROUP:arg.argforcombuf + +pcont: + mov DI, OFFSET TRANGROUP:tpbuf ; destination is temporary token buffer + mov BL, ' ' ; no special delimiter, for now + +parseloop: + mov comptr,si ; save ptr into original command buffer + xor BP, BP ; switch information put here by cparse + mov byte ptr [expand_star],0 ; don't expand *'s to ?'s + invoke scanoff ; skip leading blanks... + invoke cparse ; byte off a token (args in SI, DI, BL) + jnc More_prse + or BP,BP ; Check for trailing switch character + jz parsedone + call newarg ; We hit CR but BP is non-zero. The + ; typical cause of this is that a + ; switch char IMMEDIATELY preceeds + ; the CR. We have an argument, but it + ; is sort of an error. + jmp short parsedone ; We're done (found the CR). + +More_prse: + mov cpyflag,2 ; tell CPARSE that 1st token is done + call newarg ; add to argv array (CX has char count) + jnc parseloop ; was everything OK? + jmp short parse_error ; NO, it wasn't -- bug out (CF set) + +parsedone: ; successful completion of parseline + popf + clc + jmp short parse_exit + +parse_error: ; error entry (er, exit) point + popf + stc +parse_exit: ; depend on not changing CF + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + ret + +;--------------- +; parseline ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; NEWARG adds the supplied argstring and cparse data to arg.argv[]. +; ENTRY: +; BH argflags +; CX character count in argstring +; DI pointer to argstring +; comptr ptr to starting loc of current token in original command +; [STARTEL] cparse's answer to where the last element starts +; EXIT: +; argbufptr points to next free section of argbuffer +; arg.argbuf contains null-terminated argument strings +; arg.argvcnt argument count +; arg.argv[] array of flags and pointers +; arg.arg_ocomptr ptr to starting loc of current token in original command +; CF set if error +; AL carry set: error code; otherwise, zero +;--------------- +newarg: +;--------------- + + push BX + push CX + push DX ; one never knows, do one? + push DI + push SI + pushf + call arg_switch ; if it's a switch, record switch info + ; LEAVE SWITCH ON COMMAND LINE!! +;;; jc newarg_done ; previous arg's switches -- and leave + + cmp arg.argvcnt, ARGMAX ; check to ensure we've not + jge too_many_args ; exceeded array limits + mov DH, BH ; save argflags + mov BX, arg.argvcnt ; argv[argvcnt++] = arg data + inc arg.argvcnt + mov AX, OFFSET TRANGROUP:arg.argv + call argv_calc ; convert offset to pointer + mov [BX].argsw_word, 0 ; no switch information, yet... + mov [BX].arglen, CX ; argv[argvcnt].arglen = arg length + mov [BX].argflags, DH ; argv[argvcnt].argflags = cparse flags + mov SI, argbufptr + mov [BX].argpointer, SI ; argv[argvcnt].argpointer = [argbufptr] + add SI, [STARTEL] ; save startel from new location + sub SI, DI ; form pointer into argbuf + mov [BX].argstartel, SI ; argv[argvcnt].argstartel = new [STARTEL] + mov si,[comptr] + mov [BX].arg_ocomptr,si ; arg_ocomptr=ptr into original com line + + mov SI, DI ; now save argstring in argbuffer + mov DI, argbufptr ; load the argbuf pointer and make + add DI, CX ; sure we're not about to run off + cmp DI, OFFSET TRANGROUP:arg.argbuf+ARGBLEN-1 + jge buf_ovflow ; the end of the buffer (plus null byte) + sub DI, CX ; adjust the pointer + cld + rep movsb ; and save the string in argbuffer + mov AL, ANULL ; tack a null byte on the end + stosb + mov argbufptr, DI ; update argbufptr after copy + +newarg_done: + popf + clc + jmp short newarg_exit + +too_many_args: + mov AX, arg_cnt_error + jmp short newarg_error + +buf_ovflow: + mov AX, arg_buf_ovflow + +newarg_error: + popf + stc + +newarg_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + ret + +;--------------- +; NewArg ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; ARG_SWITCH decides if an argument might really be a switch. In the +; event that it is, and we can recognize +; ENTRY: +; As in . +; EXIT: +; CF -- clear (wasn't a switch); set (was a switch) +; NOTE(S): +; * The mechanism mapping a switch into a bit-value depends entirely +; on the order of definition in the variable and the +; values chosen to define the bits in CMDT:COMEQU.ASM. Change either +; or the definitions in CMDT:COMEQU.ASM -- and rewrite +; this mechanism. This code taken from CMDT:TCODE.ASM. +; * The declared below is redundant to one declared in +; TDATA.ASM, and used in TCODE.ASM. +; * An ugly routine. +;--------------- +; CONSTANTS: +;--------------- +; Constants come from the definitions in CMDT:COMEQU.ASM. +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn switch_list:byte + switch_count EQU $-switch_list +transpace ends + +;--------------- +Arg_Switch: +;--------------- + + push AX + push BX + push CX + push DI + pushf + test BH, MASK sw_flag ; is it a switch? (preserve flag word) + jz arg_no_switch0 + cmp [LAST_ARG], -1 ; have we encountered any REAL args yet? + je arg_no_switch1 ; no, so leading switches don't matter + mov BX, [LAST_ARG] ; yes, add switch info to last REAL arg + mov AX, OFFSET TRANGROUP:arg.argv + call argv_calc + or [BX].argsw_word, BP + or arg.argswinfo, BP + +arg_yes_switch: ; ah, sweet success... + popf + stc + jmp short arg_switch_exit + +arg_no_switch0: + mov AX, arg.argvcnt ; future switches should then affect + mov [LAST_ARG], AX ; this argument + +arg_no_switch1: ; wasn't a switch, or we're pretending + popf + clc + +arg_switch_exit: + pop DI + pop CX + pop BX + pop AX + ret + +;--------------- +; Arg_Switch ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; ARGV_CALC maps an array index into a byte-offset from the base of +; the supplied array. Method used for computing the address is: +; Array Index * Array Elt Size + Base Addr = Elt Addr +; ENTRY: +; AX -- base of array +; BX -- array index +; EXIT: +; BX -- byte offset +;--------------- + +argv_calc: + push ax ; Save base + mov al,bl ; al = array index + mov bl,SIZE argv_ele ; bl = size of an argv element + mul bl ; ax = base offset + pop bx ; Get base + add ax,bx ; Add in base offset + xchg ax,bx ; Restore ax and put byte offset in bx + ret + +;--------------- +; argv_calc ends +;---------------------------------------------------------------------------- + + + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/PATH1.ASM b/v4.0/src/CMD/COMMAND/PATH1.ASM new file mode 100644 index 0000000..4567174 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PATH1.ASM @@ -0,0 +1,507 @@ + page 80,132 +; SCCSID = @(#)path1.asm 1.1 85/05/14 +; SCCSID = @(#)path1.asm 1.1 85/05/14 +.sall +.xlist +.xcref +INCLUDE DOSSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + +break +;---------------------------------------------------------------------------- +; PATH.ASM contains the routines to perform pathname incovation. Path and +; Parse share a temporary buffer and argv[] definitions. , +; given a pathname, attempts to find a corresponding executable or batch +; file on disk. Directories specified in the user's search path will be +; searched for a matching file, if a match is not found in the current +; directory and if the pathname is actually only an MSDOS filename. +; assumes that the parsed command name can be found in +; argv[0] -- in other words, should be executed prior to +; . Alternatively, the command name and appropriate +; information could be placed in argv[0], or could be +; (easily) modified to make no assumptions about where its input is found. +; Please find enclosed yet another important routine, , which +; places the entire arg/argv[]/argbuf structure on a piece of newly +; allocated memory. This is handy for for-loop processing, and anything +; else that wants to save the whole shebang and then process other command +; lines. +; +; Alan L, OS/MSDOS August 15, 1983 +; +; ENTRY: +; : argv[0]. +; : bytes to allocate in addition to arg structure +; EXIT: +; : success flag, best pathname match in EXECPATH. +; : success flag, segment address of new memory +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN baddrv_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN BADPMES_ptr:word + EXTRN curdrv:byte + EXTRN EXECPATH:byte + EXTRN search_best_buf:byte + EXTRN search_error:word + EXTRN string_ptr_2:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + +break +;------------------------------------------------------------------------------ +; PATH_SEARCH tries to find the file it's given, somewhere. An initial value +; of *argv[0].argstartel == 0 implies that there is no command (empty line +; or 'd:' or 'd:/'). This check is done in strip; otherwise, strip formats +; the filename/pathname into tpbuf. Search(tpbuf) is executed to see if we +; have a match, either in the current working directory if we were handed +; a filename, or in the specified directory, given a pathname. If this call +; fails, and we were given a pathname, then Path_Search fails. Otherwise, +; Path_Crunch is repeatedly invoked on tpbuf[STARTEL] (if there's a drive +; prefix, we want to skip it) for each pathstring in userpath. Success on +; either the first invocation of search or on one of the succeeding calls +; sets up the appropriate information for copying the successful pathname +; prefix (if any) into the result buffer, followed by the successful filename +; match (from [search_best_buf]). The result is returned in in EXECPATH. +; ENTRY: +; argv[0] -- command name and associated information +; EXIT: +; AX -- non-zero indicates type of file found +; EXECPATH -- successful pathname (AX non-zero) +; NOTE(S): +; 1) Uses the temporary buffer, tpbuf, from the parse routines. +; 2) Some files are more equal than others. See search: for rankings. +; 3) Path_Search terminates as soon as a call to search succeeds, even +; if search returns an .exe or .bat. +; 5) Clobbers dma address. + +pbuflen equ 128 ; length of EXECPATH +path_sep_char equ ';' + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN fbuf:byte + EXTRN pathinfo:word + EXTRN psep_char:byte +TRANSPACE ENDS + +Procedure Path_Search,NEAR + + push BX + push CX + push DX ; could use a "stack 'em" instruction + push SI + push DI + push BP + pushf + test DS:arg.argv[0].argflags, (MASK wildcard) + (MASK sw_flag) + jz path_search_ok + +path_failure_jmp: + jmp path_failure ; ambiguous commands not allowed + +path_search_ok: + call store_pchar ; figure out the pathname separator + mov DX, OFFSET TRANGROUP:fbuf ; clobber old dma value with + trap set_dma ; a pointer to our dma buffer + push ES + invoke find_path ; get a handle (ES:DI) on user path + mov DS:pathinfo[0], ES ; and squirrel it away + mov DS:pathinfo[2], DI ; "old" pathstring pointer + mov DS:pathinfo[4], DI ; "new" pathstring pointer + pop ES + + mov BX, pbuflen ; copy/format argv[0] into temp buffer + mov SI, OFFSET TRANGROUP:EXECPATH + invoke strip + jc path_failure_jmp ; if possible, of course + + mov DX, SI ; search(EXECPATH, error_message) + mov [search_error], OFFSET TRANGROUP:BADDRV_ptr + invoke search ; must do at least one search + or AX, AX ; find anything? + jz path_noinit ; failure ... search farther + + mov BP, AX ; success... save filetype code + mov DI, OFFSET TRANGROUP:EXECPATH + mov SI, DS:arg.argv[0].argpointer + mov CX, DS:arg.argv[0].argstartel + sub CX, SI ; compute prefix bytes to copy +; +; We have the number of bytes in the prefix (up to the final component). +; We need to form the complete pathname including leading drive and current +; directory. +; +; Is there a drive letter present? +; + + mov ah,':' + cmp cx,2 ; room for drive letter? + jb AddDrive ; no, stick it in + cmp [si+1],ah ; colon present? + jz MoveDrive ; yes, just move it + +AddDrive: + mov al,curdrv ; get current drive + add al,"A" ; convert to uppercase letter + stosw ; store d: + jmp short CheckPath + +MoveDrive: + lodsw ; move d: + stosw + sub cx,2 ; 2 bytes less to move + +CheckPath: + or al,20h + mov dl,al + sub dl,"a"-1 ; convert to 1-based for current dir +; +; Stick in beginning path char +; + mov al,psep_char + stosb +; +; Is there a leading /? If so, then no current dir copy is necessary. +; Otherwise, get current dir for DL. +; + cmp cx,1 ; is there room for path char? + jb AddPath ; no, go add path + lodsb + dec cx + cmp al,psep_char ; is there a path separator? + jz MovePath ; yes, go move remainder of path + inc cx + dec si ; undo the lodsb + +AddPath: + SaveReg + mov si,di ; remainder of buffer + trap Current_dir +; +; The previous current dir will succeed a previous find_first already worked. +; +; Find end of string. +; + mov di,si + RestoreReg + mov al,psep_char + cmp byte ptr [di],0 ; root (empty dir string)? + jz MovePath ; yes, no need for path char + +ScanEnd: + cmp byte ptr [dI],0 ; end of string? + jz FoundEnd + inc di + jmp ScanEnd +; +; Stick in a trailing path char +; +FoundEnd: + stosb +; +; Move remaining part of path. Skip leading path char if present. +; +MovePath: + cmp [si],al ; first char a path char? + jnz CopyPath + inc si ; move past leading char + dec cx ; drop from count + +CopyPath: + jcxz CopyDone ; no chars to move! + rep movsb + +CopyDone: + jmp path_success ; run off and form complete pathname + +path_noinit: + test DS:arg.argv[0].argflags, MASK path_sep + jnz path_failure ; complete pathname specified ==> fail + + mov BH, path_sep_char ; semicolon terminates pathstring + mov DX, DS:arg.argv[0].argstartel ; this is where the last element starts + sub DX, DS:arg.argv[0].argpointer ; form pointer into EXECPATH, + add DX, OFFSET TRANGROUP:EXECPATH ; skipping over drive spec, if any + +path_loop: + call path_crunch ; pcrunch(EXECPATH, pathinfo) + mov BP, AX ; save filetype code + + lahf ; save flags, just in case + or BP, BP ; did path_crunch find anything? + jne path_found + sahf ; see? needed those flags, after all! + jnc path_loop ; is there anything left to the path? + +path_failure: + xor AX, AX +;; jmp short path_exit ; 3/3/KK + jmp path_exit ;AC000; 3/3/KK + +path_found: ; pathinfo[] points to winner + mov DI, OFFSET TRANGROUP:EXECPATH + mov CX, pathinfo[4] ; "new" pointer -- end of string + mov SI, pathinfo[2] ; "old" pointer -- beginning of string + +; +; BAS Nov 20/84 +; Look at the pathname and expand . and .. if they are the first element +; in the pathname (after the drive letter) +; + push ES + push pathinfo[0] + pop ES + cmp Byte Ptr ES:[SI+2],'.' ; Look for Current dir at start of path + jnz path_cpy + + push CX ; Save pointer to end of string + mov AL, ES:[SI] + mov [DI],AL ; Copy drive letter, :, and root char + mov AL, ES:[SI+1] ; to EXECPATH + mov [DI+1],AL + mov AL,psep_char + mov [DI+2],AL + push SI ; Save pointer to begining of string + mov DL,ES:[SI] ; Convert device letter for cur dir + or DL,20h + sub DL,"a"-1 + mov SI,DI ; pointer to EXECPATH + add SI, 3 ; Don't wipe out drive and root info + trap Current_dir + invoke DStrlen ; Determine length of present info + add SI,CX ; Don't copy over drive and root info + dec SI + mov DI,SI ; Point to end of target string + pop SI ; Restore pointer to begining of string + add SI, 3 ; Point past drive letter, :, . + pop CX ; Restore pointer to end of string + +path_cpy: + pop ES + sub CX, SI ; yields character count + push DS ; time to switch segments + push pathinfo[0] ; string lives in this segment + pop DS + cld +;; rep movsb 3/3/KK ; copy the prefix path into EXECPATH + +Kloop: ;AN000; 3/3/KK + lodsb ;AN000; 3/3/KK + stosb ;AN000; 3/3/KK + invoke testkanj ;AN000; 3/3/KK + jz NotKanj1 ;AN000; 3/3/KK + dec cx ;AN000; 3/3/KK + JCXZ PopDone ;AN000; Ignore boundary error 3/3/KK + movsb ;AN000; 3/3/KK + dec cx ;AN000; 3/3/KK + cmp cx,1 ;AN000; One char (the terminator) left ? 3/3/KK + ja Kloop ;AN000; no. 3/3/KK + +PopDone: ;AN000; 3/3/KK + POP DS ;AN000; Yes ES:DI->terminator, last char is 3/3/KK + mov AL, psep_char ;AN000; KANJI 3/3/KK + jmp Short path_store ;AN000; 3/3/KK + +NotKanj1: + loop Kloop + pop DS ; return to our segment + dec DI ; overwrite terminator + mov AL, psep_char ; with a pathname separator + cmp al,byte ptr [di-1] + jz path_success + +path_store: ;AN000; 3/3/KK + stosb + +path_success: + mov SI, OFFSET TRANGROUP:search_best_buf + xor CX, CX + +path_succ_loop: + lodsb ; append winning filename to path + stosb ; (including terminating null) + or al,al + jnz path_succ_loop + mov AX, BP ; retrieve filetype code + +path_exit: + popf + pop BP + pop DI + pop SI ; chill out... + pop DX + pop CX + pop BX + ret +EndProc Path_Search + +break +;---------------------------------------------------------------------------- +; STORE_PCHAR determines the pathname-element separator and squirrels +; it away. In other words, must we say '/bin/ls' or '\bin\ls'? +; ENTRY: +; EXIT: +; NOTE(S): +; * Uses , defined in . +;--------------- +;--------------- +Procedure Store_PChar,NEAR +;--------------- + + push AX + mov AL, '/' ; is the pathname-element separator + invoke pathchrcmp ; a regular slash? + jz store_slash ; if yes, remember slash + mov al,'\' + mov [psep_char], al ; otherwise, remember back-slash + pop ax + ret + +store_slash: + mov [psep_char], al + pop ax + return +;--------------- +EndProc Store_Pchar +;---------------------------------------------------------------------------- + +break +;---------------------------------------------------------------------------- +; PATH_CRUNCH takes a prefix from a prefix string, and a suffix from +; EXECPATH, and smooshes them into tpbuf. The caller may supply an +; additional separator to use for breaking up the path-string. Null is the +; default. Once the user-string has been formed, search is invoked to see +; what's out there. +; ENTRY: +; BH -- additional terminator character +; SI -- pointer into pathstring to be dissected +; DX -- pointer to stripped filename +; EXIT: +; AX -- non-zero (file type), zero (nothing found) +; SI -- moves along pathstring from call to call +; [search_best_buf] -- name of best file (AX non-zero) +; [tpbuf] -- clobbered +; NOTE(S): +; * Implicit in this code is the ability to specify when to search +; the current directory (if at all) through the PATH defined by +; the user, a la UNIX (e.g., PATH=;c:\bin;c:\etc searches the +; current directory before the bin and etc directories of drive c). +;--------------- +Procedure Path_Crunch,NEAR +;--------------- + push BX + push CX + push DX + push DI + push SI + pushf + call store_pchar ; figure out pathname separator + mov DI, OFFSET TRANGROUP:tpbuf ; destination of concatenated string + mov SI, pathinfo[4] ; "new" pointer to start with + mov pathinfo[2], SI ; becomes "old" pointer + push DS ; save old segment pointer + push pathinfo[0] ; replace with pointer to userpath's + pop DS ; segment + xor cl,cl ;AN000; clear flag for later use 3/3/KK + +path_cr_copy: + lodsb ; get a pathname byte + or al,al ; check for terminator(s) + jz path_seg ; null terminates segment & pathstring + cmp AL, BH + jz path_seg ; BH terminates a pathstring segment + invoke testkanj ;AN000; 3/3/KK + jz NotKanj2 ;AN000; 3/3/KK + stosb ;AN000; 3/3/KK + movsb ;AN000; 3/3/KK + MOV CL,1 ;AN000; CL=1 means latest stored char is DBCS 3/3/KK + jmp path_cr_copy ;AN000; 3/3/KK + +NotKanj2: ;AN000; 3/3/KK + xor cl,cl ;AN000; CL=0 means latest stored char is SBCS 3/3/KK + stosb ; save byte in concat buffer + jmp path_cr_copy ; loop until we see a terminator + +path_seg: + pop DS ; restore old data segment + mov pathinfo[4], SI ; save "new" pointer for next time + mov BL, AL ; remember if we saw null or not... + ;;; REMOVE NEXT 3 LINES FOR CURDIR SPEC + xor AX, AX ; in case nothing in pathstr... + cmp DI, OFFSET TRANGROUP:tpbuf ; was there really anything in pathstr? + je path_cr_leave ; if nothing was copied, pathstr empty + +path_cr_look: ; form complete pathname + mov al, psep_char ; add pathname separator for suffix + or cl,cl ;AN000; 3/3/KK + jnz path_cr_store ;AN000; this is a trailing byte of ECS code 3/3/KK + cmp al,byte ptr [di-1] + jz path_cr_l1 + +path_cr_store: ;AN000; 3/3/KK + stosb + +path_cr_l1: + mov SI, DX + +path_cr_l2: + lodsb ; tack the stripped filename onto + stosb ; the end of the path, up to and + or AL, AL ; including the terminating null + jnz path_cr_l2 + mov DX, OFFSET TRANGROUP:tpbuf ; and look for an appropriate file... + mov [search_error], OFFSET TRANGROUP:BADPMES_ptr + invoke search ; results are in AX & search_best_buf + +path_cr_leave: + or BL, BL ; did we finish off the pathstring? + jz path_cr_empty ; null in BL means all gone... + popf ; otherwise, plenty left + clc + jmp short path_cr_exit + +path_cr_empty: + popf + stc + +path_cr_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + ret +;--------------- +EndProc Path_Crunch +;---------------------------------------------------------------------------- + + +trancode ends +END diff --git a/v4.0/src/CMD/COMMAND/PATH2.ASM b/v4.0/src/CMD/COMMAND/PATH2.ASM new file mode 100644 index 0000000..8f8d8b8 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PATH2.ASM @@ -0,0 +1,458 @@ + page 80,132 +; SCCSID = @(#)path2.asm 1.1 85/05/14 +; SCCSID = @(#)path2.asm 1.1 85/05/14 +.sall +.xlist +.xcref +INCLUDE DOSSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE + EXTRN FORFLAG:BYTE +DATARES ENDS + + +break +;---------------------------------------------------------------------------- +; PATH.ASM contains the routines to perform pathname incovation. Path and +; Parse share a temporary buffer and argv[] definitions. , +; given a pathname, attempts to find a corresponding executable or batch +; file on disk. Directories specified in the user's search path will be +; searched for a matching file, if a match is not found in the current +; directory and if the pathname is actually only an MSDOS filename. +; assumes that the parsed command name can be found in +; argv[0] -- in other words, should be executed prior to +; . Alternatively, the command name and appropriate +; information could be placed in argv[0], or could be +; (easily) modified to make no assumptions about where its input is found. +; Please find enclosed yet another important routine, , which +; places the entire arg/argv[]/argbuf structure on a piece of newly +; allocated memory. This is handy for for-loop processing, and anything +; else that wants to save the whole shebang and then process other command +; lines. +; +; Alan L, OS/MSDOS August 15, 1983 +; +; ENTRY: +; : argv[0]. +; : bytes to allocate in addition to arg structure +; EXIT: +; : success flag, best pathname match in EXECPATH. +; : success flag, segment address of new memory +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN BADPMES_ptr:word + EXTRN curdrv:byte + EXTRN EXECPATH:byte + EXTRN ext_entered:byte ;AN005; + EXTRN fbuf:byte + EXTRN pathinfo:word + EXTRN psep_char:byte + EXTRN string_ptr_2:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + + +break +;---------------------------------------------------------------------------- +; SEARCH, when given a pathname, attempts to find a file with +; one of the following extensions: .com, .exe, .bat (highest to +; lowest priority). Where conflicts arise, the extension with +; the highest priority is favored. +; ENTRY: +; DX -- pointer to null-terminated pathname +; fbuf -- dma buffer for findfirst/next +; EXIT: +; AX -- 8) file found with .com extension +; 4) file found with .exe extension +; 2) file found with .bat extension +; 0) no such file to be found +; (if AX is non-zero:) +; [search_best] identical to AX +; [search_best_buf] null-terminated filename +; NOTES: +; 1) Requires caller to have allocated a dma buffer and executed a setdma. +;--------------- +; CONSTANTS: +;--------------- +search_file_not_found equ 0 +search_com equ 8 +search_exe equ 4 +search_bat equ 2 +fname_len equ 8 +fname_max_len equ 13 +dot equ '.' +wildchar equ '?' + +;--------------- +; DATA: +;--------------- +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN search_best:byte + EXTRN search_best_buf:byte + EXTRN search_curdir_buf:byte + EXTRN search_error:word +TRANSPACE ENDS + +;--------------- +Procedure Search,NEAR +;--------------- + push CX + push DX + push DI + push SI + pushf + + push DX ; check drivespec (save pname ptr) + mov DI, DX ; working copy of pathname + mov SI, OFFSET TRANGROUP:search_curdir_buf + xor DX, DX ; zero means current drive + cmp BYTE PTR [DI+1],':' ; is there a drive spec? + jne search_dir_check + mov DL, [DI] ; get the drive byte + and DL, NOT 20H ; uppercase the sucker + sub DL, '@' ; and convert to drive number + +search_dir_check: + trap Current_Dir ; can we get the drive's current + pop DX ; directory? If we can't we'll + jc search_invalid_drive ; assume it's a bad drive... + + mov CX, search_attr ; filetypes to search for + trap Find_First ; request first match, if any + jc search_no_file + mov search_best, search_file_not_found + mov [search_best_buf], ANULL ; nothing's been found, yet + +search_loop: + call search_ftype ; determine if .com, &c... + cmp AL, search_best ; better than what we've found so far? + jle search_next ; no, look for another + mov search_best, AL ; found something... save its code + mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname + mov DI, OFFSET TRANGROUP:search_best_buf + mov CX, fname_max_len + cld + rep movsb ; save complete pathname representation + cmp AL, search_com ; have we found the best of all? + je search_done + +search_next: ; keep on looking + mov CX, search_attr + trap Find_Next ; next match + jnc search_loop + +search_done: ; it's all over with... + mov AL, search_best ; pick best to return with + cmp ext_entered,1 ;AN005; Did user request a specific ext? + jz search_exit ;AN005; no - exit + mov al,ext_entered ;AN005; yes - get the real file type back + mov search_best,al ;AN005; save the real file type + jmp short search_exit + +search_invalid_drive: ; Tell the user path/drive + mov DX, [search_error] ; appropriate error message + invoke std_printf ; and pretend no file found + +search_no_file: ; couldn't find a match + mov AX, search_file_not_found + +search_exit: + popf + pop SI + pop DI + pop DX + pop CX + ret +;--------------- +EndProc Search +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; SEARCH_FTYPE determines the type of a file by examining its extension. +; ENTRY: +; fbuf -- dma buffer containing filename +; EXIT: +; AX -- file code, as given in search header +; NOTE(S): +; * Implicit assumption that NULL == search_file_not_found +;--------------- +; DATA: +;--------------- +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + extrn comext:byte,exeext:byte,batext:byte +trandata ends +;--------------- +Procedure Search_Ftype,NEAR +;--------------- + push DI + push si + mov AX, ANULL ; find the end of the filename + mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname + mov CX, fname_max_len + cld + repnz scasb ; search for the terminating null + jnz ftype_exit ; weird... no null byte at end + sub di,5 ; . + E + X + T + NULL +; +; Compare .COM +; + mov si,offset trangroup:comext + mov ax,di + cmpsw + jnz ftype_exe + cmpsw + jnz ftype_exe + mov AX, search_com ; success! + jmp short ftype_exit +; +; Compare .EXE +; + +ftype_exe: ; still looking... now for '.exe' + mov di,ax + mov si,offset trangroup:exeext + cmpsw + jnz ftype_bat + cmpsw + jnz ftype_bat + mov AX, search_exe ; success! + jmp short ftype_exit +; +; Compare .BAT +; + +ftype_bat: ; still looking... now for '.bat' + mov di,ax + mov si,offset trangroup:batext + cmpsw + jnz ftype_fail + cmpsw + jnz ftype_fail + mov AX, search_bat ; success! + jmp short ftype_exit + +ftype_fail: ; file doesn't match what we need + mov ax,ANULL + +ftype_exit: + cmp ext_entered,1 ;AN005; was an extension entered? + jz ftype_done ;AN005; no - exit + cmp ax,ANULL ;AN005; was any match found + jz ftype_done ;AN005; no - exit + mov ext_entered,al ;AN005; save the match type found + mov AX, search_com ;AN005; send back best was found to stop search + +ftype_done: ;AN005; + pop SI + pop DI + ret + +;--------------- +EndProc Search_Ftype +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; STRIP copies the source string (argv[0]) into the destination buffer, +; replacing any extension with wildcards. +; ENTRY: +; BX -- maximum length of destination buffer +; DS:SI -- address of destination buffer +; argv[0] -- command name to be stripped +; EXIT: +; CF -- set if failure, clear if successful +; NOTE(S): +;--------------- +Procedure Strip,NEAR +;--------------- + push AX + push BX + push CX + push DX + push DI + push SI + pushf + + mov ext_entered,1 ;AN005; assume no extension on file name + mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring + mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element + cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command + jz strip_error + mov CX, DX ; compute where end of argstring lies + add CX, DS:arg.argv[0].arglen + sub CX, DI ; and then find length of last element + inc CX ; include null as well + mov AL, dot ; let's find the filetype extension + cld + repnz scasb ; wind up pointing to either null or dot + jcxz process_ext ;AN005; if no extension found, just continue + mov ext_entered,0 ;AN005; we found an extension + mov al,ANULL ;AN005; continue scanning until the + repnz scasb ;AN005; end of line is reached. + +process_ext: ;AN005; + mov CX, DI ; pointer to end of argstring yields + sub CX, DX ; number of bytes to be copied + sub BX, 4 ; can argstring fit into dest. buffer? + cmp CX, BX + jg strip_error ; if not, we must have a bad pathname + mov DI, SI ; destination buffer + mov SI, DX ; source is beginning of pathname + cld + rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg + cmp ext_entered,1 ;AN005; if an extension was entered + jnz skip_wilds ;AN005; don't set up wildcard ext. + + dec DI ; overwrite null or dot + stosb ; with a dot + mov AL, wildchar ; now add wildcards + stosb + stosb + stosb + mov AL, ANULL ; and a terminating null + stosb + +skip_wilds: ;AN005; + popf + clc ; chill out... + jmp short strip_exit + +strip_error: + popf + stc + +strip_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + ret +;--------------- +EndProc Strip +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer +; structure in newly allocated memory. The argv[] structure is found at the +; beginning of this area. The caller indicates how much extra space is +; needed in the resulting structure; Save_Args returns a segment number and +; an offset into that area, indicating where the caller may preserve its own +; data. Note that can be found at . +; ENTRY: +; BX -- size (in bytes) of extra area to allocate +; EXIT: +; AX -- segment of new area. +; CF -- set if unable to save a copy. +; NOTE(S): +; 1) The allocated area will be AT LEAST the size requested -- since +; the underlying MSDOS call, returns an integral number of +; paragraphs. +; 2) It is an error if MSDOS can't allocate AT LEAST as much memory +; as the caller of Save_Args requests. +; 3) AX is undefined if CF indicates an error. +;--------------- +Procedure Save_Args,NEAR +;--------------- + push BX + push CX + push DX + push DI + push SI + push BP + pushf + add BX, SIZE arg_unit + 0FH ; space for arg structure, round up + mov CL, 4 ; to paragraph size and convert + shr BX, CL ; size in bytes to size in paragraphs + trap Alloc + jc save_error + mov BP, AX ; save segment id + push ES ; save TRANGROUP address + mov ES, AX ; switch to new memory segment +assume ES:nothing + mov CX, SIZE arg_unit ; get back structure size + xor DI, DI ; destination is new memory area + mov SI, OFFSET TRANGROUP:arg ; source is arg structure + rep movsb ; move that sucker! + mov CX, arg.argvcnt ; adjust argv pointers + xor AX, AX ; base address for argv_calc + mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf + +save_ptr_loop: + dec CX ; exhausted all args? + jl save_done + mov BX, CX ; get arg index and + invoke argv_calc ; convert to a pointer + mov DX, DS:arg.argv[BX].argpointer + sub DX, SI ; adjust argpointer + mov ES:argv[BX].argpointer, DX + mov DX, DS:arg.argv[BX].argstartel + sub DX, SI ; and adjust argstartel + mov ES:argv[BX].argstartel, DX + mov DX, DS:arg.argv[BX].arg_ocomptr + sub DX, SI ; and adjust arg_ocomptr + mov ES:argv[BX].arg_ocomptr, DX + jmp save_ptr_loop + +save_done: + pop ES ; back we go to TRANGROUP +assume ES:trangroup + mov AX, BP ; restore segment id + jmp short save_ok + +save_error: + popf + stc + jmp short save_exit + +save_ok: + popf + clc +save_exit: + pop BP + pop SI + pop DI + pop DX + pop CX + pop BX + ret +;--------------- +EndProc Save_Args +;---------------------------------------------------------------------------- + +trancode ends +END diff --git a/v4.0/src/CMD/COMMAND/RDATA.ASM b/v4.0/src/CMD/COMMAND/RDATA.ASM new file mode 100644 index 0000000..65fd4bb --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RDATA.ASM @@ -0,0 +1,611 @@ + page 80,132 +; SCCSID = @(#)rdata.asm 4.2 85/09/22 +; SCCSID = @(#)rdata.asm 4.2 85/09/22 +TITLE COMMAND Resident DATA + +include comsw.asm +.xlist +.xcref +include comseg.asm +.list +.cref + +; +; Equates for initialization (from COMEQU) +; +initInit equ 01h ; initialization in progress +initSpecial equ 02h ; in initialization time/date routine +initCtrlC equ 04h ; already in ^C handler + +Tokenized = FALSE + +CODERES SEGMENT PUBLIC BYTE ;AC000; + PUBLIC RSTACK + EXTRN EXT_EXEC:NEAR + EXTRN THEADFIX:NEAR + EXTRN TREMCHECK:NEAR + + DB (80H - 3) DUP (?) + +RSTACK LABEL WORD + +CODERES ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMMAND:NEAR +TRANCODE ENDS + +; Data for resident portion + +DATARES SEGMENT PUBLIC BYTE + + IF Tokenized + PUBLIC IOTYP + PUBLIC MESADD + ENDIF + + PUBLIC abort_char + PUBLIC append_flag ;AN020; + PUBLIC append_state ;AN020; + PUBLIC BADFAT_BLOCK ;AC000; + PUBLIC BADFAT_OP_SEG ;AC000; + PUBLIC BADFAT_SUBST ;AC000; + PUBLIC BATCH + PUBLIC Batch_Abort + PUBLIC call_batch_flag + PUBLIC call_flag + PUBLIC CDEVAT ;AC000; + PUBLIC COM_FCB1 + PUBLIC COM_FCB2 + PUBLIC COM_PTR + PUBLIC COM_XLAT_ADDR + PUBLIC COMDRV + PUBLIC COMPRMT1_BLOCK ;AC000; + PUBLIC COMPRMT1_SEG ;AC000; + PUBLIC COMPRMT1_SEG2 ;AC000; + PUBLIC COMPRMT1_SUBST ;AC000; + PUBLIC COMSPEC + PUBLIC crit_msg_off ;AC000; + PUBLIC crit_msg_seg ;AC000; + PUBLIC critical_msg_start ;AC000; + PUBLIC comspec_print + PUBLIC comspec_end + PUBLIC cpdrv + PUBLIC crit_err_INFO + PUBLIC DATARESEND + PUBLIC dbcs_vector_addr ;AN000; + PUBLIC DEVE_OP_OFF ;AC000; + PUBLIC DEVE_OP_SEG ;AC000; + PUBLIC DEVE_OP_SEG2 ;AC000; + PUBLIC DEVEMES_BLOCK ;AC000; + PUBLIC DEVEMES_SUBST ;AC000; + PUBLIC DEVENAM ;AC000; + PUBLIC DISP_CLASS ;AN000; + PUBLIC DRVLET + PUBLIC DRVNUM_BLOCK ;AC000; + PUBLIC DRVNUM_OP_OFF ;AC000; + PUBLIC DRVNUM_OP_SEG ;AC000; + PUBLIC DRVNUM_OP_SEG2 ;AC000; + PUBLIC DRVNUM_SUBST ;AC000; + PUBLIC ECHOFLAG + PUBLIC ENVIRSEG + PUBLIC ERR15_OP_SEG ;AC000; + PUBLIC ERR15_OP_SEG2 ;AC000; + PUBLIC ERR15_OP_SEG3 ;AC000; + PUBLIC ERR15MES_BLOCK ;AC000; + PUBLIC ERR15MES_SUBST ;AC000; + PUBLIC ERRCD_24 + PUBLIC ErrType + PUBLIC EXEC_BLOCK + PUBLIC EXECEMES_BLOCK ;AC000; + PUBLIC EXECEMES_SUBST ;AC000; + PUBLIC EXECEMES_OFF ;AC000; + PUBLIC EXECEMES_SEG ;AC000; + PUBLIC EXTCOM + PUBLIC extended_msg_start ;AN000; + PUBLIC extmsgend ;AN000; + PUBLIC fail_char ;AC000; + PUBLIC fFail + PUBLIC FORFLAG + PUBLIC forptr + PUBLIC fucase_addr ;AN000; + PUBLIC HANDLE01 + PUBLIC IFFlag + PUBLIC ignore_char + PUBLIC In_Batch + PUBLIC InitFlag + PUBLIC INPIPEPTR + PUBLIC INT_2E_RET + PUBLIC IO_SAVE + PUBLIC LOADING + PUBLIC LTPA + PUBLIC MEMSIZ +;AD054; PUBLIC MESBAS ;AC000; + PUBLIC MYSEG + PUBLIC MYSEG1 + PUBLIC MYSEG2 + PUBLIC nest + PUBLIC next_batch + PUBLIC no_char + PUBLIC NULLFLAG + PUBLIC NUMBER_SUBST ;AN000; + PUBLIC olderrno + PUBLIC OldTerm + PUBLIC OUTPIPEPTR + PUBLIC PARENT +;AD060; PUBLIC pars_msg_off ;AN000; +;AD060; PUBLIC pars_msg_seg ;AN000; + PUBLIC parse_msg_start ;AN000; + PUBLIC PERMCOM + PUBLIC PIPE1 + PUBLIC pipe1t + PUBLIC PIPE2 + PUBLIC pipe2t + PUBLIC PIPEFILES + PUBLIC PIPEFLAG + PUBLIC PIPEPTR + PUBLIC PIPESTR + PUBLIC RDIRCHAR + PUBLIC RE_OUT_APP + PUBLIC RE_OUTSTR + PUBLIC RemMsg + PUBLIC resmsgend ;AN000; + PUBLIC RES_TPA + PUBLIC RESTDIR + PUBLIC ResTest + PUBLIC RETCODE + PUBLIC retry_char + PUBLIC rsrc_xa_seg ;AN030; + PUBLIC RSWITCHAR + PUBLIC SAVE_PDB + PUBLIC SINGLECOM + PUBLIC SUM + PUBLIC SUPPRESS + PUBLIC TRANS + PUBLIC TranVarEnd + PUBLIC TRANVARS + PUBLIC TRNSEG + PUBLIC TrnMvFlg + PUBLIC VERVAL + PUBLIC VolName + PUBLIC VOLSER ;AN000; + PUBLIC yes_char + +;AD054;MESBAS DW 19 ;AC000; error_write_protect +;AD054; DW 20 ;AC000; error_bad_unit +;AD054; DW 21 ;AC000; error_not_ready +;AD054; DW 22 ;AC000; error_bad_command +;AD054; DW 23 ;AC000; error_CRC +;AD054; DW 24 ;AC000; error_bad_length +;AD054; DW 25 ;AC000; error_Seek +;AD054; DW 26 ;AC000; error_not_DOS_disk +;AD054; DW 27 ;AC000; error_sector_not_found +;AD054; DW 28 ;AC000; error_out_of_paper +;AD054; DW 29 ;AC000; error_write_fault +;AD054; DW 30 ;AC000; error_read_fault +;AD054; DW 31 ;AC000; error_gen_failure +;AD054; DW 32 ;AC000; error_sharing_violation +;AD054; DW 33 ;AC000; error_lock_violation +;AD054; DW 34 ;AC000; error_wrong_disk +;AD054; DW 35 ;AC000; error_FCB_unavailable +;AD054; DW 36 ;AC000; error_sharing_buffer_exceeded +;AD054; DW 37 ;AC000; error_code_page_mismatch +;AD054; DW 38 ;AC026; error_out_of_input +;AD054; DW 39 ;AN026; error_insufficient_disk_space + + + +IF Tokenized +MESADD LABEL WORD + DW OFFSET ResGroup:NEWLIN ;"0" + DW OFFSET ResGroup:COM$1 ;"1" + DW OFFSET ResGroup:ERR3 ;"2" + DW OFFSET ResGroup:ALLOC$3 ;"3" + DW OFFSET ResGroup:FILE$4 ;"4" + DW OFFSET ResGroup:RROR$5 ;"5" + DW OFFSET ResGroup:CAN$6 ;"6" + DW OFFSET ResGroup:EMORY$7 ;"7" + DW OFFSET ResGroup:BAT$8 ;"8" + DW OFFSET ResGroup:INS$9 ;"9" + +ERR0 DB "Write protec","t"+80h +ERR1 DB "Bad uni","t"+80h +ERR2 DB "Not read","y"+80h +ERR3 DB "Bad command"," "+80h +ERR4 DB "Dat","a"+80h +ERR5 DB "Bad call forma","t"+80h +ERR6 DB "See","k"+80h +ERR7 DB "Non-DOS dis","k"+80h +ERR8 DB "Sector not foun","d"+80h +ERR9 DB "No pape","r"+80h +ERR10 DB "Write faul","t"+80h +ERR11 DB "Read faul","t"+80h +ERR12 DB "General Failur","e"+80h +ERR13 DB "Sharing Violatio","n"+80h +ERR14 DB "Lock Violatio","n"+80h +ERR15 DB "Invalid Disk Chang","e"+80h +ERR16 DB "FCB unavailabl","e"+80h +ERR17 DB "Sharing buffer exceede","d"+80h + +;--- Extra message for error 15 +Err15Mes db "Please Insert disk " +VolName db 11 dup(?) + db 13,10,"$" + +MREAD DB "read" +MWRITE DB "writ" +ERRMES DB " e5" +IOTYP DB "writin","g"+80h +DRVNUM DB " drive " +DRVLET DB "A" +NEWLIN DB 13,10+80h +DEVEMES DB " device " +DEVENAM DB 8 DUP (?) + DB 13,10,"$" ;Must be $ terminated +COM$1 DB " COMMAN","D"+80h +ALLOC$3 DB " allocation"," "+80h +FILE$4 DB " file"," "+80h +RROR$5 DB "rror"," "+80h +CAN$6 DB "Cannot"," "+80h +EMORY$7 DB "emor","y"+80h +BAT$8 DB " batc","h"+80h +INS$9 DB "Inser","t"+80h + + +CDEVAT DB ? +BADFAT DB "0File 3table bad",","+80h +COMBAD DB "0Invalid1.COM","0"+80h +comprmt1 DB "9 disk with"," "+80h +comprmt2 DB " in drive " +cpdrv DB " " +PROMPT DB "0and strike any key when ready","0"+80h +ENDBATMES DB "0Terminate8 job (Y/N)?"," "+80h +EXECEMES DB "EXEC failure","0"+80h +EXEBAD DB "E5in EXE4","0"+80h +TOOBIG DB "Program too big to fit in m7","0"+80h +NOHANDMES DB "0No free4handle","s"+80h +BMEMMES DB "0M73e","5"+80h +HALTMES DB "06load1, system halte","d"+80h +FRETMES DB "06start1, exiting","0"+80h +RBADNAM DB "2or4name","0"+80h +AccDen DB "Access Denied","0"+80h +Patricide DB 13,10,"Top level process aborted, cannot continue."," "+80h +COMSPEC_PRINT DW ? + +ELSE + + +parm_block_size EQU 11 ;AN000; size of message subst block +blank EQU " " ;AN000; blank character + +DISP_CLASS DB -1 ;AN000; utility message class +NUMBER_SUBST DB 0 ;AN000; number of message substitutions - def 0 + + +DRVNUM_SUBST db 2 ;AN000; number of subst +DRVNUM_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DRVNUM_OP_OFF dw 0 ;AN000;offset of arg +DRVNUM_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg +DRVNUM_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +DRVLET DB "A" + +DEVEMES_SUBST db 2 ;AN000; number of subst +DEVEMES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DEVE_OP_OFF dw 0 ;AN000;offset of arg +DEVE_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DEVENAM ;AN000;offset of arg +DEVE_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_ASCIIZ ;AN000;character string + db 8 ;AN019;maximum width + db 8 ;AN019;minimum width + db blank ;AN000;pad character + +DEVENAM DB 8 DUP (?) + +;--- Extra message for error 15 +ERR15MES_SUBST db 3 ;AN000; number of subst +ERR15MES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLNAME ;AN000;offset of arg +ERR15_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 12 ;AN000;maximum width + db 12 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLSER+2;AN000;offset of arg +ERR15_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db right_align+Bin_Hex_Word ;AN000;long binary to decimal + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLSER ;AN000;offset of arg +ERR15_OP_SEG3 dw 0 ;AN000;segment of arg + db 3 ;AN000;third subst + db right_align+Bin_Hex_Word ;AN000;long binary to decimal + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + +;************************************ +;* DO NOT SEPARATE VOLNAME & VOLSER * +;************************************ + ;* +VolName DB 11 dup(?) ;* + DB 0 ;* +VolSer DD 0 ;* + ;* +;************************************ + + +CDEVAT DB ? + +BADFAT_SUBST db 1 ;AN000; number of subst +BADFAT_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg +BADFAT_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + + +COMPRMT1_SUBST db 2 ;AN000; number of subst +COMPRMT1_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +COMSPEC_PRINT dw ? ;AN000;offset of arg +COMPRMT1_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 64 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:CPDRV ;AN000;offset of arg +COMPRMT1_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +cpdrv DB " " +; +; Exec error messages +; +EXECEMES_SUBST db 1 ;AN000; number of subst +EXECEMES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +EXECEMES_OFF dw 0 ;AN000;offset of arg +EXECEMES_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 64 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; +; These characters MUST remain in order +; +abort_char db "A" +retry_char db "R" +ignore_char db "I" +fail_char db "F" +yes_char db "Y" +no_char db "N" +; +; End of characters that MUST remain in order +; +ENDIF + +RemMsg DD ? ;Pointer to message in error 15 +ErrType DB ? ; Error message style, 0=old, 1=new + +INT_2E_RET DD ? ; Magic command executer return address +SAVE_PDB DW ? +PARENT DW ? +OldTerm DD ? +ERRCD_24 DW ? +HANDLE01 DW ? +LOADING DB 0 +BATCH DW 0 ; Assume no batch mode initially +COMSPEC DB 64 DUP(0) +comspec_end dw ? +TRANS DW OFFSET TRANGROUP:COMMAND +TRNSEG DW ? +; BAS DEBUG +TrnMvFlg DB 0 ; Indicate if transient portion has been moved + +In_Batch DB 0 ; Indicate if we are in Batch processing mode. +Batch_Abort DB 0 ; Indicate if user wants to abort from batch mode. + +COMDRV DB ? ; DRIVE SPEC TO LOAD AUTOEXEC AND COMMAND +MEMSIZ DW ? +SUM DW ? +EXTCOM DB 1 ; For init, pretend just did an external +RETCODE DW ? +CRIT_ERR_INFO DB ? ;G hold critical error flags for R,I,F +rsrc_xa_seg DW -1 ;AN030; holds segment of xa copy buffer + +; +; The echo flag needs to be pushed and popped around pipes and batch files. +; We implement this as a bit queue that is shr/shl for push and pop. +; +ECHOFLAG DB 00000001B ; low bit TRUE => echo commands +SUPPRESS DB 1 ; used for echo, 1=echo line +IO_SAVE DW ? +RESTDIR DB 0 +PERMCOM DB 0 ; TRUE => permanent command +SINGLECOM DW 0 ; TRUE => single command version +VERVAL DW -1 +fFail DB 0 ; TRUE => FAIL all INT 24s +IFFLAG DB 0 ; TRUE => If statement in progress + +FORFLAG DB 0 ; TRUE => FOR statement in progress +FORPTR DW 0 + +NEST DW 0 ; NESTED BATCH FILE COUNTER +CALL_FLAG DB 0 ; NO CALL (BATCH COMMAND) IN PROGRESS +CALL_BATCH_FLAG DB 0 +NEXT_BATCH DW 0 ; ADDRESS OF NEXT BATCH SEGMENT +NULLFLAG DB 0 ; FLAG IF NO COMMAND ON COMMAND LINE +COM_XLAT_ADDR DB 5 DUP (0) ;G BUFFER FOR TRANSLATE TABLE ADDRESS +FUCASE_ADDR DB 5 DUP (0) ;AN000; BUFFER FOR FILE UCASE ADDRESS +CRIT_MSG_OFF DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE OFFSET +CRIT_MSG_SEG DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE SEGMENT +;AD060; PARS_MSG_OFF DW 0 ;AN000; SAVED PARSE ERROR MESSAGE OFFSET +;AD060; PARS_MSG_SEG DW 0 ;AN000; SAVED PARSE ERROR MESSAGE SEGMENT +Dbcs_vector_addr DW 0 ;AN000; DBCS vector offset + DW 0 ;AN000; DBCS vector segment +APPEND_STATE DW 0 ;AN020; current state of append (if flag = -1) +APPEND_FLAG DB 0 ;AN020; set if APPEND state valid + +RE_OUT_APP DB 0 +RE_OUTSTR DB 64+3+13 DUP (?) + +; +; We flag the state of COMMAND in order to correctly handle the ^Cs at +; various times. Here is the breakdown: +; +; initINIT We are in the init code. +; initSpecial We are in the date/time prompt +; initCtrlC We are handling a ^C already. +; +; If we get a ^C in the initialization but not in the date/time prompt, we +; ignore the ^C. This is so the system calls work on nested commands. +; +; If we are in the date/time prompt at initialization, we stuff the user's +; input buffer with a CR to pretend an empty response. +; +; If we are already handling a ^C, we set the carry bit and return to the user +; (ourselves). We can then detect the carry set and properly retry the +; operation. +; + +InitFlag DB initINIT + +;These two bytes refed as a word +PIPEFLAG DB 0 +PIPEFILES DB 0 + +;--- 2.x data for piping +; +; All the "_" are substituted later, the one before the : is substituted +; by the current drive, and the others by the CreateTemp call with the +; unique file name. Note that the first 0 is the first char of the pipe +; name. -MU +; +;--- Order dependant, do not change + +Pipe1 db "_:/" +Pipe1T db 0 + db "_______.___",0 +Pipe2 db "_:/" +Pipe2T db 0 + db "_______.___",0 + +PIPEPTR DW ? +PIPESTR DB 129 DUP(?) +INPIPEPTR DW OFFSET ResGroup:PIPE1 +OUTPIPEPTR DW OFFSET ResGroup:PIPE2 + +EXEC_BLOCK LABEL BYTE ; The data block for EXEC calls +ENVIRSEG DW ? +COM_PTR LABEL DWORD + DW 80H ; Point at unformatted parameters + DW ? +COM_FCB1 LABEL DWORD + DW 5CH + DW ? +COM_FCB2 LABEL DWORD + DW 6CH + DW ? + +TRANVARS LABEL BYTE ; Variables passed to transient + DW OFFSET ResGroup:THEADFIX +MYSEG DW 0 ; Put our own segment here +LTPA DW 0 ; WILL STORE TPA SEGMENT HERE +RSWITCHAR DB "-" +RDIRCHAR DB "/" + DW OFFSET ResGroup:EXT_EXEC +MYSEG1 DW ? + DW OFFSET ResGroup:TREMCHECK +MYSEG2 DW 0 +ResTest DW 0 +RES_TPA DW 0 ; Original TPA (not rounded to 64K) +TranVarEnd LABEL BYTE + +olderrno dw ? + +RESMSGEND DW 0 ;AN000;; holds offset of msg end (end of resident) + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP + +MSG_UTILNAME ;AN000; define utility name + +;AD054; MSG_SERVICES ;AN000; get message services data and resident messages +MSG_SERVICES ;AN054; get message services data and resident messages + + +CRITICAL_MSG_START LABEL BYTE ;AN000; start of critical error messages + +MSG_SERVICES ;AN000; get critical error messages + +DATARESEND LABEL BYTE ;AC060; end of resident portion if /msg not used + +PARSE_MSG_START LABEL BYTE ;AN000; start of parse error messages + +MSG_SERVICES ;AN000; get parse error messages + +;AD060; DATARESEND LABEL BYTE ; end of resident portion if /msg not used + +EXTENDED_MSG_START LABEL BYTE ;AN000; start of extended error messages + +MSG_SERVICES ;AN000; get extended error messages + +EXTMSGEND LABEL BYTE ;AN000; end of extended error messages + +include msgdcl.inc + +DATARES ENDS + END diff --git a/v4.0/src/CMD/COMMAND/RESMSG.EQU b/v4.0/src/CMD/COMMAND/RESMSG.EQU new file mode 100644 index 0000000..9eb5187 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RESMSG.EQU @@ -0,0 +1,43 @@ +; SCCSID = @(#)resmsg.equ 4.1 85/09/10 +; SCCSID = @(#)resmsg.equ 4.1 85/09/10 + +;**************************** +;* RESIDENT MESSAGE EQUATES * +;**************************** + +REQ_ABORT EQU 210 ;AC000; "Abort" +REQ_RETRY EQU 211 ;AC000; ", Retry" +REQ_IGNORE EQU 212 ;AC000; ", Ignore" +REQ_FAIL EQU 213 ;AC000; ", Fail" +REQ_END EQU 214 ;AC000; "? " +MREAD EQU 215 ;AC000; "reading" +MWRITE EQU 216 ;AC000; "writing" +DRVNUM EQU 217 ;AC000; "%1 drive %2" +DEVEMES EQU 218 ;AC000; "%1 device %2" +Err15Mes EQU 219 ;AC000; "Please insert volume %1 serial %2" +BADFAT EQU 220 ;AC000; "File allocation table bad, drive %1" +COMBAD EQU 221 ;AC000; 13,10,"Invalid COMMAND.COM",13,10" +comprmt1 EQU 222 ;AC000; "Insert disk with %1 in drive %1" +PROMPT EQU 223 ;AC000; "Press any key to continue" +ENDBATMES EQU 224 ;AC000; 13,10,"Terminate batch job (Y/N)? " +EXECEMES EQU 225 ;AC000; "Cannot execute %1",13,10 +EXEBAD EQU 226 ;AC000; "Error in EXE file",13,10 +TOOBIG EQU 227 ;AC000; "Program too big to fit in memory",13,10 +NOHANDMES EQU 228 ;AC000; 13,10,"No free file handles" +RBADNAM EQU 229 ;AC000; "Bad Command or file name",13,10 +AccDen EQU 230 ;AC000; Extended error - "Access denied",13,10 +BMEMMES EQU 231 ;AC000; 13,10,"Memory allocation error " +HALTMES EQU 232 ;AC000; 13,10,"Cannot load COMMAND, system halted" +FRETMES EQU 233 ;AC000; 13,10,"Cannot start COMMAND, exiting",13,10 +Patricide EQU 234 ;AC000; 13,10,"Top level process aborted, cannot continue." +NEWLIN EQU 235 ;AC000; 13,10 + +;************************ +;* INIT MESSAGE EQUATES * +;************************ + +BADVER EQU 461 ;AC000; "Incorrect DOS version",13,10,"$" +OUTENVERR_PTR EQU 463 ;AC000; "Out of environment space",13,10,0 +HEADER_PTR EQU 464 ;AC000; Long Copyright Notice +BADCOMLKMES_PTR EQU 465 ;AC000;"Specified COMMAND search directory bad",13,10,0 +BADCOMACCMES_PTR EQU 466 ;AC000; "Specified COMMAND search directory bad access denied",13,10,0 diff --git a/v4.0/src/CMD/COMMAND/RUCODE.ASM b/v4.0/src/CMD/COMMAND/RUCODE.ASM new file mode 100644 index 0000000..5a6f413 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RUCODE.ASM @@ -0,0 +1,739 @@ + page 80,132 +; SCCSID = @(#)rucode.asm 4.5 85/07/22 +; SCCSID = @(#)rucode.asm 4.5 85/07/22 +TITLE COMMAND Language modifiable Code Resident + + +.xlist +.xcref +INCLUDE DOSSYM.INC ;AC000; +include doscntry.inc ;AC000; +DEBUG = 0 ; NEED TO SET IT TO WHAT IT IS IN DOSSYM.INC + + + INCLUDE DEVSYM.INC + INCLUDE comsw.asm + INCLUDE comseg.asm + INCLUDE comequ.asm + include resmsg.equ ;AN000; +.list +.cref + + +Tokenized = FALSE + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN abort_char:byte + EXTRN badfat_block:byte ;AC000; + EXTRN badfat_subst:byte ;AC000; + EXTRN Batch_Abort:byte + EXTRN CDEVAT:BYTE + EXTRN COMSPEC:BYTE ;AN060; + EXTRN com_xlat_addr:word + EXTRN crit_err_info:byte + EXTRN crit_msg_off:word ;AC000; + EXTRN crit_msg_seg:word ;AC000; + EXTRN dbcs_vector_addr:dword ;AN000; + EXTRN devemes_block:byte ;AC000; + EXTRN devemes_subst:byte ;AC000; + EXTRN DEVENAM:BYTE + EXTRN deve_op_off:word ;AC000; + EXTRN disp_class:byte ;AC000; + EXTRN DRVLET:BYTE + EXTRN drvnum_block:byte ;AC000; + EXTRN drvnum_op_off:word ;AC000; + EXTRN drvnum_subst:byte ;AC000; + EXTRN err15mes_block:byte ;AC000; + EXTRN err15mes_subst:byte ;AC000; + EXTRN ERRCD_24:WORD + EXTRN ErrType:BYTE + EXTRN fail_char:byte + EXTRN fFail:BYTE + EXTRN FORFLAG:BYTE + EXTRN ignore_char:byte + EXTRN InitFlag:BYTE + EXTRN In_Batch:byte + EXTRN LOADING:BYTE +;AD054; EXTRN MESBAS:BYTE + EXTRN no_char:byte + EXTRN number_subst:byte ;AC000; + EXTRN olderrno:word + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AC000; +;AD060; EXTRN pars_msg_seg:word ;AC000; + EXTRN PERMCOM:BYTE + EXTRN RemMsg:DWORD + EXTRN retry_char:byte + EXTRN PIPEFLAG:BYTE + EXTRN SINGLECOM:WORD + EXTRN VolName:BYTE + EXTRN yes_char:byte + + IF Tokenized + EXTRN IOTYP:BYTE + EXTRN MESADD:BYTE + ENDIF + +DATARES ENDS + + +CODERES SEGMENT PUBLIC BYTE + + EXTRN GETCOMDSK2:NEAR + + PUBLIC ASKEND + PUBLIC CRLF + PUBLIC DSKERR + PUBLIC ITESTKANJ ;AN000; + PUBLIC RESET_MSG_POINTERS ;AC000; + PUBLIC RPRINT + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; AskEnd - prompt the user to see if he should terminate the batch file. If +; any system call returns with carry set or if RPRINT returns with carry set, +; we jump to the top and start over. +; +; Returns: carry set if response indicates that the batch file should +; be terminated. +; carry clear otherwise. +; + +ASSUME DS:RESGROUP +ASKEND: + MOV DX,ENDBATMES ;AC000; get batch terminate question + CALL RPRINT + MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT + INT 21H + call in_char_xlat ;g change to upper case + CMP AL,no_char + retz ; carry is clear => no free + CMP AL,yes_char + JNZ ASKEND + stc ; carry set => free batch + return + +DSKERR: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + ; ****************************************************** + ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE + ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO + ; INTERCEPT INTERRUPT 24H. + ; ****************************************************** + STI + PUSH DS + PUSH ES + PUSH SI ;AN000; save si + PUSH CX + PUSH DI + PUSH CX + PUSH AX + MOV DS,BP + MOV AX,[SI.SDEVATT] + MOV [CDEVAT],AH + PUSH CS + POP ES + MOV DI,OFFSET RESGROUP:DEVENAM + MOV CX,8 + ADD SI,SDEVNAME ; Suck up device name (even on Block) + REP MOVSB + POP AX + POP CX + POP DI ; Stack just contains DS and ES + ; at this point + INVOKE SAVHAND + PUSH CS + POP DS ; Set up local data segment +ASSUME DS:RESGROUP + + PUSH DX + CALL CRLF + POP DX + MOV CRIT_ERR_INFO,AH ;G save so we know if R,I,F are valid + + ADD AL,'A' ; Compute drive letter (even on character) + MOV [DRVLET],AL + TEST AH,80H ; Check if hard disk error + JZ NOHARDE + TEST [CDEVAT],DEVTYP SHR 8 + JNZ NOHARDE + JMP FATERR + +NOHARDE: + MOV SI,MREAD ;AC000; + TEST AH,1 + JZ SAVMES + MOV SI,MWRITE ;AC000; + +SAVMES: + IF Tokenized + LODSW + MOV WORD PTR [IOTYP],AX + LODSW + MOV WORD PTR [IOTYP+2],AX + ENDIF + + mov olderrno,di ; keep code in a safe place + PUSH ES ;AN000; + PUSH DS ; GetExtendedError likes to STOMP + PUSH BP + PUSH SI + PUSH DX + PUSH CX + PUSH BX + mov ah,GetExtendedError ; get extended error code + INT 21H + POP BX + POP CX + POP DX + POP SI + POP BP + POP DS + mov word ptr cs:[RemMsg],di ;AC000; save pointer to remote message + mov word ptr cs:[RemMsg+2],es ;AC000; (only used on code 15) + pop ES ;AN000; + XOR AH,AH + mov di,ax ; REAL error code to DI +; +; DI is now the correct error code. Classify things to see what we are +; allowed to report. We convert DI into a 0-based index into a message table. +; This presumes that the int 24 errors (oldstyle) and new errors (sharing and +; the like) are contiguous. +; + SUB DI,error_write_protect + JAE HavCod + MOV DI,error_Gen_failure-error_write_protect +; +; DI now has the mapped error code. Old style errors are: +; FOOBAR ing drive ZZ. +; New style errors are: +; FOOBAR +; We need to figure out which the particular error belongs to. +; + +HAVCOD: + mov ErrType,0 ; assume Old style + cmp di,error_FCB_Unavailable-error_write_protect + jz SetStyle + cmp di,error_sharing_buffer_exceeded-error_write_protect + jnz GotStyle + +SetStyle: + mov ErrType,1 ; must be new type + +GotStyle: + MOV [ERRCD_24],DI + cmp di,error_handle_disk_full-error_write_protect ;AC026; + ; If the error message is unknown + jbe NormalError ; redirector, continue. Otherwise, +; +; We do not know how to handle this error. Ask IFSFUNC if she knows +; how to handle things +; + +;input to IFSFUNC: AL=1 +; BX=extended error number + +;output from IFSFUNC: AL=error type (0 or 1) +; 0= error (read/writ)ing (drive/device) xxx +; Abort, Retry, Ignore +; 1= +; Abort, Retry, Ignore +; ES:DI=pointer to message text +; carry set=>no message + + MOV DI,AX ; retrieve correct extended error... + mov ax,0500h ; Is the redir there? + int 2fh + cmp al,0ffh + jnz NoHandler ; No, go to NoHandler + push bx ;AN063; + mov bx,di ; Get ErrType and ptr to error msg ;AC063; + mov ax,0501h ;AC063; + int 2fh + pop bx ;AC063; + jc NoHandler + + mov ErrType,al + push ds + push es + pop ds + mov dx,di + mov cx,-1 ; Find the end of the error msg and turn + xor al,al ; the high byte on for rprint + repnz scasb + + IF Tokenized + or byte ptr [di-2],80h + call rprint ; Print the message + and byte ptr [di-2], NOT 80h ; Restore msg to original condition + ELSE + mov byte ptr [di-1],'$' + MOV AH,Std_con_string_output ;AC000; Print the message + INT 21h ;AN000; + mov byte ptr [di-1],0 ; Restore msg to original condition + ENDIF + + pop ds ; Clean up and continue processing + jmp short CheckErrType + +NoHandler: ; Redir isn't available or doesn't + mov ErrType,0 ; recognize the error. Reset vars and + mov di,olderrno ; regs to unextended err and continue + mov ERRCD_24,di ; normally. + +NormalError: +;AD054; SHL DI,1 +;AD054; MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message + add DI,error_write_protect ;AN054; + XCHG DI,DX ; May need DX later + MOV DISP_CLASS,EXT_CRLF_CLASS ;AN054; printing extended error class + CALL RPRINT ; Print error type + +CheckErrType: + cmp ErrType,0 ; Check error style... + je ContOld + call CRLF ; if new style then done printing + jmp short ASK + +ContOld: + IF NOT Tokenized + MOV AX,SI ;AN000; get reading/writing for message + MOV DH,UTIL_MSG_CLASS ;AN000; this is a utility message + CALL SYSGETMSG ;AN000; get the message + ENDIF + + TEST [CDEVAT],DEVTYP SHR 8 + JZ BLKERR + MOV DX,DEVEMES ;AC000; get message number for device message + MOV DEVE_OP_OFF,SI ;AN000; put address of read/write in subst block + MOV AL,DEVEMES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:DEVEMES_BLOCK;AN000; get address of subst block + + CALL RPRINT ;AC000; print the message + JMP SHORT ASK ; Don't ralph on COMMAND + +BLKERR: + MOV DX,DRVNUM ;AN000; get drive message number + MOV DRVNUM_OP_OFF,SI ;AN000; put address of read/write in subst block + MOV AL,DRVNUM_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:DRVNUM_BLOCK ;AN000; get address of subst block + CALL RPRINT + CMP [LOADING],0 + JZ ASK + INVOKE RESTHAND + JMP GETCOMDSK2 ; If error loading COMMAND, re-prompt + +ASK: + cmp [ERRCD_24],15 ; Wait! Error 15 has an extra message + jne Not15 + PUSH CX + push ds + pop es + lds si,[RemMsg] +assume ds:nothing + push di + mov di,offset resgroup:VolName + mov cx,16 ;AC000; extra message volume name & serial number + cld ; just in case! + rep movsb + pop di + push es + pop ds + POP CX +assume ds:resgroup + mov dx,Err15Mes ;AC000; get message number + MOV AL,ERR15MES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:ERR15MES_BLOCK ;AN000; get address of subst block + CALL RPRINT + +; PRINT OUT ABORT, RETRY, IGNORE, FAIL MESSAGE. ONLY PRINT OUT OPTIONS +; THAT ARE VALID + +Not15: + MOV DX,REQ_ABORT ;AC000;G print out abort message + CALL RPRINT ;G + TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is retry allowed? + JZ TRY_IGNORE ;G + MOV DX,REQ_RETRY ;AC000;G yes,print out retry message + CALL RPRINT ;G + +try_ignore: + TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is ignore allowed? + JZ TRY_FAIL ;G + MOV DX,REQ_IGNORE ;AC000;G yes,print out ignore message + CALL RPRINT ;G + +try_fail: + TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed? + JZ TERM_QUESTION ;G + MOV DX,REQ_FAIL ;AC000;G yes,print out FAIL message + CALL RPRINT ;G + +Term_Question: + MOV DX,REQ_END ;AC000;G terminate the string + CALL RPRINT ;G +; +; If the /f switch was given, we fail all requests... +; + TEST fFail,-1 + JZ DoPrompt + MOV AH,3 ; signal fail + JMP EExit + +DoPrompt: + MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT + INT 21H ; Get response + + invoke TestKanjR ;AN000; 3/3/KK + jz notkanj ;AN000; 3/3/KK + MOV AX,(STD_CON_INPUT SHL 8) ;AN000; eat the 2nd byte of ECS code 3/3/KK + INT 21H ;AN000; 3/3/KK + CALL CRLF ;AN000; 3/3/KK + JMP ASK ;AN000; 3/3/KK + +notkanj: ;AN000; 3/3/KK + CALL CRLF + CALL IN_CHAR_XLAT ;G Convert to upper case + MOV AH,0 ; Return code for ignore + TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is IGNORE allowed? + JZ USER_RETRY ;G + CMP AL,ignore_char ; Ignore? + JZ EEXITJ + +USER_RETRY: + INC AH ; return code for retry + TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is RETRY allowed? + JZ USER_ABORT ;G + CMP AL,retry_char ; Retry? + JZ EEXITJ + +USER_ABORT: + INC AH ; return code for abort - always allowed + CMP AL,abort_char ; Abort? + JZ abort_process ;G exit user program + INC AH ;G return code for fail + TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed? + JZ ASKJ ;G + CMP AL,fail_char ;G fail? + JZ EEXITJ ;G + +ASKJ: + JMP ASK ;G + +EEXITJ: + JMP SHORT EEXIT ;G + +abort_process: + test InitFlag,initINIT ; Was command initialization interrupted + jz AbortCont ; No, handle it normally + cmp PERMCOM,0 ; Is this the top level process? + jz JustExit ; Yes, just exit + mov dx,Patricide ;AC000; No, load ptr to error msg + call RPRINT ; Print it + +DeadInTheWater: + jmp DeadInTheWater ; Loop until the user reboots + +JustExit: +ASSUME DS:RESGROUP + call reset_msg_pointers ;AN000; reset critical & parse message addresses + mov ax,[PARENT] ; Load real parent PID + mov word ptr ds:[PDB_Parent_PID],ax ; Put it back where it belongs + mov ax,(Exit SHL 8) OR 255 + int 21H + +AbortCont: + test byte ptr [In_Batch],-1 ; Are we accessing a batch file? + jz Not_Batch_Abort + mov byte ptr [Batch_Abort],1 ; set flag for abort + +Not_Batch_Abort: + mov dl,PipeFlag + invoke ResPipeOff + OR DL,DL + JZ CHECKFORA + CMP [SINGLECOM],0 + JZ CHECKFORA + MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits + +CHECKFORA: + CMP [ERRCD_24],0 ; Write protect + JZ ABORTFOR + CMP [ERRCD_24],2 ; Drive not ready + JNZ EEXIT ; Don't abort the FOR + +ABORTFOR: + MOV [FORFLAG],0 ; Abort a FOR in progress + CMP [SINGLECOM],0 + JZ EEXIT + MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits + +EEXIT: + MOV AL,AH + MOV DX,DI + +RESTHD: + INVOKE RESTHAND + POP CX + POP SI ;AN000; restore registers + POP ES + POP DS + IRET + +FATERR: + MOV DX,BADFAT ;AC000; + MOV AL,BADFAT_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:BADFAT_BLOCK ;AN000; get address of subst block + CALL RPRINT + + IF Tokenized + MOV DX,OFFSET RESGROUP:ERRMES + CALL RPRINT + ENDIF + + MOV AL,2 ; Abort + JMP RESTHD + +;********************************************* +; Print routines for Tokenized resident messages + +ASSUME DS:RESGROUP,SS:RESGROUP + +CRLF: + MOV DX,NEWLIN ;AC000; + +; +; RPRINT prints out a message on the user's console. We clear carry before +; each system call. We do this so that the ^C checker may change things so +; that carry is set. If we detect a system call that returns with carry set, +; we merely return. +; +; Inputs: DX has the message number as an offset from DS. +; Outputs: Carry clear: no carries detected in the system calls +; Carry set: at least one system call returned with carry set +; Registers modified: none +; + +RPRINT: + +; +; If we are not tokenized, the message consists of a $-terminated string. +; Use CPM io to output it. +; + +if NOT tokenized + PUSH AX + PUSH BX ;AC000; save BX register + PUSH CX ;AC000; save CX register + PUSH DX ;AC000; save DX register + MOV AX,DX ;AC000; get message number + MOV DH,DISP_CLASS ;AC000; get display class + MOV DL,NO_CONT_FLAG ;AN000; set control flags off + MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12 + XOR CH,CH ;AC000; clear upper part of cx + MOV CL,NUMBER_SUBST ;AC000; set number of substitutions + CALL SYSDISPMSG ;AC000; display the message + MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class + MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions + POP DX ;AC000; restore registers + POP CX ;AC000; + POP BX ;AC000; + POP AX + + return +endif + +; +; If we are tokenized, output character-by-character. If there is a digit in +; the output, look up that substring in the tokenization table. Use the high +; bit to determine the end-of-string. +; + +If Tokenized + SaveReg + MOV SI,DX + +RPRINT1: + LODSB + PUSH AX ; save for EOS testing + AND AL,7FH + CMP AL,'0' + JB RPRINT2 + CMP AL,'9' + JA RPRINT2 + SUB AL,'0' + CBW ; DS must be RESGROUP if we get here + SHL AX,1 ; clear carry + XCHG SI,AX + MOV DX,[SI + OFFSET RESGroup:MesADD] + CALL RPrint + XCHG SI,AX + JMP SHORT RPRINT3 + +RPRINT2: + MOV DL,AL + MOV AH,STD_CON_OUTPUT + clc ; set ok flag + INT 21H + +RPRINT3: + POP AX + JC RPrint5 ; Abnormal termination? + TEST AL,80h ; High bit set indicates end (carry clear) + JZ RPRINT1 + +RPRINT5: + RestoreReg + RET +endif + + +;g +;g This routine returns the upper case of the character in AL +;g from the upper case table in DOS if character if above +;g ascii 128, else subtract 20H if between "a" and "z" +;g + +assume ds:resgroup + +in_char_xlat proc near + + cmp al,80h ;g see if char is above ascii 128 + jb other_xlat ;g no - upper case math + sub al,80h ;g only upper 128 characters in table + push ds + push bx + lds bx,dword ptr com_xlat_addr+1 ;g get table address + add bx,2 ;g skip over first word, of table + xlat ds:byte ptr [bx] ;g convert to upper case + pop bx + pop ds + jmp short in_char_xlat_end ;g we finished - exit + +other_xlat: + cmp al,'a' ;g if between "a" and "z", subtract + jb in_char_xlat_end ;g 20h to get upper case + cmp al,'z' ;g equivalent. + ja in_char_xlat_end ;g + sub al,20h ;g Lower-case changed to upper-case + +in_char_xlat_end: + + ret + +in_char_xlat endp +;---------------------- DBCS lead byte check. this is resident code ; 3/3/KK + +ITESTKANJ: ;AN000; +TestKanjR: ;AN000; 3/3/KK + push ds ;AN000; 3/3/KK + push si ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + lds si,dbcs_vector_addr ;AN000; GET DBCS VECTOR + +ktlop: ;AN000; 3/3/KK + cmp word ptr ds:[si],0 ;AN000; 3/3/KK end of Lead Byte Table + je notlead ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jb notlead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jbe islead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + jmp short ktlop ;AN000; 3/3/KK try another range + +Notlead: ;AN000; 3/3/KK + xor ax,ax ;AN000; 3/3/KK set zero + jmp short ktret ;AN000; 3/3/KK + +Islead: ;AN000; 3/3/KK + xor ax,ax ;AN000; 3/3/KK reset zero + inc ax ;AN000; 3/3/KK + +ktret: ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + pop si ;AN000; 3/3/KK + pop ds ;AN000; 3/3/KK + return ;AN000; 3/3/KK + + +; **************************************************************** +; * +; * ROUTINE: RESET_MSG_POINTERS +; * +; * FUNCTION: Resets addresses for parse and critical error +; * messages in DOS via INT 2fh. This routine +; * is invoked before command exits. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +reset_msg_pointers proc near + +assume ds:resgroup, es:nothing + + push es ;AN000; save used registers + push ax ;AN000; + push dx ;AN000; + push di ;AN000; +;AD060; mov ah,multdos ;AN000; reset parse message pointers +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address +;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages +;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages +;AD060; int 2fh ;AN000; go set it + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; reset critical message pointers + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,crit_msg_off ;AN000; old offset of critical messages + mov es,crit_msg_seg ;AN000; old segment of critical messages + int 2fh ;AN000; go set it + pop di ;AN000; restore used registers + pop dx ;AN000; + pop ax ;AN000; + pop es ;AN000; + + ret + + +reset_msg_pointers endp + +PUBLIC MSG_SERV_ST ;AN000; +MSG_SERV_ST LABEL BYTE ;AN000; + +PUBLIC SYSGETMSG,SYSDISPMSG + +ASSUME DS:RESGROUP, ES:RESGROUP + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AC060; include message services macro + +PUBLIC RES_CODE_END ;AN000; +RES_CODE_END LABEL BYTE ;AN000; + +include msgdcl.inc + +CODERES ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TBATCH.ASM b/v4.0/src/CMD/COMMAND/TBATCH.ASM new file mode 100644 index 0000000..6ec51b5 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TBATCH.ASM @@ -0,0 +1,1045 @@ + page 80,132 +; SCCSID = @(#)tbatch.asm 4.5 85/10/01 +; SCCSID = @(#)tbatch.asm 4.5 85/10/01 +TITLE Batch processing routines + + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + include doscntry.inc ;AN000; + include version.inc +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN Batch_Abort:byte + EXTRN call_batch_flag:byte + EXTRN ECHOFLAG:BYTE + EXTRN forflag:byte + EXTRN forptr:word + EXTRN IFFlag:BYTE + EXTRN In_Batch:byte + EXTRN LTPA:WORD + EXTRN Nest:word + EXTRN next_batch:word + EXTRN nullflag:byte + EXTRN PIPEFLAG:BYTE + EXTRN RES_TPA:WORD + EXTRN SINGLECOM:WORD + EXTRN SUPPRESS:BYTE ;AC000; +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADBAT_PTR:WORD + EXTRN Extend_buf_ptr:word ;AC000; + EXTRN Extend_buf_sub:byte ;AN022; + EXTRN msg_disp_class:byte ;AC000; + EXTRN NEEDBAT_PTR:WORD + EXTRN pausemes_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN BatBufPos:WORD + EXTRN BATHAND:WORD + EXTRN bwdbuf:byte ;AN022; + EXTRN BYTCNT:WORD + EXTRN COMBUF:BYTE + EXTRN EXECPATH:BYTE + EXTRN ID:BYTE + EXTRN RCH_ADDR:DWORD + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word ;AC000; + EXTRN TPA:WORD + EXTRN TRAN_TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN tcommand:near + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn arg:byte ; the arg structure! +transpace ends +;--------------- + +Break + +; +; Open the batch file. If we cannot find the batch file. If the media is +; changeable, we prompt for the change. Otherwise, we terminate the batch +; file. Leave segment registers alone. +; + +Procedure PromptBat,NEAR + ASSUME DS:ResGroup,ES:NOTHING + invoke BATOPEN ; attempt to open batch file + retnc + cmp dx,error_file_not_found ;AN022; Ask for diskette if file not found + jz Bat_Remcheck ;AN022; + cmp dx,error_path_not_found ;AN022; Ask for diskette if path not found + jz Bat_Remcheck ;AN022; Otherwise, issue message and exit + invoke output_batch_name ;AN022; set up batch name in bwdbuf + jmp short BatDie ;AN022; + +Bat_Remcheck: ;AN022; Go see if media is removable + CALL [RCH_ADDR] ; DX has error number + JZ AskForBat ; Media is removable +; +; The media is not changeable. Turn everything off. +; + invoke ForOff + invoke PipeOff + MOV IfFlag,AL ; No If in progress. + MOV DX,OFFSET TRANGROUP:BADBAT_ptr + +BatDie: + call BatchOff + PUSH CS + POP DS + ASSUME DS:TranGroup + invoke std_eprintf ;AC022; display message + +; +; TCOMMAND resets the stack. This is the equivalent of a non-local goto. +; + JMP TCOMMAND ; he cleans off stack + +; +; Ask the user to reinsert the batch file +; +ASKFORBAT: + ASSUME DS:ResGroup + PUSH DS + PUSH CS + POP DS + ASSUME DS:TranGroup + MOV DX,OFFSET TRANGROUP:NEEDBAT_ptr ;AN022; + invoke std_eprintf ;Prompt for batch file on stderr + mov dx,offset trangroup:pausemes_ptr ;AN000; get second part of message + invoke std_eprintf ;AN000; print it to stderr + CALL GetKeystroke + POP DS + ASSUME DS:ResGroup + jmp PromptBat +EndProc PromptBat + +;**************************************************************** +;* +;* ROUTINE: Output_batch_name +;* +;* FUNCTION: Sets up batch name to be printed on extended error +;* +;* INPUT: DX - extended error number +;* +;* OUTPUT: Ready to call print routine +;* +;**************************************************************** + +public output_batch_name ;AN022; + +Output_batch_name proc near ;AN022; + + push ds ;AN022; save resident segment + mov ds,[batch] ;AN022; get batch file segment +assume DS:nothing ;AN022; + mov SI,BatFile ;AN022; get offset of batch file + invoke dstrlen ;AN022; get length of string + mov di,offset Trangroup:bwdbuf ;AN022; target for batch name + rep movsb ;AN022; move the name + + push cs ;AN022; get local segment + pop ds ;AN022; +assume DS:trangroup ;AN022; + mov extend_buf_ptr,dx ;AN022; put message number in block + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer + mov string_ptr_2,offset trangroup:bwdbuf ;AN022; point to substitution + mov extend_buf_sub,one_subst ;AN022; set up for one subst + pop ds ;AN022; restore data segment + + ret ;AN022; return + +Output_batch_name endp ;AN022; + +Break + +; +; read the next keystroke. Since there may be several characters in the queue +; after the one we ask for (function keys/Kanji), we need to flush the queue +; AFTER waiting. +; +Procedure GetKeyStroke,NEAR +; +; read any character at any mode, interim mode or not. +; + + PUSH DX ;AN000; 3/3/KK + MOV AX,(ECS_call SHL 8) OR GetInterimMode ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + PUSH DX ;AN000; save interim state 3/3/KK + MOV AX,(ECS_call SHL 8) OR SetInterimMode ;AN000; 3/3/KK + MOV DL,InterimMode ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_INPUT_no_echo + INT int_command ; Get character with KB buffer flush + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT int_command + + MOV AX,(ECS_call SHL 8) OR SetInterimMode ;AN000; 3/3/KK + POP DX ;AN000; restore interim state 3/3/KK + INT int_command ;AN000; 3/3/KK + POP DX ;AN000; 3/3/KK + + return +EndProc GetKeyStroke + +Break + +; +; ReadBat - read a single line from the batch file. Perform all substitutions +; as appropriate +; + +Procedure ReadBat,NEAR + ASSUME DS:ResGroup,ES:TranGroup + mov suppress,yes_echo ;g initialize line suppress status + test byte ptr [Batch_Abort],-1 + jnz Trying_To_Abort + mov byte ptr [In_Batch],1 ; set flag to indicate batch job + CALL PromptBat + +Trying_To_Abort: + MOV DI,OFFSET TRANGROUP:COMBUF+2 + +; +; Save position and try to scan for first non delimiter. +; + +TESTNOP: + MOV AX,DS + MOV DS,Batch + ASSUME DS:NOTHING + PUSH WORD PTR DS:[BatSeek] + PUSH WORD PTR DS:[BatSeek+2] ; save current location. + MOV DS,AX + ASSUME DS:ResGroup + invoke SkipDelim ; skip to first non-delim +; +; If the first non-delimiter is not a : (label), we reseek back to the +; beginning and read the line. +; + CMP AL,':' ; is it a label? + POP CX + POP DX ; restore position in bat file + JZ NopLine ; yes, resync everything. + TEST [BATCH],-1 ; are we done with the batch file? + JZ RdBat + + CMP AL, NO_ECHO_CHAR ;g see if user wants to suppress line + JNZ SET_BAT_POS ;g no - go and set batch file position + MOV SUPPRESS, NO_ECHO ;g yes set flag to indicate + jmp Rdbat ;g go read batch file + +SET_BAT_POS: ;g + PUSH DS + MOV DS,Batch + ASSUME DS:NOTHING + MOV WORD PTR DS:[BatSeek],DX ; reseek back to beginning + MOV WORD PTR DS:[BatSeek+2],CX + POP DS + ASSUME DS:ResGroup + MOV AX,(LSEEK SHL 8) + 0 ; seek back + INT int_command + MOV BatBufPos,-1 ; nuke batch buffer position + xor cx,cx ; Initialize line length to zero + JMP RdBat +; +; The first non-delimiter is a :. This line is not echoed and is ignored. +; We eat characters until a CR is seen. +; + +NOPLINE: + CALL SkipToEOL + invoke GetBatByt ; eat trailing LF + TEST [BATCH],-1 ; are we done with the batch file? + JNZ TESTNOP ; no, go get another line + return ; Hit EOF + +; +; Read a line into the buffer pointed to by ES:DI. If any %s are seen in the +; input, we are to consider two special cases: +; +; %0 to %9 These represent replaceable parameters from the batch segment +; %sym% This is a symbol from the environment +; + +RDBAT: + invoke GetBatByt + inc cx ; Inc the line length + cmp cx,COMBUFLEN ; Is it too long? + jae TooLong ; Yes - handle it, handle it +; +; See if we have a parameter character. +; + CMP AL,'%' ; Check for parameter + JZ NEEDPARM +; +; no parameter character. Store it as usual and see if we are done. +; + +SAVBATBYT: + STOSB + CMP AL,0DH ; End of line found? + JNZ RDBAT ; no, go for more +; +; We have read in an entire line. Decide whether we should echo the command +; line or not. +; + +Found_EOL: + SUB DI,OFFSET TRANGROUP:COMBUF+3 + MOV AX,DI ; remember that we've not counted the CR + MOV ES:[COMBUF+1],AL ; Set length of line + invoke GetBatByt ; Eat linefeed + invoke BATCLOSE + CMP SUPPRESS, NO_ECHO ;G + JZ Reset ;G + test [echoflag],1 ; To echo or not to echo, that is the + jnz try_nextflag + +Reset: + PUSH CS ; question. (Profound, huh?) + POP DS ; Go back to local segment + retz ; no echoing here... +; +; Echo the command line with appropriate CRLF... +; + + +try_nextflag: + cmp nullflag,nullcommand ;G was there a command last time? + jz No_crlf_print ;G no - don't print crlf + invoke CRLF2 ;G Print out prompt + +no_crlf_print: + invoke PRINT_PROMPT ;G + PUSH CS ;G change data segment + POP DS ;G + +ASSUME DS:TRANGROUP + mov dx,OFFSET TRANGROUP:COMBUF+2 ; get command line for echoing + invoke CRPRINT + invoke CRLF2 + return +; +; The line was too long. Eat remainder of input text up until the CR +; +TooLong: + ASSUME DS:ResGroup + cmp al,0dh ; Has the end of the line been reached? + jz Ltlcont ; Yes, continue + CALL SkipToEOL ; Eat remainder of line + +Ltlcont: + stosb ; Terminate the command + jmp Found_EOL ; Go process the valid part of the line +; +; We have found a parameter lead-in character. Check for the 0-9 case first +; + +NEEDPARM: + invoke GetBatByt ; get next character + CMP AL,'%' ; Check for two consecutive % + JZ SAVBATBYT ; if so, replace with a single % + CMP AL,0Dh ; Check for end-of-line + JZ SAVBATBYT ; yes, treat it normally +; +; We have found %. If the is in the range 0-9, we +; retrieve the appropriate parameter from the batch segment. Otherwise we +; see if the has a terminating % and then look up the contents +; in the environment +; +PAROK: + SUB AL,'0' + JB NEEDENV ; look for parameter in the environment + CMP AL,9 + JA NEEDENV +; +; We have found %. This is taken from the parameters in the +; allocated batch area. +; + CBW + MOV BX,AX ; move index into AX + SHL BX,1 ; convert word index into byte ptr + SaveReg + MOV ES,Batch +; +; The structure of the batch area is: +; +; BYTE type of segment +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; +; Get pointer to BX'th argument +; + MOV SI,ES:BatParm[BX] + RestoreReg +; +; Is there a parameter here? +; + CMP SI,-1 ; Check if parameter exists + JNZ Yes_there_is ;G Yes go get it + JMP RDBAT ; Ignore if it doesn't +; +; Copy in the found parameter from batch segment +; + +Yes_there_is: + PUSH DS + MOV DS,Batch + ASSUME DS:NOTHING + dec cx ; Don't count '%' in line length + +CopyParm: + LODSB ; From resident segment + CMP AL,0DH ; Check for end of parameter + JZ EndParam + inc cx ; Inc the line length + cmp cx,COMBUFLEN ; Is it too long? + jae LineTooL ; Yes - handle it, handle it + STOSB + JMP CopyParm +; +; We have copied up to the limit. Stop copying and eat remainder of batch +; line. We need to make sure that the tooLong code isn't fooled into +; believing that we are at EOL. Clobber AL too. +; + +LineTooL: + XOR AL,AL + POP DS + ASSUME DS:RESGROUP + JMP TooLong +; +; We have copied in an entire parameter. Go back for more +; + +EndParam: + POP DS + JMP RDBat +; +; We have found % followed by something other than 0-9. We presume that there +; will be a following % character. In between is an environment variable that +; we will fetch and replace in the batch line with its value. +; + +NEEDENV: + SaveReg + MOV DI,OFFSET TRANGROUP:ID ; temp spot for name + ADD AL,'0' ; reconvert character + STOSB ; store it in appropriate place +; +; loop getting characters until the next % is found or until EOL +; + +GETENV1: + invoke GetBatByt ; get the byte + STOSB ; store it + CMP AL,0Dh ; EOL? + JNZ GETENV15 ; no, see if it the term char +; +; The user entered a string with a % but no trailing %. We copy the string. +; + mov byte ptr es:[di-1],0 ; nul terminate the string + mov si,offset TranGroup:ID ; point to buffer + pop di ; point to line buffer + push cs + pop ds + call StrCpy +IF IBMCOPYRIGHT + dec di + pop ds +ELSE + pop ds + jc LineTooL +ENDIF + jmp SavBatByt + +getenv15: + CMP AL,'%' ; terminating %? + JNZ GETENV1 ; no, go suck out more characters + mov al,'=' ; terminate with = + MOV ES:[DI-1],al +; +; ID now either has a =-terminated string which we are to find in the +; environment or a non =-terminated string which will not be found in the +; environment. +; +GETENV2: + MOV SI,OFFSET TRANGROUP:ID + PUSH CS + POP DS ; DS:SI POINTS TO NAME + ASSUME DS:TRANGROUP + PUSH CX + INVOKE FIND_NAME_IN_environment + ASSUME ES:RESGROUP + POP CX + PUSH ES + POP DS + assume ds:resgroup + PUSH CS + POP ES + ASSUME ES:TRANGROUP + MOV SI,DI + POP DI ; get back pointer to command line +; +; If the parameter was not found, there is no need to perform any replacement. +; We merely pretend that we've copied the parameter. +; +IF IBMCOPYRIGHT + JC GETENV6 +ELSE + jnc GETENV4 + pop ds + jmp rdbat +ENDIF +; +; ES:DI points to command line being built +; DS:SI points either to nul-terminated environment object AFTER = +; + +GETENV4: + ASSUME ES:NOTHING + call StrCpy + +IF IBMCOPYRIGHT + dec di + +GETENV6: + POP DS ; restore pointer to resgroup +ELSE + pop ds + jc LineTooL +ENDIF + JMP RDBAT ; no, go back to batch file + +EndProc ReadBat + +; +; SkipToEOL - read from batch file until end of line +; + +Procedure SkipToEOL,NEAR + + ASSUME DS:ResGroup,ES:NOTHING + + TEST Batch,-1 + retz ; no batch file in effect + invoke GetBatByt + CMP AL,0Dh ; eol character? + JNZ SkipToEOL ; no, go eat another + return + +EndProc SkipToEOL + +Break + +; +; Free Transient. Modify ES,AX,flags +; + +Procedure Free_TPA,NEAR + +ASSUME DS:TRANGROUP,ES:RESGROUP + + PUSH ES + MOV ES,[RESSEG] + MOV ES,[RES_TPA] + MOV AH,DEALLOC + INT int_command ; Make lots of free memory + POP ES + + return + +EndProc Free_TPA + +; +; Allocate transient. Modify AX,BX,DX,flags +; + +Procedure Alloc_TPA,NEAR + +ASSUME DS:TRANGROUP,ES:RESGROUP + + PUSH ES + MOV ES,[RESSEG] + MOV BX,0FFFFH ; Re-allocate the transient + MOV AH,ALLOC + INT int_command + PUSH BX ; Save size of block + MOV AH,ALLOC + INT int_command +; +; Attempt to align TPA on 64K boundary +; + POP BX ; Restore size of block + MOV [RES_TPA], AX ; Save segment to beginning of block + MOV [TRAN_TPA], AX +; +; Is the segment already aligned on a 64K boundary +; + MOV DX, AX ; Save segment + AND AX, 0FFFH ; Test if above boundary + JNZ Calc_TPA + MOV AX, DX + AND AX, 0F000H ; Test if multiple of 64K + JNZ NOROUND + +Calc_TPA: + MOV AX, DX + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JC NOROUND ; Memory wrap if carry set +; +; Make sure that new boundary is within allocated range +; + MOV DX, [RES_TPA] + ADD DX, BX ; Compute maximum address + CMP DX, AX ; Is 64K address out of range? + JB NOROUND +; +; Make sure that we won't overwrite the transient +; + MOV BX, CS ; CS is beginning of transient + CMP BX, AX + JB NOROUND +; +; The area from the 64K boundary to the beginning of the transient must +; be at least 64K. +; + SUB BX, AX + CMP BX, 4096 ; Size greater than 64K? + JAE ROUNDDONE + +NOROUND: + MOV AX, [RES_TPA] + +ROUNDDONE: + MOV [LTPA],AX ; Re-compute everything + MOV [TPA],AX + MOV BX,AX + MOV AX,CS + SUB AX,BX + PUSH BX + MOV BX,16 + MUL BX + POP BX + OR DX,DX + JZ SAVSIZ2 + MOV AX,-1 + +SAVSIZ2: +; +; AX is the number of bytes free in the buffer between the resident and the +; transient with a maximum of 64K-1. We round this down to a multiple of 512. +; + CMP AX,512 + JBE GotSize + AND AX,0FE00h ; NOT 511 = NOT 1FF + +GotSize: + MOV [BYTCNT],AX + POP ES + + return + +EndProc Alloc_TPA + +Break + +; +; The exec search has determined that the user has requested a batch file for +; execution. We parse the arguments, create the batch segment, and signal +; batch processing. +; +Procedure BatCom,NEAR + +ASSUME DS:TRANGROUP, ES:NOTHING + +; +; Batch parameters are read with ES set to segment of resident part +; + + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + cmp es:[call_batch_flag],call_in_progress ;AN043; If in CALL, + jz skip_ioset ;AN043; redirection was already set up + invoke IOSET ; Set up any redirection + +skip_ioset: ;AN043; + CALL FREE_TPA ; G + cmp es:[call_batch_flag],call_in_progress ;G + jz getecho ; G if we're in a call, don't execute +; +; Since BATCH has lower precedence than PIPE or FOR. If a new BATCH file is +; being started it MUST be true that no FOR or PIPE is currently in progress. +; Don't execute if in call +; + invoke ForOff + +getecho: + invoke PipeOff + mov al,EchoFlag ; preserve echo state for chaining + + and al, 1 ; Save current echo state + push ax + + xor ax,ax ;G + test es:[batch],-1 ;G Are we in a batch file? + jz leavebat ;G No, nothing to save + mov ax,es:[batch] ;G get current batch segment + cmp es:[call_batch_flag],call_in_progress ;G + jz leavebat ;G +; +; We are in a chained batch file, save batlast from previous batch segment +; so that if we're in a CALL, we will return to the correct batch file. +; + push es ;G + mov es,ax ;G get current batch segment + mov ax,es:[batlast] ;G get previous batch segment + pop es ;G + +leavebat: ;G + push ax ;G keep segment until new one created + cmp es:[call_batch_flag],call_in_progress ;G are we in a CALL? + jz startbat ;G Yes, keep current batch segment + call BatchOff ;G No, deallocate old batch segment + +; +; Find length of batch file +; + +startbat: ;G + ASSUME ES:RESGROUP + MOV es:[CALL_BATCH_FLAG], 0 ;G reset call flag + mov SI, OFFSET TRANGROUP:EXECPATH + + mov ax,AppendTruename ;AN042; Get the real path where the batch file + int 2fh ;AN042; was found with APPEND + mov ah,Find_First ;AN042; The find_first will return it + mov dx,si ;AN042; Get the string + mov cx,search_attr ;AN042; filetypes to search for + int int_command ;AN042; + + invoke DStrLen +; +; Allocate batch area: +; BYTE type of segment +; WORD segment of last batch file +; WORD segment for FOR command +; BYTE FOR flag state on entry to batch file +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; +; We allocate the maximum size for the command line and use setblock to shrink +; later when we've squeezed out the extra +; + + MOV BX,CX ; length of file name. + ADD BX,0Fh + (SIZE BatchSegment) + COMBUFLEN + 0Fh + ; structure + max len + round up + SaveReg + MOV CL,4 + SHR BX,CL ; convert to paragraphs + PUSH BX ;G save size of batch segment + MOV AH,ALLOC + INT int_command ; Allocate batch segment + POP BX ;G get size of batch segment +; +; This should *NEVER* return an error. The transient is MUCH bigger than +; the batch segment. This may not be true, however, in a multitasking system. +; G This error will occur with nesting of batch files. We also need to +; G make sure that we don't overlay the transient. +; + jc mem_error ;G not enough memory - exit + push ax ;G save batch segment + add ax,bx ;G get end of batch segment + add ax,20h ;G add some tpa work area + mov bx,cs ;G get the transient segment + cmp ax,bx ;G do we end before the transient + pop ax ;G get batch segment back + jb enough_mem ;G we have enough memory - continue + push es ;G no we're hitting the transient + mov es,ax + mov ax,DEALLOC SHL 8 ;G deallocate the batch segment + int int_command + pop es + +mem_error: + jmp no_memory ;G Set up for message and exit + +enough_mem: + MOV [BATCH],AX + CALL ALLOC_TPA +; +; Initialize batch segment +; + RestoreReg ; length of name + POP AX ;G get saved batch segment back + inc es:nest ;G increment # batch files in progress + PUSH ES + MOV ES,[BATCH] +ASSUME ES:NOTHING + MOV ES:[BatType],BatchType ; signal batch file type + MOV ES:[batlast],ax ;G save segment of last batch file + push DS ;G + mov DS,[resseg] ;G set to resident data +ASSUME DS:RESGROUP + xor ax,ax ;G + mov bl,forflag ;G get the current FOR state + mov ES:[batforflag],bl ;G save it in the batch segment + test bl,-1 ;G are we in a FOR? + jz for_not_on ;G no, for segment set to 0 + mov ax,forptr ;G yes, get current FOR segment + mov forflag,0 ;G reset forflag + +for_not_on: + mov ES:[batforptr],ax ;G save FOR segment in batch segment + XOR AX,AX + mov forptr,ax ;G make sure for segment is not active + mov bl,echoflag ;G + pop DS ;G + + mov byte ptr es:[Batechoflag],bl ;G save echo state of parent + MOV WORD PTR ES:[BatSeek],AX ; point to beginning of file + MOV WORD PTR ES:[BatSeek+2],AX +; +; Initialize pointers +; + DEC AX ; put -1 into AX + MOV DI,BatParm ; point to parm area + MOV BX,DI + MOV CX,10 + REP STOSW ; Init to no parms +; +; Move in batch file name +; + MOV CX,DX + rep movsb ; including NUL. +; +; Now copy the command line into batch segment, parsing the arguments along +; the way. Segment will look like this: +; +; CRCR...CRCR...CR 0 +; +; or, in the case of fewer arguments: +; +; CRCR...CR CR CR ... CR 0 +; + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV CX,10 ; at most 10 arguments +; +; Look for beginning of next argument +; +EACHPARM: + invoke SCANOFF ; skip to argument +; +; AL is first non-delimiter. DS:SI points to char = AL +; + CMP AL,0DH ; end of road? + JZ HAVPARM ; yes, no more arguments +; +; If CX = 0 then we have stored the most parm we can. Skip store +; + JCXZ MOVPARM ; Only first 10 parms get pointers +; +; Go into allocated piece and stick in new argument pointer. +; + MOV ES:[BX],DI ; store batch pointer + ADD BX,2 ; advance arg counter +; +; Move the parameter into batch segment +; +MOVPARM: + LODSB ; get byte + INVOKE DELIM ; if delimiter + JZ ENDPARM ; then done with parm + STOSB ; store byte + CMP AL,0DH ; if CR then not delimiter + JZ HAVPARM ; but end of parm list, finish + JMP SHORT MOVPARM +; +; We have copied a parameter up until the first separator. Terminate it with +; CR +; + +ENDPARM: + MOV AL,0DH + STOSB + JCXZ EACHPARM ; if no parameters, don't dec + DEC CX ; remember that we've seen one. + JMP SHORT EACHPARM +; +; We have parsed the entire line. Terminate the arg list +; + +HAVPARM: + XOR AL,AL + STOSB ; Nul terminate the parms +; +; Now we know EXACTLY how big the BATCH segment is. Round up size (from DI) +; into paragraphs and setblock to the appropriate size +; + LEA BX,[DI+15] + MOV CL,4 + SHR BX,CL + MOV AH,SetBlock + INT int_command + + POP ES +ASSUME ES:RESGROUP + PUSH ES + POP DS ; Simply batch FCB setup +ASSUME DS:RESGROUP + CMP [SINGLECOM],-1 + JNZ NOBATSING + MOV [SINGLECOM],0FFF0H ; Flag single command BATCH job + +NOBATSING: +; +; Enter the batch file with the current echo state +; + pop ax ; Get original echo state + mov echoflag,al ;g restore it + JMP TCOMMAND + +; +; The following is executed if there isn't enough memory for batch segment +; + +NO_MEMORY: + assume ds:trangroup,es:resgroup + pop dx ;g even up our stack + pop ax ;g + pop ax ;g + call Alloc_tpa ;g reallocate memory + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block + jmp cerror ;g print error message and go... + +EndProc BatCom + +Procedure BatchOff + + ASSUME DS:NOTHING,ES:NOTHING + + SaveReg + PUSH DS ;G + PUSH BX ;G + MOV ES,ResSeg + MOV DS,ResSeg ;G + ASSUME ES:ResGroup,DS:Resgroup ;G + MOV AX,Batch ; Free the batch segment + OR AX,AX + JZ nofree + + PUSH ES + MOV ES,AX + test [echoflag],1 ;G Is echo on? + jnz echo_last_line ;G Yes - echo last line in file + mov suppress,no_echo ;G no - don't echo last line in file + +echo_last_line: + MOV BL,ES:[BATECHOFLAG] ;G Get echo state + mov [echoflag],bl ;G and restore it + MOV BX,ES:[BATFORPTR] ;G Get FOR segment + MOV FORPTR,BX ;G and restore it + MOV BL,ES:[BATFORFLAG] ;G Get FOR flag + MOV FORFLAG,BL ;G and restore it + MOV BX,es:[batlast] ;G get old batch segment + MOV AH,DEALLOC + INT int_command + POP ES + MOV Next_BATCH,BX ;G reset batch segment + DEC es:NEST ;G + + XOR AX,AX + MOV Batch,AX ; No batch in progress + +NoFree: + POP BX ;G + pop ds ;G + RestoreReg + + return + +EndProc BatchOff + + +IF IBMCOPYRIGHT + +Procedure StrCpy,near + + push ax +cycle: + lodsb + stosb + or al,al + jnz cycle + pop ax + + return + +EndProc StrCpy + +ELSE +; StrCpy - copy string, checking count in CX against COMBUFLEN +; Entry : DS:SI ==> source string +; ES:DI ==> destination string +; CX = current length of destination string +; Exit : string copied, CX updated, Carry set if length limit exceeded +Procedure StrCpy,NEAR + push ax +ccycle: + lodsb + inc cx + cmp cx,COMBUFLEN + jb ccopy + stc ; set carry to signal error + jmp short ccend +ccopy: + stosb + or al,al + jnz ccycle + +ccend: + dec cx ; discount extra byte + dec di ; back up pointer + pop ax + return ; return carry clear +EndProc StrCpy + +ENDIF + +TRANCODE ENDS + END + diff --git a/v4.0/src/CMD/COMMAND/TBATCH2.ASM b/v4.0/src/CMD/COMMAND/TBATCH2.ASM new file mode 100644 index 0000000..501c637 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TBATCH2.ASM @@ -0,0 +1,753 @@ + page 80,132 +; SCCSID = @(#)tbatch2.asm 4.2 85/07/22 +; SCCSID = @(#)tbatch2.asm 4.2 85/07/22 +TITLE Batch processing routines part II + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN Batch_Abort:byte + EXTRN call_batch_flag:byte + EXTRN call_flag:byte + EXTRN IFFlag:BYTE + EXTRN In_Batch:byte + EXTRN Nest:word + EXTRN PIPEFILES:BYTE + EXTRN RETCODE:WORD + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADLAB_PTR:WORD + EXTRN BatBufLen:WORD + EXTRN IFTAB:BYTE + EXTRN SYNTMES_PTR:WORD +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! + EXTRN BatBuf:BYTE + EXTRN BatBufEnd:WORD + EXTRN BatBufPos:WORD + EXTRN BATHAND:WORD + EXTRN COMBUF:BYTE + EXTRN DIRBUF:BYTE + EXTRN GOTOLEN:WORD + EXTRN if_not_count:word + EXTRN IFNOTFLAG:BYTE + EXTRN RESSEG:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN docom1:near + EXTRN tcommand:near + + public $if,iferlev,goto,shift,ifexists,ifnot,forerror,$call + + +Break + +; Get one byte from the batch file and return it in AL. End-of-file returns +; and ends batch mode. DS must be set to resident segment. +; AH, DX destroyed. + +Procedure GETBATBYT,NEAR + +ASSUME DS:RESGROUP + + SaveReg + test byte ptr [Batch_Abort],-1 + jnz BatEOF + TEST Batch,-1 + JZ BatEOF + PUSH ES + MOV ES,Batch + ASSUME ES:NOTHING + ADD WORD PTR ES:[BatSeek],1 + ADC WORD PTR ES:[BatSeek+2],0 + POP ES +; +; See if we have bytes buffered... +; + MOV AX,CS + MOV DS,AX + ASSUME DS:TranGroup + MOV BX,BatBufPos + CMP BX,-1 + JNZ UnBuf +; +; There are no bytes in the buffer. Let's try to fill it up. +; + MOV DX,OFFSET TranGROUP:BatBuf + MOV CX,BatBufLen ; max to read. + MOV BX,BatHand + MOV AH,READ + INT int_command ; Get one more byte from batch file + jnc bat_read_ok ;AN022; if no error - continue + invoke get_ext_error_number ;AN022; get the error + push ds ;AN022; save local segment + mov ds,[resseg] ;AN022; get resident segment +assume ds:resgroup ;AN022; + mov dx,ax ;AN022; put error in DX + invoke output_batch_name ;AN022; set up to print the error + pop ds ;AN022; +assume ds:trangroup ;AN022; + invoke std_eprintf ;AN022; print out the error + mov byte ptr combuf+2,end_of_line_in;AN022; terminate the batch line for parsing + mov byte ptr combuf+3,end_of_line_out ;AN022; terminate the batch line for output + jmp bateof ;AN022; terminate the batch file + +bat_read_ok: ;AN022; + MOV CX,AX + JCXZ BATEOFDS + MOV BatBufEnd,CX + XOR BX,BX + MOV BatBufPos,BX +; +; Buffered bytes! +; +UnBuf: + MOV AL,BatBuf[BX] ; get next byte + INC BX + CMP BX,BatBufEnd ; beyond end of buffer? + JB SetBufPos + MOV BX,-1 + +SetBufPos: + MOV BatBufPos,BX + CMP AL,1AH ; ^Z for termination? + jnz GetByteDone + +BatEOFDS: + ASSUME DS:TranGroup + MOV DS,ResSeg + ASSUME DS:ResGroup + +BATEOF: + invoke BatchOff + CALL BATCLOSE + MOV AL,0DH ; If end-of-file, then end of line + test byte ptr [Batch_Abort],-1 + mov byte ptr [Batch_Abort],0 + jz Cont_Get_Byt + mov di,offset TRANGROUP:COMBUF+2 ; reset pointer to beginning of buffer + xor cx,cx ; zero line length + jmp short GetByteDone + +Cont_Get_Byt: + CMP [SINGLECOM],0FFF0H ; See if we need to set SINGLECOM + JNZ GetByteDone + CMP NEST,0 ;G See if we have nested batch files + JNZ GETBYTEDONE ;G Yes - don't exit just yet + MOV [SINGLECOM],-1 ; Cause termination + +GetByteDone: + RestoreReg + + return + +EndProc GetBatByt + + break <$If - conditional execution> +assume ds:trangroup,es:trangroup + +IFERRORP: + POP AX +IFERROR: +FORERROR: + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + JMP CERROR + +$IF: +; +; Turn off any pipes in progress. +; + push ds ;AN004; save local DS + mov ds,[resseg] ;AN004; get resident segment + assume ds:resgroup ;AN004; + cmp [PIPEFILES],0 ;AN004; Only turn off if present. + jz IFNoPipe ;AN004; no pipe - continue + invoke PipeDel ;AN004; turn off piping + +IFNoPipe: ;AN004; + pop ds ;AN004; get local DS back + assume ds:trangroup ;AN004; + MOV [IFNOTFLAG],0 + mov [if_not_count], 0 + MOV SI,81H + +IFREENT: + invoke SCANOFF + CMP AL,0DH + JZ IFERROR + MOV BP,SI + MOV DI,OFFSET TRANGROUP:IFTAB ; Prepare to search if table + MOV CH,0 + +IFINDCOM: + MOV SI,BP + MOV CL,[DI] + INC DI + JCXZ IFSTRING + JMP SHORT FIRSTCOMP + +IFCOMP: + JNZ IF_DIF ;AC000; + +FIRSTCOMP: + LODSB + MOV AH,ES:[DI] + INC DI + CMP AL,AH + JZ IFLP + OR AH,20H ; Try lower case + CMP AL,AH + +IFLP: + LOOP IFCOMP + +IF_DIF: ;AC000; + LAHF + ADD DI,CX ; Bump to next position without affecting flags + MOV BX,[DI] ; Get handler address + INC DI + INC DI + SAHF + JNZ IFINDCOM + LODSB + CMP AL,0DH + +IFERRORJ: + JZ IFERROR + invoke DELIM + JNZ IFINDCOM + invoke SCANOFF + JMP BX + +IFNOT: + NOT [IFNOTFLAG] + inc [if_not_count] + JMP IFREENT + +; +; We are comparing two strings for equality. First, find the end of the +; first string. +; + +IFSTRING: + PUSH SI ; save away pointer for later compare + XOR CX,CX ; count of chars in first string + +FIRST_STRING: + LODSB ; get character + CMP AL,0DH ; end of line? + JZ IFERRORP ; yes => error + invoke DELIM ; is it a delimiter? + JZ EQUAL_CHECK ; yes, go find equal sign + INC CX ; remember 1 byte for the length + JMP FIRST_STRING ; go back for more +; +; We have found the end of the first string. Unfortunately, we CANNOT use +; scanoff to find the next token; = is a valid separator and will be skipped +; over. +; + +EQUAL_CHECK: + CMP AL,'=' ; is char we have an = sign? + JZ EQUAL_CHECK2 ; yes, go find second one. + CMP AL,0DH ; end of line? + JZ IFERRORPj ;AC004; yes, syntax error + LODSB ; get next char + JMP EQUAL_CHECK +; +; The first = has been found. The next char had better be an = too. +; + +EQUAL_CHECK2: + LODSB ; get potential = char + CMP AL,'=' ; is it good? + jnz iferrorpj ; no, error +; +; Find beginning of second string. +; + invoke SCANOFF + CMP AL,0DH + jz iferrorpj + POP DI +; +; DS:SI points to second string +; CX has number of chars in first string +; ES:DI points to first string +; +; Perform compare to elicit match +; + REPE CMPSB + JZ MATCH ; match found! +; +; No match. Let's find out what was wrong. The character that did not match +; has been advanced over. Let's back up to it. +; + DEC SI +; +; If it is EOL, then syntax error +; + CMP BYTE PTR [SI],0DH + JZ IFERRORJ +; +; Advance pointer over remainder of unmatched text to next delimiter +; + +SKIPSTRINGEND: + LODSB + +NOTMATCH: + CMP AL,0DH + +IFERRORJ2: + JZ IFERRORJ + invoke DELIM + JNZ SKIPSTRINGEND +; +; Signal that we did NOT have a match +; + MOV AL,-1 + JMP SHORT IFRET + +iferrorpj: + jmp iferrorp +; +; The compare succeeded. Was the second string longer than the first? We +; do this by seeing if the next char is a delimiter. +; + +MATCH: + LODSB + invoke DELIM + JNZ NOTMATCH ; not same. + XOR AL,AL + JMP SHORT IFRET + +IFEXISTS: +ifexist_attr EQU attr_hidden+attr_system + +moredelim: + lodsb ; move command line pointer over + invoke delim ; pathname -- have to do it ourselves + jnz moredelim ; 'cause parse_file_descriptor is dumb + mov DX, OFFSET TRANGROUP:dirbuf + trap set_dma + mov BX, 2 ; if(0) [|not](|1) exist[1|2] file(2|3) + add BX, [if_not_count] + mov AX, OFFSET TRANGROUP:arg.argv + invoke argv_calc ; convert arg index to pointer + mov DX, [BX].argpointer ; get pointer to supposed filename + mov CX, ifexist_attr ; filetypes to search for + trap Find_First ; request first match, if any + jc if_ex_c ; carry is how to determine error + xor AL, AL + jmp ifret + +if_ex_c: + mov AL, -1 ; false 'n' fall through... + +IFRET: + TEST [IFNOTFLAG],-1 + JZ REALTEST + NOT AL + +REALTEST: + OR AL,AL + JZ IFTRUE + JMP TCOMMAND + +IFTRUE: + invoke SCANOFF + MOV CX,SI + SUB CX,81H + SUB DS:[80H],CL + MOV CL,DS:[80H] + MOV [COMBUF+1],CL + MOV DI,OFFSET TRANGROUP:COMBUF+2 + CLD + REP MOVSB + MOV AL,0DH + STOSB +; +; Signal that an IF was done. This prevents the redirections from getting +; lost. +; + PUSH DS + MOV DS,ResSeg + ASSUME DS:RESGROUP + MOV IFFlag,-1 + POP DS + ASSUME DS:TRANGROUP +; +; Go do the command +; + JMP DOCOM1 + +iferrorj3: + jmp iferrorj2 + +IFERLEV: + MOV BH,10 + XOR BL,BL + +GETNUMLP: + LODSB + CMP AL,0DH + jz iferrorj3 + invoke DELIM + JZ GOTNUM + SUB AL,'0' + XCHG AL,BL + MUL BH + ADD AL,BL + XCHG AL,BL + JMP SHORT GETNUMLP + +GOTNUM: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AH,BYTE PTR [RETCODE] + POP DS +ASSUME DS:TRANGROUP + XOR AL,AL + CMP AH,BL + JAE IFRET + DEC AL + JMP SHORT IFRET + + + break +assume ds:trangroup,es:trangroup + +; +; Shift the parameters in the batch structure by 1 and set up the new argument. +; This is a NOP if no batch in progress. +; + +Procedure Shift,NEAR + + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AX,[BATCH] ; get batch pointer + OR AX,AX ; in batch mode? + retz ; no, done. + MOV ES,AX ; operate in batch segment + MOV DS,AX + +ASSUME DS:NOTHING,ES:NOTHING + +; +; Now move the batch args down by 1 word +; + MOV DI,BatParm ; point to parm table + LEA SI,[DI+2] ; make source = dest + 2 + MOV CX,9 ; move 9 parameters + REP MOVSW ; SHIFT down +; +; If the last parameter (the one not moved) is empty (= -1) then we are done. +; We have copied it into the previous position +; + CMP WORD PTR [DI],-1 ; if last one was not in use then + retz ; No new parm +; +; This last pointer is NOT nul. Get it and scan to find the next argument. +; Assume, first, that there is no next argument +; + MOV SI,[DI] + MOV WORD PTR [DI],-1 ; Assume no parm +; +; The parameters are CR separated. Scan for end of this parm +; +SKIPCRLP: + LODSB + CMP AL,0DH + JNZ SKIPCRLP +; +; We are now pointing at next arg. If it is 0 (end of original line) then we +; are finished. There ARE no more parms and the pointer has been previously +; initialized to indicate it. +; + CMP BYTE PTR [SI],0 + retz ; End of parms + MOV [DI],SI ; Pointer to next parm as %9 + + return + +EndProc Shift + +; +; Skip delim reads bytes from the batch file until a non-delimiter is seen. +; returns char in AL, carry set -> eof +; + +Procedure SkipDelim,NEAR + + ASSUME DS:ResGroup,ES:NOTHING + TEST Batch,-1 + JZ SkipErr ; batch file empty. OOPS! + CALL GetBatByt ; get a char + invoke Delim ; check for ignoreable chars + JZ SkipDelim ; ignore this char. + clc + return + +SkipErr: + stc + return + +EndProc SkipDelim + + break $Call + +; CALL is an internal command that transfers control to a .bat, .exe, or +; .com file. This routine strips the CALL off the command line, sets +; the CALL_FLAG to indicate a call in progress, and returns control to +; DOCOM1 in TCODE to reprocess the command line and execute the file +; being CALLed. + +$CALL: + +; strip off CALL from command line + + ASSUME DS:trangroup,ES:trangroup + push si + push di + push ax + push cx + mov si,offset trangroup:combuf+2 + invoke scanoff ;get to first non-delimeter + add si,length_call ;point to char past CALL + mov di,offset trangroup:combuf+2 + mov cx,combuflen-length_call ;get length of buffer + rep movsb ;move it + pop cx + pop ax + pop di + pop si + + +; set call flag to indicate call in progress + + push ds + mov ds,[resseg] + ASSUME DS:resgroup,ES:resgroup + mov call_flag, call_in_progress + mov call_batch_flag, call_in_progress +; +; Turn off any pipes in progress. +; + cmp [PIPEFILES],0 ; Only turn off if present. + jz NoPipe + invoke PipeDel +NoPipe: + pop ds + + ret + + break Goto + +GOTO: + +assume ds:trangroup,es:trangroup + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + TEST [BATCH],-1 + retz ; If not in batch mode, a nop + XOR DX,DX + PUSH DS + MOV DS,Batch + MOV WORD PTR DS:[BatSeek],DX ; Back to start + MOV WORD PTR DS:[BatSeek+2],DX ; Back to start + POP DS + +GotoOpen: + invoke promptBat + MOV DI,FCB+1 ; Get the label + MOV CX,11 + MOV AL,' ' + REPNE SCASB + JNZ NOINC + INC CX + +NOINC: + SUB CX,11 + NEG CX + MOV [GOTOLEN],CX +; +; At beginning of file. Skip to first non-delimiter char +; + CALL SkipDelim + JC BadGoto + CMP AL,':' + JZ CHKLABEL + +LABLKLP: ; Look for the label + CALL GETBATBYT + CMP AL,0AH + JNZ LABLKTST +; +; At beginning of line. Skip to first non-delimiter char +; + CALL SkipDelim + JC BadGoto + CMP AL,':' + JZ CHKLABEL + +LABLKTST: + TEST [BATCH],-1 + JNZ LABLKLP + +BadGoto: + CALL BATCLOSE + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADLAB_ptr + JMP CERROR + +; +; Found the :. Skip to first non-delimiter char +; + +CHKLABEL: + CALL SkipDelim + JC BadGoto + MOV DI,FCB+1 + MOV CX,[GOTOLEN] + JMP SHORT GotByte + +NEXTCHRLP: + PUSH CX + CALL GETBATBYT + POP CX + +GotByte: + INVOKE TESTKANJ ;AN000; 3/3/KK + JZ NOTKANJ1 ;AN000; 3/3/KK + CMP AL, ES:[DI] ;AN000; 3/3/KK + JNZ LABLKTST ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + DEC CX ;AN000; 3/3/KK + JCXZ LABLKTST ;AN000; 3/3/KK + PUSH CX ;AN000; 3/3/KK + CALL GETBATBYT ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + CMP AL, ES:[DI] ;AN000; 3/3/KK + JMP SHORT KNEXTLABCHR ;AN000; 3/3/KK + +NOTKANJ1: ;AN000; 3/3/KK + OR AL,20H + CMP AL,ES:[DI] + JNZ TRYUPPER + JMP SHORT NEXTLABCHR + +TRYUPPER: + SUB AL,20H + CMP AL,ES:[DI] + +KNEXTLABCHR: ;AN000; 3/3/KK + JNZ LABLKTST + +NEXTLABCHR: + INC DI + LOOP NEXTCHRLP + CALL GETBATBYT + cmp [GOTOLEN],8 ; Is the label atleast 8 chars long? + jge gotocont ; Yes, then the next char doesn't matter + CMP AL,' ' + JA LABLKTST + +gotocont: + CMP AL,0DH + JZ SKIPLFEED + +TONEXTBATLIN: + CALL GETBATBYT + CMP AL,0DH + JNZ TONEXTBATLIN + +SKIPLFEED: + CALL GETBATBYT + CALL BatClose + + return + +Procedure BatClose,NEAR + + MOV BX,CS:[BATHAND] + CMP BX,5 + JB CloseReturn + MOV AH,CLOSE + INT int_command + +CloseReturn: + mov byte ptr [In_Batch],0 ; reset flag + return + +EndProc BatClose + +; +; Open the BATCH file, If open fails, AL is drive of batch file (A=1) +; Also, fills internal batch buffer. If access denied, then AX = -1 +; + +Procedure BatOpen,NEAR + +ASSUME DS:RESGROUP,ES:TRANGROUP + + PUSH DS + MOV DS,[BATCH] +ASSUME DS:NOTHING + + MOV DX,BatFile + MOV AX,OPEN SHL 8 + INT int_command ; Open the batch file + JC SETERRDL + MOV DX,WORD PTR DS:[BatSeek] + MOV CX,WORD PTR DS:[BatSeek+2] + POP DS +ASSUME DS:RESGROUP + + MOV [BATHAND],AX + MOV BX,AX + MOV AX,LSEEK SHL 8 ; Go to the right spot + INT int_command + MOV BatBufPos,-1 ; nuke batch buffer position + + return + +SETERRDL: + MOV BX,DX + invoke get_ext_error_number ;AN022; get the extended error + mov dx,ax ;AN022; save extended error in DX + MOV AL,[BX] ; Get drive spec + SUB AL,'@' ; A = 1 + POP DS + STC ; SUB mucked over carry + + return + +EndProc BatOpen + + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD1A.ASM b/v4.0/src/CMD/COMMAND/TCMD1A.ASM new file mode 100644 index 0000000..fd662b3 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD1A.ASM @@ -0,0 +1,598 @@ + page 80,132 +; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14 +; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14 +TITLE PART4 COMMAND Transient routines. + +; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm ;AC000; + include ioctl.inc ;AN000; +.list +.cref + +DATARES SEGMENT PUBLIC BYTE ;AN020; + EXTRN append_flag:byte ;AN020; + EXTRN append_state:word ;AN020; +DATARES ENDS ;AN020; + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BadCD_ptr:word + EXTRN bits:word + EXTRN Bytmes_ptr:word + EXTRN comsw:word + EXTRN dir_w_syn:word ;AC000; + EXTRN dirdat_mo_day:word ;AC000; + EXTRN dirdat_yr:word ;AC000; + EXTRN dirdattim_ptr:word + EXTRN dirhead_ptr:word + EXTRN dirtim_hr_min:word ;AC000; + EXTRN Dirmes_ptr:word + EXTRN disp_file_size_ptr:word + EXTRN Dmes_ptr:word + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN msg_disp_class:byte ;AN000; + EXTRN parse_dir:byte ;AC000; + EXTRN slash_p_syn:word ;AC000; + EXTRN string_buf_ptr:word + EXTRN tab_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN bytes_free:word + EXTRN charbuf:byte + EXTRN COM:byte + EXTRN Destisdir:byte + EXTRN Desttail:word + EXTRN dir_num:word + EXTRN Dirbuf:byte + EXTRN dirflag:byte ;AN015; + EXTRN display_ioctl:word ;AC000; + EXTRN display_mode:byte ;AC000; + EXTRN filecnt:word + EXTRN file_size_high:word + EXTRN file_size_low:word + EXTRN fullscr:word + EXTRN ID:byte + EXTRN lincnt:byte ;AC000; + EXTRN linlen:byte + EXTRN linperpag:word ;AC000; + EXTRN msg_numb:word ;AN022; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_syn:word ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN pathcnt:word ;AN000; + EXTRN pathpos:word ;AN000; + EXTRN resseg:word ;AN020; + EXTRN srcbuf:byte ;AC000; + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +TRANSPACE ENDS +;--------------- + + EXTRN cerror:near + EXTRN std_printf:near + + + PUBLIC catalog + + + break Catalog - Directory command +assume ds:trangroup,es:trangroup + +; +; The DIR command displays the contents of a directory. +; +; **************************************************************** +; * +; * ROUTINE: CATALOG - display file(s) in directory +; * +; * FUNCTION: PARSE command line for drive, file, or path name. +; * DIR allows two switches, /P (pause) and /W (wide). +; * If an error occurs issue and error message and +; * transfer control to CERROR. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +CATALOG: + +; +; Set up DTA for dir search firsts +; + mov dx,offset trangroup:Dirbuf ;AC000; Set Disk transfer address + mov ah,Set_DMA ;AC000; + int int_command ;AC000; +; +; Set up defaults for switches and parse the command line. +; + mov msg_numb,0 ;AN022; initialize message flag + mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf + mov [pathpos],di ;AN000; this is start of path + mov [pathcnt],1 ;AN000; initialize length to 1 char + mov al,star ;AN000; initialize srcbuf to *,0d + stosb ;AN000; + mov al,end_of_line_in ;AN000; + stosb ;AN000; + mov si,81H ;AN000; Get command line + mov di,offset trangroup:parse_dir ;AN000; Get adderss of PARSE_DIR + xor cx,cx ;AC000; clear counter for positionals + mov ComSw,cx ;AC000; initialize flags + mov bits,cx ;AC000; initialize switches + mov linperpag,linesperpage ;AC000; Set default for lines per page + mov linlen,normperlin ;AC000; Set number of entries per line + mov lincnt,normperlin ;AC000; + +dirscan: + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jne dirscan_cont ;AN000; No - continue parsing + jmp scandone ;AN000; yes - go process + +dirscan_cont: + cmp ax,result_no_error ;AN000; did we have an error? + jz dirscan_cont2 ;AN000; No - continue parsing + jmp badparm ;AN000; yes - exit + +dirscan_cont2: + cmp parse1_syn,offset trangroup:dir_w_syn ;AN000; was /W entered? + je set_dir_width ;AN000; yes - go set wide lines + cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered? + je set_dir_pause ;AN000; yes - go set pause at end of screen +; +; Must be filespec since no other matches occurred. move filename to srcbuf +; + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + push si ;AN000; save address + invoke move_to_srcbuf ;AC000; move to srcbuf + pop dx ;AC000; get address in DX + +; +; The user may have specified a device. Search for the path and see if the +; attributes indicate a device. +; + mov ah,Find_First ;AC000; find the file + int int_command ;AC000; + jnc Dir_check_device ;AN022; if no error - check device + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_no_more_files ;AN022; was error no file found + jz Dir_fspec_end ;AC022; yes -> obviously not a device + cmp ax,error_path_not_found ;AN022; was error no file found + jz Dir_fspec_end ;AC022; yes -> obviously not a device + jmp dir_err_setup ;AN022; otherwise - go issue error message + +dir_check_device: ;AN022; + test byte ptr (DirBuf+find_buf_attr),attr_device ;AC000; + jz Dir_fspec_end ;AC000; no, go do normal operation + mov ComSw,-2 ;AC000; signal device + +dir_fspec_end: + pop si ;AC000; restore position in line + jmp short dirscan ;AC000; keep parsing + +set_dir_width: + test byte ptr[bits],SwitchW ;AN018; /W already set? + jz ok_set_width ;AN018; no - okay to set width + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp badparm ;AN018; exit + +ok_set_width: + or bits,switchw ;AC000; indicate /w was selected + mov linlen,wideperlin ;AC000; Set number of entries per line + mov lincnt,wideperlin ;AC000; + jmp short dirscan ;AC000; keep parsing + +set_dir_pause: + test byte ptr[bits],SwitchP ;AN018; /p already set? + jz ok_set_pause ;AN018; no - okay to set width + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp badparm ;AN018; exit + +ok_set_pause: + or bits,switchp ;AC000; indicate /p was selected + push cx ;AN000; save necessary registers + push si ;AN000; + mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display + mov bx,stdout ;AN000; lines for stdout + mov ch,ioc_sc ;AN000; type is display + mov cl,get_generic ;AN000; get information + mov dx,offset trangroup:display_ioctl ;AN000; + int int_command ;AN000; + +lines_set: + dec linperpag ;AN000; lines per actual page should + dec linperpag ;AN000; two less than the max + mov ax,linperpag ;AN000; get number of lines into + mov [fullscr],ax ;AC000; screen line counter + pop si ;AN000; restore registers + pop cx ;AN000; + jmp dirscan ;AC000; keep parsing + +; +; The syntax is incorrect. Report only message we can. +; +BadParm: + jmp cerror ;AC000; invalid switches get displayed + +ScanDone: + +; +; Find and display the volume ID on the drive. +; + + invoke okvolarg ;AC000; + mov [filecnt],0 ;AC000; Keep track of how many files found + cmp comsw,0 ;AC000; did an error occur? + jnz doheader ;AC000; yes - don't bother to fix path + + mov dirflag,-1 ;AN015; set pathcrunch called from DIR + invoke pathcrunch ;AC000; set up FCB for dir + mov dirflag,0 ;AN015; reset dirflag + jc DirCheckPath ;AC015; no CHDIRs worked. + jz doheader ;AC015; chdirs worked - path\*.* + mov si,[desttail] ;AN015; get filename back + jmp short DoRealParse ;AN015; go parse it + +DirCheckPath: + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; Is there a message? + jnz dir_err_setup ;AN022; yes - there's an error + cmp [destisdir],0 ;AC000; Were pathchars found? + jz doparse ;AC000; no - no problem + inc comsw ;AC000; indicate error + jmp short doheader ;AC000; go print header + +DirNF: + mov ax,error_file_not_found ;AN022; get message number in control block + +dir_err_setup: + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov extend_buf_ptr,ax ;AN022; + +DirError: + jmp Cerror + +; +; We have changed to something. We also have a file. Parse it into a +; reasonable form, leaving drive alone, leaving extention alone and leaving +; filename alone. We need to special case ... If we are at the root, the +; parse will fail and it will give us a file not found instead of file not +; found. +; +DoParse: + mov si,offset trangroup:srcbuf ;AN000; Get address of source + cmp byte ptr [si+1],colon_char ;AN000; Is there a drive? + jnz dir_no_drive ;AN000; no - keep going + lodsw ;AN000; bypass drive + +dir_no_drive: + cmp [si],".." + jnz DoRealParse + cmp byte ptr [si+2],0 + jnz DoRealParse + inc ComSw + jmp short DoHeader + +DoRealParse: + mov di,FCB ; where to put the file name + mov ax,(Parse_File_Descriptor SHL 8) OR 0EH + int int_command + +; +; Check to see if APPEND installed. If it is installed, set all flags +; off. This will be reset in the HEADFIX routine +; + +DoHeader: + mov ax,AppendInstall ;AN020; see if append installed + int 2fh ;AN020; + cmp al,0 ;AN020; append installed? + je DoHeaderCont ;AN020; no - continue + mov ax,AppendDOS ;AN020; see if append DOS version right + int 2fh ;AN020; + cmp ax,-1 ;AN020; append version correct? + jne DoHeaderCont ;AN020; no - continue + mov ax,AppendGetState ;AN020; Get the state of Append + int 2fh ;AN020; + push ds ;AN020; save current data segment + mov ds,[resseg] ;AN020; get resident segment + assume ds:resgroup ;AN020; + mov append_state,bx ;AN020; save append state + mov append_flag,-1 ;AN020; set append flag + xor bx,bx ;AN020; clear out state + mov ax,AppendSetState ;AN020; Set the state of Append + int 2fh ;AN020; set everything off + pop ds ;AN020; save current data segment + assume ds:trangroup ;AN020; + +; +; Display the header +; + +DoHeaderCont: + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before DIR header + invoke build_dir_string ; get current dir string + mov dx,offset trangroup:Dirhead_ptr + invoke printf_crlf ; bang! + +; +; If there were chars left after parse or device, then invalid file name +; + cmp ComSw,0 + jz DoSearch ; nothing left; good parse + jl DirNFFix ; not .. => error file not found + invoke RestUDir + mov dx,offset TranGroup:BadCD_ptr + jmp Cerror ; was .. => error directory not found +DirNFFix: + invoke RestUDir + jmp DirNF +; +; We are assured that everything is correct. Let's go and search. Use +; attributes that will include finding directories. perform the first search +; and reset our directory afterward. +; +DoSearch: + mov byte ptr DS:[FCB-7],0FFH + mov byte ptr DS:[FCB-1],010H +; +; Caution! Since we are using an extended FCB, we will *also* be returning +; the directory information as an extended FCB. We must bias all fetches into +; DIRBUF by 8 (Extended FCB part + drive) +; + mov ah,Dir_Search_First + mov dx,FCB-7 + int int_command + + push ax ;AN022; save return state + inc al ;AN022; did an error occur? + pop ax ;AN022; get return state back + jnz found_first_file ;AN022; no error - start dir + invoke set_ext_error_msg ;AN022; yes - set up error message + push dx ;AN022; save message + invoke restudir ;AN022; restore user's dir + pop dx ;AN022; restore message + cmp word ptr Extend_Buf_Ptr,Error_No_More_Files ;AN022; convert no more files to + jnz DirCerrorJ ;AN022; file not found + mov Extend_Buf_Ptr,Error_File_Not_Found ;AN022; + +DirCerrorJ: ;AN022; + jmp Cerror ;AN022; exit + +; +; Restore the user's directory. We preserve, though, the return from the +; previous system call for later checking. +; + +found_first_file: + push ax + invoke restudir + pop ax +; +; Main scanning loop. Entry has AL = Search first/next error code. Test for +; no more. +; +DIRSTART: + inc al ; FF = file not found + jnz Display + jmp DirDone ; Either an error or we are finished +; +; Note that we've seen a file and display the found file. +; + +Display: + inc [filecnt] ; Keep track of how many we find + mov si,offset trangroup:dirbuf+8 ; SI -> information returned by sys call + call shoname +; +; If we are displaying in wide mode, do not output the file info +; + test byte ptr[bits],SwitchW ; W switch set? + jz DirTest + jmp nexent ; If so, no size, date, or time + +; +; Test for directory. +; +DirTest: + test [dirbuf+8].dir_attr,attr_directory + jz fileent +; +; We have a directory. Display the field in place of the file size +; + mov dx,offset trangroup:Dmes_ptr + call std_printf + jmp short nofsiz +; +; We have a file. Display the file size +; +fileent: + mov dx,[DirBuf+8].dir_size_l + mov file_size_low,dx + mov dx,[DirBuf+8].dir_size_h + mov file_size_high,dx + mov dx,offset trangroup:disp_file_size_ptr + call std_printf +; +; Display time and date of last modification +; +nofsiz: + mov ax,[DirBuf+8].dir_date ; Get date +; +; If the date is 0, then we have found a 1.x level diskette. We skip the +; date/time fields as 1.x did not have them. +; + or ax,ax + jz nexent ; Skip if no date + mov bx,ax + and ax,1FH ; get day + mov dl,al + mov ax,bx + mov cl,5 + shr ax,cl ; Align month + and al,0FH ; Get month + mov dh,al + mov cl,bh + shr cl,1 ; Align year + xor ch,ch + add cx,80 ; Relative 1980 + cmp cl,100 + jb millenium + sub cl,100 + +millenium: + xchg dh,dl ;AN000; switch month & day + mov DirDat_yr,cx ;AC000; put year into message control block + mov DirDat_mo_day,dx ;AC000; put month and day into message control block + mov cx,[DirBuf+8].dir_time ; Get time + jcxz prbuf ; Time field present? + shr cx,1 + shr cx,1 + shr cx,1 + shr cl,1 + shr cl,1 ; Hours in CH, minutes in CL + xchg ch,cl ;AN000; switch hours & minutes + mov DirTim_hr_min,cx ;AC000; put hours and minutes into message subst block + +prbuf: + mov dx,offset trangroup:DirDatTim_ptr + call std_printf + invoke crlf2 ;AC066;end the line + dec byte ptr [fullscr] ;AC066;count the line + jnz endif04 ;AN066;IF the last on the screen THEN + call check_for_P ;AN066; pause if /P requested + endif04: ;AN066; + jmp scroll ; If not, just continue +;AD061; mov DirDat_yr,0 ;AC000; reset year, month and day +;AD061; mov DirDat_mo_day,0 ;AC000; in control block +;AD061; mov DirTim_hr_min,0 ;AC000; reset hour & minute in control block +; +; We are done displaying an entry. The code between "noexent:" and "scroll:" +; is only for /W case. +; +nexent: + mov bl,[lincnt] ;AN066;save for check for first entry on line + dec [lincnt] ;count this entry on the line + jnz else01 ;AX066;IF last entry on line THEN + mov al,[linlen] + mov [lincnt],al + invoke crlf2 + cmp [fullscr],0 ;AC066;IF have filled the screen THEN + jnz endif02 ;AN066; + call check_for_P ;AN066; reinitialize fullscr, + endif02: ;AN066; IF P requested THEN pause + jmp short endif01 ;AN066; + else01: ;AN066;ELSE since screen not full + cmp bl,[linlen] ;AN066; IF starting new line THEN + jne endif03 ; count the line + dec byte ptr [fullscr] ;AN066; ENDIF + endif03: ;AC066;We are outputting on the same line, between fields, we tab. + mov dx,offset trangroup:tab_ptr ;Output a tab + call std_printf + endif01: ;AX066; +; +; All we need to do now is to get the next directory entry. +; +scroll: + mov ah,Dir_Search_Next + mov dx,FCB-7 ; DX -> Unopened FCB + int int_command ; Search for a file to match FCB + jmp DirStart +; +; If no files have been found, display a not-found message +; +DirDone: + invoke get_ext_error_number ;AN022; get the extended error number + cmp ax,error_no_more_files ;AN022; was error file not found? + jnz dir_err_setup_jmp ;AN022; no - setup error message + test [filecnt],-1 + jnz Trailer + mov ax,error_file_not_found ;AN022; + +dir_err_setup_jmp: ;AN022; + jmp dir_err_setup ;AN022; go setup error msg & print it +; +; If we have printed the maximum number of files per line, terminate it with +; CRLF. +; +Trailer: + mov al,[linlen] + cmp al,[lincnt] ; Will be equal if just had CR/LF + jz mmessage + invoke crlf2 + cmp [fullscr],0 ;AN066;IF on last line of screen THEN + jnz endif06 ;AN066; pause before going on + call check_for_P ;AN066; to number and freespace + endif06: ;AN066; displays + +mmessage: + mov dx,offset trangroup:Dirmes_ptr + mov si,[filecnt] + mov dir_num,si + call std_printf + mov ah,Get_Drive_Freespace + mov dl,byte ptr DS:[FCB] + int int_command + cmp ax,-1 + retz + mul cx ; AX is bytes per cluster + mul bx + mov bytes_free,ax ;AC000; + mov bytes_free+2,dx ;AC000; + MOV DX,OFFSET TRANGROUP:BYTMES_ptr + jmp std_printf + +shoname: + mov di,offset trangroup:charbuf + mov cx,8 + rep movsb + mov al,' ' + stosb + mov cx,3 + rep movsb + xor ax,ax + stosb + push dx + mov dx,offset trangroup:charbuf + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + call std_printf + pop DX + return + +check_for_P PROC NEAR ;AN066; + +test byte ptr[bits],SwitchP ;P switch present? +jz endif05 ;AN066; + mov ax,linperpag ;AN000; transfer lines per page + mov [fullscr],ax ;AC000; to fullscr + invoke Pause +endif05: +ret ;AN066; + +check_for_P ENDP ;AN066; + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TCMD1B.ASM b/v4.0/src/CMD/COMMAND/TCMD1B.ASM new file mode 100644 index 0000000..7a45e9d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD1B.ASM @@ -0,0 +1,730 @@ + page 80,132 +; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14 +; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14 +TITLE PART4 COMMAND Transient routines. + +; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comsw.asm ;AC000; + INCLUDE comequ.asm + INCLUDE ioctl.inc ;AN000; + INCLUDE ea.inc ;AN030; +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN badcpmes_ptr:word ;AC022; + EXTRN Extend_buf_ptr:word ;AC000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN inornot_ptr:word + EXTRN msg_disp_class:byte ;AC000; + EXTRN parse_erase:byte ;AC000; + EXTRN parse_mrdir:byte ;AC000; + EXTRN parse_rename:byte ;AC000; + EXTRN parse_vol:byte ;AC000; + EXTRN PauseMes_ptr:word + EXTRN renerr_ptr:word + EXTRN slash_p_syn:word ;AC000; + EXTRN volmes_ptr:word ;AC000; + EXTRN volmes_ptr_2:word ;AC000; + EXTRN volsermes_ptr:word ;AC000; + EXTRN xa_cp:byte ;AN030; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN bytcnt:word + EXTRN charbuf:byte + EXTRN comsw:word + EXTRN cpyflag:byte ;AC000; + EXTRN curdrv:byte + EXTRN destinfo:byte + EXTRN destisdir:byte + EXTRN dirbuf:byte + EXTRN msg_numb:word ;AN022; + EXTRN one_char_val:byte + EXTRN parse1_addr:dword ;AN000; + EXTRN parse1_syn:word ;AN000; + EXTRN srcbuf:byte ;AN000; + EXTRN string_ptr_2:word ;AN000; + EXTRN TPA:word + EXTRN vol_drv:byte + EXTRN vol_ioctl_buf:byte ;AC000; + EXTRN vol_label:byte ;AC000; + EXTRN vol_serial:dword ;AC000; + EXTRN xa_cp_out:byte ;AN030; + EXTRN xa_cp_length:word ;AN030; + EXTRN xa_list_attr:word ;AC030; + EXTRN zflag:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +transpace ends +;--------------- + + EXTRN cerror:near + EXTRN error_output:near + EXTRN notest2:near + EXTRN slashp_erase:near ;AN000; + EXTRN std_printf:near + EXTRN tcommand:near + + PUBLIC badpath_err ;AN022; + PUBLIC crename + PUBLIC erase + PUBLIC extend_setup ;AN022; + PUBLIC Get_ext_error_number ;AN022; + PUBLIC Get_file_code_page_tag ;AN000; + PUBLIC pause + PUBLIC Set_ext_error_msg ;AN000; + PUBLIC set_file_code_page ;AN000; + PUBLIC typefil + PUBLIC volume + + +assume ds:trangroup,es:trangroup + + break Pause +assume ds:trangroup,es:trangroup + +PAUSE: + mov dx,offset trangroup:pausemes_ptr + call std_printf + invoke GetKeystroke + invoke crlf2 + return + + break Erase + +;**************************************************************** +;* +;* ROUTINE: DEL/ERASE - erase file(s) +;* +;* FUNCTION: PARSE command line for file or path name and /P +;* and invoke PATHCRUNCH. If an error occurs, set +;* up an error message and transfer control to CERROR. +;* Otherwise, transfer control to NOTEST2 if /P not +;* entered or SLASHP_ERASE if /P entered. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: if no error: +;* FCB at 5ch set up with filename(s) entered +;* Current directory set to entered directory +;* +;**************************************************************** + +assume ds:trangroup,es:trangroup + +ERASE: + mov si,81H ;AC000; get command line + mov comsw,0 ;AN000; clear switch indicator + mov di,offset trangroup:parse_erase ;AN000; Get adderss of PARSE_erase + xor cx,cx ;AN000; clear cx,dx + +erase_scan: + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jz good_line ;AN000; yes - done parsing + cmp ax,result_no_error ;AC000; did we have an error? + jnz errj2 ;AC000; yes exit + + cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered? + je set_erase_prompt ;AN000; yes - go set prompt + +; +; Must be filespec since no other matches occurred. move filename to srcbuf +; + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + cmp byte ptr[si+1],colon_char ;AC000; drive specified? + jnz Erase_drive_ok ;AC000; no - continue + cmp byte ptr[si+2],end_of_line_out ;AC000; was only drive entered? + jnz erase_drive_ok ;AC000; no - continue + mov ax,error_file_not_found ;AN022; get message number in control block + jmp short extend_setup ;AC000; exit + +erase_drive_ok: + invoke move_to_srcbuf ;AC000; move to srcbuf + pop si ;AC000; get position back + jmp short erase_scan ;AN000; continue parsing + +set_erase_prompt: + cmp comsw,0 ;AN018; was /P already entered? + jz ok_to_set_erase_prompt ;AN018; no go set switch + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp short errj2 ;AN018; exit + +ok_to_set_erase_prompt: ;AN018; + inc comsw ;AN000; indicate /p specified + jmp short erase_scan ;AN000; continue parsing + +good_line: ;G We know line is good + invoke pathcrunch + jnc checkdr + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; was message flag set? + jnz extend_setup ;AN022; yes - print out message + cmp [destisdir],0 ; No CHDIRs worked + jnz badpath_err ;AC022; see if they should have + +checkdr: + cmp comsw,0 ;AN000; was /p specified + jz notest2j ;AN000; no - go to notest2 + jmp slashp_erase ;AN000; yes - go to slashp_erase + +notest2j: + jmp notest2 + +badpath_err: ;AN022; "Path not found" message + mov ax,error_path_not_found ;AN022; set up error number + +extend_setup: ;AN022; + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC022; get extended message pointer + mov Extend_Buf_ptr,ax ;AN022; get message number in control block +errj2: ;AC022; exit jump + jmp Cerror ;AN022; + + break Rename + +; **************************************************************** +; * +; * ROUTINE: CRENAME - rename file(s) +; * +; * FUNCTION: PARSE command line for one full filespec and one +; * filename. Invoke PATHCRUNCH on the full filespec. +; * Make sure the second filespec only contains a +; * filename. If both openands are valid, attempt +; * to rename the file. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +CRENAME: + + mov si,81H ;AC000; Point to command line + mov di,offset trangroup:parse_rename;AN000; Get adderss of PARSE_RENAME + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jz crename_no_parse_error ;AC000; no - continue + JMP crename_parse_error ;AC000; Yes, fail. (need long jump) + +; +; Get first file name returned from parse into our buffer +; +crename_no_parse_error: + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + invoke move_to_srcbuf ;AN000; move to srcbuf + pop si ;AN000; restore position in line + + xor dx,dx ;AN000; clear dx + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AN000; did we have an error? + JNZ crename_parse_error ;AN000; Yes, fail. + +; +; Check the second file name for drive letter colon +; + push si ;AN000; save position in line + lds si,parse1_addr ;AC000; get address of path + + mov al,':' ;AC000; + cmp [si+1],al ;AC000; Does the 2nd parm have a drive spec? + jnz ren_no_drive ;AN000; Yes, error + mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,BadParm_ptr ;AN000; get "Invalid parameter" message number + + pop si ;AN000; +crename_parse_error: ;AC022; + jmp short errj ;AC000; + +; +; Get second file name returned from parse into the fCB. Save +; character after file name so we can later check to make sure it +; isn't a path character. +; + +ren_no_drive: + mov di,FCB+10H ;AC000; set up to parse second file name + mov ax,(Parse_File_Descriptor SHL 8) OR 01H ;AC000; + int int_command ;AC000; do the function + lodsb ;AC000; Load char after filename + mov one_char_val,al ;AN000; save char after filename + pop si ;AN000; get line position back + +; +; We have source and target. See if any args beyond. +; + + mov di,offset trangroup:parse_rename;AC000; get address of parse_rename + invoke parse_check_eol ;AC000; are we at end of line? + jnz crename_parse_error ;AN000; no, fail. + + invoke pathcrunch + mov dx,offset trangroup:badcpmes_ptr + jz errj2 ; If 1st parm a dir, print error msg + jnc notest3 + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; was message flag set? + jnz extend_setup ;AN022; yes - print out message + cmp [destisdir],0 ; No CHDIRs worked + jz notest3 ; see if they should have + Jmp badpath_err ;AC022; set up error + +notest3: + mov al,one_char_val ;AN000; move char into AX + mov dx,offset trangroup:inornot_ptr ; Load invalid fname error ptr + invoke pathchrcmp ; Is the char in al a path sep? + jz errj ; Yes, error - 2nd arg must be + ; filename only. + + mov ah,FCB_Rename + mov dx,FCB + int int_command + cmp al, 0FFH ; Did an error occur?? + jnz renameok + + invoke get_ext_error_number ;AN022; get extended error + SaveReg ;AC022; Save results + mov al, 0FFH ; Restore original error state + +renameok: + push ax + invoke restudir + pop ax + inc al + retnz + + RestoreReg ;AC022; get the error number back + cmp ax,error_file_not_found ;AN022; error file not found? + jz use_renerr ;AN022; yes - use generic error message + cmp ax,error_access_denied ;AN022; error file not found? + jz use_renerr ;AN022; yes - use generic error message + jmp extend_setup ;AN022; need long jump - use extended error + +use_renerr: + mov dx,offset trangroup:RenErr_ptr ;AC022; + +ERRJ: + jmp Cerror + +ret56: ret + + break Type + +;**************************************************************** +;* +;* ROUTINE: TYPEFIL - Display the contents of a file to the +;* standard output device +;* +;* SYNTAX: TYPE filespec +;* +;* FUNCTION: If a valid filespec is found, read the file until +;* 1Ah and display the contents to STDOUT. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: none +;* +;**************************************************************** + +assume ds:trangroup,es:trangroup + +TYPEFIL: + mov si,81H + mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jnz typefil_parse_error ;AN000; yes - issue error message + + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + invoke move_to_srcbuf ;AC000; move to srcbuf + pop si ;AC000; get position back + mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir + invoke parse_check_eol ;AC000; are we at end of line? + jz gottarg ;AC000; yes - continue + +typefil_parse_error: ;AN000; no - set up error message and exit + jmp Cerror + +gottarg: + invoke setpath + test [destinfo],00000010b ; Does the filespec contain wildcards + jz nowilds ; No, continue processing + mov dx,offset trangroup:inornot_ptr ; Yes, report error + jmp Cerror +nowilds: + mov ax,ExtOpen SHL 8 ;AC000; open the file + mov bx,read_open_mode ;AN000; get open mode for TYPE + xor cx,cx ;AN000; no special files + mov dx,read_open_flag ;AN000; set up open flags + mov di,-1 ;AN030; no parm list + mov si,offset trangroup:srcbuf ;AN030; get file name + int int_command + jnc typecont ; If open worked, continue. Otherwise load + +Typerr: ;AN022; + push cs ;AN022; make sure we have local segment + pop ds ;AN022; + invoke set_ext_error_msg ;AN022; + +Typerr2: ;AN022; + mov string_ptr_2,offset trangroup:srcbuf ;AC022; get address of failed string + mov Extend_buf_sub,one_subst ;AC022; put number of subst in control block + jmp cerror ;AC022; exit + +typecont: + mov bx,ax ;AC000; get Handle + mov cx,stdout ;AN000; set output to STDOUT + call set_file_code_page ;AN000; Set code page on output device + jc typerr2 ;AN022; exit if error + + mov zflag,0 ; Reset ^Z flag + mov ds,[TPA] + xor dx,dx +ASSUME DS:NOTHING + +typelp: + cmp cs:[zflag],0 ;AC050; Is the ^Z flag set? + retnz ; Yes, return + mov cx,cs:[bytcnt] ;AC056; No, continue + mov ah,read + int int_command + jc typerr ;AN022; Exit if error + mov cx,ax + jcxz typelp_ret ;AC000; exit if nothing read + push ds + pop es ; Check to see if a ^Z was read. +assume es:nothing + xor di,di + push ax + mov al,1ah + repnz scasb + pop ax + xchg ax,cx + cmp ax,0 + jnz foundz ; Yes, handle it + cmp byte ptr [di-1],1ah ; No, double check + jnz typecont2 ; No ^Z, continue + +foundz: + sub cx,ax ; Otherwise change cx so that only those + dec cx ; bytes up to but NOT including the ^Z + push cs ; will be typed. + pop es +assume es:trangroup + not zflag ; Turn on ^Z flag so that the routine + +typecont2: ; will quit after this write. + push bx + mov bx,1 + mov ah,write + int int_command + pop bx + jc Error_outputj + cmp ax,cx + jz typelp + dec cx + cmp ax,cx + retz ; One less byte OK (^Z) + +Error_outputj: + mov bx,1 + mov ax,IOCTL SHL 8 + int int_command + test dl,devid_ISDEV + retnz ; If device, no error message + jmp error_output + +typelp_ret: + ret + + break Volume +assume ds:trangroup,es:trangroup + +; +; VOLUME command displays the volume ID on the specified drive +; +VOLUME: + + mov si,81H + mov di,offset trangroup:parse_vol ;AN000; Get adderss of PARSE_VOL + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + jz OkVolArg ;AC000; Yes, display default volume ID + cmp ax,result_no_error ;AC000; did we have an error? + jnz BadVolArg ;AC000; Yes, fail. +; +; We have parsed off the drive. See if there are any more chars left +; + + mov di,offset trangroup:parse_vol ;AC000; get address of parse_vol + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jz OkVolArg ;AC000; yes, end of road +; +; The line was not interpretable. Report an error. +; +badvolarg: + jmp Cerror +; +; Find the Volume ID on the disk. +; +PUBLIC OkVolArg +OKVOLARG: + invoke crlf2 + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before volume message + push ds + pop es +; +; Volume IDs are only findable via extended FCBs or find_first with attributes +; of volume_id ONLY. +; + + mov di,FCB-7 ; Point to extended FCB beginning + mov al,-1 ; Tag to indicate Extention + stosb + xor ax,ax ; Zero padding to volume label + stosw + stosw + stosb + mov al,attr_volume_ID ; Look for volume label + stosb + inc di ; Skip drive byte; it is already set + mov cx,11 ; fill in remainder of file + mov al,'?' + rep stosb +; +; Set up transfer address (destination of search first information) +; + mov dx,offset trangroup:dirbuf + mov ah,set_DMA + int int_command +; +; Do the search +; + mov dx,FCB-7 + mov ah,Dir_Search_First + int int_command + +;******************************** +; Print volume ID info + + push ax ;AC000; AX return from SEARCH_FIRST for VOL ID + mov al,DS:[FCB] ;AC000; get drive letter + add al,'@' + cmp al,'@' + jnz drvok + mov al,[curdrv] + add al,capital_A +drvok: + mov vol_drv,al ;AC000; get drive letter into argument + pop ax ;AC000; get return code back + or al,al ;AC000; volume label found? + jz Get_vol_name ;AC000; volume label exists - go get it + mov dx,offset trangroup:VolMes_ptr_2 ;AC000; set up no volume message + jmp short print_serial ;AC000; go print it + +Get_vol_name: + mov di,offset trangroup:charbuf + mov dx,di + mov si,offset trangroup:dirbuf + 8 ;AN000; 3/3/KK + mov cx,11 ;AN000; 3/3/KK + rep movsb ;AN000; 3/3/KK + + xor al,al ;AC000; store a zero to terminate the string + stosb + mov dx,offset trangroup:VolMes_ptr ;AC000; set up message + +PRINT_SERIAL: + +; +; Attempt to get the volume serial number from the disk. If an error +; occurs, do not print volume serial number. +; + + push dx ;AN000; save message offset + mov ax,(GetSetMediaID SHL 8) ;AC036; Get the volume serial info + mov bl,DS:[FCB] ;AN000; get drive number from FCB + mov dx,offset trangroup:vol_ioctl_buf ;AN000;target buffer + int int_command ;AN000; do the call + pop dx ;AN000; get message offset back + jc printvol_end ;AN000; if error, just go print label + call std_printf ;AC000; go print volume message + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before volume message + mov dx,offset trangroup:VolSerMes_ptr ;AN000; get serial number message + +printvol_end: + jmp std_printf ;AC000; go print and exit + +;**************************************************************** +;* +;* ROUTINE: Set file Code page +;* +;* FUNCTION: Check CPSW status, if CPSW is on, get the file's +;* code page and attempt to invoke it on the +;* output device. +;* +;* INPUT: file handle in BX - unless copyflg is set +;* handle of output device in CX +;* +;* OUTPUT: if carry set (code page invoke failed) +;* ax = extended error +;* otherwise +;* ax modified +;* +;* +;**************************************************************** + +Set_file_code_page proc near ;AN000; + + push bx ;AN000; save registers + push di ;AN000; + push dx ;AN000; + + cmp cpyflag,1 ;AN000; were we called from COPY? + jz Already_have_cp ;AN000; yes - already have code page + call get_file_code_page_tag ;AN000; get the file's code page + jc cp_set_error ;AN000; if error - just continue + +already_have_cp: ;AN000; See what was returned. + mov ax,(file_times SHL 8)+set_XA ;AC030; set code page + mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list + mov bx,cx ;AN000; get handle of output device + int int_command ;AN000; + jnc set_file_cp_end ;AN000; all okay - return +cp_set_error: + pop dx ;AC030; we don't restore DX for error - + call Set_Ext_Error_msg ;AN000; we return error message + jmp short set_file_cp_exit ;AC030; exit + +set_file_cp_end: ;AN000; finished + pop dx ;AN000; restore registers + +set_file_cp_exit: + pop di ;AN000; + pop bx ;AN000; + + ret ;AN000; return + +Set_file_code_page endp ;AN000; + + +;**************************************************************** +;* +;* ROUTINE: Get file Code page tag +;* +;* FUNCTION: Get code page file attribute. +;* +;* INPUT: file handle in BX +;* +;* OUTPUT: if error - carry set +;* otherwise - xa_list_attr set to file's code page +;* +;* AX and DI modified +;* +;**************************************************************** + + +Get_file_code_page_tag proc near ;AN000; + + push cx ;AN030; + push si ;AN030; + push di ;AN030; + mov xa_list_attr,0 ;AN030; initialize code page + mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attributes + mov si,offset trangroup:xa_cp ;AN030; get xa request buffer + mov di,offset trangroup:xa_cp_out ;AC030; get xa output buffer + mov cx,xa_cp_length ;AN030; length of buffer + int int_command ;AN000; + pop di ;AN030; + pop si ;AN030; + pop cx ;AN030; + + ret ;AN000; return + +Get_file_code_page_tag endp ;AN000; + + +;**************************************************************** +;* +;* ROUTINE: Set_ext_error_msg +;* +;* FUNCTION: Sets up extended error message for printing +;* +;* INPUT: return from INT 21 +;* +;* OUTPUT: extended error message set up in extended error +;* buffer. +;* +;**************************************************************** + +Set_ext_error_msg proc near ;AN000; + + call get_ext_error_number ;AC022; get the extended error + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,ax ;AN000; get message number in control block + stc ;AN000; make sure carry is set + + ret ;AN000; return + +Set_ext_error_msg endp ;AN000; + +;**************************************************************** +;* +;* ROUTINE: Get_ext_error_number +;* +;* FUNCTION: Does get extended error function call +;* +;* INPUT: return from INT 21 +;* +;* OUTPUT: AX - extended error number +;* +;**************************************************************** + +Get_ext_error_number proc near ;AN022; + + SaveReg ;AN022; save registers + mov ah,GetExtendedError ;AN022; get extended error + xor bx,bx ;AN022; clear BX + int int_command ;AN022; + RestoreReg ;AN022; restore registers + + ret ;AN022; return + +Get_ext_error_number endp ;AN022; + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD2A.ASM b/v4.0/src/CMD/COMMAND/TCMD2A.ASM new file mode 100644 index 0000000..9dcb066 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD2A.ASM @@ -0,0 +1,552 @@ + page 80,132 +; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 +; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 +TITLE PART5 COMMAND Transient routines. + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comequ.asm + INCLUDE comseg.asm + include ioctl.inc +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf_ptr:word + EXTRN BadCurDrv:byte ;AC000; + EXTRN clsstring:byte + EXTRN dback_ptr:word + EXTRN display_ioctl:word ;AN000; + EXTRN display_width:word ;AN000; + EXTRN Extend_buf_ptr:word ;AN049; + EXTRN linperpag:word ;AN000; + EXTRN msg_disp_class:byte ;AN049; + EXTRN nulpath_ptr:word + EXTRN prompt_table:word + EXTRN string_buf_ptr:word ;AC000; + EXTRN vermes_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN Arg_Buf:byte + EXTRN bwdbuf:byte + EXTRN curdrv:byte + EXTRN dirchar:byte + EXTRN major_ver_num:word + EXTRN minor_ver_num:word + EXTRN srcxname:byte ;AN049; + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +transpace ends +;--------------- + + EXTRN cerror:near ;AN049; + EXTRN crlf2:near + EXTRN drvbad:near + EXTRN std_printf:near + + PUBLIC build_dir_for_chdir + PUBLIC build_dir_for_prompt + PUBLIC build_dir_string + PUBLIC cls + PUBLIC path + PUBLIC print_char + PUBLIC print_drive + PUBLIC print_version + PUBLIC print_b + PUBLIC print_back + PUBLIC print_eq + PUBLIC print_esc + PUBLIC print_g + PUBLIC print_l + PUBLIC print_prompt + PUBLIC version + + break Version +assume ds:trangroup,es:trangroup + +VERSION: + call crlf2 + call print_version + jmp crlf2 + +print_version: + mov ah,Get_version + int int_command + push ax + xor ah,ah + mov major_ver_num,ax + pop ax + xchg ah,al + xor ah,ah + mov minor_ver_num,ax + mov dx,offset trangroup:vermes_ptr + jmp std_printf + +print_prompt: + push ds + push cs + pop ds ; MAKE SURE DS IS IN TRANGROUP + push es + invoke find_prompt ; LOOK FOR PROMPT STRING + jc PP0 ; CAN'T FIND ONE + cmp byte ptr es:[di],0 + jnz PP1 +PP0: + call print_drive ; USE DEFAULT PROMPT + mov al,sym + call print_char + jmp short PP5 + +PP1: + mov al,es:[di] ; GET A CHAR + inc di + or al,al + jz PP5 ; NUL TERMINATED + cmp al,dollar ; META CHARACTER? + jz PP2 ; NOPE +PPP1: + call print_char + jmp PP1 + +PP2: + mov al,es:[di] + inc di + mov bx,offset trangroup:prompt_table-3 + or al,al + jz PP5 + +PP3: + add bx,3 + invoke upconv + cmp al,[bx] + jz PP4 + cmp byte ptr [bx],0 + jnz PP3 + jmp PP1 + +PP4: + push es + push di + push cs + pop es + call [bx+1] + pop di + pop es + jmp PP1 + +PP5: + pop es ; RESTORE SEGMENTS + pop ds + return + + +print_back: + mov dx,offset trangroup:dback_ptr + jmp std_printf + +print_EQ: + mov al,'=' + jmp short print_char + +print_esc: + mov al,1BH + jmp short print_char + +print_G: + mov al,rabracket + jmp short print_char + +print_L: + mov al,labracket + jmp short print_char + +print_B: + mov al,vbar + +print_char: + push es + push ds + pop es + push di + push dx + mov dl,al ;AC000; Get char into al + mov ah,Std_CON_output ;AC000; print the char to stdout + int int_command ;AC000; + pop dx + pop di + pop es + ret + +print_drive: + mov ah,Get_Default_drive + int int_command + add al,capital_A + call print_char + ret + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +build_dir_for_prompt: + xor dl,dl + mov si,offset trangroup:bwdbuf + mov di,SI + mov al,CurDrv + add al,'A' + mov ah,':' + stosw + mov al,[dirchar] + stosb + xchg si,di + mov string_ptr_2,di + mov ah,Current_dir + int int_command + mov dx,offset trangroup:string_buf_ptr + jnc DoPrint + mov dx,offset trangroup:BadCurDrv +DoPrint: + call std_printf + + ret + +build_dir_for_chdir: + call build_dir_string + mov dx,offset trangroup:bwdbuf + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + call std_printf + ret + +build_dir_string: + mov dl,ds:[FCB] + mov al,DL + add al,'@' + cmp al,'@' + jnz gotdrive + add al,[CURDRV] + inc al + +gotdrive: + push ax + mov si,offset trangroup:bwdbuf+3 + mov ah,Current_dir + int int_command + jnc dpbisok + push cs + pop ds + jmp drvbad + +dpbisok: + mov di,offset trangroup:bwdbuf + mov dx,di + pop ax + mov ah,':' + stosw + mov al,[dirchar] + stosb + + ret + + break Path +assume ds:trangroup,es:trangroup + +PATH: + xor al,al ;AN049; Set up holding buffer + mov di,offset Trangroup:srcxname ;AN049; for PATH while parsing + stosb ;AN049; Initialize PATH to null + dec di ;AN049; point to the start of buffer + invoke PGetarg ; Pre scan for arguments + jz disppath ; Print the current path + cmp al,semicolon ;AC049; NUL path argument? + jnz pathslp ;AC049; + inc si ;AN049; point past semicolon + jmp short scan_white ;AC049; Yes - make sure nothing else on line + +pathslp: ; Get the user specified path + lodsb ; Get a character + cmp al,end_of_line_in ;AC049; Is it end of line? + jz path_eol ;AC049; yes - end of command + + invoke testkanj ;See if DBCS + jz notkanj2 ;No - continue + stosb ;AC049; Yes - store the first byte + lodsb ;skip second byte of DBCS + +path_hold: ;AN049; + stosb ;AC049; Store a byte in the PATH buffer + jmp short pathslp ;continue parsing + +notkanj2: + invoke upconv ;upper case the character + cmp al,semicolon ;AC049; ';' not a delimiter on PATH + jz path_hold ;AC049; go store it + invoke delim ;delimiter? + jnz path_hold ;AC049; no - go store character + +scan_white: ;AN049; make sure were at EOL + lodsb ;AN049; get a character + cmp al,end_of_line_in ;AN049; end of line? + jz path_eol ;AN049; yes - go set path + cmp al,blank ;AN049; whitespace? + jz scan_white ;AN049; yes - continue scanning + cmp al,tab_chr ;AN049; whitespace? + jz scan_white ;AN049; yes - continue scanning + + mov dx,offset TranGroup:Extend_Buf_ptr ;AN049; no - set up error message + mov Extend_Buf_ptr,MoreArgs_ptr ;AN049; get "Too many parameters" message number + mov msg_disp_class,parse_msg_class ;AN049; set up parse error msg class + jmp cerror ;AN049; + +path_eol: ;AN049; Parsing was clean + xor al,al ;AN049; null terminate the PATH + stosb ;AN049; buffer + invoke find_path ;AN049; Find PATH in environment + invoke delete_path ;AC049; Delete any offending name + invoke scan_double_null ;AC049; Scan to end of environment + invoke move_name ;AC049; move in PATH= + mov si,offset Trangroup:srcxname ;AN049; Set up source as PATH buffer + +store_path: ;AN049; Store the PATH in the environment + lodsb ;AN049; Get a character + cmp al,end_of_line_out ;AN049; null character? + jz got_paths ;AN049; yes - exit + invoke store_char ;AN049; no - store character + jmp short store_path ;AN049; continue + +got_paths: ;AN049; we're finished + xor ax,ax ;null terminate the PATH in + stosw ; the environment + return + +disppath: + invoke find_path ;AN049; + call print_path + call crlf2 + return + +print_path: + cmp byte ptr es:[di],0 + jnz path1 + +path0: + mov dx,offset trangroup:nulpath_ptr + push cs + pop es + push cs + pop ds + jmp std_printf + +path1: + push es + pop ds + sub di,5 + mov si,di +ASSUME DS:RESGROUP + invoke scasb2 ; LOOK FOR NUL + cmp cx,0FFH + jz path0 + push cs + pop es + mov di,offset trangroup:arg_buf + mov dx,100h + sub dx,cx + xchg dx,cx + rep movsb + mov dx,offset trangroup:arg_buf_ptr + push cs + pop ds + jmp std_printf + +ASSUME DS:TRANGROUP + + break Cls + +; **************************************************************** +; * +; * ROUTINE: CLS +; * +; * FUNCTION: Clear the screen using INT 10h. If ANSI.SYS is +; * installed, send a control string to clear the +; * screen. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +ANSI_installed equ 0ffh + +CLS: + mov ah,Mult_ANSI ;AN000; see if ANSI.SYS installed + mov al,0 ;AN000; + int 2fh ;AN000; + cmp al,ANSI_installed ;AN000; + jz ansicls ;AN000; installed - go do ANSI CLS + +check_lines: + mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display + mov bx,stdout ;AN000; lines for stdout + mov ch,ioc_sc ;AN000; type is display + mov cl,get_generic ;AN000; get information + mov dx,offset trangroup:display_ioctl ;AN000; + int int_command ;AN000; + jc no_variable ;AN000; function had error, use default + mov ax,linperpag ;AN000; get number of rows returned + mov dh,al ;AN000; set number of rows + mov ax,display_width ;AN000; get number of columns returned + mov dl,al ;AN000; set number of columns + jmp short regcls ;AN000; go do cls + +no_variable: + mov bx,stdout ;AC000; set handle as stdout + mov ax,IOCTL SHL 8 ;AC000; do ioctl - get device + int int_command ;AC000; info + test dl,devid_ISDEV ;AC000; is handle a device + jz ANSICLS ;AC000; If a file put out ANSI + test dl,devid_SPECIAL ;AC000; + jnz cls_normal ;AC000; If not special CON, do ANSI + +ansicls: + call ansi_cls ;AN000; clear the screen + jmp short cls_ret ;AN000; exit + +; +; Get video mode +; + +cls_normal: ;AC000; + + mov ah,get_video_state ;AC000; set up to get video state + int video_io_int ;AC000; do int 10h - BIOS video IO + cmp al,video_alpha ;AC000; see if in text mode + jbe DoAlpha + cmp al,video_bw ;AC000; see if black & white card + jz DoAlpha +; +; We are in graphics mode. Bogus IBM ROM does not scroll correctly. We will +; be just as bogus and set the mode that we just got. This will blank the +; screen too. +; + mov ah,set_video_mode ;AC000; set video mode call + int video_io_int ;AC000; do int 10h - BIOS video IO + jmp short cls_ret ;AC000; exit + +DoAlpha: +; +; Get video mode and number of columns to scroll +; + mov ah,get_video_state ;AC000; set up to get current video state + int video_io_int ;AC000; do int 10h - BIOS video IO + mov dl,ah + mov dh,linesperpage ;AC000; have 25 rows on the screen + +regcls: + call reg_cls ;AC000; go clear the screen + +cls_ret: + ret ;AC000; exit + +; **************************************************************** +; * +; * ROUTINE: REG_CLS +; * +; * FUNCTION: Clear the screen using INT 10H. +; * +; * INPUT: DL = NUMBER OF COLUMNS +; * DH = NUMBER OF ROWS +; * +; * OUTPUT: none +; * +; **************************************************************** + +reg_cls proc near ;AC000; + +; +; Set overscan to black. +; + + dec dh ;AC000; decrement rows and columns + dec dl ;AC000; to zero base + push dx ;AN000; save rows,columns + mov ah,set_color_palette ;AC000; set up to set the color to blank + xor bx,bx + int video_io_int ;AC000; do int 10h - BIOS video IO + pop dx ;AN000; retore rows,colums + + xor ax,ax ;AC000; zero out ax + mov CX,ax ;AC000; an cx +; +; Scroll active page +; + mov ah,scroll_video_page ;AC000; set up to scroll page up + mov bh,video_attribute ;AC000; attribute for blank line + xor bl,bl ;AC000; set BL to 0 + int video_io_int ;AC000; do int 10h - BIOS video IO +; +; Seek to cursor to 0,0 +; + mov ah,set_cursor_position ;AC000; set up to set cursor position + xor dx,dx ;AC000; row and column 0 + mov bh,0 ;AC000; + int video_io_int ;AC000; do into 10h - BIOS video IO + + ret ;AC000; + +reg_cls endp ;AC000; + + + +; **************************************************************** +; * +; * ROUTINE: ANSI_CLS +; * +; * FUNCTION: Clear the screen using by writing a control code +; * to STDOUT. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +ansi_cls proc near ;AC000; + + mov si,offset trangroup:clsstring + lodsb + mov cl,al + xor ch,ch + mov ah,Raw_CON_IO +clrloop: + lodsb + mov DL,al + int int_command + loop clrloop + return + +ansi_cls endp ;AC000; + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD2B.ASM b/v4.0/src/CMD/COMMAND/TCMD2B.ASM new file mode 100644 index 0000000..4db1f11 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD2B.ASM @@ -0,0 +1,597 @@ + page 80,132 +; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 +; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 +TITLE PART5 COMMAND Transient routines. + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN LODCOM1:NEAR +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN crit_msg_off:word ;AC000; + EXTRN crit_msg_seg:word ;AC000; + EXTRN IO_SAVE:WORD + EXTRN OldTerm:DWORD + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AC000; +;AD060; EXTRN pars_msg_seg:word ;AC000; + EXTRN PERMCOM:BYTE ;AN045; + EXTRN RetCode:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN ACRLF_PTR:WORD ;AN007; + EXTRN baddev_ptr:word + EXTRN CP_active_Ptr:word + EXTRN CP_not_all_Ptr:word + EXTRN CP_not_set_Ptr:word + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN inv_code_page:word ;AC000; + EXTRN msg_disp_class:byte ;AN000; + EXTRN NLSFUNC_Ptr:word ;AC000; + EXTRN parse_chcp:byte ;AC000; + EXTRN parse_chdir:byte ;AC000; + EXTRN parse_ctty:byte ;AC000; + EXTRN string_buf_ptr:word ;AC000; + +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMBUF:BYTE + EXTRN parse_last:word ;AN018; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN RESSEG:WORD + EXTRN srcbuf:byte + EXTRN srcxname:byte ;AC000; + EXTRN string_ptr_2:word + EXTRN system_cpage:word + EXTRN TRAN_TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +TRANSPACE ENDS +;--------------- + + EXTRN cerror:near + + PUBLIC $exit + PUBLIC chcp + PUBLIC ctty + PUBLIC parse_check_eol ;AN000; + PUBLIC parse_with_msg ;AN018; + PUBLIC setup_parse_error_msg ;AN018; + PUBLIC truename ;AN000; + + break Ctty +assume ds:trangroup,es:trangroup + +; **************************************************************** +; * +; * ROUTINE: CTTY - Change console +; * +; * SYNTAX: CTTY device +; * +; * FUNCTION: If a valid console device is specified, CTTY will +; * duplicate the device handle to STDIN, STDOUT and +; * STDERR. This routine returns to LODCOM1. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +CTTY: + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AC000; Get command argument for CTTY + + mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY + xor cx,cx ;AC000; clear cx,dx + xor dx,dx ;AC000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jz ctty_error ;AN000; yes - error + cmp ax,result_no_error ;AN000; did an error occur + jnz ctty_error ;AN000; YES -ERROR + + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf + +ctty_move_filename: ;AN000; put filespec in srcbuf + lodsb ;AN000; get a char from buffer + stosb ;AN000; store in srcbuf + cmp al,end_of_line_out ;AN000; it char a terminator? + jnz ctty_move_filename ;AN000; no - keep moving + pop si ;AN000; get line position back + mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY + call parse_check_eol ;AN000; are we at end of line? + jz nocolon ;AN000; yes - continue + +ctty_error: + jmp isbaddev ;AC000; yes - exit + +nocolon: + mov dx,offset trangroup:srcbuf ;AN000; get address of srcbuf + MOV AX,(OPEN SHL 8) OR 2 ; Read and write + INT int_command ; Open new device + JC ISBADDEV + MOV BX,AX + MOV AX,IOCTL SHL 8 + INT int_command + TEST DL,80H + JNZ DEVISOK + +CLOSEDEV: ;AN007; + MOV AH,CLOSE ; Close initial handle + INT int_command + +ISBADDEV: + MOV DX,OFFSET TRANGROUP:BADDEV_ptr + invoke std_printf + JMP RESRET + +DEVISOK: + push dx ;AN007; save device info + mov ax,acrlf_ptr ;AN021; get message number for 0d, 0a + mov dh,util_msg_class ;AN021; this is a utility message + push bx ;AN021; save handle + invoke Tsysgetmsg ;AN021; get the address of the message + mov dx,si ;AN021; get address into dx + mov ax,(write shl 8) ;AN007; write to device + mov cx,2 ;AN007; write two bytes + int int_command ;AN007; + pop bx ;AN021; get back handle + pop dx ;AN007; get back device info + jc closedev ;AN007; if error, quit + XOR DH,DH + OR DL,3 ; Make sure has CON attributes + MOV AX,(IOCTL SHL 8) OR 1 + INT int_command + PUSH BX ; Save handle + MOV CX,3 + XOR BX,BX + +ICLLOOP: ; Close basic handles + MOV AH,CLOSE + INT int_command + INC BX + LOOP ICLLOOP + POP BX ; Get handle + MOV AH,XDUP + INT int_command ; Dup it to 0 + MOV AH,XDUP + INT int_command ; Dup to 1 + MOV AH,XDUP + INT int_command ; Dup to 2 + MOV AH,CLOSE ; Close initial handle + INT int_command + +RESRET: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + PUSH DS + MOV AX,WORD PTR DS:[PDB_JFN_Table] ; Get new 0 and 1 + MOV [IO_SAVE],AX + MOV AX,OFFSET RESGROUP:LODCOM1 + PUSH AX + +ZMMMM PROC FAR + RET ; Force header to be checked +ZMMMM ENDP + + break Chcp + +;**************************************************************** +;* +;* ROUTINE: CHCP - Change code page internal command +;* (added DOS 3.30 07/21/86) +;* +;* SYNTAX: CHCP [xxx] +;* where xxx is a valid code page +;* +;* FUNCTION: If xxx is specified, CHCP will use INT 21H function +;* 6402H to set the code page to xxxx. If no parameters +;* are specified, CHCP will use INT 21H function 6401H +;* to get global code page and display it to the user. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: none +;* +;**************************************************************** + +NLSFUNC_installed equ 0ffh +set_global_cp equ 2 +get_global_cp equ 1 + +assume ds:trangroup,es:trangroup + +CHCP: + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AC000; Get command argument for CHCP + + mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP + xor cx,cx ;AC000; clear cx,dx + xor dx,dx ;AC000; + call parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + + jnz setcp ;AC000; no go get number & set code page + jmp getcp ;AC000; yes - no parm - get code page + +setcp: + cmp ax,result_no_error ;AN000; did we have an error? + jne cp_error ;AC018; yes - go issue message + + push cx ;AN000; save positional count + mov bx,offset trangroup:parse1_addr ;AN000; get number returned + mov cx,word ptr [bx] ;AN000; into cx + mov system_cpage,cx ;AN000; save user input number + pop cx ;AC000; restore positional count + mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP + call parse_check_eol ;AN000; are we at end of line? + jnz cp_error ;AC000; no - exit + +okset: + mov ah,NLSFUNC ;AN000; see if NLSFUNC installed + mov al,0 ;AN000; + int 2fh ;AN000; + cmp al,NLSFUNC_installed ;AN000; + jz got_NLS ;AN000; Yes - continue + mov dx,offset trangroup:NLSFUNC_ptr ;AN000; no - set up error message + jmp short cp_error ;AN000; error exit + +got_NLS: + mov bx,system_cpage ;AN000; get user input code page + mov ah,getsetcdpg ;get/set global code page function + mov al,set_global_cp ;minor - set + int int_command + jnc chcp_return ;no error - exit +; +;added for p716 +; + cmp ax,error_file_not_found ;p716 was the error file not found? + jnz chcp_other_error ;no - country.sys was found + + mov ah,GetExtendedError ;p850 see if error is invalid data + xor bx,bx ; which is file was found but CP + int int_command ; information was not found. + cmp ax,error_invalid_data ;AC000; invalid code page + jnz no_countrysys ;no - use file not found + mov dx,offset trangroup:inv_code_page ;AN000; get message + jmp short cp_error ;AC000; error exit + +no_countrysys: + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block + jmp short cp_error ;AC000; error exit + +chcp_other_error: +; +; end of p716 +; + mov ah,GetExtendedError ;error - see what it is + xor bx,bx + int int_command + cmp ax,65 ;was it access denied? + jnz none_set ;no - assume all failed + mov dx,offset trangroup:cp_not_all_ptr ;set up message + jmp short cp_error ;AC000; error exit + +none_set: + mov dx,offset trangroup:cp_not_set_ptr ;set up message +cp_error: ;AN000; + jmp cerror ;exit + +getcp: + mov ah,getsetcdpg ;get/set global code page function + mov al,get_global_cp ;minor - get + int int_command + mov system_cpage,bx ;get active cp for output + mov dx,offset trangroup:cp_active_ptr + invoke std_printf ;print it out + +chcp_return: + + RET + + break TRUENAME ;AN000; + + +; **************************************************************** +; * +; * ROUTINE: TRUENAME +; * +; * FUNCTION: Entry point for the internal TRUENAME command. +; * Parses the command line. If a path is found, set +; * SRCXNAME to path. If only a drive letter is +; * found, set SRCXNAME to the drive letter. If +; * no path is found, set the path of SRCXNAME to +; * dot (.) for current directory. Use the NAME +; * TRANSLATE system call to get the real name and +; * then display the real name. If an error occurs +; * issue an error message and transfer control to +; * CERROR. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup ;AN000; + +TRUENAME: ;AN000; TRUENAME entry point + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AN000; Get command line + mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + call parse_with_msg ;AC018; call parser + + mov di,offset trangroup:srcxname ;AN000; get address of srcxname + cmp ax,end_of_line ;AN000; are we at end of line? + je tn_eol ;AN000; yes - go process + cmp ax,result_no_error ;AN000; did we have an error? + jne tn_parse_error ;AN000; yes - go issue message + cmp parse1_type,result_drive ;AN000; was a drive entered? + je tn_drive ;AN000; yes - go process + jmp short tn_filespec ;AN000; nothing else - must be filespec + +tn_eol: ;AN000; no parameters on line + mov ah,end_of_line_out ;AN000; set buffer to . + mov al,dot_chr ;AN000; for current dir + stosw ;AN000; store in srcxname + jmp short tn_doit ;AN000; go do command + +tn_drive: ;AN000; a drive was entered + push si ;AN000; save position in line + mov si,offset trangroup:parse1_addr ;AN000; get address of drive + lodsb ;AN000; get the drive number + add al,"A"-1 ;AN000; convert it to char + stosb ;AN000; store it in srcxname + mov ax,dot_colon ;AN000; get colon and . and + stosw ;AN000; store in srcxname + mov al,end_of_line_out ;AN000; put a terminator char + stosb ;AN000; + pop si ;AN000; get line position back + jmp short tn_check_eol ;AN000; check to make sure eol + +tn_filespec: ;AN000; a filespec was entered + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + +tn_move_filename: ;AN000; put filespec in srcxname + lodsb ;AN000; get a char from buffer + stosb ;AN000; store in srcxname + cmp al,end_of_line_out ;AN000; it char a terminator? + jnz tn_move_filename ;AN000; no - keep moving + pop si ;AN000; get line position back + +tn_check_eol: ;AN000; make sure no extra parms + mov di,offset trangroup:parse_chdir ;AN000; get address of parse_chdir + call parse_check_eol ;AN000; are we at end of line? + je tn_doit ;AN000; Yes - do the command + +tn_parse_error: ;AN000; A parse error occurred + jmp cerror ;AN000; Go to error routine + +tn_doit: ;AN000; + mov si,offset trangroup:srcxname ;AN000; set up srcxname as source + mov di,offset trangroup:combuf ;AN000; set up combuf as target (need big target) + mov ah,xnametrans ;AN000; do name translate call + int int_command ;AN000; + jnc tn_print_xname ;AN000; If no error - print result + + invoke Set_ext_error_msg ;AN000; get extended message + mov string_ptr_2,offset trangroup:srcxname ;AN000; get address of failed string + mov Extend_buf_sub,one_subst ;AN000; put number of subst in control block + jmp cerror ;AN000; Go to error routine + +tn_print_xname: ;AN000; + mov string_ptr_2,offset Trangroup:combuf ;AN000; Set up address of combuf + mov dx,offset trangroup:string_buf_ptr ;AN000; Set up address of print control block + invoke crlf2 ;AN000; print a crlf + invoke printf_crlf ;AN000; print it out + + ret ;AN000; + + break $Exit + +assume ds:trangroup,es:trangroup + +$EXIT: + push ds ;AN000; save data segment + mov ds,[resseg] ;AN000; get resident data segment + +assume ds:resgroup ;AN000; + + cmp [permcom],0 ;AN045; is this a permanent COMMAND? + jnz no_reset ;AN045; Yes - don't do anything +;AD060; mov ah,multdos ;AN000; reset parse message pointers +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address +;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages +;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages +;AD060; int 2fh ;AN000; go set it + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,crit_msg_off ;AN000; old offset of critical messages + mov es,crit_msg_seg ;AN000; old segment of critical messages + int 2fh ;AN000; go set it +no_reset: ;AN045; + pop ds ;AN000; restore local data segment + +assume ds:trangroup ;AN000; + + MOV ES,[RESSEG] + +assume es:resgroup + + MOV AX,[PARENT] + MOV WORD PTR ES:[PDB_Parent_PID],AX + MOV AX,WORD PTR OldTerm + MOV WORD PTR ES:[PDB_Exit],AX + MOV AX,WORD PTR OldTerm+2 + MOV WORD PTR ES:[PDB_Exit+2],AX + + PUSH ES + MOV ES,[TRAN_TPA] + MOV AH,DEALLOC + INT int_command ; Now running in "free" space + POP ES + + MOV AH,Exit + MOV AL,BYTE PTR RetCode + INT int_command + + +; **************************************************************** +; * +; * ROUTINE: PARSE_CHECK_EOL +; * +; * FUNCTION: Calls parser to see if end of line occurred. +; * If not end of line, set up to print parse +; * error message. ASSUMES NO MORE PARAMETERS ARE +; * EXPECTED! +; * +; * INPUT: DS:SI last output from parser +; * ES:DI points to parse block +; * CX last output from parser +; * +; * OUTPUT: AX parser return code +; * +; * if end of line found +; * zero flag set +; * else +; * MSG_DISPLAY_CLASS set to parse error +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN000; + +parse_check_eol Proc near ;AN000; + + xor dx,dx ;AN000; + mov [parse_last],si ;AN018; save start of parameter + invoke cmd_parse ;AN000; call parser + cmp al,end_of_line ;AN000; Are we at end of line? + jz parse_good_eol ;AN000; yes - no problem + + cmp ax,result_no_error ;AN018; was any error found? + jnz ok_to_setup_pmsg ;AN018; yes - continue + inc ax ;AN018; set AX to 1 and turn off zero flag + +ok_to_setup_pmsg: + call setup_parse_error_msg ;AN018; go set up error message + +parse_good_eol: + ret ;AN000; + +parse_check_eol endp ;AN000; + +; **************************************************************** +; * +; * ROUTINE: PARSE_WITH_MSG +; * +; * FUNCTION: Calls parser. If an error occurred, the error +; * message is set up. +; * +; * INPUT: DS:SI last output from parser +; * ES:DI points to parse block +; * CX last output from parser +; * +; * OUTPUT: AX parser return code +; * +; * if no error +; * outputs from parser +; * else +; * MSG_DISPLAY_CLASS set to parse error +; * error message set up for STD_PRINTF +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018; + +parse_with_msg Proc near ;AN018; + + mov [parse_last],si ;AN018; save start of parameter + invoke cmd_parse ;AN018; call parser + cmp al,end_of_line ;AN018; Are we at end of line? + jz parse_msg_good ;AN018; yes - no problem + cmp ax,result_no_error ;AN018; did an error occur + jz parse_msg_good ;AN018; yes - no problem + + call setup_parse_error_msg ;AN018; go set up error message + +parse_msg_good: + ret ;AN018; + +parse_with_msg endp ;AN018; + +; **************************************************************** +; * +; * ROUTINE: SETUP_PARSE_ERROR_MSG +; * +; * FUNCTION: Calls parser. If an error occurred, the error +; * message is set up. +; * +; * INPUT: AX Parse error number +; * SI Set to past last parameter +; * Parse_last Set to start of last parameter +; * +; * OUTPUT: MSG_DISPLAY_CLASS set to parse error +; * error message set up for STD_PRINTF +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018; + +SETUP_PARSE_ERROR_MSG Proc near ;AN018; + + mov msg_disp_class,parse_msg_class ;AC018; Set up parse message class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC018; get extended message pointer + mov byte ptr [si],end_of_line_out ;AC018; terminate the parameter string + mov Extend_Buf_ptr,ax ;AC018; get message number in control block + cmp ax,lessargs_ptr ;AC018; if required parameter missing + jz Setup_parse_msg_ret ;AN018; no subst + mov si,[parse_last] ;AC018; get start of parameter + mov string_ptr_2,si ;AC018; get address of failed string + mov Extend_buf_sub,one_subst ;AC018; put number of subst in control block + +setup_parse_msg_ret: + inc si ;AN018; make sure zero flag not set + + ret ;AC018; + +SETUP_PARSE_ERROR_MSG Endp ;AN018; + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TCODE.ASM b/v4.0/src/CMD/COMMAND/TCODE.ASM new file mode 100644 index 0000000..17ad82d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCODE.ASM @@ -0,0 +1,540 @@ + page 80,132 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +TITLE Part1 COMMAND Transient Routines + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN EXEC_WAIT:NEAR +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN CALL_BATCH_FLAG:byte + EXTRN CALL_FLAG:BYTE + EXTRN ECHOFLAG:BYTE + EXTRN envirseg:word + EXTRN EXTCOM:BYTE + EXTRN FORFLAG:BYTE + EXTRN IFFLAG:BYTE + EXTRN next_batch:word + EXTRN nullflag:byte + EXTRN PIPEFILES:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN RE_OUT_APP:BYTE + EXTRN RE_OUTSTR:BYTE + EXTRN RESTDIR:BYTE + EXTRN SINGLECOM:WORD + EXTRN VERVAL:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BadNam_Ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN APPEND_EXEC:BYTE ;AN041; + EXTRN ARG1S:WORD + EXTRN ARG2S:WORD + EXTRN ARGTS:WORD + EXTRN BYTCNT:WORD + EXTRN COMBUF:BYTE + EXTRN COMSW:WORD + EXTRN CURDRV:BYTE + EXTRN HEADCALL:DWORD + EXTRN IDLEN:BYTE + EXTRN INTERNATVARS:BYTE + EXTRN PARM1:BYTE + EXTRN PARM2:BYTE + EXTRN RE_INSTR:BYTE + EXTRN RESSEG:WORD + EXTRN SPECDRV:BYTE + EXTRN STACK:WORD + EXTRN SWITCHAR:BYTE + EXTRN TPA:WORD + EXTRN UCOMBUF:BYTE + EXTRN USERDIR1:BYTE + IF IBM + EXTRN ROM_CALL:BYTE + EXTRN ROM_CS:WORD + EXTRN ROM_IP:WORD + ENDIF + +TRANSPACE ENDS + +; ******************************************************************** +; START OF TRANSIENT PORTION +; This code is loaded at the end of memory and may be overwritten by +; memory-intensive user programs. + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN $EXIT:NEAR + EXTRN DRVBAD:NEAR + EXTRN EXTERNAL:NEAR + EXTRN FNDCOM:NEAR + EXTRN FORPROC:NEAR + EXTRN PIPEPROC:NEAR + EXTRN PIPEPROCSTRT:NEAR + + PUBLIC COMMAND + PUBLIC DOCOM + PUBLIC DOCOM1 + PUBLIC NOPIPEPROC + PUBLIC TCOMMAND + + IF IBM + PUBLIC ROM_EXEC + PUBLIC ROM_SCAN + ENDIF + + ORG 0 +ZERO = $ + + ORG 100H ; Allow for 100H parameter area + +SETDRV: + MOV AH,SET_DEFAULT_DRIVE + INT int_command +; +; TCOMMAND is the recycle point in COMMAND. Nothing is known here. +; No registers (CS:IP) no flags, nothing. +; + +TCOMMAND: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AX,-1 + XCHG AX,[VERVAL] + CMP AX,-1 + JZ NOSETVER2 + MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value + INT int_command + +NOSETVER2: + CALL [HEADCALL] ; Make sure header fixed + XOR BP,BP ; Flag transient not read + CMP [SINGLECOM],-1 + JNZ COMMAND + +$EXITPREP: + PUSH CS + POP DS + JMP $EXIT ; Have finished the single command +ASSUME DS:NOTHING +; +; Main entry point from resident portion. +; +; If BP <> 0, then we have just loaded transient portion otherwise we are +; just beginning the processing of another command. +; + +COMMAND: + +; +; We are not always sure of the state of the world at this time. We presume +; worst case and initialize the relevant registers: segments and stack. +; + ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CLD + MOV AX,CS + CLI + MOV SS,AX +ASSUME SS:TRANGROUP + MOV SP,OFFSET TRANGROUP:STACK + STI + MOV ES,AX + MOV DS,AX ;AN000; set DS to transient +ASSUME ES:TRANGROUP,DS:TRANGROUP ;AC000; + invoke TSYSLOADMSG ;AN000; preload messages + invoke SETSTDINOFF ;AN026; turn off critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + mov append_exec,0 ;AN041; set internal append state off + + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + + MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF + MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE) +; +; If we have just loaded the transient, then we do NOT need to initialize the +; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I +; guess not: the only circumstances in which we reload the command processor +; is after a transient program execution. In this case, we let the current +; directory lie where it may. +; + OR BP,BP ; See if just read + JZ TESTRDIR ; Not read, check user directory + MOV WORD PTR [UCOMBUF+1],0D01H ; Reset buffer + JMP SHORT NOSETBUF + +TESTRDIR: + CMP [RESTDIR],0 + JZ NOSETBUF ; User directory OK + PUSH DS +; +; We have an unusual situation to handle. The user *may* have changed his +; directory as a result of an internal command that got aborted. Restoring it +; twice may not help us: the problem may never go away. We just attempt it +; once and give up. +; + MOV [RESTDIR],0 ; Flag users dirs OK + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV DX,OFFSET TRANGROUP:USERDIR1 + MOV AH,CHDIR + INT int_command ; Restore users directory + POP DS +ASSUME DS:RESGROUP + +NOSETBUF: + CMP [PIPEFILES],0 + JZ NOPCLOSE ; Don't bother if they don't exist + CMP [PIPEFLAG],0 + JNZ NOPCLOSE ; Don't del if still piping + INVOKE PIPEDEL + +NOPCLOSE: + MOV [EXTCOM],0 ; Flag internal command + MOV AX,CS ; Get segment we're in + MOV DS,AX +ASSUME DS:TRANGROUP + + PUSH AX + MOV DX,OFFSET TRANGROUP:INTERNATVARS + MOV AX,INTERNATIONAL SHL 8 + INT 21H + POP AX + SUB AX,[TPA] ; AX=size of TPA in paragraphs + PUSH BX + MOV BX,16 + MUL BX ; DX:AX=size of TPA in bytes + POP BX + OR DX,DX ; See if over 64K + JZ SAVSIZ ; OK if not + MOV AX,-1 ; If so, limit to 65535 bytes + +SAVSIZ: +; +; AX is the number of bytes free in the buffer between the resident and the +; transient with a maximum of 64K-1. We round this down to a multiple of 512. +; + CMP AX,512 + JBE GotSize + AND AX,0FE00h ; NOT 511 = NOT 1FF + +GotSize: + MOV [BYTCNT],AX ; Max no. of bytes that can be buffered + MOV DS,[RESSEG] ; All batch work must use resident seg. +ASSUME DS:RESGROUP + + TEST [ECHOFLAG],1 + JZ GETCOM ; Don't do the CRLF + INVOKE SINGLETEST + JB GETCOM + TEST [PIPEFLAG],-1 + JNZ GETCOM + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ GETCOM ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ GETCOM ; G + INVOKE CRLF2 + +GETCOM: + MOV CALL_FLAG,0 ; G Reset call flags + MOV CALL_BATCH_FLAG,0 ; G + MOV AH,GET_DEFAULT_DRIVE + INT int_command + MOV [CURDRV],AL + TEST [PIPEFLAG],-1 ; Pipe has highest presedence + JZ NOPIPE + JMP PIPEPROC ; Continue the pipeline + +NOPIPE: + TEST [ECHOFLAG],1 + JZ NOPDRV ; No prompt if echo off + INVOKE SINGLETEST + JB NOPDRV + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ NOPDRV ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ TESTFORBAT ; G + INVOKE PRINT_PROMPT ; Prompt the user + +NOPDRV: + TEST [FORFLAG],-1 ; FOR has next highest precedence + JZ TESTFORbat + JMP FORPROC ; Continue the FOR + +TESTFORBAT: + MOV [RE_INSTR],0 ; Turn redirection back off + MOV [RE_OUTSTR],0 + MOV [RE_OUT_APP],0 + MOV IFFlag,0 ; no more ifs... + TEST [BATCH],-1 ; Batch has lowest precedence + JZ ISNOBAT + + push es ;AN000; save ES + push ds ;AN000; save DS + mov ax,mult_shell_get ;AN000; check to see if SHELL has command + mov es,[batch] ;AN000; get batch segment + mov di,batfile ;AN000; get batch file name + push cs ;AN000; get local segment to DS + pop ds ;AN000; + mov dx,offset trangroup:combuf ;AN000; pass communications buffer + int 2fh ;AN000; call the shell + cmp al,shell_action ;AN000; does shell have a commmand? + pop ds ;AN000; restore DS + pop es ;AN000; restore ES + jz jdocom1 ;AN000; yes - go process command + + PUSH DS ;G + INVOKE READBAT ; Continue BATCH + POP DS ;G + mov nullflag,0 ;G reset no command flag + TEST [BATCH],-1 ;G + JNZ JDOCOM1 ;G if batch still in progress continue + MOV BX,NEXT_BATCH ;G + CMP BX,0 ;G see if there is a new batch file + JZ JDOCOM1 ;G no - go do command + MOV BATCH,BX ;G get segment of next batch file + MOV NEXT_BATCH,0 ;G reset next batch +JDOCOM1: + PUSH CS ;G + POP DS ;G + JMP SHORT DoCom1 ; echoing already done + +ISNOBAT: + CMP [SINGLECOM],0 + JZ REGCOM + MOV SI,-1 + XCHG SI,[SINGLECOM] + MOV DI,OFFSET TRANGROUP:COMBUF + 2 + XOR CX,CX + +SINGLELOOP: + LODSB + STOSB + INC CX + CMP AL,0DH + JNZ SINGLELOOP + DEC CX + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV [COMBUF + 1],CL +; +; do NOT issue a trailing CRLF... +; + JMP DOCOM1 + +; +; We have a normal command. +; Printers are a bizarre quantity. Sometimes they are a stream and +; sometimes they aren't. At this point, we automatically close all spool +; files and turn on truncation mode. +; + +REGCOM: + MOV AX,(ServerCall SHL 8) + 9 + INT 21h + MOV AX,(ServerCall SHL 8) + 8 + MOV DL,1 + INT 21h + + PUSH CS + POP DS ; Need local segment to point to buffer + MOV DX,OFFSET TRANGROUP:UCOMBUF + MOV AH,STD_CON_STRING_INPUT + INT int_command ; Get a command + MOV CL,[UCOMBUF] + XOR CH,CH + ADD CX,3 + MOV SI,OFFSET TRANGROUP:UCOMBUF + MOV DI,OFFSET TRANGROUP:COMBUF + REP MOVSB ; Transfer it to the cooked buffer + +;--------------- + +transpace segment + extrn arg:byte ; the arg structure! +transpace ends +;--------------- + + +DOCOM: + INVOKE CRLF2 + +DOCOM1: + INVOKE PRESCAN ; Cook the input buffer + JZ NOPIPEPROC + JMP PIPEPROCSTRT ; Fire up the pipe + +nullcomj: + jmp nullcom + +NOPIPEPROC: + invoke parseline + jnc OkParse ; user error? or maybe we goofed? + +BadParse: + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADNAM_ptr + INVOKE std_eprintf + JMP TCOMMAND + +OkParse: + test arg.argv[0].argflags, MASK wildcard + jnz BadParse ; ambiguous commands not allowed + cmp arg.argvcnt, 0 ; there WAS a command, wasn't there? + jz nullcomj + cmp arg.argv[0].arglen, 0 ; probably an unnecessary check... + jz nullcomj ; guarantees argv[0] at least x + + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV DI,OFFSET TRANGROUP:IDLEN + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H ; Make FCB with blank scan-off + INT int_command + mov BX, arg.argv[0].argpointer + cmp BYTE PTR [BX+1],':' ; was a drive specified? + jne short drvgd ; no, use default of zero... + + mov DL, BYTE PTR [BX] ; pick-up drive letter + and DL, NOT 20H ; uppercase the sucker + sub DL, capital_A ; convert it to a drive number, A=0 + + CMP AL,-1 ; See what PARSE said about our drive letter. + JZ drvbadj2 ; It was invalid. + + mov DI, arg.argv[0].argstartel + cmp BYTE PTR [DI], 0 ; is there actually a command there? + jnz drvgd ; if not, we have: "d:", "d:\", "d:/" + jmp setdrv ; and set drive to new drive spec + +drvbadj2: + jmp drvbad + +DRVGD: + MOV AL,[DI] + MOV [SPECDRV],AL + MOV AL,' ' + MOV CX,9 + INC DI + REPNE SCASB ; Count no. of letters in command name + MOV AL,8 + SUB AL,CL + MOV [IDLEN],AL ; IDLEN is truly the length + MOV DI,81H + PUSH SI + + mov si, OFFSET TRANGROUP:COMBUF+2 ; Skip over all leading delims + invoke scanoff + +do_skipcom: + lodsb ; move command line pointer over + invoke delim ; pathname -- have to do it ourselves + jz do_skipped ; 'cause parse_file_descriptor is dumb + cmp AL, 0DH ; can't always depend on argv[0].arglen + jz do_skipped ; to be the same length as the user- + cmp AL, [SWITCHAR] ; specified command string + jnz do_skipcom + +do_skipped: + dec SI + XOR CX,CX + +COMTAIL: + LODSB + STOSB ; Move command tail to 80H + CMP AL,13 + LOOPNZ COMTAIL + DEC DI + MOV BP,DI + NOT CL + MOV BYTE PTR DS:[80H],CL + POP SI + +;----- +; Some of these comments are sadly at odds with this brave new code. +;----- +; If the command has 0 parameters must check here for +; any switches that might be present. +; SI -> first character after the command. + + mov DI, arg.argv[0].argsw_word + mov [COMSW], DI ; ah yes, the old addressing mode problem... + mov SI, arg.argv[1 * SIZE argv_ele].argpointer ; s = argv[1]; + OR SI,SI ; if (s == NULL) + JNZ DoParse + MOV SI,BP ; s = bp; (buffer end) + +DoParse: + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command + MOV [PARM1],AL ; Save result of parse + + mov DI, arg.argv[1*SIZE argv_ele].argsw_word + mov [ARG1S], DI + mov SI, arg.argv[2*SIZE argv_ele].argpointer ; s = argv[2]; + OR SI,SI ; if (s == NULL) + JNZ DoParse2 + MOV SI,BP ; s = bp; (bufend)1 + +DoParse2: + MOV DI,FCB+10H + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command ; Parse file name + MOV [PARM2],AL ; Save result + + mov DI, arg.argv[2*SIZE argv_ele].argsw_word + mov [ARG2S], DI + mov DI, arg.argv[0].argsw_word + not DI ; ARGTS doesn't include the flags + and DI, arg.argswinfo ; from COMSW... + mov [ARGTS], DI + + MOV AL,[IDLEN] + MOV DL,[SPECDRV] + or DL, DL ; if a drive was specified... + jnz externalj1 ; it MUST be external, by this time + dec al ; (I don't know why -- old code did it) + jmp fndcom ; otherwise, check internal com table + +externalj1: + jmp external + +nullcom: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + TEST [BATCH], -1 ;G Are we in a batch file? + JZ nosetflag ;G only set flag if in batch + mov nullflag,nullcommand ;G set flag to indicate no command + +nosetflag: + CMP [SINGLECOM],-1 + JZ EXITJ + JMP GETCOM + +EXITJ: + JMP $EXITPREP + +IF IBM + include mshalo.asm +ENDIF + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TDATA.ASM b/v4.0/src/CMD/COMMAND/TDATA.ASM new file mode 100644 index 0000000..c80c588 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TDATA.ASM @@ -0,0 +1,777 @@ + page 80,132 +; SCCSID = @(#)tdata.asm 4.3 85/05/17 +; SCCSID = @(#)tdata.asm 4.3 85/05/17 +TITLE COMMAND Transient Initialized DATA + +; MODIFICATION HISTORY +; +; EE 10-20-83 Changed the drive check indicator bytes (DCIB's) in +; COMTAB to be a flag byte in which bit 0 is now the +; DCIB(bit) and bit 1 is on if the command can take +; switches. + +fmt macro name,string,args + local a +a db string +PUBLIC name +name dw offset trangroup:a +irp val, + dw offset trangroup:val +endm +endm + +btab macro b,sym + db b + dw offset trangroup:sym + endm + +.xlist +.xcref + INCLUDE comsw.asm ;AC000; + INCLUDE comseg.asm + INCLUDE EA.inc ;AN030; + INCLUDE dirent.inc ;AN042; +.list +.cref + +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + +; +; WARNING: DO NOT INCLUDE DOSSYM.INC BECAUSE IT DESTROYS THE MACRO 'FMT' THAT +; has been defined above - RS. +; + INCLUDE CURDIR.INC + INCLUDE ERROR.INC + INCLUDE ifequ.asm + INCLUDE comequ.asm + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf:BYTE + EXTRN bwdbuf:byte + EXTRN bytes_free:WORD + EXTRN charbuf:byte + EXTRN copy_Num:WORD + EXTRN cpyflag:BYTE + EXTRN DATE_OUTPUT:BYTE ;AC000; + EXTRN Dir_Num:WORD + EXTRN DRIVE_OUTPUT:BYTE ;AC000; + EXTRN file_size_high:WORD + EXTRN file_size_low:WORD + EXTRN major_ver_num:WORD + EXTRN minor_ver_num:WORD + EXTRN one_char_val:BYTE + EXTRN PARSE1_OUTPUT:BYTE ;AC000; + EXTRN srcbuf:byte + EXTRN string_ptr_2:WORD + EXTRN system_cpage:word + EXTRN TIME_OUTPUT:BYTE ;AC000; + EXTRN vol_drv:BYTE + EXTRN vol_serial:dword ;AN000; +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN $CALL:NEAR + EXTRN $CHDIR:NEAR + EXTRN $EXIT:NEAR + EXTRN $FOR:NEAR + EXTRN $IF:NEAR + EXTRN $MKDIR:NEAR + EXTRN $RMDIR:NEAR + EXTRN ADD_NAME_TO_ENVIRONMENT:NEAR + EXTRN ADD_PROMPT:NEAR + EXTRN build_dir_for_prompt:near + EXTRN CATALOG:NEAR + EXTRN CHCP:NEAR + EXTRN CLS:NEAR + EXTRN CNTRLC:NEAR + EXTRN COPY:NEAR + EXTRN CRENAME:NEAR + EXTRN CRLF2:NEAR + EXTRN CTIME:NEAR + EXTRN CTTY:NEAR + EXTRN DATE:NEAR + EXTRN ECHO:NEAR + EXTRN ERASE:NEAR + EXTRN GOTO:NEAR + EXTRN IFERLEV:NEAR + EXTRN IFEXISTS:NEAR + EXTRN IFNOT:NEAR + EXTRN PATH:NEAR + EXTRN PAUSE:NEAR + EXTRN PRINT_B:NEAR + EXTRN PRINT_BACK:NEAR + EXTRN PRINT_DATE:NEAR + EXTRN PRINT_CHAR:NEAR + EXTRN PRINT_DRIVE:NEAR + EXTRN PRINT_EQ:NEAR + EXTRN PRINT_ESC:NEAR + EXTRN PRINT_G:NEAR + EXTRN PRINT_L:NEAR + EXTRN PRINT_TIME:NEAR + EXTRN PRINT_VERSION:NEAR + EXTRN SHIFT:NEAR + EXTRN TCOMMAND:NEAR + EXTRN TRUENAME:NEAR ;AN000; + EXTRN TYPEFIL:NEAR + EXTRN VERSION:NEAR + EXTRN VOLUME:NEAR + EXTRN VERIFY:NEAR +; +; WARNING!!! No code may appear after this label!!!! +; +PUBLIC TranCodeLast +TranCodeLast LABEL BYTE +TRANCODE ENDS + +; Data for transient portion + +TRANDATA SEGMENT PUBLIC BYTE + + PUBLIC accden_ptr ;AN000; + PUBLIC acrlf_ptr ;AN000; + PUBLIC arg_buf_ptr ;AN000; + PUBLIC badbat_ptr ;AN000; + PUBLIC badcd_ptr ;AN000; + PUBLIC badCPmes_ptr ;AN000; + PUBLIC badcurdrv ;AN000; + PUBLIC baddat_ptr ;AN000; + PUBLIC baddev_ptr ;AN000; + PUBLIC baddrv_ptr ;AN000; + PUBLIC badlab_ptr ;AN000; + PUBLIC badmkd_ptr ;AN000; + PUBLIC badnam_ptr ;AN000; + PUBLIC bad_on_off_ptr ;AN000; + PUBLIC badPmes_ptr ;AN000; + PUBLIC badrmd_ptr ;AN000; + PUBLIC badtim_ptr ;AN000; + PUBLIC batext + PUBLIC bytmes_ptr ;AN000; + PUBLIC CLSSTRING + PUBLIC comext + PUBLIC COMSPECSTR + PUBLIC COMTAB + PUBLIC copied_ptr ;AN000; + PUBLIC cp_active_ptr ;AN000; + PUBLIC cp_not_all_ptr ;AN000; + PUBLIC cp_not_set_ptr ;AN000; + PUBLIC ctrlcmes_ptr ;AN000; + PUBLIC curdat_mo_day ;AN000; + PUBLIC curdat_ptr ;AN000; + PUBLIC curdat_yr ;AN000; + PUBLIC curtim_hr_min ;AN000; + PUBLIC curtim_ptr ;AN000; + PUBLIC curtim_sec_hn ;AN000; + PUBLIC dback_ptr ;AN000; + PUBLIC del_Y_N_ptr ;AN000; + PUBLIC devwmes_ptr ;AN000; + PUBLIC dirdattim_ptr ;AN000; + PUBLIC dirdat_mo_day ;AN000; + PUBLIC dirdat_yr ;AN000; + PUBLIC dirhead_ptr ;AN000; + PUBLIC dirmes_ptr ;AN000; + PUBLIC dirtim_hr_min ;AN000; + PUBLIC dirtim_sec_hn ;AN000; + PUBLIC DIR_W_SYN ;AN000; + PUBLIC disp_file_size_ptr ;AN000; + PUBLIC dmes_ptr ;AN000; + PUBLIC echomes_ptr ;AN000; + PUBLIC enverr_ptr ;AN000; + PUBLIC eurdat_ptr ;AN000; + PUBLIC exeext + PUBLIC extend_buf_off ;AN000; + PUBLIC extend_buf_ptr ;AN000; + PUBLIC extend_buf_seg ;AN000; + PUBLIC extend_buf_sub ;AN000; + PUBLIC file_name_ptr ;AN000; + PUBLIC fornestmes_ptr ;AN000; + PUBLIC fuldir_ptr ;AN000; + PUBLIC IFTAB + PUBLIC inBdev_ptr ;AN000; + PUBLIC inornot_ptr ;AN000; + PUBLIC Inv_code_page ;AN000; + PUBLIC inval_path_ptr ;AN000; + PUBLIC japdat_ptr ;AN000; + PUBLIC Losterr_ptr ;AN000; + PUBLIC md_exists_ptr ;AN006; + PUBLIC msg_cont_flag ;AN000; + PUBLIC msg_disp_class ;AN000; + PUBLIC needbat_ptr ;AN000; + PUBLIC newdat_format ;AN000; + PUBLIC newdat_ptr ;AN000; + PUBLIC newtim_ptr ;AN000; + PUBLIC NLSFUNC_ptr ;AN000; + PUBLIC nospace_ptr ;AN000; + PUBLIC no_values ;AN000; + PUBLIC nulpath_ptr ;AN000; + PUBLIC offmes_ptr ;AN000; + PUBLIC onmes_ptr ;AN000; + PUBLIC overwr_ptr ;AN000; + PUBLIC PARSE_BREAK ;AN000; + PUBLIC PARSE_CHCP ;AN000; + PUBLIC PARSE_CHDIR ;AN000; + PUBLIC PARSE_CTTY ;AN000; + PUBLIC PARSE_DATE ;AN000; + PUBLIC PARSE_DIR ;AN000; + PUBLIC PARSE_ERASE ;AN000; + PUBLIC PARSE_MRDIR ;AN000; + PUBLIC PARSE_RENAME ;AN000; + PUBLIC PARSE_TIME ;AN000; + PUBLIC PARSE_VOL ;AN000; + PUBLIC PATH_TEXT + PUBLIC pausemes_ptr ;AN000; + PUBLIC pipeEmes_ptr ;AN000; + PUBLIC promptdat_moday ;AN000; + PUBLIC promptdat_ptr ;AN000; + PUBLIC promptdat_yr ;AN000; + PUBLIC PROMPT_TABLE + PUBLIC PROMPT_TEXT + PUBLIC promtim_hr_min ;AN000; + PUBLIC promtim_ptr ;AN000; + PUBLIC promtim_sec_hn ;AN000; + PUBLIC renerr_ptr ;AN000; + PUBLIC SLASH_P_SYN ;AN000; + PUBLIC string_buf_ptr ;AN000; + PUBLIC suremes_ptr ;AN000; + PUBLIC switch_list + PUBLIC syntmes_ptr ;AN000; + PUBLIC tab_ptr ;AN000; + PUBLIC TRANDATAEND + PUBLIC usadat_ptr ;AN000; + PUBLIC verimes_ptr ;AN000; + PUBLIC vermes_ptr ;AN000; + PUBLIC volmes_ptr ;AN000; + PUBLIC volmes_ptr_2 ;AN000; + PUBLIC volsermes_ptr ;AN000; + PUBLIC WEEKTAB + PUBLIC xa_cp ;AN030; + +INCLUDE tranmsg.asm + +CLSSTRING DB 4,01BH,"[2J" ; ANSI Clear screen + +PROMPT_TABLE LABEL BYTE + btab "B",Print_B + btab "D",PRINT_DATE + btab "E",PRINT_ESC + btab "G",PRINT_G + btab "H",PRINT_BACK + btab "L",PRINT_L + btab "N",PRINT_DRIVE + btab "P",build_dir_for_prompt + btab "Q",PRINT_EQ + btab "T",PRINT_TIME + btab "V",PRINT_VERSION + btab "_",CRLF2 + btab "$",PRINT_CHAR + DB 0 ; NUL TERMINATED + +IFTAB LABEL BYTE ; Table of IF conditionals + DB 3,"NOT" ; First byte is count + DW OFFSET TRANGROUP:IFNOT + DB 10,"ERRORLEVEL" + DW OFFSET TRANGROUP:IFERLEV + DB 5,"EXIST" + DW OFFSET TRANGROUP:IFEXISTS + DB 0 + +; Table for internal command names +COMTAB DB 3,"DIR",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:CATALOG ; In TCMD1.ASM + DB 4,"CALL",fSwitchAllowed + DW OFFSET TRANGROUP:$CALL ; In TBATCH2.ASM + DB 4,"CHCP",fSwitchAllowed + DW OFFSET TRANGROUP:CHCP ; In TCMD2B.ASM + DB 6,"RENAME",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM + DB 3,"REN",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM + DB 5,"ERASE",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM + DB 3,"DEL",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM + DB 4,"TYPE",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:TYPEFIL ; In TCMD1.ASM + DB 3,"REM",fSwitchAllowed + DW OFFSET TRANGROUP:TCOMMAND ; In TCODE.ASM + DB 4,"COPY",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:COPY ; In COPY.ASM + DB 5,"PAUSE",fSwitchAllowed + DW OFFSET TRANGROUP:PAUSE ; In TCMD1.ASM + DB 4,"DATE",fSwitchAllowed + DW OFFSET TRANGROUP:DATE ; In TPIPE.ASM + DB 4,"TIME",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:CTIME ; In TPIPE.ASM + DB 3,"VER",0 + DW OFFSET TRANGROUP:VERSION ; In TCMD2.ASM + DB 3,"VOL",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:VOLUME ; In TCMD1.ASM + DB 2,"CD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM + DB 5,"CHDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM + DB 2,"MD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM + DB 5,"MKDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM + DB 2,"RD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM + DB 5,"RMDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM + DB 5,"BREAK",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:CNTRLC ; In TUCODE.ASM + DB 6,"VERIFY",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:VERIFY ; In TUCODE.ASM + DB 3,"SET",fSwitchAllowed + DW OFFSET TRANGROUP:ADD_NAME_TO_ENVIRONMENT; In TENV.ASM + DB 6,"PROMPT",fSwitchAllowed + DW OFFSET TRANGROUP:ADD_PROMPT ; In TENV.ASM + DB 4,"PATH",fSwitchAllowed + DW OFFSET TRANGROUP:PATH ; In TCMD2.ASM + DB 4,"EXIT",0 + DW OFFSET TRANGROUP:$EXIT ; In TCMD2.ASM + DB 4,"CTTY",fCheckDrive+fSwitchAllowed + DW OFFSET TRANGROUP:CTTY ; In TCMD2.ASM + DB 4,"ECHO",fSwitchAllowed + DW OFFSET TRANGROUP:ECHO ; In TUCODE.ASM + DB 4,"GOTO",fSwitchAllowed + DW OFFSET TRANGROUP:GOTO ; In TBATCH.ASM + DB 5,"SHIFT",fSwitchAllowed + DW OFFSET TRANGROUP:SHIFT ; In TBATCH.ASM + DB 2,"IF",fSwitchAllowed + DW OFFSET TRANGROUP:$IF ; In TBATCH.ASM + DB 3,"FOR",fSwitchAllowed + DW OFFSET TRANGROUP:$FOR ; In TBATCH.ASM + DB 3,"CLS",0 + DW OFFSET TRANGROUP:CLS ; In TCMD2.ASM + DB 8,"TRUENAME",fSwitchAllowed+fCheckDrive ;AN000; P3903 changed + DW OFFSET TRANGROUP:TRUENAME ;AN000; + DB 0 ; Terminate command table + + +comext dB ".COM" +exeext dB ".EXE" +batext dB ".BAT" + +switch_list DB "VBAPW" ; flags we can recognize + + +XA_cp Label byte ;AN030; list for one extended attribute + DW 1 ;AN030; + DB EAISBINARY ;AN030; type + DW EASYSTEM ;AN030; flags + DB 2 ;AN030; name length + DB "CP" ;AN030; name + + + + +PUBLIC BatBufLen +BatBufLen DW BatLen + +; ***************************************************** +; EMG 4.00 +; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00 +; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE +; ***************************************************** + +; +; COMMON PARSE BLOCKS +; + +; +; Indicates no value list for PARSE. +; + +NO_VALUES DW 0 ;AN000; no values + +; +; PARSE control block for a required file specification (upper cased) +; + +FILE_REQUIRED LABEL BYTE ;AN000; + DW 0200H ;AN000; filespec - required + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional file specification (upper cased) +; or drive number +; + +FILE_OPTIONAL LABEL BYTE ;AN000; + DW 0301H ;AN000; filespec or drive number + ; optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional file specification (upper cased) +; + +FILE_OPTIONAL2 LABEL BYTE ;AN000; + DW 0201H ;AN000; filespec or drive number + ; optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional /P switch +; + +SLASH_P_SWITCH LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize - char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 1 ;AN000; 1 keyword +SLASH_P_SYN DB "/P",0 ;AN000; /P switch + + + +; PARSE BLOCK FOR BREAK, VERIFY, ECHO + +; +; The following parse control block can be used for any command which +; needs only the optional "ON" and "OFF" keywords as operands. Allows +; the equal sign as an additional delimiter. Returns verified result +; in PARSE1_OUTPUT. Currently used for the BREAK, VERIFY, and ECHO +; internal commands. +; + +PARSE_BREAK LABEL BYTE ;AN000; + DW TRANGROUP:BREAK_PARMS ;AN000; + DB 0 ;AN032; no extra delimiter + +BREAK_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:BREAK_CONTROL1;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +BREAK_CONTROL1 LABEL BYTE ;AN000; + DW 2001H ;AN000; string value - optional + DW 2 ;AN000; capitalize - char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:BREAK_VALUES ;AN000; + DB 0 ;AN000; no keywords + +BREAK_VALUES LABEL BYTE ;AN000; + DB 3 ;AN000; + DB 0 ;AN000; no ranges + DB 0 ;AN000; no numeric values + DB 2 ;AN000; 2 string values + DB 0 ;AN000; returned if ON + DW TRANGROUP:BREAK_ON ;AN000; point to ON string + DB 'f' ;AN000; returned if OFF + DW TRANGROUP:BREAK_OFF ;AN000; point to OFF string + +BREAK_ON DB "ON",0 ;AN000; +BREAK_OFF DB "OFF",0 ;AN000; + +; +; PARSE BLOCK FOR CHCP +; + +; +; The following parse control block can be used for any command which +; needs only one optional three digit decimal parameter for operands. +; Returns verified result in PARSE1_OUTPUT. Currently used for the +; CHCP internal command. +; +CHCP_MINVAL EQU 100 ;AN000; +CHCP_MAXVAL EQU 999 ;AN000; + +PARSE_CHCP LABEL BYTE ;AN000; + DW TRANGROUP:CHCP_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CHCP_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:CHCP_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +CHCP_CONTROL1 LABEL BYTE ;AN000; + DW 8001H ;AN000; numeric value - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:CHCP_VALUES ;AN000; + DB 0 ;AN000; no keywords + +CHCP_VALUES LABEL BYTE ;AN000; + DB 1 ;AN000; + DB 1 ;AN000; 1 range + DB 1 ;AN000; returned if result + DD CHCP_MINVAL,CHCP_MAXVAL ;AN000; minimum & maximum value + DB 0 ;AN000; no numeric values + DB 0 ;AN000; no string values + + +; +; PARSE BLOCK FOR DATE +; + +; +; The following parse control block can be used for any command which +; needs only an optional date string as an operand. Returns unverified +; result in DATE_OUTPUT. Currently used for the DATE internal command. +; + +PARSE_DATE LABEL BYTE ;AN000; + DW TRANGROUP:DATE_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +DATE_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:DATE_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +DATE_CONTROL1 LABEL BYTE ;AN000; + DW 1001H ;AN000; date - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:DATE_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR TIME +; + +; +; The following parse control block can be used for any command which +; needs only an optional time string as an operand. Returns unverified +; result in TIME_OUTPUT. Currently used for the TIME internal command. +; + +PARSE_TIME LABEL BYTE ;AN000; + DW TRANGROUP:TIME_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +TIME_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:TIME_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +TIME_CONTROL1 LABEL BYTE ;AN000; + DW 0801H ;AN000; TIME - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:TIME_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + + +; +; PARSE BLOCK FOR VOL +; + +; +; The following parse control block can be used for any command which +; needs only an optional drive letter as an operand. Returns unverified +; drive number (one based) in DRIVE_OUTPUT. Currently used for the VOL +; internal command. +; + +PARSE_VOL LABEL BYTE ;AN000; + DW TRANGROUP:VOL_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +VOL_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:DRIVE_CONTROL1;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +DRIVE_CONTROL1 LABEL BYTE ;AN000; + DW 0101H ;AN000; DRIVE - optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:DRIVE_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + + +; +; PARSE BLOCK FOR MKDIR, RMDIR, TYPE +; + +; +; The following parse control block can be used for any command which +; needs only one required file specification as an operand. Returns a +; pointer to the unverified string in PARSE1_OUTPUT. Currently used +; for the MKDIR, RMDIR, and TYPE internal commands. +; + +PARSE_MRDIR LABEL BYTE ;AN000; + DW TRANGROUP:MRDIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +MRDIR_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR CHDIR, TRUENAME +; + +; +; The following parse control block can be used for any command which +; needs only one optional file specification an operand. Returns a +; pointer to the unverified string in PARSE1_OUTPUT. Currently used +; for the CHDIR and TRUENAME internal commands. +; + +PARSE_CHDIR LABEL BYTE ;AN000; + DW TRANGROUP:CHDIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CHDIR_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_OPTIONAL ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR ERASE +; + +; +; The following parse control block is used for the DEL/ERASE internal +; commands. This command has one required file specification and an +; optional switch (/p) as operands. The verified switch or unverified +; file specification is returned in PARSE1_OUTPUT. +; + +PARSE_ERASE LABEL BYTE ;AN000; + DW TRANGROUP:ERASE_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +ERASE_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 1 ;AN000; 1 switch + DW TRANGROUP:SLASH_P_SWITCH;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR DIR +; + +; +; The following parse control block is used for the DIR internal command. +; This command has one optional file specification and two optional +; switches (/p and /w) as operands. The verified switch or unverified +; file specification is returned in PARSE1_OUTPUT. +; + +PARSE_DIR LABEL BYTE ;AN000; + DW TRANGROUP:DIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +DIR_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_OPTIONAL2;AN000; + DB 2 ;AN000; 2 switches + DW TRANGROUP:SLASH_P_SWITCH;AN000; + DW TRANGROUP:DIR_SWITCH1 ;AN000; + DB 0 ;AN000; no keywords + +DIR_SWITCH1 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 1 ;AN000; 1 keyword +DIR_W_SYN DB "/W",0 ;AN000; /W switch + +; +; PARSE BLOCK FOR RENAME +; + +; +; The following parse control block can be used for any command which +; needs only two required file specifications as operands. Returns +; pointers to the unverified string in PARSE1_OUTPUT. +; Currently used for the RENAME internal command. +; + +PARSE_RENAME LABEL BYTE ;AN000; + DW TRANGROUP:RENAME_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +RENAME_PARMS LABEL BYTE ;AN000; + DB 2,2 ;AN000; 2 positional parms + DW TRANGROUP:FILE_REQUIRED ;AN000; + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR CTTY +; + +; +; The following parse control block can be used for any command which +; needs one required device name as an operand. Returns a pointer to +; unverified string in PARSE1_OUTPUT. Currently used for the CTTY +; internal command. +; + +PARSE_CTTY LABEL BYTE ;AN000; + DW TRANGROUP:CTTY_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CTTY_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:CTTY_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +CTTY_CONTROL1 LABEL BYTE ;AN000; + DW 2000H ;AN000; string value - required + DW 11H ;AN000; capitalize - file table + ;AN000; remove colon at end + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +TRANDATA ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AN000; + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; + +.list +.cref + +ASSUME DS:TRANGROUP,ES:TRANGROUP,CS:TRANGROUP + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AN000; The transient messages + +include msgdcl.inc + +TRANCODE ENDS ;AN000; + +TRANDATA SEGMENT PUBLIC BYTE + +TRANDATAEND LABEL BYTE + +TRANDATA ENDS ;AN000; + + END diff --git a/v4.0/src/CMD/COMMAND/TENV.ASM b/v4.0/src/CMD/COMMAND/TENV.ASM new file mode 100644 index 0000000..e1d43f6 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TENV.ASM @@ -0,0 +1,633 @@ + page 80,132 +; SCCSID = @(#)tenv.asm 4.2 85/08/16 +; SCCSID = @(#)tenv.asm 4.2 85/08/16 +TITLE Part6 COMMAND Transient routines. + +; Environment utilities and misc. routines + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + INCLUDE DOSCNTRY.INC ;AN000; +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN comdrv:byte + EXTRN comspec_end:word + EXTRN comspec_print:word + EXTRN cpdrv:byte + EXTRN dbcs_vector_addr:dword ;AN000; + EXTRN ENVIRSEG:WORD + EXTRN fucase_addr:word ;AC000; + EXTRN RESTDIR:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf_ptr:word + EXTRN comspec:byte + EXTRN comspec_flag:byte + EXTRN comspecstr:byte + EXTRN ENVERR_PTR:WORD + EXTRN PATH_TEXT:byte + EXTRN PROMPT_TEXT:byte + EXTRN SYNTMES_PTR:WORD +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN Arg_Buf:BYTE + EXTRN RESSEG:WORD + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + + PUBLIC add_name_to_environment + PUBLIC add_prompt + PUBLIC delete_path + PUBLIC find_name_in_environment + PUBLIC find_path + PUBLIC find_prompt + PUBLIC move_name + PUBLIC restudir + PUBLIC restudir1 + PUBLIC scan_double_null + PUBLIC scasb2 + PUBLIC store_char + PUBLIC Testkanj ;AN000; 3/3/KK + PUBLIC upconv + +BREAK +ASSUME DS:TRANGROUP + + break Prompt command +assume ds:trangroup,es:trangroup + +ADD_PROMPT: + CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT + CALL SCAN_DOUBLE_NULL + +ADD_PROMPT2: + PUSH SI + CALL GETARG + POP SI + retz ; PRE SCAN FOR ARGUMENTS + CALL MOVE_NAME ; MOVE IN NAME + CALL GETARG + PUSH SI + JMP SHORT ADD_NAME + + + break The SET command +assume ds:trangroup,es:trangroup + +; +; Input: DS:SI points to a CR terminated string +; Output: carry flag is set if no room +; otherwise name is added to environment +; + +DISP_ENVj: + jmp DISP_ENV + +ADD_NAME_TO_ENVIRONMENT: + CALL GETARG + JZ DISP_ENVj +; +; check if line contains exactly one equals sign +; + XOR BX,BX ;= COUNT IS 0 + PUSH SI ;SAVE POINTER TO BEGINNING OF LINE + +EQLP: + LODSB ;GET A CHAR + CMP AL,13 ;IF CR WE'RE ALL DONE + JZ QUEQ + CMP AL,'=' ;LOOK FOR = SIGN + JNZ EQLP ;NOT THERE, GET NEXT CHAR + INC BL ;OTHERWISE INCREMENT EQ COUNT + CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN + JNZ EQLP + INC BH ;SET BH=1 MEANS NO PARAMETERS + JMP EQLP ;AND LOOK FOR MORE + +QUEQ: + POP SI ;RESTORE BEGINNING OF LINE + DEC BL ;ZERO FLAG MEANS ONLY ONE EQ + JZ ONEQ ;GOOD LINE + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + JMP CERROR + +ONEQ: + PUSH BX + CALL DELETE_NAME_IN_ENVIRONMENT + POP BX + DEC BH + retz + + CALL SCAN_DOUBLE_NULL + mov bx,di ; Save ptr to beginning of env var name + CALL MOVE_NAME + push si + xchg bx,di ; Switch ptrs to beginning and end of + ; env var name +; +; We want to special-case COMSPEC. This is to reduce the amount of code +; necessary in the resident for re-reading the transient. Let's look for +; COMSPEC= +; + mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC" + mov cx,4 ; If the new env var is comspec, set + repz cmpsw ; the comspec_flag +; +; Zero set => exact match +; + jnz not_comspec + mov comspec_flag,1 + +not_comspec: + mov di,bx ; Load ptr to end of env var name + +ADD_NAME: ; Add the value of the new env var + pop si ; to the environment. + push si + +add_name1: + LODSB + CMP AL,13 + jz add_name_ret + CALL STORE_CHAR + JMP ADD_NAME1 + +add_name_ret: + pop si + cmp comspec_flag,0 ; If the new env var is comspec, + retz ; copy the value into the +; +; We have changed the COMSPEC variable. We need to update the resident +; pieces necessary to reread in the info. First, skip all delimiters +; + invoke ScanOff + mov es,[resseg] ; comspec var in the resident + assume es:resgroup +; +; Make sure that the printer knows where the beginning of the string is +; + mov di,offset resgroup:comspec + mov bx,di +; +; Generate drive letter for display +; + xor ax,ax ;g assume no drive first + mov comdrv,al ;g + push ax ;AN000; 3/3/KK + mov al,[si] ;AN000; 3/3/KK + call testkanj ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + jnz GotDrive + cmp byte ptr [si+1],':' ; drive specified? + jnz GotDrive + mov al,[si] ; get his specified drive + call UpConv ; convert to uppercase + sub al,'A' ; convert to 0-based + add di,2 + inc al ; convert to 1-based number + mov comdrv,al +; +; Stick the drive letter in the prompt message. Nothing special needs to be +; done here.. +; + + add al,'A'-1 + +GotDrive: ;g + mov comspec_print,di ;g point to beginning of name after drive + mov es:cpdrv,al +; +; Copy chars until delim +; + + mov di,bx + +copy_comspec: + lodsb + invoke Delim + jz CopyDone + cmp al,13 + jz CopyDone + stosb + jmp short copy_comspec + +CopyDone: + xor al,al ; Null terminate the string and quit + stosb + mov comspec_flag,0 + dec di + mov comspec_end,di + + ret + +DISP_ENV: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV DS,[ENVIRSEG] +ASSUME DS:NOTHING + XOR SI,SI + +PENVLP: + CMP BYTE PTR [SI],0 + retz + mov di,offset trangroup:arg_buf + +PENVLP2: + LODSB + stosb + OR AL,AL + JNZ PENVLP2 + mov dx,offset trangroup:arg_buf_ptr + push ds + push es + pop ds + invoke printf_crlf + pop ds + JMP PENVLP + +ASSUME DS:TRANGROUP + +DELETE_PATH: + MOV SI,OFFSET TRANGROUP:PATH_TEXT + JMP SHORT DELETE_NAME_IN_environment + +DELETE_PROMPT: + MOV SI,OFFSET TRANGROUP:PROMPT_TEXT + +DELETE_NAME_IN_environment: +; +; Input: DS:SI points to a "=" terminated string +; Output: carry flag is set if name not found +; otherwise name is deleted +; + PUSH SI + PUSH DS + CALL FIND ; ES:DI POINTS TO NAME + JC DEL1 + MOV SI,DI ; SAVE IT + CALL SCASB2 ; SCAN FOR THE NUL + XCHG SI,DI + CALL GETENVSIZ + SUB CX,SI + PUSH ES + POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME + REP MOVSB ; DELETE THE NAME + +DEL1: + POP DS + POP SI + return + +FIND_PATH: + MOV SI,OFFSET TRANGROUP:PATH_TEXT + JMP SHORT FIND_NAME_IN_environment + +FIND_PROMPT: + MOV SI,OFFSET TRANGROUP:PROMPT_TEXT + +FIND_NAME_IN_environment: +; +; Input: DS:SI points to a "=" terminated string +; Output: ES:DI points to the arguments in the environment +; zero is set if name not found +; carry flag is set if name not valid format +; + CALL FIND ; FIND THE NAME + retc ; CARRY MEANS NOT FOUND + JMP SCASB1 ; SCAN FOR = SIGN +; +; On return of FIND1, ES:DI points to beginning of name +; +FIND: + CLD + CALL COUNT0 ; CX = LENGTH OF NAME + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV ES,[ENVIRSEG] +ASSUME ES:NOTHING + XOR DI,DI + +FIND1: + PUSH CX + PUSH SI + PUSH DI + +FIND11: + LODSB + CALL TESTKANJ + JZ NOTKANJ3 + DEC SI + LODSW + INC DI + INC DI + CMP AX,ES:[DI-2] + JNZ FIND12 + DEC CX + LOOP FIND11 + JMP SHORT FIND12 + +NOTKANJ3: + CALL UPCONV + INC DI + CMP AL,ES:[DI-1] + JNZ FIND12 + LOOP FIND11 + +FIND12: + POP DI + POP SI + POP CX + retz + PUSH CX + CALL SCASB2 ; SCAN FOR A NUL + POP CX + CMP BYTE PTR ES:[DI],0 + JNZ FIND1 + STC ; INDICATE NOT FOUND + return + +COUNT0: + PUSH DS + POP ES + MOV DI,SI + +COUNT1: + PUSH DI ; COUNT NUMBER OF CHARS UNTIL "=" + CALL SCASB1 + JMP SHORT COUNTX + +COUNT2: + PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL + CALL SCASB2 + +COUNTX: + POP CX + SUB DI,CX + XCHG DI,CX + return + +MOVE_NAME: + CMP BYTE PTR DS:[SI],13 + retz + LODSB + +;;;; IF KANJI 3/3/KK + CALL TESTKANJ + JZ NOTKANJ1 + CALL STORE_CHAR + LODSB + CALL STORE_CHAR + JMP SHORT MOVE_NAME + +NOTKANJ1: +;;;; ENDIF 3/3/KK + + CALL UPCONV + CALL STORE_CHAR + CMP AL,'=' + JNZ MOVE_NAME + return + +GETARG: + MOV SI,80H + LODSB + OR AL,AL + retz + invoke SCANOFF + CMP AL,13 + return + +; +; Point ES:DI to the final NULL string. Note that in an empty environment, +; there is NO double NULL, merely a string that is empty. +; +SCAN_DOUBLE_NULL: + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV ES,[ENVIRSEG] +ASSUME ES:NOTHING + XOR DI,DI +; +; Top cycle-point. If the string here is empty, then we are done +; +SDN1: + cmp byte ptr es:[di],0 ; nul string? + retz ; yep, all done + CALL SCASB2 + JMP SDN1 + +SCASB1: + MOV AL,'=' ; SCAN FOR AN = + JMP SHORT SCASBX +SCASB2: + XOR AL,AL ; SCAN FOR A NUL +SCASBX: + MOV CX,100H + REPNZ SCASB + return + +TESTKANJ: + push ds ;AN000; 3/3/KK + push si ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + mov ds,cs:[resseg] ;AN000; Get resident segment + assume ds:resgroup ;AN000; + lds si,dbcs_vector_addr ;AN000; get DBCS vector +ktlop: ;AN000; 3/3/KK + cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK + je notlead ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jb notlead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jbe islead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + jmp short ktlop ;AN000; try another range ; 3/3/KK +Notlead: ;AN000; 3/3/KK + xor ax,ax ;AN000; set zero 3/3/KK + jmp short ktret ;AN000; 3/3/KK +Islead: ;AN000; 3/3/KK + xor ax,ax ;AN000; reset zero 3/3/KK + inc ax ;AN000; 3/3/KK +ktret: ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + pop si ;AN000; 3/3/KK + pop ds ;AN000; 3/3/KK + return ;AN000; 3/3/KK +;------------------------------------- ;3/3/KK + + +; **************************************************************** +; * +; * ROUTINE: UPCONV (ADDED BY EMG 4.00) +; * +; * FUNCTION: This routine returns the upper case equivalent of +; * the character in AL from the file upper case table +; * in DOS if character if above ascii 128, else +; * subtracts 20H if between "a" and "z". +; * +; * INPUT: AL char to be upper cased +; * FUCASE_ADDR set to the file upper case table +; * +; * OUTPUT: AL upper cased character +; * +; **************************************************************** + +assume ds:trangroup ;AN000; + +upconv proc near ;AN000; + + cmp al,80h ;AN000; see if char is > ascii 128 + jb oth_fucase ;AN000; no - upper case math + sub al,80h ;AN000; only upper 128 chars in table + push ds ;AN000; + push bx ;AN000; + mov ds,[resseg] ;AN000; get resident data segment +assume ds:resgroup ;AN000; + lds bx,dword ptr fucase_addr+1 ;AN000; get table address + add bx,2 ;AN000; skip over first word + xlat ds:byte ptr [bx] ;AN000; convert to upper case + pop bx ;AN000; + pop ds ;AN000; +assume ds:trangroup ;AN000; + jmp short upconv_end ;AN000; we finished - exit + +oth_fucase: ;AN000; + cmp al,small_a ;AC000; if between "a" and "z", + jb upconv_end ;AC000; subtract 20h to get + cmp al,small_z ;AC000; upper case equivalent. + ja upconv_end ;AC000; + sub al,20h ;AC000; Change lower-case to upper + +upconv_end: ;AN000; + ret + +upconv endp ;AN000; + + +; +; STORE A CHAR IN environment, GROWING IT IF NECESSARY +; +STORE_CHAR: + PUSH CX + PUSH BX + PUSH ES ;AN056; + PUSH DS ;AN056; Save local DS + MOV DS,[RESSEG] ;AN056; Get resident segment + ASSUME DS:RESGROUP ;AN056; + MOV ES,[ENVIRSEG] ;AN056; Get environment segment + ASSUME ES:NOTHING ;AN056; + POP DS ;AN056; Get local segment back + ASSUME DS:TRANGROUP ;AN056; + CALL GETENVSIZ + MOV BX,CX + SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL + CMP DI,BX + JB STORE1 + + PUSH AX + PUSH CX + PUSH BX ; Save Size of environment + invoke FREE_TPA + POP BX + ADD BX,2 ; Recover true environment size + + CMP BX, 8000H ; Don't let environment grow > 32K + JB ENVSIZ_OK +BAD_ENV_SIZE: ;AN056; + STC + JMP ENVNOSET +ENVSIZ_OK: + + MOV CL,4 + SHR BX,CL ; Convert back to paragraphs + INC BX ; Try to grow environment by one para + MOV CX,ES ;AN056; Get environment segment + ADD CX,BX ;AN056; Add in size of environment + ADD CX,020H ;AN056; Add in some TPA + MOV AX,CS ;AN056; Get the transient segment + CMP CX,AX ;AN056; Are we hitting the transient? + JNB BAD_ENV_SIZE ;AN056; Yes - don't do it!!! + MOV AH,SETBLOCK + INT int_command +ENVNOSET: + PUSHF + PUSH ES + MOV ES,[RESSEG] + invoke ALLOC_TPA + POP ES + POPF + POP CX + POP AX + JNC STORE1 + POP ES ;AN056; + MOV DX,OFFSET TRANGROUP:ENVERR_ptr + JMP CERROR +STORE1: + STOSB + MOV WORD PTR ES:[DI],0 ; NULL IS AT END + POP ES ;AN056; + POP BX + POP CX + return + +GETENVSIZ: +;Get size of environment in bytes, rounded up to paragraph boundry +;ES has environment segment +;Size returned in CX, all other registers preserved + + PUSH ES + PUSH AX + MOV AX,ES + DEC AX ;Point at arena + MOV ES,AX + MOV AX,ES:[arena_size] + MOV CL,4 + SHL AX,CL ;Convert to bytes + MOV CX,AX + POP AX + POP ES + return + + +ASSUME DS:TRANGROUP + + +RESTUDIR1: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + CMP [RESTDIR],0 + POP DS +ASSUME DS:TRANGROUP + retz + +RESTUDIR: + MOV DX,OFFSET TRANGROUP:USERDIR1 + MOV AH,CHDIR + INT int_command ; Restore users DIR + XOR AL,AL + invoke SETREST +RET56: + return + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TENV2.ASM b/v4.0/src/CMD/COMMAND/TENV2.ASM new file mode 100644 index 0000000..0c47958 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TENV2.ASM @@ -0,0 +1,663 @@ + page 80,132 +; SCCSID = @(#)tenv2.asm 1.1 85/05/14 +; SCCSID = @(#)tenv2.asm 1.1 85/05/14 +TITLE Part6 COMMAND Transient routines. + +; Environment utilities and misc. routines + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN pipeflag:byte +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN ACRLF_PTR:WORD + EXTRN BadCD_Ptr:WORD + EXTRN Badmkd_ptr:word + EXTRN BADRMD_PTR:WORD + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN022; + EXTRN MD_exists_ptr:word ;AN006; + EXTRN msg_disp_class:byte ;AC000; + EXTRN NOSPACE_PTR:WORD + EXTRN parse_chdir:byte ;AC000; + EXTRN parse_mrdir:byte ;AC000; + EXTRN PIPEEMES_PTR:WORD + EXTRN string_buf_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN CURDRV:BYTE + EXTRN DESTINFO:BYTE + EXTRN DESTTAIL:WORD + EXTRN DIRCHAR:BYTE + EXTRN dirflag:byte ;AN015; + EXTRN KPARSE:BYTE ;AC000; 3/3/KK + EXTRN msg_numb:word ;AN022; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN PATHPOS:WORD + EXTRN RESSEG:WORD + EXTRN srcxname:byte ;AC000; + EXTRN string_ptr_2:word + EXTRN SWITCHAR:BYTE + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + + PUBLIC $chdir + PUBLIC $mkdir + PUBLIC $rmdir + PUBLIC crlf2 + PUBLIC crprint + PUBLIC delim + PUBLIC error_output + PUBLIC fcb_to_ascz + PUBLIC pathchrcmp + PUBLIC pathcrunch + PUBLIC savudir + PUBLIC savudir1 + PUBLIC scanoff + PUBLIC strcomp + +break $Chdir + +; **************************************************************** +; * +; * ROUTINE: $CHDIR +; * +; * FUNCTION: Entry point for CHDIR command. Parse the command +; * line. If path is found, CHDIR to path. If a drive +; * letter is found, get and display the current dir +; * of the specified drive. If nothing is found, get +; * and display the current dir of the default drive. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +$CHDIR: + + mov si,81H + mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + + cmp ax,end_of_line ;AC000; are we at end of line? + jz bwdJ ; No args + cmp ax,result_no_error ;AC000; did we have an error? + jnz ChDirErr ;AC018; yes - exit + + cmp parse1_type,result_drive ;AC000; was a drive entered? + jnz REALCD ; no +; +; D: was found. See if there is anything more. +; + mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jnz ChDirErr ;AC000; + +bwdJ: + invoke build_dir_for_chdir ; Drive only specified + call crlf2 + return + +REALCD: + + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + invoke move_to_srcbuf ;AN000; move to srcbuf + pop si ;AN000; restore position in line + mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jnz ChDirErr ;AC000; + + invoke SETPATH + TEST [DESTINFO],2 + JNZ BadChdir + MOV AH,CHDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz BadChDir ;AN022; yes - issue old message + call Set_Ext_Error_Subst ;AN022; + jmp short chdirerr ;AN022; + +BadChDir: + MOV DX,OFFSET TRANGROUP:BADCD_ptr + +ChDirErr: + invoke Std_Eprintf + return + +break $Mkdir + +assume ds:trangroup,es:trangroup + +$MKDIR: + CALL SETRMMK + JC MkDirErr + MOV AH,MKDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz MD_other_err ;AN022; yes - issue old message + cmp ax,error_access_denied ;AN022; access denied? + jz badmderr ;AN022; yes - see if file exists + + call Set_Ext_Error_Subst ;AN022; + jmp short MkDirerr ;AC022; yes - go print it + +BADMDERR: + mov dx,offset trangroup:srcxname ;AN006; Set Disk transfer address + mov ah,Set_DMA ;AN006; + int int_command ;AN006; + MOV AH,Find_First ;AN006; see if file/dir exists + mov cx,attr_directory ;AN006; search for directory + INT int_command ;AN006; + jc MD_other_err ;AN006; doesn't exist - must be something else + mov dl,srcxname.find_buf_attr ;AN006; we found a file/dir + test dl,attr_directory ;AN006; was it a directory? + jz MD_other_err ;AN006; no - must have been a file + mov dx,offset trangroup:MD_exists_ptr ;AN006; set up already exists error + jmp short MkDirErr ;AN006; make sure we didn't have network error +MD_other_err: ;AN006; + MOV DX,OFFSET TRANGROUP:BADMKD_ptr +MkDirErr: + invoke Std_Eprintf + return + +Break + +;**************************************************************** +;* +;* ROUTINE: SETRMMK +;* +;* FUNCTION: Parse routine for the internal MKDIR and RMDIR +;* commands. Parses the command line for a required +;* filespec. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: carry clear +;* DS:DX points to ASCIIZ argument +;* carry set +;* DS:DX has error message pointer +;* +;**************************************************************** + +SETRMMK: + mov si,81H + mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC000; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jnz NOARGERR ;AC000; yes - exit + + mov di,offset trangroup:srcxname ;AN000; get address of srcxname + push di ;AN000; save address + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of path + +mrdir_move_filename: ;AN000; put filespec in srcxname + lodsb ;get a char from buffer + stosb ;AN000; store in srcxname + cmp al,end_of_line_out ;AC000; it char a terminator? + jnz mrdir_move_filename ;AC000; no - keep moving + pop si ;AN000; get line position back + +; +; we have scanned an argument. See if any args beyond. +; + + mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir + invoke parse_check_eol ;AC000; are we at end of line? + pop dx ;AC000; get address of SRCXNAME + retz ;yes - return no error +NOARGERR: + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + XOR AX,AX + STC + return + +break $Rmdir + +assume ds:trangroup,es:trangroup + +$RMDIR: + CALL SETRMMK + JC RmDirErr + JNZ BADRDERR + MOV AH,RMDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz badrderr ;AN022; yes - issue old message + cmp ax,error_access_denied ;AN022; access denied? + jz badrderr ;AN022; yes - issue old message + + call Set_Ext_Error_Subst ;AN022; + jmp short RmDirerr ;AC022; yes - go print it + +BADRDERR: + MOV DX,OFFSET TRANGROUP:BADRMD_ptr + +RmDirErr: + invoke STD_Eprintf + return + +;**************************************************************** +;* +;* ROUTINE: Set_ext_error_subst +;* +;* FUNCTION: Sets up substitution for extended error +;* +;* INPUT: AX - extended error number +;* DX - offset of string +;* +;* OUTPUT: Extend_Buf_Ptr set up for STD_EPRINTF +;* +;**************************************************************** + +Set_ext_error_subst proc near ;AN022; + + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov string_ptr_2,dx ;AN022; get address of failed string + mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block + mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer + mov Extend_Buf_ptr,ax ;AN022; get message number in control block + + ret ;AN022; return + +Set_ext_error_subst endp ;AN022; + + + + + +Break + +; +; SavUDir - move the user's current directory on a drive into UserDir1 +; SavUDir1 - move the user's current directory on a drive into a specified +; buffer +; +; Inputs: DL has 1-based drive number +; ES:DI has destination buffer (SavUDir1 only) +; Outputs: Carry Clear +; DS = TranGroup +; Carry Set +; AX has error code +; Registers Modified: AX, SI +; + +SAVUDIR: + MOV DI,OFFSET TRANGROUP:USERDIR1 + +SAVUDIR1: + MOV AL,DL + ADD AL,'@' + CMP AL,'@' + JNZ GOTUDRV + ADD AL,[CURDRV] + INC AL ; A = 1 + +GOTUDRV: + STOSB + MOV AH,[DIRCHAR] + MOV AL,':' + STOSW + PUSH ES + POP DS +ASSUME DS:NOTHING + + MOV SI,DI + MOV AH,CURRENT_DIR ; Get the Directory Text + INT int_command + retc + PUSH CS + POP DS +ASSUME DS:TRANGROUP + + return + + +CRLF2: + PUSH DX + MOV DX,OFFSET TRANGROUP:ACRLF_ptr + +PR: + PUSH DS + PUSH CS + POP DS + invoke std_printf + POP DS + POP DX + + return + +; +; These routines (SCANOFF, DELIM) are called in batch processing when DS +; may NOT be TRANGROUP +; +ASSUME DS:NOTHING,ES:NOTHING + +SCANOFF: + LODSB + CALL DELIM + JZ SCANOFF + DEC SI ; Point to first non-delimiter + return + +; +; Input: AL is character to classify +; Output: Z set if delimiter +; NZ set otherwise +; Registers modified: none +; + +DELIM: + CMP AL,' ' + retz + CMP AL,'=' + retz + CMP AL,',' + retz + CMP AL,';' + retz + CMP AL,9 ; Check for TAB character + retz + CMP AL,0ah ; Check for line feed character - BAS + return + + +ASSUME DS:TRANGROUP,ES:TRANGROUP + + +FCB_TO_ASCZ: ; Convert DS:SI to ASCIZ ES:DI + MOV CX,8 + +MAINNAME: + LODSB + CMP AL,' ' + JZ SKIPSPC + STOSB + +SKIPSPC: + LOOP MAINNAME + LODSB + CMP AL,' ' + JZ GOTNAME + MOV AH,AL + MOV AL,dot_chr + STOSB + XCHG AL,AH + STOSB + MOV CL,2 + +EXTNAME: + LODSB + CMP AL,' ' + JZ GOTNAME + STOSB + LOOP EXTNAME + +GOTNAME: + XOR AL,AL + STOSB + return + +STRCOMP: +; +; Compare ASCIZ DS:SI with ES:DI. +; SI,DI destroyed. +; + CMPSB + retnz ; Strings not equal + cmp byte ptr [SI-1],0 ; Hit NUL terminator? + retz ; Yes, strings equal + jmp short STRCOMP ; Equal so far, keep going + + +CRPRINT: + PUSH AX + MOV AL,13 + PUSH CX + PUSH DI + MOV DI,DX + MOV CX,-1 + PUSH ES + PUSH DS + POP ES + + REPNZ SCASB ; LOOK FOR TERMINATOR + mov byte ptr [di-1],0 ; nul terminate the string + POP ES + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + invoke std_printf + mov ds:byte ptr [di-1],13 ; now put the CR back + JC ERROR_OUTPUT + + POP DI + POP CX + POP AX + + return + +ERROR_OUTPUT: + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + + MOV DX,OFFSET TRANGROUP:NOSPACE_ptr + CMP [PIPEFLAG],0 + JZ GO_TO_ERROR + + invoke PipeOff + MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr +GO_TO_ERROR: + JMP CERROR + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +PATHCHRCMP: +;---- Mod for path invocation ---- +PUBLIC pathchrcmp +;---- + + push ax + mov ah,'/' + CMP [SWITCHAR],ah + JZ NOSLASHT + CMP AL,'/' + jz pccont + +NOSLASHT: + CMP AL,'\' +pccont: + pop ax + + return + +; Drive taken from FCB +; User dir saved in userdir1 +; +; Zero set if path dir, CHDIR to this dir, FCB filled with ? +; NZ set if path/file, CHDIR to file, FCB has file (parsed fill ' ') +; [DESTTAIL] points to parse point +; Carry set if no CHDIRs worked, FCB not altered. +; DESTISDIR set non zero if PATHCHRs in path (via SETPATH) +; +PATHCRUNCH: + mov [msg_numb],0 ;AN022; Set up message flag + MOV DL,DS:[FCB] + CALL SAVUDIR + jc pcrunch_cderrJ ;AN022; if error on current dir - report + + invoke SETPATH + TEST [DESTINFO],2 + JNZ TRYPEEL ; If ? or * cannot be pure dir + + MOV AH,CHDIR + INT int_command + jnc chdir_worked ;AN022; no error - continue + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; if path not found + jz trypeel ;AC022; keep trying + cmp ax,error_access_denied ;AN022; if access denied + jz trypeel ;AC022; keep trying + mov [msg_numb],ax ;AN022; set up message flag + jmp peelfail ;AN022; exit with other error + +chdir_worked: + invoke SETREST1 + MOV AL,'?' ; *.* is default file spec if pure dir + MOV DI,5DH + MOV CX,11 + REP STOSB + XOR AL,AL ; Set zero + return + +pcrunch_cderrj: ;AN022; need this for long jmp + jmp pcrunch_cderr ;AN022; + +TRYPEEL: + MOV SI,[PATHPOS] + DEC SI ; Point at NUL + MOV AL,[SI-1] + + CMP [KPARSE],0 + JNZ DELSTRT ; Last char is second KANJI byte, might be '\' + + CALL PATHCHRCMP + JZ PEELFAIL ; Trailing '/' + +DELSTRT: + MOV CX,SI + MOV SI,DX + PUSH DX +DELLOOP: + CMP SI,CX + JZ GOTDELE + LODSB + invoke TESTKANJ + JZ NOTKANJ8 + INC SI + JMP DELLOOP + +NOTKANJ8: + CALL PATHCHRCMP + JNZ DELLOOP + MOV DX,SI + DEC DX + JMP DELLOOP + +GOTDELE: + MOV SI,DX + POP DX + CMP SI,DX + JZ BADRET + MOV CX,SI + MOV SI,DX +DELLOOP2: ; Set value of KPARSE + CMP SI,CX + JZ TRYCD + MOV [KPARSE],0 + LODSB + INVOKE TESTKANJ + JZ DELLOOP2 + INC SI + INC [KPARSE] + JMP DELLOOP2 + +TRYCD: + push ax + mov al,dot_chr + CMP BYTE PTR [SI+1],al + pop ax + JZ PEELFAIL ; If . or .., pure cd should have worked + mov al,[si-1] + CMP al,':' ; Special case d:\file + JZ BADRET + + CMP [KPARSE],0 + JNZ NOTDOUBLESL ; Last char is second KANJI byte, might be '\' + + CALL PATHCHRCMP + JNZ NOTDOUBLESL +PEELFAIL: + STC ; // + return +NOTDOUBLESL: + MOV BYTE PTR [SI],0 + MOV AH,CHDIR + INT int_command + JNC CDSUCC +pcrunch_cderr: + invoke get_ext_error_number ;AN022; get the extended error + mov [msg_numb],ax ;AN022; set up message flag + or si,si ;AN022; set up zero flag to not zero + stc ;AN022; set up carry flag + return + +BADRET: + MOV AL,[SI] + CALL PATHCHRCMP ; Special case 'DIRCHAR'file + STC + retnz + XOR BL,BL + XCHG BL,[SI+1] + MOV AH,CHDIR + INT int_command + jc pcrunch_cderr ;AN022; go to error exit + MOV [SI+1],BL +CDSUCC: + invoke SETREST1 + INC SI ; Reset zero + MOV [DESTTAIL],SI + pushf ;AN015; save flags + cmp dirflag,-1 ;AN015; don't do parse if in DIR + jz pcrunch_end ;AN015; + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H ; Parse with default drive + INT int_command +pcrunch_end: + popf ;AN015; get flags back + return + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TFOR.ASM b/v4.0/src/CMD/COMMAND/TFOR.ASM new file mode 100644 index 0000000..8454d5c --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TFOR.ASM @@ -0,0 +1,551 @@ + page 80,132 +; SCCSID = @(#)tfor.asm 4.1 85/09/17 +; SCCSID = @(#)tfor.asm 4.1 85/09/17 +TITLE Part3 COMMAND Transient Routines + +; For loop processing routines + + +.xlist +.xcref + include comsw.asm + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + include comseg.asm + include comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN ECHOFLAG:BYTE + EXTRN FORFLAG:BYTE + EXTRN FORPTR:WORD + EXTRN NEST:WORD + EXTRN NULLFLAG:BYTE + EXTRN PIPEFILES:BYTE + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN Extend_buf_ptr:word ;AN000; + extrn fornestmes_ptr:word + EXTRN msg_disp_class:byte ;AN000; + extrn string_buf_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn arg:byte ; the arg structure! + EXTRN COMBUF:BYTE + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN docom:near + EXTRN docom1:near + EXTRN forerror:near + EXTRN tcommand:near + + PUBLIC $for + PUBLIC forproc + + +; All batch proccessing has DS set to segment of resident portion +ASSUME DS:RESGROUP,ES:TRANGROUP + + +FORTERM: + push cs ;AN037; Get local segment into + pop ds ;AN037; DS, ES + push cs ;AN037; + pop es ;AN037; + call ForOff + mov ds,ResSeg +ASSUME DS:RESGROUP + CMP [SINGLECOM],0FF00H + JNZ BATCRLF + CMP NEST,0 ;G See if we have nested batch files + JNZ BATCRLF ;G Yes - don't exit just yet + MOV [SINGLECOM],-1 ; Cause a terminate + JMP SHORT NOFORP2 + +BATCRLF: + test [ECHOFLAG],1 ;G Is echo on? + JZ NOFORP2 ;G no - exit + TEST [BATCH], -1 ;G print CRLF if in batch + JZ NOFORP2 ;G + invoke CRLF2 + +NOFORP2: + JMP TCOMMAND + + +;------ +; For-loop processing. For loops are of the form: +; for % in () do +; where may contain references of the form %, which are +; later substituted with the items in . The for-loop structure is +; set-up by the procedure '$for'; successive calls to 'forproc' execute +; once for each item in . All of the information needed for +; loop processing is stored on a piece of memory gotten from 'alloc'. This +; structure is actually fairly large, on the order of 700 bytes, and includes +; a complete copy of the original command-line structure as parsed by +; 'parseline', loop control variables, and a dma buffer for the +; 'FindFirst/FindNext' expansion of wildcard filenames in . When loop +; processing has completed, this chunk of memory is returned to the system. +; +; All of the previously defined variables, in 'datares', used for loop +; processing may be erased. Only one, (DW) ForPtr, need be allocated. +; +; The error message, 'for_alloc_mes', should be moved into the file +; containing all of the other error messages. +; +; Referencing the allocated for-loop structure is a little tricky. +; At the moment, a byte is defined as part of a new segment, 'for_segment'. +; When 'forproc' actually runs, ES and DS are set to point to the base of the +; new chunk of memory. References to this byte, 'f', thus assemble correctly +; as offsets of ES or DS. 'f' would not be necessary, except that the +; assembler translates an instruction such as 'mov AX, [for_minarg]' as an +; immediate move of the offset of 'for_minarg' into AX. In other words, in +; terms of PDP-11 mnemonics, the assembler ACTUALLY assembles +; mov AX, #for_minarg ; AX := 02CA (for example) +; instead of +; mov AX, for_minarg ; AX := [02CA] (contents of 02CA) +; By using 'f', we pretend that we are actually referencing an allocated +; structure, and the assembler coughs up the code we want. Notice that it +; doesn't matter whether we put brackets around the location or not -- the +; assembler is "smart" enough to know that we want an address instead of the +; contents of that location. +; +; Finally, there now exists the potential to easily implement nested loops. +; One method would be to have a link field in each for-structure pointing to +; its parent. Variable references that couldn't be resolved in the local +; frame would cause a search of prior frames. For-structures would still be +; allocated and released in exactly the same fashion. The only limit on the +; number of nested loops would be memory size (although at 700 bytes a pop, +; memory wouldn't last THAT long). Alternately, a small structure could be +; maintained in the resident data area. This structure would be an array of +; control-variable names and pointers to for-structure blocks. This would +; greatly speed up the resolution of non-local variable references. However, +; since space in the resident is precious, we would have to compromise on a +; "reasonable" level of nesting -- 10, 16, 32 levels, whatever. For-structure +; allocation and de-allocation would have to be modified slightly to take this +; new structure into account. +; +; Oops, just one more thing. Forbuf need not be a part of the for-structure. +; It could just as well be one structure allocated in 'transpace'. Actually, +; it may be easier to allocate it as part of 'for_segment'. +;------ + + include fordata.asm + +$for_exit: + jmp forterm ; exceeding maxarg means all done + +forproc: +assume DS:resgroup + mov AX, [ForPtr] + mov DS, AX + mov ES, AX ; operate in for-info area +assume DS:for_segment, ES:for_segment + + mov DX, OFFSET fordma + trap Set_Dma +for_begin: + cmp f.for_expand, 0 ; non-zero for_expand equals FALSE + je for_begin1 + inc f.for_minarg +for_begin1: + mov BX, f.for_minarg ; current item in to examine + cmp BX, f.for_maxarg + jg $for_exit ; exceeding maxarg means all done + mov AX, OFFSET for_args.argv + invoke argv_calc ; compute argv[x] address + + mov CX, [BX].argstartel + mov DX, [BX].argpointer + test [bx].argflags,00000100b ; Is there a path separator in this arg? + jnz forsub ; Yes, argstartel should be correct + mov si, [BX].argpointer + mov al,lparen + cmp byte ptr [si-1],al ; If the current token is the first + jnz forsub ; one in the list and originally had + inc cx ; the opening paren as its first char, + ; the argstartel ptr needs to be + ; advanced passed it before the prefix + ; length is computed. + mov al,':' + cmp byte ptr [si+1],al ; If the token begins with "(d:", + jnz forsub ; argstartel has to be moved over the + add cx,2 ; rest of the prefix as well. + +forsub: + sub CX, DX ; compute length of pathname prefix + cmp f.for_expand, 0 ; are we still expanding a name? + je for_find_next ; if so, get next matching filename + + test [BX].argflags, MASK wildcard + jnz for_find_first ; should we expand THIS (new) arg? + mov CX, [BX].arglen ; else, just copy all of it directly + jmp for_smoosh + +for_find_first: + PUSH CX + XOR CX,CX + trap Find_First ; and search for first filename match + POP CX + jmp for_result +for_find_next: + trap Find_Next ; search for next filename match + +for_result: + mov AX, -1 ; assume worst case + jc forCheck + mov ax,0 +forCheck: ; Find* returns 0 for SUCCESS + mov f.FOR_EXPAND, AX ; record success of findfirst/next + or AX, AX ; anything out there? + jnz for_begin ; if not, try next arg + +for_smoosh: + mov SI, [BX].argpointer ; copy argv[arg][0,CX] into destbuf + mov DI, OFFSET forbuf ; some days this will be the entire + rep movsb ; arg, some days just the path prefix + + cmp f.FOR_EXPAND, 0 ; if we're not expanding, we can + jnz for_make_com ; skip the following + + mov SI, OFFSET fordma.find_buf_pname +for_more: ; tack on matching filename + cmp BYTE PTR [SI], 0 + je for_make_com + movsb + jnz for_more + +for_make_com: + xor AL, AL ; tack a null byte onto the end + stosb ; of the substitute string + + xor CX, CX ; character count for command line + not CX ; negate it -- take advantage of loopnz + xor BX, BX ; argpointer + mov DI, OFFSET TRANGROUP:COMBUF+2 + mov bl, f.FOR_COM_START ; argindex + mov DH, f.FOR_VAR ; % is replaced by [forbuf] + ; time to form the string + push CS + pop ES +assume ES:trangroup + + mov AX, OFFSET for_args ; translate offset to pointer + invoke argv_calc + mov si,[bx].arg_ocomptr + inc si ; mov ptr passed beginning space + +for_make_loop: + mov al,[si] ; the arg, byte by byte + inc si + cmp AL,'%' ; looking for % + jne for_stosb ; no % ... add byte to string + cmp BYTE PTR [SI], DH ; got the right ? + jne for_stosb ; got a %, but wrong + inc SI ; skip over + + push SI + mov SI, OFFSET forbuf ; substitute the for + ; to make a final to execute +sloop: + lodsb ; grab all those bytes, and + stosb ; add 'em to the string, + or AL, AL ; until we run into a null + loopnz sloop + dec DI ; adjust length and pointer + inc CX ; so we can overwrite the null + + pop SI + jmp for_make_loop ; got back for more bytes +for_stosb: + stosb ; take a byte from the arg + dec CX ; and put it into the to be + ; executed (and note length, too) + cmp al,0dh ; If not done, loop. + jne for_make_loop + +for_made_com: ; finished all the args + not CL ; compute and record command length + mov [COMBUF+1], CL + + mov DS, [RESSEG] +assume DS:resgroup + + test [ECHOFLAG],1 ; shall we echo this , dearie? + jz noecho3 + cmp nullflag,nullcommand ;G was there a command last time? + jz No_crlf_pr ;G no - don't print crlf + invoke CRLF2 ;G Print out prompt + +no_crlf_pr: + mov nullflag,0 ;G reset no command flag + push CS + pop DS + assume DS:trangroup + push di + invoke PRINT_PROMPT ;G Prompt the user + pop di + mov BYTE PTR ES:[DI-1],0 ; yeah, PRINT it out... + mov string_ptr_2,OFFSET TRANGROUP:COMBUF+2 + mov dx,offset trangroup:string_buf_ptr + invoke std_printf + mov BYTE PTR ES:[DI-1], 0DH + jmp DoCom +noecho3: ; run silent, run deep... + assume DS:resgroup + mov nullflag,0 ;G reset no command flag + push CS + pop DS + assume DS:trangroup + jmp docom1 + + +fornesterrj: ; no multi-loop processing... yet! +assume ES:resgroup + call ForOff + jmp fornesterr + +forerrorj: + jmp forerror + + break $For +assume ds:trangroup,es:trangroup + +$for: + mov ES, [RESSEG] +assume ES:resgroup + + cmp ForFlag,0 ; is another one already running? + jnz fornesterrj ; if flag is set.... boom! + +; +; Turn off any pipes in progress. +; + cmp [PIPEFILES],0 ; Only turn off if present. + jz NoPipe + invoke PipeDel +NoPipe: + xor DX, DX ; counter (0 <= DX < argvcnt) + call nextarg ; move to next argv[n] + jc forerrorj ; no more args -- bad forloop + cmp AL,'%' ; next arg MUST start with '%'... + jne forerrorj + mov BP, AX ; save forloop variable + lodsb + or AL, AL ; and MUST end immediately... + jne forerrorj + + call nextarg ; let's make sure the next arg is 'in' + jc forerrorj + and AX, NOT 2020H ; uppercase the letters + cmp AX, in_word + jne forerrorj + lodsb + or AL, AL ; it, too, must end right away + je CheckLParen +; +; Not null. Perhaps there are no spaces between this and the (: +; FOR %i in(foo bar... +; Check for the Lparen here +; + CMP AL,lparen + JNZ forerrorj +; +; The token was in(... We strip off the "in" part to simulate a separator +; being there in the first place. +; + ADD [BX].argpointer,2 ; advance source pointer + ADD [BX].arg_ocomptr,2 ; advance original string + SUB [BX].arglen,2 ; decrement the appropriate length +; +; SI now points past the in(. Simulate a nextarg call that results in the +; current value. +; + MOV ax,[si-1] ; get lparen and next char + jmp short lpcheck + +CheckLParen: + call nextarg ; lparen delimits beginning of + jc forerrorj +lpcheck: + cmp al, lparen + jne forerrorj + cmp ah,0 + je for_paren_token + + cmp ah, rparen ; special case: null list + jne for_list_not_empty + jmp forterm + +for_list_not_empty: + inc [bx].argpointer ; Advance ptr past "(" + ; Adjust the rest of this argv entry + dec [bx].arglen ; to agree. + inc si ; Inc si so check for ")" works + jmp for_list + +for_paren_token: + call nextarg ; what have we in our ? + jc forerrorj + cmp ax, nullrparen ; special case: null list + jne for_list + jmp forterm + +forerrorjj: + jmp forerror + +for_list: ; skip over rest of + mov CX, DX ; first arg of +skip_list: + add si,[bx].arglen + sub si,3 ; si = ptr to last char of token + mov al,rparen + cmp byte ptr [si],al ; Is this the last element in + je for_end_list ; Yes, exit loop. + call nextarg ; No, get next arg + jc forerrorjj ; If no more and no rparen, error. + jmp skip_list +for_end_list: + mov DI, DX ; record position of last arg in + mov byte ptr [si],0 ; Zap the rparen + cmp ax,nullrparen ; Was this token only a rparen + jz for_do ; Yes, continue + inc di ; No, inc position of last arg + +for_do: + call nextarg ; now we had BETTER find a 'do'... + jc forerrorjj + and AX, NOT 2020H ; uppercase the letters + cmp AX, do_word + jne forerrorjj + lodsb + or AL, AL ; and it had BETTER be ONLY a 'do'... + jne forerrorjj + + call nextarg ; on to the beginning of + jc forerrorjj ; null not legal + + push AX + push BX + push CX + push DX ; preserve registers against disaster + push DI + push SI + push BP + invoke FREE_TPA ; need to make free memory, first +ASSUME ES:RESGROUP + call ForOff + mov BX, SIZE for_info - SIZE arg_unit + invoke Save_Args ; extra bytes needed for for-info + pushf + mov [ForPtr], AX + invoke ALLOC_TPA ; ALLOC_TPA clobbers registers... + popf + pop BP + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + jc for_alloc_err + + push ES ; save resgroup seg... + push [ForPtr] + pop ES +assume ES:for_segment ; make references to for-info segment + + dec CX ; forproc wants min pointing before + dec DI ; first arg, max right at last one + mov f.for_minarg, CX + mov f.for_maxarg, DI + mov f.for_com_start, DL + mov f.for_expand, -1 ; non-zero means FALSE + mov AX, BP + mov f.for_var, AH + pop ES +assume ES:resgroup + + inc [FORFLAG] + cmp [SINGLECOM], -1 + jnz for_ret + mov [SINGLECOM], 0FF00H +for_ret: + ret + +for_alloc_err: + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block + jmp cerror + +nextarg: + inc DX ; next argv[n] + cmp DX, arg.argvcnt ; make sure we don't run off end + jge nextarg_err ; of argv[]... + mov BX, DX + mov AX, OFFSET TRANGROUP:arg.argv + invoke argv_calc ; convert array index to pointer + mov SI, [BX].argpointer ; load pointer to argstring + lodsw ; and load first two chars + clc + ret +nextarg_err: + stc + ret + + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +FORNESTERR: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV DX,OFFSET TRANGROUP:FORNESTMES_ptr + CMP [SINGLECOM],0FF00H + JNZ NOFORP3 + MOV [SINGLECOM],-1 ; Cause termination +NOFORP3: + POP DS +ASSUME DS:TRANGROUP + JMP CERROR +; +; General routine called to free the for segment. We also clear the forflag +; too. Change no registers. +; +PUBLIC ForOff +ForOff: + assume DS:NOTHING,ES:NOTHING + SaveReg + mov es,ResSeg + assume es:ResGroup + mov AX,ForPtr + or ax,ax + jz FreeDone + push es + mov es,ax + mov ah,dealloc + int 21h + pop es +FreeDone: + mov ForPtr,0 + mov ForFlag,0 + RestoreReg + return + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TMISC1.ASM b/v4.0/src/CMD/COMMAND/TMISC1.ASM new file mode 100644 index 0000000..4b55aac --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TMISC1.ASM @@ -0,0 +1,655 @@ + page 80,132 +; SCCSID = @(#)tmisc1.asm 4.1 85/09/22 +; SCCSID = @(#)tmisc1.asm 4.1 85/09/22 +TITLE Part7 COMMAND Transient Routines + +; More misc routines + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN RSTACK:BYTE +CodeRes ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN CALL_FLAG:BYTE + EXTRN EchoFlag:BYTE + EXTRN EXEC_BLOCK:BYTE + EXTRN EXTCOM:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN PIPEPTR:WORD + EXTRN PIPESTR:BYTE + EXTRN RESTDIR:BYTE + EXTRN RE_OUT_APP:BYTE + EXTRN RE_OUTSTR:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADDRV_PTR:WORD + EXTRN BADNAM_PTR:WORD + EXTRN COMTAB:BYTE ;AC000; + EXTRN extend_buf_ptr:word ;AN000; + EXTRN msg_disp_class:byte ;AN000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! + EXTRN APPEND_EXEC:BYTE ;AN041; + EXTRN CHKDRV:BYTE + EXTRN COMBUF:BYTE + EXTRN EXECPATH:BYTE + EXTRN EXEC_ADDR:DWORD + EXTRN FILTYP:BYTE + EXTRN IDLEN:BYTE + EXTRN KPARSE:BYTE ;AC000; + EXTRN PARM1:BYTE + EXTRN PARM2:BYTE + EXTRN PathPos:word + EXTRN RESSEG:WORD + EXTRN RE_INSTR:BYTE + EXTRN SPECDRV:BYTE + EXTRN SWITCHAR:BYTE + EXTRN switch_list:byte + EXTRN TRAN_TPA:WORD + + IF IBM + EXTRN ROM_CALL:BYTE + EXTRN ROM_CS:WORD + EXTRN ROM_IP:WORD + ENDIF + +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN APPEND_PARSE:NEAR ;AN010; + EXTRN BATCOM:NEAR + EXTRN DOCOM1:NEAR + EXTRN PIPEERRSYN:NEAR + EXTRN TCOMMAND:NEAR + + IF IBM + EXTRN ROM_EXEC:NEAR + EXTRN ROM_SCAN:NEAR + ENDIF + + PUBLIC CERROR + PUBLIC DRVBAD + PUBLIC EXTERNAL + PUBLIC FNDCOM + PUBLIC PRESCAN + PUBLIC SWITCH + + +ASSUME DS:TRANGROUP + +;--------------------------- +; We can get rid of this switch processing code if we can take +; care of the remaining two calls to switch, later in the file. +; However, I have not checked whether or not any other files use +; switch -- after all, it IS public! +;--------------------------- +RETSW: + XCHG AX,BX ; Put switches in AX + return + +SWITCH: + XOR BX,BX ; Initialize - no switches set +SWLOOP: + INVOKE SCANOFF ; Skip any delimiters + CMP AL,[SWITCHAR] ; Is it a switch specifier? + JNZ RETSW ; No -- we're finished + OR BX,fSwitch ; Indicate there is a switch specified + INC SI ; Skip over the switch character + INVOKE SCANOFF + CMP AL,0DH + JZ RETSW ; Oops + INC SI +; Convert lower case input to upper case + INVOKE UPCONV + MOV DI,OFFSET TRANGROUP:switch_list + MOV CX,SWCOUNT + REPNE SCASB ; Look for matching switch + JNZ BADSW + MOV AX,1 + SHL AX,CL ; Set a bit for the switch + OR BX,AX + JMP SHORT SWLOOP + +BADSW: + JMP SHORT SWLOOP + +SWCOUNT EQU 5 ; Length of switch_list + +DRVBAD: + MOV DX,OFFSET TRANGROUP:BADDRV_ptr + JMP CERROR + +externalj: + jmp EXTERNAL + +fndcom: ; search the internal command table + OR AL,AL ; Get real length of first arg + jz externalj ; If 0, it must begin with "\" so has + ; to be external. +; barryf code starts here + + IF IBM + call test_append ; see if APPEND installed + je contcom ; not loaded + +append_internal: + mov cl,TRANGROUP:IDLEN + mov ch,0 + mov pathpos,cx + inc append_exec ;AN041; set APPEND to ON + + invoke ioset ; re-direct the o'l io + + mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set + mov DX,-1 ; set invoke function + mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND + mov AX,0AE01H + int 2FH ; execute command + cmp TRANGROUP:IDLEN,0 ; execute requested + jne contcom + jmp Cmd_done + +contcom: ; continue with internal scan + ENDIF + +; barryf code ends here + + mov DI, OFFSET TRANGROUP:COMTAB + XOR CX,CX + +findcom: + mov SI, offset TRANGROUP:IDLEN+1 ; pointer to command argument + mov CL, [DI] ; load length of internal command + inc di ; advance past length + jcxz externalj ; if it's zero, we're out of internals + cmp CL, IDLEN ; that of the command argument + jnz abcd ; lengths not equal ==> strings not eq + MOV PathPos,CX ; store length of command + repz cmpsb + +abcd: + lahf ; save the good ol' flags + add DI, CX ; skip over remaining internal, if any + mov AL, BYTE PTR [DI] ; load drive-check indicator byte (DCIB) + mov [CHKDRV], AL ; save command flag byte in chkdrv + inc DI ; increment DI (OK, OK, I'll stop) + mov BX, WORD PTR [DI] ; load internal command address + inc DI ; skip over the puppy + inc DI + sahf ; remember those flags? + jnz findcom ; well, if all the cmps worked... +; +; All messages get redirected. +; + cmp append_exec,0 ;AN041; APPEND just executed? + jnz dont_set_io ;AN041; Yes - this junk is already set + invoke ioset ; re-direct the ol' i/o + +dont_set_io: ;AN041; + invoke SETSTDINON ;AN026; turn on critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + test [CHKDRV], fCheckDrive ; did we wanna check those drives? + jz nocheck + mov AL, [PARM1] ; parse_file_descriptor results tell + or AL, [PARM2] ; us whether those drives were OK + cmp AL, -1 + jnz nocheck + jmp drvbad + + +; +; The user may have omitted the space between the command and its arguments. +; We need to copy the remainder of the user's command line into the buffer. +; Note that thisdoes not screw up the arg structure; it points into COMBUF not +; into the command line at 80. +; +nocheck: + call cmd_copy + +switcheck: + test [CHKDRV], fSwitchAllowed ; Does the command take switches + jnz realwork ; Yes, process the command + call noswit ; No, check to see if any switches + jnz realwork ; None, process the command + mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class + MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number + jmp CERROR ; Print error and chill out... +realwork: + call BX ; do some real work, at last + +; See if we're in a batch CALL command. If we are, reprocess the command line, +; otherwise, go get another command. + +Cmd_done: + push cs ; g restore data segment + pop ds ; g + push ds ; g save data segment + mov ds,[resseg] ; g get segment containing call flag + ASSUME ds:resgroup + cmp call_flag, call_in_progress ; G Is a call in progress? + mov call_flag, 0 ; G Either way, reset flag + pop ds ; g get data segment back + jz incall ; G + jmp tcommand ; chill out... + +incall: + JMP DOCOM1 + +noswit: + push di ; Save di + mov di,81h ; di = ptr to command args + mov si,80h ; Get address of length of command args + lodsb ; Load length + mov cl,al ; Move length to cl + xor ch,ch ; Zero ch + mov al,[SWITCHAR] ; al = switch character + cmp al,0 ; Turn off ZF + repnz scasb ; Scan for a switch character and return + pop di ; with ZF set if one was found + ret + +EXTERNAL: + +IF IBM + call test_append ; check to see if append installed + je not_barryf ; no - truly external command + jmp append_internal ; yes - go to Barryf code + +not_barryf: + +ENDIF + + MOV [FILTYP],0 + MOV DL,[SPECDRV] + MOV [IDLEN],DL +IF IBM + MOV [ROM_CALL],0 + PUSH DX + MOV DX,OFFSET TRANGROUP:IDLEN + CALL ROM_SCAN + POP DX + JNC DO_SCAN + INC [ROM_CALL] + JMP PostSave +DO_SCAN: +ENDIF +IF IBM +PostSave: +ENDIF + MOV DI,OFFSET TRANGROUP:EXECPATH + MOV BYTE PTR [DI],0 ; Initialize to current directory +IF IBM + CMP [ROM_CALL],0 + JZ Research + JMP NeoExecute +ENDIF +RESEARCH: + invoke path_search ; find the mother (result in execpath) + or AX, AX ; did we find anything? + je badcomj45 ; null means no (sob) + cmp AX, 04H ; 04H and 08H are .exe and .com + jl rsrch_br1 ; fuckin' sixteen-bit machine ought + jmp execute ; to be able to handle a SIXTEEN-BIT +rsrch_br1: ; DISPLACEMENT!! + jmp batcom ; 02H is .bat +BADCOMJ45: + JMP BADCOM + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +EXECUTE: +NeoExecute: + invoke IOSET + invoke SETSTDINOFF ;AN026; turn off critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + MOV ES,[TRAN_TPA] + MOV AH,DEALLOC + INT int_command ; Now running in "free" space + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + INC [EXTCOM] ; Indicate external command + MOV [RESTDIR],0 ; Since USERDIR1 is in transient, insure + ; this flag value for re-entry to COMMAND + MOV DI,FCB + MOV SI,DI + MOV CX,052H ; moving (100h-5Ch)/2 = 80h-2Eh + REP MOVSW ; Transfer parameters to resident header + MOV DX,OFFSET TRANGROUP:EXECPATH + MOV BX,OFFSET RESGROUP:EXEC_BLOCK + MOV AX,EXEC SHL 8 +IF IBM + TEST [ROM_CALL],-1 + JZ OK_EXEC + JMP ROM_EXEC +OK_EXEC: +ENDIF +; +; we are now running in free space. anything we do from here on may get +; trashed. Move the stack (also in free space) to allocated space because +; since EXEC restores the stack, somebody may trash what is on the stack. +; + MOV CX,ES + MOV SS,CX + MOV SP,OFFSET RESGROUP:RSTACK + JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident + +BADCOM: + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADNAM_ptr + +CERROR: + INVOKE std_eprintf + JMP TCOMMAND + +; +; Prescan converts the input buffer into a canonicalized form. All +; redirections and pipes are removed. +; +PRESCAN: ; Cook the input buffer + +ASSUME DS:TRANGROUP,ES:TRANGROUP + + XOR CX,CX + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV DI,SI + +CountQuotes: + LODSB ; get a byte + CMP AL,22h ; is it a quote? + JNZ CountEnd ; no, try for end of road + INC CH ; bump count + JMP CountQuotes ; go get next char + +CountEnd: + CMP AL,13 ; end of road? + JNZ CountQuotes ; no, go back for next char + +;;;; IF KANJI 3/3/KK + PUSH CX ; save count + MOV SI,DI ; get back beginning of buffer + +KanjiScan: + LODSB ; get a byte + INVOKE TestKanj ; is it a leadin byte + JZ KanjiQuote ; no, check for quotes + MOV AH,AL ; save leadin + LODSB ; get trailing byte + CMP AX,8140h ; is it Kanji space + JNZ KanjiScan ; no, go get next + MOV [SI-2],2020h ; replace with spaces + JMP KanjiScan ; go get next char + +KanjiQuote: + CMP AL,22h ; beginning of quoted string + JNZ KanjiEnd ; no, check for end + DEC CH ; drop count + JZ KanjiScan ; if count is zero, no quoting + +KanjiQuoteLoop: + LODSB ; get next byte + CMP AL,22h ; is it another quote + JNZ KanjiQuoteLoop ; no, get another + DEC CH ; yes, drop count + JMP KanjiScan ; go get next char + +KanjiEnd: + CMP AL,13 ; end of line character? + JNZ KanjiScan ; go back to beginning + POP CX ; get back original count +;;;; ENDIF 3/3/KK + + MOV SI,DI ; restore pointer to begining + +PRESCANLP: + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE TESTKANJ + JZ NOTKANJ6 + MOV [DI],AL + INC DI ; fake STOSB into DS + LODSB ; grab second byte + MOV [DI],AL ; fake stosb into DS + INC DI + INC CL + INC CL + JMP PRESCANLP + +NOTKANJ6: +;;;; ENDIF 3/3/KK + + CMP AL,'"' ; " character + JNZ TRYGREATER + DEC CH + JZ TRYGREATER + +QLOOP: + MOV [DI],AL + INC DI + INC CL + LODSB + CMP AL,'"' ; " character + JNZ QLOOP + DEC CH + +TRYGREATER: + CMP AL,rabracket + JNZ NOOUT +; +; We have found a ">" char. We need to see if there is another ">" +; following it. +; + CMP BYTE PTR [SI],al + JNZ NOAPPND + LODSB + INC [RE_OUT_APP] ; Flag >> + +NOAPPND: +; +; Now we attempt to find the file name. First, scan off all whitespace +; + INVOKE SCANOFF + CMP AL,labracket ;AN040; was there no filename? + JZ REOUT_ERRSET ;AN040; yes - set up error + CMP AL,0DH + JNZ GOTREOFIL +; +; There was no file present. Set us up at end-of-line. +; +REOUT_ERRSET: ;AN040; set up for an error + mov byte ptr [di], 0dh ; Clobber first ">" + MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later + JMP PRESCANEND + +GOTREOFIL: + PUSH DI + MOV DI,OFFSET RESGROUP:RE_OUTSTR + MOV BX,DI + PUSH ES + +SETREOUTSTR: ; Get the output redirection name + LODSB + CMP AL,0DH + JZ GOTRESTR + INVOKE DELIM + JZ GOTRESTR + CMP AL,[SWITCHAR] + JZ GOTRESTR + CMP AL,'"' ;AN033; Is the character a quote? + JZ PIPEERRSYNJ5 ;AN033; Yes - get out quick - or system crashes + CMP AL,labracket ;AN002; Is char for input redirection + JZ ABRACKET_TERM ;AN002; yes - end of string + CMP AL,rabracket ;AN002; Is char for output redirection + JNZ NO_ABRACKET ;AN002; no - not end of string + +abracket_term: ;AN002; have end of string by < or > + DEC SI ;AN002; back up over symbol + MOV AL,BLANK ;AN002; show delimiter as char + JMP SHORT GOTRESTR ;AN002; go process it + +no_abracket: ;AN002; not at end of string + STOSB ; store it into resgroup + JMP SHORT SETREOUTSTR + +NOOUT: + CMP AL,labracket + JNZ CHKPIPE + mov bx,si ; Save loc of "<" + INVOKE SCANOFF + CMP AL,rabracket ;AN040; was there no filename? + JZ REIN_ERRSET ;AN040; yes - set up error + CMP AL,0DH + JNZ GOTREIFIL + +REIN_ERRSET: ;AN040; set up for error + mov byte ptr [di],0dh ; Clobber "<" + MOV WORD PTR [RE_INSTR],09H ; Cause an error later + JMP SHORT PRESCANEND + +GOTREIFIL: + PUSH DI + MOV DI,OFFSET TranGROUP:RE_INSTR + MOV BX,DI + PUSH ES + PUSH CS + POP ES ; store in TRANGROUP + JMP SHORT SETREOUTSTR ; Get the input redirection name + +CHKPIPE: + MOV AH,AL + CMP AH,AltPipeChr + JZ IsPipe3 + CMP AH,vbar + JNZ CONTPRESCAN + +IsPipe3: +; +; Only push the echo flag if we are entering the pipe for the first time. +; + CMP PipeFlag,0 + JNZ NoEchoPush + SHL EchoFlag,1 ; push echo state and turn it off +NoEchoPush: + INC [PIPEFLAG] + INVOKE SCANOFF + CMP AL,0DH + JZ PIPEERRSYNJ5 + CMP AL,AltPipeChr + JZ PIPEERRSYNJ5 + CMP AL,vbar ; Double '|'? + JNZ CONTPRESCAN + +PIPEERRSYNJ5: + PUSH ES + POP DS ; DS->RESGROUP + JMP PIPEERRSYN + +; +; Trailing :s are allowed on devices. Check to be sure that there is more +; than just a : in the redir string. +; +GOTRESTR: + XCHG AH,AL + mov al,':' + SUB BX,DI ; compute negatinve of number of chars + CMP BX,-1 ; is there just a :? + JZ NotTrailCol ; yep, don't change + CMP BYTE PTR ES:[DI-1],al ; Trailing ':' OK on devices + JNZ NOTTRAILCOL + DEC DI ; Back up over trailing ':' + +NOTTRAILCOL: + XOR AL,AL + STOSB ; NUL terminate the string + POP ES + POP DI ; Remember the start + +CONTPRESCAN: + MOV [DI],AH ; "delete" the redirection string + INC DI + CMP AH,0DH + JZ PRESCANEND + INC CL + JMP PRESCANLP + +PRESCANEND: + CMP [PIPEFLAG],0 + JZ ISNOPIPE + MOV DI,OFFSET RESGROUP:PIPESTR + MOV [PIPEPTR],DI + MOV SI,OFFSET TRANGROUP:COMBUF+2 + INVOKE SCANOFF + +PIPESETLP: ; Transfer the pipe into the resident + LODSB ; pipe buffer + STOSB + CMP AL,0DH + JNZ PIPESETLP + +ISNOPIPE: + MOV [COMBUF+1],CL + CMP [PIPEFLAG],0 + PUSH CS + POP ES + return + +cmd_copy proc near + + MOV SI,OFFSET TRANGROUP:COMBUF+2 + INVOKE Scanoff ; advance past separators... + add si,PathPos + mov di,81h + xor cx,cx + +CmdCopy: + lodsb + stosb + cmp al,0dh + jz CopyDone + inc cx + jmp CmdCopy + +CopyDone: + mov byte ptr ds:[80h],cl ; Store count + + ret +cmd_copy endp + + +test_append proc near + + mov BX,offset TRANGROUP:COMBUF ; barry can address + mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set + mov DX,-1 ; set install check function + mov AX,0AE00H + int 2FH ; see if loaded + cmp AL,00H + + ret + +test_append endp + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TMISC2.ASM b/v4.0/src/CMD/COMMAND/TMISC2.ASM new file mode 100644 index 0000000..cc30428 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TMISC2.ASM @@ -0,0 +1,487 @@ + page 80,132 +; SCCSID = @(#)tmisc2.asm 4.3 85/06/25 +; SCCSID = @(#)tmisc2.asm 4.3 85/06/25 +TITLE Part7 COMMAND Transient Routines + +; More misc routines + + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + INCLUDE ioctl.inc +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CodeRes ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN IFFlag:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN RE_OUTSTR:BYTE + EXTRN RE_OUT_APP:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN AccDen_PTR:WORD + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN FULDIR_PTR:WORD + EXTRN msg_disp_class:byte ;AN000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN DESTINFO:BYTE + EXTRN DESTISDIR:BYTE + EXTRN KPARSE:BYTE ;AC000; + EXTRN ONE_CHAR_VAL:BYTE ;AN011; + EXTRN PATHCNT:WORD + EXTRN PATHPOS:WORD + EXTRN PATHSW:WORD + EXTRN RE_INSTR:BYTE + EXTRN RESSEG:WORD + EXTRN SRCBUF:BYTE + EXTRN SWITCHAR:BYTE + + IF IBM + EXTRN ROM_CALL:BYTE + EXTRN ROM_CS:WORD + EXTRN ROM_IP:WORD + ENDIF + +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN CERROR:NEAR + + IF IBM + EXTRN ROM_EXEC:NEAR + EXTRN ROM_SCAN:NEAR + ENDIF + + PUBLIC IOSET + PUBLIC MOVE_TO_SRCBUF ;AN000; + PUBLIC PGETARG + PUBLIC SETPATH + PUBLIC TESTDOREIN + PUBLIC TESTDOREOUT + + +ASSUME DS:TRANGROUP + +SETPATH: +; +; Get an ASCIZ argument from the unformatted parms +; DESTISDIR set if pathchars in string +; DESTINFO set if ? or * in string +; + MOV AX,[PATHCNT] ;AC000; get length of string + MOV SI,[PATHPOS] ;AC000; get start of source buffer + +GETPATH: + MOV [DESTINFO],0 + MOV [DESTISDIR],0 + MOV SI,[PATHPOS] + MOV CX,[PATHCNT] + MOV DX,SI + JCXZ PATHDONE + PUSH CX + PUSH SI + INVOKE SWITCH + MOV [PATHSW],AX + POP BX + SUB BX,SI + POP CX + ADD CX,BX + MOV DX,SI + +SKIPPATH: + +;;;; IF KANJI 3/3/KK + MOV [KPARSE],0 + +SKIPPATH2: +;;;; ENDIF 3/3/KK + + JCXZ PATHDONE + DEC CX + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE TESTKANJ + JZ TESTPPSEP + DEC CX + INC SI + INC [KPARSE] + JMP SKIPPATH2 + +TESTPPSEP: +;;;; ENDIF 3/3/KK + + INVOKE PATHCHRCMP + JNZ TESTPMETA + INC [DESTISDIR] + +TESTPMETA: + CMP AL,'?' + JNZ TESTPSTAR + OR [DESTINFO],2 + +TESTPSTAR: + CMP AL,star + JNZ TESTPDELIM + OR [DESTINFO],2 + +TESTPDELIM: + INVOKE DELIM + JZ PATHDONEDEC + CMP AL,[SWITCHAR] + JNZ SKIPPATH + +PATHDONEDEC: + DEC SI + +PATHDONE: + XOR AL,AL + XCHG AL,[SI] + INC SI + CMP AL,0DH + JNZ NOPSTORE + MOV [SI],AL ;Don't loose the CR + +NOPSTORE: + MOV [PATHPOS],SI + MOV [PATHCNT],CX + return + +PGETARG: + MOV SI,80H + LODSB + OR AL,AL + retz + CALL PSCANOFF + CMP AL,13 + return + +PSCANOFF: + LODSB + INVOKE DELIM + JNZ PSCANOFFD + CMP AL,';' + JNZ PSCANOFF ; ';' is not a delimiter + +PSCANOFFD: + DEC SI ; Point to first non-delimiter + return + +IOSET: +; +; ALL REGISTERS PRESERVED +; +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUSH DS + PUSH DX + PUSH AX + PUSH BX + PUSH CX + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + + CMP [PIPEFLAG],0 + JNZ NOREDIR ; Don't muck up the pipe + TEST IFFlag,-1 + JNZ NoRedir + CALL TESTDOREIN + CALL TESTDOREOUT + +NOREDIR: + POP CX + POP BX + POP AX + POP DX + POP DS +ASSUME DS:NOTHING + return + +TESTDOREIN: + +ASSUME DS:RESGROUP + + CMP [RE_INSTR],0 + retz + PUSH DS + PUSH CS + POP DS + MOV DX,OFFSET tranGROUP:RE_INSTR + MOV AX,(OPEN SHL 8) + MOV BX,AX + INT int_command + POP DS + JC REDIRERR + MOV BX,AX + MOV AL,0FFH +; +; Mega sleaze!! We move the SFN from the new handle spot into the old stdin +; spot. We invalidate the new JFN we got. +; + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table],AL + + return +; +; We had some kind of error on the redirection. Figure out what the +; appropriate message should be; BX has the system call that failed +; +REDIRERR: + PUSH CS + POP DS + Call TriageError +; +; At this point, we have recognized the network-generated access denied error. +; The correct message is in DX +; + CMP AX,65 + JZ CERRORJ ;AC000; just issue message returned + CMP BH,OPEN + JZ OpenError +; +; The error was for a create operation. Report the error as a creation error. +; + MOV DX,OFFSET TranGroup:FULDIR_PTR + +CERRORJ: + JMP CERROR +; +; The system call was an OPEN. Report either file not found or path not found. +; + +OpenError: + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,ax ;AN000; get message number in control block + JMP CERROR + +TESTDOREOUT: + +ASSUME DS:RESGROUP + + CMP [RE_OUTSTR],0 + JNZ REOUTEXISTS ;AN017; need long jump + JMP NOREOUT ;AN017; + +REOUTEXISTS: + CMP [RE_OUT_APP],0 + JZ REOUTCRT +; +; The output redirection was for append. We open for write and seek to the +; end. +; + MOV DX,OFFSET RESGROUP:RE_OUTSTR + MOV AX,(OPEN SHL 8) OR 2 ;AC011; Open for read/write + PUSH AX + INT int_command + POP BX + JC OpenWriteError + + MOV BX,AX + MOV AX,IOCTL SHL 8 ;AN035; Get attributes of handle + INT int_command ;AN035; + TEST DL,devid_ISDEV ;AN035; Is it a device? + JNZ SET_REOUT ;AN035; Yes, don't read from it + + MOV AX,(LSEEK SHL 8) OR 2 + MOV CX,-1 ;AC011; MOVE TO EOF -1 + MOV DX,CX ;AC011; + INT int_command + PUSH CS ;AN011; Get transient seg to DS + POP DS ;AN011; + assume DS:Trangroup ;AN011; + MOV AX,(READ SHL 8) ;AN011; Read one byte from the + MOV CX,1 ;AN011; file into one_char_val + MOV DX,OFFSET Trangroup:ONE_CHAR_VAL;AN011; + INT int_command ;AN011; + JC OpenWriteError ;AN011; If error, exit + cmp ax,cx ;AN017; Did we read 1 byte? + jnz reout_0_length ;AN017; No - file must be 0 length + + cmp one_char_val,01ah ;AN011; Was char an eof mark? + mov DS,[resseg] ;AN011; Get resident segment back + assume DS:Resgroup ;AN011; + JNZ SET_REOUT ;AN011; No, just continue + MOV AX,(LSEEK SHL 8) OR 1 ;AN011; EOF mark found + MOV CX,-1 ;AN011; LSEEK back one byte + MOV DX,CX ;AN011; + INT int_command ;AN011; + JMP SHORT SET_REOUT + +reout_0_length: ;AN017; We have a 0 length file + mov DS,[resseg] ;AN017; Get resident segment back + assume DS:Resgroup ;AN017; + MOV AX,(LSEEK SHL 8) ;AN017; Move to beginning of file + XOR CX,CX ;AN017; Offset is 0 + MOV DX,CX ;AN017; + INT int_command ;AN017; + JMP SHORT SET_REOUT ;AN017; now finish setting up redirection + +OpenWriteError: + CMP AX,error_access_denied + STC ; preserve error + JNZ REOUTCRT ;AN017; need long jump + JMP REDIRERR ;AN017; + +REOUTCRT: + MOV DX,OFFSET RESGROUP:RE_OUTSTR + XOR CX,CX + MOV AH,CREAT + PUSH AX + INT int_command + POP BX + JNC NOREDIRERR ;AC011; + JMP REDIRERR ;AC011; + +NOREDIRERR: ;AN011; + MOV BX,AX + +SET_REOUT: +; +; Mega sleaze!! We move the SFN from the new handle spot into the old stdout +; spot. We invalidate the new JFN we got. +; + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table+1],AL + +NOREOUT: + return + +; +; Compute length of string (including NUL) in DS:SI into CX. Change no other +; registers +; +Procedure DSTRLEN,NEAR + + SaveReg + XOR CX,CX + CLD + +DLoop: LODSB + INC CX + OR AL,AL + JNZ DLoop + SUB SI,CX + RestoreReg + return + +EndProc DSTRLEN + +Break + +; +; TriageError will examine the return from a carry-set system call and +; return the correct error if applicable. +; +; Inputs: outputs from a carry-settable system call +; No system calls may be done in the interrim +; Outputs: If carry was set on input +; carry set on output +; DX contains trangroup offset to printf message +; else +; No registers changed +; + +Procedure TriageError,NEAR + + retnc ; no carry => do nothing... + PUSHF + SaveReg + MOV AH,GetExtendedError + INT 21h + RestoreReg ; restore original AX + MOV DX,OFFSET TranGroup:AccDen_PTR + CMP AX,65 ; network access denied? + JZ NoMove ; Yes, return it. + MOV AX,BX + MOV DX,CX + +NoMove: + RestoreReg + popf + return + +EndProc TriageError + +PUBLIC Triage_Init +Triage_Init proc FAR + call TriageError + ret +Triage_Init endp + + +; **************************************************************** +; * +; * ROUTINE: MOVE_TO_SRCBUF +; * +; * FUNCTION: Move ASCIIZ string from DS:SI to SRCBUF. Change +; * terminating 0 to 0dH. Set PATHCNT to length of +; * string. Set PATHPOS to start of SRCBUF. +; * +; * INPUT: DS:SI points to ASCIIZ string +; * ES points to TRANGROUP +; * +; * OUTPUT: SRCBUF filled in with string terminated by 0dH +; * PATHCNT set to length of string +; * PATHPOS set to start of SRCBUF +; * CX,AX changed +; * +; **************************************************************** + +assume es:trangroup,ds:nothing ;AN000; + +MOVE_TO_SRCBUF PROC NEAR ;AN000; + + push si ;AN000; save si,di + push di ;AN000; + push cx ;AN000; + mov di,offset TRANGROUP:srcbuf ;AN000; set ES:DI to srcbuf + xor cx,cx ;AN000; clear cx for counint + mov ax,cx ;AN000; clear ax + push di ;AN000; save start of srcbuf + lodsb ;AN000; get a character from DS:SI + +mts_get_chars: ;AN000; + cmp al,0 ;AN000; was it a null char? + jz mts_end_string ;AN000; yes - exit + stosb ;AN000; no - store it in srcbuf + inc cx ;AN000; increment length count + lodsb ;AN000; get a character from DS:SI + jmp short mts_get_chars ;AN000; go check it + +mts_end_string: ;AN000; we've reached the end of line + mov al,end_of_line_in ;AN000; store 0dH in srcbuf + stosb ;AN000; + pop di ;AN000; restore start of srcbuf + + push cs ;AN000; set DS to local segment + pop ds ;AN000; +assume ds:trangroup ;AN000; + mov [pathcnt],cx ;AN000; set patchcnt to length count + mov [pathpos],di ;AN000; set pathpos to start of srcbuf + pop cx ;AN000; restore cx,di,si + pop di ;AN000; + pop si ;AN000; + + RET ;AN000; exit + +MOVE_TO_SRCBUF ENDP ;AN000; + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TPARSE.ASM b/v4.0/src/CMD/COMMAND/TPARSE.ASM new file mode 100644 index 0000000..9268017 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPARSE.ASM @@ -0,0 +1,76 @@ + page 80,132 +; SCCSID = @(#)tparse.asm 4.1 87/04/28 +; SCCSID = @(#)tparse.asm 4.1 87/04/28 +TITLE COMMAND interface to SYSPARSE + +.xlist +.xcref + INCLUDE comseg.asm ;AN000; +.list +.cref + +TRANSPACE SEGMENT PUBLIC BYTE ;AN000; + + CmpxSW equ 0 ;AN000; do not check complex list + KeySW equ 0 ;AN000; do not support keywords + Val2SW equ 0 ;AN000; do not Support value definition 2 + IncSW equ 0 ;AN000; do not include psdata.inc + QusSW equ 0 ;AN025; do not include quoted string + LFEOLSW equ 0 ;AN044; do not use 0ah as line terminator + +.xlist +.xcref + +include psdata.inc ;AN000; + +.list +.cref + +TRANSPACE ENDS ;AN000; + +TRANCODE SEGMENT PUBLIC BYTE ;AN000; + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN054; + +; **************************************************************** +; * +; * ROUTINE: CMD_PARSE +; * +; * FUNCTION: Interface for transient COMMAND to invoke +; * SYSPARSE. +; * +; * INPUT: inputs to SYSPARSE +; * +; * OUTPUT: outputs from SYSPARSE +; * +; **************************************************************** + + public Cmd_parse ;AN000; + +.xlist +.xcref + INCLUDE parse.asm ;AN000; +.list +.cref + +Cmd_parse Proc near ;AN000; + + call sysparse ;AN000; + + ret ;AN000; + +Cmd_parse endp ;AN000; + + public Append_parse ;AN010; + +Append_parse Proc Far ;AN010; + + call sysparse ;AN010; + + ret ;AN010; + +Append_parse endp ;AN010; + +trancode ends ;AN000; + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TPIPE.ASM b/v4.0/src/CMD/COMMAND/TPIPE.ASM new file mode 100644 index 0000000..23f8417 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPIPE.ASM @@ -0,0 +1,660 @@ + page 80,132 +; SCCSID = @(#)tpipe.asm 1.1 85/05/14 +; SCCSID = @(#)tpipe.asm 1.1 85/05/14 +TITLE PART8 COMMAND Transient routines. + + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN ECHOFLAG:BYTE + EXTRN InitFlag:byte + EXTRN INPIPEPTR:WORD + EXTRN OUTPIPEPTR:WORD + EXTRN PIPE1:BYTE + EXTRN PIPE1T:BYTE + EXTRN PIPE2:BYTE + EXTRN PIPE2T:BYTE + EXTRN PIPEFILES:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN PIPEPTR:WORD + EXTRN RESTDIR:BYTE + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADDAT_PTR:WORD + EXTRN BADTIM_PTR:WORD + EXTRN curdat_mo_day:word ;AN000; + EXTRN CURDAT_PTR:WORD + EXTRN curdat_yr:word ;AN000; + EXTRN curtim_hr_min:word ;AN000; + EXTRN CURTIM_PTR:WORD + EXTRN curtim_sec_hn:word ;AN000; + EXTRN eurdat_ptr:word + EXTRN japdat_ptr:word + EXTRN newdat_format:word ;AN000; + EXTRN NEWDAT_PTR:WORD + EXTRN NEWTIM_PTR:WORD + EXTRN parse_date:byte ;AN000; + EXTRN parse_time:byte ;AN000; + EXTRN PIPEEMES_PTR:WORD + EXTRN promtim_hr_min:word ;AN000; + EXTRN promtim_ptr:word ;AN000; + EXTRN promtim_sec_hn:word ;AN000; + EXTRN STRING_BUF_PTR:WORD ;AC000; + EXTRN SYNTMES_PTR:WORD + EXTRN usadat_ptr:word + +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMBUF:BYTE + EXTRN date_day:byte ;AN000; + EXTRN date_month:byte ;AN000; + EXTRN date_year:word ;AN000; + EXTRN INTERNATVARS:BYTE + EXTRN RESSEG:WORD + EXTRN time_fraction:byte ;AN000; + EXTRN time_hour:byte ;AN000; + EXTRN time_minutes:byte ;AN000; + EXTRN time_seconds:byte ;AN000; +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN CERROR:NEAR + EXTRN NOPIPEPROC:NEAR + EXTRN STD_PRINTF:NEAR + EXTRN TCOMMAND:NEAR + EXTRN TESTDOREIN:NEAR + EXTRN TESTDOREOUT:NEAR + EXTRN TESTKANJ:NEAR ;AN000;3/3/KK + EXTRN TSYSGETMSG:NEAR ;AN000; + + PUBLIC CTIME + PUBLIC DATE + PUBLIC DATINIT + PUBLIC PIPEDEL + PUBLIC PIPEERRSYN + PUBLIC PIPEPROC + PUBLIC PIPEPROCSTRT + PUBLIC PRINT_TIME + PUBLIC SETREST + PUBLIC SETREST1 + PUBLIC SINGLETEST + +SINGLETEST: + ASSUME DS:NOTHING + push ds + MOV DS,ResSeg + ASSUME DS:ResGroup + CMP [SINGLECOM],0 + JZ TestDone + CMP [SINGLECOM],0EFFFH +TestDone: + pop ds + return + + +ASSUME DS:TRANGROUP +SETREST1: + MOV AL,1 +SETREST: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV [RESTDIR],AL + POP DS +ASSUME DS:TRANGROUP + return + +ASSUME DS:RESGROUP + +; +; Note that we need to handle the same thing that RestDir handles: the +; requirement that we try only once to restore the user's environment after +; and INT 24 or the like. If the condition that causes the INT 24 does not +; disappear, we just give up. +; + +PIPEDEL: + assume ds:nothing + push ds + PUSH DX + mov ds,ResSeg + assume ds:ResGroup + mov DX,OFFSET RESGROUP:PIPE1 ; Clean up in case ^C + MOV AH,UNLINK + INT int_command + MOV DX,OFFSET RESGROUP:PIPE2 + MOV AH,UNLINK + INT int_command + POP DX + call PipeOff + mov PipeFiles,0 + pop ds + return + +PIPEERRSYN: + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + CALL PIPEDEL + PUSH CS + POP DS + JMP CERROR +PIPEERR: + pushf + invoke triageError + SaveReg ; Save results from TriageError + MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr + CALL PIPEDEL + PUSH CS + POP DS + invoke std_eprintf + RestoreReg ; Restore results from TriageError + popf + cmp ax, 65 + jnz tcommandj + JMP CERROR +tcommandj: + jmp tcommand + +PIPEPROCSTRT: +ASSUME DS:TRANGROUP,ES:TRANGROUP + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + INC [PIPEFILES] ; Flag that the pipe files exist + MOV AH,Get_Default_Drive ; Get current drive + INT int_command + ADD AL,capital_A + MOV [PIPE2],AL ; Make pipe files in root of def drv + MOV BX,OFFSET RESGROUP:PIPE1 + MOV [BX],AL + xor ah,ah ; nul terminate path names + mov [Pipe1T],ah + mov [Pipe2T],ah + MOV DX,BX + XOR CX,CX + mov ah,CreateTempFile ; the CreateTemp call + INT int_command + JC PIPEERR ; Couldn't create + MOV BX,AX + MOV AH,CLOSE ; Don't proliferate handles + INT int_command + + MOV DX,OFFSET RESGROUP:PIPE2 + mov ah,createTempFile ; the CreateTemp call + INT int_command + JC PIPEERR + MOV BX,AX + MOV AH,CLOSE + INT int_command + + CALL TESTDOREIN ; Set up a redirection if specified + MOV SI,[PIPEPTR] + CMP [SINGLECOM],-1 + JNZ NOSINGP + MOV [SINGLECOM],0F000H ; Flag single command pipe +NOSINGP: + JMP SHORT FIRSTPIPE + +PIPEPROC: +ASSUME DS:RESGROUP + AND [ECHOFLAG],0FEh ; force current echo to be off + MOV SI,[PIPEPTR] + LODSB + CMP AL,AltPipeChr ; Alternate pipe char? + JZ IsPipe1 ; Yes + CMP AL,vbar + jz IsPipe1 + jmp PIPEEND ; Pipe done +IsPipe1: + MOV DX,[INPIPEPTR] ; Get the input file name + MOV AX,(OPEN SHL 8) + INT int_command +PIPEERRJ: + jnc no_pipeerr + JMP PIPEERR ; Lost the pipe file +no_pipeerr: + MOV BX,AX + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table],AL ; Redirect + +FIRSTPIPE: + MOV DI,OFFSET TRANGROUP:COMBUF + 2 + XOR CX,CX + CMP BYTE PTR [SI],0DH ; '|' + JNZ PIPEOK1 +PIPEERRSYNJ: + JMP PIPEERRSYN +PIPEOK1: + mov al,vbar + CMP BYTE PTR [SI],al ; '||' + JZ PIPEERRSYNJ + CMP BYTE PTR [SI],AltPipeChr ; '##' or '|#'? + JZ PipeErrSynJ ; Yes, Error +PIPECOMLP: + LODSB + STOSB + +;;;; IF KANJI 3/3/KK + CALL TESTKANJ + JZ NOTKANJ5 + MOVSB +; +; Added following 2 commands to the fix pipe bug. +; + inc cx ;AN000; 3/3/KK + inc cx ;AN000; 3/3/KK +; + JMP PIPECOMLP + +NOTKANJ5: +;;;; ENDIF ; 3/3/KK + + CMP AL,0DH + JZ LASTPIPE + INC CX + CMP AL,AltPipeChr + JZ IsPipe2 + CMP AL,vbar + JNZ PIPECOMLP +IsPipe2: + MOV BYTE PTR ES:[DI-1],0DH + DEC CX + MOV [COMBUF+1],CL + DEC SI + MOV [PIPEPTR],SI ; On to next pipe element + MOV DX,[OUTPIPEPTR] + PUSH CX + XOR CX,CX + MOV AX,(CREAT SHL 8) + INT int_command + POP CX + JC PIPEERRJ ; Lost the file + MOV BX,AX + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table+1],AL + XCHG DX,[INPIPEPTR] ; Swap for next element of pipe + MOV [OUTPIPEPTR],DX + JMP SHORT PIPECOM + +LASTPIPE: + MOV [COMBUF+1],CL + DEC SI + MOV [PIPEPTR],SI ; Point at the CR (anything not '|' will do) + CALL TESTDOREOUT ; Set up the redirection if specified +PIPECOM: + PUSH CS + POP DS + JMP NOPIPEPROC ; Process the pipe element + +PIPEEND: + CALL PIPEDEL + CMP [SINGLECOM],0F000H + JNZ NOSINGP2 + MOV [SINGLECOM],-1 ; Make it return +NOSINGP2: + JMP TCOMMAND + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +; Date and time are set during initialization and use +; this routines since they need to do a long return + +DATINIT PROC FAR + mov cs:[resseg],ds ; SetInitFlag needs resseg initialized + PUSH ES + PUSH DS ; Going to use the previous stack + MOV AX,CS ; Set up the appropriate segment registers + MOV ES,AX + MOV DS,AX + invoke TSYSLOADMSG ;AN000; preload messages + invoke SETSTDINON ;AN026; turn on critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + MOV DX,OFFSET TRANGROUP:INTERNATVARS;Set up internat vars + MOV AX,INTERNATIONAL SHL 8 + INT 21H + MOV WORD PTR DS:[81H],13 ; Want to prompt for date during initialization + MOV [COMBUF],COMBUFLEN ; Init COMBUF + MOV WORD PTR [COMBUF+1],0D01H + CALL DATE + CALL CTIME + POP DS + POP ES + RET +DATINIT ENDP + +; DATE - Gets and sets the time + + + break Date + + +; **************************************************************** +; * +; * ROUTINE: DATE - Set system date +; * +; * FUNCTION: If a date is specified, set the system date, +; * otherwise display the current system date and +; * prompt the user for a new date. If an invalid +; * date is specified, issue an error message and +; * prompt for a new date. If the user enters +; * nothing when prompted for a date, terminate. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +DATE: + MOV SI,81H ; Accepting argument for date inline + mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + JZ PRMTDAT ;AC000; yes - go ask for date + cmp ax,result_no_error ;AN000; did we have an error? + jne daterr ;AN000; yes - go issue message + JMP COMDAT ;AC000; we have a date + +PRMTDAT: + ; Print "Current date is + + invoke GetDate ;AN000; get date for output + xchg dh,dl ;AN000; switch month & day + mov CurDat_yr,cx ;AC000; put year into message control block + mov CurDat_mo_day,dx ;AC000; put month and day into message control block + mov dx,offset trangroup:CurDat_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov CurDat_yr,0 ;AC000; reset year, month and day +;AD061; mov CurDat_mo_day,0 ;AC000; pointers in control block + +GET_NEW_DATE: ;AN000; + call getdat ;AC000; prompt user for date + cmp ax,end_of_line ;AC000; are we at end of line? + jz date_end ;AC000; yes - exit + cmp ax,result_no_error ;AN000; did we have an error? + jne daterr ;AN000; yes - go issue message +COMDAT: + mov cx,date_year ;AC000; get parts of date in + mov dh,date_month ;AC000; cx and dx for set + mov dl,date_day ;AC000; date function call. + push cx ;AC000; save date + push dx ;AC000; + mov cx,1 ;AC000; set 1 positional entered + xor dx,dx ;AN029; + invoke cmd_parse ;AN029; call parser + cmp al,end_of_line ;AN029; Are we at end of line? + pop dx ;AC000; retrieve date + pop cx ;AC000; + jnz daterr ;AC000; extra stuff on line - try again + MOV AH,SET_DATE ;yes - set date + INT int_command + OR AL,AL + JNZ DATERR +date_end: + ret + +DATERR: + invoke crlf2 ;AN028; print out a blank line + MOV DX,OFFSET TRANGROUP:BADDAT_ptr + invoke std_printf + JMP GET_NEW_DATE ;AC000; get date again + + +; TIME gets and sets the time + + break Time + +; **************************************************************** +; * +; * ROUTINE: TIME - Set system time +; * +; * FUNCTION: If a time is specified, set the system time, +; * otherwise display the current system time and +; * prompt the user for a new time. If an invalid +; * time is specified, issue an error message and +; * prompt for a new time. If the user enters +; * nothing when prompted for a time, terminate. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +CTIME: + MOV SI,81H ; Accepting argument for time inline + mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_time + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + JZ PRMTTIM ;AC000; yes - prompt for time + cmp ax,result_no_error ;AN000; did we have an error? + jne timerr ;AN000; yes - go issue message + JMP COMTIM ;AC000; we have a time + +PRMTTIM: + ;Printf "Current time is ... " + + MOV AH,GET_TIME ;AC000; get the current time + INT int_command ;AC000; Get time in CX:DX + xchg ch,cl ;AN000; switch hours & minutes + xchg dh,dl ;AN000; switch seconds & hundredths + mov CurTim_hr_min,cx ;AC000; put hours and minutes into message subst block + mov CurTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block + mov dx,offset trangroup:CurTim_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov CurTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths +;AD061; mov CurTim_sec_hn,0 ;AC000; pointers in control block + +GET_NEW_TIME: + call gettim ;AC000; + cmp ax,end_of_line ;AC000; are we at end of line? + jz time_end ;AC000; + cmp ax,result_no_error ;AN000; did we have an error? + jne timerr ;AN000; yes - go issue message + +COMTIM: + mov ch,time_hour ;AC000; get parts of time in + mov cl,time_minutes ;AC000; cx and dx for set + mov dh,time_seconds ;AC000; time function call + mov dl,time_fraction ;AC000; + push cx ;AC000; save time + push dx ;AC000; + mov cx,1 ;AC000; set 1 positional parm entered + xor dx,dx ;AN029; + invoke cmd_parse ;AN029; call parser + cmp al,end_of_line ;AN029; Are we at end of line? + pop dx ;AC000; retieve time + pop cx ;AC000; + jnz timerr ;AC000; extra stuff on line - try again + +SAVTIM: + MOV AH,SET_TIME + INT int_command + OR AL,AL + JNZ TIMERR ;AC000; if an error occured, try again + +TIME_END: + + ret + +TIMERR: + invoke crlf2 ;AN028; print out a blank line + MOV DX,OFFSET TRANGROUP:BADTIM_ptr + invoke std_printf ; Print error message + JMP GET_NEW_TIME ;AC000; Try again + + +; +; Set the special flag in the INIT flag to the value in CX. +; +SetInitFlag: + mov ds,[RESSEG] +assume ds:resgroup + and InitFlag,NOT initSpecial + or InitFlag,cL + push cs + pop ds + return + +Public PipeOff +PipeOff: + ASSUME DS:NOTHING,ES:NOTHING + SaveReg + MOV DS,ResSeg + ASSUME DS:RESGroup + XOR AL,AL + XCHG PipeFlag,AL + OR AL,AL + JZ PipeOffDone + SHR EchoFlag,1 +PipeOffDone: + RestoreReg + return + + +PRINT_TIME: + + MOV AH,GET_TIME + INT int_command ; Get time in CX:DX + + PUSH ES + PUSH CS + POP ES + xchg ch,cl ;AN000; switch hours & minutes + xchg dh,dl ;AN000; switch seconds & hundredths + mov promTim_hr_min,cx ;AC000; put hours and minutes into message subst block + mov promTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block + mov dx,offset trangroup:promTim_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov promTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths +;AD061; mov promTim_sec_hn,0 ;AC000; pointers in control block + + POP ES + return + + +; **************************************************************** +; * +; * ROUTINE: GETDAT - Prompt user for date +; * +; * FUNCTION: Gets the date format from the COUNTRY DEPENDENT +; * INFORMATION and issues the "Enter new date" +; * message with the proper date format. COMBUF +; * is reset to get a date from the command line. +; * The PARSE_DATE blocks are then reset and the +; * PARSE function call is issued. +; * +; * INPUT: NONE +; * +; * OUTPUT: COMBUF +; * PARSER RETURN CODES +; * +; **************************************************************** + + +GETDAT proc near ;AC000; + + mov ax,(International SHL 8) ; Determine what format the date + mov dx,5ch ; should be entered in and + int int_command ; print a message describing it + mov si,dx + lodsw + mov dx,usadat_ptr ;AC000; get mm-dd-yy + dec ax + js printformat + mov dx,eurdat_ptr ;AC000; get dd-mm-yy + jz printformat + mov dx,japdat_ptr ;AC000; get yy-mm-dd +printformat: + mov ax,dx ;AN000; get message number of format + mov dh,util_msg_class ;AN000; this is a utility message + call Tsysgetmsg ;AN000; get the address of the message + mov newdat_format,si ;AN000; put the address in subst block + MOV DX,OFFSET TRANGROUP:NEWDAT_ptr ;AC000; get address of message to print + invoke std_printf + mov newdat_format,no_subst ;AN000; reset subst block + + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET TRANGROUP:COMBUF + mov cx,initSpecial ; Set bit in InitFlag that indicates + call SetInitFlag ; prompting for date. + INT int_command ; Get input line + xor cx,cx ; Reset bit in InitFlag that indicates + call SetInitFlag ; prompting for date. + invoke CRLF2 + MOV SI,OFFSET TRANGROUP:COMBUF+2 + mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + + ret + +GETDAT endp ;AC000; + + +; **************************************************************** +; * +; * ROUTINE: GETTIME - Prompt user for time +; * +; * FUNCTION: Gets the time format from the COUNTRY DEPENDENT +; * INFORMATION and issues the "Enter new time" +; * message. COMBUF is reset to get a time from the +; * command line. The PARSE_TIME blocks are then +; * reset and the PARSE function call is issued. +; * +; * INPUT: NONE +; * +; * OUTPUT: COMBUF +; * PARSER RETURN CODES +; * +; **************************************************************** + + +GETTIM proc near ;AC000; + + XOR CX,CX ; Initialize hours and minutes to zero + MOV DX,OFFSET TRANGROUP:NEWTIM_ptr + invoke std_printf + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET TRANGROUP:COMBUF + mov cx,initSpecial ; Set bit in InitFlag that indicates + call SetInitFlag ; prompting for time. + INT int_command ; Get input line + xor cx,cx ; Reset bit in InitFlag that indicates + call SetInitFlag ; prompting for time. + invoke CRLF2 + MOV SI,OFFSET TRANGROUP:COMBUF+2 + mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_TIME + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + + ret + +GETTIM endp ;AC000; + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TPRINTF.ASM b/v4.0/src/CMD/COMMAND/TPRINTF.ASM new file mode 100644 index 0000000..c502f83 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPRINTF.ASM @@ -0,0 +1,365 @@ + page 80,132 +; SCCSID = @(#)tprintf.asm 4.3 85/07/02 +; SCCSID = @(#)tprintf.asm 4.3 85/07/02 +TITLE COMMAND Transient Printf routine + +;**************************************************************** +;* +;* ROUTINE: STD_PRINTF/STD_EPRINTF +;* +;* FUNCTION: Set up to print out a message using SYSDISPMSG. +;* Set up substitutions if utility message. Make +;* sure any changes to message variables in TDATA +;* are reset to avoid reloading the transient. +;* +;* INPUT: Msg_Disp_Class - set to message class +;* Msg_Cont_Flag - set to control flags +;* DS points to transient segment +;* +;* if utility message: +;* DX points to a block with message number +;* (word), number of substitutions (byte), +;* followed by substitution list if there +;* are substitutions. If substitutions +;* are not in transient segment they must +;* be set. +;* else +;* AX set to message number +;* +;* OUTPUT: none +;* +;**************************************************************** + +.xlist +.xcref + INCLUDE comsw.asm ;AC000; + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm ;AN000; + INCLUDE SYSMSG.INC ;AN000; +.list +.cref + +datares segment public + extrn pipeflag:byte +datares ends + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN extend_buf_off:word ;AN000; + EXTRN Extend_Buf_ptr:word ;AN000; + EXTRN Extend_Buf_seg:word ;AN000; + EXTRN Msg_Cont_Flag:byte ;AN000; + EXTRN Msg_disp_Class:byte ;AN000; + EXTRN pipeemes_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN msg_flag:byte ;AN022; + EXTRN print_err_flag:word ;AN000; + EXTRN RESSEG:WORD + EXTRN String_ptr_2:word ;AC000; + EXTRN Subst_buffer:byte ;AN061; +;AD061; EXTRN String_ptr_2_sb:word ;AN000; + + ; include data area for message services + + MSG_UTILNAME ;AN000; define utility name + + MSG_SERVICES ;AN000; + +PRINTF_HANDLE DW ? ;AC000; + +TRANSPACE ENDS ;AC000; + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + + EXTRN cerror:near + EXTRN crlf2:near + EXTRN tcommand:near ;AN026; + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING,SS:NOTHING ;AC000; + + PUBLIC SETSTDINOFF ;AN026; + PUBLIC SETSTDINON ;AN026; + PUBLIC SETSTDOUTOFF ;AN026; + PUBLIC SETSTDOUTON ;AN026; + PUBLIC TSYSGETMSG ;AN000; + PUBLIC TSYSLOADMSG ;AN000; + +PUBLIC Printf_Init +printf_init proc far + call std_printf + ret +printf_init endp + +Public Printf_Crlf +PRINTF_CRLF: + CALL STD_PRINTF + CALL CRLF2 + RET + +PUBLIC Std_EPrintf +STD_EPRINTF: + mov Printf_Handle,2 ;AC000;Print to STDERR + jmp short NEW_PRINTF ;AC000; +PUBLIC Std_Printf +STD_PRINTF: + mov Printf_Handle,1 ;AC000;Print to STDOUT + +NEW_PRINTF: + push ax ;AN000;save registers + push bx ;AN000; + push cx ;AN000; + push es ;AN000;get local ES + push ds ;AN000; + pop es ;AN000; + push di ;AN000; + push si ;AN000; + push dx ;AN000; + assume es:trangroup ;AN000; +;AD061; mov string_ptr_2_sb,0 ;AN000;initialize + mov print_err_flag,0 ;AN000; + +UTILITY_SETUP: + mov si,dx ;AN000;Get offset of message number + lodsw ;AN000;load message number + push ax ;AN000;save it + lodsb ;AN000;get number of substitutions + mov cl,al ;AN000;set up CX as # of subst + xor ch,ch ;AN000; SI now points to subst list + pop ax ;AN000;get message number back + cmp cx,0 ;AN000;Any substitutions? + jz READY_TO_PRINT ;AN000;No - continue + +;AD061; add dx,Ptr_Seg_Pos ;AN000;Point to position of first segment +;AD061; push cx ;AN000;save substitution count + +;AD061;SET_SUBST: +;AD061; mov bx,dx ;AN000;get dx into base register +;AD061; cmp word ptr [bx],0 ;AN000;has segment been set? +;AD061; jnz SUBST_SEG_SET ;AN000;if not 0, don't replace it +;AD061; test word ptr [bx+3],date_type ;AN000;if date or time - don't set segment +;AD061; jnz subst_seg_set ;AN000;yes - skip it +;AD061; mov word ptr [bx],cs ;AN000;put segment of subst parm in list + +;AD061;SUBST_SEG_SET: +;AD061; add dx,Parm_Block_Size ;AN000;point to position of next segment +;AD061; loop SET_SUBST ;AN000;keep replacing until complete +;AD061; pop cx ;AN000; + +;AD061;NO_REPLACEMENT: +;AD061; mov bx,parm_off_pos [si] ;AN000;get subst offset +;AD061; cmp bx,offset trangroup:string_ptr_2 ;AN000;this is used for double indirection +;AD061; jnz ready_to_print ;AN000;we already have address +;AD061; mov dx,string_ptr_2 ;AN000;get address in string_ptr_2 +;AD061; mov parm_off_pos [si],dx ;AN000;put proper address in table +;AD061; mov string_ptr_2_sb,si ;AN000;save block changed + + mov di,offset trangroup:subst_buffer;AN061; Get address of message subst buffer + push di ;AN061; save it + push cx ;AN061; save number of subst + +MOVE_SUBST: + push cx ;AN061;save number of subst + mov bx,si ;AN061;save start of sublist + mov cx,parm_block_size ;AN061;get size of sublist + rep movsb ;AN061;move sublist + test byte ptr [bx.$M_S_FLAG],date_type ;AN061;are we doing date/time? + jz move_subst_cont ;AN061;no - no need to reset + mov word ptr [bx.$M_S_VALUE],0 ;AN061;reset original date or time to 0 + mov word ptr [bx.$M_S_VALUE+2],0 ;AN061; + +MOVE_SUBST_CONT: ;AN061; + pop cx ;AN061;get number of subst back + loop move_subst ;AN061;move cx sublists + + pop cx ;AN061;get number of subst + push ax ;AN061;save message number + cmp Msg_Disp_Class,Util_Msg_Class ;AN061;Is this a utility message + jz CHECK_FIX ;AN061;YES - go see if substitutions + mov msg_flag,ext_msg_class ;AN061;set message flag + mov di,offset trangroup:extend_buf_ptr ;AN061; Get address of extended message block + xor ax,ax ;AN061;clear ax register + stosw ;AN061;clear out message number + stosb ;AN061;clear out subst count + +CHECK_FIX: ;AN061; + pop ax ;AN061;get message number back + pop di ;AN061;get start of sublists + mov si,di ;AN061;get into SI for msgserv + mov bx,si ;AN061;get into BX for addressing + push cx ;AN061;save number of subst + +SET_SUBST: ;AN061;store the segment of the subst + cmp word ptr [bx.$M_S_VALUE+2],0 ;AN061;was it set already? + jnz subst_seg_set ;AN061;if not 0, don't replace it + test byte ptr [bx.$M_S_FLAG],date_type ;AN061;don't replace if date or time + jnz subst_seg_set ;AN061;yes - skip it + mov word ptr [bx.$M_S_VALUE+2],cs ;AN061;set segment value + +SUBST_SEG_SET: ;AN061; + add bx,parm_block_size ;AN061;go to next sublist + loop set_subst ;AN061;loop CX times + pop cx ;AN061;get number of subst back + + mov bx,si ;AN061;get start of sublist to BX + cmp word ptr [bx.$M_S_VALUE],offset trangroup:string_ptr_2 ;AN061;are we using double indirection? + jnz ready_to_print ;AN061;no - we already have address + mov dx,string_ptr_2 ;AN061;get address in string_ptr_2 + mov word ptr [bx.$M_S_VALUE],dx ;AN061;put it into the subst block + +READY_TO_PRINT: + mov bx,Printf_Handle ;AN000;get print handle + mov dl,Msg_Cont_Flag ;AN000;set up control flag + mov dh,Msg_Disp_Class ;AN000;set up display class + mov Msg_Cont_Flag,No_Cont_Flag ;AN061;reset flags to avoid + mov Msg_Disp_Class,Util_Msg_Class ;AN061; transient reload + +;AD061; push bx ;AN026; save registers +;AD061; push cx ;AN026; +;AD061; push dx ;AN026; +;AD061; push si ;AN026; +;AD061; push di ;AN026; + push ds ;AN026; + push es ;AN026; + + + call SYSDISPMSG ;AN000;call Rod + + pop es ;AN026; restore registers + pop ds ;AN026; +;AD061; pop di ;AN026; +;AD061; pop si ;AN026; +;AD061; pop dx ;AN026; +;AD061; pop cx ;AN026; +;AD061; pop bx ;AN026; + + jnc Print_success ;AN000; everything went okay + mov print_err_flag,ax ;AN000; + +print_success: +;AD061; cmp Msg_Disp_Class,Util_Msg_Class ;AN000;Is this a utility message +;AD061; jz CHECK_FIX ;AN000;YES - go see if substitutions +;AD061; mov msg_flag,ext_msg_class ;AN022;set message flag +;AD061; mov di,offset trangroup:extend_buf_ptr ;AN000; Get address of extended message block +;AD061; xor ax,ax ;AN000;clear ax register +;AD061; stosw ;AN000;clear out message number +;AD061; stosb ;AN000;clear out subst count + +;AD061; CHECK_FIX: +;AD061; pop dx ;AN000;restore dx +;AD061; cmp cx,0 ;AN000;Any substitutions? +;AD061; jz NO_FIXUP ;AN000;No - leave + +;AD061; mov si,dx ;AN000;Reset changes so transient won't reload +;AD061; add si,Ptr_Seg_Pos ;AN000;Point to position of first segment + +;AD061;FIX_SUBST: +;AD061; mov word ptr [si],0 ;AN000;reset segment to 0 +;AD061; add si,Parm_Block_Size ;AN000;point to position of next segment +;AD061; loop FIX_SUBST ;AN000;keep replacing until complete +;AD061; cmp string_ptr_2_sb,no_subst ;AN000;was double indirection used? +;AD061; jz no_fixup ;AN000;no - we're finished +;AD061; mov si,string_ptr_2_sb ;AN000;get offset changed +;AD061; mov parm_off_pos [si],offset trangroup:string_ptr_2 ;AN000; set address back to string_ptr_2 + +;AD061;NO_FIXUP: +;AD061; mov Msg_Cont_Flag,No_Cont_Flag ;AN000;reset flags to avoid +;AD061; mov Msg_Disp_Class,Util_Msg_Class ;AN000; transient reload + pop dx ;AN061;restore dx + pop si ;AN000;restore registers + pop di ;AN000; + pop es ;AN000;restore registers + pop cx ;AN000; + pop bx ;AN000; + pop ax ;AN000; + cmp print_err_flag,0 ;AN000; if an error occurred - handle it + jnz print_err ;AN000; + + ret ;AC000; + +print_err: + push cs + pop es + cmp Printf_Handle,2 ;AN026;Print to STDERR? + jnz not_stderr ;AN026;no - continue + jmp tcommand ;AN026;Yes - hopless - just exit + +not_stderr: + mov ax,print_err_flag ;AN026;get extended error number back + mov es,[resseg] ; No, set up for error, load the +assume es:resgroup ; right error msg, and jmp to cerror. + test PipeFlag,-1 + jz go_to_error + invoke PipeOff + mov dx,offset trangroup:pipeemes_ptr + jmp print_err_exit ;AC000; + +go_to_error: + mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + mov Extend_Buf_ptr,ax ;AN000; get message number in control block + +PRINT_ERR_EXIT: ;AC000; + push cs + pop es + JMP CERROR + +;**************************************************************** +;* +;* ROUTINE: TSYSLOADMSG +;* +;* FUNCTION: Interface to call SYSLOADMSG to avoid duplicate +;* names since these routines are also used in the +;* resident. +;* +;* INPUT: Inputs to SYSLOADMSG +;* +;* OUTPUT: Outputs from SYSLOADMSG +;* +;**************************************************************** + + +TSYSLOADMSG PROC NEAR ;AN000; + + push bx ;AN000; + call sysloadmsg ;AN000; call routine + pop bx ;AN000; + ret ;AN000; exit + +TSYSLOADMSG ENDP ;AN000; + +;**************************************************************** +;* +;* ROUTINE: TSYSGETMSG +;* +;* FUNCTION: Interface to call SYSGETMSG to avoid duplicate +;* names since these routines are also used in the +;* resident. +;* +;* INPUT: Inputs to SYSGETMSG +;* +;* OUTPUT: Outputs from SYSGETMSG +;* +;**************************************************************** + + +TSYSGETMSG PROC NEAR ;AN000; + + push cx ;AN000; + call sysgetmsg ;AN000; call routine + pop cx ;AN000; + ret ;AN000; exit + +TSYSGETMSG ENDP ;AN000; + +MSG_SERVICES ;AC026; The message services +MSG_SERVICES ;AC026; The message services + +PRINTF_LAST LABEL WORD + +include msgdcl.inc + + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TRANMSG.ASM b/v4.0/src/CMD/COMMAND/TRANMSG.ASM new file mode 100644 index 0000000..38b04ba --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TRANMSG.ASM @@ -0,0 +1,671 @@ + +;**************************************************** +;* TRANSIENT MESSAGE POINTERS & SUBSTITUTION BLOCKS * +;**************************************************** + +msg_disp_class db Util_msg_class +msg_cont_flag db No_cont_flag + +; extended error string output +; +Extend_Buf_ptr dw 0 ;AN000;set to no message +Extend_Buf_sub db 0 ;AN000;set to no substitutions + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +Extend_Buf_off dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg +Extend_Buf_seg dw 0 ;AN000;segment of arg + db 0 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; "Duplicate file name or file not found" +; +Renerr_Ptr dw 1002 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path or file name" +; +BadCPMes_Ptr dw 1003 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Insufficient disk space" +; +NoSpace_Ptr dw 1004 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Out of environment space" +; +EnvErr_Ptr dw 1007 ;AN000;message number + db no_subst ;AN000;number of subst + +; "File creation error" +; +FulDir_Ptr dw 1008 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Batch file missing",13,10 +; +BadBat_Ptr dw 1009 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Insert disk with batch file",13,10 +; +NeedBat_Ptr dw 1010 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Bad command or file name",13,10 +; +BadNam_Ptr dw 1011 ;AN000;message number + db no_subst ;AN000;number of subst + + +; "Access denied",13,10 +; +AccDen_Ptr dw 1014 ;AN000;message number + db no_subst ;AN000;number of subst + +; "File cannot be copied onto itself",13,10 +; +OverWr_Ptr dw 1015 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Content of destination lost before copy",13,10 +; +LostErr_Ptr dw 1016 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid filename or file not found",13,10 +; +InOrNot_Ptr dw 1017 ;AN000;message number + db no_subst ;AN000;number of subst + +; "%1 File(s) copied",13,10 +; +Copied_Ptr dw 1018 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Copy_num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 9 ;AN000;maximum width + db 9 ;AN000;minimum width + db blank ;AN000;pad character + +; "%1 File(s) " +; +DirMes_Ptr dw 1019 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Dir_num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 9 ;AN000;maximum width + db 9 ;AN000;minimum width + db blank ;AN000;pad character + +; "%1 bytes free",13,10 +; +BytMes_Ptr dw 1020 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Bytes_Free ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + +; "Invalid drive specification",13,10 +; +BadDrv_Ptr dw 1021 ;AN000;message number + db no_subst ;AN000;number of subst + + +; "Code page %1 not prepared for system",13,10 +; +CP_not_set_Ptr dw 1022 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Code page %1 not prepared for all devices",13,10 +; +CP_not_all_Ptr dw 1023 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Active code page: %1",13,10 +; +CP_active_Ptr dw 1024 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "NLSFUNC not installed",13,10 +; +NLSFUNC_Ptr dw 1025 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid code page",13,10 +; +Inv_Code_Page dw 1026 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current drive is no longer valid" +; +BadCurDrv dw 1027 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Press any key to continue" +; +PauseMes_Ptr dw 1028 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Label not found",13,10 +; +BadLab_Ptr dw 1029 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Syntax error",13,10 +; +SyntMes_Ptr dw 1030 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid date",13,10 +; +BadDat_Ptr dw 1031 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current date is %1 %2",13,10 +; +CurDat_Ptr dw 1032 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 3 ;AN000;maximum width + db 3 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +CurDat_yr dw 0 ;AN000;year +CurDat_mo_day dw 0 ;AN000;month,day + db 2 ;AN000;second subst + db DATE_MDY_4 ;AN000;date + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + + +; "SunMonTueWedThuFriSat" +; +WeekTab dw 1033 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Enter new date (%1):" +; +NewDat_Ptr dw 1034 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +NewDat_Format dw 0 ;AN000;offset of replacement + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 8 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + +; "Invalid time",13,10 +; +BadTim_Ptr dw 1035 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current time is %1",13,10 +; +CurTim_Ptr dw 1036 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +CurTim_hr_min dw 0 ;AN000;hours,minutes +CurTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 1 ;AN000;first subst + db Right_Align+TIME_HHMMSSHH_Cty ;AC059;time + db 12 ;AC059;maximum width + db 12 ;AC059;minimum width + db blank ;AN000;pad character + +; "Enter new time:" +; +NewTim_Ptr dw 1037 ;AN000;message number + db no_subst ;AN000;number of subst + +; ", Delete (Y/N)?",13,10 +; +Del_Y_N_Ptr dw 1038 ;AN000;message number + db no_subst ;AN000;number of subst + +; "All files in directory will be deleted!",13,10 +; "Are you sure (Y/N)?",13,10 +; +SureMes_Ptr dw 1039 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Microsoft DOS Version %1.%2",13,10 +; +VerMes_Ptr dw 1040 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Major_Ver_Num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Minor_Ver_Num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Unsgn_Bin_Word ;AN000;binary to decimal + db 2 ;AN000;maximum width + db 2 ;AN000;minimum width + db "0" ;AN000;pad character + +; "Volume in drive %1 has no label",13,10 +; +VolMes_Ptr_2 dw 1041 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_drv ;AN000;offset of drive + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_Char ;AN000;character + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Volume in drive %1 is %2",13,10 +; +VolMes_Ptr dw 1042 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_drv ;AN000;offset of drive + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db 00000000b ;AN000;character + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:CHARBUF ;AN000;offset of string + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Volume Serial Number is %1-%2",13,10 +; +VolSerMes_Ptr dw 1043 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_serial+2 ;AN000;offset of serial + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Bin_Hex_Word ;AN000;binary to hex + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_serial ;AN000;offset of serial + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Right_Align+Bin_Hex_Word ;AN000;binary to hex + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + +; "Invalid directory",13,10 +; +BadCD_Ptr dw 1044 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Unable to create directory",13,10 +; +BadMkD_Ptr dw 1045 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path, not directory,",13,10 +; "or directory not empty",13,10 +; +BadRmD_Ptr dw 1046 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Must specify ON or OFF",13,10 +; +Bad_ON_OFF_Ptr dw 1047 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Directory of %1",13,10 +; +DirHead_Ptr dw 1048 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:BWDBUF ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; "No Path",13,10 +; +NulPath_Ptr dw 1049 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid drive in search path",13,10 +; +BadPMes_Ptr dw 1050 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid device",13,10 +; +BadDev_Ptr dw 1051 ;AN000;message number + db no_subst ;AN000;number of subst + +; "FOR cannot be nested",13,10 +; +ForNestMes_Ptr dw 1052 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Intermediate file error during pipe",13,10 +; +PipeEMes_Ptr dw 1053 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Cannot do binary reads from a device",13,10 +; +InBDev_Ptr dw 1054 ;AN000;message number + db no_subst ;AN000;number of subst + +; "BREAK is %1",13,10 +; +CtrlcMes_Ptr dw 1055 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "VERIFY is %1",13,10 +; +VeriMes_Ptr dw 1056 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "ECHO is %1",13,10 +; +EchoMes_Ptr dw 1057 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "off" +; +OffMes_Ptr dw 1059 ;AN000;message number + db no_subst ;AN000;number of subst + +; "on" +; +OnMes_Ptr dw 1060 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Error writing to device",13,10 +; +DevWMes_Ptr dw 1061 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path",13,10 +; +Inval_Path_Ptr dw 1062 ;AN000;message number + db no_subst ;AN000;number of subst + +; unformatted string output +; +arg_Buf_Ptr dw 1063 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; file name output +; +File_Name_Ptr dw 1064 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:SRCBUF ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; file size output for dir +; +Disp_File_Size_Ptr dw 1065 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:File_size_low ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + +; unformatted string output +; %s +String_Buf_Ptr dw 1066 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db 0 ;AN000; + +; tab character +; +Tab_ptr dw 1067 ;AN000;message number + db no_subst ;AN000;number of subst + +; " " +; +DMes_Ptr dw 1068 ;AN000;message number + db no_subst ;AN000;number of subst + +; destructive back space +; +Dback_Ptr dw 1069 ;AN000;message number + db no_subst ;AN000;number of subst + +; carriage return / line feed +; +ACRLF_Ptr dw 1070 ;AN000;message number + db no_subst ;AN000;number of subst + +; output a single character +; +;One_Char_Buf_Ptr dw 1071 ;AN000;message number +; db 1 ;AN000;number of subst +; db parm_block_size ;AN000;size of sublist +; db 0 ;AN000;reserved +; dw OFFSET TranGroup:One_Char_Val ;AN000;offset of charcacter +; dw 0 ;AN000;segment of arg +; db 1 ;AN000;first subst +; db Char_field_Char ;AN000;character +; db 1 ;AN000;maximum width +; db 1 ;AN000;minimum width +; db blank ;AN000;pad character + +; "mm-dd-yy" +; +USADat_Ptr dw 1072 ;AN000;message number + db no_subst ;AN000;number of subst + +; "dd-mm-yy" +; +EurDat_Ptr dw 1073 ;AN000;message number + db no_subst ;AN000;number of subst + +; "yy-mm-dd" +; +JapDat_Ptr dw 1074 ;AN000;message number + db no_subst ;AN000;number of subst + +; date string for prompt +; +promptDat_Ptr dw 1075 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 3 ;AN000;maximum width + db 3 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +promptDat_yr dw 0 ;AN000;year +promptDat_moday dw 0 ;AN000;month,day + db 2 ;AN000;second subst + db DATE_MDY_4 ;AN000;date + db 10 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + + +; Time for prompt +; +promTim_Ptr dw 1076 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +PromTim_hr_min dw 0 ;AN000;hours,minutes +PromTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 1 ;AN000;first subst + db Right_Align+TIME_HHMMSSHH_24 ;AC013;time + db 11 ;AN000;maximum width + db 11 ;AC013;minimum width + db blank ;AN000;pad character + +; Date and time for DIR +; +DirDatTim_Ptr dw 1077 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DirDat_yr dw 0 ;AN000;year +DirDat_mo_day dw 0 ;AN000;month,day + db 1 ;AN000;first subst + db Right_Align+DATE_MDY_2 ;AN000;date + db 10 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DirTim_hr_min dw 0 ;AN000;hours,minutes +DirTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 2 ;AN000;second subst + db Right_align+TIME_HHMM_Cty ;AN000;time + db 6 ;AN000;maximum width + db 6 ;AN000;minimum width + db blank ;AN000;pad character + +; "Directory already exists" +; +MD_exists_ptr dw 1078 ;AN000;message number + db no_subst ;AN000;number of subst + +PATH_TEXT DB "PATH=" +PROMPT_TEXT DB "PROMPT=" +comspecstr db "COMSPEC=" diff --git a/v4.0/src/CMD/COMMAND/TSPC.ASM b/v4.0/src/CMD/COMMAND/TSPC.ASM new file mode 100644 index 0000000..10e5758 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TSPC.ASM @@ -0,0 +1,488 @@ + page 80,132 +; SCCSID = @(#)tspc.asm 4.1 85/09/22 +; SCCSID = @(#)tspc.asm 4.1 85/09/22 +TITLE COMMAND Transient Uninitialized DATA + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comequ.asm + INCLUDE comseg.asm + INCLUDE EA.inc ;AN030; +.list +.cref + +; Uninitialized transient data +TRANSPACE SEGMENT PUBLIC BYTE + + PUBLIC ALLSWITCH + PUBLIC append_exec ;AN041; + PUBLIC arg + PUBLIC argbufptr + PUBLIC ARGC + PUBLIC ARG1S + PUBLIC ARG2S + PUBLIC ARGTS + PUBLIC arg_buf + PUBLIC ASCII + PUBLIC BatBuf + PUBLIC BatBufEnd + PUBLIC BatBufPos + PUBLIC BATHAND + PUBLIC BINARY + PUBLIC BITS + PUBLIC BWDBUF + PUBLIC BYTCNT + PUBLIC bytes_free + PUBLIC CFLAG + PUBLIC CHARBUF + PUBLIC CHKDRV + PUBLIC COM + PUBLIC COMBUF + PUBLIC comma + PUBLIC comptr + PUBLIC comspec_flag + PUBLIC COMSW + PUBLIC CONCAT + PUBLIC concat_xa ;AN000; + PUBLIC copy_Num + PUBLIC CPDATE + PUBLIC CPTIME + PUBLIC cpyflag + PUBLIC CURDRV + PUBLIC DATE_DAY ;AN000; + PUBLIC DATE_MONTH ;AN000; + PUBLIC DATE_OUTPUT ;AN000; + PUBLIC DATE_TYPE ;AN000; + PUBLIC DATE_YEAR ;AN000; + PUBLIC DEST + PUBLIC DESTBUF + PUBLIC DestClosed + PUBLIC DESTDIR + PUBLIC DESTFCB + PUBLIC DESTFCB2 + PUBLIC DESTHAND + PUBLIC DESTINFO + PUBLIC DESTISDEV + PUBLIC DESTISDIR + PUBLIC DESTNAME + PUBLIC DESTSIZ + PUBLIC DESTSWITCH + PUBLIC DESTTAIL + PUBLIC DESTVARS + PUBLIC DIRBUF + PUBLIC DIRCHAR + PUBLIC dirflag ;AN015; + PUBLIC Dir_Num + PUBLIC display_ioctl ;AN000; + PUBLIC display_mode ;AN000; + PUBLIC display_width ;AN000; + PUBLIC DRIVE_NUMBER ;AN000; + PUBLIC DRIVE_OUTPUT ;AN000; + PUBLIC DRIVE_TYPE ;AN000; + PUBLIC DRIVE_VALUE ;AN000; + PUBLIC ELCNT + PUBLIC ELPOS + PUBLIC EXECPATH + PUBLIC EXEC_ADDR + PUBLIC EXEFCB + PUBLIC expand_star + PUBLIC ext_entered ;AN005; + PUBLIC ext_open_off ;AN000; + PUBLIC ext_open_parms ;AN000; + PUBLIC ext_open_seg ;AN000; + PUBLIC FBUF + PUBLIC FILECNT + PUBLIC file_size_high + PUBLIC file_size_low + PUBLIC FILTYP + PUBLIC FIRSTDEST + PUBLIC FRSTSRCH + PUBLIC FULLSCR + PUBLIC GOTOLEN + PUBLIC HEADCALL + PUBLIC ID + PUBLIC IDLEN + PUBLIC IFNOTFLAG + PUBLIC if_not_count + PUBLIC INEXACT + PUBLIC INTERNATVARS + PUBLIC KPARSE + PUBLIC last_arg + PUBLIC LINCNT + PUBLIC LINLEN + PUBLIC linperpag ;AN000; + PUBLIC major_ver_num + PUBLIC MELCOPY + PUBLIC MELSTART + PUBLIC minor_ver_num + PUBLIC msg_flag ;AN022; + PUBLIC msg_numb ;AN022; + PUBLIC NOWRITE + PUBLIC NXTADD + PUBLIC objcnt + PUBLIC one_char_val + PUBLIC PARM1 + PUBLIC PARM2 + PUBLIC parse_last ;AN018; + PUBLIC PARSE1_ADDR ;AN000; + PUBLIC PARSE1_CODE ;AN000; + PUBLIC PARSE1_OUTPUT ;AN000; + PUBLIC PARSE1_SYN ;AN000; + PUBLIC PARSE1_TYPE ;AN000; + PUBLIC PATHCNT + PUBLIC pathinfo + PUBLIC PATHPOS + PUBLIC PATHSW + PUBLIC PLUS + PUBLIC plus_comma + PUBLIC print_err_flag ;AN000; + PUBLIC psep_char + PUBLIC RCH_ADDR + PUBLIC RDEOF + PUBLIC RE_INSTR + PUBLIC RESSEG + PUBLIC SCANBUF + PUBLIC SDIRBUF + PUBLIC search_best + PUBLIC search_best_buf + PUBLIC search_curdir_buf + PUBLIC search_error + PUBLIC SKPDEL + PUBLIC SOURCE + PUBLIC SPECDRV + PUBLIC SRCBUF + PUBLIC SRCHAND + PUBLIC SRCINFO + PUBLIC SRCISDEV + PUBLIC SRCISDIR + PUBLIC SRCPT + PUBLIC SRCSIZ + PUBLIC SRCTAIL + PUBLIC SRCVARS + PUBLIC srcxname + PUBLIC src_xa_seg ;AN000; + PUBLIC src_xa_size ;AN000; + PUBLIC STACK + PUBLIC STARTEL + PUBLIC string_ptr_2 +;AD061; PUBLIC string_ptr_2_sb ;AN000; + PUBLIC subst_buffer ;AN061; + PUBLIC SWITCHAR + PUBLIC system_cpage + PUBLIC TERMREAD + PUBLIC TIME_FRACTION ;AN000; + PUBLIC TIME_HOUR ;AN000; + PUBLIC TIME_MINUTES ;AN000; + PUBLIC TIME_OUTPUT ;AN000; + PUBLIC TIME_SECONDS ;AN000; + PUBLIC TIME_TYPE ;AN000; + PUBLIC TPA + PUBLIC tpbuf + PUBLIC TRANSPACEEND + PUBLIC TRAN_TPA + PUBLIC trgxname + PUBLIC UCOMBUF + PUBLIC USERDIR1 + PUBLIC vol_drv + PUBLIC vol_ioctl_buf ;AC030; + PUBLIC vol_serial ;AC030; + PUBLIC vol_label ;AC030; + PUBLIC WRITTEN + PUBLIC xa_cp_length ;AN030; + PUBLIC xa_cp_out ;AN030; + PUBLIC xa_list_attr ;AN030; + PUBLIC zflag + + IF IBM + PUBLIC ROM_CALL + PUBLIC ROM_CS + PUBLIC ROM_IP + ENDIF + + + ORG 0 +ZERO = $ +SRCXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate +TRGXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate +UCOMBUF DB COMBUFLEN+3 DUP(?) ; Raw console buffer +COMBUF DB COMBUFLEN+3 DUP(?) ; Cooked console buffer +USERDIR1 DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory +EXECPATH DB COMBUFLEN+3 DUP(?) ; Path for external command +RE_INSTR DB DIRSTRLEN+3+13 DUP (?) ; path for input to redirection + +; Variables passed up from resident +HEADCALL LABEL DWORD + DW ? +RESSEG DW ? +TPA DW ? +SWITCHAR DB ? +DIRCHAR DB ? +EXEC_ADDR DD ? +RCH_ADDR DD ? +fTest DW ? +TRAN_TPA DW ? + +CHKDRV DB ? +RDEOF LABEL BYTE ; Misc flags +IFNOTFLAG LABEL BYTE +FILTYP DB ? +CURDRV DB ? +concat_xa db 0 ;AN000; flag for XA on file concatenations +CONCAT LABEL BYTE +PARM1 DB ? +ARGC LABEL BYTE +PARM2 DB ? +COMSW DW ? ; Switches between command and 1st arg +ARG1S DW ? ; Switches between 1st and 2nd arg +DESTSWITCH LABEL WORD +ARG2S DW ? ; Switches after 2nd arg +ALLSWITCH LABEL WORD +ARGTS DW ? ; ALL switches except for COMSW +CFLAG DB ? +DESTCLOSED LABEL BYTE +SPECDRV DB ? +BYTCNT DW ? ; Size of buffer between RES and TRANS +NXTADD DW ? +FRSTSRCH DB ? +LINCNT DB ? +LINLEN DB ? +FILECNT DW ? +CHARBUF DB 80 DUP (?) ;line byte character buffer for xenix write +DESTFCB2 LABEL BYTE +IDLEN DB ? +ID DB 8 DUP(?) +COM DB 3 DUP(?) +DEST DB 37 DUP(?) +DESTNAME DB 11 DUP(?) +DESTFCB LABEL BYTE +DESTDIR DB DIRSTRLEN DUP(?) ; Directory for PATH searches +GOTOLEN LABEL WORD +BWDBUF LABEL BYTE +EXEFCB LABEL WORD +DIRBUF DB DIRSTRLEN+3 DUP(?) +SDIRBUF DB 12 DUP(?) +BITS DW ? +PATHCNT DW ? +PATHPOS DW ? +PATHSW DW ? +FULLSCR DW ? +comma db 0 ;g flag set if +,, occurs +plus_comma db 0 ;g flag set if +,, occurs +dirflag db 0 ;AN015; set when pathcrunch called from DIR +parse_last dw 0 ;AN018; used to hold parsing position + +system_cpage DW 0 ;AC001; used for CHCP variable +src_XA_size DW 0 ;AN000; size of extended attributes +src_XA_seg DW 0 ;AN000; segment of extended attributes + +ext_open_parms label byte ;AN000; extended open parameter list +;emg340 ext_open_off dw offset trangroup:srcbuf ;AN000; offset of file name +ext_open_off dw ? ;AN030; offset of extended attributes +ext_open_seg dw ? ;AN000; segment of extended attributes + dw 0 ;AN000; no additional parameters + +XA_cp_out label byte ;AN030; list for one extended attribute + DW 1 ;AN030; count of entries + DB EAISBINARY ;AN030; ea_type + DW EASYSTEM ;AN030; ea_flags + DB ? ;AN030; ea_rc + DB 2 ;AN030; ea_namelen + DW 2 ;AN030; ea_valuelen + DB "CP" ;AN030; ea_name +xa_list_attr DW 0 ;AC030; code page +xa_cp_length DW $-XA_cp_out ;AN030; length of buffer + + + +arg_buf db 128 dup (?) +file_size_low dw ? ;AC000; +file_size_high dw ? ;AC000; +string_ptr_2 dw ? +;AD061;string_ptr_2_sb dw ? +copy_Num dw ? +cpyflag db ? +Dir_Num DW ? +bytes_free dw ? + dw ? +major_ver_num dw ? +minor_ver_num dw ? +one_char_val db ?,0 +vol_drv db ? + +IF IBM +ROM_CALL DB ? ; flag for rom function +ROM_IP DW ? +ROM_CS DW ? +ENDIF + +DESTVARS LABEL BYTE +DESTISDIR DB ? +DESTSIZ DB ? +DESTTAIL DW ? +DESTINFO DB ? +DESTBUF DB DIRSTRLEN + 20 DUP (?) + +DESTHAND DW ? +DESTISDEV DB ? +FIRSTDEST DB ? +MELCOPY DB ? +MELSTART DW ? + +SRCVARS LABEL BYTE +SRCISDIR DB ? +SRCSIZ DB ? +SRCTAIL DW ? +SRCINFO DB ? +SRCBUF DB DIRSTRLEN + 20 DUP (?) + +SRCHAND DW ? +SRCISDEV DB ? + +SCANBUF DB DIRSTRLEN + 20 DUP (?) + +SRCPT DW ? +INEXACT DB ? +NOWRITE DB ? +BINARY DB ? +WRITTEN DW ? +TERMREAD DB ? +ASCII DB ? +PLUS DB ? +objcnt db ? ; Used in copy +CPDATE DW ? +CPTIME DW ? +BATHAND DW ? ; Batch handle +STARTEL DW ? +ELCNT DB ? +ELPOS DB ? +SKPDEL DB ? +SOURCE DB 11 DUP(?) + +ext_entered db 0 ;AN005; + +display_ioctl db 0 ;AN000; info level + db 0 ;AN000; reserved + dw crt_ioctl_ln ;AN000; length of data + dw ? ;AN000; control flags +display_mode db ? ;AN000; display mode, colors + db 0 ;AN000; reserved + dw ? ;AN023; colors + dw ? ;AN000; display width (PELS) + dw ? ;AN000; display length (PELS) +display_width dw ? ;AN000; display width +linperpag dw linesperpage ;AN000; display length (default to linesperpage) + +vol_ioctl_buf label byte ;AN000; buffer for ioctl volume label/serial call + dw 0 ;AN000; info level +vol_serial dd 0 ;AN000; volume serial number +vol_label db 11 dup (" ") ;AN000; volume label - init to blanks + db 8 dup (" ") ;AN000; file system type + +expand_star db ? +comspec_flag db ? +msg_flag db ? ;AN022; flag set if non-utility message issued +msg_numb dw 0 ;AN022; set with extended error message issued +append_exec db 0 ;AN041; set if internal append executed +print_err_flag dw 0 ;AN000; flag set if error during sysdispmsg +subst_buffer db parm_block_size*2 dup (0);AN061; + +;;;; IF KANJI 3/3/KK +KPARSE DB ? +;;;; ENDIF 3/3/KK + +; Data declarations taken out of parse.asm + +arg arg_unit <> ; pointers, arg count, string buffer +argbufptr DW ? ; index for argv[].argpointer +tpbuf DB 128 DUP (?) ; temporary buffer +LAST_ARG DW ? ; point at which to accumulate switch info +comptr dw ? ; ptr into combuf + +; Data declarations taken out of path.asm +fbuf find_buf <> ; dma buffer for findfirst/findnext +pathinfo DW 3 DUP (?) ; ES, SI(old), and SI(new) of user path +psep_char DB ? ; '/' or '\' +search_best DB (?) ; best code, best filename so far +fname_max_len equ 13 +search_best_buf DB fname_max_len DUP (?) +search_curdir_buf DB 64 DUP (?) ; a place for CurDir info, if successful +search_error DW (?) ; address of error message to be printed + +; Data declarations taken out of tbatch.asm +if_not_count DW ? + +zflag db ? ; Used by typefil to indicate ^Z's + + DW 80H DUP(0) ; Init to 0 to make sure the linker is not fooled +STACK LABEL WORD + +INTERNATVARS internat_block <> + DB (internat_block_max - ($ - INTERNATVARS)) DUP (?) + +BatBufPos DW ? ; integer position in buffer of next byte +BatBuf DB BatLen DUP (?) +BatBufEnd DW ? + +; ***************************************************** +; EMG 4.00 +; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00 +; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE +; ***************************************************** +; +; COMMON PARSE OUTPUT BLOCKS +; + + +; +; Common output blocks for PARSE number, complex, or string values. +; + +PARSE1_OUTPUT LABEL BYTE ;AN000; +PARSE1_TYPE DB 0 ;AN000; type +PARSE1_CODE DB 0 ;AN000; return value +PARSE1_SYN DW 0 ;AN000; es offset of synonym +PARSE1_ADDR DD 0 ;AN000; numeric value / address + ; of string value + +; +; Common output block for PARSE date strings. +; + +DATE_OUTPUT LABEL BYTE ;AN000; +DATE_TYPE DB 0 ;AN000; type + DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +DATE_YEAR DW 0 ;AN000; year +DATE_MONTH DB 0 ;AN000; month +DATE_DAY DB 0 ;AN000; day + +; +; Common output block for PARSE time strings. +; + +TIME_OUTPUT LABEL BYTE ;AN000; +TIME_TYPE DB 0 ;AN000; type + DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +TIME_HOUR DB 0 ;AN000; hour +TIME_MINUTES DB 0 ;AN000; minutes +TIME_SECONDS DB 0 ;AN000; seconds +TIME_FRACTION DB 0 ;AN000; hundredths + +; +; Common output block for PARSE drive specifier (one based drive number). +; + +DRIVE_OUTPUT LABEL BYTE ;AN000; +DRIVE_TYPE DB 0 ;AN000; type +DRIVE_VALUE DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +DRIVE_NUMBER DB 0 ;AN000; drive number + DB 0,0,0 ;AN000; reserved + +TRANSPACEEND LABEL BYTE + +TRANSPACE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TUCODE.ASM b/v4.0/src/CMD/COMMAND/TUCODE.ASM new file mode 100644 index 0000000..6531c44 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TUCODE.ASM @@ -0,0 +1,520 @@ + page 80,132 +; SCCSID = @(#)tucode.asm 4.2 85/05/31 +; SCCSID = @(#)tucode.asm 4.2 85/05/31 +Title COMMAND Language midifiable Code Transient + + +.xlist +.xcref + INCLUDE dossym.inc + INCLUDE comsw.asm + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN ECHOFLAG:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BAD_ON_OFF_ptr:word + EXTRN ctrlcmes_ptr:word + EXTRN DEL_Y_N_PTR:WORD + EXTRN ECHOMES_ptr:word + EXTRN extend_buf_ptr:word ;AC000; + EXTRN offmes_ptr:word + EXTRN onmes_ptr:word + EXTRN PARSE_BREAK:BYTE ;AN000; + EXTRN promptdat_moday:word ;AC000; + EXTRN promptdat_ptr:word ;AC000; + EXTRN promptdat_yr:word ;AC000; + EXTRN string_buf_ptr:word + EXTRN SUREMES_ptr:word + EXTRN VERIMES_ptr:BYTE + EXTRN WeekTab:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf:byte + EXTRN BWDBUF:BYTE + EXTRN DEST:BYTE + EXTRN destdir:byte + EXTRN dirchar:byte + EXTRN PARSE1_CODE:BYTE ;AN000; + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word + +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN CERROR:NEAR + EXTRN CRLF2:NEAR + EXTRN extend_setup:near ;AN022; + + PUBLIC CNTRLC + PUBLIC ECHO + PUBLIC GetDate + PUBLIC NOTEST2 + PUBLIC PRINT_DATE + PUBLIC SLASHP_ERASE ;AN000; + PUBLIC VERIFY + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +; **************************************************************** +; * +; * ROUTINE: NOTEST2 - execution of DEL/ERASE command +; * +; * FUNCTION: Delete files based on user parsed input. Prompt +; * user for Y/N if necessary. If an error occurs, +; * set up an error message and go to CERROR. +; * +; * INPUT: FCB at 5ch set up with filename(s) entered +; * Current directory set to entered directory +; * +; * OUTPUT: none +; * +; **************************************************************** +; +; ARE YOU SURE prompt when deleting *.* + +NOTEST2: + MOV CX,11 + MOV SI,FCB+1 + +AMBSPEC: + LODSB + CMP AL,'?' + JNZ ALLFIL + LOOP AMBSPEC + +ALLFIL: + CMP CX,0 + JNZ NOPRMPT + +ASKAGN: + MOV DX,OFFSET TRANGROUP:SUREMES_ptr ; "Are you sure (Y/N)?" + invoke std_printf + MOV SI,80H + MOV DX,SI + MOV WORD PTR [SI],120 ; zero length + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_STRING_INPUT + INT 21H + LODSW + OR AH,AH + JZ ASKAGN + INVOKE SCANOFF + call char_in_xlat ;G Convert to upper case + retc ;AN000; return if function not supported + CMP AL,CAPITAL_N ;G + retz + CMP AL,CAPITAL_Y ;G + PUSHF + CALL CRLF2 + POPF + JNZ ASKAGN + +NOPRMPT: + MOV AH,FCB_DELETE + MOV DX,FCB + INT 21H + INC AL + jz eraerr + invoke RESTUDIR + ret ; If no error, return + +eraerr: + invoke set_ext_error_msg ;AN022; set up the extended error + push dx ;AN022; save message + invoke RESTUDIR + pop dx ;AN022; restore message + + cmp word ptr extend_buf_ptr,error_no_more_files ;AN022; convert no more files to + jnz cerrorj2 ;AN022; file not found + mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block + +cerrorj2: + jmp cerror + + +; **************************************************************** +; * +; * ROUTINE: SLASHP_ERASE - execution of DEL/ERASE /P +; * +; * FUNCTION: Delete files based on user parsed input. Prompt +; * user for Y/N where necessary. If an error occurs +; * set up and error message and transfer control +; * to CERROR. +; * +; * INPUT: FCB at 5ch set up with filename(s) entered +; * Current directory set to entered directory +; * +; * OUTPUT: none +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +SLASHP_ERASE: ;AN000; entry point + invoke build_dir_string ;AN000; set up current directory string for output + mov ah,Set_DMA ;AN000; issue set dta int 21h + mov dx,offset trangroup:destdir ;AN000; use Destdir for target + int 21H ;AN000; + mov ah,Dir_Search_First ;AN000; do dir search first int 21h + mov dx,FCB ;AN000; use FCB at 5Ch for target + int 21H ;AN000; + inc al ;AN000; did an error occur + jz eraerr ;AN022; go to error exit + +delete_prompt_loop: ;AN000; + mov si,offset trangroup:destdir+1 ;AN000; set up FCB as source + mov di,offset trangroup:dest ;AN000; set up dest as target + mov al,dirchar ;AN000; store a "\" in the first char + stosb ;AN000; of DEST + invoke fcb_to_ascz ;AN000; convert filename from FCB to ASCIIZ string + +slashp_askagn: ;AN000; + call crlf2 ;AN000; print out carriage return, line feed + mov dx,offset trangroup:bwdbuf ;AN000; print out current directory string + mov bx,dx ;AN000; get string pointer in bx + cmp byte ptr [bx+3],end_of_line_out ;AN000; see if only D:\,0 + jnz not_del_root ;AN000; no continue + mov byte ptr [bx+2],end_of_line_out ;AN000; yes, get rid of \ + +Not_del_root: ;AN000; + mov string_ptr_2,dx ;AN000; + mov dx,offset trangroup:string_buf_ptr ;AN000; + invoke std_printf ;AN000; + mov dx,offset trangroup:dest ;AN000; print out file name string + mov string_ptr_2,dx ;AN000; + mov dx,offset trangroup:string_buf_ptr ;AN000; + invoke std_printf ;AN000; + mov dx,offset trangroup:Del_Y_N_Ptr ;AN000; issue ", Delete (Y/N)?" message + invoke std_printf ;AN000; + mov si,80H ;AN000; set up buffer for input + mov dx,si ;AN000; + mov word ptr [si],combuflen ;AN000; + mov ax,(std_con_input_flush shl 8) or std_con_string_input ;AN000; + int int_command ;AN000; get input from the user + lodsw ;AN000; + or ah,ah ;AN000; was a character entered? + jz slashp_askagn ;AN000; no - ask again + invoke scanoff ;AN000; scan off leading delimiters + call char_in_xlat ;AN000; yes - upper case it + retc ;AN000; return if function not supported + cmp al,capital_n ;AN000; was it no? + jz next_del_file ;AN000; yes - don't delete file + cmp al,capital_y ;AN000; was it yes? + jz delete_this_file ;AN000; yes - delete the file + jmp short slashp_askagn ;AN000; it was neither - ask again + +delete_this_file: ;AN000; + mov ah,fcb_delete ;AN000; delete the file + mov dx,offset trangroup:destdir ;AN000; use Destdir for target + int int_command ;AN000; + inc al ;AN000; did an error occur? + jnz next_del_file ;AN000; no - get next file + jmp eraerr ;AN022; go to error exit - need long jmp + +next_del_file: ;AN000; + mov ah,dir_search_next ;AN000; search for another file + mov dx,FCB ;AN000; + int int_command ;AN000; + inc al ;AN000; was a file found? + jz slash_p_exit ;AN000; no - exit + jmp delete_prompt_loop ;AN000; yes - continue (need long jump) + +slash_p_exit: + invoke get_ext_error_number ;AN022; get the extended error number + cmp ax,error_no_more_files ;AN022; was error file not found? + jz good_erase_exit ;AN022; yes - clean exit + jmp extend_setup ;AN022; go issue error message + +good_erase_exit: + invoke restudir ;AN000; we're finished - restore user's dir + call crlf2 ;AN000; print out carriage return, line feed + ret ;AN000; exit + + +;************************************************ +; ECHO, BREAK, and VERIFY commands. Check for "ON" and "OFF" + + break Echo + +assume ds:trangroup,es:trangroup + +ECHO: + CALL ON_OFF + JC DOEMES + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + JNZ ECH_OFF + OR [ECHOFLAG],1 + RET +ECH_OFF: + AND [ECHOFLAG],NOT 1 + RET + + +CERRORJ: + JMP CERROR + +; +; There was no discrenable ON or OFF after the ECHO. If there is nothing but +; delimiters on the command line, we issue the ECHO is ON/OFF message. +; + +ASSUME DS:TRANGROUP + +DOEMES: + cmp cl,0 ;AC000; was anything on the line? + jz PEcho ; just display current state. + MOV DX,82H ; Skip one char after "ECHO" + invoke CRPRINT + JMP CRLF2 + +PECHO: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV BL,[ECHOFLAG] + PUSH CS + POP DS +ASSUME DS:TRANGROUP + AND BL,1 + MOV DX,OFFSET TRANGROUP:ECHOMES_ptr + JMP SHORT PYN + + break Break +assume ds:trangroup,es:trangroup + +CNTRLC: + CALL ON_OFF + MOV AX,(SET_CTRL_C_TRAPPING SHL 8) OR 1 + JC PCNTRLC + JNZ CNTRLC_OFF + MOV DL,1 + INT 21H ; Set ^C + RET + +CNTRLC_OFF: + XOR DL,DL + INT 21H ; Turn off ^C check + RET + +PCNTRLC: + CMP CL,0 ;AC000; rest of line blank? + JNZ CERRORJ ; no, oops! + +pccont: + XOR AL,AL + INT 21H + MOV BL,DL + MOV DX,OFFSET TRANGROUP:CTRLCMES_ptr + +PYN: + mov si,offset trangroup:onmes_ptr ;AC000; get ON pointer + OR BL,BL + JNZ PRINTVAL + mov si,offset trangroup:offmes_ptr ;AC000; get OFF pointer + +PRINTVAL: + push dx ;AN000; save offset of message block + mov bx,dx ;AN000; save offset value + lodsw ;AN000; get message number of on or off + mov dh,util_msg_class ;AN000; this is a utility message + invoke Tsysgetmsg ;AN000; get the address of the message + add bx,ptr_off_pos ;AN000; point to offset of ON/OFF + mov word ptr [bx],si ;AN000; put the offset in the message block + pop dx ;AN000; get message back + invoke std_printf ;AC000; go print message + mov word ptr [bx],0 ;AN000; zero out message pointer + + ret ;AN000; exit + + break Verify +assume ds:trangroup,es:trangroup + +VERIFY: + CALL ON_OFF + MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 + JC PVERIFY + JNZ VER_OFF + INT 21H ; Set verify + RET + +VER_OFF: + DEC AL + INT 21H ; Turn off verify after write + RET + +PVERIFY: + CMP CL,0 ;AC000; is rest of line blank? + JNZ CERRORJ ; nope... + MOV AH,GET_VERIFY_ON_WRITE + INT 21H + MOV BL,AL + MOV DX,OFFSET TRANGROUP:VERIMES_ptr + JMP PYN + +; **************************************************************** +; * +; * ROUTINE: ON_OFF +; * +; * FUNCTION: Parse the command line for an optional ON or +; * OFF string for the BREAK, VERIFY, and ECHO +; * routines. +; * +; * INPUT: command line at offset 81H +; * PARSE_BREAK control block +; * +; * OUTPUT: If carry is clear +; * If ON is found +; * Zero flag set +; * If OFF is found +; * Zero flag clear +; * If carry set +; * If nothing on command line +; * CL set to zero +; * If error +; * CL contains error value from parse +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +ON_OFF: + MOV SI,81h + +scan_on_off: ;AN032; scan off leading blanks & equal + lodsb ;AN032; get a char + cmp al,blank ;AN032; if whitespace + jz scan_on_off ;AN032; keep scanning + cmp al,tab_chr ;AN032; if tab + jz scan_on_off ;AN032; keep scanning + cmp al,equal_chr ;AN032; if equal char + jz parse_on_off ;AN032; start parsing + dec si ;AN032; if none of above - back up + +parse_on_off: ;AN032; and start parsing + mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + jz BADONF ;AC000; yes, return error + cmp ax,result_no_error ;AN000; did an error occur + jz on_off_there ;AN000; no - continue + mov cx,ax ;AN000; yes - set cl to error code + jmp short BADONF ;AN000; return error + +on_off_there: + cmp parse1_code,-1 ;AN014; was a valid positional present? + jnz good_on_off ;AN014; yes - continue + mov cx,badparm_ptr ;AN014; something other than ON/OFF + jmp short BADONF ;AN014; return error + +good_on_off: ;AN014; + xor ax,ax ;AC000; set up return code for + or al,parse1_code ;AC000; ON or OFF in AX + pushf ;AN000; save flags + mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK + xor dx,dx ;AN000; + invoke cmd_parse ;AN000; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jnz BADONF_flags ;AN000; NO, return error + popf ;AN000; restore flags + clc ;AC000; no error + jmp short on_off_end ;AN000; return to caller + +BADONF_flags: + mov cx,ax + popf + +; +; No discernable ON or OFF has been found. Put an error message pointer in DX +; and return the error +; +BADONF: + MOV DX,OFFSET TRANGROUP:BAD_ON_OFF_ptr + STC + +ON_OFF_END: + + RET + + + +;************************************************************************* +; print date + +PRINT_DATE: + PUSH ES + PUSH DI + PUSH CS + POP ES + CALL GetDate ; get date + xchg dh,dl ;AN000; switch month & day + mov promptDat_yr,cx ;AC000; put year into message control block + mov promptDat_moday,dx ;AC000; put month and day into message control block + mov dx,offset trangroup:promptDat_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov promptDat_yr,0 ;AC000; reset year, month and day +;AD061; mov promptDat_moday,0 ;AC000; pointers in control block + POP DI ;AC000; restore di,es + POP ES ;AC000; + return +; +; Do GET DATE system call and set up 3 character day of week in ARG_BUF +; for output. Date will be returned in CX,DX. +; + +GetDate: + mov di,offset trangroup:arg_buf ;AC000; target for day of week + MOV AH,GET_DATE ;AC000; get current date + INT int_command ;AC000; Get date in CX:DX + CBW ;AC000; + + push cx ;AN000; save date returned in + push dx ;AN000; CX:DX + MOV SI,AX + SHL SI,1 + ADD SI,AX ; SI=AX*3 + mov cx,si ;AN000; save si + mov ax,weektab ;AN000; get message number of weektab + mov dh,util_msg_class ;AN000; this is a utility message + push di ;AN000; save argument buffer + invoke Tsysgetmsg ;AN000; get the address of the message + pop di ;AN000; retrieve argument buffer + add si,cx ;AC000; get day of week + MOV CX,3 + REP MOVSB + mov al,end_of_line_out ;AC000; terminate the string + stosb + pop dx ;AN000; get back date + pop cx ;AN000; + + return +;g +;g This routine determines whether the character in AL is a +;g Yes or No character. On return, if AL=0, the character is +;g No, if AL=1, the character is Yes. +;g + +assume ds:trangroup + +char_in_xlat proc near + + mov dl,al ;AC000; get character into DX + xor dh,dh ;AC000; + mov ax,(getextcntry SHL 8) + 35 ;AC000; Yes/No char call + int int_command ;AC000; + + ret + +char_in_xlat endp + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/UINIT.ASM b/v4.0/src/CMD/COMMAND/UINIT.ASM new file mode 100644 index 0000000..8f3498b --- /dev/null +++ b/v4.0/src/CMD/COMMAND/UINIT.ASM @@ -0,0 +1,270 @@ + page 80,132 +; SCCSID = @(#)uinit.asm 4.5 85/12/04 +; SCCSID = @(#)uinit.asm 4.5 85/12/04 +TITLE COMMAND Initialization messages + +.XCREF +.XLIST +include comsw.asm +include comseg.asm +include ifequ.asm +.LIST +.CREF + +addr macro sym,name + public name + ifidn ,<> + + dw offset resgroup:sym + else + +name dw offset resgroup:sym + endif + endm + + +ENVIRONMENT SEGMENT PUBLIC PARA ;AC000; + EXTRN ECOMSPEC:BYTE +ENVIRONMENT ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + extrn Printf_init:FAR + extrn Triage_Init:FAR + extrn append_parse:FAR ;AN054; +TranCode ENDS + +INIT SEGMENT PUBLIC PARA ;AC000; + + + public icondev + public BADCSPFL + public COMSPECT + public AUTOBAT + public fslash + public bslash + public space + public PRDATTM + public INITADD + public print_add + public CHUCKENV + public scswitch + public ucasea + public ECOMLOC + public equalsign + public lcasea + public lcasez + public comspstring + public EnvSiz + public EnvMax + public initend + public trnsize + public resetenv ;AC000; + public ext_msg ;AC000; + public num_positionals + public internat_info + public parsemes_ptr + + PUBLIC triage_add + PUBLIC oldenv + PUBLIC usedenv + PUBLIC KAUTOBAT ;AN000; 3/3/KK + public eswitch ;AN018; + public dswitch ;AN018; + public init_parse ;AN054; + public old_parse_ptr ;AN057; + PUBLIC pars_msg_off ;AN060; + PUBLIC pars_msg_seg ;AN060; + +include resmsg.equ ;AC000; + + +ICONDEV LABEL BYTE + DB "/DEV/" + DB "CON",0,0,0,0,0,0 ; Room for 8 char device +BADCSPFL DB 0 +COMSPECT DB "/COMMAND.COM",0,0 +AUTOBAT DB 0,":\AUTOEXEC.BAT",0,0DH ;AC027; +KAUTOBAT DB 0,":\KAUTOEXE.BAT",0,0DH ;AC027; 3/3/KK + +PRDATTM DB -1 ;Init not to prompt for date time +INITADD DD ? +print_add LABEL DWORD + DW OFFSET TranGroup:Printf_INIT + DW 0 +triage_add LABEL DWORD + DW OFFSET TranGroup:Triage_Init + DW 0 +CHUCKENV DB 0 +;eg ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC-10H +ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC ;eg + +COMSPSTRING DB "COMSPEC=" +equalsign db "=" +lcasea db "a" +lcasez db "z" +fslash db "/" +bslash db "\" +space db " " +scswitch db "C" ; Single command +ucasea db "A" + +EnvSiz DW 0 ; size user wants to allocate +EnvMax DW 0 ; maximum size allowed. +oldenv DW 0 ; envirseg at initialization +usedenv DW 0 ; amount of envirseg used +PARS_MSG_OFF DW 0 ;AN060; SAVED PARSE ERROR MESSAGE OFFSET +PARS_MSG_SEG DW 0 ;AN060; SAVED PARSE ERROR MESSAGE SEGMENT + +;Do not separate the following two words. Used to call transient PARSE routine + +init_parse label dword ;AN054; +init_p DW TRANGROUP:APPEND_PARSE ;AN054; +initend DW 0 ;eg segment address of end of init + +;End of data that shouldn't be separated. + +trnsize DW 0 ;eg size of transient in paragraphs +resetenv DB 0 ;eg set if we need to setblck env at endinit +ext_msg DB 0 ;AN000; set if /MSG switch entered +eswitch db 0 ;AN018; set if /e was entered +dswitch db 0 ;AN018; set if /d was entered +parsemes_ptr dw 0 ;AN000; word to store parse error number + +; +; PARSE BLOCK FOR COMMAND +; +PUBLIC PARSE_COMMAND ;AN000; +PUBLIC COMND1_OUTPUT ;AN000; +PUBLIC COMND1_TYPE ;AN000; +PUBLIC COMND1_CODE ;AN000; +PUBLIC COMND1_SYN ;AN000; +PUBLIC COMND1_ADDR ;AN000; +PUBLIC COMMAND_F_SYN ;AN000; +PUBLIC COMMAND_P_SYN ;AN000; +PUBLIC COMMAND_C_SYN ;AN000; +PUBLIC COMMAND_D_SYN ;AN000; +PUBLIC COMMAND_E_SYN ;AN000; +PUBLIC COMMAND_M_SYN ;AN000; + +; +; The following parse control block is used for COMMAND. This block is +; used for parsing during initialization. The sytax for COMMAND is: +; COMMAND [d:][path][/P][/F][/D][/E:xxxxx][/MSG][/C executable] +; Anything on the command line after the /C switch will be passed to the +; executable command, so if /C is used, it must be specified last. The +; /MSG switch can only be specified if the /P switch is specified. +; + +ENVBIG EQU 32768 ;AN000; maximum environment size +ENVSML EQU 160 ;AN000; minimum environment size + +INTERNAT_INFO LABEL BYTE ;AN000; used for country info after parsing is completed +PARSE_COMMAND LABEL BYTE ;AN000; + DW RESGROUP:COMMAND_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +COMMAND_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW RESGROUP:COMMAND_FILE ;AN000; + DB 6 ;AN000; 6 switches + DW RESGROUP:COMMAND_SWITCH1 ;AN000; + DW RESGROUP:COMMAND_SWITCH2 ;AN000; + DW RESGROUP:COMMAND_SWITCH3 ;AN000; + DW RESGROUP:COMMAND_SWITCH4 ;AN000; + DW RESGROUP:COMMAND_SWITCH5 ;AN000; + DW RESGROUP:COMMAND_SWITCH6 ;AN000; + DB 0 ;AN000; no keywords + +COMMAND_FILE LABEL BYTE ;AN000; + DW 0201H ;AN000; filespec - optional + DW 1 ;AN000; capitalize - file table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 0 ;AN000; no keywords + +COMMAND_SWITCH1 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_P_SYN DB "/P",0 ;AN000; /P switch + +COMMAND_SWITCH2 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_F_SYN DB "/F",0 ;AN000; /F switch + +COMMAND_SWITCH3 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_D_SYN DB "/D",0 ;AN000; /D switch + +COMMAND_SWITCH4 LABEL BYTE ;AN000; + DW 8000H ;AN000; numeric value - required + DW 0 ;AN000; no function flags + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:COMMAND_E_VAL ;AN000; pointer to value list + DB 1 ;AN000; 1 keyword +COMMAND_E_SYN DB "/E",0 ;AN000; /E switch + +COMMAND_E_VAL LABEL BYTE ;AN000; + DB 1 ;AN000; + DB 1 ;AN000; 1 range + DB 1 ;AN000; returned if result + DD ENVSML,ENVBIG ;AN000; minimum & maximum value + DB 0 ;AN000; no numeric values + DB 0 ;AN000; no string values + +COMMAND_SWITCH5 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_C_SYN DB "/C",0 ;AN000; /C switch + +COMMAND_SWITCH6 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_M_SYN DB "/MSG",0 ;AN000; /MSG switch + +COMND1_OUTPUT LABEL BYTE ;AN000; +COMND1_TYPE DB 0 ;AN000; type +COMND1_CODE DB 0 ;AN000; return value +COMND1_SYN DW 0 ;AN000; synonym pointer +COMND1_ADDR DD 0 ;AN000; numeric value / address + ; of string value + +NO_VAL DB 0 ;AN000; no values +num_positionals DW 0 ;AN000; counter for positionals +old_parse_ptr DW 0 ;AN057; SI position before calling parser + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; get message services routine + +.list +.cref + +ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AN000; include initialization messages + +include msgdcl.inc + +INIT ENDS + + END diff --git a/v4.0/src/CMD/COMP/COMP.LNK b/v4.0/src/CMD/COMP/COMP.LNK new file mode 100644 index 0000000..f8b53de --- /dev/null +++ b/v4.0/src/CMD/COMP/COMP.LNK @@ -0,0 +1,6 @@ +COMP1+ +COMPPAR+ +COMPP+ +COMPSM+ +COMP2,COMP,COMP.MAP/M; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMP.SKL b/v4.0/src/CMD/COMP/COMP.SKL new file mode 100644 index 0000000..96a1115 --- /dev/null +++ b/v4.0/src/CMD/COMP/COMP.SKL @@ -0,0 +1,30 @@ +:util COMP ;utility name ;AN000; + +:class A ;system messages ;AN000; + +:use 1 COMMON1 ;"Incorrect DOS version" ;AN000; +:use 2 EXTEND8 ;"Insufficient memory" ;AN000; +:use 3 PARSE10 ;"Invalid parameter" ;AN000; + +:def 4 "10 Mismatches - ending compare",CR,LF ;AN000; +:use 5 EXTEND15 ;"Invalid drive specification" ;AN000; +:def 6 "Compare error at OFFSET %1",CR,LF ;AN000; +:def 7 "File 1 = %1",CR,LF ;AN000; +:def 8 "File 2 = %1",CR,LF ;AN000; +:def 9 "Eof mark not found",CR,LF ;AN000; +:def 10 "Files compare ok",CR,LF ;AN000; +:use 11 EXTEND2 ;"File not found" ;AN000; +:use 12 COMMON25 ;"Invalid path" ;AN000; +:use 13 EXTEND32 ;"Sharing violation" ;AN000; +:use 14 EXTEND4 ;"Too many open files" ;AN000; +:def 15 CR,LF,CR,LF,"Enter primary filename",CR,LF ;AN000; +:def 16 CR,LF,CR,LF,"Enter 2nd filename or drive id",CR,LF ;AN000; +:def 17 "Files are different sizes",CR,LF ;AN000; +:def 18 "Compare more files (Y/N) ?" ;AN000; +:def 19 "%1 and %2",CR,LF ;AN000; +:def 20 CR,LF ;AN000; +:use 21 EXTEND5 ;"Access Denied" ;AN000; +:use 22 EXTEND37 ;"Code page mismatch" ;AN000; +:DEF 23 "Files compare ok",CR,LF ;AN000; +:end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMP1.ASM b/v4.0/src/CMD/COMP/COMP1.ASM new file mode 100644 index 0000000..b732543 --- /dev/null +++ b/v4.0/src/CMD/COMP/COMP1.ASM @@ -0,0 +1,190 @@ + page ,132 ; + title COMP.SAL - COMPARE A PAIR OF FILES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMP1.ASM +; +; DESCRIPTIVE NAME: Compare two files to show they are identical or not. +; +; FUNCTION: The paths and names of each pair of files is +; displayed as the comparing process proceeds. An +; error message will follow the names if: +; (1) a file matching the second filename can't be found, +; (2) the files are different sizes, or +; (3) either path is invalid. +; +; During the comparison, an error message will appear for any +; location that contains mismatching information in the 2 +; files. The message indicates the offset into the files of +; the mismatching bytes, and the contents of the 2 bytes +; themselves (all in hex). This will occur for up to 10 +; mismatching bytes - if more than 10 compare errors are +; found, the program assumes that further comparison would be +; useless, and ends its compare of the 2 files at that point. +; +; If all bytes in the 2 files match, a "Files compare OK" +; message will appear. +; +; In all cases, after the comparing of 2 files ends, comparing +; will proceed with the next pair of files that match the 2 +; filenames, until no more files can be found that match the +; first filename. You are then asked if you want to compare +; any more files. Replying "N" returns you to the DOS prompt +; (such as A>); a reply of "Y" results in prompts for new +; primary and secondary filenames. +; +; In all compares, COMP looks at the last byte of one of the +; files being compared to assure that it contains a valid +; end-of-file mark (CTRL-Z, which is the hex character 1A). +; If found, no action is taken by COMP. If the end-of-file +; mark is NOT found, COMP produces the message "EOF mark not +; found". This is done because some products produce files +; whose sizes are always recorded in the directory as a +; multiple of 128 bytes, even though the actual usable data in +; the file will usually be a few bytes less than the directory +; size. In this case, COMP may produce "Compare error" +; messages when comparing the few bytes beyond the last real +; data byte in the last block of 128 bytes (COMP always +; compares the number of bytes reflected in the directory). +; Thus, the "EOF mark not found" message indicates that the +; compare errors may not have occurred in the usable data +; portion of the file. +; +; Multiple compare operations may be performed with one load +; of COMP. A prompt, "Compare more files (Y/N)?" permits additional +; executions. +; +; ENTRY POINT: "START" at ORG 100h, jumps to "INIT". +; +; INPUT: (DOS command line parameters) +; [d:][path] COMP [d:][path][filenam1[.ext]] [d:][path][filenam2[.ext]] +; +; Where +; [d:][path] before COMP to specify the drive and path that +; contains the COMP command file. +; +; [d:][path][filenam1[.ext]] - to specify the FIRST (or primary) +; file or group of files to be compared +; +; [d:][path][filenam2[.ext]] - to specify the SECOND file or group +; of files to be compared with the corresponding file +; from the FIRST group +; +; Global filename characters are allowed in both filenames, +; and will cause all of the files matching the first filename +; to be compared with the corresponding files from the second +; filename. Thus, entering COMP A:*.ASM B:*.BAK will cause +; each file from drive A: that has an extension of .ASM to be +; compared with a file of the same name (but with an extension +; of .BAK) from drive B:. +; +; If you enter only a drive specification, COMP will assume +; all files in the current directory of the specified drive. +; If you enter a path without a filename, COMP assumes all +; files in the specified directory. Thus, COMP A:\LEVEL1 +; B:\LEVEL2 will compare all files in directory A:\LEVEL1 with +; the files of the same names in directory B:\LEVEL2. +; +; If no parameters are entered with the COMP command, you will +; be prompted for both. If the second parm is omitted, COMP +; will prompt for it. If you simply press ENTER when prompted +; for the second filename, COMP assumes *.* (all files +; matching the primary filename), and will use the current +; directory of the default drive. +; +; If no file matches the primary filename, COMP will prompt +; again for both parameters. +; +; EXIT-NORMAL: Errorlevel = 0, Function completed successfully. +; +; EXIT-ERROR: Errorlevel = 1, Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on the diskette. +; +; EFFECTS: Files are not altered. A Message will show result of compare. +; +; INTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; WORKAREA - Temporary storage +; +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; SYSPARSE - Processes the DOS Command line, finds parms. +; +; DATA AREAS: +; COMPSM.SAL - Defines the control blocks that describe the messages +; COMPPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT COMP1,NUL +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; Sample LINK command: +; +; LINK @COMP.ARF +; +; Where the COMP.ARF is defined as: +; +; COMP1+ +; COMPPAR+ +; COMPP+ +; COMPSM+ +; COMP2 +; +; These modules must be linked in this order. The load module is +; a COM file, to be converted to COM with EXE2BIN. +; +; REVISION HISTORY: +; AN000 Version 4.00: add PARSER, System Message Handler, +; Add compare of code page extended attribute, if present. +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "COMPSM.SAL" module: +; +; "The DOS COMP Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft" +; +;PROGRAM AUTHOR: Original written by: Dave L. +; 3.30 modifications by Russ W. +; 4.0 modifications by: Edwin M. K. +; 4.0 modifications by: Bill L. +;****************** END OF SPECIFICATIONS ***************************** + PAGE +; $SALUT (4,13,18,36) + IF1 + %OUT COMPONENT=COMP, MODULE=COMP1.ASM + ENDIF + +CSEG segment PARA public 'CODE' ;AN000; + assume cs:CSEG,ds:CSEG,es:CSEG,ss:CSEG ;AS SET BY DOS LOADER +PSP_HEADER EQU $ ;START OF PROGRAM SEGMENT PREFIX AREA + org 02h +MEMORY_SIZE LABEL WORD + PUBLIC MEMORY_SIZE + + org 5Ch +FCB LABEL BYTE + PUBLIC FCB + + org 80h +PARM_AREA LABEL BYTE + PUBLIC PARM_AREA + + org 100h + EXTRN INIT:NEAR ;"INIT" IS IN COMP2.SAL +START: jmp INIT ;DEFINE THE DOS ENTRY POINT + +CSEG ENDS + END START + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMP2.ASM b/v4.0/src/CMD/COMP/COMP2.ASM new file mode 100644 index 0000000..e4e719a --- /dev/null +++ b/v4.0/src/CMD/COMP/COMP2.ASM @@ -0,0 +1,1932 @@ + PAGE ,132 ; + title COMP2.SAL - COMPARES FILES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMP2.ASM +; +; DESCRIPTIVE NAME: Compare two files to show they are identical or not. +; +; FUNCTION: The paths and names of each pair of files is +; displayed as the comparing process proceeds. An +; error message will follow the names if: +; (1) a file matching the second filename can't be found, +; (2) the files are different sizes, +; (3) either path is invalid, or. +; (4) CHCP=Yes (CODE PAGE active) and code page of files +; do not match. +; +; During the comparison, an error message will appear for any +; location that contains mismatching information in the 2 +; files. The message indicates the offset into the files of +; the mismatching bytes, and the contents of the 2 bytes +; themselves (all in hex). This will occur for up to 10 +; mismatching bytes - if more than 10 compare errors are +; found, the program assumes that further comparison would be +; useless, and ends its compare of the 2 files at that point. +; +; If all bytes in the 2 files match, a "Files compare OK" +; message will appear. +; +; In all cases, after the comparing of 2 files ends, comparing +; will proceed with the next pair of files that match the 2 +; filenames, until no more files can be found that match the +; first filename. You are then asked if you want to compare +; any more files. Replying "N" returns you to the DOS prompt +; (such as A>); a reply of "Y" results in prompts for new +; primary and secondary filenames. +; +; In all compares, COMP looks at the last byte of one of the +; files being compared to assure that it contains a valid +; end-of-file mark (CTRL-Z, which is the hex character 1A). +; If found, no action is taken by COMP. If the end-of-file +; mark is NOT found, COMP produces the message "EOF mark not +; found". This is done because some products produce files +; whose sizes are always recorded in the directory as a +; multiple of 128 bytes, even though the actual usable data in +; the file will usually be a few bytes less than the directory +; size. In this case, COMP may produce "Compare error" +; messages when comparing the few bytes beyond the last real +; data byte in the last block of 128 bytes (COMP always +; compares the number of bytes reflected in the directory). +; Thus, the "EOF mark not found" message indicates that the +; compare errors may not have occurred in the usable data +; portion of the file. +; +; Multiple compare operations may be performed with one load +; of COMP. A prompt, "Compare more files (Y/N)?" permits additional +; executions. +; +; ENTRY POINT: "INIT", jumped to by COMP1 at the DOS entry point. +; +; INPUT: (DOS command line parameters) +; [d:][path] COMP [d:][path][filenam1[.ext]] [d:][path][filenam2[.ext]] +; +; Where +; [d:][path] before COMP to specify the drive and path that +; contains the COMP command file. +; +; [d:][path][filenam1[.ext]] - to specify the FIRST (or primary) +; file or group of files to be compared +; +; [d:][path][filenam2[.ext]] - to specify the SECOND file or group +; of files to be compared with the corresponding file +; from the FIRST group +; +; Global filename characters are allowed in both filenames, +; and will cause all of the files matching the first filename +; to be compared with the corresponding files from the second +; filename. Thus, entering COMP A:*.ASM B:*.BAK will cause +; each file from drive A: that has an extension of .ASM to be +; compared with a file of the same name (but with an extension +; of .BAK) from drive B:. +; +; If you enter only a drive specification, COMP will assume +; all files in the current directory of the specified drive. +; If you enter a path without a filename, COMP assumes all +; files in the specified directory. Thus, COMP A:\LEVEL1 +; B:\LEVEL2 will compare all files in directory A:\LEVEL1 with +; the files of the same names in directory B:\LEVEL2. +; +; If no parameters are entered with the COMP command, you will +; be prompted for both. If the second parm is omitted, COMP +; will prompt for it. If you simply press ENTER when prompted +; for the second filename, COMP assumes *.* (all files +; matching the primary filename), and will use the current +; directory of the default drive. +; +; If no file matches the primary filename, COMP will prompt +; again for both parameters. +; +; EXIT-NORMAL: Errorlevel = 0, Function completed successfully. +; +; EXIT-ERROR: Errorlevel = 1, Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on the diskette. +; +; EFFECTS: Files are not altered. A Message will show result of compare. +; +; INTERNAL REFERENCES: +; ROUTINES: +; SENDMSG - passes parms to regs and invokes the system message routine. +; EXTERR - get extended error and display message. +; INIT_CP - record chcp switch then turn off. Allows COMP to open first +; or second file regardless of the system code page. +; RESTORE_CP - resets the chcp switch to the initial value. +; COMP_CODEPAGE - verify matching code pages. +; GET_CP - do an extended open, get code page, then close. +; +; DATA AREAS: +; WORKAREA - Temporary storage +; +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; SYSPARSE - Processes the DOS Command line, finds parms. +; +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; COMPSM.SAL - Defines the control blocks that describe the messages +; COMPPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT COMP2,NUL +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK information, reference Prolog of COMP1.SAL. +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "COMPSM.SAL" module: +; +; "The DOS COMP Utility" +; "Version 4.0 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft" +; +; Modification History: +; +; Version Author date comment +; ------- ------ ---- ------- +; V0.0 Dave L. Original author +; +; V3.3 Russ W. +; +; V4.0 Edwin M. K. ;AN000; Extended attribute support, +; Bill L. 7/10/87 parser, message retriever support +; +; V4.0 Bill L. 9/17/87 ;AN001; - DCR 201 enhancements to the +; extended attribute support +; +; V4.0 Bill L. ;AN002; - PTM 708 +; ;AN003; - PTM 728 +; ;AN004; - PTM 1610 +; ;AN005; - PTM 274 +; ;AN006; - PTM 2205 (DBCS support) +; ;AN007; - PTM 3056 (y/n -> STDERR) +; ;AN008; - optimizations +; ;AN009; - PTM 4076 network hang +; +;****************** END OF SPECIFICATIONS ***************************** + page + + if1 + %OUT COMPONENT=COMP, MODULE=COMP2.SAL + endif + +;*********************************** +; Macro definitions +;*********************************** + +fill_name1 macro pfcb ;AN000; + push dx ;AN000; + push di ;AN000; + push si ;AN000; + mov dx,offset name1 ;AN000; + mov si,offset path1 ;AN000; + mov di,offset pfcb ;AN000; + call fill_n ;AN000; + pop si ;AN000; + pop di ;AN000; + pop dx ;AN000; + endm ;AN000; + +fill_name2 macro ;AN000; + push dx ;AN000; + push di ;AN000; + push si ;AN000; + mov dx,offset name2 ;AN000; + mov si,offset path2 ;AN000; + mov di,offset outfcb ;AN000; + call fill_n ;AN000; + pop si ;AN000; + pop di ;AN000; + pop dx ;AN000; + endm ;AN000; + +print_msg macro msg,handle ;AC003; + push ax ;AN000; + mov dx,offset msg ;AN000; ;dx: ptr to msg descriptor + ifnb ;AN003; ;check if new handle given + push di ;AN003; ;put new handle in msg structure + mov di,dx ;AN003; + mov [di].msg_handle,handle ;AN003; + pop di ;AN003; + endif ;AN003; + call sendmsg ;AC000; + pop ax ;AN000; + endm ;AN000; + +doscall macro func,subfunc ;AN000; + ifnb ;AN000; ;are there any parms at all ? + ifnb ;AN000; ;is there a sub-function ? + mov ax,(func shl 8)+subfunc ;AN000; ;yes, ah=func, al=subfunc + else ;AN000; ;no sub-function + mov ah,func ;AN000; + endif ;AN000; + endif ;AN000; + int 21h ;AN000; + endm ;AN000; + +;*********************************** +; Include equates +;*********************************** + + include compeq.inc ;AN000; ;include some equates + +;*********************************** +; Extended attribute structures +;*********************************** + +ea struc ;AN001; ;extended attr. structure +ea_type db EAISBINARY ;AN001; +ea_flags dw EASYSTEM ;AN001; +ea_rc db ? ;AN001; +ea_namelen db 2 ;AN001; +ea_vallen dw 2 ;AN001; +ea_name db "CP" ;AN001; +ea_value dw ? ;AN001; +ea ends ;AN001; + +qea struc ;AN001; ;query extended attr. name +qea_type db EAISBINARY ;AN001; +qea_flags dw EASYSTEM ;AN001; +qea_namelen db 2 ;AN001; +qea_name db "CP" ;AN001; +qea ends ;AN001; + +;*********************************** +; Code Segment +;*********************************** + +cseg segment para public 'CODE' ;AC000; + assume cs:cseg,ds:cseg,es:cseg,ss:cseg ;as set by DOS loader + + extrn parser:near ;AN000; + extrn sysloadmsg:near ;AN000; + extrn sysdispmsg:near ;AN000; + extrn memory_size:word + extrn fcb:byte + extrn parms:word ;AN000; + extrn parm_area:byte + extrn parm_count:word ;AN000; + extrn current_parm:word ;AN000; + extrn ordinal:word ;AN000; + extrn msgnum_mem:word ;AN000; + extrn msgnum_para:word ;AN000; + extrn msgnum_tenmsg:word ;AN000; + extrn msgnum_baddrv:word ;AN000; + extrn msgnum_bad:word ;AN000; + extrn msgnum_adr:word ;AN000; + extrn msgnum_bdr:word ;AN000; + extrn msgnum_eor:word ;AN000; + extrn msgnum_done:word ;AN000; + extrn msgnum_fnf:word ;AN000; + extrn msgnum_bad_path:word ;AN000; + extrn msgnum_share:word ;AN000; + extrn msgnum_too_many:word ;AN000; + extrn msgnum_prinam:word ;AN000; + extrn msgnum_secnam:word ;AN000; + extrn msgnum_badsiz:word ;AN000; + extrn msgnum_nother:word ;AN000; + extrn msgnum_and_msg:word ;AN000; + extrn msgnum_crlf:word ;AN000; + extrn msgnum_accessdenied:word ;AN000; + extrn msgnum_cp_mismatch:word ;AN000; + extrn msgnum_ok:word ;AN000; + extrn msgnum_exterr:word ;AN000; + extrn msgnum_pparse:word ;AN000; + extrn sublist_6:word ;AN000; + extrn sublist_7:word ;AN000; + extrn sublist_8:word ;AN000; + extrn sublist_11:word ;AN000; + extrn sublist_12:word ;AN000; + extrn sublist_13:word ;AN000; + extrn sublist_19a:word ;AN000; + extrn sublist_19b:word ;AN000; + extrn sublist_21:word ;AN000; + extrn sublist_exterr:word ;AN000; + extrn sublist_24:word ;AN000; + +;*********************************** +; Data area in code segment +;*********************************** + + public path1 ;AN000; + public path2 ;AN000; + public name1 ;AN000; + public name2 ;AN000; + public cur_name ;AN000; + public exitfl ;AN000; + + even ;AN000; ;align stack on word boundary + +stack_area db 512 dup ("S") ;Added in DOS 3.20 to support hardware requiring +End_Stack_Area db 00h ;large stacks. DO NOT PUT DATA ABOVE THIS ! + +clear db 00h ;AN000; ;clear path2 +cur_name dw 00h ;AN000; ;ptr to current filename +input_buf db 130 dup (0) ;AN000; ;input buffer for keyb input +name1 db 130 dup (0) ;AN000; ;source file name +name2 db 130 dup (0) ;AN000; ;target file name +byte1 db 00h ;AN000; ;on compare: bad byte for source +byte2 db 00h ;AN000; ;on compare: bad byte for target +fcb2 db 16 dup (0) ;entered target filespec +;--------KEEP NEXT VARIABLes IN ORIGINAL ORDER------------- +oldp1 db 67 dup (0) ;original path for the first drive 1 KEEP IN ORDER +path1 db 130 dup (0) ;path we'll use for the first drive 2 +infcb db 37 dup (0) ;source fcb 3 +oldp2 db 67 dup (0) ;original path for second drive 4 +path2 db 130 dup (0) ;path we'll use for second drive 5 +outfcb db 37 dup (0) ;target fcb 6 +;--------KEEP ABOVE VARIABLes IN ORIGINAL ORDER------------ +sav db 2 dup (0) +mem db 2 dup (0) ;size of large buffer in bytes +curfcb db 4 dup (0) ;first 2 bytes = addr of fcb for large buffer, + ;last 2 bytes = addr of fcb for small buffer +curpos dw 00h ;current byte offset in large buffer +buf2 dw 00h ;seg address of large buffer +siz dw 512 ;# bytes of data left to compare in large buffer +swt db 00h ;Bit switch: + ; 1 = read file to eof + ; 4 = had compare error + ; 8 = eof mark not found + ; 16 = secondary dir path has been found + ; 32 = primary file opened + ; 64 = secondary file opened + ; 128 = zero suppress switch +swt2 db 00h ;Bit switch: + ; 1 = oldp1 setup + ; 2 = oldp2 setup +offs db 00h,00h,00h,00h ;count of bytes compared +cnt db 00h ;# of bad compares +offp db 8 dup(0) ;AC000; ;offset of mis-compare between bytes +off_byte db 8 dup (0) ;AN000; ;same as offp, but the words are reversed +curdrv db 00h ;actual number of default drive +cdrv db " :" ;ascii letter of default drive +pathchar db "\",00h +tbl db "0123456789ABCDEF" +openpath db 15 dup (0) ;An fcb will be parsed into this path. +cpsw_orig db 00h ;AN000; ;save original cpsw value +exitfl db EXOK ;AN000; ;errorlevel return code +handle dw 00h ;AN000; + +dbcs_off dw 0 ;AN006; +dbcs_seg dw 0 ;AN006; +dbcs_len dw 0 ;AN006; +string_off dw 0 ;AN006; +string_seg dw 0 ;AN006; +dstring db 128 dup(0) ;AN006; + +parm_list label word ;AN001; + dd -1 ;AN001; + dw 1 ;AN001; + db 6 ;AN001; + dw 2 ;AN001; + +querylist label byte ;AN001; ;query general list + dw 1 ;AN001; ;# of entries +querylist_qea qea ;AN001; + +qlist label byte ;AN001; ;general get/set list + dw 1 ;AN001; ;count of attr entries +qlist_ea ea ;AN001; ;return code page in this structure + +;*********************************** +; Code area in code segment +;*********************************** + + +;----------------------------------------------------------------------------- +; INIT - Fill in fill_seg, fill_off in all msg sublists with current seg_id +; and offset. Also calls the system load massage function so it can +; establish addressability to the system messages, and for it to verify +; the DOS version +;----------------------------------------------------------------------------- +init proc near ;AC000; + public init ;AN000; + + mov sp,offset End_Stack_Area ;Big Stack + push ax ;AN000; ;on entry--ax (should) = valid drive parm + call setfill ;AN000; ;init fill_seg, fill_off in sublists + call sysloadmsg ;AN000; ;init sysmsg handler + +; $if c ;AN000; ;if there was a problem + JNC $$IF1 + call sysdispmsg ;AN000; ;let him say why we had a problem + mov exitfl,EXVER ;AN000; ;tell errorlevel bad DOS version +; $else ;AN000; ;since sysdispmsg is happy + JMP SHORT $$EN1 +$$IF1: + call get_dbcs_vector ;AN006; ;get DOS DBCS table vector +;;(deleted for AN009) call init_cp ;AN000; ;get current setting of CHCP + pop ax ;AN000; ;restore valid drive parm + call more_init ;AN000; ;do more init + call main ;AN000; ;do rest of utility as normal +;;(deleted for AN009) call restore_cp ;AN000; ;set CHCP back to normal +; $endif ;AN000; ;ok with sysdispmsg? +$$EN1: + mov al,exitfl ;AN000; ;pass back errorlevel ret code + doscall RET_FN ;AN000; ;return to DOS with ret code + int 20h ;AN000; ;if above not work, + ;AN000; ;take stick and kill it +init endp ;AN000; + + +;------------------------------------------------------------------------------ +; MAIN - Does the compare for two sets of files +;------------------------------------------------------------------------------ +; +main proc near ;AN000; + public main ;AN000; + + mov clear,0 ;clear it +; $do ;AN000; +$$DO4: + cmp byte ptr path1,0 ;was first parm given? +; $leave ne ;AN000; ;Yes, LEAVE INPUT loop + JNE $$EN4 + mov byte ptr path2,0 ;AN000; ;make sure that we get the second file name +rpt: + mov dx,offset msgnum_prinam ;AC000; ;to ask user for first parm + mov parm_count,FIRST_PARM_CT ;AN000; ;THIS IS FIRST PARM (ONLY ONE ACTUALLY) + call getnam ;get first parm from user in path1 and fcb + mov di,offset fcb ;AN000; ;es:di=ptr TO UNOPENED fcb + mov si,offset path1 ;AN000; ;ds:si=ptr TO COMMAND LINE TO PARSE + ;AN000; ;AL-BIT VALUE CONTROLS PARsiNG + doscall PARSE_FILENAME,01H ;AN000; ;AND GO MAKE AN fcb, SCAN OFF LEAdiNG SEPARATORS + cmp AL,255 ;AN000; ;INVALID DRIVE? +; $if e ;AN000; ;Yes + JNE $$IF6 + print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec." + mov byte ptr path1,00 ;AN000; ;BLANK FIRST CHAR. SO TO loop AGAIN +; $endif ;AN000; +$$IF6: +; $enddo ;AC000; ;REPEAT UNTIL FIRST PARM OK + JMP SHORT $$DO4 +$$EN4: + +;chek2: ;GET/SET SECOND FILENAME + cmp clear,1 +; $if e + JNE $$IF9 + mov byte ptr path2,0 + mov clear,0 +; $endif +$$IF9: +; $do ;AN000; +$$DO11: + cmp byte ptr path2,0 ;was second parm given? +; $leave ne ;AN000; ;Yes, LEAVE INPUT loop + JNE $$EN11 + mov dx,offset msgnum_secnam ;AC000; ;to ask for second parm + mov parm_count,TRICK_PARM_CT ;AN000; ;THIS IS FIRST PARM (ONLY ONE ACTUALLY) + ;AN000; ;BUT PUT FILENAME IN path2 INSTEAD OF path1 + call getnam ;get second parm in path2 and fcb2 + mov di,offset fcb2 ;AN000; ;es:di=ptr TO UNOPENED fcb + mov si,offset path2 ;AN000; ;ds:si=ptr TO COMMAND LINE TO PARSE + ;AN000; ;AL-BIT VALUE CONTROLS PARsiNG + doscall PARSE_FILENAME,01H ;AN000; ;AND GO MAKE AN fcb, SCAN OFF LEAdiNG SEPARATORS + cmp AL,255 ;AN000; ;INVALID DRIVE? +; $if e ;AN000; ;Yes + JNE $$IF13 + print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec." + mov byte ptr path2, 00 ;AN000; ;BLANK FIRST CHAR. SO TO loop AGAIN +; $endif ;AN000; +$$IF13: +; $enddo ;AC000; ;SECOND PARM? + JMP SHORT $$DO11 +$$EN11: + mov si,offset path1 ;AN000; ;si = ptr TO PATH NAME TO FIND "\" IN + call findfs ;AN000; ;FIND LAST "\" AND SAVE ADDR + mov si,offset path2 ;AN000; ;si = ptr TO PATH NAME TO FIND "\" IN + call findfs ;AN000; ;FIND LAST "\" AND SAVE ADDR + mov al,curdrv ;get default drive + cmp byte ptr fcb,0 ;source on default? +; $if e ;AC000; ;Yes + JNE $$IF16 + mov fcb,al ;yes, set to actual drive +; $endif ;AC000; +$$IF16: + cmp byte ptr fcb2,0 ;target on default? +; $if e ;AC000; ;Yes + JNE $$IF18 + mov fcb2,al ;yes, set to actual drive +; $endif ;AC000; ;***** FIND PRI FILE +$$IF18: + mov si,offset path1 + mov di,offset fcb + call findpath ;locate primary's specified dir +; $if ne ;AC000; + JE $$IF20 + fill_name1 fcb ;AN000; ;get full path name + mov sublist_12.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Invalid path - %0: + mov dx,offset msgnum_bad_path ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY + ;AN000; ;VALUE IN di,si,dx PAssED TO BADFIL CODE + jmp badfil ;dir not found - tell user +; $endif ;AC000; +$$IF20: + mov dx,offset infcb + doscall SETDTA ;AC000; ;diR FOUND, SET DTA TO SOURCE fcb + mov dx,di ;fcb + doscall SEARCHF ;AC000; SEARCH FIRST SOURCE FILE + or al,al ;find one? +; $if nz ;AC000; ;Yes + JZ $$IF22 + fill_name1 fcb ;AN000; ;get full path name + mov sublist_11.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "File not found - %0" + mov dx,offset msgnum_fnf ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY + ;AN000; ;VALUE IN di,si,dx PAssED TO BADFIL CODE + jmp badfil +; $endif ;AC000; +$$IF22: +f1ok: ;OPEN, PRIME PRIMARY FILE + and swt,09Fh ;clear file open flags + mov dx,offset infcb + doscall FCBOPEN ;AC000; OPEN SOURCE FILE + or al,al ;Error ? + + ;Try to open the same file using a handle open with read access +; $if nz ;AC000; ;IF fcb OPEN FAILED, THEN SHARING ERROR + JZ $$IF24 + jmp shrerr +; $endif ;AC000; +$$IF24: + mov si,offset infcb ;Take this fcb... + mov di,offset OpenPath ; and in this area... + call MakePathFromfcb ; make an ASCIIZ path. + mov dx,offset OpenPath + doscall HANDLEOPEN,READONLYACCESS ;AC000; TRY TO OPEN IT WITH READONLY ACCEss +; $if c ;AC000; + JNC $$IF26 + jmp accessdenied1 ;ERROR OPENING FILE. AssUME ACCEss DENIED. +; $endif ;AC000; +$$IF26: + mov bx,ax ;Put the handle in bx... + doscall HANDLECLOSE ;AC000; AND CLOSE IT + cmp byte ptr path1,0 ;using current dir? +; $if ne ;AC000; ;NO + JE $$IF28 + mov dx,offset oldp1 + doscall CHDIR ;AN000; change directory +; $endif ;AC000; +$$IF28: +;p1ok: + mov word ptr infcb+14,1 ;set record size + xor ax,ax + mov di,offset infcb+33 + stosw ;set rr fields + stosw + Mov dx,offset infcb + call get ;and prime big buffer from first file + print_msg msgnum_crlf,STDOUT ;AN000; ;dispLAY CRLF + print_msg msgnum_crlf,STDOUT ;AN000; ;dispLAY CRLF + fill_name1 infcb ;AN000; ;get full path name + mov sublist_19a.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist FOR "%1 AND %2" MSG + mov al,fcb2 ;target drive + mov outfcb,al ;to target fcb + + ;****** FIND SECONDARY diR + mov si,offset path2 + test byte ptr swt,16 ;has secondary path already been found? +; $if z ;AC000; ;NO + JNZ $$IF30 + mov di,offset fcb2 + call findpath ;no, find its path now +; $else ;AC000; ;siNCE SECONDARY PATH ALREADY BEEN FOUND + JMP SHORT $$EN30 +$$IF30: + cmp byte ptr [si],0 ;is there a path? +; $if ne ;AC000; ;Yes + JE $$IF32 + ; BUT IF NOT, WILL USE CURRENT DIR + mov dx,si + doscall CHDIR ;AC000; ;yes, set the secondary dir to proper node + + cmp al,al ;force eq +; $endif ;AC000; +$$IF32: +; $endif ;AC000; +$$EN30: + pushf ;save status of secondary dir search + mov cx,11 + mov di,offset outfcb+1 ;target filename field + mov si,offset fcb2+1 ;current target filename + mov bx,offset infcb+1 ;current source filename +; $do ;AC000; +$$DO35: + lodsb ;get target name char + cmp al,"?" ;is it ambiguous? +; $if E ;AC000; ;Yes + JNE $$IF36 + mov al,[bx] ;yes, copy char from source +; $endif ;AC000; +$$IF36: + stosb ;build target name + inc bx ;next source char +; $enddo loop ;AC000; + LOOP $$DO35 + fill_name2 ;AN000; ;get full path name + mov sublist_19b.sub_value,offset name2 ;AN000; ;SET UP %2 IN sublist FOR "%1 AND %2" MSG + print_msg msgnum_and_msg,STDOUT ;AN000; ;dispLAY " AND " + print_msg msgnum_crlf,STDOUT ;AN000; ;dispLAY CRLF + popf ;return from getting secondary dir +; $if ne ;AC000; ;diD NOT GET IT + JE $$IF39 + fill_name2 ;AN000; ;get full path name + mov sublist_12.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist FOR "%1 - INVALID PATH" ;AN000; + print_msg msgnum_bad_path,STDERR ;AN000; ;"Invalid path - %0" + mov dx,offset oldp2 ;Get back to current dir on sec drive + doscall CHDIR ;AC000; + jmp quit5 + +; $endif ;AC000; +$$IF39: + mov dx,offset outfcb + doscall SETDTA ;AC000; diR FOUND, SET DTA TO TARGET fcb + mov dx,offset outfcb + doscall SEARCHF ;AC000; FIND FIRST TARGET FILE + or al,al ;Find one? +; $if NZ ;AC000; ;Yes + JZ $$IF41 + print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF + fill_name2 ;AN000; ;get full path name + mov sublist_11.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF MSG + print_msg msgnum_fnf,STDERR ;AN000; ;"File not found - %0" + mov dx,offset oldp2 ;Get back to current dir on sec drive + doscall CHDIR ;AC000; + jmp quit3 ;and get the next source file + +; $endif ;AC000; +$$IF41: + mov dx,offset outfcb + doscall FCBOPEN ;AC000; OPEN TARGET FILE + or al,al ;Was the fcb open ok? + + jnz ShrViolation ;If fcb open failed, then SHARING ERROR + mov si,offset outfcb ;Take this fcb... + mov di,offset OpenPath ; and in this area... + call MakePathFromfcb ; make an ASCIIZ path. + mov dx,offset OpenPath + doscall HANDLEOPEN,READONLYACCESS ;AC000; TRY TO OPEN IT WITH READONLY ACCEss + jc accessdenied2 + mov bx,ax ;Put the handle in bx... + doscall HANDLECLOSE ;AC000; AND CLOSE IT. + call RestoreDir + jmp filopn ;If successful then continue +accessdenied2: ;Oops, there was an error. AssUME it was Access Denied + call RestoreDir + print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF + fill_name2 ;AN000; ;get full path name + mov sublist_21.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF "Access Denied - %0" + mov dx,offset oldp2 ;Get back to current dir on sec drive + doscall CHDIR ;AC000; + print_msg msgnum_accessdenied,STDERR ;AN000; ;"Access Denied - %0" + jmp quit3 ;and get the next source file + +ShrViolation: + call RestoreDir + print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF + fill_name2 ;AN000; ;get full path name + mov sublist_13.sub_value,offset name2 ;AN000; ;SET UP %1 IN sublist OF "Sharing violation - %0" + mov dx,offset oldp2 ;Get back to current dir on sec drive + doscall CHDIR ;AC000; + print_msg msgnum_share,STDERR ;AN000; ;"Sharing violation - %0" + jmp quit3 ;and get the next source file +filopn: + mov word ptr outfcb+14,1 ;record size + xor ax,ax + mov di,offset outfcb+33 + stosw + stosw + mov ax,word ptr infcb+16 ;low part of file size + mov dx,word ptr infcb+18 ;high part + cmp ax,word ptr outfcb+16 ;are files the same size? + jne invsiz ;no, error + cmp dx,word ptr outfcb+18 + je sizok ;yes, ok +invsiz: + print_msg msgnum_badsiz,STDOUT ;AN000; ;"Files are different sizes" + jmp quit3 ;tell user sizes are different and process next source file +sizok: +;;(deleted for AN009) call comp_codepage ;AN000; ;VERIFY BOTH FILes HAVE THE SAME CODEPAGE +;;(deleted for AN009) $if c ;AN000; ;ERROR WITH CODEPAGE +;;(deleted for AN009) jmp quit3 ;AN000; ;go on to other files if any +;;(deleted for AN009) $endif ;AN000; + mov dx,offset infcb + mov word ptr curfcb,dx ;get fcb's in proper order + mov dx,offset outfcb + mov word ptr curfcb+2,dx + mov word ptr offs,0 ;set constants + mov word ptr offs+2,0 + mov byte ptr cnt,0 ;and fall through to process +process: ;**** PREPARE TO COMPARE DATA + mov dx,word ptr curfcb+2 ;small buffer's file + cmp word ptr siz,0 ;any data left in large buffer? + jne getsec ;yes, use it + test byte ptr swt,1 ;no, have we reached eof yet? + jz large ;no - fill large buffer from other file + doscall FCBCLOSE ;AC000; CLOSE THE FILE FILLING SMALL BUFFER + test byte ptr swt,8 ;yes, files are done - did we find eof mark? +; $if z ;AC000; ;NO + JNZ $$IF43 + print_msg msgnum_eor,STDOUT ;AN000; ;"Eof mark not found" +; $endif ;AC000; +$$IF43: + test byte ptr swt,4 ;any compare errors? +; $if Z ;AC000; + JNZ $$IF45 + print_msg msgnum_ok,STDOUT ;AN000; ;"FILes COMPARE OK" +; $endif ;AC000; +$$IF45: + jmp quit3 ;had compare errors - no "ok" msg + +large: ;Fill large buffer + xchg dx,word ptr curfcb ;AC000; ;switch fcbs' association with buffers + xchg dx,word ptr curfcb+2 + call get ;fill large buffer from currently mounted file + jmp process ;and now fill small buffer from other file +getsec: + call getf2 ;fill small buffer with 1024 bytes + sub siz,cx ;# bytes left in big buffer after this compare + mov bp,cx ;save # bytes of compare + les di,dword ptr curpos ;current byte in large buffer + mov si,offset buf ;current byte in small buffer +comp: + jcxz compok ;all done and equal + repe cmpsb + jne cmp1 ;bytes don't match +compok: + push ds + pop es ;get es back + mov curpos,di ;next byte to compare in large buffer + mov ax,word ptr offs+2 ;low part of bytes compared so far + add ax,bp ;increment count of bytes compared + adc word ptr offs,0 ;adjust high part + mov word ptr offs+2,ax ;save low part + jmp process ;and keep going +cmp1: ;***** FOUND UNEQUAL BYTes + or byte ptr swt,4 ;indicate had compare error + dec si ;point to the bad bytes + dec di + mov al,[si] ;bad byte from small buffer + mov ah,es:[di] ;bad byte from large buffer + mov dx,offset infcb ;AC000; ;FIND OUT WHICH byte CAME FROM WHICH FILE + ;AN000; ;SO THAT "File 1 = %1" AND "File 2 = %1" + ;AN000; ;MEssAGes WILL BE CORRECT. + cmp word ptr curfcb+2,dx ;is first file in small buffer? +; $if ne ;AC000; ;NO + JE $$IF47 + xchg ah,al ;no, reverse the bad bytes +; $endif ;AC000; +$$IF47: + mov byte1,al ;AN000; ;SAVE FIRST FILE BAD byte + mov byte2,ah ;AN000; ;SAVE SECOND FILE BAD byte + ;AN000; ;COMPUTE offset IN FILE OF BAD BYTes + mov bx,word ptr offs ;high part of byte count + mov ax,si ;addr of the bad byte in small buffer + sub ax,offset buf ;bad byte's offset in this buffer + add ax,word ptr offs+2 ;offset into file + adc bx,0 ;adjust high part if needed + mov word ptr offp,bx ;AC000; ;SAVE HIGH PART OF offset + mov word ptr off_byte+2,bx ;AN000; ;SAVE HIGH PART OF offset + mov word ptr offp+2,ax ;AN000; ;SAVE LOW PART OF offset + mov word ptr off_byte,ax ;AN000; ;SAVE LOW PART OF offset + inc si ;back to correct position + inc di + push cx ;save remaining byte count + push si ;save next data byte addr + +mdone: + mov sublist_6.sub_value,offset OFF_byte ;AN000; ;sublist OF MSG DesC + print_msg msgnum_bad,STDOUT ;AN000; ;"Compare error at offset %1" + mov sublist_7.sub_value,offset byte1 ;AN000; ;sublist OF MSG DesC. (ptr TO BAD byte IN FIRST FILE) + print_msg msgnum_adr,STDOUT ;AN000; ;"File 1 = %1" + mov sublist_8.sub_value,offset byte2 ;AN000; ;sublist OF MSG DesC. (ptr TO BAD byte IN SECOND FILE) + print_msg msgnum_bdr,STDOUT ;AN000; ;"File 2 = %1" + pop si ;get regs back + pop cx + inc byte ptr cnt ;count errors + cmp byte ptr cnt,10 ;10 errors yet? + je gotten ;yes, further compare is useless + jmp comp ;no, go on with following byte +gotten: + push ds + pop es ;get es back + print_msg msgnum_tenmsg,STDOUT ;AN000; ;"10 Mismatches - ending compare" + +quit3: ;terminate + mov byte ptr swt,16 ;say we've found the secondary dir + cmp byte ptr path1,0 ;is primary file in the drive's current dir? +; $if ne ;AN000; NO + JE $$IF49 + mov dx,offset path1 ;no, + doscall CHDIR ;AC000; +; $endif ;AC000; +$$IF49: + mov dx,offset infcb + doscall SETDTA ;AC000; ;DTA = SOURCE fcb + mov dx,offset fcb + doscall SEARCHN ;AC000; ;12H FIND NEXT SOURCE FILE + or al,al ;find one? + jnz quit4 ;no + jmp f1ok ;yes, go process it +AccessDenied1: ;Oops, there was an error. AssUME it was Access Denied + fill_name1 INfcb ;AN000; ;get full path name + mov sublist_21.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Access Denied - %0" + mov dx,offset msgnum_accessdenied ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY + ;AN000; ;VALUES IN dx,si,di PAssED TO BADFIL CODE + jmp short badfil + +ShrErr: + fill_name1 INfcb ;AN000; ;get full path name + mov sublist_13.sub_value,offset name1 ;AN000; ;SET UP %1 IN sublist OF "Sharing violation - %0" + mov dx,offset msgnum_SHARE ;AC000; ;dx = ptr TO MSG DesCRIPTOR TO dispLAY + ;AN000; ;VALUes IN dx,si,di PAssED TO BADFIL CODE +badfil: ;assume si = path, di = fcb , dx = MSG DesCRIPTOR + push dx + push cx + print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF + print_msg msgnum_crlf,STDERR ;AN000; ;dispLAY CRLF + pop cx + pop dx +; DISPLAY MSG THAT WAS POINTED TO BY DX + push ax + push di ;AN003; + mov di,dx ;AN003; + mov [di].msg_handle,STDERR ;AN003; + pop di ;AN003; + call sendmsg ;AC000; ;dispLAY IT + pop ax ;AN000; +quit4: ;no more primary files +;;;;;; cmp byte ptr path1,0 ;current dir on pri drive? +;;;;;; je quit5 ;yes + mov dx,offset oldp1 + doscall CHDIR ;AC000; ;no, restore it now +quit5: + mov byte ptr path2,0 ;force get of second name - leave this here + mov byte ptr swt,0 +; $do ;AC000; ;REPEAT UNTIL A VALID Y/N REspONSE +$$DO51: + mov dx,offset msgnum_nother ;AN000; ;dispLAY (Y/N) MEssAGE + push di ;AN007; save DI + mov di,dx ;AN007; DI -> message struct + mov [di].msg_handle,STDERR ;AN007; display to STDERR + pop di ;AN007; restore DI + call sendmsg ;AC000; ;dispLAY IT + push ax ;SAVE REspONSE + print_msg msgnum_crlf,STDERR ;AC003; ;dispLAY CRLF + print_msg msgnum_crlf,STDOUT ;AC009; ;dispLAY CRLF + pop dx ;AN000; ;GET REspONSE BACK + doscall GET_EXT_CNTRY_INFO,YESNO_CHECK ;AC000; ;CHECK REspONSE, dx=REspONSE + cmp al,YES ;AN000; ;Yes REspONSE +; $leave e ;AN000; ;LEAVE loop + JE $$EN51 + cmp al,0 ;AN000; ;NO REspONSE +; $leave e + JE $$EN51 +; $enddo ;AN000; ;REPEAT UNTIL A VALID Y/N REspONSE + JMP SHORT $$DO51 +$$EN51: + cmp al,YES ;AC000; ;ax=0=NO, ax=1=Yes (CHECK REspONSE) +; $if e ;AC000; ;GOT A Yes REspONSE, REPEAT COMP + JNE $$IF55 + xor ax,ax ;AN008; ;AN000; ;CHAR TO USE TO CLEAR BUFFER + mov di,offset path1 ;AN000; ;CLEAR OLD PATH, FILE NAMes TO START AGAIN + mov cx,129 ;AN000; ;LENGTH OF BUFFER +; $do ;AN000; +$$DO56: + stosb ;AN000; +; $enddo loop ;AN000; + LOOP $$DO56 + mov di,offset path2 ;AN000; ;CLEAR OLD PATH, FILE NAMes TO START AGAIN + mov cx,129 ;AN000; ;LENGTH OF BUFFER +; $do ;AN000; +$$DO58: + stosb ;AN000; +; $enddo loop ;AN000; + LOOP $$DO58 + mov clear,1 ;set clear + jmp rpt ;AC000; ;REPEAT COMP +; $endif ;AC000; +$$IF55: + ret ;AN000; ;QUIT + + +;-------------------------------------------- +; CONTROL BREAK EXIT CODE (INTERRUPT HANDLER) +;-------------------------------------------- +CBExit: + test swt2,2 ;oldp2 set? +; $if nz ;AC000; ;no, restore it now + JZ $$IF61 + mov dx,offset oldp2 + doscall CHDIR ;AC000; ;no, restore it now +; $endif ;AC000; +$$IF61: + + test swt2,1 ;oldp1 set? +; $if nz ;AC000; ;if it was + JZ $$IF63 + mov dx,offset oldp1 + doscall CHDIR ;AC000; ;no, restore it now +; $endif ;AC000; +$$IF63: + +;;(deleted for AN009) call restore_cp ;AN000; ;restore the codepage + mov al,EXCB ;AN000; ;errorlevel: control break exit + doscall RET_FN ;AN000; ;return to DOS with ret code + + int 20h ;AC000; ;if exit didn't work, kill it +main endp ;AN000; + +;------------------------------------------------------------------------------ +; -----------------------------SUBROUTINES---------------------------------- +;------------------------------------------------------------------------------ + + +;------------------------------------------------------------------------------ +; FINDFS - Finds the last "\" in the path name given. This is done so that the +; path and not the filename can be derived from the path name. +; +; INPUT - SI = ptr to path name to work on +; OUTPUT - saves address of last "\" at end of buffer that SI points to. +; (this is tricky) +;------------------------------------------------------------------------------ +findfs proc near ;AN000; + mov string_off,si ;AN006; save addr of string for Check_DBCS_slash + mov string_seg,cs ;AN006; + push dx ;AN000; + push si ;AN000; + xor dx,dx ;AN008; ;AN000; ;CLEAR dx IN THE CASE THAT NO "\" IS FOUND +; $do ;AN000; +$$DO65: + lodsb ;AN000; ;GET A CHARACTER + cmp al,0 ;AN000; ;AT END OF STRING YET ? +; $leave z ;AN000; ;Yes, LEAVE + JZ $$EN65 + push si ;AN006; Check the character in AL == '\' + dec si ;AN006; and the character in front of + call Check_DBCS_slash ;AN006; the '\' is not DBCS. + pop si ;AN006; + +; $if z ;AN000; ;Yes, SAVE ADDR OF IT IN dx + JNZ $$IF67 + mov dx,si ;AN000; + dec dx ;AN000; +; $endif ;AN000; +$$IF67: +; $enddo ;AN000; + JMP SHORT $$DO65 +$$EN65: + pop si ;AN000; + mov [si+128],dx ;AN000; ;SAVE ADDR OF LAST "\" IN THE LAST TWO BYTes OF PATH + pop dx ;AN000; + ret ;AN000; +findfs endp ;AN000; + + +;------------------------------------------------------------------------------ +; GETNAM - Inputs a filename from STDIN to be used as either the first or second +; parameter for COMP. +; +; INPUT - PARM_COUNT = ordinal number for parser +; DX = ptr to msg descriptor of message to display +; BX = ptr to FCB of file +; SI = ptr to FCB structure +;------------------------------------------------------------------------------ +getnam proc near + mov input_buf,INPUT_LEN ;AN000; ;PUT LENGTH OF BUFFER AS FIRST byte OF BUFFER + mov di,dx ;AN000; ;FILL IN offset OF INPUT BUFFER IN MSG DesC. + mov [di].msg_input, offset input_buf ;AN000; ;ptr TO INPUT BUFFER + mov [di].msg_handle, STDERR + push ax ;AN000; + call sendmsg ;AC000; ;dispLAY MEssAGE, GET BUFFERED INPUT + pop ax ;AN000; + xor ch,ch ;AN000; ;CLEAR HIGH byte OF cx + mov cl,input_len ;AN000; ;CL = LENGTH OF INPUT BUFFER + ;get offset into input buffer (to skip length word) + mov current_parm,offset INPUT_BUF+2 ;AN000; ;CURRENT_PARM = offset OF INPUT BUFFER + mov ordinal,ZERO_PARM_CT ;AN000; ;TELL PARSER THAT THIS IS FIRST PARAMETER (ONLY ONE) + call parser ;PUT NEW STRING AT WHERE di POINTS TO + ret ;then go back +getnam endp ;AC000; + + +;------------------------------------------------------------------------------ +; FINDPATH - Check if path is a directory. If yes, then CHDIR to it and set the +; FCB to ????????.???. If no, check for "\". If no "\", then assume +; we are in the correct directory and set FCB to ????????.??? if blank. +; If "\" is found, then strip last name off path into FCBYTE (?'s if +; nothing follows "\") and try to find the directory again. +; +; INPUT - SI = ptr to path string +; DI = ptr to FCB (drive byte is valid) +; OUTPUT - if path found then set ZERO flag and CHDIR to directory and FCB set. +; else FCB set and reset ZERO flag. +;------------------------------------------------------------------------------ +findpath proc near + mov dl,[di] ;drive number from fcb + push di + push si + mov di,si + sub di,67 ;where to put current dir for the drive + mov al,dl ;AN005; ;get drive number + add al,64 ;AN005; ;convert to ascii letter + stosb ;AN005; + mov al,':' ;AN005; + stosb ;AN005; + mov al,pathchar ;get path separator + stosb ;and put in beginning of path + mov si,di + doscall CURDIR ;AC000; ;GET DRIVE'S CURRENT diR + cmp di,offset oldp1+3 ;See if pri cur dir is set up +; $if e ;AC000; + JNE $$IF70 + or swt2,1 +; $endif ;AC000; +$$IF70: + cmp di,offset oldp2+3 ;See if sec cur dir is set up +; $if e ;AC000; + JNE $$IF72 + or swt2,2 +; $endif ;AC000; +$$IF72: + pop si ;path string + pop di ;fcb + cmp byte ptr [si],0 ;is there a path? + jne fp3 ;yes +fp0: + cmp byte ptr [di+1]," " ;no, is there a name in the fcb? + jne fp2 ;yes, use current dir +fp1: + call setq ;no, set it to ????????.??? +fp2: + cmp al,al ;force eq on return + ret +fp3: ;there's a path + mov dx,si ;path + doscall CHDIR ;AC000; ;see if it's a dir + jnc fp1 ;yes, set fcb to ?'s - path found and set + mov bx,[si+128] ;no - get last \ in string + or bx,bx ;is there a \? + jnz fp4 ;yes, go strip off last name + mov byte ptr [si],0 ;no, there's only 1 name in path - must be filename + jmp short fp0 ;go use current dir +fp4: + call backoff ;strip last name off line into fcb + mov dx,si + doscall CHDIR ;AC000; ;noword ptr is result line a valid path? + jnc fp2 ;yes, fcb and path are set +fp5: + cmp ax,1234h ;no, pass back error - path has first part of name, + ret ;remainder is in fcb +findpath endp ;AN000; + + +;------------------------------------------------------------------------------ +; BACKOFF - Removes the last name of a path and puts it into an FCB. Assumes at +; least one "\" in path. If no name is found then set the FCB to +; ????????.??? and +; +; INPUT - SI = ptr to path string. +; DI = ptr to FCB to format. +; OUTPUT - +;------------------------------------------------------------------------------ +backoff proc near + push si + mov bx,[si+128] ;address of last \ in path + cmp byte ptr [si+1],":" ;AN002; +; $if e ;AN002; + JNE $$IF74 + add si,2 ;char following d: in path name +; $endif ;AN002; +$$IF74: + cmp si,bx ;is it the only \ and is it at beg of line? + mov si,bx +; $if e ;AC000; ;Yes + JNE $$IF76 + inc bx ;yes, going to root - leave \ alone +; $endif ;AC000; +$$IF76: + inc si ;char following \ + cmp byte ptr [si],0 ;are there any? + jne bo4 ;yes + call setq ;no, use ????????.??? in root + jmp short bo3 ;AC008; +bo4: + push di + ;AC000; ;ds:si=POINTER TO COMMAND LINE TO PARSE + ;AC000; ;es:di=POINTER TO UNOPENED fcb + ;AC000; ;AL-BIT VALUE CONTROLS PARsiNG + doscall PARSE_FILENAME,02h ;AC000; ;PARSE LAST NAME ON LINE INTO fcb, LEAVE DRIVE byte ALONE + pop di + cmp byte ptr [di+1]," " ;is there a file name? +; $if ne ;AC000; ;Yes, TRUNCATE PATH AND LEAVE + JE $$IF78 +bo3: + mov byte ptr [bx],0 ;truncate the path name + pop si +; $else ;AC000; ;siNCE NO FILE NAME, + JMP SHORT $$EN78 +$$IF78: + pop si ;no, restore si + pop ax ;strip return to findpath + call setq ;fill fcb with ?'s + cmp ax,1234h ;AN000; ;SET ERROR retURN +; $endif ;AC000; +$$EN78: + ret +backoff endp ;AN000; + + +;------------------------------------------------------------------------------ +; SETQ - Set an FCB filename field to ????????.??? +; +; INPUT - DI = ptr to FCB +; OUTPUT - FCB is changed. +;------------------------------------------------------------------------------ +setq proc near + ;di = ^ fcb + push di + mov al,"?" + mov cx,11 + inc di ;point to filename +; $do ;AC000; +$$DO81: + stosb +; $enddo loop ;AC000; + LOOP $$DO81 + pop di + ret +setq endp ;AC000; + + +;------------------------------------------------------------------------------ +; GET - Fill large buffer +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +get proc near + push dx ;save fcb address + mov ds,buf2 ;point to large buffer + xor dx,dx + doscall SETDTA ;AC000; ;SET DTA TO LARGE BUFFER + push cs + pop ds ;get ds back + pop dx ;and get fcb addr back + mov cx,word ptr mem ;# bytes of avail mem in large buffer + doscall FCBRNDBLKREAD ;AC000; ;FILL LARGE BUFFER + mov siz,cx ;# bytes we read + mov word ptr curpos,0 ;current byte position offset in large buffer + or al,al ;get eof? +; $if nz ;AC000; ;Yes, AT EOF + JZ $$IF83 + call fileend ;AC000; +; $endif ;AC000; +$$IF83: + ret ;No, keep on going +get endp ;AC000; + + +;------------------------------------------------------------------------------ +; FILEEND - Check for EOF char on last read into large buffer (?) +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +fileend proc near + or byte ptr swt,1 ;yes, flag it + mov bx,cx ;# bytes just read + mov ds,buf2 + cmp byte ptr [bx-1],26 ;is the last char of file an eof? + push cs + pop ds +; $if e ;AC000; ;Yes + JNE $$IF85 + or byte ptr swt,8 ;yes, say we found the eof +; $endif ;AC000; +$$IF85: + doscall FCBCLOSE ;AC000; ;Close the file filling large buffer + ret +fileend endp ;AN000; + + +;------------------------------------------------------------------------------ +; GETF2 - Read 8 sectors from file that FCB points to. +; +; INPUT - DX = ptr to FCB +; OUTPUT - fills small buffer +;------------------------------------------------------------------------------ +getf2 proc near + ;fill small buffer from fcb at [dx] + push dx + mov dx,offset buf ;small buffer addr + doscall SETDTA ;AC000; ;SET THE DTA + pop dx + mov cx,4096 ;ask for 8 sectors + doscall FCBRNDBLKREAD ;AC000; ;GET THE DATA + ret +getf2 endp ;AN000; + + +;------------------------------------------------------------------------------ +; FILL_N - This routine fills the buffer NAME1 or NAME2 with the full path name +; of the corresponding file. +; +; INPUT - DX = ptr to buffer to put full path name in +; DI = ptr to FCB to get drive letter,filename,extension from +; SI = ptr to PATH1 or PATH2 depending on whether first or second file +; OUTPUT - +;------------------------------------------------------------------------------ +fill_n proc near + push ax ;AN000; + push cx ;AN000; + mov string_off,dx ;AN006; pass whole string to Check_DBCS_slash + mov string_seg,cs ;AN006; +;get drive letter & colon ;AN000; + xchg dx,si ;AN000; ;make dx=fcb ptr, si=buffer ptr + mov al,[di] ;AN000; ;drive byte from fcb + inc di ;AN000; ;point to filename + add al,64 ;AN000; ;drive to ascii + mov [si],al ;AN000; ;save letter in string + inc si ;AN000; ;increment ptr + mov byte ptr [si],":" ;AN000; ;add colon to drive letter + inc si ;AN000; + xchg dx,si ;AN000; +;get full path ;AN000; + xchg dx,di ;AN000; + cmp byte ptr [si],0 ;AN000; ;is there a path? +; $if ne ;AN000; ;Yes + JE $$IF87 + cmp byte ptr [si+1],':' ;is thera a drive letter ? +; $if e + JNE $$IF88 + add si,2 ;AN000; ;yes, skip drive id in path +; $endif +$$IF88: +; $do ;AC000; +$$DO90: + lodsb ;AN000; ;get a path char + or al,al ;AN000; ;end of path? +; $leave Z ;AN000; ;Yes + JZ $$EN90 + stosb ;AN000; ;copy character +; $enddo ;AC000; + JMP SHORT $$DO90 +$$EN90: + push si ;AN006; Check the character in AL == '\' + mov si,di ;AN006; and the character in front of + dec si ;AN006; the '\' is not DBCS. + call Check_DBCS_slash ;AN006; + pop si ;AN006; + +; $if NE ;AC000; ;NO + JE $$IF93 + mov al,"\" ;AC000; ;no, display separator ahead of filename + stosb ;AN000; +; $endif ;AC000; +$$IF93: +; $endif ;AC000; +$$IF87: +;get filename ;AN000; + xchg dx,si ;AC000; ;dx=path1 or path2, si=ptr buffer, di=ptr fcb + mov cx,8 ;AN000; +; $do ;AC000; +$$DO96: + lodsb ;AC000; ;display filename + cmp al," " ;AC000; ;Is it end of filename +; $leave e ;AC000; ;Yes, GET EXTENsiON + JE $$EN96 + stosb ;AN000; +; $enddo loop ;AC000; ;GET MORE CHARS, IF ANY + LOOP $$DO96 +$$EN96: + and cx,cx ;AC008; +; $if ne + JE $$IF99 + dec cx ;AC000; ;# of spaces left to skip in filename +; $do ;AC000; ;step thru spaces to get to file extension +$$DO100: + inc si ;AN000; +; $enddo loop ;AC000; ;until cx=0 + LOOP $$DO100 +; $endif +$$IF99: +;get filename extension ;AN000; + cmp byte ptr [si]," " ;AC000; ;is there an extension? +; $if ne ;AC000; ;Yes, DO PERIOD + JE $$IF103 + mov al,"." ;AN000; + stosb ;AN000; + mov cx,3 ;AN000; +; $do ;AC000; +$$DO104: + lodsb ;AC000; ;display extension + cmp al," " ;AC000; ;is it end of extension? +; $leave e ;AC000; ;Yes + JE $$EN104 + stosb ;AN000; +; $enddo loop ;AC000; + LOOP $$DO104 +$$EN104: +; $endif ;AC000; ;EXTENsiON? +$$IF103: + mov al,0 ;AN000; + stosb ;AC000; ;end of string marker + xchg dx,si ;AN000; + xchg dx,di ;AN000; + pop cx ;AN000; + pop ax ;AN000; + ret +fill_n endp ;AN000; + + +;------------------------------------------------------------------------------ +; MAKEPATHFROMFCB - Creates an ASCIIZ path at DI from the FCB pointed to by SI. +; +; INPUT - SI = ptr to FCB +; DI = buffer for path name to be stored. +; OUTPUT - +;------------------------------------------------------------------------------ +MakePathFromFcb proc near + push si ;Save fcb address + mov al,byte ptr [si] ;Get drive letter from fcb (0=A,1=B,...) + add al,64 ;Convert it to ASCII + stosb ;Store it in the PATH + mov al,":" ;Put a drive separator + stosb ; in the PATH. + inc si + mov cx,8 ;Copy [1..8] bytes + ; GET FILENAME +; $do ;AC000; +$$DO108: + movsb ;Move the char from the fcb + cmp byte ptr [si]," " ;Is the next char a blank ? +; $leave e ;AC000; ;Yes, NO MORE CHARS IN FILENAME + JE $$EN108 +; $enddo loop ;AC000; ;NO, GET NEXT CHAR, IF ANY + LOOP $$DO108 +$$EN108: + ; InsertPeriod + mov byte ptr [di],"." ;Stick a period in there... + inc di ; and increment the pointer + mov cx,3 ;Copy [0..3] bytes... + pop si ; from the fcb's + add si,9 ; extension area +; $do ;AC000; +$$DO111: + cmp byte ptr [si]," " ;Is the next char a blank? +; $leave e ;AC000; ;Yes, THEN WE ARE DONE + JE $$EN111 + movsb ; No, move it +; $enddo loop ;AC000; ;AND GET THE NEXT ONE, IF ANY + LOOP $$DO111 +$$EN111: + mov al,00 + stosb ;Copy in a byte of Hex 0 + ret +MakePathFromFcb endp + + +;------------------------------------------------------------------------------ +; RESTOREDIR - Do a CHDIR to the original directory this program started in. +; +; INPUT - OLDP2 = path string of original directory (for target filespec) +; PATH2 = path string of target filespec. +; OUTPUT - changes the current directory +;------------------------------------------------------------------------------ +RestoreDir proc near + cmp byte ptr path2,0 ;working with current dir on secondary file? +; $if ne ;AC000; ;NO, + JE $$IF114 + push ax ;restore old current directory + mov dx,offset oldp2 + doscall CHDIR ;AC000; + pop ax +; $endif ;AC000; +$$IF114: + ret +RestoreDir endp ;AN000; + + +;------------------------------------------------------------------------------ +; INIT_CP - To permit "COMP" to open the first and second files regardless of +; the system codepage, and to avoid any codepage mismatch critical +; error from occurring from the open, we temporarily suspend codepage +; support. It will be restored at the end of COMP. +; +; INPUT - +; OUTPUT - CPSW_ORIG byte will have the CPSW bit set on if cpsw = on +;------------------------------------------------------------------------------ +init_cp proc near ;AN000; + public init_cp ;AN000; + + doscall CPSW_CHECK,GET_CPSW_STATE ;AN000; ;IS CODEPAGE SUPPORT LOADED + and dl,dl ;AC008; ;AN000; +; $if ne ;AN000; ;IF CPSW IS LOADED + JE $$IF116 + or cpsw_orig,CPSW ;AN000; ;SET FLAG TO INdiCATE CPSW=ON + mov dl,CPSW_OFF ;AN000; ; TO CPSW=OFF + doscall CPSW_CHECK,SET_CPSW_STATE ;AN000; ;SET CPSW=OFF +; $endif ;AN000; ;CPSW LOADED? +$$IF116: + ret ;AN000; ;retURN TO callER +init_cp endp ;AN000; + + +;------------------------------------------------------------------------------ +; RESTORE_CP - Restore chcp status (codepage support to original values) +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +restore_cp proc near ;AN000; + public restore_cp ;AN000; + + test cpsw_orig,CPSW ;AN000; ;WAS CPSW ON WHEN WE STARTED? +; $if nz ;AN000; ;IF CPSW WAS ON + JZ $$IF118 + mov dl,CPSW_ON ;AN000; ; TO CPSW=ON + doscall CPSW_CHECK,SET_CPSW_STATE ;AN000; ;SET CPSW=ON +; $endif ;AN000; ;CPSW WAS ON? +$$IF118: + ret ;AN000; ;retURN TO callER +restore_cp endp ;AN000; + + +;------------------------------------------------------------------------------ +; COMP_CODEPAGE - If chcp=on, verify that the codepage of the two files agree. +; +; INPUT - PATH1 has the asciiz of the first path\filename +; PATH2 has the asciiz of the second path\filename +; OUTPUT - +;------------------------------------------------------------------------------ +comp_codepage proc near ;AN000; + public comp_codepage ;AN000; + + test cpsw_orig,CPSW ;AN000; ;WAS CPSW=ON WHEN WE STARTED? +; $if nz ;AN000; ;IF CPSW IS LOADED + JZ $$IF120 + fill_name1 infcb ;AN000; ;get full path name + mov cur_name,offset name1 ;AN000; ;PAss INPUTED FILENAME OF FIRST FILE + call getcp ;AN000; ;GET CODEPAGE OF FIRST FILE + mov ax,qlist_ea.ea_value ;AC001; ;SAVE ITS CODEPAGE + push ax ;AN000; ;ON THE STACK + fill_name2 ;AN000; ;get full path name + mov cur_name,offset name2 ;AN000; ;PAss INPUTED FILENAME OF SECOND FILE + call getcp ;AN000; ;GET CODEPAGE OF SECOND FILE + pop ax ;AN000; ;GET FIRST FILE CODEPAGE + mov bx,qlist_ea.ea_value ;AC001; ;GET SECOND FILE CODEPAGE + and ax,ax ;AC008; ;AN000; ;COMPARE TO ZERO CP +; $if ne ;AN000; ;FIRST FILE HAS NON-ZERO CODE PAGE + JE $$IF121 + and bx,bx ;AC008; ;AN000; ;COMPARE TO ZERO CP +; $if ne ;AN000; ;SECOND FILE HAS NON-ZERO CODE PAGE + JE $$IF122 + cmp ax,bx ;AN000; ;COMPARE CP OF 1ST WITH CP OF 2ND +; $if e ;AN000; ;CP ARE ALIKE + JNE $$IF123 + clc ;AN000; ;INdiCATE MATCHING CP +; $else ;AN000; ;siNCE CP ARE NOT ALIKE + JMP SHORT $$EN123 +$$IF123: + stc ;AN000; ;INdiCATE NON-MATCHING CP +; $endif ;AN000; ;CP ARE ALIKE +$$EN123: +; $else ;AN000; ;siNCE 2ND HAS NO CODE PAGE + JMP SHORT $$EN122 +$$IF122: + stc ;AN000; ;INdiCATE NON-MATCHING CP +; $endif ;AN000; ;2ND FILE HAS CODE PAGE? +$$EN122: +; $else ;AN000; ;siNCE 1ST FILE HAS NO CODE PAGE + JMP SHORT $$EN121 +$$IF121: + and bx,bx ;AC008; ;AN000; ;COMPARE TO ZERO CP +; $if ne ;AN000; ;2ND FILE HAS NO CODE PAGE + JE $$IF129 + stc ;AN000; ;INdiCATE NON-MATCHING CP +; $else ;AN000; ;siNCE 2ND FILE HAS NO CODE PAGE EITHER + JMP SHORT $$EN129 +$$IF129: + clc ;AN000; ;INdiCATE OK, NO CP TO COMPARE +; $endif ;AN000; ;2ND FILE HAS CP? +$$EN129: +; $endif ;AN000; ;1ST FILE HAS CODE PAGE? +$$EN121: +; $if c ;AN000; ;IF CARRY + JNC $$IF133 + print_msg msgnum_cp_mismatch,STDERR ;AN000; ;"CODE PAGE MISMATCH" + stc ;AN000; ;PAss INdiCATOR OF NON-MATCH CP +; $endif ;AN000; +$$IF133: +; $else ;AN000; ;siNCE CODE PAGE NOT ACTIVE + JMP SHORT $$EN120 +$$IF120: + clc ;AN000; ;PAss INdiCTOR OF OK CP +; $endif ;AN000; ;CODEPAGE LOADED? +$$EN120: + ret ;AN000; ;retURN TO callER +comp_codepage endp ;AN000; + + +;------------------------------------------------------------------------------ +; GETCP - Does an extended open, gets codepage #, closes file. +; +; INPUT - AX = ptr to real filename to open +; CUR_NAME = ptr to inputed filename to open (display this if error) +; OUTPUT - +;------------------------------------------------------------------------------ +getcp proc near ;AN000; + public getcp ;AN000; + +; SET UP INPUTS TO EXTENDED OPEN: +; REQUesT FUNCTIONS: READ,COMPATABILITY,NO INHERIT,INT 24H ret ERR, +; NO COMMIT, NO ATTR, FAIL IF NOT EXIST, OPEN IF EXIST +; NO CODE PAGE CHECK + + mov bx,OPEN_MODE ;AN000; ;SET READ MODE TO CORRECT VALUE FOR EXTENDED OPEN + xor cx,cx ;AC008; ;AN000; ;NO ATTRIBUTE TO WORRY ABOUT (00H = NO_ATTR) + mov dx,FUNC_CNTRL ;AN000; ;SET FUNCTION CONTROL FOR EXTENDED OPEN + mov di,offset parm_list ;AN000; ;PAss offset TO PARM_LIST + mov si,cur_name ;AN000; ;ptr to name of file to open + doscall EXT_OPEN,EXT_OPEN_RD ;AN000; + mov handle,ax ;AN000; ;SAVE HANDLE +; $if c ;AN000; ;IF ERROR + JNC $$IF137 + call exterr ;AN000; ;GET EXTENDED ERROR, SHOW MSG +; $else ;AN000; ;siNCE NO ERROR ON OPEN + JMP SHORT $$EN137 +$$IF137: + ;AN000; ;GET_EXT_ATTR_LIST (5702), GET + ;AN000; ;EXTENDED ATTR. TO LIST + mov bx,handle ;AN000; ;bx=HANDLE + mov di,offset qlist ;AC001; ;es:di=QLIST + mov cx,13 ;AN001; ;size of QLIST returned + mov si,offset querylist ;AN001; ;get code page attr. only + doscall EXT_ATTR_LIST,GET_EXT_ATTR_LIST ;AN000; + ;AN000; ;CY SET IF ERROR +; $if c ;AN000; ;IF ERROR + JNC $$IF139 + call exterr ;AN000; ;GET EXTENDED ERROR, SHOW MSG +; $endif ;AN000; +$$IF139: + mov bx,handle ;AN000; ;PAss HANDLE TO CLOSE FILE + doscall HANDLECLOSE ;AN000; ;CLOSE THIS EXTENDED OPEN OF THE FILE +; $endif ;AN000; +$$EN137: + ret ;AN000; ;retURN TO callER +getcp endp ;AN000; + + +;------------------------------------------------------------------------------ +; EXTERR - Displays the extended error message and filename. +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +exterr proc near ;AN000; + public exterr ;AN000; + + xor bx,bx ;AC008; ;AN000; ;bx = MINOR VERsiON # OF DOS + doscall EXTERROR ;AN000; ;GET EXTENDED ERROR + mov msgnum_exterr.msg_num,ax ;AN000; ;PUT EXT. ERROR # IN MSG DesCRIPTOR STRUCT. + mov msgnum_exterr.msg_sublist,offset sublist_EXTERR ;AN000; ;ptr TO sublist + mov msgnum_exterr.msg_count,NO_SUBS ;AN000; ;ONE sublist WILL BE USED. + mov ax,cur_name ;AN000; ;GET CURRENT FILENAME + mov sublist_exterr.sub_value,ax ;AN000; ;FILL IN offset OF FILENAME TEXT + print_msg msgnum_exterr,STDERR ;AN000; ;dispLAY EXTENDED ERROR MEssAGE + + mov exitfl,EXVER ;AN000; ;INdiCATE AN ERROR + ret ;AN000; +exterr endp ;AN000; + + +;------------------------------------------------------------------------------ +; GET_DBCS_VECTOR - Get the DOS double byte character table segment and offset +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +bufferDB db 6 dup(0) + +get_dbcs_vector proc near ;AN006; + push es ;AN006; + push di ;AN006; + push ax ;AN006; + push bx ;AN006; + push cx ;AN006; + push dx ;AN006; +; + mov ax,cs ;AN006; ;segment of return buffer + mov es,ax ;AN006; + mov di,offset bufferDB ;AN006; ;offset of return buffer + mov ah,65h ;AN006; ;get extended country info + mov al,07h ;AN006; ;get DBCS environment table + mov bx,0ffffh ;AN006; ;use active code page + mov cx,5 ;AN006; ;number of bytes returned + mov dx,0ffffh ;AN006; ;default country ID + int 21h ;AN006; ;DOS function call,vector returned + ;AN006; ; in ES:DI + inc di ;AN006; ;skip over id byte returned + mov ax,word ptr es:[di] ;AN006; ;get offset of DBCS table + mov cs:dbcs_off,ax ;AN006; ;save it +; + add di,2 ;AN006; ;skip over offset to get segment + mov bx,word ptr es:[di] ;AN006; ;get segment of DBCS table + mov cs:dbcs_seg,bx ;AN006; ;save it +; + mov di,ax ;AN006; ;Point to DBCS table to get length + mov es,bx ;AN006; + mov ax,word ptr es:[di] ;AN006; + mov cs:dbcs_len,ax ;AN006; + add cs:dbcs_off,2 ;AN006; ;change offset to point to table +; + pop dx ;AN006; + pop cx ;AN006; + pop bx ;AN006; + pop ax ;AN006; + pop di ;AN006; + pop es ;AN006; +; + ret ;AN006; +get_dbcs_vector endp ;AN006; + + +;------------------------------------------------------------------------------ +; Check_DBCS_slash - given SI pointing to string, check if the character SI +; points to is a slash and that the preceeding character +; is not DBCS. +; +; INPUT - SI = ptr to possible slash character +; STRING_SEG:STRING_OFF points to the beginning of string +; OUTPUT - set ZERO flag if [SI-1] != DBCS character AND [SI] == '\', +; else resets ZERO flag. +;------------------------------------------------------------------------------ +Check_DBCS_slash proc near ;AN006; + push es ;AN006; + push di ;AN006; + push si ;AN006; + push ax ;AN006; + push bx ;AN006; + push cx ;AN006; +; + cmp byte ptr [si],'\' ;AN006; ;Is character a slash ? + jne reset_zero ;AN006; ;no, quit. +; + cld ;AN006; + mov cx,128 ;AN006; ;clear darray to zeroes + mov di,offset dstring ;AN006; ;dstring will correspond to the string pointed to by + mov al,00 ;AN006; ;string_seg:string_off and for each character in the string + rep stosb ;AN006; ;that is DBCS a corresponding "D" will be stored in dstring. + ;AN006; ;example: string : [c:\\\ ] + ; dstring: [ D D ] (there are two DBCS characters) +; + sub si,string_off ;AN006; ;si will equal length of string from beginning to character that may be a slash. + and si,si ;AC008; ;AN006; ;is character in first position ? + jbe set_zero ;AN006; ;yes, quit. + mov cx,si ;AN006; ;cx will contain the count of characters to check DBCS status of. + push cx ;AN006; ;save for later + mov si,string_off ;AN006; ;si points to beginning of string. +; + mov bx,cs:dbcs_seg ;AN006; ;ES:SI -> DOS dbcs table (segment) + mov es,bx ;AN006; +; + mov bx,offset dstring ;AN006; ;bx points to dstring +DB_loop: ;AN006; + mov di,cs:dbcs_off ;AN006; ;ES:SI -> DOS dbcs table (offset) + lodsb ;AN006; ;get character into al +; +; Two consecutive 00 bytes signifies end of table +; + +is_loop: ;AN006; + cmp word ptr es:[di],00h ;AN006; ;Check for two consecutive 00 bytes + jne is_next1 ;AN006; ;no, continue + jmp short DB_inc ;AC008; ;AN006; ;yes, found them, quit +; +; Check if byte is within range values of DOS dbcs table +; +is_next1: ;AN006; + cmp al,byte ptr es:[di] ;AN006; ;is byte >= first byte in range? + jae is_next2 ;AN006; ;yes, continue + jmp short is_again ;AC008; ;AN006; ;no, loop again +is_next2: ;AN006; + cmp al,byte ptr es:[di+1] ;AN006; ;is byte <= last byte in range? + jbe is_found ;AN006; ;yes, found a lead byte of db char +is_again: ;AN006; + add di,2 ;AN006; ;no, increment ptr to next range + jmp is_loop ;AN006; +is_found: ;AN006; + mov byte ptr ds:[bx],'D' ;AN006; ;byte is lead byte of db char, set [BX] = 'D' + inc bx ;AN006; ;skip over second part of double byte char. + inc si ;AN006; ; " " " " " " " " +DB_inc: ;AN006; + inc bx ;AN006; + dec cx ;AN006; + and cx,cx ;AC008; ;AN006; ;are we done check characters for DBCS + jne DB_loop ;AN006; ;no, check next character +; +; end of loop +; + pop cx ;AN006; ;restore offset into string + dec cx ;AN006; ;check character preceeding slah to see if it is DBCS + mov si,offset dstring ;AN006; ;get beginning of string + add si,cx ;AN006; ;si now point to char preceeding slash + cmp byte ptr [si],'D' ;AN006; ;Is it DBCS ? + je reset_zero ;AN006; ;yes +set_zero: ;AN006; + cmp al,al ;AN006; ;set ZERO flag + jmp short is_bye ;AC008; ;AN006; +reset_zero: ;AN006; + mov bx,01h ;AN006; + cmp bx,0ffh ;AN006; ;reset ZERO flag +is_bye: ;AN006; + pop cx ;AN006; + pop bx ;AN006; + pop ax ;AN006; + pop si ;AN006; + pop di ;AN006; + pop es ;AN006; +; ;AN006; + ret ;AN006; +Check_DBCS_slash endp ;AN006; + + +;------------------------------------------------------------------------------ +; SENDMSG - Transfer msg descriptor info to registers and call the msg retriever +; +; INPUT - DX = ptr to msg descriptor for this message +; OUTPUT - DX, AX altered, others ok. +;------------------------------------------------------------------------------ +sendmsg proc near ;AN000; + public sendmsg ;AN000; + + push bx ;AN000; ;SAVE callER'S REGS + push cx ;AN000; + push si ;AN000; + push di ;AN000; + mov di,dx ;AN000; ;PUT ptr TO MSG DesC. IN di + mov dx,[di].msg_input ;AN000; ;GET ptr TO INPUT BUFFER AND PUT IN dx + push dx ;AN000; ;SAVE IT ON THE STACK FOR LATER + +; PAss PARMS TO MEssAGE HANDLER IN +; THE APPROPRIATE REGISTERS IT NEEds. + mov ax,[di].msg_num ;AN000; ;MEssAGE NUMBER + mov bx,[di].msg_handle ;AN000; ;HANDLE TO dispLAY TO + mov si,[di].msg_sublist ;AN000; ;offset IN es: OF sublist, OR 0 IF NONE + mov cx,[di].msg_count ;AN000; ;NUMBER OF %PARMS, 0 IF NONE + mov dx,[di].msg_class ;AN000; ;CLAss IN HIGH byte, INPUT FUNCTION IN LOW + pop di ;AN000; ;GET OLD dx VALUE (ptr TO INPUT BUFFER) + call sysdispmsg ;AN000; ;dispLAY THE MEssAGE +; $if c ;AN000; ;IF THERE IS A PROBLEM + JNC $$IF142 + ;AN000; ;ax=EXTENDED ERROR NUMBER + mov bx,STDERR ;AN000; ;HANDLE TO dispLAY TO + xor si,si ;AC008; ;AN000; ;offset IN es: OF sublist, OR 0 IF NONE + xor cx,cx ;AC008; ;AN000; ;NUMBER OF %PARMS, 0 IF NONE + mov dh,CLASS_1 ;AN000; ;CLAss IN HIGH byte, INPUT FUNCTION IN LOW + call sysdispmsg ;AN000; ;TRY TO SAY WHAT HAPPENED + stc ;AN000; ;REPORT PROBLEM +; $endif ;AN000; ;PROBLEM WITH dispLAY? +$$IF142: + + pop di ;AN000; ;ResTORE callER'S REGISTERS + pop si ;AN000; + pop cx ;AN000; + pop bx ;AN000; + + ret ;AN000; +sendmsg endp ;AN000; + + + +;------FIND BOUNDARY-------------- + if ($-cseg) mod 16 ;AN000; ;IF NOT ALREADY ON 16 byte BOUNDARY + org ($-cseg)+16-(($-cseg) mod 16) ;AN000; ;ADJUST TO 16 byte BOUNDARY + endif ;AN000; +;--------------------------------- + +buf label byte +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;ALL CODE BELOW THIS POINT WILL BE OVERLAID WITH DATA BEING COMPARED;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;------------------------------------------------------------------------------ +; SETFILL - sets the fill_seg, fill_off with the current seg_id, offset in +; sublists of msg. +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +setfill proc near ;AN000; + public setfill ;AN000; + push ax ;AN000; ;save registers + mov ax,cs ;AN000; ;get the code segment + mov sublist_6.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_7.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_8.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_11.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_12.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_13.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_19a.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_19b.sub_value_seg,ax ;AN000; ;save seg_id in sublist + mov sublist_24.sub_value_seg,ax ;AN000; ;FILL IN CODE SEGMENT + mov sublist_exterr.sub_value_seg,ax ;AN000; ;FILL IN CODE SEGMENT + pop ax ;AN000; ; GET OLD VALUE IN ax BACK + ret ;AN000; +setfill endp ;AN000; + + +;------------------------------------------------------------------------------ +; MORE_INIT - finishes the initialization. this code will be overlaid with data +; after it executes. +; +; INPUT - +; OUTPUT - +;------------------------------------------------------------------------------ +more_init proc near ;AC000; + public more_init ;AN000; + + cld + or ah,al + cmp ah,-1 ;was either drive specified invalid? +; $if e ;AC000; ;one or both of drives are invalid + JNE $$IF144 + print_msg msgnum_baddrv,STDERR ;AN000; ;"INVALID DRIVE SPEC." + int 20h ;and quit +; $endif ;AC000; +$$IF144: + mov ax, offset buf+4096 ;end of pgm + add ax,16 + mov cl,4 + shr ax,cl ;in seg form + push cs + pop dx + add ax,dx ;seg addr of buf2 + mov buf2,ax + mov dx,Memory_Size ;# paragraphs in machine + cmp ax,dx ;does start of buf2 exceed mem? + jnb badmem ;yes, can't do nothin' without mem + sub dx,ax ;# avail paragraphs + cmp dx,256 ;have at least 4k? + jnb havmem ;yes +badmem: + print_msg msgnum_mem,STDERR ;AN000; ;"INSUFFICIENT MEMORY" + int 20h ;and quit +havmem: + cmp dx,3840 ;over 61440 bytes avail? + jbe cmem ;no + mov dx,3840 ;yes, set to max of 61440 bytes +cmem: + mov cl,4 + shl dx,cl ;# bytes avail + and dx,0f000h ;round down to a 4096-byte boundary + mov word ptr mem,dx ;and save buf2 size in bytes + mov byte ptr swt,0 ;initialize master switch + doscall DEFDRV ;AC000; ;get default drive + inc al + mov curdrv,al ;and save + or al,64 ;drive to ascii + mov cdrv,al ;save + xor ch,ch + mov cl,Parm_Area ;length of input parms + mov si,129 ;where parms are + + mov current_parm,si ;AN000; ;pass to parser ptr to input parm buffer + mov ordinal,ZERO_PARM_CT ;AN000; ;pass ordinal #, this is begin of parse + mov parm_count,FIRST_PARM_CT ;AN000; ;parse the first parm and second parm + call parser ;AC000; ;returns first filename in path1, and the + ;AN000; ;second filename in path2. + ;fcb is already formatted with correct drive + mov si,offset path2 + mov di,offset fcb2 + doscall PARSE_FILENAME,01H ;AC000; ;build 2nd fcb from 2nd parm, + ;AC000; ;scan off leading separators + cmp al,-1 ;invalid drive? +; $if e ;AC000; ;Yes, invalid drive + JNE $$IF146 + print_msg msgnum_baddrv,STDERR ;AN000; ;"Invalid drive spec." + int 20h ;and quit +; $else ;AC000; + JMP SHORT $$EN146 +$$IF146: + mov dx,offset CBExit + doscall SETVECTOR,23H ;AC000; ;change control break vector, #23h +; $endif ;AC000; +$$EN146: + + ret ;AN000; ;return to main +more_init endp ;AN000; + +cseg ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMPEQ.INC b/v4.0/src/CMD/COMP/COMPEQ.INC new file mode 100644 index 0000000..5272927 --- /dev/null +++ b/v4.0/src/CMD/COMP/COMPEQ.INC @@ -0,0 +1,184 @@ +;***************************************************************************** +; +; MODULE: compeq.inc +; +; Modification History: +; +; version author date comment +; ------- ------ ---- ------- +; V4.0 Bill L. 9/17/87 moved equates from comp2.sal to here! +; +;***************************************************************************** + if1 ;AN000; + %OUT INCLUDING COMPEQ.INC... ;AN000; + endif ;AN000; + +EAISBINARY equ 02h ;extended attribute is a binary integer ;AN001; +EASYSTEM equ 8000h ;extended attr. is system defined ;AN001; + +VERSION EQU 00H ;DOS VERSION, =00H (NOT USED) ;AN000; +NUL EQU 00H ;END OF STRING (ASCIIZ) MARKER ;AN000; +ONE_PARM EQU 01H ;ONLY PARSE ONE PARAMETER ;AN000; +ZERO_PARM_CT EQU 00H ;ORDINAL # BEFORE PARSING FIRST PARM. ;AN000; +FIRST_PARM_CT EQU 01H ;ORDINAL # AFTER PARSING FIRST PARM. ;AN000; +TRICK_PARM_CT EQU 02H ;TRICK PARSER SO THAT FILENAME GOES TO PATH2 ;AN000; + ;INSTEAD OF PATH1 ;AN000; +YES EQU 01H ;A VALID YES RESPONSE EQUALS 1 ;AN000; +KEYB_INP_CLR EQU 0C1H ; does an INT 21H fuction 0CH, 01H ;AN000; +KEYB_INPUT EQU 0FFH ;DO A READ ON CLEAR KEYBOARD ;AN000; +INPUT_LEN EQU 127 ;LENGTH OF INPUT BUFFER ON BUFFERED INPUT ;AN000; +KEYIN EQU 01H ;WAIT FOR KEYBOARD INPUT TO AL ;AN000; +DISP_OUT EQU 02H ;DL = CHAR TO BE DISPLAYED TO STD OUT ;AN000; +DIRECT_IO EQU 06H ;DUMBY CALL, USED IN CLEARING KEYBOARD ;AN000; +BUFFD_KEYBD EQU 0AH ;BUFFERED KEYBOARD INPUT TO DX ;AN000; +IN_STAT EQU 0BH ;check keyboard status ;AC210; +CLEAR_KEYBD EQU 0CH ;CLEAR KEYB, DO KEYB FUNC IN AL ;AN000; +FCBOpen equ 0FH ;fcb open ;AN000; +FCBCLOSE EQU 10H ;FCB CLOSE FILE ;AN000; +SearchF equ 11H ;FCB Search function call ;AN000; +SEARCHN EQU 12H ;FCB SEARCH NEXT ;AN000; +SetDTA equ 1AH ;Set DTA ;AN000; +DEFDRV equ 19H ;get default drive ;AN000; +YESNO_CHECK EQU 23H ;CHECK (Y/N) RESPONSE ON INPUT (EXTENDED COUNTRY INFO) ;AN000; +SETVECTOR equ 25H ;set interrupt vector in AL to DS:DX ;AN000; +FCBRndBlkRead equ 27H ;Read function call ;AN000; +PARSE_FILENAME EQU 29H ;PARSE FILENAME ;AN000; +GETVER equ 30H ;get dos version ;AN000; +CHDIR equ 3BH ;CHDIR function call ;AN000; +HandleOpen equ 3DH ;Handle open function call ;AN000; +HANDLECLOSE EQU 3EH ;HANDLE CLOSE FUNCTION CALL ;AN000; +Write equ 40H ;Write function call ;AN000; +CURDIR equ 47H ;get current directory for drive in [dl] ;AN000; +RET_FN EQU 4CH ;"RETURN TO DOS" NOT REMAIN RESIDENT ;AN000; +GET_EXT_CNTRY_INFO EQU 65H ;EXTENED COUNTRY INFO DOS CALL ;AN000; + +STDOUT equ 0001H ;Standard output device ;AN000; +STDERR equ 0002H ;Standard error device ;AN000; + +ReadOnlyAccess equ 00H ;Access code for Handle Open function call ;AN000; + +CPSW_CHECK EQU 33H ;CODE PAGE SWITCHING CONTROL ;AN000; +GET_CPSW_STATE EQU 03H ;AL=3, GET STATE TO DL ;AN000; +SET_CPSW_STATE EQU 04H ;AL=4, SET STATE FROM DL ;AN000; +CPSW_OFF EQU 00H ; DL=0, OFF ;AN000; +CPSW_ON EQU 01H ; DL=1, ON ;AN000; +CPSW EQU 40H ;IN CPSW_ORIG: ON, CPSW=ON ;AN000; +ZERO_CP EQU 00H ; A ZERO CODE PAGE ;AN000; + +; EXTENDED OPEN EQUATES ; LOOK ;AN000; +NO_ATTR_LIST EQU 00H ;NO ATTRIBUTE LIST NEEDED || ;AN000; +OPEN_MODE EQU 82H ;OPEN MODE FOR EXTENDED OPEN || ;AN000; +FUNC_CNTRL EQU 0101H ;FUNCTION CONTROL FOR EXTENDED OPEN || ;AN000; +EXT_OPEN_RD EQU 00H ;READ MODE ON EXTENDED OPEN \/ ;AN000; +EXT_OPEN EQU 6CH ;EXTENDED OPEN ;AN000; + ;AL=FUNCTION CONTROL, IN FORMAT=CE ;AN000; + ; C=DOES NOT EXIST ACTION: ;AN000; + ; 0=FAIL, 1=CREATE ;AN000; + ; E=EXISTS ACTION ;AN000; + ; 0=FAIL, 1=OPEN, 2=REPLACE/OPEN ;AN000; + ;BX=OPEN MODE, FORMAT=0WF00000ISSS0AAA ;AN000; + ; AAA=ACCESS CODE: 0=READ, 1=WRITE ;AN000; + ; 2=READ/WRITE, 4=EXECUTE (UNDOC) ;AN000; + ; 7=FCB (UNDOC) ;AN000; + ; SSS=SHARING MODE: 0=COMPATIBILITY ;AN000; + ; 1=DENY READ/WRITE, 2=DENY WRITE ;AN000; + ; 2=DENY READ, 3=DENY NONE ;AN000; + ; I=0, PASS HANDLE TO CHILD, 1=NO INHERIT ;AN000; + ; F=0, INT 24H, 1=RETURN ERROR ;AN000; + ;ON THIS OPEN AND ANY IO TO THIS HANDLE ;AN000; + ; W=0, NO COMMIT, 1=AUTO-COMMIT ON WRITE ;AN000; + ;CX=SCARCH/CREATE ATTRIBUTE ;AN000; + ;DX=FUNCTION CONTROL, 0000000C NNNNEEEE ;AN000; + ; NNNN=DOES NOT EXIST ACTION: ;AN000; + ; 0=FAIL,1=CREATE ;AN000; + ; EEEE=DOES EXIST ACTION: ;AN000; + ; 0=FAIL,1=OPEN,2=REPLACE/OPEN ;AN000; + ; C=CODEPAGE ACTION: ;AN000; + ; 0=VALIDATE, 1=NO CHECK CODE PAGE ;AN000; + ;DS:SI=PARM LIST: ;AN000; + ; DD POINT TO NAME TO OPEN ;AN000; + ; DB NUMBER OF ADDITIONAL PARMS ;AN000; + ; DB 1 IO MODE ;AN000; + ; DB IOMODE ;AN000; + ; ???0H=UNSPECIFIED (DEFAULT) ;AN000; + ; ???1H=MAINLY SEQUENTIAL ;AN000; + ; ???2H=MAINLY RANDOM ;AN000; + ; ???3H=RANDOM WITH LOCALITY ;AN000; + ; ???=RESERVED (SET TO ZERO) ;AN000; + ;ES:DI=EXTENTED ATTR LIST ;AN000; + + ;OUTPUT: CY SET ON ERROR ;AN000; + ; AX=HANDLE ;AN000; + ; CX=ACTION TAKEN: 1=FILE OPENED, ;AN000; + ; 2=FILE CREATED/OPENED, ;AN000; + ; 3=FILE REPLACED/OPENED ;AN000; + +EXT_ATTR_LIST EQU 57H ;FUNCTION # : EXTENDED ATTR LIST ;AN000; +GET_EXT_ATTR_LIST EQU 02H ;SUB-FUNC. # : GET EXTENDED ATTR TO LIST ;AN000; + ;BX=HANDLE ;AN000; + ;ES:DI=LIST ;AN000; + ;CY SET IF ERROR ;AN000; + + +EXTERROR EQU 59H ;EXTENDED ERROR ;AN000; + ;BX = 40 VERSION NUMBER (FOR 3.40) ;AN000; + ;OUTPUT: ;AN000; + ;AX=EXTENDED ERROR ;AN000; + ;BH=ERROR CLASS ;AN000; + ;BL=SUGGESTED ACTION ;AN000; + ;CH=LOCUS ;AN000; + +; ERRORLEVEL RETURN CODES, PASSED IN "EXITFL" ;AN000; +EXOK EQU 0 ;NORMAL RETURN CODE, NO PROBLEM ;AN000; +EXCB EQU 1 ;CONTROL BREAK EXIT ;AN000; +EXVER EQU 1 ;BAD DOS VERSION OR OTHER ;AN000; + ; SYSLOADMSG DIFFICULTY ;AN000; + +; VALUES FOR THE MSG_DESC CONTROL BLOCK ;AN000; +NO_SUBS EQU 0 ;NO VARIABLE FIELDS IN MESSAGE ;AN000; +ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE ;AN000; +TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE ;AN000; +THREE_SUBS EQU 3 ;THREE VARIABLE FIELDS IN MESSAGE ;AN000; +CLASS_1 EQU 1 ;CLASS 1 (DOS EXTENDED ERRORS) ;AN000; +CLASS_2 EQU 2 ;CLASS 2 (PARSE ERRORS) ;AN000; +CLASS_A EQU -1 ;CLASS A TYPE MESSAGE ;AN000; + +;***************************** ;AN000; +; Message Retriever structures ;AN000; +;***************************** ;AN000; + +msg_desc struc ;AN000; +msg_num dw 0 ;MESSAGE NUMBER (TO AX) ;AN000; +msg_handle dw STDOUT ;HANDLE OF OUTPUT DEVICE (TO BX) ;AN000; +msg_sublist dw 0 ;POINTER TO SUBLIST (TO SI) ;AN000; +msg_count dw 0 ;SUBSTITUTION COUNT (TO CX) ;AN000; +msg_class dw CLASS_A shl 8 ;MESSAGE CLASS (IN HIGH BYTE, TO DH) ;AN000; + ;LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) ;AN000; +msg_input dw ? ;######EXTRA WORD - ONLY FOR MESSAGES WITH BUFFERED INPUT ;AN000; + ;######OTHERWISE THIS WORD IS NOT VALID AS PART OF THE STRUCT ;AN000; + ;POINTER TO INPUT BUFFER ;AN000; +msg_desc ends ;AN000; + +MAX_0 equ 0 ;MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT) ;AN000; +PAD_BLK equ " " ;CHAR FOR PAD FIELD ;AN000; + + +sublist struc ;AN000; +sub_size db 11 ;SUBLIST SIZE (POINTER TO NEXT SUBLIST) ;AN000; +sub_res db 0 ;RESERVED ;AN000; + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD ;AN000; +sub_value dw 0 ;TIME, DATE, OR PTR TO DATA ITEM ;AN000; +sub_value_seg dw 0 ;SEG ID OF PTR ;AN000; + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME ;AN000; + ; IF THIS IS A .COM FILE) ;AN000; +sub_id db 0 ;N OF %N ;AN000; +sub_flags db 0 ;DATA TYPE FLAGS ;AN000; +sub_max_width db MAX_0 ;MAXIMUM FIELD WIDTH (0=UNLIMITED) ;AN000; +sub_min_width db 0 ;MINIMUM FIELD WIDTH ;AN000; +sub_pad_char db PAD_BLK ;CHARACTER FOR PAD FIELD ;AN000; + ; CAN BE " ", "0" OR ",". ;AN000; + ; "," CAUSES INSERTION OF THE ACTIVE ;AN000; + ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS. ;AN000; +sublist ends ;AN000; + +;end of COMPEQ.INC ;AN000; diff --git a/v4.0/src/CMD/COMP/COMPMS.INC b/v4.0/src/CMD/COMP/COMPMS.INC new file mode 100644 index 0000000..3ac0844 --- /dev/null +++ b/v4.0/src/CMD/COMP/COMPMS.INC @@ -0,0 +1,156 @@ +;:util COMP ;utility name ;AN000; +;:class 1 ;DOS extended errors: ;AN000; +;:class 2 ;parse errors: ;AN000; +;; ;AN000; +;:class A ;system messages ;AN000; +; ;AN000; +;:use 1 COMMON1 ;"Incorrect DOS version" ;AN000; +;:use 2 EXTEND8 ;"Insufficient memory" ;AN000; +;:use 3 PARSE10 ;"Invalid parameter" ;AN000; +;:def 4 "10 Mismatches - ending compare",CR,LF ;AN000; +;:use 5 EXTEND15 ;"Invalid drive specification" ;AN000; +;:def 6 "Compare error at OFFSET %1",CR,LF ;AN000; +;:def 7 "File 1 = %1",CR,LF ;AN000; +;:def 8 "File 2 = %1",CR,LF ;AN000; +;:def 9 "Eof mark not found",CR,LF ;AN000; +;:def 10 "Files compare ok",CR,LF ;AN000; +;:use 11 EXTEND2 ;"File not found" ;AN000; +;:use 12 COMMON25 ;"Invalid path" ;AN000; +;:use 13 EXTEND32 ;"Sharing violation" ;AN000; +;:use 14 EXTEND4 ;"Too many open files" ;AN000; +;:def 15 CR,LF,CR,LF,"Enter primary file name",CR,LF ;AN000; +;:def 16 CR,LF,CR,LF,"Enter 2nd file name or drive id",CR,LF ;AN000; +;:def 17 "Files are different sizes",CR,LF ;AN000; +;:def 18 "Compare more files? (Y/N)",CR,LF ;AN000; +;:def 19 "%1 and %2",CR,LF ;AN000; +;:def 20 CR,LF ;AN000; +;:use 21 EXTEND5 ;"Access Denied" ;AN000; +;:use 22 EXTEND37 ;"Code page mismatch" ;AN000; +;:DEF 23 "Files compare ok",CR,LF ;AN000; +;:end ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; + IF1 ;AN000; + %OUT COMPONENT=COMP, MODULE=COMPMS.INC... ;AN000; + ENDIF ;AN000; +; $SALUT (0,13,18,22) ;AN000; +; ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +; ;AN000; +; THE NEXT GROUP ARE ADDITIONAL CLASS "A" MESSAGES ;AN000; +; SPECIFICALLY DEFINED FOR THE COMP UTILITY ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; +; ;AN000; +; THIS IS SUBLIST FOR MSGNUM_EXTERR (A CLASS 1 MESSAGE) ;AN000; +SUBLIST_EXTERR SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_EXTERR ;AN000; +; ;AN000; +; "Insufficient memory" ;AN000; +MSGNUM_MEM MSG_DESC <2> ;AN000; + PUBLIC MSGNUM_MEM ;AN000; +; ;AN000; +; "invalid parameter" ;AN000; +MSGNUM_PARA MSG_DESC <3> ;AN000; + PUBLIC MSGNUM_PARA ;AN000; +; ;AN000; +; "10 Mismatches - ending compare",CR,LF ;AN000; +MSGNUM_TENMSG MSG_DESC <4> ;AN000; + PUBLIC MSGNUM_TENMSG ;AN000; +; ;AN000; +; "Invalid drive specification",CR,LF ;AN000; +MSGNUM_BADDRV MSG_DESC <5,STDOUT> ;AN000; + PUBLIC MSGNUM_BADDRV ;AN000; +; ;AN000; +; "Compare error at OFFSET %1",CR,LF ;AN000; +MSGNUM_BAD MSG_DESC <6,,SUBLIST_6,ONE_SUBS> ;AN000; +SUBLIST_6 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; +; NOTE: ERROR NUMBER IS DWORD ;AN000; + PUBLIC MSGNUM_BAD,SUBLIST_6 ;AN000; +; ;AN000; +; "File 1 = %1",CR,LF ;AN000; +MSGNUM_ADR MSG_DESC <7,,SUBLIST_7,ONE_SUBS> ;AN000; +SUBLIST_7 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_ADR,SUBLIST_7 ;AN000; +; ;AN000; +; "File 2 = %1",CR,LF ;AN000; +MSGNUM_BDR MSG_DESC <8,,SUBLIST_8,ONE_SUBS> ;AN000; +SUBLIST_8 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_BDR,SUBLIST_8 ;AN000; +; ;AN000; +; "Eof mark not found",CR,LF ;AN000; +MSGNUM_EOR MSG_DESC <9> ;AN000; + PUBLIC MSGNUM_EOR ;AN000; +; ;AN000; +; "Files compare ok",CR,LF ;AN000; +MSGNUM_DONE MSG_DESC <10> ;AN000; + PUBLIC MSGNUM_DONE ;AN000; +; ;AN000; +; "%1 - File not found",CR,LF ;AN000; +MSGNUM_FNF MSG_DESC <11,,SUBLIST_11,ONE_SUBS> ;AN000; +SUBLIST_11 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_FNF,SUBLIST_11 ;AN000; +; ;AN000; +; "%1 - Invalid path",CR,LF ;AN000; +MSGNUM_BAD_PATH MSG_DESC <12,,SUBLIST_12,ONE_SUBS> ;AN000; +SUBLIST_12 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_BAD_PATH,SUBLIST_12 ;AN000; +; ;AN000; +; "%1 - File sharing conflict",CR,LF ;AN000; +MSGNUM_SHARE MSG_DESC <13,,SUBLIST_13,ONE_SUBS> ;AN000; +SUBLIST_13 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_SHARE,SUBLIST_13 ;AN000; +; ;AN000; +; "Too many files open",CR,LF ;AN000; +MSGNUM_TOO_MANY MSG_DESC <14> ;AN000; + PUBLIC MSGNUM_TOO_MANY ;AN000; +; ;AN000; +; CR,LF,CR,LF,"Enter primary file name",CR,LF ;AN000; +MSGNUM_PRINAM MSG_DESC <15,,,,(CLASS_A SHL 8) OR DOS_BUF_KEYB_INP> ;AN000; + DW ? ;DEFINE EXTRA WORD FOR PTR TO INPUT BUFFER ;AN000; + ;IT WILL BE ACCESSED AS A FIELD OF THE ABOVE STRUCT ;AN000; + PUBLIC MSGNUM_PRINAM ;AN000; +; ;AN000; +; CR,LF,CR,LF,"Enter 2nd file name or drive id",CR,LF ;AN000; +MSGNUM_SECNAM MSG_DESC <16,,,,(CLASS_A SHL 8) OR DOS_BUF_KEYB_INP> ;AN000; + DW ? ;DEFINE EXTRA WORD FOR PTR TO INPUT BUFFER ;AN000; + ;IT WILL BE ACCESSED AS A FIELD OF THE ABOVE STRUCT ;AN000; + PUBLIC MSGNUM_SECNAM ;AN000; +; ;AN000; +; "Files are different sizes",CR,LF ;AN000; +MSGNUM_BADSIZ MSG_DESC <17> ;AN000; + PUBLIC MSGNUM_BADSIZ ;AN000; +; ;AN000; +; "Compare more files (Y/N) ?",CR,LF ;AN000; +MSGNUM_NOTHER MSG_DESC <18,STDOUT,,,(CLASS_A SHL 8) OR 0C1H> ;AC210;;AD176; + PUBLIC MSGNUM_NOTHER ;AN000; +; ;AN000; +; "%1 and %2",CR,LF ;AN000; +MSGNUM_AND_MSG MSG_DESC <19,,SUBLIST_19A,TWO_SUBS> ;AN000; +SUBLIST_19A SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_19B SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_2,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_AND_MSG,SUBLIST_19A,SUBLIST_19B ;AN000; +; ;AN000; +; CR,LF ;AN000; +MSGNUM_CRLF MSG_DESC <20> ;AN000; + PUBLIC MSGNUM_CRLF ;AN000; +; ;AN000; +; "%1 - Access Denied",CR,LF ;AN000; +MSGNUM_ACCESSDENIED MSG_DESC <21,,SUBLIST_21,ONE_SUBS> ;AN000; +SUBLIST_21 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_ACCESSDENIED,SUBLIST_21 ;AN000; +; ;AN000; +; "Code page mismatch" ;AN000; +MSGNUM_CP_MISMATCH MSG_DESC <22> ;AN000; + PUBLIC MSGNUM_CP_MISMATCH ;AN000; +; ;AN000; +; "Files compare ok" ;AN000; +MSGNUM_OK MSG_DESC <23> ;AN000; + PUBLIC MSGNUM_OK ;AN000; +; +; +MSGNUM_PPARSE MSG_DESC <,STDERR,SUBLIST_24,ONE_SUBS,(CLASS_2 SHL 8)> ;AN000; +SUBLIST_24 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC MSGNUM_PPARSE,SUBLIST_24 ;AN000; + +; ;AN000; +;end of COMPMS.INC ;AN000; diff --git a/v4.0/src/CMD/COMP/COMPP.ASM b/v4.0/src/CMD/COMP/COMPP.ASM new file mode 100644 index 0000000..9f2bbba --- /dev/null +++ b/v4.0/src/CMD/COMP/COMPP.ASM @@ -0,0 +1,130 @@ + PAGE ,132 ; + TITLE COMPP.SAL - COMP SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMPP.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of COMP. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .COM. +; The Common PARSER is then INCLUDEd. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.ASM statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.ASM statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT COMPP,NUL,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; COMP1.ASM. +; +; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, +; Add compare of code page extended attribute, if present. +; +; COPYRIGHT: "The DOS COMP Utility" +; "Version 4.0 (C)Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft" +; +;PROGRAM AUTHOR: DOS 4.0 Edwin M. K., Bill L. +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=COMP, MODULE=COMPP.SAL... ;AN000; + ENDIF ;AN000; + +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + PUBLIC SYSPARSE ;SUBROUTINE ENTRY POINT ;AN000; + +FARSW EQU 0 ;CALL THE PARSER BY NEAR CALL ;AN000; +DATESW EQU 0 ;SUPPRESS DATE CHECKING ;AN000; +TIMESW EQU 0 ;SUPPRESS TIME CHECKING ;AN000; +FILESW EQU 1 ;DO CHECK FILE SPECIFICATION ;AN000; +CAPSW EQU 1 ;DO USE FILE TABLE CAPS ;AN000; +CMPXSW EQU 0 ;SUPPRESS CHECKING COMPLEX LIST ;AN000; +DRVSW EQU 1 ;DO SUPPORT DRIVE ONLY FORMAT ;AN000; +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMT ;AN000; +NUMSW EQU 0 ;SUPPRESS CHECKING NUMERIC VALUE ;AN000; +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT ;AN000; +SWSW EQU 1 ;DO SUPPORT SWITCHES ;AN000; +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 ;AN000; +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 ;AN000; +VAL3SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 3 ;AN000; +INCSW EQU 0 ;DON'T INCLUDE PSDATA.INC +BASESW EQU 1 ;use DS to index off of for PSDATA + + IF1 ;AN000; + %OUT COMPONENT=COMP, SUBCOMPONENT=PARSE, INCLUDED PARSE.ASM... ;AN000; + ENDIF ;AN000; + + INCLUDE PSDATA.INC ;AN000; + INCLUDE PARSE.ASM ;AN000; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMPPAR.ASM b/v4.0/src/CMD/COMP/COMPPAR.ASM new file mode 100644 index 0000000..e47ce55 --- /dev/null +++ b/v4.0/src/CMD/COMP/COMPPAR.ASM @@ -0,0 +1,410 @@ + PAGE ,132 ; + TITLE COMPPAR.SAL - LOOK AT COMMAND LINE PARMS +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMPPAR.SAL +; +; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters +; and the interface to the DOS system PARSER. +; +;FUNCTION: The static data areas are prescribed by the DOS system PARSER +; to define the several parameters presented to COMP. These +; data areas are passed to the PARSER, and its responses checked +; to determine the nature of the user's specifications. Any errors +; found in the user's parameters are defined in messages back +; to the user. +; +; ENTRY POINT: PARSER, near +; +; INPUT: (DOS COMMAND LINE PARAMETERS) +; +; [d:][path] COMP [d:][path][filenam1[.ext]] [d:][path][filenam2[.ext]] +; +; Where +; [d:][path] before COMP to specify the drive and path that +; contains the COMP command file. +; +; [d:][path][filenam1[.ext]] - to specify the FIRST (or primary) +; file or group of files to be compared +; +; [d:][path][filenam2[.ext]] - to specify the SECOND file or group +; of files to be compared with the corresponding file +; from the FIRST group +; +; Global filename characters are allowed in both filenames, +; and will cause all of the files matching the first filename +; to be compared with the corresponding files from the second +; filename. Thus, entering COMP A:*.ASM B:*.BAK will cause +; each file from drive A: that has an extension of .ASM to be +; compared with a file of the same name (but with an extension +; of .BAK) from drive B:. +; +; If you enter only a drive specification, COMP will assume +; all files in the current directory of the specified drive. +; If you enter a path without a filename, COMP assumes all +; files in the specified directory. Thus, COMP A:\LEVEL1 +; B:\LEVEL2 will compare all files in directory A:\LEVEL1 with +; the files of the same names in directory B:\LEVEL2. +; +; If no parameters are entered with the COMP command, you will +; be prompted for both. If the second parm is omitted, COMP +; will prompt for it. If you simply press ENTER when prompted +; for the second filename, COMP assumes *.* (all files +; matching the primary filename), and will use the current +; directory of the default drive. +; +; If no file matches the primary filename, COMP will prompt +; again for both parameters. +; +; +; Upon entry to PARSER in this module, +; "CURRENT_PARM" = offset to start of parm text in command string +; "ORDINAL" = initialized to zero +; PSP+81H = text of DOS command line parms string +; +; EXIT-NORMAL: If a Code Page number was specified +; BX = Offset to language table to be loaded +; DX = Integer value of Code Page specified +; If /STATUS (or /STA) was specified +; BX = 0 +; If Question mark was specified +; BX=-1 +; +; EXIT-ERROR: If there was any problem with the parms, +; the question mark is assumed, and the appropriate +; PARSE error message is displayed. +; The Errorlevel code of "EXPAR" (3), meaning: "PARM ERROR", +; set in "EXITFL", is requested to be returned to the user. +; +; INTERNAL REFERENCES: +; ROUTINES: +; PARSE_ERROR:NEAR Display the appropriate Parse error message. +; +; DATA AREAS: +; The several parameter control blocks, defined by the System +; PARSER interface, defining the COMP parameters. +; +; EXTERNAL REFERENCES: +; ROUTINES: +; SENDMSG:NEAR Uses Msg Descriptor to drive message handler. +; SYSPARSE:NEAR System Command Line Common Parser. +; +; DATA AREAS: +; EXITFL:BYTE Errorlevel return code. +; MSGNUM_PARSE:WORD Message descriptor for all parse errors. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT COMPPAR,NUL +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; COMP1.SAL. +; +; REVISION HISTORY: +; A000 Version 4.0 : add PARSER, System Message Handler, +; Add compare of extended attributes, if present. +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "COMPSM.SAL" module: +; +; "The DOS COMP Utility" +; "Version 4.0 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft" +; +;PROGRAM AUTHOR: Edwin M. K. +; modified: Bill L. +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=COMP, MODULE=COMPPAR.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = ;AN000; +HEADER MACRO TEXT ;;AN000; +.XLIST ;;AN000; + SUBTTL TEXT ;;AN000; +.LIST ;;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = ;AN000; +; $SALUT (4,23,28,36) ;AN000; + + INCLUDE COMPEQ.INC ;AN000; +; LOCAL EQUATES ;AN000; +MAX_PATH_LEN EQU 64 ;MAX CHAR IN A PATH ;AN000; +EXPAR EQU 1 ;RETURN TO DOS, INVALID DOS COMMAND LINE PARMS ;AN000; +ZERO_PARM_CT EQU 0 ;ORDINAL VALUE BEFORE FIRST PARM FOUND ;AN000; +FIRST_PARM_CT EQU 1 ;ORDINAL VALUE AFTER FIRST PARM FOUND ;AN000; +NUL EQU 0 ;ASCIIZ STRING DELIMITER ;AN000; +; = = = = = = = = = = = = ;AN000; +; EXIT CODES FROM SYSPARSE (WHEN CY=0) ;AN000; + +SYSPRM_EX_OK EQU 0 ; no error ;AN000; +SYSPRM_EX_MANY EQU 1 ; too many operands ;AN000; +SYSPRM_EX_MISSING EQU 2 ; required operand missing ;AN000; +SYSPRM_EX_NOT_SWLIST EQU 3 ; not in switch list provided ;AN000; +SYSPRM_EX_NOT_KEYLIST EQU 4 ; not in keyword list provided ;AN000; +SYSPRM_EX_RANGE EQU 6 ; out of range specified ;AN000; +SYSPRM_EX_VALUE EQU 7 ; not in value list provided ;AN000; +SYSPRM_EX_STRING EQU 8 ; not in string list provided ;AN000; +SYSPRM_EX_SYNTAX EQU 9 ; syntax error ;AN000; +SYSPRM_EX_EOL EQU -1 ; end of command line ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +PSP STRUC ;AN000; + DB 80H DUP (?) ;SKIP OVER FIRST HALF OF PSP ;AN000; +PSP_PARMLEN DB ? ;NUMBER OF BYTES IN DOS COMMAND LINE ;AN000; +PSP_COMMAND DB 127 DUP(?) ;TEXT OF DOS COMMAND LINE ;AN000; +PSP ENDS ;AN000; +; = = = = = = = = = = = = ;AN000; +FILESPEC STRUC ;AN000; +FS_DRIVE_ID DB ? ;DRIVE LETTER ;AN000; +FS_COLON DB ":" ;COLON SEPARATOR ;AN000; +FS_SLASH1 DB "\" ;LEADING BACKSLASH,START AT ROOT ;AN000; +FS_PATH DB MAX_PATH_LEN DUP (0) ;TEXT OF PATH ;AN000; + +;LOCATION OF REMAINING FIELDS DEPENDS ON LENGTH OF ACTUAL PATH ;AN000; +;POSITIONS SHOWN ARE FOR MAX PATH LENGTH ONLY ;AN000; + +FS_SLASH2 DB 0 ;TRAILING BACKSLASH ;AN000; +FS_FNAME DB 8 DUP (0) ;FILENAME ;AN000; +FS_PER DB 0 ;PERIOD END OF FILENAME ;AN000; +FS_EXT DB 3 DUP (0) ;FILENAME EXTENSION ;AN000; +FILESPEC ENDS ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +; $SALUT (4,14,19,36) ;AN000; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + EXTRN SENDMSG:NEAR ;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR ;AN000; + EXTRN SYSPARSE:NEAR ;SYSTEM COMMAND LINE PARSER ;AN000; + + EXTRN EXITFL:BYTE ;ERRORLEVEL RETURN CODE ;AN000; + EXTRN PATH1:BYTE ;FIRST POSITIONAL PARM ;AN000; + EXTRN PATH2:BYTE ;SECOND POSITIONAL PARM ;AN000; + EXTRN MSGNUM_PPARSE:WORD ;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS ;AN000; + EXTRN SUBLIST_24:WORD ;sublist for parse error messages ;AN000; +; = = = = = = = = = = = = ;AN000; + +CURRENT_PARM DW 81H ;POINTER INTO COMMAND OF NEXT OPERAND ;AN000; + PUBLIC CURRENT_PARM ;AN000; + +ORDINAL DW 0 ;ORDINAL NUMBER OF WHICH PARM TO PARSE ;AN000; + PUBLIC ORDINAL ;AN000; + +PARM_COUNT DW 00H ;CURRENT PARM COUNT (USED TO TRICK "PARSER" ;AN000; + PUBLIC PARM_COUNT ;INTO PARSING FILE NAMES ENTERED FROM THE ;AN000; + ;KEYBOARD INSTEAD OF COMMAND LINE ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; + +;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER ;AN000; + + PUBLIC PARMS ;LET LINK MAKE PARMS BLOCK ADDRESSABLE ;AN000; +PARMS LABEL BYTE ;PARMS CONTROL BLOCK ;AN000; + DW PARMSX ;POINTER TO PARMS EXTENSION ;AN000; + DB 0 ; NUMBER OF STRINGS (0, 1, 2) ;AN000; + ; NEXT LIST WOULD BE EXTRA DELIM LIST ;AN000; + ; (,& WHITESPACE ALWAYS) ;AN000; + ; NEXT LIST WOULD BE EXTRA END OF LINE LIST ;AN000; + ; (CR,LF,0 ALWAYS) ;AN000; + +;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK ;AN000; +PARMSX LABEL BYTE ;PARMS EXTENSION CONTROL BLOCK ;AN000; + DB 0,2 ; MIN, MAX POSITIONAL OPERANDS ALLOWED ;AN000; + DW CONTROL_POS ; DESCRIPTION OF POSITIONAL 1 ;AN000; + DW CONTROL_POS ; DESCRIPTION OF POSITIONAL 2 ;AN000; + + DB 0 ; MAX SWITCH OPERANDS ALLOWED ;AN000; + + DB 0 ; MAX KEYWORD OPERANDS ALLOWED ;AN000; + ; THERE IS NO CONTROL BLOCK ;AN000; + ; DEFINING KEYWORDS ;AN000; + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL ;AN000; +;BOTH POSITIONAL PARAMETER ARE: ;AN000; +; [d:][path][filename[.ext]] ;AN000; + + PUBLIC CONTROL_POS ;LET LINK MAKE THIS ADDRESSABLE ;AN000; +CONTROL_POS LABEL BYTE ;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC, ;AN000; + ; OPTIONAL ;AN000; + DW 0201H ; CONTROLS TYPE MATCHED ;AN000; + ; SELECTED BITS: "FILESPEC" AND "OPTIONAL" ;AN000; + + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) ;AN000; + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE ;AN000; + ; CHECKED) ;AN000; + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) ;AN000; + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) ;AN000; + ; 0010H=IGNORE ":" AT END IN MATCH ;AN000; + ; 0002H=REPEATS ALLOWED ;AN000; + ; 0001H=OPTIONAL ;AN000; + + DW 0001H ;FUNCTION_FLAGS ;AN000; + ; 0001H=CAP RESULT BY FILE TABLE ;AN000; + ; 0002H=CAP RESULT BY CHAR TABLE ;AN000; + ; 0010H=REMOVE ":" AT END ;AN000; + DW RESULT1 ; RESULT BUFFER ;AN000; + DW NOVALS ; VALUE LISTS ;AN000; + DB 0 ; NUMBER OF KEYWORD/SWITCH SYNONYMS ;AN000; + ; IN FOLLOWING LIST ;AN000; + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; +;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER ;AN000; +RESULT1 LABEL BYTE ; BELOW FILLED IN FOR DEFAULTS ;AN000; + DB 5 ; TYPE RETURNED: 0=RESERVED, ;AN000; + ; 1=NUMBER, 2=LIST INDEX, ;AN000; + ; 3=STRING, 4=COMPLEX, ;AN000; + ; 5=FILESPEC, 6=DRIVE ;AN000; + ; 7=DATE, 8=TIME ;AN000; + ; 9=QUOTED STRING ;AN000; +RESULT_TAG DB 0FFH ; MATCHED ITEM TAG ;AN000; + DW 0 ;POINTER TO SYNONYM ;AN000; + +RESULT_PTR1 DD ? ; OFFSET OF STRING VALUE ;AN000; + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; +;VALUE CONTROL BLOCK ;AN000; +NOVALS LABEL BYTE ;AN000; + DB 0 ; NUMBER OF VALUE DEFINITIONS (0 - 3) ;AN000; + +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +; $SALUT (4,4,9,36) ;AN000; +PARSER PROC NEAR ;AN000; + PUBLIC PARSER ;AN000; + +;INPUT: "CURRENT_PARM" = OFFSET TO NEXT PARM IN COMMAND STRING ;AN000; +; "ORDINAL" = COUNT OF NEXT PARM TO PARSE ;AN000; +; PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING ;AN000; + +;OUTPUT: IF SPECIFIED, FIRST PARM GOES TO "PATH1". ;AN000; +; IF SPECIFIED, SECOND PARM GOES TO "PATH2". ;AN000; +; IF EITHER PARM MISSING, THEN "PATHn" STARTS WITH NUL CHAR. ;AN000; +; CARRY SET IF ERROR. ;AN000; +; = = = = = = = = = = = = ;AN000; + +; $SEARCH COMPLEX ;LOOP THRU COMMAND LINE ;AN000; + JMP SHORT $$SS1 +$$DO1: + ;LOOKING AT RETURN CODE FROM SYSPARSE... ;AN000; + AND AX,AX ;AN008; ;WERE THERE ANY ERRORS? ;AN000; +; $EXITIF NE ;HAD A PROBLEM ;AN000; + JE $$IF1 + CALL PARSE_ERROR ;DISPLAY REASON FOR ERROR ;AN000; + MOV AL,01h ;AN000; ;pass back errorlevel ret code + mov ah,4ch + int 21h +; $ORELSE ;SINCE NO PROBLEM, SO FAR ;AN000; + JMP SHORT $$SR1 +$$IF1: + MOV ORDINAL,CX ;SAVE UPDATED COUNT ;AN000; + MOV CURRENT_PARM,SI ;REMEMBER HOW FAR I GOT ;AN000; + MOV BX,DX ;SET DATA BASE REG TO POINT TO ;AN000; + ;RESULT BUFFER OF THIS OPERAND ;AN000; + + MOV SI,WORD PTR RESULT_PTR1 ;GET WHERE STRING IS PUT ;AN000; + ;GUESS, THIS IS THE FIRST PARM ;AN000; + MOV DI,OFFSET PATH1 ;GET WHERE STRING IS TO GO ;AN000; + + ;IF PARSING FILENAME INPUTED FROM KEYBOARD ;AN000; + ;THEN PARM_COUNT MUST = ZERO_PARM_CT = 0 ;AN000; + CMP CX,PARM_COUNT ;IS THIS THE FIRST PARM OR JUST A FILENAME IN BUFFER ;AN000; + +; $IF NE ;NO, MUST BE THE SECOND PARM ;AN000; + JE $$IF4 + ;MADE A BAD GUESS, FIX IT ;AN000; + MOV DI,OFFSET PATH2 ;CHANGE DEST TO WHERE SECOND STRING GOES ;AN000; +; $ENDIF ;AN000; +$$IF4: + + ;MOVE ASCIIZ STRING FROM DS:SI ;AN000; + ;WHERE COMMAND PARSE PUT IT ;AN000; + ;TO ES:DI WHERE COMP2 USES IT ;AN000; + +; $DO COMPLEX ;AN000; + JMP SHORT $$SD6 +$$DO6: + STOSB ;PUT CHAR IN AL TO ES:DI ;AN000; +; $STRTDO ;AN000; +$$SD6: + LODSB ;GET CHAR FROM DS:SI TO AL ;AN000; + CMP AL,NUL ;IS THAT THE END OF STRING? ;AN000; +; $ENDDO E ;IF SO, QUIT ;AN000; + JNE $$DO6 + +; $STRTSRCH ;AN000; +$$SS1: + LEA DI,PARMS ;ES:DI = PARSE CONTROL DEFINITON ;AN000; + MOV SI,CURRENT_PARM ;DS:SI = COMMAND STRING, NEXT PARM ;AN000; + XOR DX,DX ;RESERVED, INIT TO ZERO ;AN000; + MOV CX,ORDINAL ;OPERAND ORDINAL, INITIALLY ZERO ;AN000; + CALL SYSPARSE ;LOOK AT DOS PARMS ;AN000; + ;AX=EXIT CODE ;AN000; + ;BL=TERMINATED DELIMETER CODE ;AN000; + ;CX=NEW OPERAND ORDINAL ;AN000; + ;SI=SET TO PAST SCANNED OPERAND ;AN000; + ;DX=SELECTED RESULT BUFFER ;AN000; + CMP AX,SYSPRM_EX_EOL ;IS THAT THE END OF THE PARMS? ;AN000; + ;IF NOT, LOOP BACK AND FIND OUT ;AN000; + ;WHAT THAT PARM IS ;AN000; +; $ENDLOOP E ;END OF LIST ;AN000; + JNE $$DO1 + CLC ;RETURN FLAG FOR "NO ERROR" ;AN000; +; $ENDSRCH ;FINISHED WITH DOS COMMAND LINE ;AN000; +$$SR1: + RET ;RETURN TO CALLER ;AN000; +PARSER ENDP ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +PARSE_ERROR PROC NEAR ;AN000; + +;INPUT: "FIRST_TIME" - IF NON-ZERO, FORCE ERROR CODE TO "TOO MANY PARMS" ;AN000; +; AX - ERROR NUMBER RETURNED FROM PARSE. ;AN000; +;OUTPUT: APPROPRIATE ERROR MESSAGE IS DISPLAYED. ;AN000; +; = = = = = = = = = = = = ;AN000; + + MOV MSGNUM_PPARSE,AX ;PASS MESSAGE NUMBER TO DESCRIPTOR ;AN000; + MOV DX,OFFSET MSGNUM_PPARSE ;PASS MESSAGE DESCRIPTOR ;AN000; + MOV BX,CURRENT_PARM ;AN000; +PE_BX: ;AN000; + CMP BX,SI ;are we past the point the parser stopped ? ;AN000; + JAE PE_BX_OK ;yes, we are done. ;AN000; + CMP BYTE PTR [BX],20H ;by-pass leading blanks ;AN000; + JNE PE_BX_OK ;AN000; + INC BX ;AN000; + JMP PE_BX ;AN000; +PE_BX_OK: ;AN000; + MOV SUBLIST_24.SUB_VALUE,BX ;AN000; +; +;make a ASCIIZ string out of parameter +; +PE_LOOP: ;AN000; + CMP BX,SI ;are we past the point the parser stopped ? ;AN000; + JAE PE_OK ;yes, we are done. ;AN000; + CMP BYTE PTR [BX],20H ;check for spaec or end of line ;AN000; + JE PE_OK ;AN000; + INC BX ;AN000; + JMP PE_LOOP ;AN000; +PE_OK: ;AN000; + MOV byte ptr [BX],00H ;end string with zero ;AN000; + + CALL SENDMSG ;DISPLAY ERROR MESSAGE ;AN000; + + MOV EXITFL,EXPAR ;ERRORLEVEL CODE TO "PARM ERROR" ;AN000; + RET ;RETURN TO CALLER ;AN000; +PARSE_ERROR ENDP ;AN000; ;AN000; +; = = = = = = = = = = = = ;AN000; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/COMPSM.ASM b/v4.0/src/CMD/COMP/COMPSM.ASM new file mode 100644 index 0000000..9bf26ab --- /dev/null +++ b/v4.0/src/CMD/COMP/COMPSM.ASM @@ -0,0 +1,159 @@ + PAGE ,132 ; + TITLE COMPSM.SAL - COMP SYSTEM MESSAGES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMPSM.SAL +; +; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT +; configuration expected by the modules of COMP. +; +;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a +; part of the COMP module by using INCLUDE to bring in the +; common portion, in SYSMSG.INC. This included code contains +; the routines to initialize for message services, to find +; where a particular message is, and to display a message. +; +; ENTRY POINT: SYSDISPMSG:near +; SYSGETMSG:near +; SYSLOADMSG:near +; +; INPUT: +; AX = MESSAGE NUMBER +; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12) +; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE +; CX = NUMBER OF %PARMS, 0 IF NONE +; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW +; CALL SYSDISPMSG ;DISPLAY THE MESSAGE +; +; If carry set, extended error already called: +; AX = EXTENDED MESSAGE NUMBER +; BH = ERROR CLASS +; BL = SUGGESTED ACTION +; CH = LOCUS +; _ _ _ _ _ _ _ _ _ _ _ _ +; +; AX = MESSAGE NUMBER +; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG) +; CALL SYSGETMSG ;FIND WHERE A MSG IS +; +; If carry set, error +; CX = 0, MESSAGE NOT FOUND +; If carry NOT set, ok, and resulting regs are: +; CX = MESSAGE SIZE +; DS:SI = MESSAGE TEXT +; _ _ _ _ _ _ _ _ _ _ _ _ +; +; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION +; If carry not set: +; CX = SIZE OF MSGS LOADED +; +; If carry is set, regs preset up for SYSDISPMSG, as: +; AX = ERROR CODE IF CARRY SET +; AX = 1, INCORRECT DOS VERSION +; DH =-1, (Utility msg) +; OR, +; AX = 1, Error loading messages +; DH = 0, (Message manager error) +; BX = STDERR +; CX = NO_REPLACE +; DL = NO_INPUT +; +; EXIT-NORMAL: CARRY is not set +; +; EXIT-ERROR: CARRY is set +; Call Get Extended Error for reason code, for SYSDISPMSG and +; SYSGETMSG. +; +; INTERNAL REFERENCES: +; ROUTINES: (Generated by the MSG_SERVICES macro) +; SYSLOADMSG +; SYSDISPMSG +; SYSGETMSG +; +; DATA AREAS: +; INCLUDED "COMPMS.INC" - message defining control blocks +; INCLUDED "MSGHAN.INC" - Define STRUCs for msg control blocks +; INCLUDE SYSMSG.INC ;Permit System Message handler definition +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT COMPSM,nul,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; COMP1.ASM. +; +; REVISION HISTORY: A000 Version 4.0 : add PARSER, System Message Handler, +; Add compare of code page extended attribute, if present. +; +; COPYRIGHT: "The DOS COMP Utility" +; "Version 4.0 (C)Copyright 1988 Micorsoft " +; "Licensed Material - Property of Microsoft " +; +;PROGRAM AUTHOR: DOS 3.20 Dave L. +; DOS 3.30 modifications by Russ W. +; DOS 4.0 modifications by Edwin M. K., Bill L. +;****************** END OF SPECIFICATIONS ***************************** +; ;AN000; + IF1 ;AN000; + %OUT COMPONENT=COMP, MODULE=COMPSM.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = ;AN000; +; ;AN000; +HEADER MACRO TEXT ;AN000; +.XLIST ;AN000; + SUBTTL TEXT ;AN000; +.LIST ;AN000; + PAGE ;AN000; + ENDM ;AN000; +; = = = = = = = = = = = = ;AN000; + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + MSG_UTILNAME ;IDENTIFY THE UTILITY ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +; $SALUT (4,12,18,36) ;AN000; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; +; ;AN000; + PUBLIC COPYRIGHT ;AN000; +COPYRIGHT DB "The DOS COMP Utility" ;AN000; + INCLUDE MSGHAN.INC ;DEFINE THE MESSAGE HANDLER CONTROL BLOCKS ;AN000; + INCLUDE COMPMS.INC ;DEFINE THE MESSAGES, AND CONTROL BLOCKS ;AN000; + MSG_SERVICES ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; + PUBLIC SYSLOADMSG ;AN000; + PUBLIC SYSDISPMSG ;AN000; + PUBLIC SYSGETMSG ;AN000; +; ;AN000; +; MSG_SERVICES ;AN000; + ;DEFAULT=CHECK DOS VERSION ;AN000; + ;DEFAULT=NEARmsg ;AN000; + ;DEFAULT=INPUTmsg ;AN000; + ;DEFAULT=NUMmsg ;AN000; + ;DEFAULT=NO TIMEmsg ;AN000; + ;DEFAULT=NO DATEmsg ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; +.LIST ;AN000; +.CREF ;AN000; +; ;AN000; + MSG_SERVICES ;TEXTS OF MESSAGES ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;AN000; +CSEG ENDS ;AN000; + + include msgdcl.inc + + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMP/MAKEFILE b/v4.0/src/CMD/COMP/MAKEFILE new file mode 100644 index 0000000..b1bfdde --- /dev/null +++ b/v4.0/src/CMD/COMP/MAKEFILE @@ -0,0 +1,52 @@ +#************************* makefile for cmd\comp ************************* + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: comp.com + +comp.ctl: comp.skl \ + $(msg)\$(COUNTRY).msg \ + +comp1.obj: comp1.asm \ + makefile + +comppar.obj: comppar.asm \ + compeq.inc \ + makefile + +compp.obj: compp.asm \ + $(inc)\parse.asm \ + makefile + +compsm.obj: compsm.asm \ + $(inc)\copyrigh.inc \ + $(inc)\versiona.inc \ + $(inc)\sysmsg.inc \ + $(inc)\msghan.inc \ + comp.ctl \ + comp.cl1 \ + comp.cl2 \ + comp.cla \ + compms.inc \ + makefile + +comp2.obj: comp2.asm \ + compeq.inc \ + makefile + +comp.com: comp1.obj \ + comp.lnk \ + comppar.obj \ + compp.obj \ + compsm.obj \ + comp2.obj + link @comp.lnk + exe2bin comp.exe comp.com + del comp.exe diff --git a/v4.0/src/CMD/DEBUG/DEBASM.ASM b/v4.0/src/CMD/DEBUG/DEBASM.ASM new file mode 100644 index 0000000..8f34c52 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBASM.ASM @@ -0,0 +1,1441 @@ + PAGE 80,132 ; + TITLE DEBASM.ASM +; CODE FOR THE ASSEMBLE COMMAND IN THE DEBUGGER + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBASM + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM +.CREF +.LIST + + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + + EXTRN DBMN:BYTE,CSSAVE:WORD,REG8:BYTE,REG16:BYTE,SIZ8:BYTE + EXTRN SYNERR_PTR:BYTE,OPTAB:BYTE,MAXOP:ABS + +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + + EXTRN HINUM:WORD,LOWNUM:WORD,ASSEM_CNT:BYTE + EXTRN ASSEM1:BYTE,ASSEM2:BYTE,ASSEM3:BYTE,ASSEM4:BYTE,ASSEM5:BYTE + EXTRN ASSEM6:BYTE,OPBUF:BYTE,OPCODE:WORD,REGMEM:BYTE,INDEX:WORD + EXTRN ASMADD:BYTE,ASMSP:WORD,MOVFLG:BYTE,SEGFLG:BYTE,TSTFLG:BYTE + EXTRN NUMFLG:BYTE,DIRFLG:BYTE,BYTEBUF:BYTE,F8087:BYTE,DIFLG:BYTE + EXTRN SIFLG:BYTE,BXFLG:BYTE,BPFLG:BYTE,NEGFLG:BYTE,MEMFLG:BYTE + EXTRN REGFLG:BYTE,AWORD:BYTE,MIDFLD:BYTE,MODE:BYTE + EXTRN ARG_BUF:BYTE,HEX_PTR:BYTE + +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + PUBLIC ASSEM + PUBLIC DB_OPER,DW_OPER,ASSEMLOOP,GROUP2,AA_OPER,DCINC_OPER + PUBLIC GROUP1,ESC_OPER,FGROUPP,FGROUPX,FDE_OPER,FGROUPZ + PUBLIC FD9_OPER,FGROUP,FDB_OPER,FGROUPB,FGROUP3,FGROUP3W + PUBLIC FGROUPDS,INT_OPER,IN_OPER,DISP8_OPER,JMP_OPER,NO_OPER + PUBLIC OUT_OPER,L_OPER,MOV_OPER,POP_OPER,PUSH_OPER,ROTOP + PUBLIC TST_OPER,EX_OPER,GET_DATA16,CALL_OPER, DOORG + + EXTRN INBUF:NEAR,SCANB:NEAR,SCANP:NEAR,GETHX:NEAR,GET_ADDRESS:NEAR + EXTRN DEFAULT:NEAR,OUTDI:NEAR,BLANK:NEAR,TAB:NEAR + EXTRN STD_PRINTF:NEAR,PRINTF_CRLF:NEAR + +; Line by line assembler + +MASKMOD EQU 11000000B +SHMOD EQU 6 +MASKREG EQU 00111000B +SHREG EQU 3 +MASKRM EQU 00000111B +SHRM EQU 0 + +ASSEM: + MOV BP,[CSSAVE] ; Default code segment + MOV DI,OFFSET DG:ASMADD ; Default address + CALL DEFAULT + MOV WORD PTR [ASMADD],DX ; Displacement of disassembly + MOV WORD PTR [ASMADD+2],AX ; Segment + MOV [ASMSP],SP ; Save sp in case of error + +ASSEMLOOP: + MOV SP,[ASMSP] ; Restore sp in case of error + LES DI,DWORD PTR ASMADD ; GET PC + CALL OUTDI ; OUTPUT ADDRESS + PUSH CS + POP ES + PUSH DI + MOV DI,OFFSET DG:ARG_BUF +; No spacing is needed. The format string already has one. +; CALL BLANK ; SKIP A SPACE + XOR AL,AL + STOSB + MOV DX,OFFSET DG:HEX_PTR + CALL STD_PRINTF + POP DI + CALL INBUF ; GET A BUFFER + CALL SCANB + JNZ OPLOOK + RET ; if empty just return + +; At this point ds:si points to the opcode mnemonic... +OPLOOK: + XOR CX,CX ; OP-CODE COUNT = 0 + MOV DI,OFFSET DG:DBMN +OPSCAN: + XOR BX,BX +OPLOOP: + MOV AL,[DI+BX] + CMP AL,[SI+BX] + JZ OPMATCH + INC CX ; INCREMENT OP-CODE COUNT + CMP CX,MAXOP ; CHECK FOR END OF LIST + JB OP1 + JMP ASMERR +OP1: + INC DI ; SCAN FOR NEXT OP-CODE... + CMP BYTE PTR [DI-1],0 + JNZ OP1 + JMP OPSCAN + +OPMATCH: + INC BX ; COMPARE NEXT CHAR + CMP BYTE PTR [DI+BX],0 ; ARE WE DONE? + JNZ OPLOOP ; ..IF NOT KEEP COMPARING + XCHG BX,CX + MOV AX,BX + SHL AX,1 + ADD AX,BX + ADD AX,OFFSET DG:OPTAB + MOV BX,AX + +; CX = COUNT OF CHARS IN OPCODE +; BX = POINTER INTO OPCODE TABLE + + XOR AX,AX + MOV BYTE PTR [AWORD],AL + MOV WORD PTR [MOVFLG],AX ; MOVFLG + TSTFLG + MOV BYTE PTR [SEGFLG],AL ; ZERO SEGMENT REGISTER FLAG + MOV AH,00001010B ; SET UP FOR AA_OPER + MOV AL,BYTE PTR [BX] + MOV WORD PTR [ASSEM1],AX + MOV BYTE PTR [ASSEM_CNT],1 + + ADD SI,CX ; SI POINTS TO OPERAND + JMP WORD PTR [BX+1] + +; 8087 INSTRUCTIONS WITH NO OPERANDS + +FDE_OPER: + MOV AH,0DEH + JMP SHORT FDX_OPER +FDB_OPER: + MOV AH,0DBH + JMP SHORT FDX_OPER +FD9_OPER: + MOV AH,0D9H +FDX_OPER: + XCHG AL,AH + MOV WORD PTR [ASSEM1],AX + +; AAD AND AAM INSTRUCIONS + +AA_OPER: + INC BYTE PTR [ASSEM_CNT] + +; INSTRUCTIONS WITH NO OPERANDS + +NO_OPER: + CALL STUFF_BYTES + CALL SCANP + PUSH CS + POP ES + JNZ OPLOOK + JMP ASSEMLOOP + +; PUSH INSTRUCTION + +PUSH_OPER: + MOV AH,11111111B + JMP SHORT POP1 + +; POP INSTRUCTION + +POP_OPER: + MOV AH,10001111B +POP1: + MOV [ASSEM1],AH + MOV [MIDFLD],AL + INC BYTE PTR [MOVFLG] ; ALLOW SEGMENT REGISTERS + MOV BYTE PTR [AWORD],2 ; MUST BE 16 BITS + CALL GETREGMEM + CALL BUILDIT + MOV AL,[DI+2] + CMP AL,11000000B + JB DATRET + MOV BYTE PTR [DI],1 + CMP BYTE PTR [MOVFLG],2 + JNZ POP2 + AND AL,00011000B + OR AL,00000110B + CMP BYTE PTR [MIDFLD],0 + JNZ POP3 + OR AL,00000001B + JMP SHORT POP3 + +POP2: + AND AL,MASKRM + OR AL,01010000B + CMP BYTE PTR [MIDFLD],0 + JNZ POP3 + OR AL,01011000B +POP3: + MOV BYTE PTR [DI+1],AL + JMP ASSEM_EXIT + +; RET AND RETF INSTRUCTIONS + +GET_DATA16: + CALL SCANB + MOV CX,4 + CALL GETHX + JC DATRET + DEC BYTE PTR [ASSEM1] ; CHANGE OP-CODE + ADD BYTE PTR [ASSEM_CNT],2 ; UPDATE LENGTH + MOV WORD PTR [ASSEM2],DX ; SAVE OFFSET +DATRET: + JMP ASSEM_EXIT + + +; INT INSTRUCTION + +INT_OPER: + CALL SCANB + MOV CX,2 + CALL GETHX + JC ERRV1 + MOV AL,DL + CMP AL,3 + JZ DATRET + INC BYTE PTR [ASSEM1] + JMP DISPX + +; IN INSTRUCTION + +IN_OPER: + CALL SCANB + LODSW + CMP AX,'A'+4C00H ; "AL" + JZ IN_1 + CMP AX,'A'+5800H ; "AX" + JZ IN_0 +ERRV1: + JMP ASMERR +IN_0: + INC BYTE PTR [ASSEM1] +IN_1: + CALL SCANP + CMP WORD PTR [SI],'D'+5800H ; "DX" + JZ DATRET + MOV CX,2 + CALL GETHX + JC ERRV1 + AND BYTE PTR [ASSEM1],11110111B + MOV AL,DL + JMP DISPX + +; OUT INSTRUCTION + +OUT_OPER: + CALL SCANB + CMP WORD PTR [SI],'D'+5800H ; "DX" + JNZ OUT_0 + INC SI + INC SI + JMP SHORT OUT_1 +OUT_0: + AND BYTE PTR [ASSEM1],11110111B + MOV CX,2 + CALL GETHX + JC ERRV1 + INC BYTE PTR [ASSEM_CNT] + MOV BYTE PTR [ASSEM2],DL +OUT_1: + CALL SCANP + LODSW + CMP AX,'A'+4C00H ; "AL" + JZ DATRET + CMP AX,'A'+5800H ; "AX" + JNZ ERRV1 + INC BYTE PTR [ASSEM1] + JMP DATRET + + +; JUMP INSTRUCTION + +JMP_OPER: + INC BYTE PTR [TSTFLG] + +; CALL INSTRUCTION + +CALL_OPER: + MOV BYTE PTR [ASSEM1],11111111B + MOV BYTE PTR [MIDFLD],AL + CALL GETREGMEM + CALL BUILD3 + CMP BYTE PTR [MEMFLG],0 + JNZ CALLJ1 + CMP BYTE PTR [REGMEM],-1 + JZ CALLJ2 + +; INDIRECT JUMPS OR CALLS + +CALLJ1: + CMP BYTE PTR [AWORD],1 +ERRZ4: + JZ ERRV1 + CMP BYTE PTR [AWORD],4 + JNZ ASMEX4 + OR BYTE PTR [DI+2],1000B + JMP SHORT ASMEX4 + +; DIRECT JUMPS OR CALLS + +CALLJ2: + MOV AX,[LOWNUM] + MOV DX,[HINUM] + MOV BL,[AWORD] + CMP BYTE PTR [NUMFLG],0 + JZ ERRZ4 + +; BL = NUMBER OF BYTES IN JUMP +; DX = OFFSET +; AX = SEGMENT + +CALLJ3: + MOV BYTE PTR [DI],5 + MOV [DI+2],AX + MOV [DI+4],DX + + MOV AL,10011010B ; SET UP INTER SEGMENT CALL + CMP BYTE PTR [TSTFLG],0 + JZ CALLJ5 + MOV AL,11101010B ; FIX UP FOR JUMP +CALLJ5: + MOV BYTE PTR [DI+1],AL + CMP BL,4 ; FAR SPECIFIED? + JZ ASMEX4 + OR BL,BL + JNZ CALLJ6 + CMP DX,WORD PTR [ASMADD+2] ; DIFFERENT SEGMENT? + JNZ ASMEX4 + +CALLJ6: + MOV BYTE PTR [DI],3 + MOV AL,11101000B ; SET UP FOR INTRASEGMENT + OR AL,[TSTFLG] + MOV BYTE PTR [DI+1],AL + + MOV AX,[LOWNUM] + SUB AX,WORD PTR [ASMADD] + SUB AX,3 + MOV [DI+2],AX + CMP BYTE PTR [TSTFLG],0 + JZ ASMEX4 + CMP BL,2 + JZ ASMEX4 + + INC AX + MOV CX,AX + CBW + CMP AX,CX + JNZ ASMEX3 + MOV BYTE PTR [DI+1],11101011B + MOV [DI+2],AX + DEC BYTE PTR [DI] +ASMEX4: + JMP ASSEM_EXIT + +; CONDITIONAL JUMPS AND LOOP INSTRUCTIONS + +DISP8_OPER: + MOV BP,WORD PTR [ASMADD+2] ; GET DEFAULT DISPLACEMENT + CALL GET_ADDRESS + SUB DX,WORD PTR [ASMADD] + DEC DX + DEC DX + CALL CHKSIZ + CMP CL,1 + JNZ ERRV2 +DISPX: + INC [ASSEM_CNT] + MOV BYTE PTR [ASSEM2],AL +ASMEX3: + JMP ASSEM_EXIT + +; LDS, LES, AND LEA INSTRUCTIONS + +L_OPER: + CALL SCANB + LODSW + MOV CX,8 + MOV DI,OFFSET DG:REG16 + CALL CHKREG + JZ ERRV2 ; CX = 0 MEANS NO REGISTER + SHL AL,1 + SHL AL,1 + SHL AL,1 + MOV BYTE PTR [MIDFLD],AL + CALL SCANP + CALL GETREGMEM + CMP BYTE PTR [AWORD],0 + JNZ ERRV2 + CALL BUILD2 + JMP SHORT ASEXV + +; DEC AND INC INSTRUCTIONS + +DCINC_OPER: + MOV BYTE PTR [ASSEM1],11111110B + MOV BYTE PTR [MIDFLD],AL + CALL GETREGMEM + CALL BUILDIT + TEST BYTE PTR [DI+1],1 + JZ ASEXV + MOV AL,[DI+2] + CMP AL,MASKMOD + JB ASEXV + AND AL,1111B + OR AL,01000000B + MOV [DI+1],AL + DEC BYTE PTR [DI] +ASEXV: + JMP ASSEM_EXIT + +ERRV2: + JMP ASMERR + +; ESC INSTRUCTION + +ESC_OPER: + INC BYTE PTR [AWORD] + CALL SCANB + MOV CX,2 + CALL GETHX + CMP DX,64 + JAE ERRV2 + CALL SCANP + MOV AX,DX + MOV CL,3 + SHR DX,CL + OR [ASSEM1],DL + AND AL,111B + SHL AL,CL + JMP GROUPE + +; 8087 ARITHMETIC INSTUCTIONS + +; OPERANDS THAT ALLOW THE REVERSE BIT + +FGROUPDS: + CALL SETMID + CALL GETREGMEM2 + CALL BUILD3 + CMP BYTE PTR [MODE],11000000B + JNZ FGROUP1 + MOV AL,[DIRFLG] + OR AL,AL + JZ FEXIT + OR [DI+1],AL ; IF D=1... + XOR BYTE PTR [DI+2],00001000B ; ...REVERSE THE SENSE OF R + JMP SHORT FEXIT + +; HERE WHEN INSTRUCTION COULD HAVE MEMORY OR REGISTER OPERAND + +FGROUPX: + CALL SETMID ; THIS ENTRY POINT FOR 1 MEM OPER + MOV BYTE PTR [DIRFLG],0 + JMP SHORT FGRP2 +FGROUP: + CALL SETMID +FGRP2: + CALL GETREGMEM2 + CALL BUILD3 + CMP BYTE PTR [MODE],11000000B + JNZ FGROUP1 + MOV AL,[DIRFLG] + OR [DI+1],AL + JMP SHORT FEXIT +FGROUP1: + CALL SETMF +FEXIT: + JMP ASSEM_EXIT + +; THESE 8087 INSTRUCTIONS REQUIRE A MEMORY OPERAND +FGROUPB: + MOV AH,5 ; MUST BE TBYTE + JMP SHORT FGROUP3E +FGROUP3W: + MOV AH,2 ; MUST BE WORD + JMP SHORT FGROUP3E +FGROUP3: + MOV AH,-1 ; SIZE CANNOT BE SPECIFIED +FGROUP3E: + MOV [AWORD],AH + CALL SETMID + CALL GETREGMEM + CMP BYTE PTR [MODE],11000000B + JZ FGRPERR +FGRP: + CALL BUILD3 + JMP FEXIT + +; THESE 8087 INSTRUCTIONS REQUIRE A REGISTER OPERAND +FGROUPP: ; 8087 POP OPERANDS + MOV BYTE PTR [AWORD],-1 + CALL SETMID + CALL GETREGMEM2 + CMP BYTE PTR [DIRFLG],0 + JNZ FGRP +FGRPERR: + JMP ASMERR + +FGROUPZ: ; ENTRY POINT WHERE ARG MUST BE MEM + CALL SETMID + MOV BYTE PTR [DIRFLG],0 + CALL GETREGMEM + CMP BYTE PTR [MODE],11000000B + JZ FGRPERR + CALL BUILD3 + CALL SETMF + JMP FEXIT + +; NOT, NEG, MUL, IMUL, DIV, AND IDIV INSTRUCTIONS + +GROUP1: + MOV [ASSEM1],11110110B +GROUPE: + MOV BYTE PTR [MIDFLD],AL + CALL GETREGMEM + CALL BUILDIT + JMP FEXIT + +; SHIFT AND ROTATE INSTRUCTIONS + +ROTOP: + MOV [ASSEM1],11010000B + MOV BYTE PTR [MIDFLD],AL + CALL GETREGMEM + CALL BUILDIT + CALL SCANP + CMP BYTE PTR [SI],'1' + JZ ASMEXV1 + CMP WORD PTR [SI],"LC" ; CL + JZ ROTOP1 +ROTERR: + JMP ASMERR +ROTOP1: + OR BYTE PTR [ASSEM1],10B +ASMEXV1: + JMP ASSEM_EXIT + +; XCHG INSTRUCTION + +EX_OPER: + INC BYTE PTR [TSTFLG] + +; TEST INSTRUCTION + +TST_OPER: + INC BYTE PTR [TSTFLG] + JMP SHORT MOVOP + +; MOV INSTRUCTION + +MOV_OPER: + INC BYTE PTR [MOVFLG] +MOVOP: + XOR AX,AX + JMP SHORT GROUPM + +; ADD, ADC, SUB, SBB, CMP, AND, OR, XOR instructions + +GROUP2: + MOV BYTE PTR [ASSEM1],10000000B +GROUPM: + MOV BYTE PTR [MIDFLD],AL + + PUSH AX + CALL GETREGMEM + CALL BUILD2 + CALL SCANP ; POINT TO NEXT OPERAND + MOV AL,BYTE PTR [ASSEM_CNT] + PUSH AX + CALL GETREGMEM + POP AX + MOV BYTE PTR [DI],AL + POP AX + MOV BL,BYTE PTR [AWORD] + OR BL,BL + JZ ERRV5 + DEC BL + AND BL,1 + OR BYTE PTR [DI+1],BL + + CMP BYTE PTR [MEMFLG],0 + JNZ G21V + CMP BYTE PTR [NUMFLG],0 ; TEST FOR IMMEDIATE DATA + JZ G21V + CMP BYTE PTR [SEGFLG],0 + JNZ ERRV5 + CMP BYTE PTR [TSTFLG],2 ; XCHG? + JNZ IMMED1 +ERRV5: + JMP ASMERR +G21V: + JMP GRP21 + +; SECOND OPERAND WAS IMMEDIATE + +IMMED1: + MOV AL,BYTE PTR [DI+2] + CMP BYTE PTR [MOVFLG],0 + JZ NOTMOV1 + AND AL,11000000B + CMP AL,11000000B + JNZ GRP23 ; not to a register + ; MOVE IMMEDIATE TO REGISTER + MOV AL,BYTE PTR [DI+1] + AND AL,1 ; SET SIZE + PUSHF + SHL AL,1 + SHL AL,1 + SHL AL,1 + OR AL,BYTE PTR [DI+2] ; SET REGISTER + AND AL,00001111B + OR AL,10110000B + MOV BYTE PTR [DI+1],AL + MOV AX,WORD PTR [LOWNUM] + MOV WORD PTR [DI+2],AX + POPF + JZ EXVEC + INC BYTE PTR [DI] +EXVEC: + JMP GRPEX + +NOTMOV1: + AND AL,11000111B + CMP AL,11000000B + JZ IMMACC ; IMMEDIATE TO ACC + + CMP BYTE PTR [TSTFLG],0 + JNZ GRP23 + CMP BYTE PTR [MIDFLD],1*8 ; OR? + JZ GRP23 + CMP BYTE PTR [MIDFLD],4*8 ; AND? + JZ GRP23 + CMP BYTE PTR [MIDFLD],6*8 ; XOR? + JZ GRP23 + TEST BYTE PTR [DI+1],1 ; TEST IF BYTE OPCODE + JZ GRP23 + + MOV AX,[LOWNUM] + MOV BX,AX + CBW + CMP AX,BX + JNZ GRP23 ; SMALL ENOUGH? + + MOV BL,[DI] + DEC BYTE PTR [DI] + OR BYTE PTR [DI+1],10B + JMP SHORT GRP23X + +IMMACC: + MOV AL,BYTE PTR [DI+1] + AND AL,1 + CMP BYTE PTR [TSTFLG],0 + JZ NOTTST + OR AL,10101000B + JMP SHORT TEST1 +NOTTST: + OR AL,BYTE PTR [MIDFLD] + OR AL,100B +TEST1: + MOV BYTE PTR [DI+1],AL + DEC BYTE PTR [DI] + +GRP23: + MOV BL,BYTE PTR [DI] +GRP23X: + XOR BH,BH + ADD BX,DI + INC BX + MOV AX,WORD PTR [LOWNUM] + MOV WORD PTR [BX],AX + INC BYTE PTR [DI] + TEST BYTE PTR [DI+1],1 + JZ GRPEX1 + INC BYTE PTR [DI] +GRPEX1: + JMP GRPEX + +; SECOND OPERAND WAS MEMORY OR REGISTER + +GRP21: + CMP BYTE PTR [SEGFLG],0 + JZ GRP28 ; FIRST OPERAND WAS A SEGMENT REG + MOV AL,BYTE PTR [REGMEM] + TEST AL,10000B + JZ NOTSEG1 +ERRV3: + JMP ASMERR +NOTSEG1: + AND AL,111B + OR BYTE PTR [DI+2],AL + AND BYTE PTR [DI+1],11111110B + CMP BYTE PTR [MEMFLG],0 + JNZ G22V + JMP GRPEX + +GRP28: + AND BYTE PTR [DI+2],11000111B + MOV AL,BYTE PTR [DI+1] ; GET FIRST OPCODE + AND AL,1B + CMP BYTE PTR [MOVFLG],0 + JZ NOTMOV2 + OR AL,10001000B + JMP SHORT MOV1 +NOTMOV2: + CMP BYTE PTR [TSTFLG],0 + JZ NOTTST2 + OR AL,10000100B + CMP BYTE PTR [TSTFLG],2 + JNZ NOTTST2 + OR AL,10B +NOTTST2: + OR AL,BYTE PTR [MIDFLD] ; MIDFLD IS ZERO FOR TST +MOV1: + MOV BYTE PTR [DI+1],AL + CMP BYTE PTR [MEMFLG],0 +G22V: + JZ NotGRP22 + JMP GRP22 +NotGRP22: + +; SECOND OPERAND WAS A REGISTER + + MOV AL,BYTE PTR [REGMEM] + TEST AL,10000B ; SEGMENT REGISTER? + JZ NOTSEG + CMP BYTE PTR [MOVFLG],0 + JZ ERRV3 + MOV BYTE PTR [DI+1],10001100B + +NOTSEG: + AND AL,111B + SHL AL,1 + SHL AL,1 + SHL AL,1 + OR BYTE PTR [DI+2],AL +; ARR 2.4 +; In the case of the XCHG reg,reg and TEST reg,reg we have just built the +; instruction backwards. This is because these two instructions do not have +; the D bit. We need to switch R/S and REG +; +; Good comment Aaron, except that we do NOT switch if a memory operand was +; present for precisely the reason that the D bit is not present +; + CMP BYTE PTR [TSTFLG],0 + JZ NOSWITCH ; Not XCHG or TEST +; +; See if there is a memory operand specified. If the MOD field is 11, then +; we do perform the exchange. +; + MOV AH,[DI+2] + AND AH,MASKMOD + CMP AH,MASKMOD + JNZ NOSWITCH + MOV AH,BYTE PTR [DI+2] + AND AH,MASKRM + SHL AH,1 ; Low three bits to middle three + SHL AH,1 + SHL AH,1 + MOV AL,BYTE PTR [DI+2] + AND AL,MASKREG + SHR AL,1 ; Middle three to low three + SHR AL,1 + SHR AL,1 + OR AL,AH ; Re combine + AND BYTE PTR [DI+2],MASKMOD ; Zap original + OR BYTE PTR [DI+2],AL ; New low 6 bits +NOSWITCH: + + +; SPECIAL FORM OF THE EXCHANGE COMMAND + + CMP BYTE PTR [TSTFLG],2 + JNZ GRPEX + TEST BYTE PTR [DI+1],1 + JZ GRPEX + PUSH AX + MOV AL,BYTE PTR [DI+2] + AND AL,MASKMOD + CMP AL,MASKMOD ; MUST BE REGISTER TO REGISTER + POP AX + JB GRPEX + OR AL,AL + JZ SPECX + MOV AL,[DI+2] + AND AL,MASKRM + JNZ GRPEX + MOV CL,3 + SHR BYTE PTR [DI+2],CL +SPECX: + MOV AL,[DI+2] + AND AL,MASKRM + OR AL,10010000B + MOV BYTE PTR [DI+1],AL + DEC BYTE PTR [DI] + JMP SHORT GRPEX + +; SECOND OPERAND WAS A MEMORY REFERENCE + +GRP22: + CMP BYTE PTR [TSTFLG],0 + JNZ TST2 + OR BYTE PTR [DI+1],10B +TST2: + MOV AL,BYTE PTR [DI+2] + CMP AL,MASKMOD ; MUST BE A REGISTER + JB ASMERR + CMP BYTE PTR [SEGFLG],0 + JZ GRP223 + AND AL,00011000B + JMP SHORT GRP222 +GRP223: + AND AL,MASKRM + SHL AL,1 + SHL AL,1 + SHL AL,1 +GRP222: + OR AL,BYTE PTR [MODE] + OR AL,BYTE PTR [REGMEM] + MOV BYTE PTR [DI+2],AL + MOV AX,WORD PTR [LOWNUM] + MOV WORD PTR [DI+3],AX +GRPSIZ: + MOV BYTE PTR [DI],2 + MOV AL,BYTE PTR [DI+2] + AND AL,11000111B + CMP AL,00000110B + JZ GRP24 + AND AL,MASKMOD + CMP AL,01000000B + JZ GRP25 + CMP AL,10000000B + JNZ GRPEX +GRP24: + INC BYTE PTR [DI] +GRP25: + INC BYTE PTR [DI] + +GRPEX: + CMP BYTE PTR [MOVFLG],0 + JZ ASSEM_EXIT + +; TEST FOR SPECIAL FORM OF MOV AX,[MEM] OR MOV [MEM],AX + + MOV AL,[DI+1] ; GET OP-CODE + AND AL,11111100B + CMP AL,10001000B + JNZ ASSEM_EXIT + CMP BYTE PTR [DI+2],00000110B ; MEM TO AX OR AX TO MEM + JNZ ASSEM_EXIT + MOV AL,BYTE PTR [DI+1] + AND AL,11B + XOR AL,10B + OR AL,10100000B + MOV BYTE PTR [DI+1],AL + DEC BYTE PTR [DI] + MOV AX,[DI+3] + MOV WORD PTR [DI+2],AX + +ASSEM_EXIT: + CALL STUFF_BYTES + JMP ASSEMLOOP + +; Assem error. SI points to character in the input buffer +; which caused error. By subtracting from start of buffer, +; we will know how far to tab over to appear directly below +; it on the terminal. Then print "^ Error". + +ASMERR: + SUB SI,OFFSET DG:(BYTEBUF-10) ; How many char processed so far? + MOV CX,SI ; Parameter for TAB in CX + MOV DI,OFFSET DG:ARG_BUF + CALL TAB ; Directly below bad char + MOV BYTE PTR [DI],0 + MOV DX,OFFSET DG:SYNERR_PTR ; Error message + CALL PRINTF_CRLF + JMP ASSEMLOOP +; +; assemble the different parts into an instruction +; +BUILDIT: + MOV AL,BYTE PTR [AWORD] + OR AL,AL + JNZ BUILD1 +BLDERR: + JMP ASMERR + +BUILD1: + DEC AL + OR BYTE PTR [DI+1],AL ; SET THE SIZE + +BUILD2: + CMP BYTE PTR [NUMFLG],0 ; TEST FOR IMMEDIATE DATA + JZ BUILD3 + CMP BYTE PTR [MEMFLG],0 + JZ BLDERR + +BUILD3: + MOV AL,BYTE PTR [REGMEM] + CMP AL,-1 + JZ BLD1 + TEST AL,10000B ; TEST IF SEGMENT REGISTER + JZ BLD1 + CMP BYTE PTR [MOVFLG],0 + JZ BLDERR + MOV WORD PTR [DI+1],10001110B + INC BYTE PTR [MOVFLG] + INC BYTE PTR [SEGFLG] + AND AL,00000011B + SHL AL,1 + SHL AL,1 + SHL AL,1 + OR AL,MASKMOD + MOV BYTE PTR [DI+2],AL + RET + +BLD1: + AND AL,00000111B +BLD4: + OR AL,BYTE PTR [MODE] + OR AL,BYTE PTR [MIDFLD] + MOV BYTE PTR [DI+2],AL + MOV AX,WORD PTR [LOWNUM] + MOV WORD PTR [DI+3],AX + RET + +GETREGMEM: + MOV BYTE PTR [F8087],0 +GETREGMEM2: + CALL SCANP + XOR AX,AX + MOV WORD PTR [LOWNUM],AX ; OFFSET + MOV WORD PTR [DIFLG],AX ; DIFLG+SIFLG + MOV WORD PTR [BXFLG],AX ; BXFLG+BPFLG + MOV WORD PTR [NEGFLG],AX ; NEGFLG+NUMFLG + MOV WORD PTR [MEMFLG],AX ; MEMFLG+REGFLG + DEC AL + CMP BYTE PTR [F8087],0 + JZ PUTREG + MOV AL,1 ; DEFAULT 8087 REG IS 1 +PUTREG: + MOV BYTE PTR [REGMEM],AL + +GETLOOP: + MOV BYTE PTR [NEGFLG],0 +GETLOOP1: + MOV AX,WORD PTR [SI] + CMP AL,',' + JZ GOMODE + CMP AL,13 + JZ GOMODE + CMP AL,';' + JZ GOMODE + CMP AL,9 + JZ GETTB + CMP AL,' ' + JNZ GOGET +GETTB: + INC SI + JMP GETLOOP1 +GOGET: + JMP GETINFO + +; DETERMINE THE MODE BITS + +GOMODE: + MOV DI,OFFSET DG:ASSEM_CNT + MOV BYTE PTR [MODE],11000000B + MOV BYTE PTR [ASSEM_CNT],2 + CMP BYTE PTR [MEMFLG],0 + JNZ GOMODE1 + MOV AL,[NUMFLG] + OR AL,[REGFLG] + JNZ MORET + OR AL,[F8087] + JZ ERRET + MOV AL,[DI+1] + OR AL,[DIRFLG] + CMP AL,0DCH ; ARITHMETIC? + JNZ MORET + MOV BYTE PTR [DI+1],0DEH ; ADD POP TO NULL ARG 8087 +MORET: + RET +ERRET: + JMP ASMERR + +GOMODE1: + MOV BYTE PTR [MODE],0 + CMP BYTE PTR [NUMFLG],0 + JZ GOREGMEM + + MOV BYTE PTR [DI],4 + MOV AX,WORD PTR [DIFLG] + OR AX,WORD PTR [BXFLG] + JNZ GOMODE2 + MOV BYTE PTR [REGMEM],00000110B + RET + +GOMODE2: + MOV BYTE PTR [MODE],10000000B + CALL CHKSIZ1 + CMP CL,2 + JZ GOREGMEM + DEC BYTE PTR [DI] + MOV BYTE PTR [MODE],01000000B + +; DETERMINE THE REG-MEM BITS + +GOREGMEM: + MOV BX,WORD PTR [BXFLG] + MOV CX,WORD PTR [DIFLG] + XOR DX,DX +GOREG0: + MOV AL,BL ; BX + ADD AL,CH ; SI + CMP AL,2 + JZ GOGO + INC DL + MOV AL,BL + ADD AL,CL + CMP AL,2 + JZ GOGO + INC DL + MOV AL,BH + ADD AL,CH + CMP AL,2 + JZ GOGO + INC DL + MOV AL,BH + ADD AL,CL + CMP AL,2 + JZ GOGO + INC DL + OR CH,CH + JNZ GOGO + INC DL + OR CL,CL + JNZ GOGO + INC DL ; BP+DISP + OR BH,BH + JZ GOREG1 + CMP BYTE PTR [MODE],0 + JNZ GOGO + MOV BYTE PTR [MODE],01000000B + INC BYTE PTR [DI] + DEC DL +GOREG1: + INC DL ; BX+DISP +GOGO: + MOV BYTE PTR [REGMEM],DL + RET + +GETINFO: + CMP AX,'EN' ; NEAR + JNZ GETREG3 +GETREG0: + MOV DL,2 +GETRG01: + CALL SETSIZ1 +GETREG1: + CALL SCANS + MOV AX,WORD PTR [SI] + CMP AX,"TP" ; PTR + JZ GETREG1 + JMP GETLOOP + +GETREG3: + MOV CX,5 + MOV DI,OFFSET DG:SIZ8 + CALL CHKREG ; LOOK FOR BYTE, WORD, DWORD, ETC. + JZ GETREG41 + INC AL + MOV DL,AL + JMP GETRG01 + +GETREG41: + MOV AX,[SI] + CMP BYTE PTR [F8087],0 + JZ GETREG5 + CMP AX,"TS" ; 8087 STACK OPERAND + JNZ GETREG5 + CMP BYTE PTR [SI+2],',' + JNZ GETREG5 + MOV BYTE PTR [DIRFLG],0 + ADD SI,3 + JMP GETLOOP + +GETREG5: + CMP AX,"HS" ; SHORT + JZ GETREG1 + + CMP AX,"AF" ; FAR + JNZ GETRG51 + CMP BYTE PTR [SI+2],'R' + JNZ GETRG51 + ADD SI,3 + MOV DL,4 + JMP GETRG01 + +GETRG51: + CMP AL,'[' + JNZ GETREG7 +GETREG6: + INC BYTE PTR [MEMFLG] +GETREGADD: + INC SI + JMP GETLOOP + +GETREG7: + CMP AL,']' + JZ GETREG6 + CMP AL,'.' + JZ GETREG6 + CMP AL,'+' + JZ GETREGAdd + CMP AL,'-' + JNZ GETREG8 + INC BYTE PTR [NEGFLG] + INC SI + JMP GETLOOP1 + +GETREG8: ; LOOK FOR A REGISTER + CMP BYTE PTR [F8087],0 + JZ GETREGREG + CMP AX,"TS" + JNZ GETREGREG + CMP BYTE PTR [SI+2],'(' + JNZ GETREGREG + CMP BYTE PTR [SI+4],')' + JNZ ASMPOP + MOV AL,[SI+3] + SUB AL,'0' + JB ASMPOP + CMP AL,7 + JA ASMPOP + MOV [REGMEM],AL + INC BYTE PTR [REGFLG] + ADD SI,5 + CMP WORD PTR [SI],"S," + JNZ ZLOOP + CMP BYTE PTR [SI+2],'T' + JNZ ZLOOP + ADD SI,3 +ZLOOP: + JMP GETLOOP + +GETREGREG: + MOV CX,20 + MOV DI,OFFSET DG:REG8 + CALL CHKREG + JZ GETREG12 ; CX = 0 MEANS NO REGISTER + MOV BYTE PTR [REGMEM],AL + INC BYTE PTR [REGFLG] ; TELL EVERYONE WE FOUND A REG + CMP BYTE PTR [MEMFLG],0 + JNZ NOSIZE + CALL SETSIZ +INCSI2: + ADD SI,2 + JMP GETLOOP + +NOSIZE: + CMP AL,11 ; BX REGISTER? + JNZ GETREG9 + CMP WORD PTR [BXFLG],0 + JZ GETOK +ASMPOP: + JMP ASMERR + +GETOK: + INC BYTE PTR [BXFLG] + JMP INCSI2 +GETREG9: + CMP AL,13 ; BP REGISTER? + JNZ GETREG10 + CMP WORD PTR [BXFLG],0 + JNZ ASMPOP + INC BYTE PTR [BPFLG] + JMP INCSI2 +GETREG10: + CMP AL,14 ; SI REGISTER? + JNZ GETREG11 + CMP WORD PTR [DIFLG],0 + JNZ ASMPOP + INC BYTE PTR [SIFLG] + JMP INCSI2 +GETREG11: + CMP AL,15 ; DI REGISTER? + JNZ ASMPOP ; *** error + CMP WORD PTR [DIFLG],0 + JNZ ASMPOP + INC BYTE PTR [DIFLG] + JMP INCSI2 + +GETREG12: ; BETTER BE A NUMBER! + MOV BP,WORD PTR [ASMADD+2] + CMP BYTE PTR [MEMFLG],0 + JZ GTRG121 +GTRG119: + MOV CX,4 +GTRG120: + CALL GETHX + JMP SHORT GTRG122 +GTRG121: + MOV CX,2 + CMP BYTE PTR [AWORD],1 + JZ GTRG120 + CMP BYTE PTR [AWORD],CL + JZ GTRG119 + CALL GET_ADDRESS +GTRG122: + JC ASMPOP + MOV [HINUM],AX + CMP BYTE PTR [NEGFLG],0 + JZ GETREG13 + NEG DX +GETREG13: + ADD WORD PTR [LOWNUM],DX + INC BYTE PTR [NUMFLG] +GETLOOPV: + JMP GETLOOP + +CHKREG: + PUSH CX + INC CX + REPNZ SCASW + POP AX + SUB AX,CX + OR CX,CX + RET + +STUFF_BYTES: + PUSH SI + LES DI,DWORD PTR ASMADD + MOV SI,OFFSET DG:ASSEM_CNT + XOR AX,AX + LODSB + MOV CX,AX + JCXZ STUFFRET + REP MOVSB + MOV WORD PTR [ASMADD],DI +STUFFRET: + POP SI + RET + +SETSIZ: + MOV DL,1 + TEST AL,11000B ; 16 BIT OR SEGMENT REGISTER? + JZ SETSIZ1 + INC DL +SETSIZ1: + CMP BYTE PTR [AWORD],0 + JZ SETSIZ2 + CMP BYTE PTR [AWORD],DL + JZ SETSIZ2 +SETERR: + POP DX + JMP ASMPOP +SETSIZ2: + MOV BYTE PTR [AWORD],DL + RET + +; DETERMINE IF NUMBER IN AX:DX IS 8 BITS, 16 BITS, OR 32 BITS + +CHKSIZ: + MOV CL,4 + CMP AX,BP + JNZ RETCHK +CHKSIZ1: + MOV CL,2 + MOV AX,DX + CBW + CMP AX,DX + JNZ RETCHK + DEC CL +RETCHK: + RET + +; get first character after first space + +SCANS: + CMP BYTE PTR [SI],13 + JZ RETCHK + CMP BYTE PTR [SI],'[' + JZ RETCHK + LODSB + CMP AL,' ' + JZ SCANBV + CMP AL,9 + JNZ SCANS +SCANBV: + JMP SCANB + +; Set up for 8087 op-codes + +SETMID: + MOV BYTE PTR [ASSEM1],0D8H + MOV AH,AL + AND AL,111B ; SET MIDDLE BITS OF SECOND BYTE + SHL AL,1 + SHL AL,1 + SHL AL,1 + MOV [MIDFLD],AL + MOV AL,AH ; SET LOWER BITS OF FIRST BYTE + SHR AL,1 + SHR AL,1 + SHR AL,1 + OR [ASSEM1],AL + MOV BYTE PTR [F8087],1 ; INDICATE 8087 OPERAND + MOV BYTE PTR [DIRFLG],100B + RET + +; Set MF bits for 8087 op-codes + +SETMF: + MOV AL,[AWORD] + TEST BYTE PTR [DI+1],10B + JNZ SETMFI + AND BYTE PTR [DI+1],11111001B ; CLEAR MF BITS + CMP AL,3 ; DWORD? + JZ SETMFRET + CMP AL,4 ; QWORD? + JZ SETMFRET2 + TEST BYTE PTR [DI+1],1 + JZ SETMFERR + CMP AL,5 ; TBYTE? + JZ SETMFRET3 + JMP SHORT SETMFERR + +SETMFI: + CMP AL,3 ; DWORD? + JZ SETMFRET + CMP AL,2 ; WORD? + JZ SETMFRET2 + TEST BYTE PTR [DI+1],1 + JZ SETMFERR + CMP AL,4 ; QWORD? + JNZ SETMFERR + OR BYTE PTR [DI+1],111B +SETMFRET3: + OR BYTE PTR [DI+1],011B + OR BYTE PTR [DI+2],101000B + JMP SHORT SETMFRET +SETMFRET2: + OR BYTE PTR [DI+1],100B +SETMFRET: + RET + +SETMFERR: + JMP ASMPOP + + +DW_OPER: + MOV BP,1 + JMP SHORT DBEN + +DB_OPER: + XOR BP,BP +DBEN: + MOV DI,OFFSET DG:ASSEM_CNT + DEC BYTE PTR [DI] + INC DI +DB0: + XOR BL,BL + CALL SCANP + JNZ DB1 +DBEX: + JMP ASSEM_EXIT +DB1: + OR BL,BL + JNZ DB3 + MOV BH,BYTE PTR [SI] + CMP BH,"'" + JZ DB2 + CMP BH,'"' + JNZ DB4 +DB2: + INC SI + INC BL +DB3: + LODSB + CMP AL,13 + JZ DBEX + CMP AL,BH + JZ DB0 + STOSB + INC BYTE PTR [ASSEM_CNT] + JMP DB3 +DB4: + MOV CX,2 + CMP BP,0 + JZ DB41 + MOV CL,4 +DB41: + PUSH BX + CALL GETHX + POP BX + JNC DB5 + JMP ASMERR +DB5: + MOV AX,DX + CMP BP,0 + JZ DB6 + STOSW + INC BYTE PTR [ASSEM_CNT] + JMP SHORT DB7 +DB6: + STOSB +DB7: + INC BYTE PTR [ASSEM_CNT] + JMP DB0 + +; ORG pseudo op + +DOORG: + MOV BP,WORD PTR ASMADD+2 + CALL GET_ADDRESS + MOV WORD PTR ASMADD,DX + MOV WORD PTR ASMADD+2,AX + JMP ASSEMLOOP + +CODE ENDS + END ASSEM + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBCOM1.ASM b/v4.0/src/CMD/DEBUG/DEBCOM1.ASM new file mode 100644 index 0000000..fda97c0 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBCOM1.ASM @@ -0,0 +1,969 @@ + PAGE 60,132 ; + TITLE DEBCOM1.ASM - PART1 DEBUGGER COMMANDS PC DOS +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DECOM1.SAL +; +; DESCRIPTIVE NAME: DEBUGGING TOOL +; +; FUNCTION: PROVIDES USERS WITH A TOOL FOR DEBUGGING PROGRAMS. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: DEBCOM2 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBMES - CONTAINS ROUTINES CALLED BY DEBUG +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT DBCS HANDLING DMS:6/17/87 +; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87 +; - IMPLEMENT > 32MB SUPPORT DMS:6/17/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +;======================= END OF SPECIFICATIONS =========================== + +; Routines to perform debugger commands except ASSEMble and UASSEMble + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBCOM1 + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM +.CREF +.LIST + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + EXTRN SYNERR_PTR:BYTE + EXTRN DISPB:WORD,DSIZ:BYTE,DSSAVE:WORD + IF SYSVER + EXTRN CIN:DWORD,PFLAG:BYTE + ENDIF +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN DEFLEN:WORD,BYTEBUF:BYTE,DEFDUMP:BYTE + EXTRN ARG_BUF:BYTE,ARG_BUF_PTR:BYTE + EXTRN ONE_CHAR_BUF:BYTE,ONE_CHAR_BUF_PTR:WORD +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + PUBLIC HEXCHK,GETHEX1,PRINT,DSRANGE,ADDRESS,HEXIN,PERROR + PUBLIC GETHEX,GET_ADDRESS,GETEOL,GETHX,PERR + PUBLIC PERR,MOVE,DUMP,ENTERDATA,FILL,SEARCH,DEFAULT + IF SYSVER + PUBLIC IN + EXTRN DISPREG:NEAR,DEVIOCALL:NEAR + ENDIF + EXTRN CRLF:NEAR,OUTDI:NEAR,OUTSI:NEAR,SCANP:NEAR + EXTRN SCANB:NEAR,BLANK:NEAR,TAB:NEAR,COMMAND:NEAR + EXTRN HEX:NEAR,BACKUP:NEAR + EXTRN PRINTF_CRLF:NEAR,HEX_ADDRESS_ONLY:NEAR,HEX_ADDRESS_STR:NEAR + EXTRN STD_PRINTF:NEAR +DEBCOM1: +; RANGE - Looks for parameters defining an address range. +; The first parameter is the starting address. The second parameter +; may specify the ending address, or it may be preceded by +; "L" and specify a length (4 digits max), or it may be +; omitted and a length of 128 bytes is assumed. Returns with +; segment in AX, displacement in DX, and length in CX. +DSRANGE: + MOV BP,[DSSAVE] ; Set default segment to DS + MOV [DEFLEN],128 ; And default length to 128 bytes +RANGE: + CALL ADDRESS + + PUSH AX ; Save segment + PUSH DX ; Save offset + CALL SCANP ; Get to next parameter + + MOV AL,[SI] + CMP AL,UPPER_L ; Length indicator? + JE GETLEN + + MOV DX,[DEFLEN] ; Default length + CALL HEXIN ; Second parameter present? + + JC GETDEF ; If not, use default + + MOV CX,4 + CALL GETHEX ; Get ending address (same segment) + + MOV CX,DX ; Low 16 bits of ending addr. + POP DX ; Low 16 bits of starting addr. + SUB CX,DX ; Compute range + JAE DSRNG2 + +DSRNG1: + JMP PERROR ; Negative range +DSRNG2: + INC CX ; Include last location +; JCXZ DSRNG1 ; Wrap around error +; Removing this instruction allows 0 FFFF to valid range + POP AX ; Restore segment + RET +GETDEF: + POP CX ; get original offset + PUSH CX ; save it + NEG CX ; rest of segment + JZ RNGRET ; use default + + CMP CX,DX ; more room in segment? + JAE RNGRET ; yes, use default + + JMP RNGRET1 ; no, length is in CX + +GETLEN: + INC SI ; Skip over "L" to length + MOV CX,4 ; Length may have 4 digits + CALL GETHEX ; Get the range + +RNGRET: + MOV CX,DX ; Length +RNGRET1: + POP DX ; Offset + MOV AX,CX + ADD AX,DX + JNC OKRET + + CMP AX,1 + JAE DSRNG1 ; Look for wrap error + +OKRET: + POP AX ; Segment + RET +DEFAULT: +; DI points to default address and CX has default length + CALL SCANP + + JZ USEDEF ; Use default if no parameters + + MOV [DEFLEN],CX + CALL RANGE + + JMP GETEOL + +USEDEF: + MOV SI,DI + LODSW ; Get default displacement + MOV DX,AX + LODSW ; Get default segment + RET + +; Dump an area of memory in both hex and ASCII +DUMP: + MOV BP,[DSSAVE] + MOV CX,DISPB + MOV DI,OFFSET DG:DEFDUMP + CALL DEFAULT ; Get range if specified + + MOV DS,AX ; Set segment + ASSUME DS:NOTHING + + MOV SI,DX ; SI has displacement in segment + PUSH SI ; save SI away + MOV AL,DSIZ + XOR AH,AH + XOR AX,-1 + AND SI,AX ; convert to para number + MOV DI,OFFSET DG:ARG_BUF ; Build the output str in arg_buf + CALL OUTSI ; display location + + POP SI ; get SI back +; Determine where the registers display should begin. + MOV AX,SI ; move offset + MOV AH,3 ; spaces per byte + AND AL,DSIZ ; convert to real offset + MUL AH ; 3 char positions per byte of output + OR AL,AL ; at beginning? + JZ INROW ; if so, then no movement. + + PUSH CX + MOV CX,AX + CALL TAB + + POP CX +INROW: + PUSH SI ; Save address for ASCII dump +BYTE0: + CALL BLANK ; Space between bytes +BYTE1: + LODSB ; Get byte to dump + CALL HEX ; and display it + + POP DX ; DX has start addr. for ASCII dump + DEC CX ; Drop loop count + JZ ASCII ; If through do ASCII dump + + MOV AX,SI + TEST AL,DSIZ ; On row boundary? + JZ ENDROW + + PUSH DX ; Didn't need ASCII addr. yet + TEST AL,7 ; On 8-byte boundary? + JNZ BYTE0 + + MOV AL,CHAR_MINUS ; Mark every 8 bytes with "-" + STOSB + JMP SHORT BYTE1 + +ENDROW: + CALL ASCII ; Show it in ASCII + + MOV DI,OFFSET DG:ARG_BUF ; Build the output str in arg_buf + CALL OUTSI ; Get the address at start of line + + JMP INROW ; Loop until count is zero + +; Produce a dump of the ascii text characters. We take the current SI which +; contains the byte after the last one dumped. From this we determine how +; many spaces we need to output to get to the ascii column. Then we look at +; the beginning address of the dump to tsee how many spaces we need to indent. +ASCII: + PUSH CX ; Save count of remaining bytes +; Determine how many spaces to go until the ASCII column. + MOV AX,SI ; get offset of next byte + DEC AL + AND AL,DSIZ + INC AL +; AX now has the number of bytes that we have displayed: 1 to Dsiz+1. +; Compute characters remaining to be displayed. We *always* put the ASCII +; dump in column 51 (or whereever) + SUB AL,10H ; get negative of number + DEC AL ; + NEG AL ; convert to positive + CBW ; convert to word +; 3 character positions for each byte displayed. + MOV CX,AX + SHL AX,1 + ADD CX,AX +; Compute indent for ascii dump + MOV AX,DX + AND AL,DSIZ + XOR AH,AH + ADD CX,AX +; Tab over + CALL TAB + +; Set up for true dump + MOV CX,SI + MOV SI,DX + SUB CX,SI +ASCDMP: + LODSB ; Get ASCII byte to dump + CMP AL,CHAR_RUBOUT + JAE NOPRT ; Don't print RUBOUT or above + + CMP AL,CHAR_BLANK + JAE PRIN ; print space through RUBOUT-1 + +NOPRT: + MOV AL,CHAR_PERIOD ; If unprintable character +PRIN: + STOSB + LOOP ASCDMP ; CX times + MOV AL,0 + STOSB + PUSH DS + PUSH CS + POP DS + ASSUME DS:DG + + CALL HEX_ADDRESS_STR + + CALL CRLF + + POP DS + ASSUME DS:NOTHING + + POP CX ; Restore overall dump len + MOV WORD PTR [DEFDUMP],SI + MOV WORD PTR [DEFDUMP+WORD],DS ; Save last address as def + RET + + ASSUME DS:DG +; Block move one area of memory to another Overlapping moves are performed +; correctly, i.e., so that a source byte is not overwritten until after it has +; been moved. +MOVE: + CALL DSRANGE ; Get range of source area + + PUSH CX ; Save length + PUSH AX ; Save segment + PUSH DX ; Save source displacement + CALL ADDRESS ; Get destination address (sam + + CALL GETEOL ; Check for errors + + POP SI + MOV DI,DX ; Set dest. displacement + POP BX ; Source segment + MOV DS,BX + MOV ES,AX ; Destination segment + POP CX ; Length + CMP DI,SI ; Check direction of move + SBB AX,BX ; Extend the CMP to 32 bits + JB COPYLIST ; Move forward into lower mem. + +; Otherwise, move backward. Figure end of source and destination +; areas and flip direction flag. + DEC CX + ADD SI,CX ; End of source area + ADD DI,CX ; End of destination area + STD ; Reverse direction + INC CX +COPYLIST: + MOVSB ; Do at least 1 - Range is 1-1 + DEC CX + REP MOVSB ; Block move +RET1: + RET + +; Fill an area of memory with a list values. If the list +; is bigger than the area, don't use the whole list. If the +; list is smaller, repeat it as many times as necessary. +FILL: + CALL DSRANGE ; Get range to fill + + PUSH CX ; Save length + PUSH AX ; Save segment number + PUSH DX ; Save displacement + CALL LIST ; Get list of values to fill w + + POP DI ; Displacement in segment + POP ES ; Segment + POP CX ; Length + CMP BX,CX ; BX is length of fill list + MOV SI,OFFSET DG:BYTEBUF ; List is in byte buffer + JCXZ BIGRNG + + JAE COPYLIST ; If list is big, copy part of + +BIGRNG: + SUB CX,BX ; How much bigger is area than + XCHG CX,BX ; CX=length of list + PUSH DI ; Save starting addr. of area + REP MOVSB ; Move list into area + POP SI +; The list has been copied into the beginning of the +; specified area of memory. SI is the first address +; of that area, DI is the end of the copy of the list +; plus one, which is where the list will begin to repeat. +; All we need to do now is copy [SI] to [DI] until the +; end of the memory area is reached. This will cause the +; list to repeat as many times as necessary. + MOV CX,BX ; Length of area minus list + PUSH ES ; Different index register + POP DS ; requires different segment r + JMP SHORT COPYLIST ; Do the block move + +; Search a specified area of memory for given list of bytes. +; Print address of first byte of each match. +SEARCH: + CALL DSRANGE ; Get area to be searched + + PUSH CX ; Save count + PUSH AX ; Save segment number + PUSH DX ; Save displacement + CALL LIST ; Get search list + + DEC BX ; No. of bytes in list-1 + POP DI ; Displacement within segment + POP ES ; Segment + POP CX ; Length to be searched + SUB CX,BX ; minus length of list +SCAN: + MOV SI,OFFSET DG:BYTEBUF ; List kept in byte buffer + LODSB ; Bring first byte into AL +DOSCAN: + SCASB ; Search for first byte + LOOPNE DOSCAN ; Do at least once by using LO + + JNZ RET1 ; Exit if not found + + PUSH BX ; Length of list minus 1 + XCHG BX,CX + PUSH DI ; Will resume search here + REPE CMPSB ; Compare rest of string + MOV CX,BX ; Area length back in CX + POP DI ; Next search location + POP BX ; Restore list length + JNZ TTEST ; Continue search if no match + + DEC DI ; Match address + CALL OUTDI ; Print it + + INC DI ; Restore search address + CALL HEX_ADDRESS_ONLY ; Print the addresss + + CALL CRLF + +TTEST: + JCXZ RET1 + + JMP SHORT SCAN ; Look for next occurrence + +; Get the next parameter, which must be a hex number. +; CX is maximum number of digits the number may have. + +;========================================================================= +; GETHX: This routine calculates the binary representation of an address +; entered in ASCII by a user. GETHX has been modified to provide +; support for sector addresses > 32mb. To do this the bx register +; has been added to provide a 32 bit address. BX is the high word +; and DX is the low word. For routines that rely on DX for a 16 +; bit address, the use of BX will have no effect. +; +; Date : 6/16/87 +;========================================================================= + +GETHX: + CALL SCANP +GETHX1: + XOR DX,DX ; Initialize the number + xor bx,bx ;an000;initialize high word for + ; sector address + CALL HEXIN ; Get a hex digit + + JC HXERR ; Must be one valid digit + + MOV DL,AL ; First 4 bits in position +GETLP: + INC SI ; Next char in buffer + DEC CX ; Digit count + CALL HEXIN ; Get another hex digit? + + JC RETHX ; All done if no more digits + + STC + JCXZ HXERR ; Too many digits? + + + call ADDRESS_32_BIT ;an000;multiply by 32 + JMP SHORT GETLP ; Get more digits + +GETHEX: + CALL GETHX ; Scan to next parameter + + JMP SHORT GETHX2 + +GETHEX1: + CALL GETHX1 +GETHX2: + JC PERROR +RETHX: + CLC +HXERR: + RET + +; Check if next character in the input buffer is a hex digit +; and convert it to binary if it is. Carry set if not. +HEXIN: + MOV AL,[SI] +; Check if AL is a hex digit and convert it to binary if it +; is. Carry set if not. +HEXCHK: + SUB AL,CHAR_ZERO ; Kill ASCII numeric bias + JC RET2 + + CMP AL,10 + CMC + JNC RET2 ; OK if 0-9 + + AND AL,5FH + SUB AL,7 ; Kill A-F bias + CMP AL,10 + JC RET2 + + CMP AL,16 + CMC +RET2: + RET + +; Process one parameter when a list of bytes is +; required. Carry set if parameter bad. Called by LIST. +LISTITEM: + CALL SCANP ; Scan to parameter + + CALL HEXIN ; Is it in hex? + + JC STRINGCHK ; If not, could be a string + + MOV CX,2 ; Only 2 hex digits for bytes + push bx ;an000;save it - we stomp it + CALL GETHEX ; Get the byte value + pop bx ;an000;restore it + + MOV [BX],DL ; Add to list + INC BX +GRET: + CLC ; Parameter was OK + RET + +STRINGCHK: + MOV AL,[SI] ; Get first character of param + CMP AL,SINGLE_QUOTE ; String? + JZ STRING + + CMP AL,DOUBLE_QUOTE ; Either quote is all right + JZ STRING + + STC ; Not string, not hex - bad + RET +STRING: + MOV AH,AL ; Save for closing quote + INC SI +STRNGLP: + LODSB ; Next char of string + CMP AL,CR ; Check for end of line + JZ PERR ; Must find a close quote + + CMP AL,AH ; Check for close quote + JNZ STOSTRG ; Add new character to list + + CMP AH,[SI] ; Two quotes in a row? + JNZ GRET ; If not, we're done + + INC SI ; Yes - skip second one +STOSTRG: + MOV [BX],AL ; Put new char in list + INC BX + JMP SHORT STRNGLP ; Get more characters + +; Get a byte list for ENTER, FILL or SEARCH. Accepts any number +; of 2-digit hex values or character strings in either single +; (') or double (") quotes. +LIST: + MOV BX,OFFSET DG:BYTEBUF ; Put byte list in the byte buffer +LISTLP: + CALL LISTITEM ; Process a parameter + + JNC LISTLP ; If OK, try for more + + SUB BX,OFFSET DG:BYTEBUF ; BX now has no. of bytes in list + JZ PERROR ; List must not be empty + +; Make sure there is nothing more on the line except for +; blanks and carriage return. If there is, it is an +; unrecognized parameter and an error. +GETEOL: + CALL SCANB ; Skip blanks + + JNZ PERROR ; Better be a RETURN +RET3: + RET + +; Command error. SI has been incremented beyond the command letter so it must +; decremented for the error pointer to work. +PERR: + DEC SI +; Syntax error. SI points to character in the input buffer which caused +; error. By subtracting from start of buffer, we will know how far to tab +; over to appear directly below it on the terminal. Then print "^ Error". +PERROR: + SUB SI,OFFSET DG:(BYTEBUF-1) ; How many char processed so far? + MOV CX,SI ; Parameter for TAB in CX + MOV DI,OFFSET DG:ARG_BUF ; + CALL TAB ; Directly below bad char + + MOV BYTE PTR [DI],0 ; nul terminate the tab + MOV DX,OFFSET DG:SYNERR_PTR ; Error message +; Print error message and abort to command level +PRINT: + CALL PRINTF_CRLF + + JMP COMMAND + +; Gets an address in Segment:Displacement format. Segment may be omitted +; and a default (kept in BP) will be used, or it may be a segment +; register (DS, ES, SS, CS). Returns with segment in AX, OFFSET in DX. +ADDRESS: + CALL GET_ADDRESS + + JC PERROR + +ADRERR: + STC + RET + +GET_ADDRESS: + CALL SCANP + + MOV AL,[SI+1] + CMP AL,UPPER_S + JZ SEGREG + + MOV CX,4 + CALL GETHX + + JC ADRERR + + MOV AX,BP ; Get default segment + CMP BYTE PTR [SI],CHAR_COLON + JNZ GETRET + + PUSH DX +GETDISP: + INC SI ; Skip over ":" + MOV CX,4 + CALL GETHX + + POP AX + JC ADRERR + +GETRET: + CLC + RET + +SEGREG: + MOV AL,[SI] + MOV DI,OFFSET DG:SEGLET ; SEGLET DB "CSED" + MOV CX,4 + REPNE SCASB + JNZ ADRERR + + INC SI + INC SI + SHL CX,1 + MOV BX,CX + CMP BYTE PTR [SI],CHAR_COLON + JNZ ADRERR + + PUSH [BX+DSSAVE] + JMP SHORT GETDISP + +SEGLET DB "CSED" ; First letter of each of the segregs: CS,SS,ES,DS + +; Short form of ENTER command. A list of values from the +; command line are put into memory without using normal +; ENTER mode. +GETLIST: + CALL LIST ; Get the bytes to enter + + POP DI ; Displacement within segment + POP ES ; Segment to enter into + MOV SI,OFFSET DG:BYTEBUF ; List of bytes is in byte buffer + MOV CX,BX ; Count of bytes + REP MOVSB ; Enter that byte list + RET + +; Enter values into memory at a specified address. If the line contains +; nothing but the address we go into "enter mode", where the address and its +; current value are printed and the user may change it if desired. To change, +; type in new value in hex. Backspace works to correct errors. If an illegal +; hex digit or too many digits are typed, the bell is sounded but it is +; otherwise ignored. To go to the next byte (with or without change), hit +; space bar. To back CLDto a previous address, type "-". On every 8-byte +; boundary a new line is started and the address is printed. To terminate +; command, type carriage return. +; Alternatively, the list of bytes to be entered may be included on the +; original command line immediately following the address. This is in regular +; LIST format so any number of hex values or strings in quotes may be entered. +ENTERDATA: + MOV BP,[DSSAVE] ; Set default segment to DS + CALL ADDRESS + + PUSH AX ; Save for later + PUSH DX + CALL SCANB ; Any more parameters? + + JNZ GETLIST ; If not end-of-line get list + + POP DI ; Displacement of ENTER + POP ES ; Segment +GETROW: + CALL OUTDI ; Print address of entry + + PUSH DI + PUSH ES + PUSH DS + POP ES + MOV DI,OFFSET DG:ARG_BUF + CALL BLANK + + XOR AL,AL + STOSB + CALL HEX_ADDRESS_STR + + POP ES + POP DI +GETBYTE: + MOV AL,ES:[DI] ; Get current value + PUSH DI + PUSH ES + PUSH DS + POP ES + MOV DI,OFFSET DG:ARG_BUF + CALL HEX ; And display it + + MOV AL,CHAR_PERIOD + STOSB + XOR AL,AL + STOSB + MOV DX,OFFSET DG:ARG_BUF_PTR + CALL STD_PRINTF + + POP ES + POP DI +LOOK_AGAIN: + MOV CX,2 ; Max of 2 digits in new value + MOV DX,0 ; Intial new value +GETDIG: + CALL INPT ; Get digit from user + + MOV AH,AL ; Save + CALL HEXCHK ; Hex digit? + + XCHG AH,AL ; Need original for echo + JC NOHEX ; If not, try special command + + MOV DH,DL ; Rotate new value + MOV DL,AH ; And include new digit + LOOP GETDIG ; At most 2 digits + +; We have two digits, so all we will accept now is a command. +DWAIT: + CALL INPT ; Get command character +NOHEX: + CMP AL,CHAR_BACKSPACE ; Backspace + JZ BS + + CMP AL,CHAR_RUBOUT ; RUBOUT + JZ RUB + + CMP AL,CHAR_MINUS ; Back up to previous address + JZ PREV + + CMP AL,CR ; All done with command? + JZ EOL + + CMP AL,CHAR_BLANK ; Go to next address + JZ NEXT + + MOV AL,CHAR_BACKSPACE + CALL OUT_CHAR ; Back up over illegal character + + CALL BACKUP + + JCXZ DWAIT + + JMP SHORT GETDIG + +RUB: + MOV AL,CHAR_BACKSPACE + CALL OUT_char +BS: + CMP CL,2 ; CX=2 means nothing typed yet + JZ PUTDOT ; Put back the dot we backed up over + + INC CL ; Accept one more character + MOV DL,DH ; Rotate out last digit + MOV DH,CH ; Zero this digit + CALL BACKUP ; Physical backspace + + JMP SHORT GETDIG ; Get more digits + +PUTDOT: + MOV AL,CHAR_PERIOD + CALL OUT_CHAR + + JMP LOOK_AGAIN + +; If new value has been entered, convert it to binary and +; put into memory. Always bump pointer to next location +STORE: + CMP CL,2 ; CX=2 means nothing typed yet + JZ NOSTO ; So no new value to store + +; Rotate DH left 4 bits to combine with DL and make a byte value + PUSH CX + MOV CL,4 + SHL DH,CL + POP CX + OR DL,DH ; Hex is now converted to binary + MOV ES:[DI],DL ; Store new value +NOSTO: + INC DI ; Prepare for next location + RET + +NEXT: + CALL STORE ; Enter new value + + INC CX ; Leave a space plus two for + INC CX ; each digit not entered + PUSH DI + MOV DI,OFFSET DG:ARG_BUF + PUSH ES + PUSH DS + POP ES + CALL TAB + + XOR AL,AL + STOSB + MOV DX,OFFSET DG:ARG_BUF_PTR + CALL STD_PRINTF + + POP ES + POP DI + MOV AX,DI ; Next memory address + AND AL,7 ; Check for 8-byte boundary + JZ NEWROW ; Take 8 per line + + JMP GETBYTE + +NEWROW: + CALL CRLF ; Terminate line + + JMP GETROW ; Print address on new line + +PREV: + CALL STORE ; Enter the new value + +; DI has been bumped to next byte. Drop it 2 to go to previous addr + DEC DI + DEC DI + JMP SHORT NEWROW ; Terminate line after backing CLD + +EOL: + CALL STORE ; Enter the new value + + JMP CRLF ; CR/LF and terminate + +; Console input of single character + IF SYSVER +INPT: ;*** change for build - label to inpt + PUSH DS + PUSH SI + LDS SI,CS:[CIN] + MOV AH,4 + CALL DEVIOCALL + + POP SI + POP DS + CMP AL,3 + JNZ NOTCNTC + + INT VEC_CTRL_BREAK ;23H + +NOTCNTC: + CMP AL,UPPER_P - CHAR_AT_SIGN + JZ PRINTON + + CMP AL,UPPER_N - CHAR_AT_SIGN + JZ PRINTOFF + + CALL OUT_CHAR + + RET + +PRINTOFF: +PRINTON: + NOT [PFLAG] + JMP SHORT IN + + ELSE +INPT: ; Change label for build + MOV AH,Std_Con_Input ;OPTION=1, STANDARD CONSOLE INPUT + INT 21H + + RET + + ENDIF +OUT_CHAR: + PUSH DI + PUSH DX + PUSH ES + PUSH DS + POP ES + MOV DI,OFFSET DG:ONE_CHAR_BUF + STOSB + MOV AL,0 + STOSB + MOV DX,OFFSET DG:ONE_CHAR_BUF_PTR + CALL STD_PRINTF + + POP ES + POP DX + POP DI + RET + +;========================================================================= +; ADDRESS_32_BIT: This routine will build an address for 32bit sector +; addressibility. BX will be the high word, with DX being +; the low word. +; +; Inputs : DX/BX - registers to contain 32bit sector address +; DX & BX are both initialized to 0 on first call to routine. +; +; Outputs: DX/BX - registers to contain 32bit sector address +; +; Date : 6/16/87 +;========================================================================= + +ADDRESS_32_BIT proc near ;an000;perform 32 bit address + ; creation + push cx ;an000;save affected regs. + mov cx,04h ;an000;initialize to + ; nibble shift +; $do ;an000;while cx not= 0 +$$DO1: + cmp cx,00h ;an000;are we done? +; $leave e ;an000;yes, quit loop + JE $$EN1 + shl bx,1 ;an000;shift bx 1 bit + shl dx,1 ;an000;shift dx 1 bit +; $if c ;an000;did low word carry + JNC $$IF3 + or bx,01h ;an000;set bit 0 of high word +; $endif ;an000; +$$IF3: + dec cx ;an000;decrease counter +; $enddo ;an000;end while loop + JMP SHORT $$DO1 +$$EN1: + or dl, al ;an000;overlay low word + ; bits 0-3 with next + ; portion of the address + pop cx ;an000;restore affected regs. + + ret ;an000;return to caller + +ADDRESS_32_BIT endp ;an000;end proc + + + +CODE ENDS + END DEBCOM1 + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBCOM2.ASM b/v4.0/src/CMD/DEBUG/DEBCOM2.ASM new file mode 100644 index 0000000..b22795f --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBCOM2.ASM @@ -0,0 +1,1308 @@ + PAGE 60,132 ; + TITLE DEBCOM2.ASM - PART2 DEBUGGER COMMANDS PC DOS +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DECOM2.SAL +; +; DESCRIPTIVE NAME: DEBUGGING TOOL +; +; FUNCTION: PROVIDES USERS WITH A TOOL FOR DEBUGGING PROGRAMS. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: DEBCOM1 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBMES - CONTAINS ROUTINES CALLED BY DEBUG +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; AC000 VERSION 4.00 - +; +; - IMPLEMENT DBCS HANDLING DMS:6/17/87 +; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87 +; - IMPLEMENT > 32MB SUPPORT DMS:6/17/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +;======================= END OF SPECIFICATIONS =========================== + +; Routines to perform debugger commands except ASSEMble and UASSEMble + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBCOM2 + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM +.CREF +.LIST +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + EXTRN NOTFND_PTR:BYTE,NOROOM_PTR:BYTE,DRVLET:BYTE,ERRMES_PTR:BYTE + EXTRN NAMBAD_PTR:BYTE,NOSPACE_PTR:BYTE,TOOBIG_PTR:BYTE + EXTRN HEXERR_PTR:BYTE,HEXWRT_PTR:BYTE,ACCMES_PTR:BYTE + EXTRN EXEBAD_PTR:BYTE,EXEWRT_PTR:BYTE + EXTRN EXECEMES_PTR:BYTE,NONAMESPEC_PTR:BYTE + + EXTRN FLAGTAB:WORD,EXEC_BLOCK:BYTE,COM_LINE:DWORD,COM_FCB1:DWORD + EXTRN COM_FCB2:DWORD,COM_SSSP:DWORD,COM_CSIP:DWORD,RETSAVE:WORD + EXTRN NEWEXEC:BYTE,HEADSAVE:WORD + EXTRN REGTAB:BYTE,TOTREG:BYTE,NOREGL:BYTE + EXTRN USER_PROC_PDB:WORD,STACK:BYTE,RSTACK:WORD,AXSAVE:WORD + EXTRN BXSAVE:WORD,DSSAVE:WORD,ESSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD + EXTRN SSSAVE:WORD,CXSAVE:WORD,SPSAVE:WORD,FLSAVE:WORD + EXTRN SREG:BYTE,SEGTAB:WORD,REGDIF:ABS,RDFLG:BYTE + EXTRN REGTABEND:WORD + EXTRN NAMESPEC:BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN DEFDUMP:BYTE,TRANSADD:DWORD,INDEX:WORD,BUFFER:BYTE + EXTRN ASMADD:BYTE,DISADD:BYTE,NSEG:WORD + EXTRN SWITCHAR:BYTE,XNXCMD:BYTE,XNXOPT:BYTE + EXTRN AWORD:BYTE,EXTPTR:WORD,HANDLE:WORD,PARSERR:BYTE + EXTRN REG_NAME:WORD,REG_CONTENTS:WORD,REGISTER_PTR:BYTE + EXTRN ARG_BUF:BYTE,ARG_BUF_PTR:BYTE,LOC_ADD:WORD,LOC_PTR:BYTE + EXTRN BIG_CONTENTS:WORD,BIG_PTR:BYTE,LITTLE_CONTENTS:WORD,LITTLE_PTR:BYTE + EXTRN SINGLE_REG_ARG:WORD,CHANGE_FLAG_PTR:BYTE,DF_ERROR:BYTE + EXTRN BR_ERROR:BYTE,BF_ERROR:BYTE,SINGLE_REG_PTR:WORD + EXTRN WRT_ARG1:WORD,WRT_ARG2:WORD,WRTMES_PTR:BYTE,BEGSEG:WORD + EXTRN FILESTRT:WORD,FILEEND:WORD + EXTRN ERR_TYPE:BYTE ;ac000;converted to buffer + + extrn rel_read_write_tab:dword ;an000;primitive I/O + extrn rel_rw_add:dword ;an000;transfer address + extrn rel_low_sec:word ;an000;low sector word + extrn rel_high_sec:word ;an000;high sector word + extrn rel_sec_num:word ;an000;# of sectors + +fnd_dbcs db 0 +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + PUBLIC DEFIO,PREPNAME,DEBUG_FOUND + PUBLIC REG,LOAD + PUBLIC NAMED,DWRITE + PUBLIC DISPREG,ERR,DELIM1,DELIM2,delim0 + public getchrup,open1,open2,open3,open4,oc_file,opnret ;an001;bgb + public delete_a_file, parse_a_file, exec_a_file, open_a_file, create_a_file ;an001;bgb + public gcur,ifhex ;an001;bgb + public comtail ;an001;bgb + extrn test_lead:near ;an001;bgb + EXTRN OUTSI:NEAR,OUTDI:NEAR,INBUF:NEAR,SCANB:NEAR,SCANP:NEAR + EXTRN COMMAND:NEAR,DISASLN:NEAR,SET_TERMINATE_VECTOR:NEAR + EXTRN RESTART:NEAR,TERMINATE:NEAR,DRVERR:NEAR + EXTRN GETHEX:NEAR,GETEOL:NEAR,SKIP_FILE:NEAR + EXTRN HEXCHK:NEAR,GETHEX1:NEAR,PRINT:NEAR + EXTRN CRLF:NEAR,BLANK:NEAR + EXTRN HEX:NEAR,DIGIT:NEAR + EXTRN FIND_DEBUG:NEAR + EXTRN ADDRESS:NEAR,PERROR:NEAR + EXTRN STD_PRINTF:NEAR,PRINTF_CRLF:NEAR +DEBCOM2: +DISPLAY_LINE: + mov ax,word ptr [si] ;an000;move reg name to ax + MOV [REG_NAME],ax ;ac000;save it in reg_name + ADD SI,3 + MOV AX,[BX] + ADD BX,2 + MOV [REG_CONTENTS],AX + MOV DX,OFFSET DG:REGISTER_PTR + CALL STD_PRINTF + + LOOP DISPLAY_LINE + + RETURN + +DISPLAY_FLAGS: + MOV DI,OFFSET DG:ARG_BUF + MOV AL,CHAR_BLANK + STOSB +DISPLAY_FLAGS_2: + MOV SI,OFFSET DG:FLAGTAB + MOV CX,16 + MOV DX,[FLSAVE] +DFLAGS: + LODS CS:WORD PTR [SI] + SHL DX,1 + JC FLAGSET + + MOV AX,CS:[SI+30] +FLAGSET: + OR AX,AX + JZ NEXT_FLAG + + STOSW + MOV AL,CHAR_BLANK + STOSB +NEXT_FLAG: + LOOP DFLAGS + XOR AL,AL + STOSB + RETURN + +DISPREG: + MOV SI,OFFSET DG:REGTAB + MOV DI,OFFSET DG:ARG_BUF + MOV BX,OFFSET DG:AXSAVE + MOV BYTE PTR TOTREG,CR + MOV CH,0 + MOV CL,NOREGL +SET_DISPLAY: +REPEAT_DISPLAY: + SUB TOTREG,CL + CALL DISPLAY_LINE + + CALL CRLF + + XOR CH,CH + MOV CL,NOREGL + CMP CL,TOTREG + JB REPEAT_DISPLAY + + MOV CL,TOTREG + CALL DISPLAY_LINE + + CALL DISPLAY_FLAGS + + MOV DX,OFFSET DG:ARG_BUF_PTR + CALL PRINTF_CRLF + + MOV AX,[IPSAVE] + MOV WORD PTR [DISADD],AX + PUSH AX + MOV AX,[CSSAVE] + MOV WORD PTR [DISADD+WORD],AX + PUSH AX + MOV [NSEG],-1 + CALL DISASLN + + POP WORD PTR DISADD+WORD + POP WORD PTR DISADD + MOV AX,[NSEG] + CMP AL,-1 + JNZ ASSEM_LIN_CONT + + JMP CRLF + +ASSEM_LIN_CONT: + CMP AH,-1 + JZ NOOVER + + XCHG AL,AH +NOOVER: + CBW + MOV BX,AX + SHL BX,1 + MOV AX,WORD PTR [BX+SREG] + MOV DI,OFFSET DG:ARG_BUF + STOSB + XCHG AL,AH + STOSB + XOR AL,AL + STOSB + MOV DX,[INDEX] + MOV LOC_ADD,DX + MOV DX,OFFSET DG:LOC_PTR + CALL STD_PRINTF + + MOV BX,[BX+SEGTAB] + PUSH DS + MOV DS,[BX] + MOV BX,CS:[INDEX] + MOV BX,[BX] + POP DS + MOV BIG_CONTENTS,BX + MOV DX,OFFSET DG:BIG_PTR + TEST BYTE PTR [AWORD],-1 + JNZ SHOW_CHARS + + XOR BH,BH + MOV LITTLE_CONTENTS,BX + MOV DX,OFFSET DG:LITTLE_PTR +SHOW_CHARS: + CALL PRINTF_CRLF + + RETURN + +DISPREGJ: + JMP DISPREG + +; Perform register dump if no parameters or set register if a +; register designation is a parameter. +REG: + CALL SCANP + + JZ DISPREGJ + + MOV DL,[SI] + INC SI + MOV DH,[SI] + CMP DH,CR + JZ FLAG + + INC SI + CALL GETEOL + + CMP DH,CHAR_BLANK + JZ FLAG + + MOV DI,OFFSET DG:REGTAB + XCHG AX,DX + PUSH CS + POP ES + XOR CX,CX +CHECK_NEXT_REG: + CMP AX,WORD PTR[ DI] + JZ REG_FOUND + + ADD DI,3 + INC CX + CMP DI,OFFSET DG:REGTABEND + JB CHECK_NEXT_REG + + JMP BADREG + +REG_FOUND: + CMP DI,OFFSET DG:REGTABEND + JNZ NOTPC + + DEC DI + DEC DI + DEC DI + MOV AX,CS:[DI-WORD] +NOTPC: + PUSH DI + MOV DI,OFFSET DG:ARG_BUF + STOSB + XCHG AL,AH + STOSB + XOR AL,AL + STOSB + POP DI + PUSH DS + POP ES + LEA BX,[DI+REGDIF] + SUB BX,CX + MOV DX,[BX] + MOV SINGLE_REG_ARG,DX + MOV DX,OFFSET DG:SINGLE_REG_PTR + CALL STD_PRINTF + + CALL INBUF + + CALL SCANB + + RETZ + + push bx ;an000;save bx - we stomp it + MOV CX,4 + CALL GETHEX1 + pop bx ;an000;restore it + + CALL GETEOL + + MOV [BX],DX + RETURN +BADREG: + MOV DX,OFFSET DG:BR_ERROR ; BR ERROR + JMP ERR + +FLAG: + CMP DL,UPPER_F + JNZ BADREG + + MOV DI,OFFSET DG:ARG_BUF + CALL DISPLAY_FLAGS_2 + + MOV DX,OFFSET DG:CHANGE_FLAG_PTR + CALL STD_PRINTF + + CALL INBUF + + CALL SCANB + + XOR BX,BX + MOV DX,[FLSAVE] +GETFLG: + LODSW + CMP AL,CR + JZ SAVCHG + + CMP AH,CR + JZ FLGERR + + MOV DI,OFFSET DG:FLAGTAB + MOV CX,32 + PUSH CS + POP ES + REPNE SCASW + JNZ FLGERR + + MOV CH,CL + AND CL,0FH + MOV AX,1 + ROL AX,CL + TEST AX,BX + JNZ REPFLG + + OR BX,AX + OR DX,AX + TEST CH,16 + JNZ NEXFLG + + XOR DX,AX +NEXFLG: + CALL SCANP + + JMP SHORT GETFLG + +REPFLG: + MOV DX,OFFSET DG:DF_ERROR ; DF ERROR +FERR: + CALL SAVCHG +ERR: + push si ;an000;save affected registers + push di ;an000; + push cx ;an000; + mov cx,03h ;an000;move only three bytes + mov di,offset dg:err_type ;an000;point to buffer + mov si,dx ;an000;dx holds the string + rep movsb ;an000;fill up the buffer + pop cx ;an000;restore registers + pop di ;an000; + pop si ;an000; + MOV DX,OFFSET DG:ERRMES_PTR + JMP PRINT + +SAVCHG: + MOV [FLSAVE],DX + RETURN + +FLGERR: + MOV DX,OFFSET DG:BF_ERROR ; BF ERROR + JMP SHORT FERR + +PREPNAME: + MOV ES,DSSAVE + PUSH SI + MOV DI,81H +COMTAIL: + LODSB + STOSB + CMP AL,CR + JNZ COMTAIL + + SUB DI,82H + XCHG AX,DI + MOV ES:(BYTE PTR [80H]),AL + POP SI + MOV DI,FCB ;05cH + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR SET_DRIVEID_OPTION ;AL=01H + INT 21H + + MOV BYTE PTR [AXSAVE],AL ; Indicate analysis of first parm + CALL SKIP_FILE + + MOV DI,6CH + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR SET_DRIVEID_OPTION ;AL=01H + INT 21H + + MOV BYTE PTR [AXSAVE+1],AL ; Indicate analysis of second parm + RETURN + +; OPENS A XENIX PATHNAME SPECIFIED IN THE UNFORMATTED PARAMETERS +; VARIABLE [XNXCMD] SPECIFIES WHICH COMMAND TO OPEN IT WITH + +; VARIABLE [HANDLE] CONTAINS THE HANDLE +; VARIABLE [EXTPTR] POINTS TO THE FILES EXTENSION +DELETE_A_FILE: + MOV BYTE PTR [XNXCMD],UNLINK + JMP SHORT OC_FILE + +PARSE_A_FILE: + MOV BYTE PTR [XNXCMD],0 + JMP SHORT OC_FILE + +EXEC_A_FILE: + MOV BYTE PTR CS:[XNXCMD],EXEC + MOV BYTE PTR CS:[XNXOPT],1 + JMP SHORT OC_FILE + +OPEN_A_FILE: + MOV BYTE PTR [XNXCMD],OPEN + MOV BYTE PTR [XNXOPT],2 ; Try read write + CALL OC_FILE + + RETNC + MOV BYTE PTR [XNXCMD],OPEN + MOV BYTE PTR [XNXOPT],0 ; Try read only + JMP SHORT OC_FILE + +CREATE_A_FILE: + MOV BYTE PTR [XNXCMD],CREAT +OC_FILE: + PUSH DS + PUSH ES + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + XOR AX,AX + MOV CS:[EXTPTR],AX ; INITIALIZE POINTER TO EXTENSIONS + MOV AH,CHAR_OPER + INT 21H + + MOV CS:[SWITCHAR],DL ; GET THE CURRENT SWITCH CHARACTER + MOV SI,81H + +open1: CALL GETCHRUP ;convert 1 byte to uppercase + CALL DELIM2 ; END OF LINE? + JZ OPEN4 + + CALL DELIM1 ; SKIP LEADING DELIMITERS + JZ OPEN1 + + MOV DX,SI ; SAVE POINTER TO BEGINNING + cmp fnd_dbcs,1 +; $if z + JNZ $$IF1 + dec dx ;dec it twice if dbcs +; $endif +$$IF1: + DEC DX +open2: CMP AL,CHAR_PERIOD ; LAST CHAR A "."? + JNZ OPEN3 + + MOV CS:[EXTPTR],SI ; SAVE POINTER TO THE EXTENSION +OPEN3: + CALL GETCHRUP + + CALL DELIM1 ; LOOK FOR END OF PATHNAME + + JZ OPEN4 + + CALL DELIM2 + + JNZ OPEN2 + +OPEN4: DEC SI ; POINT BACK TO LAST CHAR + PUSH [SI] ; SAVE TERMINATION CHAR + MOV BYTE PTR [SI],0 ; NULL TERMINATE THE STRING + MOV AL,CS:[XNXOPT] + MOV AH,CS:[XNXCMD] ; OPEN OR CREATE FILE + OR AH,AH + JZ OPNRET + + MOV CS:[FILESTRT],DX ; Set values for later call on this file + MOV CS:[FILEEND],SI + PUSH CS + POP ES ; Set ES seg for EXEC_BLOCK + MOV BX,OFFSET DG:EXEC_BLOCK + XOR CX,CX + INT 21H + + MOV CS:[HANDLE],AX ; SAVE ERROR CODE OR HANDLE +OPNRET: + POP [SI] + POP SI + POP DX + POP CX + POP BX + POP AX ; blow away error code... + POP ES + POP DS + RETURN + +GETCHRUP: ;an001;bgb + lodsb ;get the character from [si] ;an001;bgb + call test_lead ;is it a dbcs lead byte? ;an001;bgb +; $IF C ;yes ;an001;bgb + JNC $$IF3 + inc si ;bump ptr to past 2nd dbcs byte ;an001;bgb + mov fnd_dbcs,1 ;found a dbcs char + jmp gcur ;dont capitalize it ;an001;bgb +; $ENDIF ;an001;bgb +$$IF3: + ; ;an001;bgb + mov fnd_dbcs,0 ;did not find a dbcs char + cmp al,lower_a ;is it >= "a" ? ;an001;bgb + jb gcur ;no - exit ;an001;bgb + ;an001;bgb + cmp al,lower_z ;is it =< "z" ? ;an001;bgb + ja gcur ;no - exit ;an001;bgb + ;an001;bgb +;if we get here, the char is lowercase, so change it ;an001;bgb + sub al,32 ;convert to uppercase ;an001;bgb + mov [si-1],al ;move it back (si points 1 past) ;an001;bgb +gcur: return ;an001;bgb + +DELIM0: + CMP AL,CHAR_LEFT_BRACKET + RETZ +DELIM1: + CMP AL,CHAR_BLANK ; SKIP THESE GUYS + RETZ + + CMP AL,CHAR_SEMICOLON + RETZ + + CMP AL,CHAR_EQUAL + RETZ + + CMP AL,CHAR_TAB + RETZ + + CMP AL,CHAR_COMMA + RETURN + +DELIM2: + CMP AL,CS:[SWITCHAR] ; STOP ON THESE GUYS + RETZ + + CMP AL,CR + RETURN + +NAMED: + OR [NAMESPEC],1 ; Flag a name command executed + CALL PREPNAME + + MOV AL,BYTE PTR AXSAVE + MOV PARSERR,AL + PUSH ES + POP DS + PUSH CS + POP ES + MOV SI,FCB ; DS:SI points to user FCB + MOV DI,SI ; ES:DI points to DEBUG FCB + MOV CX,82 + REP MOVSW + RETURN + +BADNAM: + MOV DX,OFFSET DG:NAMBAD_PTR + JMP RESTART + +IFHEX: + CMP BYTE PTR [PARSERR],-1 ; Invalid drive specification? + JZ BADNAM + + CALL PARSE_A_FILE + + MOV BX,[EXTPTR] + CMP WORD PTR DS:[BX],"EH" ; "HE" + RETNZ + + CMP BYTE PTR DS:[BX+WORD],UPPER_X + RETURN + +IFEXE: + PUSH BX + MOV BX,[EXTPTR] + CMP WORD PTR DS:[BX],"XE" ; "EX" + JNZ RETIF + + CMP BYTE PTR DS:[BX+WORD],UPPER_E +RETIF: + POP BX + RETURN + +LOAD: + MOV BYTE PTR [RDFLG],READ + JMP SHORT DSKIO + +DWRITE: + MOV BYTE PTR [RDFLG],WRITE +DSKIO: + MOV BP,[CSSAVE] + CALL SCANB + + JNZ PRIMIO + + JMP DEFIO + +PRIMIO: + CALL ADDRESS + + CALL SCANB + + JNZ PRMIO + + JMP FILEIO + +;========================================================================= +; PRMIO: This routine builds the necessary table for the new +; generic IOCtl primitive read/write logical sector function. +; +; Inputs : Binary addresses and values converted by GETHEX +; +; Outputs: REL_READ_WRITE_TAB - Table needed by IOCtl function to +; perform 32 bit sector addressing. +; +; Date : 6/17/87 +;========================================================================= + +PRMIO: + mov word ptr dg:[rel_rw_add],dx ;ac000;save transfer address + ; in table + mov word ptr dg:[rel_rw_add+2],ax ;ac000;save segment of transfer + ; address + MOV CX,2 + CALL GETHEX ; Drive number must be 2 digits or less + + PUSH DX ;save drive number + MOV CX,8 ;ac000;allow 32 bit addressibilty + CALL GETHEX ; Logical record number + mov word ptr dg:[rel_low_sec],dx ;ac000;save low word of logical + ; sector address + mov word ptr dg:[rel_high_sec],bx ;ac000;save high word of + ; logical sector address + + MOV CX,3 + CALL GETHEX ; Number of records + mov word ptr dg:[rel_sec_num],dx ;ac000;save number of sectors + ; to read/write + + CALL GETEOL + + POP BX ;ac000;drive number + CBW ; Turn off verify after write + MOV BYTE PTR DRVLET,bl ;ac000;save drive in case of error + PUSH BX + MOV DL,bL ;ac000;move drive to dl +; Clean off the buffer cache for physical I/O + push ds + MOV AH,DISK_RESET + INT 21H + + INC DL + MOV AH,GET_DPB + INT 21H + pop ds + + or al,al ;ac000;see if an error occurred + pop ax ;ac000;restore drive + + JNZ DRVERRJ + + CMP CS:BYTE PTR [RDFLG],WRITE +; $if z ;an000;we will write to sector(s) + JNZ $$IF5 + call ABSWRT ;an000;logical sector write +; $else ;an000; + JMP SHORT $$EN5 +$$IF5: + call ABSREAD ;an000;we will read sector(s) +; $endif ;an000; +$$EN5: + + +ENDABS: + JNC RET0 + +DRVERRJ: + JMP DRVERR + +RET0: +; Clean cache again... + MOV AH,DISK_RESET + INT 21H + + RETURN + + +;called from debug.sal +DEFIO: + MOV AX,[CSSAVE] ; Default segment + MOV DX,100H ; Default file I/O offset + CALL IFHEX + JNZ EXECHK + XOR DX,DX ; If HEX file, default OFFSET is zero +HEX2BINJ: + JMP HEX2BIN + +FILEIO: +; AX and DX have segment and offset of transfer, respectively + CALL IFHEX + JZ HEX2BINJ + +EXECHK: + CALL IFEXE + JNZ BINFIL + CMP BYTE PTR [RDFLG],READ + JZ EXELJ + MOV DX,OFFSET DG:EXEWRT_PTR + JMP RESTART ; Can't write .EXE files + +BINFIL: + CMP BYTE PTR [RDFLG],WRITE + JZ BINLOAD + CMP WORD PTR DS:[BX],4F00H + UPPER_C ;"CO" + JNZ BINLOAD + CMP BYTE PTR DS:[BX+WORD],UPPER_M + JNZ BINLOAD + +EXELJ: + DEC SI + CMP DX,100H + JNZ PRER + + CMP AX,[CSSAVE] + JZ OAF + +PRER: + JMP PERROR + +OAF: + CALL OPEN_A_FILE + + JNC GDOPEN + + MOV AX,ERROR_FILE_NOT_FOUND + JMP EXECERR + +GDOPEN: + XOR DX,DX + XOR CX,CX + MOV BX,[HANDLE] + MOV AL,2 + MOV AH,LSEEK + INT 21H + + CALL IFEXE ; SUBTRACT 512 BYTES FOR EXE + + JNZ BIN2 ; FILE LENGTH BECAUSE OF + + SUB AX,512 ; THE HEADER +BIN2: + MOV [BXSAVE],DX ; SET UP FILE SIZE IN DX:AX + MOV [CXSAVE],AX + MOV AH,CLOSE + INT 21H + + JMP EXELOAD + +NO_MEM_ERR: + MOV DX,OFFSET DG:TOOBIG_PTR + CALL PRINTF_CRLF + + JMP COMMAND + +WRTFILEJ: + JMP WRTFILE +NOFILEJ: + JMP NOFILE + +BINLOAD: + PUSH AX + PUSH DX + CMP BYTE PTR [RDFLG],WRITE + JZ WRTFILEJ + + CALL OPEN_A_FILE + + JC NOFILEJ + + MOV BX,[HANDLE] + MOV AX,(LSEEK SHL 8) OR LSEEK_EOF_OPTION + XOR DX,DX ;CX:DX=DISTANCE (OFFSET) TO MOVE IN BYTES + MOV CX,DX + INT 21H ; GET SIZE OF FILE + + MOV SI,DX + MOV DI,AX ; SIZE TO SI:DI + MOV AX,(LSEEK SHL 8) OR LSEEK_FROM_START + XOR DX,DX + MOV CX,DX + INT 21H ; RESET POINTER BACK TO BEGINNING + + POP AX + POP BX + PUSH BX + PUSH AX ; TRANS ADDR TO BX:AX + ADD AX,15 + RCR AX,1 + MOV CL,3 + MOV CL,4 + SHR AX,CL + ADD BX,AX ; Start of transfer rounded up to seg + MOV DX,SI + MOV AX,DI ; DX:AX is size + cmp dx,10h + jnc no_mem_err + MOV CX,16 + DIV CX + OR DX,DX + JZ NOREM + + INC AX +NOREM: ; AX is number of paras in transfer + ADD AX,BX ; AX is first seg that need not exist + jc no_mem_err + CMP AX,CS:[PDB_BLOCK_LEN] + JA NO_MEM_ERR + + MOV CXSAVE,DI + MOV BXSAVE,SI + POP DX + POP AX +; AX:DX is disk transfer address (segment:offset) +; SI:DI is length (32-bit number) +RDWR: +RDWRLOOP: + MOV BX,DX ; Make a copy of the offset + AND DX,000FH ; Establish the offset in 0H-FH range + MOV CL,4 + SHR BX,CL ; Shift offset and + ADD AX,BX ; Add to segment register to get new Seg:offset + PUSH AX + PUSH DX ; Save AX,DX register pair + MOV WORD PTR [TRANSADD],DX + MOV WORD PTR [TRANSADD+WORD],AX + MOV CX,0FFF0H ; Keep request in segment + OR SI,SI ; Need > 64K? + JNZ BIGRDWR + + MOV CX,DI ; Limit to amount requested +BIGRDWR: + PUSH DS + PUSH BX + MOV BX,[HANDLE] + MOV AH,[RDFLG] + LDS DX,[TRANSADD] + INT 21H ; Perform read or write + + POP BX + POP DS + JC BADWR + + CMP BYTE PTR [RDFLG],WRITE + JNZ GOODR + + CMP CX,AX + JZ GOODR + +BADWR: + MOV CX,AX + STC + POP DX ; READ OR WRITE BOMBED OUT + POP AX + RETURN + +GOODR: + MOV CX,AX + SUB DI,CX ; Request minus amount transferred + SBB SI,0 ; Ripple carry + OR CX,CX ; End-of-file? + POP DX ; Restore DMA address + POP AX + JZ DOCLOSE + + ADD DX,CX ; Bump DMA address by transfer length + MOV BX,SI + OR BX,DI ; Finished with request + JNZ RDWRLOOP + +DOCLOSE: + SAVEREG + MOV BX,HANDLE + MOV AH,CLOSE + INT 21H + + RESTOREREG + RETURN + +NOFILE: + MOV DX,OFFSET DG:NOTFND_PTR + JMP RESTART + +NO_NAME_GIVEN: + MOV DX,OFFSET DG:NONAMESPEC_PTR +RESTARTJMP: + JMP RESTART + +WRTFILE: + CMP [NAMESPEC],0 + JZ NO_NAME_GIVEN ; Hey User, you forgot to specify a name + + CALL CREATE_A_FILE ; Create file we want to write to + + JC CHECKREADONLY ; ARR 2.4 + + MOV SI,BXSAVE ; Get high order number of bytes to transfer + CMP SI,000FH + JLE WRTSIZE ; Is bx less than or equal to FH + + XOR SI,SI ; Ignore BX if greater than FH - set to zero +WRTSIZE: + MOV WRT_ARG2,SI + MOV DI,CXSAVE + MOV WRT_ARG1,DI + MOV DX,OFFSET DG:WRTMES_PTR + CALL PRINTF_CRLF + + POP DX + POP AX + CALL RDWR + + JNC CLSFLE + + CALL CLSFLE + + CALL DELETE_A_FILE + + MOV DX,OFFSET DG:NOSPACE_PTR + JMP RESTARTJMP + + CALL CLSFLE ;is this dead code? - edk + + JMP COMMAND + +CHECKREADONLY: ; ARR 2.4 + MOV DX,[FILESTRT] + MOV SI,[FILEEND] + PUSH [SI] + MOV BYTE PTR [SI],0 + MOV AX,CHMOD SHL 8 ;AL=0,REQUEST FILE'S CURRENT + ; ATTRIBUTE BE RETURNED IN CX + INT 21H + + POP [SI] + MOV DX,OFFSET DG:NOROOM_PTR ; Creation error - report error + JC RESTARTJMP + + TEST CX,ATTR_READ_ONLY+ATTR_HIDDEN+ATTR_SYSTEM + JZ RESTARTJMP + + MOV DX,OFFSET DG:ACCMES_PTR ; Write on read only file + JMP RESTARTJMP + +CLSFLE: + MOV AH,CLOSE + MOV BX,[HANDLE] + INT 21H + + RETURN + +EXELOAD: + POP [RETSAVE] ; Suck up return addr + INC BYTE PTR [NEWEXEC] + MOV BX,[USER_PROC_PDB] + MOV AX,BEGSEG + MOV DS,AX + ASSUME DS:NOTHING + + CMP AX,BX + JZ DEBUG_CURRENT + + JMP FIND_DEBUG + +DEBUG_CURRENT: + MOV AX,CS:[DSSAVE] +DEBUG_FOUND: + MOV CS:BYTE PTR [NEWEXEC],0 + MOV CS:[HEADSAVE],AX + PUSH CS:[RETSAVE] ; Get the return address back + PUSH AX + MOV BX,CS + SUB AX,BX + PUSH ES + MOV ES,CS:BEGSEG + ASSUME ES:NOTHING + + MOV BX,AX ; size of debug in para. + ADD BX,10H + MOV AX,CS ; and the size of printf in para. + SUB AX,CS:BEGSEG + ADD BX,AX + MOV AH,SETBLOCK + INT 21H + + POP ES + POP AX + MOV CS:WORD PTR [COM_LINE+WORD],AX + MOV CS:WORD PTR [COM_FCB1+WORD],AX + MOV CS:WORD PTR [COM_FCB2+WORD],AX + PUSH DS + PUSH CS + POP DS + CALL EXEC_A_FILE + + POP DS + MOV AX,CS:[HANDLE] + JC EXECERR + + CALL SET_TERMINATE_VECTOR ; Reset int 22 + + MOV AH,GET_CURRENT_PDB + INT 21H + + MOV CS:[USER_PROC_PDB],BX + MOV CS:[DSSAVE],BX + MOV CS:[ESSAVE],BX + MOV ES,BX + MOV WORD PTR ES:[PDB_EXIT],OFFSET DG:TERMINATE + MOV WORD PTR ES:[PDB_EXIT+WORD],CS + LES DI,CS:[COM_CSIP] + MOV CS:[CSSAVE],ES + MOV CS:[IPSAVE],DI + MOV CS:WORD PTR [DISADD+WORD],ES + MOV CS:WORD PTR [DISADD],DI + MOV CS:WORD PTR [ASMADD+WORD],ES + MOV CS:WORD PTR [ASMADD],DI + MOV CS:WORD PTR [DEFDUMP+WORD],ES + MOV CS:WORD PTR [DEFDUMP],DI + MOV BX,DS + MOV AH,SET_CURRENT_PDB + INT 21H + + LES DI,CS:[COM_SSSP] + MOV AX,ES:[DI] + INC DI + INC DI + MOV CS:[AXSAVE],AX + MOV CS:[SSSAVE],ES + MOV CS:[SPSAVE],DI + RETURN + +EXECERR: + PUSH CS + POP DS + MOV DX,OFFSET DG:NOTFND_PTR + CMP AX,ERROR_FILE_NOT_FOUND + JZ GOTEXECEMES + + MOV DX,OFFSET DG:ACCMES_PTR + CMP AX,ERROR_ACCESS_DENIED + JZ GOTEXECEMES + + MOV DX,OFFSET DG:TOOBIG_PTR + CMP AX,ERROR_NOT_ENOUGH_MEMORY + JZ GOTEXECEMES + + MOV DX,OFFSET DG:EXEBAD_PTR + CMP AX,ERROR_BAD_FORMAT + JZ GOTEXECEMES + + MOV DX,OFFSET DG:EXECEMES_PTR +GOTEXECEMES: + CALL PRINTF_CRLF + + JMP COMMAND + +HEX2BIN: + MOV [INDEX],DX + MOV DX,OFFSET DG:HEXWRT_PTR + CMP BYTE PTR [RDFLG],WRITE + JNZ RDHEX + + JMP RESTARTJ2 + +RDHEX: + MOV ES,AX + CALL OPEN_A_FILE + + MOV DX,OFFSET DG:NOTFND_PTR + JNC HEXFND + + JMP RESTART + +HEXFND: + XOR BP,BP + MOV SI,OFFSET DG:(BUFFER+BUFSIZ) ; Flag input buffer as empty +READHEX: + CALL GETCH + + CMP AL,CHAR_COLON ; Search for : to start line + JNZ READHEX + + CALL GETBYT ; Get byte count + + MOV CL,AL + MOV CH,0 + JCXZ HEXDONE + + CALL GETBYT ; Get high byte of load address + + MOV BH,AL + CALL GETBYT ; Get low byte of load address + + MOV BL,AL + ADD BX,[INDEX] ; Add in offset + MOV DI,BX + CALL GETBYT ; Throw away type byte + +READLN: + CALL GETBYT ; Get data byte + + STOSB + CMP DI,BP ; Check if this is the largest address so far + JBE HAVBIG + + MOV BP,DI ; Save new largest +HAVBIG: + LOOP READLN + + JMP SHORT READHEX + +GETCH: + CMP SI,OFFSET DG:(BUFFER+BUFSIZ) + JNZ NOREAD + + MOV DX,OFFSET DG:BUFFER + MOV SI,DX + MOV AH,READ + PUSH BX + PUSH CX + MOV CX,BUFSIZ + MOV BX,cs:[HANDLE] + INT 21H + + POP CX + POP BX + OR AX,AX + JZ HEXDONE + +NOREAD: + LODSB + CMP AL,CHAR_EOF + JZ HEXDONE + + OR AL,AL + RETNZ + +HEXDONE: + MOV [CXSAVE],BP + MOV BXSAVE,0 + RETURN + +HEXDIG: + CALL GETCH + + CALL HEXCHK + + RETNC + + MOV DX,OFFSET DG:HEXERR_PTR +RESTARTJ2: + JMP RESTART + +GETBYT: + CALL HEXDIG + + MOV BL,AL + CALL HEXDIG + + SHL BL,1 + SHL BL,1 + SHL BL,1 + SHL BL,1 + OR AL,BL + RETURN + +;========================================================================= +; ABSREAD: This routine performs a primitive logical sector read of +; the specified drive. This routine replaces the old +; INT 25h function which only allowed 16 bit addressibility. +; The new generic IOCtl logical sector read will permit +; 32 bit addressibility on a disk device. +; +; Inputs : REL_READ_WRITE_TAB - Table provides dword sector +; addressibility. +; +; Outputs: Data located at specified transfer address. +; +; Error : Carry is set on error. +; +; Date : 6/17/87 +;========================================================================= + +ABSREAD proc near ;an000;read logical sector(s) + + push ds ;an000;save affected regs + push cx ;an000;save affected regs + push bx ;an000; + + mov cx,-1 ;an000;extended format + mov bx,offset dg:rel_read_write_tab ;an000;point to read/write table + int 25h ;an000;invoke relative sector read + pop bx ;an000;discard stack word + + pop bx ;an000;restore regs + pop cx ;an000; + pop ds ;an000; + + ret ;an000;return to caller + +ABSREAD endp ;an000;end proc + + +;========================================================================= +; ABSWRT: This routine performs a primitive logical sector write of +; the specified drive. This routine replaces the old +; INT 26h function which only allowed 16 bit addressibility. +; The new generic IOCtl logical sector write will permit +; 32 bit addressibility on a disk device. +; +; Inputs : REL_READ_WRITE_TAB - Table provides dword sector +; addressibility. +; +; Outputs: Data moved from transfer address to applicable sector(s). +; +; Error : Carry is set on error. +; +; Date : 6/17/87 +;========================================================================= + +ABSWRT proc near ;an000;write logical sector(s) + + push ds ;an000;save affected regs + push cx ;an000; + push bx ;an000; + + mov cx,-1 ;an000;extended format + mov bx,offset dg:rel_read_write_tab ;an000;point to read/write table + int 26h ;an000;invoke relative sector write + pop bx ;an000;discard stack word + + pop bx ;an000;restore regs + pop cx ;an000; + pop ds ;an000; + + ret ;an000;return to caller + +ABSWRT endp ;an000;end proc + + +CODE ENDS + END DEBCOM2 + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBCOM3.ASM b/v4.0/src/CMD/DEBUG/DEBCOM3.ASM new file mode 100644 index 0000000..21e971c --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBCOM3.ASM @@ -0,0 +1,678 @@ + PAGE 80,132 ; + TITLE DEBCOM3.ASM - PART3 DEBUGGER COMMANDS +; ROUTINES TO PERFORM DEBUGGER COMMANDS + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBCOM3 + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM + INCLUDE DPL.ASM +.CREF +.LIST +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + EXTRN USER_PROC_PDB:WORD,RSTACK:WORD,STACK:BYTE + EXTRN DSSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD,axSAVE:WORD,dxSAVE:WORD + EXTRN SSSAVE:WORD,SPSAVE:WORD,FLSAVE:WORD + EXTRN NEXTCS:WORD,NEXTIP:WORD, RSETFLAG:BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN BRKCNT:WORD,TCOUNT:WORD,SWITCHAR:BYTE,BPTAB:BYTE + EXTRN BP_ERROR:BYTE,COMP_ARG1:WORD,COMP_ARG2:WORD,COMP_ARG3:WORD + EXTRN COMP_ARG4:WORD,COMP_ARG5:WORD,COMP_ARG6:WORD,COMP_PTR:BYTE + EXTRN ARG_BUF:BYTE,ARG_BUF_PTR:BYTE + EXTRN FZTRACE:BYTE, SYNERR_PTR:BYTE + EXTRN BEGSEG:WORD + IF IBMVER + EXTRN OLD_MASK:BYTE + ENDIF + EXTRN SAVESTATE:BYTE +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + PUBLIC COMPARE,INPUT,OUTPUT,GO + PUBLIC TRACE,ZTRACE,SKIP_FILE + EXTRN GETHEX:NEAR,GETEOL:NEAR,CRLF:NEAR,ERR:NEAR, PERR:NEAR + EXTRN HEX:NEAR,DIGIT:NEAR,SCANP:NEAR,DISPREG:NEAR + EXTRN COMMAND:NEAR,DABORT:NEAR,DELIM1:NEAR,DELIM2:NEAR + EXTRN NMIINT:NEAR,NMIINTEND:NEAR,PRINTF_CRLF:NEAR + EXTRN ADDRESS:NEAR,HEXIN:NEAR,DSRANGE:NEAR +; just like trace except skips OVER next INT or CALL. +DEBCOM3: +ZTRACE: + MOV FZTRACE,-1 + CALL SETADD + CALL SCANP + CALL HEXIN + MOV DX,1 + JC ZSTOCNT + MOV CX,4 + CALL GETHEX + CALL CHECKNONE +ZSTOCNT: + MOV [TCOUNT],DX + CALL GETEOL + MOV DX,NEXTCS + MOV CSSAVE,DX + MOV DX,NEXTIP + MOV IPSAVE,DX +ZSTEP: + MOV ES,[CSSAVE] ; point to instruction to execute + MOV DI,[IPSAVE] ; include offset in segment + XOR DX,DX ; where to place breakpoint +get_opcode: + MOV AL,ES:[DI] ; get the opcode + cmp al,0f0h ; lock + je is_override + cmp al,26h ; es: + je is_override + cmp al,2eh ; cs: + je is_override + cmp al,36h ; ss: + je is_override + cmp al,3eh ; ds: + jne not_override +Is_override: +; inc dx ; this seemed to put us in an endless + inc di ; loop, try this. + jmp get_opcode +Not_override: + CMP AL,11101000B ; direct intra call + JZ ZTRACE3 ; yes, 3 bytes + CMP AL,10011010B ; direct inter call + JZ ZTRACE5 ; yes, 5 bytes + CMP AL,11111111B ; indirect? + JZ ZTRACEMODRM ; yes, go figure length + CMP AL,11001100B ; short interrupt? + JZ ZTRACE1 ; yes, 1 byte + CMP AL,11001101B ; long interrupt? + JZ ZTRACE2 ; yes, 2 bytes + CMP AL,11100010B ; loop + JZ ZTRACE2 ; 2 byter + CMP AL,11100001B ; loopz/loope + JZ ZTRACE2 ; 2 byter + CMP AL,11100000B ; loopnz/loopne + JZ ZTRACE2 ; 2 byter + AND AL,11111110B ; check for rep + CMP AL,11110010B ; perhaps? + JZ FOO1 + JMP STEP ; can't do anything special, step +FOO1: + MOV AL,ES:[DI+1] ; next instruction + AND AL,11111110B ; ignore w bit + CMP AL,10100100B ; MOVS + JZ ZTRACE2 ; two byte + CMP AL,10100110B ; CMPS + JZ ZTRACE2 ; two byte + CMP AL,10101110B ; SCAS + JZ ZTRACE2 ; two byte + CMP AL,10101100B ; LODS + JZ ZTRACE2 ; two byte + CMP AL,10101010B ; STOS + JZ ZTRACE2 ; two byte + JMP STEP ; bogus, do single step + +ZTRACEMODRM: + MOV AL,ES:[DI+1] ; get next byte + AND AL,11111000B ; get mod and type + CMP AL,01010000B ; indirect intra 8 bit offset? + JZ ZTRACE3 ; yes, three byte whammy + CMP AL,01011000B ; indirect inter 8 bit offset + JZ ZTRACE3 ; yes, three byte guy + CMP AL,10010000B ; indirect intra 16 bit offset? + JZ ZTRACE4 ; four byte offset + CMP AL,10011000B ; indirect inter 16 bit offset? + JZ ZTRACE4 ; four bytes + CMP AL,11010000B ; indirect through reg? + JZ ZTRACE2 ; two byte instruction + JMP STEP ; can't figger out what this is! +ZTRACE5: + INC DX +ZTRACE4: + INC DX +ZTRACE3: + INC DX +ZTRACE2: + INC DX +ZTRACE1: + INC DX + ADD DI,DX ; offset to breakpoint instruction + MOV WORD PTR [BPTAB],DI ; save offset + MOV WORD PTR [BPTAB+2],ES ; save segment + MOV AL,ES:[DI] ; get next opcode byte + MOV BYTE PTR [BPTAB+4],AL ; save it + MOV BYTE PTR ES:[DI],0CCH ; break point it + MOV [BRKCNT],1 ; only this breakpoint + JMP DEXIT ; start the operation! + +; Trace 1 instruction or the number of instruction specified +; by the parameter using 8086 trace mode. Registers are all +; set according to values in save area +TRACE: + MOV FZTRACE,0 + CALL SETADD + CALL SCANP + CALL HEXIN + MOV DX,1 + JC STOCNT + MOV CX,4 + CALL GETHEX + CALL CHECKNONE +STOCNT: + MOV [TCOUNT],DX + CALL GETEOL + MOV DX,NEXTCS + MOV CSSAVE,DX + MOV DX,NEXTIP + MOV IPSAVE,DX +STEP: + MOV [BRKCNT],0 +; The 286 has a problem with trace mode and software interrupt instructions; +; it treats them as atomic operations. We simulate the operation in software. + MOV ES,[CSSAVE] ; Get next instruction pointer + MOV DI,[IPSAVE] + MOV AL,ES:[DI] ; get next opcode + cmp al,0e4h ; check for 'IN' opcode + jne not_inal_op + cmp es:byte ptr[di+1],21h + jne not_mask_op + add [ipsave],2 + JMP SETalmask + +not_inal_op: + cmp al,0ech ; in al,DX ? + jne not_mask_op + cmp dxsave,21h + jne not_mask_op + add [ipsave],1 +SETalmask: + mov ax,[axsave] + in al,21h + mov [axsave],ax + JMP SETENVIRON + +not_mask_op: + CMP AL,0CDH ; trace over an interrupt? + JZ DOINT ; no, check for other special cases + CMP AL,0CEH ; how about int overflow + JNZ CHECKCC + TEST FLSAVE,F_OVERFLOW ; see it overflow is present + JZ CHECKOP + MOV BX,4 ; INTO = INT 4 + DEC IPSAVE ; INTO is a singel byte + JMP SHORT DOVAL +CHECKCC: + CMP AL,0CCH + JNZ CHECKOP + MOV BX,3 ; INT 3 = CC + DEC IPSAVE + JMP SHORT DOVAL +DOINT: +; We have a software interrupt. Get destination vector + MOV BL,BYTE PTR ES:[DI+1] ; get vector number + XOR BH,BH ; clear out upper +DOVAL: + SHL BX,1 ; word index + SHL BX,1 ; dword index + XOR DI,DI ; interrupt table + MOV ES,DI + MOV AX,ES:[BX] ; point to vector + MOV BX,ES:[BX+2] ; point to vector +; AX:BX is the vector. Swap it with currect CS:IP + XCHG AX,IPSAVE ; new CS:IP + XCHG BX,CSSAVE +; AX:BX is old CS:IP. We 'PUSH' flags, oldCS and oldIP, reset flags (ifl) and +; set CS:IP to point to interrupt instruction. + MOV ES,SSSAVE ; point to user stack + MOV DI,SPSAVE +; Take old flags and PUSH the flags. + MOV CX,FLSAVE ; get flags + SUB DI,2 ; PUSHF + MOV ES:[DI],CX ; rest of push +; Push the old CS + SUB DI,2 ; PUSH CS + MOV ES:[DI],BX ; rest of push +; Push the old IP + SUB DI,2 ; PUSH IP + ADD AX,2 ; increment IP + MOV ES:[DI],AX ; rest of push +; Update stack + MOV SPSAVE,DI ; store +; Take flags and turn interrupts off and trace mode off + AND CX,NOT F_INTERRUPT ; CLI + AND CX,NOT F_TRACE ; no trace + MOV FLSAVE,CX ; rest of CLI +; Set up correct process and go to normal reentry code. + IF NOT SYSVER + MOV BX,[USER_PROC_PDB] + MOV AH,SET_CURRENT_PDB + INT 21H + ENDIF + JMP SETENVIRON +; We need to special case the following instructions that may push a TRACE bit +; on the stack: PUSHF (9C) + +; Save the opcode in A Special place +CHECKOP: + MOV RSETFLAG,AL ; no bits to turn off +SETTRACE: + OR FLSAVE,F_TRACE ; Turn on trace bit + IF IBMVER + CLI + IN AL,MASK_PORT ; Get current mask + JMP SHORT FOO +FOO: + MOV [OLD_MASK],AL ; Save it + MOV AL,INT_MASK ; New mask + OUT MASK_PORT,AL ; Set it + STI + ENDIF +DEXIT: + IF NOT SYSVER + MOV BX,[USER_PROC_PDB] + MOV AH,SET_CURRENT_PDB + INT 21H + ENDIF +; Unfortunately, any system call we issue will muck with the current extended +; errors. Here we must restore the extended error state so that if the user +; program gets it, we do not interfere. + MOV AX,(SERVERCALL SHL 8) + 10 + MOV DX,OFFSET DG:SAVESTATE + INT 21H + PUSH DS + XOR AX,AX + MOV DS,AX + MOV WORD PTR DS:[12],OFFSET DG:BREAKFIX ; Set vector 3--breakpoint instruction + MOV WORD PTR DS:[14],CS + MOV WORD PTR DS:[4],OFFSET DG:REENTER ; Set vector 1--Single step + MOV WORD PTR DS:[6],CS + CLI + IF SETCNTC + MOV WORD PTR DS:[8CH],OFFSET DG:CONTC ; Set vector 23H (CTRL-C) + MOV WORD PTR DS:[8EH],CS + ENDIF + POP DS + MOV SP,OFFSET DG:STACK + POP AX + POP BX + POP CX + POP DX + POP BP + POP BP + POP SI + POP DI + POP ES + POP ES + POP SS + MOV SP,[SPSAVE] + PUSH [FLSAVE] + PUSH [CSSAVE] + PUSH [IPSAVE] + MOV DS,[DSSAVE] + IRET +STEP1: + CALL CRLF + CALL DISPREG + TEST FZTRACE,-1 + JNZ STEPZ + JMP STEP +STEPZ: JMP ZSTEP + +; Re-entry point from CTRL-C. Top of stack has address in 86-DOS for +; continuing, so we must pop that off. +CONTC: + ADD SP,6 + JMP SHORT REENTERREAL + +; Re-entry point from breakpoint. Need to decrement instruction +; pointer so it points to location where breakpoint actually +; occured. +BREAKFIX: + PUSH BP + MOV BP,SP + DEC WORD PTR [BP].OLDIP + POP BP + JMP REENTERREAL + +; Re-entry point from trace mode or interrupt during execution. All registers +; are saved so they can be displayed or modified. +INTERRUPT_FRAME STRUC +OLDBP DW ? +OLDIP DW ? +OLDCS DW ? +OLDF DW ? +OLDERIP DW ? +OLDERCS DW ? +OLDERF DW ? +INTERRUPT_FRAME ENDS + +ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:NOTHING +; ReEnter is the main entry point for breakpoint interrupts and for trace mode +; interrupts. We treat both of these cases identically: save state, display +; registers and go for another command. If we get NMI's, we skip them or if +; it turns out that we are debugging ourselves, we skip them. + +; Due to bogosities in the 808x chip, Consider tracing over an interrupt and +; then setting a breakpoint to where the interrupt returns. You get the INT 3 +; and then trace mode gets invoked! This is why we ignore interrupts within +; ourselves. +REENTER: + PUSH BP + MOV BP,SP ; get a frame to address from + PUSH AX +; MOV AX,CS +; CMP AX,[BP].OLDCS ; Did we interrupt ourselves? +; JNZ GOREENTER ; no, go reenter + IF IBMJAPAN + MOV AX,[BP].OLDIP + CMP AX,OFFSET DG:NMIINT ; interrupt below NMI interrupt? + JB GOREENTER ; yes, go reenter + CMP [BP].OLDIP,OFFSET DG:NMIINTEND + JAE GOREENTER ; interrupt above NMI interrupt? + POP AX ; restore state + POP BP + SUB SP,6 ; switch TRACE and NMI stack frames + PUSH BP + MOV BP,SP ; set up frame + PUSH AX ; get temp variable + MOV AX,[BP].OLDERIP ; get NMI Vector + MOV [BP].OLDIP,AX ; stuff in new NMI vector + MOV AX,[BP].OLDERCS ; get NMI Vector + MOV [BP].OLDCS,AX ; stuff in new NMI vector + MOV AX,[BP].OLDERF ; get NMI Vector + AND AH,0FEH ; turn off Trace if present + MOV [BP].OLDF,AX ; stuff in new NMI vector + MOV [BP].OLDERF,AX + MOV [BP].OLDERIP,OFFSET DG:REENTER ; offset of routine + MOV [BP].OLDERCS,CS ; and CS + POP AX + POP BP + IRET ; go try again + ENDIF +GOREENTER: + IF IBMVER + MOV AL,CS:[OLD_MASK] ; Recover Old mask + OUT MASK_PORT,AL ; Restore it + ENDIF + MOV AL,CS:[RSETFLAG] +; Determine, based on the previous instruction, what we are supposed to do +; to flags on the users stack. + CMP AL,09CH ; PUSHF + JNZ NOFIX +; OlderIP = flags. Turn off trace bit + AND [BP].OLDERIP,NOT F_TRACE +NOFIX: + POP AX + POP BP +REENTERREAL: + MOV CS:[SPSAVE+SEGDIF],SP + MOV CS:[SSSAVE+SEGDIF],SS + MOV CS:[FLSAVE],CS + MOV SS,CS:[FLSAVE] + MOV SP,OFFSET DG:RSTACK + ASSUME SS:DG + + PUSH ES + PUSH DS + PUSH DI + PUSH SI + PUSH BP + DEC SP + DEC SP + PUSH DX + PUSH CX + PUSH BX + PUSH AX + PUSH SS + POP DS + ASSUME DS:DG + + MOV SS,[SSSAVE] + MOV SP,[SPSAVE] + ASSUME SS:NOTHING + + POP [IPSAVE] + POP [CSSAVE] + POP AX + AND AX,NOT F_TRACE ; TURN OFf trace mode bit + MOV [FLSAVE],AX + MOV [SPSAVE],SP +SETENVIRON: + PUSH DS + POP ES + ASSUME ES:DG + + PUSH DS + POP SS + ASSUME SS:DG + + MOV SP,OFFSET DG:STACK + PUSH DS + XOR AX,AX + MOV DS,AX + ASSUME DS:NOTHING + + IF SETCNTC + MOV WORD PTR DS:[8CH],OFFSET DG:DABORT ; Set Ctrl-C vector + MOV WORD PTR DS:[8EH],CS + ENDIF + POP DS + ASSUME DS:DG + + STI + CLD +; Since we are about to issue system calls, let's grab the current user's +; extended error info. + MOV AH,GETEXTENDEDERROR + INT 21H + ASSUME DS:NOTHING,ES:NOTHING + + MOV SAVESTATE.DPL_AX,AX + MOV SAVESTATE.DPL_BX,BX + MOV SAVESTATE.DPL_CX,CX + MOV SAVESTATE.DPL_DX,DX + MOV SAVESTATE.DPL_SI,SI + MOV SAVESTATE.DPL_DI,DI + MOV SAVESTATE.DPL_DS,DS + MOV SAVESTATE.DPL_ES,ES + MOV AX,CS + MOV DS,AX + MOV ES,AX + ASSUME DS:DG,ES:DG + + IF NOT SYSVER + MOV AH,GET_CURRENT_PDB + INT 21H + MOV [USER_PROC_PDB],BX + MOV BX,BEGSEG + MOV AH,SET_CURRENT_PDB + INT 21H + ENDIF + MOV SI,OFFSET DG:BPTAB + MOV CX,[BRKCNT] + JCXZ SHOREG + PUSH ES +CLEARBP: + LES DI,DWORD PTR [SI] + ADD SI,4 + MOVSB + LOOP CLEARBP + POP ES +SHOREG: + DEC [TCOUNT] + JZ CHECKDISP + JMP STEP1 +CHECKDISP: + CALL CRLF + CALL DISPREG + JMP COMMAND + +; Input from the specified port and display result +INPUT: + MOV CX,4 ; Port may have 4 digits + CALL GETHEX ; Get port number in DX + CALL GETEOL + + IN AL,DX ; Variable port input + + PUSH CS + POP ES + MOV DI,OFFSET DG:ARG_BUF + CALL HEX ; And display + + XOR AL,AL + STOSB + MOV DX,OFFSET DG:ARG_BUF_PTR + JMP PRINTF_CRLF + +; Output a value to specified port. +OUTPUT: + MOV CX,4 ; Port may have 4 digits + CALL GETHEX ; Get port number + PUSH DX ; Save while we get data + MOV CX,2 ; Byte output only + CALL GETHEX ; Get data to output + CALL GETEOL + XCHG AX,DX ; Output data in AL + POP DX ; Port in DX + + OUT DX,AL ; Variable port output + + RETURN + +SETADD: + MOV DX,CSSAVE ; set up start addresses + MOV NEXTCS,DX + MOV DX,IPSAVE + MOV NEXTIP,DX + MOV BP,[CSSAVE] + CALL SCANP + CMP BYTE PTR [SI],"=" + RETNZ + INC SI + CALL ADDRESS + MOV NEXTCS,AX + MOV NEXTIP,DX + RETURN + +; Jump to program, setting up registers according to the +; save area. up to 10 breakpoint addresses may be specified. +GO: + MOV RSETFLAG,0 + CALL SETADD + XOR BX,BX + MOV DI,OFFSET DG:BPTAB +GO1: + CALL SCANP + JZ DEXEC + MOV BP,[CSSAVE] + PUSH DI + PUSH BX ;AN000; DMS;SAVE BX - ADDRESS KILLS IT + CALL ADDRESS + POP BX ;AN000; DMS;RESTORE BX + POP DI + MOV [DI],DX ; Save offset + MOV [DI+2],AX ; Save segment + ADD DI,5 ; Leave a little room + INC BX + CMP BX,1+BPMAX + JNZ GO1 + MOV DX,OFFSET DG:BP_ERROR ; BP ERROR + JMP ERR +DEXEC: + MOV [BRKCNT],BX + MOV CX,BX + JCXZ NOBP + MOV DI,OFFSET DG:BPTAB + PUSH DS +SETBP: + LDS SI,ES:DWORD PTR [DI] + ADD DI,4 + MOVSB + MOV BYTE PTR [SI-1],0CCH + LOOP SETBP + POP DS +NOBP: + MOV DX,NEXTCS + MOV CSSAVE,DX + MOV DX,NEXTIP + MOV IPSAVE,DX + MOV [TCOUNT],1 + JMP DEXIT + +SKIP_FILE: + MOV AH,CHAR_OPER + INT 21H + MOV CS:[SWITCHAR],DL ; GET THE CURRENT SWITCH CHARACTER +FIND_DELIM: + LODSB + CALL DELIM1 + JZ GOTDELIM + CALL DELIM2 + JNZ FIND_DELIM +GOTDELIM: + DEC SI + RETURN + +COMPARE: + CALL DSRANGE + PUSH CX + PUSH AX + PUSH DX + CALL ADDRESS ; Same segment + CALL GETEOL + POP SI + MOV DI,DX + MOV ES,AX + POP DS + POP CX ; Length + DEC CX + CALL COMP ; Do one less than total + INC CX ; CX=1 (do last one) +COMP: + REPE CMPSB + RETZ +; Compare error. Print address, value; value, address. + DEC SI + MOV CS:COMP_ARG1,DS + MOV CS:COMP_ARG2,SI + XOR AH,AH + LODSB + MOV CS:COMP_ARG3,AX + DEC DI + MOV AL,ES:[DI] + MOV CS:COMP_ARG4,AX + MOV CS:COMP_ARG5,ES + MOV CS:COMP_ARG6,DI + INC DI + PUSH DS + PUSH CS + POP DS + MOV DX,OFFSET DG:COMP_PTR + CALL PRINTF_CRLF + POP DS + XOR AL,AL + JMP SHORT COMP + + PROCEDURE CHECKNONE,NEAR + OR DX,DX + RETNZ + MOV DX,OFFSET DG:SYNERR_PTR ; ERROR MESSAGE + JMP PERR + ENDPROC CHECKNONE + +CODE ENDS + END DEBCOM3 + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBCONST.ASM b/v4.0/src/CMD/DEBUG/DEBCONST.ASM new file mode 100644 index 0000000..a5f8b97 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBCONST.ASM @@ -0,0 +1,1128 @@ + PAGE 80,132 ; + TITLE DEBCONST.ASM + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBCONST + ENDIF +.XLIST +.XCREF +INCLUDE DOSSYM.INC +INCLUDE DEBEQU.ASM +.LIST +.CREF + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE + + EXTRN ALUFROMREG:NEAR, ALUTOREG:NEAR, ACCIMM:NEAR, SEGOP:NEAR + EXTRN ESPRE:NEAR, SSPRE:NEAR, CSPRE:NEAR, DSPRE:NEAR + EXTRN REGOP:NEAR, NOOPERANDS:NEAR, SAVHEX:NEAR, SHORTJMP:NEAR + EXTRN MOVSEGTO:NEAR, WORDTOALU:NEAR, MOVSEGFROM:NEAR + EXTRN GETADDR:NEAR, XCHGAX:NEAR, LONGJMP:NEAR, LOADACC:NEAR + EXTRN STOREACC:NEAR, REGIMMB:NEAR, SAV16:NEAR, MEMIMM:NEAR + EXTRN INT3:NEAR, SAV8:NEAR, CHK10:NEAR, M8087:NEAR + EXTRN M8087_D9:NEAR, M8087_DB:NEAR, M8087_DD:NEAR + EXTRN M8087_DF:NEAR, INFIXB:NEAR, INFIXW:NEAR, OUTFIXB:NEAR + EXTRN OUTFIXW:NEAR, JMPCALL:NEAR, INVARB:NEAR, INVARW:NEAR + EXTRN OUTVARB:NEAR, OUTVARW:NEAR, PREFIX:NEAR, IMMED:NEAR + EXTRN SIGNIMM:NEAR, SHIFT:NEAR, SHIFTV:NEAR, GRP1:NEAR + EXTRN GRP2:NEAR, REGIMMW:NEAR, DOORG:NEAR + + + EXTRN DB_OPER:NEAR, DW_OPER:NEAR, ASSEMLOOP:NEAR, GROUP2:NEAR + EXTRN NO_OPER:NEAR, GROUP1:NEAR, FGROUPP:NEAR, FGROUPX:NEAR + EXTRN FGROUPZ:NEAR, FD9_OPER:NEAR, FGROUPB:NEAR, FGROUP:NEAR + EXTRN FGROUPDS:NEAR, DCINC_OPER:NEAR, INT_OPER:NEAR + EXTRN IN_OPER:NEAR, DISP8_OPER:NEAR, JMP_OPER:NEAR, L_OPER:NEAR + EXTRN MOV_OPER:NEAR, OUT_OPER:NEAR, PUSH_OPER:NEAR + EXTRN GET_DATA16:NEAR, FGROUP3:NEAR, FGROUP3W:NEAR + EXTRN FDE_OPER:NEAR, ESC_OPER:NEAR, AA_OPER:NEAR + EXTRN CALL_OPER:NEAR, FDB_OPER:NEAR, POP_OPER:NEAR, ROTOP:NEAR + EXTRN TST_OPER:NEAR, EX_OPER:NEAR + +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + + PUBLIC REG8, REG16, SREG, SIZ8, DISTAB, DBMN, ADDMN, ADCMN, SUBMN + PUBLIC SBBMN, XORMN, ORMN, ANDMN, AAAMN, AADMN, AASMN, CALLMN, CBWMN + PUBLIC UPMN, DIMN, CMCMN, CMPMN, CWDMN, DAAMN, DASMN, DECMN, DIVMN + PUBLIC ESCMN, HLTMN, IDIVMN, IMULMN, INCMN, INTOMN, INTMN, INMN + PUBLIC IRETMN, JAMN, JCXZMN, JNCMN, JBEMN, JZMN, JGEMN, JGMN, JLEMN + PUBLIC JLMN, JMPMN, JNZMN, JPEMN, JNZMN, JPEMN, JPOMN, JNSMN, JNOMN + PUBLIC JOMN, JSMN, LAHFMN, LDSMN, LEAMN, LESMN, LOCKMN, LODBMN + PUBLIC LODWMN, LOOPNZMN, LOOPZMN, LOOPMN, MOVBMN, MOVWMN, MOVMN + PUBLIC MULMN, NEGMN, NOPMN, NOTMN, OUTMN, POPFMN, POPMN, PUSHFMN + PUBLIC PUSHMN, RCLMN, RCRMN, REPZMN, REPNZMN, RETFMN, RETMN, ROLMN + PUBLIC RORMN, SAHFMN, SARMN, SCABMN, SCAWMN, SHLMN, SHRMN, STCMN + PUBLIC DOWNMN, EIMN, STOBMN, STOWMN, TESTMN, WAITMN, XCHGMN, XLATMN + PUBLIC ESSEGMN, CSSEGMN, SSSEGMN, DSSEGMN, BADMN + + PUBLIC M8087_TAB, FI_TAB, SIZE_TAB, MD9_TAB, MD9_TAB2, MDB_TAB + PUBLIC MDB_TAB2, MDD_TAB, MDD_TAB2, MDF_TAB, OPTAB, MAXOP, SHFTAB + PUBLIC IMMTAB, GRP1TAB, GRP2TAB, SEGTAB, REGTAB, REGTABEND, FLAGTAB + PUBLIC STACK + + PUBLIC AXSAVE, BXSAVE, CXSAVE, DXSAVE, BPSAVE, SPSAVE, SISAVE + PUBLIC DISAVE, DSSAVE, ESSAVE, SSSAVE, CSSAVE, IPSAVE, FLSAVE, RSTACK + PUBLIC REGDIF, RDFLG, TOTREG, DSIZ, NOREGL, DISPB, LBUFSIZ, LBUFFCNT + PUBLIC LINEBUF, PFLAG, COLPOS, RSETFLAG + + IF SYSVER + PUBLIC CONFCB, POUT, COUT, CIN, IOBUFF, IOADDR, IOCALL, IOCOM + PUBLIC IOSTAT, IOCHRET, IOSEG, IOCNT + ENDIF + + PUBLIC QFLAG, NEWEXEC, RETSAVE, USER_PROC_PDB, HEADSAVE, EXEC_BLOCK + PUBLIC COM_LINE, COM_FCB1, COM_FCB2, COM_SSSP, COM_CSIP, NEXTCS + PUBLIC NEXTIP, NAMESPEC + +REG8 DB "ALCLDLBLAHCHDHBH" +REG16 DB "AXCXDXBXSPBPSIDI" +SREG DB "ESCSSSDS",0,0 +SIZ8 DB "BYWODWQWTB",0,0 +; 0 +DISTAB DW OFFSET DG:ADDMN,ALUFROMREG + DW OFFSET DG:ADDMN,ALUFROMREG + DW OFFSET DG:ADDMN,ALUTOREG + DW OFFSET DG:ADDMN,ALUTOREG + DW OFFSET DG:ADDMN,ACCIMM + DW OFFSET DG:ADDMN,ACCIMM + DW OFFSET DG:PUSHMN,SEGOP + DW OFFSET DG:POPMN,SEGOP + DW OFFSET DG:ORMN,ALUFROMREG + DW OFFSET DG:ORMN,ALUFROMREG + DW OFFSET DG:ORMN,ALUTOREG + DW OFFSET DG:ORMN,ALUTOREG + DW OFFSET DG:ORMN,ACCIMM + DW OFFSET DG:ORMN,ACCIMM + DW OFFSET DG:PUSHMN,SEGOP + DW OFFSET DG:POPMN,SEGOP +; 10H + DW OFFSET DG:ADCMN,ALUFROMREG + DW OFFSET DG:ADCMN,ALUFROMREG + DW OFFSET DG:ADCMN,ALUTOREG + DW OFFSET DG:ADCMN,ALUTOREG + DW OFFSET DG:ADCMN,ACCIMM + DW OFFSET DG:ADCMN,ACCIMM + DW OFFSET DG:PUSHMN,SEGOP + DW OFFSET DG:POPMN,SEGOP + DW OFFSET DG:SBBMN,ALUFROMREG + DW OFFSET DG:SBBMN,ALUFROMREG + DW OFFSET DG:SBBMN,ALUTOREG + DW OFFSET DG:SBBMN,ALUTOREG + DW OFFSET DG:SBBMN,ACCIMM + DW OFFSET DG:SBBMN,ACCIMM + DW OFFSET DG:PUSHMN,SEGOP + DW OFFSET DG:POPMN,SEGOP +; 20H + DW OFFSET DG:ANDMN,ALUFROMREG + DW OFFSET DG:ANDMN,ALUFROMREG + DW OFFSET DG:ANDMN,ALUTOREG + DW OFFSET DG:ANDMN,ALUTOREG + DW OFFSET DG:ANDMN,ACCIMM + DW OFFSET DG:ANDMN,ACCIMM + DW OFFSET DG:ESSEGMN,ESPRE + DW OFFSET DG:DAAMN,NOOPERANDS + DW OFFSET DG:SUBMN,ALUFROMREG + DW OFFSET DG:SUBMN,ALUFROMREG + DW OFFSET DG:SUBMN,ALUTOREG + DW OFFSET DG:SUBMN,ALUTOREG + DW OFFSET DG:SUBMN,ACCIMM + DW OFFSET DG:SUBMN,ACCIMM + DW OFFSET DG:CSSEGMN,CSPRE + DW OFFSET DG:DASMN,NOOPERANDS +; 30H + DW OFFSET DG:XORMN,ALUFROMREG + DW OFFSET DG:XORMN,ALUFROMREG + DW OFFSET DG:XORMN,ALUTOREG + DW OFFSET DG:XORMN,ALUTOREG + DW OFFSET DG:XORMN,ACCIMM + DW OFFSET DG:XORMN,ACCIMM + DW OFFSET DG:SSSEGMN,SSPRE + DW OFFSET DG:AAAMN,NOOPERANDS + DW OFFSET DG:CMPMN,ALUFROMREG + DW OFFSET DG:CMPMN,ALUFROMREG + DW OFFSET DG:CMPMN,ALUTOREG + DW OFFSET DG:CMPMN,ALUTOREG + DW OFFSET DG:CMPMN,ACCIMM + DW OFFSET DG:CMPMN,ACCIMM + DW OFFSET DG:DSSEGMN,DSPRE + DW OFFSET DG:AASMN,NOOPERANDS +; 40H + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:INCMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP + DW OFFSET DG:DECMN,REGOP +; 50H + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:PUSHMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP + DW OFFSET DG:POPMN,REGOP +; 60H + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX +; 70H + DW OFFSET DG:JOMN,SHORTJMP + DW OFFSET DG:JNOMN,SHORTJMP + DW OFFSET DG:JCMN,SHORTJMP + DW OFFSET DG:JNCMN,SHORTJMP + DW OFFSET DG:JZMN,SHORTJMP + DW OFFSET DG:JNZMN,SHORTJMP + DW OFFSET DG:JBEMN,SHORTJMP + DW OFFSET DG:JAMN,SHORTJMP + DW OFFSET DG:JSMN,SHORTJMP + DW OFFSET DG:JNSMN,SHORTJMP + DW OFFSET DG:JPEMN,SHORTJMP + DW OFFSET DG:JPOMN,SHORTJMP + DW OFFSET DG:JLMN,SHORTJMP + DW OFFSET DG:JGEMN,SHORTJMP + DW OFFSET DG:JLEMN,SHORTJMP + DW OFFSET DG:JGMN,SHORTJMP +; 80H + DW 0,IMMED + DW 0,IMMED + DW 0,IMMED + DW 0,SIGNIMM + DW OFFSET DG:TESTMN,ALUTOREG ;ARR 2.4 + DW OFFSET DG:TESTMN,ALUTOREG ;ARR 2.4 + DW OFFSET DG:XCHGMN,ALUTOREG ;ARR 2.4 + DW OFFSET DG:XCHGMN,ALUTOREG ;ARR 2.4 + DW OFFSET DG:MOVMN,ALUFROMREG + DW OFFSET DG:MOVMN,ALUFROMREG + DW OFFSET DG:MOVMN,ALUTOREG + DW OFFSET DG:MOVMN,ALUTOREG + DW OFFSET DG:MOVMN,MOVSEGTO + DW OFFSET DG:LEAMN,WORDTOALU + DW OFFSET DG:MOVMN,MOVSEGFROM + DW OFFSET DG:POPMN,GETADDR +; 90H + DW OFFSET DG:NOPMN,NOOPERANDS + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:XCHGMN,XCHGAX + DW OFFSET DG:CBWMN,NOOPERANDS + DW OFFSET DG:CWDMN,NOOPERANDS + DW OFFSET DG:CALLMN,LONGJMP + DW OFFSET DG:WAITMN,NOOPERANDS + DW OFFSET DG:PUSHFMN,NOOPERANDS + DW OFFSET DG:POPFMN,NOOPERANDS + DW OFFSET DG:SAHFMN,NOOPERANDS + DW OFFSET DG:LAHFMN,NOOPERANDS +; A0H + DW OFFSET DG:MOVMN,LOADACC + DW OFFSET DG:MOVMN,LOADACC + DW OFFSET DG:MOVMN,STOREACC + DW OFFSET DG:MOVMN,STOREACC + DW OFFSET DG:MOVBMN,NOOPERANDS + DW OFFSET DG:MOVWMN,NOOPERANDS + DW OFFSET DG:CMPBMN,NOOPERANDS + DW OFFSET DG:CMPWMN,NOOPERANDS + DW OFFSET DG:TESTMN,ACCIMM + DW OFFSET DG:TESTMN,ACCIMM + DW OFFSET DG:STOBMN,NOOPERANDS + DW OFFSET DG:STOWMN,NOOPERANDS + DW OFFSET DG:LODBMN,NOOPERANDS + DW OFFSET DG:LODWMN,NOOPERANDS + DW OFFSET DG:SCABMN,NOOPERANDS + DW OFFSET DG:SCAWMN,NOOPERANDS +; B0H + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMB + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW + DW OFFSET DG:MOVMN,REGIMMW +; C0H + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:RETMN,SAV16 + DW OFFSET DG:RETMN,NOOPERANDS + DW OFFSET DG:LESMN,WORDTOALU + DW OFFSET DG:LDSMN,WORDTOALU + DW OFFSET DG:MOVMN,MEMIMM + DW OFFSET DG:MOVMN,MEMIMM + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:RETFMN,SAV16 + DW OFFSET DG:RETFMN,NOOPERANDS + DW OFFSET DG:INTMN,INT3 + DW OFFSET DG:INTMN,SAV8 + DW OFFSET DG:INTOMN,NOOPERANDS + DW OFFSET DG:IRETMN,NOOPERANDS +; D0H + DW 0,SHIFT + DW 0,SHIFT + DW 0,SHIFTV + DW 0,SHIFTV + DW OFFSET DG:AAMMN,CHK10 + DW OFFSET DG:AADMN,CHK10 + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:XLATMN,NOOPERANDS + DW 0,M8087 ; d8 + DW 0,M8087_D9 ; d9 + DW 0,M8087 ; da + DW 0,M8087_DB ; db + DW 0,M8087 ; dc + DW 0,M8087_DD ; dd + DW 0,M8087 ; de + DW 0,M8087_DF ; df +; E0H + DW OFFSET DG:LOOPNZMN,SHORTJMP + DW OFFSET DG:LOOPZMN,SHORTJMP + DW OFFSET DG:LOOPMN,SHORTJMP + DW OFFSET DG:JCXZMN,SHORTJMP + DW OFFSET DG:INMN,INFIXB + DW OFFSET DG:INMN,INFIXW + DW OFFSET DG:OUTMN,OUTFIXB + DW OFFSET DG:OUTMN,OUTFIXW + DW OFFSET DG:CALLMN,JMPCALL + DW OFFSET DG:JMPMN,JMPCALL + DW OFFSET DG:JMPMN,LONGJMP + DW OFFSET DG:JMPMN,SHORTJMP + DW OFFSET DG:INMN,INVARB + DW OFFSET DG:INMN,INVARW + DW OFFSET DG:OUTMN,OUTVARB + DW OFFSET DG:OUTMN,OUTVARW +; F0H + DW OFFSET DG:LOCKMN,PREFIX + DW OFFSET DG:DBMN,SAVHEX + DW OFFSET DG:REPNZMN,PREFIX + DW OFFSET DG:REPZMN,PREFIX + DW OFFSET DG:HLTMN,NOOPERANDS + DW OFFSET DG:CMCMN,NOOPERANDS + DW 0,GRP1 + DW 0,GRP1 + DW OFFSET DG:CLCMN,NOOPERANDS + DW OFFSET DG:STCMN,NOOPERANDS + DW OFFSET DG:DIMN,NOOPERANDS + DW OFFSET DG:EIMN,NOOPERANDS + DW OFFSET DG:UPMN,NOOPERANDS + DW OFFSET DG:DOWNMN,NOOPERANDS + DW 0,GRP2 + DW 0,GRP2 + +DBMN DB "DB",0 + DB "DW",0 + DB ";",0 +ORGMN DB "ORG",0 +ADDMN DB "ADD",0 +ADCMN DB "ADC",0 +SUBMN DB "SUB",0 +SBBMN DB "SBB",0 +XORMN DB "XOR",0 +ORMN DB "OR",0 +ANDMN DB "AND",0 +AAAMN DB "AAA",0 +AADMN DB "AAD",0 +AAMMN DB "AAM",0 +AASMN DB "AAS",0 +CALLMN DB "CALL",0 +CBWMN DB "CBW",0 +CLCMN DB "CLC",0 +UPMN DB "CLD",0 ; CLD,0 +DIMN DB "CLI",0 +CMCMN DB "CMC",0 +CMPBMN DB "CMPSB",0 ; CMPSB +CMPWMN DB "CMPSW",0 ; CMPSW,0 +CMPMN DB "CMP",0 +CWDMN DB "CWD",0 +DAAMN DB "DAA",0 +DASMN DB "DAS",0 +DECMN DB "DEC",0 +DIVMN DB "DIV",0 +ESCMN DB "ESC",0 + DB "FXCH",0 + DB "FFREE",0 + DB "FCOMPP",0 + DB "FCOMP",0 + DB "FCOM",0 + DB "FICOMP",0 + DB "FICOM",0 + DB "FNOP",0 + DB "FCHS",0 + DB "FABS",0 + DB "FTST",0 + DB "FXAM",0 + DB "FLDL2T",0 + DB "FLDL2E",0 + DB "FLDLG2",0 + DB "FLDLN2",0 + DB "FLDPI",0 + DB "FLD1",0 + DB "FLDZ",0 + DB "F2XM1",0 + DB "FYL2XP1",0 + DB "FYL2X",0 + DB "FPTAN",0 + DB "FPATAN",0 + DB "FXTRACT",0 + DB "FDECSTP",0 + DB "FINCSTP",0 + DB "FPREM",0 + DB "FSQRT",0 + DB "FRNDINT",0 + DB "FSCALE",0 + DB "FINIT",0 + DB "FDISI",0 + DB "FENI",0 + DB "FCLEX",0 + DB "FBLD",0 + DB "FBSTP",0 + DB "FLDCW",0 + DB "FSTCW",0 + DB "FSTSW",0 + DB "FSTENV",0 + DB "FLDENV",0 + DB "FSAVE",0 + DB "FRSTOR",0 + DB "FADDP",0 + DB "FADD",0 + DB "FIADD",0 + DB "FSUBRP",0 + DB "FSUBR",0 + DB "FSUBP",0 + DB "FSUB",0 + DB "FISUBR",0 + DB "FISUB",0 + DB "FMULP",0 + DB "FMUL",0 + DB "FIMUL",0 + DB "FDIVRP",0 + DB "FDIVR",0 + DB "FDIVP",0 + DB "FDIV",0 + DB "FIDIVR",0 + DB "FIDIV",0 + DB "FWAIT",0 + DB "FILD",0 + DB "FLD",0 + DB "FSTP",0 + DB "FST",0 + DB "FISTP",0 + DB "FIST",0 +HLTMN DB "HLT",0 +IDIVMN DB "IDIV",0 +IMULMN DB "IMUL",0 +INCMN DB "INC",0 +INTOMN DB "INTO",0 +INTMN DB "INT",0 +INMN DB "IN",0 ; IN +IRETMN DB "IRET",0 + DB "JNBE",0 + DB "JAE",0 +JAMN DB "JA",0 +JCXZMN DB "JCXZ",0 +JNCMN DB "JNB",0 +JBEMN DB "JBE",0 +JCMN DB "JB",0 + DB "JNC",0 + DB "JC",0 + DB "JNAE",0 + DB "JNA",0 +JZMN DB "JZ",0 + DB "JE",0 +JGEMN DB "JGE",0 +JGMN DB "JG",0 + DB "JNLE",0 + DB "JNL",0 +JLEMN DB "JLE",0 +JLMN DB "JL",0 + DB "JNGE",0 + DB "JNG",0 +JMPMN DB "JMP",0 +JNZMN DB "JNZ",0 + DB "JNE",0 +JPEMN DB "JPE",0 +JPOMN DB "JPO",0 + DB "JNP",0 +JNSMN DB "JNS",0 +JNOMN DB "JNO",0 +JOMN DB "JO",0 +JSMN DB "JS",0 + DB "JP",0 +LAHFMN DB "LAHF",0 +LDSMN DB "LDS",0 +LEAMN DB "LEA",0 +LESMN DB "LES",0 +LOCKMN DB "LOCK",0 +LODBMN DB "LODSB",0 ; LODSB +LODWMN DB "LODSW",0 ; LODSW,0 +LOOPNZMN DB "LOOPNZ",0 +LOOPZMN DB "LOOPZ",0 + DB "LOOPNE",0 + DB "LOOPE",0 +LOOPMN DB "LOOP",0 +MOVBMN DB "MOVSB",0 ; MOVSB +MOVWMN DB "MOVSW",0 ; MOVSW,0 +MOVMN DB "MOV",0 +MULMN DB "MUL",0 +NEGMN DB "NEG",0 +NOPMN DB "NOP",0 +NOTMN DB "NOT",0 +OUTMN DB "OUT",0 ; OUT +POPFMN DB "POPF",0 +POPMN DB "POP",0 +PUSHFMN DB "PUSHF",0 +PUSHMN DB "PUSH",0 +RCLMN DB "RCL",0 +RCRMN DB "RCR",0 +REPZMN DB "REPZ",0 +REPNZMN DB "REPNZ",0 + DB "REPE",0 + DB "REPNE",0 + DB "REP",0 +RETFMN DB "RETF",0 +RETMN DB "RET",0 +ROLMN DB "ROL",0 +RORMN DB "ROR",0 +SAHFMN DB "SAHF",0 +SARMN DB "SAR",0 +SCABMN DB "SCASB",0 ; SCASB +SCAWMN DB "SCASW",0 ; SCASW,0 +SHLMN DB "SHL",0 +SHRMN DB "SHR",0 +STCMN DB "STC",0 +DOWNMN DB "STD",0 ; STD +EIMN DB "STI",0 ; STI +STOBMN DB "STOSB",0 ; STOSB +STOWMN DB "STOSW",0 ; STOSW,0 +TESTMN DB "TEST",0 +WAITMN DB "WAIT",0 +XCHGMN DB "XCHG",0 +XLATMN DB "XLAT",0 +ESSEGMN DB "ES:",0 +CSSEGMN DB "CS:",0 +SSSEGMN DB "SS:",0 +DSSEGMN DB "DS:",0 +BADMN DB "???",0 + +M8087_TAB DB "ADD$MUL$COM$COMP$SUB$SUBR$DIV$DIVR$" +FI_TAB DB "F$FI$F$FI$" +SIZE_TAB DB "DWORD PTR $DWORD PTR $QWORD PTR $WORD PTR $" + DB "BYTE PTR $TBYTE PTR $" + +MD9_TAB DB "LD$@$ST$STP$LDENV$LDCW$STENV$STCW$" +MD9_TAB2 DB "CHS$ABS$@$@$TST$XAM$@$@$LD1$LDL2T$LDL2E$" + DB "LDPI$LDLG2$LDLN2$LDZ$@$2XM1$YL2X$PTAN$PATAN$XTRACT$" + DB "@$DECSTP$INCSTP$PREM$YL2XP1$SQRT$@$RNDINT$SCALE$@$@$" + +MDB_TAB DB "ILD$@$IST$ISTP$@$LD$@$STP$" +MDB_TAB2 DB "ENI$DISI$CLEX$INIT$" + +MDD_TAB DB "LD$@$ST$STP$RSTOR$@$SAVE$STSW$" +MDD_TAB2 DB "FREE$XCH$ST$STP$" + +MDF_TAB DB "ILD$@$IST$ISTP$BLD$ILD$BSTP$ISTP$" + + +OPTAB DB 11111111B ; DB + DW DB_OPER + DB 11111111B ; DW + DW DW_OPER + DB 11111111B ; COMMENT + DW ASSEMLOOP + DB 11111111B ; ORG + DW DOORG + DB 0 * 8 ; ADD + DW GROUP2 + DB 2 * 8 ; ADC + DW GROUP2 + DB 5 * 8 ; SUB + DW GROUP2 + DB 3 * 8 ; SBB + DW GROUP2 + DB 6 * 8 ; XOR + DW GROUP2 + DB 1 * 8 ; OR + DW GROUP2 + DB 4 * 8 ; AND + DW GROUP2 + DB 00110111B ; AAA + DW NO_OPER + DB 11010101B ; AAD + DW AA_OPER + DB 11010100B ; AAM + DW AA_OPER + DB 00111111B ; AAS + DW NO_OPER + DB 2 * 8 ; CALL + DW CALL_OPER + DB 10011000B ; CBW + DW NO_OPER + DB 11111000B ; CLC + DW NO_OPER + DB 11111100B ; CLD + DW NO_OPER + DB 11111010B ; DIM + DW NO_OPER + DB 11110101B ; CMC + DW NO_OPER + DB 10100110B ; CMPB + DW NO_OPER + DB 10100111B ; CMPW + DW NO_OPER + DB 7 * 8 ; CMP + DW GROUP2 + DB 10011001B ; CWD + DW NO_OPER + DB 00100111B ; DAA + DW NO_OPER + DB 00101111B ; DAS + DW NO_OPER + DB 1 * 8 ; DEC + DW DCINC_OPER + DB 6 * 8 ; DIV + DW GROUP1 + DB 11011000B ; ESC + DW ESC_OPER + DB 00001001B ; FXCH + DW FGROUPP + DB 00101000B ; FFREE + DW FGROUPP + DB 11011001B ; FCOMPP + DW FDE_OPER + DB 00000011B ; FCOMP + DW FGROUPX ; Exception to normal P instructions + DB 00000010B ; FCOM + DW FGROUPX + DB 00010011B ; FICOMP + DW FGROUPZ + DB 00010010B ; FICOM + DW FGROUPZ + DB 11010000B ; FNOP + DW FD9_OPER + DB 11100000B ; FCHS + DW FD9_OPER + DB 11100001B ; FABS + DW FD9_OPER + DB 11100100B ; FTST + DW FD9_OPER + DB 11100101B ; FXAM + DW FD9_OPER + DB 11101001B ; FLDL2T + DW FD9_OPER + DB 11101010B ; FLDL2E + DW FD9_OPER + DB 11101100B ; FLDLG2 + DW FD9_OPER + DB 11101101B ; FLDLN2 + DW FD9_OPER + DB 11101011B ; FLDPI + DW FD9_OPER + DB 11101000B ; FLD1 + DW FD9_OPER + DB 11101110B ; FLDZ + DW FD9_OPER + DB 11110000B ; F2XM1 + DW FD9_OPER + DB 11111001B ; FYL2XP1 + DW FD9_OPER + DB 11110001B ; FYL2X + DW FD9_OPER + DB 11110010B ; FPTAN + DW FD9_OPER + DB 11110011B ; FPATAN + DW FD9_OPER + DB 11110100B ; FXTRACT + DW FD9_OPER + DB 11110110B ; FDECSTP + DW FD9_OPER + DB 11110111B ; FINCSTP + DW FD9_OPER + DB 11111000B ; FPREM + DW FD9_OPER + DB 11111010B ; FSQRT + DW FD9_OPER + DB 11111100B ; FRNDINT + DW FD9_OPER + DB 11111101B ; FSCALE + DW FD9_OPER + DB 11100011B ; FINIT + DW FDB_OPER + DB 11100001B ; FDISI + DW FDB_OPER + DB 11100000B ; FENI + DW FDB_OPER + DB 11100010B ; FCLEX + DW FDB_OPER + DB 00111100B ; FBLD + DW FGROUPB + DB 00111110B ; FBSTP + DW FGROUPB + DB 00001101B ; FLDCW + DW FGROUP3W + DB 00001111B ; FSTCW + DW FGROUP3W + DB 00101111B ; FSTSW + DW FGROUP3W + DB 00001110B ; FSTENV + DW FGROUP3 + DB 00001100B ; FLDENV + DW FGROUP3 + DB 00101110B ; FSAVE + DW FGROUP3 + DB 00101100B ; FRSTOR + DW FGROUP3 + DB 00110000B ; FADDP + DW FGROUPP + DB 00000000B ; FADD + DW FGROUP + DB 00010000B ; FIADD + DW FGROUPZ + DB 00110100B ; FSUBRP + DW FGROUPP + DB 00000101B ; FSUBR + DW FGROUPDS + DB 00110101B ; FSUBP + DW FGROUPP + DB 00000100B ; FSUB + DW FGROUPDS + DB 00010101B ; FISUBR + DW FGROUPZ + DB 00010100B ; FISUB + DW FGROUPZ + DB 00110001B ; FMULP + DW FGROUPP + DB 00000001B ; FMUL + DW FGROUP + DB 00010001B ; FIMUL + DW FGROUPZ + DB 00110110B ; FDIVRP + DW FGROUPP + DB 00000111B ; FDIVR + DW FGROUPDS + DB 00110111B ; FDIVP + DW FGROUPP + DB 00000110B ; FDIV + DW FGROUPDS + DB 00010111B ; FIDIVR + DW FGROUPZ + DB 00010110B ; FIDIV + DW FGROUPZ + DB 10011011B ; FWAIT + DW NO_OPER + DB 00011000B ; FILD + DW FGROUPZ + DB 00001000B ; FLD + DW FGROUPX + DB 00001011B ; FSTP + DW FGROUP ;an000; dms; + DB 00101010B ; FST + DW FGROUPX + DB 00011011B ; FISTP + DW FGROUPZ + DB 00011010B ; FIST + DW FGROUPZ + DB 11110100B ; HLT + DW NO_OPER + DB 7 * 8 ; IDIV + DW GROUP1 + DB 5 * 8 ; IMUL + DW GROUP1 + DB 0 * 8 ; INC + DW DCINC_OPER + DB 11001110B ; INTO + DW NO_OPER + DB 11001100B ; INTM + DW INT_OPER + DB 11101100B ; IN + DW IN_OPER + DB 11001111B ; IRET + DW NO_OPER + DB 01110111B ; JNBE + DW DISP8_OPER + DB 01110011B ; JAE + DW DISP8_OPER + DB 01110111B ; JA + DW DISP8_OPER + DB 11100011B ; JCXZ + DW DISP8_OPER + DB 01110011B ; JNB + DW DISP8_OPER + DB 01110110B ; JBE + DW DISP8_OPER + DB 01110010B ; JB + DW DISP8_OPER + DB 01110011B ; JNC + DW DISP8_OPER + DB 01110010B ; JC + DW DISP8_OPER + DB 01110010B ; JNAE + DW DISP8_OPER + DB 01110110B ; JNA + DW DISP8_OPER + DB 01110100B ; JZ + DW DISP8_OPER + DB 01110100B ; JE + DW DISP8_OPER + DB 01111101B ; JGE + DW DISP8_OPER + DB 01111111B ; JG + DW DISP8_OPER + DB 01111111B ; JNLE + DW DISP8_OPER + DB 01111101B ; JNL + DW DISP8_OPER + DB 01111110B ; JLE + DW DISP8_OPER + DB 01111100B ; JL + DW DISP8_OPER + DB 01111100B ; JNGE + DW DISP8_OPER + DB 01111110B ; JNG + DW DISP8_OPER + DB 4 * 8 ; JMP + DW JMP_OPER + DB 01110101B ; JNZ + DW DISP8_OPER + DB 01110101B ; JNE + DW DISP8_OPER + DB 01111010B ; JPE + DW DISP8_OPER + DB 01111011B ; JPO + DW DISP8_OPER + DB 01111011B ; JNP + DW DISP8_OPER + DB 01111001B ; JNS + DW DISP8_OPER + DB 01110001B ; JNO + DW DISP8_OPER + DB 01110000B ; JO + DW DISP8_OPER + DB 01111000B ; JS + DW DISP8_OPER + DB 01111010B ; JP + DW DISP8_OPER + DB 10011111B ; LAHF + DW NO_OPER + DB 11000101B ; LDS + DW L_OPER + DB 10001101B ; LEA + DW L_OPER + DB 11000100B ; LES + DW L_OPER + DB 11110000B ; LOCK + DW NO_OPER + DB 10101100B ; LODB + DW NO_OPER + DB 10101101B ; LODW + DW NO_OPER + DB 11100000B ; LOOPNZ + DW DISP8_OPER + DB 11100001B ; LOOPZ + DW DISP8_OPER + DB 11100000B ; LOOPNE + DW DISP8_OPER + DB 11100001B ; LOOPE + DW DISP8_OPER + DB 11100010B ; LOOP + DW DISP8_OPER + DB 10100100B ; MOVB + DW NO_OPER + DB 10100101B ; MOVW + DW NO_OPER + DB 11000110B ; MOV + DW MOV_OPER + DB 4 * 8 ; MUL + DW GROUP1 + DB 3 * 8 ; NEG + DW GROUP1 + DB 10010000B ; NOP + DW NO_OPER + DB 2 * 8 ; NOT + DW GROUP1 + DB 11101110B ; OUT + DW OUT_OPER + DB 10011101B ; POPF + DW NO_OPER + DB 0 * 8 ; POP + DW POP_OPER + DB 10011100B ; PUSHF + DW NO_OPER + DB 6 * 8 ; PUSH + DW PUSH_OPER + DB 2 * 8 ; RCL + DW ROTOP + DB 3 * 8 ; RCR + DW ROTOP + DB 11110011B ; REPZ + DW NO_OPER + DB 11110010B ; REPNZ + DW NO_OPER + DB 11110011B ; REPE + DW NO_OPER + DB 11110010B ; REPNE + DW NO_OPER + DB 11110011B ; REP + DW NO_OPER + DB 11001011B ; RETF + DW GET_DATA16 + DB 11000011B ; RET + DW GET_DATA16 + DB 0 * 8 ; ROL + DW ROTOP + DB 1 * 8 ; ROR + DW ROTOP + DB 10011110B ; SAHF + DW NO_OPER + DB 7 * 8 ; SAR + DW ROTOP + DB 10101110B ; SCAB + DW NO_OPER + DB 10101111B ; SCAW + DW NO_OPER + DB 4 * 8 ; SHL + DW ROTOP + DB 5 * 8 ; SHR + DW ROTOP + DB 11111001B ; STC + DW NO_OPER + DB 11111101B ; STD + DW NO_OPER + DB 11111011B ; EI + DW NO_OPER + DB 10101010B ; STOB + DW NO_OPER + DB 10101011B ; STOW + DW NO_OPER + DB 11110110B ; TEST + DW TST_OPER + DB 10011011B ; WAIT + DW NO_OPER + DB 10000110B ; XCHG + DW EX_OPER + DB 11010111B ; XLAT + DW NO_OPER + DB 00100110B ; ESSEG + DW NO_OPER + DB 00101110B ; CSSEG + DW NO_OPER + DB 00110110B ; SSSEG + DW NO_OPER + DB 00111110B ; DSSEG + DW NO_OPER + +ZZOPCODE LABEL BYTE +MAXOP = (ZZOPCODE-OPTAB)/3 + +SHFTAB DW OFFSET DG:ROLMN,OFFSET DG:RORMN,OFFSET DG:RCLMN + DW OFFSET DG:RCRMN,OFFSET DG:SHLMN,OFFSET DG:SHRMN + DW OFFSET DG:BADMN,OFFSET DG:SARMN + +IMMTAB DW OFFSET DG:ADDMN,OFFSET DG:ORMN,OFFSET DG:ADCMN + DW OFFSET DG:SBBMN,OFFSET DG:ANDMN,OFFSET DG:SUBMN + DW OFFSET DG:XORMN,OFFSET DG:CMPMN + +GRP1TAB DW OFFSET DG:TESTMN,OFFSET DG:BADMN,OFFSET DG:NOTMN + DW OFFSET DG:NEGMN,OFFSET DG:MULMN,OFFSET DG:IMULMN + DW OFFSET DG:DIVMN,OFFSET DG:IDIVMN + +GRP2TAB DW OFFSET DG:INCMN,OFFSET DG:DECMN,OFFSET DG:CALLMN + DW OFFSET DG:CALLMN,OFFSET DG:JMPMN,OFFSET DG:JMPMN + DW OFFSET DG:PUSHMN,OFFSET DG:BADMN + +SEGTAB DW OFFSET DG:ESSAVE,OFFSET DG:CSSAVE,OFFSET DG:SSSAVE + DW OFFSET DG:DSSAVE + +REGTAB DB "AX",0,"BX",0,"CX",0,"DX",0,"SP",0,"BP",0 + DB "SI",0,"DI",0,"DS",0,"ES",0,"SS",0,"CS",0,"IP",0,"PC",0 +REGTABEND LABEL WORD + +; Flags are ordered to correspond with the bits of the flag +; register, most significant bit first, zero if bit is not +; a flag. First 16 entries are for bit set, second 16 for +; bit reset. + +FLAGTAB DW 0 + DW 0 + DW 0 + DW 0 + DB "OV" + DB "DN" + DB "EI" ; "STI" + DW 0 + DB "NG" + DB "ZR" + DW 0 + DB "AC" + DW 0 + DB "PE" + DW 0 + DB "CY" + DW 0 + DW 0 + DW 0 + DW 0 + DB "NV" + DB "UP" ; "CLD" + DB "DI" + DW 0 + DB "PL" + DB "NZ" + DW 0 + DB "NA" + DW 0 + DB "PO" + DW 0 + DB "NC" + + DW 80H DUP(?) +STACK LABEL BYTE + + +; Register save area + +AXSAVE DW 0 +BXSAVE DW 0 +CXSAVE DW 0 +DXSAVE DW 0 +SPSAVE DW 5AH +BPSAVE DW 0 +SISAVE DW 0 +DISAVE DW 0 +DSSAVE DW 0 +ESSAVE DW 0 +RSTACK LABEL WORD ; Stack set here so registers can be saved by pushing +SSSAVE DW 0 +CSSAVE DW 0 +IPSAVE DW 100H +FLSAVE DW 0F202H + +RSETFLAG DB 0 + +REGDIF EQU AXSAVE-REGTAB + +; This value is initially 0, it is set to non-zero if a file is specified +; either at debug invokation, or via the (N)ame command. It is used to +; control the printing of the NONAMESPEC message for the (W)rite command. +NAMESPEC DB 0 + +; RAM area. + +RDFLG DB READ +TOTREG DB 13 +DSIZ DB 0FH ;changed to 7 if screen 40 col mode +NOREGL DB 8 ;changed to 4 if screen 40 col mode +DISPB DW 128 ;changed to 64 if screen 40 col mode + +LBUFSIZ DB BUFLEN +LBUFFCNT DB 0 +LINEBUF DB 0DH + DB BUFLEN DUP (?) +PFLAG DB 0 +COLPOS DB 0 + + IF SYSVER +CONFCB DB 0 + DB "PRN " + DB 25 DUP(0) + +POUT DD ? +COUT DD ? +CIN DD ? +IOBUFF DB 3 DUP (?) +IOADDR DD ? + +IOCALL DB 22 + DB 0 +IOCOM DB 0 +IOSTAT DW 0 + DB 8 DUP (0) +IOCHRET DB 0 + DW OFFSET DG:IOBUFF +IOSEG DW ? +IOCNT DW 1 + DW 0 + ENDIF + +QFLAG DB 0 +NEWEXEC DB 0 +RETSAVE DW ? + +USER_PROC_PDB DW ? +NextCS DW ? +NextIP DW ? + +HEADSAVE DW ? + +EXEC_BLOCK LABEL BYTE + DW 0 +COM_LINE LABEL DWORD + DW 80H + DW ? +COM_FCB1 LABEL DWORD + DW FCB + DW ? +COM_FCB2 LABEL DWORD + DW FCB + 10H + DW ? +COM_SSSP DD ? +COM_CSIP DD ? + +CONST ENDS + END diff --git a/v4.0/src/CMD/DEBUG/DEBDATA.ASM b/v4.0/src/CMD/DEBUG/DEBDATA.ASM new file mode 100644 index 0000000..fafae77 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBDATA.ASM @@ -0,0 +1,227 @@ + PAGE 60,132 ; + TITLE DEBDATA.SAL - PC DOS +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DEBDATA.SAL +; +; DESCRIPTIVE NAME: DATA SEGMENT VALUE DEFINITION +; +; FUNCTION: PROVIDES ALL DATA SEGMENT DEFINITIONS. +; +; ENTRY POINT: NA +; +; INPUT: ANY VALUE IN DATA SEGMENT +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: NA +; +; EXTERNAL REFERENCES: NA +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT DBCS HANDLING DMS:6/17/87 +; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87 +; - > 32 MB SUPPORT DMS:6/17/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +;======================= END OF SPECIFICATIONS =========================== + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBDATA + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM + INCLUDE DPL.ASM +.LIST +.CREF +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +DATA SEGMENT PUBLIC BYTE +DATA ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +DATA SEGMENT PUBLIC BYTE + PUBLIC PARITYFLAG,XNXOPT,XNXCMD,SWITCHAR,EXTPTR,HANDLE,TRANSADD + PUBLIC PARSERR,ASMADD,DISADD,DISCNT,ASMSP,INDEX,DEFDUMP,DEFLEN + PUBLIC REGSAVE,SEGSAVE,OFFSAVE,TEMP,BUFFER,BYTCNT,OPCODE,AWORD + PUBLIC REGMEM,MIDFLD,MODE,NSEG,BRKCNT,TCOUNT,ASSEM_CNT + PUBLIC ASSEM1,ASSEM2,ASSEM3,ASSEM4,ASSEM5,ASSEM6,BYTEBUF,BPTAB + PUBLIC DIFLG,SIFLG,BXFLG,BPFLG,NEGFLG,NUMFLG,MEMFLG,REGFLG + PUBLIC MOVFLG,TSTFLG,SEGFLG,LOWNUM,HINUM,F8087,DIRFLG,DATAEND + PUBLIC BEGSEG,CREATE_LONG,ARG_BUF_INDEX + PUBLIC FILEEND,FILESTRT,SSINTSAV,BPINTSAV + PUBLIC FZTRACE, PREV24, FIN24 + + public rel_read_write_tab ;an000;relative read/write + ; table + public rel_low_sec ;an000;sector add. low word + public rel_high_sec ;an000;sector add. high word + public rel_sec_num ;an000;# of sectors to access + public rel_rw_add ;an000;transfer address + + public lbtbl ;an000;lead byte table pointer + + public xm_page ;an000; + public xm_log ;an000; + public xm_phy ;an000; + public xm_handle ;an000; + public xm_handle_ret ;an000; + public xm_page_cnt ;an000; + public xm_handle_pages_buf ;an000; + public xm_frame ;an000; + public xm_deall_han ;an000; + public xm_alloc_pg ;an000; + public xm_total_pg ;an000; + public xm_han_total ;an000; + public xm_han_alloc ;an000; + +;========================================================================= +; REL_READ_WRITE_TAB : This table provides the new generic IOCTL primitive +; read/write with its values. +; +; Date : 6/17/87 +;========================================================================= + +REL_READ_WRITE_TAB label dword ;an000;relative read/write + ; table + rel_low_sec dw ? ;an000;sector add. low word + rel_high_sec dw ? ;an000;sector add. high word + rel_sec_num dw ? ;an000;# of sectors to write + rel_rw_add dd ? ;an000;holds the segment + ; & offset of the + ; transfer address + +;========================================================================= + +lbtbl dd ? ;an000;lead byte table pointer + + xm_page db ? ;an000;page count to allocate + xm_log db ? ;an000;log. page to map + xm_phy db ? ;an000;phy. page to map + xm_deall_han dw ? ;an000;handle to deallocate + xm_handle dw ? ;an000;handle to map + xm_handle_ret dw ? ;an000;handle created + + + xm_page_cnt dw ? ;an000;current page count + + xm_handle_pages_buf db 1024 dup(0) ;an000;hold handle pages + + xm_frame dw ? ;an000;holds frame segment + + xm_alloc_pg dw ? ;an000;active page count + + xm_total_pg dw ? ;an000;total possible page cnt. + + xm_han_total dw ? ;an000;total possible handles + + xm_han_alloc dw ? ;an000;handles allocated + + IF IBMVER + PUBLIC OLD_MASK +OLD_MASK DB ? + ENDIF +PREV24 DD ? ; prevvious INT 24 handler +FIN24 DB 0 ; TRUE => in the process of cleaning up +FZTRACE DB 0 ; TRUE => in a Ztrace +FILEEND DW ? ; ARR 2.4 +FILESTRT DW ? ; ARR 2.4 +SSINTSAV DD ? ; ARR 2.4 +BPINTSAV DD ? ; ARR 2.4 + +PARITYFLAG DB 0 + +PUBLIC SAVESTATE +SAVESTATE DPL <> ; storage for extended error info + +XNXOPT DB ? ; AL OPTION FOR DOS COMMAND +XNXCMD DB ? ; DOS COMMAND FOR OPEN_A_FILE TO PERFORM +SWITCHAR DB ? ; CURRENT SWITCH CHARACTER +EXTPTR DW ? ; POINTER TO FILE EXTENSION +HANDLE DW ? ; CURRENT HANDLE +TRANSADD DD ? ; TRANSFER ADDRESS + +PARSERR DB ? +ASMADD DB 4 DUP (?) +DISADD DB 4 DUP (?) +DISCNT DW ? +ASMSP DW ? ; SP AT ENTRY TO ASM +INDEX DW ? +DEFDUMP DB 4 DUP (?) +DEFLEN DW ? +REGSAVE DW ? +SEGSAVE DW ? +OFFSAVE DW ? + +;Do NOT move this dword variable - it sets up a long call for +;a Create_process_data_block call issued in DEBUG +CREATE_LONG LABEL DWORD + DW 100H +BEGSEG DW ? + +; The following data areas are destroyed during hex file read +TEMP DB 4 DUP(?) +BUFFER LABEL BYTE +BYTCNT DB ? +ARG_BUF_INDEX DW ? +OPCODE DW ? +AWORD DB ? +REGMEM DB ? +MIDFLD DB ? +MODE DB ? +NSEG DW ? +BRKCNT DW ? ; Number of breakpoints +TCOUNT DW ? ; Number of steps to trace +ASSEM_CNT DB ? ; preserve order of assem_cnt and assem1 +ASSEM1 DB ? +ASSEM2 DB ? +ASSEM3 DB ? +ASSEM4 DB ? +ASSEM5 DB ? +ASSEM6 DB ? ; preserve order of assemx and bytebuf +BYTEBUF DB BUFLEN DUP (?) ; Table used by LIST +BPTAB DB BPLEN DUP (?) ; Breakpoint table +DIFLG DB ? +SIFLG DB ? +BXFLG DB ? +BPFLG DB ? +NEGFLG DB ? +NUMFLG DB ? ; ZERO MEANS NO NUMBER SEEN +MEMFLG DB ? +REGFLG DB ? +MOVFLG DB ? +TSTFLG DB ? +SEGFLG DB ? +LOWNUM DW ? +HINUM DW ? +F8087 DB ? +DIRFLG DB ? + DB BUFFER+BUFSIZ-$ DUP (?) + +DATAEND LABEL WORD + +DATA ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBEMS.ASM b/v4.0/src/CMD/DEBUG/DEBEMS.ASM new file mode 100644 index 0000000..12578f0 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBEMS.ASM @@ -0,0 +1,1127 @@ + PAGE 60,132 ; + TITLE DEBEMS.SAL - EMS DEBUGGER COMMANDS PC DOS +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DEBEMS.SAL +; +; DESCRIPTIVE NAME: DEBUGGING TOOL +; +; FUNCTION: PROVIDES USERS WITH ACCESS TO RUDIMENTARY EMS FACILITIES. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: DEBCOM2 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBMES - CONTAINS ROUTINES CALLED BY DEBUG +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT EMS FUNCTIONS DSM:6/24/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +;======================= END OF SPECIFICATIONS =========================== + +INCLUDE DOSSYM.INC +include debequ.asm + + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + + extrn xm_page:byte ;an000;page count to allocate + extrn xm_log:byte ;an000;log. page to map + extrn xm_phy:byte ;an000;phy. page to map + extrn xm_handle:word ;an000;handle to map + extrn xm_handle_ret:word ;an000;handle created + + extrn xm_page_cnt:word ;an000;page count + extrn xm_handle_pages_buf:byte ;an000;holds handles and pages + extrn xm_frame:word ;an000;EMS frame value + extrn xm_deall_han:word ;an000;handle to deallocate + extrn xm_alloc_pg:word ;an000;pages allocated + extrn xm_total_pg:word ;an000;total pages possible + extrn xm_han_alloc:word ;an000;handles allocated + extrn xm_han_total:word ;an000;total handles possible + + extrn xm_han_ret_ptr:word ;an000;prints handle created + extrn xm_mapped_ptr:word ;an000;prints log/phy pages + extrn xm_page_seg_ptr:word ;an000;Frame seg status + extrn xm_deall_ptr:word ;an000;Handle deallocation + extrn xm_unall_ptr:word ;an000;prints page status + extrn xm_han_alloc_ptr:word ;an000;print handle status + + extrn xm_err80_ptr:word ;an000;ems error message + extrn xm_err83_ptr:word ;an000;ems error message + extrn xm_err84_ptr:word ;an000;ems error message + extrn xm_err85_ptr:word ;an000;ems error message + extrn xm_err86_ptr:word ;an000;ems error message + extrn xm_err87_ptr:word ;an000;ems error message + extrn xm_err88_ptr:word ;an000;ems error message + extrn xm_err89_ptr:word ;an000;ems error message + extrn xm_err8a_ptr:word ;an000;ems error message + extrn xm_err8b_ptr:word ;an000;ems error message + extrn xm_err8d_ptr:word ;an000;ems error message + extrn xm_err8e_ptr:word ;an000;ems error message + extrn xm_errff_ptr:word ;an000;ems error message + extrn xm_err_gen_ptr:word ;an000;ems error message + extrn xm_parse_err_ptr:word ;an000;input error message + extrn xm_status_ptr:word ;an000;prints status of EMS + +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + public debems ;an000;entry point + extrn std_printf:near ;an000;message retriever + extrn gethx:near ;an000;ASCII to bin conversion + extrn inbuf:near ;an000;input command line + extrn scanb:near ;an000;scan off blanks + extrn scanp:near ;an000;scan for parm + extrn perr:near ;an000;print ^ error + extrn geteol:near + extrn crlf:near ;an000;prints a cr,lf + + IF SYSVER + ENDIF + +DEBEMS: ;an000;entry to module + + call SCANP ;an000;scan for M or S parm +; $if z ;an000;no parms found + JNZ $$IF1 + call XM_PARSE_ERROR ;an000;tell user of error +; $else ;an000; + JMP SHORT $$EN1 +$$IF1: + mov al,[si] ;an000;grab parm + cmp al,"M" ;an000;is it MAP? +; $if e ;an000;yes + JNE $$IF3 + inc si ;an000;point to next byte + call XM_EMS_MAP ;an000; +; $else ;an000; + JMP SHORT $$EN3 +$$IF3: + cmp al,"S" ;an000;is it a status check? +; $if e ;an000;yes + JNE $$IF5 + inc si ;an000;point to next byte + call XM_EMS_STATUS ;an000; +; $else ;an000; + JMP SHORT $$EN5 +$$IF5: + cmp al,"D" ;an000;Deallocate pages? +; $if e ;an000;yes + JNE $$IF7 + inc si ;an000;point to next byte + call XM_EMS_DEALL ;an000; +; $else ;an000; + JMP SHORT $$EN7 +$$IF7: + cmp al,"A" ;an000;Allocate pages? +; $if e ;an000;yes + JNE $$IF9 + inc si ;an000;point to next byte + call XM_EMS_ALLOC ;an000; +; $else ;an000; + JMP SHORT $$EN9 +$$IF9: + call GETEOL ;an000;check out parm +; $endif ;an000; +$$EN9: +; $endif ;an000; +$$EN7: +; $endif ;an000; +$$EN5: +; $endif ;an000; +$$EN3: +; $endif ;an000; +$$EN1: + + ret ;an000;return to caller + + + +;========================================================================= +; XM_EMS_ALLOC : This function will provide the user the +; capability to set and change EMS logical and +; physical pages within page frame 0. +; +; Inputs: none +; +; Outputs: EMS page frames set or altered +; +; Date: 6/24/87 +;========================================================================= + +XM_EMS_ALLOC proc near ;an000;XM functions + + call XM_GET_MAN_STATUS ;an000;see if EMS active +; $if nc ;an000;EMS active + JC $$IF16 + call XM_PAGE_PROMPT ;an000;get pages to allocate + call XM_GET_HAN_ALLOC ;an000;allocate pages + mov dg:XM_HANDLE_RET,dx ;an000;save handle returned +; $if z ;an000;good return + JNZ $$IF17 + pushf ;an000;save our flags + call XM_DISP1 ;an000;tell user results + popf ;an000;restore our flags +; $else ;an000; + JMP SHORT $$EN17 +$$IF17: + call XM_ERROR ;an000;print error message +; $endif ;an000; +$$EN17: +; $else ;an000;EMS not active + JMP SHORT $$EN16 +$$IF16: + call XM_ERROR ;an000;say why not active +; $endif ;an000; +$$EN16: + + ret ;an000;return to caller + +XM_EMS_ALLOC endp ;an000; + + +;========================================================================= +; XM_EMS_MAP : This function will provide the user the +; capability to set and change EMS logical and +; physical pages within page frame 0. +; +; Inputs: none +; +; Outputs: EMS page frames set or altered +; +; Date: 6/24/87 +;========================================================================= + +XM_EMS_MAP proc near ;an000;XM functions + + call XM_GET_MAN_STATUS ;an000;see if EMS active +; $if nc ;an000;EMS active + JC $$IF22 + call XM_LOG_PROMPT ;an000;get logical page + call XM_PHY_PROMPT ;an000;get physical page + call XM_HAN_PROMPT ;an000;get handle + call XM_MAP_MEMORY ;an000;map the page +; $if z ;an000;good return + JNZ $$IF23 + pushf ;an000;save our flags + call XM_DISP2 ;an000;tell user results + popf ;an000;restore our flags +; $else ;an000; + JMP SHORT $$EN23 +$$IF23: + call XM_ERROR ;an000;tell error +; $endif ;an000; +$$EN23: +; $else ;an000;EMS not active + JMP SHORT $$EN22 +$$IF22: + call XM_ERROR ;an000;say why not active +; $endif ;an000; +$$EN22: + + ret ;an000;return to caller + +XM_EMS_MAP endp ;an000; + +;========================================================================= +; XM_GET_MAN_STATUS : This routine will determine if EMS is active for +; this session. +; +; Called Procs: none +; +; Inputs: none +; +; Outputs: Z - no error +; NZ - error +; AH - error message number +; +; Date: 6/24/87 +;========================================================================= + +XM_GET_MAN_STATUS proc near ;an000;see if EMS active + + push ds ;an000;save ds - we stomp it + mov ax,00h ;an000;set ax to 0 + mov ds,ax ;an000;set ds to 0 + cmp ds:word ptr[067h*4+0],0 ;an000;see if int 67h is there + pop ds ;an000;restore ds +; $if e ;an000;EMS not installed + JNE $$IF28 + stc ;an000;flag no ems + mov ah,XM_NOT_INST ;an000;signal EMS not installed +; $else ;an000; + JMP SHORT $$EN28 +$$IF28: + call XM_INSTALL_CHECK ;an000;see if EMS installed +; $if z ;AN000;IS EMS INSTALLED + JNZ $$IF30 + clc ;AN000;EMS INSTALLED - FLAG IT +; $else ;an000; + JMP SHORT $$EN30 +$$IF30: + stc ;AN000;FLAG EMS NOT INSTALLED + mov ah,XM_NOT_INST ;an000;signal EMS not installed +; $endif ;an000; +$$EN30: +; $endif ;an000; +$$EN28: + + RET ;AN000;RETURN TO CALLER + + +XM_GET_MAN_STATUS endp ;an000; + + + +;========================================================================= +; XM_PAGE_PROMPT : This routine prompts the user for the number of +; pages to be allocated, if he desires a new handle. +; This routine will determine whether or not the other +; prompt messages will be displayed. +; +; Called Procs: STD_PRINTF +; XM_PARSE +; +; Inputs: none +; +; Outputs: XM_PAGE_FLAG +; XM_PAGE_BUF +; XM_PAGE +; +; Date: 6/24/87 +;========================================================================= + +XM_PAGE_PROMPT proc near ;an000;prompt user for number + ; of pages to allocate + call SCANB ;an000;see if parm entered +; $if nz ;an000;if parm found + JZ $$IF34 + mov cx,02 ;an000;bytes to parse + call GETHX ;an000;get hex value +; $if c ;an000;no an error occurred + JNC $$IF35 + call PERR ;an000;display ^ error +; $else ;an000; + JMP SHORT $$EN35 +$$IF35: + mov dg:XM_PAGE,dl ;an000;save page count +; $endif ;an000; +$$EN35: +; $else ;an000; + JMP SHORT $$EN34 +$$IF34: + call PERR ;an000;display ^ error +; $endif ;an000; +$$EN34: + + ret ;an000;return to caller + +XM_PAGE_PROMPT endp ;an000; + + +;========================================================================= +; XM_LOG_PROMPT : This routine prompts the user for the number of the +; logical page that is to be mapped in EMS. This +; routine will not be performed if a page count +; was specified. +; +; Called Procs: STD_PRINTF +; XM_PARSE +; +; Inputs: none +; +; Outputs: XM_LOG_BUF +; XM_LOG +; +; Date: 6/24/87 +;========================================================================= + + +XM_LOG_PROMPT proc near ;an000;prompt user for the + ; logical page to be + ; mapped + call SCANB ;an000;see if parm entered +; $if nz ;an000;parm entered + JZ $$IF40 + mov cx,02 ;an000;bytes to parse + call GETHX ;an000;get hex value +; $if c ;an000;no an error occurred + JNC $$IF41 + call PERR ;an000;display ^ error +; $else ;an000; + JMP SHORT $$EN41 +$$IF41: + mov dg:XM_LOG,dl ;an000;save logical page +; $endif ;an000; +$$EN41: +; $else ;an000; + JMP SHORT $$EN40 +$$IF40: + call PERR ;an000;display ^ error +; $endif ;an000; +$$EN40: + + ret ;an000;return to caller + +XM_LOG_PROMPT endp ;an000; + + +;========================================================================= +; XM_PHY_PROMPT : This routine prompts the user for the number of the +; physical page that is to be mapped in EMS. This +; routine will not be performed if a page count +; was specified. +; +; Called Procs: STD_PRINTF +; XM_PARSE +; +; Inputs: none +; +; Outputs: XM_PHY_BUF +; XM_PHY +; +; Date: 6/24/87 +;========================================================================= + + +XM_PHY_PROMPT proc near ;an000;prompt user for the + ; physical page to be + ; mapped + call SCANB ;an000;see if parm entered +; $if nz ;an000;parm found + JZ $$IF46 + mov cx,02 ;an000;bytes to parse + call GETHX ;an000;get hex value +; $if c ;an000;no an error occurred + JNC $$IF47 + call PERR ;an000;display ^ error +; $else ;an000; + JMP SHORT $$EN47 +$$IF47: + mov dg:XM_PHY,dl ;an000;save logical page +; $endif ;an000; +$$EN47: +; $else ;an000; + JMP SHORT $$EN46 +$$IF46: + call PERR ;an000; +; $endif ;an000; +$$EN46: + + ret ;an000;return to caller + +XM_PHY_PROMPT endp ;an000; + + +;========================================================================= +; XM_HAN_PROMPT : This routine prompts the user for the number of the +; handle that the mapping is to occur on. This +; routine will not be performed if a page count +; was specified. +; +; Called Procs: STD_PRINTF +; XM_PARSE +; +; Inputs: none +; +; Outputs: XM_HAN_BUF +; XM_HAN +; +; Date: 6/24/87 +;========================================================================= + + +XM_HAN_PROMPT proc near ;an000;prompt user for the + ; handle to be mapped + call SCANB ;an000;see if parm entered +; $if nz ;an000;prompt found + JZ $$IF52 + mov cx,04 ;an000;bytes to parse + call GETHX ;an000;get hex value +; $if c ;an000;no an error occurred + JNC $$IF53 + call PERR ;an000;display ^ error +; $else ;an000; + JMP SHORT $$EN53 +$$IF53: + mov dg:XM_HANDLE,dx ;an000;save logical page +; $endif ;an000; +$$EN53: +; $else ;an000; + JMP SHORT $$EN52 +$$IF52: + call PERR ;an000;display ^ error +; $endif ;an000; +$$EN52: + + ret ;an000;return to caller + +XM_HAN_PROMPT endp ;an000; + + + +;========================================================================= +; XM_GET_HAN_ALLOC : This routine will get a handle and allocate the +; requested number of pages to that handle. +; +; Called Procs: none +; +; Inputs: XM_PAGE - number of pages to allocate to handle +; +; Outputs: Z - no error +; NZ - error +; DX - handle allocated +; +; Date: 6/24/87 +;========================================================================= + +XM_GET_HAN_ALLOC proc near ;an000;create handle and alloc. + ; requested pages. + push bx ;an000;save regs. + mov ah,EMS_HAN_ALLOC ;an000;function 43h + xor bh,bh ;an000;clear byte + mov bl,dg:XM_PAGE ;an000;number of pages to + ; allocate + int 67h ;an000;call EMS + or ah,ah ;an000;was there an error + pop bx ;an000;restore regs. + + ret ;an000;return to caller + +XM_GET_HAN_ALLOC endp ;an000; + +;========================================================================= +; XM_MAP_MEMORY : This routine will map the requested logical page +; to the requested physical page in EMS. +; +; Called Procs: none +; +; Inputs: XM_PHY - physical page to map to +; XM_HAN - logical page to map +; +; Outputs: Z - no error +; NZ - error +; page mapped +; +; Date: 6/24/87 +;========================================================================= + +XM_MAP_MEMORY proc near ;an000;map a logical page to + ; a physical page in + ; EMS + push bx ;an000;save regs. + push dx ;an000; + mov ah,EMS_MAP_MEMORY ;an000;function 44h + mov al,dg:XM_PHY ;an000;physical page to map + xor bh,bh ;an000;zero byte + mov bl,dg:XM_LOG ;an000;logical page to map + mov dx,dg:XM_HANDLE ;an000;handle to map page to + int 67h ;an000;call EMS + or ah,ah ;an000;was there an error + pop dx ;an000;restore regs. + pop bx ;an000; + + ret ;an000;return to caller + +XM_MAP_MEMORY endp ;an000; + + +;========================================================================= +; XM_DISP1 : This routine displays the current page frame and +; the handle created as a result of the allocate pages. +; +; Called Procs: STD_PRINTF +; +; Inputs: XM_FRAME_SEG - page frame segment +; XM_HANDLE_RET - created handle +; XM_PG_FRAME_PTR - pointer to message +; XM_HAN_RET_PTR - pointer to message +; +; Outputs: "Page Frame Segment : %1",0d,0a +; "Handle Created : %1",0d,0a +; +; Date: 6/24/87 +;========================================================================= + +XM_DISP1 proc near ;an000;display messages + + mov dx,offset dg:XM_HAN_RET_PTR ;an000;"Handle Created : " + call STD_PRINTF ;an000;call message ret. + + ret ;an000;return to caller + +XM_DISP1 endp ;an000; + + +;========================================================================= +; XM_DISP2 : This routine displays the logical page mapped and +; the physical page it was mapped to. +; +; Called Procs: STD_PRINTF +; +; Inputs: XM_MAPPED_PTR - pointer to message +; XM_LOG - logical page mapped +; XM_PHY - physical page mapped +; +; Outputs: "Logical page %1 mapped to physical page %2",0d0a +; +; Date: 6/24/87 +;========================================================================= + +XM_DISP2 proc near ;an000;display messages + + mov dx,offset dg:XM_MAPPED_PTR ;an000;"Logical page %1 mapped + ; to physical page %2" + call STD_PRINTF ;an000;call message ret. + + ret ;an000;return to caller + +XM_DISP2 endp ;an000; + +;========================================================================= +; XM_ERROR: This routine will determine what error we have by +; querying the result in the AH register. It will then +; report the error to the user through STD_PRINTF +; +; Called Procs: STD_PRINTF +; +; Inputs: AH - error code +; +; Outputs: error message +; +; Date: 6/24/87 +;========================================================================= + +XM_ERROR proc near ;an000;error message printer + + cmp ah,XM_ERR80 ;an000;error message +; $if e ;an000;found message + JNE $$IF58 + mov dx,offset dg:XM_ERR80_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF58: + + cmp ah,XM_ERR83 ;an000;error message +; $if e ;an000;found message + JNE $$IF60 + mov dx,offset dg:XM_ERR83_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF60: + + cmp ah,XM_ERR84 ;an000;error message +; $if e ;an000;found message + JNE $$IF62 + mov dx,offset dg:XM_ERR84_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF62: + + cmp ah,XM_ERR85 ;an000;error message +; $if e ;an000;found message + JNE $$IF64 + mov dx,offset dg:XM_ERR85_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF64: + + + cmp ah,XM_ERR86 ;an000;error message +; $if e ;an000;found message + JNE $$IF66 + mov dx,offset dg:XM_ERR86_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF66: + + cmp ah,XM_ERR87 ;an000;error message +; $if e ;an000;found message + JNE $$IF68 + mov dx,offset dg:XM_ERR87_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF68: + + cmp ah,XM_ERR88 ;an000;error message +; $if e ;an000;found message + JNE $$IF70 + mov dx,offset dg:XM_ERR88_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF70: + + cmp ah,XM_ERR89 ;an000;error message +; $if e ;an000;found message + JNE $$IF72 + mov dx,offset dg:XM_ERR89_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF72: + + cmp ah,XM_ERR8A ;an000;error message +; $if e ;an000;found message + JNE $$IF74 + mov dx,offset dg:XM_ERR8A_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF74: + + cmp ah,XM_ERR8B ;an000;error message +; $if e ;an000;found message + JNE $$IF76 + mov dx,offset dg:XM_ERR8B_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF76: + + cmp ah,XM_ERR8D ;an000;error message +; $if e ;an000;found message + JNE $$IF78 + mov dx,offset dg:XM_ERR8D_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF78: + + cmp ah,XM_ERR8E ;an000;error message +; $if e ;an000;found message + JNE $$IF80 + mov dx,offset dg:XM_ERR8E_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif +$$IF80: + + cmp ah,XM_NOT_INST ;an000;EMS not installed +; $if e ;an000;found message + JNE $$IF82 + mov dx,offset dg:XM_ERRFF_PTR ;an000;point to message + jmp XM_ERROR_CONT ;an000;print error +; $endif ;an000; +$$IF82: + + mov dx,offset dg:XM_ERR_GEN_PTR ;an000;general error message + +XM_ERROR_CONT: + + call STD_PRINTF ;an000;call message ret. + + ret ;an000;return to caller + +XM_ERROR endp ;an000; + +;========================================================================= +; XM_PARSE_ERROR : This routine will display that an error has occurred +; on the input of the requested data. +; +; Called Procs: STD_PRINTF +; +; Inputs: XM_PARSE_ERR_PTR - error message +; +; Outputs: "Invalid value for parameter",0d,0a +; +; Date: 6/24/87 +;========================================================================= + +XM_PARSE_ERROR proc near ;an000;input error message + + mov dx,offset dg:XM_PARSE_ERR_PTR ;an000;error message + call STD_PRINTF ;an000;call message ret. + ret ;an000;return to caller + +XM_PARSE_ERROR endp ;an000; + + + +;========================================================================= +; XM_EMS_STATUS : This function will provide the user with +; a report the the current status of EMS. +; +; Inputs: none +; +; Outputs: EMS page frames set or altered +; +; Date: 6/24/87 +;========================================================================= + +XM_EMS_STATUS proc near ;an000;XM functions + + call XM_GET_MAN_STATUS ;an000;see if EMS active +; $if nc ;an000;EMS active + JC $$IF84 + call XM_CURR_STATUS ;an000;current status of EMS +; $else ;an000;EMS not active + JMP SHORT $$EN84 +$$IF84: + call XM_ERROR ;an000;say why not active +; $endif ;an000; +$$EN84: + + ret ;an000;return to caller + +XM_EMS_STATUS endp ;an000; + + +;========================================================================= +; XM_CURR_STATUS : This routine will display the current status of +; all active EMS handles. +; +; Inputs : none +; +; Outputs : Current status of all active EMS handles +; "Handle %1 has %2 pages allocated" +; +; Physical page with it associated frame segment +; "Physical page %1 = Frame segment %2" +; +; Date: 8/05/86 +;========================================================================= + +XM_CURR_STATUS proc near ;an000;current EMS status + + mov ah,EMS_HANDLE_PAGES ;an000;get handle pages + mov di,offset dg:XM_HANDLE_PAGES_BUF ;an000;point to the buffer + int 67h ;an000; + + or ah,ah ;an000;see if an error occurred +; $if z ;an000;no error + JNZ $$IF87 +; $do ;an000;do while data in buffer +$$DO88: + cmp bx,0 ;an000;end of buffer? +; $leave e ;an000;yes + JE $$EN88 + mov ax,word ptr es:[di] ;an000;page handle + mov dg:XM_HANDLE_RET,ax ;an000;save in var + mov ax,word ptr es:[di+02];an000;page count + mov dg:XM_PAGE_CNT,ax ;an000;save in var + mov dx,offset dg:XM_STATUS_PTR ;an000;point to message + call STD_PRINTF ;an000;print it + add di,04h ;an000;next record + dec bx ;an000;decrement counter +; $enddo ;an000; + JMP SHORT $$DO88 +$$EN88: + + call CRLF ;an000;place a blank line + ; between reports + + call XM_FRAME_BUFFER ;an000;get frame buffer + ;ES:DI points to frame buffer +; $do ;an000;while cx not = 0 +$$DO91: + cmp cx,00 ;an000;at end? +; $leave e ;an000;yes + JE $$EN91 + call XM_GET_FRAME_SEG ;an000;obtain page and seg + mov dx,offset dg:XM_PAGE_SEG_PTR ;an000;message + call STD_PRINTF ;an000;print it + dec cx ;an000;decrease counter + add di,04 ;an000;adjust pointer +; $enddo ;an000; + JMP SHORT $$DO91 +$$EN91: + + call XM_UNALL_COUNT ;an000;display page status + call XM_HANDLE_COUNT ;an000;display handle status + +; $else + JMP SHORT $$EN87 +$$IF87: + call XM_ERROR ;an000;display the error +; $endif ;an000; +$$EN87: + ret ;an000; + +XM_CURR_STATUS endp ;an000; + +;========================================================================= +; XM_UNALL_COUNT : This routine generates a line of the status report +; displaying the number of pages allocated out of +; the total possible +; +; Inputs : none +; +; Outputs : Current status of allocated pages +; "%1 of a total %2 EMS pages have been allocated" +; +; Date: 8/05/86 +;========================================================================= + +XM_UNALL_COUNT proc near ;an000; + + mov ah,EMS_UNALL_PG_CNT ;an000;see how many pages + ; remaining + int 67h ;an000; + or ah,ah ;an000;see if error + +; $if z ;an000;no error + JNZ $$IF96 + push bx ;an000;save bx + push dx ;an000;save dx + call CRLF ;an000; + pop dx ;an000;restore dx + pop bx ;an000;restore bx + mov ax,dx ;an000;total page count + sub ax,bx ;an000;get pages allocated + mov dg:XM_ALLOC_PG,ax ;an000;save allocated pages + mov dg:XM_TOTAL_PG,dx ;an000;save total page count + mov dx,offset dg:XM_UNALL_PTR ;an000;"%1 of a total %2 EMS + ; pages have been allocated",cr,lf + call STD_PRINTF ;an000;print it +; $endif ;an000; +$$IF96: + + ret ;an000; + +XM_UNALL_COUNT endp ;an000; + + +;========================================================================= +; XM_HANDLE_COUNT: This routine generates a line of the status report +; displaying the number of handles allocated out of +; the total possible. +; +; Inputs : none +; +; Outputs : Current status of allocated pages +; "%1 of a total %2 EMS handles have been allocated" +; +; Date: 8/05/86 +;========================================================================= + +XM_HANDLE_COUNT proc near ;an000; + + mov ah,EMS_HANDLE_CNT ;an000;see how many handles + ; possible + int 67h ;an000; + or ah,ah ;an000;see if error + +; $if z ;an000;no error + JNZ $$IF98 + mov ax,EMS_HANDLE_TOTAL ;an000;total possible handles + mov dg:XM_HAN_TOTAL,ax ;an000;save total page count + mov dg:XM_HAN_ALLOC,bx ;an000;save allocated pages + mov dx,offset dg:XM_HAN_ALLOC_PTR + ;an000;"%1 of a total %2 EMS + ; handles have been allocated",cr,lf + call STD_PRINTF ;an000;print it +; $endif ;an000; +$$IF98: + + ret ;an000; + +XM_HANDLE_COUNT endp ;an000; + + +;========================================================================= +; XM_FRAME_SEG : This routine accesses the vector created by +; function 58h, int 67h. It obtains a physical +; page of EMS and its segment from this vector +; +; Inputs : ES:DI - points to frame buffer +; +; Outputs : XM_PHY - a physical page in EMS +; XM_FRAME - segment corresponding to the physical page +; +; Date: 8/05/86 +;========================================================================= + + +XM_GET_FRAME_SEG proc near ;an000;find the frame segment + + mov al,byte ptr es:[di+2] ;an000;get physical page + mov dg:XM_PHY,al ;an000;place in print var + mov ax,word ptr es:[di] ;an000;get frame segment + mov dg:XM_FRAME,ax ;an000;place in print var + + ret ;an000; + +XM_GET_FRAME_SEG endp ;an000; + +;========================================================================= +; XM_INSTALL_CHECK: This routine performs function 51h, int 67h to +; determine if EMS is indeed active. +; +; Inputs : XM_FRAME_BUFFER - used to receive physical page +; and segment data for EMS. +; +; Outputs : XM_FRAME_BUFFER - buffer holds physical page +; and segment data for EMS. +; +; Date: 8/05/86 +;========================================================================= + +XM_INSTALL_CHECK proc near ;an000;see if EMS installed + + MOV AH,EMS_GET_MAN_STAT ;AN000;GET EMS STATUS + XOR AL,AL ;an000;clear low byte + INT 67h ;an000; + OR AH,AH ;an000;check for error +; $IF Z ;an000;no error + JNZ $$IF100 + MOV AH,EMS_VERSION ;an000;get version number + INT 67h ;an000; + CMP AL,EMS_LIM_40 ;an000;LIM 4.0 ? +; $IF AE ;an000;4.0 or greater + JNAE $$IF101 + MOV AH,00h ;an000;set up for flag pass + OR AH,AH ;an000;set flag to ZR +; $ELSE ;an000;below 4.0 + JMP SHORT $$EN101 +$$IF101: + MOV AH,01h ;an000;set up for flag pass + OR AH,AH ;an000;set flag to NZ +; $ENDIF ;an000; +$$EN101: +; $ENDIF ;an000; +$$IF100: + + ret ;an000; + +XM_INSTALL_CHECK endp ;an000; + + + + +;========================================================================= +; XM_EMS_DEALL : This routine deallocates handles from EMS. +; +; Inputs : DX - Handle supplied by XM_DEALL_PROMPT +; +; Outputs : Good return - "Handle %1 deallocated" +; Bad return - message describing error +; +; Date: 8/05/86 +;========================================================================= + +XM_EMS_DEALL proc near ;an000;deallocate EMS pages + + call XM_GET_MAN_STATUS ;an000;see if EMS installed +; $if nc ;an000;error? + JC $$IF105 + call XM_DEALL_PROMPT ;an000;prompt user for handle + mov ah,EMS_PAGE_DEALL ;an000;function 45h, int 67h + int 67h ;an000; + + or ah,ah ;an000;error? +; $if nz ;an000;yes + JZ $$IF106 + call XM_ERROR ;an000;say why +; $else ;an000; + JMP SHORT $$EN106 +$$IF106: + mov dx,offset dg:XM_DEALL_PTR;an000;"Handle %1 deallocated" + call STD_PRINTF ;an000;print message +; $endif ;an000; +$$EN106: +; $else ;an000; + JMP SHORT $$EN105 +$$IF105: + call XM_ERROR ;an000;print type of error +; $endif ;an000; +$$EN105: + + ret ;an000; + +XM_EMS_DEALL endp ;an000; + +;========================================================================= +; XM_DEALL_PROMPT : This routine prompts the user for the handle to be +; deallocated. It converts the handle entered to +; binary and passes it back to the caller in DX. +; +; Inputs : none +; +; Outputs : DX - Handle to be deallocated. +; +; Date: 8/05/86 +;========================================================================= + +XM_DEALL_PROMPT proc near ;an000;prompt user for handle + ; to deallocate + call SCANB ;an000;see if parm entered +; $if nz ;an000;parm found + JZ $$IF111 + mov cx,04 ;an000;bytes to parse + call GETHX ;an000;get hex value +; $if c ;an000;no an error occurred + JNC $$IF112 + call PERR ;an000;display ^ error +; $else ;an000; + JMP SHORT $$EN112 +$$IF112: + mov dg:XM_DEALL_HAN,dx ;an000;save handle to deallocate +; $endif ;an000; +$$EN112: +; $else ;an000; + JMP SHORT $$EN111 +$$IF111: + call PERR ;an000;display ^ error +; $endif ;an000; +$$EN111: + + ret ;an000;return to caller + +XM_DEALL_PROMPT endp ;an000; + + +;========================================================================= +; XM_FRAME_BUFFER : This routine obtains the frame buffer +; of EMS pages. +; +; Inputs : none +; +; Outputs : ES:DI - Pointer to frame array +; CX - Number of elements in array +;========================================================================= + +XM_FRAME_BUFFER proc near ;an000; + + mov ax,EMS_PG_FRAME ;an000;get frame buffer + int 67h ;an000; + + ret ;an000; + +XM_FRAME_BUFFER endp ;an000; + + +CODE ENDS + END DEBEMS + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBEQU.ASM b/v4.0/src/CMD/DEBUG/DEBEQU.ASM new file mode 100644 index 0000000..fab6f28 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBEQU.ASM @@ -0,0 +1,164 @@ +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DEBEQU.SAL +; +; DESCRIPTIVE NAME: EQUATES NEEDED BY DEBUG +; +; FUNCTION: PROVIDES EQUATES NEEDED BY DEBUG +; +; ENTRY POINT: NA +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: NA +; +; EXTERNAL REFERENCES: NA +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT DBCS HANDLING DMS:6/17/87 +; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87 +; - > 32 MB SUPPORT DMS:6/17/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +;======================= END OF SPECIFICATIONS =========================== + + IF1 + %OUT Including DEBEQU.ASM... + ENDIF + +;IBMVER EQU TRUE ; These switches get set in version.inc +;MSVER EQU FALSE ; NOT HERE !!! + + INCLUDE SYSVER.INC + +IBMJAPAN EQU FALSE + +SETCNTC EQU TRUE ; If this is FALSE, DEBUG will not set + ; the Control C int vector + +PROMPT EQU "-" +FCB EQU 5CH +EXEFCB EQU FCB +BUFLEN EQU 80 ; Maximum length of line input buffer +BPMAX EQU 10 ; Maximum number of breakpoints +BPLEN EQU 5*BPMAX ; Length of breakpoint table +REGTABLEN EQU 14 ; Number of registers +SEGDIF EQU 0 +BUFSIZ EQU 512 + +BXREG EQU "B"+5800H ; "BX" +BPREG EQU "B"+5000H ; "BP" +SIREG EQU "S"+4900H ; "SI" +DIREG EQU "D"+4900H ; "DI" +COMMA EQU 2C00H +OPBUFLEN EQU 35 + + IF IBMVER +MASK_PORT EQU 21H ; 8259 interrupt control register +INT_MASK EQU 11111111B ; Disable ALL interrupts + ENDIF + +CR EQU 13 ;CARRIAGE RETURN +LF EQU 10 ;LINE FEED +CHAR_TAB EQU 9 ;TAB +CHAR_BACKSPACE EQU 8 ;BACKSPACE CHARACTER +CHAR_EOF EQU 1AH ;END OF FILE CHARACTER +CHAR_RUBOUT EQU 7FH ;RUBOUT CHARACTER + +CHAR_EQUAL EQU "=" ;CHARACTER EQUAL +CHAR_MINUS EQU "-" ;MINUS CHARACTER +CHAR_BLANK EQU " " ;BLANK CHARACTER +DOUBLE_QUOTE EQU '"' ;DOUBLE QUOTE CHARACTER +SINGLE_QUOTE EQU "'" ;SINGLE QUOTE CHARACTER +CHAR_COMMA EQU "," ;CHARACTER COMMA +CHAR_PERIOD EQU "." ;CHARACTER PERIOD +CHAR_COLON EQU ":" ;CHARACTER COLON +CHAR_SEMICOLON EQU ";" ;CHARACTER SEMICOLON +CHAR_LEFT_BRACKET EQU "[" ;CHARACTER LEFT BRACKET +CHAR_AT_SIGN EQU "@" ;CHARACTER "AT" SIGN +CHAR_ZERO EQU "0" ;CHARACTER ZERO + +LOWER_A EQU "a" ;LOWER CASE CHARACTER "a" +LOWER_Z EQU "z" ;LOWER CASE CHARACTER "z" + +UPPER_A EQU "A" ;UPPER CASE CHARACTER "A" +UPPER_C EQU "C" ;UPPER CASE CHARACTER "C" +UPPER_E EQU "E" ;UPPER CASE CHARACTER "E" +UPPER_F EQU "F" ;UPPER CASE CHARACTER "F" +UPPER_L EQU "L" ;UPPER CASE CHARACTER "L" +UPPER_M EQU "M" ;UPPER CASE CHARACTER "M" +UPPER_N EQU "N" ;UPPER CASE CHARACTER "N" +UPPER_P EQU "P" ;UPPER CASE CHARACTER "P" +UPPER_S EQU "S" ;UPPER CASE CHARACTER "S" +UPPER_X EQU "X" ;UPPER CASE CHARACTER "X" +UPPER_Z EQU "Z" ;UPPER CASE CHARACTER "Z" + +VEC_SING_STEP EQU 1 ;ID OF THE SINGLE STEP VECTOR +VEC_BREAKPOINT EQU 3 ;ID OF THE BREAKPOINT VECTOR +VEC_TERM_ADDR EQU 22H ;ID OF THE TERMINATE ADDRESS VECTOR +VEC_CTRL_BREAK EQU 23H ;ID OF THE CTRL BREAK EXIT ADDRESS VECTOR +VEC_CRIT_ERR EQU 24H ;ID OF THE CRITICAL ERROR HANDLER VECTOR +VEC_PRIMITIVE_DISK_READ EQU 25H ;ID OF THE PRIMITAVE DISK READ VECTOR +VEC_PRIMITIVE_DISK_WRITE EQU 26H ;ID OF THE PRIMITAVE DISK WRITE VECTOR +GENERIC_IOCTL EQU 440DH ;an000;Generic IOCtl function +READ_WRITE EQU 08H ;an000;read/write relative sectors +READ_SECTOR EQU 00H ;an000;currently unknown value +WRITE_SECTOR EQU 00H ;an000;currently unknown value + +SET_DRIVEID_OPTION EQU 1 ;AL VALUE FOR "PARSE FILENAME" FUNCTION +LSEEK_FROM_START EQU 0 ;AL VALUE FOR "LSEEK" FUNCTION +LSEEK_EOF_OPTION EQU 2 ;AL VALUE FOR "LSEEK" FUNCTION + +;======================= EMS Equates Begin =============================== + +EMS_GET_MAN_STAT equ 40h ;an000;function 40h, int 67h +EMS_UNALL_PG_CNT equ 42h ;an000;funciton 42h, int 67h +EMS_HAN_ALLOC equ 43h ;an000;function 43h, int 67h +EMS_MAP_MEMORY equ 44h ;an000;function 44h, int 67h +EMS_PAGE_DEALL equ 45h ;an000;function 45h, int 67h +EMS_VERSION equ 46h ;an000;function 46h, int 67h +EMS_SAVE_PAGE_MAP equ 47h ;an000;function 47h, int 67h +EMS_REST_PAGE_MAP equ 48h ;an000;function 48h, int 67h +EMS_HANDLE_CNT equ 4bh ;an000;function 4bh, int 67h +EMS_HANDLE_PAGES equ 4dh ;an000;function 4dh, int 67h +EMS_GET_SET_PG_MP equ 4eh ;an000;function 4eh, int 67h +EMS_GET_PAGE_MAP equ 00h ;an000;sub function 00h of +EMS_PG_FRAME equ 5800h ;an000;function 58h, int 67h + ; function 4eh, int 67h +EMS_SET_PAGE_MAP equ 01h ;an000;sub function 01h of + ; function 4eh, int 67h +EMS_HANDLE_TOTAL equ 0ffh ;an000;total possible handles + +EMS_LIM_40 equ 040h ;an000;LIM 4.0 I.D. + +XM_ERR80 equ 80h ;an000;error message type +XM_ERR83 equ 83h ;an000;error message type +XM_ERR84 equ 84h ;an000;error message type +XM_ERR85 equ 85h ;an000;error message type +XM_ERR86 equ 86h ;an000;error message type +XM_ERR87 equ 87h ;an000;error message type +XM_ERR88 equ 88h ;an000;error message type +XM_ERR89 equ 89h ;an000;error message type +XM_ERR8A equ 8Ah ;an000;error message type +XM_ERR8B equ 8Bh ;an000;error message type +XM_ERR8D equ 8Dh ;an000;error message type +XM_ERR8E equ 8Eh ;an000;error message type +XM_ERR8F equ 8Fh ;an000;error message type +XM_NOT_INST equ 0ffh ;an000;EMS not inst + +;======================= EMS Equates End ================================= + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBERR.ASM b/v4.0/src/CMD/DEBUG/DEBERR.ASM new file mode 100644 index 0000000..3c59cf0 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBERR.ASM @@ -0,0 +1,183 @@ + PAGE 80,132 ; + TITLE DEBERR.ASM - DEBUGGER DISK ERROR HANDLER + +;******************* START OF SPECIFICATIONS ***************************** +; +; MODULE NAME:DEBERR.SAL +; +; DESCRIPTIVE NAME: DISK ERROR HANDLER +; +; FUNCTION: THIS ROUTINE IS A CATCHALL ERROR HANDLER. IT PRIMARILY +; HANDLES DISK ERROR. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; INPUT: NA +; +; EXIT-NORMAL: NA +; +; EXIT-ERROR: NA +; +; INTERNAL REFERENCES: +; +; +; EXTERNAL REFERENCES: +; +; NOTES: THIS MODULE SHOULD BE PROCESSED WITH THE SALUT PRE-PROCESSOR +; WITH OPTIONS "PR". +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+DEBCONST+ +; DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION DOS 4.0 - MESSAGE RETRIEVER IMPLEMENTED. DMS:6/17/87 +; +; +; COPYRIGHT: "MS DOS DEBUG Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;******************** END OF SPECIFICATIONS ****************************** + + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBERR + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC +.CREF +.LIST + + INCLUDE DEBEQU.ASM + +FIRSTDRV EQU "A" + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + EXTRN RDFLG:BYTE + EXTRN DRVLET:BYTE + EXTRN dr1_ptr:word,dr2_ptr:word,dr3_ptr:word,dr4_ptr:word ;ac000 +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN PARITYFLAG:BYTE +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE + ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + EXTRN RESTART:NEAR + PUBLIC DRVERR, TRAPPARITY, RELEASEPARITY, NMIINT, NMIINTEND + +TRAPPARITY: + IF IBMJAPAN + PUSH BX + PUSH ES + PUSH DX ; save location of new offset + MOV DX,OFFSET DG:NMIINT ; DS:DX has new interrupt vector + CALL SWAPINT ; diddle interrupts + ASSUME ES:NOTHING + + MOV WORD PTR [NMIPTR],BX ; save old offset + MOV WORD PTR [NMIPTR+2],ES ; save old segment + POP DX ; get old regs back + POP ES ; restore old values + ASSUME ES:DG + + POP BX + MOV BYTE PTR [PARITYFLAG],0 ; no interrupts detected yet! + RET + +SWAPINT: + PUSH AX + MOV AX,(GET_INTERRUPT_VECTOR SHL 8) + 2 + INT 21H ; Get old NMI Vector + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) + 2 + INT 21h ; let OS set new vector + POP AX + ENDIF + RET + +RELEASEPARITY: + IF IBMJAPAN + PUSH DX + PUSH DS + PUSH BX + PUSH ES + LDS DX,DWORD PTR [NMIPtr] ; get old vector + CALL SwapInt ; diddle back to original + POP ES + POP BX + POP DS + POP DX + MOV [PARITYFLAG],0 ; no interrupts possible! + ENDIF + RET + +NMIInt: + IF IBMJAPAN + PUSH AX ; save AX + IN AL,0A0H ; get status register + OR AL,1 ; was there parity check? + POP AX ; get old AX back + JZ NMICHAIN ; no, go chain interrupt + OUT 0A2H,AL ; reset NMI detector + MOV CS:[PARITYFLAG],1 ; signal detection + IRET +NMICHAIN: + JMP DWORD PTR CS:[NMIPTR] ; chain the vectors +NMIPTR DD ? ; where old NMI gets stashed + ENDIF +NMIINTEND: + +DRVERR: + + or al,al ;ac000;see if drive specified +; $if nz ;an000;drive specified + JZ $$IF1 + add byte ptr drvlet,firstdrv;ac000;determine drive letter + cmp byte ptr rdflg,write ;ac000;see if it is read/write +; $if z ;an000;it is write + JNZ $$IF2 + mov dx,offset dg:dr2_ptr ;an000;message +; $else ;an000;it is read + JMP SHORT $$EN2 +$$IF2: + mov dx,offset dg:dr1_ptr ;an000;message +; $endif ;an000; +$$EN2: +; $else ;an000;write protect error + JMP SHORT $$EN1 +$$IF1: + add byte ptr drvlet,firstdrv;ac000;determine drive letter + cmp byte ptr rdflg,write ;ac000;see if it is read/write +; $if z ;an000;it is write + JNZ $$IF6 + mov dx,offset dg:dr4_ptr ;an000;message +; $else ;an000;it is read + JMP SHORT $$EN6 +$$IF6: + mov dx,offset dg:dr3_ptr ;an000;message +; $endif ;an000; +$$EN6: +; $endif ;an000; +$$EN1: + +; CLEAN OUT THE DISK... + MOV AH,DISK_RESET + INT 21H + + JMP RESTART +CODEEND: + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBMES.ASM b/v4.0/src/CMD/DEBUG/DEBMES.ASM new file mode 100644 index 0000000..23f0e0d --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBMES.ASM @@ -0,0 +1,1524 @@ +PAGE 60,132 ; + TITLE DEBMES.SAL - DEBUGGER MESSAGES PC DOS + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBMES + ENDIF + +;******************* START OF SPECIFICATIONS ***************************** +; +; MODULE NAME:DEBMES.SAL +; +; DESCRIPTIVE NAME: SUPPLIES APPLICABLE MESSAGES TO DEBUG.ASM +; +; FUNCTION: THIS ROUTINE PROVIDES A MEANS BY WHICH MESSAGES MAY BE +; OUTPUT FOR DEBUG. THIS IS HANDLED THROUGH THE MESSAGE +; RETRIEVER FUNCTION SYSDISPMSG. TO +; FACILITATE MIGRATION AWAY FROM THE PRINTF UTILITY +; THE INTERFACE FOR INVOKING MESSAGES HAS REMAINED THE SAME. +; THIS IS ACCOMPLISHED THROUGH THE USE OF MACROS AND TABLES. +; EACH MESSAGE HAS A TABLE OF VALUES REQUIRED BY THE MESSAGE +; RETRIEVER UTILITIES. THE MACROS OPERATE ON THESE TABLES +; TO SUPPLY SYSDISPMSG WITH THE VALUES NECESSARY +; TO PRINT A MESSAGE. +; +; ENTRY POINT: PRINTF +; +; INPUT: PRINTF IS INVOKED AS IT HAS ALWAYS BEEN INVOKED. DX MUST +; POINT TO THE OFFSET OF A MESSAGE TABLE. THE TABLE POINTED TO +; BY DX CONTAINS ALL THE NECESSARY INFORMATION FOR THAT MESSAGE +; TO BE PRINTED. +; +; EXIT-NORMAL: NO CARRY +; +; EXIT-ERROR: CARRY SET - EITHER MESSAGE NOT FOUND OR UNABLE TO BE DISPLAYED +; +; INTERNAL REFERENCES: +; +; ROUTINE:DISP_MESSAGE - THIS MACRO IS USED TO DIPLAY A MESSAGE +; VIA SYSDISPMSG. IT TAKES AS INPUT A POINTER +; IN DX. THIS POINTER POINTS TO A TABLE OF +; VALUES FOR THE REQUESTED MESSAGE. +; DISP_MESSAGE OBTAINS THE VALUES IT NEEDS TO +; TO INVOKE SYSDISPMSG FROM THIS TABLE. +; +; EXTERNAL REFERENCES: +; +; ROUTINE: SYSMSG.INC - THIS ROUTINE IS SUPPLIED TO INTERFACE THE +; MESSAGE RETRIEVER SERVICES. +; +; NOTES: THIS MODULE SHOULD BE PROCESSED WITH THE SALUT PRE-PROCESSOR +; WITH OPTIONS "PR". +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+DEBCONST+ +; DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION DOS 4.0 - MESSAGE RETRIEVER IMPLEMENTED. DMS:6/17/87 +; +; +; COPYRIGHT: "MS DOS DEBUG Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;******************** END OF SPECIFICATIONS ****************************** +.xlist + + include sysmsg.inc ;an000;message retriever + +.list + +msg_utilname ;an000;DEBUG messages + +;========================================================================= +;revised debmes.asm +;========================================================================= + +fatal_error equ 45 ;fatal message handler error +unlim_width equ 00h ;unlimited output width +pad_blank equ 20h ;blank pad +pre_load equ 00h ;an000;normal pre-load +pad_zero equ 30h ;an000;zero pad + + +FALSE EQU 0 +TRUE EQU NOT FALSE + +;SYSVER EQU FALSE ;if true, i/o direct to bios + INCLUDE SYSVER.INC + +;========================================================================= +; macro disp_message: the macro takes the message obtained in get_message +; and displays it to the applicable screen device. +;========================================================================= + +disp_message macro tbl ;an000;display message macro + + push si ;an000;save affected reg + push di ;an000; + push ax ;an000; + push bx ;an000; + push cx ;an000; + push dx ;an000; + + push tbl ;an000;exchange tbl with si + pop si ;an000; + + mov ax,[si] ;an000;move message number to ax + mov bx,[si+3] ;an000;display handle + mov cx,[si+7] ;an000;number of subs + mov dl,[si+9] ;an000;function type + mov di,[si+10] ;an000;input buffer if appl. + mov dh,[si+2] ;an000;message type + mov si,[si+5] ;an000;sublist + + call sysdispmsg ;an000;display the message + + pop dx ;an000;restore affected reg + pop cx ;an000; + pop bx ;an000; + pop ax ;an000; + pop di ;an000; + pop si ;an000; + + +endm ;an000;end macro disp_message + +;========================================================================= +; macro disp_message: end macro +;========================================================================= + + + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + + +code segment public byte ;an000;code segment + assume cs:dg,ds:dg,ss:dg,es:dg ;an000; + + public printf ;an000;share printf +;; public disp_fatal ;an000;fatal error display + public pre_load_message ;an000;message pre load + +.xlist + +msg_services + +.list + +;========================================================================= +; include sysmsg.inc - message retriever services +;options selected: +; NEARmsg +; DISPLAYmsg +; LOADmsg +; INPUTmsg +; CHARmsg +; NUMmsg +; CLSAmsg +; CLSBmsg +; CLSCmsg +; CLSDmsg +;========================================================================= + +.xlist + +msg_services ;an000;load the messages +msg_services ;an000;get and display messages +msg_services ;an000;input from keyboard +msg_services ;an000;message types +msg_services ;an000; +msg_services ;an000; + +.list + +;========================================================================= +; printf: printf is a replacement of the printf procedure used in DOS +; releases prior 4.00. printf invokes the macros get_message and +; disp_message to invoke the new message handler. the interface +; into printf will continue to be a pointer to a message passed +; in DX. the pointer is pointing to more than a message now. it +; is pointing to a table for that message containing all relevant +; information for retieving and printing the message. the macros +; get_message and disp_message operate on these tables. +;========================================================================= + +printf proc near ;an000;printf procedure + + disp_message dx ;an000;display a message +;; $if c ;an000;if an error occurred +;; call disp_fatal ;an000;display the fatal error +;; $endif ;an000; + + ret ;an000;return to caller + +printf endp ;an000;end printf + + +;========================================================================= +; disp_fatal: this routine displays a fatal error message in the event +; an error occurred in disp_message. +;========================================================================= + +;;disp_fatal proc near ;an000;fatal error message +;; +;; mov ax,fatal_error ;an000;fatal_error number +;; mov bx,stdout ;an000;print to console +;; mov cx,0 ;an000;no parameters +;; mov dl,no_input ;an000;no input will be coming +;; mov dh,UTILITY_MSG_CLASS ;an000;utility messages +;; call sysdispmsg ;an000;dispaly fatal error +;; ret ;an000;return to caller +;; +;;disp_fatal endp ;an000;end disp_fatal + + +;========================================================================= +; PRE_LOAD_MESSAGE : This routine provides access to the messages required +; by DEBUG. This routine will report if the load was +; successful. An unsuccessful load will cause DEBUG +; to terminate with an appropriate error message. +; +; Date : 6/15/87 +;========================================================================= + +PRE_LOAD_MESSAGE proc near ;an000;pre-load messages + + call SYSLOADMSG ;an000;invoke loader + +; $if c ;an000;if an error + JNC $$IF1 + pushf ;an000;save flags + call SYSDISPMSG ;an000;let him say why + popf ;an000;restore flags +; $endif ;an000; +$$IF1: + + ret ;an000;return to caller + +PRE_LOAD_MESSAGE endp ;an000;end proc + +include msgdcl.inc + +code ends ;an000;end code segment + + +CONST SEGMENT PUBLIC BYTE + + PUBLIC ENDMES_PTR,CRLF_PTR,NAMBAD_PTR + PUBLIC NOTFND_PTR,NOROOM_PTR,BADVER + PUBLIC NOSPACE_PTR,DRVLET + PUBLIC ACCMES_PTR,PROMPT_PTR + PUBLIC TOOBIG_PTR,SYNERR_PTR,BACMES_PTR + PUBLIC HEXERR_PTR,HEXWRT_PTR,WRTMES_PTR,EXEBAD_PTR,EXEWRT_PTR + PUBLIC EXECEMES_PTR, PARITYMES_PTR, NONAMESPEC_PTR + PUBLIC dr1_ptr,dr2_ptr,dr3_ptr,dr4_ptr ;ac000;new messages + PUBLIC CHANGE_FLAG_PTR,DF_ERROR,BF_ERROR,BR_ERROR,BP_ERROR + PUBLIC CONSTEND + +;======================= TABLE STRUCTURE ================================= +; +; byte 1 - message number of message to be displayed +; byte 2 - message type to be used, i.e.;class 1, utility, etc. +; byte 3 - display handle, i.e.; console, printer, etc. +; byte 4 - pointer to substitution list, if any. +; byte 6 - number of replaceable parameters, if any. +; byte 7 - type of input from keyboard, if any. +; byte 8 - pointer to buffer for keyboard input, if any. +; +;========================================================================= + + IF SYSVER + + PUBLIC BADDEV_PTR,BADLSTMES_PTR + + +baddev_ptr label word ;an000;"Bad device name",0 + dw 0006 ;an000;message number 6 + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +badlstmes_ptr label word ;an000;"Couldn't open list device + ; PRN","Enter name of list + ; device?" + dw 0007 ;an000;message number 7 + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db DOS_KEYB_INP ;an000;keyboard input + dw 00 ;an000;no keyboard buffer + + + ENDIF + +;================= REPLACEABLE PARAMETER SUBLIST STRUCTURE =============== +; +; byte 1 - substitution list size, always 11 +; byte 2 - reserved for use by message handler +; byte 3 - pointer to parameter to be used as a substitution +; byte 7 - which parameter is this to replace, %1, %2, etc. +; byte 8 - determines how the parameter is to be output +; byte 9 - determines the maximum width of the parameter string +; byte 10 - determines the minimum width of the parameter string +; byte 11 - define what is to be used as a pad character +; +;========================================================================= + + +;========================================================================= +; replaceable parameter sublists +;========================================================================= + +db_synerr_sub label dword ;an000;synerr parameters + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width + db pad_blank ;an000;blank pad + +db_change_sub label dword ;an000;synerr parameters + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width + db pad_blank ;an000;blank pad + +db_drive_error label dword ;an000;drive error parameters + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:drvlet ;an000;point to drive letter + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db 01 ;an000;1 byte + db 01 ;an000;1 byte + db pad_blank ;an000;blank pad + + + +;========================================================================= +; end replaceable parameter sublists +;========================================================================= + + +crlf_ptr label word ;an000;13,10,0 + dw 0008 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +bacmes_ptr label word ;an000;32,8,0 + dw 0044 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +badver label word ;an000;"Incorrect DOS version" + dw 0001 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +endmes_ptr label word ;an000;13,10,"Program terminated + ; normally",0 + dw 0009 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +nambad_ptr label word ;an000;"Invalid drive specification",0 + dw 0010 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +notfnd_ptr label word ;an000;"File not found",0 + dw 0002 ;an000;message number + db Ext_Err_Class ;an000;extended error + dw stderr ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +noroom_ptr label word ;an000;"File creation error",0 + dw 0012 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +nospace_ptr label word ;an000;"Insufficient space on disk",0 + dw 0013 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +dr1_ptr label word ;an000;"Disk error reading drive %1" + dw 0014 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_drive_error ;an000;sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +dr2_ptr label word ;an000;"Disk error writing drive %1" + dw 0015 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_drive_error ;an000;sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +dr3_ptr label word ;an000;"Write protect error reading + ; drive %1" + dw 0016 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_drive_error ;an000;sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +dr4_ptr label word ;an000;"Write protect error writing + ; drive %1" + dw 0017 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_drive_error ;an000;sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +toobig_ptr label word ;an000;"Insufficient memory",0 + dw 0008 ;an000;message number + db Ext_Err_Class ;an000;utility message + dw stderr ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +synerr_ptr label word ;an000;"%1^Error",0 + dw 0019 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_synerr_sub ;an000;sublist + dw 01 ;an000;1 sub - leading spaces + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +hexerr_ptr label word ;an000;"Error in EXE or HEX file",0 + dw 0020 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +exebad_ptr label word ;an000;"Error in EXE or HEX file",0 + dw 0020 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +hexwrt_ptr label word ;an000;"EXE and HEX files cannot be + ; written",0 + dw 0021 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +exewrt_ptr label word ;an000;"EXE and HEX files cannot be + ; written",0 + dw 0021 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +execemes_ptr label word ;an000;"EXEC failure",0 + dw 0022 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +nonamespec_ptr label word ;an000;"(W)rite error, no destination + ; defined",0 + dw 0023 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +accmes_ptr label word ;an000;Access denied",0 + dw 0024 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +paritymes_ptr label word ;an000;"Parity error or nonexistant + ; memory error detected",0 + dw 0025 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +prompt_ptr label word ;an000;"-",0 + dw 0026 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +change_flag_ptr label word ;an000;"%1 -",0 + dw 0027 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_change_sub ;an000;sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +df_error db "df",0 +bf_error db "bf",0 +br_error db "br",0 +bp_error db "bp",0 +drvlet db "A",0 + +CONSTEND LABEL BYTE + +CONST ENDS + +DATA SEGMENT PUBLIC BYTE + + PUBLIC HEX_ARG1,HEX_ARG2,HEX_PTR,ARG_BUF + PUBLIC ARG_BUF_PTR,ADD_PTR,ERR_TYPE + PUBLIC CRLF_PTR,ADD_ARG,SUB_ARG,PROMPT_PTR + PUBLIC REGISTER_PTR,REG_NAME,REG_CONTENTS + PUBLIC SINGLE_REG_PTR,SINGLE_REG_ARG + PUBLIC ERRMES_PTR,LOC_PTR,LOC_ADD + PUBLIC LITTLE_PTR,BIG_PTR,LITTLE_CONTENTS + PUBLIC BIG_CONTENTS,COMP_PTR,COMP_ARG1,COMP_ARG2 + PUBLIC COMP_ARG3,COMP_ARG4,COMP_ARG5,COMP_ARG6 + PUBLIC WRTMES_PTR,WRT_ARG1,WRT_ARG2 + PUBLIC IOTYP,MESTYP + PUBLIC ONE_CHAR_BUF,ONE_CHAR_BUF_PTR + PUBLIC OPBUF,UNASSEM_LN_PTR + + PUBLIC xm_han_ret_ptr + PUBLIC xm_mapped_ptr + PUBLIC xm_err80_ptr + PUBLIC xm_err83_ptr + PUBLIC xm_err84_ptr + PUBLIC xm_err85_ptr + PUBLIC xm_err86_ptr + PUBLIC xm_err87_ptr + PUBLIC xm_err88_ptr + PUBLIC xm_err89_ptr + PUBLIC xm_err8a_ptr + PUBLIC xm_err8b_ptr + PUBLIC xm_err8d_ptr + PUBLIC xm_err8e_ptr + PUBLIC xm_err_gen_ptr + PUBLIC xm_parse_err_ptr + PUBLIC xm_status_ptr + PUBLIC xm_page_seg_ptr + PUBLIC xm_deall_ptr + PUBLIC xm_errff_ptr + PUBLIC xm_unall_ptr + PUBLIC xm_han_alloc_ptr + + EXTRN XM_HANDLE_RET:word + EXTRN XM_LOG:byte + EXTRN XM_PHY:byte + EXTRN XM_PAGE_CNT:word + EXTRN XM_FRAME:word + EXTRN XM_DEALL_HAN:word + EXTRN XM_ALLOC_PG:word + EXTRN XM_TOTAL_PG:word + EXTRN XM_HAN_ALLOC:word + EXTRN XM_HAN_TOTAL:word + +;========================================================================= +; begin parameter sublists +;========================================================================= + +;======================= unassemble parameter sublists =================== + +db_unassem_sb1 label dword ;an000;unassemble parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width + db pad_blank ;an000;blank pad + +db_unassem_sb2 label dword ;an000;unassemble parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:opbuf ;an000;point to argument buffer + db 02 ;an000;parameter two + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width + db pad_blank ;an000;blank pad + + +;================== hex argument parameter sublists ====================== + +db_hexarg_sb1 label dword ;an000;hex argument parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:hex_arg1 ;an000;point to argument buffer + db 01 ;an000;parameter one + db right_align+bin_hex_word + ;an000;right align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_hexarg_sb2 label dword ;an000;hex argument parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:hex_arg2 ;an000;point to argument buffer + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_hexarg_sb3 label dword ;an000;hex argument parameter 3 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 03 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width + db pad_blank ;an000;blank pad + + +;================== hex add parameter sublists =========================== + +db_hexadd_sb1 label dword ;an000;hex add parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:add_arg ;an000;point to add_arg + db 01 ;an000;parameter one + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_hexadd_sb2 label dword ;an000;hex argument parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:sub_arg ;an000;point to sub_arg + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;================== end hex add parameter sublists ======================= + +;================== single register parameter sublists =================== +;string: "%1 %2",13,10,":",0 + +db_singrg_sb1 label dword ;an000;single register parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +db_singrg_sb2 label dword ;an000;single register parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:single_reg_arg ;an000;point single_reg_arg + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;================== register parameter sublists ========================== +;string: "%1=%2 ",0 + +db_regist_sb1 label dword ;an000;register parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:reg_name ;an000;point to reg_name + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db 02 ;an000;unlimited width + db 02 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +db_regist_sb2 label dword ;an000;register parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:reg_contents ;an000;point to reg_contents + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;================== error message parameter sublists ===================== +;string: "%1 Error",0 + +db_error_sb1 label dword ;an000;error message parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:err_type ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +;================== writing message parameter sublists =================== +;string: "Writing %1%2 bytes",0 + +db_wrtmes_sb1 label dword ;an000;wrtmes parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:wrt_arg1 ;an000;point to argument buffer + db 01 ;an000;parameter one + db right_align+bin_hex_word + ;an000;right align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_wrtmes_sb2 label dword ;an000;wrtmes parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:wrt_arg2 ;an000;point to argument buffer + db 02 ;an000;parameter two + db left_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;================== loc address parameter sublists ======================= +;string: "%1:%2=",0 + +db_locadd_sb1 label dword ;an000;loc address parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db right_align+Char_field_ASCIIZ + ;an000;left align/ASCIZZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +db_locadd_sb2 label dword ;an000;loc address parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:loc_add ;an000;point to loc_add + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;================== little contents parameter sublists =================== +;string "%1",0 + +db_little_sb1 label dword ;an000;one byte output parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:little_contents ;an000;point to little_contents + db 01 ;an000;parameter one + db right_align+bin_hex_byte + ;an000;left align/byte/hexadecimal + db 02 ;an000;maximum of 2 bytes + db 02 ;an000;minimum of 2 bytes + db pad_zero ;an000;blank pad + +;================== big argument parameter sublists ====================== +;string: "%1",0 + +db_big_sb1 label dword ;an000;word argument parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:big_contents ;an000;point to big_contents + db 01 ;an000;parameter one + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;======================= comp argument parameter sublists ================ +;string "%1:%2 %3 %4 %5:%6",0 + +db_comp_sb1 label dword ;an000;comp argument parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg1 ;an000;point to comp_arg1 + db 01 ;an000;parameter one + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_comp_sb2 label dword ;an000;comp argument parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg2 ;an000;point to comp_arg2 + db 02 ;an000;parameter two + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_comp_sb3 label dword ;an000;comp argument parameter 3 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg3 ;an000;point to comp_arg3 + db 03 ;an000;parameter three + db right_align+bin_hex_byte + ;an000;left align/byte/hexadecimal + db 02 ;an000;maximum of 2 bytes + db 02 ;an000;minimum of 2 bytes + db pad_zero ;an000;blank pad + +db_comp_sb4 label dword ;an000;comp argument parameter 4 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg4 ;an000;point to comp_arg4 + db 04 ;an000;parameter four + db right_align+bin_hex_byte + ;an000;left align/byte/hexadecimal + db 02 ;an000;maximum of 2 bytes + db 02 ;an000;minimum of 2 bytes + db pad_zero ;an000;blank pad + +db_comp_sb5 label dword ;an000;comp argument parameter 5 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg5 ;an000;point to comp_arg5 + db 05 ;an000;parameter five + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +db_comp_sb6 label dword ;an000;comp argument parameter 6 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:comp_arg6 ;an000; + db 06 ;an000;parameter 6 + db right_align+bin_hex_word + ;an000;left align/word/hexadecimal + db 04 ;an000;maximum of 4 bytes + db 04 ;an000;minimum of 4 bytes + db pad_zero ;an000;blank pad + +;======================= disk error parameter sublists =================== +;string: "%1 error %2 drive %3",0 + +db_disk_sb1 label dword ;an000;disk argument parameter 1 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:mestyp ;an000;point to mestyp + db 01 ;an000;parameter one + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +db_disk_sb2 label dword ;an000;disk argument parameter 2 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:iotyp ;an000;point to iotyp + db 02 ;an000;parameter two + db left_align+Char_field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +db_disk_sb3 label dword ;an000;disk argument parameter 3 + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:drive ;an000;point to drive + db 03 ;an000;parameter three + db left_align+char_field_char + ;an000;left align/character/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +arg_buf_sb1 label dword ;an000;argument sublist + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:arg_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_Field_ASCIIZ + ;an000;left align/ASCIIZ/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +one_char_sb1 label dword ;an000;character buffer sublist + db Sublist_Length ;an000;sublist size + db reserved ;an000;reserved + dd dg:one_char_buf ;an000;point to argument buffer + db 01 ;an000;parameter one + db left_align+Char_Field_Char + ;an000;left align/character/character + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum of 0 bytes + db pad_blank ;an000;blank pad + +xm_han_sub label dword ;an000;sublist for handles + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_HANDLE_RET ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 30h ;an000;pad with zeros + +xm_map_sub label dword ;an000;sublist for mappings + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_LOG ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Byte;an000; + db 02 ;an000;maximum width + db 02 ;an000;minimum width + db 30h ;an000;pad with zeros + + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_PHY ;an000;parameter 2 + db 02 ;an000;parameter 2 + db right_align+Bin_Hex_Byte;an000; + db 02 ;an000;maximum width + db 02 ;an000;minimum width + db 30h ;an000;pad with zeros + +xm_sta_sub label word ;an000;sublist for status + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_HANDLE_RET ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 30h ;an000;pad with zeros + + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_PAGE_CNT ;an000;parameter 2 + db 02 ;an000;parameter 2 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 30h ;an000;pad with zeros + +xm_page_seg_sub label word ;an000;sublist for frame seg status + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_PHY ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Byte;an000; + db 02 ;an000;maximum width + db 02 ;an000;minimum width + db 30h ;an000;pad with zeros + + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_FRAME ;an000;parameter 2 + db 02 ;an000;parameter 2 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 30h ;an000;pad with zeros + +xm_deall_sub label word ;an000;sublist for handle deallocation + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_DEALL_HAN ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Byte;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 30h ;an000;pad with zeros + +xm_unall_sub label word ;an000;sublist unallocated page report + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_ALLOC_PG ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 20h ;an000;pad with blanks + + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_TOTAL_PG ;an000;parameter 1 + db 02 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 20h ;an000;pad with zeros + + +xm_han_alloc_sub label word ;an000;sublist unallocated page report + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_HAN_ALLOC ;an000;parameter 1 + db 01 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 20h ;an000;pad with blanks + + db Sublist_Length ;an000;11 bytes + db Reserved ;an000;reserved field + dd dg:XM_HAN_TOTAL ;an000;parameter 1 + db 02 ;an000;parameter 1 + db right_align+Bin_Hex_Word;an000; + db 04 ;an000;maximum width + db 04 ;an000;minimum width + db 20h ;an000;pad with zeros +;========================================================================= +; end parameter sublists +;========================================================================= + + +unassem_ln_ptr label word ;an000;"%1%2",0 + dw 0032 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_unassem_sb1 ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +hex_ptr label word ;an000;"%1:%2 %3",0 + dw 0033 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_hexarg_sb1 ;an000;sublist + dw 03 ;an000;3 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +add_ptr label word ;an000;"%1 %2",0 + dw 0034 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_hexadd_sb1 ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + + +single_reg_ptr label word ;an000;"%1 %2",13,10,":",0 + dw 0035 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_singrg_sb1 ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + + +register_ptr label word ;an000;"%1=%2 ",0 ex: AX=FFFF + dw 0036 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_regist_sb1 ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +errmes_ptr label word ;an000;"%1 Error",0 + dw 0037 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_error_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +wrtmes_ptr label word ;an000;"Writing %1 bytes",0 + dw 0038 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_wrtmes_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +loc_ptr label word ;an000:"%1;%2=",0 ex:CX:0000 + dw 0039 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_locadd_sb1 ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +little_ptr label word ;an000;"%1",0 ex:FF + dw 0040 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_little_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +big_ptr label word ;an000;"%1",0 + dw 0041 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_big_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +comp_ptr label word ;an000;"%1:%2 %3 %4 %5:%6",0 + dw 0042 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:db_comp_sb1 ;an000;sublist + dw 06 ;an000;6 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +arg_buf_ptr label word ;an000;"%1" + dw 0046 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:arg_buf_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +one_char_buf_ptr label word ;an000;"%1" + dw 0047 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:one_char_sb1 ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_unall_ptr label word ;an000;unallocated message report + dw 0050 ;an000;"%1 of a total %2 EMS pages + ; have been allocated",cr,lf + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_UNALL_SUB ;an000;sublist + dw 02 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_han_alloc_ptr label word ;an000;unallocated message report + dw 0051 ;an000;"%1 of a total %2 EMS handles + ; have been allocated",cr,lf + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_HAN_ALLOC_SUB ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_han_ret_ptr label word ;an000;prints handle created + dw 0055 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_HAN_SUB ;an000;sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_mapped_ptr label word ;an000;prints log/phy pages + dw 0056 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_MAP_SUB ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err80_ptr label word ;an000;ems error message + dw 0057 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err83_ptr label word ;an000;ems error message + dw 0058 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err84_ptr label word ;an000;ems error message + dw 0059 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err85_ptr label word ;an000;ems error message + dw 0060 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err86_ptr label word ;an000;ems error message + dw 0061 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err87_ptr label word ;an000;ems error message + dw 0062 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err88_ptr label word ;an000;ems error message + dw 0063 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err89_ptr label word ;an000;ems error message + dw 0064 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err8a_ptr label word ;an000;ems error message + dw 0065 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err8b_ptr label word ;an000;ems error message + dw 0066 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err8d_ptr label word ;an000;ems error message + dw 0067 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err8e_ptr label word ;an000;ems error message + dw 0068 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_err_gen_ptr label word ;an000;ems error message + dw 0070 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_parse_err_ptr label word ;an000;input error message + dw 0071 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_status_ptr label word ;an000;prints status of EMS + dw 0072 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_STA_SUB ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_page_seg_ptr label word ;an000;"Physical page %1 = Frame + ; segment %2" + dw 0075 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_PAGE_SEG_SUB ;an000;sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_deall_ptr label word ;an000;"Handle %1 deallocated" + + dw 0076 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw dg:XM_DEALL_SUB ;an000;sublist + dw 01 ;an000;1 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +xm_errff_ptr label word ;an000;"EMS not installed" + + dw 0078 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility messages + dw stdout ;an000;display handle + dw 00 ;an000;sublist + dw 00 ;an000;0 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +arg_buf db 80 dup (?) ;an000;argument buffer +one_char_buf db ? ;an000;character buffer + +opbuf db 51h dup (?) + +hex_arg1 dw ? +hex_arg2 dw ? + +add_arg dw ? +sub_arg dw ? + +single_reg_arg dw ? + +reg_name dw ? +reg_contents dw ? + +err_type db 3 dup(0) ;ac000;changed to hold bf,bp,etc. + +wrt_arg1 dw ? +wrt_arg2 dw ? + +loc_add dw ? + +little_contents dw ? +big_contents dw ? + +comp_arg1 dw ? +comp_arg2 dw ? +comp_arg3 dw ? +comp_arg4 dw ? +comp_arg5 dw ? +comp_arg6 dw ? + +mestyp dw ? +iotyp dw ? +drive db ? + + +DATA ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBUASM.ASM b/v4.0/src/CMD/DEBUG/DEBUASM.ASM new file mode 100644 index 0000000..6dffb33 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBUASM.ASM @@ -0,0 +1,954 @@ + PAGE 80,132 ; + TITLE DEBUASM.ASM +; Code for the UASSEMble command in the debugger + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBUASM + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC + INCLUDE DEBEQU.ASM +.CREF +.LIST +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + EXTRN SYNERR_PTR:BYTE,UNASSEM_LN_PTR:WORD + EXTRN NSEG:WORD,SISAVE:WORD,BPSAVE:WORD,DISAVE:WORD + EXTRN BXSAVE:WORD,DSSAVE:WORD,ESSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD + EXTRN SSSAVE:WORD,CXSAVE:WORD,SPSAVE:WORD,FLSAVE:WORD + EXTRN DISTAB:WORD,SHFTAB:WORD,IMMTAB:WORD,GRP1TAB:WORD,GRP2TAB:WORD + EXTRN DBMN:BYTE,ESCMN:BYTE,DISPB:WORD,STACK:BYTE,REG8:BYTE + EXTRN REG16:BYTE,SREG:BYTE,SIZ8:BYTE,SEGTAB:WORD,M8087_TAB:BYTE + EXTRN FI_TAB:BYTE,SIZE_TAB:BYTE,MD9_TAB:BYTE,MD9_TAB2:BYTE + EXTRN MDB_TAB:BYTE,MDB_TAB2:BYTE,MDD_TAB:BYTE,MDD_TAB2:BYTE + EXTRN MDF_TAB:BYTE +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN DISADD:BYTE,DISCNT:WORD,BYTCNT:BYTE,TEMP:BYTE,AWORD:BYTE + EXTRN MIDFLD:BYTE,MODE:BYTE,REGMEM:BYTE,OPCODE:WORD,OPBUF:BYTE + EXTRN INDEX:WORD,ARG_BUF:BYTE,ARG_BUF_PTR:BYTE,ARG_BUF_INDEX:WORD + EXTRN OPBUF:BYTE,OPCODE:WORD +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CODE SEGMENT PUBLIC BYTE + ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + PUBLIC UNASSEM + PUBLIC DISASLN,MEMIMM,JMPCALL,SIGNIMM,ALUFROMREG,WORDTOALU + PUBLIC GRP2,PREFIX,OUTVARW,GRP1,SSPRE,MOVSEGTO,DSPRE,SHIFT + PUBLIC ESPRE,IMMED,CSPRE,OUTVARB,CHK10,ACCIMM,INT3,INVARB + PUBLIC MOVSEGFROM,LOADACC,OUTFIXB,XCHGAX,REGIMMW,SHORTJMP + PUBLIC SAV8,M8087,M8087_DB,M8087_DF,M8087_D9,M8087_DD + PUBLIC SAV16,SAVHEX,INFIXW,REGIMMB,OUTFIXW,SHIFTV,LONGJMP + PUBLIC INVARW,STOREACC,INFIXB,NOOPERANDS,ALUTOREG + PUBLIC SEGOP,REGOP,GETADDR + + EXTRN CRLF:NEAR,BLANK:NEAR,TAB:NEAR,STD_PRINTF:NEAR + EXTRN HEX:NEAR,DEFAULT:NEAR,OUTSI:NEAR,OUTDI:NEAR + EXTRN HEX_ADDRESS_ONLY:NEAR + +UNASSEM: + MOV BP,[CSSAVE] ; Default code segment + MOV DI,OFFSET DG:DISADD ; Default address + MOV CX,DISPB ; Default length + SHR CX,1 + SHR CX,1 + CALL DEFAULT + MOV WORD PTR [DISADD],DX ; Displacement of disassembly + MOV WORD PTR [DISADD+2],AX ; Segment + MOV WORD PTR [DISCNT],CX ; No. of bytes (but whole instructions) +DISLP: + CALL DISASLN ; Disassemble one line + CALL CRLF + TEST [DISCNT],-1 ; See if we've used up the range + JNZ DISLP + RET + +GOTDIS: + PUSH DS ; RE-GET LAST BYTE + PUSH SI + LDS SI,DWORD PTR [DISADD] + MOV AL,[SI-1] + POP SI + POP DS + RET + +GETDIS: + PUSH DS + LDS SI,DWORD PTR [DISADD] + LODSB ; Get the next byte of code + POP DS + MOV WORD PTR [DISADD],SI ; Update pointer + PUSH AX + PUSH DI + MOV DI,[ARG_BUF_INDEX] + CALL HEX ; Display each code byte + MOV [ARG_BUF_INDEX],DI + POP DI + MOV SI,[DISCNT] + OR SI,SI ; Check if range exhausted + JZ ENDRNG ; If so, don't wrap around + DEC SI ; Count off the bytes + MOV [DISCNT],SI +ENDRNG: + INC BYTE PTR[BYTCNT] ; Keep track of no. of bytes per line + POP AX + RET + +DSPRE: + INC BYTE PTR [NSEG+1] +SSPRE: + INC BYTE PTR [NSEG+1] +CSPRE: + INC BYTE PTR [NSEG+1] +ESPRE: + INC BYTE PTR [NSEG+1] + +PREFIX: + POP BX ; Dump off return address + CALL FINLN + CALL CRLF +DISASLN: + PUSH DS + LDS SI,DWORD PTR [DISADD] + CALL OUTSI ; Show disassembly address + POP DS + CALL HEX_ADDRESS_ONLY +DISASLN1: + MOV BYTE PTR [BYTCNT],0 ; Count of code bytes per line +; Fill overflow area with zeros + MOV DI,OFFSET DG:OPBUF + MOV CX,50 + MOV AL,0 + REP STOSB +; fill buffer with spaces + MOV DI,OFFSET DG:OPBUF + MOV CX,OPBUFLEN + MOV AL," " + REP STOSB + MOV DI,OFFSET DG:ARG_BUF + MOV [ARG_BUF_INDEX],DI + CALL GETDIS ; Get opcode + MOV DI,[ARG_BUF_INDEX] + MOV AH,0 + MOV BX,AX + AND AL,1 ; Mask to "W" bit + MOV [AWORD],AL + MOV AL,BL ; Restore opcode + SHL BX,1 + SHL BX,1 ; Multiply opcode by 4 + ADD BX,OFFSET DG:DISTAB + MOV DX,[BX] ; Get pointer to mnemonic from table + MOV [OPCODE],DX + MOV [ARG_BUF_INDEX],DI + MOV DI,OFFSET DG:OPBUF + CALL WORD PTR [BX+2] +FINLN: + MOV AH,[BYTCNT] ; See how many bytes in this instruction + ADD AH,AH ; Each uses two characters + MOV AL,14 ; Amount of space we want to use + SUB AL,AH ; See how many fill characters needed + CBW + XCHG CX,AX ; Parameter for TAB needed in CX + MOV DI,[ARG_BUF_INDEX] + CALL TAB + MOV SI,[OPCODE] + OR SI,SI + JZ GET_TAB +GET_OPCODE: + LODSB + OR AL,AL + JZ GET_TAB + STOSB + JMP GET_OPCODE + +GET_TAB: + MOV AL,9 + STOSB + MOV BYTE PTR [DI],0 ; nul terminate address buffer + MOV DX,OFFSET DG:UNASSEM_LN_PTR + CALL STD_PRINTF + RET + +GETMODE: + CALL GETDIS ; Get the address mode byte + MOV AH,AL + AND AL,7 ; Mask to "r/m" field + MOV [REGMEM],AL + SHR AH,1 + SHR AH,1 + SHR AH,1 + MOV AL,AH + AND AL,7 ; Mask to center 3-bit field + MOV [MIDFLD],AL + SHR AH,1 + SHR AH,1 + SHR AH,1 + MOV [MODE],AH ; Leaving 2-bit "MOD" field + RET + +IMMED: + MOV BX,OFFSET DG:IMMTAB + CALL GETMNE +FINIMM: + CALL TESTREG + JMP SHORT IMM + +MEMIMM: + CALL GETMODE + JMP SHORT FINIMM + +ACCIMM: + XOR AL,AL +IMM1: + CALL SAVREG +IMM: + MOV AL,"," + STOSB + TEST BYTE PTR [AWORD],-1 + JNZ SAV16 +SAV8: + CALL GETDIS + JMP SHORT SAVHEX + +LONGJMP: + PUSH DI + MOV DI,OFFSET DG:TEMP + CALL SAV16 + POP DI + CALL SAV16 + MOV AL,":" + STOSB + MOV SI,OFFSET DG:TEMP + MOV CX,4 +MOVDIG: + LODSB + STOSB + LOOP MOVDIG + RET + +SAV16: + CALL GETDIS ; Get low byte + MOV DL,AL + CALL GETDIS ; Get high byte + MOV DH,AL + CALL SAVHEX ; Convert and store high byte + MOV AL,DL +SAVHEX: + MOV AH,AL + SHR AL,1 + SHR AL,1 + SHR AL,1 + SHR AL,1 + CALL SAVDIG + MOV AL,AH +SAVDIG: + AND AL,0FH + ADD AL,90H + DAA + ADC AL,40H + DAA + STOSB + RET + +CHK10: + CALL GETDIS + CMP AL,10 + JNZ SAVHEX + RET + +SIGNIMM: + MOV BX,OFFSET DG:IMMTAB + CALL GETMNE + CALL TESTREG + MOV AL,"," + STOSB +SAVD8: + CALL GETDIS ; Get signed 8-bit number + CBW + MOV DX,AX ; Save true 16-bit value in DX + MOV AH,AL + MOV AL,"+" + OR AH,AH +; JZ NOSIGN + JNS POSITIV ; OK if positive + MOV AL,"-" + NEG AH ; Get magnitude if negative +POSITIV: + STOSB +; NOSIGN: + MOV AL,AH + JMP SHORT SAVHEX + +ALUFROMREG: + CALL GETADDR + MOV AL,"," + STOSB +REGFLD: + MOV AL,[MIDFLD] +SAVREG: + MOV SI,OFFSET DG:REG8 + CMP BYTE PTR [AWORD],1 + JNE FNDREG +SAVREG16: + MOV SI,OFFSET DG:REG16 +FNDREG: + CBW + ADD SI,AX + ADD SI,AX + MOVSW + RET + +SEGOP: + SHR AL,1 + SHR AL,1 + SHR AL,1 +SAVSEG: + AND AL,3 + MOV SI,OFFSET DG:SREG + JMP SHORT FNDREG + +REGOP: + AND AL,7 + JMP SHORT SAVREG16 + +MOVSEGTO: + MOV BYTE PTR [AWORD],1 + CALL GETADDR + MOV AL,"," + STOSB + MOV AL,[MIDFLD] + JMP SHORT SAVSEG + +MOVSEGFROM: + CALL GETMODE + CALL SAVSEG + MOV BYTE PTR [AWORD],1 + JMP SHORT MEMOP2 + +GETADDR: + CALL GETMODE + JMP SHORT ADDRMOD + +WORDTOALU: + MOV BYTE PTR [AWORD],1 +ALUTOREG: + CALL GETMODE + CALL REGFLD +MEMOP2: + MOV AL,"," + STOSB +ADDRMOD: + CMP BYTE PTR [MODE],3 + MOV AL,[REGMEM] + JE SAVREG + XOR BX,BX + MOV BYTE PTR [NSEG],3 + MOV BYTE PTR [DI],"[" + INC DI + CMP AL,6 + JNE NODRCT + CMP BYTE PTR [MODE],0 + JE DIRECT ; Mode=0 and R/M=6 means direct addr. +NODRCT: + MOV DL,AL + CMP AL,1 + JBE USEBX + CMP AL,7 + JE USEBX + CMP AL,3 + JBE USEBP + CMP AL,6 + JNE CHKPLS +USEBP: + MOV BX,[BPSAVE] + MOV BYTE PTR [NSEG],2 ; Change default to Stack Segment + MOV AX,BPREG +SAVBASE: + STOSW +CHKPLS: + CMP DL,4 + JAE NOPLUS + MOV AL,"+" + STOSB +NOPLUS: + CMP DL,6 + JAE DOMODE ; No index register + AND DL,1 ; Even for SI, odd for DI + JZ USESI + ADD BX,[DISAVE] + MOV AX,DIREG +SAVINDX: + STOSW +DOMODE: + MOV AL,[MODE] + OR AL,AL + JZ CLOSADD ; If no displacement, then done + CMP AL,2 + JZ ADDDIR + CALL SAVD8 ; Signed 8-bit displacement +ADDCLOS: + ADD BX,DX +CLOSADD: + MOV AL,"]" + STOSB + MOV [INDEX],BX +NOOPERANDS: + RET + +ADDDIR: + MOV AL,"+" + STOSB +DIRECT: + CALL SAV16 + JMP SHORT ADDCLOS + +USEBX: + MOV BX,[BXSAVE] + MOV AX,BXREG + JMP SHORT SAVBASE + +USESI: + ADD BX,[SISAVE] + MOV AX,SIREG + JMP SHORT SAVINDX + +SHORTJMP: + CALL GETDIS + CBW + ADD AX,WORD PTR [DISADD] + XCHG DX,AX +SAVJMP: + MOV AL,DH + CALL SAVHEX + MOV AL,DL + JMP SAVHEX + +JMPCALL: + CALL GETDIS + MOV DL,AL + CALL GETDIS + MOV DH,AL + ADD DX,WORD PTR [DISADD] + JMP SHORT SAVJMP + +XCHGAX: + AND AL,7 + CALL SAVREG16 + MOV AL,"," + STOSB + XOR AL,AL + JMP SAVREG16 + +LOADACC: + XOR AL,AL + CALL SAVREG + MOV AL,"," + STOSB +MEMDIR: + MOV AL,"[" + STOSB + XOR BX,BX + MOV BYTE PTR [NSEG],3 + JMP DIRECT + +STOREACC: + CALL MEMDIR + MOV AL,"," + STOSB + XOR AL,AL + JMP SAVREG + +REGIMMB: + MOV BYTE PTR [AWORD],0 + JMP SHORT REGIMM + +REGIMMW: + MOV BYTE PTR [AWORD],1 +REGIMM: + AND AL,7 + JMP IMM1 + +INT3: + MOV BYTE PTR [DI],"3" + INC DI + RET + +; 8087 instructions whose first byte is 0dfh +M8087_DF: + CALL GET64F + JZ ISDD3 + MOV SI,OFFSET DG:MDF_TAB + JMP NODB3 + +; 8087 instructions whose first byte is 0ddh +M8087_DD: + CALL GET64F + JZ ISDD3 + MOV SI,OFFSET DG:MDD_TAB + JMP NOD93 + +ISDD3: + MOV AL,DL + TEST AL,100B + JZ ISSTI + JMP ESC0 + +ISSTI: + AND AL,11B + MOV SI,OFFSET DG:MDD_TAB2 + MOV CL,AL + CALL MOVBYT + JMP PUTRST + +; 8087 instructions whose first byte is 0dbh +M8087_DB: + CALL GET64F + JZ ISDB3 + MOV SI,OFFSET DG:MDB_TAB +NODB3: + CALL PUTOP + CALL PUTSIZE + JMP ADDRMOD + +ISDB3: + MOV AL,DL + TEST AL,100B + JNZ ISDBIG +ESC0V: + JMP ESC0 + +ISDBIG: + CALL GOTDIS + AND AL,11111B + CMP AL,4 + JAE ESC0V + MOV SI,OFFSET DG:MDB_TAB2 + JMP DOBIG + +; 8087 instructions whose first byte is 0d9h +M8087_D9: + CALL GET64F + JZ ISD93 + + MOV SI,OFFSET DG:MD9_TAB +NOD93: + CALL PUTOP + AND AL,111B + CMP AL,3 + JA NOSHO + MOV AL,DL + CALL PUTSIZE +NOSHO: + JMP ADDRMOD + +ISD93: + MOV AL,DL + TEST AL,100B + JNZ ISD9BIG + AND AL,111B + OR AL,AL + JNZ NOTFLD + MOV AX,"DL" + STOSW + JMP SHORT PUTRST + +NOTFLD: + CMP AL,1 + JNZ NOTFXCH + MOV AX,"CX" + STOSW + MOV AL,"H" + JMP SHORT PUTRST1 + +NOTFXCH: + CMP AL,3 + JNZ NOTFSTP + MOV AX,"TS" + STOSW + MOV AL,"P" +PUTRST1: + STOSB +PUTRST: + MOV AL,9 + STOSB + JMP PUTST0 + +NOTFSTP: + CALL GOTDIS + CMP AL,11010000B ; CHECK FOR FNOP + JZ GOTFNOP + JMP ESC0 + +GOTFNOP: + MOV AX,"ON" + STOSW + MOV AL,"P" + STOSB + RET + +ISD9BIG: + CALL GOTDIS ; GET THE MODE BYTE + MOV SI,OFFSET DG:MD9_TAB2 +DOBIG: + AND AL,11111B + MOV CL,AL + JMP MOVBYT + +; entry point for the remaining 8087 instructions +M8087: + CALL GET64 + CALL PUTFI ; PUT FIRST PART OF OPCODE + MOV AL,DL + CMP BYTE PTR [MODE],11B ; CHECK FOR REGISTER MODE + JZ MODEIS3 + CALL PUTMN ; PUT MIDDLE PART OF OPCODE +NO3: + MOV AL,9 ; OUTPUT A TAB + STOSB + MOV AL,DL + CALL PUTSIZE ; OUTPUT THE OPERAND SIZE + JMP ADDRMOD + +MODEIS3: + TEST AL,100000B ; D BIT SET? + JZ MPUT ; NOPE... + TEST AL,000100B ; FDIV OR FSUB? + JZ MPUT ; NOPE... + XOR AL,1 ; REVERSE SENSE OF R + MOV DL,AL ; SAVE CHANGE +MPUT: + CALL PUTMN ; PUT MIDDLE PART OF OPCODE + MOV AL,DL + TEST AL,010000B + JZ NOPSH + MOV AL,"P" + STOSB +NOPSH: + MOV AL,9 + STOSB + MOV AL,DL + AND AL,00000111B + CMP AL,2 ; FCOM + JZ PUTST0 + CMP AL,3 ; FCOMP + JZ PUTST0 + MOV AL,DL + TEST AL,100000B + JZ PUTSTST0 + +; output 8087 registers in the form st(n),st +PUTST0ST: + CALL PUTST0 + MOV AL,',' +ISCOMP: + STOSB + +PUTST: + MOV AX,"TS" + STOSW + RET + +; output 8087 registers in the form st,st(n) +PUTSTST0: + CALL PUTST + MOV AL,',' + STOSB + +PUTST0: + CALL PUTST + MOV AL,"(" + STOSB + MOV AL,[REGMEM] + ADD AL,"0" + STOSB + MOV AL,")" + STOSB + RET + +; output an 8087 mnemonic +PUTMN: + MOV SI,OFFSET DG:M8087_TAB + MOV CL,AL + AND CL,00000111B + JMP SHORT MOVBYT + +; output either 'FI' or 'F' for first byte of opcode +PUTFI: + MOV SI,OFFSET DG:FI_TAB + JMP SHORT PUTFI2 + +; output size (dword, tbyte, etc.) +PUTSIZE: + MOV SI,OFFSET DG:SIZE_TAB +PUTFI2: + CMP BYTE PTR [MODE],11B ; check if 8087 register + JNZ PUTFI3 + AND AL,111000B ; LOOK FOR INVALID FORM OF 0DAH OPERANDS + CMP AL,010000B + JZ ESC0PJ + MOV AL,DL + CMP AL,110011B ; FCOMPP + JNZ GOFI + CMP BYTE PTR [REGMEM],1 + JZ GOFI +ESC0PJ: + JMP ESC0P + +GOFI: + XOR CL,CL + JMP SHORT MOVBYT + +; Look for qword +PUTFI3: + CMP AL,111101B + JZ GOTQU + CMP AL,111111B + JNZ NOTQU +GOTQU: + MOV CL,2 + JMP SHORT MOVBYT + +; look for tbyte +NOTQU: + CMP AL,011101B + JZ GOTTB + CMP AL,111100B + JZ GOTTB + CMP AL,111110B + JZ GOTTB + CMP AL,011111B + JNZ NOTTB +GOTTB: + MOV CL,5 + JMP SHORT MOVBYT + +NOTTB: + MOV CL,4 + SHR AL,CL + MOV CL,AL +; SI POINTS TO A TABLE OF TEXT SEPARATED BY "$" +; CL = WHICH ELEMENT IN THE TABLE YOU WISH TO COPY TO [DI] +MOVBYT: + PUSH AX + INC CL +MOVBYT1: + DEC CL + JZ MOVBYT3 +MOVBYT2: + LODSB + CMP AL,"$" + JZ MOVBYT1 + JMP MOVBYT2 + +MOVBYT3: + LODSB + CMP AL,'$' + JZ MOVBYT5 + CMP AL,'@' ; THIS MEANS RESVERED OP-CODE + JNZ MOVBYT4 + POP AX + JMP SHORT ESC0P ; GO DO AN ESCAPE COMMAND + +MOVBYT4: + STOSB + JMP MOVBYT3 + +MOVBYT5: + POP AX + RET + +PUTOP: + AND AL,111B + MOV CL,AL + CALL MOVBYT + MOV AL,9 + STOSB + MOV AL,DL + RET + +GET64F: + CALL GET64 + MOV AL,"F" + STOSB + CMP BYTE PTR [MODE],3 + MOV AL,DL + RET + +GET64: + AND AL,7 + MOV DL,AL + CALL GETMODE + SHL DL,1 + SHL DL,1 + SHL DL,1 + OR AL,DL + MOV DL,AL ; SAVE RESULT + RET + +ESC0P: + POP DI ; CLEAN UP STACK +ESC0: + MOV WORD PTR [OPCODE],OFFSET DG:ESCMN + MOV AL,DL + MOV DI,OFFSET DG:OPBUF + JMP SHORT ESC1 + +ESCP: + CALL GET64 +ESC1: + CALL SAVHEX + CMP BYTE PTR [MODE],3 + JZ SHRTESC + MOV BYTE PTR [AWORD],1 + JMP MEMOP2 + +SHRTESC: + MOV AL,"," + STOSB + MOV AL,[REGMEM] + AND AL,7 + JMP SAVREG + +INVARW: + CALL PUTAX + JMP SHORT INVAR + +INVARB: + CALL PUTAL +INVAR: + MOV AL,',' + STOSB + JMP PUTDX + +INFIXW: + CALL PUTAX + JMP SHORT INFIX + +INFIXB: + CALL PUTAL +INFIX: + MOV AL,',' + STOSB + JMP SAV8 + + STOSW ;IS THIS DEAD CODE? EMK + RET + +OUTVARB: + MOV BX,"LA" + JMP SHORT OUTVAR + +OUTVARW: + MOV BX,"XA" +OUTVAR: + CALL PUTDX +OUTFV: + MOV AL,',' + STOSB + MOV AX,BX + STOSW + RET + +OUTFIXB: + MOV BX,"LA" + JMP SHORT OUTFIX + +OUTFIXW: + MOV BX,"XA" +OUTFIX: + CALL SAV8 + JMP OUTFV + +PUTAL: + MOV AX,"A"+4C00H ; "AL" + JMP SHORT PUTX + +PUTAX: + MOV AX,"A"+5800H ; "AX" + JMP SHORT PUTX + +PUTDX: + MOV AX,"D"+5800H ; "DX" +PUTX: + STOSW + RET + +SHFT: + MOV BX,OFFSET DG:SHFTAB + CALL GETMNE +TESTREG: + CMP BYTE PTR [MODE],3 + JZ NOFLG + MOV SI,OFFSET DG:SIZE_TAB + MOV CL,3 + TEST BYTE PTR [AWORD],-1 + JNZ TEST_1 + INC CL +TEST_1: + CALL MOVBYT +NOFLG: + JMP ADDRMOD + +SHIFTV: + CALL SHFT + MOV AL,"," + STOSB + MOV WORD PTR [DI],"C"+4C00H ; "CL" + ADD DI,2 + RET + +SHIFT: + CALL SHFT + MOV AX,"1," + STOSW + RET + +GETMNE: + CALL GETMODE + MOV DL,AL + CBW + SHL AX,1 + ADD BX,AX + MOV AX,[BX] + MOV [OPCODE],AX + MOV AL,DL + RET + +GRP1: + MOV BX,OFFSET DG:GRP1TAB + CALL GETMNE + OR AL,AL + JZ FINIMMJ + JMP TESTREG +FINIMMJ: + JMP FINIMM + +GRP2: + MOV BX,OFFSET DG:GRP2TAB + CALL GETMNE + CMP AL,2 + JB TESTREG + CMP AL,6 + JAE INDIRECT + TEST AL,1 + JZ INDIRECT + MOV AX,"AF" ; "FAR" + STOSW + MOV AX," R" + STOSW +INDIRECT: + JMP ADDRMOD + +CODE ENDS + END UNASSEM + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBUG.ASM b/v4.0/src/CMD/DEBUG/DEBUG.ASM new file mode 100644 index 0000000..e986db9 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBUG.ASM @@ -0,0 +1,1236 @@ + PAGE 60,132 ; + TITLE DEBUG.SAL - DEBUGger for PC DOS + +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DEBUG.SAL +; +; DESCRIPTIVE NAME: DEBUGGING TOOL +; +; FUNCTION: PROVIDES USERS WITH A TOOL FOR DEBUGGING PROGRAMS. +; +; ENTRY POINT: START +; +; INPUT: DOS COMMAND LINE +; DEBUG COMMANDS +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: DEBCOM1 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBCOM2 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG +; DEBASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG +; DEBMES - CONTAINS MESSAGE RETRIEVER ROUTINES +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+ +; DEBCONST+DEBDATA+DEBMES +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT DBCS HANDLING DMS:6/17/87 +; - IMPLEMENT DBCS HANDLING bgb:5/03/88 ;an001;bgb +; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87 +; - > 32 MB SUPPORT DMS:6/17/87 +; +; COPYRIGHT: "MS DOS DEBUG UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +; MICROSOFT REVISION HISTORY: +; +; Modified 5/4/82 by AaronR to do all I/O direct to devices +; Runs on MS-DOS 1.28 and above +; +; REV 1.20 +; Tab expansion +; New device interface (1.29 and above) +; REV 2.0 +; line by line assembler added by C. P. +; REV 2.1 +; Uses EXEC system call +; REV 2.2 +; Ztrace mode by zibo. +; Fix dump display to indent properly +; Parity nonsense by zibo +; +; REV 2.3 NP +; Use Printf for all standard output. +; Change to EXE file +; REV 2.4 ARR +; Bug fixes. TEST, XCHG instructions reg order reversed. +; Single step, break point interrupts saved and restored. +; Access denied given on W to read only file. +;======================= END OF SPECIFICATIONS =========================== + + IF1 + %OUT COMPONENT=DEBUG, MODULE=DEBUG + ENDIF +.XLIST +.XCREF + INCLUDE DOSSYM.INC ; ALSO VERSION NUMBER +.CREF +.LIST + INCLUDE DEBEQU.ASM + IF SYSVER +; Structure for system call 72 +SYSINITVAR STRUC +DPBHEAD DD ? ; Pointer to head of DPB-FAT list +SFT_ADDR DD ? ; Pointer to first FCB table +; The following address points to the CLOCK device +BCLOCK DD ? +; The following address is used by DISKSTATCHK it is always +; points to the console input device header +BCON DD ? ; Console device entry points +MAXSEC DW 0 ; Maximum allowed sector size +BUFFHEAD DD ? +CDS DD ? +SFTFCB DD ? +KEEP DW ? +NUMIO DB 0 ; Number of disk tables +NCDS DB ? +DEVHEAD DD ? +SYSINITVAR ENDS + + ENDIF + + +;======================= macro equates =================================== + +dbcs_delim equ 81h ;an000;delimits dbcs char +asian_blk equ 40h ;an000;asian blank +amer_blk equ 20h ;an000;american blank +quote_char equ 22h ;an000;quote delim " + +;======================= end macro equates =============================== + + +;This segment must be the first loaded since we are using it to make +;a CREATE_PROCESS_DATA_BLOCK system call a la 1.0 and .COM files. +;For this system call CS must point to the Program Prefix Header, so +;by setting up a seperate segment just after the header we can issue +;an INT 21H via a long call. So don't move this guy around! + +A_CREATE_BLOCK SEGMENT + + PUBLIC CREATE_CALL + +;The other arguements to this system call have been set up +;by the caller. + +CREATE_CALL PROC FAR + MOV AH,CREATE_PROCESS_DATA_BLOCK + INT 21H + RET + +CREATE_CALL ENDP + +A_CREATE_BLOCK ENDS + + +CODE SEGMENT PUBLIC +CODE ENDS + +CONST SEGMENT PUBLIC +CONST ENDS + +CSTACK SEGMENT STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC +DATA ENDS + +DG GROUP CODE,CONST,CSTACK,DATA + +CONST SEGMENT PUBLIC BYTE + EXTRN BADVER:BYTE,ENDMES_PTR:BYTE,CRLF_PTR:BYTE + IF IBMJAPAN + EXTRN PARITYMES_PTR:BYTE + ENDIF + EXTRN PROMPT_PTR:BYTE,ADD_PTR:BYTE,HEX_PTR:BYTE + EXTRN USER_PROC_PDB:WORD,CSSAVE:WORD,DSSAVE:WORD + EXTRN SPSAVE:WORD,IPSAVE:WORD,LINEBUF:BYTE,QFLAG:BYTE + EXTRN NEWEXEC:BYTE,HEADSAVE:WORD,LBUFSIZ:BYTE,BACMES_PTR:WORD + + IF IBMVER + EXTRN DSIZ:BYTE,NOREGL:BYTE,DISPB:WORD + ENDIF + + IF SYSVER + EXTRN CONFCB:BYTE,POUT:DWORD,COUT:DWORD,CIN:DWORD,IOBUFF:BYTE + EXTRN IOADDR:DWORD,IOCALL:BYTE,IOCOM:BYTE,IOSTAT:WORD,IOCNT:WORD + EXTRN IOSEG:WORD,COLPOS:BYTE,BADDEV_PTR:BYTE,BADLSTMES_PTR:BYTE + EXTRN LBUFFCNT:BYTE,PFLAG:BYTE + ENDIF + + EXTRN NAMESPEC:BYTE + +CONST ENDS + +CSTACK SEGMENT STACK + DB (362 - 80H) + 80H DUP(?) ; (362 - 80H) == IBM'S ROM REQUIREMENTS + ; (NEW - OLD) == SIZE TO GROW STACK +CSTACK ENDS + +DATA SEGMENT PUBLIC BYTE + EXTRN ARG_BUF:BYTE,ADD_ARG:WORD,SUB_ARG:WORD,HEX_ARG1:WORD + EXTRN HEX_ARG2:WORD,STACK:BYTE, PREV24:DWORD, FIN24:BYTE + EXTRN PARSERR:BYTE,DATAEND:WORD,PARITYFLAG:BYTE,DISADD:BYTE + EXTRN ASMADD:BYTE,DEFDUMP:BYTE,BYTEBUF:BYTE,BEGSEG:WORD + EXTRN BPINTSAV:DWORD,SSINTSAV:DWORD ;ARR 2.4 + EXTRN CREATE_LONG:DWORD + + extrn lbtbl:dword ;an000;lead byte table pointer + +DATA ENDS + + EXTRN PRINTF:NEAR ;ac000;changed to NEAR call + +CODE SEGMENT PUBLIC + ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:CSTACK + + PUBLIC RESTART + PUBLIC STD_PRINTF,PRINTF_CRLF + PUBLIC HEX_ADDRESS_ONLY,HEX_ADDRESS_STR + PUBLIC RESTART,SET_TERMINATE_VECTOR,DABORT,TERMINATE,COMMAND + PUBLIC FIND_DEBUG,CRLF,BLANK,TAB,INBUF,SCANB,SCANP + PUBLIC HEX,OUTSI,OUTDI,DIGIT,BACKUP,RBUFIN + public test_lead ;an001;bgb + public test1 ;an001;bgb + + IF SYSVER +; PUBLIC SETUDEV,DEVIOCALL ; kwc 12/10/86 + PUBLIC SETUDEV ; kwc 12/10/86 + EXTRN DISPREG:NEAR,INPT:NEAR + ENDIF + + EXTRN PERR:NEAR,COMPARE:NEAR,DUMP:NEAR,ENTERDATA:NEAR,FILL:NEAR + EXTRN GO:NEAR,INPUT:NEAR,LOAD:NEAR,MOVE:NEAR,NAMED:NEAR + EXTRN REG:NEAR,SEARCH:NEAR,DWRITE:NEAR,UNASSEM:NEAR,ASSEM:NEAR + EXTRN OUTPUT:NEAR,ZTRACE:NEAR,TRACE:NEAR,GETHEX:NEAR,GETEOL:NEAR + EXTRN PREPNAME:NEAR,DEFIO:NEAR,SKIP_FILE:NEAR,DEBUG_FOUND:NEAR + EXTRN TRAPPARITY:NEAR,RELEASEPARITY:NEAR + extrn pre_load_message:near ;an000;load messages + extrn debems:near ;an000;ems support + + + DB 100H DUP (?) + +START: + JMP SHORT DSTRT + +HEADER DB "Vers 2.40" + +DSTRT: +;========================================================================= +; invoke PRE_LOAD_MESSAGE here. If the messages were not loaded we will +; exit with an appropriate error message. +; +; Date : 6/14/87 +;========================================================================= + + push ds ;an000;save regs + push es ;an000;save resg + + push cs ;an000;transfer cs + pop ds ;an000; to ds + + push cs ;an000;transfer cs + pop es ;an000; to es + assume ds:dg,es:dg ;an000;assume them + call PRE_LOAD_MESSAGE ;an000;invoke SYSLOADMSG +; $if c ;an000;if the load was unsuccessful + JNC $$IF1 + mov ax,(exit shl 8) ;an000;exit EDLIN. PRE_LOAD_MESSAGE + ; has already said why + int 21h ;an000;exit +; $endif ;an000; +$$IF1: + + pop es ;an000;restore regs. + pop ds ;an000; + assume ds:nothing,es:nothing ;an000;back to original + + MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR VEC_BREAKPOINT ;get original contents + INT 21H ; of the BREAKPOINT vector + + MOV WORD PTR [BPINTSAV],BX ; and save that vector for later + MOV WORD PTR [BPINTSAV+WORD],ES ; restoration + + MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR VEC_SING_STEP ;get original contents + INT 21H ; of the SINGLE STEP vector + + MOV WORD PTR [SSINTSAV],BX ; and save that vector for later + MOV WORD PTR [SSINTSAV+WORD],ES ; restoration + + MOV BEGSEG,DS ; save beginning DS + PUSH CS ; repair damaged ES to be + POP ES ; back to just like CS + XOR SI,SI ; set source and destination + XOR DI,DI ; indices both to zero + MOV CX,256 ; set count to size of PSP + REP MOVSB ; move to es:[di] from ds:[si] + PUSH CS ; set up DS to be just like CS + POP DS ; to match .COM rules of addressability + ASSUME DS:DG,ES:DG ; like CS, also have DS and DS as bases + + CALL TRAPPARITY ; scarf up those parity guys + MOV AH,GET_CURRENT_PDB ;(undocumented function call - 51h) + INT 21H + + MOV [USER_PROC_PDB],BX ; Initially set to DEBUG + + IF SYSVER + MOV [IOSEG],CS + ENDIF + + MOV [PARSERR],AL + + + IF SYSVER + MOV AH,GET_IN_VARS ;(undocumented function call - 52h) + INT 21H + + LDS SI,ES:[BX.BCON] ; get system console device + ASSUME DS:NOTHING + + MOV WORD PTR CS:[CIN+WORD],DS ;save vector to console input device + MOV WORD PTR CS:[CIN],SI + MOV WORD PTR CS:[COUT+WORD],DS ;save vector to console output device + MOV WORD PTR CS:[COUT],SI + PUSH CS ; restore DS to be + POP DS ; just like CS, as before + ASSUME DS:DG + + MOV DX,OFFSET DG:CONFCB ; get system printer device + MOV AH,FCB_OPEN ; open system printer "PRN" + INT 21H + + OR AL,AL ; open ok? + JZ GOTLIST ; yes, it was there + + MOV DX,OFFSET DG:BADLSTMES_ptr ; no list file found... + CALL STD_PRINTF ; tell user + + CALL RBUFIN ; ask for a new one + + CALL CRLF + + MOV CL,[LBUFFCNT] + OR CL,CL + JZ NOLIST1 ; User didn't specify one + + XOR CH,CH + MOV DI,OFFSET DG:(CONFCB + BYTE) + MOV SI,OFFSET DG:LINEBUF ; get one from input line + REP MOVSB + MOV DX,OFFSET DG:CONFCB + MOV AH,FCB_OPEN ; try to open it + INT 21H + + OR AL,AL + JZ GOTLIST ; yep, use it... + + MOV DX,OFFSET DG:BADDEV_Ptr ; complain again + CALL STD_PRINTF +NOLIST1: ; kwc 12/10/86 + MOV WORD PTR [POUT+WORD],CS ; use null device for printer + MOV WORD PTR [POUT],OFFSET DG:LONGRET + JMP NOLIST + +XXX PROC FAR +LONGRET: + RET +XXX ENDP + ENDIF + +GOTLIST: +;DX = OFFSET OF 'CONFCB', WHICH HAS JUST BEEN OPENED OK + IF SYSVER + MOV SI,DX +; LDS SI,DWORD PTR DS:[SI.FCB_FIRCLUS] ; KWC 12/10/86 + LDS SI,DWORD PTR DS:[SI.FCB_NSLD_DRVPTR] ; KWC 12/10/86 + ASSUME DS:NOTHING + + MOV WORD PTR CS:[POUT+WORD],DS + MOV WORD PTR CS:[POUT],SI + ENDIF +NOLIST: + MOV AX,CS ;restore the DS and ES segregs + MOV DS,AX ; to become once again just like CS + MOV ES,AX + ASSUME DS:DG,ES:DG + +; Code to print header +; MOV DX,OFFSET DG:HEADER_PTR +; CALL STD_PRINTF + + CALL SET_TERMINATE_VECTOR + +; Save the current INT 24 vector. We will need this to link to the previous +; handler for handling of int 24 output. + PUSH ES ; save it, about to clobber it... + MOV AX,(GET_INTERRUPT_VECTOR SHL 8) + VEC_CRIT_ERR ; get original contents + INT 21H ; of the int 24h vector + + MOV WORD PTR PREV24,BX ; remember what int 24h used to + MOV WORD PTR PREV24+WORD,ES ; point to + POP ES ; restore ES to be like CS and DS + + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) + VEC_CRIT_ERR ; change int 24h to + MOV DX,OFFSET DG:MY24 ; point to my own int 24h handler + INT 21H + + IF SETCNTC + MOV AL,VEC_CTRL_BREAK ; Set vector 23H + MOV DX,OFFSET DG:DABORT + INT 21H + ENDIF + + MOV DX,CS ;get para of where this pgm starts + MOV AX,OFFSET DG:DATAEND+15 ;get offset of end of this program + MOV CL,4 ; (plus 15 padding for rounding) + SHR AX,CL ; adjusted to number of paragraphs + ADD DX,AX ;get para of where this pgm ends + MOV AX,CS + SUB AX,BEGSEG ; add in size of printf + ADD DX,AX ; create program segment here + CALL [CREATE_LONG] ; and call special routine + + MOV AX,DX +; Initialize the segments + MOV DI,OFFSET DG:DSSAVE + CLD + STOSW + STOSW + STOSW + STOSW + MOV WORD PTR [DISADD+WORD],AX + MOV WORD PTR [ASMADD+WORD],AX + MOV WORD PTR [DEFDUMP+WORD],AX + + MOV AX,100H + MOV WORD PTR[DISADD],AX + MOV WORD PTR[ASMADD],AX + MOV WORD PTR [DEFDUMP],AX + + MOV DS,DX + MOV ES,DX + ASSUME DS:NOTHING,ES:NOTHING + + MOV DX,80H + MOV AH,SET_DMA + INT 21H ; Set default DMA address to 80H +; Set up initial stack. We already have a 'good' stack set up already. DS:6 +; has the number of bytes remaining in the segment. We should take this +; value, add 100h and use it as the Stack pointer. + MOV AX,WORD PTR DS:[6] ; get bytes remaining + MOV BX,AX + ADD AX,100h + +; MOV BX,AX +; CMP AX,0FFF0H +; PUSH CS +; POP DS +; JAE SAVSTK +; MOV AX,WORD PTR DS:[6] +; PUSH BX +; MOV BX,OFFSET DG:DATAEND + 15 +; AND BX,0FFF0H ; Size of DEBUG in bytes (rounded up to PARA) +; SUB AX,BX +; POP BX +;SAVSTK: + PUSH CS + POP DS + ASSUME DS:DG + PUSH BX ; bx is no. bytes remaining from PSP+6 + DEC AX ; ax was no. bytes remaining +100h + DEC AX ; back up one word from end of new stack + MOV BX,AX ; set base to point to last word in new stack + MOV WORD PTR ES:[BX],0 ; set final word in new stack to zero + POP BX ; back to beginning of new stack area + MOV SPSAVE,AX ; remember where new stack is + DEC AH + MOV ES:WORD PTR [6],AX ; change PSP to show usage of + SUB BX,AX ; new stack area + MOV CL,4 + SHR BX,CL + ADD ES:WORD PTR [8],BX + + IF IBMVER +; Get screen size and initialize display related variables + MOV AH,15 ;function = "request current video state" + INT 10H ;set al=screen mode + ; ah=no. char cols on screen + ; bh=current active display page + CMP AH,40 ;is screen in 40 col mode? + JNZ PARSCHK ; no, skip + ; yes, 40 col, continue + ;next fields defined in 'debconst.asm' + MOV BYTE PTR DSIZ,7 ; originally assembled as 0fh + MOV BYTE PTR NOREGL,4 ; originally assembled as 8 + MOV DISPB,64 ; originally assembled as 128 + ENDIF + +PARSCHK: + + + call DEBUG_LEAD_BYTE ;an000;build the dbcs env. table + ; of valid dbcs lead bytes + +;========================================================================= +; prep_command_line requires the use of ds:si. ds is left intact for +; the call. si is initialized to point to the command line input buffer. +; ds and si are saved since we stomp all over them in prep_command_line. +;========================================================================= + + push si ;an000;save si + + mov si,81h ;an000;point to command line + call prep_command_line ;an000;invoke command line conversion + + pop si ;an000;restore si + +;========================================================================= +; we have prepped the command line for dbcs. we can now enter the old +; routines. +;========================================================================= + +; Copy rest of command line to test program's parameter area + MOV DI,FCB ;es[di]=to be filled with unopened FCB + MOV SI,81H ;ds[si]=command line to parse + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR SET_DRIVEID_OPTION + ;func=29H, option al=1, which + ; says, drive id byte in fcb is set + ; only if drive specified in command + ; line being parsed. + INT 21H ;parse filename from command to fcb + ; ds:si=points to first char AFTER parsed filename + ; es:di=points to first byte of formatted FCB + + CALL SKIP_FILE ; Make sure si points to delimiter +test1: ;for testing only - u can remove this + CALL PREPNAME + + PUSH CS ;restore ES to point to the + POP ES ; common group +FILECHK: + MOV DI,80H ;point to byte in PSP defining parm length + CMP BYTE PTR ES:[DI],0 ; ANY STUFF FOUND? + JZ COMMAND ; no parms, skip + ; yes parms, continue +FILOOP: + INC DI ;set index to first/next char in parm text + CMP BYTE PTR ES:[DI],CR ; carriage return? (at end of parms) + JZ COMMAND ; yes, at end of parms + ; no, not at end of parms yet, continue + CMP BYTE PTR ES:[DI],CHAR_BLANK ; is this parm text char a blank? + JZ FILOOP ; yes, a blank, skip + ; no, not a blank, continue + CMP BYTE PTR ES:[DI],CHAR_TAB ; is this parm text char a tab? + JZ FILOOP ; yes, a tab, skip + ; no, not a tab, continue + OR [NAMESPEC],1 ; set flag to indicate + ; we have a specified file + ; (this could be set by "N" command also) + CALL DEFIO ; READ in the specified file + + PUSH CS ;restore DS to point to the + POP DS ; common group + + ;perform self-relocation on some internal vectors: + MOV AX,CSSAVE ; pick up the seg id to go to vectors + MOV WORD PTR DISADD+WORD,AX ; shove it into the segid portion + MOV WORD PTR ASMADD+WORD,AX ; of these two vectors + MOV AX,IPSAVE ; pick up the offset to go to vectors + MOV WORD PTR DISADD,AX ; shove it into the offset portion + MOV WORD PTR ASMADD,AX ; of these two vectors +COMMAND: + CLD + MOV AX,CS + MOV DS,AX + MOV ES,AX + cli ;disable before setting up the stack - EMK + MOV SS,AX ;now everything points to the same group + ASSUME SS:DG + + MOV SP,OFFSET DG:STACK + STI ;re-enable + CMP [PARITYFLAG],0 ; did we detect a parity error? + JZ GOPROMPT ; no, go prompt + ; yes, parity error, continue + MOV [PARITYFLAG],0 ; reset flag + IF IBMJAPAN + MOV DX,OFFSET DG:PARITYMES_PTR + CALL STD_PRINTF ;display msg about parity error + ENDIF +GOPROMPT: + MOV DX,OFFSET DG:PROMPT_PTR ;display the user prompt request + CALL STD_PRINTF + + CALL INBUF ; Get command line +; From now and throughout command line processing, DI points +; to next character in command line to be processed. + CALL SCANB ; Scan off leading blanks + + JZ COMMAND ; if zero, Null command, go get another + ; nonzero, got something in response + LODSB ; AL=first non-blank character +; Prepare command letter for table lookup +; converts the first non-blank (assumed to be the command letter) +; to in index in the "comtab" array. + SUB AL,UPPER_A ; Low end range check + JB ERR1 + + CMP AL,UPPER_Z - UPPER_A ; Upper end range check + JA ERR1 + + SHL AL,1 ; Times two + CBW ; Now a 16-bit quantity + XCHG BX,AX ; In BX we can address with it + CALL CS:[BX+COMTAB] ; Execute command + + JMP SHORT COMMAND ; Get next command +ERR1: + JMP PERR + +SET_TERMINATE_VECTOR: + PUSH DS + PUSH CS + POP DS + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR VEC_TERM_ADDR ; Set vector 22H + MOV DX,OFFSET DG:TERMINATE + INT 21H + + POP DS + RET + +RESTORE_DEB_VECT: + PUSH DS + PUSH DX + PUSH AX + LDS DX,CS:[BPINTSAV] + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR VEC_BREAKPOINT ;Vector 3 + INT 21H + + LDS DX,CS:[SSINTSAV] + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR VEC_SING_STEP ;Vector 1 + INT 21H + + POP AX + POP DX + POP DS + RET + +; Internal INT 24 handler. We allow our parent's handler to decide what to do +; and how to prompt. When our parent returns, we note the return in AL. If +; he said ABORT, we need to see if we are aborting ourselves. If so, we +; cannot turn it into fail; we may get a cascade of errors due to the original +; cause. Instead, we do the ol' disk-reset hack to clean up. This involves +; issuing a disk-reset, ignoring all errors, and then returning to the caller. +MY24: + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + +; If we are already inside an INT 24, just ignore this error + TEST FIN24,-1 + JZ DO24 + + MOV AL,0 ; signal ignore + IRET + +; Let the user decide what to do +DO24: + PUSHF + CALL PREV24 ; simulate INT 24 to him + + CMP AL,2 ; was it ABORT? + JNZ DOIRET ; no, let it happen + + PUSH AX + PUSH BX + MOV AH,GET_CURRENT_PDB ; find out who's terminating + INT 21H + + CMP BX,BEGSEG ; is it us? + POP BX + POP AX + JZ DORESET ; no, let it happen + +DOIRET: + IRET + +; We have been instructed to abort ourselves. Since we can't do this, we will +; perform a disk reset to flush out all buffers and then ignore the errors we +; get. +DORESET: + MOV FIN24,-1 ; signal that we ignore errors + MOV AH,DISK_RESET + INT 21H ; clean out cache + + MOV FIN24,0 ; reset flag + JMP COMMAND + +TERMINATE: + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + CMP QFLAG,0 + JNZ QUITING + + MOV AX,BEGSEG + MOV USER_PROC_PDB,AX + CMP NEWEXEC,0 + JZ NORMTERM + + MOV AX,CS + MOV DS,AX + ASSUME DS:DG + ;is CLI/STI needed here ? - emk + CLI + MOV SS,AX + ASSUME SS:DG + + MOV SP,OFFSET DG:STACK + STI + MOV AX,HEADSAVE + JMP DEBUG_FOUND + +NORMTERM: + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUSH CS + POP DS + ASSUME DS:DG + + MOV DX,OFFSET DG:ENDMES_PTR + JMP SHORT RESTART + +QUITING: + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + CALL RESTORE_DEB_VECT + + MOV AX,(EXIT SHL 8) + INT 21H + +RESTART: + CALL STD_PRINTF +DABORT: + MOV AX,CS + MOV DS,AX + ASSUME DS:DG + + ;is CLI\STI needed here? - emk + CLI + MOV SS,AX + ASSUME SS:DG + + MOV SP,OFFSET DG:STACK + STI +;;;;;; CALL CRLF + + JMP COMMAND + + IF SYSVER +SETUDEV: + MOV DI,OFFSET DG:CONFCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR SET_DRIVEID_OPTION + INT 21H + + CALL USERDEV + + JMP DISPREG + +USERDEV: + MOV DX,OFFSET DG:CONFCB + MOV AH,FCB_OPEN + INT 21H + + OR AL,AL + JNZ OPENERR + + MOV SI,DX +; TEST BYTE PTR [SI.FCB_DEVID],080H ; Device? ; KWC 12/10/86 +; JZ OPENERR ; NO ; KWC 12/10/86 + MOV AL,BYTE PTR [SI.FCB_NSL_DRIVE] ; KWC 12/10/86 + AND AL,NOT FCBMASK ; KWC 12/10/86 + CMP AL,0C0H ; KWC 12/10/86 + JNE OPENERR ; KWC 12/10/86 + XOR AL,AL ; KWC 12/10/86 + +; LDS SI,DWORD PTR [CONFCB.FCB_FIRCLUS] ; KWC 12/10/86 + LDS SI,DWORD PTR [CONFCB.FCB_NSLD_DRVPTR] ; KWC 12/10/86 + MOV WORD PTR CS:[CIN],SI + MOV WORD PTR CS:[CIN+WORD],DS + + MOV WORD PTR CS:[COUT],SI + MOV WORD PTR CS:[COUT+WORD],DS + PUSH CS + POP DS + RET + +OPENERR: + MOV DX,OFFSET DG:BADDEV_PTR + CALL STD_PRINTF + + RET + ENDIF +; Get input line. Convert all characters NOT in quotes to upper case. +INBUF: + CALL RBUFIN + +;========================================================================= +; prep_command_line requires the use of ds:si. ds is left intact for +; the call. si is initialized to point to the command line input buffer. +; ds and si are saved since we stomp all over them in prep_command_line. +;========================================================================= + + push si ;an000;save si + + mov si,offset dg:linebuf ;an000;point to command line + call prep_command_line ;an000;invoke command line conversion + + pop si ;an000;restore si + +;========================================================================= +; we have prepped the command line for dbcs. we can now enter the old +; routines. +;========================================================================= + + MOV SI,OFFSET DG:LINEBUF + MOV DI,OFFSET DG:BYTEBUF + +CASECHK: + + LODSB + + call Test_Lead ;DBCS lead byte ;an000; dms; +; $if c ;yes - ignore 2nd. byte ;an000; dms; + JNC $$IF3 + stosb ;save the byte ;an000; dms; + lodsb ;pick up the 2nd. character ;an000; dms; + stosb ;save it also ;an000; dms; + jmp CaseChk ;read next character ;an000; dms; +; $endif ; ;an000; dms; +$$IF3: + + CMP AL,LOWER_A + JB NOCONV + + CMP AL,LOWER_Z + JA NOCONV + + ADD AL,UPPER_A - LOWER_A ; Convert to upper case +NOCONV: + STOSB + CMP AL,CR + JZ INDONE + + CMP AL,DOUBLE_QUOTE + JZ QUOTSCAN + + CMP AL,SINGLE_QUOTE + JNZ CASECHK + +QUOTSCAN: + MOV AH,AL +KILLSTR: + LODSB + STOSB + CMP AL,CR ;CARRIAGE RETURN? + JZ INDONE + + CMP AL,AH + JNZ KILLSTR + + JMP SHORT CASECHK + +INDONE: + MOV SI,OFFSET DG:BYTEBUF + CALL CRLF + + RET + +; Physical backspace - blank, backspace, blank +BACKUP: + PUSH DX + MOV DX,OFFSET DG:BACMES_PTR + CALL STD_PRINTF + + POP DX + RET + +; Scan for parameters of a command +SCANP: + CALL SCANB ; Get first non-blank + + CMP BYTE PTR [SI],CHAR_COMMA ; One comma between params OK + JNE EOLCHK ; If not comma, we found param + + INC SI ; Skip over comma +; Scan command line for next non-blank character +SCANB: + PUSH AX +SCANNEXT: + LODSB + CMP AL,CHAR_BLANK ;is this char a "blank"? + JZ SCANNEXT + + CMP AL,CHAR_TAB ;is this char a "tab"? + JZ SCANNEXT + + DEC SI ; Back to first non-blank + POP AX +EOLCHK: + CMP BYTE PTR [SI],CR ;CARRIAGE RETURN + RET + +; Hex addition and subtraction +HEXADD: + MOV CX,4 + CALL GETHEX + + MOV DI,DX + MOV CX,4 + CALL GETHEX + + CALL GETEOL + + PUSH DX + ADD DX,DI + MOV [ADD_ARG],DX + POP DX + SUB DI,DX + MOV [SUB_ARG],DI + MOV DX,OFFSET DG:ADD_PTR + CALL PRINTF_CRLF + + RET + +; Put the hex address in DS:SI in the argument list for a call to printf +OUTSI: + MOV CS:[HEX_ARG1],DS + MOV CS:[HEX_ARG2],SI + RET + +;Put the hex address in ES:DI in the argument list for a call to printf +OUTDI: + MOV [HEX_ARG1],ES + MOV [HEX_ARG2],DI + RET + +HEX_ADDRESS_ONLY: + MOV BYTE PTR [ARG_BUF],0 +HEX_ADDRESS_STR: + MOV DX,OFFSET DG:HEX_PTR +STD_PRINTF: + PUSH DX + CALL PRINTF + POP DX ;ac000;restore dx + + RET + +PRINTF_CRLF: + PUSH DX + CALL PRINTF + POP DX ;ac000;restore dx +CRLF: + MOV DX,OFFSET DG:CRLF_PTR + PUSH DX + CALL PRINTF + POP DX ;ac000;restore dx + + RET + +HEX: + MOV AH,AL ; Save for second digit + PUSH CX + MOV CL,4 + SHR AL,CL + POP CX + + CALL DIGIT ; First digit + + MOV AL,AH ; Now do digit saved in AH +DIGIT: + AND AL,0FH ; Mask to 4 bits + ADD AL,90H + DAA + ADC AL,40H + DAA + AND AL,7FH + STOSB + RET + +RBUFIN: + PUSH AX + PUSH DX + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET DG:LBUFSIZ + INT 21H + + POP DX + POP AX + RET + +; Put one space in the printf output uffer +BLANK: + MOV AL,CHAR_BLANK + STOSB + RET + +; Put CX spaces in the printf output buffer +TAB: + JCXZ TAB_RET + + CALL BLANK + + LOOP TAB +TAB_RET: + RET + +; Command Table. Command letter indexes into table to get +; address of command. PERR prints error for no such command. + +COMTAB DW ASSEM ; A + DW PERR ; B + DW COMPARE ; C + DW DUMP ; D + DW ENTERDATA ; E + DW FILL ; F + DW GO ; G + DW HEXADD ; H + DW INPUT ; I + DW PERR ; J + DW PERR ; K + DW LOAD ; L + DW MOVE ; M + DW NAMED ; N + DW OUTPUT ; O + DW ZTRACE ; P + DW QUIT ; Q (QUIT) + DW REG ; R + DW SEARCH ; S + DW TRACE ; T + DW UNASSEM ; U + DW PERR ; V + DW DWRITE ; W + IF SYSVER + DW SETUDEV ; X + ELSE + DW DEBEMS + ENDIF + DW PERR ; Y + DW PERR ; Z + +QUIT: + INC BYTE PTR [QFLAG] + MOV BX,[USER_PROC_PDB] +FIND_DEBUG: + IF NOT SYSVER + MOV AH,SET_CURRENT_PDB + INT 21H + ENDIF + CALL RELEASEPARITY ; let system do normal parity stuff + + CALL RESTORE_DEB_VECT + + MOV AX,(EXIT SHL 8) + INT 21H + +;======================= proc prep_command_line ========================= +; prep_command_line: This proc converts a Asian DBCS space delimiter (8140h) +; into 2 20h values. In this way we can pass command +; lines throughout DEBUG without major modification +; to the source code. This proc is invoked anywhere +; a command line is initially accessed. In the case +; of DEBUG it is used in PARSCHK and INBUF. +; Any quoted string, a string delimited by ("), will +; be ignored. +; +; input: ds - segment of command line +; si - offset of command line +; +; output: command line with Asian blanks (8140h) converted to +; 2020h. +; +;========================================================================= + +prep_command_line proc near ;command line conversion + push ax ;save affected regs. + push bx ; + push si ; + + mov bl,00h ;initialize flag + ;bl is used to signal + ; a quote delimiter +; $DO ;do while not CR +$$DO5: + mov al,[si] ;move char from cmd line for compare + cmp al,CR ;is it a CR ? +; $LEAVE E ;if CR exit + JE $$EN5 + + cmp al,quote_char ;is it a quote ? +; $IF Z ;if it is a quote + JNZ $$IF7 + xor bl,01h ;set or reset the flag +; $ENDIF +$$IF7: + + cmp bl,01h ;is 1st quote set ? +; $IF NZ ;if not continue + JZ $$IF9 + call TEST_LEAD ;test for dbcs lead byte +; $IF C ;we have a lead byte + JNC $$IF10 + cmp al,dbcs_delim ;is it a dbcs char? 81h +; $IF Z ;if a dbcs char + JNZ $$IF11 + mov al,[si+1] ;move next char al + cmp al,asian_blk ;is it an Asian blank? 40h +; $IF Z ;if an Asian blank + JNZ $$IF12 + mov al,amer_blk ;set up moves + mov [si],al ; to replace + mov [si+1],al ; Asian blank w/20h + inc si ;point to si+1 +; $ELSE ;if not an asian blank + JMP SHORT $$EN12 +$$IF12: + inc si ;point to dbcs char +; $ENDIF ; +$$EN12: +; $ENDIF ; +$$IF11: +; $ENDIF ;end lead byte test +$$IF10: +; $ENDIF ; +$$IF9: + inc si ;point to si+1 +; $ENDDO ;end do while + JMP SHORT $$DO5 +$$EN5: + pop si ;restore affected regs. + pop bx ; + pop ax ; + ret ;return to caller +prep_command_line endp ;end proc + + +;========================================================================= +; DEBUG_LEAD_BYTE - This routine sets the lead-byte-pointers to point +; to the dbcs environmental vector table of lead bytes. +; This table will be used to determine if we have a +; dbcs lead byte. +; +; Inputs - none +; +; Outputs- pointer to dbcs environmental vector table of lead bytes +; LBTBL DD ? +; +; Date : 6/16/87 +;========================================================================= + +DEBUG_LEAD_BYTE proc near ;an000;get lead byte vector + + push ds ;an000;save affected regs + push es ;an000; + push si ;an000; + + mov ax,(ECS_call shl 8) or 00h ;an000;get dbcs env. vector + int 21h ;an000;invoke function + + assume ds:nothing + + mov word ptr cs:lbtbl[0],si ;an000;move offset of table + mov word ptr cs:lbtbl[2],ds ;an000;move segment of table + + pop si ;an000;restore affected regs + pop es ;an000; + pop ds ;an000; + + ret ;an000;return to caller + +DEBUG_LEAD_BYTE endp ;an000;end proc + +;========================================================================= +; TEST_LEAD - This routine will determine whether or not we have a valid +; lead byte for a DBCS character. +; +; Inputs : AL - Holds the byte to compare. Passed by POP. ;an001;bgb +; +; Outputs: Carry set if lead byte +; No carry if not lead byte +; +; Date : 6/16/87 +;========================================================================= + +TEST_LEAD proc near ;an000;check for dbcs lead byte + + push ds ;an000;save affected regs + push si ;an000; + push ax ;an000; + + xchg ah,al ;an000;ah used for compare + mov si,word ptr cs:lbtbl[2] ;an000;get segment of table + mov ds,si ;an000; + mov si,word ptr cs:lbtbl[0] ;an000;get offset of table + +ck_next: + + lodsb ;an000;load al with byte table + or al,al ;an000;end of table? +; $IF z ;an000;yes, end of table + JNZ $$IF19 + jmp lead_exit ;an000;exit with clear carry +; $ELSE ;an000; + JMP SHORT $$EN19 +$$IF19: + cmp al,ah ;an000;start > character? +; $IF a ;an000;it is above + JNA $$IF21 + clc ;an000;clear carry flag + jmp lead_exit ;an000;exit with clear carry +; $ELSE ;an000; + JMP SHORT $$EN21 +$$IF21: + lodsb ;an000;load al with byte table + cmp ah,al ;an000;character > end range +; $IF a ;an000;not a lead + JNA $$IF23 + jmp ck_next ;an000;check next range +; $ELSE ;an000;lead byte found + JMP SHORT $$EN23 +$$IF23: + stc ;an000;set carry flag +; $ENDIF ;an000; +$$EN23: +; $ENDIF ;an000; +$$EN21: +; $ENDIF ;an000; +$$EN19: + +lead_exit: ;an000;exit from check + + pop ax ;an000; + pop si ;an000;restore affected regs. + pop ds ;an000; + + ret ;an000;return to caller + +TEST_LEAD endp ;an000;end proc + + + +CODE ENDS + END START + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBUG.LNK b/v4.0/src/CMD/DEBUG/DEBUG.LNK new file mode 100644 index 0000000..e9163c0 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBUG.LNK @@ -0,0 +1,13 @@ +DEBUG+ +DEBCOM1+ +DEBCOM2+ +DEBCOM3+ +DEBASM+ +DEBUASM+ +DEBERR+ +DEBCONST+ +DEBMES+ +DEBEMS+ +DEBDATA +DEBUG.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/DEBUG.SKL b/v4.0/src/CMD/DEBUG/DEBUG.SKL new file mode 100644 index 0000000..0720426 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/DEBUG.SKL @@ -0,0 +1,125 @@ +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: DEBMES.FIL +; +; DESCRIPTIVE NAME: MESSAGES USED BY DEBUG +; +; FUNCTION: PROVIDES FASTBLD.EXE THE MESSAGES THAT ARE TO BE USED BY DEBUG. +; +; ENTRY POINT: NA +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: NA +; +; EXTERNAL REFERENCES: NA +; +; NOTES: THIS MODULE IS TO BE PREPPED BY FASTBLD.EXE. +; +; FASTBLD.EXE CREATES: DEBUG.CLA +; DEBUG.CLB +; DEBUG.CLC +; DEBUG.CLD +; DEBUG.CL1 +; DEBUG.CL2 +; +; REVISION HISTORY: NA +; +; +; COPYRIGHT: "THE IBM PERSONAL COMPUTER EDLIN UTILITY" +; "VERSION 3.40 (C) COPYRIGHT IBM CORP 1987" +; "LICENSED MATERIAL - PROGRAM PROPERTY OF IBM" +; +; PROGRAM AUTHOR: DS +; +;======================= END OF SPECIFICATIONS =========================== + +;========================================================================= +;debug utility message file +;========================================================================= + +:util DEBUG ;utility name + +:class 1 ;extended errors + +:class A ;system messages +:use 1 COMMON1 ;"Incorrect DOS version" +:use 2 COMMON2 ;"Insufficient memory" +:use 3 COMMON3 ;"Error loading messages" +:def 4 "Allocation failed or specified buffer too small",CR,LF + ;:def 5 "Bad or missing Msg info",CR,LF + +:class B ;utility messages +:def 6 "Bad device name" ;baddev_ptr +:def 7 "Couldn't open list device PRN",CR,LF +"Enter name of list device? " ;badlstmes_ptr +:def 8 CR,LF ;crlf_ptr +:def 9 CR,LF,"Program terminated normally",CR,LF ;endmes_ptr +:def 10 "Invalid drive specification",CR,LF ;nambad_ptr +:def 12 "File creation error",CR,LF ;noroom_ptr +:def 13 "Insufficient space on disk",CR,LF ;nospace_ptr +:def 14 "Disk error reading drive %1",CR,LF ;dr1_ptr +:def 15 "Disk error writing drive %1",CR,LF ;dr2_ptr +:def 16 "Write protect error reading drive %1",CR,LF ;dr3_ptr +:def 17 "Write protect error writing drive %1",CR,LF ;dr4_ptr +:def 19 "%1^ Error" ;synerr +:def 20 "Error in EXE or HEX file",CR,LF ;exebad_ptr/hexerr_ptr + +:class C +:def 21 "EXE and HEX files cannot be written",CR,LF ;exewrt_ptr/hexwrt_ptr +:def 22 "EXEC failure" ;execemes_ptr +:def 23 "(W)rite error, no destination defined",CR,LF ;nonamespec_ptr +:def 24 "Access denied",CR,LF ;accmes_ptr +:def 25 "Parity error or nonexistant memory error detected" ;paritymes_ptr +:def 26 "-" ;prompt_ptr +:def 27 "%1 -" ;change_flag_ptr +:def 32 "%1%2" ;unassem_ln_ptr +:def 33 "%1:%2 %3" ;hex_ptr +:def 34 "%1 %2" ;add_ptr +:def 35 "%1 %2",CR,LF,":" ;single_reg_ptr +:def 36 "%1=%2 " ;register_ptr +:def 37 "%1 Error" ;errmes_ptr +:def 38 "Writing %1 bytes" ;wrtmes_ptr +:def 39 "%1:%2=" ;loc_ptr +:def 40 "%1" ;little_ptr + +:class D +:def 41 "%1" ;big_ptr +:def 42 "%1:%2 %3 %4 %5:%6" ;comp_ptr +:def 44 32,8 ;bacmes_ptr + ; :def 45 "Unable to allocate message handler",CR,LF + ;fatal_error +:def 46 "%1" ;arg_buf_ptr +:def 47 "%1" ;one_char_buf_ptr + +:def 50 "%1 of a total %2 EMS pages have been allocated",cr,lf +:def 51 "%1 of a total %2 EMS handles have been allocated",cr,lf +:def 55 "Handle created = %1 ",cr,lf +:def 56 "Logical page %1 mapped to physical page %2 ",cr,lf +:def 57 "EMS hardward/software failure",cr,lf +:def 58 "Handle not found",cr,lf +:def 59 "Invalid function code",cr,lf +:def 60 "No free handles",cr,lf +:def 61 "Save/Restore error",cr,lf +:def 62 "Total pages exceeded",cr,lf +:def 63 "Free pages exceeded",cr,lf +:def 64 "Parameter error",cr,lf +:def 65 "Logical Page out of range",cr,lf +:def 66 "Physical Page out of range",cr,lf +:def 67 "Save area already in use",cr,lf +:def 68 "Save area not in use",cr,lf +:def 70 "General EMS error",cr,lf +:def 71 "Missing or invalid EMS parameter",cr,lf +:def 72 "Handle %1 has %2 pages allocated",cr,lf +:def 75 "Physical page %1 = Frame segment %2",cr,lf +:def 76 "Handle %1 deallocated",cr,lf +:def 78 "EMS not installed",cr,lf + +:end + +;========================================================================= +;========================================================================= diff --git a/v4.0/src/CMD/DEBUG/MAKEFILE b/v4.0/src/CMD/DEBUG/MAKEFILE new file mode 100644 index 0000000..d0fa39a --- /dev/null +++ b/v4.0/src/CMD/DEBUG/MAKEFILE @@ -0,0 +1,107 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: debug.com + +debug.ctl: debug.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +debug.obj: debug.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debcom1.obj: debcom1.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debcom2.obj: debcom2.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debcom3.obj: debcom3.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debasm.obj: debasm.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debuasm.obj: debuasm.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +deberr.obj: deberr.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debconst.obj: debconst.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debdata.obj: debdata.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc \ + $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc debequ.asm makefile + +debems.obj: debems.asm debequ.asm makefile + +debmes.obj: debmes.asm $(inc)\msgserv.asm $(inc)\sysmsg.inc \ + debug.ctl \ + debug.cla \ + debug.clb \ + debug.clc \ + debug.cld \ + debug.cl1 \ + debug.cl2 \ + makefile + +debug.com: debug.obj debcom1.obj debcom2.obj debcom3.obj debems.obj \ + debasm.obj debuasm.obj deberr.obj debconst.obj debdata.obj \ + debmes.obj debug.lnk makefile + link @debug.lnk + convert debug.exe + del debug.exe diff --git a/v4.0/src/CMD/DEBUG/SYSVER.FAL b/v4.0/src/CMD/DEBUG/SYSVER.FAL new file mode 100644 index 0000000..a600c51 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/SYSVER.FAL @@ -0,0 +1,10 @@ + + + IF1 + %OUT Including ..SYSVER.FAL.. + ENDIF + +SYSVER EQU FALSE ; if true, i/o direct to bios + ; so DOS can be debugged + + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/SYSVER.INC b/v4.0/src/CMD/DEBUG/SYSVER.INC new file mode 100644 index 0000000..a600c51 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/SYSVER.INC @@ -0,0 +1,10 @@ + + + IF1 + %OUT Including ..SYSVER.FAL.. + ENDIF + +SYSVER EQU FALSE ; if true, i/o direct to bios + ; so DOS can be debugged + + \ No newline at end of file diff --git a/v4.0/src/CMD/DEBUG/SYSVER.TRU b/v4.0/src/CMD/DEBUG/SYSVER.TRU new file mode 100644 index 0000000..6714b89 --- /dev/null +++ b/v4.0/src/CMD/DEBUG/SYSVER.TRU @@ -0,0 +1,10 @@ + + + IF1 + %OUT Including ..SYSVER.TRU.. + ENDIF + +SYSVER EQU TRUE ; if true, i/o direct to bios + ; so DOS can be debugged + + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/COMPINIT.ASM b/v4.0/src/CMD/DISKCOMP/COMPINIT.ASM new file mode 100644 index 0000000..245b78c --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/COMPINIT.ASM @@ -0,0 +1,1123 @@ + PAGE 90,132 ;A2 + TITLE COMPINIT -- DISKCOMP INITIALIZATION PROGRAM +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COMPINIT + +; DESCRIPTIVE NAME: Initialization for Diskette to diskette copy Utility + +;FUNCTION: DISKCOMP is to compare the contents of the diskette in the +; specified source drive to the diskette in the target +; drive. If necessary for the diskettes to use volume serial +; numbers, the actual value of those number is ignored. + +; Multiple compares may be performed with one load of DISKCOMP. +; A prompt, "Compare another (Y/N)?" permits additional +; executions, all with the same drive specifications. + +; ENTRY POINT: "DISKCOMP" at ORG 100h, jumps to "BEGIN". + +; INPUT: (DOS command line parameters) + +; [d:][path] DISKCOMP [d: [d:]] [/1] [/8] + +; WHERE +; [d:][path] - Path where the DISKCOMP command resides. + +; [d:] - To specify the Source drive +; +; [d:] - To specify the Target drive +; +; [/1] - To compare only the first side of the diskette, +; regardless of the diskette or drive type. + +; [/8] - To compare only the first 8 sectors per track, +; even if the first diskette contains 9/15 sectors +; per track. +; +; EXIT-NORMAL: Errorlevel = 0 +; Function completed successfully. + +; EXIT-ERROR: Errorlevel = 1 +; Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on +; the diskette. + +; EFFECTS: The entire source diskette is compared, including the unused +; sectors. There is no awareness of the separate files +; involved. A unique volume serial number, if present, +; is ignored in the comparison process. + +; INCLUDED FILES: +; PATHMAC.INC - PATHGEN MACRO +; INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) + +; INTERNAL REFERENCES: +; ROUTINES: +; INIT - initialization main routine +; SOURCE_TARGET_DRV - convert source/target drive to bios values +; TEST_DRIVE_VALIDITY - are source/target drives valid? +; DOS_DRIVE_VALIDITY -- check dos drive validity byte +; TEST_REMOVABLE - is specified drive removable? +; CHK_SINGLE_DRIV_OP - is target drive same as source? +; GET_LOGICAL_DRIVE - get logical drive who owns the physical drive +; DISKETTE_DRV_TYPE - check compatability source/target drives +; CHECK_REDIRECTION - is device redirected? +; BUFFER_SIZE - finds start and end of buffer +; SETUP_CTRL_BREAK - setup the ctrl-break vector +; CHECK_SERVER - is server or redirector loaded? + +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; WORKAREA - Temporary storage + +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; PARSER - Processes the DOS Command line, finds parms. + +; DATA AREAS: +; DCOMPSM.SAL - Defines the control blocks that describe the messages +; DCOMPPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT COMPINIT,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For instructions as to how to LINK, see prolog for DISKCOMP. + +;PROGRAM AUTHOR: Original written by: Jin K. +; 4.00 modifications by: Edwin M. K. +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=DISKCOMP, MODULE=COMPINIT.SAL + ENDIF + +;REVISION HISTORY: +;DATE: 10-30-84 - chk_para routine added. Many parts are modified to +; permit DISKCOMP /1, DISKCOMP D: /1 cases. Restore diskbase +; before return to DOS when invalid DOS version occurs. +;DATE: 3-27-85 MAIN PARTS OF DISKCOMP PROGRAM HAS BEEN REWRITTEN +; TO USE NEW IOCTL FUNCTIONS 'READ', 'GET_DEVICE_PARAMETERS'. +; A000 - Change spelling of "LOCAL" to "LOCALX" to make MASM 3 happy. + + INCLUDE PATHMAC.INC ;AN013; + INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) + +CSEG SEGMENT PARA PUBLIC 'CODE' ; ;AC000; + ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + + INCLUDE DISKCOMP.EQU +NOOP EQU 90H ;NO-OPERTION INSTRUCTION, USED TO DELETE ;AN001; + ; 386 SUPPORT ;AN001; +;$salut (4,2,9,41) +;**************************************************************************** +; * +; EXTERNAL VARIABLES * +; * +;**************************************************************************** + EXTRN PARSER:NEAR ;DCOPYPAR.SAL - DRIVES SYS PARSER ;AN000; + + EXTRN RECOMMENDED_BYTES_SECTOR:WORD + EXTRN S_OWNER_SAVED:BYTE + EXTRN T_OWNER_SAVED:BYTE + EXTRN ASCII_DRV1_ID:BYTE ;40H SOURCE DRIVE ID IN ASCII + EXTRN ASCII_DRV2_ID:BYTE ;40H TARGET DRIVE ID IN ASCII + + EXTRN SUBLIST_78 :WORD ; ;AN000; + EXTRN SUBLIST_11 :WORD ; ;AN000; + EXTRN SUBLIST_15A :WORD ; ;AN000; + EXTRN SUBLIST_15B :WORD ; ;AN000; + EXTRN SUBLIST_15C :WORD ; ;AN000; + EXTRN SUBLIST_17B :WORD ; ;AN000; + EXTRN SUBLIST_17C :WORD ; ;AN000; + EXTRN SUBLIST_17D :WORD ; ;AN000; + EXTRN SUBLIST_PARSE:WORD ;PARSE ERROR XX - %0 ;AN004; + + EXTRN MSGNUM_INVALID_PARM:BYTE ;"INVALID PARAMETER" ;AC000; + EXTRN MSGNUM_INVALID_DRV:BYTE ;"INVALID DRIVE SPECIFICATION" ;AC000; + EXTRN MSGNUM_DRV_REDIRECTED:BYTE ;"INVALID, DRIVE REDIRECTED" ;AC000; + EXTRN MSGNUM_NOT_COMPATIBLE:BYTE ;"DEVICE OR DISKETTE TYPES NOT COMPATIBLE";AC000; +.XLIST +;EXTRN MSG_INVALID_DOS :BYTE ;MSG FOR DOS1.0 AND 1.1 +.LIST + + EXTRN TRACK_TO_READ :BYTE + EXTRN SIDE:BYTE + + EXTRN S_DRV_SECT_TRACK :BYTE ;SECT/TRACK + EXTRN S_DRV_HEADS :BYTE ;# OF HEADS + EXTRN S_DRV_TRACKS :BYTE ;# OF TRACKS + EXTRN T_DRV_SECT_TRACK :BYTE + EXTRN T_DRV_HEADS :BYTE + EXTRN T_DRV_TRACKS :BYTE + + EXTRN COPY_TYPE :BYTE ;1 = 1-DRIVE COPY 2 = 2-DRIVE COPY + EXTRN USER_OPTION :BYTE ;NO OPTION (-1) /1 (1), INVALID (9) + EXTRN USER_OPTION_8 :BYTE ;NO OPTION (-1) /8 (1), INVALID (9) + EXTRN BUFFER_BEGIN :WORD ;STARTING BUFFER @ FOR LOADING + EXTRN BUFFER_END :WORD ;ENDING BUFFER @ FOR LOADING + EXTRN START_BUFFER :WORD ;START OF BUFFER SPACE + EXTRN MAIN_EXIT :WORD ;EXIT ADDRESS FOR CONTROL-BREAK + + EXTRN ORG_SOURCE_DRIVE:BYTE ;LOGICAL SOURCE DRIVE NUMBER + EXTRN ORG_TARGET_DRIVE:BYTE ; TARGET + EXTRN SOURCE_DRIVE:BYTE ;AS SPECIFIED BY USER PARMS, DR NUM ;AN000; + EXTRN TARGET_DRIVE:BYTE ;AS SPECIFIED BY USER PARMS, DR NUM ;AN000; + + EXTRN IO_ERROR :BYTE + + EXTRN DS_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM + EXTRN DT_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM + EXTRN DS_specialFunctions :BYTE ;AND THEIR CONTENTS + EXTRN DT_specialFunctions :BYTE + EXTRN DS_deviceType:BYTE + EXTRN DT_deviceType:BYTE + EXTRN DS_deviceAttributes :WORD + EXTRN DT_deviceAttributes :WORD + EXTRN DS_numberOfCylinders :WORD + EXTRN DT_numberOfCylinders :WORD + EXTRN DS_mediaType :BYTE + EXTRN DT_mediaType :BYTE + EXTRN DS_BPB_PTR :BYTE + EXTRN DT_BPB_PTR :BYTE + + EXTRN MS_IOCTL_DRV_PARM :BYTE ;DRIVE PARM FROM SOURCE MEDIUM + EXTRN MT_IOCTL_DRV_PARM :BYTE + + EXTRN PATCH_386:BYTE ;PATCH AREA, CHANGED TO NOOP IF NOT 386 ;AN001; + + EXTRN GENERIC_IOCTL :NEAR + EXTRN SET_LOGICAL_DRIVE :NEAR +; $salut (4,24,28,41) +MY_BPB STRUC +CBYTE_SECT DW 0 ; 200H BYTES / SECTOR +CSECT_CLUSTER DB 0 ; 2h SECTORS / CLUSTER +CRESEV_SECT DW 0 ; 1h RESERVED SECTORS +CFAT DB 0 ; 2h # OF FATS +CROOTENTRY DW 0 ; 70h # OF ROOT ENTRIES +CTOTSECT DW 0 ; 02D0h TOT. # OF SECT. + ; INCL BOOT SECT, DIRS +MEDIA_DESCRIP DB 0 ;0FDh MEDIA DISCRIPTOR +CSECT_FAT DW 0 ; 2h SECTORS / FAT +CSECT_TRACK DW 0 ; +CHEAD DW 0 ; +CHIDDEN_SECT DD 0 ; +BIG_TOT_SECT DD 0 ; + DB 6 DUP (0) ; +MY_BPB ENDS + +;USED TO CHECK FOR PRESENCE OF 386 MACHINE: +BIOS_SYSTEM_DESCRIPTOR struc ;SYSTEM TYPE STRUC ;AN001; +bios_SD_leng dw ? ;VECTOR LENGTH ;AN001; +bios_SD_modelbyte db ? ;SYSTEM MODEL TYPE ;AN001; +bios_SD_scnd_modelbyte db ? ; ;AN001; + db ? ; ;AN001; +bios_SD_featurebyte1 db ? ; ;AN001; + db 4 dup (?) ; ;AN001; +BIOS_SYSTEM_DESCRIPTOR ends ;END OF STRUC ;AN001; + + +;**************************************************************************** +; * +; VARIABLE DECLARATIONS * +; * +;**************************************************************************** +DRIVE_VALID DW ? ;DRIVE VALIDITY BYTE +DEFAULT_DRV DB ? ;DEFAULT DRIVE ID +NUMBER_OF_DRV DB ? ;TOTAL # OF DISKT DRIVES ON THE SYS + ;(NUMBER_OF_DRV = 0 ---> 1 DRIVE) +ASCII_DRIVE_LETTER DB " :",0 + PATHLABL COMPINIT ;AN013; + HEADER ; ;AN000; +; $salut (4,9,15,41) ; ;AN000; +;############################################################################# +; INITIALIZATION ROUTINE - MAIN PROGRAM +INIT PROC NEAR + PUBLIC INIT ;MAKE ENTRY IN LINK MAP ;AN000; + +;OUTPUT: DX = EXIT CODE, "FINE" +;############################################################################# + + MOV DRIVE_VALID,AX ;SAVE DRIVE VALIDITY BYTE + CALL PC_386_CHK ;SEE IF THIS IS A 386 MACHINE ;AN001; + +; REPLACE THE "FILL_SEG" IN THE SUBLIST MESSAGE CONTROL BLOCKS. + +; BECAUSE THIS IS A .COM STYLE FILE, THESE SEGID VALUES CANNOT +; BE PROVIDED BY THE DOS SYSTEM LOADER, BUT MUST BE DYNAMICALLY +; PERFORMED AT EXECUTION TIME AS PART OF A .COM FILE'S OBLIGATION +; TO BE "SELF-RELOCATING". + + MOV AX,CS ;GET SEGID OF COMMON SEGMENT + MOV SUBLIST_78.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_11.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_15A.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_15B.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_15C.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17B.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17C.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17D.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_PARSE.SUB_VALUE_SEG,AX ; ;AN004; + + CALL SETUP_CTRL_BREAK ;STEALS CTRL_BREAK + CLD ;CLEAR DIRECTION FLAG + MOV DX,FINE ;ASSUME EVERYTHING IS FINE +.XLIST +; CALL SCREENING ;CHECK DOS VERSION AND INPUT PARMS +; CMP DX,FINE ;IF FINE & DANDY +; JNE EXIT_INIT +.LIST + CALL PARSER ;LOOK AT DOS COMMAND LINE ;AN000; + + CMP DX,FINE ;IF ALL OK ;AN000; +; $IF E ; ;AN000; + JNE $$IF1 + CALL SOURCE_TARGET_DRV ;DETERMINE SOURCE AND TARGET DRV + +; $ENDIF ; ;AN000; +$$IF1: + CMP DX,FINE ;IF STILL FINE AND DANDY ;AN000; +; $IF E ; ;AN000; + JNE $$IF3 + CALL TEST_DRIVE_VALIDITY + + CMP DX,FINE +; $IF E ; ;AN000; + JNE $$IF4 + CALL DISKETTE_DRV_TYPE ;SOURCE & TARGET DRIVE TYPES + + CMP DX,FINE ;IF FINE & DANDY +; $IF E ; ;AN000; + JNE $$IF5 + CALL BUFFER_SIZE ;GET BUFFER SIZE FOR COPYING + +; $ENDIF ; ;AN000; +$$IF5: +; $ENDIF ; ;AN000; +$$IF4: +; $ENDIF ; ;AN000; +$$IF3: + RET ;RETURN TO CALLER + +INIT ENDP ;END INITIALLIZATION PROGRAM + +;############################################################################# +.XLIST +; HEADER +;****************************************************************************** +; SUBROUTINE NAME : SCREENING - CHECKS THE FOLLOWING: * +; - DOS VERSION * +; - DRIVE ID VALIDITY * +; - FILE NAME ENTERED BY MISTAKE? * +; INPUT : BL : DRIVE VALIDITY BYTE * +; OUTPUT : DX : FINE - NO ERROR * +; (OTHERS)- ERROR MSG OFFSET * +;****************************************************************************** +;SCREENING PROC NEAR + + ;CHECK DOS VERSION: +; MOV AH,DOSVER_FUNC ;SEE IF CORRECT DOS VERSION +; INT 21H ;FUNCTION CALL (AL <- DOS VERSION) +;; XCHG AH,AL ;AH=MAJOR VER, AL=MINOR VER +; CMP AX,expected_version ;IF DOS MAJOR VERSION LESS THAN 2.0 +; $IF NE ;THEN ISSUE ERROR MSG +; MOV DX,OFFSET MSG_INVALID_DOS +; MOV AH,PRINT_FUNC ;USE PRINT FUNCTION TO TELL USER +; INT 21H ;THAT HE IS USING THE OLD VERSION +; INT 20H +; $ELSE ;VERSION OK +; CALL CHK_PARA ;GENERAL SYNTAX CHECK +; $ENDIF ;END VERSION TEST +; RET +;SCREENING ENDP +; HEADER +;;************************************************************************** +;CHK_PARA PROC NEAR +;; CHECK SYNTAX OF THE ENTERED PARAMETERS * +;; ALSO, DETERMINE THE USER OPTION "/1" AND/OR "/8" IS ENTERED. * +;; INPUT: DX = FINE * +;; IF /1 HAS BEEN ENTERED, THE VARIABLE USER_OPTION = OPTION_1 * +;; ELSE USER_OPTION = NO_OPTION. * +;; IF /8 HAS BEEN ENTERED, THE USER_OPTION_8 WILL BE ON * +;; OUTPUT: DX = FINE - NO ERROR * +;; OTHERWISE DX POINTS TO ERROR MSG * +;;************************************************************************** +; PUSH CX +; MOV USER_OPTION, NO_OPTION ;ASSUME NO /1 IS ENTERED. +; MOV USER_OPTION_8, OFF ;ASSUME /8 IS NOT ENTERED. +; XOR CX, CX +; MOV CL, BYTE PTR DS:BEGIN_UNFORM_AREA ;GET # OF CHR +; CMP CL, 0 +; JZ CHK_PARA_EXIT +; CLD ;CLEAR DIRECTION +; MOV DI, BEGIN_UNFORM_AREA+2 ;STARTING POINT OF PARA +; DEC CL ;TO IGNORE LAST CHR (0DH) +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. THE POINTER WILL POINT TO THE NEXT NON_BLANK CHR +; JZ CHK_PARA_EXIT ;ONLY BLANKS ARE ENTERED. +; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 OR /8 ? +; JNC SLASH_ONE ;YES +; CALL CHK_DRV_SPEC ;IS IT A DRIVE SPECIFICATION LIKE d: ? +; JC INVALID_PARA ;IF NOT, THEN ERROR +; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN, OK. (EX. DISKCOMP D:) +; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 OR /8 ? +; JNC SLASH_ONE ;YES.(EX. DISKCOMP D:/1) +; CALL CHK_BLANK ;IF NOT, NEXT CHR SHOULD BE A BLANK. +; JC INVALID_PARA ;OTHERWISE, ERROR. +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. +; JZ CHK_PARA_EXIT ;(EX. DISKCOMP D: ) +; CALL CHK_SLASH_ONE ;IS IT /1 OR /8 ? +; JNC SLASH_ONE ;YES. (EX. DISKCOMP D: /1) +; CALL CHK_DRV_SPEC ;IF NOT /1 OR /8, THEN IS IT A DRV SPEC? +; JC INVALID_PARA ;OTHERWISE, ERROR. +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. +; JZ CHK_PARA_EXIT ;NO MORE CHR. (EX. DISKCOMP D: D:) +; CALL CHK_SLASH_ONE ;OTHERWISE, /1 AND/OR /8 SHOULD BE FOLLOWED. +; JNC SLASH_ONE ;YES, /1 OR /8. JMP TO SLASH_ONE +; JMP INVALID_PARA ;PARAMETER ERROR. +;SLASH_ONE: ;YES, FOUND EITHER OF /1 OR /8. +; CALL SKIP_BLANKS ;/1 SHOULD BE END OF PARAMETERS, OR ONLY BLANKS CAN FOLLOW. +; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN OK. +; CMP USER_OPTION, OPTION_1 ;WAS IT /1? +; JZ SLASH_8 ;THEN CHECK WHETHER NEXT IS /8. +; CALL CHK_SLASH_ONE ;OTHERWISE, IT WAS /8. NOW CHECK /1. +; JC INVALID_PARA ;NOT FOUND, ERROR +; CMP USER_OPTION, OPTION_1 +; JZ CHK_PRE_EXIT ;YES, IT IS /1 +; JMP INVALID_PARA ;OTHERWISE, FOUND /8 AGAIN. ERROR +;SLASH_8: +; CALL CHK_SLASH_ONE ;CHECK IT IS /8 +; JC INVALID_PARA ;NOT FOUND? ERROR +; CMP USER_OPTION_8, ON +; JZ CHK_PRE_EXIT ;YES. IT IS /8 +; JMP INVALID_PARA ;OTHERWISE, FOUND /1 AGAIN. ERROR +;CHK_PRE_EXIT: +; CALL SKIP_BLANKS ;SKIP BLANKS IF ANY. +; JZ CHK_PARA_EXIT ;THERE SHOULD NOT BE ANY MORE PARAMETER. +;INVALID_PARA: +; MOV DX,OFFSET MSG_INVALID_PARM_PTR ;WRONG PARM ENTERED MSG +;CHK_PARA_EXIT: +; POP CX +; +; RET +;CHK_PARA ENDP +; HEADER +;*************************************************************************** +;SKIP_BLANKS PROC NEAR +; ** SKIP BLANKS OR TABS, IF ANY, IN THE PARAMETER STRING. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR. * +; CX - # OF REMAINING CHR IN THE STRING. * +; OUTPUT: ES:DI POINT TO THE NEXT NON_BLANK CHR. * +; CX IS ADJUSTED ACCORINGLY. * +; IF THE CURRENT CHR IS NOT A BLANK, THEN DI, CX VALUE NOT CHANGED.* +; IF CX = 0, THEN ZERO FLAG WILL BE SET AND EXIT THIS PROC. * +;*************************************************************************** +;SKIP_AGAIN: +; MOV AL, 20H ;20H=BLANK +; CLD ;CLEAR DIRECTION +; REPE SCASB +; JZ SK_BL_1 ;IF NOT FOUND A NON_BLANK CHR YET, AND CX=0, EXIT THIS ROUTINE. +; DEC DI ;OTHERWISE, RESTORE DI TO THE NON_BLANK POSITION. +; INC CX ; AND RESTORE CX TO WHERE IT WAS AT NON_BLANK CHR +; ;(IF FOUND A NON_BLANK CHR, ZERO FLAG WOULD NOT BE SET) +; MOV AL, ES:BYTE PTR [DI] +; CMP AL, 09H ;09H=TAB +; JNZ SK_BL_1 ;IF THE NON_BLANK CHR IS NOT A TAB THEN EXIT +; INC DI ;ELSE TRY SKIP AGAIN. +; DEC CX +; JMP SKIP_AGAIN +;SK_BL_1: +; RET +;SKIP_BLANKS ENDP +; HEADER +;;*************************************************************************** +;CHK_SLASH_ONE PROC NEAR +; ** CHECK CURRENT CHR IS / FOLLOWED BY 1. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * +; CX REPRESENTS THE # OF CHR'S IN THE STRING. * +; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX CHANGED ACCORDINGLY. * +; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * +; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;*************************************************************************** + +; CLC ;CLEAR CARRY FLAG +; CMP CX, 2 ;# OF CHR IN THE STRING. +; JL CK_SL_0 ;IF LESS THAN 2, THEN SET CARRY AND EXIT. +; MOV AX, ES:WORD PTR [DI] ;GET CURRENT WORD IN AX +; CMP AX, '1/' ;IS IT /1 ? +; JZ CK_SL_1 ;YES. SET USER_OPTION +; CMP AX, '8/' ;IS IT /8 THEN ? +; JZ CK_SL_2 ;YES. SET USER_OPTION_8 +;CK_SL_0: +; STC ;OTHERWISE, NOT FOUND. SET CARRY +; JMP CK_SL_4 ; AND RETURN +;CK_SL_1: +; MOV USER_OPTION, OPTION_1 +; JMP CK_SL_3 +;CK_SL_2: +; MOV USER_OPTION_8, ON +;CK_SL_3: ;ADJUST CX, DI TO THE NEXT CHR. +; INC DI +; INC DI +; DEC CX +; DEC CX +; CMP CX, 0 ;SET ZERO FLAG IF NO MORE CHR. +;CK_SL_4: +; RET +;CHK_SLASH_ONE ENDP +; HEADER +;;*************************************************************************** +;CHK_DRV_SPEC PROC NEAR +; ** CHECK CURRENT CHR IS ALPHA CHR FOLLOWED BY COLON. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * +; CX -- # OF CHR IN THE STRING. * +; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX ADJUSTED ACCORDINGLY. * +; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * +; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;*************************************************************************** + +; CLC ;CLEAR CARRY +; CMP CX, 2 ;# OF CHR REMAINING IN THE STRING. +; JL CK_DR_1 ;IF LESS THAN 2, THEN NOT FOUND - SET CARRY AND EXIT. +; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR +; AND AL, 11011111B ;CHANGE IT TO UPPER_CASE CHR. +; CMP AL, 'A' +; JB CK_DR_1 ;LESS THAN 'A', THEN NOT FOUND. +; CMP AL, 'Z' +; JA CK_DR_1 ;ABOVE 'Z', THEN NOT FOUND. +; MOV AL, ES:BYTE PTR [DI+1] ;LOOK AHEAD THE FOLLOWING CHR. +; CMP AL, ':' ;SHOULD BE A COLON. +; JNZ CK_DR_1 ;NOT FOUND. +; INC DI ;FOUND. ADJUST CX, DI TO THE NEXT CHR. +; INC DI +; DEC CX +; DEC CX +; CMP CX, 0 ;IF NO MORE CHR, THAN SET THE ZERO FLAG. +; JMP CK_DR_2 +;CK_DR_1: +; STC ;SET CARRY +;CK_DR_2: +; RET +;CHK_DRV_SPEC ENDP +; HEADER +;;*************************************************************************** +;CHK_BLANK PROC NEAR +;; ** CHECK THE CURRENT CHR IS A BLANK OR A TAB. * +;; INPUT: ES:DI POINTS TO THE CURRENT CHR. * +;; CX - # OF CHR IN THE STRING. * +;; OUTPUT: FOUND - DI MOVES TO THE NEXT CHR. CX DECREASES BY 1. * +;; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;;*************************************************************************** +; +; CLC ;CLEAR CARRY +; CMP CX, 1 ;IF LESS THAN 1, NOT FOUND. +; JL CK_BL_0 ;SET CARRY AND EXIT +; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR +; CMP AL, 020H ;020H=BLANK CHR +; JZ CK_BL_1 ;FOUND +; CMP AL, 09H ;09H=TAB CHR +; JZ CK_BL_1 ;FOUND +;CK_BL_0: +; STC ;NOT FOUND. SET CARRY +; JMP CK_BL_2 +;CK_BL_1: +; INC DI ;FOUND. ADJUST DI, CX +; DEC CX +;CK_BL_2: +; RET +;CHK_BLANK ENDP +.LIST + HEADER +; QUERIES THE BIOS TO DETERMINE WHAT TYPE OF +; MACHINE WE ARE ON. WE ARE LOOKING FOR A 386. +; THIS WILL BE USED TO DETERMINE IF A DOUBLE WORD MOVE +; IS TO BE PERFORMED. +; +; INPUTS : NONE +; +; OUTPUTS : IF A 386 NOT PRESENT, CODE IS +; *** P A T C H E D *** +; TO NO-OP THE SUPPORT FOR THE DOUBLE WORD MOVE +;========================================================================= + +PC_386_CHK PROC NEAR ;DETERMINE MACHINE TYPE ;AN001; + + PUSH AX ;SAVE AFFECTED REGS ;AN001; + PUSH BX ; ;AN001; + PUSH ES ; ;AN001; + + MOV AH,0C0H ;RETURN SYSTEM CONFIGURATION ;AN001; + INT 15H ;ES:[BX] POINTS TO BIOS ;AN001; + ; SYSTEM DESCRIPTOR + ASSUME ES:NOTHING ;AN001; + +; $IF C,OR ;IF NOT A GOOD RETURN, OR... ;AN001; + JC $$LL9 + CMP AH,0 ;IS IT NEW FORMAT FOR CONFIG. ;AN001; +; $IF NE,OR ;NO, OR... ;AN001; + JNE $$LL9 + CMP ES:[BX].BIOS_SD_MODELBYTE,0F8H ;CHECK MODEL ;AN001; +; $IF NE ;IF IT IS NOT A 386 MACHINE? ;AN001; + JE $$IF9 +$$LL9: + ;PATCH OUT THE 386 CODE + MOV AL,NOOP ;WITH A NO-OP INSTRUCTION ;AN001; + MOV PATCH_386,AL ; ;AN001; + MOV PATCH_386+1,AL ; ;AN001; + MOV PATCH_386+2,AL ; ;AN001; +; $ENDIF ; ;AN001; +$$IF9: + + POP ES ;RESTORE REGS. ;AN001; + ASSUME ES:CSEG ;BACK TO USUAL ;AN001; + + POP BX ; ;AN001; + POP AX ; ;AN001; + + RET ; ;AN001; + +PC_386_CHK ENDP ; ;AN001; + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : SOURCE_TARGET_DRV DETERMINES SOURCE & TARGET DRIVES & * +; CONVERT THEM FROM DOS TO BIOS VALUE * +; INPUT : SOURCE_DRIVE & TARGET_DRIVE HAVE DOS DRIVE ID'S: * +; 0 = DEFAULT 1 = DRV A ETC. * +; * +; OUTPUT : ORG_SOURCE_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * +; : ORG_TARGET_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * +; * +; : COPY_TYPE 1 = SINGLE DRV COPY, 2 = 2 DRIVE COPY * +; : DX : FINE - NO ERROR * +;****************************************************************************** +SOURCE_TARGET_DRV PROC NEAR + PUBLIC SOURCE_TARGET_DRV ;MAKE ENTRY IN LINK MAP ;AN000; + ;GET CURRENT DEFAULT DRIVE + MOV AH,CURRENTDRV_FUNC ;FUNCTION CALL (19H) + ;(AL <- CURRENT DEFAULT DRV + INT 21H ;0 = A, 1 = B, ETC) + + MOV DEFAULT_DRV,AL ;SAVE IT + + CMP SOURCE_DRIVE,ZERO ;FIRST DRV ENTERED? ;AC000; +; $IF E ;NO DRIVE LETTER ENTERED + JNE $$IF11 + MOV CH, DEFAULT_DRV ;SET SOURCE, TARGET DRIVE TO + INC CH + MOV ORG_SOURCE_DRIVE, CH ;DEFAULT DRIVE + MOV CL, CH + MOV ORG_TARGET_DRIVE, CL +; $ELSE + JMP SHORT $$EN11 +$$IF11: + MOV CH,SOURCE_DRIVE ;GET SOURCE DRIVE FROM SPECIFIED PARM ;AC000; + MOV ORG_SOURCE_DRIVE, CH + CMP TARGET_DRIVE,ZERO ;WAS A SECOND DRIVE SPECIFIED ;AC000; +; $IF E ;TARGET DRIVE IS DEFAULT + JNE $$IF13 + MOV CL, DEFAULT_DRV + INC CL ;MAKE IT A LOGICAL DRIVE NUMBER + MOV ORG_TARGET_DRIVE, CL +; $ELSE + JMP SHORT $$EN13 +$$IF13: + MOV CL, TARGET_DRIVE ;USE USER SPECIFIED TARGET DRIVE ;AC000; + MOV ORG_TARGET_DRIVE, CL +; $ENDIF +$$EN13: +; $ENDIF +$$EN11: + + ADD ASCII_DRV1_ID,CH ;SETUP DRIVE ID ALPHABET IN THE + ADD ASCII_DRV2_ID,CL ;MESSAGES + + RET +SOURCE_TARGET_DRV ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : TEST_DRIVE_VALIDITY--MAKE SURE SOURCE AND TARGET DRIVES * +; SPECIFIED BY USER ARE VALID FOR DISKCOPY * +; * +; INPUT : ORG_SOURCE_DRIVE:BYTE, ORG_TARGET_DRIVE:BYTE * +; * +; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * +;****************************************************************************** + +TEST_DRIVE_VALIDITY PROC NEAR + PUBLIC TEST_DRIVE_VALIDITY ;MAKE ENTRY IN LINK MAP ;AN000; + + CALL DOS_DRIVE_VALIDITY + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF17 + + MOV BL,ORG_SOURCE_DRIVE + CALL CHECK_REDIRECTION + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF17 + + MOV BL,ORG_TARGET_DRIVE + CALL CHECK_REDIRECTION + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF17 + + MOV BL,ORG_SOURCE_DRIVE + CALL CHECK_SERVER + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF17 + + MOV BL,ORG_TARGET_DRIVE + CALL CHECK_SERVER + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF17 + + CALL TEST_REMOVABLE + + CMP DX,FINE +; $IF E ; ;AC000; + JNE $$IF17 + + CALL CHK_SINGLE_DRV_OP ;CHECK IF IT IS + ; ONE PHYSICAL DRIVE OPERATION +; $ENDIF ; ;AC000; +$$IF17: + RET + +TEST_DRIVE_VALIDITY ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : DOS_DRIVE_VALIDITY -- CHEKC DOS DRIVE VALIDITY BYTE * +; * +; INPUT : DRIVE_VALID:BYTE * +; THIS IS THE ORIGINAL VALUE PRESENTED IN AX BY DOS LOADER * +; * +; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * +;****************************************************************************** + +DOS_DRIVE_VALIDITY PROC NEAR + PUBLIC DOS_DRIVE_VALIDITY ;MAKE ENTRY IN LINK MAP ;AN000; + + CMP DRIVE_VALID,0 ;SEE IF DRIVES ARE VALID DOS DEVICE +; $IF NE + JE $$IF19 + MOV DX,OFFSET MSGNUM_INVALID_DRV ;AC000; +; $ENDIF +$$IF19: + RET + +DOS_DRIVE_VALIDITY ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : TEST_REMOVABLE -- CHECK IF DRIVES SPECIFED ARE REMOVABLE * +; * +; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE * +; * +; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * +;****************************************************************************** + +TEST_REMOVABLE PROC NEAR + PUBLIC TEST_REMOVABLE ;MAKE ENTRY IN LINK MAP ;AN000; + + MOV BL,ORG_SOURCE_DRIVE ;GET PARM 1 DRIVE ID + + MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE + INT 21H ;IOCTL CALL + +; $IF NC ;IF DRIVE ID IS WITHIN RANGE + JC $$IF21 + CMP AX,REMOVABLE ;THEN IF SOURCE DRIVE IS FIXED +; $IF NE ; THEN + JE $$IF22 + MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; + ; HARD DRIVE ERROR MESSAGE +; $ELSE ;ELSE, SRC IS REMOVABLE; + JMP SHORT $$EN22 +$$IF22: + MOV BL,ORG_TARGET_DRIVE ;NOW GO CHECK TARGET + MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE + INT 21H ;IOCTL CALL + +; $IF NC ;IF DRV WITHIN RANGE + JC $$IF24 + CMP AX,REMOVABLE ;THEN TGT DRV IS FIXED +; $IF NE ; THEN + JE $$IF25 + MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; + ; HARD DRV ERROR MSG +; $ENDIF ;END TEST IF TGT DRV IS FIXED +$$IF25: +; $ELSE ;TGT DRV OUT OF RANGE. EX. DRIVE X: + JMP SHORT $$EN24 +$$IF24: + MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; + ; HARD DRV ERROR MSG +; $ENDIF ;END TEST IF TGT WITHIN RANGE +$$EN24: +; $ENDIF ;END IF SRC IS REMOVABLE +$$EN22: +; $ELSE ;ELSE, SRC DRV OUT OF RANGE + JMP SHORT $$EN21 +$$IF21: + MOV DX,OFFSET MSGNUM_INVALID_DRV ;PRINT ERROR MSG ;AC000; +; $ENDIF ;END TEST IF SRC DRV WITHIN RANGE +$$EN21: + RET + +TEST_REMOVABLE ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : CHK_SINGLE_DRV_OP * +; * +; INPUT : ORG_SOURCE_DRIVE - LOGICAL DRIVE NUMBER * +; ORG_TARGET_DRIVE * +; * +; OUTPUT : COPY_TYPE WILL BE SET TO ONE OR TWO DEPENDING ON THE * +; TEST RESULT. IF IT IS A SINGLE DRIVE COPY, THEN * +; TARGET DRIVE LETTER WILL BE CHANGED TO THAT OF SOURCE. * +; THE OWNERSHIP OF THE SOURCE AND TARGET DRIVE LETTER * +; MIGHT HAVE BEEN CHANGED. * +; SO, BEFORE EXIT TO DOS, THEY SHOULD BE RESET TO THE SAVED* +; ONE USING S_OWNER_SAVED AND T_OWNER_SAVED UNLESS THEY * +; ARE EQUAL TO 0. (0 MEANS ONLY ONE DRIVE LETTER ASSIGNED.)* +; ASCII_DRV1_ID, ASCII_DRV2_ID MAY BE CHANGED ACCORDINGLY. * +;****************************************************************************** + +CHK_SINGLE_DRV_OP PROC NEAR + PUBLIC CHK_SINGLE_DRV_OP ;MAKE ENTRY IN LINK MAP ;AN000; + + PUSH AX + + MOV BL,ORG_SOURCE_DRIVE + CALL GET_LOGICAL_DRIVE + + MOV S_OWNER_SAVED, AL ;SAVE CURRENT OWNER DRIVE LETTER. + MOV BL, ORG_TARGET_DRIVE + CALL GET_LOGICAL_DRIVE + + MOV T_OWNER_SAVED, AL ;SAVE CURRENT OWNER + MOV BL, ORG_SOURCE_DRIVE + CALL SET_LOGICAL_DRIVE + + MOV BL, ORG_TARGET_DRIVE + CALL SET_LOGICAL_DRIVE + + MOV BL, ORG_SOURCE_DRIVE + CALL GET_LOGICAL_DRIVE ;CHECK IF SOURCE DRIVE OWNERSHIP HAS NOT BEEN CHAGNED? + + CMP AL, ORG_SOURCE_DRIVE +; $IF NE ;IF IT HAS BEEN CHANGED TO TARGET, THEN A SINGLE DRIVE COMPARE. + JE $$IF32 + MOV COPY_TYPE, ONE + MOV BL, ORG_SOURCE_DRIVE + MOV ORG_TARGET_DRIVE, BL ;SET TARGET DRV LETTER TO THE SOURCE. + MOV BL, ASCII_DRV1_ID + MOV ASCII_DRV2_ID, BL + MOV BL, ORG_SOURCE_DRIVE + CALL SET_LOGICAL_DRIVE ;SET THE OWNER BACK TO SOURCE DRV LETTER + +; $ELSE + JMP SHORT $$EN32 +$$IF32: + CMP AL, ORG_TARGET_DRIVE ; SOURCE DRV LETTER = TARGET DRV LETTER CASE, FOR EX. DISKCOMP A: A: +; $IF E + JNE $$IF34 + MOV COPY_TYPE, ONE +; $ELSE + JMP SHORT $$EN34 +$$IF34: + MOV COPY_TYPE, TWO +; $ENDIF +$$EN34: +; $ENDIF +$$EN32: + + POP AX + + RET +CHK_SINGLE_DRV_OP ENDP + HEADER +;****************************************************************************** +GET_LOGICAL_DRIVE PROC NEAR + PUBLIC GET_LOGICAL_DRIVE ;MAKE ENTRY IN LINK MAP ;AN000; +; *** GET THE LOGICAL DRIVE NUMBER WHO HAS THE OWNERSHIP OF THE PHYSICAL +; DRIVE. +; INPUT: BL = DRIVE NUMBER (0=DEFAULT, 1=A, 2=B...) +; OUTPUT: AL = DRIVE NUMBER (0= ONLY ONE DRIVE LETTER ASSIGNED TO THE +; BLOCK DEVICE. OTHERWISE, 1=A, 2=B...) +; +;****************************************************************************** + + MOV AH, 44H + MOV AL, 0EH ; GET THE OWNER OF LOGICAL DRIVE NUMBER + INT 21H + + CMP AL, 0 ;ONLY ONE DRIVE LETTER ASSIGNED? +; $IF E + JNE $$IF38 + MOV AL, BL ;THEN SET IT TO THE INPUT DRIVE LETTER +; $ENDIF +$$IF38: + + RET + +GET_LOGICAL_DRIVE ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : DISKETTE_DRV_TYPE DOES THE FOLLOWING: * +; - GETS SOURCE, TARGET DRIVE INFORMATIONS * +; - CHECK IF IT IS A REMOVABLE DRIVE. * +; INPUT : SOURCE_DRIVE & TARGET_DRIVE * +; 1 = DRIVE A 2 = DRIVE B, ETC. * +; * +; OUTPUT : DX : FINE - NO ERROR * +; (OTHERS)- ERROR MSG OFFSET * +;****************************************************************************** +DISKETTE_DRV_TYPE PROC NEAR + PUBLIC DISKETTE_DRV_TYPE ;MAKE ENTRY IN LINK MAP ;AN000; + + PUSH AX + XOR BX,BX + MOV BL, ORG_SOURCE_DRIVE + MOV CL, GETDEVPARM ;=60h + MOV DX, OFFSET DS_IOCTL_DRV_PARM ;POINTER TO THE CONTROL STRING + CALL GENERIC_IOCTL ;GET DEVICE PARM. + + TEST DS_deviceAttributes, 0001h ;CHECK REMOVABLE. 0001 = NOT REMOVABLE +; $IF E,AND ;NO, CONTINUE ;AC000; + JNE $$IF40 + + MOV AX, DS_numberOfCylinders ;CURRENTLY IGNORE AH. ASSUME LESS + ; THAN TWO BYTES + MOV S_DRV_TRACKS, AL + MOV BX, OFFSET DS_BPB_PTR + MOV AX, [BX].CHead + MOV S_DRV_HEADS, AL + MOV AX, [BX].CSECT_TRACK + MOV S_DRV_SECT_TRACK, AL + MOV AX, [BX].CBYTE_SECT ;RECOMMENDED BYTES/SECTOR + MOV RECOMMENDED_BYTES_SECTOR, AX + + XOR BX,BX + MOV BL, ORG_TARGET_DRIVE + MOV CL, GETDEVPARM + MOV DX, OFFSET DT_IOCTL_DRV_PARM + CALL GENERIC_IOCTL + + TEST DT_deviceAttributes, 0001h +; $IF Z ;TARGET IS NOT FIXED DISK, OK ;AC000; + JNZ $$IF40 + MOV AX, DT_numberOfCylinders + MOV T_DRV_TRACKS, AL + MOV BX, OFFSET DT_BPB_PTR + MOV AX, [BX].CHead + MOV T_DRV_HEADS, AL + MOV AX, [BX].CSECT_TRACK + MOV T_DRV_SECT_TRACK, AL + +;*** CHECK DEVICE COMPATIBILITY + MOV DX, FINE ;GUESS, ALL WILL BE OK + ; DX MAY BE CHANGED TO REFLECT ERROR + CMP DS_deviceType, DRV_720 ;0 - 48 TPI, 5.25", 96 TPI, + ; 5.25", 2 - 720kb, 3.5" +; $IF E ;WILL ONLY ALLOW DISKCOPY BETWEEN ;AC000; + JNE $$IF41 + ; 720KB, 3.5 SOURCE, TARGET + + CMP DT_deviceType, DRV_720 ;target = 720KB also? +; $IF NE ; ;AC000; + JE $$IF42 + MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ; ;AC000; +; $ENDIF ; ;AC000; +$$IF42: +; $ELSE ;SINCE SOURCE NOT 720 ;AC000; + JMP SHORT $$EN41 +$$IF41: + CMP DT_deviceType, DRV_720 ;SOURCE IS NOT 720kb, + ; IS TARGET 720? +; $IF E ;IF SO, THEN ;AC000; + JNE $$IF45 + ;DDT IS NOT COMPATIBLE + MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ; ;AC000; +; $ENDIF ; ;AC000; +$$IF45: +; $ENDIF ; ;AC000; +$$EN41: +; $ELSE ;SINCE SOURCE IS FIXED DISK, ERROR ;AC000; + JMP SHORT $$EN40 +$$IF40: + MOV DX, OFFSET MSGNUM_INVALID_DRV ;ISSUE INVALID DRV MSG ;AC000; +; $ENDIF ; ;AC000; +$$EN40: + POP AX + RET + +DISKETTE_DRV_TYPE ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : CHECK_REDIRECTION FIND OUT IF DEVICE IS REDIRECTED * +; IF IT IS, GENERATE ERROR MSG & EXIT * +; INPUT : BL - DRIVE TO BE TESTED * +; : AL : CURRENT DEFAULT DRIV * +; * +; OUTPUT : DX = LOCAL_DRV (-1) * +; = DIRECTED ( ERROR MSG OFFSET) * +; = INVALID_DRIVE (ERROR MSG OFFSET) * +;****************************************************************************** +CHECK_REDIRECTION PROC NEAR + PUBLIC CHECK_REDIRECTION ;MAKE ENTRY IN LINK MAP ;AN000; + + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + + MOV CX,DX ;SAVE RET TEMPORARILY + MOV AH,IOCTL_FUNC ;GET IOCTL FUNTION & + MOV AL,REDIRECTED_FUNC ;IOCTL SUB-FUNCTION ******CHECK*** + + INT 21H ;AND GO FIND OUT IF IT'S LOCAL +; $IF C + JNC $$IF50 + MOV CX,OFFSET MSGNUM_INVALID_DRV ;REDIR INVALID ;AC000; + +; $ELSE + JMP SHORT $$EN50 +$$IF50: + TEST DX,REMOTE_DRV ;IF DRIVE IS REDIRECTED +; $IF NZ + JZ $$IF52 + + MOV CX,OFFSET MSGNUM_DRV_REDIRECTED ; ;AC000; +; $ENDIF +$$IF52: +; $ENDIF +$$EN50: + MOV DX,CX ;GET ERROR MSG @ + + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET ;RETURN TO CALLER +CHECK_REDIRECTION ENDP + HEADER +;****************************************************************************** +; SUBROUTINE NAME : BUFFER_SIZE DETERMINES WHERE BUFFER STARTS & ENDS * +; INPUT : NONE * +; * +; OUTPUT : BUFFER_BEGIN ADDRESS * +; : BUFFER_END ADDRESS * +; : START_BUFFER ADDRESS +;****************************************************************************** +BUFFER_SIZE PROC NEAR + PUBLIC BUFFER_SIZE ;MAKE ENTRY IN LINK MAP ;AN000; + + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + MOV BX,OFFSET init ;GET ADDR OF INIT+1024 AS A FREE MEMORY + add bx, 1024 ;(OFFSET FROM CS, IN BYTES) + MOV CL,4 ;CONVERT OFFSET INTO SEGMT BY DIVIDING + SHR BX,CL ;IT BY 16 + + MOV AX,CS ;CS + OFFSET => INIT @ IN SEGMENT + ADD BX,AX ;WHERE BUFFER CAN START + + ;NEED TO START AT A NEW SECTOR ==> + AND BL,CLEAR_SEGMENT ;TRUNCATE TO PREVIOUS 512 BYTE BOUNDRY + ;(GET PREVIOUS SECTOR NUMBER) + ADD BX,20H ;THEN, ADVANCE TO THE BEGINNING OF + ;NEXT SECTOR (SINCE PART OF PREVIOUS + ;SECTOR WAS USED) + + MOV BUFFER_BEGIN,BX ;SAVE OUR BUFFER START SEGMENT ADDR + MOV START_BUFFER,BX ;SAVE IT AGAIN ELSEWHERE + ;(AT THE BEGINNING OF A SECTOR WITH + ;SEGMENT BITS CLEARED) + + MOV BX,DS:TWO ;GET ADDR WHERE BUFFER ENDS + MOV BUFFER_END,BX ;(TOP OF MEMORY, OFFSET 2 IN PSP) + + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET ;RETURN TO CALLER +BUFFER_SIZE ENDP + HEADER +;****************************************************************************** +SETUP_CTRL_BREAK PROC NEAR ;SETUP CTRL-BREAK VECTOR + PUBLIC SETUP_CTRL_BREAK ;MAKE ENTRY IN LINK MAP ;AN000; +;****************************************************************************** + PUSH AX + PUSH BX + PUSH DX + PUSH ES + + MOV AX,2523H ;SET THE CTRL-BREAK VECTOR + MOV DX,OFFSET MAIN_EXIT + INT 21H + + POP ES + POP DX + POP BX + POP AX + RET + +SETUP_CTRL_BREAK ENDP + HEADER +;****************************************************************************** +CHECK_SERVER PROC NEAR ;SEE IF SERVER OR REDIRECTOR IS IN++ + PUBLIC CHECK_SERVER ;MAKE ENTRY IN LINK MAP ;AN000; +; +; INPUT: BL = DRIVE NUMBER (1=A,2=B ETC....) +;****************************************************************************** + MOV AH,0 ;SEE IF SERVER LOADED + INT SERVER + CMP AH,0 +; $IF E + JNE $$IF55 + MOV DX,FINE +; $ELSE + JMP SHORT $$EN55 +$$IF55: + DEC BL + ADD BL,"A" ;CONVERT TO ASCII DRIVE LETTER + MOV ASCII_DRIVE_LETTER,BL ;PUT IN ASCIIZ STRING + MOV SI,OFFSET ASCII_DRIVE_LETTER + MOV AH,SHARED + CLC + INT SERVER +; $IF C + JNC $$IF57 + MOV DX,OFFSET MSGNUM_DRV_REDIRECTED ;AC000; +; $ELSE + JMP SHORT $$EN57 +$$IF57: + MOV DX,FINE +; $ENDIF +$$EN57: +; $ENDIF +$$EN55: + RET +CHECK_SERVER ENDP + + Public INIT_END +INIT_END LABEL BYTE + PATHLABL COMPINIT ;AN013; +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DCMPMACR.INC b/v4.0/src/CMD/DISKCOMP/DCMPMACR.INC new file mode 100644 index 0000000..f0cdd0d --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DCMPMACR.INC @@ -0,0 +1,171 @@ + IF1 ;AN000; + %OUT INCLUDING DCMPMACR.INC...;AN000; + ELSE ;AN000; +; %OUT INCLUDING DCMPMACR.INC... + ENDIF ;AN000; +;***************************************************************************; +; MACRO DEFINITION ; +;***************************************************************************; + +HEADER MACRO TEXT ;;AN000; +.XLIST ;;AN000; + SUBTTL &TEXT ;;AN000; +.LIST ;;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = +DOSCALL MACRO FUNC,SUBFUNC ;;AN000; + IFNB ;;AN000;IS THERE ANY PARMS AT ALL? + IFNB ;;AN000; + MOV AX,(FUNC SHL 8)+SUBFUNC ;;AN000;FUNC TO AH,SUBFUNC TO AL + ELSE ;;AN000;SINCE THERE IS NO SUBFUNC + MOV AH,FUNC ;;AN000; + ENDIF ;;AN000; + ENDIF ;;AN000; + INT 21H ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = +PRINT MACRO MESSAGE ;;AN000; + MOV DI,OFFSET MESSAGE ;;AC000; + CALL SENDMSG ;;AC000; + ENDM ;;AN000; +; = = = = = = = = = +.xlist ;AN000; +;INPUT MACRO MESSAGE +; PRINT MESSAGE +; CALL PROMPT +; ENDM +.list ;AN000; +; $SALUT (0,16,22,36) +MY_TRACKLAYOUT MACRO ;;AN000; + LOCAL CSECT_F ;;AN000; +CSECT_F DW 0 ;;AN000;# OF SECTORS IN A TRACK. Currently 18 is max. + ;; THE REST IS FOR FUTURE MEDIA + DW 1 ;;AN000;1 ST SECTOR + DW 512 ;;AN000;# OF BYTES + DW 2 ;;AN000; + DW 512 ;;AN000; + DW 3 ;;AN000; + DW 512 ;;AN000; + DW 4 ;;AN000; + DW 512 ;;AN000; + DW 5 ;;AN000; + DW 512 ;;AN000; + DW 6 ;;AN000; + DW 512 ;;AN000; + DW 7 ;;AN000; + DW 512 ;;AN000; + DW 8 ;;AN000; + DW 512 ;;AN000; + DW 9 ;;AN000; + DW 512 ;;AN000; + DW 10 ;;AN000; + DW 512 ;;AN000; + DW 11 ;;AN000; + DW 512 ;;AN000; + DW 12 ;;AN000; + DW 512 ;;AN000; + DW 13 ;;AN000; + DW 512 ;;AN000; + DW 14 ;;AN000; + DW 512 ;;AN000; + DW 15 ;;AN000; + DW 512 ;;AN000; + DW 16 ;;AN000; + DW 512 ;;AN000; + DW 17 ;;AN000; + DW 512 ;;AN000; + DW 18 ;;AN000; + DW 512 ;;AN000;CURRENTLY 18 SECTORS/TRACK IS MAXIMUM + DW 19 ;;AN000;BELOW IS FOR THE FUTURE MEDIA. + DW 512 ;;AN000; + DW 20 ;;AN000; + DW 512 ;;AN000; + DW 21 ;;AN000; + DW 512 ;;AN000; + DW 22 ;;AN000; + DW 512 ;;AN000; + DW 23 ;;AN000; + DW 512 ;;AN000; + DW 24 ;;AN000; + DW 512 ;;AN000; + DW 25 ;;AN000; + DW 512 ;;AN000; + DW 26 ;;AN000; + DW 512 ;;AN000; + DW 27 ;;AN000; + DW 512 ;;AN000; + DW 28 ;;AN000; + DW 512 ;;AN000; + DW 29 ;;AN000; + DW 512 ;;AN000; + DW 30 ;;AN000; + DW 512 ;;AN000; + DW 31 ;;AN000; + DW 512 ;;AN000; + DW 32 ;;AN000; + DW 512 ;;AN000; + DW 33 ;;AN000; + DW 512 ;;AN000; + DW 34 ;;AN000; + DW 512 ;;AN000; + DW 35 ;;AN000; + DW 512 ;;AN000; + DW 36 ;;AN000; + DW 512 ;;AN000; + DW 37 ;;AN000; + DW 512 ;;AN000; + DW 38 ;;AN000; + DW 512 ;;AN000; + DW 39 ;;AN000; + DW 512 ;;AN000; + DW 40 ;;AN000; + DW 512 ;;AN000; + DW 41 ;;AN000; + DW 512 ;;AN000; + DW 42 ;;AN000; + DW 512 ;;AN000; + DW 43 ;;AN000; + DW 512 ;;AN000; + DW 44 ;;AN000; + DW 512 ;;AN000; + DW 45 ;;AN000; + DW 512 ;;AN000; + DW 46 ;;AN000; + DW 512 ;;AN000; + DW 47 ;;AN000; + DW 512 ;;AN000; + DW 48 ;;AN000; + DW 512 ;;AN000; + DW 49 ;;AN000; + DW 512 ;;AN000; + DW 50 ;;AN000; + DW 512 ;;AN000; + DW 51 ;;AN000; + DW 512 ;;AN000; + DW 52 ;;AN000; + DW 512 ;;AN000; + DW 53 ;;AN000; + DW 512 ;;AN000; + DW 54 ;;AN000; + DW 512 ;;AN000; + DW 55 ;;AN000; + DW 512 ;;AN000; + DW 56 ;;AN000; + DW 512 ;;AN000; + DW 57 ;;AN000; + DW 512 ;;AN000; + DW 58 ;;AN000; + DW 512 ;;AN000; + DW 59 ;;AN000; + DW 512 ;;AN000; + DW 60 ;;AN000; + DW 512 ;;AN000; + DW 61 ;;AN000; + DW 512 ;;AN000; + DW 62 ;;AN000; + DW 512 ;;AN000; + DW 63 ;;AN000; + DW 512 ;;AN000; + ENDM ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DCOMPMS.INC b/v4.0/src/CMD/DISKCOMP/DCOMPMS.INC new file mode 100644 index 0000000..6808808 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DCOMPMS.INC @@ -0,0 +1,232 @@ +;:util DISKCOMP ;utility name +;:class 1 ;DOS extended errors: +;:class 2 ;parse errors: +;1 Too many parameters +;2 Required parameter missing +;3 Invalid switch +;4 Invalid keyword +;5 Parameter value not in allowed range +;6 Parameter value not allowed [parse ret codes 6 and 7] +;7 (undefined) +;8 Parameter format not correct +;9 (undefined) +;10 Invalid parameter [no corresponding parse ret code] +;11 Invalid parameter combination [no corresponding parse ret code] +;; +;:class A ;system messages +; +;:use 1 COMMON1 ;"Incorrect DOS version" +; +;:use 2 EXTEND8 ;"Insufficient memory" +; +;:use 3 PARSE10 ;"Invalid parameter" +;; +;:def 4 "Do not specify filename(s)",CR,LF +;"Command format: DISKCOMP d: d: [/1][/8]",LF,CR +; +;:def 5 CR,LF,"Invalid drive specification",CR,LF +;"Specified drive does not exist",CR,LF +;"or is non-removable",CR,LF +; +;:def 6 CR,LF,"Cannot DISKCOMP to or from",CR,LF +;"a network drive",CR,LF +; +;:def 7 CR,LF,"Insert FIRST diskette in drive %1:",CR,LF +; +;:def 8 CR,LF,"Insert SECOND diskette in drive %1:",CR,LF +; +;:def 9 CR,LF,"FIRST diskette bad or incompatible",CR,LF +; +;:def 10 CR,LF,"SECOND diskette bad or incompatible",CR,LF +; +;:use 11 EXTEND21 ;"Drive not ready" NOTE CHANGE %1 TO %0 +; +;:use 12 COMMON28 ;"Press any key to continue . . ." +; +;:use 13 EXTEND19 ;CR,LF,"Attempt to write to write-protected diskette",CR,LF +; +;:def 14 CR,LF,"Compare another diskette (Y/N) ?" +; +;:def 15 CR,LF,"Comparing %1 tracks",CR,LF +;"%2 sectors per track, %3 side(s)",CR,LF +; +;:def 16 CR,LF,"Drive types or diskette types",CR,LF +;"not compatible",CR,LF +; +;:def 17 CR,LF,"Unrecoverable read error on drive %2",CR,LF +;"side %3, track %4",CR,LF +; +;:def 18 CR,LF,"Compare error on",CR,LF,"side %3, track %4",CR,LF +; +;:def 19 "Make sure a diskette is inserted into",CR,LF +;"the drive and the door is closed",CR,LF +; +;:def 20 CR,LF,"Compare process ended",CR,LF +; +;:def 21 CR,LF,"Compare OK",CR,LF +; +;:def 22 CR,LF +;:end +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + IF1 ;AN000; + %OUT COMPONENT=DISKCOMP, MODULE=DCOMPMS.INC...;AN000; + ENDIF ;AN000; +; $SALUT (0,13,18,22) ; ;AN000; +;THIS MODULE IS INCLUDED IN DCOMPSM.SAL. +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +FOUR_SUBS EQU 4 ;AN000;FOUR VARIABLES IN ONE MSG +PC_ID_4 EQU 4 ;AN000;IDENTIFIES FOURTH REPLACEMENT PARM +PC_ID_5 EQU 5 ;AN000;IDENTIFIES FIFTH REPLACEMENT PARM +LETTER_A EQU "A" ;AN000;DEFAULT DRIVE ID +CLEAR_BUF EQU 0C0H ;AN006;CLEAR KEYBOARD BUFFER BEFORE INPUT +KEY_IN_ECHO EQU 1 ;AN000;REQUEST KEYBOARD INPUT TO AL, ECHO RESPONSE +KEY_IN EQU 8 ;AN000;REQUEST KEYBOARD INPUT TO AL, NO ECHO +FILL_OFF EQU 0 ;AN000;TO BE FILLED IN WITH OFFSET TO DATA +FILL_SEG EQU 0 ;AN000;TO BE FILLED IN WITH THE COMMON SEG ID + ; SINCE A .COM FILE CANNOT HAVE + ; SEGMENT FIXUP RECORDS + +SUBLIST_PARSE SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS ,MAX_0,MIN_1,PAD_BLK> ;AN003; + PUBLIC SUBLIST_PARSE ;AN003; + +; THE NEXT GROUP ARE ADDITIONAL CLASS "A" MESSAGES +; SPECIFICALLY DEFINED FOR THE DISKCOMP UTILITY + + ;"Insufficient memory" +MSGNUM_UNSUF_MEMORY MSG_DESC <2> ;AN000; + PUBLIC MSGNUM_UNSUF_MEMORY ;AN000; + + ;CR,LF,"Invalid parameter",CR,LF +MSGNUM_INVALID_PARM MSG_DESC <3> ;AN000; + PUBLIC MSGNUM_INVALID_PARM ;AN000; + + ;"Do not specify filename(s)",CR,LF + ;"Command format: DISKCOMP d: d: [/1][/8]",CR,LF +MSGNUM_INVALID_PARM2 MSG_DESC <4> ;AN000; + PUBLIC MSGNUM_INVALID_PARM2 ;AN000; + +; = = = = = = = = = = = = = = = = + ;CR,LF,"Invalid drive specification",CR,LF + ;"Specified drive does not exist",CR,LF + ;"or is non-removable",CR,LF +MSGNUM_INVALID_DRV MSG_DESC <5> ;AN000; + PUBLIC MSGNUM_INVALID_DRV ;AN000; + +; = = = = = = = = = = = = = = = = + ;CR,LF,"Cannot DISKCOMP to or from",CR,LF + ;"a network drive",CR,LF +MSGNUM_DRV_REDIRECTED MSG_DESC <6> ;AN000; + PUBLIC MSGNUM_DRV_REDIRECTED ;AN000; + +; = = = = = = = = = = = = = = = = + ;CR,LF,"Insert FIRST diskette in drive %1:",CR,LF +MSGNUM_LOAD_FIRST MSG_DESC <7,,SUBLIST_78,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_LOAD_FIRST,SUBLIST_78 ;AN000; + +SUBLIST_78 SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1>;AN000; +;THE "FILL" FIELDS NEED TO BE SET TO POINT TO +;"ASCII_DRV1_ID" OR "ASCII_DRV2_ID"(BELOW). + + ;CR,LF,"Insert SECOND diskette in drive %1:",CR,LF +MSGNUM_LOAD_SECOND MSG_DESC <8,,SUBLIST_78,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_LOAD_SECOND ;AN000; + + ;IF "FIRST" SPECIFIED +ASCII_DRV1_ID DB LETTER_A-BYTE ;AN000; + + ;IF "SECOND" SPECIFIED +ASCII_DRV2_ID DB LETTER_A-BYTE ;AN000; + PUBLIC ASCII_DRV1_ID,ASCII_DRV2_ID ;AN000; + +; = = = = = = = = = = = = = = = = + ;CR,LF,"FIRST diskette bad or incompatible",CR,LF +MSGNUM_BAD_FIRST MSG_DESC <9> ;AN000; + PUBLIC MSGNUM_BAD_FIRST ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"SECOND diskette bad or incompatible",CR,LF +MSGNUM_BAD_SECOND MSG_DESC <10> ;AN000; + PUBLIC MSGNUM_BAD_SECOND ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,Drive not ready",CR,LF +MSGNUM_GET_READY MSG_DESC <11,,SUBLIST_11,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_GET_READY ;AN000; + +SUBLIST_11 SUBLIST <,,DRIVE_LETTER,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1>;AN000; + PUBLIC SUBLIST_11 ;AN000; + +DRIVE_LETTER DB LETTER_A,":",NULL ;AN000; + PUBLIC DRIVE_LETTER ;AN000; + +SKIP_MSG DB NULL ;AN000; + PUBLIC SKIP_MSG ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Press any key to continue . . .",CR,LF +MSGNUM_STRIKE MSG_DESC <12,,,,(CLASS_A SHL 8) OR (CLEAR_BUF + KEY_IN)> ;AN006; + PUBLIC MSGNUM_STRIKE ;AN000; +; = = = = = = = = = = = = = = = = +; ;CR,LF,"Attempt to write to write-protected diskette",CR,LF +MSGNUM_WRITE_PROTECT MSG_DESC <13> ;AN000; + PUBLIC MSGNUM_WRITE_PROTECT ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Compare another diskette (Y/N) ?" +MSGNUM_COMP_ANOTHER MSG_DESC <14,,,,(CLASS_A SHL 8) OR (CLEAR_BUF + KEY_IN_ECHO)> ;AN006; + PUBLIC MSGNUM_COMP_ANOTHER ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Comparing %1 tracks",CR,LF + ;"%2 Sectors/Track, %3 Side(s)",CR,LF +MSGNUM_COMPARING MSG_DESC <15,,SUBLIST_15A,THREE_SUBS> ;AN000; + PUBLIC MSGNUM_COMPARING ;AN000; + +SUBLIST_15A SUBLIST <,,MSG_TRACKS,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1>;AN000; +SUBLIST_15B SUBLIST <,,MSG_SECTRK,FILL_SEG,PC_ID_2,SF_BITS,MAX_0,MIN_1>;AN000; +SUBLIST_15C SUBLIST <,,MSG_SIDES,FILL_SEG,PC_ID_3,SF_BITS,MAX_0,MIN_1>;AN000; + PUBLIC SUBLIST_15A,SUBLIST_15B,SUBLIST_15C ;AN000; + +MSG_TRACKS DW 0 ;AN000;NUMBER OF TRACKS +MSG_SECTRK DW 0 ;AN000;NUMBER OF SECTORS PER TRACK +MSG_SIDES DW 0 ;AN000;NUMBER OF SIDES + PUBLIC MSG_TRACKS,MSG_SECTRK,MSG_SIDES ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Drive types or diskette types",CR,LF + ;"not compatible",CR,LF +MSGNUM_NOT_COMPATIBLE MSG_DESC <16> ;AN000; + PUBLIC MSGNUM_NOT_COMPATIBLE ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Unrecoverable read error on drive %2",CR,LF + ;"side %3, track %4",CR,LF + ;%2 IS "DRIVE_LETTER", AND + ;"MSG_SIDES" AND "MSG_TRACKS" ARE %3 AND %4. +MSGNUM_HARD_ERROR_READ MSG_DESC <17,,SUBLIST_17B,THREE_SUBS> ;AN000; + PUBLIC MSGNUM_HARD_ERROR_READ ;AN000; + +SUBLIST_17B SUBLIST <,,DRIVE_LETTER,FILL_SEG,PC_ID_2,SF_BITS,MAX_0,MIN_1>;AN000; +SUBLIST_17C SUBLIST <,,MSG_SIDES,FILL_SEG,PC_ID_3,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_17D SUBLIST <,,MSG_TRACKS,FILL_SEG,PC_ID_4,SF_BITS,MAX_0,MIN_1>;AN000; + PUBLIC SUBLIST_17B,SUBLIST_17C,SUBLIST_17D ;AN000; + + ;CR,LF,"Compare error on",CR,LF + ;"side %3, track %4",CR,LF + ;"MSG_SIDES" AND "MSG_TRACKS" ARE %3 AND %4. +MSGNUM_HARD_ERROR_COMP MSG_DESC <18,,SUBLIST_17C,TWO_SUBS> ;AN000; + PUBLIC MSGNUM_HARD_ERROR_COMP ;AN000; +; = = = = = = = = = = = = = = = = + ;:def 19 "Make sure a diskette is inserted into",CR,LF + ;"the drive and the door is closed",CR,LF +MSGNUM_CLOSE_DOOR MSG_DESC <19> ;AN004; + PUBLIC MSGNUM_CLOSE_DOOR ;AN004; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Compare process ended",CR,LF +MSGNUM_FATAL_ERROR MSG_DESC <20> ;AN000; + PUBLIC MSGNUM_FATAL_ERROR ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Compare OK",CR,LF +MSGNUM_COMP_OK MSG_DESC <21> ;AN000; + PUBLIC MSGNUM_COMP_OK ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF +MSGNUM_NEWLINE MSG_DESC <22> ;AC007; + PUBLIC MSGNUM_NEWLINE ;AN000; +; = = = = = = = = = = = = = = = = +;end of DCOMPMS.INC + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DCOMPP.ASM b/v4.0/src/CMD/DISKCOMP/DCOMPP.ASM new file mode 100644 index 0000000..369434b --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DCOMPP.ASM @@ -0,0 +1,123 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOMPP.SAL - DISKCOMP SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOMPP.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of DISKCOMP. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .COM. +; The Common PARSER is then INCLUDEd. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.ASM statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.ASM statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT DCOMPP,NUL,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOMP.SAL. +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOMP, MODULE=DCOMPP.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + INCLUDE PATHMAC.INC ;AN013; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + PUBLIC SYSPARSE ;AN000;SUBROUTINE ENTRY POINT + +INCSW EQU 0 ;AC013;DO NOT INCLUDE PSDATA.INC +FARSW EQU 0 ;AN000;CALL THE PARSER BY NEAR CALL +DATESW EQU 0 ;AN000;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;AN000;SUPPRESS TIME CHECKING +FILESW EQU 0 ;AN000;SUPPRESS CHECK FILE SPECIFICATION +CAPSW EQU 0 ;AN000;SUPPRESS FILE TABLE CAPS +CMPXSW EQU 0 ;AN000;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 1 ;AN000;DO SUPPORT DRIVE ONLY FORMAT +QUSSW EQU 0 ;AN000;SUPPRESS SUPPORT OF QUOTED STRING FORMAT +NUMSW EQU 0 ;AN000;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;AN000;SUPPRESS KEYWORD SUPPORT +SWSW EQU 1 ;AN000;DO SUPPORT SWITCHES +VAL1SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 3 +BASESW EQU 1 ;AN012;SPECIFY, PSDATA POINTED TO BY "DS" + INCLUDE PSDATA.INC ;AN013;PARSER DATA AREA + PATHLABL DCOMPP ;AN013; +;.XLIST ;AN000; +;.XCREF ;AN000; + INCLUDE PARSE.ASM ;AN000; +.LIST ;AN000; +.CREF ;AN000; + PATHLABL DCOMPP ;AN013; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DCOMPPAR.ASM b/v4.0/src/CMD/DISKCOMP/DCOMPPAR.ASM new file mode 100644 index 0000000..7a549d2 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DCOMPPAR.ASM @@ -0,0 +1,427 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOMPPAR.SAL - LOOK AT COMMAND LINE PARMS +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOMPPAR.SAL + +; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters +; and the interface to the DOS system PARSER. + +;FUNCTION: The static data areas are prescribed by the DOS system PARSER +; to define the several parameters presented to DISKCOMP. These +; data areas are passed to the PARSER, and its responses checked +; to determine the nature of the user's specifications. Any errors +; found in the user's parameters are defined in messages back +; to the user. + +; ENTRY POINT: PARSER, near + +; INPUT: (DOS COMMAND LINE PARAMETERS) + +; [d:][path] DISKCOMP [d: [d:]] [/1] [/8] + +; WHERE +; [d:][path] - Path where the DISKCOMP command resides. + +; [d:] - To specify the Source drive +; +; [d:] - To specify the Target drive +; +; [/1] - To compare only the first side of the diskette, +; regardless of the diskette or drive type. + +; [/8] - To compare only the first 8 sectors per track, +; even if the first diskette contains 9/15 sectors +; per track. +; +; Upon entry to PARSER in this module, +; "CURRENT_PARM" = offset to start of parm text in command string +; "ORDINAL" = initialized to zero +; PSP+81H = text of DOS command line parms string + +; EXIT-NORMAL: +; "SOURCE_DRIVE" = CHAR OF FIRST DRIVE ID SPECIFIED, BLANK IF NONE +; "TARGET_DRIVE" = CHAR OF SECOND DRIVE ID IF BOTH SPECIFIED, BLANK +; IF NONE OR ONLY ONE SPECIFIED +; "USER_OPTION" = 01 ON IF /1, -1 IF /1 NOT SPECIFIED. +; "USER_OPTION_8" = 01 ON IF /8, -1 IF /8 NOT SPECIFIED. + +; EXIT-ERROR: +; IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR". + +; INTERNAL REFERENCES: +; ROUTINES: +; PARSER:NEAR Call the system Parser to decode command line +; PARSE_ERROR:NEAR Display the appropriate Parse error message. + +; DATA AREAS: +; The several parameter control blocks, defined by the System +; PARSER interface, defining the DISKCOMP parameters. + +; EXTERNAL REFERENCES: +; ROUTINES: +; SENDMSG:NEAR Uses Msg Descriptor to drive message handler. +; SYSPARSE:NEAR System Command Line Common Parser. + +; DATA AREAS: +; EXITFL:BYTE Errorlevel return code. +; MSGNUM_PARSE:WORD Message descriptor for all parse errors. +; USER_OPTION:BYTE /1 parm indicator +; USER_OPTION_8:BYTE /8 parm indicator +; SOURCE_DRIVE:BYTE character of first specified drive +; TARGET_DRIVE:BYTE character of second specified drive + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT DCOMPPAR,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOMP.SAL. + +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOMP, MODULE=DCOMPPAR.SAL... ;AN000; + ENDIF ;AN000; + INCLUDE PATHMAC.INC ;AN013; +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;AN000; + SUBTTL TEXT ;AN000; +.LIST ;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = +; $SALUT (4,23,28,36) ;AN000; +CHAR_A EQU "A" ;AN000;ASCII VALUE OF CHARACTER "A" +NUL EQU 0 ;AN003;ASCIIZ STRING DELIMITER +; EXIT CODES FROM SYSPARSE (WHEN CY=0) + +SYSPRM_EX_OK EQU 0 ;AN000; no error +SYSPRM_EX_MANY EQU 1 ;AN000; too many operands +SYSPRM_EX_MISSING EQU 2 ;AN000; required operand missing +SYSPRM_EX_NOT_SWLIST EQU 3 ;AN000; not in switch list provided +SYSPRM_EX_NOT_KEYLIST EQU 4 ;AN000; not in keyword list provided +SYSPRM_EX_RANGE EQU 6 ;AN000; out of range specified +SYSPRM_EX_VALUE EQU 7 ;AN000; not in value list provided +SYSPRM_EX_STRING EQU 8 ;AN000; not in string list provided +SYSPRM_EX_SYNTAX EQU 9 ;AN000; syntax error +SYSPRM_EX_EOL EQU -1 ;AN000; end of command line +; = = = = = = = = = = = = + HEADER ;AN000; +PSP STRUC ;AN000; + DB 80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP +PSP_PARMLEN DB ? ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE +PSP_COMMAND DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE +PSP ENDS ;AN000; + +MSG_DESC STRUC ;AN003; +MSG_NUM DW ? ;AN003;MESSAGE NUMBER (TO AX) +MSG_HANDLE DW ? ;AN003;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW ? ;AN003;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW ? ;AN003;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DW ? ;AN003;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL);AN003; +MSG_DESC ENDS ;AN003; + +ONE_SUBS EQU 1 ;AN003;NUMBER OF VARIABLES + +SUBLIST STRUC ;AN000; +SUB_SIZE DB ? ;AN003;SUBLIST SIZE (POINTER TO NEXT SUBLIST) +SUB_RES DB ? ;AN003;RESERVED + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD ;AN003; +SUB_VALUE DW ? ;AN003;TIME, DATE, OR PTR TO DATA ITEM +SUB_VALUE_SEG DW ? ;AN003;SEG ID OF PTR + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME ;AN003; + ; IF THIS IS A .COM FILE) ;AN003; +SUB_ID DB ? ;AN003;N OF %N +SUB_FLAGS DB ? ;AN003;DATA TYPE FLAGS +SUB_MAX_WIDTH DB ? ;AN003;MAXIMUM FIELD WIDTH (0=UNLIMITED) +SUB_MIN_WIDTH DB ? ;AN003;MINIMUM FIELD WIDTH +SUB_PAD_CHAR DB ? ;AN003;CHARACTER FOR PAD FIELD + ; CAN BE " ", "0" OR ",". ;AN003; + ; "," CAUSES INSERTION OF THE ACTIVE ;AN003; + ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS. ;AN003; +SUBLIST ENDS ;AN003; + +; = = = = = = = = = = = = + HEADER ;AN000; +; $SALUT (4,14,19,36) ;AN000; + EXTRN EXPAR:ABS ;AN000;ERRORLEVEL VALUE FOR BAD PARMS + EXTRN FINE:ABS ;AN000;RETURN STATUS INDICATOR + +BLANK EQU " " ;AN002;WIPE OUT SWITCH TO AVOID DUPLICATE + +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + EXTRN SENDMSG:NEAR ;AN000;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR + EXTRN SYSPARSE:NEAR ;AN000;SYSTEM COMMAND LINE PARSER + + EXTRN EXITFL:BYTE ;AN000;ERRORLEVEL RETURN CODE + + EXTRN SOURCE_DRIVE:BYTE ;AN000;FIRST DRIVE LETTER SPECIFIED IN PARMS + EXTRN USER_OPTION:BYTE ;AN000;NO OPTION (-1) /1 (1), INVALID (9) +NO_OPTION EQU -1 ;AN000;OPTION NOT SPECIFIED +OPTION_1 EQU 1 ;AN000;OPTION "/1" SPECIFIED +OPTION_8 EQU 1 ;AN000;OPTION "/8" SPECIFIED + EXTRN USER_OPTION_8:BYTE ;AN000;NO OPTION (-1) /8 (1), INVALID (9) + + EXTRN MSGNUM_PARSE:WORD ;AN000;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS + EXTRN MSGNUM_INVALID_PARM2:WORD ;AN005;HELP MESSAGE DESCRIPTOR + EXTRN SUBLIST_PARSE:WORD ;AN003;POINTS TO INVALID PARM +; = = = = = = = = = = = = + +CURRENT_PARM DW 81H ;AN000;POINTER INTO COMMAND OF NEXT OPERAND + PUBLIC CURRENT_PARM ;AN000; + +ORDINAL DW 0 ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE + PUBLIC ORDINAL ;AN000; + +; = = = = = = = = = = = = + HEADER ;AN000; + +;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER + + PUBLIC PARMS ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE +PARMS LABEL BYTE ;AN000;PARMS CONTROL BLOCK + DW PARMSX ;AN000;POINTER TO PARMS EXTENSION + DB 0 ;AN000; NUMBER OF STRINGS (0, 1, 2) + ; NEXT LIST WOULD BE EXTRA DELIM LIST + ; (,& WHITESPACE ALWAYS) + ; NEXT LIST WOULD BE EXTRA END OF LINE LIST + ; (CR,LF,0 ALWAYS) + +;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK +PARMSX LABEL BYTE ;AN000;PARMS EXTENSION CONTROL BLOCK + DB 0,2 ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED + DW CONTROL_POS ;AN000; DESCRIPTION OF POSITIONAL 1 + DW CONTROL_POS ;AN000; DESCRIPTION OF POSITIONAL 2 + + DB 1 ;AN000; MAX SWITCH OPERANDS ALLOWED + DW CONTROL_SW ;AN000; DESCRIPTION OF SWITCH + + DB 0 ;AN000; MAX KEYWORD OPERANDS ALLOWED + ; THERE IS NO CONTROL BLOCK + ; DEFINING KEYWORDS + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL + +;FIRST POSITIONAL PARAMETER IS: +; [D:] - SPECIFY THE SOURCE DRIVE. + + PUBLIC CONTROL_POS ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_POS LABEL BYTE ;AN000;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC, + ; OPTIONAL + DW 0101H ;AN000; CONTROLS TYPE MATCHED + ; SELECTED BITS: "DRIVE ONLY" AND "OPTIONAL" + + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0000H ;AN000;FUNCTION_FLAGS (NO CAPITALIZATION NEEDED) + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + DW RESULT1 ;AN000; RESULT BUFFER + DW NOVALS ;AN000; NO VALUE LISTS + DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST + +;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS +NOVALS DB 0 ;AN000;NO VALUE DEFINITIONS + +;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER +RESULT1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS + DB 3 ;AN000; TYPE RETURNED: 0=RESERVED, + ; 1=NUMBER, 2=LIST INDEX, + ; 3=STRING, 4=COMPLEX, + ; 5=FILESPEC, 6=DRIVE + ; 7=DATE, 8=TIME + ; 9=QUOTED STRING +RESULT_TAG DB 0FFH ;AN000; MATCHED ITEM TAG + DW 0 ;AN000;POINTER TO SYNONYM + +RESULT_PTR1 DB ? ;AN000;DRIVE NUMBER (A=1, B=2, ETC) + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE TWO SWITCHES, OPTIONAL + +;THE SWITCH IS "/1", MEANING ONLY COMPARE THE FIRST SIDE. +;THE SECOND SWITCH IS "/8", MEANING ONLY LOOK AT FIRST 8 SECTORS PER TRACK. + + PUBLIC CONTROL_SW ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_SW LABEL BYTE ;AN000;SWITCH DESCRIPTOR FOR /1 OR /8 + DW 0000H ;AN000; CONTROLS TYPE MATCHED + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0000H ;AN000;FUNCTION_FLAGS (NO CAPITALIZATION) + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + + DW RESULTSW1 ;AN000; RESULT BUFFER + DW NOVALS ;AN000; VALUE LISTS + DB 2 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST +SINGLE_SIDED LABEL BYTE ;AN002; +SW_1 DB "/1",0 ;AN000; IF n >0, KEYWORD 1 +SW_8 DB "/8",0 ;AN000;SECOND KEYWORD + +;RESULTS CONTROL BLOCK FOR THE SWITCHES +RESULTSW1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS + DB 3 ;AN000; TYPE RETURNED: 0=RESERVED, + ; 1=NUMBER, 2=LIST INDEX, + ; 3=STRING, 4=COMPLEX, + ; 5=FILESPEC, 6=DRIVE + ; 7=DATE, 8=TIME + ; 9=QUOTED STRING + DB 0FFh ;AN000; MATCHED ITEM TAG + +RESULTSWSYN DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:) +RESULT_PTR2 DD ? ;AN000; OFFSET OF STRING VALUE +; = = = = = = = = = = = = + PATHLABL DCOMPPAR ;AN013; + HEADER ;AN000; +; $SALUT (4,4,9,36) ;AN000; +PARSER PROC NEAR ;AN000; + PUBLIC PARSER ;AN000; + +;INPUT: "CURRENT_PARM" = OFFSET TO NEXT PARM IN COMMAND STRING +; "ORDINAL" = COUNT OF NEXT PARM TO PARSE +; PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING +;OUTPUT: "SOURCE_DRIVE" = A=1, B=2, 0 IF NONE +; "TARGET_DRIVE" = A=1, B=2, 0 IF NONE +; "USER_OPTION" = 01 ON IF /1, -1 IF /1 NOT SPECIFIED. +; "USER_OPTION_8" = 01 ON IF /8, -1 IF /8 NOT SPECIFIED. +; IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR". +; = = = = = = = = = = = = + MOV USER_OPTION,NO_OPTION ;AN000;SET DEFAULT, SWITCH NOT FOUND + MOV USER_OPTION_8,NO_OPTION ;AN000;SET DEFAULT, SWITCH NOT FOUND + +; $SEARCH COMPLEX ;AN000;LOOP THRU COMMAND LINE + JMP SHORT $$SS1 +$$DO1: + ;LOOKING AT RETURN CODE FROM SYSPARSE... ;AN000; + CMP AX,SYSPRM_EX_OK ;AN000;WERE THERE ANY ERRORS? +; $EXITIF NE ;AN000;HAD A PROBLEM + JE $$IF1 + CALL PARSE_ERROR ;AN000;DISPLAY REASON FOR ERROR + +; $ORELSE ;AN000;SINCE NO PROBLEM, SO FAR + JMP SHORT $$SR1 +$$IF1: + MOV ORDINAL,CX ;AN000;SAVE UPDATED COUNT + MOV CURRENT_PARM,SI ;AN000;REMEMBER HOW FAR I GOT + MOV BX,DX ;AN000;SET DATA BASE REG TO POINT TO THIS OPERAND + CMP BX,OFFSET RESULT1 ;AN000;WAS POSITIONAL PARM SPECIFIED? +; $IF E ;AN000;IF POSITIONAL PARM SPECIFIED, + JNE $$IF4 + MOV SI,CX ;AN000;USE COUNT OF POSITIONALS AS INDEX + MOV AL,RESULT_PTR1 ;AN000;GET VALUE OF DRIVE (A=1, B=2, ETC) + MOV SOURCE_DRIVE-1[SI],AL ;AN000;SAVE RESPONSE DRIVE VALUE + ;IN EITHER SOURCE_DRIVE OR TARGET_DRIVE + ;ACCORDING TO ORDINAL IN SI (FROM CX) +; $ELSE ;AN000;SINCE NOT POSITIONAL PARM SPECIFIED + JMP SHORT $$EN4 +$$IF4: + MOV AL,SINGLE_SIDED+BYTE ;AN000;GET ID PORTION OF SWITCH + MOV BX,RESULTSWSYN ;AN000;GET OFFSET TO MATCHING SWITCH + CMP [BX]+BYTE,AL ;AN000;WAS IT /1? +; $IF E ;AN000;YES IT WAS /1 + JNE $$IF6 + MOV SW_1,BLANK ;AN002;AVOID GETTING /1 AGAIN + MOV USER_OPTION,OPTION_1 ;AN000;MUST HAVE BEEN THE SWITCH, /1 +; $ELSE ;AN000;SINCE IT WAS NOT /1, MUST BE /8 + JMP SHORT $$EN6 +$$IF6: + MOV SW_8,BLANK ;AN002;AVOID GETTING /8 AGAIN + MOV USER_OPTION_8,OPTION_8 ;AN000;REPORT BACK, IT WAS /8 +; $ENDIF ;AN000; +$$EN6: +; $ENDIF ;AN000; +$$EN4: +; $STRTSRCH ;AN000; +$$SS1: + LEA DI,PARMS ;AN000; ES:DI = PARSE CONTROL DEFINITON + MOV SI,CURRENT_PARM ;AN000; DS:SI = COMMAND STRING, NEXT PARM + XOR DX,DX ;AN000; RESERVED, INIT TO ZERO + MOV CX,ORDINAL ;AN000; OPERAND ORDINAL, INITIALLY ZERO + CALL SYSPARSE ;AN000;LOOK AT DOS PARMS + ; AX=EXIT CODE + ; BL=TERMINATED DELIMETER CODE + ; CX=NEW OPERAND ORDINAL + ; SI=SET TO PAST SCANNED OPERAND + ; DX=SELECTED RESULT BUFFER + CMP AX,SYSPRM_EX_EOL ;AN000; IS THAT THE END OF THE PARMS? + ;IF NOT, LOOP BACK AND FIND OUT + ; WHAT THAT PARM IS +; $ENDLOOP E ;AN000;END OF LIST + JNE $$DO1 + MOV DX,FINE ;AN000;REPORT THAT PARSER WENT OK +; $ENDSRCH ;AN000;FINISHED WITH DOS COMMAND LINE +$$SR1: + RET ;AN000;RETURN TO CALLER +PARSER ENDP ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; +PARSE_ERROR PROC NEAR ;AN000; +;INPUT: AX - ERROR NUMBER RETURNED FROM PARSE. +; "CURRENT_PARM" - OFFSET INTO COMMAND OF WHERE TO START LOOKING FOR PARM +;OUTPUT: APPROPRIATE ERROR MESSAGE IS PREPARED FOR DISPLAY. +; DX IS SET TO OFFSET OF PARSE ERROR DESCRIPTOR. +; = = = = = = = = = = = = + + MOV MSGNUM_PARSE,AX ;AN000;PASS MESSAGE NUMBER TO DESCRIPTOR + MOV EXITFL,EXPAR ;AN000;ERRORLEVEL CODE TO "PARM ERROR" + MOV AX,CURRENT_PARM ;AN003;GET POINTER TO START OF BAD PARM + CMP SI,AX ;AN003;HAS THE INDEX TO COMMAND LINE MOVED? +; $IF NE ;AN003;YES, THERE IS A FAULTY PARM + JE $$IF13 + MOV BYTE PTR [SI],NUL ;AN003;DELIMIT THE BAD PARM + MOV SUBLIST_PARSE.SUB_VALUE,AX ;AN000;POINT SUBLIST TO BAD PARM + + MOV MSGNUM_PARSE.MSG_SUBLIST,OFFSET SUBLIST_PARSE ;AN003;POINT TO SUBLIST + MOV MSGNUM_PARSE.MSG_COUNT,ONE_SUBS ;AN003;SET COUNT OF SUBLISTS TO ONE +; $ENDIF ;AN003;INDEX MOVED? +$$IF13: + MOV DI,OFFSET MSGNUM_PARSE ;AC005;OFFSET TO PARSE ERR DESCRIPTOR + CALL SENDMSG ;AN005;DISPLAY ERROR MSG + + MOV DX,OFFSET MSGNUM_INVALID_PARM2 ;AN005;PASS BACK OFFSET TO HELP MSG + RET ;AN000;RETURN TO CALLER +PARSE_ERROR ENDP ;AN000; +; = = = = = = = = = = = = + PATHLABL DCOMPPAR ;AN013; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DCOMPSM.ASM b/v4.0/src/CMD/DISKCOMP/DCOMPSM.ASM new file mode 100644 index 0000000..73eb45a --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DCOMPSM.ASM @@ -0,0 +1,159 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOMPSM.SAL - DISKCOMP SYSTEM MESSAGES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOMPSM.SAL + +; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT +; configuration expected by the modules of DISKCOMP. + +;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a +; part of the DISKCOMP module by using INCLUDE to bring in the +; common portion, in SYSMSG.INC. This included code contains +; the routines to initialize for message services, to find +; where a particular message is, and to display a message. + +; ENTRY POINT: SYSDISPMSG:near +; SYSGETMSG:near +; SYSLOADMSG:near + +; INPUT: +; AX = MESSAGE NUMBER +; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12) +; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE +; CX = NUMBER OF %PARMS, 0 IF NONE +; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW +; CALL SYSDISPMSG ;DISPLAY THE MESSAGE + +; If carry set, extended error already called: +; AX = EXTENDED MESSAGE NUMBER +; BH = ERROR CLASS +; BL = SUGGESTED ACTION +; CH = LOCUS +; _ _ _ _ _ _ _ _ _ _ _ _ + +; AX = MESSAGE NUMBER +; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG) +; CALL SYSGETMSG ;FIND WHERE A MSG IS + +; If carry set, error +; CX = 0, MESSAGE NOT FOUND +; If carry NOT set ok, and resulting regs are: +; CX = MESSAGE SIZE +; DS:SI = MESSAGE TEXT +; _ _ _ _ _ _ _ _ _ _ _ _ + +; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION +; If carry not set: +; CX = SIZE OF MSGS LOADED + +; If carry is set, regs preset up for SYSDISPMSG, as: +; AX = ERROR CODE IF CARRY SET +; AX = 1, INCORRECT DOS VERSION +; DH =-1, (Utility msg) +; OR, +; AX = 1, Error loading messages +; DH = 0, (Message manager error) +; BX = STDERR +; CX = NO_REPLACE +; DL = NO_INPUT + +; EXIT-NORMAL: CARRY is not set + +; EXIT-ERROR: CARRY is set +; Call Get Extended Error for reason code, for SYSDISPMSG and +; SYSGETMSG. + +; INTERNAL REFERENCES: +; ROUTINES: (Generated by the MSG_SERVICES macro) +; SYSLOADMSG +; SYSDISPMSG +; SYSGETMSG + +; DATA AREAS: +; INCLUDED "DCOMPMS.INC" - message defining control blocks +; INCLUDE SYSMSG.INC ;Permit System Message handler definition + +; EXTERNAL REFERENCES: +; ROUTINES: none + +; DATA AREAS: control blocks pointed to by input registers. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT DCOMPSM,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOMP.SAL. + +; COPYRIGHT: "Version 4.00 (C)Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOMP, MODULE=DCOMPSM.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; + INCLUDE PATHMAC.INC ;AN013; +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;;AN000; + SUBTTL TEXT ;AN000; +.LIST ;;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = + INCLUDE SYSMSG.INC ;AN000;PERMIT SYSTEM MESSAGE HANDLER DEFINITION + MSG_UTILNAME ;AN000;IDENTIFY THE COMPONENT +; = = = = = = = = = = = = + HEADER ;AN000; +; $SALUT (4,12,18,36) ;AN000; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME SS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME DS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME ES:CSEG ;AN000;ESTABLISHED BY CALLER + +;(deleted ;AN010;) PUBLIC COPYRIGHT ; +;(deleted ;AN010;) COPYRIGHT DB "MS DOS DISKCOMP Utility " +;(deleted ;AN010;) INCLUDE COPYRIGH.INC ;(moved to MSG_SERVICES) + HEADER ;AN000; + INCLUDE MSGHAN.INC ;AN000;DEFINE THE MESSAGE HANDLER CONTROL BLOCKS + INCLUDE DCOMPMS.INC ;AN000;DEFINE THE MESSAGES, AND CONTROL BLOCKS + HEADER ;AN000; + MSG_SERVICES ;AN000;DATA AREA FOR THE MESSAGE HANDLER +; = = = = = = = = = = = = + HEADER ;AN000; + PUBLIC SYSLOADMSG ;AN000; + PUBLIC SYSDISPMSG ;AN000; + + MSG_SERVICES ;AN000;MSG TEXT + PATHLABL DCOMPSM ;AN013; + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg + ;DEFAULT=NO GETmsg +; MSG_SERVICES +.XLIST ;AN000; +.XCREF ;AN000; + MSG_SERVICES ;AN000; +.LIST ;AN000; +.CREF ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + PATHLABL DCOMPSM ;AN013; + + +CSEG ENDS ;AN000; + +include msgdcl.inc + + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DISKCOMP.ASM b/v4.0/src/CMD/DISKCOMP/DISKCOMP.ASM new file mode 100644 index 0000000..83d6a61 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DISKCOMP.ASM @@ -0,0 +1,2060 @@ + PAGE 90,132 ;A2 + TITLE DISKCOMP.SAL - COPY COMPLETE DISKETTE +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DISKCOMP + +; DESCRIPTIVE NAME: Diskette to diskette complete compare Utility + +;FUNCTION: DISKCOMP is to compare the contents of the diskette in the +; specified first drive to the diskette in the second +; drive. If the first drive has a vol serial number, that +; field in both diskettes is ignored in the comparison +; of that one sector, because DISKCOPY will create a unique +; volume serial number when it duplicates a diskette. + +; Multiple compares may be performed with one load of DISKCOMP. +; A prompt, "Compare another (Y/N)?" permits additional +; executions, all with the same drive specifications. + +; ENTRY POINT: "DISKCOMP" at ORG 100h, jumps to "BEGIN". + +; INPUT: (DOS command line parameters) + +; [d:][path] DISKCOMP [d: [d:]] [/1] [/8] + +; WHERE +; [d:][path] - Path where the DISKCOMP command resides. + +; [d:] - To specify the First drive +; +; [d:] - To specify the Second drive +; +; [/1] - To compare only the first side of the diskette, +; regardless of the diskette or drive type. + +; [/8] - To compare only the first 8 sectors per track, +; even if the first diskette contains 9/15 sectors +; per track. +; +; EXIT-NORMAL: Errorlevel = 0 +; Function completed successfully. + +; EXIT-ERROR: Errorlevel = 1 +; Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on +; the diskette. +; Errorlevel = 2 +; Termination requested by CTRL-BREAK. + +; EFFECTS: The entire diskette is compared, including the unused +; sectors. There is no awareness of the separate files +; involved. A unique volume serial number is ignored +; for the comparison of the first sector. + +; INCLUDED FILES: +; PATHMAC.INC - PATHGEN MACRO +; INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) +; INCLUDE DISKCOMP.EQU ;EQUATES + +; INTERNAL REFERENCES: +; ROUTINES: +; BEGIN - entry point from DOS +; SET_LOGICAL_DRIVE - set log. drive letter as owner of drive +; COMP - compare the diskette image +; TEST_REPEAT - see if user wants to compare another +; READ_SOURCE - read from first drive as much as possible +; CHECK_SOURCE - determine first diskette type +; READ_A_SECTOR - use IOCTL read to get a sector +; CALC_TRACK_SIZE - find mem size to hold one track +; CHECK_MEMORY_SIZE - be sure enuf memory to compare 1 track +; COMP_TARGET - compare memory data with secon diskette +; CHECK_TARGET - compare second disk boot record +; SET_DRV_PARM - request IOCTL to set device parm +; COMP_TRACK - read and compare specified track +; SWAP_DRIVE - setup for diskette swapping +; READ_TRACK - read a track to memory +; READ_OP - IOCTL to read a track +; SET_FOR_THE_OLD - use pre 2.0 BPB +; SET_TRACKLAYOUT - determine sectors per track +; GENERIC_IOCTL - perform specified IOCTL function +; EXTENDED_ERROR_HANDLER - determine and service extended errors +; SET_DRV_PARM_DEF - set drive parms via IOCTL +; +; VOLSER - during compare of first sector, avoid vol ser # +; SENDMSG - passes parms to regs and invokes the system message routine. + +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; WORKAREA - Temporary storage + +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; SYSPARSE - Processes the DOS Command line, finds parms. + +; DATA AREAS: +; DCOMPSM.SAL - Defines the control blocks that describe the messages +; DCOMPPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT DISKCOMP,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; Sample LINK command: + +; LINK @DISKCOMP.ARF + +; Where the DISKCOMP.ARF is defined as: + +; DISKCOMP+ +; DCOMPSM+ +; DCOMPP+ +; DCOMPPAR+ +; COMPINIT + +; These modules must be linked in this order. The load module is +; a COM file, to be converted to COM with EXE2BIN. + +; REVISION HISTORY: +; A000 Version 4.00: add PARSER, System Message Handler, +; Ignore vol serial number differences. +; A001 386 Support +; A002 Avoid duplicate switches +; A003 PTM 540 Show parm in error +; A004 PTM 752 Add close door after drive not ready +; A005 PTM 756 Add help msg after parm error message +; A006 PTM1100 Clear keyboard buffer before input response +; A007 PTM1464 Delete unused msgs: 22,23,24 +; A008 PTM1406 USE 69H INSTEAD OF IOCTL FOR GET/SET MEDIA ID +; A009 PTM1605 PUT A BLANK LINE OUT BEFORE PRESS ANY KEY MSG +; A010 PTM1821 move INCLUDE COPYRIGH.INC to MSG_SERVICE macro +; A011 PTM3184 SUPPORT OS/2 1.0/1.1 TYPE BOOT RECORDS ALSO +; REMOVE USE OF GET/SET MEDIA ID +; A012 PTM3262 Specify BASESW EQU 1 before PARSE.ASM +; A013 PTM3512 PATHGEN +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "DCOMPSM.SAL" module: + +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " + +;PROGRAM AUTHOR: Original written by: Jin K. +; 4.00 modifications by: Edwin M. K. +;****************** END OF SPECIFICATIONS ***************************** + IF1 ; ;AN000; + %OUT COMPONENT=DISKCOMP, MODULE=DISKCOMP.SAL + ENDIF ; ;AN000; +;***************************************************************************** +; * +; D I S K C O M P * +; * +; UPDATE HISTORY: 8-21, 8-22, 8-30, 9-4, 9-20, 9-21, 12-19 * +; 2-15-84, 2-17, 4-29, 6-20,7-24,3-27-85 * +; * +;***************************************************************************** + + INCLUDE PATHMAC.INC ;AN013; + INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) + INCLUDE DISKCOMP.EQU ;EQUATES + +; $salut (4,16,22,36) ; ;AN000; +;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, +;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN +;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. + +MSG_DESC STRUC ; ;AN000; +MSG_NUM DW ? ;MESSAGE NUMBER (TO AX) ;AN000; +MSG_HANDLE DW ? ;HANDLE OF OUTPUT DEVICE (TO BX) ;AN000; +MSG_SUBLIST DW ? ;POINTER TO SUBLIST (TO SI) ;AN000; +MSG_COUNT DW ? ;SUBSTITUTION COUNT (TO CX) ;AN000; +MSG_CLASS DW ? ;MESSAGE CLASS (IN HIGH BYTE, TO DH) ;AN000; + ;LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) ;AN000; +MSG_DESC ENDS ; ;AN000; + +MY_BPB STRUC +CBYTE_SECT DW 0 ; 200H ;BYTES / SECTOR +CSECT_CLUSTER DB 0 ; 2h ;SECTORS / CLUSTER +CRESEV_SECT DW 0 ; 1h ;RESERVED SECTORS +CFAT DB 0 ; 2h ;# OF FATS +CROOTENTRY DW 0 ; 70h ;# OF ROOT ENTRIES +CTOTSECT DW 0 ; 02D0h ;TOTAL # OF SECTORS INCLUDING + ; BOOT SECT, DIRECTORIES +MEDIA_DESCRIP DB 0 ;0FDh ;MEDIA DISCRIPTOR +CSECT_FAT DW 0 ; 2h ;SECTORS / FAT +CSECT_TRACK DW 0 ; +CHEAD DW 0 ; +CHIDDEN_SECT DD 0 ; +BIG_TOT_SECT DD 0 ; + DB 6 DUP (0) ; +MY_BPB ENDS + +CSEG SEGMENT PARA PUBLIC 'CODE' ; ;AN000; + ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + +;***************************************************************************** +; * +; EXTERNAL VARIABLES * +; * +;***************************************************************************** +;$salut (4,2,9,36) + +.XLIST +;EXTRN PROMPT :NEAR ;MESSAGE DISPLAY AND KEYBOARD INPUT ROUTINE +;EXTRN ERROR_MESSAGE :NEAR ;ERROR MESSAGE DISPLAY ROUTINE +;EXTRN COMPAT_ERROR :NEAR +;EXTRN PRINTF :NEAR ;MESSAGE DISPLAY ROUTINE +;EXTRN YES :BYTE +;EXTRN NO :BYTE +;EXTRN MSG_FIRST_BAD_PTR :BYTE +.LIST + + EXTRN SYSLOADMSG :NEAR ;SYSTEM MSG HANDLER INTIALIZATION ;AN000; + EXTRN SYSDISPMSG :NEAR ;SYSTEM MSG HANDLER DISPLAY ;AN000; + + EXTRN INIT :NEAR ;INITIALIZATION ROUTINE + + EXTRN MSG_TRACKS :WORD ; ;AN000; + EXTRN MSG_SECTRK :WORD ; ;AN000; + EXTRN MSG_SIDES :WORD ; ;AN000; + + EXTRN ASCII_DRV1_ID :BYTE ; ;AN000; + EXTRN ASCII_DRV2_ID :BYTE ; ;AN000; + + EXTRN SUBLIST_78 :WORD ; ;AN000; + EXTRN SUBLIST_17B :WORD ; ;AN000; + + EXTRN MSGNUM_EXTERR :WORD ;EXTENDED ERROR MSG DESCRIPTOR ;AN000; + EXTRN MSGNUM_LOAD_FIRST :BYTE ; ;AC000; + EXTRN MSGNUM_LOAD_SECOND :BYTE ; ;AC000; + EXTRN MSGNUM_NOT_COMPATIBLE:BYTE ; ;AC000; + EXTRN MSGNUM_COMP_ANOTHER:BYTE ; ;AC000; + EXTRN MSGNUM_GET_READY :BYTE ; ;AC000; + EXTRN MSGNUM_CLOSE_DOOR :BYTE ; ;AN004; + EXTRN MSGNUM_FATAL_ERROR :BYTE ; ;AC000; + EXTRN MSGNUM_UNSUF_MEMORY:BYTE ; ;AC000; + EXTRN MSGNUM_BAD_FIRST :BYTE ; ;AC000; + EXTRN MSGNUM_BAD_SECOND :BYTE ; ;AC000; + EXTRN MSGNUM_HARD_ERROR_READ :BYTE ; ;AC000; + EXTRN MSGNUM_HARD_ERROR_COMP :BYTE ; ;AC000; + EXTRN MSGNUM_COMPARING :BYTE ; ;AC000; + EXTRN MSGNUM_STRIKE :BYTE ; ;AC000; + EXTRN MSGNUM_WRITE_PROTECT:BYTE ; ;AC000; + EXTRN MSGNUM_COMP_OK :BYTE ; ;AC000; + EXTRN MSGNUM_NEWLINE :BYTE ; + EXTRN DRIVE_LETTER :BYTE ; + EXTRN SKIP_MSG :BYTE ;NULL REPLACEMENT FOR DRIVE LETTER ;AN000; + PAGE +;***************************************************************************** +; * +; PUBLIC VARIABLES * +; * +;***************************************************************************** + + PUBLIC DISKCOMP_BEGIN + PUBLIC DISKCOMP_END + PUBLIC RECOMMENDED_BYTES_SECTOR + PUBLIC S_OWNER_SAVED + PUBLIC T_OWNER_SAVED + PUBLIC COMP + PUBLIC SOURCE_DRIVE + PUBLIC TARGET_DRIVE + PUBLIC S_DRV_SECT_TRACK + PUBLIC S_DRV_HEADS + PUBLIC S_DRV_TRACKS + PUBLIC T_DRV_SECT_TRACK + PUBLIC T_DRV_HEADS + PUBLIC T_DRV_TRACKS + PUBLIC USER_OPTION + PUBLIC COPY_TYPE + PUBLIC END_OF_TRACK + PUBLIC BUFFER_BEGIN + PUBLIC START_BUFFER + PUBLIC BUFFER_END + PUBLIC TRACK_TO_READ + PUBLIC TRACK_TO_COMP + PUBLIC SIDE + PUBLIC USER_INPUT + PUBLIC MAIN_EXIT + + PUBLIC NO_OF_SIDES + PUBLIC USER_OPTION_8 + PUBLIC ORG_SOURCE_DRIVE + PUBLIC ORG_TARGET_DRIVE + PUBLIC COMP_STATUS + PUBLIC OPERATION + + PUBLIC IO_ERROR + + PUBLIC DS_IOCTL_DRV_PARM ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM + PUBLIC DT_IOCTL_DRV_PARM ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM + PUBLIC DS_specialFunctions ;AND THEIR CONTENTS + PUBLIC DT_specialFunctions + PUBLIC DS_deviceType + PUBLIC DT_deviceType + PUBLIC DS_deviceAttributes + PUBLIC DT_deviceAttributes + PUBLIC DS_numberOfCylinders + PUBLIC DT_numberOfCylinders + PUBLIC DS_mediaType + PUBLIC DT_mediaType + PUBLIC DS_BPB_PTR + PUBLIC DT_BPB_PTR + + PUBLIC MS_IOCTL_DRV_PARM ;DRIVE PARM FROM SOURCE MEDIUM + PUBLIC MT_IOCTL_DRV_PARM ;DRIVE PARM FROM TARGET MEDIUM + +;***************************************************************************** + ORG 100H ;PROGRAM ENTRY POINT ; + +DISKCOMP: + JMP BEGIN +;***************************************************************************** + EVEN ;PUT STACK ONTO A WORD ALIGNMENT BOUNDARY ;AN000; +;INTERNAL STACK AREA + + DB 64 DUP ('STACK ') ;512 BYTES + +MY_STACK_PTR LABEL WORD + PAGE +;***************************************************************************** +; * +; INTERNAL VARIABLES * +; * +;***************************************************************************** + +; $salut (4,22,26,36) ; ;AN000; +;DEFAULT BPB FOR OLD MEDIA +;5.25, 48 TPI BPB SINGLE SIDE (9 SECTORS/TRACK) +BPB48_SINGLE DW 512 ;BYTES/SECTOR + DB 1 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 40h ;# OF ROOT ENTRY + DW 168h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0FCh ;MEDIA BYTE + DW 2 ;SECTORS/FAT + +;5.25, 48 TPI BPB DOUBLE SIDE (9 SECTORS/TRACK) +BPB48_DOUBLE DW 512 ;BYTES/SECTOR + DB 2 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 70h ;# OF ROOT ENTRY + DW 2D0h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0FDh ;MEDIA BYTE + DW 2 ;SECTORS/FAT + +;5.25, 96 TPI BPB DOUBLE SIDE (15 SECTORS/TRACK) +BPB96 DW 512 ;BYTES/SECTOR + DB 1 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 0E0h ;# OF ROOT ENTRY + DW 960h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0F9h ;MEDIA BYTE + DW 7 ;SECTORS/FAT +BPB96_LENG EQU $-BPB96 ;THIS LENGTH WILL BE USED FOR BPB48 ALSO. + + + +; INPUT PARMETERS FROM INIT SUBROUTINE: + +S_OWNER_SAVED DB 0 ;DRIVE LETTER THAT OWNED + ; SOURCE DRIVE OWNERSHIP +T_OWNER_SAVED DB 0 +RECOMMENDED_BYTES_SECTOR DW 0 ;RECOMMENED BYTES/SECTOR FROM DEVICE PARA + +;IT IS ASSUMED THE NEXT TWO BYTES ARE CONSECUTIVE, +;AND DEFINED IN SOURCE/TARGET ORDER, BY DCOMPPAR.SAL. +SOURCE_DRIVE DB 0 ;1=A:, 2=B:,... +TARGET_DRIVE DB 0 + +ORG_SOURCE_DRIVE DB ? ;ORIGINAL SOURCE DRIVE +ORG_TARGET_DRIVE DB ? ;ORIGINAL TARGET DRIVE + +USER_OPTION DB 0 +COPY_TYPE DB 1 +START_BUFFER DW 0 +BUFFER_BEGIN DW 1000H ;BEGINNING OF BUFFER ADDR [IN SEGMENT] +BUFFER_END DW 3FF0H ;END OF BUFFER ADDR [IN SEGMENT] +USER_OPTION_8 DB ? +SECT_TRACK_LAYOUT DW 0 + +S_DRV_SECT_TRACK DB ? ;SECT/TRACK, device informations. +S_DRV_HEADS DB ? ;# OF HEADS +S_DRV_TRACKS DB ? ;# OF TRACKS +T_DRV_SECT_TRACK DB ? +T_DRV_HEADS DB ? +T_DRV_TRACKS DB ? + +;LOCAL VARIABLES: +FIRST_TIME DB 0 ;SWITCH TO ACTIVATE VOLSER CHECK ;AN000; +EXITFL DB EXOK ;ERRORLEVEL VALUE ;AN000; + PUBLIC EXITFL ; ;AN000; +EXCBR EQU 2 ;CONTROL-BREAK REQUESTED TERMINATION ;AN000; +EXVER EQU 1 ;BAD DOS VERSION ERRORLEVEL CODE ;AN000; +EXPAR EQU 1 ;ERROR IN INPUT PARMS IN COMMAND LINE ;AN000; +EXOK EQU 0 ;NORMAL ERRORLEVEL RET CODE ;AN000; + PUBLIC EXPAR ; ;AN000; + +IOCTL_SECTOR DW 1 ;used for READ_A_SECTOR routine. +IOCTL_TRACK DW 0 ;IN THE TRACK +IOCTL_HEAD DW 0 ;HEAD 0 +SAV_CSECT DW 0 ;TEMPORARY SAVING PLACE + +BOOT_SECT_TRACK DW 0 ;TEMP SAVING PLACE OF SECTOR/TRACK +BOOT_TOT_TRACK DW 0 ;FOUND FROM THE BOOT SECTOR. max # of tracks +BOOT_NUM_HEAD DW 0 ;NUMBER OF HEADS +BOOT_BYTE_SECTOR DW 0 ;BYTES / SECTOR + +READ_S_BPB_FAILURE DB 0 ;GET MEDIA BPB. SUCCESS=0, FAILURE=1 +READ_T_BPB_FAILURE DB 0 + +;*** Informations gotten from CHECK_SOURCE. +;*** These will be used as a basis for the comp process. +LAST_TRACK DB 79 ;LAST CYLINDER OF THE DASD (39 OR 79) +END_OF_TRACK DB 15 ;END OF TRACK +bSECTOR_SIZE DW 512 ;BYTES/SECTOR in bytes +NO_OF_SIDES DB ? ;0=SINGLE SIDED, 1=DOUBLE SIDED + +TRACK_TO_READ DB 0 +TRACK_TO_COMP DB 0 +TRACK_SIZE DW 0 ;BYTES/CYLINDER [IN SEGMENTS] +SECTOR_SIZE DB 0 ;BYTES/SECTOR [IN SEGMENTS] +BYTES_IN_TRACK DW ? ;BYTES/ONE SIDE TRACK (USED IN COMP_TRACK) +BUFFER_PTR DW ? +COMP_ERROR DB 0 +SIDE DB ? +OPERATION DB ? +COMP_STATUS DB ? +USER_INPUT DB ? ;DISKCOMP AGAIN? +SEC_BUFFER DW ? ;SECONDARY BUFFER SEG ADDR +COMPARE_PTR DW ? ;COMPARE POINTER +IO_ERROR DB 0 ;USED TO INDICATE IF READ/WRITE ERROR MESSAGE +MSG_FLAG DB ? +S_DRV_SET_FLAG DB 0 ;SOURCE DEVICE PARM HAS BEEN SET? +T_DRV_SET_FLAG DB 0 + +;--------------------------------------- +;DEVICE PARAMETER TABLE +;the returned info. still has the following format. + +DS_IOCTL_DRV_PARM LABEL BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM +DS_specialFunctions db ? +DS_deviceType db ? ;0=5.25, 1=5.25 96 TPI, 2=3.5" 720 KB + ;3=8" SINGLE, 4=8" DOUBLE, 5=HARD DISK +DS_deviceAttributes dw ? ;0001h - NOT REMOVABLE, 0002h - CHANGE + ; LINE SUPPORTED +DS_numberOfCylinders dw ? +DS_mediaType db ? +DS_BPB_PTR LABEL BYTE +DS_deviceBPB my_bpb <> +DS_trackLayout LABEL WORD ; ;AC000; + my_trackLayout ; ;AC000; +;--------------------------------------- + +DT_IOCTL_DRV_PARM LABEL BYTE +DT_specialFunctions db ? +DT_deviceType db ? ;0=5.25, 1=5.25 96 TPI, 2=3.5" 720 KB + ;3=8" SINGLE, 4=8" DOUBLE, 5=HARD DISK +DT_deviceAttributes dw ? ;0001h - NOT REMOVABLE, 0002h - CHANGE + ; LINE SUPPORTED +DT_numberOfCylinders dw ? +DT_mediaType db ? +DT_BPB_PTR LABEL BYTE +DT_deviceBPB my_bpb <> +DT_trackLayout LABEL WORD ; ;AC000; + my_trackLayout ; ;AC000; + +;--------------------------------------- + +MS_IOCTL_DRV_PARM LABEL BYTE ;DRIVE PARM FROM SOURCE MEDIUM +MS_specialFunctions db ? +MS_deviceType db ? ;0=5.25, 1=5.25 96 TPI, 2=3.5" 720 KB + ;3=8" SINGLE, 4=8" DOUBLE, 5=HARD DISK +MS_deviceAttributes dw ? ;0001h - NOT REMOVABLE, 0002h - CHANGE + ; LINE SUPPORTED +MS_numberOfCylinders dw ? +MS_mediaType db ? +MS_BPB_PTR LABEL BYTE +MS_deviceBPB my_bpb <> +MS_deviceBPB_leng equ $-MS_deviceBPB +MS_trackLayout LABEL WORD ; ;AC000; + my_trackLayout ; ;AC000; +;--------------------------------------- +MT_IOCTL_DRV_PARM LABEL BYTE ;DRIVE PARM FROM TARGET MEDIUM +MT_specialFunctions db ? +MT_deviceType db ? ;0=5.25, 1=5.25 96 TPI, 2=3.5" 720 KB + ;3=8" SINGLE, 4=8" DOUBLE, 5=HARD DISK +MT_deviceAttributes dw ? ;0001h - NOT REMOVABLE, 0002h - CHANGE + ; LINE SUPPORTED +MT_numberOfCylinders dw ? +MT_mediaType db ? +MT_BPB_PTR LABEL BYTE +MT_deviceBPB my_bpb <> +MT_trackLayout LABEL WORD ; ;AC000; + my_trackLayout ; ;AC000; + +;IOCTL read/write a track. +IOCTL_R_W LABEL BYTE +specialFunctions db 0 +Head dw ? +Cylinder dw ? +FirstSectors dw ? +numberOfSectors dw ? +TAddress_off dw ? +TAddress_seg dw ? + +;(deleted ;AN011;) MEDIA_ID_BUFFER A_MEDIA_ID_INFO <> ;BUFFER FOR GET/SET MEDIA ID ;AN000; + PATHLABL DISKCOMP ;AN013; + HEADER ; ;AN000; + PUBLIC DISKCOMP_BEGIN ; ;AN000; +DISKCOMP_BEGIN LABEL BYTE +;***************************************************************************** +; * +; D I S K C O M P M A I N P R O G R A M * +; * +;***************************************************************************** + +; $salut (4,4,10,36) ; ;AN000; +BEGIN PROC NEAR + PUBLIC BEGIN ; ;AN000; +;OUTPUT - "EXITFL" HAS ERRORLEVEL RETURN CODE + + MOV SP, OFFSET MY_STACK_PTR ;MOVE SP TO MY STACK AREA + CALL SYSLOADMSG ;INIT SYSMSG HANDLER ;AN000; + +; $IF C ;IF THERE WAS A PROBLEM ;AN000; + JNC $$IF1 + CALL SYSDISPMSG ;LET HIM SAY WHY HE HAD A PROBLEM ;AN000; + + MOV EXITFL,EXVER ;TELL ERRORLEVEL BAD DOS VERSION ;AN000; +; $ELSE ;SINCE SYSDISPMSG IS HAPPY ;AN000; + JMP SHORT $$EN1 +$$IF1: + CALL INIT ;RUN INITIALIZATION ROUTINE + + CMP DX,FINE ;CHECK FOR ERROR DURING INIT +; $IF E ;IF NO ERROR THEN PROCEED TO COMP + JNE $$IF3 +; $DO +$$DO4: + CALL COMP ;PERFORM DISKCOMP + + CALL TEST_REPEAT ;COMP ANOTHER ? + +; $ENDDO C + JNC $$DO4 + ;NORMAL RETURN CODE ALREADY IN "EXITFL" +; $ELSE ;ELSE IF ERROR DETECTED IN INIT + JMP SHORT $$EN3 +$$IF3: + MOV DI,DX ;PASS NUMBER OF ERROR MSG, IF ANY ;AD000; + ;DI HAS OFFSET OF MESSAGE DESCRIPTOR + CALL SENDMSG ;DISPLAY THE ERROR MESSAGE ;AC000; + + MOV EXITFL,EXVER ;ERROR RETURN CODE ;AC000; +; $ENDIF +$$EN3: + JMP SHORT EXIT_TO_DOS + +MAIN_EXIT: ;COME HERE AFTER CONTROL-BREAK + MOV EXITFL,EXCBR ; FOR CONTROL-BREAK EXIT ;AC000; + +EXIT_TO_DOS: + XOR BX, BX + + MOV BL, S_OWNER_SAVED ;RESTORE ORIGINAL SOURCE, + ; TARGET DRIVE OWNER. + CALL SET_LOGICAL_DRIVE + + MOV BL, T_OWNER_SAVED + CALL SET_LOGICAL_DRIVE + + CMP S_DRV_SET_FLAG, 0 +; $IF NE ; ;AN000; + JE $$IF8 + MOV BL, S_OWNER_SAVED + MOV DS_specialFunctions, SET_SP_FUNC_DOS ;=0 + MOV DX, OFFSET DS_IOCTL_DRV_PARM + CALL SET_DRV_PARM_DEF ;RESTORE SOURCE DRIVE PARM + +; $ENDIF ; ;AN000; +$$IF8: + + CMP T_DRV_SET_FLAG, 0 +; $IF NE ; ;AN000; + JE $$IF10 + MOV BL, T_OWNER_SAVED + MOV DT_specialFunctions, SET_SP_FUNC_DOS ;=0 + MOV DX, OFFSET DT_IOCTL_DRV_PARM + CALL SET_DRV_PARM_DEF ;RESTORE TARGET DRIVE PARM + +; $ENDIF ; ;AN000; +$$IF10: +EXIT_PROGRAM: + MOV AL,EXITFL ;PASS ERRORLEVEL RET CODE ;AN000; +; $ENDIF ;OK WITH SYSDISPMSG? ;AN000; +$$EN1: + MOV AL,EXITFL ;PASS BACK ERRORLEVEL RET CODE ;AN000; + DOSCALL RET_CD_EXIT ;RETURN TO DOS WITH RET CODE ;AN000; + + INT 20H ;IF ABOVE NOT WORK, ;AN000; +BEGIN ENDP ; ;AN000; +; = = = = = = = = = = = = = = = = = + HEADER ; ;AN000; +MORE_INIT PROC NEAR ; ;AN000; + RET ;RETURN TO CALLER ;AN000; +MORE_INIT ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; + PUBLIC SET_LOGICAL_DRIVE +;***************************************************************************** +SET_LOGICAL_DRIVE PROC NEAR +; *** SET THE LOGICAL DRIVE LETTER THAT WILL BE THE OWNER OF THE DRIVE +; INPUT: BL - DRIVE LETTER +; OUTPUT: OWNER WILL BE SET ACCORDINGLY. +;***************************************************************************** + CMP BL, 0 ;IS THIS DRIVE ZERO? + ;IF BL = 0, THEN JUST RETURN +; $IF NE + JE $$IF13 + DOSCALL IOCTL_FUNC,SET_LOG_DRIVE ; ;AC000; + ;SET BL AS AN OWNER OF THAT DRIVE +; $ENDIF +$$IF13: + RET +SET_LOGICAL_DRIVE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +COMP PROC NEAR +;***************************************************************************** + MOV AL,ORG_SOURCE_DRIVE ;INITIALIZE THE FIRST AND SECOND + MOV SOURCE_DRIVE,AL ;DRIVE IN THE ORDER THE USER + MOV AL,ORG_TARGET_DRIVE ;ENTERED ON THE COMMAND LINE + MOV TARGET_DRIVE,AL + MOV AX, RECOMMENDED_BYTES_SECTOR + MOV bSECTOR_SIZE, AX ;USE RECOMMENDED SECTOR SIZE + ; TO READ A SECTOR + MOV READ_S_BPB_FAILURE, 0 ;RESET GET BPB FAILURE FLAG + MOV READ_T_BPB_FAILURE, 0 + MOV COMP_ERROR,0 ;RESET COMPARE ERROR COUNT + MOV COMP_STATUS,OK ;RESET COMP STATUS BYTE + CMP COPY_TYPE,2 ;IF TWO DRIVE COMP +; $IF E + JNE $$IF15 + CALL DISPLAY_LOAD_FIRST ;"Insert FIRST diskette in drive %1:" ;AN000; + + CALL DISPLAY_LOAD_SECOND ;"Insert SECOND diskette in drive %1:" ;AN000; + + CALL PRESS_ANY_KEY ;"Press any key to continue . . ." ;AC009; + +; $ENDIF +$$IF15: + MOV TRACK_TO_READ,0 ;INITIALIZE TRACK NUMBERS + MOV TRACK_TO_COMP,0 + +COMP_TEST_END: + MOV AL,TRACK_TO_COMP ;WHILE TRACK_TO_COMP<=LAST_TRACK + CMP AL,LAST_TRACK + JA COMP_END + + CALL READ_SOURCE + + CMP COMP_STATUS,FATAL ;MAKE SURE DRIVES WERE COMPATIBLE + JE COMP_EXIT + + CALL COMP_TARGET + + CMP COMP_STATUS,FATAL ;MAKE SURE TARGET AND SOURCE + JE COMP_EXIT ;DISKETTES ARE COMPATIBLE + + JMP COMP_TEST_END + +COMP_END: + CMP COMP_ERROR,0 ;IF ERROR IN COMP +; $IF E ;WARN USER + JNE $$IF17 + PRINT MSGNUM_COMP_OK ;"Compare OK" ;AC000; + +;kiser note: this is a warning???? + +; $ENDIF +$$IF17: + +COMP_EXIT: + CMP COMP_STATUS,FATAL ;WAS COMP ABORTED ? +; $IF E + JNE $$IF19 + ;"Compare process ended" + PRINT MSGNUM_FATAL_ERROR ;IF SO THEN TELL USER ;AC000; + +; $ENDIF +$$IF19: + RET + +COMP ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +DISPLAY_LOAD_FIRST PROC NEAR ; ;AN000; + PUBLIC DISPLAY_LOAD_FIRST ; ;AN000; +; = = = = = = = = = = = = + + MOV SUBLIST_78.SUB_VALUE,OFFSET ASCII_DRV1_ID ;PASS CHAR DRIVE ID ;AN000; + ;"Insert FIRST diskette in drive %1:" + PRINT MSGNUM_LOAD_FIRST ;OUTPUT LOAD FIRST DISKETTE MESSAGE ;AC000; + + MOV MSG_FLAG,SECOND + RET ;RETURN TO CALLER ;AN000; +DISPLAY_LOAD_FIRST ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +DISPLAY_LOAD_SECOND PROC NEAR ; ;AN000; + PUBLIC DISPLAY_LOAD_SECOND ; ;AN000; +; = = = = = = = = = = = = + + MOV SUBLIST_78.SUB_VALUE,OFFSET ASCII_DRV2_ID ;PASS CHAR DRIVE ID ;AN000; + ;CR,LF,"Insert SECOND diskette in drive %1:",CR,LF + PRINT MSGNUM_LOAD_SECOND ;OUTPUT LOAD SECOND DISKETTE MESSAGE ;AC000; + + MOV MSG_FLAG,FIRST + RET ;RETURN TO CALLER ;AN000; +DISPLAY_LOAD_SECOND ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC TEST_REPEAT ;MAKE ENTRY IN LINK MAP ;AN000; +TEST_REPEAT PROC NEAR ;TEST IF USER WANTS TO COMP ANOTHER * +; DISKETTE * +; INPUT : USER_INPUT ("Y" OR "N") +; OUTPUT: NC = COMP AGAIN * +; CY = EXIT TO DOS * +;***************************************************************************** +; $SEARCH ;REPEAT THIS PROMPT UNTIL (Y/N) RESPONDED ;AC000; +$$DO21: + ;"Compare another diskette (Y/N)?" + PRINT MSGNUM_COMP_ANOTHER ;SEE IF USER WANTS TO COMPARE ANOTHER ;AC000; + ; AND READ RESPONSE TO AL + PUSH AX ;SAVE THE RESPONSE ;AN000; + PRINT MSGNUM_NEWLINE ;CR,LF,LF ;AC000; + + POP DX ;RESTORE THE REPONSE CHAR TO DL ;AN000; + CALL YESNO ;CHECK FOR (Y/N) ;AN000; + +; $EXITIF C,NUL ;QUIT IF OK ANSWER ;AN000; + JC $$SR21 + CMP AL,BAD_YESNO ;WAS THE RESPONSE INVALID? ;AN000; +; $ENDLOOP B ;QUIT IF OK ANSWER (AX=0 OR 1) ;AN000; + JNB $$DO21 + CMP AL,YES ;WAS "YES" SPECIFIED ;AN000; +; $IF E ;IF "YES" ;AN000; + JNE $$IF24 + MOV FIRST_TIME,ZERO ;SET UP TO DO ANOTHER VOLSER CHECK ;AN000; + CLC ;CLEAR CARRY TO INDICATE COMPARE AGAIN ;AN000; +; $ELSE ;SINCE NOT "YES" ;AN000; + JMP SHORT $$EN24 +$$IF24: + STC ;SET CARRY TO INDICATE NO REPEAT ;AN000; +; $ENDIF ; ;AN000; +$$EN24: +; $ENDSRCH ; ;AN000; +$$SR21: + RET + +TEST_REPEAT ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC READ_SOURCE ;MAKE ENTRY IN LINK MAP ;AN000; +READ_SOURCE PROC NEAR ;FILL ALL AVAILABLE MOMORY WITH SOURCE DATA +; * +;***************************************************************************** + + CMP TRACK_TO_READ,0 ;1ST TRACK ? +; $IF E ;IF SO + JNE $$IF28 + CMP COPY_TYPE,1 ;IF SINGLE DRIVE COMP +; $IF E ;PROMPT MSG + JNE $$IF29 + CALL DISPLAY_LOAD_FIRST ;"Insert FIRST diskette in drive %1:" ;AN000; + + CALL PRESS_ANY_KEY ;"Press any key to continue . . ." ;AC000; + +; $ENDIF +$$IF29: + CALL CHECK_SOURCE ;DO NECESSARY CHECKING + + CALL CALC_TRACK_SIZE + + CALL CHECK_MEMORY_SIZE + + CMP COMP_STATUS,FATAL + JE RS_EXIT + +; $ENDIF +$$IF28: + MOV BX,BUFFER_BEGIN + MOV BUFFER_PTR,BX ;INITIALIZE BUFFER POINTER + +; $DO +$$DO32: + MOV AL,TRACK_TO_READ ;DID WE FINISH READING ALL TRACKS? + CMP AL,LAST_TRACK +; $LEAVE A + JA $$EN32 + + MOV AX,BUFFER_PTR ;DID WE RUN OUT OF BUFFER SPACE + ADD AX,TRACK_SIZE + CMP AX,BUFFER_END +; $LEAVE A + JA $$EN32 + + CALL READ_TRACK ;NO, GO READ ANOTHER TRACK + + INC TRACK_TO_READ +; $ENDDO + JMP SHORT $$DO32 +$$EN32: + +RS_EXIT: + RET + +READ_SOURCE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC CHECK_SOURCE ;MAKE ENTRY IN LINK MAP ;AN000; +CHECK_SOURCE PROC NEAR ;CHECK SOURCE DISKETTE TYPE * +; SET END_OF_TRACK, LAST_TRACK * +; NO_OF_SIDES, bSECTOR_SIZE * +; ** this routine will call "Get dev parm" with "BUILD BPB BIT" on. If it * +; ** fails to get that info, then the source medium must be bad(vergin) or * +; ** below DOS 2.0 level diskette, and will jmp to the old logic. * +; ** For compatibility reasons (in case of non IBM formatted media), this * +; ** routine covers old diskcopy routines. But this will only supports +; ** 5.25" 48 tpi 8, 9 sectors, 40 tracks and 5.25" 96 tpi, 15 sectors, 80 tracks +; ** media. Other non IBM formatted media which are formatted differenty +; ** from those values will result in unpreditable copy process. +;***************************************************************************** + +CS_AGAIN: + XOR BX, BX + MOV BL, SOURCE_DRIVE + MOV MS_specialFunctions, GET_SP_FUNC_MED ;=00000001b + MOV CL, GETDEVPARM ;=60h + MOV DX, OFFSET MS_IOCTL_DRV_PARM + CALL GENERIC_IOCTL ;TRY TO GET MEDIA BPB INFO TOGETHER + ;WITH DEFAULT DEVICE INFO. + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? + JE CS_AGAIN + + CMP IO_ERROR, HARD_ERROR ;CANNOT GET MEDIA BPB? + JNE CS_NEW ; ;AC000; +CS_OLD_BRIDGE: + JMP CS_OLD ;ASSUME OLD FORMATTED DISKETTE, FIRST. ;AC000; +CS_NEW: ; ;AN000; + cmp ms_deviceBPB.csect_track,0 ;patch 1/16/86 J.K. + je cs_old_BRIDGE + + cmp ms_deviceBPB.chead,0 ;cannot trust the info. from DOS. + je cs_old ;sanity check for devide by 0. + + MOV AX, MS_deviceBPB.CTOTSECT + CWD ;CONVERT IT TO A DOUBLE WORD + DIV MS_deviceBPB.CSECT_TRACK + DIV MS_deviceBPB.CHEAD ;(TOTAL SECTORS / # OF TRACKS) / # OF HEADS + CMP AL, T_DRV_TRACKS ;IF # OF TRACKS FOR SOURCE MEDIA > # OF + ; TRACKS FOR TARGET DEVICE + JA CS_FATAL ;THEN, NOT COMPATIBLE + + DEC AX ;DECREASE BY 1 FOR THIS PROGRAM'S USE. + MOV LAST_TRACK, AL ;SET LAST_TRACK + MOV AX, MS_deviceBPB.CSECT_TRACK + MOV SECT_TRACK_LAYOUT, AX ;VARIABLE FOR MS, MT_trackLayout.CSECT_F + CMP USER_OPTION_8, ON ;/8 OPTION SPECIFIED? + JNE CS_GO_ON + + CMP AX, 8 ;SOURCE MEDIA # OF SECTORS/TRACK < 8 ? + JB CS_FATAL ;IF IT IS, THEN FATAL ERROR. + + MOV AX, 8 ;ELSE SET IT TO 8 +CS_GO_ON: + CMP AL, T_DRV_SECT_TRACK + JA CS_FATAL + + MOV END_OF_TRACK, AL ;SET END_OF_TRACK + MOV AX, MS_deviceBPB.CBYTE_SECT + MOV bSECTOR_SIZE, AX ;set the sector size in bytes. + CMP USER_OPTION, 1 + JE CS_OPTION_1 + + MOV AX, MS_deviceBPB.CHEAD ;HEAD=1, 2 + CMP AL, T_DRV_HEADS ;COMPARE SOURCE MEDIA SIDE WITH TARGET + ; DRIVE HEAD NUMBER + JA CS_FATAL ;SOURCE MEDIUM IS DOUBLE SIDED AND + ; TARGET DRIVE IS SINGLE SIDED. + + DEC AX + MOV NO_OF_SIDES, AL ;NO_OF_SIDES=0, 1 + JMP CS_SET_TABLE + +CS_FATAL: + MOV COMP_STATUS, FATAL + ;"Drive types or diskette types" + ;"not compatible" + PRINT MSGNUM_NOT_COMPATIBLE ; ;AC000; + + JMP CS_EXIT + +CS_BAD: + MOV COMP_STATUS, FATAL + PRINT MSGNUM_BAD_FIRST ;"FIRST diskette bad or incompatible" ;AC000; + + JMP CS_EXIT + +CS_OLD: + + MOV READ_S_BPB_FAILURE, 1 ;SET FLAG + MOV bSECTOR_SIZE, 512 ;OLD SECTOR SIZE MUST BE 512 BYTES + XOR BX, BX + MOV BL, SOURCE_DRIVE + MOV IOCTL_TRACK, 0 ;TRACK=0 + MOV IOCTL_SECTOR, 8 ;SECTOR=8 + MOV IOCTL_HEAD, 0 ;HEAD = 0 + CALL READ_A_SECTOR + + JC CS_BAD ;SOURCE BAD + + MOV IOCTL_SECTOR, 9 ;TRY TO READ SECTOR=9 + CALL READ_A_SECTOR + + JC CS_SECT8 ;YES, 8 SECTORS. ASSUME 40 TRACKS + + MOV IOCTL_SECTOR, 15 ;try to read sector=15 + CALL READ_A_SECTOR + + JC CS_SECT9 ;**REMEMBER THIS ROUTINE DOES NOT COVER 3.5" MEDIA + + JMP CS_SECT15 + +CS_OPTION_1: + MOV NO_OF_SIDES, 0 ;1 SIDE COPY + JMP CS_SET_TABLE + +CS_SECT15: + MOV SECT_TRACK_LAYOUT, 15 ;VARIABLE FOR MS, MT_trackLayout.CSECT_F + MOV END_OF_TRACK, 15 ;ELSE END_OF_TRACK = 15 + MOV LAST_TRACK, 79 + JMP CS_OPTIONS + +CS_SECT8: + MOV SECT_TRACK_LAYOUT, 8 ;VARIABLE FOR MS, MT_trackLayout.CSECT_F + MOV END_OF_TRACK, 8 ;SOURCE 8 SECTORS + MOV LAST_TRACK, 39 ;ASSUME 40 TRACKS. + JMP CS_OPTIONS + +CS_SECT9: + MOV SECT_TRACK_LAYOUT, 9 ;VARIABLE FOR MS, MT_trackLayout.CSECT_F + MOV END_OF_TRACK, 9 + MOV LAST_TRACK, 39 ;ASSUME 5.25 DISKETTE +CS_OPTIONS: + CMP USER_OPTION_8, ON + JNE CS_CHK_SIDE + + MOV END_OF_TRACK, 8 +CS_CHK_SIDE: + CMP USER_OPTION, 1 + JE CS_OPTION_1 + + MOV IOCTL_HEAD, 1 ;HEAD 1 + XOR AX, AX + MOV AL, END_OF_TRACK ;READ MATCHING END_OF_TRACK + ; OF THE OTHER SURFACE. + MOV IOCTL_SECTOR, AX + CALL READ_A_SECTOR + + JC CS_OPTION_1 ;1 SIDED SOURCE + + MOV NO_OF_SIDES, 1 ;2 SIDED SOURCE + CMP T_DRV_HEADS, 2 ;SOUCE=2 SIDED MEDIUM. IS TARGET + ; DOUBLE SIDED DRV? + JE CS_SET_TABLE + + JMP CS_FATAL ;NOT COMPATIBLE + +CS_SET_TABLE: + CMP READ_S_BPB_FAILURE, 1 ;diskette without BPB info? + JNE CS_SET_TABLE_NEXT + + CALL SET_FOR_THE_OLD ;set deviceBPB info for before 2.0 level + +CS_SET_TABLE_NEXT: + MOV BX, OFFSET MS_trackLayout ;SET TRACKLAYOUT OF SOURCE + CALL SET_TRACKLAYOUT + + MOV S_DRV_SET_FLAG, 1 ;indicate SOURCE DRIVE + ; PARAMETER HAS BEEN SET + XOR BX, BX + MOV BL, SOURCE_DRIVE + MOV DX, OFFSET MS_IOCTL_DRV_PARM + MOV MS_specialFunctions, SET_SP_FUNC_DEF + CALL SET_DRV_PARM_DEF ;set device parameter for read + + XOR AX, AX + MOV AL, END_OF_TRACK + MOV numberOfSectors, AX ;SET NUMBEROFSECTORS IN IOCTL_R_W TABLE + + MOV AL, LAST_TRACK ;NOW, SHOW THE MESSAGE "COMPARING ..." + INC AL + MOV BYTE PTR MSG_TRACKS,AL ;HOW MANY TRACKS? ;AC000; + + MOV AL, END_OF_TRACK + MOV BYTE PTR MSG_SECTRK,AL ;HOW MANY SECTORS? ;AC000; + + MOV AL, NO_OF_SIDES ;TELL USER HOW MANY SIDE TO COPY + INC AL + MOV BYTE PTR MSG_SIDES,AL ; ;AC000; + ;CR,LF,"Comparing %1 tracks",CR,LF + ;"%2 Sectors/Track, %3 Side(s)",CR,LF + PRINT MSGNUM_COMPARING ; ;AC000; + +CS_EXIT: + RET + +CHECK_SOURCE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC READ_A_SECTOR ;MAKE ENTRY IN LINK MAP ;AN000; +READ_A_SECTOR PROC NEAR +; +;TRY TO READ A SECTOR USING IOCTL READ FUNCTION CALL. +;THIS ROUTINE WILL STEAL "IOCTL_R_W" TABLE TEMPORARILY. +;INPUT: BX - LOGICAL DRIVE NUMBER +; IOCTL_SECTOR - SECTOR TO READ +; IOCTL_TRACK - TRACK +; IOCTL_HEAD - HEAD TO READ +; bSECTOR_SIZE - SECTOR SIZE IN BYTES +;OUTPUT: +; IF NOT A SUCCESS, CARRY WILL BE SET +; ALL REGISTORS SAVED +;***************************************************************************** + PUSH AX + PUSH BX + PUSH CX + PUSH DX + + MOV AX, numberOfSectors ;SAVE IOCTL_R_W TABLE VALUES + MOV SAV_CSECT, AX + +; $DO +$$DO36: + MOV AX, IOCTL_HEAD + MOV Head, AX ;SURFACE TO READ + MOV AX, IOCTL_TRACK + MOV Cylinder, AX ;TRACK TO READ + MOV AX, IOCTL_SECTOR + dec ax ;????? currently firstsector=0 => + ; 1st sector ???? + MOV FirstSectors, AX ;SECTOR TO READ + MOV numberOfSectors, 1 ;read just one sector + MOV AX, offset INIT ;READ IT INTO INIT (CURRELTLY, MAX 1K) + MOV TAddress_off, AX + MOV TAddress_seg, DS + MOV CL, READ_FUNC + MOV DX, OFFSET IOCTL_R_W ;POINTS TO CONTROL TABLE + call generic_ioctl + + CMP IO_ERROR, SOFT_ERROR ;TRY ONCE MORE? +; $ENDDO NE + JE $$DO36 + + CMP IO_ERROR, HARD_ERROR ;HARD ERROR? +; $IF NE + JE $$IF38 + + CLC ;READ SUCCESS +; $ELSE + JMP SHORT $$EN38 +$$IF38: + + STC ;READ FAILURE, SET CARRY +; $ENDIF +$$EN38: + MOV AX, SAV_CSECT ;RESTORE ORIGINAL IOCTL_R_W TABLE + MOV numberOfSectors, AX + POP DX + POP CX + POP BX + POP AX + RET +READ_A_SECTOR ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC CALC_TRACK_SIZE ;MAKE ENTRY IN LINK MAP ;AN000; +CALC_TRACK_SIZE PROC NEAR ;CALCULATE MEMORY SIZE REQUIRED TO STORE ONE +; TRACK (IN SEGMENTS) * +;CALCULATE SECTOR_SIZE IN PARA FROM bSECTOR_SIZE. IF bSECTOR_SIZE CANNOT BE +;CHANGED TO SECTOR_SIZE IN PARA EXACTLY, THEN ADD 1 TO THE SECTOR_SIZE. +;SECTOR_SIZE IS USED FOR MEMORY MANAGEMANT ONLY. THE ACTUAL COPY OR FORMAT +;SHOULD BE DEPENDS ON bSECTOR_SIZE TO FIGURE OUT HOW BIG A SECTOR IS. +;ALSO, CURRENTLY, THIS ROUTINE ASSUME A BSECTOR SIZE BE LESS THAN 0FFFh. +;***************************************************************************** + + PUSH AX + PUSH BX + PUSH CX + + MOV AX, bSECTOR_SIZE + XOR DX, DX + XOR BX, BX + MOV BL, END_OF_TRACK + MUL BX ;ASSUME DX=0 + MOV BYTES_IN_TRACK,AX ;BYTES/TRACK ON A SIDE OF THE DISKETTE + + MOV AX, bSECTOR_SIZE + MOV CL, 16 + DIV CL ;AX / 16 = AL ... AH + CMP AH, 0 ;NO REMAINER? +; $IF NE + JE $$IF41 + + INC AL ;THERE REMAINER IS. INC AL +; $ENDIF +$$IF41: + MOV SECTOR_SIZE, AL ;SECTOR_SIZE+ IN PARA. + MOV AL,NO_OF_SIDES ;TRACK_SIZE = (NO OF SIDES + INC AL ; + 1) + MUL END_OF_TRACK ; * END_OF_TRACK + MOV BL,SECTOR_SIZE ; * SECTPR_SIZE + MUL BL ;AMOUNT OF MEMORY REQUIRED (IN SEG) + MOV TRACK_SIZE,AX ;TO STORE A TRACK + + MOV BX,START_BUFFER ;SET SECONDARY AT START OF BUFFER SPACE + MOV SEC_BUFFER,BX ;SET THE SECONDARY BUFFER SEG ADDR + ADD BX,AX ;MOVE THE PRIMARY BUFFER BELOW THE + MOV BUFFER_BEGIN,BX ;SECONDARY BUFFER + POP CX + POP BX + POP AX + + RET + +CALC_TRACK_SIZE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC CHECK_MEMORY_SIZE ;MAKE ENTRY IN LINK MAP ;AN000; +CHECK_MEMORY_SIZE PROC NEAR ;MAKE SURE WE HAVE ENOUGH TO COMP 1 TRACK INTO +; TO BUFFER ELSE ABORT COMP * +;***************************************************************************** + MOV AX,BUFFER_END + SUB AX,BUFFER_BEGIN + CMP AX,TRACK_SIZE +; $IF B + JNB $$IF43 + MOV COMP_STATUS,FATAL + ;"Insufficient memory" + PRINT MSGNUM_UNSUF_MEMORY ; ;AC000; + +; $ENDIF +$$IF43: + RET + +CHECK_MEMORY_SIZE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC COMP_TARGET ;MAKE ENTRY IN LINK MAP ;AN000; +COMP_TARGET PROC NEAR ;COMPARE DATA FROM MEMORY TO TARGET DISKETTE +; * +;***************************************************************************** + + CMP COPY_TYPE,1 ;IF SINGLE DRIVE COMP +; $IF E ;PROMPT MSG + JNE $$IF45 + CMP MSG_FLAG,SECOND +; $IF E + JNE $$IF46 + CALL DISPLAY_LOAD_SECOND ;"Insert SECOND diskette in drive %1:" ;AN000; + +; $ELSE + JMP SHORT $$EN46 +$$IF46: + CALL DISPLAY_LOAD_FIRST ;"Insert FIRST diskette in drive %1:" ;AN000; + +; $ENDIF +$$EN46: + CALL PRESS_ANY_KEY ;"Press any key to continue . . ." ;AC009; + +; $ENDIF +$$IF45: + MOV BX,BUFFER_BEGIN + MOV COMPARE_PTR,BX ;INITIALIZE BUFFER POINTER + CMP TRACK_TO_COMP,0 ;IF TRK 0, CHECK COMPATIBILITY +; $IF E + JNE $$IF50 + CALL CHECK_TARGET + + CMP COMP_STATUS,FATAL ;IF INCOMPATIBLE, THEN EXIT + JE CT_EXIT + +; $ENDIF +$$IF50: + + CALL SWAP_DRIVE + +; $DO +$$DO52: + CALL COMP_TRACK ;NO, GO READ ANOTHER TRACK + + INC TRACK_TO_READ + MOV AL,TRACK_TO_READ ;DID WE FINISH READING ALL TRACKS? + CMP AL,LAST_TRACK +; $LEAVE A + JA $$EN52 + + MOV AX,COMPARE_PTR ;DID WE RUN OUT OF BUFFER SPACE + ADD AX,TRACK_SIZE + CMP AX,BUFFER_END +; $ENDDO A + JNA $$DO52 +$$EN52: + +CT_EXIT: + RET +COMP_TARGET ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC CHECK_TARGET ;MAKE ENTRY IN LINK MAP ;AN000; +CHECK_TARGET PROC NEAR ; * +; ** CHECK_SOURCE PROCEDURE ALREADY CHECKS OUT THE INCOMPATIBILITY BETWEEN * +; ** SOURCE MEDIA AND TARGET DRIVE. (CHECKING SOURCE MEDIA SECTOR/TRACK * +; ** EXCEEDS TARGET DRV SECTOR/TRACK, AND SOURCE MEDIA # OF TRACKS WITH * +; ** THAT OF TARGET DRV.) * +; ** THIS ROUTINE WILL TRY TO READ TARGET MEDIA BOOT RECORD. * +; ** IF A SUCCESS,THEN COMPARE BPB INFO WITH THAT OF SOURCE MEDIA. * +; ** IF THEY ARE DIFFERENT, THEN ERROR - NOT COMPATIBLE * +; ** IF FAILED TO READ A BOOT, THEN TRY OLD LOGICS BEFORE DOS 3.2 FOR * +; ** COMPATIBILITY REASONS. * +;***************************************************************************** +; $DO +$$DO55: + XOR BX, BX + MOV BL, TARGET_DRIVE + MOV MT_specialFunctions, GET_SP_FUNC_MED ;=00000001b + MOV CL, GETDEVPARM + MOV DX, OFFSET MT_IOCTL_DRV_PARM + CALL GENERIC_IOCTL ;TRY TO GET MEDIA BPB INFO TOGETHER + ;WITH THE DEFAULT DEVICE INFO. + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? +; $ENDDO NE + JE $$DO55 + + CMP IO_ERROR, HARD_ERROR ;ASSUME OLD DISKTETTE. OR DISKETTE BAD + JE CHT_OLD + + cmp mt_deviceBPB.csect_track,0 ;patch 1/16/86, J.K. + je cht_old + + cmp mt_deviceBPB.chead,0 ;cannot trust the info from DOS. + je cht_old ;sanity check for devide by 0 + + MOV AX, MT_deviceBPB.CTOTSECT + CWD ;CONVERT IT TO A DOUBLE WORD + DIV MT_deviceBPB.CSECT_TRACK + DIV MT_deviceBPB.CHEAD ;(TOTAL SECTORS / # OF TRACKS) / # OF HEADS + DEC AX ;DECREASE BY 1 FOR THIS PROGRAM + CMP LAST_TRACK, AL ;COMPARE WITH SOURCE LAST TRACK + JNE CHT_FATAL_BRIDGE ;IF LAST_TRACK IS DIFFERENT, + ; THEN INCOMPATIBLE. + + MOV AX, MT_deviceBPB.CSECT_TRACK + MOV SECT_TRACK_LAYOUT, AX ;VARIBLE FOR MT_trackLayout.CSECT_F +CHT_GO_ON: + CMP END_OF_TRACK, AL + JA CHT_FATAL_BRIDGE ;IF SOURCE END_OF_TRACK > TARGET + ; END_OF_TRACK, THEN ERROR + + ;8 SECTORED SOURCE AND 9 SECTORED TARGET + ; IS OK AS FAR AS THE COMPATIBILITY GOES. + MOV AX, MT_deviceBPB.CBYTE_SECT + CMP AX, bSECTOR_SIZE ;IF SECTOR SIZE ARE DIFFERENT, THEN + ; NOT COMPATIBLE + JNE CHT_FATAL_BRIDGE + + CMP NO_OF_SIDES, 1 ;TWO SIDED COPY? + JNE CHT_SET_BRIDGE ;NO, ONE SIDED. DON'T + ; CARE ABOUT TARGET SIDES. + + CMP MT_deviceBPB.CHEAD, 2 ;TARGET FORMATTED INTO TWO SIDES? + JNE CHT_FATAL_BRIDGE ;NO, NOT COMPATIBLE + + JMP CHT_SET_DRV ;OK. SOURCE, TARGET MEDIA ARE MATCHING. SET + ; DRV PARM FOR READING + +CHT_SET_BRIDGE: + JMP CHT_SET_DRV + +CHT_FATAL_BRIDGE: + JMP CHT_FATAL + +CHT_SECOND_BAD: + MOV COMP_STATUS, FATAL + PRINT MSGNUM_BAD_SECOND ;"SECOND diskette bad or incompatible" ;AC000; + + JMP CHT_EXIT + +CHT_OLD: ;SAME OLD. ;AGAIN, THIS DOES + ; NOT RECOGNIZE 3.5 MEDIA + MOV READ_T_BPB_FAILURE, 1 ;SET THE FLAG. + XOR BX, BX + MOV BL, TARGET_DRIVE + MOV IOCTL_TRACK, 0 + MOV IOCTL_SECTOR, 8 + MOV IOCTL_HEAD, 0 ;TRY TO READ HEAD 0, TRACK 0, SECTOR 8 + CALL READ_A_SECTOR + + JC CHT_SECOND_BAD ;ASSUME TARGET MEDIA NOT FORMATTED. + + MOV IOCTL_SECTOR, 9 ;TRY TO READ SECTOR 9 + CALL READ_A_SECTOR + + JC CHT_8_SECTOR ;TARGET IS 8 SECTOR MEDIA + + MOV IOCTL_SECTOR, 15 + CALL READ_A_SECTOR + + JC CHT_9_SECTOR ;TARGET IS 9 SECTOR MEDIA + +;CHT_15_SECTOR: ;TARGET IS 15 SECTOR MEDIA + MOV SECT_TRACK_LAYOUT, 15 + CMP END_OF_TRACK, 15 ;IS SOUCE ALSO 96 TPI? + JNE CHT_FATAL ;NO, FATAL ERROR + + JMP SHORT CHT_CHK_SIDE ;YES, OK. + +CHT_8_SECTOR: + MOV SECT_TRACK_LAYOUT, 8 + CMP END_OF_TRACK, 15 + JE CHT_FATAL ;IF SOURCE IS 96 TPI, THEN FATAL ERROR + + CMP END_OF_TRACK, 9 + JE CHT_FATAL ;IF SOURCE IS 9 SECTOR, THEN + ; SHOULD FORMAT TARGET + + JMP SHORT CHT_CHK_SIDE ;ELSE ASSUME SOURCE IS 8 SECTOR. + +CHT_9_SECTOR: + MOV SECT_TRACK_LAYOUT, 9 + CMP END_OF_TRACK, 15 ;IS SOURCE 96 TPI? THEN ERROR + JE CHT_FATAL ;ELSE SOUCE IS 8 OR 9 SECTORED + ; 48 TPI DISKETTE + +CHT_CHK_SIDE: ;CHECK THE TARGET DISKETTE # OF SIDES + CMP NO_OF_SIDES, 0 ;1 SIDE COMP? + JE CHT_EXIT_OLD ; + + MOV IOCTL_HEAD, 1 ;ELSE TWO SIDE COMP + XOR AX, AX + MOV AL, END_OF_TRACK ;TRY TO READ MATCHING TARGET SECTOR + MOV IOCTL_SECTOR, AX ;OF THE OTHERSIDE + CALL READ_A_SECTOR + + JNC CHT_EXIT_OLD ;SUCCESS? OK + +CHT_FATAL: + CALL COMPAT_ERROR + + JMP SHORT CHT_EXIT + +CHT_EXIT_OLD: + CALL SET_FOR_THE_OLD ;SET MT_deviceBPB INFO. + +CHT_SET_DRV: + MOV BX, OFFSET MT_trackLayout ;SET TARGET TRACK LAYOUT + CALL SET_TRACKLAYOUT + + JC CHT_FATAL ;IF FAILED, THEN, NOT COMPATIBLE + + MOV T_DRV_SET_FLAG, 1 ;INDICATES THE TARGET DEFAULT + ; DEVICE PARM HAS BEEN SET + XOR BX, BX + mov bl, last_track ;To make sure the number of + ; cyl. of target. 3/27/86,J.K. + inc bl + mov MT_numberOfCylinders, bx + MOV BL, TARGET_DRIVE + MOV DX, OFFSET MT_IOCTL_DRV_PARM + MOV MT_specialFunctions, SET_SP_FUNC_DEF + CALL SET_DRV_PARM_DEF + +CHT_EXIT: + RET + +CHECK_TARGET ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC SET_DRV_PARM_DEF ;MAKE ENTRY IN LINK MAP ;AN000; +SET_DRV_PARM_DEF PROC NEAR +;INPUT: BL - DRIVE NUMBER +; DX - POINTER TO THE PARAMETER TABLE +; specialFunction should be set before this call +;***************************************************************************** + + MOV CL, SETDEVPARM ;=40H + CALL GENERIC_IOCTL + + RET + +SET_DRV_PARM_DEF ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC COMP_TRACK ;MAKE ENTRY IN LINK MAP ;AN000; +COMP_TRACK PROC NEAR ;COMPARE TRACK SPECIFIED IN TRACK_TO_COMP +; * +;***************************************************************************** + MOV AX,SEC_BUFFER ;READ IN THE TRACK TO BE COMPARED + MOV BUFFER_PTR,AX ;INTO THE SECONDARY BUFFER + CALL READ_TRACK + + MOV SIDE,0 ;START ON SIDE ZERO + MOV CX,BYTES_IN_TRACK ;GET NUMBER TO COMPARE + PUSH DS + PUSH ES + MOV ES,COMPARE_PTR ;SET DESTINATION SEG ADDR + MOV DS,SEC_BUFFER ;SET SOURCE SEG ADDR + + ASSUME ES:NOTHING + ASSUME DS:NOTHING + + XOR DI,DI ;SET TO START OF TRACK + XOR SI,SI + CMP FIRST_TIME,ZERO ;IF THIS IS THE FIRST SECTOR TO BE COMPARED ;AN000; +; $IF E ; ;AN000; + JNE $$IF57 + CALL VOLSER ;SPECIAL HANDLING FOR VOL SER # ;AN000; + + MOV FIRST_TIME,ONE ;FLAG FIRST TIME AS "DONE" ;AN000; +; $ENDIF ; ;AN000; +$$IF57: + CALL DO_COMPARE ;COMPARE STRING ;AN000; + + POP ES + POP DS + + ASSUME ES:CSEG + ASSUME DS:CSEG + +; $IF NZ + JZ $$IF59 + PUSH AX ;SAVE AX SINCE ERROR_MESSAGE WILL DESTROY IT + MOV OPERATION,COMPARE_FUNC + CALL ERROR_MESSAGE + + INC COMP_ERROR + POP AX +; $ENDIF +$$IF59: + CMP NO_OF_SIDES,1 ;TWO SIDED COMPARE? +; $IF E ;YES + JNE $$IF61 + MOV SIDE,1 ;MARK IT AS SUCH + MOV SI,BYTES_IN_TRACK ;BUMP UP BUFFER POINTERS + MOV DI,BYTES_IN_TRACK ;TO START OF SECOND SIDE + MOV CX,BYTES_IN_TRACK ;GET NUMBER TO COMPARE + PUSH DS + PUSH ES + MOV ES,COMPARE_PTR ;SET DESTINATION SEG ADDR + MOV DS,SEC_BUFFER ;SET SOURCE SEG ADDR + CALL DO_COMPARE ;COMPARE STRING ;AN000; + + POP ES + POP DS +; $IF NZ + JZ $$IF62 + PUSH AX ;SAVE AX SINCE ERROR_MESSAGE WILL DESTROY IT + MOV OPERATION,COMPARE_FUNC + CALL ERROR_MESSAGE + + INC COMP_ERROR + POP AX +; $ENDIF +$$IF62: +; $ENDIF +$$IF61: + MOV AX,TRACK_SIZE ;ADVANCE COMPARE POINTER + ADD COMPARE_PTR,AX + RET +COMP_TRACK ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +DO_COMPARE PROC NEAR ; ;AN000; + PUBLIC DO_COMPARE ;ADD ENTRY TO LINK MAP ;AN000; +;INPUT: DS:[SI] POINTS TO ONE BUFFER, ES:[DI] POINTS TO THE OTHER +; CX HAS THE BYTE COUNT +;OUTPUT:CONDITION CODE IN CONDITION FLAGS REFLECT RESULT OF COMPARISON +; = = = = = = = = = = = = + SHR CX,1 ;DIVIDE BY TWO, CHANGE TO WORD COUNT ;AN000; + + PUBLIC PATCH_386 ;SO INIT CAN DO FIXUP ;AN001; +PATCH_386 LABEL BYTE + SHR CX,1 ;CONVERT WORD COUNT TO DWORD COUNT ;AN001; + DB 66H ;PREFIX FOR A DWORD COMPARE ;AN001; +; END OF PATCH AREA. IF THIS IS NOT A 386, THE ABOVE 3 BYTES ARE CHANGED +; TO NOP BY DISKINIT.SAL DURING INITIALIZATION. + + REPE CMPSW ;PERFORM THE COMPARISON ;AN000; + + RET ;RETURN TO CALLER ;AN000; +DO_COMPARE ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC SWAP_DRIVE ;MAKE ENTRY IN LINK MAP ;AN000; +SWAP_DRIVE PROC NEAR ;SWAP SOURCE, TARGET DRIVE +;***************************************************************************** + MOV AL,SOURCE_DRIVE + XCHG AL,TARGET_DRIVE + MOV SOURCE_DRIVE,AL + MOV AL,TRACK_TO_COMP + XCHG AL,TRACK_TO_READ + MOV TRACK_TO_COMP,AL + RET + +SWAP_DRIVE ENDP + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC READ_TRACK ;MAKE ENTRY IN LINK MAP ;AN000; +READ_TRACK PROC NEAR ;READ A TRACK AND STORE IT INTO MEMORY +; * +;***************************************************************************** + + MOV SIDE, 0 +; $DO +$$DO65: + CALL READ_OP + + CMP NO_OF_SIDES, 0 ;SINGLE SIDE COPY? +; $IF E ;YES + JNE $$IF66 + MOV AX, TRACK_SIZE +; $ELSE ;NO, DOUBLE SIDE + JMP SHORT $$EN66 +$$IF66: + XOR DX, DX + MOV AX, TRACK_SIZE + MOV CX, 2 + DIV CX ;AX / 2 +; $ENDIF +$$EN66: + ADD BUFFER_PTR, AX + INC SIDE ;NEXT SIDE + MOV AL, SIDE + CMP AL, NO_OF_SIDES ;FINISHED WITH THE LAST SIDE? +; $ENDDO G + JNG $$DO65 + RET + +READ_TRACK ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** +; * + PUBLIC READ_OP ;MAKE ENTRY IN LINK MAP ;AN000; +READ_OP PROC NEAR ;IOCTL READ A TRACK OPERATION +; * +;***************************************************************************** +; $SEARCH +$$DO70: +RO_AGAIN: + XOR AX, AX + MOV AL, SIDE + MOV Head, AX ;HEAD TO READ + MOV AL, TRACK_TO_READ + MOV Cylinder, AX ;TRACK TO READ + MOV FirstSectors, 0 ;???? SHOULD BE 1 BUT CURRENTLY 0 ??? + MOV AX, BUFFER_PTR + MOV Taddress_seg, AX ;BUFFER ADDRESS + MOV Taddress_off, 0 + XOR BX, BX + MOV BL, SOURCE_DRIVE + MOV CL, READ_FUNC ;=61h + MOV DX, OFFSET IOCTL_R_W + CALL GENERIC_IOCTL + + CMP IO_ERROR, NO_ERROR ;OK? +; $EXITIF E,NUL + JE $$SR70 + + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? +; $ENDLOOP NE + JE $$DO70 + + MOV OPERATION, READ_FUNC + PUSH AX + CALL ERROR_MESSAGE + + POP AX + INC COMP_ERROR ;INCREASE COPY_ERROR COUNT +; $ENDSRCH +$$SR70: + RET +READ_OP ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC SET_FOR_THE_OLD ;MAKE ENTRY IN LINK MAP ;AN000; +SET_FOR_THE_OLD PROC NEAR +;set MS_deviceBPB or MT_deviceBPB for before-2.0 formatted media. +;***************************************************************************** + PUSH AX + + CMP SECT_TRACK_LAYOUT,9 ;IF SECTORS/TRACK <= 9, THEN CHECK + ;NO_OF_SIDES. IF SINGLE SIDE COPY + ; THEN USE BPB48_SINGLE + ;ELSE USE BPB48_DOUBLE. +; $IF A ;SECTORS/TRACK > 9 THEN USE BPB96 TABLE + JNA $$IF74 + MOV SI, OFFSET BPB96 +; $ELSE + JMP SHORT $$EN74 +$$IF74: + CMP NO_OF_SIDES, 0 ;SINGLE SIDE COPY? +; $IF NE + JE $$IF76 + MOV SI, OFFSET BPB48_DOUBLE ;ELSE USE BPB48 DOUBLE +; $ELSE + JMP SHORT $$EN76 +$$IF76: + MOV SI, OFFSET BPB48_SINGLE +; $ENDIF +$$EN76: +; $ENDIF +$$EN74: + MOV AX, SECT_TRACK_LAYOUT + CMP READ_S_BPB_FAILURE, 1 ;FAILURE ON THE SOURCE? +; $IF E + JNE $$IF80 + MOV MS_deviceBPB.CSECT_TRACK,AX ;SET # OF SECTORS IN IOCTL_DRV_PARM + MOV DI, OFFSET MS_deviceBPB + MOV CX, BPB96_LENG + REP MOVSB ;OLD DEFAULT BPB INFO => MS_deviceBPB +; $ELSE + JMP SHORT $$EN80 +$$IF80: + CMP READ_T_BPB_FAILURE, 1 ;FAILURE ON THE TARGET? +; $IF E + JNE $$IF82 + MOV MT_deviceBPB.CSECT_TRACK,AX + MOV DI, OFFSET MT_deviceBPB + MOV CX, BPB96_LENG + REP MOVSB ;OLD DEFAULT BPB INTO => MT_deviceBPB +; $ENDIF +$$IF82: +; $ENDIF +$$EN80: + POP AX + RET +SET_FOR_THE_OLD ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;***************************************************************************** + PUBLIC SET_TRACKLAYOUT ;MAKE ENTRY IN LINK MAP ;AN000; +SET_TRACKLAYOUT PROC NEAR +;INPUT: BX - POINTER TO DESTINATION +; SECT_TRACK_LAYOUT +;***************************************************************************** + MOV CX, SECT_TRACK_LAYOUT ;MEDIA SECTORS/TRACK + MOV WORD PTR [BX], CX ;SET CSECT_F TO THE NUMBER OF SECTORS + ; IN A TRACK + ADD BX, 2 ;NOW BX POINTS TO THE FIRST SECTORNUMBER + MOV CX, 1 + MOV AX, bSECTOR_SIZE + +; $DO +$$DO85: + CMP CX, SECT_TRACK_LAYOUT +; $LEAVE A + JA $$EN85 + + MOV WORD PTR [BX], CX + INC BX + INC BX + MOV WORD PTR [BX], AX + INC BX + INC BX + + INC CX +; $ENDDO + JMP SHORT $$DO85 +$$EN85: + + RET +SET_TRACKLAYOUT ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +PUBLIC GENERIC_IOCTL +;****************************************************************************** +GENERIC_IOCTL PROC NEAR +;INPUT: CL - MINOR CODE; 60 - GET DEVICE PARM, 40 - SET DEVICE PARM +; 61 - READ TRACK, 41 - WRITE TRACK, +; 42 - FORMAT AND VERIFY TRACK +; 62 - VERIFY TRACK +; BL - LOGICAL DRIVE LETTER +; DS:DX - POINTER TO PARAMETERS +;****************************************************************************** + + MOV IO_ERROR, NO_ERROR ;reset io_error + MOV AH, IOCTL_FUNC ;IOCTL FUNC = 44H + MOV AL, GENERIC_IOCTL_CODE ;GENERIC IOCTL REQUEST = 0DH + MOV CH, MAJOR_CODE ;MAJOR CODE=08H, REMOVABLE + INT 21H +; $IF C + JNC $$IF88 + CALL EXTENDED_ERROR_HANDLER ;ERROR, SEE WHAT IT IS! + +; $ENDIF +$$IF88: + RET +GENERIC_IOCTL ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +;****************************************************************************** + PUBLIC EXTENDED_ERROR_HANDLER ;MAKE ENTRY IN LINK MAP ;AN000; +EXTENDED_ERROR_HANDLER PROC NEAR +;INPUT: BL - LOGICAL DRIVE LETTER +;****************************************************************************** + PUSHF + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES + PUSH DS + PUSH BX + + MOV AH, 59H + MOV BX, 0 + INT 21H + +; CMP BL, 5 ;ACTION=IMMEDIATE EXIT? +; JE EEH_JUST_EXIT + + POP BX ;RESTORE BL FOR DRIVE LETTER + POP DS + POP ES + + CMP AX, 21 ;DRIVE NOT READY? + JE WARN_USER_1 + + CMP AX, 19 ;ATTEMP TO WRITE ON WRITE_PROTECTED? + JE WARN_USER_2 + + JMP EEH_HARD_ERROR ;OTHERWISE, HARD_ERROR + +WARN_USER_1: + MOV DRIVE_LETTER, 'A' + DEC BL ;CHANGE LOGICAL TO PHYSICAL + ADD DRIVE_LETTER, BL + ;"Drive not ready - X:" + PRINT MSGNUM_GET_READY ; ;AC000; + + PRINT MSGNUM_CLOSE_DOOR ;"Make sure a diskette is inserted into ;AN004; + ; the drive and the door is closed" + JMP WAIT_FOR_USER + +WARN_USER_2: + ;"Attempt to write to write-protected diskette" + PRINT MSGNUM_WRITE_PROTECT ; ;AC000; + +WAIT_FOR_USER: + CALL PRESS_ANY_KEY ;"Press any key to continue . . ." ;AC009; + +EEH_SOFT_ERROR: + MOV IO_ERROR, SOFT_ERROR ;INDICATE THE CALLER TO TRY AGAIN + JMP SHORT EEH_EXIT + +EEH_HARD_ERROR: + MOV IO_ERROR, HARD_ERROR + +EEH_EXIT: + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + POPF + RET + +;EEH_JUST_EXIT: +; JMP EXIT_PROGRAM ;UNCONDITIONAL EXIT + +EXTENDED_ERROR_HANDLER ENDP +.XLIST +; HEADER +;CALL_PRINTF PROC NEAR +; PUBLIC CALL_PRINTF +;;INPUT - DX HAS OFFSET INTO DS OF MESSAGE PARM LIST +; PUSH DX +; PUSH CS +; CALL PRINTF +; +; RET +;CALL_PRINTF ENDP +.LIST +; = = = = = = = = = = = = + HEADER ; ;AN000; +ERROR_MESSAGE PROC NEAR ;DISPLAY ERROR MESSAGE + PUBLIC ERROR_MESSAGE +; +; FUNCTION: THIS SUBROUTINE DISPLAYS WHAT OPERATION FAILED (READ OR WRITE) +; AND WHERE IT FAILED (TRACK NO. AND SIDE). +; +; INPUT: OPERATION = IOCTL DISKETTE READ(=61H) OR COMPARE_FUNC(59H) +; = = = = = = = = = = = = + + CMP OPERATION,READ_FUNC ;ERROR DURING READ ? +; $IF E + JNE $$IF90 +.XLIST +; MOV BX,OFFSET READ_ERROR ;TELL USER ERROR DURING READ OP +; MOV MSG_HARD_ERROR_PTR+2,BX +.LIST + MOV DL,SOURCE_DRIVE ;WHICH DRIVE IS BAD + dec dl ;change logical letter to phisical + ADD DL,"A" ;CORRESPONDANT ALPHABET + MOV DRIVE_LETTER,DL + MOV SUBLIST_17B.SUB_VALUE,OFFSET DRIVE_LETTER ; + + MOV BL,TRACK_TO_READ ;SAVE BAD TRACK NUMBER FOR READ + ;CR,LF,"Unrecoverable read error on drive %2",CR,LF + ;"side %3, track %4",CR,LF + ;%2 IS "DRIVE_LETTER", AND + ;"MSG_SIDES" AND "MSG_TRACKS" ARE %3 AND %4. + MOV DI,OFFSET MSGNUM_HARD_ERROR_READ ; ;AN000; +; $ELSE + JMP SHORT $$EN90 +$$IF90: +.XLIST +; MOV BX,OFFSET COMPARE_ERROR ;TELL USER ERROR DURING COMPARE OP +; MOV MSG_HARD_ERROR_PTR+2,BX +.LIST + MOV BL,TRACK_TO_READ ;SAVE BAD TRACK NUMBER FOR WRITE + ;CR,LF,"Compare error on",CR,LF + ;"side %3, track %4",CR,LF + ;"MSG_SIDES" AND "MSG_TRACKS" ARE %3 AND %4. + MOV DI,OFFSET MSGNUM_HARD_ERROR_COMP ; ;AN000; +; $ENDIF +$$EN90: + + MOV AL,SIDE + MOV BYTE PTR MSG_SIDES,AL + MOV BYTE PTR MSG_TRACKS,BL + CALL SENDMSG ;PRINT MSG SELECTED ABOVE ;AN000; + + RET +ERROR_MESSAGE ENDP +; = = = = = = = = = = = = + HEADER ; ;AN000; +COMPAT_ERROR PROC NEAR ;DISPLAY COMPAT MSG + PUBLIC COMPAT_ERROR +; = = = = = = = = = = = = + + MOV COMP_STATUS,FATAL ;INCOMPATIBLE, ABORT + ;"Drive types or diskette types" + ;"not compatible" + PRINT MSGNUM_NOT_COMPATIBLE + + RET +COMPAT_ERROR ENDP +; = = = = = = = = = = = = + HEADER ; ;AN009; +PRESS_ANY_KEY PROC NEAR ; +;THE CANNED MESSAGE "PRESS ANY KEY..." DOES NOT START WITH CR,LF. +;THIS PUTS OUT THE CR LF TO CAUSE SEPARATION OF THIS PROMP FROM +;PRECEEDING MESSAGES. +; = = = = = = = = = = = = + PRINT MSGNUM_NEWLINE ;SKIP A SPACE ;AN009; + + PRINT MSGNUM_STRIKE ;"Press any key when ready..." ;AN009; + + RET ;RETURN TO CALLER ;AN009; +PRESS_ANY_KEY ENDP ; ;AN009; +; = = = = = = = = = = = = + HEADER ; ;AN000; +SENDMSG PROC NEAR ; ;AN000; + PUBLIC SENDMSG ; ;AN000; +; INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE +; OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED +; IF CARRY CLEAR, ALL OK +; IN EITHER CASE, DI AND AX ALTERED, OTHERS OK + +; = = = = = = = = = = = = + + PUSH BX ; SAVE CALLER'S REGS ;AN000; + PUSH CX ; ;AN000; + PUSH DX ; ;AN000; + PUSH SI ; ;AN000; + +; PASS PARMS TO MESSAGE HANDLER IN +; THE APPROPRIATE REGISTERS IT NEEDS. + MOV AX,[DI].MSG_NUM ;MESSAGE NUMBER ;AN000; + MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; + MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; + MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; + MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; + CALL SYSDISPMSG ;DISPLAY THE MESSAGE ;AN000; + +; $IF C ;IF THERE IS A PROBLEM ;AN000; + JNC $$IF93 + ;AX=EXTENDED ERROR NUMBER ;AN000; + LEA DI,MSGNUM_EXTERR ;GET REST OF ERROR DESCRIPTOR ;AN000; + MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; + MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; + MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; + MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; + CALL SYSDISPMSG ;TRY TO SAY WHAT HAPPENED ;AN000; + + STC ;REPORT PROBLEM ;AN000; +; $ENDIF ;PROBLEM WITH DISPLAY? ;AN000; +$$IF93: + + POP SI ;RESTORE CALLER'S REGISTERS ;AN000; + POP DX ; ;AN000; + POP CX ; ;AN000; + POP BX ; ;AN000; + + RET ;RETURN TO CALLER ;AN000; +SENDMSG ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +YESNO PROC NEAR ; ;AN000; + PUBLIC YESNO ;MAKE ENTRY IN LINK MAP ;AN000; +;INPUT: DL=CHAR WITH Y OR N EQUIVALENT CHAR TO BE TESTED +;OUTPUT: AX=0=NO; AX=1=YES ; AX=2=INVALID RESPONSE, NEITHER Y NOR N +; IF CARRY SET, PROBLEM WITH THE FUNCTION, CALLER SHOULD ASSUME "NO" +; = = = = = = = = = = = = + ;AL=SUBFUNCTION, AS: + ; 20H=CAPITALIZE SINGLE CHAR + ; 21H=CAPITALIZE STRING + ; 22H=CAPITALIZE ASCIIZ STRING + ; 23H=YES/NO CHECK + ; 80H BIT 0=USE NORMAL UPPER CASE TABLE + ; 80H BIT 1=USE FILE UPPER CASE TABLE + ;DL=CHAR TO CAP (FUNCTION 23H) ;AN000; + MOV AX,(GET_EXT_CNTRY_INFO SHL 8) + YESNO_CHECK ;(6523H) GET EXTENDED ;AN000; + ; COUNTRY INFORMATION, (Y/N) + INT 21H ;SEE IF Y OR N ;AN000; + + RET ;RETURN TO CALLER ;AN000; +YESNO ENDP ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +VOLSER PROC NEAR ;VERIFY FIRST SECTOR, IGNORING VOL SER # ;AN000; + PUBLIC VOLSER ; ;AN000; +;IF THE FIRST DISKETTE SUPPORTED A VOL SERIAL NUMBER, THEN +;COPY IT TO THE SECOND DISKETTE BUFFER AREA (NOT THE DISKETTE). +;INPUT: FIRST DRIVE NUMBER +; DS:=SEGID OF BUFFER OF FIRST DISKETTE, FIRST SECTOR, SIDE 0 +; ES:=SEGID OF BUFFER OF SECOND DISKETTE, FIRST SECTOR, SIDE 0 +; SI AND DI = 0, INDEX OF WHERE IN BUFFERS TO START LOOKING +; CX="BYTES_IN_TRACK"; NUMBER OF BYTES TO BE EVENTUALLY COMPARED +;OUTPUT: BUFFER OF 2ND DISKETTE ALTERED TO MATCH THE VOL SERIAL NUMBER OF 1ST. +; = = = = = = = = = = = = = = = = = = + + ASSUME DS:NOTHING ;BUFFER OF FIRST DISKETTE ;AN000; + ASSUME ES:NOTHING ;BUFFER OF SECOND DISKETTE ;AN000; + + PUSH CX ;SAVE CALLER'S REGS ;AN000; + PUSH SI ; ;AN000; + PUSH DI ; ;AN000; +;(deleted ;AN011;) PUSH DS ;SAVE BUFFER OF FIRST DISKETTE ;AN000; + +;(deleted ;AN011;) PUSH CS ;RESTORE ADDRESSABILITY TO COMMON SEG ;AN000; +;(deleted ;AN011;) POP DS ; TO ACCESS GET MEDIA ID BUFFER AREA ;AN000; +;(deleted ;AN011;) ASSUME DS:CSEG ;AN000; + +;(deleted ;AN011;); ISSUE GET MEDIA ID FROM SOURCE +;(deleted ;AN011;) MOV BH,0 ;BH=0, RES ;AN000; +;(deleted ;AN011;) MOV BL,SOURCE_DRIVE ;BL=DRIVE NUM (A:=1, B:=2, ETC.) ;AN000; +;(deleted ;AN011;) MOV DX,OFFSET MEDIA_ID_BUFFER ;DS:DX=BUFFER +;(deleted ;AN011;) DOSCALL GSET_MEDIA_ID,GET_ID ;(6900H) GET MEDIA ID ;AC008; +;(deleted ;AN011;) ;CARRY SET ON ERROR (OLD STYLE BOOT RECORD) +;(deleted ;AN011;) POP DS ;RESTORE THIS BACK TO BUFFER OF FIRST DISKETTE;AN000; +;(deleted ;AN011;) ASSUME DS:NOTHING ; LIKE IT WAS AT ENTRY TO THIS PROC ;AN000; + +;(deleted ;AN011;) $IF NC ;IF THERE IS NO PROBLEM ;AN000; +;(deleted ;AN011;) ; THEN THIS DISKETTE HAS A VOL SER # + + PUSH BX ;AN011; + LEA BX,DS:[DI].EXT_BOOT_BPB ;AN011;POINT TO BPB PORTION OF BOOT RECORD + MOV AL,DS:[BX].EBPB_MEDIADESCRIPTOR ;AN011;GET TYPE OF MEDIA + AND AL,0F0H ;AN011;SAVE LEFT NIBBLE ONLY + CMP AL,0F0H ;AN011;IF DISKETTE HAS PROPER DESCRIPTOR +; $IF E ;AN011; + JNE $$IF95 + MOV AL,DS:[DI].EXT_BOOT_SIG ;AN011;GET "SIGNATURE" OF BOOT RECORD + CMP AL,28H ;AN011;IS THIS BOOT STYLE OF OS/2 1.0 OR 1.1? +; $IF E,OR ;AN011;YES, IS A BOOT WITH A SERIAL IN IT + JE $$LL96 + CMP AL,29H ;AN011;IS THIS A BOOT STYLE OF OS/S 1.2? +; $IF E ;AN011;YES, IS A BOOT WITH A SERIAL IN IT + JNE $$IF96 +$$LL96: + +;THE PURPOSE HERE IS TO CAUSE DISKCOMP TO IGNORE ANY DIFFERENCES IN THE +;VOL SERIAL NUMBER FIELD. THIS IS DONE BY TAKING ONE VOL SERIAL NUMBER +;FROM ONE BUFFER, ALREADY LOADED WITH THE FIRST TRACK OF ONE DISKETTE, +;AND MOVING THAT SERIAL NUMBER TO THE CORRESPONDING POSITION IN THE OTHER +;BUFFER, ALREADY LOADED WITH THE SIMILAR TRACK FROM THE OTHER DISKETTE. +;WHEN THIS RETURNS TO THE MAIN ROUTINE, THE ENTIRE TRACK (INCUDING THIS +;VOL SERIAL NUMBER FIELD) WILL BE COMPARED. IF THERE ARE ANY DIFFERENCES, +;THEY WILL BE OTHER THAN IN THE VOL SERIAL NUMBERS. + + MOV SI,OFFSET VOL_SERIAL ;GET WHERE VOL SERIAL NUMBER IS + MOV DI,OFFSET VOL_SERIAL ;GET WHERE VOL SERIAL NUMBER IS + MOV CX,TYPE VOL_SERIAL ;GET NUMBER BYTES IN VOL SER FIELD + REP MOVSB ;FORCE THE SERIAL NUMBERS TO BE ALIKE + +; $ENDIF ; ;AN000; +$$IF96: +; $ENDIF ;AN011; +$$IF95: + POP BX ;AN011; + POP DI + POP SI + POP CX ;RESTORE COUNT + RET ;RETURN TO CALLER ;AN000; +VOLSER ENDP ;AN000; +; = = = = = = = = = = = = = = = = = = = +DISKCOMP_END LABEL BYTE + PATHLABL DISKCOMP ;AN013; +CSEG ENDS + END DISKCOMP + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DISKCOMP.EQU b/v4.0/src/CMD/DISKCOMP/DISKCOMP.EQU new file mode 100644 index 0000000..3777c37 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DISKCOMP.EQU @@ -0,0 +1,170 @@ + + IF1 + %OUT INCLUDING DISKCOMP.EQU... + ELSE +; %OUT INCLUDING DISKCOMP.EQU... + ENDIF + +;---------------------------------------------------------------------------; +; EQUATES ; +;---------------------------------------------------------------------------; + +; *** CONSTANTS *** + +ZERO EQU 0 +ONE EQU 1 +TWO EQU 2 +THREE EQU 3 +FOUR EQU 4 +TYPE_4 EQU 4 +FIVE EQU 5 +SIX EQU 6 +SEVEN EQU 7 +EIGHT EQU 8 +NINE EQU 9 +TEN EQU 0AH +ON EQU 1 +OFF EQU 0 +TRUE EQU 01 +FALSE EQU 00 +GOOD EQU 0 +BAD EQU 1 +FIRST EQU 1 +SECOND EQU 2 +HARD_ERROR EQU 02 +SOFT_ERROR EQU 01 +NO_ERROR EQU 0 +;DOS_LEVEL EQU 0314H ;DOS VERSION 3.20 +BLANK EQU 20H ;BLANK IN ASCII (32 DEC) +CLEAR_SEGMENT EQU 0E0H ;USED TO CLEAR SEGMENT BITS (ROUND UP + ;TO NEXT SECTOR) +SECTOR8 EQU 8 ; +SECTOR9 EQU 9 ; +SECTOR14 EQU 14 ; +SECTOR15 EQU 15 ; +DRV_48TPI EQU 0 ;48 TPI DRIVE +DRV_96TPI EQU 1 ;96 TPI DRIVE +DRV_720 EQU 2 ;3.5", 720 KB DRIVE (FOR CASHEW OR P14) +NRLFUNC EQU 5F02H ;GET NETWORK-REDIRECTION-LIST FUNTION +NRLMAX EQU 1CH ;(MAXIMUM # OF NAMES ON NRL) - 1 +DOS20 EQU 2 ;DOS VERSION 2.0 + PUBLIC FINE ; ;AN000; +FINE EQU -1 ;"FINE AND DANDY", USED FOR RETURN CODE + ;(-1 WAS USED TO AVOID CONFUSION WITH ERROR + ;OFFSET WHICH CAN BE ZERO) +LOCAL_DRV EQU -1 ;DEVICE NOT DIRECTED +REMOTE_DRV EQU 1000H ;REMOTE DRIVE TEST BITS +NO_OPTION EQU -1 ;NO OPTION "/1" SPECIFIED +OPTION_1 EQU 1 ;OPTION "/1" SPECIFIED +REMOVABLE EQU 0000H ;REMOVABLE FILE +INVAL_PARM EQU -9 ;INVALID PARAMETER ENTERED + +PAGE +; *** PROGRAM SEGMENT PREFIX *** + +FCB1_DRV_ID EQU 5CH ;DRIVE NUMBER ADDR IN FILE CONTROL BLOCK 1 +FCB1_FILENM EQU 5DH ;FILE NAME ADDR IN FILE CONTROL BLOCK 1 +FCB2_DRV_ID EQU 6CH ;DRIVE NUMBER ADDR IN FILE CONTROL BLOCK 2 +FCB2_FILENM EQU 6DH ;FILE NAME ADDR IN FILE CONTROL BLOCK 2 +BEGIN_UNFORM_AREA EQU 80H ;BEGINNING @ OF THE UNFORMATTED AREA +END_UNFORM_AREA EQU 100H ;ENDING @ OF THE UNFORMATTED AREA + + +; *** DOS FUNCTONS *** + +RET_CD_EXIT EQU 4CH ;EXIT TO DOS, PASSING RETURN CODE ;AN000; +PUT_CHAR EQU 02H ;DOS DISPLAY OUTPUT FUNCTION +PRINT_FUNC EQU 09H ;DOS PRINT STRING FUNCTION +REDIRECTED_FUNC EQU 09H ;IOCTL SUB FUNCTION ****** TO BE CHECKED **** +KB_INPUT_FUNC EQU 0C01H ;DOS KEYBOARD INPUT (CLEARS INPUT BUFF FIRST) +CURRENTDRV_FUNC EQU 19H ;GET CURRENT DRIVE FUNCTION CALL +;DOSVER_FUNC EQU 30H ;DOS VERSION FUNCTION CALL +IOCTL_FUNC EQU 44H ;IOCTL FUNCTION CALL +DRIVE_CHECK EQU 4408H ;DOS CHECK FOR REMOVABLE DRIVE IOCTL CALL +STD_ERROR EQU 0002H ;STANDARD ERROR FILE HANDLE +WRITE_FILE EQU 40H ;WRITE TO FILE OR DEVICE FUNCTION CALL +GET_ASSIGN_MODE EQU 5F00H ;SET ASSIGN MODE COMMAND +SET_ASSIGN_MODE EQU 5F01H ;SET ASSIGN MODE COMMAND +SERVER EQU 2AH ;NETWORK SERVER INTERUPT +SHARED EQU 03H ;DEVICE SHARED CHECK +GET_EXT_CNTRY_INFO EQU 65H ;GET EXTENDED COUNTRY INFO ;AN000; +YESNO_CHECK EQU 23H ;REQUEST (Y/N) CHECK OF GET_EXT_CNTRY_INFO ;AN000; +YES EQU 1 ;(Y/N) RESPONSE IS "YES" ;AN000; +BAD_YESNO EQU 2 ;(Y/N) RESPONSE IS NEITHER "Y" NOR "N" ;AN000; + +;IOCTL DISKETTE I/O FUNCTIONS +GENERIC_IOCTL_CODE EQU 0DH ;GENERIC IOCTL REQUEST +MAJOR_CODE EQU 08H ;GENERIC IOCTL MAJOR CODE +READ_FUNC EQU 61H ;IOCTL DISKETTE RAED FUNCITON +WRITE_FUNC EQU 41H ;IOCTL DISKETTE WRITE FUNCTION +VERIFY_FUNC EQU 62H ;IOCTL DISKETTE VERIFY FUNCTION +FORMAT_FUNC EQU 42H ;IOCTL DISKETTE FORMAT FUNCITON +GETDEVPARM EQU 60H ;IOCTL GET DEVICE PARAMETER +SETDEVPARM EQU 40H ;IOCTL SET DEVICE PARAMETER +SET_LOG_DRIVE EQU 0FH ;SET LOGICAL DRIVE ;AN000; +GSET_MEDIA_ID EQU 69H ;GET/SET MEDIA ID ;AN008; +GET_ID EQU 0 ;AL=0, GET MEDIA ID ;AN008; +SET_ID EQU 1 ;AL=1, SET MEDIA ID ;AN008; +; +COMPARE_FUNC EQU 59H ;JUST USED TO IDENTIFY FOR ERROR MESSAGE +; +;specialFunctions +GET_SP_FUNC_DEF EQU 00000000B ;GET DEVICE PARM. DEFAULT BPB +GET_SP_FUNC_MED EQU 00000001B ;GET DEVICE PARM. media bpb +SET_SP_FUNC_DEF EQU 00000100B ;SET DEFAULT DEVICE PARM +SET_SP_FUNC_DOS EQU 00000100B ;SET DEVICE PARM BEFORE RETURN TO DOS +R_W_SP_FUNC EQU 00000000B ;READ, WRITE + +; *** BIOS DISKETTE I/O ERROR CODES *** + +;NOT_READY EQU 80H ;DISKETTE I/O NOT READY ERROR +;CHANG_LINE EQU 06H ;CHANGE LINE ERROR +;BAD_CONTROLLER EQU 20H ;BAD DISKETTE/DISK CONTOROLLER +;WRITE_PROTECT EQU 03H ;DISKETTE I/O WRITE PROTECT ERROR +;BAD_ADDR_MARK EQU 02H ;DISKETTE I/O BAD ADDRESS MARK ERROR +;REC_NOT_FOUND EQU 04H ;DISETTTE I/O RECORD NOT FOUND ERROR +;BAD_CRC EQU 10H ;DISKETTE I/O BAD CRC ERROR +;HARD_WR_ERROR EQU 03H ;DISKETTE WRITE HARD ERROR COUNT +;HARD_FMT_ERROR EQU 02H ;DISKETTE FORMAT HARD ERROR COUNT +;SINGLE_SIDE_COPY EQU 00H ;WHEN READING TRACK 0 SIDE 1 IF HARD ERROR + ;OCCURS, WE WILL ASSUME IT WILL BE SINGLE + ;SIDED COPY AND AL WILL BE SET TO 0, SO THAT + ;BUFFER_PTR WILL NOT BE ADVANCED AND + ;IF THE TRACK HAPPENS TO FALL INTO DMA BOUNDRY + ;IT WILL SKIP THE SECOND PART OF READ_TRACK + +; *** COPY STATUS BYTE *** + +FATAL EQU 01H ;FATAL COPY ERROR, ABORT +OK EQU 00H ;OK, PROCEED + +; *** MESSAGES SUBLIST DESCRIPTOR *** + +SUBLIST STRUC ;AN000; +SUB_SIZE DB ? ;SUBLIST SIZE (POINTER TO NEXT SUBLIST) ;AN000; +SUB_RES DB ? ;RESERVED ;AN000; + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD ;AN000; +SUB_VALUE DW ? ;TIME, DATE, OR PTR TO DATA ITEM ;AN000; +SUB_VALUE_SEG DW ? ;SEG ID OF PTR ;AN000; + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME ;AN000; + ; IF THIS IS A .COM FILE) ;AN000; +SUB_ID DB ? ;N OF %N ;AN000; +SUB_FLAGS DB ? ;DATA TYPE FLAGS ;AN000; +SUB_MAX_WIDTH DB ? ;MAXIMUM FIELD WIDTH (0=UNLIMITED) ;AN000; +SUB_MIN_WIDTH DB ? ;MINIMUM FIELD WIDTH ;AN000; +SUB_PAD_CHAR DB ? ;CHARACTER FOR PAD FIELD ;AN000; + ; CAN BE " ", "0" OR ",". ;AN000; + ; "," CAUSES INSERTION OF THE ACTIVE ;AN000; + ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS. ;AN000; +SUBLIST ENDS ;AN000; + + ;BUFFER AREA FOR COMMUNICATION WITH GET/SET MEDIA ID FUNCTION CALL: +;(deleted ;AN011;) A_MEDIA_ID_INFO struc +;(deleted ;AN011;) MI_level dw 0 ;info level +;(deleted ;AN011;) MI_Serial dd 0 ;Serial # +;(deleted ;AN011;) MI_Label db 11 dup (' ') ;Volume Label +;(deleted ;AN011;) MI_System db 8 dup (' ') ;File System type +;(deleted ;AN011;) A_MEDIA_ID_INFO ends + INCLUDE BOOTFORM.INC ;GET DESCRIPTION OF BOOT RECORD +VOL_SERIAL EQU EXT_BOOT_SERIAL ;LOCATION IN BOOT RECORD OF VOLSER NUM ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DISKCOMP.LNK b/v4.0/src/CMD/DISKCOMP/DISKCOMP.LNK new file mode 100644 index 0000000..a6d0f36 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DISKCOMP.LNK @@ -0,0 +1,6 @@ +DISKCOMP+ +DCOMPSM+ +DCOMPP+ +DCOMPPAR+ +COMPINIT; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/DISKCOMP.SKL b/v4.0/src/CMD/DISKCOMP/DISKCOMP.SKL new file mode 100644 index 0000000..44e8251 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/DISKCOMP.SKL @@ -0,0 +1,56 @@ +:util DISKCOMP ;AN000;utility name +:class A ;AN000;system messages +; +:use 1 COMMON1 ;AN000;"Incorrect DOS version" +; +:use 2 EXTEND8 ;AN000;"Insufficient memory" +; +:use 3 PARSE10 ;AN000;"Invalid parameter" +; +:def 4 "Do not specify filename(s)",CR,LF ;AN000; +"Command format: DISKCOMP d: d: [/1][/8]",LF,CR ;AN000; +; +:def 5 CR,LF,"Invalid drive specification",CR,LF ;AN000; +"Specified drive does not exist",CR,LF ;AN000; +"or is non-removable",CR,LF ;AN000; +; +:def 6 CR,LF,"Cannot DISKCOMP to or from",CR,LF ;AN000; +"a network drive",CR,LF ;AN000; +; +:def 7 CR,LF,"Insert FIRST diskette in drive %1:",CR,LF ;AN000; + +:def 8 CR,LF,"Insert SECOND diskette in drive %1:",CR,LF ;AN000; + +:def 9 CR,LF,"FIRST diskette bad or incompatible",CR,LF ;AN000; + +:def 10 CR,LF,"SECOND diskette bad or incompatible",CR,LF ;AN000; +; +:use 11 EXTEND21 ;AN000;"Drive not ready" NOTE CHANGE %1 TO %0 +; +:use 12 COMMON28 ;AN000;"Press any key to continue . . ." +; +:use 13 EXTEND19 ;AN000;CR,LF,"Attempt to write to write-protected diskette",CR,LF +; +:def 14 CR,LF,"Compare another diskette (Y/N) ?" ;AN000; +; +:def 15 CR,LF,"Comparing %1 tracks",CR,LF ;AN000; +"%2 sectors per track, %3 side(s)",CR,LF ;AN000; +; +:def 16 CR,LF,"Drive types or diskette types",CR,LF ;AN000; +"not compatible",CR,LF ;AN000; +; +:def 17 CR,LF,"Unrecoverable read error on drive %2",CR,LF ;AN000; +"side %3, track %4",CR,LF ;AN000; +; +:def 18 CR,LF,"Compare error on",CR,LF,"side %3, track %4",CR,LF ;AN000; +; +:def 19 "Make sure a diskette is inserted into",CR,LF ;AN004; +"the drive and the door is closed",CR,LF ;AN004; +; +:def 20 CR,LF,"Compare process ended",CR,LF ;AN000; +; +:def 21 CR,LF,"Compare OK",CR,LF ;AN000; +; +:def 22 CR,LF ;AC007; +:end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOMP/MAKEFILE b/v4.0/src/CMD/DISKCOMP/MAKEFILE new file mode 100644 index 0000000..09415b1 --- /dev/null +++ b/v4.0/src/CMD/DISKCOMP/MAKEFILE @@ -0,0 +1,59 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: diskcomp.com + +diskcomp.ctl: diskcomp.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +diskcomp.obj: diskcomp.asm \ + makefile \ + dcmpmacr.inc \ + $(inc)\bootform.inc \ + diskcomp.equ + +compinit.obj: compinit.asm \ + makefile \ + dcmpmacr.inc \ + $(inc)\bootform.inc \ + diskcomp.equ + +dcompp.obj: dcompp.asm \ + makefile \ + $(inc)\parse.asm + +dcompsm.obj: dcompsm.asm \ + makefile \ + $(inc)\sysmsg.inc \ + $(inc)\msghan.inc \ + $(inc)\versiona.inc \ + diskcomp.ctl \ + diskcomp.cla \ + diskcomp.cl1 \ + diskcomp.cl2 \ + dcompms.inc \ + $(inc)\copyrigh.inc + +dcomppar.obj: dcomppar.asm \ + makefile + +diskcomp.com: diskcomp.obj \ + makefile \ + diskcomp.lnk \ + dcompsm.obj \ + dcompp.obj \ + dcomppar.obj \ + compinit.obj + link @diskcomp.lnk + exe2bin diskcomp.exe diskcomp.com + del diskcomp.exe + diff --git a/v4.0/src/CMD/DISKCOPY/COPYINIT.ASM b/v4.0/src/CMD/DISKCOPY/COPYINIT.ASM new file mode 100644 index 0000000..4410925 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/COPYINIT.ASM @@ -0,0 +1,1046 @@ + PAGE 90,132 ;A2 + TITLE COPYINIT -- DISKCOPY INITIALIZATION PROGRAM +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: COPYINIT + +; DESCRIPTIVE NAME: Initialization for Diskette to diskette copy Utility + +;FUNCTION: DISKCOPY is to copy the contents of the diskette in the +; specified source drive to the diskette in the target +; drive. If necessary, the target diskette is also +; formatted. + +; Multiple copies may be performed with one load of DISKCOPY. +; A prompt, "Copy another (Y/N)?" permits additional +; executions, all with the same drive specifications. + +; ENTRY POINT: "DISKCOPY" at ORG 100h, jumps to "BEGIN". + +; INPUT: (DOS command line parameters) +; [d:][path]DISKCOPY [d: [D:]][/1] + +; Where + +; [d:][path] before DISKCOPY to specify the drive and path that +; contains the DISKCOPY command file. + +; [d:] to specify the source drive id + +; [D:] to specify the destination drive id + +; [/1] to request single sided operations only + +; EXIT-NORMAL: Errorlevel = 0 +; Function completed successfully. + +; EXIT-ERROR: Errorlevel = 1 +; Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on +; the diskette. + +; EFFECTS: The entire source diskette is copied, including the unused +; sectors. There is no awareness of the separate files +; involved. A unique volume serial number is generated +; for the target diskette. + +; INCLUDED FILES: +; INCLUDE DCPYMACR.INC +; INCLUDE DISKCOPY.EQU +; INCLUDE PATHMAC.INC ;PATHGEN MACRO + +; INTERNAL REFERENCES: +; ROUTINES: +; INIT - INITIALIZATION ROUTINE, MAIN PROGRAM +; SOURCE_TARGET_DRV - CONVERT SOURCE/TARGET DRIVE TO BIOS VALUES +; TEST_DRIVE_VALIDITY - ARE SOURCE/TARGET DRIVES VALID? +; DOS_DRIVE_VALIDITY - CHECK DOS DRIVE VALIDITY BYTE +; TEST_REMOVABLE - IS SPECIFIED DRIVE REMOVABLE? +; CHK_SINGLE_DRIV_OP - IS TARGET DRIVE SAME AS SOURCE? +; GET_LOGICAL_DRIVE - GET LOG. DRIV NO. WHO OWNS PHYSICAL DRIVE +; DISKETTE_DRV_TYPE - CHECK COMPATABILITY SOURCE/TARGET DRIVES +; CHECK_REDIRECTION - IS DEVICE REDIRECTED? +; BUFFER_SIZE - FINDS START AND END OF BUFFER +; SETUP_CTRL_BREAK - SETUP THE CTRL-BREAK VECTOR +; CHECK_SERVER - IS SERVER OR REDIRECTOR LOADED? + +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; WORKAREA - Temporary storage + +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; PARSER - Processes the DOS Command line, finds parms. + +; DATA AREAS: +; DCOPYSM.SAL - Defines the control blocks that describe the messages +; DCOPYPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT COPYINIT,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For instructions as to how to LINK, see prolog for DISKCOPY. + +;PROGRAM AUTHOR: Original written by: JK +; 4.00 modifications by: EMK +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=DISKCOPY, MODULE=COPYINIT.SAL + ENDIF + +;DATE: 9-22-83 +;TIME: 8:00 PM +;DATE: 10-30-84 - chk_para routine added. many parts are modified to +; permit DISKCOPY /1, DISKCOPY D: /1 cases. Restore diskbase +; before return to DOS when invalid DOS version occurs. +;DATE: 3-27-85 MAIN PARTS OF DISKCOPY PROGRAM HAS BEEN REWRITTEN +; TO USE NEW IOCTL FUNCTION CALLS - READ, WRITE AND FORMAT. + + INCLUDE DCPYMACR.INC + INCLUDE PATHMAC.INC ;AN015;PATHGEN MACRO + +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + + INCLUDE DISKCOPY.EQU +;$salut (4,2,9,41) +;**************************************************************************** +; * +; EXTERNAL VARIABLES * +; * +;**************************************************************************** + + EXTRN PARSER:NEAR ;DCOPYPAR.SAL - DRIVES SYS PARSER ;AN000; + + EXTRN RECOMMENDED_BYTES_SECTOR:WORD ;SOURCE DRIVE DEFAULT BYTES/SECTOR + EXTRN S_OWNER_SAVED:BYTE + EXTRN T_OWNER_SAVED:BYTE + EXTRN ASCII_DRV1_ID:BYTE ;40H SOURCE DRIVE ID IN ASCII + EXTRN ASCII_DRV2_ID:BYTE ;40H TARGET DRIVE ID IN ASCII + EXTRN MSGNUM_INVALID_DRV:BYTE ;"INVALID DRIVE SPECIFICATION" ;AC000; + EXTRN MSGNUM_NOT_COMPATIBLE :BYTE ;"DEVICE TYPE OF DISKETTE TYPES NOT COMPATIBLE";AC000; + EXTRN MSGNUM_DRV_REDIRECTED:BYTE ;"INVALID, DRIVE REDIRECTED" ;AC000; + + + EXTRN SUBLIST_8 :WORD ; ;AN000; + EXTRN SUBLIST_9 :WORD ; ;AN000; + EXTRN SUBLIST_13 :WORD ; ;AN000; + EXTRN SUBLIST_17A :WORD ; ;AN000; + EXTRN SUBLIST_17B :WORD ; ;AN000; + EXTRN SUBLIST_17C :WORD ; ;AN000; + EXTRN SUBLIST_19C :WORD ; ;AN000; + EXTRN SUBLIST_19D :WORD ; ;AN000; + EXTRN SUBLIST_19E :WORD ; ;AN000; + EXTRN SUBLIST_26A :WORD ; ;AN001; + EXTRN SUBLIST_26B :WORD ; ;AN001; + EXTRN SUBLIST_PARSE:WORD ;PARSE ERROR XX - %0 ;AN003; + +.XLIST +;EXTRN MSG_INVALID_PARM_PTR:BYTE ;"INVALID PARAMETER" +;EXTRN MSG_INVALID_DOS :BYTE ;"INVALID DOS" +.LIST + EXTRN S_DRV_SECT_TRACK :BYTE ;SECT/TRACK + EXTRN S_DRV_HEADS :BYTE ;# OF HEADS + EXTRN S_DRV_TRACKS :BYTE ;# OF TRACKS + EXTRN T_DRV_SECT_TRACK :BYTE + EXTRN T_DRV_HEADS :BYTE + EXTRN T_DRV_TRACKS :BYTE + EXTRN SOURCE_DRIVE :BYTE ;SRC DRV LOGICAL NUMBER + EXTRN TARGET_DRIVE :BYTE ;TARGET DRV LOGICAL NUMBER + EXTRN COPY_TYPE :BYTE ;1 = 1-DRIVE COPY 2 = 2-DRIVE COPY + EXTRN USER_OPTION :BYTE ;NO OPTION (-1) /1 (1), INVALID (9) + EXTRN BUFFER_BEGIN :WORD ;STARTING BUFFER @ FOR LOADING + EXTRN BUFFER_END :WORD ;ENDING BUFFER @ FOR LOADING + EXTRN MAIN_EXIT :WORD ;EXIT ADDRESS FOR CONTROL-BREAK + + EXTRN IO_ERROR :BYTE + + EXTRN DS_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM + EXTRN DT_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM + EXTRN DS_specialFunctions :BYTE ;AND THEIR CONTENTS + EXTRN DT_specialFunctions :BYTE + EXTRN DS_deviceType:BYTE + EXTRN DT_deviceType:BYTE + EXTRN DS_deviceAttributes :WORD + EXTRN DT_deviceAttributes :WORD + EXTRN DS_numberOfCylinders :WORD + EXTRN DT_numberOfCylinders :WORD + EXTRN DS_mediaType :BYTE + EXTRN DT_mediaType :BYTE + EXTRN DS_BPB_PTR :BYTE + EXTRN DT_BPB_PTR :BYTE + + EXTRN MS_IOCTL_DRV_PARM :BYTE ;DRIVE PARM FROM SOURCE MEDIUM + EXTRN MT_IOCTL_DRV_PARM :BYTE + + EXTRN GENERIC_IOCTL :NEAR + EXTRN SET_LOGICAL_DRIVE :NEAR + +; $salut (4,20,24,41) ; ;AN000; +MY_BPB STRUC +CBYTE_SECT DW 0 ; 200H BYTES / SECTOR +CSECT_CLUSTER DB 0 ; 2h SECTORS / CLUSTER +CRESEV_SECT DW 0 ; 1h RESERVED SECTORS +CFAT DB 0 ; 2h # OF FATS +CROOTENTRY DW 0 ; 70h # OF ROOT ENTRIES +CTOTSECT DW 0 ; 02D0h TOTAL # OF SECTORS + ; INC. BOOT SECT, DIRECTORIES +MEDIA_DESCRIP DB 0 ;0FDh MEDIA DISCRIPTOR +CSECT_FAT DW 0 ; 2h SECTORS / FAT +CSECT_TRACK DW 0 ; +CHEAD DW 0 ; +CHIDDEN_SECT DD 0 ; +BIG_TOT_SECT DD 0 ; + DB 6 DUP (0) ; +MY_BPB ENDS + + +;**************************************************************************** +; * +; VARIABLE DECLARATIONS * +; * +;**************************************************************************** +DRIVE_VALID DW ? ;DRIVE VALIDITY INDICATOR +DEFAULT_DRV DB ? ;DEFAULT DRIVE ID (0=A,1=B,ETC) +NUMBER_OF_DRV DB ? ;TOTAL # OF DISKT DRIVES ON THE SYS + ;(NUMBER_OF_DRV = 0 ---> 1 DRIVE) +ASCII_DRIVE_LETTER DB " :",0 + PATHLABL COPYINIT ;AN015; + HEADER ; ;AN000; +; $salut (4,9,15,41) ; ;AN000; +;############################################################################# +; INITIALIZATION ROUTINE - MAIN PROGRAM +INIT PROC NEAR + PUBLIC INIT ;MAKE ENTRY IN LINK MAP ;AN000; + +;OUTPUT: DX = EXIT CODE, "FINE" +;############################################################################# + + MOV DRIVE_VALID,AX ;SAVE DRIVE VALIDITY BYTE + +; REPLACE THE "FILL_SEG" IN THE SUBLIST MESSAGE CONTROL BLOCKS. + +; BECAUSE THIS IS A .COM STYLE FILE, THESE SEGID VALUES CANNOT +; BE PROVIDED BY THE DOS SYSTEM LOADER, BUT MUST BE DYNAMICALLY +; PERFORMED AT EXECUTION TIME AS PART OF A .COM FILE'S OBLIGATION +; TO BE "SELF-RELOCATING". + + MOV AX,CS ;GET SEGID OF COMMON SEGMENT ;AN000; + MOV SUBLIST_8.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_9.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_13.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17A.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17B.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_17C.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_19C.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_19D.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_19E.SUB_VALUE_SEG,AX ; ;AN000; + MOV SUBLIST_26A.SUB_VALUE_SEG,AX ; ;AN001; + MOV SUBLIST_26B.SUB_VALUE_SEG,AX ; ;AN001; + MOV SUBLIST_PARSE.SUB_VALUE_SEG,AX ; ;AN003; + + CALL SETUP_CTRL_BREAK ;STEALS CTRL_BREAK + CLD ;CLEAR DIRECTION FLAG + MOV DX,FINE ;ASSUME EVERYTHING IS FINE +.XLIST +; CALL SCREENING ;CHECK DOS VERSION AND INPUT PARMS +; CALL CHK_PARA ; GENERAL SYNTAX CHECK +.LIST + CALL PARSER ;LOOK AT DOS COMMAND LINE ;AN000; + + CMP DX,FINE ;IF ALL OK ;AN000; +; $IF E ; ;AN000; + JNE $$IF1 + CALL SOURCE_TARGET_DRV ;SET UP TO USE THE DRIVE LETTERS ;AN000; + + CALL TEST_DRIVE_VALIDITY + + CMP DX,FINE +; $IF E ; ;AN000; + JNE $$IF2 + CALL DISKETTE_DRV_TYPE ;SOURCE & TARGET DRIVE TYPES + + CMP DX,FINE ;IF FINE & DANDY +; $IF E ; ;AN000; + JNE $$IF3 + CALL BUFFER_SIZE ;GET BUFFER SIZE FOR COPYING + +; $ENDIF ; ;AN000; +$$IF3: +; $ENDIF ; ;AN000; +$$IF2: +; $ENDIF ; ;AN000; +$$IF1: +EXIT_INIT: ;DX <-- 1 IF INIT OK + RET ;DX <-- ERROR OFFSET IF NOT OK + ;RETURN TO CALLER +INIT ENDP ;END INITIALLIZATION PROGRAM + +.XLIST +; HEADER +;****************************************************************************** +; SUBROUTINE NAME : SCREENING - CHECKS THE FOLLOWING: * +; - DOS VERSION * +; - GENERAL SYNTAX CHECKING FOR PARAMETERS * +; INPUT : NONE * +; OUTPUT : DX : FINE - NO ERROR * +; (OTHERS)- ERROR MSG OFFSET * +;****************************************************************************** + +;SCREENING PROC NEAR + ;CHECK DOS VERSION: +; MOV AH,DOSVER_FUNC ;SEE IF CORRECT DOS VERSION +; INT 21H ;FUNCTION CALL (AL <- DOS VERSION) + ;NOTE: BX IS DESTROYED +; XCHG AH,AL ;AH=MAJOR VER, AL=MINOR VER +; CMP AX,expected_version ;IF DOS MAJOR VERSION LESS THAN 3.00 +; $IF NE ;THEN ISSUE ERROR MSG +; MOV DX,OFFSET MSG_INVALID_DOS +; MOV AH,PRINT_FUNC ;USE PRINT FUNCTION TO TELL USER +; INT 21H ;THAT HE IS USING THE OLD VERSION +; INT 20H ;EXIT TO DOS +; $ELSE ;VERSION OK +; CALL CHK_PARA ;GENERAL SYNTAX CHECK +; $ENDIF ;END VERSION TEST +; RET +;SCREENING ENDP +; HEADER +;************************************************************************** + +;kiser: this proc is to be deleted + +;CHK_PARA PROC NEAR +; CHECK SYNTAX OF THE ENTERED PARAMETERS * +; ALSO, DETERMINE THE USER OPTION "/1" IS ENTERED OR NOT. * +; INPUT: DX = FINE * +; IF /1 HAS BEEN ENTERED, THE VARIABLE USER_OPTION = OPTION_1 * +; ELSE USER_OPTION = NO_OPTION. * +; OUTPUT: DX = FINE - NO ERROR * +; OTHERWISE DX POINTS TO ERROR MSG * +;************************************************************************** +; PUSH CX +; MOV USER_OPTION, NO_OPTION ;ASSUME NO /1 IS ENTERED. +; XOR CX, CX +; MOV CL, BYTE PTR DS:BEGIN_UNFORM_AREA ;GET # OF CHR +; CMP CL, 0 +; $IF NZ +; CLD ;CLEAR DIRECTION +; MOV DI, BEGIN_UNFORM_AREA+2 ;STARTING POINT OF PARA +; DEC CL ;TO IGNORE LAST CHR (0DH) +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. THE POINTER +; ; WILL POINT TO THE NEXT NON_BLANK CHR +; +; $IF NZ ;SOMETHING OTHER THAN BLANKS +; ; ARE ENTERED +; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 ? +; +; JNC SLASH_ONE ;YES +; CALL CHK_DRV_SPEC ;IS IT A DRIVE SPECIFICATION LIKE d: ? +; +; JC INVALID_PARA ;IF NOT, THEN ERROR +; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN, OK. (EX. DISKCOPY D:) +; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 ? +; +; JNC SLASH_ONE ;YES.(EX. DISKCOPY D:/1) +; CALL CHK_BLANK ;IF NOT, NEXT CHR SHOULD BE A BLANK. +; +; JC INVALID_PARA ;OTHERWISE, ERROR. +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. +; +; JZ CHK_PARA_EXIT ;(EX. DISKCOPY D: ) +; CALL CHK_SLASH_ONE ;IS IT A /1 ? +; +; JNC SLASH_ONE ;YES. (EX. DISKCOPY D: /1) +; CALL CHK_DRV_SPEC ;IF NOT /1, THEN IS IT A DRV SPEC? +; +; JC INVALID_PARA ;OTHERWISE, ERROR. +; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. +; +; JZ CHK_PARA_EXIT ;NO MORE CHR. (EX. DISKCOPY D: D:) +; CALL CHK_SLASH_ONE ;OTHERWISE, IT SHOULD BE /1. +; +; JNC SLASH_ONE ;YES, /1. JMP TO SLASH_ONE +; JMP INVALID_PARA ;PARAMETER ERROR. +;SLASH_ONE: +; MOV USER_OPTION, OPTION_1 ;YES, /1 HAS BEEN ENTERED. +; CALL SKIP_BLANKS ;/1 SHOULD BE END OF PARAMETERS, OR ONLY BLANKS CAN FOLLOW. +; +; $IF NZ +;INVALID_PARA: +; MOV DX,OFFSET MSG_INVALID_PARM_PTR ;WRONG PARM ENTERED MSG +; $ENDIF +; $ENDIF +; $ENDIF +;CHK_PARA_EXIT: +; POP CX +; +; RET +;CHK_PARA ENDP +; HEADER +;*************************************************************************** +;SKIP_BLANKS PROC NEAR +; ** SKIP BLANKS, OR TABS IF ANY, IN THE PARAMETER STRING. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR. * +; CX - # OF REMAINING CHR IN THE STRING. * +; OUTPUT: ES:DI POINT TO THE NEXT NON_BLANK CHR. * +; CX IS ADJUSTED ACCORINGLY. * +; IF THE CURRENT CHR IS NOT A BLANK, THEN DI, CX VALUE NOT CHANGED.* +; IF CX = 0, THEN ZERO FLAG WILL BE SET AND EXIT THIS PROC. * +;*************************************************************************** +; $DO +; MOV AL, 20H ;20H=BLANK +; CLD ;CLEAR DIRECTION +; REPE SCASB +; $LEAVE Z ;IF NOT FOUND A NON_BLANK CHR YET, AND CX=0, EXIT THIS ROUTINE. +; DEC DI ;OTHERWISE, RESTORE DI TO THE NON_BLANK POSITION. +; INC CX ; AND RESTORE CX TO WHERE IT WAS AT NON_BLANK CHR +; ;(IF FOUND A NON_BLANK CHR, ZERO FLAG WOULD NOT BE SET) +; MOV AL, ES:BYTE PTR [DI] +; CMP AL, 09H ;09H=TAB +; $LEAVE NZ ;IF THE NON_BLANK CHR IS NOT A TAB THEN EXIT +; INC DI ;ELSE TRY SKIP AGAIN +; DEC CX +; $ENDDO +; RET +;SKIP_BLANKS ENDP +; HEADER +;*************************************************************************** + +;kiser: this proc is to be deleted + +;CHK_SLASH_ONE PROC NEAR +; ** CHECK CURRENT CHR IS / FOLLOWED BY 1. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * +; CX REPRESENTS THE # OF CHR'S IN THE STRING. * +; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX CHANGED ACCORDINGLY. * +; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * +; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;*************************************************************************** +; +; CLC ;CLEAR CARRY FLAG +; CMP CX, 2 ;# OF CHR IN THE STRING. +; $IF NL,AND ;IF LESS THAN 2, THEN SET CARRY AND EXIT. +; +; MOV AX, ES:WORD PTR [DI] ;GET CURRENT WORD IN AX +; CMP AX, '1/' ;IS IT /1 ? +; $IF Z ;IF NOT, THEN SET CARRY AND EXIT +; INC DI ;ADJUST CX, DI TO THE NEXT CHR +; INC DI +; DEC CX +; DEC CX +; CMP CX, 0 ;IF NO MORE CHR, THEN SET ZERO FLAG. +; $ELSE +; STC ;NOT FOUND, SET CARRY FLAG. +; $ENDIF +; RET +;CHK_SLASH_ONE ENDP +; HEADER +;*************************************************************************** + +;kiser: this proc is to be deleted + +;CHK_DRV_SPEC PROC NEAR +; ** CHECK CURRENT CHR IS ALPHA CHR FOLLOWED BY COLON. * +; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * +; CX -- # OF CHR IN THE STRING. * +; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX ADJUSTED ACCORDINGLY. * +; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * +; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;*************************************************************************** + +; CLC ;CLEAR CARRY +; CMP CX, 2 ;# OF CHR REMAINING IN THE STRING. +; $IF NL,AND ;IF NOT LESS THAN 2, THEN FOUND +; ;IF LESS THAN 2, THEN NOT FOUND - SET CARRY AND EXIT. +; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR +; AND AL, 11011111B ;CHANGE IT TO UPPER_CASE CHR. +; CMP AL, 'A' +; $IF NB,AND ;NOT BELOW 'A', THEN MAYBE FOUND OK +; +; CMP AL, 'Z' +; $IF NA,AND ;NOT ABOVE 'Z', THEN FOUND +; +; MOV AL, ES:BYTE PTR [DI+1] ;LOOK AHEAD THE FOLLOWING CHR. +; CMP AL, ':' ;SHOULD BE A COLON. +; $IF Z ;IF FOUND. +; INC DI ;FOUND. ADJUST CX, DI TO THE NEXT CHR. +; INC DI +; DEC CX +; DEC CX +; CMP CX, 0 ;IF NO MORE CHR, THAN SET THE ZERO FLAG. +; $ELSE +; STC ;SET CARRY +; $ENDIF +; RET +;CHK_DRV_SPEC ENDP +; HEADER +;*************************************************************************** + +;kiser: this proc is to be deleted + +;CHK_BLANK PROC NEAR +;; ** CHECK THE CURRENT CHR IS A BLANK OR TAB * +;; INPUT: ES:DI POINTS TO THE CURRENT CHR. * +; CX - # OF CHR IN THE STRING. * +; OUTPUT: FOUND - DI MOVES TO THE NEXT CHR. CX DECREASES BY 1. * +; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * +;*************************************************************************** + +; CLC ;CLEAR CARRY +; CMP CX, 1 ;IF LESS THAN 1, NOT FOUND. +; $IF L,OR ;GO SET CARRY AND EXIT +; +; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR +; CMP AL, 020H ;020H=BLANK CHR +; $IF NZ,AND ;NOT FOUND +; CMP AL, 09H ;09H=TAB CHR +; $IF NZ ;NOT FOUND EITHER +; +; ;THEN NOT FOUND +; STC ;SET CARRY +; $ELSE ;CHAR MUST BE EITHER TAB OR BLANK +; INC DI ;FOUND. ADJUST DI, CX +; DEC CX +; $ENDIF +; RET +;CHK_BLANK ENDP +.LIST + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : SOURCE_TARGET_DRV DETERMINES SOURCE & TARGET DRIVES & * +; CONVERT THEM FROM DOS TO BIOS VALUE * +; INPUT : SOURCE_DRIVE & TARGET_DRIVE HAVE DOS DRIVE ID'S: * +; 0 = DEFAULT 1 = DRV A * +; 2 = DRV B 3 = DRV C ETC * +; * +; * +; OUTPUT : DEFAULT_DRV: CURRENT DEFAULT DRIVE * +; 0 - DRIVE A 1 - DRIVE B * +; 2 - DRIVE C 3 - DRIVE D * +; * +; : SOURCE_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * +; : TARGET_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * +; (UNCHANGED) * +;****************************************************************************** +SOURCE_TARGET_DRV PROC NEAR + PUBLIC SOURCE_TARGET_DRV ;MAKE ENTRY IN LINK MAP ;AN000; + ;GET CURRENT DEFAULT DRIVE + MOV AH,CURRENTDRV_FUNC ;FUNCTION CALL (19H) + ;(AL <- CURRENT DEFAULT DRV + INT 21H ;0 = A, 1 = B, ETC) + + MOV DEFAULT_DRV,AL ;SAVE IT + INC AL ;NOW A=1, B=2, ETC ;AN000; + CMP SOURCE_DRIVE,ZERO ;FIRST DRV ENTERED? ;AC000; +; $IF E ;NO DRIVE LETTER ENTERED + JNE $$IF7 + MOV SOURCE_DRIVE,AL ;USE DEFAULT DRIVE AS SOURCE ;AC000; + MOV TARGET_DRIVE,AL ; AND AS TARGET ;AC000; +; $ELSE + JMP SHORT $$EN7 +$$IF7: + CMP TARGET_DRIVE,ZERO ;WAS THE SECOND DRIVE ID SPECIFIED? ;AC000; +; $IF E ;NO, SO TARGET DRV IS DEFAULT ;AC000; + JNE $$IF9 + MOV TARGET_DRIVE,AL ;USE DEFAULT DRIVE AS TARGET ;AC000; +; $ENDIF +$$IF9: +; $ENDIF +$$EN7: + MOV AX,WORD PTR SOURCE_DRIVE ;SOURCE TO AL, TARGET TO AH ;AC000; + ADD ASCII_DRV1_ID,AL ;MAKE THE DRIVE ALPHABET READABLE + ADD ASCII_DRV2_ID,AH ;IN THE MESSAGE + + RET + +SOURCE_TARGET_DRV ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : TEST_DRIVE_VALIDITY--MAKE SURE SOURCE AND TARGET DRIVES * +; SPECIFIED BY USER ARE VALID FOR DISKCOPY * +; * +; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE * +; * +; OUTPUT : DX='FINE' IF DRIVES ARE VALID, ELSE DX CONTAINS MSG PTR * +;****************************************************************************** + +TEST_DRIVE_VALIDITY PROC NEAR + PUBLIC TEST_DRIVE_VALIDITY ;MAKE ENTRY IN LINK MAP ;AN000; + + CALL DOS_DRIVE_VALIDITY + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF12 + + MOV BL,SOURCE_DRIVE + CALL CHECK_REDIRECTION + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF12 + + MOV BL,TARGET_DRIVE + CALL CHECK_REDIRECTION + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF12 + + MOV BL,SOURCE_DRIVE + CALL CHECK_SERVER + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF12 + + MOV BL,TARGET_DRIVE + CALL CHECK_SERVER + + CMP DX,FINE +; $IF E,AND ; ;AC000; + JNE $$IF12 + + CALL TEST_REMOVABLE + + CMP DX,FINE +; $IF E ; ;AC000; + JNE $$IF12 + + CALL CHK_SINGLE_DRV_OP ;CHECK IF IT IS + ; ONE PHYSICAL DRIVE OPERATION +; $ENDIF ; ;AC000; +$$IF12: + RET + +TEST_DRIVE_VALIDITY ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : DOS_DRIVE_VALIDITY -- CHECK DOS DRIVE VALIDITY BYTE * +; * +; INPUT : DRIVE_VALID:BYTE * +; * +; OUTPUT : DX="FINE" IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * +;****************************************************************************** + +DOS_DRIVE_VALIDITY PROC NEAR + + CMP DRIVE_VALID,0 ;SEE IF DRIVES ARE VALID DOS DEVICE +; $IF NE + JE $$IF14 + MOV DX,OFFSET MSGNUM_INVALID_DRV ; ;AC000; +; $ENDIF +$$IF14: + RET + +DOS_DRIVE_VALIDITY ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : TEST_REMOVABLE -- CHECK IF DRIVES SPECIFED ARE REMOVABLE * +; * +; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE * +; * +; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * +;****************************************************************************** + +TEST_REMOVABLE PROC NEAR + + MOV BL,SOURCE_DRIVE ;GET PARM 1 DRIVE ID + + MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE = 4408h + INT 21H ;IOCTL CALL +; $IF NC ;IF DRIVE ID IS WITHIN RANGE + JC $$IF16 + CMP AX,REMOVABLE ;THEN IF SOURCE DRIVE IS FIXED +; $IF NE ; THEN + JE $$IF17 + MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE HARD ;AC000; + ; DRIVE ERROR MESSAGE +; $ELSE ;ELSE, SRC IS REMOVABLE; + JMP SHORT $$EN17 +$$IF17: + MOV BL,TARGET_DRIVE ;NOW GO CHECK TARGET + + MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE + INT 21H ;IOCTL CALL +; $IF NC ;IF DRV WITHIN RANGE + JC $$IF19 + CMP AX,REMOVABLE ;THEN TGT DRV IS FIXED +; $IF NE ; THEN + JE $$IF20 + MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE HARD ;AC000; + ; DRV ERROR MSG +; $ENDIF ;END TEST IF TGT DRV IS FIXED +$$IF20: +; $ELSE ;TGT DRV OUT OF RANGE. EX. DRIVE X: + JMP SHORT $$EN19 +$$IF19: + MOV DX,OFFSET MSGNUM_INVALID_DRV ; ;AC000; +; $ENDIF ;END TEST IF TGT WITHIN RANGE +$$EN19: +; $ENDIF ;END IF SRC IS REMOVABLE +$$EN17: +; $ELSE ;ELSE, SRC DRV OUT OF RANGE + JMP SHORT $$EN16 +$$IF16: + MOV DX,OFFSET MSGNUM_INVALID_DRV ;PRINT ERROR MSG ;AC000; +; $ENDIF ;END TEST IF SRC DRV WITHIN RANGE +$$EN16: + RET + +TEST_REMOVABLE ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : CHK_SINGLE_DRV_OP * +; * +; INPUT : SOURCE_DRIVE - LOGICAL DRIVE NUMBER * +; TARGET_DRIVE * +; * +; OUTPUT : COPY_TYPE WILL BE SET TO ONE OR TWO DEPENDING ON THE * +; TEST RESULT. IF IT IS A SINGLE DRIVE COPY, THEN * +; TARGET DRIVE LETTER WILL BE CHANGED TO THAT OF SOURCE. * +; THE OWNERSHIP OF THE SOURCE AND TARGET DRIVE LETTER * +; MIGHT HAVE BEEN CHANGED. * +; SO, BEFORE EXIT TO DOS, THEY SHOULD BE RESET TO THE SAVED* +; ONE USING S_OWNER_SAVED AND T_OWNER_SAVED UNLESS THEY * +; ARE EQUAL TO 0. (0 MEANS ONLY ONE DRIVE LETTER ASSIGNED.)* +; ASCII_DRV1_ID, ASCII_DRV2_ID MAY BE CHANGED ACCORDINGLY. * +;****************************************************************************** + +CHK_SINGLE_DRV_OP PROC NEAR + + PUSH AX + + MOV BL,SOURCE_DRIVE + CALL GET_LOGICAL_DRIVE + + MOV S_OWNER_SAVED, AL ;SAVE CURRENT OWNER DRIVE LETTER. + MOV BL, TARGET_DRIVE + CALL GET_LOGICAL_DRIVE + + MOV T_OWNER_SAVED, AL ;SAVE CURRENT OWNER + MOV BL, SOURCE_DRIVE + CALL SET_LOGICAL_DRIVE + + MOV BL, TARGET_DRIVE + CALL SET_LOGICAL_DRIVE + + MOV BL, SOURCE_DRIVE + CALL GET_LOGICAL_DRIVE ;CHECK SOURCE DRV LETTER + ; STILL HAS A OWNERSHIP. + + CMP AL, SOURCE_DRIVE ; +; $IF NE ;IF IT DOES NOT, THEN A + JE $$IF27 + ; SINGLE DRIVE COPY. + MOV COPY_TYPE, ONE + MOV BL, SOURCE_DRIVE + MOV TARGET_DRIVE, BL ;SET TARGET DRV LETTER + ; TO THAT OF SOURCE + MOV BL, ASCII_DRV1_ID + MOV ASCII_DRV2_ID, BL + MOV BL, SOURCE_DRIVE + CALL SET_LOGICAL_DRIVE ;SET THE OWNER BACK TO + ; SOURCE DRV LETTER + +; $ELSE + JMP SHORT $$EN27 +$$IF27: + CMP AL, TARGET_DRIVE ;SOURCE DRV LETTER = TARGET DRV + ; LETTER CASE, FOR EX. DISKCOPY A: A: +; $IF E + JNE $$IF29 + MOV COPY_TYPE, ONE +; $ELSE + JMP SHORT $$EN29 +$$IF29: + MOV COPY_TYPE, TWO +; $ENDIF +$$EN29: +; $ENDIF +$$EN27: + + POP AX + + RET +CHK_SINGLE_DRV_OP ENDP + HEADER ;AN000; +;****************************************************************************** +GET_LOGICAL_DRIVE PROC NEAR +; *** GET THE LOGICAL DRIVE NUMBER WHO HAS THE OWNERSHIP OF THE PHYSICAL +; DRIVE. +; INPUT: BL = DRIVE NUMBER (0=DEFAULT, 1=A, 2=B...) +; OUTPUT: AL = DRIVE NUMBER (0= ONLY ONE DRIVE LETTER ASSIGNED TO THE +; BLOCK DEVICE. OTHERWISE, 1=A, 2=B...) +; +;****************************************************************************** + + MOV AH, 44H + MOV AL, 0EH ; GET THE OWNER OF LOGICAL DRIVE NUMBER + INT 21H + CMP AL, 0 ;ONLY ONE DRIVE LETTER ASSIGNED? +; $IF E + JNE $$IF33 + MOV AL, BL ;THEN SET THE INPUT DRIVE NUMBER TO AL. +; $ENDIF +$$IF33: + + RET + +GET_LOGICAL_DRIVE ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : DISKETTE_DRV_TYPE DOES THE FOLLOWING: * +; - GETS SOURCE, TARGET DRIVE INFORMATION * +; - CHECK REMOVABLE DRIVE * +; *** REMARK: WILL NOT ALLOW DISKCOPY BETWEEN 5.25" AND 3.5" DRIVES. * +; *** ALSO, IN THE MAIN PROGRAM, SOURCE MEDIA BPB INFORMATIONS (# OF SEC/TRK, * +; *** # OF TRACKS) SHOULD BE CHECKED AGAINST TARGET DEVICE INFORMATIONS. * +; *** IF # OF SECT/TRACK, # OF TRACKS OF TARGET DEVICE ARE EQUAL TO, OR * +; *** GREATER THAN THOSE OF THE SOURCE MEDIA BPB, THEN IT IS OK. OTHERWISE * +; *** DEVICE NOT COMPATIBLE. * +; *** IF THIS DOES NOT GAURANTEES COMPATIBILITY BETWEEN SOURCE AND TARGET * +; *** DEVICE OR MEDIA, EVENTUALLY, FAILURE TO FORMAT THE TARGET WILL * +; *** TELL THAT SOURCE, TARGET DEVICE OR MEDIA ARE NOT COMPATIBLE. * +; * +;****************************************************************************** +DISKETTE_DRV_TYPE PROC NEAR + PUSH AX + + xor bx, bx + MOV BL, SOURCE_DRIVE + MOV CL, GETDEVPARM ;=60h + MOV DX, OFFSET DS_IOCTL_DRV_PARM ;POINTER TO THE CONTROL STRING + CALL GENERIC_IOCTL ;GET DEFAULT DEVICE PARM. + + TEST DS_deviceAttributes, 0001h ;CHECK REMOVABLE. 0001 = NOT REMOVABLE +; $IF E,AND ;NO, CONTINUE ;AC000; + JNE $$IF35 + + MOV AX, DS_numberOfCylinders ;CURRENTLY IGNORE AH. ASSUME LESS + ; THAN TWO BYTES + MOV S_DRV_TRACKS, AL + MOV BX, OFFSET DS_BPB_PTR + MOV AX, [BX].CHead + MOV S_DRV_HEADS, AL + MOV AX, [BX].CSECT_TRACK + MOV S_DRV_SECT_TRACK, AL + MOV AX, [BX].CBYTE_SECT ;RECOMMENDED BYTES/SECTOR + MOV RECOMMENDED_BYTES_SECTOR, AX + + XOR BX,BX + MOV BL, TARGET_DRIVE + MOV CL, GETDEVPARM + MOV DX, OFFSET DT_IOCTL_DRV_PARM + CALL GENERIC_IOCTL ;GET DEFAULT DEVICE PARM. + + TEST DT_deviceAttributes, 0001h ;FIXED DISK? +; $IF Z ;TARGET IS NOT FIXED DISK, OK ;AC000; + JNZ $$IF35 + + MOV AX, DT_numberOfCylinders + MOV T_DRV_TRACKS, AL + MOV BX, OFFSET DT_BPB_PTR + MOV AX, [BX].CHead + MOV T_DRV_HEADS, AL + MOV AX, [BX].CSECT_TRACK + MOV T_DRV_SECT_TRACK, AL + +;**NOW, CHECK SOURCE, TARGET DEVICE COMPATIBILITY + MOV DX, FINE ;GUESS, ALL WILL BE OK + ; DX MAY BE CHANGED TO REFLECT ERROR + CMP DS_deviceType, DRV_720 ;0 - 48 TPI, 5.25", 96 TPI, + ; 5.25", 2 - 720kb, 3.5" +; $IF E ;WILL ONLY ALLOW DISKCOPY BETWEEN ;AC000; + JNE $$IF36 + ; 720KB, 3.5 SOURCE, TARGET + + CMP DT_deviceType, DRV_720 ;target = 720KB also? +; $IF NE ; ;AC000; + JE $$IF37 + MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ;AC000; +; $ENDIF ; ;AC000; +$$IF37: +; $ELSE ;SINCE SOURCE NOT 720 ;AC000; + JMP SHORT $$EN36 +$$IF36: + CMP DT_deviceType, DRV_720 ;SOURCE IS NOT 720kb, + ; IS TARGET 720? +; $IF E ;IF SO, THEN ;AC000; + JNE $$IF40 + ;DDT IS NOT COMPATIBLE + MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ; ;AC000; +; $ENDIF ; ;AC000; +$$IF40: +; $ENDIF ; ;AC000; +$$EN36: +; $ELSE ;SINCE SOURCE IS FIXED DISK, ERROR ;AC000; + JMP SHORT $$EN35 +$$IF35: + MOV DX, OFFSET MSGNUM_INVALID_DRV ;ISSUE BAD DRV MSG ;AC000; +; $ENDIF ; ;AC000; +$$EN35: + POP AX + RET + +DISKETTE_DRV_TYPE ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : CHECK_REDIRECTION FIND OUT IF DEVICE IS REDIRECTED * +; IF IT IS, GENERATE ERROR MSG & EXIT * +; INPUT : BL - DRIVE TO BE TESTED * +; : AL : CURRENT DEFAULT DRIV * +; * +; OUTPUT : DX = LOCAL_DRV (-1) * +; = DIRECTED ( ERROR MSG OFFSET) * +; = INVALID_DRIVE (ERROR MSG OFFSET) * +;****************************************************************************** +CHECK_REDIRECTION PROC NEAR + + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + + MOV CX,DX ;SAVE RET TEMPORARILY + MOV AH,IOCTL_FUNC ;GET IOCTL FUNTION & + MOV AL,REDIRECTED_FUNC ;IOCTL SUB-FUNCTION ******CHECK*** + + INT 21H ;AND GO FIND OUT IF IT'S LOCAL +; $IF C + JNC $$IF45 + MOV CX,OFFSET MSGNUM_INVALID_DRV ;REDIR INVALID ;AC000; + +; $ELSE + JMP SHORT $$EN45 +$$IF45: + TEST DX,REMOTE_DRV ;IF DRIVE IS REDIRECTED +; $IF NZ + JZ $$IF47 + + MOV CX,OFFSET MSGNUM_DRV_REDIRECTED ; ;AC000; +; $ENDIF +$$IF47: +; $ENDIF +$$EN45: + MOV DX,CX ;GET ERROR MSG @ + + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET ;RETURN TO CALLER +CHECK_REDIRECTION ENDP + HEADER ; ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : BUFFER_SIZE DETERMINES WHERE BUFFER STARTS & ENDS * +; INPUT : NONE * +; * +; OUTPUT : BUFFER_BEGIN ADDRESS * +; : BUFFER_END ADDRESS * +;****************************************************************************** +BUFFER_SIZE PROC NEAR + + + PUSH AX ;SAVE REGISTERS + PUSH BX + PUSH CX + MOV BX, offset init ;GET ADDR OF INIT + 1024 AS + ; A START OF BUFFER + add bx, 1024 ;(OFFSET FROM CS, IN BYTES) + MOV CL,4 ;CONVERT OFFSET INTO SEGMT BY DIVIDING + SHR BX,CL ;IT BY 16 + + MOV AX,CS ;CS + OFFSET => INIT+1024@ IN SEGMENT + ADD BX,AX ;WHERE BUFFER CAN START + + ;NEED TO START AT A NEW SECTOR ==> + AND BL,CLEAR_SEGMENT ;TRUNCATE TO PREVIOUS 512 BYTE BOUNDRY + ;(GET PREVIOUS SECTOR NUMBER) + ADD BX,20H ;THEN, ADVANCE TO THE BEGINNING OF + ;NEXT SECTOR (SINCE PART OF PREVIOUS + ;SECTOR WAS USED) + + MOV BUFFER_BEGIN,BX ;SAVE OUR BUFFER START SEGMENT ADDR + ;(AT THE BEGINNING OF A SECTOR WITH + ;SEGMENT BITS CLEARED) + + MOV BX,DS:TWO ;GET ADDR WHERE BUFFER ENDS + MOV BUFFER_END,BX ;(TOP OF MEMORY, OFFSET 2 IN PSP) + + POP CX ;RESTORE REGISTERS + POP BX + POP AX + RET ;RETURN TO CALLER +BUFFER_SIZE ENDP + HEADER ; ;AN000; +;****************************************************************************** +SETUP_CTRL_BREAK PROC NEAR ;SETUP CTRL-BREAK VECTOR +;****************************************************************************** + PUSH AX + PUSH BX + PUSH DX + PUSH ES + + MOV AX,SET_CTL_BREAK_VECT ;SET THE CTRL-BREAK VECTOR + MOV DX,OFFSET MAIN_EXIT + INT 21H + + POP ES + POP DX + POP BX + POP AX + RET + +SETUP_CTRL_BREAK ENDP + HEADER ; ;AN000; +;****************************************************************************** +CHECK_SERVER PROC NEAR ;SEE IF SERVER OR REDIRECTOR IS IN++ +; +; INPUT: BL = DRIVE NUMBER (1=A,2=B ETC....) +;****************************************************************************** + MOV AH,0 ;SEE IF SERVER LOADED + INT SERVER + CMP AH,0 +; $IF E + JNE $$IF50 + MOV DX,FINE +; $ELSE + JMP SHORT $$EN50 +$$IF50: + DEC BL + ADD BL,"A" ;CONVERT TO ASCII DRIVE LETTER + MOV ASCII_DRIVE_LETTER,BL ;PUT IN ASCIIZ STRING + MOV SI,OFFSET ASCII_DRIVE_LETTER + MOV AH,SHARED + CLC + INT SERVER +; $IF C + JNC $$IF52 + MOV DX,OFFSET MSGNUM_DRV_REDIRECTED ; ;AC000; +; $ELSE + JMP SHORT $$EN52 +$$IF52: + MOV DX,FINE +; $ENDIF +$$EN52: +; $ENDIF +$$EN50: + RET +CHECK_SERVER ENDP + +COPYINIT_END LABEL NEAR + PUBLIC COPYINIT_END + + PATHLABL COPYINIT ;AN015; + +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DCOPYMS.INC b/v4.0/src/CMD/DISKCOPY/DCOPYMS.INC new file mode 100644 index 0000000..2cb7622 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DCOPYMS.INC @@ -0,0 +1,269 @@ +;:util DISKCOPY ;utility name +;:class 1 ;DOS extended errors: +;:class 2 ;parse errors: +;1 Too many parameters +;2 Required parameter missing +;3 Invalid switch +;4 Invalid keyword +;5 Parameter value not in allowed range +;6 Parameter value not allowed [parse ret codes 6 and 7] +;7 (undefined) +;8 Parameter format not correct +;9 (undefined) +;10 Invalid parameter [no corresponding parse ret code] +;11 Invalid parameter combination [no corresponding parse ret code] +;; +;:class A ;system messages +;:use 1 COMMON1 ;MSG 1 is always "Incorrect DOS version" +;; +;:def 2 CR,LF +; +;:use 3 PARSE10 ;CR,LF,"Invalid parameter",CR,LF +; +;:def 4 "Do not specify filename(s)",CR,LF +;"Command Format: DISKCOPY d: d: [/1]",CR,LF +;; +;:def 5 CR,LF,"Invalid drive specification",CR,LF +;"Specified drive does not exist",CR,LF +;"or is non-removable",CR,LF +; +;:def 6 CR,LF,"Cannot DISKCOPY to or from",CR,LF +;"a network drive",CR,LF +; +;:def 7 CR,LF,"Formatting while copying",CR,LF +; +;:def 8 CR,LF,"Insert SOURCE diskette in drive %1:",CR,LF +; +;:def 9 CR,LF,"Insert TARGET diskette in drive %1:",CR,LF +; +;:def 10 "Make sure a diskette is inserted into",CR,LF +;"the drive and the door is closed",CR,LF +; +;:def 11 CR,LF,"Target diskette may be unusable",CR,LF +; +;:def 12 CR,LF,"Target diskette unusable",CR,LF +; +;:use 13 EXTEND21 ;CR,LF,Drive not ready",CR,LF +; +;:use 14 EXTEND19 ;CR,LF,"Attempt to write to write-protected diskette",CR,LF +; +;:use 15 COMMON28 ;CR,LF,"Press any key to continue . . .",CR,LF +; +;:def 16 CR,LF,"Copy another diskette (Y/N)? " +; +;:def 17 CR,LF,"Copying %1 tracks",CR,LF +;"%2 Sectors/Track, %3 Side(s)",CR,LF +; +;:def 18 CR,LF,"Drive types or diskette types",CR,LF +;"not compatible",CR,LF +; +;:def 19 CR,LF,"Unrecoverable read error on drive %1",CR,LF +;"Side %2, track %3",CR,LF +; +;:def 20 CR,LF,"Unrecoverable write error on drive %1",CR,LF +;"Side %2, track %3",CR,LF +; +;:def 21 CR,LF,"Copy process ended",CR,LF +; +;:def 22 CR,LF,"SOURCE diskette bad or incompatible" +; +;:def 23 CR,LF,"TARGET diskette bad or incompatible" +; +;:use 25 EXTEND8 ;CR,LF,"Insufficient memory",CR,LF +; +;:use 26 COMMON36 ;"Volume Serial Number is %1-%2",CR,LF +; +;:end +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + IF1 ;AN000; + %OUT COMPONENT=DISKCOPY, MODULE=DCOPYMS.INC... ;AN000; + ENDIF ;AN000; +; $SALUT (0,13,18,22) ; ;AN000; +;THIS MODULE IS INCLUDED IN DCOPYSM.SAL. +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; + +FOUR_SUBS EQU 4 ;AN000;FOUR VARIABLES IN ONE MSG +PC_ID_4 EQU 4 ;AN000;IDENTIFIES FOURTH REPLACEMENT PARM +LETTER_A EQU "A" ;AN000;DEFAULT DRIVE ID +PAD_0 EQU "0" ;AN001;PAD CHAR FOR NUMERIC FIXED LEN FIELD +FILL_OFF EQU 0 ;AN000;TO BE FILLED IN WITH OFFSET TO DATA +FILL_SEG EQU 0 ;AN000;TO BE FILLED IN WITH THE COMMON SEG ID + ; SINCE A .COM FILE CANNOT HAVE + ; SEGMENT FIXUP RECORDS + +; DOS FUNCTIONS REFERENCED: +CLEAR_BUF EQU 0C0H ;AN007;CLEAR KEYBOARD BUFFER BEFORE INPUT +KEY_IN EQU 08H ;AN000;WAIT FOR STD INPUT, NO ECHO + ;OUTPUT: AL = CHAR FROM KEYBOARD + ;CTL-BREAK IS CHECKED FOR + +KEY_IN_ECHO EQU 01H ;AN000;WAIT FOR STD INPUT, ECHO RESPONSE + ;OUTPUT: AL = CHAR FROM KEYBOARD + ;CTL-BREAK IS CHECKED FOR + +SUBLIST_PARSE SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS ,MAX_0,MIN_1,PAD_BLK> ;AN003; + PUBLIC SUBLIST_PARSE ;AN003; + +; THE NEXT GROUP ARE ADDITIONAL CLASS "A" MESSAGES +; SPECIFICALLY DEFINED FOR THE DISKCOPY UTILITY + + ;CR,LF +MSGNUM_CR_LF MSG_DESC <2> ;AN000; + PUBLIC MSGNUM_CR_LF ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Invalid parameter",CR,LF +MSGNUM_INVALID_PARM MSG_DESC <3> ;AN000; + PUBLIC MSGNUM_INVALID_PARM ;AN000; +; = = = = = = = = = = = = = = = = + ; "Do not specify filename(s)",CR,LF + ; "Command Format: DISKCOPY d: d: [/1]",CR,LF +MSGNUM_INVALID_PARM2 MSG_DESC <4> ;AN000; + PUBLIC MSGNUM_INVALID_PARM2 ;AN000; +; = = = = = = = = = = = = = = = = + ;:def 5 CR,LF,"Invalid drive specification",CR,LF + ;"Specified drive does not exist",CR,LF + ;"or is non-removable",CR,LF +MSGNUM_INVALID_DRV MSG_DESC <5> ;AN000; + PUBLIC MSGNUM_INVALID_DRV ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Cannot DISKCOPY to or from",CR,LF + ;"a network drive",CR,LF +MSGNUM_DRV_REDIRECTED MSG_DESC <6> ;AN000; + PUBLIC MSGNUM_DRV_REDIRECTED ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Formatting while copying",CR,LF +MSGNUM_FORMATTING MSG_DESC <7> ;AN000; + PUBLIC MSGNUM_FORMATTING ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Insert SOURCE diskette in drive %1:",CR,LF +MSGNUM_LOAD_SOURCE MSG_DESC <8,,SUBLIST_8,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_LOAD_SOURCE ;AN000; + +SUBLIST_8 SUBLIST <,,ASCII_DRV1_ID,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_8 ;AN000; + +ASCII_DRV1_ID DB LETTER_A - BYTE;AN000; + PUBLIC ASCII_DRV1_ID ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Insert TARGET diskette in drive %1:",CR,LF +MSGNUM_LOAD_TARGET MSG_DESC <9,,SUBLIST_9,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_LOAD_TARGET ;AN000; + +SUBLIST_9 SUBLIST <,,ASCII_DRV2_ID,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_9 ;AN000; + +ASCII_DRV2_ID DB LETTER_A - BYTE ;AN000;A:=1, B:=1, ETC + PUBLIC ASCII_DRV2_ID ;AN000; +; = = = = = = = = = = = = = = = = + ;:def 10 "Make sure a diskette is inserted into",CR,LF + ;"the drive and the door is closed",CR,LF +MSGNUM_CLOSE_DOOR MSG_DESC <10> ;AN004; + PUBLIC MSGNUM_CLOSE_DOOR ;AN004; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Target diskette may be unusable",CR,LF +MSGNUM_TARGET_MB_UNUSABLE MSG_DESC <11> ;AN000; + PUBLIC MSGNUM_TARGET_MB_UNUSABLE ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Target diskette unusable",CR,LF +MSGNUM_TARGET_UNUSABLE MSG_DESC <12> ;AN000; + PUBLIC MSGNUM_TARGET_UNUSABLE ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Drive not ready - %0",CR,LF +MSGNUM_GET_READY MSG_DESC <13,,SUBLIST_13,ONE_SUBS> ;AN000; + PUBLIC MSGNUM_GET_READY ;AN000; + +SUBLIST_13 SUBLIST <,,DRIVE_LETTER,FILL_SEG,PC_ID_0,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_13 ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Attempt to write to write-protected diskette",CR,LF +MSGNUM_WRITE_PROTECT MSG_DESC <14> ;AN000; + PUBLIC MSGNUM_WRITE_PROTECT ;AN000; +; = = = = = = = = = = = = = = = = + ;"Press any key to continue . . .",CR,LF +MSGNUM_STRIKE MSG_DESC <15,,,,(CLASS_A SHL 8) OR (CLEAR_BUF + KEY_IN)> ;AN007; + PUBLIC MSGNUM_STRIKE ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Copy another diskette (Y/N)? " + ; AND READ RESPONSE TO AL + ; (EVENTUALLY EXPECTED IN "USER_INPUT") +MSGNUM_COPY_ANOTHER MSG_DESC <16,,,,(CLASS_A SHL 8) OR (CLEAR_BUF + KEY_IN_ECHO)> ;AN007; + PUBLIC MSGNUM_COPY_ANOTHER ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Copying %1 tracks",CR,LF + ;"%2 Sectors/Track, %3 Side(s)",CR,LF +MSGNUM_COPYING MSG_DESC <17,,SUBLIST_17A,THREE_SUBS> ;AN000; + PUBLIC MSGNUM_COPYING ;AN000; + +SUBLIST_17A SUBLIST <,,MSG_TRACKS,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_17B SUBLIST <,,MSG_SECTRK,FILL_SEG,PC_ID_2,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_17C SUBLIST <,,MSG_SIDES,FILL_SEG,PC_ID_3,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_17A ;AN000; + PUBLIC SUBLIST_17B ;AN000; + PUBLIC SUBLIST_17C ;AN000; + +MSG_TRACKS DW 0 ;AN000;NUMBER OF TRACKS +MSG_SECTRK DW 0 ;AN000;NUMBER OF SECTORS PER TRACK +MSG_SIDES DW 0 ;AN000;NUMBER OF SIDES + PUBLIC MSG_TRACKS ;AN000; + PUBLIC MSG_SECTRK ;AN000; + PUBLIC MSG_SIDES ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Drive types or diskette types",CR,LF + ;"not compatible",CR,LF +MSGNUM_NOT_COMPATIBLE MSG_DESC <18> ;AN000; + PUBLIC MSGNUM_NOT_COMPATIBLE ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Unrecoverable read error on drive %1",CR,LF + ;"Side %2, track %3",CR,LF +MSGNUM_HARD_ERROR_READ MSG_DESC <19,,SUBLIST_19C,THREE_SUBS> ;AN000; + PUBLIC MSGNUM_HARD_ERROR_READ ;AN000; + + ;CR,LF,"Unrecoverable write error on drive %1",CR,LF + ;"Side %2, track %3",CR,LF +MSGNUM_HARD_ERROR_WRITE MSG_DESC <20,,SUBLIST_19C,THREE_SUBS> ;AN000; + PUBLIC MSGNUM_HARD_ERROR_WRITE ;AN000; + +SUBLIST_19C SUBLIST <,,DRIVE_LETTER,FILL_SEG,PC_ID_1,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_19D SUBLIST <,,ERROR_SIDE_NUMBER,FILL_SEG,PC_ID_2,SF_BITS,MAX_0,MIN_1> ;AN000; +SUBLIST_19E SUBLIST <,,ERROR_TRACK_NUMBER,FILL_SEG,PC_ID_3,SF_BITS,MAX_0,MIN_1> ;AN000; + PUBLIC SUBLIST_19C ;AN000; + PUBLIC SUBLIST_19D ;AN000; + PUBLIC SUBLIST_19E ;AN000; + +DRIVE_LETTER DB LETTER_A,":",NULL ;AN000; + PUBLIC DRIVE_LETTER ;AN000; + +ERROR_SIDE_NUMBER DW ? ;AN000; + PUBLIC ERROR_SIDE_NUMBER ;AN000; + +ERROR_TRACK_NUMBER DW ? ;AN000; + PUBLIC ERROR_TRACK_NUMBER ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Copy process ended",CR,LF +MSGNUM_FATAL_ERROR MSG_DESC <21> ;AN000; + PUBLIC MSGNUM_FATAL_ERROR ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"SOURCE diskette bad or incompatible" +MSGNUM_BAD_SOURCE MSG_DESC <22> ;AN000; + PUBLIC MSGNUM_BAD_SOURCE ;AN000; + +; = = = = = = = = = = = = = = = = + ;CR,LF,"TARGET diskette bad or incompatible" +MSGNUM_BAD_TARGET MSG_DESC <23> ;AN000; + PUBLIC MSGNUM_BAD_TARGET ;AN000; +; = = = = = = = = = = = = = = = = + ;CR,LF,"Insufficient memory",CR,LF +MSGNUM_UNSUF_MEMORY MSG_DESC <25> ;AN000; + PUBLIC MSGNUM_UNSUF_MEMORY ;AN000; +; = = = = = = = = = = = = = = = = + ;"Volume Serial Number is %1-%2" +MSGNUM_SERNO MSG_DESC <26,,SUBLIST_26A,TWO_SUBS> ;AN001; + PUBLIC MSGNUM_SERNO ;AN001; + +SUBLIST_26A SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_1,SF_BITS,DWORD,DWORD,PAD_0> ;AN001; +SUBLIST_26B SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_2,SF_BITS,DWORD,DWORD,PAD_0> ;AN001; + PUBLIC SUBLIST_26A,SUBLIST_26B ;AN001; +; = = = = = = = = = = = = = = = = +;end of DCOPYMS.INC + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DCOPYP.ASM b/v4.0/src/CMD/DISKCOPY/DCOPYP.ASM new file mode 100644 index 0000000..344b8c4 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DCOPYP.ASM @@ -0,0 +1,139 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOPYP.SAL - DISKCOPY SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOPYP.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of DISKCOPY. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .COM. +; The Common PARSER is then INCLUDEd. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.ASM statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.ASM statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT DCOPYP,NUL,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOPY.SAL. +; +;PROGRAM AUTHOR: DOS 4.00 EMK +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOPY, MODULE=DCOPYP.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; +; = = = = = = = = = = = = + INCLUDE PATHMAC.INC ;AN015;PATHGEN MACRO +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;AN000; + SUBTTL TEXT ;AN000; +.LIST ;AN000; + PAGE ;;AN000; + ENDM ;;AN000; + +; = = = = = = = = = = = = + HEADER ;AN000; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + +;DISKCOPY INPUT PARMS EXPECTED: +; [D: [d:]] [/1] + + PUBLIC SYSPARSE ;AN000;SUBROUTINE ENTRY POINT + +FARSW EQU 0 ;AN000;CALL THE PARSER BY NEAR CALL +DATESW EQU 0 ;AN000;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;AN000;SUPPRESS TIME CHECKING +FILESW EQU 0 ;AN000;SUPPRESS CHECK FILE SPECIFICATION +CAPSW EQU 1 ;AN000;DO USE FILE TABLE CAPS +CMPXSW EQU 0 ;AN000;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 1 ;AN000;DO SUPPORT DRIVE ONLY FORMAT +QUSSW EQU 0 ;AN000;SUPPRESS SUPPORT OF QUOTED STRING FORMAT +NUMSW EQU 0 ;AN000;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;AN000;SUPPRESS KEYWORD SUPPORT +SWSW EQU 1 ;AN000;DO SUPPORT SWITCHES +VAL1SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 3 +INCSW EQU 0 ;AN000;DO NOT INCLUDE PSDATA.INC +BASESW EQU 1 ;AN014;SPECIFY, PSDATA POINTED TO BY "DS" + + INCLUDE PSDATA.INC ;AN015; + + PATHLABL DCOPYP ;AN015; + INCLUDE PARSE.ASM ;AN000; + PATHLABL DCOPYP ;AN015; + +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DCOPYPAR.ASM b/v4.0/src/CMD/DISKCOPY/DCOPYPAR.ASM new file mode 100644 index 0000000..0b74cec --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DCOPYPAR.ASM @@ -0,0 +1,413 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOPYPAR.SAL - LOOK AT COMMAND LINE PARMS +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOPYPAR.SAL +; +; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters +; and the interface to the DOS system PARSER. +; +;FUNCTION: The static data areas are prescribed by the DOS system PARSER +; to define the several parameters presented to DISKCOPY. These +; data areas are passed to the PARSER, and its responses checked +; to determine the nature of the user's specifications. Any errors +; found in the user's parameters are defined in messages back +; to the user. +; +; ENTRY POINT: PARSER, near +; +; INPUT: (DOS COMMAND LINE PARAMETERS) +; +; [d:][path] DISKCOPY [d: [d:]][/1] +; +; WHERE +; [d:][path] - Path where the DISKCOPY command resides. +; +; [d:] - To specify the Source drive +; +; [d:] - To specify the Destination drive +; +; [/1] - To copy only the first side of the diskette, +; regardless of the diskette or drive type. +; +; Upon entry to PARSER in this module, +; "CURRENT_PARM" = offset to start of parm text in command string +; "ORDINAL" = initialized to zero +; PSP+81H = text of DOS command line parms string + +; EXIT-NORMAL: +; "SOURCE_DRIVE" = CHAR OF FIRST DRIVE ID SPECIFIED, BLANK IF NONE +; "TARGET_DRIVE" = CHAR OF SECOND DRIVE ID IF BOTH SPECIFIED, BLANK +; IF NONE OR ONLY ONE SPECIFIED +; "USER_OPTION" = 01 ON IF /1, -1 IF /1 NOT SPECIFIED. + +; EXIT-ERROR: +; IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR". + +; INTERNAL REFERENCES: +; ROUTINES: +; PARSER:NEAR Call the system Parser to decode command line +; PARSE_ERROR:NEAR Display the appropriate Parse error message. + +; DATA AREAS: +; The several parameter control blocks, defined by the System +; PARSER interface, defining the DISKCOPY parameters. + +; EXTERNAL REFERENCES: +; ROUTINES: +; SENDMSG:NEAR Uses Msg Descriptor to drive message handler. +; SYSPARSE:NEAR System Command Line Common Parser. +; +; DATA AREAS: +; EXITFL:BYTE Errorlevel return code. +; MSGNUM_PARSE:WORD Message descriptor for all parse errors. +; USER_OPTION:BYTE /1 parm indicator +; SOURCE_DRIVE:BYTE character of first specified drive +; TARGET_DRIVE:BYTE character of second specified drive +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT DCOPYPAR,NUL +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOPY.SAL. +; +;PROGRAM AUTHOR: DOS 4.00 EMK +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOPY, MODULE=DCOPYPAR.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + INCLUDE PATHMAC.INC ;AN015;PATHGEN MACRO +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;;AN000; + SUBTTL TEXT ;;AN000; +.LIST ;;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = +; $SALUT (4,23,28,36) ;AN000; +; LOCAL EQUATES + +FALSE EQU 0 ;AN000;RETURN VALUES FOR +TRUE EQU NOT FALSE ;AN000; /1 SWITCH +CHAR_A EQU "A" ;AN000;ASCII VALUE OF CHARACTER "A" +BLANK EQU " " ;AN001; +NUL EQU 0 ;AN003; +; = = = = = = = = = = = = +; EXIT CODES FROM SYSPARSE (WHEN CY=0) + +SYSPRM_EX_OK EQU 0 ;AN000; no error +SYSPRM_EX_MANY EQU 1 ;AN000; too many operands +SYSPRM_EX_MISSING EQU 2 ;AN000; required operand missing +SYSPRM_EX_NOT_SWLIST EQU 3 ;AN000; not in switch list provided +SYSPRM_EX_NOT_KEYLIST EQU 4 ;AN000; not in keyword list provided +SYSPRM_EX_RANGE EQU 6 ;AN000; out of range specified +SYSPRM_EX_VALUE EQU 7 ;AN000; not in value list provided +SYSPRM_EX_STRING EQU 8 ;AN000; not in string list provided +SYSPRM_EX_SYNTAX EQU 9 ;AN000; syntax error +SYSPRM_EX_EOL EQU -1 ;AN000; end of command line +; = = = = = = = = = = = = + HEADER ;AN000; +PSP STRUC ;AN000; + DB 80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP +PSP_PARMLEN DB ? ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE +PSP_COMMAND DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE +PSP ENDS ;AN000; + +MSG_DESC STRUC ;AN003; +MSG_NUM DW ? ;AN003;MESSAGE NUMBER (TO AX) +MSG_HANDLE DW ? ;AN003;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW ? ;AN003;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW ? ;AN003;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DW ? ;AN003;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) +MSG_DESC ENDS ;AN003; + +ONE_SUBS EQU 1 ;AN003;NUMBER OF VARIABLES + +SUBLIST STRUC ;AN000; +SUB_SIZE DB ? ;AN003;SUBLIST SIZE (POINTER TO NEXT SUBLIST) +SUB_RES DB ? ;AN003;RESERVED + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD +SUB_VALUE DW ? ;AN003;TIME, DATE, OR PTR TO DATA ITEM +SUB_VALUE_SEG DW ? ;AN003;SEG ID OF PTR + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME + ; IF THIS IS A .COM FILE) +SUB_ID DB ? ;AN003;N OF %N +SUB_FLAGS DB ? ;AN003;DATA TYPE FLAGS +SUB_MAX_WIDTH DB ? ;AN003;MAXIMUM FIELD WIDTH (0=UNLIMITED) +SUB_MIN_WIDTH DB ? ;AN003;MINIMUM FIELD WIDTH +SUB_PAD_CHAR DB ? ;AN003;CHARACTER FOR PAD FIELD + ; CAN BE " ", "0" OR ",". + ; "," CAUSES INSERTION OF THE ACTIVE + ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS. +SUBLIST ENDS ;AN003; + +; = = = = = = = = = = = = + HEADER ;AN000; +; $SALUT (4,14,19,36) ;AN000; + EXTRN EXPAR:ABS ;AN000;ERRORLEVEL VALUE FOR BAD PARMS + EXTRN FINE:ABS ;AN000;RETURN STATUS INDICATOR +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + EXTRN SENDMSG:NEAR ;AN000;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR + EXTRN SYSPARSE:NEAR ;AN000;SYSTEM COMMAND LINE PARSER + + EXTRN EXITFL:BYTE ;AN000;ERRORLEVEL RETURN CODE + + EXTRN SOURCE_DRIVE:BYTE ;AN000;FIRST DRIVE LETTER SPECIFIED IN PARMS + EXTRN TARGET_DRIVE:BYTE ;AN000;SECOND DRIVE LETTER SPECIFIED + + EXTRN USER_OPTION:BYTE ;AN000;NO OPTION (-1) /1 (1), INVALID (9) +NO_OPTION EQU -1 ;AN000;NO OPTION "/1" SPECIFIED +OPTION_1 EQU 1 ;AN000;OPTION "/1" SPECIFIED + EXTRN MSGNUM_PARSE:WORD ;AN000;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS + EXTRN MSGNUM_INVALID_PARM2:WORD ;AN005;HELP INFO + EXTRN SUBLIST_PARSE:WORD ;AN003;POINTS TO INVALID PARM +; = = = = = = = = = = = = + +CURRENT_PARM DW 81H ;AN000;POINTER INTO COMMAND OF NEXT OPERAND + PUBLIC CURRENT_PARM ;AN000; + +ORDINAL DW 0 ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE + PUBLIC ORDINAL ;AN000; + +; = = = = = = = = = = = = + HEADER ;AN000; + +;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER + + PUBLIC PARMS ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE +PARMS LABEL BYTE ;AN000;PARMS CONTROL BLOCK + DW PARMSX ;AN000;POINTER TO PARMS EXTENSION + DB 0 ;AN000; NUMBER OF STRINGS (0, 1, 2) + ; NEXT LIST WOULD BE EXTRA DELIM LIST + ; (,& WHITESPACE ALWAYS) + ; NEXT LIST WOULD BE EXTRA END OF LINE LIST + ; (CR,LF,0 ALWAYS) + +;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK +PARMSX LABEL BYTE ;AN000;PARMS EXTENSION CONTROL BLOCK + DB 0,2 ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED + DW CONTROL_POS ;AN000; DESCRIPTION OF POSITIONAL 1 + DW CONTROL_POS ;AN000; DESCRIPTION OF POSITIONAL 2 + + DB 1 ;AN000; MAX SWITCH OPERANDS ALLOWED + DW CONTROL_SW ;AN000; DESCRIPTION OF SWITCH 1 + + DB 0 ;AN000; MAX KEYWORD OPERANDS ALLOWED + ; THERE IS NO CONTROL BLOCK + ; DEFINING KEYWORDS + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL + +;FIRST POSITIONAL PARAMETER IS: +; [D:] - SPECIFY THE SOURCE DRIVE. + + PUBLIC CONTROL_POS ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_POS LABEL BYTE ;AN000;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC, + ; OPTIONAL + DW 0101H ;AN000; CONTROLS TYPE MATCHED + ; SELECTED BITS: "DRIVE ONLY" AND "OPTIONAL" + + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0002H ;AN000;FUNCTION_FLAGS + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + DW RESULT1 ;AN000; RESULT BUFFER + DW NOVALS ;AN000; NO VALUE LISTS + DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST + +;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS +NOVALS DB 0 ;AN000;NO VALUE DEFINITIONS + +;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER +RESULT1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS + DB 6 ;AN000; TYPE RETURNED: 0=RESERVED, + ; 1=NUMBER, 2=LIST INDEX, + ; 3=STRING, 4=COMPLEX, + ; 5=FILESPEC, 6=DRIVE + ; 7=DATE, 8=TIME + ; 9=QUOTED STRING +RESULT_TAG DB 0FFH ;AN000; MATCHED ITEM TAG + DW 0 ;AN000;POINTER TO SYNONYM + +RESULT_PTR1 DB ? ;AN000;DRIVE NUMBER (A=1, B=2, ETC) + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY SWITCH, OPTIONAL + +;THE SWITCH IS "/1", MEANING ONLY COPY FIRST SIDE. + + PUBLIC CONTROL_SW ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_SW LABEL BYTE ;AN000;SWITCH DESCRIPTOR FOR /1 + DW 0001H ;AN000; CONTROLS TYPE MATCHED + ;SELECTED BITS: "OPTIONAL" + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0002H ;AN000;FUNCTION_FLAGS + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + + DW RESULTSW1 ;AN000; RESULT BUFFER + DW NOVALS ;AN000; VALUE LISTS + DB 1 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST +SW_1 DB "/1",0 ;AN000; IF n >0, SWITCH 1 + +;RESULTS CONTROL BLOCK FOR THE SWITCHES +RESULTSW1 LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS + DB 3 ;AN000; TYPE RETURNED: 0=RESERVED, + ; 1=NUMBER, 2=LIST INDEX, + ; 3=STRING, 4=COMPLEX, + ; 5=FILESPEC, 6=DRIVE + ; 7=DATE, 8=TIME + ; 9=QUOTED STRING + DB 0FFh ;AN000; MATCHED ITEM TAG + + DW 0 ;AN000; SYNONYM POINTER (BASED ON ES:) +RESULT_PTR2 DD ? ;AN000; OFFSET OF STRING VALUE +; = = = = = = = = = = = = + PATHLABL DCOPYPAR ;AN015; + HEADER ;AN000; +; $SALUT (4,4,9,36) ;AN000; +PARSER PROC NEAR ;AN000; + PUBLIC PARSER ;AN000; + +;INPUT: "CURRENT_PARM" = OFFSET TO NEXT PARM IN COMMAND STRING +; "ORDINAL" = COUNT OF NEXT PARM TO PARSE +; PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING +;OUTPUT: "SOURCE_DRIVE" = VALUE OF FIRST DRIVE ID SPECIFIED, 0 IF NONE +; "TARGET_DRIVE" = VALUE OF SECOND DRIVE ID IF BOTH SPECIFIED, 0 +; IF NONE OR ONLY ONE SPECIFIED +; "USER_OPTION" = "OPTION_1" IF /1 SPECIFIED, -1 IF NOT SPECIFIED +; IF ERROR, ERROR MESSAGE IS DISPLAYED, AND "EXITFL" HAS "EXPAR". +; DX="FINE" IF NO ERROR, OR HAS OFFSET OF PARSE ERROR DESCRIPTOR IF PROBLEM +; = = = = = = = = = = = = + + MOV USER_OPTION, NO_OPTION ;AN000;ASSUME NO /1 IS ENTERED. +; $SEARCH COMPLEX ;AN000;LOOP THRU COMMAND LINE + JMP SHORT $$SS1 +$$DO1: + ;LOOKING AT RETURN CODE FROM SYSPARSE... + CMP AX,SYSPRM_EX_OK ;AN000;WERE THERE ANY ERRORS? +; $EXITIF NE ;AN000;HAD A PROBLEM + JE $$IF1 + CALL PARSE_ERROR ;AN000;DISPLAY REASON FOR ERROR + +; $ORELSE ;AN000;SINCE NO PROBLEM, SO FAR + JMP SHORT $$SR1 +$$IF1: + MOV ORDINAL,CX ;AN000;SAVE UPDATED COUNT + MOV CURRENT_PARM,SI ;AN000;REMEMBER HOW FAR I GOT + MOV BX,DX ;AN000;SET DATA BASE REG TO POINT TO THIS OPERAND + CMP BX,OFFSET RESULT1 ;AN000;WAS POSITIONAL PARM SPECIFIED? +; $IF E ;AN000;IF POSITIONAL PARM SPECIFIED, + JNE $$IF4 + MOV SI,CX ;AN000;USE COUNT OF POSITIONALS AS INDEX + MOV AL,RESULT_PTR1 ;AN000;GET VALUE OF DRIVE (A=1, B=2, ETC) + MOV SOURCE_DRIVE-1[SI],AL ;AN000;SAVE RESPONSE VALUE + ;IN EITHER SOURCE_DRIVE OR TARGET_DRIVE + ;ACCORDING TO ORDINAL IN SI (FROM CX) +; $ELSE ;AN000;SINCE NOT POSITIONAL PARM SPECIFIED + JMP SHORT $$EN4 +$$IF4: + MOV SW_1,BLANK ;AN001;AVOID GETTING DUPLICATE SWITCH + MOV USER_OPTION,OPTION_1 ;AN000;MUST HAVE BEEN THE SWITCH, /1 +; $ENDIF ;AN000; +$$EN4: +; $STRTSRCH ;AN000; +$$SS1: + LEA DI,PARMS ;AN000; ES:DI = PARSE CONTROL DEFINITON + MOV SI,CURRENT_PARM ;AN000; DS:SI = COMMAND STRING, NEXT PARM + XOR DX,DX ;AN000; RESERVED, INIT TO ZERO + MOV CX,ORDINAL ;AN000; OPERAND ORDINAL, INITIALLY ZERO + CALL SYSPARSE ;AN000;LOOK AT DOS PARMS + ; AX=EXIT CODE + ; BL=TERMINATED DELIMETER CODE + ; CX=NEW OPERAND ORDINAL + ; SI=SET TO PAST SCANNED OPERAND + ; DX=SELECTED RESULT BUFFER + CMP AX,SYSPRM_EX_EOL ;AN000; IS THAT THE END OF THE PARMS? + ;IF NOT, LOOP BACK AND FIND OUT + ; WHAT THAT PARM IS +; $ENDLOOP E ;AN000;END OF LIST + JNE $$DO1 + MOV DX,FINE ;AN000;REPORT THAT PARSER WENT OK +; $ENDSRCH ;AN000;FINISHED WITH DOS COMMAND LINE +$$SR1: + RET ;AN000;RETURN TO CALLER +PARSER ENDP ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; +PARSE_ERROR PROC NEAR ;AN000; +;INPUT: AX - ERROR NUMBER RETURNED FROM PARSE. +; "CURRENT_PARM" - OFFSET TO WHERE THE BAD PARM STARTED +;OUTPUT: APPROPRIATE ERROR MESSAGE IS PREPARED FOR DISPLAY. +; DX IS SET TO OFFSET OF PARSE ERROR DESCRIPTOR. +; = = = = = = = = = = = = + + MOV MSGNUM_PARSE,AX ;AN000;PASS MESSAGE NUMBER TO DESCRIPTOR + MOV EXITFL,EXPAR ;AN000;ERRORLEVEL CODE TO "PARM ERROR" + MOV AX,CURRENT_PARM ;AN003;GET POINTER TO START OF BAD PARM + CMP SI,AX ;AN003;HAS THE INDEX TO COMMAND LINE MOVED? +; $IF NE ;AN003;YES, THERE IS A FAULTY PARM + JE $$IF10 + MOV BYTE PTR [SI],NUL ;AN003;DELIMIT THE BAD PARM + MOV SUBLIST_PARSE.SUB_VALUE,AX ;AN000;POINT SUBLIST TO BAD PARM + + MOV MSGNUM_PARSE.MSG_SUBLIST,OFFSET SUBLIST_PARSE ;AN003;POINT TO SUBLIST + MOV MSGNUM_PARSE.MSG_COUNT,ONE_SUBS ;AN003;SET COUNT OF SUBLISTS TO ONE +; $ENDIF ;AN003;INDEX MOVED? +$$IF10: + MOV DI,OFFSET MSGNUM_PARSE ;AC005;PASS BACK OFFSET TO PARSE ERR DESCRIPTOR + CALL SENDMSG ;AN005;DISPLAY THE ERROR MESSAGE + + ; "Do not specify filename(s)",CR,LF + ; "Command Format: DISKCOPY d: d: [/1]",CR,LF + MOV DX,OFFSET MSGNUM_INVALID_PARM2 ;AN005;DISPLAY HELP INFO + RET ;AN000;RETURN TO CALLER +PARSE_ERROR ENDP ;AN000; +; = = = = = = = = = = = = + PATHLABL DCOPYPAR ;AN015; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DCOPYSM.ASM b/v4.0/src/CMD/DISKCOPY/DCOPYSM.ASM new file mode 100644 index 0000000..035fa73 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DCOPYSM.ASM @@ -0,0 +1,153 @@ + PAGE 90,132 ;AN000;A2 + TITLE DCOPYSM.SAL - DISKCOPY SYSTEM MESSAGES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DCOPYSM.SAL + +; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT +; configuration expected by the modules of DISKCOPY. + +;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a +; part of the DISKCOPY module by using INCLUDE to bring in the +; common portion, in SYSMSG.INC. This included code contains +; the routines to initialize for message services, to find +; where a particular message is, and to display a message. + +; ENTRY POINT: SYSDISPMSG:near +; SYSGETMSG:near +; SYSLOADMSG:near + +; INPUT: +; AX = MESSAGE NUMBER +; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12) +; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE +; CX = NUMBER OF %PARMS, 0 IF NONE +; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW +; CALL SYSDISPMSG ;DISPLAY THE MESSAGE + +; If carry set, extended error already called: +; AX = EXTENDED MESSAGE NUMBER +; BH = ERROR CLASS +; BL = SUGGESTED ACTION +; CH = LOCUS +; _ _ _ _ _ _ _ _ _ _ _ _ + +; AX = MESSAGE NUMBER +; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG) +; CALL SYSGETMSG ;FIND WHERE A MSG IS + +; If carry set, error +; CX = 0, MESSAGE NOT FOUND +; If carry not set, ok, and resulting regs are: +; CX = MESSAGE SIZE +; DS:SI = MESSAGE TEXT +; _ _ _ _ _ _ _ _ _ _ _ _ + +; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION +; If carry not set: +; CX = SIZE OF MSGS LOADED + +; If carry is set, regs preset up for SYSDISPMSG, as: +; AX = ERROR CODE IF CARRY SET +; AX = 1, INCORRECT DOS VERSION +; DH =-1, (Utility msg) +; OR, +; AX = 1, Error loading messages +; DH = 0, (Message manager error) +; BX = STDERR +; CX = NO_REPLACE +; DL = NO_INPUT + +; EXIT-NORMAL: CARRY is not set + +; EXIT-ERROR: CARRY is set +; Call Get Extended Error for reason code, for SYSDISPMSG and +; SYSGETMSG. + +; INTERNAL REFERENCES: +; ROUTINES: (Generated by the MSG_SERVICES macro) +; SYSLOADMSG +; SYSDISPMSG +; SYSGETMSG + +; DATA AREAS: +; INCLUDED "DCOPYMS.INC" - message defining control blocks +; INCLUDE SYSMSG.INC ;Permit System Message handler definition + +; EXTERNAL REFERENCES: +; ROUTINES: none + +; DATA AREAS: control blocks pointed to by input registers. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT DCOPYSM,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; DISKCOPY.SAL. + +; COPYRIGHT: "Version 4.00 (C)Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=DISKCOPY, MODULE=DCOPYSM.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + INCLUDE PATHMAC.INC ;AN015;PATHGEN MACRO +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;;AN000; + SUBTTL TEXT ;;AN000; +.LIST ;;AN000; + PAGE ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = + INCLUDE SYSMSG.INC ;AN000;PERMIT SYSTEM MESSAGE HANDLER DEFINITION + MSG_UTILNAME ;AN000;IDENTIFY THE COMPONENT +; = = = = = = = = = = = = + HEADER ;AN000; +; $SALUT (4,12,18,36) ;AN000; +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME SS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME DS:CSEG ;AN000;ESTABLISHED BY CALLER + ASSUME ES:CSEG ;AN000;ESTABLISHED BY CALLER + +;(deleted ;AN010;) PUBLIC COPYRIGHT ; +;(deleted ;AN010;) COPYRIGHT DB "MS DOS DISKCOPY Utility " +;(deleted ;AN010;) INCLUDE COPYRIGH.INC ;(this is now being done my MSG_SERVICES) + HEADER ;AN000; + INCLUDE MSGHAN.INC ;AN000;DEFINE THE MESSAGE HANDLER CONTROL BLOCKS + INCLUDE DCOPYMS.INC ;AN000;DEFINE THE MESSAGES, AND CONTROL BLOCKS + HEADER ;AN000; + MSG_SERVICES ;AN000;WORKAREAS FOR SYSTEM MESSAGE HANDLER +; = = = = = = = = = = = = + HEADER ;AN000; + PUBLIC SYSLOADMSG ;AN000; + PUBLIC SYSDISPMSG ;AN000; + + MSG_SERVICES ;AN000;MSG TEXT + + PATHLABL DCOPYSM ;AN015; + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg +; MSG_SERVICES +.xlist ;AN000; +.xcref ;AN000; + MSG_SERVICES ;AN000; +.cref ;AN000; +.list ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + PATHLABL DCOPYSM ;AN015; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DCPYMACR.INC b/v4.0/src/CMD/DISKCOPY/DCPYMACR.INC new file mode 100644 index 0000000..da247a5 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DCPYMACR.INC @@ -0,0 +1,164 @@ + IF1 ;AN000; + %OUT COMPONENT=DISKCOPY, INCLUDING DCPYMACR.INC...;AN000; + ENDIF ;AN000; +;***************************************************************************; +; MACRO DEFINITION ; +;***************************************************************************; + +HEADER MACRO TEXT ;AN000; +.XLIST ;AN000; + SUBTTL &TEXT ;AN000; +.LIST ;AN000; + PAGE ;AN000; + ENDM ;AN000; +; = = = = = = = = = +; $SALUT (0,36,40,44) +DOSCALL MACRO FUNC,SUBFUNC ;;AN000; + IFNB ;;AN000;IS THERE ANY PARMS AT ALL? + IFNB ;;AN000; + MOV AX,(FUNC SHL 8)+SUBFUNC ;;AN000;FUNC TO AH,SUBFUNC TO AL + ELSE ;;AN000;SINCE THERE IS NO SUBFUNC + MOV AH,FUNC ;;AN000; + ENDIF ;;AN000; + ENDIF ;;AN000; + INT 21H ;;AN000; + ENDM ;;AN000; +; = = = = = = = = = +PRINT MACRO MESSAGE;;AN000; + MOV DI,OFFSET MESSAGE ;;AC000; + CALL SENDMSG ;;AC000; + ENDM ;;AN000; +; = = = = = = = = = +; $SALUT (0,16,22,36) +MY_TRACKLAYOUT MACRO ;AN000; + LOCAL CSECT_F ;AN000; +CSECT_F DW 0 ;;AN000;# OF SECTORS IN A TRACK. Currently 18 is max. + ;; THE REST IS FOR FUTURE MEDIA + DW 1 ;;AN000;1 ST SECTOR + DW 512 ;;AN000;# OF BYTES + DW 2 ;;AN000; + DW 512 ;;AN000; + DW 3 ;;AN000; + DW 512 ;;AN000; + DW 4 ;;AN000; + DW 512 ;;AN000; + DW 5 ;;AN000; + DW 512 ;;AN000; + DW 6 ;;AN000; + DW 512 ;;AN000; + DW 7 ;;AN000; + DW 512 ;;AN000; + DW 8 ;;AN000; + DW 512 ;;AN000; + DW 9 ;;AN000; + DW 512 ;;AN000; + DW 10 ;;AN000; + DW 512 ;;AN000; + DW 11 ;;AN000; + DW 512 ;;AN000; + DW 12 ;;AN000; + DW 512 ;;AN000; + DW 13 ;;AN000; + DW 512 ;;AN000; + DW 14 ;;AN000; + DW 512 ;;AN000; + DW 15 ;;AN000; + DW 512 ;;AN000; + DW 16 ;;AN000; + DW 512 ;;AN000; + DW 17 ;;AN000; + DW 512 ;;AN000; + DW 18 ;;AN000; + DW 512 ;;AN000;CURRENTLY 18 SECTORS/TRACK IS MAXIMUM + DW 19 ;;AN000;BELOW IS FOR THE FUTURE MEDIA. + DW 512 ;;AN000; + DW 20 ;;AN000; + DW 512 ;;AN000; + DW 21 ;;AN000; + DW 512 ;;AN000; + DW 22 ;;AN000; + DW 512 ;;AN000; + DW 23 ;;AN000; + DW 512 ;;AN000; + DW 24 ;;AN000; + DW 512 ;;AN000; + DW 25 ;;AN000; + DW 512 ;;AN000; + DW 26 ;;AN000; + DW 512 ;;AN000; + DW 27 ;;AN000; + DW 512 ;;AN000; + DW 28 ;;AN000; + DW 512 ;;AN000; + DW 29 ;;AN000; + DW 512 ;;AN000; + DW 30 ;;AN000; + DW 512 ;;AN000; + DW 31 ;;AN000; + DW 512 ;;AN000; + DW 32 ;;AN000; + DW 512 ;;AN000; + DW 33 ;;AN000; + DW 512 ;;AN000; + DW 34 ;;AN000; + DW 512 ;;AN000; + DW 35 ;;AN000; + DW 512 ;;AN000; + DW 36 ;;AN000; + DW 512 ;;AN000; + DW 37 ;;AN000; + DW 512 ;;AN000; + DW 38 ;;AN000; + DW 512 ;;AN000; + DW 39 ;;AN000; + DW 512 ;;AN000; + DW 40 ;;AN000; + DW 512 ;;AN000; + DW 41 ;;AN000; + DW 512 ;;AN000; + DW 42 ;;AN000; + DW 512 ;;AN000; + DW 43 ;;AN000; + DW 512 ;;AN000; + DW 44 ;;AN000; + DW 512 ;;AN000; + DW 45 ;;AN000; + DW 512 ;;AN000; + DW 46 ;;AN000; + DW 512 ;;AN000; + DW 47 ;;AN000; + DW 512 ;;AN000; + DW 48 ;;AN000; + DW 512 ;;AN000; + DW 49 ;;AN000; + DW 512 ;;AN000; + DW 50 ;;AN000; + DW 512 ;;AN000; + DW 51 ;;AN000; + DW 512 ;;AN000; + DW 52 ;;AN000; + DW 512 ;;AN000; + DW 53 ;;AN000; + DW 512 ;;AN000; + DW 54 ;;AN000; + DW 512 ;;AN000; + DW 55 ;;AN000; + DW 512 ;;AN000; + DW 56 ;;AN000; + DW 512 ;;AN000; + DW 57 ;;AN000; + DW 512 ;;AN000; + DW 58 ;;AN000; + DW 512 ;;AN000; + DW 59 ;;AN000; + DW 512 ;;AN000; + DW 60 ;;AN000; + DW 512 ;;AN000; + DW 61 ;;AN000; + DW 512 ;;AN000; + DW 62 ;;AN000; + DW 512 ;;AN000; + DW 63 ;;AN000; + DW 512 ;;AN000; + ENDM ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DISKCOPY.ASM b/v4.0/src/CMD/DISKCOPY/DISKCOPY.ASM new file mode 100644 index 0000000..e278c9e --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DISKCOPY.ASM @@ -0,0 +1,2452 @@ + PAGE 90,132 ;A2 + TITLE DISKCOPY.SAL - DISKETTE DUPLICATION UTILITY ; +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: DISKCOPY + +; DESCRIPTIVE NAME: Diskette to diskette complete copy Utility + +;FUNCTION: DISKCOPY is to copy the contents of the diskette in the +; specified source drive to the diskette in the target +; drive. If necessary, the target diskette is also +; formatted. + + +; Multiple copies may be performed with one load of DISKCOPY. +; A prompt, "Copy another (Y/N)?" permits additional +; executions, all with the same drive specifications. + +; ENTRY POINT: "DISKCOPY" at ORG 100h, jumps to "BEGIN". + +; INPUT: (DOS command line parameters) +; [d:][path]DISKCOPY [d: [D:]][/1] + +; Where + +; [d:][path] before DISKCOPY to specify the drive and path that +; contains the DISKCOPY command file. + +; [d:] to specify the source drive id + +; [D:] to specify the destination drive id + +; [/1] to request single sided operations only + +; EXIT-NORMAL: Errorlevel = 0 +; Function completed successfully. + +; EXIT-ERROR: Errorlevel = 1 +; Abnormal termination due to error, wrong DOS, +; invalid parameters, unrecoverable I/O errors on +; the diskette. +; +; Errorlevel = 2 +; Termination requested by Cntrl-Break. + +; EFFECTS: The entire source diskette is copied, including the unused +; sectors. There is no awareness of the separate files +; involved. A unique volume serial number is generated +; for the target diskette. + +; INCLUDED FILES: +; INCLUDE DCPYMACR.INC ;(formerly called MACRO.DEF) +; INCLUDE DISKCOPY.EQU ;EQUATES +; INCLUDE BOOTFORM.INC ;DEFINE EXT_BPB_INFO & EXT_IBMBOOT_HEADER +; INCLUDE PATHMAC.INC ;PATHGEN MACRO + +; INTERNAL REFERENCES: +; ROUTINES: +; BEGIN - VERSION CHECK, SYSMSG INIT, EXIT TO DOS +; SET_LOGICAL_DRIVE - SET LOG. DRV LETTER THAT OWNS DRIVE +; COPY - COPY THE DISKETTE IMAGE +; TEST_REPEAT - SEE IF USER WANTS TO COPY ANOTHER +; READ_SOURCE - READ FROM SOURCE AS MUCH AS POSSIBLE +; WRITE_TARGET - WRITE DATA FROM MEMORY TO TARGET DISKETTE +; READ_WRITE_TRACK - READ A TRACK AND STORE IT INTO MEMORY +; READ_OP - IOCTL READ A TRACK OPERATION +; MAYBE_ADJUST_SERIAL - MAKE NEW SERIAL IN BOOT +; WRITE_OP - IOCTL WRITE A TRACK OPERATION +; FORMAT_ALL - FORMATS ALL TRACKS TO END +; FORMAT_TRACK - IOCTL FORMAT A TRACK +; CHECK_SOURCE - CHECK SOURCE DISKETTE TYPE +; READ_A_SECTOR - GET ONE SECTOR WITH IOCTL READ +; CALC_TRACK_SIZE - GET MEM SIZE TO STORE ONE TRACK +; CHECK_MEMORY_SIZE - VERIFY WE HAVE ENUF TO COPY 1 TRACK +; SET_FOR_THE_OLD - SET BPB FOR BEFORE-2.0 FMTTED MEDIA +; SET_TRACKLAYOUT - MOVE DATA TO TRACK IMAGE +; CHECK_TARGET - READ TARGET BOOT RCD, NEEDS FORMAT? +; CHK_MULTI_MEDIA - CHECK IF DRIVE IS MULTI-MEDIA +; SET_DRV_PARM_DEF - SET DRIVE PARMS VIA IOCTL +; CHK_MEDIATYPE - DETERMINE MEDIATYPE OF TARGET FOR FORMAT +; GENERIC_IOCTL - COMMUNICATE WITH THE DEVICE DRIVER +; EXTENDED_ERROR_HANDLER - RESPOND TO DOS ERRORS +; TRY_FORMAT - ATTEMPT TRACK FORMAT, TRY FOR ERROR RECOVERY +; ERROR_MESSAGE - SAY WHAT AND WHERE FAILURE +; SENDMSG - PASS IN REGS DATA FROM MSG DESCRIPTOR TO DISP MSG +; YESNO - DETERMINE IF A RESPONSE IS YES OR NO +;(DELETED ;AN013;)READ_VOLSER - OBTAIN OLD VOLUME SERIAL NUMBER FROM SOURCE +; WRITE_VOLSER - PUT NEW VOL SER NUMBER TO TARGET +; DATA AREAS: +; PSP - Contains the DOS command line parameters. +; WORKAREA - Temporary storage + +; EXTERNAL REFERENCES: +; ROUTINES: +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; SYSPARSE - Processes the DOS Command line, finds parms. + +; DATA AREAS: +; DCOPYSM.SAL - Defines the control blocks that describe the messages +; DCOPYPAR.SAL - Defines the control blocks that describe the +; DOS Command line parameters. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT DISKCOPY,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; Sample LINK command: + +; LINK @DISKCOPY.ARF + +; Where the DISKCOPY.ARF is defined as: + +; DISKCOPY+ +; DCOPYSM+ +; DCOPYP+ +; DCOPYPAR+ +; COPYINIT + +; These modules must be linked in this order. The load module is +; a COM file, to be converted to COM with EXE2BIN. + +; REVISION HISTORY: +; A000 Version 4.00: add PARSER, System Message Handler, +; Make new unique vol serial number on new diskette. +; A001 DCR 27, display vol serial number, if present. +; A002 ptm473 Flag duplicate switches as error +; A003 Display parm in error +; A004 PTR752 Add close door to drive not ready +; A005 PTR756 After bad parms, specify help info +; A006 DCR210 SELECT, if present, handles all msgs +; A007 PTM1100 Clear keyboard buffer before input response +; A008 PTM1434 CR,LF MISSING FROM MSGS 22 AND 23 +; A009 PTM1406 USE 69H INSTEAD OF IOCTL FOR GET/SET MEDIA ID +; A010 PTM1821 Move INCLUDE COPYRIGH.INC into MSG_SERVICE macro. +; A011 PTM1837 ADD CHECK FOR UNKNOWN MEDIA TO TRIGGER FORMAT +; A012 PTM2441 COPY FROM 360 TO 1.2 CLOBBERS 1.2 +; A013 PTM3184 SUPPORT OS/2 1.0/1.1 TYPE BOOT RECORDS ALSO +; REMOVE USE OF GET/SET MEDIA ID +; A014 PTM3262 specify BASESW EQU 1 before PARSE.ASM +; A015 PTM3512 PATHGEN +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "DCOPYSM.SAL" module: + +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " + +;PROGRAM AUTHOR: Original written by: JK +; 4.00 modifications by: EMK +;****************** END OF SPECIFICATIONS ***************************** + IF1 ; + %OUT COMPONENT=DISKCOPY, MODULE=DISKCOPY.SAL ; + ENDIF ; + +;***************************************************************************** +; * +; D I S K C O P Y * +; * +; UPDATE HISTORY: 7-31, 8-3, 8-5A, 8-6, 8-7, 8-8, 8-10, 8-11, 8-13, 8-14 * +; 8-16, 8-17, 8-18, 8-20, 8-28, 9-3, 9-11, 10-6, 10-11 * +; 11-7,11-12, 11-17, 11-18, 12-19, 2-16-84, 3-27, 4-5, 4-7 * +; 6-20,7-23,10-31,3-27,4-24 * +; * +;***************************************************************************** + + + +;***************************************************************************** +; * +; MACRO DEFINITION * +; * +;***************************************************************************** + + INCLUDE PATHMAC.INC ;AN015;PATHGEN MACRO + INCLUDE DCPYMACR.INC ;(formerly called MACRO.DEF) + INCLUDE DISKCOPY.EQU ;EQUATES + +; $salut (4,16,22,36) ;AN000; +MY_BPB STRUC ; +CBYTE_SECT DW 0 ; 200H BYTES / SECTOR +CSECT_CLUSTER DB 0 ; 2h SECTORS / CLUSTER +CRESEV_SECT DW 0 ; 1h RESERVED SECTORS +CFAT DB 0 ; 2h # OF FATS +CROOTENTRY DW 0 ; 70h # OF ROOT ENTRIES +CTOTSECT DW 0 ; 02D0h TOTAL # OF SECTORS INCLUDING + ; BOOT SECT, DIRECTORIES ... +MEDIA_DESCRIP DB 0 ;0FDh MEDIA DISCRIPTOR +CSECT_FAT DW 0 ; 2h SECTORS / FAT +CSECT_TRACK DW 0 ; +CHEAD DW 0 ; +CHIDDEN_SECT DD 0 ; +BIG_TOT_SECT DD 0 ; + DB 6 DUP (0) ; +MY_BPB ENDS ; + + INCLUDE BOOTFORM.INC ;AN013;DEFINE EXT_BPB_INFO & EXT_IBMBOOT_HEADER + +CSEG SEGMENT PARA PUBLIC 'CODE' ;AN000; + ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG ; + +;***************************************************************************** +; * +; EXTERNAL VARIABLES * +; * +;***************************************************************************** +;$salut (4,2,9,36) ;AN000; + EXTRN SYSLOADMSG :NEAR ;AN000;SYSTEM MSG HANDLER INTIALIZATION + EXTRN SYSDISPMSG :NEAR ;AN000;SYSTEM MSG HANDLER DISPLAY + + EXTRN INIT :NEAR ;INITIALIZATION ROUTINE +.XLIST ; +;EXTRN PRINTF :NEAR ;MESSAGE DISPLAY ROUTINE +;EXTRN PROMPT :NEAR ;MESSAGE DISPLAY AND KEYBOARD INPUT ROUTINE +;EXTRN ERROR_MESSAGE :NEAR ;ERROR MESSAGE DISPLAY ROUTINE +;EXTRN MSG_SOURCE_BAD_PTR :BYTE +;EXTRN YES :BYTE +;EXTRN NO :BYTE +.LIST ; + EXTRN ASCII_DRV1_ID :BYTE ;AN000;SOURCE DRIVE LETTER CHARACTER + EXTRN ASCII_DRV2_ID :BYTE ;AN000;TARGET DRIVE LETTER CHARACTER + EXTRN MSG_TRACKS :WORD ;AN000;NUMBER OF TRACKS + EXTRN MSG_SECTRK :WORD ;AN000;SECTORS PER TRACK + EXTRN MSG_SIDES :WORD ;AN000;NUMBER OF SIDES + EXTRN ERROR_SIDE_NUMBER :WORD ;AN000;NUMBER OF SIDES (SUBFIELD OF MSG 19) + EXTRN ERROR_TRACK_NUMBER :WORD ;AN000;NUMBER OF TRACKS (SUBFIELD OF MSG 19) + + EXTRN MSGNUM_EXTERR :WORD ;AN000;EXTENDED ERROR MSG DESCRIPTOR + EXTRN MSGNUM_HARD_ERROR_READ:WORD ;AN000;"Unrecoverable read/write error on drive %1",CR,LF + EXTRN MSGNUM_HARD_ERROR_WRITE:WORD ;AN000;"Side %2, track %3" ; + EXTRN MSGNUM_LOAD_SOURCE :WORD ;AC000;"Insert SOURCE diskette in drive %2:" + EXTRN MSGNUM_LOAD_TARGET :WORD ;AC000;"Insert TARGET diskette in drive %2:" + EXTRN MSGNUM_TARGET_MB_UNUSABLE :WORD ;AC000;"Target diskette may be unusable" + EXTRN MSGNUM_NOT_COMPATIBLE :WORD ;AC000;"Drive types or diskette types",CR,LF + ;"not compatible" + EXTRN MSGNUM_BAD_SOURCE :WORD ;AC000;"SOURCE diskette bad or incompatible" + EXTRN MSGNUM_BAD_TARGET :WORD ;AC000;"TARGET diskette bad or incompatible" + EXTRN MSGNUM_COPY_ANOTHER :WORD ;AC000;"Copy another diskette (Y/N)?" + EXTRN MSGNUM_FORMATTING :WORD ;AC000;"Formatting while copying" + EXTRN MSGNUM_GET_READY :WORD ;AC000;"Drive not ready - %0" + EXTRN MSGNUM_CLOSE_DOOR :WORD ;AN004;"Make sure a diskette is inserted into + ; the drive and the door is closed" + EXTRN MSGNUM_FATAL_ERROR :WORD ;AC000;"Copy process ended" + EXTRN MSGNUM_UNSUF_MEMORY:WORD ;AC000;"Insufficient memory" + EXTRN MSGNUM_COPYING :WORD ;AC000;"Copying %1 tracks",CR,LF + ;"%2 Sectors/Track, %3 Side(s)" + EXTRN MSGNUM_STRIKE :WORD ;AC000;"Press any key to continue . . ." + EXTRN MSGNUM_WRITE_PROTECT :WORD ;AC000;"Attempt to write to write-protected diskette" + EXTRN MSGNUM_CR_LF :WORD ;AC000; + EXTRN MSGNUM_SERNO :WORD ;AN001;"VOLUME SERIAL NUMBER IS %1-%0" + EXTRN SUBLIST_26A :WORD ;AN001;POINTS TO FIRST PART OF SERIAL NUMBER + EXTRN SUBLIST_26B :WORD ;AN001;POINTS TO SECND PART OF SERIAL NUMBER + + EXTRN DRIVE_LETTER :BYTE ;AN000; +;***************************************************************************** +; * +; PUBLIC VARIABLES * +; * +;***************************************************************************** + + PUBLIC RECOMMENDED_BYTES_SECTOR ; + PUBLIC COPY ; + PUBLIC S_OWNER_SAVED ; + PUBLIC T_OWNER_SAVED ; + PUBLIC SOURCE_DRIVE ; + PUBLIC TARGET_DRIVE ; + PUBLIC S_DRV_SECT_TRACK ; + PUBLIC S_DRV_HEADS ; + PUBLIC S_DRV_TRACKS ; + PUBLIC T_DRV_SECT_TRACK ; + PUBLIC T_DRV_HEADS ; + PUBLIC T_DRV_TRACKS ; + PUBLIC USER_OPTION ; + PUBLIC COPY_TYPE ; + PUBLIC BUFFER_BEGIN ; + PUBLIC BUFFER_END ; + PUBLIC TRACK_TO_READ ; + PUBLIC TRACK_TO_WRITE ; + PUBLIC SIDE ; + PUBLIC USER_INPUT ; + PUBLIC MAIN_EXIT ; + + PUBLIC IO_ERROR ; + + PUBLIC DS_IOCTL_DRV_PARM ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM + PUBLIC DT_IOCTL_DRV_PARM ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM + PUBLIC DS_specialFunctions ;AND THEIR CONTENTS + PUBLIC DT_specialFunctions ; + PUBLIC DS_deviceType ; + PUBLIC DT_deviceType ; + PUBLIC DS_deviceAttributes ; + PUBLIC DT_deviceAttributes ; + PUBLIC DS_numberOfCylinders ; + PUBLIC DT_numberOfCylinders ; + PUBLIC DS_mediaType ; + PUBLIC DT_mediaType ; + PUBLIC DS_BPB_PTR ; + PUBLIC DT_BPB_PTR ; + + PUBLIC MS_IOCTL_DRV_PARM ;DRIVE PARM FROM SOURCE MEDIUM + PUBLIC MT_IOCTL_DRV_PARM ;DRIVE PARM FROM TARGET MEDIUM + +;***************************************************************************** + ORG 100H ;PROGRAM ENTRY POINT + +DISKCOPY: ; + JMP BEGIN ; +;***************************************************************************** + +;INTERNAL STACK AREA + EVEN ;AN000;MAKE STACK WORD ALIGNED + DB 64 DUP ('STACK ') ;512 BYTES +MY_STACK_PTR LABEL WORD ; + +;***************************************************************************** +; * +; INTERNAL VARIABLES * +; * +;***************************************************************************** +; $salut (4,22,26,36) ;AN000; +; INPUT PARMETERS FROM INIT SUBROUTINE: + +S_OWNER_SAVED DB 0 ;DRIVE LETTER THAT OWNED SOUCE DRIVE OWNERSHIP +T_OWNER_SAVED DB 0 ; + +RECOMMENDED_BYTES_SECTOR DW 0 ;RECOMMENED BYTES/SECTOR FROM DEVICE PARA +SOURCE_DRIVE DB 0 ;SOURCE DRIVE ID: 1=DRV A, 2=DRV B ETC. +TARGET_DRIVE DB 0 ;TARGET DRIVE ID +USER_OPTION DB 0 ;=1 OF /1 OPTION IS ENTERED +COPY_TYPE DB 1 ;SINGLE DRV COPY=1, DOUBLE DRIVE COPY=2 +BUFFER_BEGIN DW 1000H ;BEGINNING OF BUFFER ADDR [IN SEGMENT] +BUFFER_END DW 3FF0H ;END OF BUFFER ADDR [IN SEGMENT] +S_DRV_SECT_TRACK DB ? ;SECT/TRACK, device informations. +S_DRV_HEADS DB ? ;# OF HEADS +S_DRV_TRACKS DB ? ;# OF TRACKS +T_DRV_SECT_TRACK DB ? ; +T_DRV_HEADS DB ? ; +T_DRV_TRACKS DB ? ; + +;DEFAULT BPB FOR OLD MEDIA +;5.25, 48 TPI BPB SINGLE SIDE (9 SECTORS/TRACK) +BPB48_SINGLE DW 512 ;BYTES/SECTOR + DB 1 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 40h ;# OF ROOT ENTRY + DW 168h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0FCh ;MEDIA BYTE + DW 2 ;SECTORS/FAT + +;5.25, 48 TPI BPB DOUBLE SIDE (9 SECTORS/TRACK) +BPB48_DOUBLE DW 512 ;BYTES/SECTOR + DB 2 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 70h ;# OF ROOT ENTRY + DW 2D0h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0FDh ;MEDIA BYTE + DW 2 ;SECTORS/FAT + +;5.25, 96 TPI BPB DOUBLE SIDE (15 SECTORS/TRACK) +BPB96 DW 512 ;BYTES/SECTOR + DB 1 ;SECTOR/CLUSTER + DW 1 ;# OF RESERVED SECTORS + DB 2 ;# OF FATS + DW 0E0h ;# OF ROOT ENTRY + DW 960h ;TOTAL # OF SECTORS IN THE MEDIA + DB 0F9h ;MEDIA BYTE + DW 7 ;SECTORS/FAT +BPB96_LENG EQU $-BPB96 ;THIS LENGTH WILL BE USED FOR BPB48 ALSO. + +; LOCAL VARIABLES: +VOLSER_FLAG DB 0 ;AN000;0=EITHER MEDIA NOT READ YET, OR +; SOURCE VOL SER ID NOT AVAILABLE +; 1=TARGET NEEDS VOL SER WRITTEN +SERIAL DD 0 ;AN013;SERIAL NUMBER OF NEW DISKETTE +EXITFL DB EXOK ;AN000;ERRORLEVEL VALUE + PUBLIC EXITFL ;AN000; + PUBLIC EXPAR ;AN000; +EXCBR EQU 2 ;AN000;CONTROL BREAK +EXVER EQU 1 ;AN000;BAD DOS VERSION ERRORLEVEL CODE +EXPAR EQU 1 ;AN000; BAD PARMS, OR OTHER ERRORS +EXOK EQU 0 ;AN000;NORMAL ERRORLEVEL RET CODE + +S_DRV_SET_FLAG DB 0 ;1 = SOURCE DRIVE PARM HAD BEEN SET +T_DRV_SET_FLAG DB 0 ;1 = TARGET DRIVE PARM HAD BEEN SET + +IOCTL_SECTOR DW 1 ;used for READ_A_SECTOR routine. +IOCTL_TRACK DW 0 ;IN THE TRACK +IOCTL_HEAD DW 0 ;HEAD 0 +SAV_CSECT DW 0 ;TEMPORARY SAVING PLACE +SAV_CN1 DW 0 ; +SAV_CB1 DW 0 ; +SAV_CYLN DW 0 ; + +BOOT_SECT_TRACK DW 0 ;TEMP SAVING PLACE OF SECTOR/TRACK +BOOT_TOT_TRACK DW 0 ;FOUND FROM THE BOOT SECTOR. max # of tracks +BOOT_NUM_HEAD DW 0 ;NUMBER OF HEADS +BOOT_BYTE_SECTOR DW 0 ;BYTES / SECTOR + +READ_S_BPB_FAILURE DB 0 ;GET MEDIA BPB. SUCCESS=0, FAILURE=1 +READ_T_BPB_FAILURE DB 0 ; + +;*** Informations from CHECK_SOURCE. +;*** These will be used as a basis for the copy process. +LAST_TRACK DB 79 ;LAST CYLINDER OF THE DASD (39 OR 79) +END_OF_TRACK DB 15 ;END OF TRACK, 8,9 OR 15 CURRENTLY. +bSECTOR_SIZE DW 512 ;BYTES/SECTOR in bytes +NO_OF_SIDES DB ? ;0=SINGLE SIDED, 1=DOUBLE SIDED + +FORMAT_FLAG DB 0 ;(ON/OFF) FORMAT BEFORE WRITE IF TURNED ON +TRACK_TO_READ DB 0 ;NEXT TRACK TO READ +TRACK_TO_WRITE DB 0 ;NEXT TRACK TO WRITE +TRACK_TO_FORMAT DB 0 ;STARTS FORMAT WITH THIS TRACK + ; TO THE LAST TRACK +TRACK_SIZE DW ? ;BYTES/CYLINDER [IN SEGMENTS] +SECTOR_SIZE DB ? ;BYTES/SECTOR [IN SEGMENTS] +BUFFER_PTR DW ? ;BUFFER POINTER FOR READ/WRITE OP +COPY_ERROR DB 0 ;=0 IF NO ERROR, >0 IF ERROR DETECTED +SIDE DB ? ;NEXT SIDE TO READ/WRITE (0,1) +SIDE_TO_FORMAT DB 0 ;NEXT SIDE TO FORMAT (0, 1) +OPERATION DB ? ;READ/WRITE/VERIFY OPERATION +COPY_STATUS DB ? ;(OK OR FATAL) ABORT COPY PROCESS IF FATAL +USER_INPUT DB ? ;DISKCOPY AGAIN? +IO_ERROR DB 0 ;SET BY EXTENDED_ERROR_HANDLER +UKM_ERR DB 0 ;AN011;IF ON, HARD ERROR IS TYPE: "UNKNOWN MEDIA" +MSG_FLAG DB ? ;USED TO INDICATE IF READ/WRITE ERROR MESSAGE + ;IS TO BE DISPLAYED (ON/OFF) +TARGET_OP DB 0 ;FLAG TO INDICATE ANY OPERATIONS ON TARGET +TRY_FORMAT_FLAG DB 0 ;FLAG TO INDICATE "TRY_FORMAT" PROCEDURE TO + ; CHECK THE "TIME OUT ERROR" +TIME_OUT_FLAG DB 0 ;FLAG TO INDICATE THE "TIME OUT" ERROR + ; WAS A REAL "TIME OUT ERROR" +SELECT_FLAG DB 0 ;INDICATES SELECT IS PRESENT + PAGE ; +; DEVICE PARAMETER TABLE +;the returned info. still has the following format. + +DS_IOCTL_DRV_PARM LABEL BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM +DS_specialFunctions db ? ; +DS_deviceType db ? ;0 - 5.25"(48tpi), 1 - 5.25"(96tpi), + ; 2 - 3.5"(720KB) +DS_deviceAttributes dw ? ;0001h - NOT REMOVABLE, + ; 0002h - CHANGE LINE SUPPORTED +DS_numberOfCylinders dw ? ; +DS_mediaType db ? ; +DS_BPB_PTR LABEL BYTE ; +DS_deviceBPB my_bpb <> ; +DS_trackLayout LABEL WORD ;AC000; + my_trackLayout ;AC000; +;--------------------------------------- + +DT_IOCTL_DRV_PARM LABEL BYTE ; +DT_specialFunctions db ? ; +DT_deviceType db ? ; +DT_deviceAttributes dw ? ;0001h - NOT REMOVABLE, + ; 0002h - CHANGE LINE SUPPORTED +DT_numberOfCylinders dw ? ; +DT_mediaType db ? ; +DT_BPB_PTR LABEL BYTE ; +DT_deviceBPB my_bpb <> ; +DT_trackLayout LABEL WORD ;AC000; + my_trackLayout ;AC000; + +;--------------------------------------- + +MS_IOCTL_DRV_PARM LABEL BYTE ;DRIVE PARM FROM SOURCE MEDIUM +MS_specialFunctions db ? ; +MS_deviceType db ? ; +MS_deviceAttributes dw ? ;0001h - NOT REMOVABLE, + ; 0002h - CHANGE LINE SUPPORTED +MS_numberOfCylinders dw ? ; +MS_mediaType db ? ; +MS_BPB_PTR LABEL BYTE ; +MS_deviceBPB my_bpb <> ; +MS_deviceBPB_leng equ $-MS_deviceBPB ; +MS_trackLayout LABEL WORD ;AC000; + my_trackLayout ;AC000; +;--------------------------------------- +MT_IOCTL_DRV_PARM LABEL BYTE ;DRIVE PARM FROM TARGET MEDIUM +MT_specialFunctions db ? ; +MT_deviceType db ? ; +MT_deviceAttributes dw ? ;0001h - NOT REMOVABLE, + ; 0002h - CHANGE LINE SUPPORTED +MT_numberOfCylinders dw ? ; +MT_mediaType db ? ; +MT_BPB_PTR LABEL BYTE ; +MT_deviceBPB my_bpb <> ; +MT_trackLayout LABEL WORD ;AC000; + my_trackLayout ;AC000; + + +; IOCTL format a track function control string. +IOCTL_FORMAT LABEL BYTE ; +FspecialFunctions db 0 ; +FHead dw ? ; +FCylinder dw ? ; + +; IOCTL read/write a track. +IOCTL_R_W LABEL BYTE ; +specialFunctions db 0 ; +Head dw ? ; +Cylinder dw ? ; +FirstSectors dw ? ; +numberOfSectors dw ? ; +TAddress_off dw ? ; +TAddress_seg dw ? ; +; = = = = = = = = = = = = +; GET/SET MEDIA ID - FUNCTION OF GENERIC IOCTL +; (USED BY VOLSER PROC) +;(Deleted ;AN013;) MEDIA_ID_BUF A_MEDIA_ID_INFO <> ; ;AN000; +; = = = = = = = = = = = = + PATHLABL DISKCOPY ;AN015; + HEADER ;AN000; + PUBLIC DISKCOPY_BEGIN ; +DISKCOPY_BEGIN LABEL NEAR ; + +;***************************************************************************** +; * +; D I S K C O P Y M A I N P R O G R A M * +; * +;***************************************************************************** +; $salut (4,4,10,36) ;AN000; +BEGIN PROC NEAR ; + PUBLIC BEGIN ;AN000; +;OUTPUT - "EXITFL" HAS ERRORLEVEL RETURN CODE + + MOV SP, OFFSET MY_STACK_PTR ;MOVE SP TO MY STACK PTR + CALL SYSLOADMSG ;AN000;INIT SYSMSG HANDLER + +; $IF C ;AN000;IF THERE WAS A PROBLEM + JNC $$IF1 + CALL SYSDISPMSG ;AN000;LET HIM SAY WHY HE HAD A PROBLEM + + MOV EXITFL,EXVER ;AN000;TELL ERRORLEVEL BAD DOS VERSION +; $ELSE ;AN000;SINCE SYSDISPMSG IS HAPPY + JMP SHORT $$EN1 +$$IF1: + CALL INIT ;RUN INITIALIZATION ROUTINE + + CMP DX,FINE ;CHECK FOR ERROR DURING INIT +; $IF E ;IF NO ERROR THEN PROCEED TO COPY + JNE $$IF3 +; $DO ; +$$DO4: + CALL COPY ;PERFORM DISKCOPY + + CALL TEST_REPEAT ;COPY ANOTHER ? + +; $ENDDO C ; + JNC $$DO4 + ;NORMAL RETURN CODE ALREADY IN "EXITFL" +; $ELSE ;ELSE IF ERROR DETECTED IN INIT + JMP SHORT $$EN3 +$$IF3: +.XLIST ; +; PUSH DX +; PUSH CS +; CALL PRINTF ;DISPLAY ERROR MESSAGE +.LIST ; + MOV DI,DX ;PASS NUMBER OF ERROR MSG, IF ANY ;AD000; + ;DI HAS OFFSET OF MESSAGE DESCRIPTOR + CALL SENDMSG ;AC000;DISPLAY THE ERROR MESSAGE + + MOV EXITFL,EXVER ;AC000;ERROR RETURN CODE +; $ENDIF ; +$$EN3: + JMP SHORT EXIT_TO_DOS ; + +MAIN_EXIT: ;COME HERE AFTER CONTROL-BREAK + MOV EXITFL,EXCBR ;AC000; FOR CONTROL-BREAK EXIT + +EXIT_TO_DOS: ; + XOR BX, BX ; + + MOV BL, S_OWNER_SAVED ;RESTORE ORIGINAL SOURCE, + ; TARGET DRIVE OWNER. + CALL SET_LOGICAL_DRIVE ; + + MOV BL, T_OWNER_SAVED ; + CALL SET_LOGICAL_DRIVE ; + + CMP S_DRV_SET_FLAG, 0 ; +; $IF NE ;AN000; + JE $$IF8 + MOV BL, SOURCE_DRIVE ; + MOV DS_specialFunctions, SET_SP_FUNC_DOS ;=0 + MOV DX, OFFSET DS_IOCTL_DRV_PARM ; + CALL SET_DRV_PARM_DEF ;RESTORE SOURCE DRIVE PARM + +; $ENDIF ;AN000; +$$IF8: + + CMP T_DRV_SET_FLAG, 0 ; +; $IF NE ;AN000; + JE $$IF10 + MOV BL, TARGET_DRIVE ; + MOV DT_specialFunctions, SET_SP_FUNC_DOS ;=0 + MOV DX, OFFSET DT_IOCTL_DRV_PARM ; + CALL SET_DRV_PARM_DEF ;RESTORE TARGET DRIVE PARM + +; $ENDIF ;AN000; +$$IF10: +EXIT_PROGRAM: ; + +; $ENDIF ;AN000;OK WITH SYSDISPMSG? +$$EN1: + MOV AL,EXITFL ;AN000;PASS BACK ERRORLEVEL RET CODE + DOSCALL RET_CD_EXIT ;AN000;RETURN TO DOS WITH RET CODE + + INT 20H ;AN000;IF ABOVE NOT WORK, +BEGIN ENDP ;AN000; +; = = = = = = = = = = = = = = = = = + HEADER ;AN000; + PUBLIC SET_LOGICAL_DRIVE ; +;***************************************************************************** +SET_LOGICAL_DRIVE PROC NEAR ; +; *** SET THE LOGICAL DRIVE LETTER THAT WILL BE THE OWNER OF THE DRIVE +; INPUT: BL - DRIVE LETTER +; OUTPUT: OWNER WILL BE SET ACCORDINGLY. +;***************************************************************************** + CMP BL, 0 ; +; $IF NE ;IF BL = 0, THEN JUST RETURN + JE $$IF13 + ;ELSE SET BL AS AN OWNER OF THAT DRIVE + MOV AX,(IOCTL_FUNC SHL 8)+SET_LOGIC_DRIVE ;AC000; + INT 21H ; +; $ENDIF ; +$$IF13: + RET ; +SET_LOGICAL_DRIVE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +;MODULE NAME: COPY * +; * +; INPUT: COPY_TYPE BYTE 1=SINGLE DRIVE COPY * +; 2=DOUBLE DRIVE COPY * +; * +; OUTPUT: NONE * +;***************************************************************************** +COPY PROC NEAR ;COPY DISKETTE IMAGE + MOV VOLSER_FLAG,0 ;AN000;RESET MEDIA ID VOL SERIAL NUMBER FLAG + MOV COPY_ERROR,0 ;RESET COPY ERROR FLAG + MOV COPY_STATUS,OK ;RESET COPY STATUS BYTE + MOV TARGET_OP, OFF ; + MOV TRY_FORMAT_FLAG, OFF ; + MOV TIME_OUT_FLAG, OFF ; + MOV FORMAT_FLAG,OFF ;ASSUME FORMAT IS NOT REQUIRED + MOV READ_S_BPB_FAILURE, 0 ;RESET GET BPB FAILURE FLAG + MOV READ_T_BPB_FAILURE, 0 ; + MOV AX, RECOMMENDED_BYTES_SECTOR ; + MOV bSECTOR_SIZE, AX ;USE RECOMMENDED SECTOR SIZE TO READ A SECTOR + CMP COPY_TYPE,2 ;IF TWO DRIVE COPY +; $IF E ; + JNE $$IF15 + PRINT MSGNUM_LOAD_SOURCE ;AC000;OUTPUT LOAD SOURCE DISKETTE MESSAGE + ;"INSERT SOURCE DISKETTE INTO DRIVE X:" + + PRINT MSGNUM_LOAD_TARGET ;AC000;"INSERT TARGET DISKETTE INTO DRIVE X:" + + CALL PRESS_ANY_KEY ;AC000;"PRESS ANY KEY TO CONTINUE" (WAIT FOR KEYB) + +; $ENDIF ; +$$IF15: + MOV TRACK_TO_READ,0 ;INITIALIZE TRACK NUMBERS + MOV TRACK_TO_WRITE,0 ; + +COPY_TEST_END: ; +; $SEARCH ; +$$DO17: + MOV AL,TRACK_TO_WRITE ;WHILE TRACK_TO_WRITE<=LAST_TRACK + CMP AL,LAST_TRACK ; +; $LEAVE A ; + JA $$EN17 + CALL READ_SOURCE ;READ AS MANY TRACK AS POSSIBLE + + CMP COPY_STATUS,FATAL ;MAKE SURE DRIVES WERE COMPATIBLE +; $EXITIF E,NUL,OR ; + JE $$SR17 + CALL WRITE_TARGET ;WRITE THE CONTENT OF BUFFER TO TARGET + + CMP COPY_STATUS,FATAL ;MAKE SURE TARGET AND SOURCE +; $EXITIF E,NUL ; + JE $$SR17 +; $ENDLOOP ; + JMP SHORT $$DO17 +$$EN17: + + CMP COPY_ERROR,FALSE ;IF ERROR IN COPY +; $IF NE ; + JE $$IF21 + ;CR,LF,"Target diskette may be unusable",CR,LF + PRINT MSGNUM_TARGET_MB_UNUSABLE ;AC000; + +; $ENDIF ; +$$IF21: +; $ENDSRCH ; +$$SR17: + CMP COPY_STATUS,FATAL ;WAS COPY ABORTED ? +; $IF E ; + JNE $$IF24 + ;CR,LF,"Copy process ended",CR,LF + PRINT MSGNUM_FATAL_ERROR ;AC000;IF SO THEN TELL USER + +; $ELSE ;AN000;SINCE NOT ABORTED, + JMP SHORT $$EN24 +$$IF24: + CALL WRITE_VOLSER ;AN000;GO CHANGE VOLID OF TARGET + +; $ENDIF ; +$$EN24: + RET ; + +COPY ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC TEST_REPEAT ;AN000;MAKE ENTRY IN LINK MAP +TEST_REPEAT PROC NEAR ;TEST IF USER WANTS TO COPY ANOTHER * +; DISKETTE * +; INPUT : USER_INPUT ("Y" OR "N") +; OUTPUT: NC = COPY AGAIN * +; CY = EXIT TO DOS * +;***************************************************************************** +; $SEARCH COMPLEX ;AC000;REPEAT THIS PROMPT UNTIL (Y/N) RESPONDED + JMP SHORT $$SS27 +$$DO27: + PRINT MSGNUM_CR_LF ;AC000; + +; $STRTSRCH ;AN000; +$$SS27: + ;CR,LF,"Copy another diskette (Y/N)?" + PRINT MSGNUM_COPY_ANOTHER ;AC000;SEE IF USER WANTS TO COPY ANOTHER + ; AND READ RESPONSE TO AL + PUSH AX ;AN000;SAVE THE RESPONSE + PRINT MSGNUM_CR_LF ;AC000; + + POP DX ;AN000;RESTORE THE REPONSE CHAR TO DL + CALL YESNO ;AN000;CHECK FOR (Y/N) + ;AX=0,NO; AX=1,YES; AX=2,INVALID +; $EXITIF C,NUL ;AN000;IF CARRY SET, PROBLEM,PRETEND "NO" + JC $$SR27 + + CMP AX,BAD_YESNO ;AN000;WAS THE RESPONSE INVALID? +; $ENDLOOP B ;AN000;QUIT IF OK ANSWER (AX=0 OR 1) + JNB $$DO27 + CMP AL,YES ;AN000;WAS "YES" SPECIFIED +; $IF E ;AN000;IF "YES" + JNE $$IF31 + CLC ;AN000;CLEAR CARRY TO INDICATE COPY AGAIN +; $ELSE ;AN000;SINCE NOT "YES" + JMP SHORT $$EN31 +$$IF31: + STC ;AN000;SET CARRY TO INDICATE NO REPEAT +; $ENDIF ;AN000; +$$EN31: +; $ENDSRCH ;AN000; +$$SR27: +.XLIST ; +; MOV AL,USER_INPUT +; AND AL,11011111B ;MAKE USER INPUT UPPER CASE +; CMP AL,YES ;IF YES THEN COPY AGAIN +; $EXITIF E +; CLC ;CLEAR CARRY TO INDICATE COPY AGAIN +; $ORELSE +; CMP AL,NO ;IF NOT "N" OR "Y" THEN PROMPT AGAIN +; $ENDLOOP E +; STC ;SET CARRY TO INDICATE NO REPEAT +; $ENDSRCH +.LIST ; + RET ; + +TEST_REPEAT ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC READ_SOURCE ;AN000;MAKE ENTRY IN LINK MAP * +READ_SOURCE PROC NEAR ;READ AS MANY TRACKS AS POSSIBLE FROM SOURCE* +; ;DISKETTE TO FILL THE AVAILABLE BUFFER SPACE * +;***************************************************************************** + + CMP COPY_TYPE,1 ;IF SINGLE DRIVE COPY +; $IF E ;PROMPT MSG + JNE $$IF35 + PRINT MSGNUM_LOAD_SOURCE ;AN000;"INSERT SOURCE DISKETTE INTO DRIVE X:" + + CALL PRESS_ANY_KEY ;AC000;"PRESS ANY KEY TO CONTINUE" (WAIT FOR KEYB) + +; $ENDIF ; +$$IF35: + CMP TRACK_TO_READ,0 ;1ST TRACK ? +; $IF NE,OR ;IF NOT + JNE $$LL37 + + CALL CHECK_SOURCE ;DO NECESSARY CHECKING + + CALL CALC_TRACK_SIZE ; + + CALL CHECK_MEMORY_SIZE ; + + CMP COPY_STATUS,FATAL ; +; $IF NE ; + JE $$IF37 +$$LL37: +;(deleted ;AN013;) CALL READ_VOLSER ;GO READ THE MEDIA ID TO GET SERIAL NUMBER ;AN000; + + MOV BX,BUFFER_BEGIN ; + MOV BUFFER_PTR,BX ;INITIALIZE BUFFER POINTER + +; $DO ; +$$DO38: + MOV AL,TRACK_TO_READ ;DID WE FINISH READING ALL TRACKS? + CMP AL,LAST_TRACK ; +; $LEAVE A ; + JA $$EN38 + MOV AX,BUFFER_PTR ;DID WE RUN OUT OF BUFFER SPACE + ADD AX,TRACK_SIZE ; + CMP AX,BUFFER_END ; +; $LEAVE A ; + JA $$EN38 + MOV OPERATION,READ_FUNC ; + CALL READ_WRITE_TRACK ;NO, GO READ ANOTHER TRACK + + INC TRACK_TO_READ ; +; $ENDDO ; + JMP SHORT $$DO38 +$$EN38: +; $ENDIF ; +$$IF37: + RET ; +READ_SOURCE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC WRITE_TARGET ;AN000;MAKE ENTRY IN LINK MAP +WRITE_TARGET PROC ;WRITE DATA FROM MEMORY TO TARGET DISKETTE* +; * +;***************************************************************************** + + CMP COPY_TYPE,1 ;IF SINGLE DRIVE COPY +; $IF E ;PROMPT MSG + JNE $$IF43 + PRINT MSGNUM_LOAD_TARGET ;AC000;"INSERT TARGET DISKETTE INTO DRIVE X:" + + CALL PRESS_ANY_KEY ;AC000;"PRESS ANY KEY TO CONTINUE" (WAIT FOR KEYB) + +; $ENDIF ; +$$IF43: + MOV TARGET_OP, ON ;INDICATE A OPERATION ON TARGET + MOV BX,BUFFER_BEGIN ; + MOV BUFFER_PTR,BX ;INITIALIZE BUFFER POINTER + CMP TRACK_TO_WRITE,0 ;IF TRK 0, CHECK COMPATIBILITY +; $IF NE,OR ; + JNE $$LL45 + + MOV SIDE, 0 ; + CALL CHECK_TARGET ; + + CMP COPY_STATUS,FATAL ;IF INCOMPATIBLE, THEN EXIT +; $IF NE ; + JE $$IF45 +$$LL45: + +; $DO ; +$$DO46: + MOV AL,TRACK_TO_WRITE ;DID WE FINISH WRITING ALL TRACKS? + CMP AL,LAST_TRACK ; +; $LEAVE A ; + JA $$EN46 + MOV AX,BUFFER_PTR ;DID WE RUN OUT OF BUFFER SPACE + ADD AX,TRACK_SIZE ; + CMP AX,BUFFER_END ; +; $LEAVE A ; + JA $$EN46 + MOV OPERATION,WRITE_FUNC ; + CALL READ_WRITE_TRACK ;NO, GO WRITE ANOTHER TRACK + + CMP COPY_STATUS,FATAL ;IF INCOMPATIBLE, THEN EXIT +; $LEAVE E ; + JE $$EN46 + INC TRACK_TO_WRITE ; +; $ENDDO ; + JMP SHORT $$DO46 +$$EN46: +; $ENDIF ; +$$IF45: + MOV TARGET_OP, OFF ; + RET ; +WRITE_TARGET ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC READ_WRITE_TRACK ;AN000;MAKE ENTRY IN LINK MAP +READ_WRITE_TRACK PROC NEAR ;READ A TRACK AND STORE IT INTO MEMORY * +; * +;INPUT: OPERATION = 61h THEN READ OPERATION * +; 41h THEN WRITE OPERATION * +;***************************************************************************** + + MOV SIDE, 0 ; +; $DO ; +$$DO52: + MOV MSG_FLAG, ON ; + CMP OPERATION, READ_FUNC ; +; $IF E ; + JNE $$IF53 + CALL READ_OP ; + +; $ELSE ; + JMP SHORT $$EN53 +$$IF53: + CALL WRITE_OP ; + + CMP COPY_STATUS, FATAL ; + JE RWT_EXIT ; + +; $ENDIF ; +$$EN53: + CMP NO_OF_SIDES, 0 ;SINGLE SIDE COPY? +; $IF E ;YES + JNE $$IF56 + MOV AX, TRACK_SIZE ; +; $ELSE ;NO, DOUBLE SIDE + JMP SHORT $$EN56 +$$IF56: + XOR DX, DX ; + MOV AX, TRACK_SIZE ; + MOV CX, 2 ; + DIV CX ;AX / 2 +; $ENDIF ; +$$EN56: + ADD BUFFER_PTR, AX ; + INC SIDE ;NEXT SIDE + MOV AL, SIDE ; + CMP AL, NO_OF_SIDES ;FINISHED WITH THE LAST SIDE? +; $ENDDO G ; + JNG $$DO52 +RWT_EXIT: ; + RET ; +READ_WRITE_TRACK ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC READ_OP ;AN000;MAKE ENTRY IN LINK MAP +READ_OP PROC NEAR ;IOCTL READ A TRACK OPERATION * +; * +;***************************************************************************** + +; $SEARCH ; +$$DO60: + XOR AX, AX ; + MOV AL, SIDE ; + MOV Head, AX ;HEAD TO READ + MOV AL, TRACK_TO_READ ; + MOV Cylinder, AX ;TRACK TO READ + MOV FirstSectors, 0 ;???? SHOULD BE 1 BUT CURRENTLY 0 ??? + MOV AX, BUFFER_PTR ; + MOV Taddress_seg, AX ;BUFFER ADDRESS + MOV Taddress_off, 0 ; + XOR BX, BX ; + MOV BL, SOURCE_DRIVE ; + MOV CL, READ_FUNC ;=61h + MOV DX, OFFSET IOCTL_R_W ; + CALL GENERIC_IOCTL ; + + CMP IO_ERROR, NO_ERROR ;OK? +; $EXITIF E ;AC013;IF NO ERROR SO FAR, GOOD + JNE $$IF60 + CMP CYLINDER,0 ;AN013;IS THIS THE FIRST READ? +; $IF E,AND ;AN013;IF THIS IS THE FIRST TRACK, AND + JNE $$IF62 + CMP HEAD,0 ;AN013;IS THIS THE FIRST SIDE? +; $IF E ;AN013;AND IF THIS IS THE FIRST SIDE + JNE $$IF62 + CALL MAYBE_ADJUST_SERIAL ;AN013;IF BOOT HAS SERIAL, GENERATE NEW ONE + +; $ENDIF ;AN013;FIRST TRACK AND HEAD? +$$IF62: +; $ORELSE ;AN013;SINCE SOME KIND OF ERROR, OOPS + JMP SHORT $$SR60 +$$IF60: + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? +; $ENDLOOP NE ; + JE $$DO60 + + CMP MSG_FLAG, ON ;ELSE HARD ERROR. SEE IF + ; MESSAGE TO BE DISPLAYED +; $IF E ; + JNE $$IF66 + + MOV AH, READ_FUNC ; + mov dl, source_drive ; + CALL ERROR_MESSAGE ; + + INC COPY_ERROR ;INCREASE COPY_ERROR COUNT + MOV MSG_FLAG, OFF ; +; $ENDIF ; +$$IF66: +; $ENDSRCH ; +$$SR60: + RET ; +READ_OP ENDP ; +; = = = = = = = = = = = = + HEADER ;AN013; +MAYBE_ADJUST_SERIAL PROC NEAR ;AN013; +;INPUT: TADDRESS_OFF/_SEG HAS TRACK BUFFER WHICH HAS BOOT RECORD +; "VOLSER_FLAG" IS FALSE. +;OUTPUT:SERIAL NUMBER FIELD IS MODIFIED TO HAVE NEW SERIAL NUMBER +; A COPY OF WHICH IS PRESERVED IN "SERIAL" FOR LATER DISPLAY IN MSG. +; "VOLSER_FLAG" SET TO TRUE TO INDICATE NEW SERIAL GENERATED. +; IF THIS BOOT DOES NOT HAVE A SERIAL, NO CHANGE MADE, AND +; "VOLSER_FLAG" LEFT AS FALSE. + +; A BOOT RECORD IS ASSUMED TO HAVE A SERIAL NUMBER IF: +; EBPB_MEDIADESCRIPTOR=0F?H AND EXT_BOOT_SIG IS EITHER 28H OR 29H. + + PUSH ES ;AN013;SAVE EXTRA SEG REG TEMPORARILY + PUSH BX ;AN013;AND SAVE THE BASE POINTER + PUSH SI ;AN013; AND THE INDEX + LES BX,DWORD PTR TADDRESS_OFF ;AN013;POINT TO BUFFER AREA CONTAINING BOOT RECORD + LEA SI,ES:[BX].EXT_BOOT_BPB ;AN013;POINT TO BPB PORTION OF BOOT RECORD + MOV AL,ES:[SI].EBPB_MEDIADESCRIPTOR ;AN013;GET TYPE OF MEDIA + AND AL,0F0H ;AN013;SAVE LEFT NIBBLE ONLY + CMP AL,0F0H ;AN013;IF DISKETTE HAS PROPER DESCRIPTOR +; $IF E ;AN013;IF OK DESCRIPTOR + JNE $$IF69 + MOV AL,ES:[BX].EXT_BOOT_SIG ;AN013;GET "SIGNATURE" OF BOOT RECORD + CMP AL,28H ;AN013;IS THIS BOOT STYLE OF OS/2 1.0 OR 1.1? +; $IF E,OR ;AN013;YES, IS A BOOT WITH A SERIAL IN IT + JE $$LL70 + CMP AL,29H ;AN013;IS THIS A BOOT STYLE OF OS/S 1.2? +; $IF E ;AN013;YES, IS A BOOT WITH A SERIAL IN IT + JNE $$IF70 +$$LL70: +; GET CURRENT DATE + DOSCALL GET_DATE ;AN013;READ SYSTEM DATE + ;OUTPUT: DL = DAY (1-31) + ; AL = DAY OF WEEK (0=SUN,6=SAT) + ; CX = YEAR (1980-2099) + ; DH = MONTH (1-12) + PUSH CX ;AN013;SAVE THESE FOR + PUSH DX ;AN013; INPUT INTO HASH ALGORITHM +; GET CURRENT TIME + DOSCALL GET_TIME ;AN013;READ SYSTEM TIME CLOCK + ;OUTPUT: CH = HOUR (0-23) + ; CL = MINUTES (0-59) + ; DH = SECONDS (0-59) + ; DL = HUNDREDTHS (0-99) + +; HASH THESE INTO A UNIQUE 4 BYTE NEW VOLUME SERIAL NUMBER: +; SERIAL+0 = DX FROM DATE + DX FROM TIME +; SERIAL+2 = CX FROM DATE + CX FROM TIME + + POP AX ;AN013;GET THE DX FROM DATE + ADD AX,DX ;AN013;ADD IN THE DX FROM TIME + MOV WORD PTR SERIAL,AX ;AN013;SAVE FIRST RESULT OF HASH + MOV WORD PTR ES:[BX].EXT_BOOT_SERIAL,AX ;AN013;AND IN BOOT RECORD ITSELF + + POP AX ;AN013;GET THE CX FROM DATE + ADD AX,CX ;AN013;ADD IN THE CX FROM TIME + MOV WORD PTR SERIAL+WORD,AX ;AN013;SAVE SECOND RESULT OF HASH + MOV WORD PTR ES:[BX].EXT_BOOT_SERIAL+WORD,AX ;AN013;AND IN BOOT RECORD + + MOV VOLSER_FLAG,TRUE ;AN013;REQUEST THE NEW VOL SERIAL NUMBER BE WRITTEN + +; $ENDIF ;AN013;BOOT HAVE SERIAL? +$$IF70: +; $ENDIF ;AN013;PROPER DESCRIPTOR? +$$IF69: + POP SI ;AN013;RESTORE THE INDEX REG + POP BX ;AN013;RESTORE THE BASE POINTER + POP ES ;AN013;RESTORE EXTRA SEG REG + RET ;AN013;RETURN TO CALLER +MAYBE_ADJUST_SERIAL ENDP ;AN013; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC WRITE_OP ;AN000;MAKE ENTRY IN LINK MAP +WRITE_OP PROC NEAR ;IOCTL WRITE A TRACK OPERATION * +; * +;***************************************************************************** + +WO_AGAIN: ; +; $SEARCH ; +$$DO73: + XOR AX, AX ; + MOV AL, SIDE ; + MOV Head, AX ;HEAD TO WRITE + MOV AL, TRACK_TO_WRITE ; + MOV Cylinder, AX ;TRACK TO WRITE + MOV FirstSectors, 0 ;???? SHOULD BE 1 BUT CURRENTLY 0 ??? + MOV AX, BUFFER_PTR ; + MOV Taddress_seg, AX ;BUFFER ADDRESS + MOV Taddress_off, 0 ; + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV CL, WRITE_FUNC ;= 41h + MOV DX, OFFSET IOCTL_R_W ; + CALL GENERIC_IOCTL ; + + CMP IO_ERROR, NO_ERROR ;OK? +; $LEAVE E ;YES, SUCCESS. EXIT THIS ROUTINE + JE $$EN73 + + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? + JE WO_AGAIN ; + ;ELSE HARD ERROR + ;WRITE FAILURE, LET'S TRY TO FORMAT. + CMP FORMAT_FLAG, ON ;WAS THIS TRACK FORMATTED BEFORE? +; $EXITIF E ;YES, GIVE UP WRITING AND + JNE $$IF73 + ; CHECK WHEN IT HAPPENDED. + ;GIVE UP WRITING AND SHOW ERROR MESSAGE. + INC COPY_ERROR ;INDICATE ERROR OCCURS DURING COPY. + MOV AH, WRITE_FUNC ; + mov dl, target_drive ; + CALL ERROR_MESSAGE ;SHOW MESSAGE 'WRITE ERROR SIDE, TRACK...' + + MOV MSG_FLAG, OFF ; +; $ORELSE ;ELSE TRY FORMAT AND TRY WRITE AGAIN + JMP SHORT $$SR73 +$$IF73: + + ;CR,LF,"Formatting while copying",CR,LF + PRINT MSGNUM_FORMATTING ;AN000;SHOW MESSAGE + + MOV FORMAT_FLAG, ON ;FORMAT ALL TRACKS FROM THIS TRACK + CALL FORMAT_ALL ;format all the rest of the tracks + + CMP COPY_STATUS, FATAL ; +; $ENDLOOP E ; + JNE $$DO73 +$$EN73: +.XLIST ; +;this next is dead code, nobody calls WO_FATAL, so the move copy_status +;and the print not compatible msg should be removed, and just the JMP WO_EXIT +;will no longer be needed to skip stuff that is not there. Kiser +; JMP WO_EXIT ;AND EXIT THIS ROUTINE +;WO_FATAL: +; MOV COPY_STATUS, FATAL ;WE ARE GOING TO ABORT PROGRAM +; PRINT MSG_NOT_COMPATIBLE ;SHOW NOT COMPATIABLE MESSAGE +.LIST ; +; $ENDSRCH ; +$$SR73: +WO_EXIT: ; + RET ; + +WRITE_OP ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC FORMAT_ALL ;AN000;MAKE ENTRY IN LINK MAP +FORMAT_ALL PROC NEAR ; +; * +;Format all tracks starting from TRACK_TO_WRITE to the end. * +;This routine will set MT_deviceBPB to that of MS_deviceBPB. * +;trackLayout had been all set correctly. * +;If error, then fail to diskcopy. * +;***************************************************************************** + + MOV CX, MS_deviceBPB_leng ;set length of BPB + MOV SI, OFFSET MS_deviceBPB ; + MOV DI, OFFSET MT_deviceBPB ; + REP MOVSB ; + CALL CHK_MEDIATYPE ;set MT_mediaTYPE for FORMAT operation + + MOV MT_specialFunctions, SET_SP_BF_FORM ;=00000101B + MOV CL, SETDEVPARM ;=40h + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + XOR BX, BX ; + mov bl, last_track ;patch 3/27/86 for 3.2 diskcopy. J.K. + inc bl ; + mov MT_numberOfCylinders, bx ;make sure target # of cyl. + MOV BL, TARGET_DRIVE ; + CALL GENERIC_IOCTL ; + + JC FA_FATAL ; + + MOV FspecialFunctions, STATUS_CHK ;check to see if the parameters set + ;by "SET DEVICE PARM" func above are + ; supported or not. + MOV AX,(IOCTL_FUNC SHL 8)+GENERIC_IOCTL_CODE ;AC000;(440DH) + MOV CH, MAJOR_CODE ;=8 + MOV CL, FORMAT_FUNC ;=42H + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV DX, OFFSET IOCTL_FORMAT ;result is in Fspecialfunction + INT 21H ;0 - Thre is ROM support of AH=18h, INT 13h, and + ; it is a valid combination + + MOV AL, FspecialFunctions ;1 - No ROM support. 2 - There is ROM support, + ; but invalid combination + MOV FspecialFunctions, FORMAT_SP_FUNC ;restore specialfunction value + CMP AL, 2 ;ROM support, but this combination is not valid? + JE FA_FATAL ; + + MOV AL, TRACK_TO_WRITE ; + MOV TRACK_TO_FORMAT, AL ; + MOV AL, SIDE ; + MOV SIDE_TO_FORMAT, AL ; + CMP AL, NO_OF_SIDES ; + JE FA_SIDE_WHILE ;STARTS WITH THE OTHER SIDE TO FORMAT + +FA_TRACK_WHILE: ; + MOV AL, LAST_TRACK ; + CMP TRACK_TO_FORMAT, AL ; + JA FA_DONE ; + +FA_SIDE_WHILE: ; + MOV AL, NO_OF_SIDES ; + CMP SIDE_TO_FORMAT, AL ; + JA FA_NEXT_TRACK ; + + CALL FORMAT_TRACK ;FORMAT THIS TRACK + + CMP IO_ERROR, HARD_ERROR ; + JNE FA_NEXT_SIDE ; + + CMP SIDE_TO_FORMAT, 1 ;HARD ERROR AT SIDE 1? + JNE FA_TARGET_BAD ;THEN ASSUME TARGET DISKETTE BAD + + CMP TRACK_TO_FORMAT, 0 ;AT CYLINDER 0? + JNE FA_TARGET_BAD ; + + JMP FA_FATAL ;THEN, SOURCE IS TWO SIDED AND + ; TARGET IS SINGLE SIDE DISKETTE + +FA_NEXT_SIDE: ; + INC SIDE_TO_FORMAT ; + JMP FA_SIDE_WHILE ; + +FA_NEXT_TRACK: ; + MOV SIDE_TO_FORMAT, 0 ;RESET SIDE_TO_FORMAT + INC TRACK_TO_FORMAT ; + JMP FA_TRACK_WHILE ; + +FA_FATAL: ; + MOV COPY_STATUS, FATAL ;WE ARE GOING TO ABORT PROGRAM + ;"Drive types or diskette types" + ;"not compatible" + PRINT MSGNUM_NOT_COMPATIBLE ;AC000;SHOW NOT COMPATIBLE MESSAGE + + JMP SHORT FA_DONE ; + +FA_TARGET_BAD: ; + MOV COPY_STATUS, FATAL ;WE ARE GOING TO ABORT PROGRAM + ;CR,LF,"TARGET diskette bad or incompatible" + PRINT MSGNUM_BAD_TARGET ;AC000;SHOW TARGET BAD MESSAGE + +FA_DONE: ; + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV T_DRV_SET_FLAG, 1 ;INDICATE TARGET DRIVE PARM HAS BEEN SET + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + MOV MT_specialFunctions, SET_SP_FUNC_DEF ; + CALL SET_DRV_PARM_DEF ;SET IT BACK FOR WRITING. + + RET ; +FORMAT_ALL ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;****************************************************************************** +; SUBROUTINE NAME : FORMAT_TRACK - IOCTL FORMAT A TRACK * +; (BOTH SIDES IF 2-SIDED DSKT) * +; * +; INPUT : TRACK_TO_FORMAT * +; : SIDE BYTE 0, 1 (HEAD NUMBER) * +; : END_OF_TRACK BYTE 8, 9, 15 * +; : TARGET_DRIVE BYTE 1 = A, 2 = B, ETC * +; * +; OUTPUT : none. This routine does not report format error. * +; Write routine will detect the error consequently. * +; REGISTER(S) AFFECTED: * +;****************************************************************************** + PUBLIC FORMAT_TRACK ;AN000;MAKE ENTRY IN LINK MAP +FORMAT_TRACK PROC NEAR ; + +FT_AGAIN: ; +; $DO ; +$$DO79: + XOR AX, AX ; + MOV AL, SIDE_TO_FORMAT ; + MOV FHead, AX ;HEAD TO FORMAT + MOV AL, TRACK_TO_FORMAT ; + MOV FCylinder, AX ;TRACK TO FORMAT + + XOR BX, BX ; + MOV BL, TARGET_DRIVE ;DRIVE TO FORMAT + MOV CL, FORMAT_FUNC ;=42h + MOV DX, OFFSET IOCTL_FORMAT ; + CALL GENERIC_IOCTL ; + + CMP IO_ERROR, SOFT_ERROR ;TRY FORMAT AGAIN? + ; (DRIVE NOT READY OR WRITE PROTECTED) +; $ENDDO NE ; + JE $$DO79 + + RET ; +FORMAT_TRACK ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * + PUBLIC CHECK_SOURCE ;AN000;MAKE ENTRY IN LINK MAP +CHECK_SOURCE PROC NEAR ;CHECK SOURCE DISKETTE TYPE * +; SET END_OF_TRACK, LAST_TRACK * +; NO_OF_SIDES, bSECTOR_SIZE * +; ** this routine will call "Get dev parm" with "BUILD BPB BIT" on. If it * +; ** fails to get that info, then the source medium must be bad(vergin) or * +; ** below DOS 2.0 level diskette, and will jmp to the old logic. * +; ** For compatibility reasons (in case of non IBM formatted media), this * +; ** routine covers old diskcopy routines. But this will only supports +; ** 5.25" 48 tpi 8, 9 sectors, 40 tracks and 5.25" 96 tpi, 15 sectors, 80 tracks +; ** media. Other non IBM formatted media which are formatted differenty +; ** from those values will result in unpreditable copy process. +;***************************************************************************** + +; $DO ; +$$DO81: + XOR BX, BX ; + MOV BL, SOURCE_DRIVE ; + MOV MS_specialFunctions, GET_SP_FUNC_MED ;=00000001b + MOV CL, GETDEVPARM ;=60h + MOV DX, OFFSET MS_IOCTL_DRV_PARM ; + CALL GENERIC_IOCTL ;TRY TO GET MEDIA BPB INFO TOGETHER + ;WITH DEFAULT DEVICE INFO. + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? +; $ENDDO NE ; + JE $$DO81 + + CMP IO_ERROR, HARD_ERROR ;CANNOT GET MEDIA BPB? + JE CS_OLD ;ASSUME OLD FORMATTED DISKETTE, FIRST. + + cmp ms_deviceBPB.csect_track,0 ;patch 1/16/86 + je cs_old ; + + cmp ms_deviceBPB.chead,0 ;cannot trust the info from dos + je cs_old ;sanity check for divide by 0 + + MOV AX, MS_deviceBPB.CTOTSECT ; + CWD ;CONVERT IT TO A DOUBLE WORD + DIV MS_deviceBPB.CSECT_TRACK ; + DIV MS_deviceBPB.CHEAD ;(TOTAL SECTORS / # OF TRACKS) / # OF HEADS + CMP AL, T_DRV_TRACKS ;SOURCE MEDIA # OF TRACK > TARGET + ; DEVICE # OF TRACKS? + JA CS_FATAL ;THEN, NOT COMPATIBLE. + + DEC AX ;DECREASE BY 1 FOR THE USE OF THIS PROGRAM. + MOV LAST_TRACK, AL ;SET LAST_TRACK + MOV AX, MS_deviceBPB.CSECT_TRACK ; + CMP AL, T_DRV_SECT_TRACK ;SOURCE MEDIA # OF SECT/TRACK > TARGET + ; DEVICE # OF SECT/TRACK? + JA CS_FATAL ;THEN, NOT COMPATIBLE + + MOV END_OF_TRACK, AL ; + MOV AX, MS_deviceBPB.CBYTE_SECT ; + MOV bSECTOR_SIZE, AX ;set the sector size in bytes. + CMP USER_OPTION, 1 ; + JE CS_OPTION_1 ; + + MOV AX, MS_deviceBPB.CHEAD ;HEAD=1, 2 + CMP AL, T_DRV_HEADS ;COMPARE SOURCE MEDIA SIDE WITH + ; TARGET DRIVE HEAD NUMBER + JA CS_FATAL ;SOURCE MEDIUM IS DOUBLE SIDED AND + ; TARGET DRIVE IS SINGLE SIDED. + + DEC AX ; + MOV NO_OF_SIDES, AL ;NO_OF_SIDES=0, 1 + JMP CS_SET_TABLE ; +; = = = = = = = = = = = +CS_FATAL: ; + MOV COPY_STATUS, FATAL ; + ;CR,LF,"Drive types or diskette types",CR,LF + ;"not compatible",CR,LF + PRINT MSGNUM_NOT_COMPATIBLE ;AC000; + JMP CS_EXIT ; + +; = = = = = = = = = = = +CS_BAD: ; + MOV COPY_STATUS, FATAL ; + PRINT MSGNUM_BAD_SOURCE ;CR,LF,"SOURCE diskette bad or incompatible" + + JMP CS_EXIT ; + +; = = = = = = = = = = = +CS_OLD: ; + MOV READ_S_BPB_FAILURE, 1 ;SET FLAG + MOV bSECTOR_SIZE, 512 ;OLD SECTOR SIZE MUST BE 512 BYTES + XOR BX, BX ; + MOV BL, SOURCE_DRIVE ; + MOV IOCTL_TRACK, 0 ;TRACK=0 + MOV IOCTL_SECTOR, 8 ;SECTOR=8 + MOV IOCTL_HEAD, 0 ;HEAD = 0 + CALL READ_A_SECTOR ; + + JC CS_BAD ;SOURCE BAD + + MOV IOCTL_SECTOR, 9 ;TRY TO READ SECTOR=9 + CALL READ_A_SECTOR ; + + JC CS_SECT8 ;YES, 8 SECTORS. ASSUME 40 TRACKS + + MOV IOCTL_SECTOR, 15 ;try to read sector=15 + CALL READ_A_SECTOR ; + + JC CS_SECT9 ;**REMEMBER THIS ROUTINE DOES NOT COVER 3.5" MEDIA + + JMP SHORT CS_SECT15 ; + +; = = = = = = = = = = = +CS_OPTION_1: ; + MOV NO_OF_SIDES, 0 ;1 SIDE COPY + JMP SHORT CS_SET_TABLE ; + +; = = = = = = = = = = = +CS_SECT15: ; + MOV END_OF_TRACK, 15 ;ELSE END_OF_TRACK = 15 + MOV LAST_TRACK, 79 ; + JMP SHORT CS_CHK_SIDE ; + +; = = = = = = = = = = = +CS_SECT8: ; + MOV END_OF_TRACK, 8 ;SOURCE 8 SECTORS + MOV LAST_TRACK, 39 ;ASSUME 40 TRACKS. + JMP SHORT CS_CHK_SIDE ; + +; = = = = = = = = = = = +CS_SECT9: ; + MOV END_OF_TRACK, 9 ; + MOV LAST_TRACK, 39 ;ASSUME 5.25 DISKETTE + JMP SHORT CS_CHK_SIDE ; + +; = = = = = = = = = = = +CS_CHK_SIDE: ; + CMP USER_OPTION, 1 ; + JE CS_OPTION_1 ; + + MOV IOCTL_HEAD, 1 ;HEAD 1 + XOR AX, AX ; + MOV AL, END_OF_TRACK ;READ MATCHING END_OF_TRACK + ; OF THE OTHER SURFACE. + MOV IOCTL_SECTOR, AX ; + CALL READ_A_SECTOR ; + + JC CS_OPTION_1 ;1 SIDED SOURCE + + MOV NO_OF_SIDES, 1 ;2 SIDED SOURCE + CMP T_DRV_HEADS, 2 ;SOUCE=2 SIDED MEDIUM. IS TARGET + ; DOUBLE SIDED DRV? + JE CS_SET_TABLE ; + + JMP CS_FATAL ;NOT COMPATIBLE + +; = = = = = = = = = = = +CS_SET_TABLE: ; + CMP READ_S_BPB_FAILURE, 1 ;DISKETTE WITHOUT BPB INFO? +; $IF E ; + JNE $$IF83 + CALL SET_FOR_THE_OLD ; + +; $ENDIF ; +$$IF83: + MOV BX, OFFSET MS_trackLayout ;SET TRACKLAYOUT OF SOURCE + CALL SET_TRACKLAYOUT ; + + MOV BX, OFFSET MT_trackLayout ;YES, ASSUME TARGET IS SAME + CALL SET_TRACKLAYOUT ; + + MOV S_DRV_SET_FLAG, 1 ; + XOR BX, BX ; + MOV BL, SOURCE_DRIVE ; + MOV MS_specialFunctions, SET_SP_FUNC_DEF ;=00000100B + MOV DX, OFFSET MS_IOCTL_DRV_PARM ; + CALL SET_DRV_PARM_DEF ;NOW, SET SOURCE DRIVE PARM + ; FOR READ OPERATION. + + XOR AX, AX ; + MOV AL, END_OF_TRACK ; + MOV numberOfSectors, AX ;SET NUMBEROFSECTORS IN IOCTL_R_W TABLE + + MOV AL, LAST_TRACK ;NOW, SHOW THE MESSAGE "COPYING ..." + INC AL ; +.XLIST ; +; MOV BYTE PTR MSG_COPYING_PTR+2, AL ;HOW MANY TRACKS? +.LIST ; + MOV BYTE PTR MSG_TRACKS, AL ;AC000;HOW MANY TRACKS? + + MOV AL, END_OF_TRACK ; +.XLIST ; +; MOV BYTE PTR MSG_COPYING_PTR+4, AL ;HOW MANY SECTORS? +.LIST ; + MOV BYTE PTR MSG_SECTRK,AL ;AC000;HOW MANY SECTORS? + + MOV AL, NO_OF_SIDES ;TELL USER HOW MANY SIDE TO COPY + INC AL ; +.XLIST ; +; MOV BYTE PTR MSG_COPYING_PTR+6, AL +.LIST ; + MOV BYTE PTR MSG_SIDES,AL ;AC000;HOW MANY SIDES? + ;CR,LF,"Copying %1 tracks",CR,LF + ;"%2 Sectors/Track, %3 Side(s)",CR,LF + PRINT MSGNUM_COPYING ;AC000; + +CS_EXIT: ; + RET ; + +CHECK_SOURCE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;****************************************************************************** + PUBLIC READ_A_SECTOR ;AN000;MAKE ENTRY IN LINK MAP +READ_A_SECTOR PROC NEAR ; +; * +;TRY TO READ A SECTOR USING IOCTL READ FUNCTION CALL. * +;THIS ROUTINE WILL STEAL "IOCTL_R_W" TABLE TEMPORARILY. * +;INPUT: BX - LOGICAL DRIVE NUMBER * +; IOCTL_SECTOR - SECTOR TO READ * +; IOCTL_TRACK - TRACK * +; IOCTL_HEAD - HEAD TO READ * +; bSECTOR_SIZE - SECTOR SIZE IN BYTES * +;OUTPUT: * +; IF NOT A SUCCESS, CARRY WILL BE SET * +; ALL REGISTORS SAVED * +; +;****************************************************************************** + + PUSH AX ; + PUSH BX ; + PUSH CX ; + PUSH DX ; + + MOV AX, numberOfSectors ;SAVE IOCTL_R_W TABLE VALUES + MOV SAV_CSECT, AX ; + +;RAS_AGAIN: +; $DO ; +$$DO85: + MOV AX, IOCTL_HEAD ; + MOV Head, AX ;SURFACE TO READ + MOV AX, IOCTL_TRACK ; + MOV Cylinder, AX ;TRACK TO READ + MOV AX, IOCTL_SECTOR ; + dec ax ;????? currently + ; firstsector=0 => 1st sector ???? + MOV FirstSectors, AX ;SECTOR TO READ + MOV numberOfSectors, 1 ;read just one sector + MOV AX, offset INIT ;READ IT INTO INIT + ; (CURRELTLY, MAX 1K) + MOV TAddress_off, AX ; + MOV TAddress_seg, DS ; + MOV CL, READ_FUNC ; + MOV DX, OFFSET IOCTL_R_W ;POINTS TO CONTROL TABLE + call generic_ioctl ; + + CMP IO_ERROR, SOFT_ERROR ;TRY ONCE MORE? +; $ENDDO NE ; + JE $$DO85 + + CMP IO_ERROR, HARD_ERROR ;HARD ERROR? +; $IF NE ; + JE $$IF87 + + CLC ;READ SUCCESS +; $ELSE ; + JMP SHORT $$EN87 +$$IF87: + STC ;SET CARRY +; $ENDIF ; +$$EN87: + MOV AX, SAV_CSECT ;RESTORE ORIGINAL IOCTL_R_W TABLE + MOV numberOfSectors, AX ; + POP DX ; + POP CX ; + POP BX ; + POP AX ; + RET ; + +READ_A_SECTOR ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC CALC_TRACK_SIZE ;AN000;MAKE ENTRY IN LINK MAP +CALC_TRACK_SIZE PROC NEAR ;CALCULATE MEMORY SIZE REQUIRED TO STORE ONE +; TRACK (IN SEGMENTS) * +; +;CALCULATE SECTOR_SIZE IN PARA FROM bSECTOR_SIZE. IF bSECTOR_SIZE CANNOT BE * +;CHANGED TO SECTOR_SIZE IN PARA EXACTLY, THEN ADD 1 TO THE SECTOR_SIZE. * +;SECTOR_SIZE IS USED FOR MEMORY MANAGEMANT ONLY. THE ACTUAL COPY OR FORMAT * +;SHOULD BE DEPENDS ON bSECTOR_SIZE TO FIGURE OUT HOW BIG A SECTOR IS. * +;ALSO, CURRENTLY, THIS ROUTINE ASSUME A BSECTOR SIZE BE LESS THAN 0FFFh. * +;***************************************************************************** + + PUSH AX ; + PUSH BX ; + PUSH CX ; + + MOV AX, bSECTOR_SIZE ; + MOV CL, 16 ; + DIV CL ;AX / 16 = AL ... AH + CMP AH, 0 ;NO REMAINER? +; $IF NE ; + JE $$IF90 + + INC AL ;THERE REMAINER IS. INC AL + +; $ENDIF ; +$$IF90: + MOV SECTOR_SIZE, AL ;SECTOR_SIZE+ IN PARA. + MOV AL,NO_OF_SIDES ;TRACK_SIZE = (NO OF SIDES + INC AL ; + 1) + MUL END_OF_TRACK ; * END_OF_TRACK + MOV BL,SECTOR_SIZE ; * SECTPR_SIZE + MUL BL ;AMOUNT OF MEMORY REQUIRED (IN SEG) + MOV TRACK_SIZE,AX ;TO STORE A TRACK + POP CX ; + POP BX ; + POP AX ; + + RET ; +CALC_TRACK_SIZE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC CHECK_MEMORY_SIZE ;AN000;MAKE ENTRY IN LINK MAP +CHECK_MEMORY_SIZE PROC NEAR ;MAKE SURE WE HAVE ENOUGH TO COPY 1 TRACK INTO +; TO BUFFER ELSE ABORT COPY * +;***************************************************************************** + MOV AX,BUFFER_END ;CALCULATE AVAILABLE MEMORY + SUB AX,BUFFER_BEGIN ;IN SEGMENTS + CMP AX,TRACK_SIZE ;DO WE HAVE ENOUGH TO STORE A CYLINDER? +; $IF B ; + JNB $$IF92 + MOV COPY_STATUS,FATAL ;NO, ABORT COPY + PRINT MSGNUM_UNSUF_MEMORY ;AC000;AND TELL USER WHY + +; $ENDIF ; +$$IF92: + RET ; + +CHECK_MEMORY_SIZE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC SET_FOR_THE_OLD ;AN000;MAKE ENTRY IN LINK MAP +SET_FOR_THE_OLD PROC NEAR ; + +;set MS_deviceBPB for before-2.0 formatted media +;***************************************************************************** + PUSH AX ; + + CMP END_OF_TRACK,9 ;IF SECTORS/TRACK <= 9, THEN CHECK + ;NO_OF_SIDES. IF SINGLE SIDE + ; COPY THEN USE BPB48_SINGLE + ;ELSE USE BPB48_DOUBLE. +; $IF A ;SECTORS/TRACK > 9 THEN USE BPB96 TABLE + JNA $$IF94 + MOV SI, OFFSET BPB96 ; +; $ELSE ; + JMP SHORT $$EN94 +$$IF94: + CMP NO_OF_SIDES, 0 ;SINGLE SIDE COPY? +; $IF NE ;IF NOT, + JE $$IF96 + MOV SI, OFFSET BPB48_DOUBLE ;USE BPB48 DOUBLE +; $ELSE ; + JMP SHORT $$EN96 +$$IF96: + MOV SI, OFFSET BPB48_SINGLE ; +; $ENDIF ; +$$EN96: +; $ENDIF ; +$$EN94: + XOR AX, AX ; + MOV AL, END_OF_TRACK ; + + MOV MS_deviceBPB.CSECT_TRACK,AX ;SET # OF SECTORS IN IOCTL_DRV_PARM + MOV DI, OFFSET MS_deviceBPB ; + MOV CX, BPB96_LENG ; + REP MOVSB ;OLD DEFAULT BPB INFO => MS_deviceBPB + + POP AX ; + RET ; +SET_FOR_THE_OLD ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC SET_TRACKLAYOUT ;AN000;MAKE ENTRY IN LINK MAP +SET_TRACKLAYOUT PROC NEAR ; + +;INPUT: BX - POINTER TO DESTINATION +;***************************************************************************** + + XOR CX, CX ; + MOV CL, END_OF_TRACK ; + MOV WORD PTR [BX], CX ;SET CSECT_F TO THE NUMBER OF + ; SECTORS IN A TRACK + ADD BX, 2 ;NOW BX POINTS TO + ; THE FIRST SECTORNUMBER + MOV CX, 1 ; + MOV AX, bSECTOR_SIZE ; + +; $DO ; +$$DO100: + CMP CL, END_OF_TRACK ; +; $LEAVE A ; + JA $$EN100 + + MOV WORD PTR [BX], CX ; + INC BX ; + INC BX ; + MOV WORD PTR [BX], AX ; + INC BX ; + INC BX ; + + INC CX ; +; $ENDDO ; + JMP SHORT $$DO100 +$$EN100: + + RET ; +SET_TRACKLAYOUT ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC CHECK_TARGET ;AN000;MAKE ENTRY IN LINK MAP +CHECK_TARGET PROC NEAR ; * +; ** THIS ROUTINE WILL TRY TO READ TARGET MEDIA BOOT RECORD. * +; ** IF A SUCCESS,THEN COMPARES BPB INFO WITH THAT OF SOURCE MEDIA. * +; ** IF THEY ARE DIFFERENT, THEN SET FORMAT_FLAG AND RETURN. * +; ** IF FAILED TO READ A BOOT, THEN TRY OLD LOGICS BEFORE DOS 3.2 FOR * +; ** COMPATIBILITY REASON. * +;***************************************************************************** + +; $DO ; +$$DO103: + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV MT_specialFunctions, GET_SP_FUNC_MED ;=00000001b + MOV CL, GETDEVPARM ;=60h + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + CALL GENERIC_IOCTL ;TRY TO GET MEDIA BPB INFO TOGETHER + ;WITH DEFAULT DEVICE INFO. + CMP IO_ERROR, SOFT_ERROR ;TRY AGAIN? +; $ENDDO NE ; + JE $$DO103 + + CMP IO_ERROR, HARD_ERROR ;CANNOT GET MEDIA BPB? + JE CT_OLD ;ASSUME OLD FORMATTED DISKETTE, FIRST. + + cmp mt_deviceBPB.csect_track,0 ;patch 1/16/86 for 3.2 diskcopy + je ct_old ; + + cmp mt_deviceBPB.chead,0 ;cannot belive the info from dos + je ct_old ;sanity check for divide by 0. + + MOV AX, MT_deviceBPB.CTOTSECT ; + CWD ;CONVERT IT TO A DOUBLE WORD + DIV MT_deviceBPB.CSECT_TRACK ; + DIV MT_deviceBPB.CHEAD ;(TOTAL SECTORS / # OF TRACKS) / # OF HEADS + DEC AX ;DECREASE BY 1 FOR THIS PROGRAM. + CMP LAST_TRACK, AL ;COMPARE WITH THE LAST TRACK OF SOURCE + JE CT_SECTOR_TRACK ;IF SAME, THEN CHECK SECTOR PER TRACK + ;SINCE NOT THE SAME, CONTINUE... + + CMP MT_deviceBPB.CSECT_TRACK,0FH ;AN012;IS TARGET 15 SEC / TRK? + JNE CT_FORMAT ;AN012;NO, SOMETHING ELSE... + ;YES, 15 SEC/TRACK, CONTINUE... + + CMP LAST_TRACK,27H ;AN012;IS SOURCE ORIGINALLY 40 TRACK? + JNE CT_FORMAT ;AN012;NO, SOMETHING ELSE... + ;YES, 40 TRACK, CONTINUE... + JMP CT_FATAL ;AN012;ABORT THIS, DO NOT MESS UP THE 1.2M + ; WITH NOBLE ATTEMPTS TO FORMAT +CT_SECTOR_TRACK: ; + MOV AX, MT_deviceBPB.CSECT_TRACK ; + CMP END_OF_TRACK, AL ; + JNE CT_FORMAT ; + +CT_BYTE_SECTOR: ; + MOV AX, MT_deviceBPB.CBYTE_SECT ; + CMP AX, bSECTOR_SIZE ; + JNE CT_FORMAT ; + +CT_HEAD: ; + MOV AX, MT_deviceBPB.CHEAD ; + DEC AX ; + CMP AL, NO_OF_SIDES ; + JB CT_FORMAT ;IF TARGET SIDE < SOURCE SIDE + ; THEN FORMAT IT. + + JMP CT_SET_DRV ;TARGET IS O.K. SET DRIVE PARM + ; AND EXIT + +CT_FORMAT: ; + PRINT MSGNUM_FORMATTING ;AC000;"Formatting while copying" + + MOV FORMAT_FLAG, ON ; + CALL FORMAT_ALL ;FORMAT ALL TRACKS STARTING + ; FROM TRACK_TO_WRITE + JMP CT_EXIT ; + +CT_OLD: ;AC011; + CMP UKM_ERR,ON ;AN011;IS THIS HARD ERROR "UNKNOWN MEDIA"? + JE CT_FORMAT ;AN011; IF SO, GO TRY FORMATTING + ;SAME OLD... ;AGAIN, THIS DOES + ; NOT RECOGNIZE 3.5 MEDIA + MOV READ_T_BPB_FAILURE, 1 ;SET THE FLAG + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV IOCTL_TRACK, 0 ; + MOV IOCTL_SECTOR, 8 ; + MOV IOCTL_HEAD, 0 ;TRY TO READ HEAD 0, TRACK 0, SECTOR 8 + CALL READ_A_SECTOR ; + + JC CT_FORMAT ;ASSUME TARGET MEDIA NOT FORMATTED. + + MOV IOCTL_SECTOR, 9 ;TRY TO READ SECTOR 9 + CALL READ_A_SECTOR ; + + JC CT_8_SECTOR ;TARGET IS 8 SECTOR MEDIA + + MOV IOCTL_SECTOR, 15 ; + CALL READ_A_SECTOR ; + + JC CT_9_SECTOR ;TARGET IS 9 SECTOR MEDIA + +;CT_15_SECTOR: ;TARGET IS 15 SECTOR MEDIA + CMP END_OF_TRACK, 15 ;IS SOURCE ALSO 96 TPI? + JNE CT_FATAL ;NO, FATAL ERROR + + JMP CT_EXIT_OLD ;OK + +CT_8_SECTOR: ; + CMP END_OF_TRACK, 15 ; + JE CT_FATAL ;IF SOURCE IS 96 TPI, THEN FATAL ERROR + + CMP END_OF_TRACK, 9 ; + JE CT_FORMAT ;IF SOURCE IS 9 SECTOR, THEN + ; SHOULD FORMAT TARGET + + JMP CT_EXIT_OLD ;ELSE ASSUME SOURCE IS 8 SECTOR. + +CT_9_SECTOR: ; + CMP END_OF_TRACK, 15 ;IS SOURCE 96 TPI ? + JNE CT_EXIT_OLD ;NO. SOUCE IS 8 OR 9 + ; SECTORED 48 TPI DISKETTE + +CT_FATAL: ; + MOV COPY_STATUS, FATAL ; + ;"Drive types or diskette types" + PRINT MSGNUM_NOT_COMPATIBLE ;AC000;"not compatible" + + JMP SHORT CT_EXIT ; + +CT_EXIT_OLD: ; + MOV CX, MS_deviceBPB_leng ; + MOV SI, OFFSET MS_deviceBPB ; + MOV DI, OFFSET MT_deviceBPB ; + REP MOVSB ;set MT_deviceBPB to MS_deviceBPB +CT_SET_DRV: ; + MOV T_DRV_SET_FLAG, 1 ;INDICATE THE TARGET DEFAULT + ; DEVICE PARM HAS BEEN SET. + XOR BX, BX ; + mov bl, last_track ;patch for 3.2 diskcopy, 3/27/86 J.K. + inc bl ; + mov MT_numberOfCylinders, bx ;make sure the # of cyl of the target + MOV BL, TARGET_DRIVE ; + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + MOV MT_specialFunctions, SET_SP_FUNC_DEF ; + CALL SET_DRV_PARM_DEF ; + +CT_EXIT: ; + RET ; + +CHECK_TARGET ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC CHK_MULTI_MEDIA ;AN000;MAKE ENTRY IN LINK MAP +CHK_MULTI_MEDIA PROC NEAR ; +;IF THE SOURCE IS 96 TPI DISKETTE, AND TARGET IS 48 TPI +;DISKETTE, OR VICE VERSA, THEN SET THE CARRY BIT. +;THIS ROUTINE BE CALLED WHEN BPB INFORMATIONS OF TARGET HAS BEEN SUCCESSFULLY +;READ. +;*** CURRENTLY, ONLY 96 TPI DRIVE IN PC_AT CAN HAVE MULTI_MEDIA. +;INPUT: AX - TARGET MEDIA CYLINDER NUMBER - 1 +; LAST_TRACK - SOURCE MEDIA CYLINDER NUMBER - 1 +;***************************************************************************** + CLC ;CLEAR CARRY + CMP LAST_TRACK, 39 ;SOURCE IS 48 TPI MEDIA? +; $IF E,AND ; + JNE $$IF105 + CMP AL, 79 ;AND TARGET IS 96 TPI MEDIA? +; $IF E ; + JNE $$IF105 + STC ;THEN SET CARRY +; $ELSE ; + JMP SHORT $$EN105 +$$IF105: + CMP LAST_TRACK, 79 ;SOURCE IS 96 TPI MEDIA? +; $IF E,AND ; + JNE $$IF107 + CMP AL, 39 ;AND TARGET IS 48 TPI? +; $IF E ; + JNE $$IF107 + STC ; +; $ENDIF ; +$$IF107: +; $ENDIF ; +$$EN105: + RET ; +CHK_MULTI_MEDIA ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC SET_DRV_PARM_DEF ;AN000;MAKE ENTRY IN LINK MAP +SET_DRV_PARM_DEF PROC NEAR ; +;SET THE DRV PARMAMETERS +;INPUT: BL - DRIVE NUMBER +; DX - POINTER TO THE DEFAULT PARAMETER TABLE +; specialfunc should be set before calling this routine +;***************************************************************************** + MOV CL, SETDEVPARM ;=40H + CALL GENERIC_IOCTL ; + + RET ; +SET_DRV_PARM_DEF ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC CHK_MEDIATYPE ;AN000;MAKE ENTRY IN LINK MAP +CHK_MEDIATYPE PROC NEAR ; +;SET THE mediaType OF IOCTL_DRV_PARM FOR TARGET DRIVE IN CASE OF FORMAT. +;IF TARGET IS A MULTI-MEDIA DEVICE, mediaType SHOULD BE SET CORRECTLY +;TO FORMAT THE TARGET MEDIA. +;IF EITHER OF LAST_TRACK OR END_OF_TRACK IS LESS THAN THAT OF TARGET +;DRIVE, THEN mediaType WILL BE SET TO 1. OTHERWISE, IT WILL BE 0 FOR +;THE DEFAULT VALUE. +;***************************************************************************** + + MOV AL, T_DRV_TRACKS ;TARGET DEVICE MAXIUM TRACKS + DEC AL ; + CMP LAST_TRACK, AL ;COMPARE SOURCE MEDIA # OF TRACKS TO IT +; $IF B,OR ; + JB $$LL110 + MOV AL, T_DRV_SECT_TRACK ; + CMP END_OF_TRACK, AL ;SOURCE # OF SECT/TRACK < TARGET DEVICE? +; $IF B ; + JNB $$IF110 +$$LL110: + MOV MT_mediaType, 1 ; +; $ENDIF ; +$$IF110: + RET ; +CHK_MEDIATYPE ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC GENERIC_IOCTL ;AN000;MAKE ENTRY IN LINK MAP +GENERIC_IOCTL PROC NEAR ; +;INPUT: CL - MINOR CODE; 60 - GET DEVICE PARM, 40 - SET DEVICE PARM +; 61 - READ TRACK, 41 - WRITE TRACK, +; 42 - FORMAT AND VERIFY TRACK, 43 - SET MEDIA ID +; 62 - VERIFY TRACK, 63 - GET MEDIA ID +; BL - LOGICAL DRIVE LETTER +; DS:DX - POINTER TO PARAMETERS +;***************************************************************************** + MOV IO_ERROR, NO_ERROR ;reset io_error + MOV CH, MAJOR_CODE ;MAJOR CODE, REMOVABLE = 08H + DOSCALL IOCTL_FUNC,GENERIC_IOCTL_CODE ;AC000;(440DH) CALL THE DEVICE DRIVER + +; $IF C ; + JNC $$IF112 + CALL EXTENDED_ERROR_HANDLER ;ERROR, SEE WHAT IT IS! + +; $ENDIF ; +$$IF112: + RET ; +GENERIC_IOCTL ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC EXTENDED_ERROR_HANDLER ;AN000;MAKE ENTRY IN LINK MAP +EXTENDED_ERROR_HANDLER PROC NEAR ; +;INPUT: BL - LOGICAL DRIVE LETTER +;***************************************************************************** + + PUSHF ; + PUSH AX ; + PUSH BX ; + PUSH CX ; + PUSH DX ; + PUSH SI ; + PUSH DI ; + PUSH ES ; + PUSH DS ; + PUSH BX ; + + MOV AH, EXTENDED_ERROR ;59H + MOV BX, 0 ; + INT 21H ; + + POP BX ;RESTORE BL FOR DRIVE LETTER + POP DS ; + POP ES ; + + CMP AX, 21 ;DRIVE NOT READY? (TIME_OUT ERROR?) + JE EEH_CHK_TIMEOUT ; + + CMP AX, 19 ;ATTEMP TO WRITE ON WRITE_PROTECTED? + JE WARN_USER_2 ; + + JMP EEH_HARD_ERROR ;OTHERWISE, HARD_ERROR + +EEH_CHK_TIMEOUT: ;BECAUSE OF THE INACCURACY + ; OF TIME OUT ERROR, + ;IN READING AND WRITING OPERATION, + ; CHECK OUT CAREFULLY WITH "FORMAT" + CMP FORMAT_FLAG, ON ;AFTER OR DURING FORMAT OPERATION, + JE WARN_USER_1 ; TIME OUT ERROR IS + ; ASSUMED TO BE CORRECT. + + CMP TRY_FORMAT_FLAG, ON ;HAPPENED AT "TRY_FORMAT" PROCEDURE? + JE EEH_TIMEOUT ; + + CMP TARGET_OP, ON ;HAPPENED ON TARGET DRIVE? + JNE WARN_USER_1 ;IF NOT, THEN ASSUME TIME OUT ERROR + + MOV TRY_FORMAT_FLAG, ON ; + CALL TRY_FORMAT ;JUST TRY TO FORMAT THE TRACK. + + MOV TRY_FORMAT_FLAG, OFF ; + CMP TIME_OUT_FLAG, ON ;REAL TIME OUT? + JE WARN_USER_1 ;YES, A SOFT ERROR. + + CMP IO_ERROR, SOFT_ERROR ;IT HAPPENED AT TRY_FORMAT PROC AND + ; PC_AT WHEN THE DRIVE DOOR OPENED ABRUPTLY. + JE EEH_EXIT ;IT WAS WRITE PROTECTED ERROR. + + JMP EEH_HARD_ERROR ;NO, "ADDRESS MARK NOT OUT". A HARD ERROR. + +EEH_TIMEOUT: ; + MOV TIME_OUT_FLAG, ON ;SET TIME_OUT_FLAG AND EXIT THIS ROUTINE + JMP EEH_EXIT ; + +WARN_USER_1: ; + MOV DRIVE_LETTER, 'A' ; + DEC BL ;CHANGE LOGICAL TO PHYSICAL + ADD DRIVE_LETTER, BL ; + PRINT MSGNUM_GET_READY ;AC000;"Drive not ready - %0" + + PRINT MSGNUM_CLOSE_DOOR ;AN004;"Make sure a diskette is inserted into + ; the drive and the door is closed" + JMP WAIT_FOR_USER ; + +WARN_USER_2: ; + PRINT MSGNUM_WRITE_PROTECT ;AC000;"Attempt to write to write-protected diskette" + +WAIT_FOR_USER: ; + ;"Press any key when ready . . ." + CALL PRESS_ANY_KEY ;AC000; THEN WAIT FOR ANY RESPONSE + + MOV IO_ERROR, SOFT_ERROR ;INDICATE THE CALLER TO TRY AGAIN + JMP SHORT EEH_EXIT ; + +EEH_HARD_ERROR: ; + MOV IO_ERROR, HARD_ERROR ; + MOV UKM_ERR,OFF ;AN011;ASSUME NOT "UNKNOWN MEDIA" TYPE ERROR + CMP AX,26 ;AN011;IS THE ERROR TYPE IS "UNKNOWN MEDIA"? +; $IF E ;AN011;IF "UNKNOWN MEDIA" TYPE ERROR + JNE $$IF114 + MOV UKM_ERR,ON ;AN011;SET FLAG TO INDICATE "UNKNOWN MEDIA" + ; TO CAUSE FORMATTING OF TARGET DISKETTE +; $ENDIF ;AN011; +$$IF114: + +EEH_EXIT: ; + POP DI ; + POP SI ; + POP DX ; + POP CX ; + POP BX ; + POP AX ; + POPF ; + RET ; +.XLIST ; +;EEH_JUST_EXIT: +; JMP EXIT_PROGRAM ;UNCONDITIONAL EXIT (IN MAIN PROC) +.LIST ; +EXTENDED_ERROR_HANDLER ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** + PUBLIC TRY_FORMAT ;AN000;MAKE ENTRY IN LINK MAP +TRY_FORMAT PROC NEAR ; +;*** TRY TO FORMAT A TRACK. +;*** CALLED BY "EXTENDED_ERROR_HANDLER" TO CHECK THE TIME OUT ERROR IS A REAL +;*** ONE OR CAUSED BY "ADDR MARK NOT FOUND" ERROR.(THIS IS HARDWARE ERROR THAT +;*** DOES NOT GIVE CORRECT ERROR CODE). +;*** THIS ROUTINE WILL CALL "GENERIC_IOCTL" WHICH IN TURN WILL CALL "EXTENDED_ +;*** ERROR_HANDLER" WHERE THE ERROR WILL BE REEXAMINED. +;***************************************************************************** + PUSH ES ; + + PUSH DS ; + POP ES ; + + MOV CX, MS_deviceBPB_leng ;set length of BPB + MOV SI, OFFSET MS_deviceBPB ; + MOV DI, OFFSET MT_deviceBPB ; + REP MOVSB ; + CALL CHK_MEDIATYPE ;set MT_mediaTYPE for FORMAT operation + + MOV MT_specialFunctions, SET_SP_BF_FORM ;=00000101B + MOV CL, SETDEVPARM ;=40h + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + CALL GENERIC_IOCTL ; + + XOR AX, AX ; + MOV AL, SIDE ;SIDE TO FORMAT + MOV Fhead, AX ; + MOV AL, TRACK_TO_WRITE ;TRACK TO FORMAT + MOV Fcylinder, AX ; + + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV CL, FORMAT_FUNC ;=42h + MOV DX, OFFSET IOCTL_FORMAT ; + CALL GENERIC_IOCTL ; + + MOV AL, IO_ERROR ;SAVE IO_ERROR, IN CASE FOR PC_AT CASE. + PUSH AX ; + + XOR BX, BX ; + MOV BL, TARGET_DRIVE ; + MOV T_DRV_SET_FLAG, 1 ;INDICATE TARGET DRIVE PARM HAS BEEN SET + MOV DX, OFFSET MT_IOCTL_DRV_PARM ; + MOV MT_specialFunctions, SET_SP_FUNC_DEF ; + CALL SET_DRV_PARM_DEF ;SET IT BACK FOR NORMAL + ; OPERATION, EX. WRITING + + POP AX ; + MOV IO_ERROR, AL ;RESTORE IO_ERROR + + POP ES ; + + RET ; + +TRY_FORMAT ENDP ; +; = = = = = = = = = = = = + HEADER ;AN000; +;***************************************************************************** +; * +ERROR_MESSAGE PROC NEAR ;DISPLAY ERROR MESSAGE * + PUBLIC ERROR_MESSAGE ;AN000;MAKE ENTRY IN LINK MAP +; * +; FUNCTION: THIS SUBROUTINE DISPLAYS WHAT OPERATION FAILED (READ OR WRITE) * +; AND WHERE IT FAILED (TRACK NO. AND SIDE). * +; * +; INPUT: AH = IOCTL I/O COMMAND CODE (3=READ, 4=WRITE) * +; * +;***************************************************************************** + CMP AH,READ_FUNC ;ERROR DURING READ ? +.XLIST ; +; $IF E +; MOV BX,OFFSET READ_ERROR +; MOV MSG_HARD_ERR_TYPE,BX ;ERROR DURING READ OP +; MOV BL,TRACK_TO_READ ;SAVE BAD TRACK NUMBER FOR READ +; $ELSE +; MOV BX,OFFSET WRITE_ERROR +; MOV MSG_HARD_ERR_TYPE,BX ;ERROR DURING WRITE OP +; MOV BL,TRACK_TO_WRITE ;SAVE BAD TRACK NUMBER FOR WRITE +; $ENDIF +.LIST ; +; $IF E ;AN000;YES, READ ERROR + JNE $$IF116 + MOV BL,TRACK_TO_READ ;SAVE BAD TRACK NUMBER FOR READ + MOV DI,OFFSET MSGNUM_HARD_ERROR_READ ;AN000; +; $ELSE ;AN000;NO, NOT READ, MUST BE WRITE ERROR + JMP SHORT $$EN116 +$$IF116: + MOV BL,TRACK_TO_WRITE ;SAVE BAD TRACK NUMBER FOR WRITE + MOV DI,OFFSET MSGNUM_HARD_ERROR_WRITE ;AN000; +; $ENDIF ;AN000;READ ERROR? +$$EN116: + MOV AL,SIDE ; + MOV DRIVE_LETTER,"A" ; + dec dl ;change logical drive letter to physical one. + ADD DRIVE_LETTER,DL ;SHOW DRIVE LETTER +.XLIST ; +; MOV BYTE PTR MSG_HARD_ERROR_PTR+8,AL ;SIDE NUMBER +; MOV BYTE PTR MSG_HARD_ERROR_PTR+10,BL ;TRACK NUMBER WHERE THE ERROR +.LIST ; + MOV BYTE PTR ERROR_SIDE_NUMBER,AL ;AC000;SIDE NUMBER + MOV BYTE PTR ERROR_TRACK_NUMBER,BL ;AC000;TRACK NUMBER WHERE THE ERROR + ;CR,LF,"Unrecoverable read/write error on drive %1",CR,LF + CALL SENDMSG ;"Side %2, track %3",CR,LF ;ACN000; + + RET ; +ERROR_MESSAGE ENDP ; +.XLIST ; +; HEADER +;KB_INPUT_FUNC EQU 0C01H ;DOS KEYBOARD INPUT +;***************************************************************************** +; * +;PROMPT PROC NEAR ;DISPLAY MESSAGE * +; AND GET A USER INPUT CHARACTER * +; PUBLIC PROMPT * +; * +; INPUT: DX = MESSAGE POINTER * +; OUTPUT: BYTE USER_INPUT * +; * +;***************************************************************************** +; PUSH AX +; MOV AX,KB_INPUT_FUNC ;KEYBOARD INPUT +; INT 21H +; MOV USER_INPUT,AL ;SAVE USER'S RESPONSE +; POP AX +; RET +;PROMPT ENDP +; HEADER +;CALL_PRINTF PROC NEAR +; PUBLIC CALL_PRINTF +;INPUT - DX HAS OFFSET INTO DS OF MESSAGE PARM LIST +; PUSH DX +; PUSH CS +; CALL PRINTF + +; RET +;CALL_PRINTF ENDP +; = = = = = = = = = = = = +.list ; + HEADER ;AN000; +SENDMSG PROC NEAR ;AN000; + PUBLIC SENDMSG ;AN000; +; INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE +; OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED +; IF CARRY CLEAR, ALL OK +; IN EITHER CASE, DI AND AX ALTERED, OTHERS OK +; = = = = = = = = = = = = + + PUSH BX ;AN000;SAVE CALLER'S REGS + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + +; PASS PARMS TO MESSAGE HANDLER IN +; THE APPROPRIATE REGISTERS IT NEEDS. + MOV BX,[DI].MSG_NUM ;AC006;MESSAGE NUMBER + MOV SI,[DI].MSG_SUBLIST ;AN000;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE + MOV CX,[DI].MSG_COUNT ;AN000;NUMBER OF %PARMS, 0 IF NONE + MOV DX,[DI].MSG_CLASS ;AN000;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW + MOV AX,SELECT_MPX ;AN006;REQUEST THE SELECT MULTIPLEXOR, IF PRESENT + INT MULTIPLEXOR ;AN006;CALL THE MULTIPLEXOR FUNCTION + + CMP AL,SELECT_PRESENT ;AN006;CHECK MULTIPLEXOR RESPONSE CODE +; $IF NE ;AN006;IF SELECT HAS NOT HANDLED THE MESSAGE + JE $$IF119 + MOV AX,[DI].MSG_NUM ;AN000;MESSAGE NUMBER + MOV BX,[DI].MSG_HANDLE ;AN006;HANDLE TO DISPLAY TO + CALL SYSDISPMSG ;AN000;DISPLAY THE MESSAGE + +; $IF C ;AN000;IF THERE IS A PROBLEM + JNC $$IF120 + ;AX=EXTENDED ERROR NUMBER ;AN000; + LEA DI,MSGNUM_EXTERR ;AN000;GET REST OF ERROR DESCRIPTOR + MOV BX,[DI].MSG_HANDLE ;AN000;HANDLE TO DISPLAY TO + MOV SI,[DI].MSG_SUBLIST ;AN000;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE + MOV CX,[DI].MSG_COUNT ;AN000;NUMBER OF %PARMS, 0 IF NONE + MOV DX,[DI].MSG_CLASS ;AN000;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW + CALL SYSDISPMSG ;AN000;TRY TO SAY WHAT HAPPENED + + STC ;AN000;REPORT PROBLEM +; $ENDIF ;AN000;PROBLEM WITH DISPLAY? +$$IF120: +; $ELSE ;AN006;SINCE SELECT DID THE MESSAGE + JMP SHORT $$EN119 +$$IF119: + MOV SELECT_FLAG,TRUE ;AN006;INDICATE SELECT IS DOING THE MESSAGES + CLC ;AN006;GENERATE A "NO PROBLEM" RESPONSE +; $ENDIF ;AN006;DID SELECT HANDLE THE MESSAGE? +$$EN119: + + POP SI ;AN000;RESTORE CALLER'S REGISTERS + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + + RET ;AN000; +SENDMSG ENDP ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; +YESNO PROC NEAR ;AN000; + PUBLIC YESNO ;AN000;MAKE ENTRY IN LINK MAP +;INPUT: DL=CHAR WITH Y OR N EQUIVALENT CHAR TO BE TESTED +; SELECT_FLAG - IF SELECT IS DOING MESSAGES, ALWAYS ASSUME "NO" +;OUTPUT: AX=0=NO; AX=1=YES ; AX=2=INVALID RESPONSE, NEITHER Y NOR N +; IF CARRY SET, PROBLEM WITH THE FUNCTION, CALLER SHOULD ASSUME "NO" +; = = = = = = = = = = = = + + CMP SELECT_FLAG,TRUE ;AN006;IS SELECT DOING THE MESSAGES? +; $IF NE ;AN006;IF SELECT HAS NOT HANDLED THE MESSAGE + JE $$IF124 + ;AL=SUBFUNCTION, AS: + ; 20H=CAPITALIZE SINGLE CHAR + ; 21H=CAPITALIZE STRING + ; 22H=CAPITALIZE ASCIIZ STRING + ; 23H=YES/NO CHECK + ; 80H BIT 0=USE NORMAL UPPER CASE TABLE + ; 80H BIT 1=USE FILE UPPER CASE TABLE + ;DL=CHAR TO CAP (FUNCTION 23H) ;AN000; + MOV AX,(GET_EXT_CNTRY_INFO SHL 8) + YESNO_CHECK ;AN000;(6523H) GET EXTENDED + ; COUNTRY INFORMATION, (Y/N) + INT 21H ;AN000;SEE IF Y OR N + +; $ELSE ;AN006;SINCE SELECT IS NOT PRESET + JMP SHORT $$EN124 +$$IF124: + MOV AX,NO ;AN006;ASSUME RESPONSE WAS 'NO' +; $ENDIF ;AN006; +$$EN124: + RET ;AN000;RETURN TO CALLER +YESNO ENDP ;AN000; +; = = = = = = = = = = = = +;(deleted ;AN013;) HEADER ;AN000; +;(deleted ;AN013;) READ_VOLSER PROC NEAR ; ;AN000; +;(deleted ;AN013;) PUBLIC READ_VOLSER ; ;AN000; +;(deleted ;AN013;) ;IF THE SOURCE DISKETTE SUPPORTED A VOL SERIAL NUMBER, THEN MAKE A NEW ONE +;(deleted ;AN013;) ; AND SEND IT TO THE TARGET DISKETTE. FOR OLD STYLE DISKETTES THAT DID NOT +;(deleted ;AN013;) ; HAVE ANY VOL SERIAL NUMBER, MAKE NO CHANGE AFTER THE TRADITIONAL FULL COPY. +;(deleted ;AN013;) ;INPUT: SOURCE AND TARGET DRIVE ID +;(deleted ;AN013;) ; THE TARGET DISKETTE IS A COMPLETE COPY OF THE SOURCE. +;(deleted ;AN013;) ;REFERENCED: A_MEDIA_ID_INFO STRUC (DEFINED IN DISKCOPY.EQU) +;(deleted ;AN013;) ; = = = = = = = = = = = = = = = = = = +;(deleted ;AN013;) ; ISSUE GET MEDIA ID FROM SOURCE +;(deleted ;AN013;) MOV BH,ZERO ;BH=0, RES ;AN000; +;(deleted ;AN013;) MOV BL,SOURCE_DRIVE ;BL=DRIVE NUM (1=A:, 2=B:, ETC);AN000; +;(deleted ;AN013;) MOV DX,OFFSET MEDIA_ID_BUF ;DS:DX=BUFFER (see A_MEDIA_ID_INFO STRUC);AN000; +;(deleted ;AN013;) DOSCALL GSET_MEDIA_ID,GET_ID ;(6900H) GET MEDIA ID ;AC009; +;(deleted ;AN013;) ;CARRY SET ON ERROR (OLD STYLE BOOT RECORD) +;(deleted ;AN013;) +;(deleted ;AN013;) $IF NC ;IF THERE IS NO PROBLEM ;AN000; +;(deleted ;AN013;) ; GET CURRENT DATE +;(deleted ;AN013;) DOSCALL GET_DATE ;READ SYSTEM DATE ;AN000; +;(deleted ;AN013;) ;OUTPUT: DL = DAY (1-31) +;(deleted ;AN013;) ; AL = DAY OF WEEK (0=SUN,6=SAT) +;(deleted ;AN013;) ; CX = YEAR (1980-2099) +;(deleted ;AN013;) ; DH = MONTH (1-12) +;(deleted ;AN013;) PUSH CX ;SAVE THESE FOR ;AN000; +;(deleted ;AN013;) PUSH DX ; INPUT INTO HASH ALGORITHM ;AN000; +;(deleted ;AN013;) ; GET CURRENT TIME +;(deleted ;AN013;) DOSCALL GET_TIME ;READ SYSTEM TIME CLOCK ;AN000; +;(deleted ;AN013;) ;OUTPUT: CH = HOUR (0-23) +;(deleted ;AN013;) ; CL = MINUTES (0-59) +;(deleted ;AN013;) ; DH = SECONDS (0-59) +;(deleted ;AN013;) ; DL = HUNDREDTHS (0-99) +;(deleted ;AN013;) +;(deleted ;AN013;) ; HASH THESE INTO A UNIQUE 4 BYTE NEW VOLUME SERIAL NUMBER: +;(deleted ;AN013;) ; MI_SERIAL+0 = DX FROM DATE + DX FROM TIME +;(deleted ;AN013;) ; MI_SERIAL+2 = CX FROM DATE + CX FROM TIME +;(deleted ;AN013;) +;(deleted ;AN013;) POP AX ;GET THE DX FROM DATE ;AN000; +;(deleted ;AN013;) ADD AX,DX ;ADD IN THE DX FROM TIME ;AN000; +;(deleted ;AN013;) MOV WORD PTR MEDIA_ID_BUF.MI_SERIAL,AX ;SAVE FIRST RESULT OF HASH;AN000; +;(deleted ;AN013;) +;(deleted ;AN013;) POP AX ;GET THE CX FROM DATE ;AN000; +;(deleted ;AN013;) ADD AX,CX ;ADD IN THE CX FROM TIME ;AN000; +;(deleted ;AN013;) MOV WORD PTR MEDIA_ID_BUF.MI_SERIAL+WORD,AX ;SAVE SECOND RESULT OF HASH;AN000; +;(deleted ;AN013;) +;(deleted ;AN013;) MOV VOLSER_FLAG,TRUE ;REQUEST THE NEW VOL SERIAL NUMBER BE WRITTEN;AN000; +;(deleted ;AN013;) $ENDIF ; ;AN000; +;(deleted ;AN013;) RET ;RETURN TO CALLER ;AN000; +;(deleted ;AN013;) READ_VOLSER ENDP ; ;AN000; +; = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +WRITE_VOLSER PROC NEAR ;AN000; + PUBLIC WRITE_VOLSER ;AN000;MAKE ENTRY IN LINK MAP + CMP VOLSER_FLAG,TRUE ;AN000;IF NEW NUMBER READY TO BE WRITTEN +; $IF E ;AN000;THEN WRITE IT + JNE $$IF127 + +;NOTE FOR ;AN013; +;THERE IS NO NEED TO DO A SET MEDIA ID TO WRITE OUT THE MODIFIED SERIAL NUMBER +;BECAUSE THAT NUMBER WAS CHANGED IN THE IMAGE OF THE BOOT RECORD WHEN THE +;ORIGINAL BOOT RECORD WAS READ IN, SO WHEN THAT TRACK IMAGE WAS WRITTEN, +;IT CONTAINED THE NEW SERIAL NUMBER ALREADY. + +;(deleted ;AN013;) ; ISSUE SET MEDIA ID TO TARGET +;(deleted ;AN013;) MOV BH,ZERO ;BH=0, RES ;AN000; +;(deleted ;AN013;) MOV BL,TARGET_DRIVE ;BL=DRIVE NUM ;AN000; +;(deleted ;AN013;) MOV DX,OFFSET MEDIA_ID_BUF ;DS:DX=BUFFER (see STRUC above);AN000; +;(deleted ;AN013;) DOSCALL GSET_MEDIA_ID,SET_ID ;(6901H) SET MEDIA ID ;AC009; + +; NOTE: IN THE FOLLOWING TWO SUBLISTS, WE ARE GOING TO DISPLAY, IN HEX, +; A CONSECUTIVE SET OF 4 BYTES, THE VOLUME SERIAL NUMBER. THE ORDER OF +; THESE TWO WORDS OF HEX IS, LEAST SIGNIFICANT WORD FIRST, THEN THE +; MOST SIGNIFICANT WORD. WHEN DISPLAYED, THE MOST SIGNIFICANT IS TO BE +; DISPLAYED FIRST, SO THE VALUE AT SERIAL+2 GOES TO THE 26A SUBLIST, +; AND THE LEAST SIGNIFICANT VALUE AT SERIAL+0 GOES TO THE SECOND POSITION, +; REPRESENTED BY THE 26B SUBLIST. + + LEA AX,SERIAL ;AC013;GET POINTER TO DATA TO BE PRINTED + MOV SUBLIST_26B.SUB_VALUE,AX ;AN001; INTO THE SUBLIST + + LEA AX,SERIAL+WORD ;AC013;GET POINTER TO DATA TO BE PRINTED + MOV SUBLIST_26A.SUB_VALUE,AX ;AN001; INTO THE SUBLIST + + PRINT MSGNUM_CR_LF ;AN000;SKIP A SPACE + + ;"Volume Serial Number is %1-%2" + PRINT MSGNUM_SERNO ;AN001;DISPLAY THE NEW SERIAL NUMBER + +; $ENDIF ;AN000; +$$IF127: + RET ;AN000;RETURN TO CALLER +WRITE_VOLSER ENDP ;AN000; +; = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +PRESS_ANY_KEY PROC NEAR ; +;THE CANNED MESSAGE "PRESS ANY KEY..." DOES NOT START WITH CR,LF. +;THIS PUTS OUT THE CR LF TO CAUSE SEPARATION OF THIS PROMP FROM +;PRECEEDING MESSAGES. +; = = = = = = = = = = = = + PRINT MSGNUM_CR_LF ;AN000;SKIP A SPACE + + PRINT MSGNUM_STRIKE ;AN000;"Press any key when ready..." + + RET ;AN000;RETURN TO CALLER +PRESS_ANY_KEY ENDP ;AN000; +; = = = = = = = = = = = = + PUBLIC DISKCOPY_END ; +DISKCOPY_END LABEL NEAR ; + + PATHLABL DISKCOPY ;AN015; +CSEG ENDS ; + END DISKCOPY ; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DISKCOPY.EQU b/v4.0/src/CMD/DISKCOPY/DISKCOPY.EQU new file mode 100644 index 0000000..914fc43 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DISKCOPY.EQU @@ -0,0 +1,207 @@ + IF1 ; + %OUT COMPONENT=DISKCOPY, INCLUDING DISKCOPY.EQU... ; + ENDIF ; +; $SALUT (4,21,26,36) +;---------------------------------------------------------------------------; +; EQUATES ; +;---------------------------------------------------------------------------; + +; *** CONSTANTS *** + +ZERO EQU 0 ; +ONE EQU 1 ; +TWO EQU 2 ; +THREE EQU 3 ; +FOUR EQU 4 ; +TYPE_4 EQU 4 ; +FIVE EQU 5 ; +SIX EQU 6 ; +SEVEN EQU 7 ; +EIGHT EQU 8 ; +NINE EQU 9 ; +TEN EQU 0AH ; +ON EQU 1 ; +OFF EQU 0 ; +TRUE EQU 01 ; +FALSE EQU 00 ; +GOOD EQU 0 ; +BAD EQU 1 ; +FIRST EQU 1 ; +SECOND EQU 2 ; +NO_ERROR EQU 0 ; +SOFT_ERROR EQU 1 ; +HARD_ERROR EQU 2 ; + +BLANK EQU 20H ;BLANK IN ASCII (32 DEC) +CLEAR_SEGMENT EQU 0E0H ;USED TO CLEAR SEGMENT BITS (ROUND UP + ;TO NEXT SECTOR) +SECTOR8 EQU 8 ; +SECTOR9 EQU 9 ; +SECTOR14 EQU 14 ; +SECTOR15 EQU 15 ; +DRV_48TPI EQU 0 ;48 TPI DRIVE +DRV_96TPI EQU 1 ;96 TPI DRIVE +DRV_720 EQU 2 ;3.5", 720 KB DRIVE (FOR CASHEW OR P14) +NRLFUNC EQU 5F02H ;GET NETWORK-REDIRECTION-LIST FUNCTION +NRLMAX EQU 1CH ;(MAXIMUM # OF NAMES ON NRL) - 1 +DOS20 EQU 2 ;DOS VERSION 2.0 + PUBLIC FINE ;AN000;PARSER NEEDS IT +FINE EQU -1 ;"FINE AND DANDY", USED FOR RETURN CODE + ;(-1 WAS USED TO AVOID CONFUSION WITH ERROR + ;OFFSET WHICH CAN BE ZERO) +LOCAL_DRV EQU -1 ;DEVICE NOT DIRECTED +REMOTE_DRV EQU 1000H ;REMOTE DRIVE TEST BITS +NO_OPTION EQU -1 ;NO OPTION "/1" SPECIFIED +OPTION_1 EQU 1 ;OPTION "/1" SPECIFIED +REMOVABLE EQU 0000H ;REMOVABLE FILE +INVAL_PARM EQU -9 ;INVALID PARAMETER ENTERED +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; *** COPY STATUS BYTE *** + +FATAL EQU 01H ;FATAL COPY ERROR, ABORT +OK EQU 00H ;OK, PROCEED +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; *** PROGRAM SEGMENT PREFIX *** + +FCB1_DRV_ID EQU 5CH ;DRIVE NUMBER ADDR IN FILE CONTROL BLOCK 1 +FCB1_FILENM EQU 5DH ;FILE NAME ADDR IN FILE CONTROL BLOCK 1 +FCB2_DRV_ID EQU 6CH ;DRIVE NUMBER ADDR IN FILE CONTROL BLOCK 2 +FCB2_FILENM EQU 6DH ;FILE NAME ADDR IN FILE CONTROL BLOCK 2 +BEGIN_UNFORM_AREA EQU 80H ;BEGINNING @ OF THE UNFORMATTED AREA +END_UNFORM_AREA EQU 100H ;ENDING @ OF THE UNFORMATTED AREA +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; *** DOS FUNCTONS *** + +KB_INPUT_FUNC EQU 01H ;DOS KEYBOARD INPUT FUNCTION +PRINT_FUNC EQU 09H ;DOS PRINT STRING FUNCTION +REDIRECTED_FUNC EQU 09H ;IOCTL SUB FUNCTION ****** TO BE CHECKED **** +CURRENTDRV_FUNC EQU 19H ;GET CURRENT DRIVE FUNCTION CALL +DOSVER_FUNC EQU 30H ;DOS VERSION FUNCTION CALL +IOCTL_FUNC EQU 44H ;IOCTL FUNCTION CALL +GET_DISKBASE_VECTOR EQU 351EH ; +SET_DISKBASE_VECTOR EQU 251EH ; +GET_CTL_BREAK_VECT EQU 3523H ;AN000;GET VECTOR FOR INT 23H (CTRL-BREAK) +SET_CTL_BREAK_VECT EQU 2523H ;AN000;SET VECTOR FOR INT 23H (CTRL-BREAK) +DRIVE_CHECK EQU 4408H ;DOS CHECK FOR REMOVABLE DRIVE IOCTL CALL +STD_ERROR EQU 0002H ;STANDARD ERROR FILE HANDLE +WRITE_FILE EQU 40H ;WRITE TO FILE OR DEVICE FUNCTION CALL +GET_ASSIGN_MODE EQU 5F00H ;SET ASSIGN MODE COMMAND +SET_ASSIGN_MODE EQU 5F01H ;SET ASSIGN MODE COMMAND +SERVER EQU 2AH ;NETWORK SERVER INTERUPT +SHARED EQU 03H ;DEVICE SHARED CHECK +EXTENDED_ERROR EQU 59H ;EXTENDED ERROR +GET_DATE EQU 2AH ;AN000;READ SYSTEM DATE +GET_TIME EQU 2CH ;AN000;READ SYSTEM TIME CLOCK +RET_CD_EXIT EQU 4CH ;AN000;EXIT TO DOS, PASSING RETURN CODE +GET_EXT_CNTRY_INFO EQU 65H ;AN000;GET EXTENDED COUNTRY INFORMATION +YESNO_CHECK EQU 23H ;AN000;REQUEST (Y/N) CHECK OF GET_EXT_CNTRY_INFO +NO EQU 0 ;AN006;(Y/N) RESPONSE IS "NO" +YES EQU 1 ;AN000;(Y/N) RESPONSE IS "YES" +BAD_YESNO EQU 2 ;AN000;(Y/N) RESPONSE IS NEITHER "Y" NOR "N" +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; *** IOCTL DISKETTE I/O FUNCTONS *** +GENERIC_IOCTL_CODE EQU 0DH ;GENERIC IOCTL REQUEST +MAJOR_CODE EQU 08H ;GENERIC IOCTL MAJOR CODE +READ_FUNC EQU 61H ;IOCTL DISKETTE READ FUNCTION +WRITE_FUNC EQU 41H ;IOCTL DISKETTE WRITE FUNCTION +VERIFY_FUNC EQU 62H ;IOCTL DISKETTE VERIFY FUNCTION +FORMAT_FUNC EQU 42H ;IOCTL DISKETTE FORMAT FUNCTION +GETDEVPARM EQU 60H ;IOCTL GET DEVICE PARAMETER +SETDEVPARM EQU 40H ;IOCTL SET DEVICE PARAMETER +SET_LOGIC_DRIVE EQU 0FH ;AN000;IOCTL SET LOGICAL DRIVE +;(deleted ;AN013) GSET_MEDIA_ID EQU 69H ;GET OR SET MEDIA ID ;AN009; +;(deleted ;AN013) GET_ID EQU 0 ;AL=0;GET MEDIA ID ;AN009; +;(deleted ;AN013) SET_ID EQU 1 ;AL=1;SET MEDIA ID ;AN009; + +;special Functions +GET_SP_FUNC_DEF EQU 00000000B ;GET DEVICE PARM. DEFAULT BPB +GET_SP_FUNC_MED EQU 00000001B ;GET DEVICE PARM. BOOT BPB +SET_SP_FUNC_DEF EQU 00000100B ;SET DEFAULT DEVICE PARM +SET_SP_FUNC_DOS EQU 00000100B ;SET DEVICE PARM BEFORE RETURN TO DOS. +SET_SP_BF_FORM EQU 00000101B ;SET DEV PARM BEFORE FORMAT +R_W_SP_FUNC EQU 00000000B ;READ, WRITE +STATUS_CHK EQU 00000001B ;USED IN FORMAT PACKET AND VALIDATE + ;THE "SET DEVICE PARM" REQUEST. +FORMAT_SP_FUNC EQU 00000000B ;FORMAT +.XLIST ; +;READ_DASD_FUNC EQU 15H ;BIOS READ DASD TYPE (DISKETTE DRIVE TYPE) +;SET_DASD_FUNC EQU 17H ;BIOS SET DASD TYPE +;COMPARE_FUNC EQU 03H ;BIOS COMPARE FUNC # FOR ERROR MSG PROC +.LIST ; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; *** BIOS DISKETTE I/O ERROR CODES *** + +;NOT_READY EQU 80H ;DISKETTE I/O NOT READY ERROR +;CHANG_LINE EQU 06H ;CHANGE LINE ERROR +;BAD_CONTROLLER EQU 20H ;BAD DISKETTE/DISK CONTOROLLER +;WRITE_PROTECT EQU 03H ;DISKETTE I/O WRITE PROTECT ERROR +;BAD_ADDR_MARK EQU 02H ;DISKETTE I/O BAD ADDRESS MARK ERROR +;REC_NOT_FOUND EQU 04H ;DISETTTE I/O RECORD NOT FOUND ERROR +;BAD_CRC EQU 10H ;DISKETTE I/O BAD CRC ERROR +;HARD_WR_ERROR EQU 03H ;DISKETTE WRITE HARD ERROR COUNT +;HARD_FMT_ERROR EQU 02H ;DISKETTE FORMAT HARD ERROR COUNT +;SINGLE_SIDE_COPY EQU 00H ;WHEN READING TRACK 0 SIDE 1 IF HARD ERROR + ;OCCURS, WE WILL ASSUME IT WILL BE SINGLE + ;SIDED COPY AND AL WILL BE SET TO 0, SO THAT + ;BUFFER_PTR WILL NOT BE ADVANCED AND + ;IF THE TRACK HAPPENS TO FALL INTO DMA BOUNDRY + ;IT WILL SKIP THE SECOND PART OF READ_TRACK +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; SYSTEM MESSAGE HANDLER EQUATES +EXT_ERR_CLASS EQU 01H ;AN000;DOS Extended error class +PARSE_ERR_CLASS EQU 02H ;AN000;Parse error class +UTILITY_MSG_CLASS EQU 0FFH ;AN000;Utility message class +CLASS_A EQU UTILITY_MSG_CLASS ;AN000;IN MSG DESCRIPTOR +MAX_0 EQU 0 ;AN000;MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT) +PAD_BLK EQU " " ;AN000;CHAR FOR PAD FIELD +STDOUT EQU 0001H ;AN000;Standard Output device handle +STDERR EQU 0002H ;AN000;Standard Error Output device handle + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; SELECT MULTIPLEXOR INTERFACE +SELECT_MPX EQU 0ADC1H ;AN006;THE SELECT MULTIPLEXOR ID +SELECT_PRESENT EQU 0FFH ;AN006;RESPONSE IN AL, IF SELECT IS PRESENT +MULTIPLEXOR EQU 2FH ;AN006;THE MULTIPLEXOR INTERRUPT NUMBER +;---------------------------------------------------------------------------; +; CONTROL BLOCKS (STRUCS) ; +;---------------------------------------------------------------------------; + +MSG_DESC STRUC ; +MSG_NUM DW 0 ;AN000;MESSAGE NUMBER (TO AX) +MSG_HANDLE DW STDOUT ;AN000;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW 0 ;AN000;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW 0 ;AN000;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DW CLASS_A SHL 8 ;AN000;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL);AN000; +MSG_DESC ENDS ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +SUBLIST STRUC ;AN000; +SUB_SIZE DB 11 ;AN000;SUBLIST SIZE (POINTER TO NEXT SUBLIST) +SUB_RES DB 0 ;AN000;RESERVED + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD +SUB_VALUE DW 0 ;AN000;TIME, DATE, OR PTR TO DATA ITEM +SUB_VALUE_SEG DW 0 ;AN000;SEG ID OF PTR + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION + ; TIME, IF THIS IS A .COM FILE) +SUB_ID DB 0 ;AN000;N OF %N +SUB_FLAGS DB 0 ;AN000;DATA TYPE FLAGS +SUB_MAX_WIDTH DB MAX_0 ;AN000;MAXIMUM FIELD WIDTH (0=UNLIMITED) +SUB_MIN_WIDTH DB 0 ;AN000;MINIMUM FIELD WIDTH +SUB_PAD_CHAR DB PAD_BLK ;AN000;CHARACTER FOR PAD FIELD + ; CAN BE " ", "0" OR ",". + ; "," CAUSES INSERTION OF THE ACTIVE + ; THOUSANDS SEPARATOR BETWEEN EVERY + ; 3 DIGITS. +SUBLIST ENDS ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +;BUFFER AREA FOR COMMUNICATION WITH GET/SET MEDIA ID FUNCTION CALL +; (USED BY VOLSER PROC) + +;(deleted ;AN013;) A_MEDIA_ID_INFO STRUC ; ;AN000; +;(deleted ;AN013;) MI_LEVEL DW 0 ;INFO LEVEL ;AN000; +;(deleted ;AN013;) MI_SERIAL DD 0 ;SERIAL # ;AN000; +;(deleted ;AN013;) MI_LABEL DB 11 DUP (' ') ;VOLUME LABEL ;AN000; +;(deleted ;AN013;) MI_SYSTEM DB 8 DUP (' ') ;FILE SYSTEM TYPE ;AN000; +;(deleted ;AN013;) A_MEDIA_ID_INFO ENDS ; ;AN000; + +;END OF DISKCOPY.EQU diff --git a/v4.0/src/CMD/DISKCOPY/DISKCOPY.LNK b/v4.0/src/CMD/DISKCOPY/DISKCOPY.LNK new file mode 100644 index 0000000..b0eaaff --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DISKCOPY.LNK @@ -0,0 +1,6 @@ +DISKCOPY.OBJ+ +DCOPYSM.OBJ+ +DCOPYP.OBJ+ +DCOPYPAR.OBJ+ +COPYINIT.OBJ; + \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/DISKCOPY.SKL b/v4.0/src/CMD/DISKCOPY/DISKCOPY.SKL new file mode 100644 index 0000000..bc346ac --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/DISKCOPY.SKL @@ -0,0 +1,65 @@ +:util DISKCOPY ;AN000;utility name +:class A ;AN000;system messages +:use 1 COMMON1 ;AN000;MSG 1 is always "Incorrect DOS version" + +:def 2 CR,LF ;AN000; + +:use 3 PARSE10 ;AN000;CR,LF,"Invalid parameter",CR,LF + +:def 4 "Do not specify filename(s)",CR,LF ;AN000; +"Command Format: DISKCOPY d: d: [/1]",CR,LF ;AN000; + +:def 5 CR,LF,"Invalid drive specification",CR,LF ;AN000; +"Specified drive does not exist",CR,LF ;AN000; +"or is non-removable",CR,LF ;AN000; + +:def 6 CR,LF,"Cannot DISKCOPY to or from",CR,LF ;AN000; +"a network drive",CR,LF ;AN000; + +:def 7 CR,LF,"Formatting while copying",CR,LF ;AN000; + +:def 8 CR,LF,"Insert SOURCE diskette in drive %1:",CR,LF ;AN000; + +:def 9 CR,LF,"Insert TARGET diskette in drive %1:",CR,LF ;AN000; + +:def 10 "Make sure a diskette is inserted into",CR,LF ;AN004; +"the drive and the door is closed",CR,LF ;AN004; + +:def 11 CR,LF,"Target diskette may be unusable",CR,LF ;AN000; + +:def 12 CR,LF,"Target diskette unusable",CR,LF ;AN000; + +:use 13 EXTEND21 ;AN000;CR,LF,Drive not ready",CR,LF + +:use 14 EXTEND19 ;AN000;CR,LF,"Attempt to write to write-protected diskette",CR,LF + +:use 15 COMMON28 ;AN000;CR,LF,"Press any key to continue . . .",CR,LF + +:def 16 CR,LF,"Copy another diskette (Y/N)? " ;AN000; + +:def 17 CR,LF,"Copying %1 tracks",CR,LF ;AN000; +"%2 Sectors/Track, %3 Side(s)",CR,LF ;AN000; + +:def 18 CR,LF,"Drive types or diskette types",CR,LF ;AN000; +"not compatible",CR,LF ;AN000; + +:def 19 CR,LF,"Unrecoverable read error on drive %1",CR,LF ;AN000; +"Side %2, track %3",CR,LF ;AN000; + +:def 20 CR,LF,"Unrecoverable write error on drive %1",CR,LF ;AN000; +"Side %2, track %3",CR,LF ;AN000; + +:def 21 CR,LF,"Copy process ended",CR,LF ;AN000; + +:def 22 CR,LF,"SOURCE diskette bad or incompatible",CR,LF ;AC008; + +:def 23 CR,LF,"TARGET diskette bad or incompatible",CR,LF ;AC008; + +:use 25 EXTEND8 ;AN000;"Insufficient memory",CR,LF + +:use 26 COMMON36 ;AN001;"Volume Serial Number is %1-%2",CR,LF + +:end ;AN000; +lume Serial Number is %1-%2",CR,LF + +:end \ No newline at end of file diff --git a/v4.0/src/CMD/DISKCOPY/MAKEFILE b/v4.0/src/CMD/DISKCOPY/MAKEFILE new file mode 100644 index 0000000..9a3e564 --- /dev/null +++ b/v4.0/src/CMD/DISKCOPY/MAKEFILE @@ -0,0 +1,57 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: diskcopy.com + +diskcopy.ctl: diskcopy.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +diskcopy.obj: diskcopy.asm \ + makefile \ + dcpymacr.inc \ + diskcopy.equ \ + $(inc)\bootform.inc + +copyinit.obj: copyinit.asm \ + makefile \ + dcpymacr.inc \ + diskcopy.equ + +dcopyp.obj: dcopyp.asm \ + makefile \ + $(inc)\parse.asm + +dcopysm.obj: dcopysm.asm \ + makefile \ + $(inc)\sysmsg.inc \ + $(inc)\msghan.inc \ + $(inc)\versiona.inc \ + diskcopy.ctl \ + diskcopy.cla \ + diskcopy.cl1 \ + diskcopy.cl2 \ + dcopyms.inc \ + $(inc)\copyrigh.inc + +dcopypar.obj: dcopypar.asm \ + makefile + +diskcopy.com: diskcopy.obj \ + makefile \ + diskcopy.lnk \ + dcopysm.obj \ + dcopyp.obj \ + dcopypar.obj \ + copyinit.obj + link @diskcopy.lnk + exe2bin diskcopy.exe diskcopy.com + del diskcopy.exe diff --git a/v4.0/src/CMD/EDLIN/EDLCMD1.ASM b/v4.0/src/CMD/EDLIN/EDLCMD1.ASM new file mode 100644 index 0000000..ea304f4 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLCMD1.ASM @@ -0,0 +1,664 @@ + PAGE 60,132; + TITLE EDLCMD1.ASM + +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLCMD1.SAL +; +; DESCRIPTIVE NAME: EDLIN ROUTINES +; +; FUNCTION: THIS MODULE PROVIDES ROUTINES NEEDED FOR EDLIN'S EXECUTION. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; EXIT NORMAL: NA +; +; EXIT ERROR : NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: EDLCMD2 - ROUTINES MAY BE CALLED FROM EDLCMD2 +; EDLMES - ROUTINES MAY BE CALLED FROM EDLMES +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; REVISION HISTORY: +; +; AN000 VERSION DOS 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT SYSPARSE +; - IMPLEMENT MESSAGE RETRIEVER +; - IMPLEMENT DBCS ENABLING +; - ENHANCED VIDEO SUPPORT +; - EXTENDED OPENS +; - SCROLLING ERROR +; +; COPYRIGHT: "MS DOS EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; +;======================= END OF SPECIFICATIONS =========================== + +include edlequ.asm + +SUBTTL Contants and Data areas +PAGE + + +CODE SEGMENT PUBLIC +CODE ENDS + +CONST SEGMENT PUBLIC WORD +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC WORD +DATA ENDS + +DG GROUP CODE,CONST,cstack,DATA + +CONST SEGMENT PUBLIC WORD + EXTRN DSKFUL_ptr:word,READ_ERR_PTR:word + EXTRN NOSUCH_ptr:word,TOOLNG_ptr:word,EOF_ptr:word + extrn txt1:byte,txt2:byte +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC WORD + extrn ParamCt:WORD + extrn current:word,pointer:word,start:word,endtxt:word + extrn wrt_handle:word,editbuf:byte,path_name:byte,fname_len:word + extrn arg_buf:byte,arg_buf_ptr:word + extrn olddat:byte,oldlen:word,newlen:word,param1:word,param2:word + extrn srchflg:byte,srchmod:byte,comline:word,lstfnd:word,numpos:word + extrn lstnum:word,srchcnt:word,amnt_req:word,delflg:byte,lastlin:word + extrn three4th:word,one4th:word,last:word,rd_handle:word,ending:byte + extrn haveof:byte + extrn Disp_Len:Byte + +DATA ENDS + +CODE SEGMENT PUBLIC +ASSUME CS:DG,DS:DG,SS:CStack,ES:DG + + extrn findlin:near,shownum:near,loadbuf:near + extrn delbak:near,unquote:near,lf:near + extrn dispone:near,display:near,query:near + extrn quit:near,scanln:near,scaneof:near + extrn fndfirst:near,fndnext:near,replace:near,memerr:near + extrn std_printf:near,chkrange:near,comerr:near + + public xerror,bad_read,append,nocom,pager,list + public delete,replac_from_curr,search_from_curr,ewrite,wrt + +NOMOREJ:JMP NOMORE + +APPEND: + CMP ParamCt,1 + JZ AppendOK + JMP ComErr +AppendOK: + TEST BYTE PTR [HAVEOF],-1 + JNZ NOMOREJ + MOV DX,[ENDTXT] + CMP [PARAM1],0 ;See if parameter is missing + JNZ PARMAPP + CMP DX,[THREE4TH] ;See if already 3/4ths full + jb parmapp + return ;If so, then done already +PARMAPP: + MOV DI,DX + MOV CX,[LAST] + SUB CX,DX ;Amount of memory available + jnz sj53 + jmp memerr +sj53: + MOV DX,[ENDTXT] + MOV BX,[RD_HANDLE] + mov [amnt_req],cx ;Save number of chars requested + MOV AH,READ + INT 21H ;Fill memory with file data + CMP CX,AX ;Did we read less than we asked for? + JZ SJ55 +; Make sure this is an end-of-file by trying to read more + PUSH AX ;Save old byte count + ADD DX,AX ;Point to next open space in buffer + MOV CX,1 ;Just one character past EOF + MOV AH,READ + INT 21H + CMP AX,0 ;Is it EOF? + POP AX + JNZ SJ54 ;No -- we have one more character + MOV BYTE PTR [HAVEOF],1 ;Yes - set old style system call flag + JMP SHORT SJ55 +SJ54: + INC AX ;Include one more char in byte count +sj55: + MOV CX,AX ;Want byte count in CX + PUSH CX ;Save actual byte count + CALL SCANEOF + JNZ NOTEND + MOV BYTE PTR [HAVEOF],1 ;Set flag if 1AH found in file +NOTEND: + XOR DX,DX + MOV BX,[PARAM1] + OR BX,BX + JNZ COUNTLN + MOV AX,DI + ADD AX,CX ;First byte after loaded text + CMP AX,[THREE4TH] ;See if we made 3/4 full + JBE COUNTLN + MOV DI,[THREE4TH] + MOV CX,AX + SUB CX,DI ;Length remaining over 3/4 + MOV BX,1 ;Look for one more line +COUNTLN: + CALL SCANLN ;Look for BX lines + CMP [DI-1],AL ;Check for full line + JZ FULLN + CMP HavEof,1 + JNZ DoBackScan +; +; We have an incomplete line in the buffer at end of file. Fix it up to be +; pretty. +; + MOV BYTE PTR [DI],13 ; CR + MOV BYTE PTR [DI+1],10 ; LF + ADD DI,2 ; length is 2 greater + POP CX + ADD CX,2 + PUSH CX + JMP SHORT FULLN + +DoBackScan: + DEC DI + MOV CX,[LAST] + STD + REPNE SCASB ;Scan backwards for last line + CLD + INC DI + INC DI + DEC DX +FULLN: + POP CX ;Actual amount read + MOV WORD PTR [DI],1AH ;Place EOF after last line + SUB CX,DI + XCHG DI,[ENDTXT] + ADD DI,CX ;Amount of file read but not used +; Must seek for old partial line + OR DI,DI + JZ FULLN1 + PUSH DX + PUSH BX + MOV BX,[RD_HANDLE] + MOV DX,DI + NEG DX + MOV CX,-1 + MOV AL,1 + MOV AH,LSEEK + INT 21H + POP BX + POP DX + JC BAD_READ +FULLN1: + CMP BX,DX + JNZ EOFCHK + MOV BYTE PTR [HAVEOF],0 + return +NOMORE: + MOV DX,OFFSET DG:EOF_ptr + call std_printf +ret3: return + +BAD_READ: + MOV DX,OFFSET DG:READ_ERR_ptr + MOV DI,offset dg:path_name + ADD DI,[FNAME_LEN] + MOV AL,0 + STOSB + JMP XERROR + +EOFCHK: + TEST BYTE PTR [HAVEOF],-1 + JNZ NOMORE + TEST BYTE PTR [ENDING],-1 + retnz ;Suppress memory error during End + JMP MEMERR + +EWRITE: + CMP ParamCt,1 + JBE EWriteOK + JMP ComErr +EWriteOK: + MOV BX,[PARAM1] + OR BX,BX + JNZ WRT + MOV CX,[ONE4TH] + MOV DI,[ENDTXT] + SUB DI,CX ;Write everything in front of here + JBE RET3 + CMP DI,OFFSET DG:START ;See if there's anything to write + JBE RET3 + XOR DX,DX + MOV BX,1 ;Look for one more line + CALL SCANLN + JMP SHORT WRTADD +WRT: + INC BX + CALL FINDLIN +WRTADD: + CMP BYTE PTR [DELFLG],0 + JNZ WRTADD1 + PUSH DI + CALL DELBAK ;Want to delete the .BAK file + ;as soon as the first write occurs + POP DI +WRTADD1: + MOV CX,DI + MOV DX,OFFSET DG:START + SUB CX,DX ;Amount to write + retz + MOV BX,[WRT_HANDLE] + MOV AH,WRITE + INT 21H + JC WRTERR + CMP AX,CX ; MZ correct full disk detection + JNZ WRTERR ; MZ correct full disk detection + MOV SI,DI + MOV DI,OFFSET DG:START + MOV [POINTER],DI + MOV CX,[ENDTXT] + SUB CX,SI + INC CX ;Amount of text remaining + CLD + REP MOVSB + DEC DI ;Point to EOF + MOV [ENDTXT],DI + MOV [CURRENT],1 + return + +WRTERR: + MOV BX,[WRT_HANDLE] + MOV AH,CLOSE + INT 21H + MOV DX,OFFSET DG:DSKFUL_ptr +xERROR: + push cs + pop ds + call std_printf + mov al,0ffh + mov ah,exit + int 21h + +NOTFNDJ:JMP NOTFND + +replac_from_curr: + CMP ParamCt,2 + JBE Replace1 + JMP ComErr +Replace1: + mov byte ptr [srchmod],1 ;search from curr+1 line + jmp short sj6 + +REPLAC: + mov byte ptr [srchmod],0 ;search from beg of buffer +sj6: + MOV BYTE PTR [SRCHFLG],0 + CALL FNDFIRST + JNZ NOTFNDJ +REPLP: + MOV SI,[NUMPOS] + CALL LOADBUF ;Count length of line + SUB DX,[OLDLEN] + MOV CX,[NEWLEN] + ADD DX,CX ;Length of new line + CMP DX,254 + jbe len_ok + Jmp TOOLONG +len_ok: + MOV BX,[LSTNUM] + PUSH DX + CALL SHOWNUM + POP DX + MOV CX,[LSTFND] + MOV SI,[NUMPOS] + SUB CX,SI ;Get no. of char on line before change + DEC CX + mov di,offset dg:arg_buf ;Initialize the output string buffer + CALL OUTCNT ;Output first part of line + PUSH SI + MOV SI,1+ OFFSET DG:TXT2 + MOV CX,[NEWLEN] + CALL OUTCNT ;Output change + POP SI + ADD SI,[OLDLEN] ;Skip over old stuff in line + MOV CX,DX ;DX=no. of char left in line + ADD CX,2 ;Include CR/LF + CALL OUTCNT ;Output last part of line + xor al,al + stosb + mov dx,offset dg:arg_buf_ptr + call std_printf + CALL QUERY ;Check if change OK + JNZ REPNXT + CALL PUTCURS + MOV DI,[LSTFND] + DEC DI + MOV SI,1+ OFFSET DG:TXT2 + MOV DX,[OLDLEN] + MOV CX,[NEWLEN] + DEC CX + ADD [LSTFND],CX ;Bump pointer beyond new text + INC CX + DEC DX + SUB [SRCHCNT],DX ;Old text will not be searched + JAE SOMELEFT + MOV [SRCHCNT],0 +SOMELEFT: + INC DX + CALL REPLACE +REPNXT: + CALL FNDNEXT + retnz + JMP REPLP + +OUTCNT: + JCXZ RET8 +OUTLP: + LODSB + stosb + DEC DX + LOOP OUTLP +RET8: return + +TOOLONG: + MOV DX,OFFSET DG:TOOLNG_ptr + JMP SHORT PERR + +search_from_curr: + CMP ParamCt,2 + JBE Search1 + JMP ComErr +Search1: + mov byte ptr [srchmod],1 ;search from curr+1 line + jmp short sj7 + +SEARCH: + mov byte ptr [srchmod],0 ;search from beg of buffer +sj7: + MOV BYTE PTR [SRCHFLG],1 + CALL FNDFIRST + JNZ NOTFND +SRCH: + MOV BX,[LSTNUM] + MOV SI,[NUMPOS] + CALL DISPONE + MOV DI,[LSTFND] + MOV CX,[SRCHCNT] + MOV AL,10 + CLD + REPNE SCASB + JNZ NOTFND + MOV [LSTFND],DI + MOV [NUMPOS],DI + MOV [SRCHCNT],CX + INC [LSTNUM] + CALL QUERY + JZ PUTCURS1 + CALL FNDNEXT + JZ SRCH +NOTFND: + MOV DX,OFFSET DG:NOSUCH_ptr +PERR: + call std_printf + return + +; +; Replace enters here with LSTNUM pointing to the correct line. +; +PUTCURS: + MOV BX,[LSTNUM] + jmp short putcursor +; +; Search enters here with LSTNUM pointing AFTER the correct line +; +putcurs1: + MOV BX,[LSTNUM] + DEC BX ;Current <= Last matched line + +putcursor: + CALL FINDLIN + MOV [CURRENT],DX + MOV [POINTER],DI + return + +; +; n,mD deletes a range of lines. Allowable values for n are: +; 1 ... LAST. Allowable values for m are: +; 1 ... LAST. +; nD deletes a single line +; D deletes the current line +; +DELETE: + CMP ParamCt,2 ; at most two parameters specified. + JA ComErrJ + MOV BX,Param1 + OR BX,BX ; default first arg? + JNZ DelParm2 + MOV BX,Current ; use current as default + MOV Param1,BX +DelParm2: + MOV BX,Param2 ; did we default second arg? + OR BX,BX + JNZ DelCheck ; no, use it. + MOV BX,Param1 ; use param1 as default + MOV Param2,BX +DelCheck: + MOV BX,Param1 + CALL ChkRange ; returns by itself if bad range +; +; BX is first line of range to be deleted. Param2 is last line in range to +; be deleted. Get pointer to beginning of block. Save location +; + CALL FINDLIN ; Grab line + retnz ; If not found => return + PUSH BX + PUSH DI +; +; Get pointer past end of block (Param2+1). +; + MOV BX,Param2 + INC BX + CALL FINDLIN +; +; Set up pointers. Compute number of chars to move. +; + MOV SI,DI ; move from second line+1 + POP DI ; restore destination (first line) + POP Current ; Current line is first param + MOV Pointer,DI ; internal current line + MOV CX,EndTxt ; compute count + SUB CX,SI + JB ComErrJ ; should never occur: ChkRange + INC CX ; remember ^Z at end + CLD + REP MOVSB ; move data + DEC DI + MOV EndTxt,DI ; reset end pointer + return + +COMERRJ: + JMP COMERR + +PAGER: + CMP ParamCt,2 + JA ComErrJ + xor bx,bx ;get last line in the buffer + call findlin + mov [lastlin],dx + + mov bx,[param1] + or bx,bx ;was it specified? + jnz frstok ;yes, use it + mov bx,[current] + cmp bx,1 ;if current line =1 start from there + je frstok + inc bx ;start from current+1 line +frstok: + cmp bx,[lastlin] ;check that we are in the buffer + jbe frstok1 + return ;if not just quit +frstok1: + mov dx,[param2] + or dx,dx ;was param2 specified? + jnz scndok ;yes,.... + mov dx,bx ;no, take the end line to be the + ; start line + length of active display + +;========================================================================= +; This modification is to provide support for screens larger than +; 24 lines. +; +; Date : 6/10/87 +;========================================================================= + + push ax ;an000;save affected registers + + mov ah,00h ;an000;zero out high byte + mov al,dg:disp_len ;an000;set ax to active display length + sub ax,2 ;an000;adjust for length of screen & current + ; line + add dx,ax ;an000;this gives us the last line to be + ; printed + pop ax ;an000;restore affected registers + +;========================================================================= + +scndok: + inc dx + cmp dx,[lastlin] ;check that we are in the buffer + jbe infile + mov dx,[lastlin] ;we are not, take the last line as end +infile: + cmp dx,bx ;is param1 < param2 ? + retz + ja sj33 + jmp comerr ;yes, no backwards listing, print error +sj33: + push dx ;save the end line + push bx ;save start line + mov bx,dx ;set the current line + dec bx + call findlin + mov [pointer],di + mov [current],dx + pop bx ;restore start line + call findlin ;get pointer to start line + mov si,di ;save pointer + pop di ;get end line + sub di,bx ;number of lines + jmp short display_lines + + +LIST: + CMP ParamCt,2 + JBE ListOK + JMP ComERR +ListOK: + MOV BX,[PARAM1] + OR BX,BX + JNZ CHKP2 + MOV BX,[CURRENT] + SUB BX,11 + JA CHKP2 + MOV BX,1 +CHKP2: + CALL FINDLIN + retnz + MOV SI,DI + MOV DI,[PARAM2] + INC DI + SUB DI,BX + JA DISPLAY_lines + +;========================================================================= +; This modification is to provide support for screens larger than +; 24 lines. +; +; Date : 6/10/87 +;========================================================================= + + push ax ;an000;save affected registers + + mov ah,00h ;an000;zero out high byte + mov al,dg:disp_len ;an000;set ax to active display length dec ax ;an000;allow room at bottom for + ; messages + mov di,ax ;an000;number of lines to print an + ; entire screen less 1. + pop ax ;an000;restore affected registers + +;========================================================================= + +display_lines: + call DISPLAY + return + +Break + +; +; NOCOM is called when there is a single line being edited. This occurs when +; the command letter is CR or is ;. +; +NOCOM: + CMP ParamCt,2 + JB NoComOK + JMP ComErr +NoComOK: + DEC [COMLINE] + MOV BX,[PARAM1] + OR BX,BX + JNZ HAVLIN + MOV BX,[CURRENT] + INC BX ;Default is current line plus one + CALL CHKRANGE +HAVLIN: + CALL FINDLIN + MOV SI,DI + MOV [CURRENT],DX + MOV [POINTER],SI + jz sj12 +ret12: return +sj12: + CMP SI,[ENDTXT] + retz + CALL LOADBUF + MOV [OLDLEN],DX + MOV SI,[POINTER] + CALL DISPONE + CALL SHOWNUM + MOV AH,STD_CON_STRING_INPUT ;Get input buffer + MOV DX,OFFSET DG:EDITBUF + INT 21H + CALL lf + MOV CL,[EDITBUF+1] + MOV CH,0 + JCXZ RET12 + MOV DX,[OLDLEN] + MOV SI,2 + OFFSET DG:EDITBUF +;----------------------------------------------------------------------- + call unquote ;scan for quote chars if any +;----------------------------------------------------------------------- + mov cl,[EditBuf+1] ;an000; dms;get new line length + mov ch,0 ;an000; dms;clear high byte + MOV DI,[POINTER] + JMP Replace ; MZ 11/30 + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLCMD2.ASM b/v4.0/src/CMD/EDLIN/EDLCMD2.ASM new file mode 100644 index 0000000..decc228 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLCMD2.ASM @@ -0,0 +1,1203 @@ + PAGE 60,132 +TITLE Edlcmd2 - PART2 procedures called from EDLIN + + +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLCMD2.SAL +; +; DESCRIPTIVE NAME: EDLIN ROUTINES +; +; FUNCTION: THIS MODULE PROVIDES ROUTINES NEEDED FOR EDLIN'S EXECUTION. +; +; ENTRY POINT: ANY CALLED ROUTINE +; +; EXIT NORMAL: NA +; +; EXIT ERROR : NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: EDLCMD1 - ROUTINES MAY BE CALLED FROM EDLCMD1 +; EDLMES - ROUTINES MAY BE CALLED FROM EDLMES +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; +; REVISION HISTORY: +; +; AN000 VERSION DOS 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT SYSPARSE +; - IMPLEMENT MESSAGE RETRIEVER +; - IMPLEMENT DBCS ENABLING +; - ENHANCED VIDEO SUPPORT +; - EXTENDED OPENS +; - SCROLLING ERROR +; +; COPYRIGHT: "MS DOS EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; +;======================= END OF SPECIFICATIONS =========================== + +include edlequ.asm + +CODE SEGMENT PUBLIC +CODE ENDS + +CONST SEGMENT PUBLIC WORD +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC WORD +DATA ENDS + + +DG GROUP CODE,CONST,cstack,DATA + +CONST SEGMENT PUBLIC WORD + extrn crlf_ptr:byte,lf_ptr:byte,qmes_ptr:byte,ask_ptr:byte + extrn bak:byte,$$$file:byte,delflg:byte,loadmod:byte,txt1:byte + extrn txt2:byte,memful_ptr:word,YES_BYTE:BYTE + + extrn Del_Bak_Ptr:byte ;an000;dms; + extrn cont_ptr:byte ;an000;dms:6/10/87 + +CONST ENDS + +DATA SEGMENT PUBLIC WORD + extrn ParamCt:WORD + extrn current:word,pointer:word,start:word,endtxt:word + extrn wrt_handle:word,editbuf:byte,ext_ptr:word,qflg:byte + extrn temp_path:byte,line_num:word,line_flag:byte + extrn line_num_buf_ptr:byte,arg_buf:byte,arg_buf_ptr:word + extrn olddat:byte,oldlen:word,newlen:word,param1:word,param2:word + extrn srchflg:byte,srchmod:byte,comline:word,lstfnd:word,numpos:word + extrn lstnum:word,last:word,srchcnt:word,amnt_req:word + + extrn lc_adj:byte ;an000;dms:6/10/87 + extrn continue:byte ;an000;dms:6/10/87 + extrn pg_count:byte ;an000;dms:6/10/87 + extrn Disp_Len:byte ;an000;dms; + extrn Disp_Width:byte ;an000;dms; + extrn lc_flag:byte ;an000;dms:6/10/87 + + if kanji + extrn lbtbl:dword + endif + +DATA ENDS + +CODE SEGMENT PUBLIC + +ASSUME CS:DG,DS:DG,SS:CStack,ES:DG + + public findlin,shownum,loadbuf,crlf,lf,abortcom,unquote + public kill_bl,make_caps,display,dispone,make_cntrl + public query,quit,scanln,delbak,scaneof,memerr + public fndfirst,fndnext,replace + if kanji + public testkanj + endif + extrn std_printf:near,command:near,chkrange:near,ComErr:NEAR + extrn Xerror:near + + +FINDLIN: + +; Inputs +; BX = Line number to be located in buffer (0 means last line+1) +; Outputs: +; DX = Actual line found +; DI = Pointer to start of line DX +; Zero set if BX = DX (if specified line found) +; AL,CX destroyed. No other registers affected. + + MOV DX,[CURRENT] + MOV DI,[POINTER] + CMP BX,DX ; fast find. Current = requested + retz + JA FINDIT ; start scanning at current? + OR BX,BX ; special case of EOF? + JZ FINDIT ; yes + MOV DX,1 ; set up for scan at beginning + MOV DI,OFFSET DG:START + CMP BX,DX ; at beginning? + retz +FINDIT: + MOV CX,[ENDTXT] ; count of bytes in buffer + SUB CX,DI ; for scan +SCANLN: + MOV AL,10 ; LF is what we look for. + OR AL,AL ; Clear zero flag for JCXZ +FINLIN: + JCXZ RET4 ; at end? Yes, no skip. + REPNE SCASB ; find EOL + INC DX ; increment count + CMP BX,DX ; find correct line? + JNZ FINLIN ; no, try again. +RET4: return + +; Inputs: +; BX = Line number to be displayed +; Function: +; Displays line number on terminal in 8-character +; format, suppressing leading zeros. +; AX, CX, DX destroyed. No other registers affected. + +SHOWNUM: + mov dx,offset dg:line_num_buf_ptr + mov line_num,bx + MOV line_flag,"*" + CMP BX,[CURRENT] + JZ STARLIN + MOV line_flag," " +STARLIN: + call std_printf +ret5: return + + +DISPONE: + MOV DI,1 + +DISPLAY: + +; Inputs: +; BX = Line number +; SI = Pointer to text buffer +; DI = No. of lines +; Function: +; Ouputs specified no. of line to terminal, each +; with leading line number. +; Outputs: +; BX = Last line output. +; All registers destroyed. + + MOV CX,[ENDTXT] + SUB CX,SI + retz ; no lines to display +;========================================================================= +; Initialize screen size and line counts for use by display. +; +; Date : 6/10/87 +;========================================================================= + + push ax ;an000;save affected regs + + mov al,dg:disp_len ;an000;length of video display + mov pg_count,al ;an000;init. screen size ctr. + + pop ax ;an000;restore affected regs + +;========================================================================= + + mov dx,di ;number of lines to print +; +; CX is the number of bytes in the buffer +; dx is the number of lines to be output +; +DISPLN: + SaveReg + CALL SHOWNUM + RestoreReg + mov di,offset dg:arg_buf +; +; Copy chars until CR/LF or end of line hit +; +OUTLN: + LODSB + CMP DI,254+offset dg:arg_buf ; are we at end of buffer? + JAE StoreDone ; Yes, do NOT store + CMP AL," " + JAE SEND + CMP AL,10 + JZ SEND + CMP AL,13 + JZ SEND + CMP AL,9 + JZ SEND + MOV AH,"^" + OR AL,40h + XCHG AL,AH + STOSW + JMP StoreDone +SEND: + stosb +StoreDone: + CMP AL,10 ; perform copy until LF is seen + LOOPNZ OUTLN +; +; Make sure buffer ends with CRLF +; + cmp byte ptr [di-1],10 + jz Terminate +; +; No LF seen. See if CR +; + cmp byte ptr [di-1],CR + jz StoreLF + mov al,CR + stosb +StoreLF: + mov al,10 + stosb +Terminate: + mov byte ptr [di],0 + + call EDLIN_DISP_COUNT ;an000;determine lines printed + ; DMS:6/10/87 + push dx + mov dx,offset dg:arg_buf_ptr + call std_printf + pop dx + JCXZ ret7 + INC BX + + call EDLIN_PG_COUNT ;an000;adjust screen line count + ; DMS:6/10/87 + cmp lc_flag,false ;an000;continue DISPLAY? + ; DMS:6/10/87 + JNZ DISPLN + DEC BX +ret7: return + +FNDFIRST: + MOV DI,1+OFFSET DG:TXT1 + mov byte ptr[olddat],1 ;replace with old value if none new + CALL GETTEXT + OR AL,AL ;Reset zero flag in case CX is zero + JCXZ RET7 + cmp al,1ah ;terminated with a ^Z ? + jne sj8 + mov byte ptr[olddat],0 ;do not replace with old value +sj8: + MOV [OLDLEN],CX + XOR CX,CX + CMP AL,0DH + JZ SETBUF + CMP BYTE PTR [SRCHFLG],0 + JZ NXTBUF +SETBUF: + DEC SI +NXTBUF: + MOV [COMLINE],SI + MOV DI,1+OFFSET DG:TXT2 + CALL GETTEXT + CMP BYTE PTR [SRCHFLG],0 + JNZ NOTREPL + CMP AL,0DH + JNZ HAVCHR + DEC SI +HAVCHR: + MOV [COMLINE],SI +NOTREPL: + MOV [NEWLEN],CX + MOV BX,[PARAM1] + OR BX,BX + JNZ CALLER + cmp byte ptr[srchmod],0 + jne sj9 + mov bx,1 ;start from line number 1 + jmp short sj9a +sj9: + MOV BX,[CURRENT] + INC BX ;Default search and replace to current+1 +sj9a: + CALL CHKRANGE +CALLER: + CALL FINDLIN + MOV [LSTFND],DI + MOV [NUMPOS],DI + MOV [LSTNUM],DX + MOV BX,[PARAM2] + CMP BX,1 + SBB BX,-1 ;Decrement everything except zero + CALL FINDLIN + MOV CX,DI + SUB CX,[LSTFND] + OR AL,-1 + JCXZ aret + CMP CX,[OLDLEN] + jae sj10 +aret: return +sj10: + MOV [SRCHCNT],CX + +FNDNEXT: + +; Inputs: +; [TXT1+1] has string to search for +; [OLDLEN] has length of the string +; [LSTFND] has starting position of search in text buffer +; [LSTNUM] has line number which has [LSTFND] +; [SRCHCNT] has length to be searched +; [NUMPOS] has beginning of line which has [LSTFND] +; Outputs: +; Zero flag set if match found +; [LSTFND],[LSTNUM],[SRCHCNT] updated for continuing the search +; [NUMPOS] has beginning of line in which match was made + + MOV AL,[TXT1+1] + MOV CX,[SRCHCNT] + MOV DI,[LSTFND] +SCAN: + OR DI,DI ;Clear zero flag in case CX=0 + REPNE SCASB ;look for first byte of string + + retnz ;return if you don't find +if kanji + call kanji_check ;see if the found byte is on a character boundary + jnz scan +endif + MOV DX,CX + MOV BX,DI ;Save search position + MOV CX,[OLDLEN] + DEC CX + MOV SI,2 + OFFSET DG:TXT1 + CMP AL,AL ;Set zero flag in case CX=0 + REPE CMPSB + MOV CX,DX + MOV DI,BX + JNZ SCAN + MOV [SRCHCNT],CX + MOV CX,DI + MOV [LSTFND],DI + MOV DI,[NUMPOS] + SUB CX,DI + MOV AL,10 + MOV DX,[LSTNUM] +;Determine line number of match +GETLIN: + INC DX + MOV BX,DI + REPNE SCASB + JZ GETLIN + DEC DX + MOV [LSTNUM],DX + MOV [NUMPOS],BX + XOR AL,AL + return + +if kanji + +;Kanji_check idea is to scan backwards to the first +; character which can't be a kanji or part of one +; (.lt. 40h) then scan forward to see if the +; current byte is on character boundary +; +;Output ZR <==> we're on a character boundary +; NZ <==> we're not on character boundary i.e. No Match +kanji_check: + push ax ;save search character + push di + dec di ;point to the character we found + mov si,di ;start searching bakwards from there + std +srch_loop: + lodsb + cmp al,40H + jae srch_loop + inc si ;point to first non-kanji + cld ;forward search +kan_loop: + cmp si,di ;are we at current byte? + jae passed_char ;if we are, or are passed it, exit + call next_char ;otherwise advance si to next char + jmp short kan_loop ;and loop +passed_char: + pop di + pop ax + ret + +;Next_char si points to a character boundary +; advance si to point to the beginning of the next char +; +; +next_char: + push ax + lodsb + call testkanj + jz not_kanj + inc si +not_kanj: + pop ax + ret + +;--------------------------------------------------------------------; +; TESTKANJ ~ FIND OUT IS THE BYTE IS A KANJI PREFIX ; +; ; +; entry: AL byte to test ; +; ; +; exit: NZ if lead byte ortherwise ZR ; +; ; +; modifies: AX ; +; ; +;--------------------------------------------------------------------; + +testkanj: + push ax + xchg ah,al ;put byte in ah + push ds + push si + lds si,cs:[lbtbl] ;get pointer to lead byte table +ktlop: + lodsb ;direction flag should be OK + or al,al ;are we at the end of table? + jz notlead ;brif so + cmp al,ah ;is START RANGE > CHARACTER? + ja notlead ;brif so, not a lead character (carry clear) + lodsb ;get second range byte + cmp ah,al ;is CHARACTER > END RANGE + ja ktlop ;brif so, not a lead character (check next range) + or al,al ;make NZ +notl_exit: + pop si + pop ds + pop ax + ret +notlead: + cmp al,al + jmp notl_exit + +endif + +GETTEXT: + +; Inputs: +; SI points into command line buffer +; DI points to result buffer +; Function: +; Moves [SI] to [DI] until ctrl-Z (1AH) or +; RETURN (0DH) is found. Termination char not moved. +; Outputs: +; AL = Termination character +; CX = No of characters moved. +; SI points one past termination character +; DI points to next free location + + XOR CX,CX + +GETIT: + LODSB +;----------------------------------------------------------------------- + cmp al,quote_char ;a quote character? + jne sj101 ;no, skip.... + lodsb ;yes, get quoted character + call make_cntrl + jmp short sj102 +;----------------------------------------------------------------------- +sj101: + CMP AL,1AH + JZ DEFCHK +sj102: + CMP AL,0DH + JZ DEFCHK + STOSB + INC CX + JMP SHORT GETIT + +DEFCHK: + OR CX,CX + JZ OLDTXT + PUSH DI + SUB DI,CX + MOV BYTE PTR [DI-1],cl + POP DI + return + +OLDTXT: + cmp byte ptr[olddat],1 ;replace with old text? + je sj11 ;yes... + mov byte ptr[di-1],cl ;zero text buffer char count + return + +sj11: + MOV CL,BYTE PTR [DI-1] + ADD DI,CX + return + +REPLACE: + +; Inputs: +; CX = Length of new text +; DX = Length of original text +; SI = Pointer to new text +; DI = Pointer to old text in buffer +; Function: +; New text replaces old text in buffer and buffer +; size is adjusted. CX or DX may be zero. +; CX, SI, DI all destroyed. No other registers affected. + + CMP CX,DX + JZ COPYIN + PUSH SI + PUSH DI + PUSH CX + MOV SI,DI + ADD SI,DX + ADD DI,CX + MOV AX,[ENDTXT] + SUB AX,DX + ADD AX,CX + CMP AX,[LAST] + JAE MEMERR + XCHG AX,[ENDTXT] + MOV CX,AX + SUB CX,SI + CMP SI,DI + JA DOMOV + ADD SI,CX + ADD DI,CX + STD +DOMOV: + INC CX + + REP MOVSB + CLD + POP CX + POP DI + POP SI +COPYIN: + REP MOVSB + return + +MEMERR: + MOV DX,OFFSET DG:MEMFUL_ptr + call std_printf + JMP COMMAND + + +LOADBUF: + MOV DI,2 + OFFSET DG:EDITBUF + MOV CX,255 + MOV DX,-1 +LOADLP: + LODSB + STOSB + INC DX + CMP AL,13 + LOOPNZ LOADLP + MOV [EDITBUF+1],DL + retz +TRUNCLP: + LODSB + INC DX + CMP AL,13 + JNZ TRUNCLP + DEC DI + STOSB + return + +SCANEOF: + cmp [loadmod],0 + je sj52 + +;----- Load till physical end of file + + cmp cx,word ptr[amnt_req] + jb sj51 + xor al,al + inc al ;reset zero flag + return +sj51: + jcxz sj51b + push di ;get rid of any ^Z at the end of the file + add di,cx + dec di ;points to last char + cmp byte ptr [di],1ah + pop di + jne sj51b + dec cx +sj51b: + xor al,al ;set zero flag + call check_end ;check that we have a CRLF pair at the end + return + +;----- Load till first ^Z is found + +sj52: + PUSH DI + PUSH CX + MOV AL,1AH + or cx,cx + jz not_found ;skip with zero flag set + REPNE SCASB ;Scan for end of file mark + jnz not_found + LAHF ;Save flags momentarily + inc cx ;include the ^Z + SAHF ;Restore flags +not_found: + mov di,cx ;not found at the end + POP CX + LAHF ;Save flags momentarily + SUB CX,DI ;Reduce byte count if EOF found + SAHF ;Restore flags + POP DI + call check_end ;check that we have a CRLF pair at the end + + return + + +;----------------------------------------------------------------------- +; If the end of file was found, then check that the last character +; in the file is a LF. If not put a CRLF pair in. + +check_end: + jnz not_end ;end was not reached + pushf ;save return flag + push di ;save pointer to buffer + add di,cx ;points to one past end on text + dec di ;points to last character + cmp di,offset dg:start + je check_no + cmp byte ptr[di],0ah ;is a LF the last character? + je check_done ;yes, exit +check_no: + mov byte ptr[di+1],0dh ;no, put a CR + inc cx ;one more char in text + mov byte ptr[di+2],0ah ;put a LF + inc cx ;another character at the end +check_done: + pop di + popf +not_end: + return + +CRLF: + push dx + mov dx,offset dg:crlf_ptr + call std_printf + pop dx + return +LF: + MOV dx,offset dg:lf_ptr + call std_printf + return + +ABORTCOM: + MOV AX,CS + MOV DS,AX + MOV ES,AX + MOV AX,cstack + MOV SS,AX + MOV SP,STACK + STI + CALL CRLF + JMP COMMAND + +DELBAK: + ;Delete old backup file (.BAK) + + MOV BYTE PTR [DELFLG],1 + MOV DI,[EXT_PTR] + MOV SI,OFFSET DG:BAK + MOVSW + MOVSW + MOVSB + MOV AH,UNLINK + MOV DX,OFFSET DG:TEMP_PATH + INT 21H +; $if c ;error ? ;an000; dms; + JNC $$IF1 + cmp ax,Access_Denied ;file read only? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE $$IF2 + mov bx,[Wrt_Handle] ;close .$$$ file ;an000; dms; + mov ah,Close ;close function ;an000; dms; + int 21h ;close it ;an000; dms; + + mov di,[Ext_Ptr] ;point to extension ;an000; dms; + mov si,offset dg:$$$File ;point to .$$$ extension;an000; dms; + movsw ;get .$$$ extension ;an000; dms; + movsw ; ;an000; dms; + movsb ; ;an000; dms; + mov dx,offset dg:Temp_Path ;point to .$$$ file ;an000; dms; + mov ah,Unlink ;delete it ;an000; dms; + int 21h ; ;an000; dms; + + mov di,[Ext_Ptr] ;point to extension ;an000; dms; + mov si,offset dg:BAK ;point to .BAK extension;an000; dms; + movsw ;get .BAK extension ;an000; dms; + movsw ; ;an000; dms; + movsb ; ;an000; dms; + mov dx,offset dg:Del_Bak_Ptr;point to error message ;an000; dms; + jmp Xerror ;display message & exit ;an000; dms; +; $endif +$$IF2: +; $endif +$$IF1: + + MOV DI,[EXT_PTR] + MOV SI,OFFSET DG:$$$FILE + MOVSW + MOVSW + MOVSB + return + + +;-----------------------------------------------------------------------; +; Will scan buffer given pointed to by SI and get rid of quote +;characters, compressing the line and adjusting the length at the +;begining of the line. +; Preserves al registers except flags and AX . + +unquote: + push cx + push di + push si + mov di,si + mov cl,[si-1] ;length of buffer + xor ch,ch + mov al,quote_char + cld +unq_loop: + jcxz unq_done ;no more chars in the buffer, exit + repnz scasb ;search for quote character + jnz unq_done ;none found, exit + push cx ;save chars left in buffer + push di ;save pointer to quoted character + push ax ;save quote character + mov al,byte ptr[di] ;get quoted character + call make_cntrl + mov byte ptr[di],al + pop ax ;restore quote character + mov si,di + dec di ;points to the quote character + inc cx ;include the carriage return also + rep movsb ;compact line + pop di ;now points to after quoted character + pop cx + jcxz sj13 ;if quote char was last of line do not adjust + dec cx ;one less char left in the buffer +sj13: pop si + dec byte ptr[si-1] ;one less character in total buffer count also + push si + jmp short unq_loop + +unq_done: + pop si + pop di + pop cx + return + + +;-----------------------------------------------------------------------; +; Convert the character in AL to the corresponding control +; character. AL has to be between @ and _ to be converted. That is, +; it has to be a capital letter. All other letters are left unchanged. + +make_cntrl: + push ax + and ax,11100000b + cmp ax,01000000b + pop ax + jne sj14 + and ax,00011111b +sj14: + return + + +;---- Kill spaces in buffer --------------------------------------------; +;========================================================================= +; kill_bl : Parses over spaces in a buffer. +; +; Date : 6/10/86 +;========================================================================= +kill_bl: + + push bx ;an000;save affected reg. +kill_bl_cont: + + lodsb ;get rid of blanks + cmp al,9 + je kill_bl_cont ;an000;it is a tab + + cmp al,10 + je kill_bl_cont ;an000;if LF + + cmp al,' ' + je kill_bl_cont ;an000;we have a space + + if kanji ;an000;is this a kanji assembly + call testkanj ;an000;do we have a dbcs lead byte +; $if nz ;an000;yes, we have a lead byte + JZ $$IF5 + cmp al,dbcs_lead_byte;an000;is it 81h +; $if z ;an000;it is 81h + JNZ $$IF6 + mov bl,ds:[si] ;an000;set up for compare + cmp bl,asian_blk;an000;is it 40h +; $if z ;an000;we have an asian blank + JNZ $$IF7 + lodsb ;an000;skip byte containing 81h + jmp kill_bl_cont +; $endif ;an000; +$$IF7: +; $endif ;an000;fall through no delim +$$IF6: + ; found +; $endif ;an000;end test for dbcs lead byte +$$IF5: + endif ;an000;end conditional assembly + + pop bx ;an000;restore affected reg. + return + +;----- Capitalize the character in AL ----------------------------------; +; ; +; Input: ; +; ; +; AL contains a character to capitalize ; +; ; +; Output: ; +; ; +; AL contains a capitalized character ; +; ; +;-----------------------------------------------------------------------; + +MAKE_CAPS: + CMP AL,"a" + JB CAPS1 + CMP AL,"z" +if KANJI + JA CAPS1 ; M003 MSKK TAR 476, kana chars +else + JG CAPS1 +endif + AND AL,0DFH +CAPS1: + return + +QUIT: + CMP ParamCt,1 + JZ Quit1 +CERR: JMP ComErr +Quit1: CMP Param1,0 + JNZ CERR + MOV DX,OFFSET DG:QMES_ptr + call std_printf + +IF KANJI + CALL TESTKANJ + JZ ASCII + MOV AX, (STD_CON_INPUT_FLUSH SHL 8) + 0 + INT 21H ; Eat the trailing byte. + JMP CRLF +ASCII: +ENDIF +;========================================================================= +; We are invoking the VAL_YN proc here. This will replace the +; method of Y/N validation used prior to DOS 4.00. +; +; Date : 6/10/87 +;========================================================================= + + call val_yn ;an000;pass Y/N byte in AL to macro + cmp ax,yes ;an000;did we return a Y + jz NoCRLF ;an000; dms; close the file + cmp ax,no ;an000; dms; return N? +; $if ne ;an000; dms; neither N or Y - reprompt + JE $$IF11 + push dx ;an000; dms; must be N + mov dx,offset dg:crlf_ptr ;an000; dms; spit out CRLF + call std_printf ;an000; dms; and return + pop dx ;an000; dms; to caller + jmp Quit1 ;an000; dms; reprompt +; $endif ;an000; dms; +$$IF11: + push dx ;an000; dms; must be N + mov dx,offset dg:crlf_ptr ;an000; dms; spit out CRLF + call std_printf ;an000; dms; and return + pop dx ;an000; dms; to caller + return ;an000; dms; + +;========================================================================= +; End of Y/N validation check for qmes_ptr +;========================================================================= + +NOCRLF: + MOV BX,[WRT_HANDLE] + MOV AH,CLOSE + INT 21H + MOV DX,OFFSET DG:TEMP_PATH + MOV AH,UNLINK + INT 21H + mov ah,exit + xor al,al + INT 21H + +QUERY: + TEST BYTE PTR [QFLG],-1 + retz + MOV DX,OFFSET DG:ASK_ptr + call std_printf + PUSH AX + CALL CRLF + POP AX +IF KANJI + CALL TESTKANJ + JZ ASCII1 + PUSH AX + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT 21H ;Eat the trailing byte + XOR AX,AX + INC AX ; non zero flag + POP AX + return +ASCII1: +ENDIF + CMP AL,13 ;Carriage return means yes + retz +;========================================================================= +; We are invoking the VAL_YN proc here. This will replace the +; method of Y/N validation used prior to DOS 4.00. +; This invocation of val_yn will return ZR if Y is found, otherwise +; it will return NZ. +; +; Date : 6/10/87 +;========================================================================= + + call val_yn ;an000;pass Y/N byte in AL to macro + cmp ax,yes ;an000;did we return a Y + je Query_Exit ;an000; dms; exit Y/N validation + cmp ax,no ;an000; dms; N response? + jne Query ;an000; dms; no - reprompt user + cmp ax,yes ;an000; dms; must have N response - force + ; NZ flag +Query_Exit: + + +;========================================================================= +; End of Y/N validation check for ask_ptr +;========================================================================= + + return + +;========================================================================= +; EDLIN_DISP_COUNT: This routine will determine the number of lines +; actually displayed to the screen. Lines displayed to +; the screen for one EDLIN line printed will be calculated +; by the following formula: +; +; LINES_PRINTED = (LINE_LEN + 10) / SCREEN_WIDTH +; +; LINES_PRINTED - Actual number of lines printed on screen +; for one EDLIN line. If LINES_PRINTED has +; a remainder, it will be rounded up. +; +; LINE_LEN - The length, in bytes, of the EDLIN line +; printed. +; +; SCREEN_WIDTH - The width in bytes of the current display. +; +; Inputs : DI - offset into buffer containing line printed +; DISP_WIDTH - width of current video output +; +; Outputs: LC_ADJ - factor to adjust line counter by +; +; Date : 6/10/87 +;========================================================================= + +EDLIN_DISP_COUNT proc near ;an000;lines printed + + push dx ;an000;save affected regs + push di ;an000; + push ax ;an000; + push bx ;an000; + push cx ;an000; + + mov bx,offset dg:arg_buf ;an000;arg_buf holds line + ; printed + mov ax,di ;an000;where print line ends + sub ax,bx ;an000;diff = line's length + add ax,10 ;an000;adjust for leading blks + mov cl,dg:disp_width ;an000;set up for division + div cl ;an000;divide AX by the + ; width of the console + cmp ah,0 ;an000;see if a remainder +; $if nz ;an000;if a remainder + JZ $$IF13 + add al,1 ;an000;increment AL 1 + ; to round upward +; $endif ;an000; +$$IF13: + + mov lc_adj,al ;an000;number of lines printed + ; on console + pop cx ;an000;restore affected regs + pop bx ;an000; + pop ax ;an000; + pop di ;an000; + pop dx ;an000; + + ret ;an000;return to caller + +EDLIN_DISP_COUNT endp ;an000;end proc + +;========================================================================= +; EDLIN_PG_COUNT : This routine determines whether or not we will continue +; displaying text lines based on the count of lines that +; can be output to the current video screen. +; +; Inputs : LC_ADJ - adjustment factor for number of lines printed +; PG_COUNT - number of lines remaining on current video +; display +; DX - holds the total number of lines to print +; CONTINUE - signals if the user wants to continue +; printing lines. +; +; Outputs: LC_FLAG - used to signal completion of print +; +; Date : 6/10/87 +;========================================================================= + +EDLIN_PG_COUNT proc near ;an000;track remaining lines + + push ax ;an000;save affected regs + + mov lc_flag,true ;an000;init. flag to signal + ; continue printing + + mov al,pg_count ;an000;set up for page adj. + cmp al,lc_adj ;an000;see if we are at end +; $if be ;an000 + JNBE $$IF15 + mov pg_count,0 ;an000;set pg_count to 0 +; $else + JMP SHORT $$EN15 +$$IF15: + sub al,lc_adj ;an000;adjust number of lines + mov pg_count,al ;an000;save remaining line ct. +; $endif ;an000; +$$EN15: + + dec dx ;an000;decrease total number + ; of lines to print by 1 +; $if nz ;an000;more lines to print + JZ $$IF18 + cmp pg_count,0 ;an000;have we printed screen +; $if be ;an000;we have printed screen + JNBE $$IF19 + call EDLIN_PG_PROMPT ;an000;prompt the user to + ; "Continue(Y/N)?" + cmp continue,true ;an000;did user say continue +; $if z ;an000;continue + JNZ $$IF20 + mov al,dg:disp_len ;an000;begin init of screen +; dec al ;an000; length + mov pg_count,al ;an000; +; $else ;an000;do not continue + JMP SHORT $$EN20 +$$IF20: + mov lc_flag,false ;an000;signal no more to print +; $endif ;an000; +$$EN20: +; $endif ;an000; +$$IF19: +; $else ;an000;total lines printed + JMP SHORT $$EN18 +$$IF18: + mov lc_flag,false ;an000;signal no more to print +; $endif ;an000; +$$EN18: + + pop ax ;an000;restore affected regs + + ret ;an000;return to caller + +EDLIN_PG_COUNT endp ;an000;end procedure + +;========================================================================= +; EDLIN_PG_PROMPT : This routine prompts the user as to whether or not to +; continue printing lines to the video display, if lines +; are still present for printing. +; +; Inputs : none +; +; Outputs: CONTINUE - flag that signals other routines whether or +; not to continue printing. +; +; Date : 6/10/87 +;========================================================================= + +EDLIN_PG_PROMPT proc near ;an000;ask user to continue? + + push dx ;an000;save affected regs. + push ax ;an000; + +EPP_Reprompt: + + mov dx,offset dg:cont_ptr ;an000;point to Continue msg. + call std_printf ;an000;invoke message ret. + + push ax ;an000;save affected regs. + call crlf ;an000;send crlf + pop ax ;an000;restore affected regs. + + call val_yn ;an000;Y/N validation + + cmp ax,yes ;an000;did we have a Y + jz EPP_True_Exit ;an000;we had a Y + cmp ax,no ;an000;did we have a N + jz EPP_False_Exit ;an000;yes + jmp EPP_Reprompt ;an000;neither Y or N - reprompt + +EPP_True_Exit: + + mov Continue,True ;an000;flag Y found + jmp EPP_Exit ;an000;exit routine + +EPP_False_Exit: + + mov Continue,False ;an000;flag N found + +EPP_Exit: + + pop ax ;an000;restore affected regs. + pop dx ;an000; + + ret ;an000;return to caller + +EDLIN_PG_PROMPT endp ;an000;end procedure + +;========================================================================= +; val_yn: This proc validates a Y/N response entered by the user. The +; routine uses the new functionality of "GET EXTENDED COUNTRY +; INFORMATION" being implemented in DOS 4.00. +; +; Inputs : AL - character to be validated for Y/N response +; +; Outputs: AX - 00h = "N"o +; - 01h = "Y"es +;========================================================================= + +val_yn proc near ;an000;validate Y/N response + + push dx ;an000;save affected registers + push cx ;an000; + push bx ;an000; + + mov dl,al ;an000;character to be checked for Y/N + mov ah,GetExtCntry ;an000;get extended country information + mov al,yn_chk ;an000;perform Y/N checking + mov cx,max_len ;an000;max. len. of Y/N char. + int 21h ;an000;invoke function + + pop bx ;an000;restore affected registers + pop cx ;an000; + pop dx ;an000; + + ret ;an000;return to caller + +val_yn endp ;an000;end proc + + + +code ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLEQU.ASM b/v4.0/src/CMD/EDLIN/EDLEQU.ASM new file mode 100644 index 0000000..d60796d --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLEQU.ASM @@ -0,0 +1,156 @@ + page 60,132 ; + + .xlist + include DOSSYM.INC + include EDLSTDSW.INC + .list + +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLEQU.SAL +; +; DESCRIPTIVE NAME: EQUATES FOR EDLIN +; +; FUNCTION: PROVIDES EQUATES FOR EDLIN. IT ALSO PROVIDES THE MACRO +; VAL_YN. +; +; ENTRY POINT: NA +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; ROUTINE: VAL_YN - VALIDATES Y/N RESPONSES FROM THE KEYBOARD +; +; EXTERNAL REFERENCES: +; +; ROUTINE: NA +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT SYSPARSE +; - IMPLEMENT MESSAGE RETRIEVER +; - IMPLEMENT DBCS ENABLING +; - ENHANCED VIDEO SUPPORT +; - EXTENDED OPENS +; - SCROLLING ERROR +; +; COPYRIGHT: "MS DOS EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; +;======================= END OF SPECIFICATIONS =========================== + + + + + + +COMAND_LINE_LENGTH EQU 128 +QUOTE_CHAR EQU 16H ;Quote character = ^V +CR EQU 13 +STKSIZ EQU 200h +STACK equ stksiz + +asian_blk equ 40h ;an000;asian blank 2nd. byte +dbcs_lead_byte equ 81h ;an000;asian blank lead byte +nul equ 00h ;an000;nul character +Access_Denied equ 0005h ;an000;extended error code for access denied + +;======== Y/N validation equates ========================================= + +yn_chk equ 23h ;an000;check for Y/N response +max_len equ 01h ;an000;max. len. for Y/N char. +yes equ 01h ;an000;boolean yes value +no equ 00h ;an000;boolean no value + +;======== text display values for initialization ========================= + +video_get equ 0fh ;an000;int 10 get video attributes +video_set equ 00h ;an000;int 10 set video attributes +video_text equ 03h ;an000;80 X 25 color monitor + +;======== code page values for functions ================================= + +get_set_cp equ 66h ;an000;get or set code page +get_cp equ 01h ;an000;get active code page +set_cp equ 02h ;an000;set active code page + +;======== screen length & width defaults ================================= + +std_out equ 01h ;an000;console output +display_attr equ 03h ;an000;display for IOCTL +Get_Display equ 7fh ;an000;Get display for IOCTL +Def_Disp_Len equ 25 ;an000;default display length +Def_Disp_Width equ 80 ;an000;default display width + +;======== extended open equates ========================================== + +rw equ 0082h ;an000;read/write + ; compatibility + ; noinherit + ; int 24h handler + ; no commit + +ext_read equ 0080h ;an000;read + ; compatibility + ; noinherit + ; int 24h handler + ; no commit + +rw_flag equ 0101h ;an000;fail if file not exist + ; open if file exists + ; don't validate code page + +creat_flag equ 0110h ;an000;create if file does not exist + ; fail if file exists + ; don't validate code page + +open_flag equ 0101h ;an000;fail if file not exist + ; open if file exists + ; don't validate code page + +creat_open_flag equ 0112h ;an000;create if file does not exist + ; open/replace if file exists + ; don't validate code page + +attr equ 00h ;an000;attributes set to 0 + +;======== parse value equates ============================================ + +nrm_parse_exit equ 0ffffh ;an000;normal exit from sysparse +too_many equ 01h ;an000;too many parms entered +op_missing equ 02h ;an000;required operand missing +sw_missing equ 03h ;an000;not a valid switch + + +;======== Strucs ========================================================= + +Display_Buffer_Struc Struc ;an000;dms; + + Display_Info_Level db ? ;an000;dms; + Display_Reserved db ? ;an000;dms; + Display_Buffer_Size dw ? ;an000;dms; + Display_Flags dw ? ;an000;dms; + Display_Mode db ? ;an000;dms; + ; TEXT=01 + ; APA =02 + Display_Mode_Reserved db ? ;an000;dms; + Display_Colors dw ? ;an000;dms;# of colors + Display_Width_Pixels dw ? ;an000;dms;# of pixels in width + Display_Length_Pixels dw ? ;an000;dms;# of pixels in len. + Display_Width_Char dw ? ;an000;dms;# of chars in width + Display_Length_Char dw ? ;an000;dms;# of chars in length + +Display_Buffer_Struc ends ;an000;dms; + + + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLIN.ASM b/v4.0/src/CMD/EDLIN/EDLIN.ASM new file mode 100644 index 0000000..5368db0 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLIN.ASM @@ -0,0 +1,1843 @@ + PAGE 60,132; + TITLE EDLIN + +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLIN.SAL +; +; DESCRIPTIVE NAME: LINE TEXT EDITOR +; +; FUNCTION: EDLIN IS A SIMPLE, LINE ORIENTED TEXT EDITOR. IT PROVIDES +; USERS OF DOS THE ABILITY TO CREATE AND EDIT TEXT FILES. +; +; ENTRY POINT: EDLIN +; +; INPUT: DOS COMMAND LINE +; EDLIN COMMANDS +; TEXT +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: +; +; EXTERNAL REFERENCES: +; +; ROUTINE: EDLCMD1 - CONTAINS ROUTINES CALLED BY EDLIN +; EDLCMD1 - CONTAINS ROUTINES CALLED BY EDLIN +; EDLMES - CONTAINS ROUTINES CALLED BY EDLIN +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING: +; +; - IMPLEMENT SYSPARSE +; - IMPLEMENT MESSAGE RETRIEVER +; - IMPLEMENT DBCS ENABLING +; - ENHANCED VIDEO SUPPORT +; - EXTENDED OPENS +; - SCROLLING ERROR +; +; COPYRIGHT: "MS DOS EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft" +; +; +; MICROSOFT REVISION HISTORY: +; ; +; V1.02 ; +; ; +; V2.00 9/13/82 M.A.U ; +; ; +; 2/23/82 Rev. 13 N. P ; +; Changed to 2.0 system calls. ; +; Added an error message for READ-ONLY files ; +; ; +; 11/7/83 Rev. 14 N. P ; +; Changed to .EXE format and added Printf ; +; ; +; V2.50 11/15/83 Rev. 1 M.A. U ; +; Official dos 2.50 version. Some random bug ; +; fixes and message changes. ; +; ; +; 11/30/83 Rev. 2 MZ ; +; Close input file before rename. ; +; Jmp to replace after line edit ; +; ; +; 02/01/84 Rev. 3 M.A. U ; +; Now it is called 3.00 dos. Repaired problem ; +; with using printf and having %'s as data. ; +; ; +; 02/15/84 MZ make out of space a fatal error with output; +; ; +; 03/28/84 MZ fixes bogus (totally) code in MOVE/COPY ; +; ; +; 04/02/84 MZ fixes DELETE and changes MOVE/COPY/EDIT ; +; ; +; V3.20 08/29/86 Rev. 1 S.M. G ; +; ; +; 08/29/86 M001 MSKK TAR 593, TAB MOVEMENT ; +; ; +; 08/29/86 M002 MSKK TAR 157, BLKMOVE 1,1,1m, 1,3,1m ; +; ; +; 08/29/86 M003 MSKK TAR 476, EDLCMD2,MAKECAPS,kana char; +; ; +; 08/29/86 M004 MSKK TAR 191, Append load size ; +; ; +; 08/29/86 M005 IBMJ TAR Transfer Load command ; +; +; +;======================= END OF SPECIFICATIONS =========================== ; + +include edlequ.asm + +SUBTTL Contants and Data areas +PAGE + extrn parser_command:near ;an000;SYSPARSE + +CODE SEGMENT PUBLIC +CODE ENDS + +CONST SEGMENT PUBLIC WORD +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC WORD +DATA ENDS + +DG GROUP CODE,CONST,cstack,DATA + +CONST SEGMENT PUBLIC WORD + + public bak,$$$file,delflg,loadmod,txt1,txt2 + + EXTRN BADDRV_ptr:word,NDNAME_ptr:word,bad_vers_err:byte,opt_err_ptr:word + EXTRN NOBAK_ptr:word,BADCOM_ptr:word,NEWFIL_ptr:word,DEST_ptr:word,MRGERR_ptr:word + EXTRN NODIR_ptr:word,FILENM_ptr:word,ro_err_ptr:word,bcreat_ptr:word + EXTRN TOO_MANY_ptr:word,lf_ptr:word,prompt_ptr:word + EXTRN MemFul_Ptr:word + +BAK DB ".BAK",0 + +$$$FILE DB ".$$$",0 + +fourth db 0 ;fourth parameter flag + +loadmod db 0 ;Load mode flag, 0 = ^Z marks the + ; end of a file, 1 = viceversa. +optchar db "-" + +TXT1 DB 0,80H DUP (?) +TXT2 DB 0,80H DUP (?) +DELFLG DB 0 +fNew DB 0 ; old file +HAVEOF DB 0 + +CONST ENDS + +cstack segment stack + db stksiz dup (?) +cstack ends + +DATA SEGMENT PUBLIC WORD + + extrn arg_buf_ptr:word ;an000; + extrn line_num_buf_ptr:word ;an000; + + public path_name,ext_ptr,start,line_num,line_flag + public arg_buf,wrt_handle,temp_path + public current,pointer,qflg,editbuf,amnt_req,fname_len,delflg,lastlin + public olddat,oldlen,newlen,srchflg,srchmod + public comline,lstfnd,numpos,lstnum,last,srchcnt + public rd_handle,haveof,ending,three4th,one4th + + public lc_adj ;an000;page length adj. factor + public lc_flag ;an000;display cont. flag + public pg_count ;an000;lines left on screen + public Disp_Len ;an000;display length + public Disp_Width ;an000;display width + public continue ;an000;boolean T/F + public temp_path ;an000;pointer to filespec buf + +Video_Buffer label word ;an000;buffer for video attr + db 0 ;an000;dms; + db 0 ;an000;dms; + dw 14 ;an000;dms; + dw 0 ;an000;dms; + db ? ;an000;dms; + db 0 ;an000;dms; + dw ? ;an000;dms;# of colors + dw ? ;an000;dms;# of pixels in width + dw ? ;an000;dms;# of pixels in len. + dw ? ;an000;dms;# of chars in width + dw ? ;an000;dms;# of chars in length + + +video_org db ? ;an000;original video mode on + ; entry to EDLIN. +lc_adj db ? ;an000;page length adj. factor +lc_flag db ? ;an000;display cont. flag +pg_count db ? ;an000;lines left on screen +Disp_Len db ? ;an000;display length +Disp_Width db ? ;an000;display width +continue db ? ;an000;boolean T/F + + +;-----------------------------------------------------------------------; +; This is a table that is sequentially filled via GetNum. Any additions to it +; must be placed in the correct position. Currently Param4 is known to be a +; count and thus is treated specially. + + public param1,param2,Param3,param4,ParamCt +PARAM1 DW ? +PARAM2 DW ? +PARAM3 DW ? +PARAM4 DW ? +ParamCt DW ? ; count of passed parameters + if kanji ; Used in TESTKANJ: +LBTbl dd ? ; long pointer to lead byte table + endif ; in the dos (from syscall 63H) + +;-----------------------------------------------------------------------; + +PUBLIC PTR_1, PTR_2, PTR_3, OLDLEN, NEWLEN, LSTFND, LSTNUM, NUMPOS, SRCHCNT +PUBLIC CURRENT, POINTER, ONE4TH, THREE4TH, LAST, ENDTXT, COPYSIZ +PUBLIC COMLINE, LASTLIN, COMBUF, EDITBUF, EOL, QFLG, ENDING, SRCHFLG +PUBLIC PATH_NAME, FNAME_LEN, RD_HANDLE, TEMP_PATH, WRT_HANDLE, EXT_PTR +PUBLIC MRG_PATH_NAME, MRG_HANDLE, amnt_req, olddat, srchmod, MOVFLG, org_ds +if kanji +public lbtbl +endif + +; +; These comprise the known state of the internal buffer. All editing +; functions must preserve these values. +; +CURRENT DW ? ; the 1-based index of the current line +POINTER DW ? ; pointer to the current line +ENDTXT DW ? ; pointer to end of buffer. (at ^Z) +LAST DW ? ; offset of last byte of memory +; +; The label Start is the beginning of the in-core buffer. +; + +; +; Internal temporary pointers +; +PTR_1 DW ? +PTR_2 DW ? +PTR_3 DW ? + +QFLG DB ? ; TRUE => query for replacement +OLDLEN DW ? +NEWLEN DW ? +LSTFND DW ? +LSTNUM DW ? +NUMPOS DW ? +SRCHCNT DW ? +ONE4TH DW ? +THREE4TH DW ? +COPYSIZ DW ? ; total length to copy +COPYLEN DW ? ; single copy length +COMLINE DW ? +LASTLIN DW ? +COMBUF DB 82H DUP (?) +EDITBUF DB 258 DUP (?) +EOL DB ? +ENDING DB ? +SRCHFLG DB ? +PATH_NAME DB 128 DUP(0) +FNAME_LEN DW ? +RD_HANDLE DW ? +TEMP_PATH DB 128 DUP(?) +WRT_HANDLE DW ? +EXT_PTR DW ? +MRG_PATH_NAME DB 128 DUP(?) +MRG_HANDLE DW ? +amnt_req dw ? ; amount of bytes requested to read +olddat db ? ; Used in replace and search, replace + ; by old data flag (1=yes) +srchmod db ? ; Search mode: 1=from current+1 to + ; end of buffer, 0=from beg. of + ; buffer to the end (old way). +MOVFLG DB ? +org_ds dw ? ;Orginal ds points to header block + +arg_buf db 258 dup (?) + +EA_Flag db False ;an000; dms;set to false + +EA_Buffer_Size dw ? ;an000; dms;EA buffer's size + +EA_Parm_List label word ;an000; dms;EA parms + dd dg:Start ;an000; dms;ptr to EA's + dw 0001h ;an000; dms;additional parms + db 06h ;an000; dms; + dw 0002h ;an000; dms;iomode + + +line_num dw ? + +line_flag db ?,0 + EVEN ;align on word boundaries +; +; Byte before start of data buffer must be < 40H !!!!!! +; + dw 0 ;we scan backwards looking for + ;a character which can't be part + ;of a two-byte seqence. This + ;double byte sequence will cause the back + ;scan to stop here. +START LABEL WORD + +DATA ENDS + + +CODE SEGMENT PUBLIC + +ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:CStack + + + + extrn pre_load_message:near ;an000;message loader + extrn disp_fatal:near ;an000;fatal message + extrn printf:near ;an000;new PRINTF routine + + extrn findlin:near,shownum:near,loadbuf:near,crlf:near,lf:near + extrn abortcom:near,delbak:near,unquote:near,kill_bl:near + extrn make_caps:near,dispone:near,display:near,query:near + extrn quit:near,make_cntrl:near,scanln:near,scaneof:near + extrn fndfirst:near,fndnext:near,replace:near,memerr:near + extrn xerror:near,bad_read:near,append:near + extrn nocom:near,pager:near,list:near,search_from_curr:near + extrn replac_from_curr:near,ewrite:near,wrt:near,delete:near + + + extrn filespec:byte ;an000;parser's filespec + extrn parse_switch_b:byte ;an000;result of switch scan + + public std_printf,command,chkrange,comerr + ; exit from EDLIN + + IF KANJI + extrn testkanj:near + ENDIF + +EDLIN: + JMP SHORT SIMPED + +std_printf proc near ;ac000;convert to proc + + push dx + call printf + pop dx ;an000;balance the push + ret + +std_printf endp ;ac000;end proc + +NONAME: + MOV DX,OFFSET DG:NDNAME_ptr + JMP XERROR + +SIMPED: + mov org_ds,DS + push ax ;ac000;save for drive compare + + push cs ;an000;exchange cs/es + pop es ;an000; + + push cs ;an000;exchange cs/ds + pop ds ;an000; + assume ds:dg,es:dg ;an000;establish addressibility + + MOV dg:ENDING,0 + mov sp,stack + call EDLIN_DISP_GET ;an000;get current video + ; mode & set it to + ; text + +;========================================================================= +; invoke PRE_LOAD_MESSAGE here. If the messages were not loaded we will +; exit with an appropriate error message. +; +; Date : 6/14/87 +;========================================================================= + + call PRE_LOAD_MESSAGE ;an000;invoke SYSLOADMSG +; $if c ;an000;if the load was unsuccessful + JNC $$IF1 + mov ah,exit ;an000;exit EDLIN. PRE_LOAD_MESSAGE + ; has said why we are exiting + mov al,00h ;an000 + int 21h ;an000;exit +; $endif ;an000; +$$IF1: + + + +VERS_OK: +;----- Check for valid drive specifier --------------------------------; + + pop ax + OR AL,AL + JZ get_switch_char + MOV DX,OFFSET DG:BADDRV_ptr + JMP xerror +get_switch_char: + MOV AX,(CHAR_OPER SHL 8) ;GET SWITCH CHARACTER + INT 21H + CMP DL,"/" + JNZ CMD_LINE ;IF NOT / , THEN NOT PC + MOV OPTCHAR,"/" ;IN PC, OPTION CHAR = / + + IF KANJI + push ds ; SAVE! all regs destroyed on this + push es + push si ; call !! + mov ax,(ECS_call shl 8) or 00h ; get kanji lead tbl + int 21h +assume ds:nothing +assume es:nothing + mov word ptr [LBTbl],si + mov word ptr [LBTbl+2],ds + pop si + pop es + pop ds +assume ds:dg +assume es:dg + ENDIF + + +CMD_LINE: + push cs + pop es + ASSUME ES:DG + +;----- Process any options ------------------------------------------; + +;========================================================================= +; The system parser, called through PARSER_COMMAND, parses external +; command lines. In the case of EDLIN we are looking for two parameters +; on the command line. +; +; Parameter 1 - Filespec (REQUIRED) +; Parameter 2 - \B switch (OPTIONAL) +; +; PARSER_COMMAND - exit_normal : ffffh +; exit_error : not = ffffh +;========================================================================= + + + call PARSER_COMMAND ;an000;invoke sysparse + ; DMS:6/11/87 + cmp ax,nrm_parse_exit ;an000;was it a good parse +; $if z ;an000;it was a good parse + JNZ $$IF3 + call EDLIN_COMMAND ;an000;interface results + ; into EDLIN +; $else ;an000; + JMP SHORT $$EN3 +$$IF3: + cmp ax,too_many ;an000;too many operands +; $if z ;an000;we have too many + JNZ $$IF5 + jmp badopt ;an000;say why and exit +; $endif +$$IF5: + + cmp ax,op_missing ;an000;required parm missing +; $if z ;an000;missing parm + JNZ $$IF7 + jmp noname ;an000;say why and exit +; $endif ;an000; +$$IF7: + + cmp ax,sw_missing ;an000;is it an invalid switch +; $if z ;an000;invalid switch + JNZ $$IF9 + jmp badopt ;an000;say why and exit +; $endif ;an000; +$$IF9: + +; $endif ;an000; +$$EN3: + +;========================================================================= +;======================= begin .BAK check ================================ +; Check for .BAK extension on the filename + + push ds ;an000;save reg. + push cs ;an000;set up addressibility + pop ds ;an000; + assume ds:dg ;an000; + + push ax ;an000;save reg. + mov ax,offset dg:path_name ;an000;point to path_name + add ax,[fname_len] ;an000;calculate end of path_name + mov si,ax ;an000;point to end of path_name + pop ax ;an000;restore reg. + + MOV CX,4 ;compare 4 bytes + SUB SI,4 ;Point 4th to last char + MOV DI,OFFSET DG:BAK ;Point to string ".BAK" + REPE CMPSB ;Compare the two strings + pop ds + ASSUME DS:NOTHING + JNZ NOTBAK + JMP HAVBAK + +;======================= end .BAK check ================================== + +;======================= begin NOTBAK ==================================== +; we have a file without a .BAK extension, try to open it + +NOTBAK: + push ds + push cs + pop ds + ASSUME DS:DG + +;========================================================================= +; implement EXTENDED OPEN +;========================================================================= + + push es ;an000;save reg. + mov bx,RW ;an000;open for read/write + mov cx,ATTR ;an000;file attributes + mov dx,RW_FLAG ;an000;action to take on open + mov di,0ffffh ;an000;nul parm list + + call EXT_OPEN1 ;an000;open for R/W;DMS:6/10/87 + pop es ;an000;restore reg. + +;========================================================================= + pop ds + ASSUME DS:NOTHING + JC CHK_OPEN_ERR ;an open error occurred + MOV RD_HANDLE,AX ;Save the handle + + call Calc_Memory_Avail ;an000; dms;enough memory? + + mov bx,RD_Handle ;an000; dms;set up for call + call Query_Extend_Attrib ;an000; dms;memory required? + + cmp dx,cx ;an000; dms;enough memory for EA's? +; $if b ;an000; dms;no + JNB $$IF12 + call EA_Fail_Exit ;an000; dms;say why and exit +; $endif ;an000; dms; +$$IF12: + + mov bx,RD_Handle ;an000; dms;set up for call + mov EA_Flag,True ;an000; dms; + call Get_Extended_Attrib ;an000; dms;get attribs + + Jmp HavFil ;work with the opened file + +;======================= end NOTBAK ====================================== + +Badopt: + MOV DX,OFFSET DG:OPT_ERR_ptr;Bad option specified + JMP XERROR + +;========================================================================= +; +; The open of the file failed. We need to figure out why and report the +; correct message. The circumstances we can handle are: +; +; open returns pathnotfound => bad drive or file name +; open returns toomanyopenfiles => too many open files +; open returns access denied => +; chmod indicates read-only => cannot edit read only file +; else => file creation error +; open returns filenotfound => +; creat ok => close, delete, new file +; creat fails => file creation error +; else => file cre +; + +CHK_OPEN_ERR: + cmp ax,error_path_not_found + jz BadDriveError + cmp ax,error_too_many_open_files + jz TooManyError + cmp ax,error_access_denied + jnz CheckFNF + push ds + push cs + pop ds + assume ds:dg + mov ax,(chmod shl 8) + MOV DX,OFFSET DG:PATH_NAME + int 21h + jc FileCreationError + test cx,attr_read_only + jz FileCreationError + jmp ReadOnlyError + +CheckFNF: + cmp ax,error_file_not_found + jnz FileCreationError +; +; Try to create the file to see if it is OK. +; + push ds + push cs + pop ds + assume ds:dg +;========================================================================= +; implement EXTENDED OPEN +;========================================================================= + + mov bx,RW ;an000;open for read/write + mov cx,ATTR ;an000;file attributes + mov dx,CREAT_FLAG ;an000;action to take on open + mov di,0ffffh ;an000;null parm list + call EXT_OPEN1 ;an000;create file;DMS:6/10/87 + +;========================================================================= + + pop ds + assume ds:nothing + jc CreateCheck + mov bx,ax + mov ah,close + int 21h + push ds + push cs + pop ds + assume ds:dg + mov ah,unlink + MOV DX,OFFSET DG:PATH_NAME + int 21h + pop ds + assume ds:nothing + jc FileCreationError ; This should NEVER be taken!!! + MOV HAVEOF,0FFH ; Flag from a system 1.xx call + MOV fNew,-1 + JMP HAVFIL + +CreateCheck: + cmp ax,error_access_denied + jnz BadDriveError +DiskFull: + MOV DX,OFFSET DG:nodir_ptr + jmp xerror + +FileCreationError: + mov dx,offset dg:BCreat_PTR + jmp xerror + +ReadOnlyError: + MOV DX,OFFSET DG:RO_ERR_ptr + jmp xerror + +BadDriveError: + MOV DX,OFFSET DG:BADDRV_PTR + jmp xerror + +TooManyError: + MOV DX,OFFSET DG:TOO_MANY_ptr + jmp xerror + + +CREAT_ERR: + CMP DELFLG,0 + JNZ DiskFull + push cs + pop ds + CALL DELBAK + JMP MAKFIL + +HAVBAK: + MOV DX,OFFSET DG:NOBAK_ptr + JMP XERROR + +HAVFIL: + push cs + pop ds + ASSUME DS:DG + CMP fNew,0 + JZ MakeBak + MOV DX,OFFSET DG:NEWFIL_ptr ; Print new file message + call std_printf +MakeBak: + MOV SI,OFFSET DG:PATH_NAME + MOV CX,[FNAME_LEN] + PUSH CX + MOV DI,OFFSET DG:TEMP_PATH + REP MOVSB + DEC DI + MOV DX,DI + POP CX + MOV AL,"." + STD + REPNE SCASB + JZ FOUND_EXT + MOV DI,DX ;Point to last char in filename +FOUND_EXT: + CLD + INC DI + MOV [EXT_PTR],DI + MOV SI,OFFSET DG:$$$FILE + MOV CX,5 + REP MOVSB + +;Create .$$$ file to make sure directory has room +MAKFIL: + +;========================================================================= +; implement EXTENDED OPEN +;========================================================================= + + mov bx,RW ;an000;open for read/write + mov cx,ATTR ;an000;file attributes + mov dx,Creat_Open_Flag ;an000;action to take on open + cmp EA_Flag,True ;an000;EA_Buffer used? +; $if e ;an000;yes + JNE $$IF14 + mov di,offset dg:EA_Parm_List ;an000; point to buffer +; $else ;an000; + JMP SHORT $$EN14 +$$IF14: + mov di,0ffffh ;an000;nul parm list +; $endif ;an000; +$$EN14: + call EXT_OPEN2 ;an000;create file;DMS:6/10/87 + +;========================================================================= + + JC CREAT_ERR + MOV [WRT_HANDLE],AX +; +; We determine the size of the available memory. Use the word in the PDB at +; [2] to determine the number of paragraphs. Then truncate this to 64K at +; most. +; + push ds ;save ds for size calc + mov ds,[org_ds] + MOV CX,DS:[2] + MOV DI,CS + SUB CX,DI + CMP CX,1000h + JBE GotSize + MOV CX,0FFFh +GotSize: + SHL CX,1 + SHL CX,1 + SHL CX,1 + SHL CX,1 + pop ds ;restore ds after size calc + DEC CX + MOV [LAST],CX + MOV DI,OFFSET DG:START + TEST fNew,-1 + JNZ SAVEND + SUB CX,OFFSET DG:START ;Available memory + SHR CX,1 ;1/2 of available memory + MOV AX,CX + SHR CX,1 ;1/4 of available memory + MOV [ONE4TH],CX ;Save amount of 1/4 full + ADD CX,AX ;3/4 of available memory + MOV DX,CX + ADD DX,OFFSET DG:START + MOV [THREE4TH],DX ;Save pointer to 3/4 full + MOV DX,OFFSET DG:START +SAVEND: + CLD + MOV BYTE PTR [DI],1AH + MOV [ENDTXT],DI + MOV BYTE PTR [COMBUF],128 + MOV BYTE PTR [EDITBUF],255 + MOV BYTE PTR [EOL],10 + MOV [POINTER],OFFSET DG:START + MOV [CURRENT],1 + MOV ParamCt,1 + MOV [PARAM1],0 ;M004 Leave room in memory, was -1 + TEST fNew,-1 + JNZ COMMAND +; +; The above setting of PARAM1 to -1 causes this call to APPEND to try to read +; in as many lines that will fit, BUT.... What we are doing is simulating +; the user issuing an APPEND command, and if the user asks for more lines +; than we get then an "Insufficient memory" error occurs. In this case we +; DO NOT want this error, we just want as many lines as possible read in. +; The twiddle of ENDING suppresses the memory error +; + MOV BYTE PTR [ENDING],1 ;Suppress memory errors + CALL APPEND + MOV ENDING,0 ; restore correct initial value + +Break
+ +; +; Main read/parse/execute loop. We reset the stack all the time as there +; are routines that JMP back here. Don't blame me; Tim Paterson write this. +; +COMMAND: + push cs ;an000;set up addressibility + pop ds ;an000; + push cs ;an000; + pop es ;an000; + assume ds:dg,es:dg ;an000; + + MOV SP, STACK + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H + MOV DX,OFFSET DG:ABORTCOM + INT 21H + mov dx,offset dg:prompt_ptr + call std_printf + MOV DX,OFFSET DG:COMBUF + MOV AH,STD_CON_STRING_INPUT + INT 21H + MOV [COMLINE],OFFSET DG:COMBUF + 2 + mov dx,offset dg:lf_ptr + call std_printf +PARSE: + MOV [PARAM2],0 + MOV [PARAM3],0 + MOV [PARAM4],0 + mov [fourth],0 ;reset the fourth parameter flag + MOV QFLG,0 + MOV SI,[COMLINE] + MOV BP,OFFSET DG:PARAM1 + XOR DI,DI +CHKLP: + CALL GETNUM +; +; AL has first char after arg +; + MOV ds:[BP+DI],DX + ADD DI,2 + + MOV ParamCt,DI ; set up count of parameters + SHR ParamCt,1 ; convert to index (1-based) + + CALL SKIP1 ; skip to next parameter + CMP AL,"," ; is there a comma? + JZ CHKLP ; if so, then get another arg + DEC SI ; point at char next + CALL Kill_BL ; skip all blanks + CMP AL,"?" ; is there a ? + JNZ DISPATCH ; no, got command letter + MOV QFLG,-1 ; signal query + CALL Kill_BL +DISPATCH: + CMP AL,5FH + JBE UPCASE + cmp al,"z" + ja upcase + AND AL,5FH +UPCASE: + MOV DI,OFFSET DG:COMTAB + MOV CX,NUMCOM + REPNE SCASB + JNZ COMERR + SUB DI,1+OFFSET DG:COMTAB ; convert to index + MOV BX,DI + MOV AX,[PARAM2] + OR AX,AX + JZ PARMOK + CMP AX,[PARAM1] + JB COMERR ; Param. 2 must be >= param 1 +PARMOK: + MOV [COMLINE],SI + SHL BX,1 + CALL [BX+TABLE] +COMOVER: + MOV SI,[COMLINE] + CALL Kill_BL + CMP AL,0DH + JZ COMMANDJ + CMP AL,1AH + JZ DELIM + CMP AL,";" + JNZ NODELIM +DELIM: + INC SI +NODELIM: + DEC SI + MOV [COMLINE],SI + JMP PARSE + +COMMANDJ: + JMP COMMAND + +SKIP1: + DEC SI + CALL Kill_BL +ret1: return + +Break + +; +; People call here. we need to reset the stack. +; Inputs: BX has param1 +; Outputs: Returns if BX <= Param2 +; + +CHKRANGE: + CMP [PARAM2],0 + retz + CMP BX,[PARAM2] + JBE RET1 + POP DX ; clean up return address +COMERR: + MOV DX,OFFSET DG:BADCOM_ptr +COMERR1: + call std_printf + JMP COMMAND + +; +; GetNum parses off 1 argument from the command line. Argument forms are: +; nnn a number < 65536 +; +nnn current line + number +; -nnn current line - number +; . current line +; # lastline + 1 +; +; + +GETNUM: + CALL Kill_BL + cmp di,6 ;Is this the fourth parameter? + jne sk1 + mov [fourth],1 ;yes, set the flag +sk1: + CMP AL,"." + JZ CURLIN + CMP AL,"#" + JZ MAXLIN + CMP AL,"+" + JZ FORLIN + CMP AL,"-" + JZ BACKLIN + MOV DX,0 + MOV CL,0 ;Flag no parameter seen yet +NUMLP: + CMP AL,"0" + JB NUMCHK + CMP AL,"9" + JA NUMCHK + CMP DX,6553 ;Max line/10 + JAE COMERR ;Ten times this is too big + MOV CL,1 ;Parameter digit has been found + SUB AL,"0" + MOV BX,DX + SHL DX,1 + SHL DX,1 + ADD DX,BX + SHL DX,1 + CBW + ADD DX,AX + LODSB + JMP SHORT NUMLP +NUMCHK: + CMP CL,0 + retz + OR DX,DX + JZ COMERR ;Don't allow zero as a parameter + return + +CURLIN: + cmp [fourth],1 ;the fourth parameter? + je comerra ;yes, an error + MOV DX,[CURRENT] + LODSB + return +MAXLIN: + cmp [fourth],1 ;the fourth parameter? + je comerra ;yes, an error + MOV DX,1 + MOV AL,0Ah + PUSH DI + MOV DI,OFFSET DG:START + MOV CX,EndTxt + SUB CX,DI +MLoop: + JCXZ MDone + REPNZ SCASB + JNZ MDone + INC DX + JMP MLoop +MDone: + POP DI + LODSB + return +FORLIN: + cmp [fourth],1 ;the fourth parameter? + je comerra ;yes, an error + CALL GETNUM + ADD DX,[CURRENT] + return +BACKLIN: + cmp [fourth],1 ;the fourth parameter? + je comerra ;yes, an error + CALL GETNUM + MOV BX,[CURRENT] + SUB BX,DX + JA OkLin ; if negative or zero + MOV BX,1 ; use first line +OkLin: + MOV DX,BX + return + +comerra: + jmp comerr + +Break + +;-----------------------------------------------------------------------; +; Careful changing the order of the next two tables. They are linked and +; changes should be be to both. + +COMTAB DB 13,";ACDEILMPQRSTW" +NUMCOM EQU $-COMTAB + +TABLE DW NOCOM ; Blank line + DW NOCOM ; ; + DW APPEND ; A(ppend) + DW COPY ; C(opy) + DW DELETE ; D(elete) + DW ENDED ; E(xit) + DW INSERT ; I(nsert) + DW LIST ; L(ist) + DW MOVE ; M(ove) + DW PAGER ; P(age) + DW QUIT ; Q(uit) + dw replac_from_curr ; R(eplace) + dw search_from_curr ; S(earch) + DW MERGE ; T(merge) + DW EWRITE ; W(rite) + +ERRORJ: + JMP COMERR +ERROR1J: + JMP COMERR1 + +Break + +PUBLIC MOVE +MOVE: + CMP ParamCt,3 + JNZ ERRORJ + MOV BYTE PTR [MOVFLG],1 + JMP SHORT BLKMOVE + +PUBLIC COPY +COPY: + CMP ParamCt,3 + JB ERRORJ + MOV BYTE PTR [MOVFLG],0 +; +; We are to move/copy a number of lines from one range to another. +; +; Memory looks like this: +; +; START: line 1 +; ... +; pointer-> line n Current has n in it +; ... +; line m +; endtxt-> ^Z +; +; The algoritm is: +; +; Bounds check on args. +; set ptr1 and ptr2 to range before move +; set copysiz to number to move +; open up copysize * count for destination +; if destination is before ptr1 then +; add copysize * count to both ptrs +; while count > 0 do +; move from ptr1 to destination for copysize bytes +; count -- +; if moving then +; move from ptr2 through end to ptr1 +; set endtxt to last byte moved. +; set current, pointer to original destination +; + +BLKMOVE: +; +; Make sure that all correct arguments are specified. +; + MOV BX,[PARAM3] ; get destination of move/copy + OR BX,BX ; must be specified (non-0) + MOV DX,OFFSET DG:DEST_ptr + JZ ERROR1J ; is 0 => error +; +; get arg 1 (defaulting if necessary) and range check it. +; + MOV BX,[PARAM1] ; get first argument + OR BX,BX ; do we default it? + JNZ NXTARG ; no, assume it is OK. + MOV BX,[CURRENT] ; Defaults to the current line + CALL CHKRANGE ; Make sure it is good. + MOV [PARAM1],BX ; set it +NXTARG: + CALL FINDLIN ; find first argument line + JNZ ErrorJ ; line not found + MOV [PTR_1],DI +; +; get arg 2 (defaulting if necessary) and range check it. +; + MOV BX,[PARAM2] ; Get the second parameter + OR BX,BX ; do we default it too? + JNZ HAVARGS ; Nope. + MOV BX,[CURRENT] ; Defaults to the current line + MOV [PARAM2],BX ; Stash it away +HAVARGS: + CALL FindLin + JNZ ErrorJ ; line not found + MOV BX,Param2 + INC BX ;Get pointer to line Param2+1 + CALL FINDLIN + MOV [PTR_2],DI ;Save it +; +; We now have true line number arguments and pointers to the relevant places. +; ptr_1 points to beginning of region and ptr_2 points to first byte beyond +; that region. +; +; Check args for correct ordering of first two arguments +; + mov dx,[param1] + cmp dx,[param2] + jbe havargs1 ; first must be <= second + jmp comerr +havargs1: +; +; make sure that the third argument is not contained in the first range +; + MOV DX,[PARAM3] + CMP DX,[PARAM1] ; third must be <= first or + JBE NOERROR + CMP DX,[PARAM2] + JA NoError ; third must be > last + JMP ComErr +NOERROR: +; +; Determine number to move +; + MOV CX,Ptr_2 + SUB CX,Ptr_1 ; Calculate number of bytes to copy + MOV CopySiz,CX + MOV CopyLen,CX ; Save for individual move. + MOV AX,[PARAM4] ; Was count defaulted? + OR AX,AX + JZ SizeOk ; yes, CX has correct value + MUL [COPYSIZ] ; convert to true size + MOV CX,AX ; move to count register + OR DX,DX ; overflow? + JZ SizeOK ; no + JMP MEMERR ; yes, bomb. +SizeOK: + MOV [COPYSIZ],CX +; +; Check to see that we have room to grow by copysiz +; + MOV AX,[ENDTXT] ; get pointer to last byte + MOV DI,[LAST] ; get offset of last location in memory + SUB DI,AX ; remainder of space + CMP DI,CX ; is there at least copysiz room? + JAE HAV_ROOM ; yes + JMP MEMERR +HAV_ROOM: +; +; Find destination of move/copy +; + MOV BX,[PARAM3] + CALL FINDLIN + MOV [PTR_3],DI +; +; open up copysiz bytes of space at destination +; +; move (p3, p3+copysiz, endtxt-p3); +; + MOV SI,EndTxt ; get source pointer to end + MOV CX,SI + SUB CX,DI ; number of bytes from here to end + INC CX ; remember ^Z at end + MOV DI,SI ; destination starts at end + ADD DI,[COPYSIZ] ; plus size we are opening + MOV [ENDTXT],DI ; new end point + STD ; go backwards + REP MOVSB ; and store everything + CLD ; go forward +; +; relocate ptr_1 and ptr_2 if we moved them +; + MOV BX,Ptr_3 + CMP BX,Ptr_1 ; was dest before source? + JA NoReloc ; no, above. no relocation + MOV BX,CopySiz + ADD Ptr_1,BX + ADD Ptr_2,BX ; relocate pointers +NoReloc: +; +; Now we copy for count times copylen bytes from ptr_1 to ptr_3 +; +; move (ptr_1, ptr_3, copylen); +; + MOV BX,Param4 ; count (0 and 1 are both 1) + MOV DI,Ptr_3 ; destination +CopyText: + MOV CX,CopyLen ; number to move + MOV SI,Ptr_1 ; start point + REP MOVSB ; move the bytes + SUB BX,1 ; exhaust count? + JG CopyText ; no, go for more +; +; If we are moving +; + CMP BYTE PTR MovFlg,0 + JZ CopyDone +; +; Delete the source text between ptr_1 and ptr_2 +; +; move (ptr_2, ptr_1, endtxt-ptr_2); +; + MOV DI,Ptr_1 ; destination + MOV SI,Ptr_2 ; source + MOV CX,EndTxt ; pointer to end + SUB CX,SI ; number of bytes to move + CLD ; forwards + REP MOVSB + MOV BYTE PTR ES:[DI],1Ah ; remember ^Z terminate + MOV EndTxt,DI ; new end of file +; +; May need to relocate current line (parameter 3). +; + MOV BX,Param3 ; get new current line + CMP BX,Param1 ; do we need to relocate + JBE CopyDone ; no, current line is before removed M002 + ADD BX,Param1 ; add in first + SUB BX,Param2 ; current += first-last - 1; + DEC BX + MOV Param3,BX +CopyDone: +; +; we are done. Make current line the destination +; + MOV BX,Param3 ; set parameter 3 to be current + CALL FINDLIN + MOV [POINTER],DI + MOV [CURRENT],BX + return + +Break + +; +; MoveFile moves the text in the buffer to create a hole +; +; Inputs: DX is spot in buffer for destination +; DI is spot in buffer for source +MOVEFILE: + MOV CX,[ENDTXT] ;Get End-of-text marker + MOV SI,CX + SUB CX,DI ;Calculate number of bytes to copy + INC CX ; remember ^Z + MOV DI,DX + STD + REP MOVSB ;Copy CX bytes + XCHG SI,DI + CLD + INC DI + MOV BP,SI +SETPTS: + MOV [POINTER],DI ;Current line is first free loc + MOV [CURRENT],BX ; in the file + MOV [ENDTXT],BP ;End-of-text is last free loc before + return + +NAMERR: + cmp ax,error_file_not_found + jne otherMergeErr + MOV DX,OFFSET DG:FILENM_ptr + JMP COMERR1 + +otherMergeErr: + MOV DX,OFFSET DG:BADDRV_ptr + JMP COMERR1 + +PUBLIC MERGE +MERGE: + CMP ParamCt,1 + JZ MergeOK + JMP Comerr +MergeOK: + CALL KILL_BL + DEC SI + MOV DI,OFFSET DG:MRG_PATH_NAME + XOR CX,CX + CLD +MRG1: + LODSB + CMP AL," " + JE MRG2 + CMP AL,9 + JE MRG2 + CMP AL,CR + JE MRG2 + CMP AL,";" + JE MRG2 + STOSB + JMP SHORT MRG1 +MRG2: + MOV BYTE PTR[DI],0 + DEC SI + MOV [COMLINE],SI + +;========================================================================= +; implement EXTENDED OPEN +;========================================================================= + + push es ;an000;save reg. + mov bx,ext_read ;an000;open for read + mov cx,ATTR ;an000;file attributes + mov dx,OPEN_FLAG ;an000;action to take on open + mov di,0ffffh ;an000;null parm list + call EXT_OPEN3 ;an000;create file;DMS:6/10/87 + pop es ;an000;restore reg. + +;========================================================================= + + JC NAMERR + + MOV [MRG_HANDLE],AX + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H + MOV DX,OFFSET DG:ABORTMERGE + INT 21H + MOV BX,[PARAM1] + OR BX,BX + JNZ MRG + MOV BX,[CURRENT] + CALL CHKRANGE +MRG: + CALL FINDLIN + MOV BX,DX + MOV DX,[LAST] + CALL MOVEFILE + MOV DX,[POINTER] + MOV CX,[ENDTXT] + SUB CX,[POINTER] + PUSH CX + MOV BX,[MRG_HANDLE] + MOV AH,READ + INT 21H + POP DX + MOV CX,AX + CMP DX,CX + JA FILEMRG ; M005 + MOV DX,OFFSET DG:MRGERR_ptr + call std_printf + MOV CX,[POINTER] + JMP SHORT RESTORE +FILEMRG: + ADD CX,[POINTER] + MOV SI,CX + dec si + LODSB + CMP AL,1AH + JNZ RESTORE + dec cx +RESTORE: + MOV DI,CX + MOV SI,[ENDTXT] + INC SI + MOV CX,[LAST] + SUB CX,SI + inc cx ; remember ^Z + REP MOVSB + dec di ; unremember ^Z + MOV [ENDTXT],DI + MOV BX,[MRG_HANDLE] + MOV AH,CLOSE + INT 21H + return + +PUBLIC INSERT +INSERT: + CMP ParamCt,1 + JBE OKIns + JMP ComErr +OKIns: + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ;Set vector 23H + MOV DX,OFFSET DG:ABORTINS + INT 21H + MOV BX,[PARAM1] + OR BX,BX + JNZ INS + MOV BX,[CURRENT] + CALL CHKRANGE +INS: + CALL FINDLIN + MOV BX,DX + MOV DX,[LAST] + CALL MOVEFILE +INLP: + CALL SETPTS ;Update the pointers into file + CALL SHOWNUM + MOV DX,OFFSET DG:EDITBUF + MOV AH,STD_CON_STRING_INPUT + INT 21H + CALL LF + MOV SI,2 + OFFSET DG:EDITBUF + CMP BYTE PTR [SI],1AH + JZ ENDINS +;----------------------------------------------------------------------- + call unquote ;scan for quote chars if any +;----------------------------------------------------------------------- + MOV CL,[SI-1] + MOV CH,0 + MOV DX,DI + INC CX + ADD DX,CX + JC MEMERRJ1 + JZ MEMERRJ1 + CMP DX,BP + JB MEMOK +MEMERRJ1: + CALL END_INS + JMP MEMERR +MEMOK: + REP MOVSB + MOV AL,10 + STOSB + INC BX + JMP SHORT INLP + +ABORTMERGE: + MOV DX,OFFSET DG:START + MOV AH,SET_DMA + INT 21H + +ABORTINS: + MOV AX,CS ;Restore segment registers + MOV DS,AX + MOV ES,AX + MOV AX,CSTACK + MOV SS,AX + MOV SP,STACK + STI + CALL CRLF + CALL ENDINS + JMP COMOVER + +ENDINS: + CALL END_INS + return + +END_INS: + MOV BP,[ENDTXT] + MOV DI,[POINTER] + MOV SI,BP + INC SI + MOV CX,[LAST] + SUB CX,BP + REP MOVSB + DEC DI + MOV [ENDTXT],DI + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H + MOV DX,OFFSET DG:ABORTCOM + INT 21H + return + + +FILLBUF: + MOV [PARAM1],-1 ;Read in max. no of lines + MOV ParamCt,1 + CALL APPEND + MOV Param1,0 +PUBLIC ENDED +ENDED: + +;Write text out to .$$$ file + + CMP ParamCt,1 + JZ ENDED1 +CERR: JMP ComErr +Ended1: + CMP Param1,0 + JNZ Cerr + MOV BYTE PTR [ENDING],1 ;Suppress memory errors + MOV BX,-1 ;Write max. no of lines + CALL WRT + TEST BYTE PTR [HAVEOF],-1 + JZ FILLBUF + MOV DX,[ENDTXT] + MOV CX,1 + MOV BX,[WRT_HANDLE] + MOV AH,WRITE + INT 21H ;Write end-of-file byte + +;Close input file ; MZ 11/30 + ; MZ 11/30 + MOV BX,[RD_HANDLE] ; MZ 11/30 + MOV AH,CLOSE ; MZ 11/30 + INT 21H ; MZ 11/30 + +;Close .$$$ file + + MOV BX,[WRT_HANDLE] + MOV AH,CLOSE + INT 21H + +;Rename original file .BAK + + MOV DI,[EXT_PTR] + MOV SI,OFFSET DG:BAK + MOVSW + MOVSW + MOVSB + MOV DX,OFFSET DG:PATH_NAME + MOV DI,OFFSET DG:TEMP_PATH + MOV AH,RENAME + INT 21H + MOV DI,[EXT_PTR] + MOV SI,OFFSET DG:$$$FILE + MOVSW + MOVSW + MOVSB + +;Rename .$$$ file to original name + + MOV DX,OFFSET DG:TEMP_PATH + MOV DI,OFFSET DG:PATH_NAME + MOV AH,RENAME + INT 21H + ; mode + mov ah,exit + xor al,al + int 21h + +;========================================================================= +; EDLIN_DISP_GET: This routine will give us the attributes of the +; current display, which are to be used to restore the screen +; back to its original state on exit from EDLIN. We also +; set the screen to a text mode here with an 80 X 25 color +; format. +; +; Inputs : VIDEO_GET - 0fH (get current video mode) +; VIDEO_SET - 00h (set video mode) +; VIDEO_TEXT- 03h (80 X 25 color mode) +; +; Outputs : VIDEO_ORG - Original video attributes on entry to EDLIN +; +;========================================================================= + +EDLIN_DISP_GET proc near ;an000;video attributes + + push ax ;an000;save affected regs. + push bx ;an000; + push cx ;an000; + push dx ;an000; + push si ;an000; + push ds ;an000; + + push cs ;an000;exchange cs/ds + pop ds ;an000; + + mov ax,440Ch ;an000;generic ioctl + mov bx,Std_Out ;an000;Console + mov cx,(Display_Attr shl 8) or Get_Display ;an000;get display + mov dx,offset dg:Video_Buffer ;an000;buffer for video attr. + int 21h ;an000; +; $if nc ;an000;function returned a + JC $$IF17 + ; buffer + mov si,dx ;an000;get pointer + mov ax,word ptr dg:[si].Display_Length_Char ;an000;get video len. + dec ax ;an000;allow room for message + mov dg:Disp_Len,al ;an000;put it into var. + mov ax,word ptr dg:[si].Display_Width_Char ;an000;get video width + mov dg:Disp_Width,al ;an000;put it into var. +; $else ;an000;function failed use + JMP SHORT $$EN17 +$$IF17: + ; default values + mov al,Def_Disp_Len ;an000;get default length + dec al ;an000;leave room for messages + mov dg:Disp_Len,al ;an000;use default length + mov dg:Disp_Width,Def_Disp_Width;an000;use default width +; $endif ;an000; +$$EN17: + + pop ds ;an000;restore affected regs. + pop si ;an000; + pop dx ;an000; + pop cx ;an000; + pop bx ;an000; + pop ax ;an000; + + ret ;an000;return to caller + +EDLIN_DISP_GET endp ;an000;end proc. + + +;========================================================================= +; EXT_OPEN1 : This routine opens a file for read/write access. If the file +; if not present for opening the open will fail and return with a +; carry set. +; +; Inputs : BX - Open mode +; CX - File attributes +; DX - Open action +; +; Outputs: CY - If error +; +; Date : 6/10/87 +;========================================================================= + +EXT_OPEN1 proc near ;an000;open for R/W + + assume ds:dg + push ds ;an000;save regs + push si ;an000; + + mov ah,ExtOpen ;an000;extended open + mov al,0 ;an000;reserved by system + mov si,offset dg:path_name ;an000;point to PATH_NAME + + int 21h ;an000;invoke function + pop si ;an000;restore regs + pop ds ;an000; + + ret ;an000;return to caller + +EXT_OPEN1 endp ;an000;end proc. + +;========================================================================= +; EXT_OPEN2 : This routine will attempt to create a file for read/write +; access. If the files exists the create will fail and return +; with the carry set. +; +; Inputs : BX - Open mode +; CX - File attributes +; DX - Open action +; +; Outputs: CY - If error +; +; Date : 6/10/87 +;========================================================================= + +EXT_OPEN2 proc near ;an000;create a file + + assume ds:dg + push ds ;an000;save regs + push si ;an000; + + mov ah,ExtOpen ;an000;extended open + mov al,0 ;an000;reserved by system + mov si,offset dg:temp_path ;an000;point to TEMP_PATH + + int 21h ;an000;invoke function + + pop si ;an000;restore regs + pop ds ;an000; + + ret ;an000;return to caller + +EXT_OPEN2 endp ;an000;end proc. + +;========================================================================= +; EXT_OPEN3 : This routine will attempt to create a file for read +; access. If the files exists the create will fail and return +; with the carry set. +; +; Inputs : BX - Open mode +; CX - File attributes +; DX - Open action +; +; Outputs: CY - If error +; +; Date : 6/10/87 +;========================================================================= + +EXT_OPEN3 proc near ;an000;create a file + + assume ds:dg + push ds ;an000;save regs + push si ;an000; + + mov ah,ExtOpen ;an000;extended open + mov al,0 ;an000;reserved by system + mov si,offset dg:mrg_path_name ;an000;point to mrg_path_name + + int 21h ;an000;invoke function + + pop si ;an000;restore regs + pop ds ;an000; + + ret ;an000;return to caller + +EXT_OPEN3 endp ;an000;end proc. + + +;========================================================================= +; EDLIN_COMMAND : This routine provides an interface between the new +; parser and the existing logic of EDLIN. We will be +; interfacing the parser with three existing variables. +; +; Inputs : FILESPEC - Filespec entered by the user and passed by +; the parser. +; +; PARSE_SWITCH_B - Contains the result of the parse for the +; /B switch. This is passed by the parser. +; +; Outputs: PATH_NAME - Filespec +; LOADMOD - Flag for /B switch +; FNAME_LEN - Length of filespec +; +; Date : 6/11/87 +;========================================================================= + +EDLIN_COMMAND proc near ;an000;interface parser + + push ax ;an000;save regs. + push cx ;an000; + push di ;an000 + push si ;an000; + + mov si,offset dg:filespec ;an000;get its offset + mov di,offset dg:path_name ;an000;get its offset + + mov cx,00h ;an000;cx will count filespec + ; length + cmp parse_switch_b,true ;an000;do we have /B switch +; $if z ;an000;we have the switch + JNZ $$IF20 + mov [LOADMOD],01h ;an000;signal switch found +; $endif ;an000 +$$IF20: + +; $do ;an000;while we have filespec +$$DO22: + lodsb ;an000;move byte to al + cmp al,nul ;an000;see if we are at + ; the end of the + ; filespec +; $leave e ;an000;exit while loop + JE $$EN22 + stosb ;an000;move byte to path_name + inc cx ;an000;increment the length + ; of the filespec +; $enddo ;an000;end do while + JMP SHORT $$DO22 +$$EN22: + + mov [FNAME_LEN],cx ;an000;save filespec's length + + pop si ;an000; restore regs + pop di ;an000; + pop cx ;an000; + pop ax ;an000; + + ret ;an000;return to caller + +EDLIN_COMMAND endp ;an000;end proc + +;========================================================================= +; Get_Extended_Attrib : This routine gets the extended attributes of +; the file that was opened. +; +;========================================================================= + +Get_Extended_Attrib proc near ;an000; dms; + + mov ax,5702h ;an000; dms;get extended attrib + mov si,0ffffh ;an000; dms;all attribs + mov cx,dg:EA_Buffer_Size ;an000; dms;buffer size + mov di,offset dg:Start ;an000; dms;point to buffer + int 21h ;an000; dms; + ret ;an000; dms; + +Get_Extended_Attrib endp ;an000; dms; + + +;========================================================================= +; Query_Extend_Attrib : This routine gets the extended attributes of +; the file that was opened. +; +; Inputs : Start - Buffer for extended attributes +; +; Outputs : CX - size in paras +; +;========================================================================= + +Query_Extend_Attrib proc near ;an000; dms; + + mov ax,5702h ;an000; dms;get extended attrib + mov si,0ffffh ;an000; dms;all attribs + mov cx,0000h ;an000; dms;get buffer size + mov di,offset dg:Start ;an000; dms;point to buffer + int 21h ;an000; dms; + mov dg:EA_Buffer_Size,cx ;an000; dms;save buffer size + ret ;an000; dms; + +Query_Extend_Attrib endp ;an000; dms; + + +;========================================================================= +; Calc_Memory_Avail : This routine will calculate the memory +; available for use by EDLIN. +; +; Inputs : ORG_DS - DS of PSP +; +; Outputs : DX - paras available +;========================================================================= + +Calc_Memory_Avail proc near ;an000; dms; + + push ds ;save ds for size calc + push cx ;an000; dms; + push di ;an000; dms; + + mov ds,cs:[org_ds] + MOV CX,DS:[2] + MOV DI,CS + SUB CX,DI + mov dx,cx ;an000; dms;put paras in DX + + pop di ;an000; dms; + pop cx ;an000; dms; + pop ds ;an000; dms; + + ret ;an000; dms; + +Calc_Memory_Avail endp ;an000; dms; + +;========================================================================= +; EA_Fail_Exit : This routine tells the user that there was +; Insufficient memory and exits EDLIN. +; +; Inputs : MemFul_Ptr - "Insufficient memory" +; +; Outputs : message +;========================================================================= + +EA_Fail_Exit proc near ;an000; dms; + + mov dx,offset dg:MemFul_Ptr ;an000; dms;"Insufficient + + push cs ;an000; dms;xchange ds/cs + pop ds ;an000; dms; + ; memory" + call Std_Printf ;an000; dms;print message + mov ah,exit ;an000; dms;exit + xor al,al ;an000; dms;clear al + int 21h ;an000; dms; + ret ;an000; dms; + +EA_Fail_Exit endp ;an000; dms; + +CODE ENDS + END EDLIN + + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLIN.LNK b/v4.0/src/CMD/EDLIN/EDLIN.LNK new file mode 100644 index 0000000..8b90da5 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLIN.LNK @@ -0,0 +1,7 @@ +EDLIN+ +EDLCMD1+ +EDLCMD2+ +EDLMES+ +EDLPARSE +EDLIN.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLIN.SKL b/v4.0/src/CMD/EDLIN/EDLIN.SKL new file mode 100644 index 0000000..ff5109e --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLIN.SKL @@ -0,0 +1,75 @@ +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLMES.FIL +; +; DESCRIPTIVE NAME: EDLIN MESSAGES +; +; FUNCTION: PROVIDES A SET OF MESSAGES FOR EDLIN. +; +; ENTRY POINT: NA +; +; INPUT: NA +; +; EXIT NORMAL: NA +; +; EXIT ERROR: NA +; +; INTERNAL REFERENCES: NA +; +; EXTERNAL REFERENCES: NA +; +; +; NOTES: THIS MODULE IS TO BE PREPPED BY FASTBLD.EXE. +; +; REVISION HISTORY: +; +; VERSION 4.00 - CREATED FOR DOS 4.00 +; +;======================= END OF SPECIFICATIONS =========================== + +;========================================================================= +; edlin utility message file +;========================================================================= + +:util EDLIN ;utility name +:class 1 + +:class A ;system messages +:use 1 COMMON1 ;"Incorrect DOS version",CR,LF +:use 2 COMMON2 ;"Insufficient memory",CR,LF +:use 3 COMMON3 ;"Error loading messages",CR,LF + +:class B ;utility messages +:def 6 "*" ;prompt_ptr +:def 7 "Invalid drive or file name",CR,LF ;baddrv_ptr +:def 8 "File name must be specified",CR,LF ;ndname_ptr +:def 10 "File is READ-ONLY",CR,LF ;ro_err_ptr +:def 11 "File Creation Error",CR,LF ;bcreat_ptr +:def 12 "Too many files open",CR,LF ;too_many_ptr +:def 13 "Read error in:",CR,LF,"%1",CR,LF ;read_err_ptr +:def 14 "Cannot edit .BAK file--rename file",CR,LF ;nobak_ptr +:def 15 "No room in directory for file",CR,LF ;nodir_ptr +:def 16 "Disk full. Edits lost.",CR,LF ;dskful_ptr +:def 18 "Entry error",CR,LF ;badcom_ptr +:def 19 "New file",CR,LF ;newfil_ptr +:def 20 "Not found",CR,LF ;nosuch_ptr + +:class C ;utility messages +:def 21 "O.K.? " ;ask_ptr +:def 22 "Line too long",CR,LF ;toolng_ptr +:def 23 "End of input file",CR,LF ;eof_ptr +:def 24 "Abort edit (Y/N)? " ;qmes_ptr +:def 25 "Must specify destination line number",CR,LF ;dest_ptr +:def 26 "Not enough room to merge the entire file",CR,LF ;mrgerr_ptr +:def 27 CR,LF ;crlf_ptr +:def 28 LF ;lf_ptr +:def 29 "Continue (Y/N)?" ;cont_ptr +:def 30 "Unable to print message",CR,LF ;fatal_error +:def 31 "%1" ;arg_buf_ptr +:def 32 "%1:%2" ;line_num_buf_ptr +:def 33 "Cannot merge - Code page mismatch",CR,LF ;cp_err_ptr + +:end + +;========================================================================= +;========================================================================= diff --git a/v4.0/src/CMD/EDLIN/EDLMES.ASM b/v4.0/src/CMD/EDLIN/EDLMES.ASM new file mode 100644 index 0000000..889a044 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLMES.ASM @@ -0,0 +1,665 @@ + PAGE 60,132; + title EDLIN Messages +;======================= START OF SPECIFICATIONS ========================= +; +; MODULE NAME: EDLMES.SAL +; +; DESCRIPTIVE NAME: MESSAGE RETRIEVER INTERFACE MODULE +; +; FUNCTION: THIS MODULE PROVIDES AN INTERFACE FOR THE MODULES THAT ARE +; NEEDED TO INVOKE THE MESSAGE RETRIEVER. +; +; ENTRY POINT: PRINTF +; +; INPUT: OFFSET CARRIED IN DX TO APPLICABLE MESSAGE TABLE +; +; EXIT NORMAL: NO CARRY +; +; EXIT ERROR : CARRY +; +; INTERNAL REFERENCES: +; +; ROUTINE: PRINTF - PROVIDES THE ORIGINAL INTERFACE FOR THE ORIGINAL +; PRINTF USED PRIOR TO VERSION 4.00. PRINTS MESSAGES. +; +; DISP_MESSAGE - BUILDS THE REGISTERS NECESSARY FOR INVOCATION +; OF THE MESSAGE RETRIEVER, BASED ON THE TABLE +; POINTED TO BY DX. +; +; DISP_FATAL - INVOKED IF AN ERROR OCCURS (CARRY) IN THE +; MESSAGE RETRIEVER. IT DISPLAYS THE APPROPRIATE +; MESSAGE. +; +; EXTERNAL REFERENCES: +; +; ROUTINE: SYSLOADMSG - LOAD MESSAGES FOR THE MESSAGE RETRIEVER +; SYSDISPMSG - DISPLAYS THE REQUESTED MESSAGE +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; REVISION HISTORY: +; +; AN000 VERSION DOS 4.00 - IMPLEMENTATION OF MESSAGE RETRIEVER +; +; COPYRIGHT: "MS DOS EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft" +; "LICENSED MATERIAL - PROPERTY OF Microsoft " +; +; MICROSOFT REVISION HISTORY +; +; MODIFIED BY: AARON R +; M.A. U +; N. P +;======================= END OF SPECIFICATIONS =========================== + +.xlist + +include sysmsg.inc ;an000;message retriever + +msg_utilname ;an000;EDLIN messages +.list +;-----------------------------------------------------------------------; +; ; +; Done for Vers 2.00 (rev 9) by Aaron R ; +; Update for rev. 11 by M.A. U ; +; Printf for 2.5 by Nancy P ; +; ; +;-----------------------------------------------------------------------; + +;========================================================================= +; revised edlmes.asm +;========================================================================= + +fatal_error equ 30 ;an000;fatal message handler +unlim_width equ 00h ;an000;unlimited output width +pad_blank equ 20h ;an000;blank pad +pre_load equ 00h ;an000;normal pre-load + + + +message_table struc ;an000;struc for message table + + entry1 dw 0 ;an000;message number + entry2 db 0 ;an000;message type + entry3 dw 0 ;an000;display handle + entry4 dw 0 ;an000;pointer to sublist + entry5 dw 0 ;an000;substitution count + entry6 db 0 ;an000;use keyb input? + entry7 dw 0 ;an000;keyb buffer to use + +message_table ends ;an000;end struc + +;========================================================================= +; macro disp_message: this macro takes a pointer to a message table +; and displays the applicable message based on +; the table's contents. +; this is to provide an interface into the module +; of the message retriever, SYSDISPMSG. +; +; Date : 6/11/87 +;========================================================================= + +disp_message macro tbl ;an000;display message macro + + push bx ;an000; + push cx ;an000; + push dx ;an000; + push di ;an000; + push si ;an000; + + push tbl ;an000;exchange tbl with si + pop si ;an000;exchanged + + mov ax,[si].entry1 ;an000;move message number + mov bx,[si].entry3 ;an000;display handle + mov cx,[si].entry5 ;an000;number of subs + mov dl,[si].entry6 ;an000;function type + mov di,[si].entry7 ;an000;input buffer if appl. + mov dh,[si].entry2 ;an000;message type + mov si,[si].entry4 ;an000;sublist + + call sysdispmsg ;an000;display the message + + pop si ;an000;restore affected regs + pop di ;an000; + pop dx ;an000; + pop cx ;an000; + pop bx ;an000; + +endm ;an000;end macro disp_message + +;========================================================================= +; macro disp_message: end macro +;========================================================================= + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC BYTE + + extrn path_name:byte + +DATA ENDS + +DG GROUP CODE,CONST,cstack,DATA + +code segment public byte ;an000;code segment + assume cs:dg,ds:dg,es:dg,ss:CStack ;an000; + + public printf ;an000;share printf + public disp_fatal ;an000;fatal error display + public pre_load_message ;an000;message loader + +.xlist +msg_services ;an000; +.list + +;======================= sysmsg.inc invocation =========================== +; +; include sysmsg.inc - message retriever services +; +; +; options selected: +; NEARmsg +; DISPLAYmsg +; LOADmsg +; CHARmsg +; NUMmsg +; CLSAmsg +; CLSBmsg +; CLSCmsg +; +;========================================================================= + +.xlist + + msg_services ;an000;no version check + msg_services ;an000;display messages + msg_services ;an000;message types + msg_services ;an000;message types + msg_services ;an000; + +.list + +;========================================================================= +; printf: printf is a replacement of the printf procedure used in DOS +; releases prior to 4.00. printf invokes the macro disp_message +; to display a message through the new message handler. the +; interface into printf will continue to be a pointer to a message +; passed in DX. the pointer is pointing to more than a message +; now. it is pointing to a table for that message containing +; all relevant information for printing the message. the macro +; disp_message operates on these tables. +; +; Date : 6/11/87 +;========================================================================= + +printf proc near ;an000;printf procedure + + disp_message dx ;an000;display a message +; $if c ;an000;if an error occurred + JNC $$IF1 + call disp_fatal ;an000;display the fatal error +; $endif ;an000; +$$IF1: + + ret ;an000;return to caller + +printf endp ;an000;end printf proc + + +;========================================================================= +; disp_fatal: this routine displays a fatal error message in the event +; an error occurred in disp_message. +; +; Date : 6/11/87 +;========================================================================= + +disp_fatal proc near ;an000;fatal error message + + mov ax,fatal_error ;an000;fatal_error number + mov bx,stdout ;an000;print to console + mov cx,0 ;an000;no parameters + mov dl,no_input ;an000;no keyboard input + mov dh,UTILITY_MSG_CLASS ;an000;utility messages + + call sysdispmsg ;an000;display fatal error + + ret ;an000;return to caller + +disp_fatal endp ;an000;end disp_fatal proc + +;========================================================================= +; PRE_LOAD_MESSAGE : This routine provides access to the messages required +; by EDLIN. This routine will report if the load was +; successful. An unsuccessful load will cause EDLIN +; to terminate with an appropriate error message. +; +; Date : 6/11/87 +;========================================================================= + +PRE_LOAD_MESSAGE proc near ;an000;pre-load messages + + + call SYSLOADMSG ;an000;invoke loader + +; $if c ;an000;if an error + JNC $$IF3 + pushf ;an000;save flags + call SYSDISPMSG ;an000;let him say why + popf ;an000;restore flags +; $endif ;an000; +$$IF3: + + ret ;an000;return to caller + +PRE_LOAD_MESSAGE endp ;an000;end proc + +include msgdcl.inc + +code ends ;an000;end code segment + + + + +CONST SEGMENT PUBLIC BYTE + + extrn arg_buf:byte ;an000; + extrn line_num:byte ;an000; + extrn line_flag:byte ;an000; + extrn Temp_Path:byte ;an000; + + public baddrv_ptr,bad_vers_err,opt_err_ptr,nobak_ptr + public too_many_ptr,dskful_ptr,memful_ptr,badcom_ptr + public nodir_ptr,filenm_ptr,newfil_ptr,read_err_ptr + public nosuch_ptr,toolng_ptr,eof_ptr,dest_ptr + public mrgerr_ptr,ro_err_ptr,bcreat_ptr,ndname_ptr + public ask_ptr,qmes_ptr,crlf_ptr,lf_ptr,yes_byte + public prompt_ptr + public line_num_buf_ptr ;an000;DMS:6/15/87 + public arg_buf_ptr ;an000;DMS:6/15/87 + public cont_ptr ;an000;DMS:6/18/87 + public cp_err_ptr ;an000;DMS:6/22/87 + public Del_Bak_Ptr ;an000;dms; + + yes_byte db "y" + +;============== REPLACEABLE PARAMETER SUBLIST STRUCTURE ================== +; +; byte 1 - substitution list size, always 11 +; byte 2 - reserved for use by message handler +; byte 3 - pointer to parameter to be used as a substitution +; byte 7 - which parameter is this to replace, %1, %2, etc. +; byte 8 - determines how the parameter is to be output +; byte 9 - determines the maximum width of the parameter string +; byte 10 - determines the minimum width of the parameter string +; byte 11 - define what is to be used as a pad character +; +;========================================================================= + +;========================================================================= +; replaceable parameter sublists +;========================================================================= + +ed_read_sub label dword ;an000;a read error occurred + + db 11 ;an000;sublist size + db 00 ;an000;reserved + dd dg:path_name ;an000;pointer to parameter + db 01 ;an000;parm 1 + db Char_Field_ASCIIZ ;an000;left align/asciiz/char. + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width of 0 + db pad_blank ;an000;pad with blanks + +arg_sub label dword ;an000;line output buffer + + db 11 ;an000;sublist size + db 00 ;an000;reserved + dd dg:arg_buf ;an000;pointer to parameter + db 01 ;an000;parm 1 + db Char_Field_ASCIIZ ;an000;left align/asciiz/char. + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width of 0 + db pad_blank ;an000;pad with blank + +num_sub label dword ;an000;line number + + db 11 ;an000;sublist size + db 00 ;an000;reserved + dd dg:line_num ;an000;pointer to parameter + db 01 ;an000;parm 1 + db Right_Align+Unsgn_Bin_Word ;an000;right align/decimal + db 08 ;an000;maximum width + db 08 ;an000;minimum width of 0 + db pad_blank ;an000;pad with blank + + db 11 ;an000;optional flag + db 00 ;an000;reserved + dd dg:line_flag ;an000;pointer to parameter + db 02 ;an000;parm 2 + db Char_Field_Char ;an000;character + db 01 ;an000;minimum width of 1 + db 01 ;an000;maximum width of 1 + db pad_blank ;an000;pad with blank + +BAK_Sub label dword ;an000;line output buffer + + db 11 ;an000;sublist size + db 00 ;an000;reserved + dd dg:Temp_Path ;an000;pointer to parameter + db 00 ;an000;parm 0 + db Char_Field_ASCIIZ ;an000;left align/asciiz/char. + db unlim_width ;an000;unlimited width + db 00 ;an000;minimum width of 0 + db pad_blank ;an000;pad with blank + + +;========================================================================= +; end replaceable parameter sublists +;========================================================================= + +;======================= TABLE STRUCTURE ================================= +; +; bute 1-2 : message number of message to be displayed +; byte 3 : message type to be used, i.e.;class 1, utility, etc. +; byte 4-5 : display handle, i.e.; console, printer, etc. +; byte 6-7 : pointer to substitution list, if any. +; byte 8-9 : number of replaceable parameters, if any. +; byte 10 : type of input from keyboard, if any. +; byte 11-12: pointer to buffer for keyboard input, if any. +; +;========================================================================= + + +bad_vers_err label word ;an000;"Incorrect DOS version" + dw 0001 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +prompt_ptr label word ;an000;"*",0 + dw 0006 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +baddrv_ptr label word ;an000;"Invalid drive or file name" + ;an000;,0d,0a,0 + dw 0007 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +ndname_ptr label word ;an000;"File name must be + ;an000;specified",0d,0a,0 + dw 0008 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +opt_err_ptr label word ;an000;"Invalid parameter",0d,0a,0 + dw 0010 ;an000;message number + db Parse_Err_Class ;an000;utility message + dw StdErr ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +ro_err_ptr label word ;an000;"File is READ-ONLY",0d,0a,0 + dw 0010 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +bcreat_ptr label word ;an000;"File Creation Error",0d,0a,0 + dw 0011 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +too_many_ptr label word ;an000;"Too many files open",0d,0a,0 + dw 0012 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +read_err_ptr label word ;an000;"Read error in:", + ;an000;0d,0a,"%1",0d,0a,0 + dw 0013 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:ed_read_sub ;an000;point to sublist + dw 0001 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + + +nobak_ptr label word ;an000;"Cannot edit .BAK file + ;an000;--rename file",0d,0a,0 + dw 0014 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +nodir_ptr label word ;an000;"No room in directory + ;an000;for file",0d,0d,0 + dw 0015 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +dskful_ptr label word ;an000;"Disk full. Edits lost.",0d,0a,0 + dw 0016 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +memful_ptr label word ;an000;"Insufficient memory",0d,0a,0 + dw 0008 ;an000;message number + db Ext_Err_Class ;an000;extended error + dw stderr ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +filenm_ptr label word ;an000;"File not found",0d,0a + dw 0002 ;an000;message number + db Ext_Err_Class ;an000;utility message + dw stderr ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +badcom_ptr label word ;an000;"Entry error",0d,0a,0 + dw 0018 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +newfil_ptr label word ;an000;"New file",0d,0a,0 + dw 0019 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +nosuch_ptr label word ;an000;"Not found",0d,0a,0 + dw 0020 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +ask_ptr label word ;an000;"O.K.? ",0 + dw 0021 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db DOS_KEYB_INP ;an000;keyboard input - AX + dw 00 ;an000;no keyboard buffer + +toolng_ptr label word ;an000;"Line too long",0d,0a,0 + dw 0022 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +eof_ptr label word ;an000;"End of input file",0d,0a,0 + dw 0023 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +qmes_ptr label word ;an000;"Abort edit (Y/N)? ",0 + dw 0024 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db DOS_KEYB_INP ;an000;keyboard input - AX + dw 00 ;an000;no keyboard buffer + +dest_ptr label word ;an000;"Must specify destination + ;an000;line number",0d,0a,0 + dw 0025 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +mrgerr_ptr label word ;an000;"Not enough room to + ;an000;merge the entire file",0d,0a,0 + dw 0026 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +crlf_ptr label word ;an000;0d,0a,0 + dw 0027 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +lf_ptr label word ;an000;0a,0 + dw 0028 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +cont_ptr label word ;an000;"Continue (Y/N)?" + dw 0029 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no sub + db DOS_KEYB_INP ;an000;keyboard input + dw 00 ;an000;no keyboard buffer + +arg_buf_ptr label word ;an000;argument buffer for + ; line output + dw 0031 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:arg_sub ;an000;argument sublist + dw 01 ;an000;1 sub + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +line_num_buf_ptr label word ;an000;holds line numbers + dw 0032 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw dg:num_sub ;an000;argument sublist + dw 02 ;an000;2 subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +cp_err_ptr label word ;an000;"Cannot merge - Code page + ; mismatch",0d,0a + dw 0033 ;an000;message number + db UTILITY_MSG_CLASS ;an000;utility message + dw stdout ;an000;display handle + dw 00 ;an000;no sublist + dw 00 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +del_bak_ptr label word ;an000;"Access Denied - xxxxxxxx.BAK" + dw 0005 ;an000;message number + db Ext_Err_Class ;an000;utility message + dw stderr ;an000;display handle + dw dg:BAK_Sub ;an000;no sublist + dw 01 ;an000;no subs + db no_input ;an000;no keyboard input + dw 00 ;an000;no keyboard buffer + +CONST ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLPARSE.ASM b/v4.0/src/CMD/EDLIN/EDLPARSE.ASM new file mode 100644 index 0000000..32f6f4c --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLPARSE.ASM @@ -0,0 +1,281 @@ + + page 60,132; + title EDLPARSE for EDLIN + + +;******************* START OF SPECIFICATIONS ***************************** +; +; MODULE NAME: EDLPARSE.SAL +; +; DESCRIPTIVE NAME: PARSES THE EXTERNAL COMMAND LINE FOR EDLIN +; +; FUNCTION: THIS ROUTINE PROVIDES PARSING CAPABILITIES FOR THE +; EXTERNAL COMMAND LINE OF EDLIN. IT PARSES FOR THE PRESENCE +; OF A REQUIRED FILESPEC AND AN OPTIONAL SWITCH (/B). +; +; ENTRY POINT: PARSER_COMMAND +; +; INPUT: DOS COMMAND LINE +; +; EXIT NORMAL: AX = 0FFH - VALID SWITCH AND FILESPEC SPECIFIED +; +; EXIT ERROR: AX NOT= 0FFH - INVALID SWITCH OR NO FILESPEC SPECIFIED +; +; INTERNAL REFERENCES +; +; ROUTINE: PARSER_COMMAND - THIS ROUTINE PARSES FOR THE PRESENCE +; OF THE /B SWITCH AND A FILESPEC. THE +; FILEPSEC IS REQUIRED, WHILE THE SWITCH +; IS OPTIONAL. +; +; EXTERNAL REFERENCES: +; +; ROUTINE: PARSE.ASM - THIS IS THE PARSER CODE. +; +; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS. +; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE +; +; REVISION HISTORY: +; +; AN000 VERSION 4.00 - IMPLEMENTS THE SYSTEM PARSER (SYSPARSE) +; +; COPYRIGHT: "THE IBM PERSONAL COMPUTER EDLIN UTILITY" +; "VERSION 4.00 (C) COPYRIGHT 1988" +; "LICENSED MATERIAL - PROPERTY OF Microsoft" +; +; +;******************** END OF SPECIFICATIONS ****************************** + + +;======================= equates for edlparse ============================ + +parse_ok equ 0 ;an000;good parse return +parse_command equ 081h ;an000;offset of command line +nul equ 0 ;an000;nul +fs_flag equ 05h ;an000;filespec found +sw_flag equ 03h ;an000;switch found +true equ 0ffffh ;an000;true +false equ 00h ;an000;false +too_many equ 01h ;an000;too many parms + +;======================= end equates ===================================== + + +CODE SEGMENT PUBLIC BYTE +CODE ENDS + +CONST SEGMENT PUBLIC BYTE +CONST ENDS + +cstack segment stack +cstack ends + +DATA SEGMENT PUBLIC BYTE + + extrn path_name:byte + extrn org_ds:word ;an000; dms; + + public parse_switch_b ;an000;parse switch result + public filespec ;an000;actual filespec + +;======================= input parameters control blocks ================= +; these control blocks are used by sysparse and must be pointed to by +; es:di on invocation. + + public parms ;an000;share parms +parms label byte ;an000;parms control block + dw dg:parmsx ;an000;point to parms structure + db 00h ;an000;no additional delims. + +parmsx label byte ;an000;parameter types + db 1,1 ;an000;must have filespec + dw dg:fs_pos ;an000;filespec control block + db 1 ;an000;max. number of switches + dw dg:sw_b ;an000;\b switch control block + db 00h ;an000;no keywords + +;======================= filespec positional tables ====================== + +fs_pos label byte ;an000;filespec positional + dw 0200h ;an000;filespec/not optional + dw 0001h ;an000;cap + dw dg:filespec_res ;an000;filespec result table + dw dg:noval ;an000;value list/none + db 0 ;an000;no keyword/switch syns. + +filespec_res label byte ;an000;filespec result table +parse_fs_res db ? ;an000;must be filespec (05) +parse_fs_tag db ? ;an000;item tag +parse_fs_syn dw ? ;an000;synonym pointer +parse_fs_off dw ? ;an000;offset to filespec +parse_fs_seg dw ? ;an000;segment of filespec + +;======================= switch tables /b ================================ + +sw_b label byte ;an000;/b switch + dw 0000h ;an000;no match flags + dw 0000h ;an000;no cap + dw dg:switch_res ;an000;result buffer + dw dg:noval ;an000;value list/none + db 1 ;an000;1 switch +sw_b_switch db "/B",0 ;an000;/B means ignore CTL-Z + +switch_res label byte ;an000;switch result table +parse_sw_res db ? ;an000;must be string (03) +parse_sw_tag db ? ;an000;item tag +parse_sw_syn dw ? ;an000;synonym pointer +parse_sw_ptr dd ? ;an000;pointer to result + +noval label byte ;an000;value table + db 0 ;an000;no values + + +;======================= end input parameter control blocks ============== + +filespec db 128 dup (0) ;an000;holds filespec +parse_switch_b db ? ;an000;hold boolean result + ; of /b parse +parse_sw_b db "/B" ;an000;comparison switch + +DATA ENDS + +DG GROUP CODE,CONST,cstack,DATA + +code segment public byte ;an000;code segment + assume cs:dg,ds:dg,es:dg,ss:CStack ;an000; + + public parser_command ;an000;share this routine + + + +;======================= begin main routine ============================== +.xlist + +include parse.asm ;an000;parser + +.list + +parser_command proc near ;an000;parse routine + + push es ;an000;save registers + push ds ;an000; + push di ;an000; + push si ;an000; + + mov dg:parse_switch_b,false ;an000;init. to false + xor cx,cx ;an000;set cx to 0 + xor dx,dx ;an000;set dx to 0 + mov di,offset dg:parms ;an000;point to parms + mov si,parse_command ;an000;point to ds:81h + mov ds,dg:org_ds ;an000;get ds at entry + assume ds:nothing ;an000; + +parse_continue: ;an000;loop return point + + call sysparse ;an000;invoke parser + cmp ax,parse_ok ;an000;is it a good parse + jne parse_end ;an000;continue on good parse + push si + mov si,dx + cmp byte ptr es:[si],fs_flag ;an000;do we have a filespec +; $if e ;an000;yes we do + JNE $$IF1 + call build_fs ;an000;save filespec +; $else ;an000; + JMP SHORT $$EN1 +$$IF1: + cmp parse_switch_b,true ;an000;see if already set +; $if nz ;an000;if not + JZ $$IF3 + call val_sw ;an000;see which switch +; $else ;an000; + JMP SHORT $$EN3 +$$IF3: + mov ax,too_many ;an000;set error level + jmp parse_end ;an000;exit parser +; $endif ;an000; +$$EN3: +; $endif ;an000; +$$EN1: + + pop si + jmp parse_continue ;an000;continue parsing + +parse_end: ;an000;end parse routine + + pop si ;an000;restore registers + pop di ;an000; for return to caller + pop ds ;an000; + assume ds:dg ;an000; + pop es ;an000; + + ret ;an000;return to caller + +parser_command endp ;an000;end parser_command + + +;======================= subroutine area ================================= + + +;========================================================================= +; build_fs: This routine saves the filespec for use by the calling program. +;========================================================================= + +build_fs proc near ;an000;save filespec + + push ax ;an000;save affected regs. + push di ;an000; + push si ;an000; + push ds ;an000; + push es ;an000; + + mov di,offset dg:filespec ;an000;point to filespec buffer + lds si,dword ptr es:parse_fs_off ;an000;get offset + +build_cont: ;an000;continue routine + + lodsb ;an000;mov ds:si to al + cmp al,nul ;an000;is it end of filespec +; $if nz ;an000;if not + JZ $$IF7 + stosb ;an000;move byte to filespec + jmp build_cont ;an000;continue buffer fill +; $endif ;an000; +$$IF7: + stosb ;an000;save nul + + pop es ;an000;restore regs + pop ds ;an000; + pop si ;an000; + pop di ;an000; + pop ax ;an000; + + ret ;an000;return to caller + +build_fs endp ;an000;end proc + +;========================================================================= +; val_sw : determines which switch we have. +;========================================================================= + +val_sw proc near ;an000;switch determination + + cmp es:parse_sw_syn,offset es:sw_b_switch ;an000;/B switch? +; $if e ;an000;compare good + JNE $$IF9 + mov dg:parse_switch_b,true ;an000;signal /B found +; $else ;an000; + JMP SHORT $$EN9 +$$IF9: + mov dg:parse_switch_b,false ;an000;signal /B not found +; $endif ;an000; +$$EN9: + + ret ;an000;return to caller + +val_sw endp ;an000;end proc + + +code ends ;an000;end segment + end ;an000; + \ No newline at end of file diff --git a/v4.0/src/CMD/EDLIN/EDLSTDSW.INC b/v4.0/src/CMD/EDLIN/EDLSTDSW.INC new file mode 100644 index 0000000..436f09f --- /dev/null +++ b/v4.0/src/CMD/EDLIN/EDLSTDSW.INC @@ -0,0 +1,32 @@ +; SCCSID = @(#)stdsw.asm 1.1 85/04/10 +; Use the switches below to produce the standard Microsoft version or the IBM +; version of the operating system + + +;include EDLVERS.INC ;IBM/MSVER/JAPVER switches + + +WANG EQU FALSE +Rainbow EQU FALSE + + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + + IF IBM +ESCCH EQU 0 ; character to begin escape seq. +CANCEL EQU 27 ;Cancel with ESCAPE +TOGLPRN EQU TRUE ;One key toggles printer echo +ZEROEXT EQU TRUE + ELSE + IF WANG ;Are we assembling for WANG? +ESCCH EQU 1FH ;Yes. Use 1FH for escape character + ELSE +ESCCH EQU 1BH + ENDIF +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLPRN EQU FALSE ;Separate keys for printer echo on + ;and off +ZEROEXT EQU TRUE + ENDIF + diff --git a/v4.0/src/CMD/EDLIN/MAKEFILE b/v4.0/src/CMD/EDLIN/MAKEFILE new file mode 100644 index 0000000..d01bbb1 --- /dev/null +++ b/v4.0/src/CMD/EDLIN/MAKEFILE @@ -0,0 +1,56 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: edlin.com + +edlin.ctl: edlin.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + + +edlin.obj: edlin.asm edlequ.asm edlstdsw.inc makefile \ + $(inc)\dossym.inc \ + $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\mult.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc $(inc)\cpmfcb.inc \ + $(inc)\find.inc $(inc)\pdb.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\error.inc $(inc)\syscall.inc + +edlcmd1.obj: edlcmd1.asm edlequ.asm edlstdsw.inc makefile \ + $(inc)\dossym.inc \ + $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\mult.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc $(inc)\cpmfcb.inc \ + $(inc)\find.inc $(inc)\pdb.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\error.inc $(inc)\syscall.inc + +edlcmd2.obj: edlcmd2.asm edlequ.asm edlstdsw.inc makefile \ + $(inc)\dossym.inc \ + $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\mult.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc $(inc)\cpmfcb.inc \ + $(inc)\find.inc $(inc)\pdb.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\error.inc $(inc)\syscall.inc + +edlmes.obj: edlmes.asm $(inc)\sysmsg.inc makefile \ + edlin.ctl \ + edlin.cla \ + edlin.clb \ + edlin.cl1 \ + edlin.cl2 \ + +edlparse.obj: edlparse.asm $(inc)\parse.asm makefile + +edlin.com: edlin.obj edlcmd1.obj edlcmd2.obj edlmes.obj edlparse.obj \ + edlin.lnk makefile + link @edlin.lnk + convert edlin.exe + del edlin.exe diff --git a/v4.0/src/CMD/EXE2BIN/DISPLAY.ASM b/v4.0/src/CMD/EXE2BIN/DISPLAY.ASM new file mode 100644 index 0000000..4c4bae7 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/DISPLAY.ASM @@ -0,0 +1,110 @@ + + +CODE SEGMENT PARA PUBLIC 'CODE' +CODE ENDS +DATA SEGMENT PARA PUBLIC 'DATA' +DATA ENDS +STACK SEGMENT PARA STACK 'STACK' +STACK ENDS +ZLOAD SEGMENT PARA PUBLIC 'ZLOAD' +ZLOAD ENDS + +CODE SEGMENT PARA PUBLIC 'CODE' + assume cs:code,ds:data +; +;***************************************************************************** +; External Declarations +;***************************************************************************** +; + + extrn SysDispMsg:near + +; +;*************************************************************************** +; Message Structures +;*************************************************************************** +; + + +Message_Table struc ; ;AN000; + ; +Entry1 dw 0 ; ;AN000; +Entry2 dw 0 ; ;AN000; +Entry3 dw 0 ; ;AN000; +Entry4 dw 0 ; ;AN000; +Entry5 db 0 ; ;AN000; +Entry6 db 0 ; ;AN000; +Entry7 dw 0 ; ;AN000; + ; +Message_Table ends ; ;AN000; + + + +;***************************************************************************** +;Routine name&gml Display_Interface +;***************************************************************************** +; +;DescriptioN&gml Save all registers, set up registers required for SysDispMsg +; routine. This information is contained in a message description +; table pointed to by the DX register. Call SysDispMsg, then +; restore registers. This routine assumes that the only time an +; error will be returned is if an extended error message was +; requested, so it will ignore error returns +; +;Called Procedures: Message (macro) +; +;Change History&gml Created 4/22/87 MT +; +;Input&gml ES&gmlDX = pointer to message description +; +;Output&gml None +; +;Psuedocode +;---------- +; +; Save all registers +; Setup registers for SysDispMsg from Message Description Tables +; CALL SysDispMsg +; Restore registers +; ret +;***************************************************************************** + +Public Display_Interface +Display_Interface proc ; ;AN000; + + push ds ; ;AN000; + push es ; ;AN000; + push ax ;Save registers ;AN000; + push bx ; " " " " ;AN000; + push cx ; " " " " ;AN000; + push dx ; " " " " ;AN000; + push si ; " " " " ;AN000; + push di ; " " " " ;AN000; + mov di,dx ;Change pointer to table ;AN000; + mov dx,SEG data ;Point to data segment + mov ds,dx ; + mov es,dx + mov ax,[di].Entry1 ;Message number ;AN000; + mov bx,[di].Entry2 ;Handle ;AN000; + mov si,[di].Entry3 ;Sublist ;AN000; + mov cx,[di].Entry4 ;Count ;AN000; + mov dh,[di].Entry5 ;Class ;AN000; + mov dl,[di].Entry6 ;Function ;AN000; + mov di,[di].Entry7 ;Input ;AN000; + call SysDispMsg ;Display the message ;AN000; + pop di ;Restore registers ;AN000; + pop si ; " " " " ;AN000; + pop dx ; " " " " ;AN000; + pop cx ; " " " " ;AN000; + pop bx ; " " " " ;AN000; + pop ax ; " " " " ;AN000; + pop es ; ;AN000; + pop ds ; ;AN000; + ret ;All done ;AN000; + +Display_Interface endp ; ;AN000; +code ends + + + end + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/E2BCHNG.INC b/v4.0/src/CMD/EXE2BIN/E2BCHNG.INC new file mode 100644 index 0000000..560618d --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BCHNG.INC @@ -0,0 +1,21 @@ +.xlist +; +; +;***************************************************************************** +;* * +;* Change list to EXE2BIN modules * +;* * +;* Lines are tagged ANxxx for new, ACxxx for changed * +;* --------------------------------------------------------------------------* +;* 000 - DOS 4.00 Spec additions and DCR's thru unit/function test * +;* Date: 12/31/87 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 001 - DOS 4.00 PTM P3964 Pass invalid parameter to message retriever for * +;* replacement in error message. * +;* Date: 03/24/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;***************************************************************************** +;* Note: This is file E2BCHNG.INC for updating purposes * +;***************************************************************************** +.list + diff --git a/v4.0/src/CMD/EXE2BIN/E2BEQU.INC b/v4.0/src/CMD/EXE2BIN/E2BEQU.INC new file mode 100644 index 0000000..d127c92 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BEQU.INC @@ -0,0 +1,50 @@ + ; ; ; + +NO equ 0 +YES equ not NO + + +DOS_Found equ 0 + +INIT equ 0 + + +Net_Check equ 1200h +Assign_Check equ 8000h + +Found_Yes equ 1 +Found_No equ 0 + +Asciiz_End equ 0 +;DBCS equ 81h +DBCS_Blank equ 40h +DBCS_Vector_Size equ 2 +End_Of_Vector equ 0 + + +Blank equ " " + +Label_Length equ 11 +CR equ 13 + +DBCS_VECTOR equ NO + +;------------------------------------------------------------------------------- + + + + + +DRNUM EQU 5CH + + + +; Exit status defines +ExitOK equ 0 + + +;------------------------------------------------------------------------------- +; These are the data structures which we will need + + + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/E2BINIT.ASM b/v4.0/src/CMD/EXE2BIN/E2BINIT.ASM new file mode 100644 index 0000000..60422d4 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BINIT.ASM @@ -0,0 +1,1123 @@ + +Title E2BINIT(EXE2BIN) + +;***************************************************************************** +; Loader for EXE files under 86-DOS +; VER 1.5 +; 05/21/82 Added rev number +; VER 1.6 +; 07/01/82 A little less choosy about size matches +; VER 2.0 M.A.U +; 10/08/82 Modified to use new 2.0 system calls for file i/o +; Ver 2.1 M.A.U +; 10/27/82 Added the DOS version check +; Ver 2.2 MZ +; 8/30/83 Fixed command line parsing +; Ver 2.3 EE +; 10-12-83 More fixes to command line parsing +; Ver 2.4 NP +; 10/17/83 Use Printf for messages +; Ver 2.5 MZ Fix LOCATE sss D: problem +; 04/09/87 Add PARSER and MESSAGE RETRIEVER +; Ver 4.00 DRM +;***************************************************************************** + + +INCLUDE SYSMSG.INC +MSG_UTILNAME ;AN000; + + subttl Main Code Area ;AN000; + page + + +; The following switch allows use with the "old linker", which put a version +; number where the new linker puts the number of bytes used in the last page. +; If enabled, this will cause a test for 0004 at this location (the old linker +; version number), and if equal, change it to 200H so all of the last page +; will be used. + +OLDLINK EQU 0 ;1 to enable, 0 to disable + +CODE SEGMENT PARA PUBLIC 'CODE' ;AN000; +CODE ENDS ;AN000; +DATA SEGMENT PARA PUBLIC 'DATA' ;AN000; +DATA ENDS ;AN000; +STACK SEGMENT PARA PUBLIC 'STACK' ;AN000; +STACK ENDS ;AN000; +ZLOAD SEGMENT PARA PUBLIC 'ZLOAD' ;AN000; +ZLOAD ENDS ;AN000; + +DATA SEGMENT PARA PUBLIC 'DATA' ;AN000; + +MSG_SERVICES ;AN000; + +Command_Line_Buffer db 128 dup(0) ;AN000; +Command_Line_Length equ $ - Command_Line_Buffer ;AN000; + +Fatal_Error db 0 ;AN000; + +Command_Line db NO + + + +rev db "2.4" + + +file1_ext db ".EXE",00h +file2_ext db ".BIN",00h + +per11 db 0 ;AN000; +per2 db 0 +per22 db 0 ;AN000; + +update equ 0 ;AN000; +noupdate equ -1 ;AN000; + +file1 db (64+13) dup(?) +fnptr dw offset file1 ; Ptr to filename in file1 +handle1 dw 1 dup(?) + +file2 db (64+13) dup(?) +f2cspot dw offset file2 ; Ptr to spot in file2, file1 maybe added +handle2 dw 1 dup(?) + +dma_buf db 80h dup(0) ; DMA transfer buffer + +INBUF DB 5,0 + DB 5 DUP(?) + +;The following locations must be defined for storing the header: + +RUNVAR LABEL BYTE ;Start of RUN variables +RELPT DW ? +LASTP LABEL WORD +RELSEG DW ? +SIZ LABEL WORD ;Share these locations +PAGES DW ? +RELCNT DW ? +HEADSIZ DW ? + DW ? +LOADLOW DW ? +INITSS DW ? +INITSP DW ? + DW ? +INITIP DW ? +INITCS DW ? +RELTAB DW ? +RUNVARSIZ EQU $-RUNVAR + +DBCS_Vector_Off dw 0 ;AN000; +DBCS_Vector_Seg dw 0 ;AN000; + +parse_ptr DW ? + +DATA ENDS + + +STACK SEGMENT PARA PUBLIC 'STACK' + DB (362 - 80h) + 80H DUP (?) ; (362 - 80h) is IBMs ROM requirement + ; (New - Old) == size of growth +STACK ENDS +; + + + +ZLOAD SEGMENT PARA PUBLIC 'ZLOAD' + db ? +ZLOAD ENDS +LOAD EQU ZLOAD +; + + + +; +;***************************************************************************** +; Include files +;***************************************************************************** +; + +.xlist +INCLUDE DOSSYM.INC ; also versiona.inc ;AN000; +INCLUDE SYSCALL.INC ;AN000; +INCLUDE E2BMACRO.INC ;AN000; +INCLUDE E2BEQU.INC ;AN000; +INCLUDE E2BTABLE.INC ;AN000; +INCLUDE E2BPARSE.INC ;AN000; +include version.inc +.list + + + +CODE SEGMENT PARA PUBLIC 'CODE' + assume cs:CODE,ds:DATA,es:NOTHING,SS:STACK ;AN000; + +psp_ptr dw 1 dup(?) ;AN000; +; +;***************************************************************************** +; SysDisplayMsg Declarations +;***************************************************************************** +; +.xlist +MSG_SERVICES ;AN000; +MSG_SERVICES ;AN000; +MSG_SERVICES ;AN000; +MSG_SERVICES ;AN000; +MSG_SERVICES ;AN000; + + +.list + +; +;***************************************************************************** +; External Routine Declarations +;***************************************************************************** +; + + public SysDispMsg ;AN000; + public SysLoadMsg ;AN000; + + +;***************************************************************************** +;Routine name: Main_Init +;***************************************************************************** +; +;Description: Main control routine for init section +; +;Called Procedures: Message (macro) +; Check_DOS_Version +; Init_Input_Output +; Validate_Target_Drive +; Hook_CNTRL_C +; +;Input: None +; +;Output: None +; +;Change History: Created 6/22/87 DM +; +;***************************************************************************** + +procedure Main_Init near ; ;AN000; + + ASSUME DS:NOTHING ; THIS IS WHAT dos GIVES YOU ;AN000; + ASSUME ES:NOTHING ;AN000; + + PUSH DS ;AN000; + mov psp_ptr,ds ;AN000; + XOR AX,AX ;AN000; + PUSH AX ;Push return address to DS:0 ;AN000; + + MOV AX,SEG DATA ;SET UP ADDRESSABILITY TO ;AN000; + MOV DS,AX ; THE DATA SEGMENT ;AN000; + ASSUME DS:DATA ;TELL ASSEMBLER WHAT I JUST DID ;AN000; + + mov Fatal_Error,No ;Init the error flag ;AN000; + call Init_Input_Output ;Setup messages and parse ;AN000; + cmp Fatal_Error,Yes ;Error occur? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF1 + call LOCATE ;Go do the real program ;AN000; +; $ENDIF ;AN000; +$$IF1: + xor al,al ;AN000; + Dos_call Exit ;AN000; + int 20h ;If other exit fails ;AN000; + +Main_Init endp ;AN000; + +;***************************************************************************** +;Routine name: Init_Input_Output +;***************************************************************************** +; +;Description: Initialize messages, Parse command line, allocate memory as +; needed. If there is a /FS switch, go handle it first as +; syntax of IFS format may be different from FAT format. +; +;Called Procedures: Preload_Messages +; Parse_For_FS_Switch +; Parse_Command_Line +; Interpret_Parse +; +;Change History: Created 6/22/87 DM +; +;Input: PSP command line at 81h and length at 80h +; Fatal_Error = No +; +;Output: Fatal_Error = YES/NO +; +;***************************************************************************** + +procedure Init_Input_Output near ;AN000; + + call Preload_Messages ;Load up message retriever ;AN000; + cmp Fatal_Error,YES ;Quit? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF3 + call Parse_Command_Line ;Parse in command line input ;AN000; +; $ENDIF ;AN000; +$$IF3: + ret ;AN000; + +Init_Input_Output endp ;AN000; + +;***************************************************************************** +;Routine name: Preload_Messages +;***************************************************************************** +; +;Description: Preload messages using common message retriever routines. +; +;Called Procedures: SysLoadMsg +; +; +;Change History: Created 6/22/87 DM +; +;Input: Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;***************************************************************************** + +procedure Preload_Messages near ;AN000; + + call SYSLOADMSG ;Preload the messages ;AN000; +; $IF C ;Error? ;AN000; + JNC $$IF5 + call SYSDISPMSG ;AN000; + mov fatal_error, YES ;AN000; +; $ENDIF ;AN000; +$$IF5: + ret ;AN000; +Preload_Messages endp ;AN000; + + +;***************************************************************************** +;Routine name: Parse_Command_Line +;***************************************************************************** +; +;Description: Parses command line. +; +;Called Procedures: Message (macro) +; Sysparse +; +;Change History: Created 6/22/87 DM +; +;Input: Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;***************************************************************************** + + +Procedure Parse_Command_Line ;AN000; + + push ds ;AN000; + mov ds,psp_ptr ;AN000; + ASSUME DS:NOTHING ;AN000; + mov si,Command_Line_Parms ;AN000; + mov ax,seg command_line_table ;AN000; + push es ;AN000; + mov es,ax ;AN000; + ASSUME ES:NOTHING ;AN000; + mov di,offset Command_Line_Table ;AN000; + xor cx,cx ;AN000; + +; $DO ;AN000; +$$DO7: + xor dx,dx ;AN000; + mov es:parse_ptr,si + call Sysparse ;AN000; + cmp ax,No_Error ;AN000; + +; $IF E ;AN000; + JNE $$IF8 + + push ax ;AN000; + push bx ;AN000; + push ds ;AN000; + push es ;AN000; + push si ;AN000; + push di ;AN000; + + cmp cx,1 ;AN000; + +; $IF E ;AN000; + JNE $$IF9 + + mov ax,seg rb_string1_off ;AN000; + mov ds,ax ;AN000; + ASSUME DS:NOTHING ;AN000; + mov si,offset rb_string1_off ;AN000; + mov ax,ds:[si] ;AN000; + mov bx,ax ;AN000; + + + mov ax,ds:[si+2] ;AN000; + mov ds,ax ;AN000; + ASSUME DS:NOTHING ;AN000; + mov si,bx ;AN000; + + mov ax,seg file1 ;AN000; + mov es,ax ;AN000; + ASSUME ES:NOTHING ;AN000; + mov di,offset file1 ;AN000; + call copyfs ;AN000; + +; $ELSE ;AN000; + JMP SHORT $$EN9 +$$IF9: + + mov ax,seg rb_string2_off ;AN000; + mov ds,ax ;AN000; + ASSUME DS:NOTHING ;AN000; + mov si,offset rb_string2_off ;AN000; + mov ax,ds:[si] ;AN000; + mov bx,ax ;AN000; + + + mov ax,ds:[si+2] ;AN000; + mov ds,ax ;AN000; + ASSUME DS:NOTHING ;AN000; + mov si,bx ;AN000; + + mov ax,seg file2 ;AN000; + mov es,ax ;AN000; + ASSUME ES:NOTHING ;AN000; + mov di,offset file2 ;AN000; + call copyfs ;AN000; + +; $ENDIF ;AN000; +$$EN9: + + pop di ;AN000; + pop si ;AN000; + pop es ;AN000; + ASSUME ES:NOTHING ;AN000; + pop ds ;AN000; + ASSUME DS:NOTHING ;AN000; + pop bx ;AN000; + pop ax ;AN000; + +; $ENDIF ;AN000; +$$IF8: + + cmp ax,No_Error ;AN000; + +; $ENDDO NE ;AN000; + JE $$DO7 + + cmp ax,End_of_Parse ;Check for parse error ;AN000; +; $IF NE ;AN000; + JE $$IF14 + push ax ;AN001; + mov ax,es:parse_ptr ;AN001; + mov es:parsoff,ax ;AN001; + mov es:parseg,ds ;AN001; + mov byte ptr ds:[si],0 ;AN001; + pop ax ;AN001; + parse_message ;Must enter file name ;AN000; + mov es:Fatal_Error,YES ;Indicate death! ;AN000; +; $ENDIF ;AN000; +$$IF14: + + pop es ;AN000; + ASSUME ES:NOTHING ;AN000; + pop ds ;AN000; + ASSUME DS:DATA ;AN000; + + ret ;AN000; + +Parse_Command_Line endp ;AN000; + +;***************************************************************************** + +INCLUDE PARSE.ASM + +;***************************************************************************** + + +procedure LOCATE near + + push ds ;AN000; + ASSUME ES:NOTHING ; THIS IS THE WAY IT GETS HERE! ;AN000; + mov ax,es ; ES -> PSP ;AN000; + mov ds,ax ; DS -> PSP ;AN000; + ASSUME DS:NOTHING ;AN000; + + MOV SI,offset file1 + MOV BX,SEG DATA + MOV ES,BX + assume es:data ;AN000; + + MOV BX,WORD PTR DS:[2] ;Get size of memory + + +;-----------------------------------------------------------------------; + +; +; The rules for the arguments are: +; File 1: +; If no extention is present, .EXE is used. +; File 2: +; If no drive is present in file2, use the one from file1 +; If no path is specified, then use current dir +; If no filename is specified, use the filename from file1 +; If no extention is present in file2, .BIN is used +; + + +;----- Get the first file name + push ds ;AN000; + push es ;AN000; + ASSUME ES:DATA ;AN000; + pop ds ;AN000; + ASSUME DS:DATA ;AN000; + +sj01: + mov si,offset file1 ; d = file1; + mov per11,0 ; assume no extension on file1;AC000; + +;****************************************************************************** + +sj0: + lodsb ; while (!IsBlank(c=*p++)) { + cmp al,0 + JE SJ2 + call dbcs_check ; see if a dbcs character ;AN000; + jc dbcs_1 ; dbcs character, go load another char ;AN000; + cmp al,'\' ; if (c == '\\' || c == ':') { + jnz sj05 + mov per11,update ;AC000; + mov fnptr,si ; fnptr = ptr to slash +sj05: + cmp al,':' ; if (c == '\\' || c == ':') { + jnz checkper1 + mov per11,update ;AC000; + mov fnptr,si ; fnptr = ptr to slash +checkper1: + cmp al,'.' ; if (c == '.') + jne sj1 + mov per11,noupdate ; set file1 to have extension ;AN000; + +sj1: + +IF IBMCOPYRIGHT +ELSE + cmp al,'*' + je File1_Err + cmp al,'?' + je File1_Err +ENDIF + + jmp short sj0 ; } + +IF IBMCOPYRIGHT +ELSE +File1_Err: + stc + mov dx, offset file1 + jmp DosError +ENDIF + +dbcs_1: ; ;AN000; + lodsb ; load another character and got to ;AN000; + jmp short sj0 ; the start again. ;AN000; + +;****************************************************************************** + +sj2: +get_second: +;----- Get the second file name + MOV SI,offset file1 + mov di,offset file2 ; d = file2 + +;****************************************************************************** + +sj3: + cmp word ptr [di],00 ; check to see if first character of + je sj32 ; file2 is a null. ;AN000; + mov si,offset file2 ; set pointer to file2 + +;****************************************************************************** + +sj31: + lodsb ; If file2 first character is not a + mov f2cspot,si + cmp al,0 ; null, this loop will check to see + JZ maycopy ; the file has an extension assigned;AN000; + call dbcs_check ; to it. If not it will set per2 to ;AN000; + jc dbcs_2 ; go load another byte ;AN000; + mov per22,noupdate ; ;AN000; + cmp al,'\' ; 0 so that in check_ext, the .BIN + jnz checkper6 ; will be added to the filename. + mov per2,update ; ;AC000; + mov per22,update ; ;AN000; +checkper6: + cmp al,':' ; if (c == '\\' || c == ':') { + jnz checkper4 + mov per22,update ; ;AN000; +checkper4: ; there is an extension already. + cmp al,'.' ; + jne sj33 ; + mov per2,noupdate ; ;AC000; + +sj33: ; + +IF IBMCOPYRIGHT +ELSE + cmp al,'*' + je File2_Err + cmp al,'?' + je File2_Err +ENDIF + + jmp short sj31 ; + +IF IBMCOPYRIGHT +ELSE +File2_Err: + stc + mov dx, offset file2 + jmp DosError +ENDIF + + +dbcs_2: + lodsb ;load another character and got to ;AN000; + jmp short sj31 ;the start again. ;AN000; + +;****************************************************************************** + +maycopy: ; Check to see if the ;AN000; + cmp per22,noupdate ; Last thing copied was either a ;AN000; + je SJ5 ; driver letter or "\". ;AN000; + dec f2cspot ;AN000; + mov di,f2cspot ;AN000; + +sj32: + ; There is no second filename so + mov si,fnptr ;AN000; + mov per2,update ; set per2 to 0 to get default .BIN ;AN000; + ; extension in check_ext. + +;****************************************************************************** + +copy1to2: ;AN000; + lodsb ; This loop is executed when there is ;AN000; + cmp al,0 ; no file2 specified on the command ;AN000; + JZ SJ5 ; line. It will copy the file1 name ;AN000; + call dbcs_check ; check for dbcs character ;AN000; + jc dbcs_3 ; got a dbcs character, go copy. ;AN000; + cmp al,'.' ; extension. The defult extension ;AN000; + je sj5 ; of .BIN will be added in check_ext. ;AN000; + stosb ;AN000; + jmp short copy1to2 ;AN000; +dbcs_3: + stosb ; Got a dbcs character. Copy ;AN000; + lodsb ; two characters and then go to ;AN000; + stosb ; next character in filename. ;AN000; + jmp short copy1to2 ;AN000; ;AN000; + +;****************************************************************************** + +sj5: +; mov byte ptr es:[di],00h ; *d = 0; + mov ah,Set_DMA ; Use find_first to see if file2 is + mov dx,offset dma_buf ; a directory. If it isn't, go to + int 21h ; set f2cspot to point to the spot + mov ah,Find_First ; right after the backslash, and + mov dx,offset file2 ; fall through to no_second so that + mov cx,-1 ; file1's name will be added to file2. + int 21h + jc check_ext + test dma_buf+21,00010000b + jNZ DoDirectory + jmp Check_Ext +DoDirectory: + mov AL,'\' + mov di,f2cspot + dec di + stosb +SetSecond: + mov per22,update ;AN000; + inc di + mov f2cspot,di + jmp maycopy + + +;----- Check that files have an extension, otherwise set default +check_ext: + cmp per11,noupdate ; if (per1 == NULL) { ;AC000; + jz file1_ok + mov di,offset file1 ; d = file1; + mov si,offset file1_ext ; s = ".EXE"; + call strcat ; strcat (d, s); +file1_ok: ; } + cmp per2,noupdate ; if (per2 != NULL) { ;AC000; + je file2_ok + mov di,offset file2 ; d = file2; + mov si,offset file2_ext ; s = ".BIN"; + call strcat ; strcap (d, s); + jmp short file2_ok ; } + +;-----------------------------------------------------------------------; +file2_ok: + mov dx,offset file1 + mov ax,(open SHL 8) + 0 ;for reading only + INT 21H ;Open input file + jc bad_file + mov [handle1],ax + jmp exeload + +bad_file: + jmp DosError + +BADEXE: + pop ds + ASSUME DS:nothing ;AN000; + MESSAGE msgNoConvert ;AC000; + jmp getout ;AN000; + +ReadError: + jmp DosError + +EXELOAD: + ASSUME DS:DATA ;AN000; + MOV DX,OFFSET RUNVAR ;Read header in here + MOV CX,RUNVARSIZ ;Amount of header info we need + push bx + mov bx,[handle1] + MOV AH,read + INT 21H ;Read in header + pop bx + jc ReadError + CMP [RELPT],5A4DH ;Check signature word + JNZ BADEXE + MOV AX,[HEADSIZ] ;size of header in paragraphs + ADD AX,31 ;Round up first + CMP AX,1000H ;Must not be >=64K + JAE TOOBIG + AND AX,NOT 31 + MOV CL,4 + SHL AX,CL ;Header size in bytes + + push dx + push cx + push ax + push bx + mov dx,ax + xor cx,cx + mov al,0 + mov bx,[handle1] + mov ah,lseek + int 21h + jc LseekError + pop bx + pop ax + pop cx + pop dx + + XCHG AL,AH + SHR AX,1 ;Convert to pages + MOV DX,[PAGES] ;Total size of file in 512-byte pages + SUB DX,AX ;Size of program in pages + CMP DX,80H ;Fit in 64K? (128 * 512 = 64k) + JAE TOOBIG + XCHG DH,DL + SHL DX,1 ;Convert pages to bytes + MOV AX,[LASTP] ;Get count of bytes in last page + OR AX,AX ;If zero, use all of last page + JZ WHOLEP + + IF OLDLINK + CMP AX,4 ;Produced by old linker? + JZ WHOLEP ;If so, use all of last page too + ENDIF + + SUB DX,200H ;Subtract last page + ADD DX,AX ;Add in byte count for last page +WHOLEP: + MOV [SIZ],DX + ADD DX,15 + SHR DX,CL ;Convert bytes to paragraphs + MOV BP,SEG LOAD + ADD DX,BP ;Size + start = minimum memory (paragr.) + CMP DX,BX ;Enough memory? + JA TOOBIG + MOV AX,[INITSS] + OR AX,[INITSP] + OR AX,[INITCS] + JMP ERRORNZ + +TOOBIG: + pop ds + ASSUME DS:NOTHING ;AN000; + MESSAGE msgOutOfMemory ;AN000; + jmp getout ;AN000; + +LseekError: + jmp DosError + + +ERRORNZ: + ASSUME DS:DATA ;AN000; + jz xj + JMP BADEXE ;AC000; For ptm P475; +xj: MOV AX,[INITIP] + OR AX,AX ;If IP=0, do binary fix + JZ BINFIX + CMP AX,100H ;COM file must be set up for CS:100 + JNZ ERRORNZ + + push dx + push cx + push ax + push bx + mov dx,100h ;chop off first 100h + xor cx,cx + mov al,1 ;seek from current position + mov bx,[handle1] + mov ah,lseek + int 21h + jc LseekError + pop bx + pop ax + pop cx + pop dx + + SUB [SIZ],AX ;And count decreased size + CMP [RELCNT],0 ;Must have no fixups + JNZ ERRORNZ +BINFIX: + XOR BX,BX ;Initialize fixup segment +;See if segment fixups needed + CMP [RELCNT],0 + JZ LOADEXE +GETSEG: + pop ds + ASSUME DS:NOTHING ;AN000; + MESSAGE msgFixUp ;AN000; + PUSH DS + PUSH ES + POP DS + ASSUME DS:DATA ;AN000; + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET INBUF + INT 21H ;Get user response + MOV SI,OFFSET INBUF+2 +;;dcl;; MOV BYTE PTR [SI-1],0 ;Any digits? + cmp BYTE PTR [SI-1],0 ;Any digits? ;AC000; + JZ GETSEG +DIGLP: + LODSB + SUB AL,"0" + JC DIGERR + CMP AL,10 + JB HAVDIG + AND AL,5FH ;Convert to upper case + SUB AL,7 + CMP AL,10 + JB DIGERR + CMP AL,10H + JAE DIGERR +HAVDIG: + SHL BX,1 + SHL BX,1 + SHL BX,1 + SHL BX,1 + OR BL,AL + JMP DIGLP + +DIGERR: + CMP BYTE PTR [SI-1],0DH ;Is last char. a CR? + JNZ GETSEG +LOADEXE: + XCHG BX,BP ;BX has LOAD, BP has fixup + + MOV CX,[SIZ] + MOV AH,read + push di + mov di,[handle1] + PUSH DS + MOV DS,BX + ASSUME DS:NOTHING ;AN000; + XOR DX,DX + push bx + mov bx,di + INT 21H ;Read in up to 64K + pop bx + POP DS + ASSUME DS:DATA ;AN000; + pop di + Jnc HAVEXE ;Did we get it all? + + jmp DosError + +LseekError2: + jmp DosError + +HAVEXE: + ASSUME DS:DATA ;AN000; + CMP [RELCNT],0 ;Any fixups to do? + JZ STORE + MOV AX,[RELTAB] ;Get position of table + + push dx + push cx + push ax + push bx + mov dx,ax + xor cx,cx + mov al,0 + mov bx,[handle1] + mov ah,lseek + int 21h + jc LseekError2 + pop bx + pop ax + pop cx + pop dx + + MOV DX,OFFSET RELPT ;4-byte buffer for relocation address +RELOC: + MOV DX,OFFSET RELPT ;4-byte buffer for relocation address + MOV CX,4 + MOV AH,read + push bx + mov bx,[handle1] + INT 21H ;Read in one relocation pointer + pop bx + Jnc RDCMP + jmp DosError +RDCMP: + MOV DI,[RELPT] ;Get offset of relocation pointer + MOV AX,[RELSEG] ;Get segment + ADD AX,BX ;Bias segment with actual load segment + MOV ES,AX + ASSUME ES:NOTHING ;AN000; + ADD ES:[DI],BP ;Relocate + DEC [RELCNT] ;Count off + JNZ RELOC +STORE: + MOV AH,CREAT + MOV DX,OFFSET file2 + xor cx,cx + INT 21H + Jc MKERR + mov [handle2],ax + MOV CX,[SIZ] + MOV AH,write + push di + mov di,[handle2] + PUSH DS + MOV DS,BX + ASSUME DS:NOTHING ;AN000; + XOR DX,DX ;Address 0 in segment + push bx + mov bx,di + INT 21H + pop bx + POP DS + ASSUME DS:DATA ;AN000; + pop di + Jc WRTERR ;Must be zero if more to come + cmp AX,CX + jnz NOROOM + MOV AH,CLOSE + push bx + mov bx,[handle2] + INT 21H + jc CloseError + pop bx + pop ds + pop ds + ASSUME DS:NOTHING ;AN000; + + RET + +;******************************************************************************* + +NOROOM: ; ;AN000; + ASSUME DS:DATA ;AN000; + MOV AH,CLOSE ; Close the file here ;AN000; + push bx ; ;AN000; + mov bx,[handle2] ; ;AN000; + INT 21H ; ;AN000; + jc CloseError ; If error let extend messages get it;AN000; + pop bx ; ;AN000; + mov ah,UNLINK ; Delete the file because it did ;AN000; + MOV DX,OFFSET file2 ; not get written correctly. ;AN000; + INT 21H ; ;AN000; + jc CloseError ; If error let extend messages get it;AN000; + pop ds ; ;AN000; + ASSUME DS:NOTHING ; ;AN000; + message msgNoDiskSpace ; Put out insufficient disk space ;AN000; + jmp getout ; message ;AN000; + RET ; return to main_init ;AN000; + +;******************************************************************************* + +WRTERR: ;AN000; +MKERR: ;AN000; +CloseError: ;AN000; + + public DosError ;AN000; +DosError: ;AN000; + mov es:FileNameSegment,ds ; save for opens, creates, ;AN000; + mov es:FileNameOffset,dx ;AN000; + + mov bx,0 ; get the extended error code ;AN000; + mov ah,059h ;AN000; + int 21h ;AN000; + + mov si,offset ds:Sublist_msg_exterror ;AC001; + extend_message ;AN001; + pop ds ;AN001; + +getout: ;AN000; + pop ds ;AN000; + ASSUME DS:NOTHING ;AN000; + + ret ;AN000; + + +LOCATE ENDP + +;----- concatenate two strings +strcat proc near ; while (*d) + cmp byte ptr [di],0 + jz atend + inc di ; d++; + jmp strcat +atend: ; while (*d++ = *s++) + lodsb + stosb + or al,al ; ; + jnz atend + ret +strcat endp + +;----- Find the first non-ignorable char, return carry if CR found +kill_bl proc near + cld +sj10: ; while ( *p != 13 && + lodsb + CMP AL,13 ; IsBlank (*p++)) + JZ BreakOut + CALL IsBlank + JZ SJ10 ; ; +BreakOut: + dec si ; p--; + cmp al,0dh ; return *p == 13; + clc + jne sj11 + stc +sj11: + ret +kill_bl endp + +IsBlank proc near + cmp al,00 ;AN000; + retz ;AN000; + cmp al,13 + retz + cmp al,' ' ; space + retz + cmp al,9 ; tab + retz + cmp al,',' ; comma + retz + cmp al,';' ; semicolon + retz + cmp al,'+' ; plus + retz + cmp al,10 ; line feed + retz + cmp al,'=' ; equal sign + return +IsBlank Endp + + +procedure copyfs near + + push ax ;AN000; + +; $do ; while we have filespec ;AN000; +$$DO16: + lodsb ; move byte to al ;AN000; + cmp al,0 ; see if we are at ;AN000; + ; the end of the + ; filespec +; $leave e ; exit while loop ;AN000; + JE $$EN16 + stosb ; move byte to path_name ;AN000; +; $enddo ; end do while ;AN000; + JMP SHORT $$DO16 +$$EN16: + stosb ;AN000; + pop ax ;AN000; + + ret ;AN000; +copyfs endp ;AN000; + + +procedure dbcs_check near + + push ds ;Save registers ;AC000; + push si ; " " " " ;AC000; + push ax ; " " " " ;AC000; + push ds ; " " " " ;AC000; + pop es ;Establish addressability;AC000; + cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;AC000; + push ax ;Save input character ;AC000; +; $IF NE ;Nope ;AN000; + JE $$IF19 + mov al,0 ;Get DBCS environment vectors;AC000; + DOS_Call Hongeul ; " " " " ;AC000; + mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector;AC000; + mov es:DBCS_Vector_Off,si ;Save the vector ;AC000; + mov ax,ds ; ;AC000; + mov es:DBCS_Vector_Seg,ax ; ;AC000; +; $ENDIF ; for next time in ;AC000; +$$IF19: + pop ax ;Restore input character;AC000; + mov si,es:DBCS_Vector_Seg ;Get saved vector pointer;AC000; + mov ds,si ; ;AC000; + mov si,es:DBCS_Vector_Off ; ;AC000; +; $SEARCH ;Check all the vectors ;AC000; +$$DO21: + cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;AC000; +; $LEAVE E ;Yes, done ;AC000; + JE $$EN21 + cmp al,ds:[si] ;See if char is in vector;AC000; +; $EXITIF AE,AND ;If >= to lower, and ;AC000; + JNAE $$IF21 + cmp al,ds:[si+1] ; =< than higher range ;AC000; +; $EXITIF BE ; then DBCS character ;AC000; + JNBE $$IF21 + stc ;Set CY to indicate DBCS;AC000; +; $ORELSE ;Not in range, check next;AC000; + JMP SHORT $$SR21 +$$IF21: + add si,DBCS_Vector_Size ;Get next DBCS vector ;AC000; +; $ENDLOOP ;We didn't find DBCS chaR;AC000; + JMP SHORT $$DO21 +$$EN21: + clc ;Clear CY for exit ;AC000; +; $ENDSRCH ; ;AC000; +$$SR21: + pop ax ;Restore registers ;AC000; + pop si ; " " " " ;AC000; + pop ds ;Restore data segment ;AC000; + ret ; ;AC000; + + ret ;AN000; +dbcs_check endp ;AN000; + + + +CODE ends + + + end main_init ;AC000; + + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/E2BMACRO.INC b/v4.0/src/CMD/EXE2BIN/E2BMACRO.INC new file mode 100644 index 0000000..c01206d --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BMACRO.INC @@ -0,0 +1,80 @@ + + + + + + + +; +;****************************************************************************** +; Message Macro Definitions +;****************************************************************************** +; + + EXTRN Display_Interface:near + + +;----------------------------------------------------------------------------- + +MESSAGE macro Message_Name ; ;AN000; + ; + mov dx,offset Message_Name ; ;AN000; + call Display_Interface ; ;AN000; + ; + endm ; ;AN000; + + +; +;***************************************************************************** +; General Macro's +;***************************************************************************** +; + +Procedure macro Proc_Name + +Public Proc_Name +Proc_Name proc + + endm +;----------------------------------------------------------------------------- + +DOS_Call macro Function + + mov ah,Function + int 21h + + endm +;----------------------------------------------------------------------------- + +Parse_Message macro ;AN000; + + + push ds ;AN000; + mov dx,SEG parse_ptr ;AN000; + mov ds,dx ;AN000; + ASSUME DS:DATA ;AN000; + ASSUME ES:DATA ;AN000; + mov word ptr Parse_Error_Msg,ax ;AN000; + mov dx,offset Parse_Error_Msg ; ;AN000; + call Display_Interface ; ;AN000; + pop ds + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Extend_Message macro ; ;AN001; + + ; + push ds ;AN001; + mov dx,SEG parse_ptr ;AN001; + mov ds,dx ;AN001; + ASSUME DS:DATA ;AN001; + ASSUME ES:DATA ;AN001; + mov word ptr Extend_Error_Msg,ax ; ;AN001; + mov dx,offset Extend_Error_Msg ; ;AN001; + call Display_Interface ; ;AN001; + pop ds ;AN001; + endm ; ;AN001; + +;----------------------------------------------------------------------------- + diff --git a/v4.0/src/CMD/EXE2BIN/E2BPARSE.INC b/v4.0/src/CMD/EXE2BIN/E2BPARSE.INC new file mode 100644 index 0000000..9867a46 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BPARSE.INC @@ -0,0 +1,180 @@ + + + +data segment public 'DATA' + + + +; +;*************************************************************************** +; Equates +;*************************************************************************** +; + +;Match Flags + +Numeric_Value equ 8000h ; ;AN000; +Signed_Numeric_Value equ 4000h ; ;AN000; +Simple_String equ 2000h ; ;AN000; +Date_String equ 1000h ; ;AN000; +Time_String equ 0800h ; ;AN000; +Complex_List equ 0400h ; ;AN000; +Filespec equ 0200h ; ;AN000; +Drive_Only equ 0100h ; ;AN000; +Quoted_String equ 0080h ; ;AN000; +Ignore_Colon equ 0010h ; ;AN000; +Repeats_Allowed equ 0002h ; ;AN000; +Optional equ 0001h ; ;AN000; + +;Function_Flags + +File_Table_Capitalize equ 1 ; ;AN000; + +;Result buffer type returned +rb_Number equ 1 +rb_List_Index equ 2 +rb_String equ 3 +rb_Complex equ 4 +rb_Filespec equ 5 +rb_Drive equ 6 +rb_Date equ 7 +rb_Time equ 8 +rb_Quoted_String equ 9 + + +;Extra delimeters and EOL + +Delimiters_Only equ 1 ; ;AN000; +EOL_Or_Delimiters equ 2 ; ;AN000; + +Semi_Colon equ ";" ; ;AN000; +Tab equ 09h ; ;AN000; +Colon1 equ ":" ; ;AN000; +NUL equ "0" + +;Parse Errors + +No_Error equ 0 ; ;AN000; +Too_Many_Operands equ 1 ; ;AN000; +Operand_Missing equ 2 ; ;AN000; +Not_In_Switch_List equ 3 ; ;AN000; +Not_In_Keyword_List equ 4 ; ;AN000; +Out_Of_Range equ 6 ; ;AN000; +Not_In_Value_List equ 7 ; ;AN000; +Not_In_String_List equ 8 ; ;AN000; +Syntax_Error equ 9 ; ;AN000; +End_Of_Parse equ -1 ; ;AN000; + +;Other + +None equ 0 ; ;AN000; +No_Error equ 0 ; ;AN000; +Switch_Found equ 0FFFFh ; ;AN000; +Range_Ok equ 1 ; ;AN000; +Command_Line_Parms equ 81h ; ;AN000; + +; +;***************************************************************************** +; Parse Structures +;***************************************************************************** +; + +Control struc + +Match_Flags dw ? +Function_Flags dw ? +Result dw ? +Values dw ? +Num_Keywords db ? +Keyword db ? + +Control ends + +File_Name_Return struc ; ;AN000; + +Drive_Type db 0 ; ;AN000; +Drive_Item_Tag db 0 ; ;AN000; +Synonym dw 0 ; ;AN000; +String_Value_ptr db 0 ;File Name ;AN000; + +File_Name_Return ends ; ;AN000; + + +; +;************************************************************************** +; Parse tables +;************************************************************************** +; + +Command_Line_Table label byte ; ;AN000; + + dw Command_Control ;Point to next level ;AN000; + db Delimiters_Only ; ;AN000; + db 1 ; ;AN000; + db Semi_Colon ; ;AN000; + + +; +;************************************************************************** +; Define Positionals, Switches and Keywords +;************************************************************************** +; + +Command_Control label byte ; ;AN000; + + db 1,2 ;File names Positional (1 required) ;AN000; + dw Positional_Control1 ;Pointer to control table ;AN000; + dw Positional_Control2 ;Pointer to control table ;AN000; + db None ;no switches ;AN000; + db None ;No Keywords (maxk) ;AN000; + +; +;************************************************************************** +;Control Tables +;************************************************************************** +; + +Positional_Control1 label byte ; ;AN000; + + dw Filespec ;Match_Flag ;AN000; + dw File_Table_Capitalize ;No function flags ;AN000; + dw File_Name_Buffer1 ;Where it will be returned ;AN000; + dw No_Value ;No value ranges defined ;AN000; + db None ;No defined switches/keywords ;AN000; + +Positional_Control2 label byte ; ;AN000; + + dw Filespec+Optional ;Match_Flag ;AN000; + + dw File_Table_Capitalize ;No function flags ;AN000; + dw File_Name_Buffer2 ;Where it will be returned ;AN000; + dw No_Value ;No value ranges defined ;AN000; + db None ;No defined switches/keywords ;AN000; + +No_Value label byte ; ;AN000; + db 0 ; ;AN000; + +; +;************************************************************************ +; PARSE Return Buffers +;************************************************************************ +; +File_name_Buffer1 label byte ; ;AN000; + +rb_type1 db 0 ;type returned ;AN000; +rb_item_tag1 db 0 ;matched item tag ;AN000; +rb_synonym1 dw 0 ;found synonyms ;AN000; +rb_string1_off dw 0 ;Offset of string ;AN000; +rb_string1_seg dw 0 ;Offset of string ;AN000; + +File_name_Buffer2 label byte ; ;AN000; + +rb_type2 db 0 ;type returned ;AN000; +rb_item_tag2 db 0 ;matched item tag ;AN000; +rb_synonym2 dw 0 ;found synonyms ;AN000; +rb_string2_off dw 0 ;Offset of string ;AN000; +rb_string2_seg dw 0 ;Offset of string ;AN000; + +data ends + + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/E2BTABLE.INC b/v4.0/src/CMD/EXE2BIN/E2BTABLE.INC new file mode 100644 index 0000000..d163c3b --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/E2BTABLE.INC @@ -0,0 +1,189 @@ +data segment + +; +;***************************************************************************** +; Macro's +;***************************************************************************** +; + + +Define_Msg macro Message_Name ; ;AN000; + ; +Create_Msg Message_Name,Message_Number,Handle,Sublist,Count,Class,Function,Input;AN000; + ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Create_Msg macro Parm1,Parm2,Parm3,Parm4,Parm5,Parm6,Parm7,Parm8; ;AN000; + +Parm1 label word ; ;AN000; + dw Parm2 ; ;AN000; + dw Parm3 ; ;AN000; + dw Parm4 ; ;AN000; + dw Parm5 ; ;AN000; + db Parm6 ; ;AN000; + db Parm7 ; ;AN000; + dw Parm8 ; ;AN000; + endm ; ;AN000; + + +;--------------------------- ; ;AN001; +Sublist_msg_parserr label dword ; ;AN001; + ;AN001; + db Sublist_Length ;11 ;AN001; + db Reserved ;0 ;AN001; +parsoff dw ? ;off ;AN001; +parseg dw ? ; ;AN001; + db 0 ;USE PERCENT ZERO ;AN001; + db Left_Align+Char_Field_ASCIIZ ;type of data ;AN001; + db 128 ;max width ;AN001; + db 1 ;min width ;AN001; + db Blank ;pad char ;AN001; +;--------------------------- ; ;AN001; + +Sublist_msg_exterror label word ;AN001; + + db Sublist_Length ;AN001; + db Reserved ;AN001; +FileNamePointer label dword ;AN001; +FileNameOffset dw ? ;AN001; +FileNameSegment dw ? ;AN001; + db 0 ; SPECIAL %0 - Extended Errors only ;AN001; + db Left_Align+Char_Field_ASCIIZ ;AN001; + db 132 ;AN001; + db 0 ;AN001; + db Blank ;AN001; +;----------------------------------------------------------------------------- +; +;***************************************************************************** +; Message Retriever equates +;***************************************************************************** +; + +Format_Msg equ 'C' + +N_A equ 0 + +Blank equ " " +No_Function equ 0 + +No_Input equ 0 + + +; +;***************************************************************************** +; Message Description Tables +;***************************************************************************** +; + +;---------------------- ; +Message_Number = 1 ; ;AN000; +Handle = No_Handle ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadDOSVersion ; ;AN000; +;---------------------- ; +Message_Number = 2 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgOutOfMemory ; ;AN000; +;---------------------- ; +Message_Number = 3 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgLoadFailure ; ;AN000; +;---------------------- ; +Message_Number = 4 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoAccess ; ;AN000; +;---------------------- ; +Message_Number = 5 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoConvert ; ;AN000; +;---------------------- ; +Message_Number = 6 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoFile ; ;AN000; +;---------------------- ; +Message_Number = 7 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFileCreateError ; ;AN000; +;---------------------- ; +Message_Number = 8 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = DOS_BUF_KEYB_INP ; ;AN000; +Input = INBUF ; ;AN000; + Define_Msg msgFixUp ; ;AN000; +;---------------------- ; +Message_Number = 0 ; ;AN001; +Handle = STDERR ; ;AN001; +Sublist = ds:sublist_msg_parserr ; ;AN001; +Count = 1 ; ;AN001; +Class = Parse_Err_Class ; ;AN001; +Function = No_Input ; ;AN001; +Input = N_A ; ;AN001; + Define_Msg parse_error_msg ; ;AN001; +;---------------------- ; +Message_Number = 0 ; ;AN001; +Handle = STDERR ; ;AN001; +Sublist = ds:sublist_msg_exterror ; ;AN001; +Count = 1 ; ;AN001; +Class = ext_Err_Class ; ;AN001; +Function = No_Input ; ;AN001; +Input = N_A ; ;AN001; + Define_Msg extend_error_msg ; ;AN001; +;---------------------- ; +Message_Number = 10 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoDiskSpace ; ;AN000; +;---------------------- ; +Message_Number = 12 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoFileName ; ;AN000; +;---------------------- ; +data ends diff --git a/v4.0/src/CMD/EXE2BIN/EXE2BIN.LNK b/v4.0/src/CMD/EXE2BIN/EXE2BIN.LNK new file mode 100644 index 0000000..652fceb --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/EXE2BIN.LNK @@ -0,0 +1,5 @@ +/DOSSEG /MAP /E+ +E2BINIT.obj+ +DISPLAY.obj +EXE2BIN.EXE, EXE2BIN.MAP; + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/EXE2BIN.SKL b/v4.0/src/CMD/EXE2BIN/EXE2BIN.SKL new file mode 100644 index 0000000..6a6a0f3 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/EXE2BIN.SKL @@ -0,0 +1,71 @@ + +:util EXE2BIN + +:class 1 +:use EXTEND2 +:use EXTEND3 +:use EXTEND4 +:use EXTEND5 +:use EXTEND6 +:use EXTEND15 +:use EXTEND18 + +:class 2 + +:class A +;msgBadDosVersion +;"Incorrect DOS version",CR,LF,"$" +:use 1 COMMON1 + +;msgOutOfMemory +;"Insufficient memory",CR,LF +:def 2 "Insufficient memory",CR,LF + +;msgLoadFailure +;"Can't find messages" +:def 3 "Can't find messages",CR,LF + +:CLASS B + +;msgNoAccess +;"Access denied ", CR, LF +:def 4 "Access denied",CR,LF + +;msgNoConvert +;"File cannot be converted", CR, LF +:def 5 "File cannot be converted",CR,LF + +;msgNoFile +;"File not found ", CR, LF +:def 6 "File not found",CR,LF + +;msgFileCreateError +;"File creation error", CR, LF +:def 7 "File creation error",CR,LF + +;msgFixUp +;"Fix-ups needed - base segment (hex):" +:def 8 "Fix-ups needed - base segment (hex):" + +;msgBadParameter +;"Invalid parameter",CR,LF,0 +:use 9 EXTEND87 + +;msgNoDiskSpace +;"Insufficient disk space", CR, LF +;def 10 "Insufficient disk space",CR,LF +:use 10 COMMON20 + +;msgNoFileName +;"File name must be specified ", CR, LF +:def 12 "File name must be specified",CR,LF + +:end + + + + + + + + \ No newline at end of file diff --git a/v4.0/src/CMD/EXE2BIN/LOCATE.ASM b/v4.0/src/CMD/EXE2BIN/LOCATE.ASM new file mode 100644 index 0000000..a2d44f4 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/LOCATE.ASM @@ -0,0 +1,592 @@ +; SCCSID = @(#)locate.asm 4.3 85/09/13 +Title LOCATE (EXE2BIN) + +; Loader for EXE files under 86-DOS +; VER 1.5 +; 05/21/82 Added rev number +; VER 1.6 +; 07/01/82 A little less choosy about size matches +; VER 2.0 M.A.U +; 10/08/82 Modified to use new 2.0 system calls for file i/o +; Ver 2.1 M.A.U +; 10/27/82 Added the DOS version check +; Ver 2.2 MZ +; 8/30/83 Fixed command line parsing +; Ver 2.3 EE +; 10-12-83 More fixes to command line parsing +; Ver 2.4 NP +; 10/17/83 Use Printf for messages +; Ver 2.5 MZ Fix LOCATE sss D: problem +; 04/09/87 Add PARSER and MESSAGE RETRIEVER +; Ver 4.00 DRM + +; The following switch allows use with the "old linker", which put a version +; number where the new linker puts the number of bytes used in the last page. +; If enabled, this will cause a test for 0004 at this location (the old linker +; version number), and if equal, change it to 200H so all of the last page +; will be used. + + +OLDLINK EQU 0 ;1 to enable, 0 to disable + + .xlist + +; INCLUDE DOSSYM.INC ; also versiona.inc +; INCLUDE E2BMACRO.INC + + .list + + subttl Main Code Area + page + +DATA SEGMENT PUBLIC BYTE + +rev db "2.4" + + +file1_ext db ".EXE",00h +file2_ext db ".BIN",00h + +per1 dW 0 +per2 db 0 + +file1 db (64+13) dup(?) +fnptr dw offset file1 ; Ptr to filename in file1 +handle1 dw 1 dup(?) + +file2 db (64+13) dup(?) +f2cspot dw offset file2 ; Ptr to spot in file2, file1 maybe added +handle2 dw 1 dup(?) + +dma_buf db 80h dup(0) ; DMA transfer buffer + +INBUF DB 5,0 + DB 5 DUP(?) + +;The following locations must be defined for storing the header: + +RUNVAR LABEL BYTE ;Start of RUN variables +RELPT DW ? +LASTP LABEL WORD +RELSEG DW ? +SIZ LABEL WORD ;Share these locations +PAGES DW ? +RELCNT DW ? +HEADSIZ DW ? + DW ? +LOADLOW DW ? +INITSS DW ? +INITSP DW ? + DW ? +INITIP DW ? +INITCS DW ? +RELTAB DW ? +RUNVARSIZ EQU $-RUNVAR + +DATA ENDS + +STACK SEGMENT WORD STACK + DB (362 - 80h) + 80H DUP (?) ; (362 - 80h) is IBMs ROM requirement + ; (New - Old) == size of growth +STACK ENDS + + +ZLOAD SEGMENT +ZLOAD ENDS +LOAD EQU ZLOAD + + +CODE SEGMENT BYTE + + ASSUME CS:CODE,SS:STACK + +LOCATE PROC NEAR + +LOCSTRT: + PUSH DS + XOR AX,AX + PUSH AX ;Push return address to DS:0 + + + MOV SI,81H + MOV BX,DATA + MOV ES,BX + MOV BX,WORD PTR DS:[2] ;Get size of memory + + assume es:data + + + + + + +;-----------------------------------------------------------------------; + +; +; The rules for the arguments are: +; File 1: +; If no extention is present, .EXE is used. +; File 2: +; If no drive is present in file2, use the one from file1 +; If no path is specified, then use current dir +; If no filename is specified, use the filename from file1 +; If no extention is present in file2, .BIN is used +; + + +;----- Get the first file name + call kill_bl ; p = skipblanks (p); + jnc sj01 ; if (p == NULL) + push es + pop ds + MESSAGE msgNoFile ;AC000; +sj01: + mov di,offset file1 ; d = file1; +sj0: + lodsb ; while (!IsBlank(c=*p++)) { + CALL IsBlank + JZ SJ2 + mov DX,per1 + cmp al,'\' ; if (c == '\\' || c == ':') { + jz sj05 + cmp al,':' + jnz checkper1 +sj05: + mov fnptr,di ; fnptr = ptr to slash + inc fnptr ; fnptr advanced past slash to fname + xor DX,DX ; per1 = NULL; +checkper1: + cmp al,'.' ; if (c == '.') + jne sj1 + mov DX,DI ; per1 = p-1; + DEC DX ; +sj1: + mov per1,DX + stosb ; *d++ = c; + jmp short sj0 ; } +sj2: + dec si ; p--; + mov byte ptr es:[di],00h ; *d = 0; + call kill_bl ; if (End(p)) + jnc get_second + cmp byte ptr [file1+1],':' ; Drive spec on first file? + jnz nsja ; no + mov ax,word ptr file1 ; get drive stuff + mov word ptr file2,ax + inc f2cspot + inc f2cspot +nsja: + jmp no_second ; goto No_second; + + +get_second: +;----- Get the second file name + mov di,offset file2 ; d = file2 + cmp byte ptr [si+1],':' ; Drive spec on second file? + jz sj3 ; yes + cmp byte ptr [file1+1],':' ; Drive spec on first file? + jnz sj3 ; no + push ax ; Suck drive spec from file1 + mov ax,word ptr file1 + stosw + mov f2cspot,di + pop ax +sj3: + lodsb ; while (!IsBlank(c=*p++)) { + CALL IsBlank + JZ SJ5 + mov ah,per2 + cmp al,'\' ; if (c == '\\') + jnz checkper2 + xor ah,ah ; per2 = FALSE; +checkper2: + cmp al,'.' ; if (c == '.') + jne sj4 + mov ah,-1 ; per2 = TRUE; +sj4: + mov per2,ah + stosb ; *d++ = c; + jmp short sj3 ; } +sj5: + mov byte ptr es:[di],00h ; *d = 0; + mov ah,Set_DMA ; Use find_first to see if file2 is + mov dx,offset dma_buf ; a directory. If it isn't, go to + push es ; chex_ext. If it is, put a back- + pop ds ; slash on the end of the string, + int 21h ; set f2cspot to point to the spot + mov ah,Find_First ; right after the backslash, and + mov dx,offset file2 ; fall through to no_second so that + mov cx,-1 ; file1's name will be added to file2. + int 21h + jc checkDrive + test dma_buf+21,00010000b + jNZ DoDirectory + jmp Check_Ext +CheckDrive: + CMP BYTE PTR ES:[DI-1],':' + JNZ Check_Ext ; if char is not a : then skip + JMP SetSecond ; presume drive: +DoDirectory: + mov AL,5ch + stosb +SetSecond: + mov per2,FALSE + mov f2cspot,di + +;----- Copy file1 to file2 +no_second: + PUSH ES + POP DS + assume ds:data + + mov si,fnptr ; s = ptr to fname in file1; + mov di,f2cspot ; d = spot in file2 to cat file1; + mov dx,per1 ; dx = ptr to ext dot in file1; + inc dx + +sj6: ; while (TRUE) { + cmp SI,dx ; if (s == per1) + je sj7 ; break; + lodsb ; c = *s++; + cmp al,00h ; if (!c) + je sj7 ; break; + stosb ; *d++ = c; + jmp short sj6 ; } +sj7: + mov byte ptr [di],00h ; *d = 0; + +;----- Check that files have an extension, otherwise set default +check_ext: + PUSH ES + POP DS + assume ds:data + + cmp per1,0 ; if (per1 == NULL) { + jNZ file1_ok + mov di,offset file1 ; d = file1; + mov si,offset file1_ext ; s = ".EXE"; + call strcat ; strcat (d, s); +file1_ok: ; } + cmp per2,-1 ; if (per2 != NULL) { + je file2_ok + mov di,offset file2 ; d = file2; + mov si,offset file2_ext ; s = ".BIN"; + call strcat ; strcap (d, s); + jmp short file2_ok ; } + +;-----------------------------------------------------------------------; +file2_ok: + mov dx,offset file1 + mov ax,(open SHL 8) + 0 ;for reading only + INT 21H ;Open input file + jc bad_file + mov [handle1],ax + jmp exeload + +bad_file: + MESSAGE msgNoFile ;AC000; + call TriageError +BADEXE: + MESSAGE msgNoConvert ;AC000; +TOOBIG: + MESSAGE msgOutOfMemory ;AC000; + +EXELOAD: + MOV DX,OFFSET RUNVAR ;Read header in here + MOV CX,RUNVARSIZ ;Amount of header info we need + push bx + mov bx,[handle1] + MOV AH,read + INT 21H ;Read in header + pop bx + CMP [RELPT],5A4DH ;Check signature word + JNZ BADEXE + MOV AX,[HEADSIZ] ;size of header in paragraphs + ADD AX,31 ;Round up first + CMP AX,1000H ;Must not be >=64K + JAE TOOBIG + AND AX,NOT 31 + MOV CL,4 + SHL AX,CL ;Header size in bytes + + push dx + push cx + push ax + push bx + mov dx,ax + xor cx,cx + mov al,0 + mov bx,[handle1] + mov ah,lseek + int 21h + pop bx + pop ax + pop cx + pop dx + + XCHG AL,AH + SHR AX,1 ;Convert to pages + MOV DX,[PAGES] ;Total size of file in 512-byte pages + SUB DX,AX ;Size of program in pages + CMP DX,80H ;Fit in 64K? + JAE TOOBIG + XCHG DH,DL + SHL DX,1 ;Convert pages to bytes + MOV AX,[LASTP] ;Get count of bytes in last page + OR AX,AX ;If zero, use all of last page + JZ WHOLEP + + IF OLDLINK + CMP AX,4 ;Produced by old linker? + JZ WHOLEP ;If so, use all of last page too + ENDIF + + SUB DX,200H ;Subtract last page + ADD DX,AX ;Add in byte count for last page +WHOLEP: + MOV [SIZ],DX + ADD DX,15 + SHR DX,CL ;Convert bytes to paragraphs + MOV BP,LOAD + ADD DX,BP ;Size + start = minimum memory (paragr.) + CMP DX,BX ;Enough memory? + JA TOOBIG + MESSAGE msgNoConvert ;AC000; + MOV AX,[INITSS] + OR AX,[INITSP] + OR AX,[INITCS] +ERRORNZ: + jz xj + JMP WRTERR ;Must not have SS, SP, or CS to init. +xj: MOV AX,[INITIP] + OR AX,AX ;If IP=0, do binary fix + JZ BINFIX + CMP AX,100H ;COM file must be set up for CS:100 + JNZ ERRORNZ + + push dx + push cx + push ax + push bx + mov dx,100h ;chop off first 100h + xor cx,cx + mov al,1 ;seek from current position + mov bx,[handle1] + mov ah,lseek + int 21h + pop bx + pop ax + pop cx + pop dx + + SUB [SIZ],AX ;And count decreased size + CMP [RELCNT],0 ;Must have no fixups + JNZ ERRORNZ +BINFIX: + XOR BX,BX ;Initialize fixup segment +;See if segment fixups needed + CMP [RELCNT],0 + JZ LOADEXE +GETSEG: + MESSAGE msgFixUp ;AC000; + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET INBUF + INT 21H ;Get user response + MOV SI,OFFSET INBUF+2 + MOV BYTE PTR [SI-1],0 ;Any digits? + JZ GETSEG +DIGLP: + LODSB + SUB AL,"0" + JC DIGERR + CMP AL,10 + JB HAVDIG + AND AL,5FH ;Convert to upper case + SUB AL,7 + CMP AL,10 + JB DIGERR + CMP AL,10H + JAE DIGERR +HAVDIG: + SHL BX,1 + SHL BX,1 + SHL BX,1 + SHL BX,1 + OR BL,AL + JMP DIGLP + +DIGERR: + CMP BYTE PTR [SI-1],0DH ;Is last char. a CR? + JNZ GETSEG +LOADEXE: + XCHG BX,BP ;BX has LOAD, BP has fixup + + MOV CX,[SIZ] + MOV AH,read + push di + mov di,[handle1] + PUSH DS + MOV DS,BX + XOR DX,DX + push bx + mov bx,di + INT 21H ;Read in up to 64K + pop bx + POP DS + pop di + Jnc HAVEXE ;Did we get it all? + MESSAGE msgReadError ;AC000; +HAVEXE: + CMP [RELCNT],0 ;Any fixups to do? + JZ STORE + MOV AX,[RELTAB] ;Get position of table + + push dx + push cx + push ax + push bx + mov dx,ax + xor cx,cx + mov al,0 + mov bx,[handle1] + mov ah,lseek + int 21h + pop bx + pop ax + pop cx + pop dx + + MOV DX,OFFSET RELPT ;4-byte buffer for relocation address +RELOC: + MOV DX,OFFSET RELPT ;4-byte buffer for relocation address + MOV CX,4 + MOV AH,read + push bx + mov bx,[handle1] + INT 21H ;Read in one relocation pointer + pop bx + Jnc RDCMP + JMP BADEXE +RDCMP: + MOV DI,[RELPT] ;Get offset of relocation pointer + MOV AX,[RELSEG] ;Get segment + ADD AX,BX ;Bias segment with actual load segment + MOV ES,AX + ADD ES:[DI],BP ;Relocate + DEC [RELCNT] ;Count off + JNZ RELOC +STORE: + MOV AH,CREAT + MOV DX,OFFSET file2 + xor cx,cx + INT 21H + Jc MKERR + mov [handle2],ax + MOV CX,[SIZ] + MOV AH,write + push di + mov di,[handle2] + PUSH DS + MOV DS,BX + XOR DX,DX ;Address 0 in segment + push bx + mov bx,di + INT 21H + pop bx + POP DS + pop di + Jc WRTERR ;Must be zero if more to come + MOV AH,CLOSE + push bx + mov bx,[handle2] + INT 21H + pop bx + RET + +WRTERR: + MESSAGE msgOutOfMemory ;AC000; + +MKERR: + MESSAGE msgFileCreateError ;AC000; + Call TriageError + + +LOCATE ENDP + +;----- concatenate two strings +strcat proc near ; while (*d) + cmp byte ptr [di],0 + jz atend + inc di ; d++; + jmp strcat +atend: ; while (*d++ = *s++) + lodsb + stosb + or al,al ; ; + jnz atend + ret +strcat endp + +;----- Find the first non-ignorable char, return carry if CR found +kill_bl proc near + cld +sj10: ; while ( *p != 13 && + lodsb + CMP AL,13 ; IsBlank (*p++)) + JZ BreakOut + CALL IsBlank + JZ SJ10 ; ; +BreakOut: + dec si ; p--; + cmp al,0dh ; return *p == 13; + clc + jne sj11 + stc +sj11: + ret +kill_bl endp + +IsBlank proc near + cmp al,13 + retz + cmp al,' ' ; space + retz + cmp al,9 ; tab + retz + cmp al,',' ; comma + retz + cmp al,';' ; semicolon + retz + cmp al,'+' ; plus + retz + cmp al,10 ; line feed + retz + cmp al,'=' ; equal sign + return +IsBlank Endp + +; +; Take a default message pointer in DX and convert it to access-denied iff +; the extended error indicates so. Leave all other registers (except AX) +; alone. +; +Procedure TriageError,near + retnc ; no carry => do nothing... + PUSHF + SaveReg + MOV AH,GetExtendedError + INT 21h + RestoreReg ; restore original AX + MESSAGE msgNoAccess ;AC000; + CMP AX,65 ; network access denied? + JZ NoMove ; Yes, return it. + MOV AX,BX + MOV DX,CX +NoMove: + RestoreReg + popf + return +TriageError ENDP + +CODE ENDS + END LOCATE diff --git a/v4.0/src/CMD/EXE2BIN/LOCMES.ASM b/v4.0/src/CMD/EXE2BIN/LOCMES.ASM new file mode 100644 index 0000000..1e87615 --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/LOCMES.ASM @@ -0,0 +1,55 @@ +; SCCSID = @(#)locmes.asm 1.1 85/06/13 + title LOCATE (EXE2BIN) Messages + +FALSE EQU 0 +TRUE EQU NOT FALSE + +addr macro sym,name + public name + ifidn ,<> + dw offset sym + else + public name +name dw offset sym + endif +endm + + +DATA SEGMENT PUBLIC BYTE + + PUBLIC bad_vers + +bad_vers db "Incorrect DOS version$" + +AccDen db "Access denied",0 + addr AccDen,AccDen_ptr + +notfnd db "File not found",0 + addr notfnd,notfnd_ptr + +NOROOM db "Insufficient memory",0 + addr noroom,noroom_ptr + +DIRFULL db "File creation error",0 + addr dirfull,dirfull_ptr + +FULL db "Insufficient disk space",0 + addr full,full_ptr + +CANTFIX db "File cannot be converted",0 + addr cantfix,cantfix_ptr + +PROMPT db "Fix-ups needed - base segment (hex): ",0 + addr prompt,prompt_ptr + + +crlf db 13,10,0 + addr crlf,crlf_ptr + +rdbad db "WARNING - Read error on EXE file.",13,10 + db " Amount read less than size in header.",0 + addr rdbad,rdbad_ptr + + +DATA ENDS + END diff --git a/v4.0/src/CMD/EXE2BIN/MAKEFILE b/v4.0/src/CMD/EXE2BIN/MAKEFILE new file mode 100644 index 0000000..0c0910b --- /dev/null +++ b/v4.0/src/CMD/EXE2BIN/MAKEFILE @@ -0,0 +1,30 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: exe2bin.exe + +exe2bin.ctl : exe2bin.skl makefile \ + $(msg)\$(COUNTRY).msg + +e2binit.obj : e2binit.asm $(inc)\syscall.inc e2bparse.inc e2bmacro.inc \ + e2bequ.inc $(inc)\sysmsg.inc e2btable.inc exe2bin.ctl \ + locate.asm $(inc)\dossym.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc \ + $(inc)\curdir.inc $(inc)\cpmfcb.inc $(inc)\find.inc \ + $(inc)\pdb.inc $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\error.inc $(inc)\syscall.inc $(inc)\parse.asm \ + $(inc)\psdata.inc makefile + +display.obj : display.asm makefile + +exe2bin.exe : display.obj e2binit.obj exe2bin.ctl makefile exe2bin.lnk + link @exe2bin.lnk diff --git a/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM b/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM new file mode 100644 index 0000000..db21b58 --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTINIT.ASM @@ -0,0 +1,2970 @@ + Page 84,132 ; + +TITLE FASTINIT - initialization code for FASTOPEN (May 13, 1988) + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +; The entire Fastopen component is divided into 5 modules. They are: +; Fastopen initialization routine-1, Fastopen initialization routine-2, +; Fastopen which manages the directory/file cache buffers, the Fastseek +; which manages the cluster information cache buffers and the +; cache buffer which holds both directory and cluster information. +; +; These modules resides in different segments for the reason that they can +; be overlayed conditionally, depending on the user request. For example +; initially all segments are loaded into the memory. If fastopen reature is +; not requested, the segment which contains Fastseek will be overlayed over +; original Fastopen to save space. Segmentation is also usefull when Fastopen +; and Fstseek need to copy into Expanded memory. Following figure shows +; memory map of the FastOpen. +; +; Modules Segment +; +; Ú-------------------¿ +; ³ MAIN ³ CSEG_MAIN +; Ã-------------------´ +; ³ FASTINIT1 ³ CSEG_MAIN +; Ã-------------------´ +; ³ ³ +; ³ FASTOPEN ³ CSEG_OPEN +; ³ ³ +; Ã-------------------´ +; ³ ³ +; ³ FASTSEEK ³ CSEG_SEEK +; ³ ³ +; Ã-------------------´ +; ³ FASTINIT2 ³ CSEG_INIT +; Ã-------------------´ +; ³ ³ +; ³ NAME AND ³ +; ³ EXTENT ³ +; ³ CACHE BUFFERS ³ CSEG_INIT +; ³ ³ +; À-------------------Ù +; +; MAIN: This module provides DOS entry point into FASTOPEN. It also +; dispatch various Fastopen and Fastseek functions. This module is +; in the file FASTOPEN.asm +; +; FASTINIT-1: This module is called INIT_TREE which is also a part of the +; Cseg_Main segment. This basically initializes both +; Name and Extent drive headers, and sets up name and extent +; cache buffers. This module can be found in the file +; FASTINIT.asm +; +; FASTINIT-1: This module is called INIT which is part of the Cseg_Init +; segment. This module parses the user commad, check memory +; requirements, overlay Fastopen and Fastseek code and finally +; installs the Fastopen to be stay resident. This module is +; eventually overlayed by the cache buffers created during the +; buffer initialization by FASTINIT-1 ( See INIT_TREE) +; This module can be found in FASTINIT.asm +; +; FASTOPEN: This module is a collection of four Fastopen functions which +; manage the File/Directory cache buffers. These functions are +; in the file FASTOPEN.asm +; +; FASTSEEK: This module is a collection of six FastSeek functions which +; manage queues associated with the cluster information +; cache buffers. This module is found in the file FASTSEEK.asm. +; +; +; Fastopen Code and Cache buffer Relocation +; ----------------------------------------- +; If user specifies both n and m in the user command and /x, then +; Cseg_Open, Cseg_Seek and Cseg_Init will be copied into a 16K page of the +; Expanded Memory. If only n is specified, then Cseg_Open and Cseg_Init will +; be copied. If only m is specified, then Cseg_Seek and Cseg_init will be +; copied. After this the total size of the segments transferred will be +; deblocked from the low memory to save available user space. +; +; If /x is not specified and only n is specified, then the Cseg_Init will +; moved over to Cseg_Seek which is followed by a deblock of memory. If only +; m is specified, then Cseg_Seek will moved over to Cseg_Open and the +; Cseg_Init will be moved over to Cseg_Seek then deblocks the size Cseg_Open. +; +; WARNING: After every move you have to recalculate the Seg ID of moved +; modules depending on how far it has been displaced and then +; replace the Seg ID in the jump vectors used for accessing +; functions in the moved modules. A wrong Seg ID can cause +; instant System CRASH ...@%+(@!$#@@*&... +; +; Future Enhancements: +; +; 1. Modify Fastopen so that it can be run on removable media (Diskette). +; At present only fixed disk is supported. +; +; 2. Allocate all Extent buffers during initialization. Now they are +; done in run time. This may avoid using flags (-2) for discontinuous +; buffers. Using (-2) requires buffers be filled with '0's during PURGE. +; +; 3. Mark the LRU extent every time buffer is changed, so that the +; the buffers need not be searched during buffer recycling +; +; 4; Currently Fastopen code and cache is kept in one 16K page of the +; Extended Memory. This puts a restriction on the size of the cache +; buffer available in EMS usually about 8K. This can be avoided by +; keeping code and cache buffers in two seperated pages, so that maximum +; of 16K is available for cache buffers. +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +; +IF1 + %OUT ASSEMBLING: FASTINIT - FASTOPEN initialization +ENDIF +NAME FASTINIT + +.XCREF +.XLIST + + +TRUE EQU 0FFFFh ;AN000; +FALSE EQU 0 ;AN000; + +DBCS = FALSE ;AN000; +Installed = TRUE ;AN000; + +IFNDEF DEBUG + DEBUG = FALSE +ENDIF + +INCLUDE dosmac.inc ;AN000; +INCLUDE vector.inc ;AN000; +INCLUDE filemode.inc ;AN000; +INCLUDE mult.inc ;AN000; +include version.inc + +.LIST +.CREF + +INCLUDE fastsegs.inc ;AN000; +INCLUDE fastopen.inc ;AN000; +INCLUDE SYSCALL.INC ; ;AN000; + +;----------------------------------------------------------------------- +; EQUATES +;----------------------------------------------------------------------- +Top_mem EQU 02h ;Top of memory index in PSP ;AN000; +Min_entry_num EQU 10 ;minimum name cache entries ;AN000; +Max_entry_num EQU 999 ;maximum name cache entries ;AN000; +Default_names EQU 34 ;default name cache entries ;AN000; +Debug EQU 0 ;for callinstall ;AN000; +Len_source_xname EQU 4 ;used for xname translate ;AN000; +No_siblings EQU -1 ;indicate no siblings ;AN000; +No_child EQU -1 ;indicate no children ;AN000; +No_backward EQU -1 ;no backward pt yet ;AN000; +Max_drives EQU 24 ;maximum number of drives allowed ;AN000; + + +; ----------------- MESSAGE EQUATES ------------------------------------- + +Not_enough_mem EQU 2 ;AN000; +Invalid_switch EQU 3 ;AN000; +Install1 EQU 4 ;AN000; +Already_install EQU 5 ;AN000; +Incorrect_param EQU 6 ;AN000; +Too_many_entries EQU 7 ;AN000; +Dup_drive EQU 8 ;AN000; +Invalid_extent EQU 11 ;AN000; +Invalid_name EQU 12 ;AN000; +Ems_failed EQU 13 ;AN000; +Ems_not_install EQU 14 ;AN000; +Invalid_drive EQU 15 ;AN000; +No_page_space EQU 16 ;AN000; +Bad_Use_Message EQU 17 +Many_Ext_Entries EQU 18 +Many_Name_Entries EQU 19 + + +;------------ E M S SUPPORT EQUATES ------------------------------- + +EMS_GET_STATUS EQU 40H ;AN000; +EMS_GET_NUM_PAGES EQU 42H ;AN000; +EMS_ALLOC_PAGES EQU 43H ;AN000; +EMS_MAP_HANDLE EQU 44H ;AN000; +EMS_GET_VERSION EQU 46H ;AN000; +EMS_SAVE_STATE EQU 47H ;AN000; +EMS_RESTORE_STATE EQU 48H ;AN000;;AN000; +EMS_PAGE_SIZE EQU 4FH ;AN000;;AN000; +EMS_2F_HANDLER EQU 1BH ;AN000;;AN000; + +IF NOT IBMCOPYRIGHT + +EMS_GET_COUNT EQU 5801H + +ELSE + +EMS_GET_COUNT EQU 5800H ;AN000; + +ENDIF + +EMS_GET_FRAME_ADDR EQU 5800H ;AN000; +EMS_HANDLE_NAME EQU 53H +EMS_INT EQU 67H ;AN000; +SINGLE_SEGMENT EQU 1 ;AN000; + + +;-------------------- STRUCTURES --------------------------------- + +PAGE_FRAME_STRUC STRUC ; EMS page frame structure ;AN000; + + PAGE_SEG DW ? ;EMS page segment ;AN000; + PAGE_NUM DW ? ;EMS page number (only one page is used) ;AN000; + +PAGE_FRAME_STRUC ENDS + +BUFFER_ENTRY_SIZE EQU TYPE PAGE_FRAME_STRUC + + +SUB_LIST STRUC ; Message handler sublist structure ;AN000; + DB 11 ; ;AN000; + DB 0 ; ;AN000; +DATA_OFF DW 0 ; offset of data to be inserted ;AN000; +DATA_SEG DW 0 ; offset of data to be inserted ;AN000; +MSG_ID DB 0 ; n of %n ;AN000; +FLAGS DB 0 ; Flags ;AN000; +MAX_WIDTH DB 0 ; Maximum field width ;AN000; +MIN_WIDTH DB 0 ; Minimum field width ;AN000; +PAD_CHAR DB 0 ; character for pad field ;AN000; +SUB_LIST ENDS ;AN000; + +;------------------------------------------------------------------------------- +; Following two segments are used to define external variable that +; are defined in two other segments. +;------------------------------------------------------------------------------- + +CSEG_OPEN SEGMENT PARA PUBLIC 'CODE' ; Cseg_Open segment + EXTRN Open_name_cache_seg:word + EXTRN Open_Name_Drive_Buff:word + EXTRN End_Open:byte + EXTRN Chk_Flag:word + EXTRN VECTOR_LOOKUP:dword ; jump vector inside Cseg_Main to make + ; a FAR call to Fopen LookUp function within + ; the segment +CSEG_OPEN ENDS + + +CSEG_SEEK SEGMENT PARA PUBLIC 'CODE' ; Cseg_Seek segment + EXTRN Seek_Extent_Drive_buff:word + EXTRN Seek_Name_Drive_buff:word + EXTRN Seek_Name_Cache_buff:word + EXTRN Seek_Name_Cache_Seg:word + EXTRN Seek_Num_Of_Drives:word + EXTRN Seek_Total_Ext_Count:word + EXTRN Seek_Total_Name_Count:word + EXTRN End_Seek:byte + EXTRN Check_Flag:word + EXTRN VECTOR_DELETE:dword ; jump vector inside Cseg_Seek to make + ; a FAR call to FSeek Delete function within + ; the segment +CSEG_SEEK ENDS + + + + + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ +CSEG_MAIN SEGMENT PARA PUBLIC 'CODE' ; MAIN segment + +; This segment is a continuation of the Cseg_Main segment in Fastopen.asm +; and contains code to initializes name and extent drive buffers +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ +ASSUME CS:cseg_main,DS:nothing,SS:stack,ES:nothing + +EXTRN MAIN:FAR ;AN000; + +IF BUFFERFLAG + +extrn restore_page_state:near ; HKN 8/25/88 + +extrn ems_save_handle1:word ; HKN +extrn ems_page_number:word ; HKN + +ENDIF + +EXTRN Main_Total_Ext_Count:word ;AN000; +EXTRN Main_Total_Name_Count:word ;AN000; +EXTRN Main_Name_Drive_Buff:word ;AN000; +EXTRN Main_Name_Cache_Buff:word ;AN000; +EXTRN Main_Name_Cache_Seg:word ;AN000; +EXTRN Main_Parambuff:byte ;AN000; +EXTRN Main_extent_drive_Buff:word ;AN000; +EXTRN Main_Num_Of_drives:word ;AN000; +EXTRN Main_Ext_Count:word ;AN000; +EXTRN Main_Ext_Cache_Size:word ;AN000; +EXTRN Main_EMS_FLAG:word ;AN000; +EXTRN Main_Res_Segs:word ;AN000; +EXTRN Main_EMS_PAGE_SEG:word ;AN000; +EXTRN Main_EMS_PAGE_SIZE:word ;AN000; + +EXTRN FOPEN_Insert:dword ;AN000; +EXTRN FOPEN_Update:dword ;AN000; +EXTRN FOPEN_Delete:dword ;AN000; +EXTRN FOPEN_Lookup:dword ;AN000; +IF BUFFERFLAG +EXTRN FOPEN_Purge:dword +ENDIF + +EXTRN FSEEK_Open:dword +EXTRN FSEEK_Close:dword +EXTRN FSEEK_Insert:dword +EXTRN FSEEK_Delete:dword +EXTRN FSEEK_Lookup:dword +EXTRN FSEEK_Truncate:dword +EXTRN FSEEK_Purge:dword + +;************************************************************************* +; +;SUBROUTINE: INIT_TREE (FASTINIT-1) +; +;FUNCTION: This routine builds 'N' name directory buffers under each drive +; header. The second half of this routine initializes the extent +; drive headers and makes the Fastopen code resident. +; +;INPUT: Drive_cache_header, End_Caches +; +;OUTPUT: Name_cache and Extent Cache entries installed for every +; drive requested. +; +;************************************************************************* + IF ($-Cseg_Main) MOD 16 ;AN000; + ORG ($-Cseg_Main)+16-(($-Cseg_Main) MOD 16) ;AN000; + ENDIF ;AN000; +End_Main1 label word ;AN000; + + +INIT_TREE: + mov ax,cseg_Main ;get addressiblity to ;AN000; + mov ds,ax ;DS --> Cseg_Main ;AN000; + ASSUME ds:cseg_Main ;AN000; + + cmp Main_Total_Name_Count,0 ;initialize Name drive headers?? ;AN000; + je Init_Ext_Drive_Hdrs ;no, init extent drive headers ;AN000; + +;----------------------------------------------------------------------------- +; Following code adds 'n' directory entry buffers to each Name Drive headers, +; depending on the value of 'n' specified with each drive ID +;----------------------------------------------------------------------------- + mov si,Main_Name_Drive_Buff ;SI-->first Name drive cache buff + mov bx,Main_Name_Cache_Buff ;BX-->Name cache buffer + xor dx,dx + xor ax,ax + + mov ax,Main_Name_Cache_Seg ;get addresability to CSeg_Init + mov ds,ax ;DS=addressablity to Cseg_Init + ASSUME ds:cseg_Init + +Set_Up_Cache: + mov [si].DCH_LRU_ROOT,bx ;set to point to first name + mov [si].DCH_NAME_BUFF,bx ;set to point to first name + mov cx,[si].DCH_num_entries ;get number of name records + +;----------------------------------------------------------------------------- +; set up MRU and LRU pointers +; AX points to last name record +; BX points to current name record +; DX points to next name record +;----------------------------------------------------------------------------- + mov [bx].nMRU_ptr,-1 ;make first MRU -1 + jmp short set_start + +Set_Up_Names: + mov [bx].nMRU_ptr,ax ;set up MRU + add ax,size name_record + +Set_Start: + mov [bx].nChild_ptr,no_child ;no children or siblings + mov [bx].nsibling_ptr,no_siblings ; right now + mov [bx].nBackward_ptr,no_backward + push es + push di + push ax + + push ds + pop es ;ES-->name cache buffer + ASSUME es:Cseg_Init + + mov ax, ' ' + mov di, bx + add di, nCmpct_Dir_Info ;blank out the Dir name area + stosb ;the directory buffer + stosw + stosw + stosw + stosw + stosw + + pop ax + pop di + pop es + + mov dx,bx ;get name offset + add dx,size name_record ;get start of next name + dec cx ;decrement num_entries + jcxz get_next_drive ;if zero - get next drive + mov [bx].nLRU_ptr,dx ;LRU pointer - next name + add bx,size name_record ; + jmp set_up_names + +Get_Next_Drive: + mov [bx].nLRU_ptr,-1 ;LRU pointer - next name + + mov [si].DCH_MRU_ROOT,bx ;set to point to last name + mov bx,dx ;get pointer to next name + cmp [si].dch_sibling_ptr,no_siblings ;is there any more to set up?? + jz Init_Ext_Drive_Hdrs ; no - set extent drive headers + add ax,size name_record ; yes - get next name directory buffer + add si,size drive_cache_header ;point to next drive header + jmp set_up_cache + + +;---------------------------------------------------------------------------- +; The following section initializes the Extent Drive Headers. +; DS has addressability to MAIN segment (CSEG_MAIN) and ES has +; addressability to Cache buffer segment (CSEG_INIT) +;---------------------------------------------------------------------------- +Init_Ext_Drive_Hdrs: + mov ax,cseg_Main ;AN000; + mov ds,ax ;DS-->Cseg_Main ;AN000; + ASSUME ds:cseg_Main ;AN000; + ;AN000; + cmp Main_Total_Ext_Count,0 ;initialize extent drive buffers ?? ;AN000; + jne init_extent_cache ;yes - continue + jmp Init_exit ;no - exit ;AN000; + +;============================================================================ +; Fill extent cache buffer with zeros. Otherwise a (-2) left in the buffer +; could generate a wrong Free buffer pointer since (-2) is the free buffer +; mark. + +Init_Extent_Cache: + mov cx, Main_Ext_Cache_Size ; CX = extent buffer size ;AN000; + mov si,Main_Extent_Drive_Buff ; SI-->start of extent cache buff ;AN000; + push ds ;AN000; + mov ax,Main_Name_Cache_Seg + mov ds,ax ; DS-->new init seg (init segment ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov al,0 ; pattern "0" ;AN000; + +Next_Byte: ; may be in Extended memory) + mov [si],al ;AN000; + inc si ;AN000; + LOOP next_byte ;AN000; + pop ds ; retore original init seg ID ;AN000; +;============================================================================ + + +Init_Set_Cache: + mov si,Main_Extent_Drive_Buff ; SI-->first extent drive header ;AN000; + mov cx,Main_num_of_drives ; number of drives + mov dx,0 ; drive counter + lea di,Main_ParamBuff ; DS:DI-->parameter buff contains ;AN000; + ; drive ID and number of extents ;AN000; + mov es,Main_name_cache_seg ; ES = addressability to Cseg_Init ;AN000; + ASSUME es:Cseg_Init ; ;AN000; + ;AN000; +INIT_LOOP: ; ES:SI-->cache buffer ;AN000; + push cx ; save counter ;AN000; + add di,dx ; points to drive ID of this driv ;AN000; + xor ax,ax ;AN000; + mov ax,[di+2] ; get Extent Count ;AN000; + cmp ax, -1 ; any extent under this drive ?? ;AN000; + je skip_this_drive ; no - dont create header for this ;AN000; + ; this drive + mov ax,0 ; *** for debugging sequence count + mov es:[si].EXTENT_COUNT,ax ; *** use this area for sequence counting + xor ax,ax ;AN000; + mov ax,[di] ; get drive ID from drive ID buff ;AN000; + mov es:[si].DRIVE_NUMBER,ax ; save drive ID in drive header ;AN000; + mov bx, size Drive_Header ;AN000; + add bx,si ; BX-->Free area ;AN000; + mov es:[si].FREE_PTR,bx ; pointing to free area ;AN000; + ;AN000; + mov es:[si].MRU_HDR_PTR,-1 ; mark OPEN QUEUE empty ;AN000; + mov es:[si].CLOSE_PTR,-1 ; make CLOSE QUEUE empty ;AN000; + xor ax,ax ;AN000; + mov ax,[di+2] ; get extent count (n) ;AN000; + mov cx, size Extent_Header ; get extent size ;AN000; + mul cx ; AX=total cache for this drive ;AN000; + mov es:[si].BUFF_SIZE,ax ; save it as initial available size ;AN000; + mov es:[si].FREE_SIZE,ax ; save it as initial free size + add ax, size Drive_Header ; (2/9/88) + add ax,si ; AX-->offset to next drive hdr ;AN000; + mov es:[si].Next_Drv_hdr_Ptr,ax ; save next drive header ptr in ;AN000; + ; current drive header ;AN000; + mov bx,ax ;AN000; + mov ax,si ; save current header pointer ;AN000; + mov si,bx ; DS:SI-->next drive header ;AN000; + ;AN000; +SKIP_THIS_DRIVE: ;AN000; + add dx,4 ; update index to next drive/extent ;AN000; + pop cx ; restore loop count ;AN000; + LOOP init_loop ; repeat for next drive number ;AN000; + ;AN000; + mov si,ax ;AN000; + mov es:[si].Next_Drv_hdr_Ptr,-1 ; mark current header as last + ; drive header +;---------------------------------------------------------------------------- +; Close handles 0 - 4 +;---------------------------------------------------------------------------- + mov bx,0 +Handle_Loop: + mov ah,03EH + INT 21H + inc bx + cmp bx,5 + jne Handle_Loop + +;---------------------------------------------------------------------------- +; Get PSP segment and find the program environment segment and deallocate +; the environment space. +;---------------------------------------------------------------------------- +INIT_EXIT: + push ds + mov si,0081H + mov ah,62H + INT 21H ; get program PSP segment ;AN000; + + mov ds,bx ; DS = PSP segment ;AN000; + mov si,02CH ; SI-->address of enviroment segment + mov ax,[si] ; AX = environment seg id + cmp ax,0 ; environment present ?? + je dont_dealloc ; no - dont deallocate + mov es,ax + mov ah,49H + INT 21H ; deallocate environment +Dont_Dealloc: + pop ds ; restore DS + +;---------------------------------------------------------------------------- +; Keep resident the Fastopen code and cache buffers. The size of the resident +; area is in (Main_Res_Segs). Size may vary depending on whether Fastopen or +; Fastseek or both or extent memory is specified. +;---------------------------------------------------------------------------- + +IF BUFFERFLAG + + call restore_page_state ; HKN 8/25/88 + +ENDIF + + mov ah,KEEP_PROCESS ;remain resident + mov al,0 ;return code + mov dx,Main_Res_Segs ;size of area in paragraph + INT 21h ;keep resident and then return + ;control to DOS + +;---------------------------------------------------------------------------- +; Calculate the size of the MAIN module in bytes. First potion of this +; segment can be found in the Fastopen.asm +;---------------------------------------------------------------------------- + IF ($-Cseg_Main) MOD 16 ;AN000; + ORG ($-Cseg_Main)+16-(($-Cseg_Main) MOD 16) ;AN000; + ENDIF ;AN000; +End_Main label word ;AN000; + + +CSEG_MAIN ENDS ; End of Cseg_Main segment +page + + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +CSEG_INIT SEGMENT PUBLIC PARA 'CODE' + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + ASSUME cs:cseg_init,ds:cseg_init,ss:stack,es:cseg_init + + EXTRN SYSPARSE:NEAR ;AN000; + EXTRN SYSLOADMSG:NEAR ;AN000; + EXTRN SYSDISPMSG:NEAR ;AN000; + +IF BUFFERFLAG + extrn save_ems_page_state:far ; HKN 8/25/88 +ENDIF + + +;---------------------------------------------------------------------------- +; The cache buffers start from the first location of Cseg_Init. +; First portion is the NAME DRIVE HEADERS, which is followed by +; NAME CACHE BUFFER, which is followed by EXTENT DRIVE HEADER. Under each +; extent drive header its cache buffer. 24 Name drive buffers are allocated +; during assembly time. Remaining drive and cache buffers are allocated +; during run time. Eventhough 24 name cache buffers are allocated during +; assembly time, this number may be reduced to the specified number of drive +; numbers during run time by overlaying other drive buffers over the unused ones. +; The initialization code will be overlayed by name and extent cache buffs +; during second half of the initialization which is in the MAIN module (see INit_Tree). +;----------------------------------------------------------------------------- + +Drive_header_start label byte ;Name cache drive buffer +Drive_Cache Drive_Cache_Header max_drives DUP (<>) ; header for 24 drives are reserved + +;----------------------------------------------------------------------------- +; Anything below this point will be overlayed by the Cache Buffers +; MSG retriever is placed after Cache buffer, so that the area can be +;----------------------------------------------------------------------------- +;============================================================================= +; Non_Resident Data Area +;============================================================================= +INIT_VECTOR DD INIT_TREE ;jump vector to INIT_TREE ;AN000; +MAIN_VECTOR DD MAIN ;entry point to MAIN routine ;AN000; +source_xname DB " :\",0 ;used for xname translate ;AN000; +target_xname DB 65 DUP (0) ;used for xname translate ;AN000; +user_drive db 0 ;current user drive ;AN000; +psp_seg dw 0 ;segment of psp ;AN000; +stack_seg_start dw 0 ;segment of temporary stack ;AN000; +stack_seg_end dw 0 ;AN000; +num_of_drives dw 0 ;number of user specified drives ;AN000; +Ext_Mem dw 0 ;=1 if exteded memory is enabled ;AN000; +drive_id db " :",0 ;AN000; +Parambuff db 50 dup (0) +Parmbuff_Ptr dw 0 ;AN000; +FRAME_COUNT dw 0 ;EMS frame count + +IF IBMCOPYRIGHT + +FRAME_BUFFER DB 30h DUP(0) ;EMS frame buffer + +ELSE + +FRAME_BUFFER DB 100h DUP(0) ; EMS frame buffer + +ENDIF + +IF BUFFERFLAG +FST_PAGE DW 0,0 ; holds the second highest page above 640k +ENDIF + +Cmdline_buff db 135 dup (0) ;command line buffer ;AN000; +name_cache_seg dw Cseg_Init ;default to Init1 seg ;AN000; +Ext_Count dw 0 ;total name extent entries ;AN000; +extent_drive_Buff dw 0 ;ptr to extent drive ;AN000; +name_cache_Buff dw 0 ;pointer to Name cache buffer ;AN000; +EMS_FLAG dw 0 ;EMI flag 1= if EMI is enabled ;AN000; +CHECK_QUEUE dw 0 ; = 1 if analyser is activated +RES_SEGS dw 010H+020H ;PSP SIZE + STACK SIZE resident segment size +EMS_PAGE_SEG DW 0 ;EMS code page segment ID ;AN000; +EMS_PAGE_NUM DW 0 ;EMS physical page number ;AN000; +Total_Ext_Count DW 0 ;Total extent entry count ;AN000; +Total_Name_Count DW 0 ;Total Name entry count ;AN000; +Total_Cache_Size DW 0 ;Total cache buffer size (name+extent) buffer ;AN000; +Name_Cache_Size DW 0 ;Total name cache size (header + entry buffs) +Name_Count DW 0 ;name entry count +Name_Drive_Buff DW 0 ;name driver buffer address ;AN000; +Ext_Cache_Size DW 0 ;extent buffer size ;AN000; +Open_SegID DW 0 ;SegId of Cseg_Open after relocation ;AN000; +Seek_SegID DW 0 ;SegId of Cseg_Seek " " ;AN000; +Init_SegID DW 0 ;SegId of Cseg_Init " " ;AN000; +MAIN_Size DW 0 ;size of Cseg_Main in Paragraph ;AN000; +OPEN_Size DW 0 ;size of Cseg_Open in paragraph ;AN000; +SEEK_Size DW 0 ;size of Cseg_Seek in paragraph ;AN000; + +;-----------------------------------------------------------------------; +; EMS Support ; +;-----------------------------------------------------------------------; +EXT_HANDLE DW ? ; EMS handle for reference ;AN000; +EMS_PAGESIZE DW ? ; EMS handle for reference ;AN000; +EMS_FRAME_ADDR DW ? ; EMS handle for reference ;AN000; +CURR_EMS_PAGE DB ? ; Current EMS page number ;AN000; +HANDLE_NAME DB 'FASTOPEN',0 ; EMS handle name ;AN000; + +IF BUFFERFLAG +SAVE_MAP_ADDR DD ? ; HKN 8/25/88 +ENDIF + +;--------------------------------------------------------------------------- +; PARSER Support +;--------------------------------------------------------------------------- +CURRENT_PARM DW 81H ;POINTER INTO COMMAND OF CUREENT OPERANT ;AN000; +NEXT_PARM DW 0 ;POINTER INTO COMMAND OF NEXT OPERAND ;AN000; +ORDINAL DW 0 ;ORDINAL NUMBER OF MAIN PARSER LOOP ;AN000; +ORDINAL1 DW 0 ;ORDINAL NUMBER OF COMPLEX ITEM LOOP ;AN000; +PREV_TYPE DB 0 ;PREVIOUS POSITIONAL PARAMETER TYPE + +;--------------------------------------------------------------------------- +; PRINT_STDOUT input parameter save area +;---------------------------------------------------------------------------- +SUBST_COUNT DW 0 ;message substitution count ;AN000; +MSG_CLASS DB 0 ;message class ;AN000; +INPUT_FLAG DB 0 ;Type of INT 21 used for KBD ;AN000; +MSG_NUM DW 0 ;message number ;AN000; + + +;---------------------------------------------------------------------------- +; Following three sublists are used by the Message Retriever +;---------------------------------------------------------------------------- +SUBLIST1 LABEL DWORD ;SUBSTITUTE LIST 1 + DB 11 ;sublist size ;AN000; + DB 0 ;reserved ;AN000; + DD 0 ;substition data Offset ;AN000; + DB 1 ;n of %n ;AN000; + DB 0 ;data type ;AN000; + DB 0 ;maximum field width ;AN000; + DB 0 ;minimum field width ;AN000; + DB 0 ;characters for Pad field ;AN000; + + +SUBLIST2 LABEL DWORD ;SUBSTITUTE LIST 2 + DB 11 ;sublist size ;AN000; + DB 0 ;reserved ;AN000; + DD 0 ;substition data Offset ;AN000; + DB 2 ;n of %n ;AN000; + DB 0 ;data type ;AN000; + DB 0 ;maximum field width ;AN000; + DB 0 ;minimum field width ;AN000; + DB 0 ;characters for Pad field ;AN000; + + + +;-------------------------------------------------------------------------- +; PARSER Control Blocks and Buffers +;-------------------------------------------------------------------------- + +PARMS label word + DW parmsx ;AN000; + DB 1 ; number of delemeters ;AN000; + DB 1 ; extra delimeters length ;AN000; + DB "=" ; extra delimeter expected ;AN000; + DB 0 ; extra end of line length ;AN000; + DB 0 ;AN000; + + +PARMSX label byte ;AN000; +par_min DB 1 ; min, max positional operands allowed ;AN000; +par_max DB 2 ; min, max positional operands allowed ;AN000; + DW Pos1 ; offset into positonal-1 control block ;AN000; + DW Pos2 ; offset into positonal-1 control block ;AN000; +par_sw DB 1 ; one switch ;AN000; + DW Switch ; offset into switch-1 control bloc ;AN000; + DB 0 ; no keywords ;AN000; + DB 0 ; 0 ;AN000; + + + +;------------------ POS2 CONTROL BLOCK -------------------------------------- + +POS1 label word ; positional-1 control definition +Pos1Type DW 0100H ; control type flag (drive only) ;AN000; + DW 0 ; function flags ;AN000; + DW Result ; offset into result buffer ;AN000; + DW value_pos1 ; offset value list buffer ;AN000; + DB 0 ; number of keyword/switch synonyms ;AN000; + + +Value_Pos1 label byte ; postional parameter value expected ;AN000; + DB 0 ; no values expected ;AN000; + + + +;---------------- POS1 CONTROL BLOCK ---------------------------------------- + +POS2 label word ; positional-2 control definition ;AN000; +Pos2Type DW 08502H ; Control type (complex/integer/drive/ ;AN000; + ; repeat) ;AN000; + DW 0 ; function flags ;AN000; + DW Result ; offset into result buffer ;AN000; + DW value_pos2 ; offset value list buffer ;AN000; + DB 0 ; number of keyword/switch synonyms ;AN000; + +Value_Pos2 label byte + DB 0 ; either (n) or (m) will be returned + + + +;--------------- RESULT BUFFER --------------------------------------------- + +RESULT label byte ; postional2 parameter result buffer ;AN000; +PosType DB ? ; type of operand returned ;AN000; +Postag DB ? ; type of item tage returned ;AN000; +synonym DW ? ; offset into synonyms returned ;AN000; +valuelo DW ? ; space for drive number/integer/strin ;AN000; +valuehi DW ? ;AN000; + + +;---------------- SWITCH CONTROL BLOCK ------------------------------------------ + +SWITCH label word ; switch control definition + DW 0 ; no match flag ;AN000; + DW 0 ; no function flags ;AN000; + DW Result ; offset into result buffer ;AN000; + DW value_sw1 ; offset value list buffer ;AN000; + DB 1 ; number of keyword/switch synonyms ;AN000; +E_Switch DB "/X" ; /X option for extended memory access ;AN000; + DB 0 ;AN000; + + +Result_sw1 label byte ; switch parameter result ;AN000; + DB ? ; type of operand returned ;AN000; + DB ? ; type of item tage returned ;AN000; +Swval DW ? ; offset into synonyms returned ;AN000; + DB ? ; switch value ;AN000; + + +Value_sw1 label byte ; switch parameter value expected ;AN000; + DB 0 ; no values expected ;AN000; + + + + + + + +;----------------------------------------------------------------------------- +; INIT (FASTINIT-2) +;----------------------------------------------------------------------------- +; +;SUBROUTINE: INIT +; +;FUNCTION: Performs FASTOPEN initialization function +; +; +;NOTE: This routine is the starting routine of FASTOPEN +; +;----------------------------------------------------------------------------- + +START: + ; on entry DS and ES -->PSP ;AN000; + push cs ; DS-->Cseg_Init ;AN000; + pop ds ;AN000; + ASSUME ds:cseg_init ;AN000; + mov psp_seg,es ; save PSP segment for later use ;AN000; + push cs ;AN000; + pop es ; ES-->Cseg_Init ;AN000; + ASSUME es:cseg_init ;AN000; + + CALL SYSLOADMSG ; Preload messages ;AN000; + jnc Parse_cmd_line ; If no error, parse command line ;AN000; + + mov ax,1 ;AN000; + CALL SYSDISPMSG ; display error ;AN000; + + mov ah,04ch ; Terminate ;AN000; + mov al,0 ; Errorlevel 0 (Compatible) ;AN000; + INT 021h ; exit to DOS + +Parse_Cmd_Line: ;AN000; + CALL PARSE ;Parse command line ;AN000; + lea si,parambuff ;drive ID buff address ;AN000; + mov ax,Total_name_Count ; ;AN000; + mov ax,Total_ext_Count ;AN000; + mov ax,num_of_drives ;AN000; + mov ax,ext_mem ;AN000; + jnc Check_Installed ;no, check if Fastopen already installed + jmp error_exit ;yes - exit ;AN000; + +Check_Installed: + CALL CHECK_INSTALL ; Fastopen installed ?? + jnc Save_SegIDs ; no - save segment IDs + jmp error_exit ; yes - exit + +;----------------------------------------------------------------------------- +; Set seg IDs of three segments. +;----------------------------------------------------------------------------- +Save_SegIds: + mov Open_SegID, Cseg_Open ;AN000; + mov Seek_SegID, Cseg_Seek ;AN000; + mov Init_SegID, Cseg_Init ;AN000; + +;----------------------------------------------------------------------------- +; Compute the size of segments and cache buffers. Setup a temporary stack +; to be used by the second half of initilization. +;----------------------------------------------------------------------------- + CALL CHECK_MEM ;See if we have enough memory ;AN000; + jnc chk_extended_mem ;yes, check for extended memory ;AN000; + jmp error_exit ;no - display not enough mem msg ;AN000; + +;----------------------------------------------------------------------------- +; Check if Extended Memeory is specified. If true, check if Extended memory is +; available. Get segid of one extended memory page. +;----------------------------------------------------------------------------- +Chk_Extended_Mem: + cmp ext_mem,1 ; enable EMS ?? ;AN000; + jne Set_Data_Areas ; no, set data areas ;AN000; + + CALL SET_EMS ; set expanded memory ;AN000; + jnc Set_Data_Areas ; if no error ;AN000; + jmp error_exit ; error exit ;AN000; + +;------------------------------------------------------------------------------ +; Copy Data and segid of Init segments to Main, Open and Seek segments. +; If code is relocated, segids have to be adjusted later. (See Adjust_SegID) +;------------------------------------------------------------------------------ +Set_Data_Areas: + CALL COPY_DATA ; copy data to other segments ;AN000; + +;----------------------------------------------------------------------------- +; Relocate code to extended memory if extended memory is specified or +; relocate in lower memory itself. +;----------------------------------------------------------------------------- +Relocate_Code: + CALL RELOCATE_SEGMENT ; Relocate the code cnd buffers ;AN000; + +;----------------------------------------------------------------------------- +; Adjust the segids and jump vectors in other segments after code relocation +;----------------------------------------------------------------------------- + CALL ADJUST_SEGIDS ; adjust segment ids after relocation ;AN000; + +;----------------------------------------------------------------------------- +; Display FASTOPEN INSTALLED message. This must be done prior to the actual +; installation. +;----------------------------------------------------------------------------- +Disp_Install_Msg: ; display FASTOPEN installed message + MOV AX,INSTALL1 ; message number ;AN000; + MOV MSG_NUM,AX ; set message number ;AN000; + MOV SUBST_COUNT,0 ; no message ;AN000; + MOV MSG_CLASS,-1 ; message class ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; show message ;AN000; + +;----------------------------------------------------------------------------- +; Install Fastopen +;----------------------------------------------------------------------------- + CALL INSTALL_FASTOPEN ; Install Fastopen ;AN000; + jnc Setup_Stack ; Installed Ok, setup stack ;AN000; + jmp error_exit ; error - exit + + +;---------------------------------------------------------------------------- +; Set Stack Values. This stack is used by the cache buffer initilization +; portion of the code. This stack area will be eventually overlayed and +; wont be used by either Fastopen or Fastseek functions in MAIN module. +;---------------------------------------------------------------------------- +SETUP_STACK: + nop ;AN000; + CLI ;no interrupts allowed during stach change ;AN000; + mov SS,Stack_Seg_Start ;set up new stack ;AN000; + mov SP,0 ; ;AN000; + STI ;interrupts ok now ;AN000; + jmp INIT_VECTOR ;Jump to Cseg_Main to do second + ;phase of the initialization +ERROR_EXIT: + mov al,1 ;set up return code + mov ah,exit ;set function code + INT INT_COMMAND ;exit to DOS + + + + +;---------------------------------------------------------------------------- +; CHECK_INSTALL +;---------------------------------------------------------------------------- +; Input: None +; +; Output: +; IF Carry = 0 - Fastopen is not already installed +; +; IF Carry = 1 - Fastopen is already installed +; +;---------------------------------------------------------------------------- +; Use CALLINSTALL macro to see if FASTOPEN is already installed. +; If carry flag set then FASTOPEN is installed. In this case display +; Already Installed message. +;---------------------------------------------------------------------------- + +CHECK_INSTALL PROC NEAR + + push ax ;save every registers that may + push bx ;be destroyed by DOS + push cx + push dx + push si + push di + push bp + + push ds + mov bx, 1 ;Fastopen function code + mov si, -1 ;special check install code + CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed + pop ds + jc Install_Msg ;yes, display already installed + ;message +;---------------------------------------------------------------------------- +; Check if Fastseek function is enabled. If true display Installed message +;---------------------------------------------------------------------------- ;AN000; + push ds ;AN000; + mov si, -1 ;special check installed code + mov bx, 2 ;for Fastseek + CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed ;AN000; + pop ds ;AN000; + jnc Chk_Install_Exit ; no, exit ;AN000; + +Install_Msg: ;installed previously display message + MOV AX,ALREADY_INSTALL ;message number ;AN000; + MOV MSG_NUM,AX ;set message number ;AN000; + MOV SUBST_COUNT,0 ;no message substitution ;AN000; + MOV MSG_CLASS,-1 ;message class ;AN000; + MOV INPUT_FLAG,0 ;no input ;AN000; + CALL PRINT_STDOUT ;show message "Already Installed" + stc + +Chk_Install_Exit: + pop bp ;restore registers + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret ;return + +CHECK_INSTALL ENDP + + + + + +;---------------------------------------------------------------------------- +; INSTALL_FASTOPEN +;---------------------------------------------------------------------------- +; Input: Addrss of entry point to Fastopen resident code +; +; Output: +; IF Carry = 0 +; Entry point to FASTOPEN resident code set +; +; IF Carry = 1 Error +; +; Calls: none +;---------------------------------------------------------------------------- +; Use CALLINSTALL macro to see if FASTOPEN is already installed. +; If FASTOPEN is not installed, install it. +; If carry flag set then FASTOPEN is installed. In this case display +; already installed message. +;---------------------------------------------------------------------------- + +INSTALL_FASTOPEN PROC NEAR + + push ax ;Save every registers,point reg since + push bx ;DOS may destroy it. + push cx + push dx + push si + push di + push bp + + cmp Total_Name_Count, 0 ;FastOpen enabled ?? ;AN000; + je Install_Ext ;no - jump + + push ds ;yes - install fastopen + mov bx, 1 ;tell DOS that this is the + lds si,Main_Vector + CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed + pop ds + jc Install_Exit ;error - exit + +;---------------------------------------------------------------------------- +; Check if Fastseek functions are enabled. If true, pass MAIN routine entry +; point and the Fastseek enabled information to DOS +;---------------------------------------------------------------------------- ;AN000; +Install_Ext: + cmp Total_Ext_Count, 0 ; Fastseek enabled ?? ;AN000; + jne ext_install ; yes - install fastseek ;AN000; + clc ;AN000; + jmp short Install_Exit ; no, exit ;AN000; + +Ext_Install: + push ds ;AN000; + mov bx, 2 ;tell DOS that this is the ;AN000; + lds si,Main_Vector ;fastseek entry point ;AN000; + CALLINSTALL fastopencom,multdos,42 ;see if fastopen installed ;AN000; + pop ds ;AN000; + jnc short install_exit + jmp short install_exit + +Installx_Msg: ;installed previously display message + MOV AX,ALREADY_INSTALL ;message number ;AN000; + MOV MSG_NUM,AX ;set message number ;AN000; + MOV SUBST_COUNT,0 ;no message substitution ;AN000; + MOV MSG_CLASS,-1 ;message class ;AN000; + MOV INPUT_FLAG,0 ;no input ;AN000; + CALL PRINT_STDOUT ;show message "Already Installed" + stc + +Install_Exit: + pop bp ;restore registers + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret ;return + +INSTALL_FASTOPEN ENDP + + + + + + +;---------------------------------------------------------------------------- +; CHECK_MEM +;---------------------------------------------------------------------------- +; Function: Compute the total size of memory required by the Fasteopen. +; This includes both code and the cache buffers. +; +; Input: Name_Count, extent_count, Drive_cache, num_of_drives +; +; Output: Memory is validated, Resident segment size is calculated +; Temporary stack segment is set +;---------------------------------------------------------------------------- +CHECK_MEM PROC NEAR ; DS-->Cseg_init + +;** Compute the total resident segment size and then add the cache buffer +;** size. The Resident segment size should be adjusted again after relocation. + + mov Total_Cache_Size,0 ;reset total cache size (Name +Ext) + mov Name_Cache_Size,0 ;reset Name cache buffer size + mov ax, offset End_Main ;size of Main_Seg in bytes ;AN000; + add ax,15 ;AN000; + mov cl,4 ;convert size to paragraph ;AN000; + shr ax,cl ;by dividng by 16 ;AN000; + mov MAIN_Size, ax ;save MAIN segment size in para ;AN000; + add Res_Segs,ax ;update resident seg count ;AN000; + ;AN000; + mov ax, offset End_Open ;size of Open_Seg in bytes ;AN000; + add ax,15 ;AN000; + mov cl,4 ;convert it to paragraph ;AN000; + shr ax,cl ;AN000; + mov OPEN_Size, ax ;save OPEN segment size in para ;AN000; + add RES_SEGS,ax ;update resident seg count ;AN000; + ;AN000; + mov ax, offset End_Seek ;add size of Seek_Seg + add ax,15 ;AN000; + mov cl,4 ;AN000; + shr ax,cl ; convert to para (divide by 16) ;AN000; + mov SEEK_Size, ax ;save Seek segment size in para ;AN000; + add RES_SEGS,ax ;update resident seg count ;AN000; + +;---------------------------------------------------------------------------- +; Calculate the size of the NAME DRIVE HEADER BUFFERS +;---------------------------------------------------------------------------- + xor ax,ax ;reset the cache size register + cmp total_Name_Count,0 ;Fastopen enabled ?? + je Check_ext_cache ;no - compute extent cache size + + mov bx,offset DRIVE_CACHE ;get beginning of cache buff + xor ax,ax + mov al,size drive_cache_header ;get size of one name entry + mul Num_Of_drives ;get total needed for drive cache + add ax,bx ;set up correct offset + add ax,15 ;round up to paragraph boundary + mov cl,4 + shr ax,cl ;convert to paragraphs + add RES_SEGS,ax ;update resident seg count + mov Total_Cache_Size, ax ;update total cache buff size + mov Name_Cache_Size, ax ;size in paragraph + +; Calculate the offset of the Name cache buffers + shl ax,cl ;AX = offset to Name cache buff + mov NAME_CACHE_BUFF,ax ;save Name cache address + +;----------------------------------------------------------------------------- +; Compute the size of the NAME CACHE buffer +;----------------------------------------------------------------------------- + mov ax,size Name_Record + mul Total_Name_Count + add ax,15 ;round up to paragraph boundary + mov cl,4 + shr ax,cl ;convert to paragraphs ( divide 16) + add RES_SEGS,ax ;AX = End of Name cache buffers + add Total_Cache_Size,ax ;update total cache buff size + add Name_Cache_Size, ax ; + +Check_Ext_Cache: + cmp total_ext_count,0 ;Fastseek enabled ?? + je Set_Stack ;no, set stack + +;--------------------------------------------------------------------------- +; Compute the size of the Extent cache including drive headers +;--------------------------------------------------------------------------- +Compute_Ext_Cache: ;calculate the extent buff offset + mov ax,Name_Cache_Size + mov cl,4 + shl ax,cl ;convert to bytes ( multiply by 16) ;AN000; + mov EXTENT_DRIVE_BUFF, ax ;save EXTENT DRIVE BUFFER address ;AN000; + + mov ax, size Drive_Header ;AN000; + mul num_Of_drives ;calc size of drive header buff ;AN000; + mov bx,ax ;save AX in BX ;AN000; + mov ax, size Extent_Header ;size of one extent ;AN000; + mul Total_Ext_Count ;calc size of extent buffers ;AN000; + add ax,bx ;AX = size of extent buff in bytes ;AN000; + mov ext_cache_size,ax ;save it for later use ;AN000; + add ax,15 ;round up to paragraph boundary ;AN000; + mov cl,4 ;AN000; + shr ax,cl ;convert to paragraphs ;AN000; + add RES_SEGS,ax ;update resident seg count ;AN000; + add Total_Cache_Size,ax ;update total cache buff size + + +;---------------------------------------------------------------------------- +; Setup stack segment followed by the extent cache buffers. This is a +; temporary stack used by the drive buffer initilization code in the +; Cseg_Main segment. This stack will be overlayed by the cache buffers. +;---------------------------------------------------------------------------- +Set_Stack: + mov ax,RES_SEGS ;AX=size of code and buffs in para + add ax,PSP_Seg ;AX=segID of stack + mov Stack_Seg_Start,ax ;start of the new STACK + add ax,20h ;add the size of the stack + mov Stack_Seg_End,ax ;get end of what we need + + push ds ; + mov ds,PSP_Seg ;access PSP for memory size + mov si,Top_mem + LODSW ;get total memory size + pop ds + sub ax,Stack_Seg_End ;see if there is enough for us + jc Not_Enough_Memory ;no - error exit + sub ax,1000h ;will there still be 64K ?? + jnc Check_Reloc_Size ;and return + +Not_Enough_Memory: + MOV AX,NOT_ENOUGH_MEM ;message number ;AN000; + MOV MSG_NUM,AX ;set message number ;AN000; + MOV SUBST_COUNT,0 ;no message substitution ;AN000; + MOV MSG_CLASS,-1 ;message class ;AN000; + MOV INPUT_FLAG,0 ;no input ;AN000; + CALL PRINT_STDOUT ;show message "Insufficient Memory" ;AN000; + stc ;set error flag ;AN000; + jmp short Set_Mem_Ret ;return ;AN000; + +;------------------------------------------------------------------------------ +; If relocation is needed, then recalculate the size of resident segment +; If extended memory relocation, OPEN, SEEK and INIT segments will be +; eliminated from the current resident seg. +;----------------------------------------------------------------------------- +Check_Reloc_Size: + cmp Ext_Mem,1 ; extended memory relocation ?? + jne Set_Mem_Exit ; no - exit ;AN000; + +;----------------------------------------------------------------------------- +; Check to see that the both code and the cache buffers fit in the +; exteneded memory one 16K page. Since the entire code segment and the +; cache buffers are going to be moved to XMA, that amount should be +; reduced from the size that should reside in the low memory. +;----------------------------------------------------------------------------- + xor ax,ax + xor bx,bx + cmp total_Name_Count,0 ;Fastseek enabled ?? + je Skip_name_size ;no - skip name size + mov ax, OPEN_SIZE ;size of Open seg in para ;AN000; +Skip_Name_Size: + cmp total_ext_count,0 ;Fastseek enabled ?? + je Skip_Ext_Size ;no - skip extent size + mov bx, SEEK_Size ;size of Seek_Seg in para ;AN000; +Skip_Ext_Size: + add ax,bx + add ax, Total_Cache_Size ;size of Init_Seg in para ;AN000; + cmp ax, 0404H ;Less than 16K ?? ;AN000; + jge Not_Enough_Space ;no - display message ;AN000; + + mov ax, OPEN_SIZE ;size of Open seg in para ;AN000; + add ax, SEEK_Size ;size of Seek_Seg in para ;AN000; + add ax, Total_Cache_Size ;reduce resident seg size ;AN000; + sub RES_SEGS,ax ;update resident seg count ;AN000; + +;----------------------------------------------------------------------------- +; If the code is to be moved to extended memory. There is no reason to +; keep Init_Tree in main memory. Remove that also to save space in base memory +;----------------------------------------------------------------------------- + mov ax, offset End_Main1 ;size of Main_Seg until Init_Tree (bytes) ;AN000; + add ax,15 ;AN000; + mov cl,4 ;convert size to paragraph ;AN000; + shr ax,cl ;by dividng by 16 ;AN000; + mov bx,Main_Size ;bx=total size of Main seg including Init_Tree + sub bx,ax ;bx=size after reducing Init_Tree + sub RES_SEGS,bx ;update base memory resident seg count ;AN000; + jmp short Set_Mem_Exit + ; +Not_Enough_Space: + MOV AX,NO_PAGE_SPACE ; not enough space in EMS page + MOV MSG_NUM,AX ; set message number + MOV SUBST_COUNT,0 ; no message + MOV MSG_CLASS,-1 ; message class + MOV INPUT_FLAG,0 ; no input + CALL PRINT_STDOUT ; display message + mov Ext_Mem, 0 ; RESET XMA FLAG + stc + jmp set_mem_ret + +Set_Mem_Exit: ;AN000; + clc ;AN000; + +Set_Mem_Ret: + ret ;AN000; + +CHECK_MEM endp + + + + + +;---------------------------------------------------------------------------- +; RELOCATE +;---------------------------------------------------------------------------- +; Function: Relocate Fastopen code and buffer in base memory or in +; Extended Memory. If base memory relocation, then +; relocate Cseg_Seek over Cseg_Open segment if the user +; didn't specify Fastopen (n). Relocate Cseg_Init over Cseg_Seek +; if user didn't specify Fastseek feature(m). If extended memory +; relocation, copy Cseg_Open, Cseg_Seek and Cseg_Init to +; a single page in extented memory if both Fastopen and Fastseek +; (n and m) are specified. Copy Cseg_open and Cseg_Init only if Fastseek +; feature (m) is not specified. Copy Cseg_Seek and Cseg_Init if +; FastOpen feature (n) is not specified +; +;---------------------------------------------------------------------------- + +RELOCATE_SEGMENT PROC NEAR + cmp Ext_Mem,1 ; Extended memory enabled ?? ;AN000; + je Set_Seg_Ids ; yes - do extented memory relocation + jmp Reloc_Low_Mem ; no - do low memory relocation ;AN000; + +;---------------------------------------------------------------------------- +; Move Fastopen, FastSeek or both to the Extended memory +;---------------------------------------------------------------------------- +Set_Seg_Ids: + cld ; clear direction flag (increment si and di) + cmp Total_Name_Count,0 ; Fastopen enabled ?? + jne Set_Open_Seg ; yes - set open seg in extented memory + + mov ax,EMS_Page_Seg ; AX = seg id of Cseg_Seek in ext mem + mov Seek_SegID,ax ; save it + jmp Set_Seek_Seg ; no - fastopen, set Seek segment + +;----------------------------------------------------------------------------- +; ---- Extended Memory Relocation ----- +; Setup Cseg_Open segment in Extended Memory +;------------------------------------------------------------------------------ +Set_Open_Seg: + mov ax,Cseg_Init ; + mov ds,ax ; DS-->Cseg_Init + ASSUME ds:Cseg_Init + mov ax,EMS_Page_Seg ; AX = seg id of Cseg_Open in ext mem + mov Open_SegID,ax ; save it + +Copy_Open_Seg: + mov ax, offset End_Open ; size of Open seg in bytes ;AN000; + mov cl,1 + shr ax,cl ; convert to words ;AN000; + mov cx,ax ; CX = number of WORDS to transfer ;AN000; + xor si,si ; offset of the source in low memory ;AN000; + xor di,di ; offset of the destination in XMA ;AN000; + mov ax,Cseg_Open ; set source segID ;AN000; + mov ds,ax ; DS-->Cseg_Open ;AN000; + ASSUME ds:Cseg_Open ;AN000; + mov ax,Open_SegID ; set destination XMA seg id ;AN000; + mov es,ax ; ES-->Extended memory page ;AN000; + ASSUME es:nothing ;AN000; + REP MOVSW ; copy Open segment to extended memory + ; SI-->Cseg_Seek segment + mov ax,Cseg_Init ; no - only Fastseek specified + mov ds,ax ; DS-->Cseg_Init + ASSUME ds:Cseg_Init + cmp Total_Ext_Count,0 ; Fastseek enabled ?? + jne Set_Seek_id ; yes -set seek id + + mov ax,Cseg_Seek ; only Fastopen is enabled ;AN000; + sub ax,Cseg_Open ; AX = size of Cesg_Open segment ;AN000; + add ax,EMS_Page_Seg ; AX = new seg ID of Cseg_Init in ext ;AN000; + mov Init_SegID,ax ; only if Fastopen is specified ;AN000; + jmp Copy_Init_Seg ; copy init_seg to extended memory + +;----------------------------------------------------------------------------- +; Setup Cseg_Seek segment in Extended Memory +;------------------------------------------------------------------------------ +Set_Seek_Id: + mov ax,Cseg_Seek ; + sub ax,Cseg_Open ; AX = size of Cesg_Open segment ;AN000; + add ax,EMS_Page_Seg ; AX = new seg ID of Cseg_Seek in ;AN000; + mov Seek_SegID,ax ; extended memory ;AN000; + jmp Copy_Seek_Seg + +Set_Seek_Seg: ; only Fastseek is specified + xor si,si ; offset of the source in low memory ;AN000; + xor di,di ; offset of the destination in XMA ;AN000; + +Copy_Seek_Seg: + mov ax, offset End_Seek ;size of Cseg_Seek in bytes ;AN000; + mov cl,1 + shr ax,cl ; convert to words ;AN000; + mov cx,ax ; CX = number of WORDS to transfer ;AN000; + xor si,si ; offset of the source in low memory ;AN000; + xor di,di ; offset of the destination in XMA ;AN000; + mov ax,Cseg_Seek ; set source segID ;AN000; + mov ds,ax + ASSUME ds:Cseg_Seek ;AN000; + mov ax,Seek_SegID ; set destination XMA seg id ;AN000; + mov es,ax + ASSUME es:nothing ;AN000; + REP MOVSW ; copy Seek segment to extended memory + ; SI-->Cseg_Init segment + mov ax,Cseg_Init ; no - only Fastseek specified + mov ds,ax ; DS-->Cseg_Init + ASSUME ds:Cseg_Init + cmp total_Name_Count,0 ; FastOpen enabled ?? + jne Set_Init_Seg ; yes - set Init Segment + + mov ax,Cseg_Init + sub ax,Cseg_Seek ; ax = size of Cseg_Seek + add ax,EMS_Page_Seg ; Cseg_Init id only if Fastseek is specified + mov Init_SegID,ax ; + jmp copy_init_seg ; copy cseg_init area to extentde memory + +;----------------------------------------------------------------------------- +; Setup Cseg_Init segment in Extended Memory +;------------------------------------------------------------------------------ +Set_Init_seg: + mov ax,Cseg_Init ; yes - set init seg id + sub ax,Cseg_Open ; AX = size of Open_Cseg+Seek_Cseg + add ax,EMS_Page_Seg ; new Cseg_Init id in XMA if both + mov Init_SegID,ax ; Fastopen and Fastseek are enabled ;AN000; + +Copy_Init_Seg: ; comes here if no Cseg_Seek is required + xor si,si ; offset of the source in low memory ;AN000; + xor di,di ; offset of the destination in XMA ;AN000; + mov ax, Total_Cache_Size ; size of Init seg area to be copied ;AN000; + mov cl,4 ; in paragraph ;AN000; + shl ax,cl ; convert to number of bytes ;AN000; + mov cl,1 ; + shr ax,cl ; convert to number ofwords ;AN000; + mov cx,ax ; CX = number of WORDS to transfer ;AN000; + mov ax,Cseg_Init ; set source segID ;AN000; + mov ds,ax + ASSUME ds:Cseg_Init ;AN000; + mov ax,Init_SegID ; set destination XMA seg id ;AN000; + mov es,ax + ASSUME es:nothing ;AN000; + REP MOVSW ; copy Init segment to extended memory + jmp reloc_exit ; then return ;AN000; + + +;NOTE: No need to adjust the resident segment size (Res_Segs) since it is +; done in the routine (Check_Mem). + + +;----------------------------------------------------------------------- +; ---- LOW MEMORY RELOCATION ---- +; Reloctae FastOpen or FastSeek or both in the low memory and adjust the +; resident size of the code. +;----------------------------------------------------------------------- +Reloc_LOW_Mem: + cmp Total_Name_Count,0 ; Fastopen function enabled ?? + jne Check_Seek ; yes, check Fastseek function + +; Relocate Cseg_Seek segment over Cseg_Open segment + mov ax, offset End_Seek ; size of Cseg_Seek in bytes ;AN000; + mov cl,1 + shr ax,cl ; convert to words ;AN000; + mov cx,ax ; CX = number of WORDS to transfer ;AN000; + xor si,si ; offset of the source ;AN000; + xor di,di ; offset of the destination ;AN000;;AN000; + mov ax,Cseg_Seek ; set source segID ;AN000; + mov ds,ax ; DS:SI-->Cseg_Seek ;AN000; + ASSUME ds:Cseg_Seek ;AN000; + mov ax,Cseg_Open ; set destination seg id ;AN000; + mov es,ax ; ES:DI--> Cseg_Open ;AN000; + ASSUME es:Cseg_Open ;AN000; + ;AN000; + REP MOVSW ; relocate code and cache buffer + mov ax,OPEN_Size ; reduce Open seg size from + sub RES_SEGS,ax ; the resident size + +;----------------------------------------------------------------------- +; Compute the new segID after relocation and save it +;----------------------------------------------------------------------- + mov ax,Cseg_Init ; + mov ds,ax ; DS-->Cseg_Init + ASSUME ds:Cseg_Init + mov ax,Cseg_Open ; AX = seg id of Cseg_Open in ext mem + mov Seek_SegID,ax ; save it + ;AN000; + mov ax,Seek_Size ; AX = size of Cseg_Seek + add ax,Cseg_Open ; AX = new seg ID of Cseg_Init in ext ;AN000; + mov Init_SegID,ax ; save it ;AN000; + jmp short reloc_exit ;then return ;AN000; + +Check_Seek: + cmp Total_Ext_Count,0 ; Fastseek function enabled ?? + jne Reloc_Exit ; yes, no need for relocation + +;----------------------------------------------------------------------- +; Relocate first portion of the Cseg_Init over Cseg_Seek segment. The size +; this portion should be same as the current size of Drive cache headers +; Anything more will overlay on Cseg_Init code which is currently active. +;----------------------------------------------------------------------- + mov ax, size Drive_Cache_Header ; size of one drive cache hdr + mov cx,Max_Drives ; CX = maximum number of drives + mul cx ; AX = size of Cseg_Init portion + mov cl,1 + shr ax,cl ; AX = size of portion in words + mov cx,ax ; CX = number of WORDS to transfer ;AN000; + mov si,0 ; offset of the source ;AN000; + mov di,0 ; offset of the destination ;AN000;;AN000; + mov ax,Cseg_Init ; set source segID ;AN000; + mov ds,ax ; DS:SI-->Cseg_Seek ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov ax,Cseg_Seek ; set destination seg id ;AN000; + mov es,ax ; ES:DI--> Cseg_Open ;AN000; + ASSUME es:Cseg_Seek ;AN000; + ;AN000; + REP MOVSW ; relocate Cseg_Init over Cseg_Seek + mov ax,Seek_Size ; reduce Seek seg size from + sub RES_SEGS,ax ; the resident size + +;----------------------------------------------------------------------- +; Compute the new segID after reloaction and save it +;----------------------------------------------------------------------- + mov ax,Cseg_Init ; + mov ds,ax ; DS-->Cseg_Init + ASSUME ds:Cseg_Init + mov ax,Cseg_Seek ; AX = seg id of Cseg_Open in ext mem + mov Init_SegID,ax + +Reloc_Exit: +; copy the latest RES_SEGS size to Cseg_Main + mov ax,Cseg_Init ; ;AN000; + mov ds,ax ; DS-->Cseg_Init ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov ax,Cseg_Main ; set destination seg id ;AN000;;AN000; + mov es,ax ; ES--> Cseg_Main ;AN000; ;AN000; + ASSUME es:Cseg_Main ;AN000;;AN000; + mov ax,Res_Segs ;AN000; + mov es:Main_Res_Segs,ax ; save it ;AN000; + + RET ;AN000; + +RELOCATE_SEGMENT ENDP + + + + + + +;----------------------------------------------------------------------- +; Procedure: COPY_DATA +;----------------------------------------------------------------------- +; Copy data values from Cseg_Init to other segments. I the code is relocated, +; seg IDs should be updated after relocation. This is done in "Update_SegID" +; +; Input: Variables inside Cseg_Open, CsegSeek and Cseg_Main segments +; +; Output: Data values copied to the above segments +; +; +;----------------------------------------------------------------------- + +COPY_DATA PROC NEAR + + mov ax,cseg_init ;AN000; + mov ds,ax ;DS--> Cseg_Init ;AN000; + ASSUME ds:Cseg_init ;AN000; + mov ax,cseg_Main ;AN000; + mov es,ax ;ES--> CSEG_MAIN ;AN000; + ASSUME es:Cseg_Main ;AN000; + ;AN000; + mov es:Main_Name_Cache_Seg, Cseg_Init ;AN000; + mov ax,Num_Of_Drives ;AN000; + mov es:Main_Num_Of_Drives,ax ;AN000; + mov ax,ext_count ;AN000; + mov es:Main_Ext_Count,ax ;AN000; + mov ax,Extent_Drive_Buff ;AN000; + mov es:Main_Extent_Drive_Buff,ax ;AN000; + mov ax,Name_Cache_Buff ;AN000; + mov es:Main_Name_Cache_Buff,ax ;AN000; + mov ax,Name_Drive_Buff ;AN000; + mov es:Main_Name_Drive_Buff,ax ;AN000; + mov ax,Ems_Flag + mov es:Main_EMS_FLAG,ax + mov ax,EMS_PAGE_Seg ;AN000; + mov es:Main_EMS_PAGE_Seg,ax ;AN000; + +IF BUFFERFLAG + mov ax, EMS_PAGE_NUM + mov es:ems_page_number, ax ;HKN +ENDIF + + mov ax,EMS_PAGE_SIZE ;AN000; + mov es:Main_EMS_PAGE_SIZE,ax ;AN000; + mov ax,Total_Ext_Count ;AN000; + mov es:Main_Total_Ext_Count,ax ;AN000; + mov ax,Ext_Cache_Size ;AN000; + mov es:Main_Ext_Cache_Size,ax ;AN000; + mov ax,Total_Name_Count ;AN000; + mov es:Main_Total_Name_Count,ax + +; Copy drive buffer to MAIN segment + lea si,ParamBuff ;AN000; + lea di,es:Main_ParamBuff ;AN000; + mov cx,50 ;AN000; + +Paramloop: + mov al,[si] ;AN000; + mov es:[di],al ;AN000; + inc si ;AN000; + inc di ;AN000; + LOOP paramloop ;AN000; + +;----------------------------------------------------------------------- +; Copy data values to OPEN segment (Cseg_Open) +;----------------------------------------------------------------------- + mov ax,cseg_Open ;AN000; + mov es,ax ;ES--> CSEG_Open ;AN000; + ASSUME es:Cseg_Open ;AN000; + mov si,offset drive_cache ;AN000; + mov es:Open_Name_Drive_Buff,si ;AN000; + mov es:Open_Name_Cache_Seg,Cseg_Init ;AN000; + mov ax,check_Queue + mov es:chk_Flag,ax + +;----------------------------------------------------------------------- +; Copy data values to SEEK segment (Cseg_Seek) for Fastseek functions +;----------------------------------------------------------------------- + mov ax,cseg_Seek ;AN000; + mov es,ax ;ES--> CSEG_Seek ;AN000; + ASSUME es:Cseg_Seek ;AN000; + mov si,Extent_Drive_Buff ;AN000; + mov es:Seek_Extent_Drive_Buff,si ;AN000; + mov es:Seek_Name_Cache_Seg,Cseg_Init ;AN000; + mov ax,Num_Of_Drives ;AN000; + mov es:Seek_Num_Of_Drives,ax ;AN000; + mov ax,Total_Ext_Count ;AN000; + mov es:Seek_Total_Ext_Count,ax ;AN000; + mov ax,Total_Name_Count ;AN000; + mov es:Seek_Total_name_Count,ax ;AN000; + mov ax,Name_Cache_Buff ;AN000; + mov es:Seek_Name_Cache_Buff,ax ;AN000; + mov ax,Name_Drive_Buff ;AN000; + mov es:Seek_Name_Drive_Buff,ax ;AN000; + mov ax,check_Queue + mov es:check_Flag,ax + ;AN000; + mov ax,cseg_Init ;AN000; + mov es,ax ;ES addressability to CSEG_Init ;AN000; + ASSUME es:Cseg_Init ;AN000; + ;AN000; + ret + +COPY_DATA ENDP + + + + +;----------------------------------------------------------------------- +; Procedure: ADJUST_SEGIDS +;----------------------------------------------------------------------- +; Function: Adjust segment Ids of various segments after relocation +; +; Input: SegID Vectors +; +; Output: SegIDs vectors are adjusted +; +; Note: The following segid and vectors are set previously either during +; link time or during initialization time. These SegIDS needs to +; be changed after the code and buffers are relocated. +;----------------------------------------------------------------------- + +ADJUST_SEGIDS PROC NEAR + + mov ax,Cseg_Init ;AN000; + mov ds,ax ;DS addressability to Cseg_Init ;AN000; + ASSUME ds:Cseg_init ;AN000;;AN000; + mov ax,cseg_Main ;AN000; + mov es,ax ;ES addressability to CSEG_MAIN ;AN000; + ASSUME es:Cseg_Main ;AN000; + + mov bx, Init_segID ; copy seg ID of Init_Seg to ;AN000; + mov es:Main_Name_Cache_Seg, bx ; Main seg ;AN000; + + cmp Total_Name_Count,0 ; Fastopen function enabled ?? + je Adjust_Seek ; yes, Adjust Cseg_Seek ID + + mov ax,Open_SegID ;AN000; + mov es,ax ; ES addressability to CSEG_Open ;AN000; + ASSUME es:Cseg_Open ; copy segid of init_seg to ;AN000; + mov es:Open_Name_Cache_Seg, bx ; Open segment + +Adjust_Seek: + cmp Total_Ext_Count,0 ;Fastopen function enabled ?? + je Adjust_Vectors ;yes, check Fastseek function + + mov ax,Seek_SegID ;AN000; + mov es,ax ; ES addressability to CSEG_Seek ;AN000; + ASSUME es:Cseg_Seek ;AN000; + mov es:Seek_Name_Cache_Seg, bx ;AN000; + + +; Adjust seg ids of jump vectors to Fastopen and Fastseek functions ;AN000; +Adjust_Vectors: + mov ax,cseg_Main ;AN000; + mov es,ax ;ES addressability to CSEG_MAIN ;AN000; + ASSUME es:Cseg_Main ;AN000; + ;DS addressability to Cseg_Init + mov ax, Open_SegID ;AN000; + mov word ptr es:FOPEN_Insert + word, ax ;AN000; + mov word ptr es:FOPEN_Update + word, ax ;AN000; + mov word ptr es:FOPEN_Delete + word, ax ;AN000; + mov word ptr es:FOPEN_Lookup + word, ax ;AN000; +IF BUFFERFLAG + mov word ptr es:FOPEN_Purge + word, ax ;TEL 9/29 +ENDIF + + + mov ax, Seek_SegID ;AN000; + mov word ptr es:FSEEK_Open + word, ax ;AN000; + mov word ptr es:FSEEK_Close + word, ax ;AN000; + mov word ptr es:FSEEK_Insert + word, ax ;AN000; + mov word ptr es:FSEEK_Delete + word, ax ;AN000; + mov word ptr es:FSEEK_Lookup + word, ax ;AN000; + mov word ptr es:FSEEK_Truncate + word, ax ;AN000; + mov word ptr es:FSEEK_Purge + word, ax ;AN000; + + cmp Total_Name_Count,0 ; Fastopen function enabled ?? + je Adjust_Delete ; no , exit + +; Change the segID of single Jump Vector inside Cseg_Main + mov ax,cseg_Main ;AN000;;AN000; + mov es,ax ;ES addressability to CSEG_MAIN ;AN000;;AN000; + ASSUME es:Cseg_Main ;AN000;;AN000; + mov ax,Open_SegID ;AN000; + mov word ptr es:Vector_LookUp + word, ax ;;AN000;AN000; + +Adjust_Delete: + cmp Total_Ext_Count,0 ; Fastseek function enabled ?? + je Adjust_Exit ; no , exit + +; Change the segID of single Jump Vector inside Cseg_Main + mov ax,cseg_Main ;AN000;;AN000; + mov es,ax ;ES addressability to CSEG_MAIN ;AN000;;AN000; + ASSUME es:Cseg_Main ;AN000;;AN000; + mov ax,Seek_SegID ;AN000; + mov word ptr es:Vector_Delete + word, ax ;;AN000;AN000; + +Adjust_Exit: + ret ;AN000; + ;return +ADJUST_SEGIDS ENDP + + + + + + + + +;****************************************************************************** +; * +; * MODULE: PARSE +; * +; * FUNCTION: Parse command line +; * +; * INPUT: FASTOPEN d: {=n | (n,m) } ... /x à +; * where à activates queue analyser for debugging +; * +; * OUTPUT: Command line is parsed +; * +; * RETURN SEQUENCE: +; * +; * If CY = 0 No error +; * +; * If CY = 1 Error +; * +; * EXTERNAL REFERENCES: SYSPARSE +; * +; ************************************************************************* + +EOL EQU -1 ; Indicator for End-Of-Line +NOERROR EQU 0 ; Return Indicator for No Errors + + +PARSE PROC NEAR + + mov num_of_drives,0 ; initialize drive count + mov name_count,0 + mov ext_count,0 + mov Total_name_count,0 ;AN000; + mov Total_ext_count,0 ;AN000; + mov Prev_Type,0 ;AN000; + mov Ext_Mem,0 ;AN000; + mov Check_Queue,0 ;AN000; + lea si,parambuff ; drive ID buff address ;AN000; + mov parmbuff_Ptr,si ; save it ;AN000; + +;---------------------------------------------------------------------------- +; Get command string address from PSP +;---------------------------------------------------------------------------- + mov si,0081H + mov ah,62H + INT 21H ; get program PSP segment ;AN000; + mov PSP_Seg,bx ; save PSP segment ;AN000; + ;AN000; + mov ds,bx ; DS = PSP segment ;AN000; + mov si,0081h ; SI-->beginning of parameter string in PSP + lea di,cmdline_buff ; DI-->command param buffer ;AN000; + mov cx,127 ; copy 127 bytes from PSP ;AN000; + +;---------------------------------------------------------------------------- +; Copy command parameters from PSP to the command buffer +;---------------------------------------------------------------------------- +Cmdloop: + mov al,ds:[si] ; DS:SI-->Command line ;AN000; + mov es:[di],al ; ES:DI-->program command buffer ;AN000; + inc si ;AN000; + inc di ;AN000; + LOOP cmdloop ; copy command line + push cs ;AN000; + pop ds ;AN000; + +;---------------------------------------------------------------------------- +; set parametrs for SysParse call +;---------------------------------------------------------------------------- + xor cx,cx ; no params processed so far ;AN000; + MOV ORDINAL,CX ; SAVE initial ordinal value ;AN000; + lea si,cmdline_buff ; ES:SI-->command line ;AN000; + lea di,parms ; ES:DI-->parameter + MOV CURRENT_PARM,SI ; pointer to next positional ;AN000; + + mov ax,0100h ; Drive only + mov pos1type,ax ; set positional control block 1 ;AN000; + mov ax,08502h ; Numeric/Complex/Drive/Repeat + mov pos2type,ax ; set positional control block 2 ;AN000; + mov al,1 ; minimum 1 positional ;AN000; + mov Par_Min,al ; + mov al,2 ;AN000; + mov Par_Max,al ; maximum 1 positional ;AN000; + jmp short set_param + +;---------------------------------------------------------------------------- +; MAIN PARSE LOOP +;---------------------------------------------------------------------------- +PARSE_LOOP: ; MAIN PARSE LOOP + mov ax,08502h ; number/drive ID/comlex/repeat + mov pos1type,ax ; set positional control block ;AN000; + mov ax,08502h ; + mov pos2type,ax ; + mov al,1 ; minimum 1 positional ;AN000; + mov Par_Min,al ; set min + mov al,2 ; maximum 2 positionals ;AN000; + mov Par_Max,al ; set max ;AN000; + +Set_Param: + mov Par_sw,1 ; set switch flag in PARSMX + xor dx,dx + push cs ;AN000; + pop es ; ES=DS=CS ;AN000; + LEA DI,PARMS ; ES:DI = PARSE CONTROL DEFINITON ;AN000; + MOV SI,CURRENT_PARM ; DS:SI = next positional ;AN000; + XOR DX,DX ; RESERVED, INIT TO ZERO ;AN000; + MOV CX,ORDINAL ; OPERAND ORDINAL, INITIALLY ;AN000; + + CALL SYSPARSE ; Parse current positional + + mov Next_Parm,si ; save pointer to next positional ;AN000; + mov ORDINAL,CX ; save current ordinal ;AN000; + cmp ax,EOL ; END-OF-COMMAND string ?? ;AN000; + jne Parse_chk_Error ; no - check error + + +;---------------------------------------------------------------------------- +; If previous positional is a drive ID without Name or Extent count then assign +; default counts . +;---------------------------------------------------------------------------- + cmp Prev_Type,6 ; previous param = drive ID ;AN000; + jne Take_Exit ; no - exit ;AN000; + ;AN000; + CALL PROC_DEFAULT ; yes - setup default counts for previous drive ;AN000; + jnc Take_Exit ; exit ;AN000; + jmp parse_Error ; error exit ;AN000; + +Take_Exit: + CALL Verify_Counts ; verify the Total counts + jnc Counts_OK ; exit if count ok + jmp parse_error ; else error exit + +Counts_Ok: + jmp parse_exit ; normal - exit + + +;---------------------------------------------------------------------------- +; CHECK ERROR CONDITIONS +;---------------------------------------------------------------------------- +Parse_Chk_Error: ; check for error conditions + cmp ax,NOERROR ; any parse error ?? + jne verify_missing_oper ; yes - check missing operand + jmp Chk_Result ; no - check result buffer ;AN000; + +Verify_Missing_Oper: + cmp ax,2 ; yes - missing operand error?? + jne disp_error ; no - jump ;AN000; + + cmp Prev_Type,0 ; yes - any previous parameters ?? + jne Chk_Prev_Drive ; yes, previous drive id ;AN000; + mov MSG_CLASS,2 + MOV MSG_NUM,AX ; set message number ;AN000; + MOV SUBST_COUNT,0 ; no message substitution ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; show message ;AN000; + stc ; set error flag ;AN000; + jmp Parse_Exit ; exit + +;---------------------------------------------------------------------------- +; If previous positional is drive ID without counts then assign default counts +;---------------------------------------------------------------------------- +Chk_prev_drive: + cmp Prev_Type,6 ; previous param = drive ID ?? ;AN000; + jne Take_Exit1 ; no - exit ;AN000; + + CALL PROC_DEFAULT ; yes - assign default ID + jnc Take_Exit1 ; no error, verify counts ;AN000; + jmp parse_Error ; error exit ;AN000; + +Take_Exit1: + CALL Verify_Counts ; verify the Total counts + jnc Counts_right ; count ok - check special case + jmp parse_error ; error - exit + +Counts_right: + cmp Prev_Type,0 ; no previous param ? (Special case) ;AN000; + je invalid_operand ; no, exit ( FASTOPEN >TEMP ) case ;AN000; + clc ;AN000; + jmp parse_exit ; exit + +Invalid_Operand: ; else error + jmp bad_param + +Disp_Error: + cmp ax, 3 ; invalid switch type ?? + jne bad_param ; no - + jmp Bad_Switch + +;---------------------------------------------------------------------------- +; If user entered à to activate the analyser, than verify the previous +; drive case. If true, assign default name extent entries, set activation +; flag and take normal exit. +;---------------------------------------------------------------------------- +Bad_Param: + mov si,Current_Parm ; SI-->current parameter (analyser hook) + mov al,0e0h ; à (hidden character to activate analyser) + cmp [si],al ; activate analyser ?? + jne set_disp_param ; no - normal error + mov Check_Queue,1 ; yes - set flag to activate analyser + clc + jmp Chk_Prev_Drive ; exit + +Set_Disp_Param: + mov di,Next_Parm ; ending address of bad param (1/6/88) + mov al,0 + mov ds:[di],al ; set termination character + LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000; + MOV AX,CURRENT_PARM ; starting address of bad parameter ;AN000; + MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000; + MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000; + MOV [SI].MSG_ID,0 ; message ID ;AN000; + MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000; + MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000; + MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000; + mov ax,incorrect_param ; Error Code ;AN000; + MOV MSG_NUM,AX ; set message number ;AN000; + MOV SUBST_COUNT,1 ; substitution count ;AN000; + MOV MSG_CLASS,-1 ; message class ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; display message ;AN000; + stc ; error flag + jmp Parse_Exit ; exit (1/6/88 P2670) + + +;---------------------------------------------------------------------------- +; CHECK POSITIONAL PARAMETER TYPE +;---------------------------------------------------------------------------- +Chk_Result: + push es ; get DS back to Program data segment ;AN000; + pop ds ;AN000; + cmp postype,1 ; number ?? ;AN000; + jne chk_switch ;AN000; + jmp short Proc_Name ; yes, process name entry ;AN000; + +chk_switch: + cmp postype,3 ; switch ?? ;AN000; + je Proc_sw ; yes, process switch ;AN000; + cmp postype,6 ; drive id ?? ;AN000; + je Proc_driveid ; yes, Process Drive ID ;AN000; + cmp postype,4 ; complex item ?? ;AN000; + jne disp_msg ;AN000; + jmp Proc_complex ; yes, process Complex item ;AN000; + +disp_msg: + mov ax,incorrect_param ; no, check reult buffer ;AN000; + jmp bad_param ; else error ;AN000; + +Proc_Sw: jmp Proc_Switch ; process switch ;AN000; + + + +;---------------------------------------------------------------------------- +; PROCESS DRIVE ID +;---------------------------------------------------------------------------- +PROC_DRIVEID: ; PROCESS DRIVE ID + cmp Prev_Type,6 ; previous param = drive ID ;AN000; + jne check_drive_id ; no, jump ;AN000; + ;AN000; +; if not set default name and extent entry count for previous drive + CALL PROC_DEFAULT ; setup default counts ;AN000; + jnc Check_Drive_id ; ;AN000; + jmp parse_Error ;AN000; + +Check_Drive_Id: ; process current drive ID + mov ax,ValueLo ; get drive letter number from result buff ;AN000; + ; C:=3 D:=4 etc, Parser drive id convention ;AN000; + add al,040H ; convert to drive letter ;AN000; + + CALL CHECK_DRIVE ; validate drive ID ?? ;AN000; + jnc set_drive_id ; yes, jump ;AN000; + jmp Parse_Exit ; no, invalid drive id , exit ;AN000; + +Set_Drive_Id: + inc num_of_drives ; update the drive count ;AN000; + xor ax,ax ;AN000; + mov ax,valuelo ; get drive number ;AN000; + xor ah,ah ; only low byte is valid ;AN000;;AN000; + mov di,ParmBuff_Ptr ; DS:DI-->driveID buffer ;AN000; + dec ax ; C:=2 D:=3 E:=4 etc Fastopen drive id ;AN000; + mov [di],ax ; save drive in Drive ID table ;AN000; + add parmbuff_ptr,2 ; points to next extent count area ;AN000; + mov al,PosTYpe ; set previous type before look for next ;AN000; + mov Prev_Type,al ; positional parameter ;AN000; + mov si,Next_Parm ; get pointer to next param (switch) ;AN000; + mov Current_Parm,si ; ;AN000; + jmp Parse_Loop ; look for next posistional parameter ;AN000; + + +;---------------------------------------------------------------------------- +; PROCESS INTEGER ( C:=n ) followed by drive ID +;---------------------------------------------------------------------------- +PROC_NAME: + cmp Prev_Type, 6 ; previous type = drive ID + je Get_Name_Value ; yes - jump + mov ax,incorrect_param ; error code ;AN000; + jmp bad_param + +Get_Name_Value: + xor ax,ax ;AN000; + mov ax,valuelo ; get name value ;AN000; + cmp ax,10 ; check validity of the count ;AN000; + jl Bad_Name_Count + cmp ax,999 ;AN000; + jle save_name_count ; count OK, save it ;AN000; + +Bad_Name_Count: ; bad name count + mov ax,Invalid_Name ; error code ;AN000; + jmp parse_error ; error - exit ;AN000; + +Save_Name_Count: + mov name_count,ax ; save it (name count) + add Total_Name_Count,ax ; update total name count + mov di,ParmBuff_Ptr ; DS:DI-->driveID buffer ;AN000; + mov ax,-1 ;AN000; + mov [di],ax ; MARK this drive has no extent entry ;AN000; + add parmbuff_ptr,2 ; points to extent count area ;AN000; + +Set_Drive_Hdr: + mov ax,Name_Count ; get name count entry ;AN000; + CALL SET_DRIVE_CACHE_HEADER ; Set Name cache header ;AN000; + jnc set_min_max ; no error set min and max ;AN000; + jmp parse_Error ; display error ;AN000; + +Set_Min_Max: + mov al,1 ;AN000; + mov Par_Min,al ; change min-max ;AN000; + mov al,2 ;AN000;;AN000; + mov Par_Max,al ;AN000; + mov al,PosTYpe ; set previous type before look for next ;AN000; + mov Prev_Type,al ;AN000; + mov si,Next_Parm ; get pointer to next param (switch) ;AN000; + mov Current_Parm,si ; ;AN000; + mov ordinal,0 ;AN000; + Jmp Parse_Loop ; parse nexy positional ;AN000; + + +;---------------------------------------------------------------------------- +; PROCESS COMPLEX (n,m) followed by a drive id +;---------------------------------------------------------------------------- +PROC_COMPLEX: + cmp Prev_Type, 6 ; previous type = drive ID ?? + je Get_Cmplx_Item ; yes - ok + mov ax,incorrect_param ; no - error, previous must be drive id ;AN000; + jmp bad_param ; display error + +Get_Cmplx_Item: + mov al, PosType ; + mov Prev_Type,al ; save current type as previous + lea di,valuelo ; DI-->result buffer ;AN000; + mov si,[di] ; get next positional param address ;AN000; + mov current_parm,si ; SI-->first complex item ;AN000; + mov ax,08001h ; Control ( Numeric/Optional ) ;AN000; + mov Pos1Type,ax ; change pos-param control block flag ;AN000; + mov Pos2Type,ax ;AN000; + mov al,1 ; atleast 1 or maximun two positionals in complex item ;AN000; + mov Par_Min,al ; set minimum = 1 + mov al,2 ;AN000; + mov Par_Max,al ; set maximum = 2 ;AN000; + mov ordinal1,0 ; initialize ordinal for complex item loop ;AN000; + mov par_sw,0 ; reset switch flag in PARMSX + +COMPLX_LOOP: + xor dx,dx + LEA DI,PARMS ;ES:DI = PARSE CONTROL DEFINITON ;AN000; + MOV SI,CURRENT_PARM ;SI = COMMAND STRING, NEXT PARM ;AN000; + XOR DX,DX ;RESERVED, INIT TO ZERO ;AN000; + MOV CX,ORDINAL1 ;OPERAND ORDINAL, INITIALLY ZERO ;AN000; + + CALL SYSPARSE ; parse positional param in complex item + + cmp ax,NOERROR ; parse error ?? + je Chk_Complex_Result ; no, check result buffer ;AN000; + cmp ax,EOL ; END-OF-COMMAND string ?? ;AN000; + jne Complex_Error ; no, check error + mov si,Next_Parm ; Set pointer to next param (4/3/88) + mov Current_Parm,si ; set next param address before parsing ;AN000; + jmp Parse_Loop ; go to main parse loop + +Complex_Error: + mov ax,Incorrect_Param ; no, check reult buffer ;AN000; + jmp bad_param ; display error + +;------------------------------------------------------------------------------- +; Ckeck The Result Buffer +;------------------------------------------------------------------------------- +Chk_Complex_Result: + mov ordinal1,cx ; save current ordinal ;AN000; ;AN000; + cmp postype,1 ; positional type = number ?? + je Proc_Complex_Name ; yes, process name entry ;AN000; + cmp postype,3 ; positional type = String ?? + je Miss_param ; yes, process missing parameter + mov ax,incorrect_param ; no, check reult buffer ;AN000; + jmp bad_param + +Miss_Param: + mov current_parm,si ; save current chara pointer ;AN000; + jmp complx_loop ; get extent count + + +;------------------------------------------------------------------------------- +; PROCESS NAME ENTRY (n) +;------------------------------------------------------------------------------- +Proc_Complex_Name: ; PROCESS COMPLEX ITEM + mov current_parm,si ; save current chara pointer ;AN000; + cmp cx,2 ; second positional in the complex ;AN000; + je proc_extent_entry ; yes, process Extent count ;AN000; + xor ax,ax ; eles process Name Count ;AN000; + mov ax,valuelo ; get name value from result buffer ;AN000; + cmp ax,10 ; validate the name value for higher ;AN000; + jl Name_Error ; and lower boundries ;AN000; + cmp ax,Max_Entry_Num ; name entry count ok ?? + jg Name_Error ; no - error + jmp short Store_Name_Count ; yes - store it + +Name_Error: ; invalid name count + mov ax,invalid_name ; error code ;AN000; + jmp parse_error ; display error + +Store_Name_Count: + mov Name_Count,ax ; save it (name count) ;AN000; ;AN000; + add Total_name_count,ax ; update total name count ;AN000; ;AN000; + + CALL SET_DRIVE_CACHE_HEADER ; Set Name cache header ;AN000; + jc Cant_Set_Header ; jump if error ;AN000; + jmp Complx_loop ; look for extent count ;AN000; + +Cant_Set_Header: + jmp Parse_Error ; error exit + + +;------------------------------------------------------------------------------- +; PROCESS EXTENT ENTRY (m) +;------------------------------------------------------------------------------- +Proc_Extent_Entry: + mov ax,valuelo ; get extent count entry + cmp ax,1 ; validate entry between 1 an 10 ;AN000; + jl Extent_Error ;AN000; + cmp ax,10 + jl set_default_ext ; if <10 set default entry 12 + cmp ax,Max_Entry_Num ; >999 ?? + jg Extent_Error ; yes - error + jmp short Store_Extent_Count ; value OK, save it + +Set_Default_Ext: ; for count 1 throug 9 set default count 12 + mov ax,12 + jmp short Store_Extent_Count + +Extent_Error: ; invalid entry error + mov ax,invalid_extent ; error code + jmp parse_error ; display error ;AN000; + +Store_Extent_Count: + mov ext_count,ax ; save the count + add Total_Ext_count,ax ; update total extent count + mov di,parmbuff_ptr ; DI-->drive/extent buffer ;AN000; + mov [di],ax ; save in buffer ;AN000; + add parmbuff_ptr,2 ; move pointer to next extent in buffer ;AN000; + mov si,Next_Parm ; get pointer to next param + mov Current_Parm,si ; set next param address before parsing ;AN000; + mov Par_Sw,1 ; set switch flag in PARMSX + Jmp Parse_Loop ; parse next positional parameter ;AN000; + + +;---------------------------------------------------------------------------- +; PROCESS SWITCH (/X) OPTION +;---------------------------------------------------------------------------- +Proc_Switch: + cmp Prev_Type,0 ; any previous type ?? + je Switch_Error ; no - error + cmp Ext_Mem,0 ; switch previously specified ?? ;AN000; + je set_sw_flag ; no, set flag ;AN000; + +Switch_Error: + mov ax,incorrect_param ; error code ;AN000; + jmp bad_param ; error - /x could be specified only once + +Set_Sw_flag: + cmp Prev_Type,6 ; previous param = drive ID 12/15 P2939 ;AN000; + jne sw_save_Ptr ; no - continue 12/15 p2939 ;AN000; + ;AN000; + CALL PROC_DEFAULT ; yes setup default counts for previous drive ;AN000; + jnc sw_save_ptr ; no error - continue 12/15 p2939 ;AN000; + jmp short parse_Error ; error - exit 12/15 P2939 ;AN000; + +Sw_save_ptr: + mov current_parm,si ; save current chara pointer ;AN000; + mov bx,synonym ; get synonym (/x) ;AN000; ;AN000; + cmp bx,offset e_switch ; /X ?? ;AN000; + je set_extflag ; yes - check result buffer ;AN000; + jmp Bad_Switch ; error exit + +Set_ExtFlag: ; no, check reult buffer + mov Ext_Mem,1 ; yes, set Hi Memory flag ;AN000; + mov si,Current_parm ; -->next parameter ;AN000; + mov al,PosTYpe ; set prevvious type before look for next ;AN000; + mov Prev_Type,al ;AN000; + jmp parse_loop ;AN000; + +Bad_Switch: + mov di,Next_Parm ; ending address of bad param 1/6/88 + mov al,0 + mov ds:[di],al ; set termination character + LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000; + MOV AX,CURRENT_PARM ; starting address of bad parameter ;AN000; + MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000; + MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000; + MOV [SI].MSG_ID,0 ; message ID ;AN000; + MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000; + MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000; + MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000; + MOV BX,Invalid_Switch ; get message number + MOV MSG_NUM,BX ; set message number ;AN000; + MOV SUBST_COUNT,1 ; substitution count ;AN000; + MOV MSG_CLASS,-1 ; message class ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; display message ;AN000; + stc ; error flag + jmp Parse_Exit ; exit (1/6/88 P2670) + + + +;---------------------------------------------------------------------------- +; PROCESS PARSE ERROR +;---------------------------------------------------------------------------- +PARSE_ERROR: ; AX = meassage number + MOV MSG_CLASS,-1 ; message class ;AN000; + MOV MSG_NUM,AX ; set message number ;AN000; + MOV SUBST_COUNT,0 ; no message substitution ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; show message ;AN000; + stc ; set error flag ;AN000; + +Parse_Exit: ; EXIT + push cs ;AN000; + pop ds ; DS - Program data area seg ;AN000; + ret ;AN000; ;AN000; +PARSE ENDP ; end of parser + + + + +;---------------------------------------------------------------------------- +; +; Procedure: PROC_DEFAULT +; +; Function: Process default parameters if name and extend counts +; are not specified with the drive id. +; +;---------------------------------------------------------------------------- + +PROC_DEFAULT PROC ; PROCESS DEFAULT + push si ; makesure to save next chara pointer ;AN000; + mov ax,30h ; get default name count ;AN000; + mov name_count,ax ; save it ;AN000; + add Total_name_count,ax ; update total name count ;AN000; + mov ext_count,ax ; save it ;AN000; ;AN000; + add Total_Ext_count,ax ; save it ;AN000; ;AN000; + mov di,ParmBuff_Ptr ; DS:DI-->parameter buffer ;AN000; + mov [di],ax ; save in buffer ;AN000; + add Parmbuff_ptr,2 ; points to next drive id position + mov ax,Name_Count ;AN000; + CALL Set_drive_Cache_Header ; Set Name cache header ;AN000; + +Default_Exit: + pop si ;AN000; + ret ; return ;AN000; + +PROC_DEFAULT ENDP + + + + +;---------------------------------------------------------------------------- +; Procedure: VERIFY_COUNTS +; +; Function: Verify the validity of the name and extent counts + +;---------------------------------------------------------------------------- +VERIFY_COUNTS PROC NEAR + +; Check the validity of NAME and EXTENT count entries + cmp Total_ext_count,0 ; any extent param ?? ;AN000; + je Chk_Name_Count ; no, dont check extent count ;AN000; + cmp Total_ext_count, Max_Entry_Num ; check lower boundry ;AN000; + jg invalid_ext ; error if not within ;AN000; + clc ; Extent Count is valid + +; Extent count is OK, check Name count +Chk_Name_Count: + cmp Total_Name_Count,0 ; any name param ?? ;AN000; + je Verify_Exit ; no, dont check extent count ;AN000; + + cmp Total_name_count, Max_Entry_Num ;AN000; + jg invalid_name_entry ;AN000; + clc ; Name count is OK ;AN000; + jmp short verify_exit ; exit ;AN000; + +Invalid_ext: + mov ax,many_ext_entries ; AX = error code ;AN000; + stc + jmp short verify_exit ;AN000; + +Invalid_name_entry: + mov ax,many_name_entries ; AX = error code ;AN000; + stc ;AN000; + +Verify_Exit: ; + + RET ;AN000; + +VERIFY_COUNTS ENDP + + + + + + + + + + + +;========================================================================= +; CHECK_DRIVE +;----------------------------------------------------------------------- +; +; INPUT: AL - Drive letter +; +; OUTPUT: +; If Carry = 0 +; user_drive set to current entered drive letter +; num_Of_drives incremented +; If Carry = 1 error +;----------------------------------------------------------------------- +; 1) see if drive is valid and removable using int 21h IOCTL +; +; 2) use int 21h name translate to make sure that the drive is not +; redirected, substed, on another machine, or in any other way shape +; or form hosed. +;========================================================================= + +CHECK_DRIVE PROC NEAR + + CALL Convert_To_Caps ; make sure it is a capital letter + mov byte ptr user_drive,al ; save it in user drive + mov byte ptr source_xname,al ; put in source string for call + + mov bl,al ;put drive letter in bl + sub bl,"A"-1 ;convert to 1 based number + + mov ah,ioctl ;set up for removable call + mov al,8 ;function code + INT int_command + + cmp ax,1 ;is drive fixed? + jz okay_drive ;yes - see if it's subst + cmp ax,0fh ;is drive valid? + jnz hosed_drive ;yes - but hosed + + mov ax,invalid_drive ; set bad drive message + jmp short drive_Error ; display error message + +Okay_Drive: + lea si,source_xname ; set up for name translate + lea di,target_xname + mov ax,xNameTrans SHL 8 + INT int_command ;do the translation + + lea si,source_xname ;compare source and target drive + lea di,target_xname + + mov cx,Len_source_xname ;get count of invalid chars + repz cmpsb ;compare until mismatch found + jz check_drive_end ;no mismatch - exit + +Hosed_Drive: + MOV AX,BAD_USE_MESSAGE ; message number + +Drive_Error: + push ax ; save message number + mov ax,Valuelo ; get drive letter number from result buff + ; C:=3 D:=4 etc, Parser drive id convention + add al,040H ; convert to drive letter + lea si,Drive_Id ; DS:SI-->drive letter save area + mov [si],al ; save drive letter in buffer + + LEA SI,SUBLIST1 ; DS:SI-->Substitution list ;AN000; + MOV AX,OFFSET DRIVE_ID ;AN000; + MOV [SI].DATA_OFF,AX ; SI-->File name ;AN000; + MOV [SI].DATA_SEG,DS ; DS-->Segment ;AN000; + MOV [SI].MSG_ID,1 ; message ID ;AN000; + MOV [SI].FLAGS,010H ; ASCIIZ string, left align ;AN000; + MOV [SI].MAX_WIDTH,0 ; MAXIMUM FIELD WITH ;AN000; + MOV [SI].MIN_WIDTH,0 ; MINIMUM FIELD WITH ;AN000; + POP AX ; restore message number ;AN000; + MOV MSG_NUM,AX ; set message number ;AN000; + MOV SUBST_COUNT,1 ; substitution count ;AN000; + MOV MSG_CLASS,-1 ; message class ;AN000; + MOV INPUT_FLAG,0 ; no input ;AN000; + CALL PRINT_STDOUT ; display message ;AN000; + stc ; error flag + +Check_Drive_End: + ret ; return + +CHECK_DRIVE endp + + + + + +;========================================================================= +; Procedure: SET_DRIVE_CACHE_HEADER +; +; Function: Set name cache drive header +; +; Input: ax contains number of entries for num_entries +; user_drive contains user drive for drive_letter +; num_Of_drives contains number of caches set up so far +; drive_cache offset of drive cache headers start +; Output: +; If successful: +; drive cache header set up +; user_drive reset to blank +; num_Of_drives incremented +; else +; bx set to error flag +; dx points to error message +;----------------------------------------------------------------------- +; 1) see if drive too many drives have been entered. +; 2) Walk through drive cache headers to make sure that the drive +; letter was not previously entered. +; 3) Set up drive cache header +;========================================================================= + +SET_DRIVE_CACHE_HEADER PROC NEAR + + mov cx,num_of_drives ;get current count of drives + mov bx,offset drive_cache ;get start of name drive cache + mov dl,user_drive ;get user entered drive + dec cx ;is this the 1st drive entered ? + jcxz set_it_up ;yes - don't check + + cmp num_Of_drives,max_drives ;no - check for maximum num of drives + jng we_have_room ;yes - go check for dup drives + mov ax,too_many_entries ;set up for error message + stc ;set up error flag + jmp short set_dheader_exit ;and exit + +;----------------------------------------------------------------------- +; Search through the drive headers to see the duplicate drive exist. +; If a new drive header at the bottom of the chain for the new drive. +; If no drives exist, then create the new header as the first drive header. +;----------------------------------------------------------------------- +We_Have_Room: ;BX-->current drive header + cmp dl,[bx].dch_drive_letter ;drive header exist for this drive?? + jnz not_dup_drive ;no - continue + mov ax,dup_drive ;yes - set up for error message + stc + jmp short set_dheader_exit ;exit + +Not_Dup_Drive: + cmp [bx].dch_sibling_ptr,no_siblings ;any more header to search ?? + jz set_drive_sibling ;no - go create the new drive header + add bx,size drive_cache_header ;yes - get pointer to next drive header + jmp short we_have_room ;check it + +Set_drive_sibling: + mov cx,bx ;save current header address + add cx,size drive_cache_header ;pointer to next header + mov [bx].dch_sibling_ptr,cx ;set pointer to new header from current hdr + mov bx,cx ;BX-->new header + +Set_it_up: + mov [bx].dch_drive_letter,dl ;save drive letter in new header + mov [bx].dch_sibling_ptr,no_siblings ;mark new header as last header in chain + mov [bx].dch_num_entries,ax ;save name count in new header + +Set_dheader_Exit: ; Exit + ret + +SET_DRIVE_CACHE_HEADER ENDP + + + + + +subttl Convert to caps +page +;========================================================================= +; Procedure: Convert_to_caps +; +; CONVERT LOWER CASE CHARACTERS TO UPPER CASE +; Convert character in al to a capital letter. + +;========================================================================= + +CONVERT_TO_CAPS PROC NEAR + + cmp al,"a" + JNAE no_convert + cmp al,"z" + JNBE no_convert + sub al,32 + +No_Convert: + ret ;and return + +CONVERT_TO_CAPS ENDP + + + + + + + +;========================================================================= +; SET_EMS : THIS MODULE SETS EMS FOR FASTOPEN CODE AND DATA +; PAGE 0 IN HIGH MEMORY IS MAPPED FOR CODE USING +; THE PHYSICAL PAGE FRAME AND PAGE 1 IS +; MAPPED FOR DATA USING PHYSICAL PAGE FRAME NUMBER +; TWO PHYSICAL PAGE FRAME SEG IDs ARE SAVED AND +; THEY WILL BE USED BY THE (MAIN) ROUTINE. +; +; INPUTS : NONE +; +; OUTPUTS : CY - ERROR +; +; NC - EMS_PAGE_SEG - SEG ID OF SINGLE PAGE FRAME +;========================================================================= + +SET_EMS PROC NEAR + CALL EMS_CHECK1 ;SEE IF EMS INSTALLED ;AN000; + JNC EMS_GET_PAGE ; yes, get page ;AN000; + + MOV EMS_FLAG,0 ; Flag EMS not installed ;AN000; + STC ; Make sure carry is Clear ;AN000; + JMP EMS_EXIT ; Leave check routine ;AN000; + +EMS_GET_PAGE: + PUSH ES ; save ES,DI they may destroy by 2F + PUSH DI + +IF NOT BUFFERFLAG + + MOV AH,EMS_2F_HANDLER + XOR AL,AL + INT 2FH ; see 2F is there + CMP AL,0FFH + JNE EMS_PAGE_ERR ; error, if not + + MOV AH,EMS_2F_HANDLER + MOV AL,0FFH + MOV DI,0FEH + INT 2FH ; get EMS page + OR AH,AH + JNZ EMS_PAGE_ERR + MOV EMS_PAGE_SEG,ES ; SAVE PAGE SEG ID + MOV EMS_PAGE_NUM,DI ; SAVE PHYSICAL PAGE NUMBER + +ELSE + +;---------------------------------------------------------------HKN 8/25/88 +; Fastopen must get an EMS page like a well behaved program and +; should not grab a reserved page from the BIOS. +; + mov cx, FRAME_COUNT + xor ax, ax + mov bx, ax + mov dx, ax + +get_page: + cmp es:[di], 0a000h ; is the page in ax above 640K + jb next_page ; if no get next_page + + mov bx, di ; we have a valid page + + inc dx ; count the # of pages above 640K + + cmp dx, 1 + je next_page + sub di, 4 + mov ax, es:[di] + mov [FST_PAGE], ax + mov ax, es:[di+2] + mov [FST_PAGE+2], ax + mov di, bx ; restore di + +next_page: + add di, 4 + loop get_page + jne found_page + jmp ems_page_err + +found_page: +; int 3 + cmp dx, 1 + jne second_last_page + mov di, bx + mov ax, es:[di] + mov ems_page_seg, ax + mov ax, es:[di+2] + mov ems_page_num, ax + jmp save_state + +second_last_page: + mov ax, [FST_PAGE] + mov ems_page_seg, ax + mov ax, [FST_PAGE+2] + mov ems_page_num, ax + +save_state: + push es + mov ax, Cseg_Main + mov es, ax + assume es:Cseg_Main + + mov word ptr save_map_addr, offset es:save_ems_page_state + mov word ptr save_map_addr + 2, ax + + mov ax, ems_page_seg + mov es:Main_EMS_PAGE_SEG, ax + pop es + assume es:Cseg_Init + call [save_map_addr] + jc ems_page_err + +;-------------------------------------------------------------------------- + +ENDIF + + POP DI + POP ES + JMP SHORT EMS_ALLOCATE_PAGE + +EMS_PAGE_ERR: + POP DI + POP ES + STC ;yes, page not found ;AN000; + JMP SHORT EMS_ERROR ;error exit ;AN000; + +;----------------------------------------------------------------------- +; Allocate one page +;----------------------------------------------------------------------- +EMS_ALLOCATE_PAGE: + MOV BX,1 ;one page ;AN000; + MOV AH,EMS_ALLOC_PAGES ;set op code ;AN000; + INT EMS_INT ;allocate page ;AN000; + OR AH,AH ;Was there an error allocating? ;AN000; + JNZ EMS_ERROR ;yes - display error ;AN000; + MOV EXT_HANDLE,DX ;no -Save EMS handle + +IF BUFFERFLAG + +;------------------------------------------------------HKN 8/25/88 +; Must save ems handle in Cseg_Main also. + + push es + push ax + mov ax, Cseg_Main + mov es, ax + assume es:Cseg_Main + mov es:ems_save_handle1, dx + pop ax + pop es + assume es:Cseg_Init + +ENDIF + +;----------------------------------------------------------------------- +; SET HANDLE NAME TO THE PAGE HANDLE +;----------------------------------------------------------------------- + PUSH DS ;AN000; + POP ES ;AN000; + ASSUME ES:CSEG_INIT ;AN000; + LEA SI,HANDLE_NAME ; DS:SI-->Handle name string ;AN000; + MOV DX,EXT_HANDLE ; handle number ;AN000; + MOV AH,EMS_HANDLE_NAME ;AN000; + MOV AL,1 ; set op code code ;AN000; + INT 67H ; set handle ;AN000; + OR AH,AH ;AN000; + JNZ EMS_ERROR ; jump if error ;AN000; + +;----------------------------------------------------------------------- +; Map logical page 0 in physical page frame FE (P254) +;----------------------------------------------------------------------- + CALL MAP_FRAME ;map two pages ;AN000; + JNC EMS_GET_SIZE ;no error, normal exit ;AN000; + +;----------------------------------------------------------------------- +; Get partial page map size +;----------------------------------------------------------------------- +EMS_GET_SIZE: + MOV AH,EMS_PAGE_SIZE ;Allocate requested pages ;AN000; + MOV AL,2 + INT EMS_INT ; ;AN000; + OR AH,AH + JNZ EMS_ERROR + XOR AH,AH + MOV EMS_PAGESIZE,AX ;save EMS page size + CLC + JMP SHORT EMS_EXIT + +EMS_ERROR: + MOV AX,EMS_FAILED ;error message ;AN000; + MOV MSG_NUM,AX ;save message number + MOV SUBST_COUNT,0 ;no message substitution ;AN000; + MOV MSG_CLASS,-1 ;message class ;AN000; + MOV INPUT_FLAG,0 ;no input ;AN000; + CALL PRINT_STDOUT ;show message "Incorrect Parameter" ;AN000; + STC ; set error flag ;AN000; + +EMS_EXIT: + RET ; Return ;AN000; + +SET_EMS ENDP + + + + + + +;========================================================================= +; EMS_CHECK1 : THIS MODULE DETERMINES WHETHER OR NOT EMS IS +; INSTALLED FOR THIS SESSION. +; +; INPUTS : NONE +; +; OUTPUTS : ES:BX - FRAME ARRAY +; CY - EMS NOT AVAILABLE +; NC - EMS AVAILABLE +;========================================================================= + +EMS_CHECK1 PROC NEAR ;EMS INSTALL CHECK + + PUSH DS ;save ds ;AN000; + XOR AX,AX ;set ax to 0 ;AN000; + MOV DS,AX ;set ds to 0 ;AN000; + CMP DS:WORD PTR[067h*4+0],0 ;see if int 67h is there ;AN000; + POP DS ;restore ds ;AN000; + JE EMS_NOT_INST1 ;no, EMS not installed ;AN000; + + MOV AH,EMS_GET_STATUS ;YES, GET STATUS ;AN000; + INT EMS_INT ;INT 67H ;AN000; + CMP AH,0 ;EMS MANAGER PRESENT ?? + JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED + + MOV AH,EMS_GET_VERSION ;YES, GET STATUS ;AN000; ;AN000; + INT EMS_INT ;INT 67H ;AN000;;AN000; + CMP AH,0 ;EMS MANAGER PRESENT ?? ;AN000; + JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED ;AN000; + + CMP AL,40H ;VERSION 4.0 ?? ;AN000; + JNE EMS_NOT_INST1 ;NO, EMS NOT INSTALLED ;AN000; + + MOV AX,EMS_GET_COUNT + INT EMS_INT ;GET ARRAY COUNT + CMP AH,0 + JNE EMS_NOT_INST1 + + MOV FRAME_COUNT,CX + MOV AX, BUFFER_ENTRY_SIZE + MUL CX ; CALCULATE THE ARRAY SIZE BE RESERVED + +IF NOT IBMCOPYRIGHT + CMP AX, 100h +ELSE + CMP AX, 30H +ENDIF + + JG EMS_NOT_INST1 + + MOV AX,EMS_GET_FRAME_ADDR ;YES, GET FRAME ADDRESS ;AN000; + PUSH DS ;SWAP DS & ES ;AN000; + POP ES ; ;AN000; + LEA DI,FRAME_BUFFER ;ES:DI--> RESULT BUFFER ;AN000; + INT EMS_INT ;GET FRAME ADDRESSES ;AN000; + CMP AH,0 ;IS EMS INSTALLED ;AN000; + JNE EMS_NOT_INST1 ;NO,exit + CMP CX,FRAME_COUNT ; ;AN000; + JNE SHORT EMS_NOT_INST1 + + CLC + MOV EMS_FLAG,1 ; EMS IS ACTIVE, SET FLAG + JMP EMS_CHECK1_EXIT + +EMS_NOT_INST1: ;EMS NOT INSTALLED + MOV AX,EMS_NOT_INSTALL ;error message ;AN000; + MOV MSG_NUM,AX ;set message number ;AN000; + MOV SUBST_COUNT,0 ;no message substitution ;AN000; + MOV MSG_CLASS,-1 ;message class ;AN000; + MOV INPUT_FLAG,0 ;no input ;AN000; + CALL PRINT_STDOUT ;show message + STC ;FLAG EMS NOT INSTALLED ;AN000; + ;AN000; +EMS_CHECK1_EXIT: ;EXIT ROUTINE + RET ;RETURN TO CALLER ;AN000; + +EMS_CHECK1 ENDP + + + + +;========================================================================= +; MAP_FRAME : THIS MODULE MAPS TWO LOGICAL PAGES IN THE HIGH +; MEMORY TO TWO PHYSICAL PAGE FEAMES IN THE LOW +; MEMORY. +; +; INPUTS : EXT_HANDLE - HANDLE +; +; OUTPUTD CY - ERROR +; NC - PAGE IS MAPPED +;========================================================================= + +MAP_FRAME PROC NEAR ; MAP physical page frames + PUSH BX ; DMS; + XOR BX,BX ; Logical page 0 ;AN000; + MOV AX,EMS_PAGE_NUM ; AL=Physical Page frame number ;AN000; + MOV AH,EMS_MAP_HANDLE ; AH=EMS function to map page ;AN000; + MOV DX,EXT_HANDLE ; EMS handle ;AN000; + INT EMS_INT ;AN000; + OR AH,AH ; Was there an error allocating? ;AN000; + JNZ MAP_ERROR ; yes - set flag ;AN000; + CLC + JMP SHORT MAP_EXIT ; no - exit ;AN000; + +MAP_ERROR: + STC ; set error flag ;AN000; + +MAP_EXIT: + POP BX ;AN000; + RET ; return ;AN000; + + +MAP_FRAME ENDP + + + + + + + + +;************************************************************ +;* +;* SUBROUTINE NAME: PRINT_STDOUT +;* +;* SUBROUTINE FUNCTION: +;* Display the requested message to the specified handle +;* +;* INPUT: +;* Paramters in parater storage area +;* DS:SI-->Substitution List +;* ES:DI-->PTR to input buffer if buffered keyboard +;* input is specified (DL = 0A) +;* OUTPUT: +;* AX = Single character entered if DL=01 +;* OR +;* ES:DI-->input buffer where string is returned if DL=0A +;* +;* The message corresponding to the requested msg number will +;* be written to Standard Out. Message substitution will +;* be performed if specified +;* +;* NORMAL EXIT: +;* Message will be successfully written to requested handle. +;* +;* ERROR EXIT: +;* None. Note that theoretically an error can be returned from +;* SYSDISPMSG, but there is nothing that the application can do. +;* +;* INTERNAL REFERENCES: SysDispMsg +;* +;* EXTERNAL REFERENCES: +;* None +;* +;************************************************************ +PRINT_STDOUT PROC NEAR + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + + MOV AX,MSG_NUM ; Message ID ;AN000; + MOV BX,STDOUT ; standard input message handle ;AN000; + MOV CX,SUBST_COUNT ; message substitution count ;AN000; + MOV DH,MSG_CLASS ; message class ;AN000; + MOV DL,INPUT_FLAG ; Type of INT 10 for KBD input ;AN000; + + CALL SYSDISPMSG ; AX=Extended key value if wait ;AN000; + ;for key ;AN000; + JNC DISP_DONE ; If CARRY SET then registers + ;will contain extended error info ;AN000; + ; AX - Extended error Number + ; BH - Error Class + ; BL - Suggested action +DISP_DONE: ; CH - Locus + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + ;AN000; + RET +PRINT_STDOUT ENDP + + +CSEG_INIT ENDS + + +;=========================================================================== +;;; STACK SEGMENT SIZE = 20 PARAGRAPHS +;=========================================================================== + +STACK SEGMENT PARA STACK 'STACK' + DB 64 dup("STACK ") ; 512 WORD STACK AREA ;AN000; +STACK ENDS + + +END START + diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM new file mode 100644 index 0000000..5594abd --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.ASM @@ -0,0 +1,2052 @@ + Page 84,132 ; +Title FASTOPEN +;Date: May 13,1988 +;============================================================================== +; EQUATES +;============================================================================== +Is_drive_head EQU 00000001b ;AN000; +Is_delete EQU 00000010b ;AN000; +Is_insert EQU 00000100b ;AN000; +Not_drive_head EQU 11111110b ;AN000; +Not_delete EQU 11111101b ;AN000; +Not_insert EQU 11111011b + +EMS_SAVE_STATE EQU 4FH ;AN000; +EMS_RESTORE_STATE EQU 4FH ;AN000; +EMS_INT EQU 67H ;AN000; +DOS_PAGE1 EQU 0FEH ;AN000; + + +;============================================================================== +; INCLUDE FILES +;============================================================================== +.xcref +.xlist +debug=0 ; an equate only for DOSMAC.inc ;AN000; +INCLUDE DOSMAC.inc ;AN000; +.list +.cref +INCLUDE dirent.inc ;AN000; +INCLUDE fastsegs.inc ; this cannot include in Fastopen.inc +INCLUDE fastopen.inc ; this include file also contains DOS equates ;AN000; +include version.inc + +;============================================================================== + + + +EXTRN FK_OPEN:FAR ;AN000; +EXTRN FK_CLOSE:FAR ;AN000; +EXTRN FK_INSERT:FAR ;AN000; +EXTRN FK_DELETE:FAR ;AN000; +EXTRN FK_LOOKUP:FAR ;AN000; +EXTRN FK_TRUNCATE:FAR ;AN000; +EXTRN FK_PURGE:FAR ;AN000; + + +;============================================================================ + +CSEG_MAIN SEGMENT PARA PUBLIC 'code' + ASSUME cs:cseg_main, ds:nothing,es:nothing,ss:nothing +;============================================================================ + +PUBLIC MAIN ;AN000; + +IF BUFFERFLAG +PUBLIC SAVE_EMS_PAGE_STATE +PUBLIC EMS_PAGE_NUMBER +ENDIF + +PUBLIC RESTORE_PAGE_STATE +PUBLIC EMS_SAVE_HANDLE1 + +PUBLIC Main_name_cache_seg ;AN000; +PUBLIC Main_Num_Of_drives ;AN000; +PUBLIC Main_Ext_Count ;AN000; +PUBLIC Main_extent_drive_Buff ;AN000; +PUBLIC Main_ext_cache_size ;AN000; +PUBLIC Main_name_cache_Buff ;AN000; +PUBLIC Main_EMS_FLAG ;AN000; +PUBLIC Main_Res_Segs ;AN000; +PUBLIC Main_EMS_PAGE_SIZE ;AN000; +PUBLIC Main_EMS_PAGE_SEG ;AN000; +PUBLIC Main_Total_Ext_Count ;AN000; +PUBLIC Main_Total_Name_Count ;AN000; +PUBLIC Main_Name_Drive_Buff ;AN000; +PUBLIC Main_ParamBuff ;AN000; + +PUBLIC FOPEN_Insert ;AN000; +PUBLIC FOPEN_Update ;AN000; +PUBLIC FOPEN_Delete ;AN000; +PUBLIC FOPEN_Lookup ;AN000; +PUBLIC FOPEN_PURGE ;AN000; + +PUBLIC FSEEK_Open ;AN000; +PUBLIC FSEEK_Close ;AN000; +PUBLIC FSEEK_Insert ;AN000; +PUBLIC FSEEK_Delete ;AN000; +PUBLIC FSEEK_Lookup ;AN000; +PUBLIC FSEEK_Truncate ;AN000; +PUBLIC FSEEK_Purge ;AN000; + +PUBLIC VECTOR_LookUp ;AN000; +PUBLIC VECTOR_Delete ;AN000; + + +; Following data variables are accessed by all other segments +call_cnt DW 0 ;AN000; +Purge_Flag DW 0 ; =1 if last call is PURGE function +Prev_drv_id DB -1 ; previous request drive id +Main_name_cache_seg DW Cseg_Init ; default to Init1 seg ;AN000; +Main_Num_Of_drives DW 0 ; number of drives ;AN000; +Main_Ext_Count DW 0 ; total name extent entries ;AN000; +Main_extent_drive_Buff DW 0 ; addrs to extent drive ;AN000; +Main_name_cache_Buff DW 0 ; address of Name cache buffer ;AN000; +Main_ext_cache_size DW 0 ; extent cache size +Main_EMS_FLAG DW 0 ; EMI flag 1= if EMI is enabled ;AN000; +Main_Res_Segs DW 0 ; number of segs to be stay resident ;AN000; +Main_Total_Ext_Count DW 0 ; Total extent count entries ;AN000; +Main_Total_Name_Count DW 0 ; Total name count entries ;AN000; +Main_Name_Drive_Buff DW 0 ; EMS data page segment ID ;AN000; +Main_ParamBuff DW 50 dup (0) ; Drive ID/extent count buffer ;AN000; + +; The following structure is for saving and restoring EMS page state +EMS_PAGE_MAP LABEL WORD +Main_EMS_SEG_COUNT DW 1 ; EMS segment count +Main_EMS_PAGE_SEG DW 0 ; EMS page segment ID ;AN000; + + +Main_EMS_PAGE_SIZE DW 0 ; EMS page size ;AN000; +EMS_PAGE_ARRAY DW 30 dup (0) ; EMS state save array + +; The following data values are used by MAIN segment +EMS_SAVE_LOG_PAGE1 DW ? ;HOLDS PREVIOUS PAGE1 ;AN000; +EMS_SAVE_HANDLE1 DW ? ;HOLDS PREVIOUS handle1 ;AN000; + +IF BUFFERFLAG +;----------------------------------------------------------HKN 8/26/88 + +EMS_PAGE_NUMBER DW ? ; holds the ems + ; physical page no. + +ENDIF +; +;----------------------------------------------------------------------------- +; Fastopen/Fastseek function jump vectors +; Inititally the jump vectors have default offset and segment values. +; If the modules are relocated, the offset and the segID in the jump vectors +; may be changed to the new segID of the new location. +;----------------------------------------------------------------------------- +FOPEN_Insert DD Insert ;AN000; +FOPEN_Update DD Update ;AN000; +FOPEN_Delete DD delete ;AN000; +FOPEN_Lookup DD lookup ;AN000; +FOPEN_Purge DD FP_purge ;AN000; + +FSEEK_Open DD Fk_Open ;AN000; +FSEEK_Close DD Fk_Close ;AN000; +FSEEK_Insert DD Fk_Insert ;AN000; +FSEEK_Delete DD Fk_Delete ;AN000; +FSEEK_Lookup DD Fk_Lookup ;AN000; +FSEEK_Truncate DD Fk_Truncate ;AN000; +FSEEK_Purge DD Fk_Purge ;AN000; + +VECTOR_LookUp DD LookUp ; jump vector to LookUp used by Insert call +VECTOR_Delete DD Fk_Delete ; jump vector to Delete used by Free_buffer routine + + + + + +;============================================================================== + +MAIN PROC FAR ; FAR procedure for FAR call from DOS + push cx ; save DOS registers ;AN000; + push dx ; makesure to restore the necessary ;AN000; + push ds ; ones on return ;AN000; + push es ;AN000; + push bp ;AN000; + push di ;AN000; + push bx ;AN000; + +;----------------------------------------------------------------------------- +; The cache buffers are maintained in a seperate segement whose segment ID is +; in Name_Cache_Seg. The ES will be used as the seg register during the access +; of data in the cache buffers, while DS will be used to access the Fastopen +; resident and non-resident data area. +;----------------------------------------------------------------------------- + cmp cs:Main_EMS_flag,1 ; EMS enabled ?? ;AN000; + jne dispatch_funcs ; no - dispatch functions ;AN000; + ; yes - save EMS page state +IF NOT BUFFERFLAG + +;----------------------------------------------------------------------------- +; SAVE EMS PAGE STATE +;----------------------------------------------------------------------------- + PUSH AX ; save registers + PUSH CX + PUSH DX ;AN000; + PUSH DS ;AN000; + PUSH ES ;AN000; + PUSH BP ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH BX ;AN000; + MOV AX, SEG EMS_PAGE_MAP ; get segid + MOV DS,AX + LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc + MOV AX, SEG EMS_PAGE_ARRAY ; get segid + MOV ES,AX + LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY + MOV AH,EMS_SAVE_STATE ; + MOV AL,0 ; subfunction code + INT EMS_INT ; save page state ;AN000; + + POP BX ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP BP ;AN000; + POP ES ;AN000; + POP DS ;AN000; + POP DX ;AN000; + POP CX ;AN000; + + CMP AH,0 ; save ok?? + JNE SAVE_FAILED ; no, error + POP AX ; clear stack + +ELSE + + +;------------------------------------------------------------HKN 8/26/88-- +; Before dispatching off the fastopen functions we must do the +; following: +; 1. save the map for this page +; 2. map this page to log. page 0 with the fastopen handle in +; ems_save_handle1. +; 3. dispatch +; + +; int 3 + + push ax + push cx + push dx + push ds + push es + push bp + push si + push di + push bx + + call far ptr save_ems_page_state + jc ems_failed + + call map_page + jc ems_failed + + pop bx + pop di + pop si + pop bp + pop es + pop ds + pop dx + pop cx + POP AX ; restore registers + + JMP DISPATCH_FUNCS ; yes, dispatch functions + +EMS_FAILED: + pop bx + pop di + pop si + pop bp + pop es + pop ds + pop dx + pop cx + +ENDIF + +IF NOT BUFFERFLAG +SAVE_FAILED: +ENDIF + + POP AX ; restore registers + + POP BX ; no, restore DOS registers ;AN000; + POP DI ;AN000; + POP BP ;AN000; + POP ES ;AN000; + POP DS ;AN000; + POP DX ;AN000; + POP CX ;AN000; + STC + JMP ERROR_RET ; error return + + +;----------------------------------------------------------------------------- +; FASTOPEN/FASTSEEK DISPATCHER +;----------------------------------------------------------------------------- +DISPATCH_FUNCS: + cmp al,5 ; buffer purge ?? + je Check_Drive_id ; yes - check drive id + cmp al,11 ; Fastopen function call ?? ;AN000; + jge Check_drive_id ; no - dispatch Fastseek functions + jmp Dispatch_fopen ; yes - dispatch Fastopen functions ;AN000; + + +;----------------------------------------------------------------------------- +; Check to see the Drive ID in DL is the valid. If not error and return DI=1 +; if Fastseek LookUp function. Makesure to preserve AL, DS, SI and DI +;----------------------------------------------------------------------------- +CHECK_DRIVE_ID: + cmp cs:Prev_drv_id, dl ; current id same as previous valid + je Dispatch_Fseek ; yes - dont check drive ID + + push si ;AN000; + push bx ;DS=addressability to Cseg_Main ;AN000; + push cx ;AN000; + lea si,cs:Main_ParamBuff ; DS:SI-->drive ID buffer ;AN000; + mov cx,cs:Main_Num_Of_Drives ; number of drives ;AN000; + +Get_Drive_Id: ;AN000; + mov bx,cs:[si] ;AN000; + cmp bl,dl ; drive ID match ?? ;AN000; + je drive_found ; yes, drive ID found ;AN000; + add si,4 ; (2/11) no, move pointer to next ID ;AN000; + LOOP get_drive_id ; check next drive id ;AN000; + +Drive_Not_Found: ; drive id not found + pop cx ; restore registers ;AN000; + pop bx ;AN000; + pop si ;AN000; + jmp Error_Exit ; return + +Drive_Found: ; drive ID found + mov cs:Prev_drv_id,dl ; save drive id as prev drive id + pop cx ; restore registers ;AN000; + pop bx ; and do the specified function ;AN000; + pop si ;AN000; + +;----------------------------------------------------------------------------- +; FASTSEEK FUNCTION DISPATCHER +;----------------------------------------------------------------------------- +DISPATCH_FSEEK: + cmp al,010H + jle Fsk_Cont + inc cs:call_cnt ;AN000; +; cmp cs:call_cnt,0efffH ; for debugging +; jne fsk_cont ; for debugging + + +Fsk_Cont: + push cs ; set addressability + pop ds ; CS = DS = Cseg_Main segment + ASSUME ds:Cseg_Main + cmp al,FONC_Purge ; PURGE call ?? ;AN000; + je chk_05 ; yes - continue ;AN000; + + mov cs:Purge_Flag, 0 ; reset purge flag + cmp al,FSK_Open ; OPEN call ;AN000; + jne chk_12 ; jump if not ;AN000; + CALL FSEEK_OPEN ;AN000; + jmp exit ;AN000; +Chk_12: + cmp al,FSK_Close ; CLOSE ?? ;AN000; + jne chk_14 ;AN000; + CALL FSEEK_CLOSE ; process close function ;AN000; + jmp exit ;AN000; +Chk_14: + cmp al,FSK_Lookup ; LOOKUP ?? ;AN000; + jne chk_15 ;AN000; + CALL FSEEK_LOOKUP ; process lookup ;AN000; + CALL RESTORE_PAGE_STATE ; restore EMS page ;AN000; + pop dx ; dont restore original BX and DI ;AN000; + pop dx ; from DOS since BX and DI contins return values ;AN000; + jmp exit_1 ; exit + +Chk_15: + cmp al,FSK_Insert ; INSERT ?? ;AN000; + jne chk_13 ;AN000; + CALL FSEEK_INSERT ; Process insert ;AN000; + jmp exit ;AN000; +Chk_13: + cmp al,FSK_DELETE ; DELETE ?? ;AN000; + jne chk_16 ;AN000; + CALL FSEEK_DELETE ; process delete ;AN000; + jmp short exit ;AN000; +Chk_16: + cmp al,FSK_Trunc ; TRUNCATE ?? ;AN000; + jne Chk_05 ; + CALL FSEEK_TRUNCATE ; process truncate ;AN000; + jmp short exit ;AN000; + +Chk_05: + cmp cs:Purge_Flag, 1 ; previous call is purge ?? ;AN000; + jne Purge_buffs ; no - purge the buffers + clc ; yes - exit + jmp short exit ;AN000; + +Purge_Buffs: + mov cs:Purge_Flag,1 ; set purge flag + cmp CS:Main_Total_Ext_Count,0 ; reset fseek buffs?? + je reset_fopen ; no - reset fopen + CALL FSEEK_PURGE ; reset extent cache ;AN000; + +Reset_Fopen: + cmp CS:Main_Total_Name_Count,0 ; reset fopen buffs?? + je Reset_Exit ; no - reset f + CALL CS:FOPEN_PURGE ; reset extent cache ;AN000; + +Reset_Exit: + clc + jmp short exit ;AN000; + + +; NOTE: Carry Flag state from Function calls must be correctly returned +; to the DOS, especially from Fastseek Lookup function + + +;----------------------------------------------------------------------------- +; FASTOPEN FUNCTION DISPATCHER +;----------------------------------------------------------------------------- +DISPATCH_FOPEN: ; dispatch FOPEN functions + cld ;AN000; + mov cs:Purge_Flag, 0 ; reset purge flag + cmp al, FONC_update ;AN000; + jne Chk_02 ;AN000; + CALL CS:Fopen_Update ; UPDATE ;AN000; + jmp short exit ;AN000; + +Chk_02: + cmp al, FONC_insert ;AN000; + jne Chk_01 ;AN000; + CALL CS:Fopen_Insert ; INSERT ;AN000; + jmp short exit ;AN000; +Chk_01: + cmp al, FONC_look_up ;AN000; + jne chk_03 ;AN000; + CALL CS:Fopen_lookup ; LOOKUP ;AN000; + jmp short exit ;AN000; +Chk_03: + cmp al, FONC_delete ;AN000; + jne Error_Exit ;AN000; + CALL CS:Fopen_delete ; DELETE ;AN000; + jmp short exit ;AN000; + + + +;----------------------------------------------------------------------------- +; EXIT TO DOS FROM FUNCTIONS +;----------------------------------------------------------------------------- + +ERROR_EXIT: ; EXIT from invalid drive id search loop + CALL RESTORE_PAGE_STATE ; restore frame buff status ;AN000; + ; on return AX should have function code + pop bx ; restore first two regs of DOS + pop di ;AN000; + cmp al,FSK_Lookup ;AN000; + jne exit_2 ;AN000; + mov di,1 ; set error flag - invalid drive id ;AN000; + stc ;AN000; + jmp short Exit_1 ;AN000; + +EXIT_2: + clc ;AN000; + jmp short Exit_1 ;AN000; + + +; Normal Exit from Fastopen Functions except Fastseek Lookup function +EXIT: + CALL RESTORE_PAGE_STATE ; restore EMS page state ;AN000;;AN000; + pop bx ; restore BX ;AN000; + pop di ; restore DI ;AN000; + + +; Exit from FastSeek Lookup function. Dont restore BX and DI +EXIT_1: + pop bp ; restore remaining DOS registers + pop es ; except BX and DI since they contain ;AN000; + pop ds ; return values. ;AN000; + pop dx ;AN000; + pop cx ;AN000; + +ERROR_RET: + ret ;AN000; + +MAIN ENDP + +IF BUFFERFLAG +;--------------------------------------------------------------------------- +; Procedure name : save_ems_page_state +; +; Description: +; Saves the state of the page whose physical segment value is +; specified in Main_EMS_PAGE_SEG. +;--------------------------------------------------------------------------- + +SAVE_EMS_PAGE_STATE PROC FAR + + PUSH AX ; save registers + PUSH CX + PUSH DX ;AN000; + PUSH DS ;AN000; + PUSH ES ;AN000; + PUSH BP ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH BX ;AN000; + + MOV AX, SEG EMS_PAGE_MAP ; get segid + MOV DS,AX + LEA SI,EMS_PAGE_MAP ; DS:SI-->page map struc + MOV AX, SEG EMS_PAGE_ARRAY ; get segid + MOV ES,AX + LEA DI,EMS_PAGE_ARRAY ; ES:DI-->Page ARRAY + MOV AH,EMS_SAVE_STATE ; + MOV AL,0 ; subfunction code + INT EMS_INT ; save page state ;AN000; + + POP BX ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP BP ;AN000; + POP ES ;AN000; + POP DS ;AN000; + POP DX ;AN000; + POP CX ;AN000; + + CMP AH,0 ; save ok?? + JE SAVE_OK ; + STC + JMP SHORT DONE +SAVE_OK: + CLC +DONE: + POP AX + RET + +SAVE_EMS_PAGE_STATE ENDP + +ENDIF + + +;----------------------------------------------------------------------------- +; PROCERDURE: RESTORE_PAGE_STATE +; +; Function: Restore state of EMS page +; +; Input: None +; Output: Page is restored +; +;----------------------------------------------------------------------------- + +RESTORE_PAGE_STATE PROC NEAR ;RESTORE EMS PAGE STATE + PUSHF ;save flag ;AN000; + CMP CS:MAIN_EMS_FLAG, 0 ;EMS enabled ?? ;AN000; + JNE REST_PUSH_REGS ;yes, restore registers + JMP SHORT RESTORE_EXIT ;no, exit ;AN000; + ;yes, restore page registers +REST_PUSH_REGS: + PUSH AX ; save function code + PUSH CX ; save caller registers ;AN000; + PUSH DX ;AN000; + PUSH DS ;AN000; + PUSH ES ;AN000; + PUSH BP ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH BX ;AN000; + + MOV AX, SEG EMS_PAGE_ARRAY + MOV DS,AX + LEA SI,EMS_PAGE_ARRAY ; DS:SI-->Page array + MOV AH,EMS_RESTORE_STATE ; + MOV AL,1 ; + INT EMS_INT ; restre page state ;AN000; + CMP AH,0 ; restore OK ?? + JE REST_POP_REGS ; yes + STC ; set carry + +REST_POP_REGS: + POP BX ; RESTORE REGISTERS ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP BP ;AN000; + POP ES ;AN000; + POP DS ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP AX ; restore function code + +RESTORE_EXIT: + POPF + RET ;AN000; + +RESTORE_PAGE_STATE ENDP + + +IF BUFFERFLAG + +;---------------------------------------------------------HKN 8/26/88------- +; procedure name : map_page +; Inputs : ems_page_number = physical page frame +; number. +; ems_save_handle1 = emm_handle. +; Output : CY - error +; NC - page is mapped to logical page 0 +;---------------------------------------------------------------------------- +map_page proc near + + push ax + push bx + push dx + + xor bx, bx + mov ax, cs:ems_page_number ; contains the page number obtained + ; during fastopen intialization. + mov ah, 44h + mov dx, cs:ems_save_handle1 ; contains the emm handle that was + ; obtained during fast init. + int ems_int + or ah, ah + jnz err_map_page + clc + jmp short map_page_done + +err_map_page: + stc + +map_page_done: + pop dx + pop bx + pop ax + ret + +map_page endp + +ENDIF + + + ; NOTE: +CSEG_MAIN ENDS ; End of the first portion of the + ; Cseg_Main segment. Remaining + ; portion is in Fastinit.asm + +;----------------------------------------------------------------------------- + + + + + +;============================================================================== +; All Fastopen functions are kept in a seperate segment. These are accessed +; by a FAR indirect call from the MAIN routine. +; ADDRESSABILTY: CS is used for accessing local data in Cseg_Open segment +; DS is used for accessing data in the drive cache buffer +; in the Cseg_Init segment +; ES is used for accessing data in the name cache buffer +; in the Cseg_Init segment +; +;***************************************************************************** +CSEG_OPEN SEGMENT PARA PUBLIC 'code' + ASSUME cs:cseg_open,ds:nothing,es:nothing,ss:nothing +;***************************************************************************** + +PUBLIC Open_name_cache_seg ;AN000; +PUBLIC Open_name_Drive_Buff ;AN000; +PUBLIC End_Open ;AN000; +PUBLIC Chk_Flag ;AN000; + +;---- FastOpen Functions Local Variables -------------- + +Current_Node DW ? ;address of current node entry buffer ;AN000; +Current_Sibling DW ? ;address of current sibling node entry buffer ;AN000; +Current_Drive DW ? ;address of current drive header ;AN000; +Matching_Node DW -1 ;flag ;AN000; +From_Delete DW 0 ;= 1 if call is from DELETE function ;AN000; +Old_SI DW 0 ;SI save area ;AN000; +Flag DB 0 ;AN000; +Level DB 0 ;depth level of the path ;AN000; +Dir_Info_Buffer DD ? ;Dir_Info buffer inside DOS ;AN000; +Extended_Info_Buffer DD ? ;Extended Info buffer inside DOS ;AN000; +New_FEI_clusnum DW 0 ;AN000; +Packed_Name DB 11 dup (0) ;Space for packed dir name ;AN000; +Top DW 0 ;AN000; +Temp DW 0 ;AN000; +Bottom DW 0 ;AN000; +Depth DB 0 ;AN000; + +Chk_Flag dw 0 ; flag used by the analyser +func_cod db 0 ; function code for analyser + +;Following data area is filled during initialization +Open_name_cache_seg DW Cseg_Init ; address of name cache buffer +Open_name_Drive_Buff DW 0 ; address of first drive buffer + + + + +; +;============================================================================== +; Pathname Tree Search +; +; Element of each path name is represented by a node in the tree. First +; node is connected to the the Drive header through first child pointer +; (DCH_Child_Ptr). The first node may have one or more nodes underneath. +; The first one is called the Child of this node and the others are the siblings +; of the child node. Previous node is connected to the first node through +; the child pointer (nChild_Ptr) and the siblings are connected through the +; sibling pointer (nSibling_Ptr). Each node is connected to the previous +; node through a backward pointer (nBackward_Ptr). For example, to go to the +; previous node from any of the siblings. It is necessary to go to the +; child through previous siblings (if any) and then to the previous from the +; child. All this backward movement is using nBackward_Ptr. +; Similarly to go to a child or sibling, nChild_ptr or nSibling_Ptr should be +; used. The strucure of drive header and the node are defined in Fastopen.inc +; + +;============================================================================== +;Subroutine: LOOKUP +; +;INPUT: +; DS:SI -> path (drive letter D: will be validated by Find_Drive_Cache_hdr) +; ES:DI -> DIR_INFO buffer to be returned inside DOS +; ES:CX -> FASTOPEN_Extended_Info buffer inside DOS +; ES:BP -> Drive_Cache_Heade +; +; +;OUTPUT: +; If the whole path is found, +; DS:SI--> 0 +; ES:DI--> DIR_INFO buffer is filled with directory info +; ES:CX--> EXT_INFO buffer is filled with extended info +; +; If partially found the path, +; DS:SI--> '\' after the matching directory name +; ES:DI--> DIR_INFO buffer is filled with directory info +; ES:CX--> EXT_INFO buffer is filled with extended info +; +; If the Name_cache tree is empty, i.e.,no root directory name, +; DS:SI--> '\' after ':' +; ES:DI--> DIR_INFO buffer is undetermined +; ES:CX--> EXT_INFO buffer is undetermined +; +;============================================================================== + +LOOKUP PROC FAR + + mov cs:func_cod,al ; save function code + cmp From_Delete, 0 ;call from DELETE function ?? + je Look_Pack_Dir ;no, dont restore DS + mov DS,bx ;yes, restore DS + ASSUME DS:Cseg_Init + jmp short Look_save_regs ;save registers + +Look_Pack_Dir: + CALL PACK_DIR_NAME ;on return drive letter => DL, + + CALL FIND_DRIVE_CACHE_HEADER ;find drive header address + ;on return ES:BP-->drive header + jnc look_save_regs ;drive buffer found + jmp lookup_error ;drive buffer not found + +Look_Save_Regs: + push es + push di + push cx + mov ax, cs:Open_Name_Cache_Seg ;AN000; + mov es, ax ;ES = Name_Cache_Seg ;AN000; + ASSUME es:Cseg_Init ;AN000; + CALL SET_LRU ;set the Real LRU, if any. + + or cs:Flag,Is_drive_head ;level of the tree. Drive header + mov cs:Matching_Node, -1 ;Nothing found yet. + mov cs:Current_Drive, BP ;drive header + mov cs:Level, 0 ;path level is 0 + +Lookup_Path: + mov cs:Current_Node, BP ;save current node address + mov cs:Current_Sibling,0fffeh ;set no sibligs yet. + mov cs:Old_SI, si ;save current path address + + CALL PACK_DIR_NAME ;get the next dir name from the path + jc Lookup_Done ;yes, found the whole path. + + test cs:Flag, Is_drive_head ;dir name = drive header ? + jz Lp_Path1 ;no- + + push ds ;yes-drive header + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init + mov BP, DS:[BP.DCH_Child_ptr] ;BP-->first child node under drive hdr + pop ds + ASSUME ds:nothing + jmp short Lp_Path2 + +Lp_Path1: + mov BP, ES:[BP.nChild_ptr] ;BP--> child of current node + +Lp_Path2: + cmp BP, -1 ;no child? + je Lookup_Done ;Not found or partially found + mov cs:Current_Node, BP ;current_node = found node + and cs:Flag, Not_drive_head ;reset the flag. + +Lp_Cmpare: + CALL CMPARE ;look for path in current node + je Lookup_Found ;Yes, found a match. Next level for + ;possible remianing path + + mov BP, ES:[BP.nSibling_ptr] ;not found. Any siblings? + mov cs:Current_Sibling,BP + cmp BP, -1 ;any more sibling? + je Lookup_Done ;no - done + + mov cs:Current_Node, BP ;yes- make the found sibling as a current + jmp short Lp_Cmpare ;node and search path in this node + +Lookup_Found: + inc cs:Level + mov cs:Matching_Node,BP ;Used by Unfold_Name_Record + + CALL PRE_LRU_STACK ;set the TEMP_LRU_Stack + jmp Lookup_Path ;continue to the next dir + +Lookup_Done: + mov si, cs:Old_SI + pop cx ;restore Extended_Info buffer + pop di ;restore Dir_Info buffer + pop es ;the segment for the above buffers + + cmp ax, -1 + je Lookup_ERR ;error occured in Pack_Dir_Name. + clc ;clear carry. + jmp short Lookup_Done1 + +Lookup_ERR: ;error exit + stc + +Lookup_Done1: + test cs:Flag, is_delete ;called by delete? + jnz Lookup_Return + jc Lookup_Exit ;If it was an error, don't change the carry flag + + CALL UNFOLD_NAME_RECORD ;unfold the current node's record +Lookup_Exit: + jmp short Lookup_Return ;return to DOS. + +Lookup_Error: ;error exit + stc + mov ax,-1 + +Lookup_Return: ;return to Delete routine. + CALL Check_It ;check tree structure + ret + +LOOKUP ENDP + + + + + +;============================================================================== +;SUBROUTINE: INSERT +; +;INPUT: DS:DI -> Dir_Info in DOS +; ES:BX -> Fastopen_Extended_Info in DOS +; Current_Node, Current_Sibling, Current_Drive, Flag +; +;OUTPUT: Information inserted into Name_cache_tree. +; +; Any Sequential Insert operation should be preceded by a Look_up +; operation. For ex., if the DOS wants to insert C:\DIR1\DIR2\File1 +; and suppose there is no matching name cache record for DIR1 in the tree. +; Firstly DOS will try to look up C:\DIR1\DIR2\File1. FASTOPEN will +; return to DOS with DS:SI points to "\" after the drive letter. +; Then, DOS will simply ask an insert operation with DS:DI, ES:BX +; points to the information on "DIR1". FASTOPEN will insert DIR1 +; onto the tree. After that DOS will ask another insert +; operation for DIR2. FASTOPEN will insert DIR2. Finally DOS will +; ask to insert File1. +; +; Suppose when DOS try to look up C:\DIR1\DIR2\File2 at this moment. +; FASTOPEN will return to DOS with DS:SI points to "\" after DIR2 (since +; DIR2 information is already in the name cache tree). Then DOS will ask +; to insert File2. +; +; Any Insert operation of subdirectory name which is deeper than (Number_ +; of_Entries - 1) will not be inserted but will just return. +; Also, for the safety reason, if the would be freed node (=LRU node) is +; the same as the Current_Node, there will be no insertion. (This is a simple +; safety valve. A more smart logic can look for the next **legitimately +; available** LRU node to use, or sometimes, simply replace the contents of the +; entry if adequate. But this will increase the complexity greatly, and I +; think the current logic is still practical enough to use despite of the +; possible small window of performance degradation in a very special cases. J.K.) +; +;============================================================================== + +INSERT PROC FAR + mov cs:func_cod,al ; save function code + inc cs:Level ;increment directory level + xor ax,ax + mov al, cs:Level + inc al + mov bp, cs:Current_Drive ;BP-->address of current drive header + push ds + mov ds,cs:Open_Name_Cache_Seg ;DS=name cache segment + + ASSUME ds:Cseg_Init ;AN000; + cmp ax, ds:[bp.DCH_Num_Entries] ;Level > (Num_Entries - 1) ? + pop ds + ASSUME ds:nothing + jbe Insert_it ;no- insert it + jmp short Insert_return ;yes return + +Insert_it: + or cs:Flag, is_insert + + CALL GET_FREE_NODE ;AX = offset value of the available + ;name_record in Name_Cache_Seg. + jc I_Exit ;Current node = would-be freed node. + + CALL MAKE_NAME_RECORD ;Fill the above name record entry. + ;ES was changed to Name_Cache_Seg. + + mov bp, cs:Current_Node ;set BP to current_node + mov bx, bp ;save it into bx + cmp cs:Current_Sibling,0fffeh ;current node sibling node ?? + je I_Child ;no-child of preceding node + mov es:[bp.nSibling_ptr], ax ;yes-make new node sibling of + jmp short I_Done ;current node + +I_Child: ;set nChild_ptr + test cs:Flag,Is_drive_head ;drive level? + jnz I_Child_first ;Yes, must be the first child + mov es:[bp.nChild_ptr], ax ;no-make ndew node child of + jmp short I_Done ;current node + +I_Child_first: ;this is the first child in this drive. + push ds + mov ds,cs:Open_Name_Cache_Seg ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov ds:[bp.DCH_Child_ptr],ax ;make new node 1st child current drive + pop ds + ASSUME ds:nothing + mov bx, cs:Current_Drive ;change bx to Current_Drive + and cs:Flag, Not_drive_head ;reset the flag + +I_Done: + mov bp, ax + mov es:[bp.nBackward_ptr],bx ;set the backward ptr of the inserted node. + + CALL PRE_LRU_STACK ;save this inserted record temporarily. + + mov cs:Current_Node,bp ;make new node current node + ;any subsequent insert operation + mov cs:Current_Sibling,0fffeh ;should be installed as a child + +I_Exit: + and cs:Flag, not_insert ;set not insert flag + +Insert_return: + CALL Check_It ;check tree structure + ret ;return + +INSERT ENDP + + + + + + +;============================================================================== +;Subroutine: DELETE +; +;INPUT: DS:SI -> path +; ES:BP -> drive_cache_header (for Look_Up operation) +; +;OUTPUT: if found, then remove the matching Name_Record will be removed from +; the tree and from the LRU chain. The freed entry will be placed +; on top of the LRU chain. +; +;============================================================================== + +DELETE PROC FAR + + mov cs:func_cod,al ; save function code + CALL PACK_DIR_NAME ;drive letter => DL, ;AN000; + + CALL FIND_DRIVE_CACHE_HEADER ;find drive header address + ;on return ES:BP-->drive header + jc d_err_exit ;error exit + + or cs:Flag, is_delete ;set the flag for Look_up. + push ds ;save DS in BX since it is going to be + pop bx ;changed for jumping to other segment + push ds + mov ax,cseg_Main + mov ds,ax ;DS=Main segment ID + assume ds:Cseg_Main + mov cs:From_Delete, 1 ;set flag indicate that the call + ;is from DELETE function + CALL VECTOR_LOOKUP ;FAR call to Lookup function + + mov cs:From_Delete, 0 ;reset from delete flag + pop ds + ASSUME ds:nothing + jc D_err_Exit ;indirectly in the same segment + + cmp byte ptr ds:[si], 0 ;found the whole path? + jne D_err_Exit ;No. + +;At this point, Current_Node = BP. + mov bx, cs:Open_Name_Cache_Seg + mov es, bx ;set ES to name_cache_seg. + ASSUME es:Cseg_Init + +Delete_Node: + cmp es:[bp.nChild_ptr], -1 ;No children? + jne D_err_Exit + CALL REMOVEFROMTREE ;remove the node while maintaing the + ;integrity of the tree. + + mov es:[bp.nCmpct_Dir_Info], ' ' ;mark that this entry is free!!! + +D_LRU_MRU: + CALL REMOVEFROMLRUCHAIN ;Remove BP from the LRU,MRU chain + + mov si, cs:Current_Drive ;Now let the deleted node to be the + push ds ; LRU node + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init ;AN000; + + mov bx, ds:[si.DCH_LRU_ROOT] ;es:bx -> first node + mov es:[bp.nLRU_ptr],bx ;Target.nLRU_ptr -> first node + mov es:[bx.nMRU_ptr],bp ;First_node.nMRU_ptr -> target + mov ds:[si.DCH_LRU_ROOT],bp ;LRU_ROOT -> target + mov es:[bp.nMRU_ptr],-1 + pop ds + ASSUME ds:nothing + jmp short D_Exit ;exit + +D_err_Exit: ;error exit + stc + mov ax, -1 + +D_Exit: + and cs:Flag, not_delete ;reset the flag + CALL Check_It ;check tree structure + ret ;return + +DELETE ENDP + + + + + +;============================================================================== +;Subroutine: UPDATE +; +;INPUT: If AH = 0, then update Dir_Entry area. +; ES:DI -> Dir_entry ("dir_first" is the key to search). +; DL = Logical Drive number (0 = A, 1 = B, ...). +; +; If AH = 1, then update "Fastopen_extended_info.FEI_clusnum". +; DL = Logical Drive number (0 = A, 1 = B, ...) +; CX = The value of "dir_first" to search. +; BP = new value of FEI_clusnum in the extended_info area. +; +; If AH = 2, then delete the entry. Same effect as Delete function +; except this time the keys used to delete are; +; DL = logical drive number +; CX = the value of "dir_first" to search. +; +; If AH = 3, then delete the entry. Same effect as Delete function +; except this time the keys used to delete are; +; DL = logical drive number +; DH = directory position +; DI = directory sector (low value) +; CX = directory sector (high value) +; +; +;OUT: if found, then data is updated +; else CY and AX = -1. +; +; This routine use "starting cluster number" and "drive letter" +; as a key to find the name record. Usually the reason is DOS +; does not have any "full path" information about the file when +; it has to call this routine to update the information. +; It follows the MRU chain until it finds the name record or +; until it reaches the free name record (identified by the +; Directory name starting with ' '), or until the end of +; the MRU chain. +; +;============================================================================== + +UPDATE PROC FAR + + mov cs:func_cod,al ; save function code + cmp ah, 0 ;update directory entry ? + je Update_Dir_Entry ;yes- + cmp ah, 1 ;update extended info ? + je Update_Extended_clusnum ;yes- + cmp ah, 2 ;delete based on first clus num ? + je Update_Delete ;yes- + cmp ah, 3 ;delete based directory sector ? + je Update_Delete1 ;yes- + +U_ERROR: ;no - error exit + stc + jmp short Update_Exit + +Update_Delete: ; same as delete + CALL FIND_CLUSTER_NUMBER ; find name entry using first cluster + jc U_ERROR + jmp Delete_Node ; if found, delete entry + +Update_Delete1: ; same as delete (PTR P3718 3/10/88) + CALL FIND_DIR_SECTOR ; find name entry using directory + jc U_ERROR ; sector and directory position + jmp Delete_Node ; if found, delete node + +Update_Dir_Entry: + mov cx, es:[di.dir_first] + push es ;save Dir_Info pointer ES:DI + push di + CALL FIND_CLUSTER_NUMBER + pop si ;restore Dir_Info pointer in DS:SI + pop ds + jc U_ERROR ;error-if not found + + push bp ;found the entry + pop di + add di, nCmpct_Dir_Info ;ES:DI->Name_Record.nCmpct_Dir_Info + mov cx, ODI_head_leng + REP MOVSB ;update Cmpct_dir_info head section + add si, ODI_skip_leng + mov cx, ODI_tail_leng + REP MOVSB ;update tail section + jmp short Update_Exit ;exit + +Update_Extended_clusnum: ;update extended info field + mov cs:New_FEI_clusnum,bp + CALL FIND_CLUSTER_NUMBER ;Find entry based first cluster number + jc U_ERROR + + add bp, nExtended_Info ;es:bp -> Name_record.nExtended_Info + mov bx, cs:New_FEI_clusnum + mov es:[bp.FEI_clusnum],bx + +Update_Exit: + CALL Check_It ;check tree structure + ret ;return + +UPDATE ENDP + + + + + + +;============================================================================== +;Subroutine: FP_PURGE Rest Name Cache Buffers +; +;INPUT: Main_Name_Drive_Buff - Offset to Name cache buffer +; Main_Name_Cache_Seg - Name cache seg id +; DL = Drive ID +; +;OUT: Buffer is purged +; +;============================================================================== + +FP_PURGE PROC FAR + + mov si,Open_Name_Drive_Buff ; SI-->first Name drive cache buff + mov es,Open_Name_Cache_Seg ; ES = name cache seg ID + mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer + inc dl ; DL=drive number + add dl,040H ; convert drive num to drive letter + +; Search for the name drive header corresponds to the drive letter +Purge_Drv_Loop: + cmp es:[si].DCH_Drive_Letter,dl ; drive letter match ?? + je Purge_drive_cache ; yes - set drive cache + add si, size Drive_Cache_Header ; no - get address of next drive cache + jmp purge_drv_loop ; try next name drive header + +Purge_Drive_Cache: ; SI-->drive header + mov bx,es:[si].DCH_Name_Buff ; BX-->Name cache buffer + mov cx,es:[si].DCH_num_entries ; get number of name records + mov ax,bx ; save last name record address + mov es:[bx].nMRU_ptr, -1 ; make first MRU -1 + jmp short set_start + +Set_Up_Names: + mov es:[bx].nMRU_ptr,ax ;save last name record as MRU entry + add ax, size Name_Record ;AX = last name record = current name record + +Set_Start: + mov es:[bx].nChild_ptr, -1 ;no children or siblings + mov es:[bx].nsibling_ptr, -1 ;right now + mov es:[bx].nBackward_ptr, -1 + + push di + push ax + mov ax, ' ' ;AX = ' ' + mov di, bx ;DI-->current name record + add di, nCmpct_Dir_Info ;blank out the Dir name area + stosb ;in the name record + stosw + stosw + stosw + stosw + stosw + pop ax ; AX = last name record address + pop di + + dec cx ;update record count + jcxz purge_exit ;exit if last name record is done + mov dx,bx + add dx, size Name_Record ;DX-->next name record + mov es:[bx].nLRU_ptr,dx ;set LRU pointer - next name record + add bx, size Name_Record + jmp set_up_names ;set next name record + +Purge_exit: + clc + ret + +FP_PURGE ENDP + + + +;---------------------------------------------------------------------------- +; FASTOPEN SUPPORT ROUTINES +;---------------------------------------------------------------------------- +; +; PROCEDURE: Find_Drive_Cache_Header +; +; Function: Validate drive ID and find address of drive cache header +; +;IN: DL - drive letter +; Drive_Header_Start ;label +; Flag. +; +;OUT: If CY = 0 Drive Header found +; ES:BP -> Drive_Cache_Header, +; +; If CY = 1 Drive Header not found +; +;---------------------------------------------------------------------------- + +FIND_DRIVE_CACHE_HEADER PROC NEAR + + mov bp, cs:Open_name_drive_buff + push ds + mov ds,cs:Open_Name_Cache_Seg ;AN000; + ASSUME ds:Cseg_Init ;DS:BP-->first drive header ;AN000; + +FDCH_while: + cmp byte ptr ds:[bp.DCH_Drive_Letter], dl ; drive letter match + jne fdch_chk_end ; no - check next header + clc ; yes - exit + jmp short FDCH_Exit + +FDCH_Chk_End: + cmp byte ptr ds:[bp.DCH_Sibling_ptr], -1 ; is this last header ? + je FDCH_Not_Found ; yes - header not found + add bp, size Drive_Cache_Header ; no - get next header + jmp short FDCH_while ; look for match + +FDCH_Not_Found: + stc ;not found + +FDCH_Exit: ;ES:BP-->header if found + pop ds + ASSUME ds:nothing ;return + ret + +FIND_DRIVE_CACHE_HEADER endp + + + + +;---------------------------------------------------------------------- +; PROCEDURE: GET_FREE_NODE +; +; called by Insert. The LRU node pointed DCH_LRU_ROOT is returned in AX +; and DCH_LRU_ROOT points to the following node in LRU chain. +; If the node is not an empty node, then it will be removed from the +; tree. +; +; IN: Current_Drive, Current_Node +; +; OUT: AX = offset of the free node in Name_Cache_Seg +; Other registers saved. +;---------------------------------------------------------------------- + +GET_FREE_NODE PROC NEAR + + push es ;save registers + push di + push si + push bp + + mov ax, cs:Open_Name_Cache_Seg ;AN000; + mov es, ax ;ES=Name cache segment ;AN000; + ASSUME es:Cseg_Init ;AN000; + mov si, cs:Current_Drive ;SI-->drive_cache_header + push ds + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init + mov ax, ds:[si.DCH_LRU_ROOT] ;get the LRU node + pop ds + ASSUME ds:nothing + + cmp ax, cs:current_Node ;LRU node=Current Node ?? + je GFN_skip ;yes- + + mov bp, ax ;BP=Current node + mov di, es:[bp.nLRU_ptr] ;DI= current LRU node's following node + mov es:[di.nMRU_ptr],-1 ;set that node's MRU ptr + push ds + mov ds,cs:Open_Name_Cache_Seg ;DS=Name cache segment + ASSUME ds:Cseg_Init + mov ds:[si.DCH_LRU_ROOT],di ;connect previous node to + pop ds ;next node + ASSUME ds:nothing + + cmp byte ptr es:[bp.nCmpct_Dir_Info],' ';an empty node? + je GFN_OK ;then no problem. + + CALL RemoveFromTree ;otherwise, it should be removed + ;from the tree. +GFN_OK: + clc + jmp short GFN_ret + +GFN_Skip: + stc + +GFN_ret: + pop bp + pop si + pop di + pop es + ret ;return + +GET_FREE_NODE endp + + + + +; +;---------------------------------------------------------------------- +; PROCEDURE: PRE_LRU_STACK +; +; When called by Look_up, Insert routine, the requested target node (BP) +; will be temporarily removed from LRU,MRU chain (until SET_LRU routine +; call), and will be pushed into a logical stack. Actually, this routine +; will not use a stack, but try to get the effect of the use of stack +; to keep the history of target nodes in "REVERSE" LRU order as follows; +; { inc Depth; +; if Depth == 1 then Bottom = BP; +; Bottom.LRU_ptr = -1; +; Bottom.MRU_ptr = -1; +; else if Depth == 2 then Top = BP; +; Top.LRU_ptr = Bottom; +; Bottom.MRU_ptr = Top; +; Top.MRU_ptr = -1; +; else if Depth >= 3 then Temp = Top; +; Top = BP; +; Top.LRU_ptr = Temp; +; Temp.MRU_ptr = Top; +; Top.MRU_ptr = -1; +; } +; +;IN: Depth, Top, Bottom, Temp, +; Requested target node (BP) +; ES = Name_Cache_Seg +; +;OUT: Target node removed from LRU,MRU chain. +; Target node's history saved in reverse LRU order. +; If called by "Delete" routine, then will just exit. +; If called by "Insert" routine, then will not attempt +; to remove the target node. +;---------------------------------------------------------------------- + +PRE_LRU_STACK PROC NEAR + + test cs:Flag, is_delete ;invoked by Delete routine + jnz PLS_Exit + test cs:Flag, is_insert ;called by Insert routine + jnz PLS_Push + + CALL RemoveFromLRUChain ;remove BP from the chain. + +PLS_Push: + push di + + inc cs:Depth + cmp cs:Depth, 1 + jne PLS_Top + mov cs:Bottom, bp ;bottom = bp + mov es:[bp.nLRU_ptr], -1 + jmp short PLS_Done + +PLS_Top: + cmp cs:Depth, 2 + jne PLS_Temp + mov cs:Top, bp ;Top = bp + mov di, cs:bottom ;di = bottom + +PLS_com: + mov es:[bp.nLRU_ptr],di ;Top.LRU_ptr = bottom + mov es:[di.nMRU_ptr],bp ;Bottom.MRU_ptr = top + jmp short PLS_Done + +PLS_Temp: + mov di, cs:Top ;di = Top + mov cs:Temp, di ;Temp = di + mov cs:Top, bp ;Top = bp + jmp short PLS_com + +PLS_Done: + mov es:[bp.nMRU_ptr],-1 + pop di + +PLS_Exit: + ret + +PRE_LRU_STACK endp +; + + + + + +;---------------------------------------------------------------------- +;PROCEDURE: SET_LRU +; +;INPUT: Depth, Top, Bottom, Current_Drive, ES = Name_Cache_Seg +; +;OUT: If Depth == 0 then exit +; Pre_LRU_Stack procedure already maintained a reverse order LRU +; mini chain. Set_LRU will just put the top after the last node +; of the current LRU chain; +; { Get the last node of LRU chain. +; if Depth == 0 then exit; +; if Depth == 1 then Last_Node.LRU_ptr = Bottom; +; Bottom.MRU_ptr = Last_Node; +; MRU_ROOT = Bottom; +; if Depth >= 2 then Last_Node.LRU_ptr = Top; +; Top.MRU_ptr = Last_Node; +; MRU_ROOT = Bottom; +; Depth = 0; +; } +;---------------------------------------------------------------------- + +SET_LRU PROC NEAR + + cmp cs:Depth, 0 ;nothing in the stack? + je SL_Exit + + push si + push di + push bx + mov si, cs:Current_Drive ;cs:si -> Drive_Cache_Header + push ds + mov ds,cs:Open_Name_Cache_Seg ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov di, ds:[si.DCH_MRU_ROOT] ;es:di -> Last node in LRU chain + + cmp cs:Depth, 1 + jne SL_Other + + mov bx, cs:Bottom + mov es:[di.nLRU_ptr],bx ;Last_Node.LRU_ptr = Bottom + mov es:[bx.nMRU_ptr],di ;Bottom.MRU_ptr = Last_Node + mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT = Bottom + jmp short SL_Done + +SL_Other: ;Depth >= 2 + mov bx, cs:Top + mov es:[di.nLRU_ptr],bx + mov es:[bx.nMRU_ptr],di + mov bx, cs:Bottom + mov ds:[si.DCH_MRU_ROOT],bx + +SL_Done: + pop ds + ASSUME ds:nothing + mov cs:Depth, 0 ;reset the Depth + pop bx + pop di + pop si + +SL_Exit: + ret + +Set_LRU endp + + + + + +;---------------------------------------------------------------------- +; Procedure RemoveFromLRUChain +; +;IN: Target node (BP) to be removed +; Current_drive +; ES - Name_Cache_Seg +; +;OUT: Target node removed from the LRU,MRU chain. LRU,MRU chain +; updated. +; +;---------------------------------------------------------------------- + +RemoveFromLRUChain PROC near + + push bx + push di + push si + + mov si, cs:Current_drive ;cs:si-> Drive_cache_header + mov bx, es:[bp.nMRU_ptr] ;es:bx-> Preceding node + mov di, es:[bp.nLRU_ptr] ;es:di-> Following node + cmp bx, -1 ;Is target the first node? + je RFLC_first_node + cmp di, -1 ;Is target the last node of LRU chain? + je RFLC_last_node + mov es:[bx.nLRU_ptr],di ;Preceding.LRU_ptr->following node + mov es:[di.nMRU_ptr],bx ;Following.MRU_ptr->preceding node + jmp short RFLC_done + +RFLC_first_node: + push ds + mov ds,cs:Open_Name_Cache_Seg ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov ds:[si.DCH_LRU_ROOT],di ;LRU_ROOT-> following node + pop ds + ASSUME ds:nothing + mov es:[di.nMRU_ptr], -1 ;Following node's MRU_ptr + jmp short RFLC_done + +RFLC_last_node: + push ds + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init + mov ds:[si.DCH_MRU_ROOT],bx ;MRU_ROOT-> preceding node + mov es:[bx.nLRU_ptr], -1 ;Preceding node's LRU_ptr + pop ds + ASSUME ds:nothing + +RFLC_done: + pop si + pop di + pop bx + ret + +RemoveFromLRUChain endp +; + + + +;---------------------------------------------------------------------- +; Proceure RemoveFromTree +; +;IN: BP - offset of node to be removed from the tree +; This node shoud not be a subdirectory that is not empty!!! +; ES - Name_Cache_Seg +; Current_Drive +; +;OUT: The node will be freed from the tree. +; The neighbor's Child_ptr, Sibling_ptr, Backward_ptr are adjusted +; accordingly. +; The freed node's child_ptr, sibling_ptr, backward_ptr are reset to -1. +;---------------------------------------------------------------------- + +REMOVEFROMTREE PROC NEAR + + push bx + push dx + + mov bx, es:[bp.nBackward_ptr] ;get the preceding node + mov dx, es:[bp.nSibling_ptr] ;get the sibling node + cmp bx, cs:Current_Drive + je RFT_First_Child ;bp is the first child + cmp es:[bx.nChild_ptr],bp + je RFT_Child ;bp is the child of the preceding node + mov es:[bx.nSibling_ptr],dx ;bp is the Sibling of the preceding node + ;Update the preceding node's Sibling ptr + jmp short RFT_Reset + +RFT_First_Child: + push ds + mov ds,cs:Open_Name_Cache_Seg ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov ds:[bx.DCH_Child_ptr],dx + pop ds + ASSUME ds:nothing + jmp short RFT_Reset + +RFT_Child: + mov es:[bx.nChild_ptr],dx + +RFT_Reset: ;reset the deleted node's tree pointers + mov es:[bp.nChild_ptr],-1 + mov es:[bp.nSibling_ptr],-1 + mov es:[bp.nBackward_ptr],-1 + + xchg dx,bx ;now, dx=preceding node, bx=following node + cmp bx,-1 ;end of sibling? + je RFT_ret + mov es:[bx.nBackward_ptr],dx;modify backward_ptr of the sibling node + +RFT_ret: + pop dx + pop bx + ret ;return + +REMOVEFROMTREE endp +; + + + + +;---------------------------------------------------------------------- +; Procedure CMPARE +; +;IN: Packed name +; BP = target node +; +;OUT: ZERO flag set when compare O.K. +; DI destroyed. +;---------------------------------------------------------------------- + +CMPARE PROC near + + push ds + push si + mov cx, 11 + push cs + pop ds + mov si, offset cs:Packed_Name ;ds:si -> Packed_Name + mov di,bp + add di,nCmpct_Dir_Info ;es:di -> bp.nCmpact_Dir_Info + REPE CMPSB + pop si + pop ds + ret +CMPARE endp + + + + +; +;---------------------------------------------------------------------- +; Procedure: MAKE_NAME_RECORD +; +;IN: DS:DI -> Dir_Info, ES:BX -> Extended_Info +; AX = offset of the Name_Record entry in Name_Cache_Seg. +; +;OUT: Name_Record in Name_Cache_Seg filled. +; nLRU_ptr, nChild_ptr, nSibling_ptr and nMRU_ptr are set to -1 for now. +; ES, SI, DI destroyed. ES will be Name_Cache_Seg. +;---------------------------------------------------------------------- + +MAKE_NAME_RECORD PROC NEAR + + push ds ;save DS + push ax + + push es ;save Extended_Info seg in DOS + push di + pop si ;DS:SI -> Dir_Info + mov di, cs:Open_Name_Cache_Seg ;AN000; + mov es, di ;AN000; + ASSUME es:Cseg_Init ;AN000; + mov di, ax ;ES:DI -> Name_Record + mov ax, -1 + mov es:[di.nLRU_ptr],ax ;initialize pointers + mov es:[di.nChild_ptr],ax + mov es:[di.nSibling_ptr],ax + mov es:[di.nMRU_ptr],ax + add di, nCmpct_Dir_Info ;ES:DI -> Name_Record.nCmpct_Dir_Info + mov cx, ODI_head_leng ;currently 10. + rep movsb ;Move header part + add si, ODI_skip_leng ;DS:SI -> tail part of Dir_Info + mov cx, ODI_tail_leng + REP MOVSB ;move tail part. + + pop ds ;restore Extended_Info seg in DS!!! + mov si, bx ;DS:SI -> Extended_Info + mov cx, size Fastopen_Extended_Info + rep movsb ;Move Extended_Info + pop ax + pop ds ;Restore DS + + ret ;return + +MAKE_NAME_RECORD ENDP +; + + + + +;---------------------------------------------------------------------- +; Procedure Unfold_Name_Record +; +;IN: Matching_Node, ES:DI -> Dir_Info buffer, ES:CX -> Extended_Info buffer +; +;OUT: if no matching node is found, then just return +; else Dir_Info, Extended_Info buffer are filled. +;---------------------------------------------------------------------- + +Unfold_Name_Record PROC near + + cmp cs:Matching_Node, -1 + je UNR_Exit ;just exit + push ds + push si + push di + push cx ;save extended_info addr + + mov si, cs:Open_Name_Cache_Seg ;AN000; + mov ds, si ;AN000; + ASSUME ds:Cseg_Init ;AN000; + mov si, cs:Matching_Node + add si, nCmpct_Dir_Info ;DS:SI -> Cmpct_Dir_Info + + mov cx, ODI_head_leng ;Dir_Info header length + REP MOVSB ;Cmpct_Dir_Info.CDI_file_name -> ODI_head + + add di, ODI_skip_leng ;length of Skiped part of Dir_Info + mov cx, ODI_tail_leng ;Dir_Info tail length + REP movsb ;Cmpct_Dir_Info.CDI_Time -> ODI_tail + ;At this moment, SI -> nExtended_Info + + pop di ;ES:DI -> Extended_info + push di ;save di again for cx. + mov cx, size Fastopen_Extended_Info + REP movsb + + pop cx ;restore extended_info addr + pop di + pop si + pop ds + ASSUME ds:nothing +UNR_Exit: + ret ;return + +Unfold_Name_Record endp +; + + + + +;---------------------------------------------------------------------- +; PROCEDURE: PACK DIR_NAME +; +; Parse the name off of DS:SI into Packed_Name. If called first time and +; DS:[SI+1] = ':' then it is ASSUMEd to be a drive letter and it will be +; returned in DL and SI will points to '\' after ':'. If it was a directory +; name then Packed_Name will be set and SI points to '\' or 0 after the +; parsed directory name or filename. This routine will check DS:[SI] when +; called to see if it points to '\' or 0. If it points to '\' then +; it is ASSUMEd that the user want to skip the delimiter. If it was 0, +; then this routine will set carry. So, with a given drive,path string, +; the user is going to keep calling this routine until it returns +; with carry set that tells the end. +;---------------------------------------------------------------------- + +PACK_DIR_NAME PROC NEAR + + cmp byte ptr ds:[si], 0 ;end of path ?? + jne PDN_Drive ;no-check for drive letter + stc + jmp short PDN_Exit ;yes-exit + +PDN_Drive: + cmp byte ptr ds:[si+1], ':' ;drive letter terminater? + jnz PDN_chk_skip ;no - + mov dl, byte ptr ds:[si] ;yes-set DL to the drive letter + inc si + inc si ;set SI -> '\' after ':' + jmp short PDN_Exit ;then exit + +PDN_chk_skip: + cmp byte ptr ds:[si], '\' ;delimeter? + jne PDN_Path ;no- + inc si ;yes-skip delimiter + cmp byte ptr ds:[si], 0 ;end of path ?? + jne PDN_Path ;no-pack path name + stc ;yes-In fact, the input from DOS was + mov ax, -1 ;D:\,0. FASTOPEN will treate + jmp short PDN_Exit ;this as an error. + +PDN_Path: ;pack path name + push es + push di + push ax + + push cs + pop es + mov di, offset cs:Packed_Name ;ES:DI-->pack buffer + + mov ax,' ' + STOSB ;blank out the Packed_Name + STOSW + STOSW + STOSW + STOSW + STOSW + mov di, offset cs:Packed_Name + +PDN_GetName: + LODSB ;DS:SI => AL, SI++ + cmp al,'.' + jz PDN_SetExt + or al,al + jz PDN_GetDone + cmp al,'\' + jz PDN_GetDone + STOSB + jmp short PDN_GetName + +PDN_SetExt: + mov di, offset cs:Packed_Name+8 + +PDN_GetExt: + LODSB + or al,al + jz PDN_GetDone + cmp al,'\' + jz PDN_GetDone + +PDN_StoExt: + STOSB + jmp PDN_GetExt + +PDN_GetDone: + dec si ;set SI back to the delimeter or 0. + pop ax + pop di + pop es + +PDN_Exit: + ret + +PACK_DIR_NAME endp + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: FIND_CLUSTER_NUMBER +; +;IN: DL = driver # (0 = A, 1 = B,...) +; CX = The value of Dir_First in Name_Record to search. +; Search Name_Record entries to find the matching starting cluster number. +; The search uses MRU chain for efficiency. +; +;OUT: ES = Name_Cache_Seg +; BP = Name_Record +; if not found, carry bit. +; ES, BP register changed. +;---------------------------------------------------------------------- + +FIND_CLUSTER_NUMBER PROC NEAR + + push ax + push cx + push dx + add dl, 'A' ;convert to a drive letter + + CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found + jc FCN_exit ;exit if not found + + mov dx, cx ;save the key in DX ;AN000; + mov ax, cs:Open_Name_Cache_Seg ;AN000; + mov es, ax ;AN000; + ASSUME es:Cseg_Init + + CALL SET_LRU ;clean up the LRU stack + + mov cs:Current_Drive,bp ;set Current_Drive (You should not set + ;Current_Drive before SET_LRU at any time!!! + push ds + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init + mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try + mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing + pop ds + ASSUME ds:nothing + +FCN_while: + cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ? + je FCN_not_found ;then no reason to continue search. + + cmp dx, es:[bp.nCmpct_Dir_Info.CDI_cluster] ;matching starting cluster # ? + je FCN_exit ;found it!!! + + mov bp, es:[bp.nMRU_ptr] ;next MRU entry address + cmp bp, -1 ;It was the end of MRU chain? + je FCN_not_found ;not found. End of search + LOOP FCN_while ;else compare cluster and contine... + +FCN_Not_found: + stc + +FCN_exit: + pop dx + pop cx + pop ax + ret + +FIND_CLUSTER_NUMBER ENDP + + + + +;---------------------------------------------------------------------- +; PROCEDURE: FIND_DIR_SECTOR (PTR 3718 3/10/88) +; +; Search Name_Record using directory sector and directory position +; for the name entry. +; +;IN: DL = driver # (0 = A, 1 = B,...) +; DI = Dirctory sector Low value +; CX = Dirctory sector high value +; DH = Dirctory position +; +;OUT: ES = Name_Cache_Seg +; BP = Name_Record +; if not found, carry bit. +; ES, BP register changed. +;---------------------------------------------------------------------- + +FIND_DIR_SECTOR PROC NEAR + + push ax + push cx + push dx + add dl, 'A' ;convert to a drive letter + + CALL FIND_DRIVE_CACHE_HEADER ;ES:BP -> driver header if found + jc FDIR_exit ; error if not found + + mov ax, cs:Open_Name_Cache_Seg ;AN000; + mov es, ax ;AN000; + ASSUME es:Cseg_Init + + CALL SET_LRU ;clean up the LRU stack + + mov ax,cx ; save directory sector high value + mov cs:Current_Drive,bp ;set Current_Drive (You should not set + ;Current_Drive before SET_LRU at any time!!! + push ds + mov ds,cs:Open_Name_Cache_Seg + ASSUME ds:Cseg_Init + mov cx, ds:[bp.DCH_Num_Entries] ;Max number to try + mov bp, ds:[bp.DCH_MRU_ROOT] ;get the start of MRU chaing + pop ds + ASSUME ds:nothing + +FDIR_while: + cmp es:[bp.nCmpct_Dir_Info], ' ' ;Is it a free node ? + je FDIR_NOT_FOUND ;then no reason to continue search. + + cmp di, word ptr es:[bp.nExtended_Info.FEI_dirsec] ;matching directory sector hi? + jne FDIR_Next ;check next entry + + cmp ax, word ptr es:[bp.nExtended_Info.FEI_dirsec+2] ;matching directory sector low ? + jne FDIR_Next ;check next entry + + cmp dh, es:[bp.nExtended_Info.FEI_dirpos] ;matching directory postion ? + je FDIR_Exit ;check next entry + +FDIR_Next: + mov bp, es:[bp.nMRU_ptr] ;next MRU entry address + cmp bp, -1 ;It was the end of MRU chain? + je FDIR_not_found ;not found. End of search + loop FDIR_while ;else compare cluster and contine... + +FDIR_Not_found: ; no found + stc + +FDIR_exit: + pop dx + pop cx + pop ax + ret + +FIND_DIR_SECTOR ENDP + + + + + +;-------------------------------------------------------------------------- +; Procedure: CHECK_IT Call Fastopen Tree Analyser to check the +; consistency of the Directory/File Tree strucutre. +;-------------------------------------------------------------------------- +CHECK_IT PROC NEAR + + pushf ; save all registers + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + cmp cs:Chk_flag,0 ;Fastopen analyser enabled ?? + je Check_Exit ;no - exit + + mov ax,cs:Open_Name_Cache_Seg ;yes-set multiplex function call + mov es,ax + mov ah,091h ;load Multiplex ID + xor al,al + xor cx,cx + mov cl,cs:func_cod ;CL=Fastopen Function code + mov di,cs:Current_Drive ;ES:DI-->current drive header + INT 2FH ;call the analyser + +Check_Exit: + pop es ;restore all registers + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf ;return + ret + +CHECK_IT ENDP + + + + + +; Calculate the size of the CSEG_OPEN Module in bytes + IF ($-Cseg_Open) MOD 16 ;AN000; + ORG ($-Cseg_Open)+16-(($-Cseg_Open) MOD 16) ;AN000; + ENDIF ;AN000; + +END_OPEN label word + + + + +CSEG_OPEN ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK b/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK new file mode 100644 index 0000000..eb37c6e --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.LNK @@ -0,0 +1,7 @@ +FASTOPEN.OBJ+ +FASTSEEK.OBJ+ +FASTINIT.OBJ+ +FASTP.OBJ+ +FASTSM.OBJ +FASTOPEN.EXE,/m; + \ No newline at end of file diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL b/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL new file mode 100644 index 0000000..25c7c5e --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.SKL @@ -0,0 +1,28 @@ +;========================================================== +; FASTOPEN MESSAGE SKELETON FILE +;========================================================== + +:util FASTOPEN ;AN000; +:class A ;System message class ;AN000; +:use 1 COMMON1 ;MSG 1 is always "Incorrect DOS Version" ;AN000; +:use 6 PARSE10 ;Invalid parameter message ;AN000; +:use 3 PARSE3 ;Invalid Switch + +:def 4 CR,LF,"FASTOPEN installed",CR,LF ;AN000; +:def 5 CR,LF,"FASTOPEN already installed",CR,LF ;AN000; +:def 7 CR,LF,"Too many drive entries",CR,LF ;AN000; +:def 8 CR,LF,"Same drive specified more than once",CR,LF ;AN000; +:def 9 CR,LF,"Invalid parameter",CR,LF ;AN000; +:def 11 CR,LF,"Invalid extent entry",CR,LF ;AN000; +:def 12 CR,LF,"Invalid number of file/directory entries",CR,LF ;AN000;;AN000; +:def 13 CR,LF,"Cannot setup expanded memory",CR,LF ;AN000;;AN000; +:def 14 CR,LF,"Expanded memory not available",CR,LF ;AN000;;AN000; +:def 15 CR,LF,"Invalid drive specification %1",CR,LF ;AN000;;AN000; +:def 16 CR,LF,"Not enough space in EMS. Low memory is used",CR,LF ;AN000; +:def 17 CR,LF,"Cannot use FASTOPEN for drive %1",CR,LF +:def 18 CR,LF,"Too many extent entries",CR,LF ;AN000; +:def 19 CR,LF,"Too many file/directory entries",CR,LF ;AN000; + +:end + +;========================================================== diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT new file mode 100644 index 0000000..b1cf286 --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT @@ -0,0 +1,615 @@ + +.* +.pm 5 +:gdoc sec='' +:frontm +:titlep +:title.FASTOPEN UTILITY HIGH LEVEL DESIGN +:date. +:author.J. K. +:ETITLEP +:toc +:body +.DH NUM +.*.pa +&SYSDATE. +.*:H1.INTRODUCTION +.*:H1.ARCHITECTURE OVERVIEW + +:H1.FASTOPEN DESIGN +:H2.FASTOPEN UTILITY +:H3.FASTOPEN Overview +FASTOPEN is a utility that allows DOS to maintain the information about +files that have been opened. The purpose is to reduce the number of times DOS +has to look into the directory area of the disk for information on the file once +the information is stored by FASTOPEN. In real life, many application +programs, especially current database systems on the market, tend to open the +same file repeatedly and every open operation needs an access to the disk if the +information does not exist in the DOS buffer. The FASTOPEN utility will +eliminate these disk accesses, and hence will increase the efficiency of DOS +performance. + + +:H3.FASTOPEN Operational Description +Conceptually FASTOPEN itself is a database maintained by DOS. The data will +be stored and maintained in the system RAM. + +FASTOPEN is a user-installable, stay resident utility loaded by entering a +command +.fo off + 1). FASTOPEN D:{=L} ... + +where "..." means a possible repetition. + + "D:" is a drive letter for a non_removable media. + + "L" is the maxium number of files and subdirectories that can be + stored in the drive cache. The default value is 34, minimum + value, 10. The total number for all the drives is less + than 1000. + +.fo on + +:H4.Name Caching +FASTOPEN will keep the history of the accessed subdirectory and file +information in LRU fashion. The data are stored in a partial tree +structure that represents all the recently accessed files and +subdirectories of that drive. The number of entries entered by the +user, or the default number of 34, represents the maximum number of +nodes and leaves of the tree. As it suggests, the bigger the +number is, the more the efficient it will be. Currently each additional +increase of the entry will take 36 bytes, which is the fixed length of +a node. + +The number entered by the user should be bigger than the deepest nesting +of path entries in the drive. + +The operation on this name cache is similar to the operation on the +physical drive. +With the look up request, FASTOPEN will traverse the name cache tree from the +root to the bottom to find the requested path, filename. If found, then the +pointer to the file or subdirectory information packet will be returned, else FASTOPEN +will return the string pointer that points up to the matching subdirectory name. +In this case, if DOS wants to insert the rest of the subdirectory/file information +an insert operation should be requested for every subdirectory/file. FASTOPEN +will use the information from the previous Look_up operation for a sequence of Insert operations. + +At this moment, if there are any free entries left, then it will be used. +Otherwise, FASTOPEN will delete the least recently used leaf. Any node cannot +be deleted until the node becomes an empty leaf, i.e., without children. +If a file or a directory has been removed, then DOS will update the name +cache tree with the Delete request. The path, file will be looked up +first, and if found, then the corresponding entries will be free to the +free entry chain. If not found, then still it is O.K. since the matching file +entries had been removed by the LRU scheme. + + +:H3.Fastopen Interface +When installed, by the nature of the functionality, FASTOPEN becomes +a part of DOS and a private communication mechanism will be +established. +Inside DOS, vector pointers are established for FASTOPEN and will be +initialized by the call "CALLinstall" macro by the FASTOPEN initialization. +The structure of the FASTOPEN entry will look like; + +.fo off +FASTOPEN_ENTRY struc +FASTOPEN_ENTRY_SIZE dw 4 ;size of the following +FASTOPEN_NAME_CACHING dd ? +;FASTOPEN_FATCHAIN_CACHING dd ? ;not for DOS 3.3 +;NUMBER_OF_SFTS dw ? ;# of files - 3 +FASTOPEN_ENTRY ends +.fo on + +The initial vector pointer for FASTOPEN_NAME_CACHING +points to a dummy routine in DOS which simply set the carry flag and set AX to 0FFFFh. + +When FASTOPEN is installed, then this vectors table will be established to +point to the matching procedures in FASTOPEN module. + +The register AL will contain subfunction value on entry to FASTOPEN. + +.fo off +;FASTOPEN NAME CACHING Subfunctions +fastopen_name_look_up equ 1 +fastopen_name_insert equ 2 +fastopen_name_delete equ 3 +;fastopen_name_purge equ 4 ;Not for DOS 3.3 + +.fo off +1. Name Caching + + a. Look up + IN) DS:SI -> d:path + ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN + ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN + OUT) + if found, DS:SI -> the last character of the path, i.e., 0. + ES:DI -> DIR INFO + ES:CX -> Extended INFO (explained in the data structure) + else if there exist the name cache for the drive, but could not + completely find the matching path, + DS:SI -> "\" following the directory that FASTOPEN can + find the match, + Will points to "\" after "d:" if no matching + root directory is found. + ES:DI -> Compct_Dir_Info of the subdirectory FASTOPEN + can find the match. + ES:CX -> the matching directory's Extended INFO + If cannot find the matching root directory entry, then + ES:DI, ES:CX are undetermined. + else carry flag set and AX = 0FFFFh. + + b. Insert + IN) DS:DI -> DIR info + ES:BX -> Extended info + + OUT) + If failed, then carry flag set and AX = 0FFFFh. + Insert operation handles only one file or subdirectory at a time. + So, usually insert operations are performed in a sequential manner. + A look up operation should be performed before any new sequential + insert operation. + FASTOPEN will keep the information of the pervious look up + operation in CURRENT_NODE. The CURRENT_NODE points to the matching + directory node of the previous Look up operation. The next insert + operation will use this CURRENT_NODE information to insert the + directory or file information. So, DOS will call only one Look_ + up operation and possibly several Insert operation to insert the + path. + + For example, suppose DOS wants to look up C:\DIR1\DIR2\FILE1 and + FASTOPEN only has the inforamtion up to C:DIR1. After the + look up operation, FASTOPEN will return with DS:SI points "\" + following C:\DIR1. + At this moment, if DOS decides to insert this information,then + it sets DS:DI to DIR_INFO, and ES:BX to EXTENDED_INFO of the + subdirectory DIR2, and will request an insert operation. + When control returned back to DOS, then it will set this time + DS:DI and ES:BX to those of FILE1, and will call an another + insert operation. + At the first insert operation, FASTOPEN automatically knows + that those informaton given by DOS belong to the child of + C:\DIR1, and will install it as a child. In the second operation, + again FASTOPEN knows that it is for the child of C:\DIR1\DIR2 + and will accordingly install the information for FILE1. + + c. Delete + IN) DS:SI -> d:path + + OUT) + If failed, then carry flag set and AX = 0FFFFh. + +.fo on + +:H3.FASTOPEN Special Considerations +FASTOPEN uses the following DOS function calls in its initialization +rouitine. No DOS or BIOS function calls are allowed inside the +main routine that is resident once installed. +:ul +:li.AH = 40h, Int 21h; Write to device for the messages, +:li.AH = 31h, Int 21h; Terminate Process and Remain Resident, +:li.AH = 48h, AH = 49h, AH = 4Ah, Int 21h; Allocate, free and +modify memory block. +:eul +:p. + +To prevent the corruption of any DOS operation, once FASTOPEN is +loaded it cannot be reloaded. + + +:H4.FASTOPEN Top Level Design + +:H5.Data Structure + +The structures of the records in FASTOPEN are: + +.fo off +NAME_record struc + LRU_pointer dw -1 + Child_pointer dw -1 + Sibling_pointer dw -1 + MRU_pointer dw -1 + Compct_Dir_info db 22 dup (?) + Extended_Info db 5 dup (?) +NAME_record ends + +Extended_Info struc +dirpos db 0 +dirsec dw 0 +clusnum dw 0 +Extended_Info ends + +Drive_cache_header struc +LRU_ROOT dw 0 ;Start of LRU chain for this Name cache +Child_ptr dw -1 ;points to the name cache +Sibling_ptr dw -1 ;points to the next drive header +MRU_ROOT dw 0 ;set to the end of LRU chain +Drive_letter db 'C' +Num_Entries dw 0 +Name_Cache_start dw 0 ;Start of name cache for this drive +Drive_cache_header ends + +Cmpct_Dir_Info struc +CD_File_name db 11 dup (0) +CD_File_attr db ? +CD_time dw ? +CD_date dw ? +CD_cluster dw ? +CD_Filesize dd ? +Cmpct_Dir_Info ends + +Dir_Info struc ;= full directory entry information. +DI_head db 12 dup (?) +DI_skip db 10 dup (0) ;reserved area. All the time 0. +DI_tail db 10 dup (?) +Dir_Info ends + +.fo + + +:H5.FASTOPEN Hierarch +:H6.FASTOPEN Components + +.fo off + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ FASTOPEN ³ + ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ + ³ + ³ + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ ³ + V V +ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +³ INIT ³ ³ MAIN ³ +ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ + ³ + V + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ ³ + ³ LOOK_UP, INSERT, DELETE, INIT_TREE ³ + ³ ³ + ³ (SUPPORTING MODULES) ³ + ³ ³ + ³ GET_FREE_NODE, PRE_LRU_STACK, ³ + ³ SET_LRU, MAKE_NAME_RECORD, ³ + ³ UNFOLD_NAME_RECORD, PACK_DIR_NAME, ³ + ³ REMOVEFROMLRUCHAIN ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +.fo + +:H6.FASTOPEN Memory Structure + +.fo off + Lo_memory ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÄÂÄ + ³ LOOK_UP, ³ ³ + ³ INSERT, ³ M + ³ DELETE, ³ A + ³ & Supporting Routines ³ I + ³ ³ N + ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ + ³ INIT_TREE ³ ³ + ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÄÅÄ + ³ DRIVE_CACHE_HEADER ³ I + ³ (After Init, this ³ N + ³ area will be used ³ I + ³ for name caches.) ³ T + ³ SHOW_ERR_MESSAGE ³ ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÄÁÄ + + High_memory +.fo + +.pa +:H5.FASTOPEN Component Interfaces + +.fo off +;************************************************************************* +; +;SUBROUTINE: INIT +; +;INPUT: +; +;OUTPUT: +; +;DESCRIPTION: +; +; 1:(Installation check) +; { Get the entry pointer of FASTOPEN from DOS. +; Check the signature ($FASTOPEN01$) +; If already installed, +; then Show 'FASTOPEN already installed'; Exit +; } +; +; 2:(Parse the command line) +; Input: User input +; +; Output: Total_Entry_Num. +; Drive_Cache_Headers set. +; End_Cache_Header. +; +; { For every drive entered +; { Drive sanity check; +; Get_Num; +; if success and Total_Entry_Num < 1000, then +; Set Drive_Cache_Header; +; } +; } +; +; 3:(Check the system memory) - Check if the system has enough +; memory for the Name caches. +; Name cache will start from the +; End_Cache_Header. +; +; Input: Total_Entry_Num, End_Cache_Header, End_Init, +; Output: End_Caches +; { +; Needed_space = size of (Name_Record) * Total_Entry_Num; +; Needed_space = Needed_space - (End_Init - End_Cache_Header); +; Free allocated memory from End_Init (AH = 4Ah); +; Set memory block from End_Init to Needed_Space (AH = 48h); +; if fail, Show 'Insufficient memory for FASTOPEN cache'; +; Set End_Caches; +; } +; +; 4: jmp to INIT_TREE +; +;************************************************************************* + + +.pa +.fo off +;************************************************************************* +; +;SUBROUTINE: INIT_TREE +; +;INPUT: Drive_cache_header, End_Caches +; +;OUTPUT:Name_cache entries installed for every drive requested. +; LRU chain established for every drive. +; FASTOPEN entry pointer set in DOS. +; Terminate & stay resident. (Up to End_Caches) +; +;DESCRIPTION: +; +; 1:(Install_Name_Cache) +; Input: Drive cache header, End_cache_header (= Name cache start) +; Output:According to the information in the header, +; the name cache entries will be established. +; Also, LRU chain, MRU_pointer are established. +; +; { Buffer_start = End_cache_header; +; For every drive header +; { LRU_ROOT = Buffer_start; +; For (i=1;i=Num_Entries;i++) +; { MRU_pointer = Buffer_start; +; Buffer_start= Buffer_start + size_of (Name_record); +; if i = Num_Entries then LRU_pointer = -1 +; else LRU_pointer = Buffer_start; +; } +; } +; } +; +; 2:(Set FASTOPEN entry pointer in DOS) +; Use CALL INSTALL macro. +; +; 3: Terminate and stay resident up to Buffer_start; +; +;************************************************************************* + + +.pa +.fo off +;************************************************************************* +; +;SUBROUTINE: MAIN +; +;INPUT: Called by DOS throught Look_up, Insert, Delete requests. +; +;OUTPUT:Request performed based on LRU scheme. +; CX, DX, DS, ES, BP value saved. Other register are destroyed. +; +;DESCRIPTION: +; Call Pack_Dir_Name ;get the drive letter in BL +; Call Get_Drive_Cache_Header ;find the matching drive header +; if not found, then AX = 0ffffh, Carry set +; else if AL = Look_up then Call Look_up +; else if AL = Insert then Call Insert +; else if AL = Delete then Call Delete +; else AX = 0ffffh, Carry set. +; +; MAJOR SUBROUTINES: +; (Look_up) - Refer to Look_up subroutine. +; (Delete) - Refer to Delete subroutine. +; (Insert) - Refer to Insert subroutine. +; +; SUPPORTING SUBROUTINES: +; 1:(Get_Free_Node) - Get the entry from the LRU_ROOT, +; Set LRU_ROOT to the next entry of the +; LRU chain +; Input: none +; Output:Entry address. LRU_ROOT updated to the next entry. +; +; 2:(Pre_LRU_Stack) - This is needed to implement LRU scheme in +; a tree structure. Since the order of traversing a tree is +; from the root to bottom and from left to right, the direct +; implementation of LRU will result the parent the least mostly +; used one instead of the child. This is exactly in the reverse +; order to what had been expected. This procedure will +; solve this problem without loss of any efficiency. In the +; Look_up operation and found the match, the found entris will +; be saved with each of its LRU, MRU pointer modified to reflect +; the desired LRU order. +; These created mini LRU chain will be attached to the +; LRU chain again by SET_LRU. SET_LRU and PRE_LRU_STACK +; should work in a synchronized fashion. SET_LRU routine +; will be called in the beginning of every Look_up, Insert +; operation. PRE_LRU_Stack will be called whenever a matching +; entry is found in a Look_up operation, or whenever a new +; entry is inserted by the Insert operation. +; Input: Current_Drive,Target node. +; Output:Depth, Top, Bottom set +; +; 3:(SET_LRU) +; Input: Depth, Top, Bottom, Current_Drive +; Output:Mini LRU chain created by Pre_LRU_Stack will be +; placed at the end of LRU chain. +; +; 4:(MAKE_NAME_RECORD) - At Insert time, BOS will give +; two types of information. DS:DI -> Dir_Info, ES:BX -> Extended_ +; Info. The Name_Record is composed of Cmpct_Dir_Info and +; Extend_Info. MAKE_NAME_RECORD will simply make a Name_Record +; from the informations from DOS. +; Input: Dir_Info, Extended_Info +; Output:Name_Record +; +; 5:(UNFOLD_NAME_RECORD) - Inverse function of above. When Look_up +; operation finishes, then unfold the Name_Record of the current_ +; node for DOS. If the Current_Node is a drive_cache_header, +; then will just return. +; Input: CS:Current_Node, ES, DI, BX set for the buffer +; Output:ES:DI->Dir_Info, ES:BX->Extended_Info buffer in DOS. +; +; 6:(PACK_DIR_NAME) - At Look_up or Delete operation, DS:SI points +; to the requested full path, for ex., "C:\DIR1.EXT\DIR2\FILE.EXT", +; 0. This routine is smart enough to recognize ":","\" and 0 as +; a delimeter and will parse until the next delimeter and leave +; SI to the next delimeter found. Also, if it is a drive name +; it will set SI to the "\" after ":" for consistency and +; it will set BL to the drive letter. +; The main function of this routine is "pack" the given directory +; name into 11 bytes format. PACKED_NAME will be filled with +; the result. For example, when it is called the first time, +; DL = "C" and SI will point to "\" before DIR1.EXT. +; The second time, PACKED_NAME will be filled with +; "DIR1 EXT" and SI will points to "\" before "DIR2". +; Likewize, if this routine is called the fourth time, +; FILE.EXT has been parsed and DS:SI will points to 0. +; When this routine is called again, then it will return +; with carry signaling that it has reached the end. +; The user is required to call this routine consequtively +; until it returns with carry. +; Input: +; Output: +; +;************************************************************************* + + +.pa +.fo off +;************************************************************************* +; +;SUBROUTINE: LOOK_UP +; +;INPUT: DS:SI -> path +; ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN +; ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN +; CS:BP -> Matching Drive_cache_header +; +;OUTPUT:if found, DS:SI -> the last character of the path, i.e., 0. +; ES:DI -> DIR_INFO +; ES:CX -> Extended_INFO (explained in the data structure) +; else if there exist the name cache for the drive, but could not +; completely find the matching path, +; DS:SI -> "\" following the directory that FASTOPEN can +; find the match, +; Will points to "\" after "d:" if no matching +; root directory is found. +; ES:DI -> Dir_Info of the subdirectory FASTOPEN +; can find the match. +; ES:CX -> the matching directory's Extended INFO +; If cannot find the matching root directory entry, then +; ES:DI, ES:BX are undetermined. +; If the requested path is "D:\,0" then FASTOPEN will +; return with carry flag set and, AX = 0ffffh. +; else carry flag set and AX = 0FFFFh. +; +;GLOBAL VARIABLES: +; CURRENT_NODE, +; CURRENT_SIBLING, +; +;DESCRIPTION: +; Save Dir_Info, Extended_Info buffer address in DOS. +; Set ES to Name_Cache_Seg +; SET_LRU; +; 1: +; Current_Node = BP +; Current_Sibling = 0 +; PACK_DIR_NAME (from the path); +; if CX = 0, then jmp to 3 /*Found*/; +; Find_child (from the current_node); +; if not found then jmp to 3 +; 2: Compare Packed_name with Child_pointer.CD_filename +; if yes, then PRE_LRU_STACK; JMP to 1 +; else Find_Sibling;Current_sibling=Sibling_pointer +; if found a sibling, then Current_Node = Current_Sibling +; jmp to 2 +; else jmp to 3; +; 3: UNFOLD_NAME_RECORD /*for the info packet to DOS */ +; Exit +; +;************************************************************************* + + +.pa +.fo off +;************************************************************************* +; +;SUBROUTINE: INSERT +; +;INPUT: DS:DI -> DIR info +; ES:BX -> Extended info +; +;OUTPUT:Automatic insertion based on CURRENT_NODE, CURRENT_SIBLING +; If failed, then carry flag set and AX = 0FFFFh. +; Insert operation handles only one file or subdirectory at a time. +; So, usually insert operations are performed in a sequential manner. +; A look up operation should be performed before any new sequential +; insert operation. +; +;GLOBAL VARIABLES: +; CURRENT_NODE, +; CURRENT_SIBLING, +; +;DESCRIPTION: +; +; Make_Name_Record ;Make Name Record from the input +; Get_Free_Node +; Set_LRU ;(from TEMP_LRU_STACK) +; if current_sibling <> 0 (or current_sibling=0FFh) +; then Install as a sibling of Current_Node +; else Install as a child under Current_Node; +; Pre_LRU_stack ;(pre operation for LRU) +; Exit +; +;************************************************************************* + + +.pa +.fo off +;************************************************************************* +; +;SUBROUTINE: Delete +; +;INPUT: DS:SI -> d:path +; +;OUTPUT: If found, then remove the item from the Tree and from the +; LRU chain. Move that slot to the Top of the LRU chain. +; +;GLOBAL VARIABLES: +; +;DESCRIPTION: +; Look_Up +; If ds:si -> 0, then Remove that entry from Tree, LRU chain, +; Put that entry to the top of LRU chain +; else AX = 0FFFFh, Carry set, +; Exit +; +;************************************************************************* + + +.fo +:egdoc. + diff --git a/v4.0/src/CMD/FASTOPEN/FASTP.ASM b/v4.0/src/CMD/FASTOPEN/FASTP.ASM new file mode 100644 index 0000000..561417c --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTP.ASM @@ -0,0 +1,131 @@ + PAGE 90,132 ;A2 + TITLE fastp.asm - fastopen SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: fastp.asm +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of fastopen. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.ASM statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.ASM statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; +; For LINK instructions, refer to the PROLOG of the main module, +; fastopen.asm. +; +; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, +; +; COPYRIGHT: "MS DOS FASTOPEN Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft " +; "Licensed Material - Property of Microsoft " +; +;PROGRAM AUTHOR: DOS 4.00 P L +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ; ;AN000; + %OUT COMPONENT=fastopen, MODULE=fastp.asm... + ENDIF ; ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +; = = = = = = = = = = = = + +HEADER MACRO TEXT ;; ;AN000; +.XLIST + SUBTTL TEXT +.LIST + PAGE ;; ;AN000; + ENDM ;; ;AN000; + +; = = = = = = = = = = = = + HEADER ; ;AN000; +CSEG_INIT SEGMENT PARA PUBLIC 'CODE' ; + ASSUME CS:CSEG_INIT,DS:CSEG_INIT,ES:CSEG_INIT + + PUBLIC SYSPARSE ;SUBROUTINE ENTRY POINT ;AN000; + + +INCSW EQU 1 ;INCLUDE PSDATA.INC ;AN000; +FARSW EQU 0 ;CALL THE PARSER BY NEAR CALL +DATESW EQU 0 ;SUPPRESS DATE CHECKING ;AN000; +TIMESW EQU 0 ;SUPPRESS TIME CHECKING ;AN000; +FILESW EQU 0 ;SUPPRESS CHECKING FILE SPECIFICATION ;AN000; +CAPSW EQU 0 ;SUPPRESS FILE TABLE CAPS ;AN000; +CMPXSW EQU 1 ;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 1 ;SUPPRESS SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT ;AN000; +NUMSW EQU 1 ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT ;AN000; +SWSW EQU 1 ;DO SUPPORT SWITCHES ;AN000; +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 ;AN000; +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 ;AN000; +VAL3SW EQU 0 ;DO SUPPORT VALUE DEFINITION 3 + + + IF1 ; ;AN000; + %OUT COMPONENT=fastopen, SUBCOMPONENT=PARSE, MODULE=PARSE.ASM... + %OUT COMPONENT=fastopen, SUBCOMPONENT=PARSE, MODULE=PSDATA.INC... + ENDIF ; ;AN000; + INCLUDE PARSE.ASM ; ;AN000; +CSEG_INIT ENDS ; + END ; ;AN000; diff --git a/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM b/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM new file mode 100644 index 0000000..90b9118 --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTSEEK.ASM @@ -0,0 +1,2944 @@ + Page 84,132 ; +Title FASTOPEN + +;--------------- INCLUDE FILES ----------------- +.xcref +.xlist +debug=0 ;this is an equate only for DOSMAC.inc +INCLUDE DOSMAC.inc +.list +.cref +INCLUDE dirent.inc +INCLUDE fastsegs.inc ; Cannot declare this in DOS includes +INCLUDE fastopen.inc ; This include file also contains DOS equates + + +CSEG_MAIN SEGMENT PARA PUBLIC 'CODE' ; Cseg_Seek segment + +EXTRN VECTOR_DELETE:dword ; jump vector inside Cseg_Seek to make + ; a FAR call to FSeek Delete function within + ; the segment + +CSEG_MAIN ENDS + + +;***************************************************************************** +; ALL FastSeek functions are kept in a seperate segment. They are accessed +; by a FAR indirect call from the MAIN routine. + +; ADDRESSABILTY: DS is for accessing local data in Cseg_Seek segment +; ES is for accessing data in the extent cache buffer +; in the Cseg_Init segment +; On entry, only DS is set, ES is set to Cache segment later +;***************************************************************************** + +CSEG_SEEK SEGMENT PARA PUBLIC 'code' + assume cs:cseg_seek,ds:nothing,es:nothing,ss:nothing + +PUBLIC Seek_name_cache_seg ;AN000; +PUBLIC Seek_Num_Of_drives +PUBLIC Seek_extent_drive_Buff ;AN000; +PUBLIC Seek_Total_Ext_Count ;AN000; +PUBLIC Seek_Total_Name_Count ;AN000; +PUBLIC Seek_Name_Drive_Buff ;AN000; +PUBLIC Seek_Name_Cache_Buff ;AN000; +PUBLIC End_Seek +PUBLIC Check_Flag + ;AN000; +PUBLIC Fk_Open +PUBLIC Fk_Close ;AN000; +PUBLIC Fk_Insert ;AN000; +PUBLIC Fk_Delete +PUBLIC Fk_Lookup ;AN000; +PUBLIC Fk_Truncate +PUBLIC Fk_Purge + + +;;---------- FASTSEEK LOCAL VARIABLES --------------------- + +First_Phys_ClusNum dw 0 ; first phys clus num of file (file id) ;AN000; +Logical_ClusNum dw 0 ; logical cluster num to be searched ;AN000; +Physical_ClusNum dw 0 ; physical clus num of above logical clus num ;AN000; +Extent_buff_Ptr dw 0 ; starting offset of extent cache ;AN000; +drv_id db -1 ; drive id of last fastseek function +func_cod db 0 ; function code + +Cur_Hdr_Ptr dw 0 ; address of current header ;AN000; +Cur_Extn_Ptr dw 0 ; address of current extent ;AN000; +New_Extn_Ptr dw 0 ; address of area where new extent will be created +New_Hdr_Ptr dw 0 ; address of area where new header will be created ;AN000; +Prev_Hdr_Ptr dw 0 ; address of previous header ;AN000; +Prev_Extn_Ptr dw 0 ; address of previous extent ;AN000; + +Prev_MRU_Extn_Ptr dw 0 ; address of previous MRU extent ;AN000; +LRU_Prev_Hdr dw 0 ; address of previous hdr to the LRU header ;AN000; +LRU_Prev_Extent dw 0 ; address of previous extent to LRU extent ;AN000; +LRU_Extent dw 0 ; address of LRU extent ;AN000; +LRU_Hdr dw 0 ; address of LRU header ;AN000; + +Drive_Hdr_Ptr dw 0 ; address of drive header of current drive ;AN000; +From_FreeBuff dw 0 ; 1 = if call from Free_Buff routine ;AN000; +Hdr_Flag dw 0 ; 1 = current header is the only + ; remaining header in Queue +Extn_Flag dw 0 ; 1 = current extent is the only ;AN000;;AN000; + ; remaining extent under this header +Fully_Flag dw 0 ; 1= cluster fully found in extent ;AN000;;AN000; + ; 0= cluster partially found +Find_Flag dw 0 ; # = specifies the relative location of the new cluster ;AN000; +Open_Queue_Flag dw 0 ; 1 = if open queue is empty ;AN000; +Free_Flag dw 0 ; Free area Type: 0 - continuous ;AN000; + ; 1 - non-continuous +Queue_Type dw 0 ; Queue Type: 0 - Open Queue ;AN000; + ; 1 - Close Queue +phys_num dw 0 ; ** for queue analyser +logic_num dw 0 ; ** for queue analyser + + +; Following data area is initialized during initialization +Check_Flag dw 0 +Seek_name_cache_seg dw Cseg_Init ; Seg ID of Ccahe buffer +Seek_Num_Of_drives dw 0 ; number of drives ;AN000; +Seek_Total_Name_Count dw 0 ; total name count +Seek_Total_Ext_Count dw 0 ; total extent count +Seek_Name_Drive_Buff dw 0 ; starting address of name drive buffers ;AN000; +Seek_Name_Cache_Buff dw 0 ; starting address of name cahe buffers ;AN000; +Seek_extent_drive_Buff dw 0 ; starting address of extent ;AN000; + ; cache in the cache buffer + + + + +;------------------------------------------------------------------------------- +;------------------------------------------------------------------------------- +; PROCEDURE: FK_OPEN +; +; FUNCTION: Create and initialize a file header using the starting +; Physical Cluster number (file id) of the file. +; +; If the file header already exist in the OPEN Queue, then increase +; the file reference count by one and make the header +; MRU header. +; +; If header is not found in the OPEN Queue, then check to +; see if it exists in the CLOSE Queue. If found in the +; CLOSE Queue, move the header and the extents to the top of +; OPEN Queue and make the header MRU header. +; +; If the header is not found in both Queues, create a new +; header at the top of the OPEN Queue and initialize with the +; given first physical cluster number. +; +; If not enough space for new header in OPEN Queue, find the +; LRU header and Last Exetent in the CLOSED Queue. Delete this +; extent and use the space for the new header. If none in +; CLOSE Queue, find the LRU header and the LRU extent in the +; OPEN Queue. Delete this extent and use this space. +; +; +; INPUT: CX = First Physical Cluster Number of the file +; DL = Drive ID +; +; +; OUTPUT: Created a new file header. If header already exist, then the file +; reference count is incremented by one. +; +; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;------------------------------------------------------------------------------- + + +FK_OPEN PROC FAR + + push cs ; establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + mov First_Phys_Clusnum,cx ; save physical cluster number ;AN000; + mov func_cod,al + +;------------------------------------------------------------------------------- +; Search for Drive header in the cache buffer using Drive ID in DL +;------------------------------------------------------------------------------- + CALL FIND_DRIVE_HEADER ; get drive buffer Header ;AN000; + ; DI-->drive header + jnc open_Search_Header ; header found - check for file header ;AN000; + jmp open_exit ; drive header not found - exit ;AN000; + +;------------------------------------------------------------------------------ +; Check if both OPEN and CLOSE Queues are empty. If empty, create a new +; file header at the top of OPEN Queue. If there are headers, search OPEN +; queue. If found, increment file count by one. If not found, check if +; the file header exists in CLOSE Queue. If found, move header to the +; top of the OPEN Queue. +;------------------------------------------------------------------------------ +Open_Search_Header: + inc es:[di].Extent_Count ; increment sequence count ( DEBUG) + mov ax,es:[di].Buff_Size ; total buffer size equal ;AN000; + cmp es:[di].Free_Size,ax ; to current free area ;AN000; + jne Search_Open_List ; yes, check OPEN and CLOSE Queues ;AN000; + ; for header + jmp Open_Make_Hdr ; no, make new header ;AN000; + + +;------------------------------------------------------------------------------ +; Search for header in the OPEN Queues. If found, increment file reference +; count by one. +;------------------------------------------------------------------------------ + +Search_Open_List: + mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; + mov si,es:[di].MRU_Hdr_Ptr ;AN000; + cmp si, -1 ; Any header in OPEN Queue ?? ;AN000; + je Open_Chk_Close_list ; none, check CLOSE Queue ;AN000; + + CALL FIND_FILE_HEADER ; search header in OPEN Queue ;AN000; + jc Open_chk_CLOSE_list ; if not found check in CLOSE Queue ;AN000; + +;------------------------------------------------------------------------------ +; Found in the OPEN Queue. Now, increment the file reference count by one +; and also make the header MRU header. If header found is LRU header then +; make previous header LRU header. If header is not LRU header, connect +; previous header to next header. If the header is the first header in the +; Queue, dont make it to MRU header since it is already at the top of Queue. +;------------------------------------------------------------------------------ + ; DI-->Header found + inc es:[di].FH_refer_Count ; increment file reference count ;AN000; + cmp Hdr_Flag, 1 ; current header Single header ?? ;AN000; + jne Open_Chk_Last_Hdr ; No, Check for last header ;AN000; + clc ; make sure caary is clear + jmp Open_Exit ; yes, exit ;AN000; + +Open_Chk_Last_Hdr: + cmp Hdr_Flag, 3 ; current header LRU header ?? ;AN000; + jne Open_Join_Gap ; no, close the gap ;AN000; + +Mark_Previous_Hdr: ; yes - mark previous hdr + mov si, Prev_Hdr_Ptr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,-1 ; yes, Mark previous Hdr LRU hdr ;AN000; + +; Make current Hdr MRU header. No need to close the gap + CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000; + clc ; make sure caary is clear + jmp Open_Exit ; then EXIT ;AN000; + + +;----------------------------------------------------------------------------- +; Comes here if current header is first of many headers or in between a previous +; and next header. Make current header MRU header and close the gap. +;----------------------------------------------------------------------------- +Open_Join_Gap: + ; DI-->Current header + cmp Hdr_Flag, 2 ; current Header First Hdr in Queue ?? ;AN000; + jne Open_Make_MRU_Hdr ; no, jump ;AN000; + clc ; MAKE SURE caary is clear + jmp Open_Exit ; yes, no need to make MRU hdr, or ;AN000; + ; or close the gap + +Open_Make_MRU_Hdr: ; header is between 1st and last headers + CALL MAKE_MRU_HEADER ; move header to top of Queue ;AN000; + + clc ; make sure caary is clear + jmp Open_exit ; then EXIT ;AN000; + + +;------------------------------------------------------------------------------ +; Look for a header in the CLOSE Queue. If found, move file header and +; and extents (if any) to top of OPEN Queue. If not found in the CLOSE +; queue, create a new header at the top of OPEN queue. +;------------------------------------------------------------------------------ +Open_Chk_Close_List: + mov di,drive_Hdr_Ptr ; DI-->current drive header ;AN000; + cmp es:[di].CLOSE_Ptr,-1 ; anything in CLOSE Queue ?? ;AN000; + jne open_search_hdr ; if any, search CLOSE Queue ;AN000; + jmp open_make_hdr ; if none, make a new header ;AN000; + + +;------------------------------------------------------------------------------ +; CLOSE Queue is not empty, next search for header in the CLOSE Queue using +; starting physical cluster number of the file. +;------------------------------------------------------------------------------ +Open_Search_Hdr: ; + mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000; + ; in the CLOSE Queue ;AN000; + mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; + CALL FIND_FILE_HEADER ; find file header in CLOSE Queue ;AN000; + ; DI-->header found + jnc open_chk_only_hdr ; if found, check only header ;AN000; + jmp short open_make_hdr ; if not, make a new header ;AN000; + +;------------------------------------------------------------------------------ +; Found header in the CLOSE Queue. Check if the header found is the single HDR +; in the CLOSE Queue, If single header, then, mark the CLOSE Queue as empty +; before copy the this header to the OPEN Queue. +;------------------------------------------------------------------------------ +Open_Chk_only_Hdr: ; + cmp Hdr_flag, 1 ; Only Header in the CLOSE Queue?? ;AN000; + jne Open_chk_Last_header ; if not check header is LRU header ;AN000; + + mov di,Drive_Hdr_Ptr ; only header in the CLOSE Queue ;AN000; + mov es:[di].Close_Ptr,-1 ; mark CLOSE Queue as empty ;AN000; + jmp short Open_Move_Hdr ; then move header to OPEN Queue ;AN000; + +;------------------------------------------------------------------------------ +; Current header is not the only header in the CLOSE Queue. Now check if the +; current header is the LRU header in CLOSE Queue. If true, mark previous +; header as LRU header before moving it from from CLOSE Queue to OPEN queue. +;------------------------------------------------------------------------------ +Open_Chk_Last_Header: ; + cmp Hdr_Flag, 3 ; Current header last header ?? ;AN000; + jne Open_Close_gap ; no, close the gap before move it ;AN000; + ; to OPEN Queue + mov si, Prev_Hdr_Ptr ;AN000; + mov es:[si].Fh_Next_Hdr_Ptr,-1 ; yes, mark the previous hdr as last ;AN000; + jmp short open_move_Hdr ; header then move to the top of ;AN000; + ; OPEN Queue + +;------------------------------------------------------------------------------ +; Close the gap in the CLOSE Queue. +;------------------------------------------------------------------------------ +Open_Close_Gap: + mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000; + CALL JOIN_PREV_TO_NEXT ; join previous header to next header ;AN000; + +;------------------------------------------------------------------------------ +; Now move the current header from CLOSE Queue to top of OPEN Queue +;------------------------------------------------------------------------------ +Open_Move_Hdr: + mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; + mov di,drive_Hdr_Ptr ; DI-->drive header ;AN000; + +;------------------------------------------------------------------------------ +;Update the file refernce count to 1 before move header to OPEN Queue +;------------------------------------------------------------------------------ + mov es:[si].FH_Refer_Count, 1 ; set refernce count = 1 ;AN000; + mov ax,es:[di].MRU_Hdr_Ptr ; address of current MRU header ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; connect new header to the ;AN000; + ; current MRU header + mov es:[di].MRU_Hdr_Ptr,si ; make the header MRU header ;AN000; + clc ;AN000; + jmp short open_exit ; then exit. ;AN000; + +;------------------------------------------------------------------------------ +; If header is not found in both OPEN and CLOSE Queues, then make a new +; header in the next available free area and initialize the new header and +; make it MRU header (mov it to the top of the OPEN Queue). +; If no free space to create a new header, get space from CLOSE Queue. +; If none in CLOSE Queue, then get space from from OPEN Queue. See the +; Procedure (Find_Free_Buffer ) +;------------------------------------------------------------------------------ +Open_Make_Hdr: + + CALL MAKE_NEW_HEADER ; create new header ;AN000; + clc ;AN000; + +Open_exit: + CALL Check_it + ret ; return ;AN000; + +Fk_Open endp + + + + + + + +;-------------------------------------------------------------------------- +; PROCEDURE: FK_CLOSE +; +; FUNCTION: Search for the header on OPEN Queue. If the header is found, +; decrement the file reference count by one. If the resultant +; count is zero, then move the header and the extents under it +; to the CLOSE Queue. If not, make the header MRU header in the +; OPEN Queue. +; +; INPUT: DL = Drive Number +; CX = First Physical Cluster Number of the file +; +; OUTPUT: Moved the file header and the extents to the close Queue +; +; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header +; +; REVISION HISTORY: New (5/87) +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;--------------------------------------------------------------------------- + +FK_CLOSE PROC FAR + ;AN000; +; Search for Drive header in the Cache buffer using Drive ID in DL + push cs ; establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + mov First_Phys_Clusnum, CX ; save phys cluster number ;AN000; + mov func_cod,al + + CALL FIND_DRIVE_HEADER ; search for drive header + ; DI-->Current drive buffer + jnc Close_search_hdr ; found, search for file header ;AN000; + clc ; MAKE SURE carry is clear + jmp Close_Exit ; not found, error ;AN000; + +;-------------------------------------------------------------------------- +; Search for file header in the OPEN Queue using given physical cluster number +;-------------------------------------------------------------------------- +Close_Search_Hdr: + inc es:[di].Extent_Count ; increment sequence coutn (DEBUG) + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN Queue ;AN000; + mov cx,First_Phys_Clusnum ; CX = First phys clus num ;AN000; + CALL FIND_FILE_HEADER ; find the header in OPEN Queue + ; DI-->header found ;AN000; + jnc Close_Chk_Last_Hdr ; jump if header found ;AN000; + clc ; clear carry ;AN000; + jmp short close_exit ; headr not found - exit ;AN000; + +;-------------------------------------------------------------------------- +; Check if the header found is the only header in the OPEN Queue. If true +; go and decrement file reference count by one. +;-------------------------------------------------------------------------- +Close_Chk_Last_Hdr: + cmp Hdr_Flag, 1 ; Only header in the Queue ?? ;AN000; + je Dec_Ref_Count ; yes - decrement count, if count =0 ;AN000; + ; then move to the top of CLOSE Queue + cmp Hdr_Flag, 3 ; no - Last Header in the CLOSE Queue?? ;AN000; + jne Close_Join_Hdr ; no, close gap ;AN000; + mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; + jmp short Dec_Ref_Count ; decrement count and move to ;AN000; + ; CLOSE Queue + +;-------------------------------------------------------------------------- +; Connect previous header to next header to close the gap in OPEN Queue +;-------------------------------------------------------------------------- +Close_Join_Hdr: + mov si,Cur_Hdr_Ptr ; SI-->Current header + dec es:[si].FH_Refer_Count ; decrement fiel refernce count + cmp es:[si].FH_Refer_Count,0 ; count = 0 ?? + jne Close_Make_MRU ; no - make current header MRU header + + mov Queue_Type, 0 ; else set flag to indicate OPEN Queue ;AN000; + CALL JOIN_PREV_TO_NEXT ; close gap before move to CLOSE queue ;AN000; + jmp short move_to_Close_List ; move header to CLOSE queue + +;-------------------------------------------------------------------------- +; Decrement the reference count by one. If count = 0, then move the header to +; the top of CLOSE Queue. Else, dont move to CLOSE queue, since the file has +; have multiple open before. In this case make the header MRU header in the +; OPEN queue. +;-------------------------------------------------------------------------- +Dec_Ref_Count: + mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; + dec es:[si].FH_Refer_Count ; decrement refernece count ;AN000; + cmp es:[si].FH_Refer_Count,0 ; reference count = 0 ?? ;AN000; + je Move_to_Close_List ; yes, move header to CLOSE Queue ;AN000; + +;-------------------------------------------------------------------------- +; Else, move current Header to top of OPEN Queue. Move to the top of the queue +; only if the header is not the first header in the queue. +;-------------------------------------------------------------------------- +Close_Make_MRU: + cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000; + je Dont_Move_To_Top ; yes, dont move to top ;AN000; + + CALL MAKE_MRU_HEADER ; move header to top of queue ;AN000; + +Dont_Move_To_Top: + clc ;AN000; + jmp short Close_Exit ; exit ;AN000; + + +;-------------------------------------------------------------------------- +; Move header to the top of the CLOSE Queue. If the header is the only header +; header in the OPEN Queue, mark OPEN Queue empty. +;-------------------------------------------------------------------------- +Move_To_Close_List: + mov si,Cur_Hdr_Ptr ; SI-->Cur_Hdr_Ptr ;AN000; + cmp hdr_flag,1 ; single header in the Queue ?? ;AN000; + jne Join_To_Close_List ; no, move header to CLOSE queue ;AN000; + mov di,Drive_Hdr_Ptr ;AN000; + mov es:[di].MRU_Hdr_Ptr, -1 ; else mark OPEN Queue empty ;AN000; + +Join_To_Close_List: + mov di,Drive_Hdr_Ptr ; DI-->current drive header ;AN000; + mov ax,es:[di].Close_Ptr ; connect current header to the ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; previous first hdr in CLOSE queue ;AN000; + mov es:[di].Close_Ptr,si ; make the current header first + ; header in the CLOSE queue + clc ;AN000; + +Close_Exit: + CALL Check_it + ret ; return ;AN000; + +FK_CLOSE ENDP + + + + + + +;------------------------------------------------------------------------ +; +; PROCEDURE: FK_DELETE +; +; FUNCTION: Delete a specific header and extents under the header +; and release the buffers to the FREE pool +; +; Search OPEN Queue for file header. If found, delete header and +; extents and release the buffer to FREE area. If not found in OPEN +; queue, search CLOSE Queue. If found, delete header and extents +; under the header and release the area to FREE area. +; +; INPUT: CX = First Physical Cluster Number of the file +; DL = drive id +; +; OUTPUT: The file header and the extents are deleted +; +; ROUTINES REFERENCED: Find_File_Header, Find_Drive_Header +; +; REVISION HISTORY: New (5/87) +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;------------------------------------------------------------------------- + +FK_DELETE PROC FAR + + push cs ; establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; + mov func_cod,al + +;-------------------------------------------------------------------------- +; If the delete call is from Free_Buff, then go straight to file header +; search. Else usual delete request from DOS +;-------------------------------------------------------------------------- + cmp From_FreeBuff,1 ; call from Free_Buff routine ?? + je Del_Search_Close_List ; yes - find file header in CLOSE queue + +;-------------------------------------------------------------------------- +; Search for Drive Cache buffer using Drive ID in DL +;-------------------------------------------------------------------------- + CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; + jnc Delete_search_hdr ; found, search for file header ;AN000; + jmp Delete_Exit ; not found, error ;AN000; + +;-------------------------------------------------------------------------- +; Search for a header in the OPEN Queue using given physical cluster number +;-------------------------------------------------------------------------- +Delete_Search_Hdr: + inc es:[di].Extent_Count ; ;***; + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; + ; in the OPEN queue ;AN000; + cmp si, -1 ; any header in OPEN Queue ?? ;AN000; + je Del_search_Close_list ; none, search CLOSE queue ;AN000; + mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; + CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000; + jnc Del_Open_Last_Hdr ; if found, jump ;AN000; + + +;-------------------------------------------------------------------------- +; Not found in OPEN queue. Search in CLOSE queue +;-------------------------------------------------------------------------- +Del_Search_Close_List: + mov di,Drive_Hdr_Ptr ;AN000; + mov si,es:[di].Close_Ptr ; SI-->first header in the ;AN000; + ; in the CLOSE queue + cmp si, -1 ; anything in CLOSE Queue ?? ;AN000; + jne Del_scan_close_list ; yes, jump ;AN000; + clc ; none, header not found ;AN000; + jmp delete_exit ; exit ;AN000; + +Del_Scan_Close_List: + mov cx,First_Phys_Clusnum ; CX = first phys clus number ;AN000; + CALL FIND_FILE_HEADER ; find the header in CLOSE queue ;AN000; + ;AN000; + jnc Del_Close_last_hdr ; if found, chk if this header ;AN000; + ; is the last header in CLOSE queue + clc ; else, set header not found ;AN000; + jmp delete_exit ; and then exit ;AN000; + + +;------------------------------------------------------------------------- +; Header found in CLOSE queue. Check header found is the only single +; header left in the queue. +;------------------------------------------------------------------------- +Del_Close_Last_Hdr: + cmp Hdr_Flag, 1 ; Single Header in CLOSE Queue ?? ;AN000; + jne Del_Chk_LRU_Hdr ; no, check for LRU header ;AN000; + +;-------------------------------------------------------------------------- +; Yes, single header in the queue, make CLOSE_PTR empty before delete the +; header from the queue. +;-------------------------------------------------------------------------- + mov di,Drive_Hdr_Ptr ;AN000; + mov es:[di].Close_Ptr, -1 ; mark CLOSE_Ptr as empty ;AN000; + jmp short delete_Free_Buff ; release the deleted header ;AN000; + +Del_Chk_LRU_Hdr: + cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000; + jne Del_Join_Hdr ; no, close gap ;AN000; + mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; + jmp short delete_Free_Buff ; release the deleted header ;AN000; + +;-------------------------------------------------------------------------- +; Connect previous header to next header to close the gap in CLOSE Queue +;-------------------------------------------------------------------------- +Del_Join_Hdr: + mov Queue_Type, 1 ; set flag to indicate CLOSE Queue ;AN000; + CALL JOIN_PREV_TO_NEXT ; close gap ;AN000; + ;AN000; + jmp short Delete_Free_Buff ; release header to FREE area ;AN000; + + + +;------------------------------------------------------------------------- +; Header found in OPEN queue. Check header found is the only single +; header left in the queue. +;------------------------------------------------------------------------- +Del_Open_Last_Hdr: + cmp Hdr_Flag, 1 ; Single Header in OPEN Queue?? ;AN000; + jne Del_Chk_Opn_LRU_Hdr ; no, check for LRU header ;AN000; + +;-------------------------------------------------------------------------- +; Yes, single header in the queue, mark OPEN Queue empty before delete +;-------------------------------------------------------------------------- +; the header from the queue. + mov di,Drive_Hdr_Ptr ;AN000; + mov es:[di].MRU_Hdr_Ptr, -1 ; mark OPEN Queue as empty ;AN000; + jmp short delete_Free_Buff ; release the delete header ;AN000; + +Del_Chk_OPN_LRU_Hdr: + cmp Hdr_Flag, 3 ; Last Header in the CLOSE Queue ?? ;AN000; + jne Del_Opn_Join_Hdr ; no, close gap ;AN000; + mov si,Prev_Hdr_Ptr ; make the previous header LRU Hdr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous hdr ;AN000; + jmp short Delete_Free_Buff ; release header to FREE area ;AN000; + +;-------------------------------------------------------------------------- +; Connect previous header to next header to close the gap in OPEN queue +;-------------------------------------------------------------------------- +Del_Opn_Join_Hdr: + mov Queue_Type, 0 ; set flag to indicate OPEN Queue ;AN000; + CALL JOIN_PREV_TO_NEXT ; close gap ;AN000; + ;AN000; + +;---------------------------------------------------------------------------- +; Header and extends found. Mark the beginning of this free area with "-2". +; Connect this header to the FREE area. Mark all extnts under this header +; and chain them together through the 4th word. Connect the last extent to +; the OLD free area. This process will effectively release the header to the +; FREE area. Finally update the FREE area size in the Drive header. +; +; NOTE: The deleted buffers have size same as the size of a header or extent. +; Each buffers first location contains a marker (-2) to indicate that +; the buffer is a discontinuous buffer. Each discontinuos buffer is +; connected to the next discontinuous buffer through the 4TH word. +;--------------------------------------------------------------------------- + +Delete_Free_buff: + mov di,Drive_Hdr_Ptr ; SI-->drive header ;AN000; + mov si,Cur_Hdr_Ptr ; DI-->current header ;AN000; + +;------------------------------------------------------------------------- +; Put (-2) in the beginning of the released area to indicate that this is +; a discontinuous free area. Each Free area is 8 bytes which is same size +; as an extent or header. +;------------------------------------------------------------------------- + mov ax,-2 ;AN000; + mov es:[si], ax ;AN000; + cmp es:[si].FH_Next_Extn_Ptr, -1 ; any extents under this header ?? ;AN000; + jne del_look_extent ; yes, jump ;AN000; + +;------------------------------------------------------------------------- +; There is no extents under this header. Connect relased header to the +; Free area and update Free area size in drive header before exit. +;------------------------------------------------------------------------- + mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; + mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000; + mov ax,es:[di].Free_Ptr ; connect current header ;AN000; + mov es:[si].FH_Next_Hdr_Ptr, ax ; to the Free AREA ;AN000; + mov es:[di].Free_Ptr,si ;AN000; + mov cx, SIZE File_Header ; start with file header size ;AN000; + mov di,Drive_Hdr_Ptr ;AN000; + add es:[di].Free_Size,cx ; update free area size ;AN000; + clc ; make sure caary is clear + jmp short Delete_Exit ; Then exit ;AN000; + + +;------------------------------------------------------------------------- +; Yes, one or more extents under this header. Connect the header to the +; the first extent through 4th word (FH_Next_Hdr_Ptr). Subsequent free +; extents are connected through the 4th word (EH_Next_Extn_Ptr). Next calculate +; the size of the header and possible extendta and update the free area +; size in the drive header. +;------------------------------------------------------------------------- +Del_Look_Extent: + mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; + mov ax, -2 ; mark header as discontinuous ;AN000; + mov es:[si],ax ; free area (12/28) ;AN000; + mov cx, SIZE File_Header ; start with file header size ;AN000; + + mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under this hdr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; connect this header to first extnt ;AN000; + ; through the 4th word ;AN000; + mov si,ax ; SI-->First extent ;AN000; + mov ax, -2 ; mark first extent as discontinous ;AN000; + mov es:[si],ax ; free area ;AN000; + +Delete_Loop: + add cx, SIZE Extent_Header ; add size of extent ;AN000; + cmp es:[si].EH_Next_Extn_Ptr, -1 ; current extent last extent ? ;AN000; + je Del_Update_Free_Size ; yes - jump (12/28) ;AN000; + mov ax,es:[si].EH_Next_Extn_Ptr ; get pointer to next extent ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; connect curr ext to next extent ;AN000; + mov si,ax ; SI-->next extent ;AN000; + mov ax, -2 ; mark subsequent extents as ;AN000; + mov es:[si],ax ; discontinuous free areas ;AN000; + jmp Delete_Loop ; adding the size until last extent ;AN000; + +Del_Update_Free_Size: + mov di,Drive_Hdr_Ptr ;AN000; + add es:[di].Free_Size,cx ; update free area in drive header ;AN000; + ;AN000; +; At this point SI-->Last extent + mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; connect last extent under this ;AN000; + ; header to the Free area + mov ax,Cur_Hdr_Ptr ; AX-->Current header ;AN000; + mov es:[di].Free_Ptr,ax ; connect header being deleted to ;AN000; + ; the free pool ;AN000; +Delete_Exit: + clc + cmp check_flag,0 + jne open_chk_Que + clc + ret +Open_Chk_Que: + CALL Check_it + ret ; exit ;AN000; + +FK_DELETE ENDP + + + + + + + + +;-------------------------------------------------------------------------- +; PROCEDURE: FK_INSERT +; +; FUNCTION: Search for a specific extent using the starting physical +; cluster number and the given logical cluster number. +; Insert the given physical cluster number in the extent +; indexed by the given logical cluster number. If extent is +; not found, create a new extent. If free space is not +; available, take free space free CLOSE or OPEN Queue. +; +; INPUT DL = drive number +; CX = First Physical Cluster Number of the file +; BX = Logical Cluster Number +; DI = Physical Cluster Number +; +; OUTPUT: Physical cluster number is inserted. If extent is not found, +; a new file is created +; +; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_LRU_Header +; +; REVISION HISTORY: New (5/87) +; +;------------------------------------------------------------------------ + +FK_INSERT PROC FAR + push cs ; Establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + + mov first_phys_clusNum,cx ; save cluster numbers ;AN000; + mov Logical_ClusNum,bx ;AN000; + mov Physical_ClusNum,di ;AN000; + mov func_cod,al + +; Search for Drive Cache buffer using Drive ID in DL + CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; + jnc Insert_Search_Hdr ; found, search for file header ;AN000; + jmp Insert_Exit ; not found, error ;AN000; + +;-------------------------------------------------------------------------- +; If there are no free buffers and there is only a single header in the +; OPEN queue then there is no headers in the CLOSE queue, then the new +; clusters wont be insterted. This is because, file header should not consume +; its own extent if no free space is available. +;-------------------------------------------------------------------------- +Insert_Search_Hdr: + inc es:[di].Extent_Count ; increment sequence count (DEBUGGING) + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in OPEN queue ;AN000; + cmp es:[si].FH_Next_Hdr_Ptr, -1 ; only one header in OPEN queue?? + je insert_chk_buff ; yes - check free buffer + jmp short insert_Inc_count ; no - go and insert clusters + +Insert_Chk_Buff: + cmp es:[di].Free_Size, 0 ; any free buffers ?? + jne Insert_Inc_Count ; yes - go insert clusters + cmp es:[di].Close_Ptr, -1 ; any headers in close queue?? (1/7/88 ;AN000; + jne Insert_Inc_Count ; yes - go insert clusters + clc ; no - dont insert clusters + jmp Insert_Exit ; exit + +insert_Inc_Count: + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the OPEN queue ;AN000; + mov cx,first_phys_clusnum ; CX = physical cluster number ;AN000; + CALL FIND_FILE_HEADER ; find the header in OPEN queue ;AN000; + ; DI-->Header + jc Insert_Make_Hdr ; header not found, make new header ;AN000; + jmp Insert_Find_extent ; header is found, now go and ;AN000; + ; search for the extent + +;-------------------------------------------------------------------------- +; If header not found, create a new header in the free area and connect it +; to the top of the OPEN queue. Mark the new header with no extents. Insert +; the first logical and physical cluster number into the header. At this +; point CX=First Physical Cluster number. +;-------------------------------------------------------------------------- +Insert_Make_Hdr: + CALL MAKE_NEW_HEADER ; make a new header at the top ;AN000; + ; top of the queue +;-------------------------------------------------------------------------- +; Now the header is created, next create an extent and put both logical and +; physical cluster number in the extent. The new extent should be +; created at the bottom end of the current queue, except if AX =3, +; then the new extent will be created between current and previous extent. +; Use Find_Free_Buffer to check the free space. +;-------------------------------------------------------------------------- + CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; + jnc ins_save_addrs1 ; found, jump ;AN000; + jmp Insert_Exit ; if free area found is its own ;AN000; + ; header, exit +Ins_Save_Addrs1: + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Extn_Ptr,ax ; save new extent address ;AN000; + CALL UPDATE_FREE_AREA ; update Free area ;AN000; + + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + mov ax,New_Extn_Ptr ; beginning of new extent ;AN000; + mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; + mov es:[si].FH_Next_Extn_Ptr,ax ; connect current header to adj CHAIN ;AN000; + mov es:[si].FH_MRU_EXTN_Ptr,ax ; connect current header to LRU chain ;AN000; + mov si,New_Extn_Ptr ; SI-->New extent + mov bx,Logical_ClusNum ;AN000; + mov es:[si].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000; + mov cx,Physical_ClusNum ;AN000; + mov es:[si].EH_Phys_Clus_Num,cx ; insert physical clus num ;AN000; + mov es:[si].EH_Count,0 ; set initial count = 0 ;AN000; + +;-------------------------------------------------------------------------- +; Make new extent LRU extent +;-------------------------------------------------------------------------- + mov es:[si].EH_Next_Extn_Ptr, -1 ; mark no next extent in sorted chain + mov es:[si].EH_Prev_Extn_Ptr, -1 ; mark no previous extent in sorted chain ;AN000; + mov es:[si].EH_Next_LRU_Ptr, -1 ; mark no next extent in MRU-LRU chain ;AN000; + mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent in MRU-LRU chain + clc ; + jmp Insert_Exit ; exit ;AN000; + +;-------------------------------------------------------------------------- +; Header found, Check to see any extent under this header. If not create +; new extent. If there are extents, search for the relative position of the +; given cluster number among the extents under current header. +;-------------------------------------------------------------------------- +Insert_Find_Extent: + mov di,Cur_Hdr_Ptr ; DI-->Current header + mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under current hdr ;AN000; + cmp si,-1 ; any extent under this header ? ;AN000; + jne Find_relative_location ; yes, Find relative location of the + ; given cluster numbers ;AN000; + +; Else create new extent under the current header. + CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; + jnc ins_save_addrs2 ; found, jump ;AN000; + jmp Insert_Exit ; else free area found is its own ;AN000; + ; header, *** ERROR **** exit +Ins_save_addrs2: + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Extn_Ptr,ax ; save new extent address ;AN000; + + CALL UPDATE_FREE_AREA ; update Free area pointers ;AN000; + + mov di,Drive_Hdr_Ptr ; DI-->Drive header pointer ;AN000; + mov ax,New_Extn_Ptr ;AN000; + mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; + mov es:[si].FH_Next_Extn_Ptr,ax ; connect new extent to header ;AN000; + mov es:[si].FH_MRU_EXTN_Ptr,ax + mov si,New_Extn_Ptr ;### next extent start in the free_ptr ;AN000; + mov bx,Logical_ClusNum ;AN000; + mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; + mov cx,Physical_ClusNum ;AN000; + mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; + mov es:[si].EH_Count,0 ; ;AN000; + mov es:[si].EH_Next_Extn_Ptr,-1 ; mark this extent as last extent ;AN000; + mov es:[si].EH_Next_LRU_Ptr,-1 ; ### mark this extent as last extent ;AN000; + mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark there is no prev extent ;AN000; + mov es:[si].EH_Prev_LRU_Ptr,-1 ; mark there is no prev LRU extent + jmp Insert_Make_MRU ; make current header MRU header ;AN000; + + +;-------------------------------------------------------------------------- +; Check if the given cluster number will be continuous to either High or Low +; end of any extent under current header or should create a new extent +; If not, check whether a new extent for the cluster is to be created +; between current and previous extent - Current and next extent or new +; extent at the bottom of the queue. +;-------------------------------------------------------------------------- +Find_Relative_Location: + CALL FIND_CLUSTER_LOCATION ; find relative position of new extent ;AN000; + jnc chk_continuity ; position found ;AN000; + clc ; clusters already exist in an extent. + jmp Insert_exit ; return to DOS ;AN000; + +;-------------------------------------------------------------------------- +; Extent found. Check for LOW end contiguous. If true insert in the current +; extent and update the count +;-------------------------------------------------------------------------- +Chk_continuity: + cmp find_flag,1 ; LO end contiguous to current extent? ;AN000; + jne Insert_chk_HI ; no - check high end contiguous ;AN000; + mov si,Cur_Extn_Ptr ; yes - insert and update ;AN000; + mov cx,Logical_ClusNum ; save new logical and pysical ;AN000; + mov es:[si].EH_Logic_Clus_Num,cx ; cluster numbers as first clusters ;AN000; + mov cx,Physical_ClusNum + mov es:[si].EH_Phys_Clus_Num,cx ;AN000; + inc es:[si].EH_Count ; update extent range count ;AN000; + mov di,Drive_Hdr_Ptr ; DI-->drive header + cmp es:[di].Free_Ptr,0 ; any free buffer ?? + je Chk_low_MRU ; no - make current extent MRU extent + jmp Insert_Make_MRU ; yes - make current header MRU header ;AN000; + +Chk_Low_MRU: + mov Cur_Extn_Ptr, si + CALL Make_MRU_Extent ; Move extent next to current header + jmp Insert_Make_MRU ; Make current header MRU header ;AN000; + +;-------------------------------------------------------------------------- +; Check if clusters are high end contiguous to current extent. If true +; increment count and then make the extent MRU extent only if no free +; buffer is available. +;-------------------------------------------------------------------------- +Insert_Chk_HI: + cmp find_flag,2 ; HI end contiguous to current extent? ;AN000; + jne Insert_chk_between ; no, jump ;AN000; + mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000; + inc es:[si].EH_Count ; increment the cluster range count ;AN000; + mov di,Drive_Hdr_Ptr ; DI-->current drive header + cmp es:[di].Free_Ptr,0 ; any free buffers ?? + je Chk_Hi_MRU ; no - make current extent MRU extent + jmp Insert_Make_MRU ; yes - current header MRU header ;AN000; + +Chk_Hi_MRU: + mov Cur_Extn_Ptr, si ; SI -->extent to be MRU + CALL Make_MRU_Extent ; move extent next to current header + jmp Insert_Make_MRU ; Make current header MRU header ;AN000; + + +;-------------------------------------------------------------------------- +; Check to see the cluster number belongs to a new extent between current +; and Previous extent or header. If not it belongs to a new extent at the +; bottom end of the queue. +;-------------------------------------------------------------------------- +Insert_Chk_Between: + cmp find_flag,3 ; between current and previous exts?? ;AN000; + je Connect_prev_next ; yes, jump ;AN000; + + cmp find_flag,5 ; between current and next extents?? ;AN000; + jne Connect_to_end ; no, create new extent at bottom ;AN000; + ; bottom of the queue + jmp Connect_cur_next ; yes create new extent between ;AN000; + ; current and next extent + +;-------------------------------------------------------------------------- +; No, make new extent at the BOTTOM of the queue. +;-------------------------------------------------------------------------- +CONNECT_TO_END: ; At this point SI-->Last extent in queue ;AN000; + CALL FIND_FREE_BUFFER ; Check for free area ;AN000; + jnc ins_save_addrs3 ;AN000; + jmp Insert_Exit ; if free area found is its own ;AN000; + ; header, *** ERROR *** exit +Ins_Save_Addrs3: + mov di,Drive_Hdr_Ptr ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Extn_Ptr,ax ; save new extent address ;AN000; + CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; + + mov ax,New_Extn_Ptr ;AN000; + mov di,Cur_Extn_Ptr ; SI-->Current extent ;AN000; + cmp ax, di ; If free area got is the last + jne Use_Cur_Extent ; last extent itself then use previous extent + mov di, Prev_Extn_Ptr ; SI-->Previous extent + +Use_Cur_extent: + mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to current or previous extent ;AN000; + mov si,New_Extn_Ptr ; next extent start in the free_ptr ;AN000; + mov es:[si].EH_Prev_Extn_Ptr, di ; set previous extent address + mov bx,Logical_ClusNum ;AN000; + mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; + mov cx,Physical_ClusNum ;AN000; + mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; + mov es:[si].EH_Count,0 ; initial cluster range + +; Make new extent last extent in the sorted chain + mov es:[si].EH_Next_Extn_Ptr, -1 ; mark as Last extent of the queue ;AN000; +; make the new extent MRU extent in the MRU_LRU chain + mov di,Cur_Hdr_Ptr ; DI-->Current header + mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent + mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent + mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; + mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent + mov di,ax + mov es:[di].EH_Prev_LRU_Ptr,si ; connect previous to current extent + jmp Insert_Make_MRU ; make current header MRU header + ;AN000; + + +;-------------------------------------------------------------------------- +; Make new extent between current and previous extents. If no previous extent +; connect the new extent to the current header. +;-------------------------------------------------------------------------- +CONNECT_PREV_NEXT: + CALL FIND_FREE_BUFFER ; get free area for new extent ;AN000; + jnc Prev_Next_Update ; found, jump ;AN000; + jmp Insert_Exit ; if free area found is its own ;AN000; + ; header, **ERROR** exit +Prev_Next_Update: + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Extn_Ptr,ax ; save new extent address ;AN000; + ;AN000; + CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; + + mov di,Drive_Hdr_Ptr ; DI-->Drive Header ;AN000; + cmp Prev_Extn_Ptr, -1 ; Any previous extents ?? ;AN000; + jne join_to_Prev_Extn ; yes - connect new extent to previous ;AN000; + ; extent +; No, connect new extent to header + mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; + mov di,New_Extn_Ptr ;AN000; + mov ax,es:[si].FH_Next_Extn_Ptr ; AX-->first extent under header + mov es:[di].EH_Next_Extn_Ptr,ax ; connect new extent to this extent + mov es:[si].FH_Next_Extn_Ptr, di ; connect new extent to cur hdr ;AN000; + mov es:[di].EH_Prev_Extn_Ptr, -1 ; address of previous extent (-1) since header + mov bx,Logical_Clusnum ; ;AN000; + mov es:[di].EH_Logic_Clus_Num,bx ; insert logical clus num ;AN000; + mov cx,Physical_Clusnum ;AN000; + mov es:[di].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; + mov es:[di].EH_Count,0 ; set count ;AN000; + mov si,ax ; SI-->previous MRU extent + mov es:[si].EH_Prev_Extn_Ptr,di ; set prev extent of prev MRU extent + +; Make the new extent MRU extent + mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; + mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header + mov di,New_Extn_Ptr ; SI-->current header ;AN000; + mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent + mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; + mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header + mov si,ax + mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent + Jmp Insert_Make_MRU ; make current header MRU hdr ;AN000; + +; Connect new extent to previous extent +Join_To_Prev_Extn: + mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000; + mov ax,Cur_Extn_Ptr ; connect previous extent ;AN000; + cmp si,ax ; new extent is created from + je join_set_adj ; current extent ?? + + mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000; + mov ax,New_Extn_Ptr ; connect new extent to ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000; + mov ax,Cur_Extn_Ptr + jmp short Join_Set_Next ; current extent + +Join_set_adj: ; yes - + mov si,Prev_Extn_Ptr ; no - SI-->Previous extent ;AN000; + mov bx,es:[si].EH_Next_Extn_Ptr ; get next extent address + mov ax,New_Extn_Ptr ; connect new extent to ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ; previous extent ;AN000; + mov ax, bx ; extent to next extent + mov Cur_Extn_Ptr,bx ; change current extent + +Join_set_Next: ; from current extent + mov si,New_Extn_Ptr ; SI-->New extent, connect new to ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ; current extent ;AN000; + mov bx,Logical_Clusnum ; then save cluster numbers ;AN000; + mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; + mov cx,Physical_Clusnum ;AN000; + mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; + mov es:[si].EH_Count,0 ; ;AN000; + mov ax, Prev_Extn_Ptr + mov es:[si].EH_Prev_Extn_Ptr,ax ; connect previous to current extent + mov di, Cur_Extn_Ptr ; setup previous extent link of + mov es:[di].EH_Prev_Extn_Ptr,si ; current extent + +; Make the new extent MRU extent + mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; + mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header + mov di,New_Extn_Ptr ; SI-->current header ;AN000; + mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent + mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; + mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header + mov si,ax + mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent + Jmp short Insert_Make_MRU ; make current header MRU hdr ;AN000; + + + +;-------------------------------------------------------------------------- +; Make new extent between current and next extents. If no next extent +; connect the new extent to the end of queue. +;-------------------------------------------------------------------------- +CONNECT_CUR_NEXT: + mov si,Cur_Extn_Ptr ; current extent ;AN000; + cmp es:[si].EH_Next_Extn_Ptr,-1 ; any next extent ?? ;AN000; + jne join_to_next_extn ; yes, join to next extent ;AN000; + jmp Connect_To_End ; make new extent at the bottom of ;AN000; + ; the current queue +Join_To_Next_Extn: + CALL FIND_FREE_BUFFER ; Find free area ;AN000; + jc Insert_Exit ; if free area found is its own ;AN000; + ; header, exit + mov di,Drive_Hdr_Ptr ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Extn_Ptr,ax ; save new extent address ;AN000; + + CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; + ;AN000; + mov si,Cur_Extn_Ptr ; SI-->Current extent + mov DX,es:[si].EH_Next_Extn_Ptr ; DI-->Next extent ;AN000; + mov ax,New_Extn_Ptr ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ;connect new extent to cur extent ;AN000; + + mov si,New_Extn_Ptr ; SI-->New extent, connect new ext ;AN000;;AN000; + mov es:[si].EH_Next_Extn_Ptr,DX ; to next extent ;AN000; + mov ax, Cur_Extn_Ptr ; AX = address of current extent + mov es:[si].EH_Prev_Extn_Ptr, ax ; save address of previous extent + mov bx,Logical_Clusnum ; then save cluster numbers ;AN000; + mov es:[si].EH_Logic_Clus_Num,bx ; insert logical ;AN000; + mov cx,Physical_Clusnum ;AN000; + mov es:[si].EH_Phys_Clus_Num,cx ; insert physical cluster numbe ;AN000; + mov es:[si].EH_Count,0 ; set cluster range ;AN000; + mov di,DX ; setup prev extent link of the + mov es:[di].EH_Prev_Extn_Ptr,si ; next extent + +; Make the new extent MRU extent + mov si,Cur_Hdr_Ptr ; SI-->current header ;AN000; + mov ax,es:[si].FH_MRU_EXTN_Ptr ; AX-->MRU extent under header + mov di,New_Extn_Ptr ; SI-->current header ;AN000; + mov es:[di].EH_Next_LRU_Ptr,ax ; connect new extent to current extent + mov es:[di].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent ;AN000; + mov es:[si].FH_MRU_Extn_Ptr,di ; connect new extent to header + mov si,ax + mov es:[si].EH_Prev_LRU_Ptr,di ; connect previous to current extent + + +;-------------------------------------------------------------------------- +; Make the Current header MRU header. If the header is MRU header, then +; dont make the header MRU header. +;-------------------------------------------------------------------------- +Insert_Make_MRU: + cmp Prev_Hdr_Ptr, -1 ; first header ?? ;AN000; + jne Ins_mru_hdr ; no, make MRU header ;AN000; + clc ; make sure caary is clear + jmp short insert_exit ; yes, exit ;AN000; + +Ins_MRU_Hdr: + CALL MAKE_MRU_HEADER ; move header to top of OPEN Queue ;AN000; + clc ; make sure caary is clear + +Insert_exit: + CALL Check_it ; analyse the queue (debugging) + ret ; EXIT ;AN000; + +FK_INSERT ENDP + + + + + + + + +;------------------------------------------------------------------------- +; PROCEDURE: FK_LOOKUP +; +; FUNCTION: Search through the OPEN Queue for a specific Header and +; extent. If header is not found, create a new header and +; make it MRU header. Else search for a specific extent which +; contains the logical cluster number. If the extent is not +; found, return partial information from previous extent or +; header. If extent is found, return physical cluster number +; corresponds to the given logical cluster number. +; +; INPUT: DL = drive number +; CX = First Physical Cluster Number of the file +; BX = Logical Cluster NUmber +; +; OUTPUT: If Carry = 0 Fully Found +; DI = Physical Cluster Number indexed by es:[BX] +; BX = Physical Cluster Number indexed by es:[BX-1] +; +; If Carry = 1 Partially Found +; BX = Last logical cluster number in previous extent +; DI = Last Physical Cluster Number indexed by es:[Last logic clus] +; +; If header not found, a new header will be created. In this case +; BX = First Logical Cluster number (0) +; DI = First Physical Cluster number of the header created +; +; NOTE: The clusters are fully found if the logical cluster has +; continuity to the previous logical cluster in the same +; extent or previous extent or previous header. +; +; ROUTINES REFERENCED: Find_File_Header, Find_Extent, Find_Drive_Header +; +; REVISION HISTORY: New (5/87) +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;--------------------------------------------------------------- + +FK_LOOKUP PROC FAR ; on entry DS = seg ID of INIT + + push cs ; establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; + mov Logical_ClusNum,bx + mov func_cod,al + +;-------------------------------------------------------------------------- +; Search for Drive header in the Cache buffer using Drive ID in DL +;-------------------------------------------------------------------------- + CALL FIND_DRIVE_HEADER ; Search for drive header ;AN000; + jnc Look_search_hdr ; found, search for file header ;AN000; + jmp Look_Exit ; not found, error ;AN000; + +;-------------------------------------------------------------------------- +; Search for a header in the OPEN Queue using given physical cluster number +;-------------------------------------------------------------------------- +Look_Search_Hdr: + inc es:[di].Extent_Count ; ;***; + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; + ; in the OPEN Queue + mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000; + CALL FIND_FILE_HEADER ; find the header in CLOSE Queue + ;AN000; + jnc Look_Find_extent ; if found, find extent under this header + ; else create a new header ;AN000; +;-------------------------------------------------------------------------- +; If the header is not found, create a new header at the top of OPEN queue. +; Insert physical cluster number and set next header and first extent pointers +; Return partially found information. +;-------------------------------------------------------------------------- + pushf ; save carry set + CALL MAKE_NEW_HEADER ; Make a new header at the top of the queue ;AN000; + xor bx,bx ; BX = First Logical cluster number ;AN000; + mov di, First_Phys_Clusnum ; DI = First physical cluster number + popf ; carry should be set + jmp Look_exit ; exit ;AN000; + + +;-------------------------------------------------------------------------- +; If the header is found, next search for the extent that contains the +; logical and physical cluster numbers. DI--> current header +;-------------------------------------------------------------------------- +Look_Find_Extent: + cmp es:[di].FH_Next_Extn_Ptr,-1 ; any extent under this header ?? ;AN000; + jne look_search_extent ; yes, search for right extent ;AN000; + + xor bx,bx ; no, return partial info from header ;AN000; + mov di,es:[di].FH_Phys_Clus_Num ; DI = first phys clus num ;AN000; + push di ; ;AN000; + push bx ; BX = 1st logc clus num = 0 ;AN000; + mov fully_flag, 0 ; set partially found flag ;AN000; + jmp look_make_MRU_hdr ; move header to top of the OPEN queue ;AN000; + + +;-------------------------------------------------------------------------- +; Search for cluster numbers in extents starting from 1st extent. +;-------------------------------------------------------------------------- +Look_Search_Extent: + mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent under curr hdr ;AN000; + mov Cur_Extn_Ptr,si ; save it ;AN000; + mov cx,Logical_ClusNum ; CX = logic clus num to search for ;AN000; + mov Prev_Extn_Ptr, -1 ; reset flags ;AN000; + mov Extn_Flag, 0 ; ;AN000; + cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000; + jl Look_proc_less + +Look_Loop1: + cmp cx,es:[si].EH_Logic_Clus_Num ; 1st logic clus num in the ;AN000; + ; current extent matches ?? + je Look_Proc_First ; yes, process 1st extent case ;AN000; + mov ax,es:[si].EH_Logic_Clus_Num ; else check subsequent extents + add ax,es:[si].EH_Count ; last logic clus num in cur extent ;AN000; + cmp cx,ax ; extent found in the cur extent ?? + jg Look_Next_Extn ; no,try next extent ;AN000;;AN000;;AN000; + jmp Look_Extn_within ; yes, process current extent ;AN000; + +Look_Next_Extn: ; + mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000; + cmp ax,-1 ; is this last extent ?? ;AN000; + je Look_last_done ; yes, get partial ;AN000; + + mov Prev_Extn_Ptr,si ; save previous extent address ;AN000; + mov si,ax ;AN000; + mov Cur_Extn_Ptr,si ; save current extent address ;AN000; + cmp cx,es:[si].EH_Logic_Clus_Num ; logic clus num in cur extent ?? ;AN000; + jge Look_Loop1 ; may be!!, check it out ;AN000; + + jmp Look_Proc_Prev ; else get partial info from ;AN000; + ; previous extent +;------------------------------------------------------------------------- +; There are no further extents. In this case partially found. Return last +; logical and physical clusters of the last extent. +;------------------------------------------------------------------------- +Look_Last_Done: + mov si,Cur_Extn_Ptr ; SI-->Previous extent ;AN000; + mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num ofprevext ;AN000; + mov di,es:[si].EH_Phys_Clus_Num ; BX = first logic clus num ofprevext ;AN000; + add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000; + add bx,es:[si].EH_Count ; BX = last logic clus number in extent ;AN000; + push di ; last logical cluster number ;AN000;;AN000; + push bx ; last physical cluster number ;AN000; + mov fully_flag,0 ; partially found case ;AN000; + jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000; + + + +;-------------------------------------------------------------------------- +; Less than starting logical cluster of first extent. In this case return +; header info as partially found. +;-------------------------------------------------------------------------- +Look_Proc_Less: + xor bx,bx ; BX = logical cluster number = 0 ;AN000; + mov ax,es:[di].FH_Phys_Clus_Num ;AN000; + push ax ; first phys clus of current hdr ;AN000; + push bx ; first logic clus (0) of cur hdr ;AN000; + mov fully_flag,0 ; partially found case ;AN000; + jmp Look_Make_MRU_Hdr ; make current header MRU header ;AN000; + + + +;-------------------------------------------------------------------------- +; If first logical cluster number of the current extent matches with the given +; logical cluster number, see if previous logical cluster in previous header +; or extent is contiguous. If true, fully found. I this case return +; BX = first physical cluster of cuurent extent and DI = first physical +; cluster number of header if it is a header or last physical cluster number +; of previous extent. If this is not true, partially found case. In this case, +; return BX = last logical cluster number and DI = last physical cluster number +; from the previous extent. If no previous extent, then return DI = first +; physical cluster and BX = 0 from the header +; +; NOTE: The clusters are fully found if the logical cluster has +; continuity to the previous logical cluster in the same +; extent or previous extent or previous header. +;-------------------------------------------------------------------------- +Look_Proc_First: + mov si,Cur_Extn_Ptr ; SI-->current extent ;AN000; + mov di,Cur_Hdr_Ptr ; DI-->current header ;AN000; + cmp Prev_Extn_Ptr, -1 ; any previous extent ?? ;AN000; + jne look_get_prev_extent ; yes, get from previous extent ;AN000; + +;-------------------------------------------------------------------------- +; No, look for current header logical cluster number continuity +;-------------------------------------------------------------------------- + mov ax,es:[si].EH_Logic_Clus_Num ; AX = First physical cluster number ;AN000; + dec ax ; of current extent ;AN000; + cmp ax,0 ; continuity to first logical clus num ;AN000; + ; of current header which is (0) + jne Look_first_partial ; no, partially found ;AN000; + + +; Yes, fully found + mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000; + ; current extent + mov ax,es:[di].FH_Phys_Clus_Num ; AX = First physical cluster number ;AN000; + ; of current header + push bx ; BX = 1st phys clus of current extent ;AN000; + push ax ; AX = 1st phys clus of prev header ;AN000; + mov fully_flag,1 ; FULLY found case ;AN000; + jmp Look_Make_MRU_Hdr ; mov cur header to top of the Queue ;AN000; + + +Look_First_Partial: + xor bx,bx ; BX = logical cluster number = 0 ;AN000; + mov ax,es:[di].FH_Phys_Clus_Num ;AN000; + push ax ; first phys clus of current hdr ;AN000; + push bx ; first logic clus (0) of cur hdr ;AN000; + mov fully_flag,0 ; partially found case ;AN000; + jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000; + + +;-------------------------------------------------------------------------- +; Get last physical and logical cluster number of the previous extent +;-------------------------------------------------------------------------- +Look_Get_Prev_Extent: + mov di,Prev_Extn_Ptr ; DI-->Previous extent ;AN000; + mov ax,es:[si].EH_Logic_Clus_Num ; AX = First logical cluster number ;AN000; + dec ax ; of current extent ;AN000; + mov bx,es:[di].EH_Logic_Clus_Num ; continuity to last logical clus num ;AN000; + add bx,es:[di].EH_Count ; of previous extent ?? ;AN000; + cmp ax,bx ;AN000; + jne Look_first_partial2 ; no, partially found ;AN000; + +; Fully found case + mov bx,es:[si].EH_Phys_Clus_Num ; BX = First physical cluster number ;AN000; + mov ax,es:[di].EH_Phys_Clus_Num ; AX = Last physical cluster number ;AN000; + add ax,es:[di].EH_Count ; from previous extent ;AN000; + push bx ; BX = 1st phys clus num from cur extn ;AN000; + push ax ; AX = last phys clus num from prev extn ;AN000; + mov fully_flag,1 ; FULLY found case ;AN000; + jmp short Look_Make_MRU_Hdr ; mov current header to top of OPEN que ;AN000; + + +Look_First_Partial2: + mov bx,es:[di].EH_Logic_Clus_Num ; BX = First Logical cluster number ;AN000; + ; of current extent + add bx,es:[di].EH_Count ; BX = Last Logic clus from prev extn ;AN000; + mov ax,es:[di].EH_Phys_Clus_Num ; AX = First physical cluster number ;AN000; + ; of previous extent + add ax,es:[di].EH_Count ; last phys clus num of prev extent ;AN000; + push ax ; AX = last phys clus of prev extent ;AN000; + push bx ; BX = last logic clus of prev extent ;AN000; + mov fully_flag,0 ; partially found case ;AN000; + jmp short Look_Make_MRU_Hdr ; make current header MRU header ;AN000; + + + +;---------------------------------------------------------------------------- +; If the given cluster number matches with any logic cluster number starting +; from 2nd and above, then fully found. Return BX=Phys clus num[log_clusnum] +; and DI=Phys clus num[log_clusnum-1] +;---------------------------------------------------------------------------- +Look_Extn_Within: + mov si,Cur_Extn_Ptr ; SI-->Current extent ;AN000; + sub cx,es:[si].EH_Logic_Clus_Num ;AN000; + mov di,es:[si].EH_Phys_Clus_Num ; DI = first phys clus num of ;AN000; + ; current extent + add di,cx ; DI = Phys clus num [logic clus num] ;AN000; + mov bx,di ; ;AN000; + dec bx ; BX = Phys clus num [logic clus num -1] ;AN000; + push di ; DI = Phys clus num [logic clus num] ;AN000; + push bx ;AN000; + mov fully_flag,1 ; fully found case ;AN000; + jmp short Look_Make_MRU_Hdr ; make current header to top of OPEN Que ;AN000; + + +;-------------------------------------------------------------------------- +; Given extent is above the upper limit of the current extent, but lower than the +; next extent. In this case, cluters are partially found. Return BX = last +; logical cluster number of the previous extent and DI = last physical cluster +; number of the previous extent. +;---------------------------------------------------------------------------- +Look_Proc_Prev: + mov si,Prev_Extn_Ptr ; SI-->Previous extent ;AN000; + mov bx,es:[si].EH_Logic_Clus_Num ; DI = first logic clus num of prev ;AN000; + ; extent + mov di,es:[si].EH_Phys_Clus_Num ; BX = first phys clus num of prev ;AN000; + ; extent + add di,es:[si].EH_Count ; DI = last phys clus number in extent ;AN000; + add bx,es:[si].EH_Count ; BX = last logic clus number in extent + push di ; save clusters to return ;AN000; + push bx ;AN000; + mov fully_flag,0 ; partially found case ;AN000; + +;---------------------------------------------------------------------------- +; Move the current header to the top of the OPEN queue +;---------------------------------------------------------------------------- +Look_Make_MRU_Hdr: + cmp Prev_Hdr_Ptr,-1 ; first header in the Queue ?? ;AN000; + je Look_Dont_Move_To_Top ; yes, dont move to top ;AN000; + + CALL MAKE_MRU_HEADER ;AN000; + +Look_Dont_Move_To_Top: + cmp fully_flag, 0 ; fully found ?? ;AN000; + je Look_set_carry ; no, partially found ;AN000; + clc ; fully found ;AN000; + jmp short Look_Restore ; restore registers ;AN000; + +Look_Set_Carry: + stc ; set flag for partially found ;AN000; + +Look_restore: + pop bx ; restore values to be reurned + pop di ; to DOS + +Look_Exit: + nop + CALL Check_it + ret ; exit + +FK_LOOKUP endp + + + + + + + +;---------------------------------------------------------------- +; PROCEDURE: Fk_Truncate +; +; FUNCTION: Using the given physical and logical clutser numbers, +; find the extent which contains the given cluster number. +; Delete all clusters folloing the given cluster and the +; subsequent extents and free the buffers. +; +; INPUT: CX = First Physical Cluster Number of the file +; BX = Logical Cluster Number +; DL = Drive number +; +; OUTPUT: CY = 0 Extents are truncated +; +; CY = 1 Extent no found DI = 0 +; +; ROUTINES REFERENCED: Find_File_Header, Find_Extent +; +; REVISION HISTORY: New (5/87) +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;--------------------------------------------------------------- + +Fk_TRUNCATE PROC FAR + + push cs ; establish addressability ;AN000; + pop ds ; DS --> code segment ;AN000; + assume ds:Cseg_Seek ;AN000; + mov es, Seek_Name_Cache_Seg ; setup cache buff segment register ;AN000; + assume es:Cseg_Init ; ES --> cache buffer segment ;AN000; + mov First_Phys_Clusnum,cx ; save phys cluster number ;AN000; + mov Logical_ClusNum,bx ;AN000; + mov func_cod,al + +;-------------------------------------------------------------------------- +; Search for Drive Cache buffer using Drive ID in DL +;-------------------------------------------------------------------------- + CALL FIND_DRIVE_HEADER ; get drive buffer ;AN000; + jnc Trunc_search_hdr ; if found, search for file header ;AN000; + jmp Trunc_Exit ; if not found, error ;AN000; + ;AN000; +;-------------------------------------------------------------------------- +; Search for a header in the OPEN Queue using given physical clusternum +;-------------------------------------------------------------------------- +Trunc_Search_Hdr: + inc es:[di].Extent_Count ; ;***; + mov si,es:[di].MRU_Hdr_Ptr ; SI-->first header in the ;AN000; + ; in the OPEN Queue + mov cx,First_Phys_Clusnum ; CX = Physical Cluster number ;AN000; + + CALL FIND_FILE_HEADER ; find file header in OPEN Queue ;AN000; + jnc Trunc_Find_extent ; if found, get extent ;AN000; + +;-------------------------------------------------------------------------- +; If the header is not found, create a new header and make it as MRU header +; insert first physical cluster number in the header +;-------------------------------------------------------------------------- + CALL MAKE_NEW_HEADER ; make new header ;AN000; + clc ;AN000; + jmp Trunc_exit ; exit ;AN000; + + +;-------------------------------------------------------------------------- +; Header is found. Next search for the extent which contains the +; given logical cluster number. +;-------------------------------------------------------------------------- +Trunc_Find_Extent: ; ;AN000; + mov Cur_Hdr_Ptr,di ; save current pointer ;AN000; + mov si,es:[di].FH_Next_Extn_Ptr ; SI-->first extent in the ;AN000; + ; current header + cmp si, -1 ; any extent under this header ?? ;AN000; + je trunc_no_extent ; none, exit ;AN000; + mov cx,Logical_Clusnum ; CX = given logical cluster number ;AN000; + + CALL FIND_EXTENT ; find the extent ;AN000; + jnc Trunc_shrink_extent ; found extent ?? ;AN000; + +Trunc_No_Extent: ; extent not found + xor di,di ; no, return DI = 0 ;AN000; + clc ; clear carry + jmp Trunc_exit ; exit ;AN000; + + + +;-------------------------------------------------------------------------- +; Found extent. Shrink the current extent and delete all subsequent extents. +; If the given logic clus num is the first cluster number in current extent, +; then delete the current extent and the subsequent ones. +; DI--->Extent found (starting extent) +;-------------------------------------------------------------------------- +Trunc_Shrink_Extent: + mov bx,Logical_Clusnum ;AN000; + cmp bx,es:[di].EH_Logic_Clus_Num ; first logic cluster match ?? ;AN000; + jne shrink_cur_extent ; no, shrink current extent ;AN000; + +;-------------------------------------------------------------------------- +; First logical clus num matched. mark previous header or extent as last +; DI--->Extent found (starting extent) +;-------------------------------------------------------------------------- + mov si,es:[di].EH_Prev_Extn_Ptr ; SI-->Previous extent ;AN000; + cmp si, -1 ; any previous extent ?? ;AN000; + je trunc_no_prev ; no, jump ;AN000; + mov es:[si].EH_Next_Extn_Ptr,-1 ; mark previous extent as last extn ;AN000; + mov si,di ; save the current extent ptr ;AN000; + mov cx, 0 ; CX = buffer release counter ;AN000; + jmp trunc_more ; release successive extents ;AN000; + +;-------------------------------------------------------------------------- +; Previous one is header. Mark so that there is no extents under it +;-------------------------------------------------------------------------- +Trunc_No_Prev: + mov si,Cur_Hdr_Ptr ; get current header ;AN000; + mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000; + mov es:[si].FH_MRU_Extn_Ptr, -1 + mov si,di ; save the current extent ptr ;AN000; + mov cx, 0 ; CX = buffer release counter ;AN000;;AN000; + jmp short trunc_more ; release the extent ;AN000; + + +Shrink_Cur_Extent: + sub bx,es:[di].EH_Logic_Clus_Num ; compute the amount to shrunk ;AN000; + dec bx ;AN000; + mov es:[di].EH_Count,bx ; save it in count to shrink extent ;AN000; + +;-------------------------------------------------------------------------- +; Mark the current extent as the last extent and delete subsequent extents. +;-------------------------------------------------------------------------- + mov si,es:[di].EH_Next_Extn_Ptr ; SI-->Next extent ;AN000; + cmp si,-1 ; current extent last extent ?? ;AN000; + jne Trunc_Last_extent + jmp Trunc_Make_MRU_Hdr ; YES, In this case no subsequent ;AN000; + ; extents left to delete. +Trunc_Last_Extent: + mov es:[di].EH_Next_Extn_Ptr, -1 ; NO, mark last extent ;AN000; + xor cx,cx ;AN000; + +;-------------------------------------------------------------------------- +; Remove extents and release the buffer +; SI--->Current extent +;-------------------------------------------------------------------------- +Trunc_More: + push si ; save the beginning of first ;AN000; + ; extent to be deleted +TRUNC_LOOP: ; loop for subsequent extents + mov ax, -2 ; mark current extent as free ;AN000; + mov es:[si],ax ; discontinuous free areas ;AN000; + add cx, SIZE Extent_Header ; add size of extent ;AN000; + + mov ax,es:[si].EH_Next_LRU_Ptr ; AX = address of Next LRU extent + cmp ax, -1 ; any next LRU extent?? + jne Trunc_Set_Next_LRU ; yes - there is a next LRU extent + +;----------------------------------------------------------------------------- +; No - this is the LRU extent +;----------------------------------------------------------------------------- + mov di,es:[si].EH_Prev_LRU_Ptr ; no - DI=address of previous LRU extent + cmp di, -1 ; any prev LRU extent ?? + je Trunc_Mark_Prev_Hdr ; no - previous is header + mov es:[di].EH_Next_LRU_Ptr, -1 ; yes - mark previous extnt LRU extent + jmp short Trunc_Chk_Next_ext ; no - check next adj extent + +Trunc_Mark_Prev_Hdr: + mov di, Cur_Hdr_Ptr ; DI = address of current header + mov es:[di].FH_Next_Extn_Ptr,-1 ; mark header for no extent ;AN000; + mov es:[di].FH_MRU_Extn_Ptr, -1 + jmp short Trunc_Chk_Next_Ext ; look for next extent + +;----------------------------------------------------------------------------- +; There is a next LRU extent AX-->Next_LRU_Extent +;----------------------------------------------------------------------------- +Trunc_Set_Next_LRU: + mov di,es:[si].EH_Prev_LRU_Ptr ; DI = address of previous LRU extent + cmp di, -1 ; any previous LRU extent ?? + jne Trunc_Set_Prev_LRU ; yes - connect prev LRU to Next LRU + + mov di, Cur_Hdr_Ptr ; DI = address of current header + mov es:[di].FH_MRU_Extn_Ptr, ax ; Connect next LRU extent to Hdr + push si ; save current extent + mov si,ax + mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous extent + pop si ; resetore current extent + jmp short Trunc_Chk_Next_Ext + + +Trunc_Set_Prev_LRU: ; DI-->Previous LRU extent + mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous LRU to Next LRU extent + push si ; save Current extent + mov si,ax ; SI-->Next LRU extent + mov es:[si].EH_Prev_LRU_Ptr, di ; set previous LRU header address + pop si ; get current extent + + +Trunc_Chk_Next_Ext: ; SI-->Current extent + mov ax,es:[si].EH_Next_Extn_Ptr ; AX-->next extent ;AN000; + cmp ax, -1 ; last extent ? ;AN000; + je Trunc_Update_Free_Size ; yes, jump ;AN000; + + mov es:[si].FH_Next_Hdr_Ptr,ax ; connect freed buffers togther ;AN000; + mov si,ax ; SI-->next extent ;AN000; + jmp Trunc_Loop ; delete next extent ;AN000; + +;------------------------------------------------------------------------- +; Update free size in the File header and connect the FREE_Ptr to the first +; extent released and connect the old Free_Ptr to end of the last extent +; SI--->Current extent +;------------------------------------------------------------------------- +Trunc_Update_Free_Size: ; SI-->Last extent released + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + add es:[di].Free_Size,cx ; update free area in drive header ;AN000; + +Trunc_Join_Free_Area: +; At this point SI-->Last extent + mov ax,es:[di].Free_Ptr ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ; connect last extent under this ;AN000; + ; header to the Free area ;AN000; + pop ax ; beginning of truncated extent ;AN000; + mov es:[di].Free_Ptr,ax ; connect current extent to ;AN000; + ; the beginning of truncated extent + +;-------------------------------------------------------------------------- +; Make the Current header MRU header ( move current header to top of current Q) +;-------------------------------------------------------------------------- +Trunc_make_MRU_Hdr: + cmp Prev_Hdr_Ptr,-1 ; first header in the Queue?? ;AN000; + jne Trunc_move_Hdr + clc + jmp short Trunc_Exit ; yes, dont move to top ;AN000; + +Trunc_move_Hdr: + CALL MAKE_MRU_HEADER ; move header to TOP of the Queue ;AN000; + clc + +Trunc_Exit: + CALL Check_it + ret ; return ;AN000; + +FK_TRUNCATE ENDP + + + + + + + + +;----------------------------------------------------------------------------- +; Procedure: PURGE_BUFFERS +; +; Function: Reset both extent and name cache buffers of a specific +; drive id +; +; Input: DL = drive ID +; +; Output: Buffers are initialized +; +; REVISION HISTORY: New (5/87) +; +; COPYRIGHT: "MS DOS 4.00 Fastopen Utility" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Property of Microsoft " +; +;----------------------------------------------------------------------------- + +FK_PURGE PROC FAR ; Purge Cache buffers + + push cs + pop ds ; DS=Code seg id used for addressing + ASSUME ds:Cseg_Seek ; local variables ;AN000; + + mov si,Seek_Extent_Drive_Buff ; SI-->beginning of extent drive ;AN000; + mov es,Seek_Name_Cache_Seg ; ES = addressability to Cseg_Init ;AN000; + ASSUME es:Cseg_Init ; ;AN000; + mov cx,Seek_Num_Of_drives ; number of drives + +Main_Loop2: ; ES:SI-->cache buffer + mov ax,es:[si].Drive_Number ; get drive id + cmp al,dl ; drive id found ?? + je purge_buffer ; yes - purge drive id buffer + mov ax, size Drive_Header ; ax size of drive heder + add ax, es:[si].Buff_Size ; ax = offset to next header + add si,ax ; (2/11)SI-->next drive header ;AN000; + LOOP main_loop2 ; try next header + +Purge_Buffer: ; SI-->drive header + mov es:[si].MRU_Hdr_Ptr,-1 ; Make OPEN QUEUE empty ;AN000; + mov es:[si].CLOSE_Ptr,-1 ; Make CLOSE QUEUE empty ;AN000; + mov cx,es:[si].BUFF_size ; drive extent cache size ;AN000; + mov es:[si].FREE_Size,cx ; set drive free buffer size ;AN000; + mov ax,si + add ax, size Drive_Header ; ax = size of drive header + mov es:[si].FREE_Ptr,ax ; set Free buffer address + +; Makesure to fill extent cache buffer with zeros. Otherwise, Free Mark left +; previous run will generate illegal Free_Buff pointer. + mov al,0 + add si, size Drive_Header ; SI-->first extent area +Ext_loop: ; fill extent cahe buffer with zeros + mov es:[si],al ; CX = extent cache size + inc si ; next byte + Loop Ext_Loop ; make it zero + +FK_Exit: + clc + CALL Check_it + ret ;AN000; + +FK_PURGE ENDP + + + + + + + +;---------------------------------------------------------------------- +; ******* SUPPORT ROUTINES ******* +;---------------------------------------------------------------------- +; +;---------------------------------------------------------------------- +; PROCEDURE: Find_Drive_Header +; +; FUNCTION: Find starting address of drive header in extent Cache Buffer using +; drive ID in DL +; +; INPUT: DL = drive id +; Extent_Drive_Buff (Ptr to the beginning of extent buffer) +; ES--> Cache Buffer Segment +; +; OUTPUT: If Carry = 0 DI --> Drive header +; Drive_Hdr_Ptr = address of drive header +; +; If Carry = 1 Drive buffer not found +; +; NOTE: If drive id in DL is same as the drive id in previous request, +; no need to search the drive header. Use the previous drive header +; +;---------------------------------------------------------------------- + +FIND_DRIVE_HEADER PROC NEAR + + mov di,Drive_Hdr_Ptr ; DI-->address of prev drive header + cmp drv_id,dl ; drive id same as previous drive id (1/11/88) + jne Search_drv_hdr ; no - search drive header + clc ; yes - dont search + jmp short drive_exit ; exit + +Search_Drv_Hdr: + mov cx,Seek_Num_of_Drives ; get number of drives ;AN000; + mov si,Seek_Extent_Drive_Buff ; SI-->start of extend drive hdr ;AN000; + +Drive_Loop: + mov al,es:[si] ; get drive ID from cache drive hdr ;AN000; + cmp al,dl ; found ?? ;AN000; + je drive_buff_found ; yes, exit ;AN000; + cmp es:[si].Next_Drv_Hdr_Ptr,-1 ; last header ?? ;AN000; + je drive_Buff_not_found ; yes - drive header not found ;AN000; + mov si,es:[si].Next_Drv_Hdr_Ptr ; SI-->next drive header ;AN000; + dec cx ; update drive count ;AN000; + jz drive_Buff_not_found ; last drive ;AN000; + jmp drive_Loop ; search for more ;AN000; + +Drive_Buff_Not_Found: ; drive buffer not found + stc ; set carry flag ;AN000; + jmp short Drive_Exit ; exit ;AN000; + +Drive_Buff_Found: ; drive buffer found + mov drv_id,dl ; save drive id + mov Drive_Hdr_ptr,si ; save drive buffer pointer ;AN000; + mov di,si ; DI-->drive header ;AN000; + clc ;AN000; + +Drive_Exit: ; return + ret ;AN000; + +FIND_DRIVE_HEADER endp + + + + + +;--------------------------------------------------------------- +; PROCEDURE: Find_File_Header +; +; FUNCTION: Find starting address of the specific file header with +; a specific starting physical cluster number. Also +; determine the type of header found. +; +; INPUT: SI --> First header in the queue +; CX = First Physical Cluster Number (file id) +; ES--> Cache Buffer Segment id +; +; OUTPUT: If Carry = 0 DI --> header found +; Cur_Hdr_Ptr = address of header found +; Prev_Hdr_Ptr = address of previous header +; +; Prev_Hdr_Ptr = -1 No Previous Header +; +; hdr_flag - Type of header found +; = 0 Header between first & last in queue +; = 1 Single header in the queue +; = 2 First header in the queue +; = 3 LRU (Last) header in the queue +; +; If Carry = 1 Header not found +; +;--------------------------------------------------------------- + +FIND_FILE_HEADER PROC NEAR + + push si ; save registers ;AN000; + push cx ;AN000; + + cmp si, -1 ; any file header in this queue ?? ;AN000; + jne Fh_search_hdr ; yes, search for it ;AN000; + stc ; no, set carry and return ;AN000; + jmp short Fh_Exit ;AN000; + +Fh_Search_Hdr: + mov Prev_Hdr_Ptr,-1 ; reset flags ;AN000; + mov Hdr_Flag, 0 ; reset header type flag ;AN000; + +Fh_Loop1: + cmp es:[si].FH_Phys_Clus_Num,CX ; check current header ;AN000; + jne Fh_next_header ; if not found branch ;AN000; + mov di,si ; DI --> header found ;AN000; + mov Cur_Hdr_Ptr,si ; save current Hdr pointer ;AN000; + jmp short Fh_header_found ; then take exit ;AN000; + +Fh_Next_header: ; else try next header + mov ax,es:[si].FH_Next_Hdr_ptr ; get address of next header ;AN000; + cmp ax,-1 ; is this last header?? ;AN000; + je Fh_not_found ; yes, header no found ;AN000; + + mov Prev_Hdr_Ptr,si ; save previous header ;AN000; + mov si,ax ; SI= next header ;AN000; + jmp Fh_Loop1 ; check next header ;AN000; + +; Determine the type of header found +Fh_Header_Found: ; header found + cmp Prev_Hdr_Ptr, -1 ; any previous headers ?? ;AN000;;AN000; + jne Fh_LRU ; yes, jump ;AN000; + cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; any headers following this hdr ?? ;AN000; + jne Fh_First ; yes, jump ;AN000; + mov Hdr_Flag, 1 ; single header in the queue ;AN000; + clc ; ;AN000; + jmp short FH_Exit ; exit ;AN000; + +Fh_First: + mov Hdr_Flag, 2 ; Header found is first header in QUE ;AN000; + clc ; set flag ;AN000; + jmp short FH_Exit ; exit ;AN000; + +Fh_LRU: + cmp es:[si].Fh_Next_Hdr_Ptr, -1 ; Last header in the queue ?? ;AN000; + jne Fh_middle_hdr ; no, Header between first and last ;AN000; + mov Hdr_Flag, 3 ; set flag indicating LRU header ;AN000; + clc ;AN000; + jmp short Fh_Exit ; exit ;AN000; + ;AN000; +Fh_Middle_Hdr: + clc ;AN000; + jmp short Fh_Exit ; exit ;AN000; + +Fh_Not_found: + stc ; header not found ;AN000; + +Fh_Exit: + pop cx ;AN000; + pop si ;AN000; + ret ; return ;AN000; + +FIND_FILE_HEADER ENDP + + + + + + + +;--------------------------------------------------------------- +; PROCEDURE: Find_Extent +; +; FUNCTION: Find starting address of the specific Extent that contains +; the given logical cluster mumber. +; Verifiy that the extent found is the LRU Extent. +; +; INPUT: SI --> First Extent under current queue +; CX = Logical Cluster number to be searched +; ES--> Cache Buffer Segment Id +; +; OUTPUT: If Carry = 0 DI --> Extent found +; Cur_Extn_Ptr = address of extent found +; Prev_Extn_Ptr = address of previous extent +; IF Extn_Flag = 1, extent found is the only +; extent under this header +; +; If Carry = 1 Extent not found +; +; REVISION HISTORY: New (5/87) +;--------------------------------------------------------------- + +FIND_EXTENT PROC NEAR + + push si ; save registers ;AN000; + push cx ;AN000; + ;AN000; + mov Prev_Extn_Ptr,-1 ; reset flags + mov Extn_Flag, 0 ;AN000; + ;AN000; +Eh_Loop1: + cmp cx,es:[si].EH_Logic_Clus_Num ;AN000; + jl Eh_Next_Extn ; try next extent ;AN000; + mov ax,es:[si].EH_Count ; get range ;AN000; + add ax,es:[si].EH_Logic_Clus_Num ; get upper range ;AN000; + cmp cx,ax ;AN000; + jg Eh_Next_Extn ; try next extent ;AN000; + +Eh_Not_LRU: + mov di,si ; DI --> Extent found ;AN000; + mov Cur_Extn_Ptr,si ; save current extent pointer ;AN000; + clc ; set flag ;AN000; + jmp Eh_Extn_found ; then take exit ;AN000; + +Eh_Next_Extn: ; else try next extent + mov ax,es:[si].EH_Next_Extn_ptr ; get address of next extent ;AN000; + cmp ax,-1 ; is this last extent?? ;AN000; + je Eh_Not_Found ; yes, exit ;AN000; + mov Prev_Extn_Ptr,si ; save previous extent ;AN000; + mov si,ax ; SI=next extent ;AN000; + jmp Eh_Loop1 ; check next extent ;AN000; + + stc ; else set flag for extent not found ;AN000; + jmp short Eh_Exit ; then exit ;AN000; + +Eh_Extn_Found: ; Extent found + cmp Prev_Extn_Ptr, -1 ; any previous extents ?? ;AN000; + jne Eh_yes ; yes, jump ;AN000; + cmp es:[di].Eh_Next_Extn_Ptr, -1 ; any extents following this extents ?? ;AN000; + jne Eh_yes ; yes, jump ;AN000; + mov Extn_Flag, 1 ; no, set flag indicating single extnt ;AN000; + ; in the queue +Eh_Yes: + clc ;AN000; + jmp short Eh_Exit ; exit ;AN000; + +Eh_Not_Found: ; extent not found + stc ;AN000; + +Eh_Exit: + pop cx ;AN000; + pop si ;AN000; + + ret ; return ;AN000; + +FIND_EXTENT ENDP + + + + + + +;--------------------------------------------------------------------------- +; PROCEDURE: FIND_CLUSTER_LOCATION +; +; FUNCTION: Find starting address of a specific extent which identifies +; the relative position of the new cluster in the queue. +; +; INPUT: SI--> First extent under current header +; ES--> Cache Buffer Segment +; +; OUTPUT: If Carry = 0 Cluster location identified +; Cur_Extn_Ptr = Current extent +; Prev_Extn_Ptr = Previous extent +; +; Find_Flag = 1 Clusters are contiguous in +; the LO end of the current extent +; +; Find_Flag = 2 Clusters are contiguous in +; the HI end of the current extent +; +; Find_Flag = 3 Clusters belong to a new +; extent between current and previous +; extent +; +; Find_Flag = 4 Clusters belong to a new +; extent at the end of the queue +; Cur_Extn_Ptr-->Last extent in queue +; +; Find_Flag = 5 Clusters belong to a new +; extent between current and next +; +; If Carry = 1 Clusters already exist +; +;----------------------------------------------------------------------- + + +FIND_CLUSTER_LOCATION PROC NEAR + +;-------------------------------------------------------------------------- +; Check to see that the given logical cluster number falls within the +; current extent. If true it is an error. +;-------------------------------------------------------------------------- + push di + mov Prev_Extn_Ptr, -1 ; initialize the flag ;AN000; + mov Cur_Extn_Ptr,si ; SI-->First extent under header ;AN000; + mov Find_Flag, -1 ; reset with illegal value + ;AN000; +Fe_LOOP1: + mov ax,es:[si].EH_Logic_Clus_Num ; AX = starting logi clus number ;AN000; + mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; + cmp bx,ax ; LOW end ?? ;AN000; + jl Fe_Chk_Low_end ; yes - jump ;AN000; + add ax,es:[si].EH_Count ; ending logical clus number ;AN000; + cmp bx,ax ; HIGH end ?? ;AN000; + jg Fe_Chk_High_end ; yes - jump ;AN000; + +;-------------------------------------------------------------------------- +; Found the given logical cluster number within the extent. +; This is a normal condition. In this case the clusters wont be insterted. +;-------------------------------------------------------------------------- + stc ; set flag + jmp Fe_Extent_Exit ; return ;AN000; + + +;-------------------------------------------------------------------------- +; If not in the extent, then see the logical clus number has continuity at +; LOW end of the current extent. +;-------------------------------------------------------------------------- +Fe_Chk_LOW_END: + mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000; + dec ax ; one below the lowest ;AN000; + mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; + cmp bx,ax ; contiguous at LOW end ?? ;AN000; + jl Fe_Curr_Prev ; no, build a new extent between ;AN000; + ; current and previous +; Logical clus has continuity at low end. Now check physical cluster number +; foe continuity. + mov ax,es:[si].EH_Phys_Clus_Num ; starting Phys clus number ;AN000; + dec ax ; one below the lowest in the extent ;AN000; + mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000; + cmp bx,ax ; within low end ?? ;AN000; + jne Fe_Curr_Prev ; no, create a new extent between ;AN000; + ; current and previous extent + mov Find_Flag,1 ; yes, set flag for LOW END continuity ;AN000; + jmp Fe_Extent_found ; then RETURN ;AN000; + + +;-------------------------------------------------------------------------- +; Check the logical clus number has continuity at High end of the current +; extent cluster range. Check physical cluster number has continuity at the +; high end. If true, check the first logical and phys cluster number is the +; the same as this one. In this case clusters exist and therefore wont be +; insterted. +;-------------------------------------------------------------------------- +Fe_CHK_HIGH_END: + mov ax,es:[si].EH_Logic_Clus_Num ; starting logi clus number ;AN000; + add ax,es:[si].EH_Count ; ending logical clus number ;AN000; + inc ax ;AN000; + mov bx,Logical_Clusnum ; BX = given logical clus num ;AN000; + cmp bx,ax ; within high end ?? ;AN000; + jg Fe_Chk_Next_Extent ; no, check next extent ;AN000; + +; Logical clus num has high end continuity, Check the Physical cluster number +; for continuity. + mov ax,es:[si].EH_Phys_Clus_Num ; starting phys clus number ;AN000; + add ax,es:[si].EH_Count ; ending phys clus number ;AN000; + inc ax ;AN000; + mov bx,Physical_Clusnum ; BX = given logical clus num ;AN000; + cmp bx,ax ; within high end ?? ;AN000; + jne Fe_Chk_Next_Extent ; no - check next extent ;AN000; + ; +; Yes - check first logical and physical cluster number of next extent + mov di,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000; + cmp di, -1 ; any next extent ?? + je Fe_High_End ; none - jump + mov ax,es:[di].EH_Logic_Clus_Num ; starting logi clus number ;AN000; + cmp ax,Logical_Clusnum ; logical cluster matches ?? + jne Fe_high_end ; no - jump + mov ax,es:[di].EH_Phys_Clus_Num ; starting phys clus number ;AN000; + cmp ax,Physical_Clusnum ; physical cluster match ?? + jne Fe_High_End ; no -jump + stc ; clusters already exist in next extent + jmp short Fe_Extent_Exit ; return ;AN000; + +Fe_High_End: + mov Find_Flag,2 ; set flag for HIGH end continuity ;AN000; + jmp short Fe_Extent_found ; then RETURN ;AN000; + + +Fe_Chk_Cur_Next: + cmp es:[si].EH_Next_Extn_Ptr, -1 ; Current extent last extent ?? ;AN000; + je Fe_flag_4 ; yes, set flag-4 ;AN000; + + mov Find_Flag,5 ; set flag for new extent between ;AN000; + jmp short Fe_Extent_Found ; current and next extent ;AN000; + +Fe_Flag_4: + mov Find_Flag,4 ; set flag for new extent at the ;AN000; + jmp short Fe_Extent_Found ; bottom end of current queue ;AN000; + +;-------------------------------------------------------------------------- +; Given cluster number has no continuity but must stay between current extent +; and previous extent +;-------------------------------------------------------------------------- +Fe_CURR_PREV: + mov Find_Flag,3 ; set flag for between current and prev ;AN000; + jmp short Fe_Extent_found ; then RETURN ;AN000; + + +;-------------------------------------------------------------------------- +; Given cluster number has no continuity. Try the next extent. +;-------------------------------------------------------------------------- +Fe_Chk_NEXT_EXTENT: ; else try next extent + mov ax,es:[si].EH_Next_Extn_Ptr ; get address of next extent ;AN000; + cmp ax,-1 ; is this last extent ?? ;AN000; + je Extent_at_Bottom ; yes, Clustr belongs to a new ;AN000; + ; extent at the bottom ;AN000; + mov Prev_Extn_Ptr,si ; save current extend as previous extnt + mov si,ax ; SI-->Next extent ;AN000; + mov Cur_Extn_Ptr, si ; save new extent as cur extent ;AN000; + jmp Fe_Loop1 ; check next extent ;AN000; + + +;-------------------------------------------------------------------------- +; Given cluster number has no continuity but stays in a new extent at +; bottom (last) of the current queue. +;-------------------------------------------------------------------------- +Extent_AT_BOTTOM: + mov Find_Flag,4 ; else set flag for new extent ;AN000; + +Fe_Extent_Found: + clc ;AN000; + +Fe_Extent_Exit: + pop di + + RET ; exit ;AN000; + + +FIND_CLUSTER_LOCATION ENDP + + + + + + + +;----------------------------------------------------------------------- +; PROCEDURE: FIND_LRU_HEADER +; +; FUNCTION: Find address of the LRU header in the current queue +; +; INPUT: SI --> First header in the current queue +; ES--> Cache Buffer Segment +; +; OUTPUT: DI --> LRU header found +; +; LRU_Prev_Hdr = Previous header address +; LRU_Hdr = Address of LRU header found +; If Hdr_Flag = 1 - Header found is only header in the queue +; +;----------------------------------------------------------------------- + +FIND_LRU_HEADER PROC NEAR + + push bx ;AN000; + mov hdr_flag,0 ; initilialize flags ;AN000; + mov LRU_Prev_Hdr, -1 ; ;AN000; + +Flh_Loop1: + cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header is last hdr ? ;AN000; + jne Flh_next_header ; if not check next header ;AN000; + mov di,si ; DI --> LRU header found ;AN000; + mov LRU_Hdr,si ; save it ;AN000; + jmp short Flh_header_found ; then take exit ;AN000; + +Flh_Next_Header: ; else try next header + mov LRU_Prev_Hdr,si ; save previous header address ;AN000; + mov si,es:[si].FH_Next_Hdr_ptr ;AN000; + jmp Flh_Loop1 ; check next header ;AN000; + +Flh_Header_Found: + cmp LRU_Prev_Hdr, -1 ; any previous header ?? ;AN000; + je F1h_Set_Flag ; no, set flag ;AN000; + clc ; yes ;AN000; + jmp short F1H_Exit ; exit ;AN000; + +F1h_Set_Flag: + mov hdr_flag,1 ; LRU header is the only hdr in queue ;AN000; + clc ;AN000; + +F1h_Exit: ; exit + pop bx ;AN000; + + ret ;AN000; + +FIND_LRU_HEADER endp + + + + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; PROCEDURE: FIND_LRU_EXTENT +; +; FUNCTION: Find address of LRU Extent under current header +; +; INPUT: ES--> Cache Buffer Segment +; SI--> Header to be searched +; +; OUTPUT: If CY = 0 LRU_Prev_Extent = Previous extent to the LRU extent +; LRU_Extent = LRU extent found +; Extn_Flag = 1 Extent is the only extent under header +; +; If CY = 1 Not found +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +FIND_LRU_EXTENT PROC NEAR + + mov LRU_Prev_Extent, -1 ; reset flags ;AN000; + mov LRU_Extent, -1 ; ;AN000; + mov Extn_Flag, 0 + mov si, es:[si].FH_MRU_Extn_Ptr ; SI--> First extent under header + cmp si, -1 ; any extent under this header ?? + jne Fle_Loop1 ; yes - check extent + stc ; no - set flag + jmp Fle_Exit ; exit + +Fle_Loop1: + cmp es:[si].EH_Next_LRU_Ptr,-1 ; last extent in the queue?? + jne Fle_next_extent ; if not found branch ;AN000; + mov LRU_Extent,si ; save LRU extent address + jmp short Fle_Extend_found ; exit + +Fle_Next_Extent: ; else try next extend + mov LRU_Prev_Extent,si ; save previous extent address + mov si,es:[si].EH_Next_LRU_Ptr ; get address of next extent + jmp Fle_Loop1 ; check next extent ;AN000; + +Fle_Extend_Found: + cmp LRU_Prev_Extent, -1 ; any previous extent ?? + je Fle_Set_Flag ; no - set flag + clc ; ;AN000; + jmp short Fle_Exit + +Fle_Set_Flag: + mov Extn_Flag, 1 ; set flag to indicate only flag + clc + +Fle_Exit: + ret ; exit ;AN000; + +FIND_LRU_EXTENT ENDP + + + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: Make_New_Header +; +; FUNCTION: Create a new header in the next available free area. +; Initialize the new header and make it MRU header ( move it +; to the top of the queue). If no free space in OPEN queue, delete +; and extent from the CLOSE queue. If no space in CLOSE queue, then +; delete an extent from OPEN Queue to make space. +; +; INPUT: Drive_Hdr_Ptr - Address of drive header +; Free_Ptr - Address of FREE area +; ES--> Cache Buffer Segment +; +; OUTPUT: Header is created +; +;---------------------------------------------------------------------- + +MAKE_NEW_HEADER PROC + +; Check if the OPEN Queue was previously empty using two cases. If open queue +; is empty, then the new header should be marked as first header in the queue. + mov Open_Queue_Flag, 0 ; clear flag open queue empty ;AN000; + mov di,Drive_Hdr_Ptr ;AN000; + +; case - 1 + mov ax,es:[di].Free_Size ; FREE size ;AN000; + cmp es:[di].Buff_Size,ax ; both are equal ? ;AN000; + je Make_Set_Entries ; if true, this is the first header ;AN000; + +; case - 2 + cmp es:[di].MRU_Hdr_Ptr, -1 ; check for empty mark ;AN000; + je Make_Set_Entries ; yes, set flag queue empty ;AN000; + jmp short Make_Set_Entry2 ; not empty ;AN000; + +Make_set_Entries: ; set up File Header entries +; When creating first header under drive header, mark header as first +; This flag is set for this purpose. + mov Open_Queue_Flag, 1 ; set flag open queue was empty ;AN000; + +Make_Set_Entry2: + CALL FIND_FREE_BUFFER ; Look for some Free area. If none ;AN000; + ;AN000; + mov di,Drive_Hdr_Ptr ; DI-->Drive header ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov New_Hdr_Ptr,ax ; save new Header address + mov ax,es:[di].Free_Size ;AN000; + + CALL UPDATE_FREE_AREA ; update Free_Ptr and Free_Size ;AN000; + ; create some free area + +;----------------------------------------------------------------------------- +; Connect the new header to the Top of the OPEN Queue. If the Queue is +; previously empty, mark the new header indicating nothing under this header. +;----------------------------------------------------------------------------- +Join_To_Drive_Buff: + mov di, drive_Hdr_Ptr ; DI-->drive buffer ;AN000; + mov si,New_Hdr_Ptr ;AN000; + mov Cur_Hdr_Ptr, si ; save as current header pointer ;AN000; + mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header + mov es:[di].MRU_Hdr_Ptr,si ; make new header MRU hdr + +; When a header is created, it should contain no extents + mov es:[si].FH_Next_Extn_Ptr,-1 ; mark header with no extents ;AN000; + mov es:[si].FH_MRU_Extn_Ptr,-1 ; ###mark header with no extents ;AN000; + mov es:[si].FH_Refer_Count,1 ; save starting file reference count ;AN000; + mov ax,First_Phys_Clusnum ;AN000; + mov es:[si].FH_Phys_Clus_Num,ax ; save physical cluster number ;AN000; + + cmp Open_Queue_Flag, 1 ; OPEN Queue empty ?? ;AN000; + je Set_Single_Header ; no, jump ;AN000; + clc + ret ;AN000; + +Set_Single_Header: ; yes mark new header as last hdr + mov si,New_Hdr_Ptr ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,-1 ; mark as only header ;AN000; + clc + ret ; exit + +MAKE_NEW_HEADER ENDP + + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: Find_Free_Buffer +; +; FUNCTION: Find free buffer space. If no free space, delete last extent +; under last header in the CLOSE queue. If none in CLOSE queue, +; delete the last extent of the LRU header in the OPEN queue. +; +; INPUT: Drive_Hdr_Ptr - Pointer to drive header +; ES--> Cache Buffer Segment +; +; OUTPUT: Released Header or extent buffer space will be addded to the +; Free area as discontinuous free area. Free size in drive head +; will be updated. +; +; If CARRY = 0 +; Free_Flag: 0 - Free area is continuous +; 1 - Free area is discontinuous +; +; if CARRY = 1 Fatal error ( no free space to spare ) +; +; NOTE: The deleted buffers have size same as the size of a header or extent. +; Each buffers first location contains a marker (-2) to indicate that +; the buffer is a discontinuous buffer. Each buffer is connected to +; the next dicontinous buffer through the 4th word. +; +;---------------------------------------------------------------------- + +FIND_FREE_BUFFER PROC NEAR + + mov di,drive_Hdr_Ptr ; DI-->Drive Header ;AN000; + cmp es:[di].free_size,0 ; any free area left ?? ;AN000; + je Free_Chk_Close_List ; none, check CLOSE queue ;AN000; + + mov si,es:[di].Free_Ptr ; check for discontinuous ;AN000; + mov ax, -2 ;AN000; + cmp es:[si], ax ; discontinuous free buffer?? ;AN000; + je Free_Set_One ; yes, set flag for discontinuous + + mov Free_Flag,0 ; no, clear flag ;AN000; + clc ;AN000; + jmp Free_Exit + +Free_Set_one: + mov Free_Flag,1 ; set flag ;AN000; + clc ;AN000; + jmp Free_exit ; yes, Free space is available ;AN000; + ; exit + + +;-------------------------------------------------------------------------- +; No free space , look for space in CLOSE Queue. Search for the LRU header +; delete the header and any extents under this header. +;-------------------------------------------------------------------------- +Free_Chk_Close_List: + mov si,es:[di].CLOSE_Ptr ; SI-->CLOSE queue ;AN000; + cmp si,-1 ; anything in CLOSE Queue ?? ;AN000; + jne Free_Chk_CLOSE_QUE ; yes - get space from CLOSE queue + jmp short Free_Look_Open_Queue ; if none, make space from OPEN Queue ;AN000; + + +; Else get space from CLOSE queue +Free_Chk_Close_QUE: ; SI-->CLOSE queue + mov si,es:[di].CLOSE_Ptr ; select OPEN Queue ;AN000; + CALL FIND_LRU_HEADER ; find LRU header in CLOSE Queue ;AN000; + ; DI-->LRU header + +; Makesure to save all local variables before calling DELETE +; since, this variables may be altered by DELETE routine. + mov ax,Hdr_Flag + push ax + mov ax,Prev_Hdr_Ptr + push ax + mov ax,Queue_Type + push ax + mov ax,Cur_Hdr_Ptr + push ax + mov ax,First_Phys_Clusnum ; save original first phys from OPEN call + push ax ; in the stack + mov cx,es:[di].FH_Phys_Clus_Num ; CX= starting phys clus num of LRU header + mov From_FreeBuff,1 ; set flag + + push ds + mov ax,Cseg_Main + mov ds,ax + assume ds:Cseg_Main + CALL VECTOR_DELETE ; delete the file + pop ds + assume ds:Cseg_Seek + + mov From_FreeBuff,0 ; clear flag + mov Free_Flag,1 ; set flag to indicate discontinuous free area + pop ax ; restore first phys clus + mov First_Phys_Clusnum,ax ; save it back where it belongs + pop ax ; restore current header + mov Cur_Hdr_Ptr,ax ; save it back where it belongs + pop ax ; restore current header + mov Queue_Type,ax ; save it back where it belongs + pop ax ; restore current header + mov Prev_Hdr_Ptr,ax ; save it back where it belongs + pop ax ; restore current header + mov Hdr_Flag,ax ; save it back where it belongs + clc + jmp Free_exit ; exit ;AN000; + + + +;---------------------------------------------------------------------------- +; No space available in CLOSE Queue . Now get some free space from OPEN Queue +; and add it to the free area. +;---------------------------------------------------------------------------- +Free_Look_Open_Queue: + mov si,es:[di].MRU_Hdr_Ptr ; SI-->First header in OPEN Queue ;AN000; + CALL FIND_LRU_HEADER ; find last header in Queue ;AN000; + ; DI-->last header + mov si,es:[di].FH_MRU_Extn_Ptr ;### SI-->first extent in this header ;AN000; + cmp si, -1 ; any extent under this header ?? ;AN000; + jne Free_Open_Find_Extent ; yes, find last extent ;AN000; + +; if no extents under this header, delete this header and free the space + cmp di,Cur_Hdr_Ptr ; header found is its own header ?? ;AN000; + jne Free_OPen_Mark_Prev ; no - free the header ;AN000; + stc ; Yes - set carry, exit ;AN000; + jmp Free_Exit ; ERROR exit ;AN000; + +Free_Open_Mark_Prev: ; mark previous header as LRU before deleting this header + mov si,LRU_Prev_Hdr ; SI-->previous header ;AN000; + mov es:[si].FH_Next_Hdr_Ptr, -1 ; mark previous header as last hdr ;AN000; + jmp Free_Open_Cl_Buffer ;AN000; + +Free_Open_Find_Extent: + mov si,di ; SI-->header to be searched + CALL FIND_LRU_EXTENT ; ### find last extent in the header ;AN000; + mov di, LRU_Extent ; DI-->LRU extent + cmp Extn_flag,1 ; Is this the only extent in the queue ? ;AN000; + jne free_Open_prev_extn ; no, mark previous extent as last extn ;AN000; + push di ; save pointer to Last extent ;AN000; + mov di,LRU_Hdr ; DI-->LRU header ;AN000; + mov es:[di].FH_Next_Extn_Ptr,-1 ; mark current HEADER with no extents ;AN000; + mov es:[di].FH_MRU_Extn_Ptr,-1 ; ### mark current HEADER with no extents ;AN000; + pop di ; DI-->LRU extent ;AN000; + jmp Free_Open_Cl_Buffer ; release this extent ;AN000; + +;---------------------------------------------------------------------- +; Mark Previous MRU extent as LRU extent and also connect the previous +; adjucent extent to the next adjcent extent. +;---------------------------------------------------------------------- +Free_Open_Prev_Extn: ; mark previous MRU extent as LRU extnt + mov si, es:[di].EH_Prev_LRU_Ptr ; no - SI-->Previous adj extent + mov es:[si].EH_Next_LRU_Ptr, -1 ;mark previous extent as last extent ;AN000; + + cmp es:[di].EH_Next_Extn_Ptr, -1 ; any next adjucent extent ?? + jne OPen_Join_extents ; yes - join previous to next + + mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent + cmp si, -1 ; any previous adj extent ?? + je Open_Prev_Hdrx ; no - previous is a header + mov es:[si].EH_Next_Extn_Ptr, -1 ; mark previous extent as the last + jmp short Free_Open_Cl_Buffer ; free the current extent + +Open_Prev_Hdrx: + push di ; DI-->extent to be deleted + mov di,LRU_Hdr ; DI-->LRU header + mov es:[di].FH_Next_Extn_Ptr, -1 ; mark header with no extents + mov es:[di].FH_MRU_Extn_Ptr, -1 ; mark header with no extents + pop di + jmp short Free_Open_Cl_Buffer ; free current extent + +Open_Join_Extents: ; DI-->current extent to be freed + mov si, es:[di].EH_Prev_Extn_Ptr ; no - SI-->Previous adj extent + cmp si, -1 ; any previous extent ?? + je Open_Prev_Hdry ; no - previous is a header - join header + ; to extent + mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent + mov es:[si].EH_Next_Extn_Ptr,ax ; connect prev adj extent to next adj extent + push di ; save addrs of extent to be deleted + mov di, ax ; SI = address of previous LRU extent + mov es:[di].EH_Prev_Extn_Ptr,si ; address of next LRU extent + pop di ; restore address + jmp short Free_Open_Cl_Buffer ; free the extent + +Open_Prev_Hdry: + mov si, LRU_Hdr ; SI-->LRU_Hdr + mov ax, es:[di].EH_Next_Extn_Ptr ; AX = address of next adjucent extent + mov es:[si].FH_Next_Extn_Ptr,ax ; connect hdr to next adj extent + mov si,ax ; SI = addrss of next adj extent + mov es:[si].EH_Prev_Extn_Ptr,-1 ; mark no previous extent + mov di,LRU_Extent ; DI-->extent to be deleted + +;---------------------------------------------------------------------------- +; Free the current Extent or Header +;---------------------------------------------------------------------------- +Free_Open_Cl_Buffer: ; + mov si,di ; SI-->LRU extent or header ;AN000; + mov di,Drive_Hdr_Ptr ; DI-->drive buffer ;AN000; + mov ax,es:[di].Free_Ptr ;AN000; + mov es:[si].EH_Next_Extn_Ptr,ax ; connect Free ptr to last ;AN000; + ; extent in the queue + mov ax, -2 ; discontinuous mark (-2) ;AN000; + mov es:[si], ax ; mark freed area as discontinuous ;AN000; + mov es:[di].Free_Ptr,si ; connect header or extent to free area ;AN000; + +; Increase the Free_Size entry in Drive Header + mov ax, Size File_Header ; size is same for both header or extent ;AN000; + add es:[di].Free_Size, ax ; update free buffer count ;AN000; + mov Free_Flag,1 ; set flag for discontinuous free area ;AN000; + clc +Free_Exit: ; exit + ret ; return ;AN000; + +FIND_FREE_BUFFER endp + + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: Make_MRU_Header +; +; FUNCTION: Move header to the top of the queue. If the header is at the +; bottom of the queue, mark previous header as LRU header +; before moving the header to the top of the queue. +; +; INPUT: Drive_Hdr_Ptr - Points to drive header +; Cur_Hdr_Ptr - Points to current header +; ES--> Cache Buffer Segment +; +; OUTPUT: Header is moved to top of the current queue +; SI-->current header +; +;---------------------------------------------------------------------- + +MAKE_MRU_HEADER PROC NEAR + + mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; + cmp es:[si].FH_Next_Hdr_Ptr,-1 ; current header LRU header ;AN000; + jne Move_close_gap ; no, jump ;AN000; + ;AN000; + mov di,Prev_Hdr_Ptr ; yes, make previous header + mov es:[di].FH_Next_Hdr_Ptr,-1 ; LRU header ;AN000; + jmp short move_to_top + +Move_Close_Gap: + mov di,Prev_Hdr_Ptr ; yes, get previous header + mov ax,es:[si].FH_Next_Hdr_Ptr ; get next header address + mov es:[di].FH_Next_Hdr_Ptr,ax ; connect previous hdr to next hdr + ;AN000; +Move_To_Top: + mov di,drive_Hdr_Ptr ; DI-->drive buffer ;AN000; + mov ax,es:[di].MRU_Hdr_Ptr ; connect current header to ;AN000; + mov es:[si].FH_Next_Hdr_Ptr,ax ; previous MRU header ;AN000; + mov es:[di].MRU_Hdr_Ptr,si ; make current header MRU hdr ;AN000; + ; + ret + +Make_MRU_Header ENDP + + + + + + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; PROCEDURE: MAKE_MRU_EXTENT +; +; FUNCTION: Move Extent to the top of the queue. If the extent is at the +; bottom of the queue, mark previous extent as LRU extent +; before moving the extent to the top of the queue. If the extent +; is between first and last, then close the MRU-LRU chain gap. +; If the extent is already MRU then exit. +; +; This routine is called if clusters are inserted or looked up +; from an existing extent. +; +; INPUT: Cur_Hdr_Ptr - Address of current header +; Cur_Extn_Ptr - Address of current extent +; ES--> Cache Buffer Segment +; +; OUTPUT: Extent is moved next to the current header +; SI-->current extent +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +MAKE_MRU_EXTENT PROC NEAR + + mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; + mov ax,Cur_Extn_Ptr + cmp es:[si].FH_MRU_Extn_Ptr, ax ; current extent already MRU?? ;AN000; + je Make_MRU_Exit ; yes - exit + + mov si, Cur_Extn_Ptr ; SI-->Current extent + mov di,es:[si].EH_Prev_LRU_Ptr ; get address of previous MRU extent + cmp di, -1 ; any previous MRU extent ?? + je Make_MRU_Exit ; none - exit- current extent is already MRU + +; Close the gap (connect previous to next extent) + mov si, Cur_Extn_Ptr + cmp es:[si].EH_Next_LRU_Ptr, -1 ; current extent LRU extent ?? + jne join_the_gap ; no - close the gap + mov es:[di].EH_Next_LRU_Ptr, -1 ; mark the previous extent MRU + jmp short move_MRU_Extent ; make mru extent + +Join_The_Gap: + mov ax, es:[si].EH_Next_LRU_Ptr ; AX-->next LRU extent + mov es:[di].EH_Next_LRU_Ptr,ax ; connect previous to next + mov bx,di ; BX-->prev LRU extent + mov di,ax ; DI-->Next LRU extent + mov es:[di].EH_Prev_LRU_Ptr, bx ; set previous LRU extent address + + +; Make the current extent MRU extent +Move_MRU_Extent: + mov di,Cur_Hdr_Ptr ; DI-->Current header + mov ax,es:[di].FH_MRU_Extn_Ptr ; AX-->Previous MRU extent + mov es:[si].EH_NEXT_LRU_Ptr,ax ; connect previous to current extent + mov es:[di].FH_MRU_Extn_Ptr,si ; make current extent MRU extent + mov es:[si].EH_Prev_LRU_Ptr, -1 ; mark no previous LRU extent + + mov di,ax ;(12/29) set prev LRU addrs of prev MRU extent + mov es:[di].EH_Prev_LRU_Ptr,si ;(12/29) + +Make_MRU_Exit: + clc + ret ; return + +MAKE_MRU_EXTENT ENDP + + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: JOIN_PREV_TO_NEXT +; +; FUNCTION: Connect previous header to next header inorder to close the +; gap created when a header is moved to top of the Queue or to +; the top of CLOSE queue. If the file header is the first header +; under the current Drive header, connect header to the MRU_Hdr_Ptr. +; +; INPUT: Prev_Hdr_Ptr - Points to Previous header +; Cur_Hdr_Ptr - Points to Current Header +; Queue_Type - Queue Type: 0 = Open Queue +; 1 = Close Queue +; ES--> Cache Buffer Segment +; OUTPUT: Gap is closed +; +;---------------------------------------------------------------------- + +JOIN_PREV_TO_NEXT PROC + + cmp Prev_Hdr_Ptr, -1 ; current hdr first file header ?? ;AN000; + jne join_prev_hdr ; no, close gap ;AN000; + +; Yes, in this case close gap by connecting Drive header to next header + mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; + mov si,Cur_Hdr_Ptr ; SI-->Current header ;AN000; + mov ax,es:[si].FH_Next_Hdr_Ptr ; AX-->Next Header ;AN000; + cmp Queue_Type, 1 ; Is this Close Queue ?? ;AN000; + je Join_Sel_Close_Ptr ; Yes, jump ;AN000; + mov es:[di].MRU_Hdr_Ptr,ax ; join next header to Drive Header ;AN000; + jmp short join_exit ; exit ;AN000; + +Join_Sel_Close_Ptr: + mov es:[di].Close_Ptr,ax ; join next header to Drive Header ;AN000; + jmp short join_exit ; exit ;AN000; + + +; Connect previous header to next header ( close the gap ) +Join_Prev_Hdr: + mov di,Prev_Hdr_Ptr ; DI-->Previous header ;AN000; + mov si,Cur_Hdr_Ptr ; SI-->Current Header ;AN000; + mov ax,es:[si].FH_Next_Hdr_Ptr ; connect previous header ;AN000; + mov es:[di].FH_Next_Hdr_Ptr,ax ; to next header ;AN000; + +Join_Exit: + ret ; exit ;AN000; + +JOIN_PREV_TO_NEXT ENDP + + + + + + +;---------------------------------------------------------------------- +; PROCEDURE: UPDATE_FREE_AREA +; +; FUNCTION: Update Free area pointer and Free area size before creating +; a new extent or new header +; +; INPUT: Prev_Hdr_Ptr - Points to Previous header +; Cur_Hdr_Ptr - Points to Current Header +; Queue_Type - Queue Type: 0 = Open Queue +; 1 = Close Queue +; Free_Flag - Free area type: 0 = continous free area +; 1 = non-contiguous free area +; ES--> Cache Buffer Segment +; +; +; OUTPUT: Free pool address and size is updated +; +;---------------------------------------------------------------------- + +UPDATE_FREE_AREA PROC + + mov di,Drive_Hdr_Ptr ; DI-->drive header ;AN000; + mov si,es:[di].Free_Ptr ; SI-->current free pointerted ;AN000; + ; + mov ax, Size Extent_Header ;AN000; + sub es:[di].Free_Size, ax ; update free area size ;AN000; + + cmp Free_Flag, 1 ; continuous free area ?? ;AN000; + jne ext_add_free_ptr ; yes - update free area pointer ;AN000; + +;---------------------------------------------------------------------- +; If discontinuous Free area. Update the Free pointer by getting pointer +; to next free from the 4th word using header or extent structure. +; This is because the discontinuous areas are connected chained through +; the 4th word +;---------------------------------------------------------------------- + mov ax,es:[si].FH_Next_Hdr_Ptr ; no, update FREE area pointer ;AN000; + mov es:[di].Free_Ptr,ax ; using the Header structure ;AN000; + jmp short Update_Free_Exit ; Exit ;AN000; + +;---------------------------------------------------------------------- +; If continuous Free area. Next free area address is computed by adding +; the size of extent of header structure. +;---------------------------------------------------------------------- +Ext_Add_Free_Ptr: + mov ax, size File_Header ; calculate the address of ;AN000; + add es:[di].Free_Ptr,ax ; next free area by adding size of ;AN000; + ; a extent or header. Both same size +Update_Free_Exit: + ret ; exit ;AN000; + +UPDATE_FREE_AREA ENDP + + + + +;---------------------------------------------------------------------- +; Procedure: CHECK_IT Checks the validity of the queues +; +;---------------------------------------------------------------------- + +CHECK_IT PROC NEAR + + pushf ; save all registers + push bx + push di + cmp check_flag,0 + je check_exit + mov ah,090h + xor al,al + xor cx,cx + mov cl,func_cod + mov di, Drive_Hdr_Ptr + INT 2FH +check_exit: + pop di + pop bx + popf + ret + +CHECK_IT ENDP + + + +; Calculate the size of the Cseg_Seek module in bytes + IF ($-Cseg_Seek) MOD 16 ;AN000; + ORG ($-Cseg_Seek)+16-(($-Cseg_Seek) MOD 16) ;AN000; + ENDIF ;AN000; +END_SEEK label word + + +CSEG_SEEK ENDS + END diff --git a/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC b/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC new file mode 100644 index 0000000..fd6c46d --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTSEGS.INC @@ -0,0 +1,20 @@ + + + +.seq +stack segment Stack 'STACK' ; represents STACK ;AN000; +stack ends ;AN000; + +cseg_main segment Public 'CODE'; represents MAIN +cseg_main ends + +cseg_open segment Public 'CODE'; represents FASTOPEN ;AN000; +cseg_open ends ;AN000; + +cseg_seek segment Public 'CODE'; represents FASTSEEK ;AN000; +cseg_seek ends ;AN000; + +cseg_init segment Public 'CODE' ; represents INIT +cseg_init ends + + \ No newline at end of file diff --git a/v4.0/src/CMD/FASTOPEN/FASTSM.ASM b/v4.0/src/CMD/FASTOPEN/FASTSM.ASM new file mode 100644 index 0000000..b2dad14 --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/FASTSM.ASM @@ -0,0 +1,145 @@ + PAGE 90,132 ;A2 + TITLE fastsm.SAL - fastopen SYSTEM MESSAGES +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: fastsm.SAL + +; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT +; configuration expected by the modules of fastopen. + +;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a +; part of the fastopen module by using INCLUDE to bring in the +; common portion, in SYSMSG.INC. This included code contains +; the routines to initialize for message services, to find +; where a particular message is, and to display a message. + +; ENTRY POINT: SYSDISPMSG:near +; SYSGETMSG:near +; SYSLOADMSG:near + +; INPUT: +; AX = MESSAGE NUMBER +; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12) +; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE +; CX = NUMBER OF %PARMS, 0 IF NONE +; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW +; CALL SYSDISPMSG ;DISPLAY THE MESSAGE + +; If carry set, extended error already called: +; AX = EXTENDED MESSAGE NUMBER +; BH = ERROR CLASS +; BL = SUGGESTED ACTION +; CH = LOCUS +; _ _ _ _ _ _ _ _ _ _ _ _ + +; AX = MESSAGE NUMBER +; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG) +; CALL SYSGETMSG ;FIND WHERE A MSG IS + +; If carry set, error +; CX = 0, MESSAGE NOT FOUND +; If carry not set, ok, and resulting regs are: +; CX = MESSAGE SIZE +; DS:SI = MESSAGE TEXT +; _ _ _ _ _ _ _ _ _ _ _ _ + +; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION +; If carry not set: +; CX = SIZE OF MSGS LOADED + +; If carry is set, regs preset up for SYSDISPMSG, as: +; AX = ERROR CODE IF CARRY SET +; AX = 1, INCORRECT DOS VERSION +; DH =-1, (Utility msg) +; OR, +; AX = 1, Error loading messages +; DH = 0, (Message manager error) +; BX = STDERR +; CX = NO_REPLACE +; DL = NO_INPUT + +; EXIT-NORMAL: CARRY is not set + +; EXIT-ERROR: CARRY is set +; Call Get Extended Error for reason code, for SYSDISPMSG and +; SYSGETMSG. + +; INTERNAL REFERENCES: +; ROUTINES: (Generated by the MSG_SERVICES macro) +; SYSLOADMSG +; SYSDISPMSG +; SYSGETMSG + +; DATA AREAS: + +; INCLUDE SYSMSG.INC ;Permit System Message handler definition +; +; EXTERNAL REFERENCES: +; ROUTINES: none + +; DATA AREAS: control blocks pointed to by input registers. + +; NOTES: + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; fastopen.asm. + +; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, +; +; COPYRIGHT: "MS DOS FASTOPEN Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft " +; "Licensed Material - Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ; ;AN000; + %OUT COMPONENT=fastopen, MODULE=fastsm.asm... + ENDIF ; ;AN000; +; = = = = = = = = = = = = + +HEADER MACRO TEXT ;; ;AN000; +.XLIST ;; + SUBTTL TEXT +.LIST ;; + PAGE ;; ;AN000; + ENDM ;; ;AN000; +; = = = = = = = = = = = = + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; +CSEG_INIT SEGMENT PARA PUBLIC 'CODE' ; + ASSUME CS:CSEG_INIT ;ESTABLISHED BY CALLER + ASSUME DS:CSEG_INIT ;ESTABLISHED BY CALLER + ASSUME ES:CSEG_INIT ;ESTABLISHED BY CALLER + + PUBLIC COPYRIGHT ; ;AN000; +COPYRIGHT DB "MS DOS FASTOPEN Utility " ; ;AN000; + INCLUDE COPYRIGH.INC ; ;AN000; + HEADER ; ;AN000; + MSG_SERVICES ;WORKAREAS FOR SYSTEM MESSAGE HANDLER ;AN000; +; = = = = = = = = = = = = + HEADER ; ;AN000; + PUBLIC SYSLOADMSG ; ;AN000; + PUBLIC SYSDISPMSG ; ;AN000; + + + MSG_SERVICES ; + + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg + +.xlist +.xcref + MSG_SERVICES ;AN000; + include msgdcl.inc +.cref +.list +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +CSEG_INIT ENDS ; + END ; ;AN000; diff --git a/v4.0/src/CMD/FASTOPEN/MAKEFILE b/v4.0/src/CMD/FASTOPEN/MAKEFILE new file mode 100644 index 0000000..8911afe --- /dev/null +++ b/v4.0/src/CMD/FASTOPEN/MAKEFILE @@ -0,0 +1,47 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: fastopen.exe + +fastopen.ctl: fastopen.skl makefile $(msg)\$(COUNTRY).msg + +fastopen.obj: fastopen.asm $(inc)\fastopen.inc \ + makefile + +fastseek.obj: fastseek.asm $(inc)\fastopen.inc \ + makefile + +fastinit.obj: fastinit.asm $(inc)\dossym.inc $(inc)\fastopen.inc \ + makefile + +fastp.obj: fastp.asm \ + makefile \ + $(inc)\psdata.inc \ + $(inc)\parse.asm + +fastsm.obj: fastsm.asm \ + makefile \ + $(inc)\versiona.inc \ + $(inc)\copyrigh.inc \ + $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm \ + fastopen.ctl \ + fastopen.cl1 \ + fastopen.cl2 \ + fastopen.cla \ + +fastopen.exe: fastopen.obj \ + fastopen.lnk \ + fastseek.obj \ + fastinit.obj \ + fastp.obj \ + fastsm.obj + link @fastopen.lnk diff --git a/v4.0/src/CMD/FC/ERROR.C b/v4.0/src/CMD/FC/ERROR.C new file mode 100644 index 0000000..47bc02d --- /dev/null +++ b/v4.0/src/CMD/FC/ERROR.C @@ -0,0 +1,16 @@ +/* error.c - return text of error corresponding to the most recent DOS error */ + +#include "tools.h" + +extern int errno; +extern sys_nerr; +extern char *sys_errlist[]; +extern char UnKnown[]; + +char *error () +{ + if (errno < 0 || errno >= sys_nerr) + return UnKnown; + else + return sys_errlist[errno]; +} diff --git a/v4.0/src/CMD/FC/FC.C b/v4.0/src/CMD/FC/FC.C new file mode 100644 index 0000000..d1dc0f6 --- /dev/null +++ b/v4.0/src/CMD/FC/FC.C @@ -0,0 +1,864 @@ +/* file compare + + Fcom compares two files in either a line-by-line mode or in a strict + byte-by-byte mode. + + The byte-by-byte mode is simple; merely read both files and print the + offsets where they differ and the contents. + + The line compare mode attempts to isolate differences in ranges of lines. + Two buffers of lines are read and compared. No hashing of lines needs + to be done; hashing only speedily tells you when things are different, + not the same. Most files run through this are expected to be largely + the same. Thus, hashing buys nothing. + + +*********************************************************************** +The algorithm that immediately follows does not work. There is an error +somewhere in the range of lines 11 on. An alternative explanation follows. + KGS +************************************************************************ + + [0] Fill buffers + [1] If both buffers are empty then + [1.1] Done + [2] Adjust buffers so 1st differing lines are at top. + [3] If buffers are empty then + [3.1] Goto [0] + + This is the difficult part. We assume that there is a sequence of inserts, + deletes and replacements that will bring the buffers back into alignment. + + [4] xd = yd = FALSE + [5] xc = yc = 1 + [6] xp = yp = 1 + [7] If buffer1[xc] and buffer2[yp] begin a "sync" range then + [7.1] Output lines 1 through xc-1 in buffer 1 + [7.2] Output lines 1 through yp-1 in buffer 2 + [7.3] Adjust buffer 1 so line xc is at beginning + [7.4] Adjust buffer 2 so line yp is at beginning + [7.5] Goto [0] + [8] If buffer1[xp] and buffer2[yc] begin a "sync" range then + [8.1] Output lines 1 through xp-1 in buffer 1 + [8.2] Output lines 1 through yc-1 in buffer 2 + [8.3] Adjust buffer 1 so line xp is at beginning + [8.4] Adjust buffer 2 so line yc is at beginning + [8.5] Goto [0] + [9] xp = xp + 1 + [10] if xp > xc then + [10.1] xp = 1 + [10.2] xc = xc + 1 + [10.3] if xc > number of lines in buffer 1 then + [10.4] xc = number of lines + [10.5] xd = TRUE + [11] if yp > yc then + [11.1] yp = 1 + [11.2] yc = yc + 1 + [11.3] if yc > number of lines in buffer 2 then + [11.4] yc = number of lines + [11.5] yd = TRUE + [12] if not xd or not yd then + [12.1] goto [6] + + At this point there is no possible match between the buffers. For + simplicity, we punt. + + [13] Display error message. + +EXPLANATION 2 + + This is a variation of the Largest Common Subsequence problem. A + detailed explanation of this can be found on p 189 of Data Structures + and Algorithms by Aho Hopcroft and Ulman. + + + + FC maintains two buffers within which it tries to find the Largest Common + Subsequence (The largest common subsequence is simply the pattern in + buffer1 that yields the most matches with the pattern in buffer2, or the + pattern in buffer2 that yields the most matches with the pattern in buffer1) + + FC makes a simplifying assumption that the contents of one buffer can be + converted to the contents of the other buffer by deleting the lines that are + different between the two buffers. + + Two indices into each buffer are maintained: + + xc, yc == point to the last line that has been scanned up to now + + xp, yp == point to the first line that has not been exhaustively + compared to lines 0 - #c in the other buffer. + + FC now makes a second simplifying assumption: + It is unnecessary to do any calculations on lines that are equal. + + Hence FC scans File1 and File two line by line until a difference is + encountered. + + + When a difference is encountered the two buffers are filled such that + the line containing the first difference heads the buffer. The following + exhaustive search algorithm is applied to find the first "sync" occurance. + (The below is simplified to use == for comparison. In practice more than + one line needs to match for a "sync" to be established). + + + FOR xc,yc = 1; xc,yx <= sizeof( BUFFERS ); xc++, yc++ + + FOR xp,yp = 1; xp,yp <= xc,yc; xp++, yp++ + + IF ( BUFFER1[xp] == BUFFER2[yc] ) + + Then the range of lines BUFFER1[ 1 ... xp ] and + BUFFER2[ 1 ... yc ] need to be deleted for the + two files to be equal. Therefore DISPLAY these + ranges, and begin scanning both files starting at + the matching lines. + FI + + IF ( BUFFER1[yp] == BUFFER2[xc] ) + + Then the range of lines BUFFER2[ 1 ... yp ] and + BUFFER1[ 1 ... xc ] need to be deleted for the + two files to be equal. Therefore DISPLAY these + ranges, and begin scanning both files starting at + the matching lines. + FI + FOREND + FOREND + + If a match is not found within the buffers, the message "RESYNC FAILED" + is issued and further comparison is aborted since there is no valid way + to find further matching lines. + + + + +END EXPLANATION 2 + + + + + + Certain flags may be set to modify the behavior of the comparison: + + -a abbreviated output. Rather than displaying all of the modified + ranges, just display the beginning, ... and the ending difference + -b compare the files in binary (or byte-by-byte) mode. This mode is + default on .EXE, .OBJ, .LIB, .COM, .BIN, and .SYS files + -c ignore case on compare (cmp = strcmpi instead of strcmp) + -l compare files in line-by-line mode + -lb n set the size of the internal line buffer to n lines from default + of 100 + -w ignore blank lines and white space (ignore len 0, use strcmps) + -t do not untabify (use fgets instead of fgetl) + -n output the line number also + -NNNN set the number of lines to resynchronize to n which defaults + to 2. Failure to have this value set correctly can result in + odd output: + file1: file2: + abcdefg abcdefg + aaaaaaa aaaaaab + aaaaaaa aaaaaaa + aaaaaaa aaaaaaa + abcdefg abcdefg + + with default sync of 2 yields: with sync => 3 yields: + + *****f1 *****f1 + abcdefg abcdefg + aaaaaaa aaaaaaa + *****f2 aaaaaaa + abcdefg *****f2 + aaaaaab abcdefg + aaaaaaa aaaaaab + aaaaaaa + *****f1 + aaaaaaa + aaaaaaa + abcdefg + *****f2 + aaaaaaa + abcdefg + + + + + + +WARNING: + This program makes use of GOTO's and hence is not as straightforward + as it could be! CAVEAT PROGRAMMER. + + + + + + + + + + + + + + + + */ + + +#include "tools.h" +#include "fc.h" + +/* #define DEBUG FALSE */ + +extern int fgetl(), + strcmp (); + +extern byte toupper (); + +int (*funcRead) (), /* function to use to read lines */ + (*fCmp) (); /* function to use to compare lines */ + +extern byte BadSw[], + Bad_ver[], + BadOpn[], + LngFil[], + NoDif[], + NoMem[], + UseMes[], + ReSyncMes[]; + +int ctSync = -1, /* number of lines required to sync */ + cLine = -1; /* number of lines in internal buffs */ + +flagType fAbbrev = FALSE, /* abbreviated output */ + fBinary = FALSE, /* binary comparison */ + fLine = FALSE, /* line comparison */ + fNumb = FALSE, /* display line numbers */ + fCase = TRUE, /* case is significant */ + fIgnore = FALSE; /* ignore spaces and blank lines */ + +#ifdef DEBUG + +flagType fDebug = FALSE; +#endif + +struct lineType *buffer1, + *buffer2; + +byte line[MAXARG]; /* single line buffer */ + +byte *extBin[] = { ".EXE", ".OBJ", ".LIB", + ".COM", ".BIN", ".SYS", NULL }; + + +main (c, v) +int c; +byte *v[]; +{ + + int i; + int j; + int fileargs; + char *strpbrk(), + *slash; + char n[2][80]; + char temp; + + + + extern byte _osmajor, _osminor; + word version; /* _osmajor._osminor, used for */ + /* version binding checks. */ + + + + /* Issue error message if DOS version is not within valid range. */ + version = ((word)_osmajor << 8) + (word)_osminor; + if (( LOWVERSION > version) || (version > HIGHVERSION)) + { + usage (Bad_ver, 1); + } + + funcRead = (int (*) ())FNADDR(fgetl); + + fileargs=0; + + for (i=1; i < c ; i++) + { +/** + * If argument doesn't begin with a /, parse a filename off of it + * then examine the argument for following switches. + * +**/ + if (*v[i] != '/') + { + slash= strpbrk( v[i],"/" ); + + if ( slash ) + { + temp = *slash; + *slash='\0' ; + strcpy(n[fileargs++],v[i]); + *slash =temp ; + } + else + strcpy(n[fileargs++],v[i]); + } + + for ( j=0 ; j < strlen( v[i] ) ; j++) + { + if(*(v[i]+j)=='/') + { + switch(toupper( *(v[i]+j+1))) + { + case 'A' : + fAbbrev = TRUE; + break; + case 'B' : + fBinary = TRUE; + break; + case 'C' : + fCase = FALSE; + break; +#ifdef DEBUG + case 'D' : + fDebug = TRUE; + break; +#endif + case 'W' : + fIgnore = TRUE; + break; + case 'L' : + if (toupper(*(v[i]+j+2))=='B') + { + cLine = ntoi ((v[i]+j+3),10); + break; + } + else + fLine = TRUE; + break; + case 'N' : + fNumb = TRUE; + break; + case 'T' : + funcRead =(int (*) ())FNADDR(fgets); + break; + default: + if (*strbskip((v[i]+j+1),"0123456789") == 0) + { + ctSync = ntoi ((v[i]+j+1), 10); + } + else + { + usage (NULL, 1); + } + } /* end switch */ + } /* end if */ + } /* end parse of argument for '/' */ + } /* End ARGUMENT Search */ + + + + if (fileargs != 2) + usage (NULL, 1); + + if (ctSync != -1) + fLine = TRUE; + else + ctSync = 2; + + if (cLine == -1) + cLine = 100; + + if (!fBinary && !fLine) + { + extention (n[0], line); + + for (i = 0; extBin[i]; i++) + if (!strcmpi (extBin[i], line)) + fBinary = TRUE; + + if (!fBinary) + fLine = TRUE; + } + + if (fBinary && (fLine || fNumb)) + usage (BadSw, 1); + + if (fIgnore) + { + if (fCase) + fCmp = FNADDR(strcmps); + else + fCmp = FNADDR(strcmpis); + } + else + { + if (fCase) + fCmp = FNADDR(strcmp); + else + fCmp = FNADDR(strcmpi); + } + + if (fBinary) + BinaryCompare (n[0], n[1]); + else + LineCompare (n[0], n[1]); + +} + +usage (p, erc) +unsigned char *p; +{ + if (p) + printf ("fc: %s\n", p); + else + printf (UseMes); + + exit (erc); +} + +BinaryCompare (f1, f2) +unsigned char *f1, *f2; +{ + register int c1, c2; + long pos; + FILE *fh1, *fh2; + flagType fSame; + + fSame = TRUE; + + if ((fh1 = fopen (f1, "rb")) == NULL) + { + sprintf (line, BadOpn, f1, error ()); + usage (line, 1); + } + + if ((fh2 = fopen (f2, "rb")) == NULL) + { + sprintf (line, BadOpn, f2, error ()); + usage (line, 1); + } + pos = 0L; + + while (TRUE) + { + if ((c1 = getc (fh1)) != EOF) + { + if ((c2 = getc (fh2)) != EOF) + { + if (c1 == c2) + ; + else + { + fSame = FALSE; + printf ("%08lX: %02X %02X\n", pos, c1, c2); + } + } + else + { + sprintf (line, LngFil, f1, f2); + usage (line, 1); + } + } + else + { + if ((c2 = getc (fh2)) == EOF) + { + if (fSame) + usage (NoDif, 0); + else + exit (1); + } + else + { + sprintf (line, LngFil, f2, f1); + usage (line, 1); + } + } + pos++; + } +} + +/* compare a range of lines */ +flagType compare (l1, s1, l2, s2, ct) +int l1, l2, ct; +register int s1, s2; +{ + +#ifdef DEBUG + if (fDebug) + printf ("compare (%d, %d, %d, %d, %d)\n", l1, s1, l2, s2, ct); +#endif + + if (ct == 0 || s1+ct > l1 || s2+ct > l2) + return FALSE; + + while (ct--) + { + +#ifdef DEBUG + if (fDebug) + printf ("'%s' == '%s'? ", buffer1[s1].text, buffer2[s2].text); +#endif + + if ((*fCmp)(buffer1[s1++].text, buffer2[s2++].text)) + { + +#ifdef DEBUG + if (fDebug) + printf ("No\n"); +#endif + return FALSE; + } + } + +#ifdef DEBUG + if (fDebug) + printf ("Yes\n"); +#endif + + return TRUE; +} + +LineCompare (f1, f2) +unsigned char *f1, *f2; +{ + FILE *fh1, *fh2; + int l1, l2, i, xp, yp, xc, yc; + flagType xd, yd, fSame; + int line1, line2; + + fSame = TRUE; + + if ((fh1 = fopen (f1, "rb")) == NULL) + { + sprintf (line, BadOpn, f1, error ()); + usage (line, 1); + } + + if ((fh2 = fopen (f2, "rb")) == NULL) + { + sprintf (line, BadOpn, f2, error ()); + usage (line, 1); + } + + if ((buffer1 = (struct lineType *)malloc (cLine * (sizeof *buffer1))) == NULL || + (buffer2 = (struct lineType *)malloc (cLine * (sizeof *buffer1))) == NULL) + usage (NoMem); + + l1 = l2 = 0; + line1 = line2 = 0; +l0: + +#ifdef DEBUG + if (fDebug) + printf ("At scan beginning\n"); +#endif + + l1 += xfill (buffer1+l1, fh1, cLine-l1, &line1); + l2 += xfill (buffer2+l2, fh2, cLine-l2, &line2); + + if (l1 == 0 && l2 == 0) + { + if (fSame) + usage (NoDif, 0); + return; + } + xc = min (l1, l2); + + for (i=0; i < xc; i++) + { + if (!compare (l1, i, l2, i, 1)) + break; + } + + if (i != xc) + i = max (i-1, 0); + + l1 = adjust (buffer1, l1, i); + l2 = adjust (buffer2, l2, i); + + /* KLUDGE ALERT!! GOTO USED */ + if (l1 == 0 && l2 == 0) + goto l0; + + l1 += xfill (buffer1+l1, fh1, cLine-l1, &line1); + l2 += xfill (buffer2+l2, fh2, cLine-l2, &line2); + +#ifdef DEBUG + if (fDebug) + printf ("buffers are adjusted, %d, %d remain\n", l1, l2); +#endif + + xd = yd = FALSE; + xc = yc = 1; + xp = yp = 1; + +l6: + +#ifdef DEBUG + if (fDebug) + printf ("Trying resync %d,%d %d,%d\n", xc, xp, yc, yp); +#endif + + i = min (l1-xc,l2-yp); + i = min (i, ctSync); + + if (compare (l1, xc, l2, yp, i)) + { + fSame = FALSE; + printf ("***** %s\n", f1); + dump (buffer1, 0, xc); + printf ("***** %s\n", f2); + dump (buffer2, 0, yp); + printf ("*****\n\n"); + + l1 = adjust (buffer1, l1, xc); + l2 = adjust (buffer2, l2, yp); + + /* KLUDGE ALERT!! GOTO USED */ + goto l0; + } + i = min (l1-xp, l2-yc); + i = min (i, ctSync); + + if (compare (l1, xp, l2, yc, i)) + { + fSame = FALSE; + printf ("***** %s\n", f1); + dump (buffer1, 0, xp); + printf ("***** %s\n", f2); + dump (buffer2, 0, yc); + printf ("*****\n\n"); + + l1 = adjust (buffer1, l1, xp); + l2 = adjust (buffer2, l2, yc); + + /* KLUDGE ALERT!! GOTO USED */ + goto l0; + } + + if (++xp > xc) + { + xp = 1; + if (++xc >= l1) + { + xc = l1; + xd = TRUE; + } + } + + if (++yp > yc) + { + yp = 1; + if (++yc >= l2) + { + yc = l1; + yd = TRUE; + } + } + + if (!xd || !yd) + goto l6; + fSame = FALSE; + + if (l1 >= cLine || l2 >= cLine) + printf ("%s", ReSyncMes); + + printf ("***** %s\n", f1); + dump (buffer1, 0, l1-1); + printf ("***** %s\n", f2); + dump (buffer2, 0, l2-1); + printf ("*****\n\n"); + exit (1); +} + + + +/* return number of lines read in */ +xfill (pl, fh, ct, plnum) +struct lineType *pl; +FILE *fh; +int ct; +int *plnum; +{ + int i; + +#ifdef DEBUG + if (fDebug) + printf ("xfill (%04x, %04x)\n", pl, fh); +#endif + + i = 0; + while (ct-- && (*funcRead) (pl->text, MAXARG, fh) != NULL) + { + if (funcRead == (int (*) ())FNADDR(fgets)) + pl->text[strlen(pl->text)-1] = 0; + if (fIgnore && !strcmps (pl->text, "")) + pl->text[0] = 0; + if (strlen (pl->text) != 0 || !fIgnore) + { + pl->line = ++*plnum; + pl++; + i++; + } + } + +#ifdef DEBUG + if (fDebug) + printf ("xfill returns %d\n", i); +#endif + + return i; +} + + +/* adjust returns number of lines in buffer */ +adjust (pl, ml, lt) +struct lineType *pl; +int ml; +int lt; +{ + +#ifdef DEBUG + if (fDebug) + printf ("adjust (%04x, %d, %d) = ", pl, ml, lt); + if (fDebug) + printf ("%d\n", ml-lt); +#endif + + if (ml <= lt) + return 0; + +#ifdef DEBUG + if (fDebug) + printf ("move (%04x, %04x, %04x)\n", &pl[lt], &pl[0], sizeof (*pl)*(ml-lt)); +#endif + + Move ((unsigned char far *)&pl[lt], (char far *)&pl[0], sizeof (*pl)*(ml-lt)); + return ml-lt; +} + + +/* dump + * dump outputs a range of lines. + * + * INPUTS + * pl pointer to current lineType structure + * start starting line number + * end ending line number + * + * CALLS + * pline, printf + * + */ +dump (pl, start, end) +struct lineType *pl; +int start, end; +{ + if (fAbbrev && end-start > 2) + { + pline (pl+start); + printf ("...\n"); + pline (pl+end); + } + else + while (start <= end) + pline (pl+start++); +} + + + + +/* PrintLINE + * pline prints a single line of output. If the /n flag + * has been specified, the line number of the printed text is added. + * + * Inputs + * pl pointer to current lineType structure + * fNumb TRUE if /n specified + * + */ +pline (pl) +struct lineType *pl; +{ + if (fNumb) + printf ("%5d: ", pl->line); + + printf ("%s\n", pl->text); +} + +/* + * strcmpi will compare two string lexically and return one of + * the following: + * - 0 if the strings are equal + * - 1 if first > the second + * - (-1) if first < the second + * + * This was written to replace the run time library version of + * strcmpi which does not correctly compare the european character set. + * This version relies on a version of toupper which uses IToupper. + */ + +int strcmpi(str1, str2) +unsigned char *str1, *str2; +{ + unsigned char c1, c2; + + while ((c1 = toupper(*str1++)) == (c2 = toupper(*str2++))) { + if (c1 == '\0') + return(0); + } + + if (c1 > c2) + return(1); + else + return(-1); +} + + +/* compare two strings, ignoring white space, case is significant, return + * 0 if identical, <>0 otherwise + */ +strcmps (p1, p2) +unsigned char *p1, *p2; +{ + while (TRUE) { + while (ISSPACE(*p1)) + p1++; + while (ISSPACE(*p2)) + p2++; + if (*p1 == *p2) + if (*p1++ == 0) + return 0; + else + p2++; + else + return *p1-*p2; + } +} + + +/* compare two strings, ignoring white space, case is not significant, return + * 0 if identical, <>0 otherwise + */ +int strcmpis (p1, p2) +unsigned char *p1, *p2; +{ + while (TRUE) { + while (ISSPACE(*p1)) + p1++; + while (ISSPACE(*p2)) + p2++; + if (toupper (*p1) == toupper (*p2)) + if (*p1++ == 0) + return 0; + else + p2++; + else + return *p1-*p2; + } +} diff --git a/v4.0/src/CMD/FC/FC.H b/v4.0/src/CMD/FC/FC.H new file mode 100644 index 0000000..aa826c3 --- /dev/null +++ b/v4.0/src/CMD/FC/FC.H @@ -0,0 +1,14 @@ +struct lineType { + int line; /* line number */ + unsigned char text[MAXARG]; /* body of line */ +}; + +#define byte unsigned char +#define word unsigned short + +#define LOWVERSION 0x0300 + 10 +#define HIGHVERSION 0x0400 + 00 + +extern unsigned char _ctype_[]; +#define _SPACE 0x8 /* tab, carriage return, new line, */ +#define ISSPACE(c) ( (_ctype_+1)[c] & _SPACE ) diff --git a/v4.0/src/CMD/FC/FC.LNK b/v4.0/src/CMD/FC/FC.LNK new file mode 100644 index 0000000..89d9fff --- /dev/null +++ b/v4.0/src/CMD/FC/FC.LNK @@ -0,0 +1,4 @@ +fc.obj error.obj fgetl.obj getl.obj itoupper.obj ..\..\inc\kstring.obj + +maxmin.obj move.obj ntoi.obj string.obj update.obj xtab.obj messages.obj +fc.exe + diff --git a/v4.0/src/CMD/FC/FGETL.C b/v4.0/src/CMD/FC/FGETL.C new file mode 100644 index 0000000..a425b39 --- /dev/null +++ b/v4.0/src/CMD/FC/FGETL.C @@ -0,0 +1,52 @@ +/* fgetl.c - expand tabs and return lines w/o separators */ + +#include "tools.h" + +/* returns line from file (no CRLFs); returns NULL if EOF */ +fgetl (buf, len, fh) +char *buf; +int len; +FILE *fh; +{ + register int c; + register char *p; + + /* remember NUL at end */ + len--; + p = buf; + while (len) { + c = getc (fh); + if (c == EOF || c == '\n') + break; +#if MSDOS + if (c != '\r') +#endif + if (c != '\t') { + *p++ = c; + len--; + } + else { + c = min (8 - ((p-buf) & 0x0007), len); + Fill (p, ' ', c); + p += c; + len -= c; + } + } + *p = 0; + return ! ( (c == EOF) && (p == buf) ); +} + +/* writes a line to file (with trailing CRLFs) from buf, return <> 0 if + * writes fail + */ +fputl (buf, len, fh) +char *buf; +int len; +FILE *fh; +{ +#if MSDOS + return (fwrite (buf, 1, len, fh) != len || fputs ("\r\n", fh) == EOF) ? EOF : 0; +#else + return (fwrite (buf, 1, len, fh) != len || fputs ("\n", fh) == EOF) ? EOF : 0; +#endif +} diff --git a/v4.0/src/CMD/FC/GETL.ASM b/v4.0/src/CMD/FC/GETL.ASM new file mode 100644 index 0000000..508eca9 --- /dev/null +++ b/v4.0/src/CMD/FC/GETL.ASM @@ -0,0 +1,146 @@ +; +; blindingly fast assembly help for Z +; + +.xlist +include version.inc +include cmacros.inc +.list + +sBegin data +assumes ds,data + +bufstart dd ? +staticW bufsrc,? +staticW buflen,? +staticW buflength,? +staticW buffh,? +globalB fGetlCR,? +bufpos dd ? + +sEnd +sBegin code + +assumes cs,code + +; +; getlpos returns current seek position in file +; +cProc getlpos, +cBegin + mov dx,word ptr bufpos+2 + mov ax,word ptr bufpos +cEnd + +; +; getlinit (buf, len, fh) initializes the getl routine for buffer buf and fh fh +; +cProc getlinit, +parmD buf +parmW len +parmW fh +cBegin + mov ax,off_buf + mov word ptr bufstart,ax + mov ax,seg_buf + mov word ptr bufstart+2,ax + mov ax,fh + mov buffh,ax + mov ax,len + mov buflength,ax + mov buflen,0 + mov word ptr bufpos,0 + mov word ptr bufpos+2,0 + mov fGetlCR,0 +cEnd + +; +; getl (dst, len) returns TRUE if a line was read. +; +cProc getl,, +parmW dst +parmW dstlen +cBegin + assumes ss,data + cld + push ds + pop es + mov ds,word ptr bufstart+2 + assumes ds,nothing + mov si,bufsrc + mov di,dst + mov cx,buflen + mov dx,dstlen + dec dx ; room for NUL at end + jcxz fill + +movc: lodsb ; get a byte + cmp al,13 ; is it special? + jbe spec ; yes, go handle special case +stoc: stosb ; put character in buffer + dec dx ; one less space in buffer +endl: loopnz movc ; go back for more characters + jnz fill ; no more characters => go fill buffer + ; cx = 0, buflen = length moved +fin: dec cx +fin1: xor ax,ax + stosb + mov bufsrc,si ; length moved = buflen - cx + xchg buflen,cx + sub cx,buflen + add word ptr bufpos,cx + adc word ptr bufpos+2,0 + not ax + jmp short getldone + +fill: + mov cx, buflen ; add length moved to bufpos + add word ptr bufpos,cx + adc word ptr bufpos+2,0 + push dx + mov dx,word ptr bufstart + mov cx,buflength + mov bx,buffh + mov ah,3Fh + int 21h + mov cx,ax + mov buflen,ax + mov si,dx + pop dx + or ax,ax + jnz movc +; if we've stored chars then terminate line else return with 0 + cmp di,dst + jnz fin1 + jmp short getldone + +setnz: or al,1 + mov fGetlCR,-1 ; indicate we've seen a CR + jmp endl + +spec: jz setnz + cmp al,10 + jz fin + cmp al,9 + jnz stoc + push cx + mov ax,di + sub ax,dst + and ax,7 + mov cx,8 + sub cx,ax + cmp cx,dx + jbe ok + mov cx,dx +ok: sub dx,cx + mov al," " + rep stosb + pop cx + jmp endl + +getldone: +cEnd + +sEnd + +end diff --git a/v4.0/src/CMD/FC/INTERNAT.H b/v4.0/src/CMD/FC/INTERNAT.H new file mode 100644 index 0000000..0cd839c --- /dev/null +++ b/v4.0/src/CMD/FC/INTERNAT.H @@ -0,0 +1,30 @@ +/* + Data structure for international table + */ + +struct InterTbl +{ + unsigned dateform ; /* Date format */ + char currsym[5] ; /* Currency symbol as ASCIZ string */ + char thousp[2] ; /* Thousands separator as ASCIZ string */ + char decsp[2] ; /* Decimal separator as ASCIZ string */ + char datesp[2] ; /* Date separator as ASCIZ string */ + char timesp[2] ; /* Time separator as ASCIZ string */ + unsigned char bits ; /* Bit field */ + unsigned char numdig ; /* Number of signifigant decimal digits */ + unsigned char timeform ;/* Time format */ + unsigned long casecall ;/* Case mapping call */ + char datasp[2] ; /* Data list separator as ASCIZ string */ + int reserv[5] ; /* RESERVED */ +} ; + + +#define DATEFORM_USA 0 +#define DATEFORM_EUROPE 1 +#define DATEFORM_JAPAN 2 + +#define BITS_CURRENCY 0x0001 +#define BITS_NUMSPC 0x0002 + +#define TIMEFORM_12 0 +#define TIMEFORM_24 1 diff --git a/v4.0/src/CMD/FC/ITOUPPER.ASM b/v4.0/src/CMD/FC/ITOUPPER.ASM new file mode 100644 index 0000000..289c691 --- /dev/null +++ b/v4.0/src/CMD/FC/ITOUPPER.ASM @@ -0,0 +1,119 @@ +.xlist +include version.inc +include cmacros.inc +.list + +sBegin code +assumes cs,code + +; +; c = IToupper (c, routine); +; +; c is char to be converted +; routine is case map call in international table +; + +cProc IToupper, +parmW c +parmD routine +cBegin + mov ax,c + or ah,ah + jnz donothing + cmp al,'a' + jb noconv + cmp al,'z' + ja noconv + sub al,20H +noconv: + call routine +donothing: +cEnd + + +;Get_Lbtbl +; +; Get pointer to LBTBL from DOS if we are running on a version +; of DOS which supports it. If not, initialize the table with +; a pointer to a local "default" table with KANJI lead bytes. +; +;Input: word pointer to LONG "Lbtbl" +;Output: long initialized to Lead byte pointer +; + +cProc get_lbtbl, + +parmW pointer_to_table + +; on entry, low word of DWORD pointer has offset of +; a default table of lead bytes defined within the C program +; If function 63 is supported, the DWORD pointer to DOS' +; table will be placed here instead. +cBegin + push si + push di + mov bx,pointer_to_table ;get pointer + mov si,[bx] ;default table pointer in DS:SI + push es + push ds + mov ax,6300h ;make Get Lead Byte call + int 21h + mov ss:[bx],si ;si didn't change if non ECS dos + mov ss:[bx+2],ds ;store segment + pop ds + pop es + pop di + pop si +cEnd + + +; +; test_ECS(char,DWORD_prt) test the char to find out if it is +; a valid lead byte using passed DWORD +; Input: char PTR to the Lead Byte table. +; DWORD PTR to table +; Output: AX=FFFF (is_lead) Lead byte table may be default in +; AX=0 (not_lead) program or ECS table in DOS when +; running on a version which supports it. +; +cProc test_ECS, ;test for lead byte ;if Lead, then + ; return AX=Is_lead + ; else + ; return AX=FALSE +Is_lead EQU 0FFFFH +Not_lead EQU 0 + +parmW char +parmD pointer ;DWORD PTR to Lead Byte Table +cBegin + mov ax,char + xchg ah,al + push SI + push DS + LDS SI,pointer +ktlop: + lodsb + or al,al + jz notlead + cmp al,ah + ja notlead + lodsb + cmp ah,al + ja ktlop + mov ax,Is_lead +notl_exit: + pop ds + pop si + jmp cexit +notlead: + mov ax,not_lead + jmp notl_exit +cexit: +cEnd + + + + +sEnd + +end diff --git a/v4.0/src/CMD/FC/MAKEFILE b/v4.0/src/CMD/FC/MAKEFILE new file mode 100644 index 0000000..393a2bb --- /dev/null +++ b/v4.0/src/CMD/FC/MAKEFILE @@ -0,0 +1,64 @@ +#** makefile for fc + +DEST =fc +MSG =messages + +# Path Definitions + +BIOS =..\..\BIOS +BOOT =..\..\BOOT +dos =..\..\DOS +inc =..\..\INC +hinc =..\..\h +H =..\..\H + +# List of object files required + +OBJ = fc.obj \ + error.obj \ + fgetl.obj \ + getl.obj \ + itoupper.obj \ + $(inc)\kstring.obj \ + maxmin.obj \ + move.obj \ + ntoi.obj \ + string.obj \ + update.obj \ + xtab.obj \ + messages.obj + +# Rules and Dependencies follow + +all: $(DEST).exe + +$(inc)\printf.obj: $(inc)\printf.asm + +$(inc)\kstring.obj: $(inc)\kstring.c $(hinc)\internat.h + +getl.obj: getl.asm $(inc)\cmacros.inc $(inc)\version.inc + +itoupper.obj: itoupper.asm $(inc)\cmacros.inc $(inc)\version.inc + +maxmin.obj: maxmin.asm $(inc)\cmacros.inc $(inc)\version.inc + +$(MSG).obj: $(MSG).asm + +move.obj: move.asm $(inc)\cmacros.inc $(inc)\version.inc + +string.obj: string.asm $(inc)\cmacros.inc $(inc)\version.inc + +xtab.obj: xtab.asm $(inc)\cmacros.inc $(inc)\version.inc + +error.obj: error.c tools.h ttypes.h + +$(DEST).obj: $(DEST).c $(DEST).h tools.h ttypes.h + +fgetl.obj: fgetl.c tools.h ttypes.h + +ntoi.obj: ntoi.c tools.h ttypes.h + +update.obj: update.c tools.h ttypes.h + +$(DEST).exe: $(OBJ) $(DEST).lnk + $(link) @$(DEST).lnk; diff --git a/v4.0/src/CMD/FC/MAXMIN.ASM b/v4.0/src/CMD/FC/MAXMIN.ASM new file mode 100644 index 0000000..eb9ce53 --- /dev/null +++ b/v4.0/src/CMD/FC/MAXMIN.ASM @@ -0,0 +1,37 @@ +; +; maximum and minimum routines. +; + +.xlist +include version.inc +include cmacros.inc +.list + +sBegin code +assumes cs,code + +cProc max, +parmW a +parmW b +cBegin + mov ax,a + cmp ax,b + jg maxdone + mov ax,b +maxdone: +cEnd + +cProc min, +parmW a +parmW b +cBegin + mov ax,a + cmp ax,b + jl mindone + mov ax,b +mindone: +cEnd + +sEnd + +end diff --git a/v4.0/src/CMD/FC/MESSAGES.ASM b/v4.0/src/CMD/FC/MESSAGES.ASM new file mode 100644 index 0000000..5b1879f --- /dev/null +++ b/v4.0/src/CMD/FC/MESSAGES.ASM @@ -0,0 +1,31 @@ +; +; message file for FC command +; + +CONST SEGMENT WORD PUBLIC 'DATA' +CONST ENDS + +_BSS SEGMENT WORD PUBLIC 'DATA' +_BSS ENDS + +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS + +DGROUP GROUP CONST, _BSS, _DATA + + ASSUME DS:DGROUP + +_DATA SEGMENT +PUBLIC _BadSw, _UseMes, _BadOpn, _LngFil, _NoDif, _NoMem, _Bad_ver, _ReSyncMes, _UnKnown + +_BadSw DB "Incompatible switches",0 +_Bad_ver DB "Incorrect DOS version",0 +_UseMes DB "usage: fc [/a] [/b] [/c] [/l] [/lbNN] [/w] [/t] [/n] [/NNNN] file1 file2",0ah,0 +_BadOpn DB "cannot open %s - %s",0 +_LngFil DB "%s longer than %s",0 +_NoDif DB "no differences encountered",0 +_NoMem DB "out of memory",0ah,0 +_ReSyncMes DB "Resync failed. Files are too different\n",0 +_UnKnown DB "Unknown error",0 +_DATA ENDS +END diff --git a/v4.0/src/CMD/FC/MOVE.ASM b/v4.0/src/CMD/FC/MOVE.ASM new file mode 100644 index 0000000..d40e5d6 --- /dev/null +++ b/v4.0/src/CMD/FC/MOVE.ASM @@ -0,0 +1,73 @@ +; +; memory routines +; + +.xlist +include version.inc +include cmacros.inc +.list + +sBegin code +assumes cs,code + +cProc Move,, +parmD src +parmD dst +parmW count +cBegin + mov cx,count + jcxz NoByte ; No characters to move + les di,dst ; grab pointers + lds si,src + cld + mov ax,ds + cmp ax,Seg_dst + jnz SimpleMove ; segments are NOT the same, no opt + cmp si,di ; is the start of source before dest + jb TestMove ; yes, try to optimize + +SimpleMove: + shr cx,1 + rep movsw + jnc NoByte + movsb + jmp short NoByte + +TestMove: + mov ax,di + sub ax,si ; ax = difference between regions + cmp ax,cx ; is difference greater than region? + jae SimpleMove ; yes, no optimize + mov ax,cx ; optimize by copying down from top + dec ax + add di,ax + add si,ax + std + rep movsb ; no word optimization here + +NoByte: + cld +cEnd + +cProc Fill,, +parmD dst +parmB value +parmW count +cBegin + cld + les di,dst + mov al,value + mov ah,value + mov cx,count + shr cx,1 + jcxz fill1 + rep stosw +fill1: + jnc fill2 + stosb +fill2: +cEnd + +sEnd + +end diff --git a/v4.0/src/CMD/FC/NTOI.C b/v4.0/src/CMD/FC/NTOI.C new file mode 100644 index 0000000..267fce7 --- /dev/null +++ b/v4.0/src/CMD/FC/NTOI.C @@ -0,0 +1,37 @@ +/* convert an arbitrary based number to an integer */ + +#include +#include "tools.h" + +/* p points to characters, return -1 if no good characters found + * and base is 2 <= base <= 16 + */ +int ntoi (p, base) +char *p; +int base; +{ + register int i, c; + flagType fFound; + + if (base < 2 || base > 16) + return -1; + i = 0; + fFound = FALSE; + while (c = *p++) { + c = tolower (c); + if (!isxdigit (c)) + break; + if (c <= '9') + c -= '0'; + else + c -= 'a'-10; + if (c >= base) + break; + i = i * base + c; + fFound = TRUE; + } + if (fFound) + return i; + else + return -1; +} diff --git a/v4.0/src/CMD/FC/STRING.ASM b/v4.0/src/CMD/FC/STRING.ASM new file mode 100644 index 0000000..d72f7a4 --- /dev/null +++ b/v4.0/src/CMD/FC/STRING.ASM @@ -0,0 +1,115 @@ +; +; string functions for lattice C +; + +.xlist +include version.inc +include cmacros.inc +.list + +sBegin data +assumes ds,data + +externB XLTab +externB XUTab + +sEnd + +sBegin code +assumes cs,code + +externP strlen + +; +; strbscan (string, set) returns pointer to 1st char in set or end +; +cProc strbscan,, +parmW str +parmW set +cBegin + push ds + pop es + cCall strlen, + inc ax + mov bx, ax + mov si,str + cld +bscan: + lodsb + mov cx,bx + mov di,set +; +; While not in the set +; + repnz scasb + jnz bscan + lea ax,[si-1] +cEnd + +; +; strbskip ( string, set ) returns pointer to 1st char not in set +; +cProc strbskip,, +parmW str +parmW set +cBegin + push ds + pop es + cCall strlen, + inc ax + mov bx, ax + mov si,str + cld +bskip: + lodsb + or al,al + jz eskip + mov cx,bx + mov di,set +; +; While not in the set +; + repnz scasb + jz bskip +eskip: + lea ax,[si-1] +cEnd + +; +; strpre (s1, s2) returns -1 if s1 is a prefix of s2, 0 otherwise. Ignores +; case. +; +cProc strpre,, +parmW pref +parmW str +cBegin + cld + mov si,pref + mov di,str + mov bx,dataOFFSET xltab +preCompare: + lodsb + mov ah,[di] + inc di + + xlat + xchg ah,al + xlat + + cmp ah,al + jnz preDif + or ah,ah + jnz preCompare +preYes: + mov ax,-1 + jmp short preDone +preDif: + or ah,ah + jz preYes + xor ax,ax +preDone: +cEnd + +sEnd + +end diff --git a/v4.0/src/CMD/FC/TOOLS.H b/v4.0/src/CMD/FC/TOOLS.H new file mode 100644 index 0000000..f6bc435 --- /dev/null +++ b/v4.0/src/CMD/FC/TOOLS.H @@ -0,0 +1,94 @@ +/* + * tools.h - Header file for accessing TOOLS.LIB routines + * includes stdio.h and ctype.h + * + * 4/14/86 dl added U_* flags for upd return values + * + * 31-Jul-1986 mz Add Connect definitions + */ + +#define TRUE -1 +#define FALSE 0 + +#if MSDOS +#define PSEPSTR "\\" +#define PSEPCHR '\\' +#else +#define PSEPSTR "/" +#define PSEPCHR '/' +#endif + +typedef char flagType; +typedef long ptrType; + +#define SETFLAG(l,f) ((l) |= (f)) +#define TESTFLAG(v,f) (((v)&(f))!=0) +#define RSETFLAG(l,f) ((l) &= ~(f)) + +#define SHIFT(c,v) {c--; v++;} + +#define LOW(w) ((int)(w)&0xFF) +#define HIGH(w) LOW((int)(w)>>8) +#define WORD(h,l) ((LOW((h))<<8)|LOW((l))) +#define POINTER(seg,off) ((((long)(seg))<<4)+ (long)(off)) + +#define FNADDR(f) (f) + +#define SELECT if(FALSE){ +#define CASE(x) }else if((x)){ +#define OTHERWISE }else{ +#define ENDSELECT } + +/* buffer description for findfirst and findnext */ + +struct findType { + char reserved[21]; /* reserved for start up */ + char attr; /* attribute found */ + unsigned time; /* time of last modify */ + unsigned date; /* date of last modify */ + long length; /* file size */ + char name[13]; /* asciz file name */ +}; + +/* attributes */ +#define A_RO 1 /* read only */ +#define A_H 2 /* hidden */ +#define A_S 4 /* system */ +#define A_V 8 /* volume id */ +#define A_D 16 /* directory */ +#define A_A 32 /* archive */ + +#define A_MOD (A_RO+A_H+A_S+A_A) /* changeable attributes */ + +#define HASATTR(a,v) TESTFLAG(a,v) /* true if a has attribute v */ + +extern char XLTab[], XUTab[]; + +#define MAXARG 128 +#define MAXPATHLEN 128 + +#include "ttypes.h" + +struct vectorType { + int max; /* max the vector can hold */ + int count; /* count of elements in vector */ + unsigned elem[1]; /* elements in vector */ +}; + +/* return flags for upd */ +#define U_DRIVE 0x8 +#define U_PATH 0x4 +#define U_NAME 0x2 +#define U_EXT 0x1 + +/* Connect definitions */ + +#define REALDRIVE 0x8000 +#define ISTMPDRIVE(x) (((x)&REALDRIVE)==0) +#define TOKTODRV(x) ((x)&~REALDRIVE) + +/* Heap Checking return codes */ + +#define HEAPOK 0 +#define HEAPBADBEGIN -1 +#define HEAPBADNODE -2 diff --git a/v4.0/src/CMD/FC/TTYPES.H b/v4.0/src/CMD/FC/TTYPES.H new file mode 100644 index 0000000..739df6f --- /dev/null +++ b/v4.0/src/CMD/FC/TTYPES.H @@ -0,0 +1,71 @@ +/* ttypes.h - type definitions for tools library */ + +#include + +/* assembly routines */ +flagType int25 (char, char far *, unsigned int, unsigned int); +flagType int26 (char, char far *, unsigned int, unsigned int); +flagType kbhit (); +char getch (); +void Move (char far *, char far *, unsigned int); +void Fill (char far *, char, unsigned int); +char *strbscan (char *, char *); +char *strbskip (char *, char *); +flagType strpre (char *, char *); +int strcmpi (unsigned char *, unsigned char *); +char *fcopy (char *, char *); +long getlpos (); +void getlinit ( char far *, int, int); +int getl (char *, int); + +/* c routines */ +/*global*/ char *lower(char *); +/*global*/ char *upper(char *); +/*global*/ char *error(void); +/*global*/ long fexpunge(char *,FILE *); +/*global*/ char *fcopy(char *,char *); +/*global*/ int fgetl(char *,int ,FILE *); +/*global*/ int fputl(char *,int ,FILE *); +/*global*/ int ffirst(char *,int ,struct findType *); +/*global*/ int fnext(struct findType *); +/*global*/ char forsemi(char *,char ( *)(), ); +/*global*/ long freespac(int ); +/*global*/ long sizeround(long ,int ); +/*global*/ int rspawnl(char *,char *,char *, ); +/*global*/ int rspawnv(char *,char *,char *,char *[0]); +/*global*/ char *MakeStr(char *); +/*global*/ int mapenv(char *,char *); +/*global*/ char *ismark(char *); +/*global*/ FILE *swopen(char *,char *); +/*global*/ int swclose(FILE *); +/*global*/ int swread(char *,int ,FILE *); +/*global*/ char *swfind(char *,FILE *,char *); +/*global*/ char *getenvini(char *,char *); +/*global*/ char fPathChr(int ); +/*global*/ char fSwitChr(int ); +/*global*/ char fPFind(char *,unsigned int * *); +/*global*/ char findpath(char *,char *,char ); +/*global*/ FILE *pathopen(char *,char *,char *); +/*global*/ int forfile(char *,int ,void ( *)(), ); +/*global*/ int rootpath(char *,char *); +/*global*/ int sti(char *,int ); +/*global*/ int ntoi(char *,int ); +/*global*/ int strcmps(unsigned char *,unsigned char *); +/*global*/ int strcmpis(unsigned char *,unsigned char *); +/*global*/ char *strend(char *); +/*global*/ int upd(char *,char *,char *); +/*global*/ int drive(char *,char *); +/*global*/ int extention(char *,char *); +/*global*/ int filename(char *,char *); +/*global*/ int filenamx(char *,char *); +/*global*/ int path(char *,char *); +/*global*/ int curdir(char *,char ); +/*global*/ int getattr(char *); +/*global*/ int fdelete(char *); +/*global*/ char *fmove(char *, char *); +/*global*/ char *fappend(char *, int); +/*global*/ long ctime2l(char *); +/*global*/ struct tm *ctime2tm(char *); +/*global*/ long date2l(int, int, int, int, int, int); +/*global*/ struct vectorType *VectorAlloc(int); +/*global*/ flagType fAppendVector(struct vectorType**, unsigned int); diff --git a/v4.0/src/CMD/FC/UPDATE.C b/v4.0/src/CMD/FC/UPDATE.C new file mode 100644 index 0000000..8263db1 --- /dev/null +++ b/v4.0/src/CMD/FC/UPDATE.C @@ -0,0 +1,128 @@ +/* + * update takes a def string and update and fills the + * update with missing defs the update allowing + * specification of missing parameters. + * the parts are: ^{[~:]#:}{%#}{[~.]#}{.[~./\:]}$ + * maximum size of MAXPATHLEN (80) bytes + * + * 4/14/86 dl use U_ flags + * + */ + +#include "tools.h" + +int upd (def, update, dst) +char *def, *update, *dst; +{ + char *p, buf[MAXPATHLEN]; + int f; + + f = 0; + p = buf; +#if MSDOS + if (drive(update, p) || drive (def, p)) + SETFLAG(f, U_DRIVE); + p += strlen (p); +#endif + + if (path(update, p) || path (def, p)) + SETFLAG(f, U_PATH); + p += strlen (p); + + if (filename(update, p) || filename (def, p)) + SETFLAG(f, U_NAME); + p += strlen (p); + + if (extention(update, p) || extention (def, p)) + SETFLAG(f, U_EXT); + + strcpy (dst, buf); + + return f; +} + +#if MSDOS +/* copy a drive from source to dest if present, return TRUE if we found one */ +drive (src, dst) +char *src, *dst; +{ + register char *p; + + p = strbscan (src, ":"); + if (*p++ == NULL) + p = src; + strcpy (dst, src); + dst[p-src] = 0; + return strlen (dst) != 0; +} +#endif + +/* copy an extention from source to dest if present. include the period. + Return TRUE if one found. + */ +extention (src, dst) +char *src, *dst; +{ + register char *p, *p1; + + p = src - 1; + while (*(p=strbscan(1+(p1=p), ".")) != NULL) + ; + /* p1 points to last . or begin of string p points to eos */ + if (*strbscan (p1, "\\/:") != NULL || *p1 != '.') + p1 = p; + strcpy (dst, p1); + return strlen (dst) != 0; +} + +/* copy a filename part from source to dest if present. return true if one + is found + */ +filename (src, dst) +char *src, *dst; +{ + register char *p, *p1; + + p = src-1; + while (*(p=strbscan (p1=p+1, "\\/:")) != NULL) + ; + /* p1 points after last / or at bos */ + p = strbscan (p1, "."); + strcpy (dst, p1); + dst[p-p1] = 0; + return strlen (dst) != 0; +} + +/* copy a filename.ext part from source to dest if present. return true if one + is found + */ +fileext (src, dst) +char *src, *dst; +{ + *dst = '\0'; + if ( filename (src, dst) ) { + dst += strlen (dst); + extention (src, dst); + return TRUE; + } + return FALSE; +} + +/* copy the paths part of the file description. return true if found + */ +path (src, dst) +char *src, *dst; +{ + register char *p, *p1; + + if (*(p=strbscan (src, ":")) != NULL) + src = p+1; + p = src-1; + /* p points to beginning of possible path (after potential drive spec) */ + while (*(p=strbscan (p1=p+1, "\\/:")) != NULL) + ; + /* p1 points after final / or bos */; + strcpy (dst, src); + dst[p1-src] = 0; + return strlen (dst) != 0; +} diff --git a/v4.0/src/CMD/FC/XTAB.ASM b/v4.0/src/CMD/FC/XTAB.ASM new file mode 100644 index 0000000..3b42529 --- /dev/null +++ b/v4.0/src/CMD/FC/XTAB.ASM @@ -0,0 +1,100 @@ +; +; xlat tables for case conversion +; + +.xlist +include version.inc +include cmacros.inc +.list + +sBegin data + +public _XLTab, _XUTab + +assumes ds,data + +; +; table for lowercase translation +; + +_XLTab LABEL BYTE + + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + + db ' !"#$%&', 027h + db '()*+,-./' + + db '01234567' + db '89:;<=>?' + + db '@abcdefg' + db 'hijklmno' + + db 'pqrstuvw' + db 'xyz[\]^_' + + db '`abcdefg' + db 'hijklmno' + + db 'pqrstuvw' + db 'xyz{|}~', 07Fh + + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08Ah, 08Bh, 08Ch, 08Dh, 08Eh, 08Fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09Ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh + db 0A0h, 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h + db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +_XUTab LABEL BYTE + + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db ' !"#$%&', 027h + db '()*+,-./' + db '01234567' + db '89:;<=>?' + db '@ABCDEFG' + db 'HIJKLMNO' + db 'PQRSTUVW' + db 'XYZ[\]^_' + db '`ABCDEFG' + db 'HIJKLMNO' + db 'PQRSTUVW' + db 'XYZ{|}~', 07Fh + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08Ah, 08Bh, 08Ch, 08Dh, 08Eh, 08Fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09Ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh + db 0A0h, 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h + db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +sEnd + +end diff --git a/v4.0/src/CMD/FDISK/BOOTREC.ASM b/v4.0/src/CMD/FDISK/BOOTREC.ASM new file mode 100644 index 0000000..0802495 --- /dev/null +++ b/v4.0/src/CMD/FDISK/BOOTREC.ASM @@ -0,0 +1,36 @@ +; Static Name Aliases +; + TITLE bootrec.asm - master boot record images for fdisk + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + +DGROUP GROUP CONST, _BSS, _DATA + ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP + +_DATA SEGMENT WORD PUBLIC 'DATA' + +; +; extern struct struct-name BootRecordData; +; +; +; + + +PUBLIC _master_boot_record + public _master_boot_record +_master_boot_record label byte + +include fdboot.inc +include fdboot.inc + +_DATA ENDS + +END + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/CONVERT.C b/v4.0/src/CMD/FDISK/CONVERT.C new file mode 100644 index 0000000..60ec6a1 --- /dev/null +++ b/v4.0/src/CMD/FDISK/CONVERT.C @@ -0,0 +1,478 @@ + +#include "fdisk.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "dos.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "string.h" +#include "ctype.h" + + +/******************************************************************************/ +/*Routine name: MBYTES_TO_CYLINDERS */ +/******************************************************************************/ +/* */ +/*Description: This routine will take input of MBtes and */ +/* convert it to cylinders rounding up to the next largest */ +/* cylinder boundry. Rounding up is done to make sure the */ +/* requester is getting at least what he asked for to the */ +/* next cylinder boundry. */ +/* */ +/*Called Procedures: none */ +/* */ +/* */ +/*Change History: Created 5/30/87 DRM */ +/* */ +/*Input: Input */ +/* */ +/*Output: Cylinders_out */ +/* */ +/******************************************************************************/ + + +unsigned mbytes_to_cylinders(mbytes_in,which_disk) /* AN004 */ + +XFLOAT mbytes_in; /* AN000 */ +char which_disk; /* AN004 */ + + + +BEGIN /* AN000 */ + +unsigned cylinders_out; /* AN000 */ +unsigned long cylinders_out1; /* AN000 */ +unsigned long number_of_sectors; /* AN000 */ +unsigned long number_of_tracks; /* AN000 */ +unsigned long divide_by; /* AN000 */ + + /* If trying to create a 3.30 compatible 32 MB partition */ + /* Set the 32mb limit - round down */ + if (mbytes_in == (XFLOAT)32) + BEGIN + cylinders_out1 = ul(DOS_MAX - max_sector[which_disk]); /* AN004 */ + divide_by = ul((max_head[which_disk]) * ul(max_sector[which_disk])); /* AN004 */ + cylinders_out = u(cylinders_out1 / divide_by); /* AN000 */ + END + else + BEGIN + number_of_sectors = ul(((mbytes_in * ONE_MEG)/BYTES_PER_SECTOR)); /* AN000 */ + if (((int)(mbytes_in * ONE_MEG) % BYTES_PER_SECTOR) != (int)0) /* AN000 */ + number_of_sectors++; /* AN000 */ + number_of_tracks = ul((number_of_sectors / max_sector[which_disk])); /* AN004 */ + if (((int)number_of_sectors % max_sector[which_disk]) != (int)0) /* AN004 */ + number_of_tracks++; /* AN000 */ + cylinders_out = u((number_of_tracks / max_head[which_disk])); /* AN004 */ + if (((int)number_of_tracks % max_head[which_disk]) != (int)0) /* AN004 */ + cylinders_out++; /* AN000 */ + END + + return(cylinders_out); /* AN000 */ +END /* AN000 */ + + + +/* */ +/*******************************************************************************/ +/*Routine name: CYLINDERS_TO_MBYTES */ +/*******************************************************************************/ +/* */ +/*Description: This routine will take input of cylinders and convert */ +/* it to MBytes. */ +/* */ +/* */ +/*Called Procedures: */ +/* */ +/* */ +/*Change History: Created 5/16/87 DRM */ +/* */ +/*Input: Cylinders_in */ +/* */ +/*Output: MBytes_out */ +/* */ +/* */ +/* */ +/*******************************************************************************/ + +XFLOAT cylinders_to_mbytes(cylinders_in,which_disk) /* AN004 */ + +unsigned cylinders_in; /* AN000 */ +char which_disk; /* AN004 */ + +BEGIN /* AN000 */ + +unsigned mbytes_out; /* AN000 */ +unsigned long number_of_bytes; /* AN000 */ +unsigned long number_of_sectors; /* AN000 */ +unsigned long number_of_tracks; /* AN000 */ +unsigned long bytes_in_one_sector; /* AN004 */ + + bytes_in_one_sector = BYTES_PER_SECTOR; /* AN004 */ + number_of_tracks = (ul(cylinders_in) * ul(max_head[which_disk])); /* AN004 */ + number_of_sectors = (number_of_tracks * ul(max_sector[which_disk])); /* AN004 */ + number_of_bytes = (ul(number_of_sectors) * ul(bytes_in_one_sector)); /* AN004 */ + mbytes_out = f(number_of_bytes / ONE_MEG); /* AN000 */ + if ((number_of_bytes % ONE_MEG) >= (ONE_MEG / 2)) mbytes_out++; /* AN000 */ + return(mbytes_out); /* AN000 */ + +END /* AN000 */ + + + + +/* */ +/*******************************************************************************/ +/*Routine name: CYLINDERS_TO_PERCENT */ +/*******************************************************************************/ +/* */ +/*Description: This routine will take input of cylinders and convert */ +/* it to Percent. */ +/* */ +/* */ +/*Called Procedures: */ +/* */ +/* */ +/*Change History: Created 5/16/87 DRM */ +/* */ +/*Input: Cylinders_in */ +/* */ +/*Output: percent_out */ +/* */ +/* */ +/* */ +/*******************************************************************************/ + +unsigned cylinders_to_percent(cylinders_in,total_cylinders) /* AN000 */ + +unsigned cylinders_in; /* AN000 */ +unsigned total_cylinders; /* AN000 */ + +BEGIN /* AN000 */ + +unsigned percentage_out; /* AN000 */ +double large_number; /* AN000 */ + + /* This is the same as (cyl_in / tot_cyl) * 100 to get the percentage */ + /* because * 100 is really 100/1 which is (cyl_in*100)/(tot_cyl*1). */ + + if (total_cylinders == 0) + percentage_out = 0; + else + BEGIN + large_number = (double)((long)cylinders_in * 100l); /* AN000 */ + percentage_out = u(large_number / total_cylinders); /* AN000 */ + END + /* this should round up to the next percent if more than .5 percent */ + if (((cylinders_in * 100) % total_cylinders) >= (total_cylinders / 2)) + percentage_out++; /* AN000 */ + if (percentage_out > u(100)) percentage_out = u(100); /* AN000 */ + return(percentage_out); /* AN000 */ +END /* AN000 */ + + + +/* */ +/******************************************************************************/ +/*Routine name: PERCENT_TO_CYLINDERS */ +/******************************************************************************/ +/* */ +/*Description: This routine will take input of percentage and */ +/* convert it to cylinders rounding up to the next largest */ +/* cylinder boundry. Rounding up is done to make sure the */ +/* requester is getting at least what he asked for to the */ +/* next cylinder boundry. */ +/* */ +/*Called Procedures: none */ +/* */ +/* */ +/*Change History: Created 5/30/87 DRM */ +/* */ +/*Input: Input */ +/* */ +/*Output: Cylinders_out */ +/* */ +/******************************************************************************/ + + +XFLOAT percent_to_cylinders(percent_in,total_cylinders) /* AN000 */ + +unsigned percent_in; /* AN000 */ +XFLOAT total_cylinders; /* AN000 */ + + +BEGIN /* AN000 */ + + XFLOAT cylinders_out; /* AN000 */ +#if IBMCOPYRIGHT + cylinders_out = ((percent_in * total_cylinders) / 100); /* AN000 */ +#else + cylinders_out = (unsigned)((ul(percent_in) * ul(total_cylinders)) / 100); +#endif + if (((percent_in * total_cylinders) % 100) != u(0)) /* AN000 */ + cylinders_out++; /* AN000 */ + return(cylinders_out); /* AN000 */ +END /* AN000 */ + + + + + + +/* */ +/*******************************************************************************/ +/*Routine name: DOS_UPPER */ +/*******************************************************************************/ +/* */ +/*Description: This routine will uppcase a character using get country */ +/* information (65H) with the capitalize single character */ +/* call (20H). */ +/* */ +/*Called Procedures: */ +/* */ +/* */ +/* */ +/*Change History: Updated 5/31/87 DRM */ +/* */ +/*Input: drive_value */ +/* */ +/*Output: input_value */ +/* */ +/*******************************************************************************/ + +char dos_upper(drive_value) /* AN000 */ + +char drive_value; /* AN000 */ + +BEGIN /* AN000 */ + + char output; /* AN000 */ + + regs.x.ax = (unsigned)CAPCHAR; /* Get extended country information - AN000 */ + regs.h.dl = (unsigned char)drive_value; /* Move input_value to register DL - AN000 */ + int86((int)INT21,®s,®s); /* AN000 */ + output = (char)regs.h.dl; /* AN000 */ + +#ifdef DEBUG + output = toupper(drive_value); +#endif + + return(output); /* AN000 */ +END /* AN000 */ + + + + + +/* */ +/*******************************************************************************/ +/*Routine name: CHECK_YN_INPUT */ +/*******************************************************************************/ +/* */ +/*Description: Get single character input, which must be a country */ +/* dependent (Y/N). Will be verified using new uppercase table */ +/* function calls. Will accept default value. */ +/* */ +/*Called Procedures: */ +/* */ +/* */ +/* */ +/*Change History: Updated 5/31/87 DRM */ +/* */ +/*Input: input_value */ +/* */ +/*Output: input */ +/* valid_input */ +/* */ +/*******************************************************************************/ + +char check_yn_input(input_value) /* AN000 */ + + char input_value; /* AN000 */ + +BEGIN + char input; /* AN000 */ + + /* Get extended country information */ + regs.x.ax = (unsigned)CAP_YN; /* AN000 */ + /* Move input_value to register DL */ + regs.h.dl = (unsigned char)input_value; /* AN000 */ + int86((int)INT21,®s,®s); /* AN000 */ + + /* check carry flag for error */ + if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG) /* AN000 */ + /* input will be 0 for NO and 1 for YES in AX */ + input = c(NO_GOOD); /* input will equal not 0 or 1 */ /* AN000 */ + else /* AN000 */ + input = c(regs.x.ax); /* AN000 */ + +#ifdef DEBUG + + input = NO_GOOD; + if ( (input_value == (char) 'Y') || (input_value == (char) 'y') ) input = c(1); + if ( (input_value == (char) 'N') || (input_value == (char) 'n') ) input = c(0); + +#endif + + return(input); /* AN000 */ +END /* AN000 */ + + + + +/* */ +/*******************************************************************************/ +/*Routine name: GET_FS_AND_VOL */ +/*******************************************************************************/ +/* */ +/*Description: This routine will invoke INT21 44h (Block Generic IOCTL */ +/* Subfunction) call to get volume label and file system type. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 6/01/87 DRM */ +/* */ +/*Input: input_drive */ +/* */ +/*Output: pointer to dx register */ +/* */ +/*******************************************************************************/ + +FLAG get_fs_and_vol(input_drive) /* AN000 */ + + char input_drive; /* AN000 */ + +BEGIN /* AN000 */ + + char output; + + /* Set up registers for Generic IOCTL INT21 (44h) get media ID */ + regs.x.ax = u(GENERIC_IOCTL); /* AN000 */ + regs.h.bh = uc(ZERO); /* AN000 */ + regs.h.bl = (((unsigned char)input_drive - 'A') + 1); /* AN000 */ + regs.x.cx = u(GET_MEDIA_ID); /* AN000 */ + regs.x.dx = (unsigned)&dx_buff; /* AN000 */ + segread(&segregs); + intdosx(®s,®s,&segregs); /* AN000 */ + + /* see if carry flag was zero or one */ + if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG) /* AN000 */ + output = FALSE; /* AN000 */ + else /* AN000 */ + output = TRUE; /* AN000 */ + + return(output); /* AN000 */ + /* AN000 */ +END + + + +/* */ +/*******************************************************************************/ +/*Routine name: GET_VOLUME_STRING */ +/*******************************************************************************/ +/* */ +/*Description: This routine will invoke INT21 4Eh (Find First Matching File) */ +/* and return the disk volume label. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 6/01/87 DRM */ +/* */ +/*Input: input_drive */ +/* */ +/*Output: volume_out */ +/* */ +/*******************************************************************************/ +void get_volume_string(input_drive,vol_label_addr) /* AN000 */ + char input_drive; /* AN000 */ + char *vol_label_addr; /* AN000 */ +BEGIN /* AN000 */ + + char first_string[13]; /* AC000 */ + char find_first_buffer[50]; /* AN000 */ + unsigned i,j; /* AC000 */ + + /* clear out any garbage in volume label field */ + for (i = u(0); i < u(12); i++) /* AN015 */ + BEGIN /* AN015 */ + vol_label_addr[i] = u(0); /* AN015 */ + END /* AN015 */ + + /* Point the DTA to our buffer so we can get the FindFirst output */ + regs.h.ah = uc(0x1A); /* AN000 */ + regs.x.dx = (unsigned)&find_first_buffer[0]; /* AN000 */ + segread(&segregs); + intdosx(®s,®s,&segregs); /* AN000 */ + + /* Find the first volume id */ + first_string[0] = input_drive; /* Find the vol label - AN000 */ + first_string[1] = (char) '\0'; + strcat(first_string,FILE_NAME); /* AN000 */ + regs.h.ah = uc(FIND_FIRST_MATCH); /* AN000 */ + regs.x.cx = u(VOL_LABEL); /* AN000 */ + regs.x.dx = (unsigned)&first_string[0]; /* AN000 */ + intdos(®s,®s); /* AN000 */ + +/* AC000 The following is modified to take care of "." in the middle of the */ +/*name */ + + if ((regs.x.cflag & CARRY_FLAG) != CARRY_FLAG) /* AN000 AC015 */ + BEGIN /* AN000 */ + for (i=j=u(0); i < strlen (&find_first_buffer[30]) ; i++) /* AN000 */ + BEGIN /* AN000 */ + if (find_first_buffer[30+i] != PERIOD) /* AN003 */ + vol_label_addr[i-j] = find_first_buffer[30+i]; /* AN000 */ + else /* AN000 */ + j = u(1); /* AN000 */ + END /* AN000 */ + END /* AN000 */ + return; /* AN000 */ +END /* AN000 */ + + +/* */ +/*******************************************************************************/ +/*Routine name: CHECK_FORMAT */ +/*******************************************************************************/ +/* */ +/*Description: This routine will invoke INT21 44h (Block Generic IOCTL */ +/* Subfunction) call to see if the drive has been previously */ +/* formatted by using a undocumented call. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 2/07/88 DRM */ +/* */ +/*Input: input_drive */ +/* */ +/*Output: pointer to dx register */ +/* */ +/*******************************************************************************/ + +FLAG check_format(input_drive) /* AN002 */ + + char input_drive; /* AN002 */ + +BEGIN /* AN002 */ + + char formatted; /* AN002 */ + + /* Set up registers for Generic IOCTL INT21 (44h) check media */ + regs.x.ax = u(GENERIC_IOCTL); /* AN002 */ + regs.h.bh = uc(ZERO); /* AN002 */ + regs.h.bl = (((unsigned char)input_drive - 'A') + 1); /* AN002 */ + regs.x.cx = u(SPECIAL_FUNCTION); /* AN002 */ + regs.x.dx = (unsigned)&disk_access; /* AN002 */ + segread(&segregs); /* AN002 */ + intdosx(®s,®s,&segregs); /* AN002 */ + + /* see if buffer returned good or not */ + if (disk_access.dac_access_flag == ZERO) /* AN002 */ + formatted = FALSE; /* AN002 */ + else /* AN002 */ + formatted = TRUE; /* AN002 */ + + return(formatted); /* AN002 */ + +END /* AN002 */ + + + diff --git a/v4.0/src/CMD/FDISK/C_MENUS.C b/v4.0/src/CMD/FDISK/C_MENUS.C new file mode 100644 index 0000000..7516ce1 --- /dev/null +++ b/v4.0/src/CMD/FDISK/C_MENUS.C @@ -0,0 +1,1067 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "stdio.h" + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: CREATE_PARTITION */ +/* */ +/* DESCRIPTIVE NAME: Create DOS related partition(s) */ +/* */ +/* FUNCTION: */ +/* This routine verifies if there are free partitions, */ +/* posts an status message if there is not, otherwise */ +/* prints a screen asking what type of partition to */ +/* be created, and passes control to the requested */ +/* function. */ +/* */ +/* NOTES: This is a screen control module only, no data is */ +/* modified. Routine also will only allow 1 DOS and */ +/* 1 Ext DOS partitions per disk, if one already exists,*/ +/* then status message is displayed when the create */ +/* option for that type partition is selected */ +/* */ +/* The following screen in managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Create DOS Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Choose one of the following: ³ */ +/* 09³ ³ */ +/* 10³ 1. Create Primary DOS partition ³ */ +/* 11³ 2. Create EXTENDED DOS partition ³ */ +/* 12³ 3. Create logical DOS drive(s) in ³ */ +/* 13³ the EXTENDED DOS partition ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Enter choice: [ ] ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: create_partition */ +/* LINKAGE: create_partition(); */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* find_free_partition */ +/* dos_create_partition */ +/* ext_create_partition */ +/* volume_create */ +/* internal_program_error */ +/* find_partition_type */ +/* get_num_input */ +/* display */ +/* wait_for_ESC */ +/* clear_screen */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void create_partition() + +BEGIN + +char input; +char default_value; +char max_input; + + + + + input = c(NUL); /* AC000 */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + /* put up heading and ESC */ + display(menu_8); + display(menu_11); + + /* Setup current drive msg */ + insert[0]=cur_disk+1+'0'; + display(menu_5); + + /* See if there are free partitions */ + if (find_free_partition() != ((char)(NOT_FOUND))) /* AC000 */ + BEGIN + /* display menu */ + display(menu_3); /* AN000 */ + display(menu_9); + + /* ############# ADD CODE HERE FOR THIS FUNCTION ############## */ + /* Do something about highlighting the available options and */ + /* setting up defaults */ + default_value = c(1); /* AC000 */ + /* ############################################################ */ + /* setup default for prompt */ + insert[0] = c('1'); /* AC000 */ + display(menu_7); + display(menu_10); + + max_input = c(3); /* AC000 */ + + input = get_num_input(default_value,max_input,input_row,input_col); + + /* Go branch to the requested function */ + switch(input) + BEGIN + case '1': dos_create_partition(); + break; + + case '2': + if ((cur_disk == c(1)) || (find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW)))) /* AN000 */ /* AC000 */ + ext_create_partition(); + else + BEGIN /* AN000 */ + /* don't have a primary partition yet, can't create an ext */ + display(error_19); /* AN000 */ + clear_screen(u(17),u(0),u(17),u(79)); /* AN000 */ + wait_for_ESC(); /* AN000 */ + END /* AN000 */ + break; + + case '3': + BEGIN + if (find_partition_type(uc(EXTENDED))) /* AC000 */ + volume_create(); + else /* AN000 */ + BEGIN /* AN000 */ + display(error_35); /* AN000 */ + clear_screen(u(17),u(0),u(17),u(79)); /* AN000 */ + wait_for_ESC(); /* AN000 */ + END /* AN000 */ + break; + END + + case ESC: break; + + default: internal_program_error(); + END + END + else + BEGIN + + /* Display prompt telling there is no avail partition */ + display(error_10); + input = wait_for_ESC(); + END + /* clear the screen before going back to main menu */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DOS_CREATE_PARTITION */ +/* */ +/* DESCRIPTIVE NAME: Create default DOS partition on disk */ +/* */ +/* FUNCTION: User is prompted to see if he wishes to use to */ +/* set up a DOS partition in the maximum available */ +/* size (limited to 32mb). If option is selected */ +/* than partition is created and marked active. The */ +/* partition is scanned to insure there are enough */ +/* contiguous good sectors for DOS. */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is created and nothing will change */ +/* */ +/* The following screen is managed: */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Create DOS Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Do you wish to use the maximum size ³ */ +/* 09³for a DOS partition and make the DOS ³ */ +/* 10³partition active (Y/N).........? [Y] ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: dos_create_partition */ +/* LINKAGE: dos_create_partition(); */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* display */ +/* get_yn_input */ +/* wait_for_ESC */ +/* input_dos_create */ +/* make_partition */ +/* check_bad_tracks */ +/* */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void dos_create_partition() + + +BEGIN + + char input; + char temp; + char second_disk_flag; /* AN000 */ + + + + second_disk_flag = (FLAG)FALSE; /* AN000 */ + input = c(NUL); /* AC000 */ + /* clear off screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Put up header */ + display(menu_12); + + /* Set up current disk message */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* Display ESC prompt */ + display(menu_11); + + /* See if already exists */ + if ((!find_partition_type(uc(DOS12))) && (!find_partition_type(uc(DOS16))) && (!find_partition_type(uc(DOSNEW)))) /* AC000 */ + + BEGIN + /* Display prompt, depending on what disk */ + if (cur_disk == c(0)) /* AC000 */ + /* Put up make active partition message */ + display(menu_13); + else + BEGIN + /* Second disk, so don;t put up prompt mentioning active partition */ + second_disk_flag = (FLAG)TRUE; /* AN000 */ + display(menu_45); /* AC000 */ + END + /* Get Y/N input */ + input = get_yn_input(c(Yes),input_row,input_col); /* AC000 AC011 */ + + /* Go handle input */ + switch(input) + BEGIN + case 1: /* AC000 */ + if ( second_disk_flag == (FLAG)FALSE) + BEGIN + /* Go get the biggest area left */ + temp = find_part_free_space(c(PRIMARY)); /* AC000 */ + make_partition(free_space[temp].space,temp,uc(ACTIVE),c(PRIMARY)); /* AC000 */ + reboot_flag = (FLAG)TRUE; /* AC000 */ + if (number_of_drives == uc(1)) /* AN000 */ + BEGIN /* AN000 */ + write_info_to_disk(); + reboot_system(); /* AC000 */ + END /* AN000 */ + clear_screen(u(16),u(0),u(23),u(79)); /* AN000 */ + display(status_12); /* AN000 */ + wait_for_ESC(); + break; + END + else + BEGIN /* AN000 */ + /* Go get the biggest area left */ /* AN000 */ + temp = find_part_free_space(c(PRIMARY)); /* AN000 */ + make_partition(free_space[temp].space,temp,uc(NUL),c(PRIMARY)); /* AN000 */ + reboot_flag = (FLAG)TRUE; /* AN000 */ + clear_screen(u(16),u(0),u(23),u(79)); /* AN000 */ + display(status_12); /* AN000 */ + wait_for_ESC(); + break; + END + + case 0: input_dos_create(); /* AC000 */ + break; + + case ESC: break; /* take no action */ + + default : internal_program_error(); + END + END + else + BEGIN + /* Display partition table-it will return if no partitions there */ + table_display(); + + /* Primary partition already exists message */ + display(error_8); + wait_for_ESC(); + END + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: INPUT_DOS_CREATE */ +/* */ +/* DESCRIPTIVE NAME: Create DOS partition on disk */ +/* */ +/* FUNCTION: Gets user specified size for partition (maximum */ +/* is 32mb or largest contiguous freespace, which- */ +/* ever is smaller). Default is largest avail free */ +/* space. Partition is created to default size,unless*/ +/* user enters different size, but is not marked */ +/* active. User specified size must be smaller or */ +/* equal to the default size */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is created and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Create DOS partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³Maximum space available for partition ³ */ +/* 16³is #### cylinders. ³ */ +/* 17³ ³ */ +/* 18³Enter partition size............: [####]³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: input_dos_create */ +/* LINKAGE: input_dos_create(); */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* table_display */ +/* get_num_input */ +/* display */ +/* wait_for_ESC */ +/* make_partition */ +/* check_bad_tracks */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void input_dos_create() + +BEGIN + + unsigned input; + unsigned default_entry; + char temp; + char location; + + input = u(NUL); /* AC000 */ + /* clear off screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Put up heading */ + display(menu_12); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* Print ESC prompt */ + display(menu_11); + + /* Display partition table-it will return if no partitions there */ + table_display(); + + sprintf(insert,"%4.0d",total_mbytes[cur_disk]); + display(menu_15); + + /* Get the free space */ + temp = find_part_free_space(c(PRIMARY)); /* AC000 */ + + /* Is there any ?*/ + if (free_space[temp].mbytes_unused != u(0)) /* AC000 */ + + BEGIN + /* Display disk space */ + sprintf(insert,"%4.0d",total_mbytes[cur_disk]); + display(menu_15); + + /* Setup and print max partition size */ + + sprintf(insert,"%4.0d%3.0d%%", + free_space[temp].mbytes_unused, + free_space[temp].percent_unused); + display(menu_16); + + /* Force repeats on the input until something valid (Non-Zero return) */ + default_entry = (unsigned)free_space[temp].mbytes_unused; /* AC000 */ + valid_input = (FLAG)FALSE; /* AC000 */ + + while (!valid_input) + + BEGIN + /* Display prompt */ + sprintf(insert,"%4.0d",default_entry); + display(menu_39); + + input = get_large_num_input(default_entry,free_space[temp].mbytes_unused,free_space[temp].percent_unused,menu_39,u(0),error_13); /* AC000 */ + + /* Update default in case of error, so it gets displayed and used */ + /* if user presses CR only */ + + default_entry = input; + clear_screen(u(19),u(0),u(23),u(79)); /* AC000 */ + END + + if (input != ((unsigned)(ESC_FLAG))) /* AC000 */ + + BEGIN + /* Change input to cylinders */ + /* check to see if input was in percent or mbytes */ + + if (PercentFlag) /* AN000 */ + BEGIN /* AN000 */ + if (input == free_space[temp].percent_unused) + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = percent_to_cylinders(input,total_disk[cur_disk]); + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + if (input == free_space[temp].mbytes_unused) + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(input, + cur_disk); /* AN004 */ + END /* AN000 */ + + /* Initialize PecentFlag back to FALSE */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + + /* Go create the partition */ + make_partition(input,temp,uc(NUL),c(PRIMARY)); /* AC000 */ + + /* clear off the old prompt */ + clear_screen(u(13),u(0),u(19),u(79)); /* AC000 */ + + /* Reissue the partition info */ + table_display(); + + /* display the "okay, we did it" msg */ + if (number_of_drives == uc(1)) /* AN000 */ + display(status_5); + else + BEGIN /* AN000 */ + clear_screen(u(16),u(0),u(23),u(79)); /* AN000 */ + display(status_12); /* AN000 */ + END /* AN000 */ + + wait_for_ESC(); + + reboot_flag = TRUE; + + END + END + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: EXT_CREATE_PARTITION */ +/* */ +/* DESCRIPTIVE NAME: Create EXTENDED DOS partition */ +/* */ +/* FUNCTION: Gets user specified size for EXTENDED partition */ +/* (Maximum is largest contiguous freespace). The */ +/* default is the largest available freespace. */ +/* space. Partition is created to default size, */ +/* unless user enters different size, but is not */ +/* marked as active. User specified size must be */ +/* smaller or equal to default size */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is created and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Create EXTENDED DOS partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³Maximum space available for partition ³ */ +/* 16³is #### cylinders. ³ */ +/* 17³ ³ */ +/* 18³Enter partition size............: [####]³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: EXTENDED_create_partition */ +/* LINKAGE: EXTENDED_create_partition(); */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* table_display */ +/* get_num_input */ +/* display */ +/* find_partition_type */ +/* wait_for_ESC */ +/* make_partition */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void ext_create_partition() + + +BEGIN + + unsigned input; + unsigned default_entry; + char temp; + + + input = u(NUL); /* AC000 */ + /* clear off screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Put up heading */ + display(menu_17); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* Display partition table-it will return if no partitions there */ + table_display(); + + /* Go see if primary already exists and ext doesn't */ + if ((cur_disk == c(1)) || (find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW)))) /* AC000 */ + BEGIN + if (!find_partition_type(uc(EXTENDED))) /* AC000 */ + /* We can go create one now */ + BEGIN + + /* Get the free space */ + temp = find_part_free_space(c(EXTENDED)); /* AC000 */ + + /* Is there any ?*/ + if (free_space[temp].percent_unused != u(0)) /* AC000 */ + BEGIN + + /* Display disk space */ + sprintf(insert,"%4.0d",total_mbytes[cur_disk]); + display(menu_15); + + /* Setup and print max partition size */ + + sprintf(insert,"%4.0d%3.0d%%", + free_space[temp].mbytes_unused, + free_space[temp].percent_unused); + display(menu_16); + + /* Force repeats on the input until something valid (Non-Zero return) */ + /* Display MBytes unless MBytes == 0, then display percent */ + if (free_space[temp].mbytes_unused == u(0)) /* AN000 */ + BEGIN /* AN000 */ + default_entry = (unsigned)free_space[temp].percent_unused; /* AC000 */ + PercentFlag = (FLAG)TRUE; /* AN000 */ + END /* AN000 */ + else /* AN000 */ + BEGIN + default_entry = (unsigned)free_space[temp].mbytes_unused; /* AC000 */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + END + + valid_input = (FLAG)FALSE; /* AC000 */ + + while (!valid_input) + BEGIN + /* Display prompt */ + if (!PercentFlag) /* AN000 */ + sprintf(insert,"%4.0d",default_entry); + else /* AN000 */ + sprintf(insert,"%3.0d%%",default_entry); /* AN000 */ + display(menu_42); /* AC000 */ + + input = get_large_num_input(default_entry,free_space[temp].mbytes_unused,free_space[temp].percent_unused,menu_42,u(0),error_13); /* AC000 */ + + /* Update default in case of error, so it gets displayed and used */ + /* if user presses CR only */ + + default_entry = input; + clear_screen(u(19),u(0),u(23),u(79)); /* AC000 */ + END + + if (input != ((unsigned)(ESC_FLAG))) /* AC000 */ + BEGIN + + /* Change input to cylinders */ + if (PercentFlag) /* AN000 */ + BEGIN /* AN000 */ + if (input == free_space[temp].percent_unused) + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = percent_to_cylinders(input,total_disk[cur_disk]); + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + if (input == free_space[temp].mbytes_unused) + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(input, + cur_disk); /* AN004 */ + END /* AN000 */ + + + /* Initialize PecentFlag back to FALSE */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + + /* Go create the partition */ + make_partition(input,temp,uc(NUL),c(EXTENDED)); /* AC000 */ + + /* clear off the old prompt */ + clear_screen(u(13),u(0),u(19),u(79)); /* AC000 */ + + /* Display the updated partition information */ + table_display(); + + /* Hit esc to continue line */ + clear_screen(u(24),u(0),u(24),u(79)); /* AN000 */ + display(menu_46); /* AN000 */ + + /* Tell user we created it */ + display(status_6); + wait_for_ESC(); + + reboot_flag = (FLAG)TRUE; /* AC000 */ + + /* Go allow him to create disk volumes */ + volume_create(); + END + END + else + BEGIN + /* No room */ + display(error_10); + wait_for_ESC(); + END + END + else + BEGIN + /* Already have ext partition, tell user and bow out */ + display(error_9); + wait_for_ESC(); + END + END + else + BEGIN + /* don't have a primary partition yet, can't create an ext */ + display(error_19); + wait_for_ESC(); + END + + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: VOLUME_CREATE */ +/* */ +/* DESCRIPTIVE NAME: Create DOS disk volumes */ +/* */ +/* FUNCTION: Create the boot record/partition table structure */ +/* needed to support the DOS disk volume arch in */ +/* the EXTENDED partition. Volume is created to the */ +/* the default size (largest contiguous freespace or */ +/* 32mb, whichever smaller) or to the user specified */ +/* size (must be smaller or equal to default size). */ +/* The volume boot record is created, and the appro- */ +/* priate pointers in other volume partition tables */ +/* are generated. */ +/* */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is created and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³Create DOS Disk Volume ³ */ +/* 01³ ³ */ +/* 02³Vol Start End Size ³ */ +/* 03³ # #### #### #### ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ ³ */ +/* 07³ ³ */ +/* 08³ ³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³Total partition size is #### cylinders. ³ */ +/* 17³Maximum space available for disk ³ */ +/* 18³volume is #### cylinders. ³ */ +/* 19³ ³ */ +/* 20³Enter disk volume size..........: [####]³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Volume_Create */ +/* LINKAGE: Volume_Create () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* display */ +/* volume_display */ +/* get_num_input */ +/* wait_for_ESC */ +/* make_partition */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void volume_create() + +BEGIN + + unsigned input; + unsigned default_entry; + char temp; + char drive_letter; + char default_value; + char location; + char previous_location; + char ext_location; + unsigned char i; + char defined_drives; + char temp_cur_disk; + unsigned ext_part_percent_unused; /* AN000 */ + unsigned ext_part_num; /* AN000 */ + + input = u(NUL); /* AC000 */ + + /* clear off screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display (menu_18); + + /* print ESC prompt */ + display(menu_11); + + /* Display volume info */ + drive_letter = volume_display(); + + /* Loop until done */ + input = u(NUL); /* AC000 */ + while (input != ((unsigned)(ESC_FLAG))) /* AC000 */ + + BEGIN + /* See if we have hit the max number of drives */ + defined_drives = c(0); /* AC000 */ + temp_cur_disk = cur_disk; + + /* Search both drives for defined drives */ + for (i = uc(0); i < number_of_drives; i++) /* AC000 */ + + BEGIN + cur_disk = ((char)(i)); + + /* See if there is a primary drive letter */ + if ((find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) || (find_partition_type(uc(DOSNEW)))) /*AC000*/ + defined_drives++; + + /* See if extended partition on disk */ + if (find_partition_type(uc(EXTENDED))) /* AC000 */ + BEGIN + /* Get number of logical drives */ + defined_drives = defined_drives + get_num_logical_dos_drives(); + END + END + /* Restore cur_disk to original */ + cur_disk = temp_cur_disk; + + /* See if 26 or less drives total */ + if (defined_drives < c(24)) /* AC000 */ + BEGIN + location = find_ext_free_space(); + + /* find the number of the extended partiton to figure out percent */ + ext_part_num = find_partition_location(uc(EXTENDED)); /* AN000 */ + + /* Set the percent used */ + ext_part_percent_unused = + cylinders_to_percent(free_space[location].space, + ((part_table[cur_disk][ext_part_num].end_cyl-part_table[cur_disk][ext_part_num].start_cyl)+1)); /* AN000 */ + + /* Is there any ?*/ + if (ext_part_percent_unused != u(0)) /* AC000 */ + BEGIN + + /* Display disk space */ + sprintf(insert,"%4.0d",get_partition_size(uc(EXTENDED)) ); + display(menu_21); + + /* Setup and print max partition size */ + + sprintf(insert,"%4.0d%3.0d%%", + free_space[location].mbytes_unused, + ext_part_percent_unused); + display(menu_22); + + /* Force repeats on the input until something valid (Non-Zero return) */ + /* If MBytes unused is equel to zero, display percent unused */ + if (free_space[location].mbytes_unused == u(0)) /* AN000 */ + BEGIN /* AN000 */ + default_entry = (unsigned)ext_part_percent_unused; /* AN000 */ + PercentFlag = (FLAG)TRUE; /* AN000 */ + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + default_entry = (unsigned)free_space[location].mbytes_unused; /* AC000 */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + END /* AN000 */ + + valid_input = (FLAG)FALSE; /* AC000 */ + + while (!valid_input) + BEGIN + /* Display prompt */ + if (!PercentFlag) /* AN000 */ + sprintf(insert,"%4.0d",default_entry); + else /* AN000 */ + sprintf(insert,"%3.0d%%",default_entry); /* AN000 */ + + display(menu_40); + + input = get_large_num_input(default_entry,free_space[location].mbytes_unused,ext_part_percent_unused,menu_40,u(0),error_12); /* AC000*/ + + /* Update default in case of error, so it gets displayed and used */ + /* if user presses CR only */ + + default_entry = input; + clear_screen(u(19),u(0),u(23),u(79)); /* AC000 */ + END + + if (input != ((unsigned)(ESC_FLAG))) /* AC000 */ + BEGIN + + /* Change input to cylinders */ + if (PercentFlag) /* AN000 */ + BEGIN /* AN000 */ + if (input == ext_part_percent_unused) + input = free_space[location].space; /* AN000 */ + else /* AN000 */ + input = percent_to_cylinders(input,((part_table[cur_disk][ext_part_num].end_cyl-part_table[cur_disk][ext_part_num].start_cyl)+1)); + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + if (input == free_space[location].mbytes_unused) + input = free_space[location].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(input, + cur_disk); /* AN004 */ + END /* AN000 */ + + /* Initialize PecentFlag back to FALSE */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + + /* go create the entry and find out where it put it */ + ext_location = make_volume(input,location); + + /* clear off the old prompt */ + clear_screen(u(15),u(0),u(19),u(79)); /* AC000 */ + + reboot_flag = (FLAG)TRUE; /* AC000 */ + + /* Display the updated partition information */ + drive_letter = volume_display(); + + /* Tell user we created it */ + display(status_7); + END + END + else + BEGIN + /* No space left or already max'd on the devices */ + /* Get rid of the size prompts */ + clear_screen(u(17),u(0),u(21),u(79)); /* AC000 */ + display(error_20); + volume_display(); + wait_for_ESC(); /* KWC, 11-01-87 */ + input = u(ESC_FLAG); /* KWC, 11-01-87 */ + END + END + else + BEGIN + /* Reached the maximum */ + /* Get rid of the size prompts */ + clear_screen(u(17),u(0),u(21),u(79)); /* AC000 */ + display(error_27); + /* Force an exit with ESC */ + wait_for_ESC(); /* KWC, 11-01-87 */ + input = u(ESC_FLAG); /* KWC, 11-01-87 */ + END + END + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + diff --git a/v4.0/src/CMD/FDISK/DISKOUT.C b/v4.0/src/CMD/FDISK/DISKOUT.C new file mode 100644 index 0000000..189795e --- /dev/null +++ b/v4.0/src/CMD/FDISK/DISKOUT.C @@ -0,0 +1,354 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "extern.h" /* AN000 */ + + +/* */ +void write_info_to_disk() + +BEGIN + +char i; +unsigned char j; +unsigned extended_location; +char extended_index; +char temp; +char first_found; +char changed_flag; +char temp_disk; + + + temp = c(NUL); /* AN009 */ + temp_disk = cur_disk; + /* See if need to update the master boot record */ + for (j = uc(0); j < number_of_drives; j++) /* AC000 */ + BEGIN + + /* Save disk number */ + cur_disk = ((char)(j)); + + /* See if there were any errors on that drive */ + if (good_disk[j]) + BEGIN + for (i=c(0); i < c(4); i++) /* AC000 */ + BEGIN + if (part_table[j][i].changed) + BEGIN + write_master_boot_to_disk(j); + break; + END + END + /* See if the extended partition exists - if not, don't fool with the logical*/ + /* drives - there is nothing to point to thier structures. Otherwise you get into */ + /* a chicken and the egg situation, where you are trying to write out 'deletes' of */ + /* the logical drive based on the start of the extended partition, but there isn't one */ + /* because it has already been deleted already. Bad things happen - PTM P941 */ + + if (find_partition_type(uc(EXTENDED))); /* AC000 */ + BEGIN + /* See if any extended partitions need to be updated */ + changed_flag = FALSE; + + for (i=c(0);i > 24)); /* AC000 */ + boot_record[0x1C8+(index)] = uc(((long_temp & 0x00FF0000l) >> 16)); /* AC000 */ + boot_record[0x1C7+(index)] = uc(((long_temp & 0x0000FF00l) >> 8)); /* AC000 */ + boot_record[0x1C6+(index)] = uc((long_temp & 0x000000FFl)); /* AC000 */ + + + /* Number of sectors */ + long_temp = part_table[disk][i].num_sec; + boot_record[0x1CD+(index)] = uc(long_temp >> 24); /* AC000 */ + boot_record[0x1CC+(index)] = uc((long_temp & 0x00FF0000l) >> 16); /* AC000 */ + boot_record[0x1CB+(index)] = uc((long_temp & 0x0000FF00l) >> 8); /* AC000 */ + boot_record[0x1CA+(index)] = uc(long_temp & 0x000000FFl); /* AC000 */ + END + END + boot_record[510] = uc(0x55); /* AC000 */ + boot_record[511] = uc(0xAA); /* AC000 */ + + return(write_boot_record(u(0),disk)); /* AC000 */ +END + +/* */ +char write_ext_boot_to_disk(entry,disk) + +char entry; +unsigned char disk; +BEGIN + +char i; +unsigned j; +unsigned long long_temp; +unsigned index; +char location; +char next_drive; +char pointer; +char write; + + /* Clean out the boot_record */ + for (j=u(0);j < u(BYTES_PER_SECTOR); j++) /* AC000 */ + BEGIN + boot_record[j] = uc(0); /* AC000 */ + END + + /* First - setup the logical devices */ + /* See if it has been deleted - if so, leave entries as zero */ + /* Otherwise - go unscramble everything out of the arrays */ + + if (ext_table[disk][sort[entry]].sys_id != uc(0)) /* AC000 */ + BEGIN + /* Get boot ind */ + boot_record[0x1BE] = ext_table[disk][sort[entry]].boot_ind; + + /* Start head */ + boot_record[0x1BF] = ext_table[disk][sort[entry]].start_head; + + /* Start sector - scramble it to INT 13 format*/ + boot_record[0x1C0] = (ext_table[disk][sort[entry]].start_sector & 0x3F) | + ((ext_table[disk][sort[entry]].start_cyl/256) << 6); + + /* Start cyl - scramble it to INT 13 format*/ + boot_record[0x1C1] = ((unsigned char)(ext_table[disk][sort[entry]].start_cyl%256)); + + /* System id */ + boot_record[0x1C2]= ext_table[disk][sort[entry]].sys_id; + + /* End head */ + boot_record[0x1C3] = ext_table[disk][sort[entry]].end_head; + + /* End sector - scramble it to INT 13 format*/ + boot_record[0x1C4] = (ext_table[disk][sort[entry]].end_sector & 0x3F) | + ((ext_table[disk][sort[entry]].end_cyl/256) << 6); + + /* End cyl - scramble it to INT 13 format*/ + boot_record[0x1C5] = ((unsigned char)(ext_table[disk][sort[entry]].end_cyl%256)); + + /* Relative sectors */ + long_temp = ext_table[disk][sort[entry]].rel_sec; + boot_record[0x1C9] = uc((long_temp >> 24)); /* AC000 */ + boot_record[0x1C8] = uc(((long_temp & 0x00FF0000l) >> 16)); /* AC000 */ + boot_record[0x1C7] = uc(((long_temp & 0x0000FF00l) >> 8)); /* AC000 */ + boot_record[0x1C6] = uc((long_temp & 0x000000FFl)); /* AC000 */ + + /* Number of sectors */ + long_temp = ext_table[disk][sort[entry]].num_sec; + boot_record[0x1CD] = uc((long_temp >> 24)); /* AC000 */ + boot_record[0x1CC] = uc(((long_temp & 0x00FF0000l) >> 16)); /* AC000 */ + boot_record[0x1CB] = uc(((long_temp & 0x0000FF00l) >> 8)); /* AC000 */ + boot_record[0x1CA] = uc((long_temp & 0x000000FFl)); /* AC000 */ + END + + /* set up pointer to next logical drive unless this is # 23 */ + if (entry != c(22)) /* AC000 */ + BEGIN + /* Find the drive to be pointed to */ + pointer = entry+1; + + /* Handle the special case of a deleted or empty first entry in partition*/ + if (entry == c(23)) /* AC000 */ + BEGIN + pointer = c(0); /* AC000 */ + END + for (i = pointer; i > 24)); /* AC000 */ + boot_record[0x1D8] = uc(((long_temp & 0x00FF0000l) >> 16)); /* AC000 */ + boot_record[0x1D7] = uc(((long_temp & 0x0000FF00l) >> 8)); /* AC000 */ + boot_record[0x1D6] = uc((long_temp & 0x000000FFl)); /* AC000 */ + + /* Number of sectors in the next volume*/ + long_temp = ((unsigned long)(ext_table[disk][next_drive].end_cyl - ext_table[disk][next_drive].start_cyl+1)) + * max_head[disk] * max_sector[disk]; + boot_record[0x1DD] = uc((long_temp >> 24)); /* AC000 */ + boot_record[0x1DC] = uc(((long_temp & 0x00FF0000l) >> 16)); /* AC000 */ + boot_record[0x1DB] = uc(((long_temp & 0x0000FF00l) >> 8)); /* AC000 */ + boot_record[0x1DA] = uc((long_temp & 0x000000FFl)); /* AC000 */ + END + END + boot_record[510] = uc(0x55); /* AC000 */ + boot_record[511] = uc(0xAA); /* AC000 */ + + /* Write the boot record out */ + if (entry != c(23)) /* AC000 */ + BEGIN + write = write_boot_record(ext_table[disk][sort[entry]].start_cyl,disk); + END + else + BEGIN + /* Write the special case of the first entry only having a pointer */ + write = write_boot_record(ext_table[disk][23].start_cyl,disk); + END + return(write); +END + + + + diff --git a/v4.0/src/CMD/FDISK/DISPLAY.C b/v4.0/src/CMD/FDISK/DISPLAY.C new file mode 100644 index 0000000..fed2393 --- /dev/null +++ b/v4.0/src/CMD/FDISK/DISPLAY.C @@ -0,0 +1,406 @@ + + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "stdio.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "doscall.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "ctype.h" /* AN000 */ + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DISPLAY */ +/* */ +/* DESCRIPTIVE NAME: Display full screen interface messages */ +/* */ +/* FUNCTION: Displays messages and handles control characters */ +/* */ +/* NOTES: */ +/* FDISK MESSAGES */ +/* Portions of the screen that are handled in the msg are */ +/* indicated on the listing of the screen with the message */ +/* name given. If the text message is defined in another */ +/* screen, then the name is followed by a "#" character */ +/* */ +/* NOTE TO TRANSLATORS The characters inside the <> and the [] */ +/* are control characters and should not be translated. The */ +/* Control characters are defined as follows: */ +/* */ +/* - Highlight the following text */ +/* - Regular text */ +/* - Blink the following text */ +/* - Turn blinking off */ +/* - Print YES character, as set by define */ +/* - Print NO character, as set by define */ +/* - Sound the beep */ +/* - Save cursor position for later use */ +/* - Insert character from insert[] string. This string */ +/* must be set up prior to displaying the message. The */ +/* first will insert Insert[0], the second */ +/* insert[1], etc....This will move the cursor one */ +/* postition. The insert[] string will be initialized */ +/* */ +/* Multiple control characters can be between the <>. */ +/* */ +/* The ^####^indicates Row and column for the text and has the */ +/* format of [rrcc] where the numbers are decimal and zero */ +/* based (first row/col is 00. The numbers are in decimal, */ +/* and must be 2 characters, which means rows/cols 0-9 should */ +/* be listed as 00-09. For example, the 5th row, 3rd column */ +/* on the screen would be listed as ^0402^. */ +/* */ +/* The column number is always the column desired. The row */ +/* number is an offset from the previous row. For example, if */ +/* the text just printed is on row 6, and the next text should */ +/* be printed 2 rows down in column 0, then the control strin */ +/* would be ^0201^. The first row specified in the message is */ +/* assumed to be based off of row 0, it would actually specify */ +/* the actual row for the start of the msg to be printed. */ +/* */ +/* ENTRY POINTS: display(*message_name); */ +/* LINKAGE: Near call */ +/* */ +/* INPUT: char *message_name */ +/* */ +/* EXIT-NORMAL: */ +/* */ +/* EXIT-ERROR: */ +/* */ +/* EFFECTS: */ +/* input_row changed if control character in message */ +/* input_col changed if control character in message */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/* viowrtcharstratt(); */ +/******************** END OF SPECIFICATIONS ********************/ +/* */ +void display(s) + +char far *s; + +BEGIN + unsigned row; + unsigned col; + char attribute; + char far *attribute_ptr = &attribute; + unsigned insert_count; + + + /* Initialize row and col, and index into array */ + row = u(0); /* AC000 */ + col = u(0); /* AC000 */ + insert_count = u(0); /* AC000 */ + /* check for a request to display a null string */ + if (*s == c('\0')) /* AC000 */ + BEGIN + /* Message string error */ + insert[0] = c('1'); /* AC000 */ + display(debug_msg); + END + else + BEGIN + /* There is data there, lets go handle it */ + + attribute = c(0x00); /* AC000 */ + /* Go until end of string */ + while (*s != c('\0')) /* AC000 */ + BEGIN + + /* Check for any imbedded control strings */ + switch (*s) + BEGIN + /* Check for control characters */ + case '<': + BEGIN + s++; + while ( (*s != c('>')) && (*s != c('\0')) ) /* AC000 */ + BEGIN + switch (*s++) + BEGIN + case 'H': if (mono_flag == TRUE) /* AN006 */ + attribute = (attribute & 0x80) | HIWHITE_ON_BLACK; /* AN006 */ + else /* AN006 */ + attribute = (attribute & 0x80) | HIWHITE_ON_BLUE; /* AC006 */ + break; + + + case 'R': if (mono_flag == TRUE) /* AN006 */ + attribute = (attribute & 0x80) | GRAY_ON_BLACK; /* AN006 */ + else /* AN006 */ + attribute = (attribute & 0x80) | WHITE_ON_BLUE; /* AC006 */ + break; + + case 'B': attribute |= 0x80; + break; + + case 'O': attribute &= 0x7F; + break; + + case 'W': DOSBEEP(u(900),u(400)); /* AC000 */ + break; + + case 'I': + BEGIN + /* display next element in the array */ + if ((mono_flag == TRUE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(GRAY_ON_BLACK); /* AN006 */ + if ((mono_flag == FALSE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(WHITE_ON_BLUE); /* AC006 */ + VIOWRTCHARSTRATT(pinsert+insert_count++,u(1),row,col++,attribute_ptr,u(0)); + break; + END + + + case 'Y': /* AC011 */ + BEGIN + /* display YES character in next location */ + *--s = c(Yes); /* AC000 */ + if ((mono_flag == TRUE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(GRAY_ON_BLACK); /* AN006 */ + if ((mono_flag == FALSE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(WHITE_ON_BLUE); /* AC006 */ + VIOWRTCHARSTRATT(s,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */ + *s++ = c(Yes); /* AC000 AC011 */ + break; + END + + case 'N': /* AC011 */ + BEGIN + /* display NO character in next location */ + *--s = c(No); /* AC000 */ + if ((mono_flag == TRUE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(GRAY_ON_BLACK); /* AN006 */ + if ((mono_flag == FALSE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(WHITE_ON_BLUE); /* AC006 */ + VIOWRTCHARSTRATT(s,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */ + *s++ = c(No); /* AC000 AC011 */ + break; + END + + + case 'S': + BEGIN + input_row = row; + input_col = col; + break; + END + + + case 'C': + BEGIN + /* Clear from current position to end of line */ + clear_screen(row,col,row,u(79)); /* AC000 */ + break; + END + + case '\0': + BEGIN + /* Message string error - string ended in the middle of control string*/ + insert[0] = c('7'); /* AC000 */ + display(debug_msg); + break; + END + + default: + BEGIN + /* Message string error - no valid control char found */ + insert[0] = c('6'); /* AC000 */ + display(debug_msg); + break; + END + END /* Switch */ + END /* While */ + /* Get the pointer past the '>' */ + s++; + break; + END /* control characters */ + + /* Check for row,col */ + case '^': /* AC000 */ + BEGIN + s++; + /* determine the row to put the message on */ + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = c('2'); /* AC000 */ + display(debug_msg); + END + else + BEGIN + row = row+((unsigned)(((*s++ - '0')*10))); + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = c('2'); /* AC000 */ + display(debug_msg); + END + else + BEGIN + row = row+((unsigned)(*s++ - '0')); + /* determine the col to put the message on */ + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = c('3'); /* AC000 */ + display(debug_msg); + END + else + BEGIN + col = ((unsigned)(*s++ - '0')); + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = c('3'); /* AC000 */ + display(debug_msg); + END + else + BEGIN + col = ((unsigned)((col* 10) + (*s++ - '0'))); + if (*s++ != c('^')) /* AC000 */ + BEGIN + /* Message string error */ + insert[0] = c('4'); /* AC000 */ + display(debug_msg); + END /* 2nd sq bracket */ + END /* 2nd digit col */ + END /* 1st digit col */ + END /* 2nd digit row */ + END /* 1st digit row */ + break; + END + /* Handle anything else */ + + + default: + BEGIN + /* See if attribute set to anything */ + if ((mono_flag == FALSE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(WHITE_ON_BLUE); /* AC006 */ + if ((mono_flag == TRUE) && (attribute == c(0x00))) /* AN006 */ + attribute = c(GRAY_ON_BLACK); /* AN006 */ + VIOWRTCHARSTRATT(s++,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */ + break; + END + END + END /* End of string check */ + END /* No characters in string check */ + return; + +END + +/* */ + +void number_in_msg(number,start) + +XFLOAT number; +unsigned start; + +BEGIN + +char mbytes[32]; + + /* Divide the space down and get it into decimal */ + sprintf(mbytes,"%4.0d",number); + insert[start+0] = mbytes[0]; + insert[start+1] = mbytes[1]; + insert[start+2] = mbytes[2]; + insert[start+3] = mbytes[3]; + + return; + +END + + +/* */ +void percent_in_msg(number,start) /* AN000 */ + +unsigned number; /* AN000 */ +unsigned start; /* AN000 */ + +BEGIN /* AN000 */ + + +char percent[32]; + + /* Divide the space down and get it into decimal */ + sprintf(percent,"%3.0d%%",number); /* AC000 */ + insert[start+0] = percent[0]; /* AC000 */ + insert[start+1] = percent[1]; /* AC000 */ + insert[start+2] = percent[2]; /* AC000 */ + insert[start+3] = percent[3]; /* AC000 */ + + return; + +END /* AN000 */ + +/* */ +void string_in_msg(string_ptr,start) /* AN000 */ + +char far *string_ptr; /* AN000 */ +unsigned start; /* AN000 */ + +BEGIN /* AN000 */ + +unsigned i; /* AN000 */ + + /* init the 8 spots to blanks */ + for (i = u(0); i < u(8);i++) /* AN000 */ + BEGIN /* AN000 */ + insert[start+i] = c(' '); /* AN000 */ + END /* AN000 */ + /* Put characters into the array */ + BEGIN /* AN000 */ + insert[start+0] = *(string_ptr+0); /* AN000 */ + insert[start+1] = *(string_ptr+1); /* AN000 */ + insert[start+2] = *(string_ptr+2); /* AN000 */ + insert[start+3] = *(string_ptr+3); /* AN000 */ + insert[start+4] = *(string_ptr+4); /* AN000 */ + insert[start+5] = *(string_ptr+5); /* AN000 */ + insert[start+6] = *(string_ptr+6); /* AN000 */ + insert[start+7] = *(string_ptr+7); /* AN000 */ + END /* AN000 */ + return; /* AN000 */ +END /* AN000 */ + + +/* */ +void volume_in_msg(string_ptr,start) /* AN000 */ + +char far *string_ptr; /* AN000 */ +unsigned start; /* AN000 */ + +BEGIN /* AN000 */ + +unsigned i; /* AN000 */ + + /* init the 11 spots to blanks */ + for (i = u(0); i < u(11);i++) /* AN000 */ + BEGIN /* AN000 */ + insert[start+i] = c(' '); /* AN000 */ + END /* AN000 */ + /* Put characters into the array */ + BEGIN /* AN000 */ + insert[start+0] = *(string_ptr+0); /* AN000 */ + insert[start+1] = *(string_ptr+1); /* AN000 */ + insert[start+2] = *(string_ptr+2); /* AN000 */ + insert[start+3] = *(string_ptr+3); /* AN000 */ + insert[start+4] = *(string_ptr+4); /* AN000 */ + insert[start+5] = *(string_ptr+5); /* AN000 */ + insert[start+6] = *(string_ptr+6); /* AN000 */ + insert[start+7] = *(string_ptr+7); /* AN000 */ + insert[start+8] = *(string_ptr+8); /* AN000 */ + insert[start+9] = *(string_ptr+9); /* AN000 */ + insert[start+10] = *(string_ptr+10); /* AN000 */ + END /* AN000 */ + return; /* AN000 */ +END /* AN000 */ + diff --git a/v4.0/src/CMD/FDISK/DOS.H b/v4.0/src/CMD/FDISK/DOS.H new file mode 100644 index 0000000..6d622b6 --- /dev/null +++ b/v4.0/src/CMD/FDISK/DOS.H @@ -0,0 +1,81 @@ +/* dos.h + * + * Defines the structs and unions used to handle the input and output + * registers for the DOS interface routines defined in the V2.0 to V3.0 + * compatability package. It also includes macros to access the segment + * and offset values of MS C "far" pointers, so that they may be used by + * these routines. + * + */ + +/* word registers */ + +struct WORDREGS { + unsigned ax; + unsigned bx; + unsigned cx; + unsigned dx; + unsigned si; + unsigned di; + unsigned cflag; + }; + +/* byte registers */ + +struct BYTEREGS { + unsigned char al, ah; + unsigned char bl, bh; + unsigned char cl, ch; + unsigned char dl, dh; + }; + +/* general purpose registers union - overlays the corresponding word and + * byte registers. + */ + +union REGS { + struct WORDREGS x; + struct BYTEREGS h; + }; + +/* segment registers */ + +struct SREGS { + unsigned es; + unsigned cs; + unsigned ss; + unsigned ds; + }; + +/* dosexterror struct */ + +struct DOSERROR { + int exterror; + char class; + char action; + char locus; + }; + +/* macros to break MS C "far" pointers into their segment and offset + * components + */ + +#define FP_SEG(fp) (*((unsigned *)&(fp) + 1)) +#define FP_OFF(fp) (*((unsigned *)&(fp))) + +/* function declarations for those who want strong type checking + * on arguments to library function calls + */ + +#ifdef LINT_ARGS /* arg. checking enabled */ + +int bdos(int, unsigned int, unsigned int); +int dosexterr(struct DOSERROR *); +int intdos(union REGS *, union REGS *); +int intdosx(union REGS *, union REGS *, struct SREGS *); +int int86(int, union REGS *, union REGS *); +int int86x(int, union REGS *, union REGS *, struct SREGS *); +void segread(struct SREGS *); + +#endif /* LINT_ARGS */ + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/DOSCALL.H b/v4.0/src/CMD/FDISK/DOSCALL.H new file mode 100644 index 0000000..295cec6 --- /dev/null +++ b/v4.0/src/CMD/FDISK/DOSCALL.H @@ -0,0 +1,2811 @@ +/*static char *SCCSID = "@(#)doscall.h 6.25 86/06/03";*/ +/*** doscall.h + * + * Shirleyd + * (C) Copyright 1988 Microsoft Corporation + * 12/13/85 + * + * Description: + * + * Function declarations to provide strong type checking + * on arguments to DOS 4.0 function calls + * + * Major Modifications 04/28/86 by S. S. + * Major Modifications 04/30/86 by K. D. + * Minor Modifications 04/30/86 by S. S. (DosTimerAsync/Start) + * Major Modifications 05/01/86 by S. S. (fix Sems,add Queues) + * Minor Modifications 05/14/86 by K. D. (DosFileLocks) + * Minor Modifications 05/16/86 by S. S. (NLS routines) + * Minor Modifications 05/20/86 by S. S. (Get/SetPrty,CreateThread) + * Minor Modifications 05/20/86 by S. S. (add DosSetVector) + * Minor Modifications 06/02/86 by S. S. (GetHugeShift, MuxSemWait) + * Major Modifications 06/03/86 by S. S. (Mouse calls) + */ + + + +/*** CursorData - structure that contains the characteristics + * of the cursor + */ + +struct CursorData { + unsigned cur_start; /* Cursor start line */ + unsigned cur_end; /* Cursor end line */ + unsigned cur_width; /* Cursor width */ + unsigned cur_attribute; /* Cursor attribute */ + }; + + + +/*** DateTime - structure for date and time */ + +struct DateTime { + unsigned char hour; /* current hour */ + unsigned char minutes; /* current minute */ + unsigned char seconds; /* current second */ + unsigned char hundredths; /* current hundredths of a second */ + unsigned char day; /* current day */ + unsigned char month; /* current month */ + unsigned year; /* current year */ + unsigned timezone; /* minutes of time west of GMT */ + unsigned char day_of_week; /* current day of week */ + }; + + + +/*** FileFindBuf - structure of area where the filesystem driver + * returns the results of the search + */ + +struct FileFindBuf { + unsigned create_date; /* date of file creation */ + unsigned create_time; /* time of file creation */ + unsigned access_date; /* date of last access */ + unsigned access_time; /* time of last access */ + unsigned write_date; /* date of last write */ + unsigned write_time; /* time of last write */ + unsigned long file_size; /* file size (end of data) */ + unsigned long falloc_size; /* file allocated size */ + unsigned attributes; /* attributes of the file */ + char string_len; /* returned length of ascii name str. */ + /* length does not include null byte */ + char file_name[12]; /* name string */ + }; + + +/*** FileStatus - structure of information list used by DosQFileInfo */ + +struct FileStatus { + unsigned create_date; /* date of file creation */ + unsigned create_time; /* time of file creation */ + unsigned access_date; /* date of last access */ + unsigned access_time; /* time of last access */ + unsigned write_date; /* date of last write */ + unsigned write_time; /* time of last write */ + unsigned long file_size; /* file size (end of data) */ + unsigned long falloc_size; /* file allocated size */ + unsigned block_size; /* blocking factor */ + unsigned attributes; /* attributes of the file */ + }; + + +/*** FSAllocate - structure of file system allocation */ + +struct FSAllocate { + unsigned long filsys_id; /* file system ID */ + unsigned long sec_per_unit; /* number sectors per allocation unit */ + unsigned long num_units; /* number of allocation units */ + unsigned long avail_units; /* avaliable allocation units */ + unsigned bytes_sec; /* bytes per sector */ + }; + + + +/*** KbdStatus - structure in which the keyboard support will information */ + +struct KbdStatus { + unsigned length; /* length in words of data structure */ + unsigned bit_mask; /* bit mask */ + unsigned turn_around_char; /* turnaround character */ + unsigned interim_char_flags; /* interim character flags */ + unsigned shift_state; /* shift state */ + }; + + + +/*** KeyData - structure that contains character data */ + +struct KeyData { + char char_code; /* ASCII character code */ + char scan_code; /* scan code */ + char status; /* indicates state of the character */ + unsigned shift_state; /* state of the shift keys */ + unsigned long time; /* time stamp of the keystroke */ + }; + + + +/*** ModeData - structure that contains characteristics of the mode */ + +struct ModeData { + unsigned length; /* Length of structure */ + char type; /* Text or graphics */ + char color; /* Color or monochrome */ + unsigned col; /* Column resolution */ + unsigned row; /* Row resolution */ + unsigned hres; /* horizontal resolution */ + unsigned vres; /* vertical resolution */ + }; + + + + +/*** ProcIDsArea - structure of the address of the area where the + * ID's will be placed + */ + +struct ProcIDsArea { + unsigned procid_cpid; /* current process' process ID */ + unsigned procid_ctid; /* current process' thread ID */ + unsigned procid_ppid; /* process ID of the parent */ + }; + + + +/*** PVBData - structure that contains information about the + * physical video buffer + */ + +struct PVBData { + unsigned pvb_size; /* size of the structure */ + unsigned long pvb_ptr; /* returns pointer to the pvb buffer */ + unsigned pvb_length; /* length of PVB */ + unsigned pvb_rows; /* buffer dimension (rows) */ + unsigned pvb_cols; /* buffer dimension (cols) */ + char pvb_type; /* color or mono */ + }; + + + +/*** SchedParmsArea - structure of address in which the scheduler + * parms will be placed + */ + +struct SchedParmsArea { + char dynvar_flag; /* dynamic variation flag, 1=enabled */ + char maxwait; /* maxwait (sec) */ + unsigned mintime; /* minimum timeslice (ms) */ + unsigned maxtime; /* maximum timeslice (ms) */ + }; + + + +/*** Tasking Processes: + * + * DosCreateThread + * DosCwait + * DosEnterCritSec + * DosExecPgm + * DosExit + * DosExitCritSec + * DosExitList + * DosGetPID + * DosGetPrty + * DosGetSchedParms + * DosSetFgnd + * DosSetPrty + * DosKillProcess + */ + + + +/*** DosCreateThread - Create another thread of execution + * + * Creates an asynchronous thread of execution under the + * current process + */ + +extern unsigned far pascal DOSCREATETHREAD ( + void (far *)(void), /* Starting Address for new thread */ + unsigned far *, /* Address to put new thread ID */ + unsigned char far * ); /* Address of stack for new thread */ + + + +/*** DosCwait - Wait for child termination + * + * Places the current thread in a wait state until a child process + * has terminated, then returns the ending process' process ID and + * termination code. + */ + +extern unsigned far pascal DOSCWAIT ( + unsigned, /* Action (execution) codes */ + unsigned, /* Wait options */ + unsigned far *, /* Address to put result code */ + unsigned far *, /* Address to put process ID */ + unsigned ); /* ProcessID of process to wait for */ + + + +/*** DosEnterCritSec - Enter critical section of execution + * + * Disables thread switching for the current process + */ + +extern void far pascal DOSENTERCRITSEC (void); + + + +/*** DosExecPgm - Execute a program + * + * Allows a program to request another program be executed as a + * child process. The requestor's process may optionally continue + * to execute asynchronous to the new program + */ + +extern unsigned far pascal DOSEXECPGM ( + unsigned, /* 0=synchronous, 1=asynchronous with */ + /* return code discarded, 2=async */ + /* with return code saved */ + unsigned, /* Trace process */ + char far *, /* Address of argument string */ + char far *, /* Address of environment string */ + unsigned far *, /* Address to put Process ID */ + char far * ); /* Address of program filename */ + + + +/*** DosExit - Exit a program + * + * This call is issued when a thread completes its execution. + * The current thread is ended. + */ + +extern void far pascal DOSEXIT ( + unsigned, /* 0=end current thread, 1=end all */ + unsigned ); /* Result Code to save for DosCwait */ + + + +/*** DosExitCritSec - Exit critical section of execution + * + * Re-enables thread switching for the current process + */ + +extern void far pascal DOSEXITCRITSEC (void); + + + +/*** DosExitList - Routine list for process termination + * + * Maintains a list of routines which are to be executed when the + * current process ends, normally or otherwise + */ + +extern unsigned far pascal DOSEXITLIST ( + unsigned, /* Function request code */ + void (far *)(void) ); /* Address of routine to be executed */ + + + +/*** DosGetPID - Return process ID + * + * Returns the current process's process ID (PID), thread ID, + * and the PID of the process that spawned it + */ + +extern void far pascal DOSGETPID ( + struct ProcIDsArea far *); /* ProcID structure */ + + + +/*** DosGetPrty - Get Process's Priority + * + * Allows the caller to learn the priority of a process or thread + */ + +extern unsigned far pascal DOSGETPRTY ( + unsigned, /* Indicate thread or process ID */ + unsigned far *, /* Address to put priority */ + unsigned ); /* PID of process/thread of interest */ + + + +/*** DosGetSchedParms - Get scheduler's parameters + * + * Gets the scheduler's current configuration parameters + */ + +extern void far pascal DOSGETSCHEDPARMS ( + struct SchedParmsArea far * ); /* Address to put parameters */ + + + +/*** DosSetFgnd - Set Foreground Process + * + * Allows the session manager to designate which process + * is to receive favored dispatching + */ + +extern unsigned far pascal DOSSETFGND ( + unsigned ); /* Process ID of target process */ + + + +/*** DosSetPrty - Set Process Priority + * + * Allows the caller to change the base priority or priority + * class of a child process or a thread in the current process + */ + +extern unsigned far pascal DOSSETPRTY ( + unsigned, /* Indicate scope of change */ + unsigned, /* Priority class to set */ + unsigned, /* Priority delta to apply */ + unsigned ); /* Process or Thread ID of target */ + + + +/*** DosKillProcess - Terminate a Process + * + * Terminates a child process and returns its termination code + * to its parent (if any) + */ + +extern unsigned far pascal DOSKILLPROCESS ( + unsigned, /* 0=kill child processes also, */ + /* 1=kill only indicated process */ + unsigned ); /* Process ID of process to end */ + + + + +/*** Asynchronous Notification (Signals): + * + * DosHoldSignal + * DosSendSignal + * DosSetSigHandler + */ + + + +/*** DosHoldSignal - Disable / Enable signals + * + * Used to termporarily disable or enable signal processing + * for the current process. + */ + +extern void far pascal DOSHOLDSIGNAL ( + unsigned ); /* 0=enable signal, 1=disable signal */ + + + +/*** DosSendSignal - Issue signal + * + * Used to send a signal event to an arbitrary process or + * command subtree. + */ + +extern unsigned far pascal DOSSENDSIGNAL ( + unsigned, /* Process ID to signal */ + unsigned, /* 0=notify entire subtree, 1=notify */ + /* only the indicated process */ + unsigned, /* Signal argument */ + unsigned ); /* Signal number */ + + + +/*** DosSetSigHandler - Handle Signal + * + * Notifies CP/DOS of a handler for a signal. It may also be used + * to ignore a signal or install a default action for a signal. + */ + +extern unsigned far pascal DOSSETSIGHANDLER ( + void (far *)(), /* Signal handler address */ + unsigned long far *, /* Address of previous handler */ + unsigned far *, /* Address of previous action */ + unsigned, /* Indicate request type */ + unsigned ); /* Signal number */ + + + + +/*** Pipes: + * + * DosMakePipe + */ + + + +/*** DosMakePipe - Create a Pipe */ + +extern unsigned far pascal DOSMAKEPIPE ( + unsigned far *, /* Addr to place the read handle */ + unsigned far *, /* Addr to place the write handle */ + unsigned ); /* Size to reserve for the pipe */ + + + + +/*** Queues: + * + * DosCloseQueue + * DosCreateQueue + * DosOpenQueue + * DosPeekQueue + * DosPurgeQueue + * DosQueryQueue + * DosReadQueue + * DosWriteQueue + */ + +/*** DosCloseQueue - Close a Queue + * + * close a queue which is in use by the requesting process + * + */ + +extern unsigned far pascal DOSCLOSEQUEUE ( + unsigned ) ; /* queue handle */ + + +/*** DosCreateQueue - Create a Queue + * + * creates a queue to be owned by the requesting process + * + */ + +extern unsigned far pascal DOSCREATEQUEUE ( + unsigned far *, /* queue handle */ + unsigned, /* queue priority */ + char far * ) ; /* queue name */ + + +/*** DosOpenQueue - Open a Queue + * + * opens a queue for the current process + * + */ + +extern unsigned far pascal DOSOPENQUEUE ( + unsigned far *, /* PID of queue owner */ + unsigned far *, /* queue handle */ + char far * ) ; /* queue name */ + + + +/*** DosPeekQueue - Peek at a Queue + * + * retrieves an element from a queue without removing it from the queue + * + */ + +extern unsigned far pascal DOSPEEKQUEUE ( + unsigned, /* queue handle */ + unsigned long far *, /* pointer to request */ + unsigned far *, /* length of datum returned */ + unsigned long far *, /* pointer to address of datum */ + unsigned far *, /* indicator of datum returned */ + unsigned char, /* wait indicator for empty queue */ + unsigned char far *, /* priority of element */ + unsigned long ) ; /* semaphore handle */ + + + +/*** DosPurgeQueue - Purge a Queue + * + * purges all elements from a queue + * + */ + +extern unsigned far pascal DOSPURGEQUEUE ( + unsigned ) ; /* queue handle */ + + + +/*** DosQueryQueue - Query size of a Queue + * + * returns the number of elements in a queue + * + */ + +extern unsigned far pascal DOSQUERYQUEUE ( + unsigned, /* queue handle */ + unsigned far * ); /* pointer for number of elements */ + + + +/*** DosReadQueue - Read from a Queue + * + * retrieves an element from a queue + * + */ + +extern unsigned far pascal DOSREADQUEUE ( + unsigned, /* queue handle */ + unsigned long far *, /* pointer to request */ + unsigned far *, /* length of datum returned */ + unsigned long far *, /* pointer to address of datum */ + unsigned, /* indicator of datum returned */ + unsigned char, /* wait indicator for empty queue */ + unsigned char far *, /* priority of element */ + unsigned long ) ; /* semaphore handle */ + + + +/*** DosWriteQueue - Write to a Queue + * + * adds an element to a queue + * + */ + +extern unsigned far pascal DOSWRITEQUEUE ( + unsigned, /* queue handle */ + unsigned, /* request */ + unsigned, /* length of datum */ + unsigned char far *, /* address of datum */ + unsigned char ); /* priority of element */ + + + + + +/*** Semaphores: + * + * DosSemClear + * DosSemRequest + * DosSemSet + * DosSemWait + * DosSemSetWait + * DosMuxSemWait + * DosCloseSem + * DosCreatSem + * DosOpenSem + */ + + + +/*** DosSemClear - Unconditionally clears a semaphore + * + * Unconditionally clears a semaphore; i.e., sets the + * state of the specified semaphore to unowned. + */ + +extern unsigned far pascal DOSSEMCLEAR ( + unsigned long ); /* semaphore handle */ + + + +/*** DosSemRequest - Wait until next DosSemClear + * + * Blocks the current thread until the next DosSemClear is + * issued to the indicated semaphore + */ + +extern unsigned far pascal DOSSEMREQUEST ( + unsigned long, /* semaphore handle */ + unsigned long ); /* Timeout, -1=no timeout, */ + /* 0=immediate timeout, >1=number ms */ + + +/*** DosSemSet - Unconditionally take a semaphore + * + * Unconditionally takes a semaphore; i.e., sets the status + * of the specified semaphore to owned. + */ + +extern unsigned far pascal DOSSEMSET ( + unsigned long ); /* semaphore handle */ + + + +/*** DosSemSetWait - Wait for a semaphore to be cleared and set it + * + * Blocks the current thread until the indicated semaphore is + * cleared and then establishes ownership of the semaphore + */ + +extern unsigned far pascal DOSSEMSETWAIT ( + unsigned long, /* semaphore handle */ + unsigned long ); /* Timeout, -1=no timeout, */ + /* 0=immediate timeout, >1=number ms */ + + +/*** DosSemWait - Wait for a semaphore to be cleared + * + * Blocks the current thread until the indicated semaphore is + * cleared but does not establish ownership of the semaphore + */ + +extern unsigned far pascal DOSSEMWAIT ( + unsigned long, /* semaphore handle */ + unsigned long ); /* Timeout, -1=no timeout, */ + /* 0=immediate timeout, >1=number ms */ + + +/*** DosMuxSemWait - Wait for 1 of N semaphores to be cleared + * + * Blocks the current thread until the indicated semaphore is + * cleared but does not establish ownership of the semaphore + */ + +extern unsigned far pascal DOSMUXSEMWAIT ( + unsigned far *, /* address for event index number */ + unsigned far *, /* list of semaphores */ + unsigned long ); /* Timeout, -1=no timeout, */ + /* 0=immediate timeout, >1=number ms */ + + + +/*** DosCloseSem - Close a system semaphore + * + * closed the specified system semaphore + */ + +extern unsigned far pascal DOSCLOSESEM ( + unsigned long ); /* semaphore handle */ + + + +/*** DosCreateSem - Create a system semaphore + * + * create a system semaphore + */ + +extern unsigned far pascal DOSCREATESEM ( + unsigned, /* =0 indicates exclusive ownership */ + unsigned long far *, /* address for semaphore handle */ + char far * ); /* name of semaphore */ + + +/*** DosOpenSem - Open a system semaphore + * + * open a system semaphore + */ + +extern unsigned far pascal DOSOPENSEM ( + unsigned long far *, /* address for semaphore handle */ + char far * ); /* name of semaphore */ + + + + +/*** Timer Services: + * + * DosGetDateTime + * DosSetDateTime + * DosSleep + * DosGetTimerInt + * DosTimerAsync + * DosTimerStart + * DosTimerStop + */ + + + +/*** DosGetDateTime - Get the current date and time + * + * Used to get the current date and time that are maintained by + * the operating system + */ + +extern unsigned far pascal DOSGETDATETIME ( + struct DateTime far * ); + + + +/*** DosSetDateTime - Set the current date and time + * + * Used to set the date and time that are maintained by the + * operating system + */ + +extern unsigned far pascal DOSSETDATETIME ( + struct DateTime far * ); + + + +/*** DosSleep - Delay Process Execution + * + * Suspends the current thread for a specified interval of time, + * or if the requested interval is '0', simply gives up the + * remainder of the current time slice. + */ + +extern unsigned far pascal DOSSLEEP ( + unsigned long ); /* TimeInterval - interval size */ + + + +/*** DosGetTimerInt - Get the timer tick interval in 1/10000 sec. + * + * Gets a word that contains the timer tick interval in ten + * thousandths of a second. This is the amount of time that + * elapses with every timer tick + */ + +extern unsigned far pascal DOSGETTIMERINT ( + unsigned far * ); /* interval size */ + + + +/*** DosTimerAsync - Start an asynchronous time delay + * + * Starts a timer that runs asynchronously to the thread issuing + * the request. It sets a RAM semaphore which can be used by the + * wait facility + */ + +extern unsigned far pascal DOSTIMERASYNC ( + unsigned long, /* Interval size */ + unsigned long, /* handle of semaphore */ + unsigned far * ); /* handle of timer */ + + + +/*** DosTimerStart - Start a Periodic Interval Timer + * + * Starts a periodic interval timer that runs asynchronously to + * the thread issuing the request. It sets a RAM semaphore which + * can be used by the wait facility. The semaphore is continually + * signalled at the specified time interval until the timer is + * turned off by DosTimerStop + */ + +extern unsigned far pascal DOSTIMERSTART ( + unsigned long, /* Interval size */ + unsigned long, /* handle of semaphore */ + unsigned far * ); /* handle of timer */ + + + +/*** DosTimerStop - Stop an interval timer + * + * Stops an interval timer that was started by DosTimerStart + */ + +extern unsigned far pascal DOSTIMERSTOP ( + unsigned ); /* Handle of the timer */ + + + + +/*** Memory Management: + * + * DosAllocSeg + * DosAllocShrSeg + * DosGetShrSeg + * DosReallocSeg + * DosFreeSeg + * DosAllocHuge + * DosGetHugeShift + * DosReallocHuge + * DosCreateCSAlias + */ + + + +/*** DosAllocSeg - Allocate Segment + * + * Allocates a segment of memory to the requesting process. + */ + +extern unsigned far pascal DOSALLOCSEG ( + unsigned, /* Number of bytes requested */ + unsigned far *, /* Selector allocated (returned) */ + unsigned ); /* Indicator for sharing */ + + + +/*** DosAllocShrSeg - Allocate Shared Segment + * + * Allocates a shared memory segment to a process. + */ + +extern unsigned far pascal DOSALLOCSHRSEG ( + unsigned, /* Number of bytes requested */ + char far *, /* Name string */ + unsigned far * ); /* Selector allocated (returned) */ + + + +/*** DosGetShrSeg - Access Shared Segment + * + * Allows a process to access a shared memory segment previously + * allocated by another process. The reference count for the + * shared segment is incremented. + */ + +extern unsigned far pascal DOSGETSHRSEG ( + char far *, /* Name string */ + unsigned far * ); /* Selector (returned) */ + + + +/*** DosGiveSeg - Give access to Segment + * + * Gives another process access to a shares memory segment + */ + +extern unsigned far pascal DOSGIVESEG ( + unsigned, /* Caller's segment handle */ + unsigned, /* Process ID of recipient */ + unsigned far * ); /* Recipient's segment handle */ + + + +/*** DosReallocSeg - Change Segment Size + * + * Changes the size of a segment already allocated. + */ + +extern unsigned far pascal DOSREALLOCSEG ( + unsigned, /* New size requested in bytes */ + unsigned ); /* Selector */ + + + +/*** DosFreeSeg - Free a Segment + * + * Deallocates a segment + */ + +extern unsigned far pascal DOSFREESEG ( + unsigned ); /* Selector */ + + + +/*** DosAllocHuge - Allocate Huge Memory + * + * Allocates memory greater than the maximum segment size + */ + +extern unsigned far pascal DOSALLOCHUGE ( + unsigned, /* Number of 65536 byte segments */ + unsigned, /* Number of bytes in last segment */ + unsigned far *, /* Selector allocated (returned) */ + unsigned ); /* Max number of 65536-byte segments */ + + + +/*** DosGetHugeShift - Get shift count used with Huge Segments + * + * Returns the shift count used in deriving selectors + * to address memory allocated by DosAllocHuge. + */ + +extern unsigned far pascal DOSGETHUGESHIFT ( + unsigned far *); /* Shift Count (returned) */ + + + +/*** DosReallocHuge - Change Huge Memory Size + * + * Changes the size of memory originally allocated by DosAllocHuge + */ + +extern unsigned far pascal DOSREALLOCHUGE ( + unsigned, /* Number of 65536 byte segments */ + unsigned, /* Number of bytes in last segment */ + unsigned ); /* Selector */ + + + +/*** DosCreateCSAlias - Create CS Alias + * + * Creates an alias descriptor for a data type descriptor passed + * as input. The type of the new descriptor is executable. + */ + +extern unsigned far pascal DOSCREATECSALIAS ( + unsigned, /* Data segment selector */ + unsigned far * ); /* Code segment selector (returned) */ + + + + +/*** Memory Sub-Allocation Package (MSP) + * + * DosSubAlloc + * DosSubFree + * DosSubSet + */ + + + +/*** DosSubAlloc - Allocate Memory + * + * Allocates memory from a segment previously allocated by + * DosAllocSeg or DosAllocShrSeg and initialized by DosSubSet + */ + +extern unsigned far pascal DOSSUBALLOC ( + unsigned, /* Segment selector */ + unsigned far *, /* Address of block offset */ + unsigned ); /* Size of requested block */ + + + +/*** DosSubFree - Free Memory + * + * Frees memory previously allocated by DosSubAlloc + */ + +extern unsigned far pascal DOSSUBFREE ( + unsigned, /* Segment selector */ + unsigned, /* Offset of memory block to free */ + unsigned ); /* Size of block in bytes */ + + + +/*** DosSubSet - Initialize or Set Allocated Memory + * + * Can be used either to initialize a segment for sub-allocation + * of to notify MSP of a change in the size of a segment already + * initialized. + */ + +extern unsigned far pascal DOSSUBSET ( + unsigned, /* Segment selector */ + unsigned, /* Parameter flags */ + unsigned ); /* New size of the block */ + + + + +/*** Program Execution Control: + * + * DosLoadModule + * DosFreeModule + * DosGetProcAddr + * DosGetModHandle + * DosGetModName + */ + + + +/*** DosLoadModule - Load Dynamic Link Routines + * + * Loads a dynamic link module and returns a handle for the module + */ + +extern unsigned far pascal DOSLOADMODULE ( + char far *, /* Module name string */ + unsigned far * ); /* Module handle (returned) */ + + + +/*** DosFreeModule - Free Dynamic Link Routines + * + * Frees the reference to the dynamic link module for this process. + * If the dynamic link module is no longer used by any process, the + * module will be freed from system memory. + */ + +extern unsigned far pascal DOSFREEMODULE ( + unsigned ); /* Module handle */ + + + +/*** DosGetProcAddr - Get Dynamic Link Procedure Address + * + * Retruns a far address to the desired procedure within a dynamic + * link module. + */ + +extern unsigned far pascal DOSGETPROCADDR ( + unsigned, /* Module handle */ + char far *, /* Module name string */ + unsigned long far * ); /* Procedure address (returned) */ + + + +/*** DosGetModHandle - Get Dynamic Link Module Handle + * + * Returns the handle to a dynamic link module that was previously + * loaded. The interface provides a mechanism for testing whether + * a dynamic link module is already loaded. + */ + +extern unsigned far pascal DOSGETMODHANDLE ( + char far *, /* Module name string */ + unsigned far *); /* Module handle (returned) */ + + + +/*** DosGetModName - Get Dynamic Link Module Name + * + * returns the fully qualified drive, path, filename, and + * extension associated with the referenced modul handle + */ + +extern unsigned far pascal DOSGETMODNAME ( + unsigned, /* Module handle */ + unsigned, /* Maximum buffer length */ + unsigned far * ); /* Buffer (returned) */ + + + + +/*** Device I/O Services: + * + * DosBeep + * DosDevConfig + * DosDevIOCtl + * DosScrDirectIO + * DosScrRedrawWait + * DosScrLock + * DosScrUnLock + * DosSGInit + * DosSGNum + * DosSGRestore + * DosSGSave + * DosSGSwitch + * DosSGSwitchMe + * DosVioAttach + * DosVioRegister + * KbdCharIn + * KbdFlushBuffer + * KbdGetStatus + * KbdPeek + * KbdSetStatus + * KbdStringIn + * VioRegister + * VioFreePhysBuf + * VioGetBuf + * VioGetCurPos + * VioGetCurType + * VioGetMode + * VioGetPhysBuf + * VioReadCellStr + * VioReadCharStr + * VioScrollDn + * VioScrollUp + * VioScrollLf + * VioScrollRt + * VioSetCurPos + * VioSetCurType + * VioSetMode + * VioShowBuf + * VioWrtCellStr + * VioWrtCharStr + * VioWrtCharStrAtt + * VioWrtNAttr + * VioWrtNCell + * VioWrtNChar + * VioWrtTTY + * VioSetANSI + * VioGetANSI + * VioPrtScreen + * VioSaveRedrawWait + * VioSaveRedrawWaitUndo + * VioScrLock + * VioScrUnlock + * VioSetMnLockTime + * VioSetMXSaveTime + * VioGetTimes + * VioPopUp + * VioEndPopUp + */ + + + +/*** DosBeep - Generate Sound From Speaker */ + +extern unsigned far pascal DOSBEEP ( + unsigned, /* Hertz (25H-7FFFH) */ + unsigned ); /* Length of sound in ms */ + + + +/*** DosDevConfig - Get Device Configurations + * + * Get information about attached devices + */ + +extern unsigned far pascal DOSDEVCONFIG ( + unsigned char far *, /* Returned information */ + unsigned, /* Item number */ + unsigned ); /* Reserved */ + + + +/*** DosDevIOCtl - Preform Control Functions Directly On Device + * + * Control functions on the device specified by the opened + * handle + */ + +extern unsigned far pascal DOSDEVIOCTL ( + char far *, /* Data area */ + char far *, /* Command-specific argument list */ + unsigned, /* Device-specific function code */ + unsigned, /* Device category */ + unsigned ); /* Device handle returned by Open */ + + + +/*** DosScrDirectIO - Direct Screen I/O + * + * Indicate direct screen I/O + */ + +extern unsigned far pascal DOSSCRDIRECTIO ( + unsigned ); /* Indicates state of direct I/O */ + /* 0=on, 1=off */ + + + +/*** DosScrRedrawWait - Screen Refresh + * + * Wait for notification to refresh or redraw screen + */ + +extern unsigned far pascal DOSSCRREDRAWWAIT (void); + + + +/*** DosScrLock - Lock Screen + * + * Lock the screen for I/O + */ + +extern unsigned far pascal DOSSCRLOCK ( + unsigned, /* Block or not - 0=return if */ + /* screen unavailable, 1=wait */ + unsigned far *); /* Return status of lock - */ + /* 0=sucessful, 1=unsuccessful */ + + + +/*** DosScrUnLock - Unlock Screen + * + * Unlock the screen for I/O + */ + +extern unsigned far pascal DOSSCRUNLOCK (void) ; + + + +/*** DosSGInit - Initialize Screen Group + * + * Initialize the specified screen group + */ + +extern unsigned far pascal DOSSGINIT ( + unsigned ); /* Number of screen group */ + + + +/*** DosSGNum - Get Number of Screen Groups + * + * Get the number of screen groups + */ + +extern unsigned far pascal DOSSGNUM ( + unsigned far *); /* Total number of screen groups */ + + + +/*** DosSGRestore - Restore Screen Group + * + * Restore the current screen group + */ + +extern unsigned far pascal DOSSGRESTORE (void); + + + +/*** DosSGSave - Save Screen Group + * + * Save the current screen group + */ + +extern unsigned far pascal DOSSGSAVE (void); + + + +/*** DosSGSwitch - Switch Screen Groups + * + * Switch the specified screen group to the active screen group + */ + +extern unsigned far pascal DOSSGSWITCH ( + unsigned ); /* Number of screen group */ + + + +/*** DosSGSwitchMe - Put Process in Screen Group + * + * Switch the caller into the specified screen group + */ + +extern unsigned far pascal DOSSGSWITCHME ( + unsigned ); /* Number of screen groups */ + + + +/*** DosVioAttach - Attach to Video Subsystem + * + * Attach to the current video subsystem for the current screen + * group. This must be done prior to using any VIO functions. + */ + +extern unsigned far pascal DOSVIOATTACH (void); + + + +/*** DosVioRegister - Register Video Subsystem + * + * Register a video subsystem for a screen group + */ + +extern unsigned far pascal DOSVIOREGISTER ( + char far *, /* Module name */ + char far * ); /* Table of entries supported by */ + /* the VIO dynamic link module */ + + + +/*** KbdCharIn - Read Character, Scan Code + * + * Return a character and scan code from the standard input device + */ + +extern unsigned far pascal KBDCHARIN ( + struct KeyData far *, /* Buffer for character code */ + unsigned, /* I/O wait - 0=wait for a */ + /* character, 1=no wait */ + unsigned ); /* keyboard handle */ + + + +/*** KbdFlushBuffer - Flush Keystroke Buffer + * + * Clear the keystroke buffer + */ + +extern unsigned far pascal KBDFLUSHBUFFER ( + unsigned ); /* keyboard handle */ + + + +/*** KbdGetStatus - Get Keyboard Status + * + * Gets the current state of the keyboard. + */ + +extern unsigned far pascal KBDGETSTATUS ( + struct KbdStatus far *, /* data structure */ + unsigned ); /* Keyboard device handle */ + + + +/*** KbdPeek - Peek at Character, Scan Code + * + * Return the character/scan code, if available, from the + * standard input device without removing it from the buffer. + */ + +extern unsigned far pascal KBDPEEK ( + struct KeyData far *, /* buffer for data */ + unsigned ); /* keyboard handle */ + + + +/*** KbdSetStatus - Set Keyboard Status + * + * Sets the characteristics of the keyboard. + */ + +extern unsigned far pascal KBDSETSTATUS ( + struct KbdStatus far *, /* data structure */ + unsigned ); /* device handle */ + + + +/*** KbdStringIn - Read Character String + * + * Read a character string (character codes only) from the + * standard input device. The character string may optionally + * be echoed at the standard output device if the echo mode + * is set (KbdSetEchoMode) + */ + +extern unsigned far pascal KBDSTRINGIN ( + char far *, /* Char string buffer */ + unsigned far *, /* Length of buffer */ + unsigned, /* I/O wait- 0=wait for a */ + /* character, 1=no wait */ + unsigned ); /* keyboard handle */ + + + +/*** VioRegister - Register Video Subsystem + * + * Register a video subsystem within a screen group + * + */ + +extern unsigned far pascal VIOREGISTER ( + char far *, /* Module name */ + char far *, /* Entry Point name */ + unsigned long, /* Function mask 1 */ + unsigned long ); /* Function mask 2 */ + + + +/*** VioFreePhysBuf - Free Physical Video Buffer + * + * Release the physical video buffer + */ + +extern unsigned far pascal VIOFREEPHYSBUF ( + char far * ); /* Physical video buffer */ + + + +/*** VioGetBuf - Get Logical Video Buffer + * + * Return the address of the logical video buffer + */ + +extern unsigned far pascal VIOGETBUF ( + unsigned long far *, /* Will point to logical video buffer */ + unsigned far *, /* Length of Buffer */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetCurPos - Get Cursor Position + * + * Return the cursor position + */ + +extern unsigned far pascal VIOGETCURPOS ( + unsigned far *, /* Current row position */ + unsigned far *, /* Current column position */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetCurType - Get Cursor Type + * + * Return the cursor type + */ + +extern unsigned far pascal VIOGETCURTYPE ( + struct CursorData far *, /* Cursor characteristics */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetMode - Get Display Mode + * + * Return the mode of the display + */ + +extern unsigned far pascal VIOGETMODE ( + struct ModeData far *, /* Length of Buffer */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetPhysBuf - Get Physical Video Buffer + * + * Return the address of the physical video buffer + */ + +extern unsigned far pascal VIOGETPHYSBUF ( + char far *, /* Buffer start address */ + char far *, /* Buffer end address */ + unsigned far *, /* Address of selector list */ + unsigned ); /* Length of selector list */ + + + +/*** VioReadCellStr - Read Character/Attributes String + * + * Read a string of character/attributes (or cells) from the + * screen starting at the specified location. + */ + +extern unsigned far pascal VIOREADCELLSTR ( + char far *, /* Character Buffer */ + unsigned far *, /* Length of cell string buffer */ + unsigned, /* Starting location (row) */ + unsigned, /* Starting location (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioReadCharStr - Read Character String + * + * Read a character string from the display starting at the + * current cursor position + */ + +extern unsigned far pascal VIOREADCHARSTR ( + char far *, /* Character Buffer */ + unsigned far *, /* Length of cell string buffer */ + unsigned, /* Starting location (row) */ + unsigned, /* Starting location (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrollDn - Scroll Screen Down + * + * Scroll the current screen down + */ + +extern unsigned far pascal VIOSCROLLDN ( + unsigned, /* Top row of section to scroll */ + unsigned, /* Left column of section to scroll */ + unsigned, /* Bottom row of section to scroll */ + unsigned, /* Right column of section to scroll */ + unsigned, /* Number of blank lines at bottom */ + char far *, /* pointer to blank Char,Attr */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrollUp - Scroll Screen Up + * + * Scroll the active page (or display) up + */ + +extern unsigned far pascal VIOSCROLLUP ( + unsigned, /* Top row of section to scroll */ + unsigned, /* Left column of section to scroll */ + unsigned, /* Bottom row of section to scroll */ + unsigned, /* Right column of section to scroll */ + unsigned, /* Number of blank lines at bottom */ + char far *, /* pointer to blank Char,Attr */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrollLf - Scroll Screen Left + * + * Scroll the current screen left + */ + +extern unsigned far pascal VIOSCROLLLF ( + unsigned, /* Top row of section to scroll */ + unsigned, /* Left column of section to scroll */ + unsigned, /* Bottom row of section to scroll */ + unsigned, /* Right column of section to scroll */ + unsigned, /* Number of blank columsn at right */ + char far *, /* pointer to blank Char,Attr */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrollLf - Scroll Screen Right + * + * Scroll the current screen right + */ + +extern unsigned far pascal VIOSCROLLRT ( + unsigned, /* Top row of section to scroll */ + unsigned, /* Left column of section to scroll */ + unsigned, /* Bottom row of section to scroll */ + unsigned, /* Right column of section to scroll */ + unsigned, /* Number of blank columsn at left */ + char far *, /* pointer to blank Char,Attr */ + unsigned ); /* Vio Handle */ + + + +/*** VioSetCurPos - Set Cursor Position + * + * Set the cursor position + */ + +extern unsigned far pascal VIOSETCURPOS ( + unsigned, /* Row return data */ + unsigned, /* Column return data */ + unsigned ); /* Vio Handle */ + + + +/*** VioSetCurType - Set Cursor Type + * + * Set the cursor type + */ + +extern unsigned far pascal VIOSETCURTYPE ( + struct CursorData far *, /* Cursor characteristics */ + unsigned ); /* Vio Handle */ + + + +/*** VioSetMode - Set Display Mode + * + * Set the mode of the display + */ + +extern unsigned far pascal VIOSETMODE ( + struct ModeData far *, /* Mode characteristics */ + unsigned ); /* Vio Handle */ + + + +/*** VioShowBuf - Display Logical Buffer + * + * Update the display with the logical video buffer + */ + +extern unsigned far pascal VIOSHOWBUF ( + unsigned, /* Offset into buffer */ + unsigned, /* Length of area to be updated */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtCellStr - Write Character/Attribute String + * + * Write a character,attribute string to the display + */ + +extern unsigned far pascal VIOWRTCELLSTR ( + char far *, /* String to be written */ + unsigned, /* Length of string */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtCharStr - Write Character String + * + * Write a character string to the display + */ + +extern unsigned far pascal VIOWRTCHARSTR ( + char far *, /* String to be written */ + unsigned, /* Length of string */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtCharStrAtt - Write Character String With Attribute + * + * Write a character string with repeated attribute to the display + */ + +extern unsigned far pascal VIOWRTCHARSTRATT ( + char far *, /* String to be written */ + unsigned, /* Length of string */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + char far *, /* Attribute to be replicated */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtNAttr - Write N Attributes + * + * Write an attribute to the display a specified number of times + */ + +extern unsigned far pascal VIOWRTNATTR ( + char far *, /* Attribute to be written */ + unsigned, /* Length of write */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtNCell - Write N Character/Attributes + * + * Write a cell (or character/attribute) to the display a + * specified number of times + */ + +extern unsigned far pascal VIOWRTNCELL ( + char far *, /* Cell to be written */ + unsigned, /* Length of write */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtNChar - Write N Characters + * + * Write a character to the display a specified number of times + */ + +extern unsigned far pascal VIOWRTNCHAR ( + unsigned, /* Character to be written */ + unsigned, /* Length of write */ + unsigned, /* Starting position for output (row) */ + unsigned, /* Starting position for output (col) */ + unsigned ); /* Vio Handle */ + + + +/*** VioWrtTTY - Write TTY String + * + * Write a character string from the current cursor position in + * TTY mode to the display. The cursor will be positioned at the + * end of the string+1 at the end of the write. + */ + +extern unsigned far pascal VIOWRTTTY ( + char far *, /* String to be written */ + unsigned, /* Length of string */ + unsigned ); /* Vio Handle */ + + + +/*** VioSetAnsi - Set ANSI On or Off + * + * Activates or deactivates ANSI support + * + */ + +extern unsigned far pascal VIOSETANSI ( + unsigned, /* ON (=1) or OFF (=0) indicator */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetAnsi - Get ANSI State + * + * Returns the current ANSI state (0=inactive, 1=active) + * + */ + +extern unsigned far pascal VIOGETANSI ( + unsigned far *, /* ANSI state (returned) */ + unsigned ); /* Vio Handle */ + + + +/*** VioPrtScreen - Print Screen + * + * Copies the screen to the printer + * + */ + +extern unsigned far pascal VIOPRTSCREEN ( + unsigned ); /* Vio Handle */ + + + +/*** VioSaveRedrWait - Screen Save Redraw Wait + * + * Allows a process to be notified when it must + * save or redraw its screen + * + */ + +extern unsigned far pascal VIOSAVEREDRAWWAIT ( + unsigned, /* Save/Redraw Indicator */ + unsigned far *, /* Notify type (returned) */ + unsigned ); /* Vio Handle */ + + + +/*** VioSaveRedrWaitUndo - Undo Screen Save Redraw Wait + * + * Allows a one thread within a process to cancel a + * VIOSAVREDRAWWAIT issued by another thread within + * that same process. Ownership of the VIOSAVREDRAWWAIT + * can either be reserved or given up. + * + */ + +extern unsigned far pascal VIOSAVEREDRAWWAITUNDO ( + unsigned, /* Ownership Indicator */ + unsigned, /* Terminate Indicator */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrLock - Lock Screen + * + * Tells a process if I/O to the physical screen buffer can occur. + * + */ + +extern unsigned far pascal VIOSCRLOCK ( + unsigned, /* Wait Flag */ + unsigned char far *, /* Status of lock (returned) */ + unsigned ); /* Vio Handle */ + + + +/*** VioScrUnlock - Unlock Screen + * + * Unlocks the physical screen buffer for I/O. + * + */ + +extern unsigned far pascal VIOSCRUNLOCK ( + unsigned ); /* Vio Handle */ + + + +/*** VioSetMnLockTime - Set Minimum Screen Lock Time + * + * Sets the minimum amount of time that the system will allow a + * process to have exclusive use of the screen via VIOSCRLOCK. + * + */ + +extern unsigned far pascal VIOSETMNLOCKTIME ( + unsigned, /* Number of seconds */ + unsigned ); /* Vio Handle */ + + + +/*** VioSetMxSaveTime - Set Maximum Screen Save/Restore Time + * + * Sets the maximum amount of time (in msec) that the system will + * allow a process to take before issuing a VIOSAVREDRWAIT call + * after being notified by the Session Mgr that one is needed. + * + */ + +extern unsigned far pascal VIOSETMXSAVETIME ( + unsigned, /* Number of milliseconds */ + unsigned ); /* Vio Handle */ + + + +/*** VioGetTimes - Return VIO Lock and Save/Redraw Times + * + * Returns the 2 word values set by the calls + * VIOSETMNLOCKTIME and VIOSETMXSAVETIME. + * + */ + +extern unsigned far pascal VIOGETTIMES ( + unsigned far *, /* Min. Lock time (in seconds) */ + unsigned far *, /* Max. Save time (in msec) */ + unsigned ); /* Vio Handle */ + + + +/*** VioPopUp - Allocate a PopUp Display Screen + * + * Creates a temporary window to display a momentary message + * + */ + +extern unsigned far pascal VIOPOPUP ( + unsigned far *, /* Wait/Nowait Bit flags */ + unsigned ); /* Vio Handle */ + + + +/*** VioEndPopUp - Deallocate a PopUp Display Screen + * + * Closes a PopUp window + * + */ + +extern unsigned far pascal VIOENDPOPUP ( + unsigned ); /* Vio Handle */ + + + + +/*** Mouse Services + * + * MouRegister + * MouGetNumButtons + * MouGetNumMickeys + * MouGetDevStatus + * MouReadEventQueue + * MouGetNumQueEl + * MouGetEventMask + * MouGetScaleFact + * MouSetScaleFact + * MouSetEventMask + * MouOpen + * MouClose + * MouSetPtrShape + * MouRemovePtr + * MouDrawPtr + * MouSetHotKey + */ + + +/*** MouRegister - Register a Mouse Subsystem or Environment Manager + * + */ + +extern unsigned far pascal MOUREGISTER ( + char far *, /* Module name */ + char far *, /* Entry Point name */ + unsigned long, /* Function mask */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetNumButtons - returns the number of mouse buttons supported + * + */ + +extern unsigned far pascal MOUGETNUMBUTTONS ( + unsigned far *, /* Number of mouse buttons (returned) */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetNumMickeys - returns the number of mickeys per centimeter + * + */ + +extern unsigned far pascal MOUGETNUMMICKEYS ( + unsigned far *, /* Number of Mickeys/cm (returned) */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetDevStatus - returns the mouse driver status flags + * + */ + +extern unsigned far pascal MOUGETDEVSTATUS ( + unsigned far *, /* Device Status (returned) */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouReadEventQueue - reads an event from the mouse event queue + * + */ + +extern unsigned far pascal MOUREADEVENTQUEUE ( + unsigned, /* Type of read operation */ + unsigned char far *, /* Event Queue Entry (returned) */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetNumQueEl - returns the status of the Mouse Event Queue + * + */ + +extern unsigned far pascal MOUGETNUMQUEEL ( + unsigned far *, /* Maximum # of Elements in Queue */ + unsigned far *, /* Current # of Elements in Queue */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetEventMask - Returns the current mouse 1-word event mask + * + */ + +extern unsigned far pascal MOUGETEVENTMASK ( + unsigned far *, /* Event Mask (returned) */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouGetScaleFact - Returns the current mouse scaling factors + * + */ + +extern unsigned far pascal MOUGETSCALEFACT ( + unsigned far *, /* Y Coordinate Scaling Factor */ + unsigned far *, /* X Coordinate Scaling Factor */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouSetScaleFact - Sets the current mouse scaling factors + * + */ + +extern unsigned far pascal MOUSETSCALEFACT ( + unsigned, /* Y Coordinate Scaling Factor */ + unsigned, /* X Coordinate Scaling Factor */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouSetEventMask - Set the current mouse 1-word event mask + * + */ + +extern unsigned far pascal MOUSETEVENTMASK ( + unsigned, /* Event Mask */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouOpen - Open the mouse device + * + */ + +extern unsigned far pascal MOUOPEN ( + unsigned far * ); /* Mouse Device Handle (returned) */ + + + +/*** MouClose - Close the mouse device + * + */ + +extern unsigned far pascal MOUCLOSE ( + unsigned ); /* Mouse Device Handle */ + + + +/*** MouSetPtrShape - Set the shape and size of the mouse pointer image + * + */ + +extern unsigned far pascal MOUSETPTRSHAPE ( + unsigned char far *, /* Pointer Shape (returned) */ + unsigned long, /* Size of data passed */ + unsigned, /* Height of Ptr Shape */ + unsigned, /* Width of Ptr Shape */ + unsigned, /* Offset to Ptr Column Center */ + unsigned, /* Offset to Ptr Row Center */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouRemovePtr - Restricts the Mouse Ptr from occurring in a region + * + */ + +extern unsigned far pascal MOUREMOVEPTR ( + unsigned far *, /* Pointer Area */ + unsigned ); /* Mouse Device Handle */ + + + +/*** MouDrawPtr - Unrestricts the Mouse Ptr + * + */ + +extern unsigned far pascal MOUDRAWPTR ( + unsigned ); /* Mouse Device Handle */ + + +/*** MouSetHotKey - Determines which Mouse Key is the system hot key + * + */ + +extern unsigned far pascal MOUSETHOTKEY ( + unsigned, /* Mouse Button Mask */ + unsigned ); /* Mouse Device Handle */ + + + + +/*** Device Monitor Services + * + * DosMonOpen + * DosMonClose + * DosMonReg + * DosMonRead + * DosMonWrite + */ + + + +/*** DosMonOpen - Open a Connection to a CP/DOS Device Monitor + * + * This call is issued once by a process which wishes to use + * device monitors + */ + +extern unsigned far pascal DOSMONOPEN ( + char far *, /* Ascii string of device name */ + unsigned far * ); /* Address for handle return value */ + + + +/*** DosMonClose - Close a Connection to a CP/DOS Device Monitor + * + * This call is issued once by a process which wishes to terminate + * monitoring. This call causes all monitor buffers associated to + * be flushed and closed. + */ + +extern unsigned far pascal DOSMONCLOSE ( + unsigned ); /* Handle from DosMonOpen */ + + + +/*** DosMonReg - Register a Set of Buffers as a Monitor + * + * This call is issued to establish a pair of buffer structures - + * one input and one output - to monitor an I/O stream + */ + +extern unsigned far pascal DOSMONREG ( + unsigned, /* Handle from DosMonOpen */ + unsigned char far *, /* Address of monitor input buffer */ + unsigned char far *, /* Address of monitor output buffer */ + unsigned, /* Position flag - 0=no positional */ + /* preference, 1=front of list, */ + /* 2=back of the list */ + unsigned ); /* Index */ + + + +/*** DosMonRead - Read Input From Monitor Structure + * + * This call is issued to wait for and read input records from + * the monitor buffer structure + */ + +extern unsigned far pascal DOSMONREAD ( + unsigned char far *, /* Address of monitor input buffer */ + unsigned char, /* Block/Run indicator - 0=block */ + /* input ready, 1=return */ + unsigned char far *, /* Address of data buffer */ + unsigned far * ); /* Number of bytes in the data record */ + + + +/*** DosMonWrite - Write Output to Monitor Structure + * + * Writes data to the monitor output buffer structure + */ + +extern unsigned far pascal DOSMONWRITE ( + unsigned char far *, /* Address of monitor output buffer */ + unsigned char far *, /* Address of data buffer */ + unsigned ); /* Number of bytes in data record */ + + + + +/*** File I/O Services: + * + * DosBufReset + * DosChdir + * DosChgFilePtr + * DosClose + * DosCreateUn + * DosDelete + * DosDupHandle + * DosFindClose + * DosFindFirst + * DosFindNext + * DosFileLocks + * DosGetInfoSeg + * DosMkdir + * DosMove + * DosNewSize + * DosOpen + * DosQCurDir + * DosQCurDisk + * DosQFHandState + * DosQFileInfo + * DosQFileMode + * DosQFSInfo + * DosQHandType + * DosQSwitChar + * DosQVerify + * DosRead + * DosReadAsync + * DosRmdir + * DosSelectDisk + * DosSetFileInfo + * DosSetFileMode + * DosSetFHandState + * DosSetFSInfo + * DosSetMaxFH + * DosSetVerify + * DosWrite + * DosWriteAsync + */ + + + +/*** DosBufReset - Commit File's Cache Buffers + * + * Flushes requesting process's cache buffers for the specified + * format + */ + +extern unsigned far pascal DOSBUFRESET ( + unsigned ); /* File handle */ + + + +/*** DosChdir - Change The Current Directory + * + * Define the current directory for the requesting process + */ + +extern unsigned far pascal DOSCHDIR ( + char far *, /* Directory path name */ + unsigned long ); /* Reserved (must be 0) */ + + + +/*** DosChgFilePtr - Change (Move) File Read Write Pointer + * + * Move the read/write pointer according to the method specified + */ + +extern unsigned far pascal DOSCHGFILEPTR ( + unsigned, /* File handle */ + long, /* Distance to move in bytes */ + unsigned, /* Method of moving (0,1,2) */ + unsigned long far * ); /* New pointer location */ + + + +/*** DosClose - Close a File Handle + * + * Closes the specified file handle + */ + +extern unsigned far pascal DOSCLOSE ( + unsigned ); /* File handle */ + + + +/*** DosCreateUn - Create a Unique File Path Name + * + * Generates a unique file path name + */ + +extern unsigned far pascal DOSCREATEUN ( + char far * ); /* File path name area */ + + + +/*** DosDelete - Delete a File + * + * Removes a directory entry associated with a filename + */ + +extern unsigned far pascal DOSDELETE ( + char far *, /* Filename path */ + unsigned long ); /* Reserved (must be 0) */ + + + +/*** DosDupHandle - Duplicate a File Handle + * + * Returns a new file handle for an open file that refers to the + * same file at the same position + */ + +extern unsigned far pascal DOSDUPHANDLE ( + unsigned, /* Existing file handle */ + unsigned far * ); /* New file handle */ + + + +/*** DosFindClose - Close Find Handle + * + * Closes the association between a directory handle and a + * DosFindFirst or DosFindNext directory search function + */ + +extern unsigned far pascal DOSFINDCLOSE ( + unsigned ); /* Directory search handle */ + + + +/*** DosFindFirst - Find First Matching File + * + * Finds the first filename that matches the specified file + * specification + */ + +extern unsigned far pascal DOSFINDFIRST ( + char far *, /* File path name */ + unsigned far *, /* Directory search handle */ + unsigned, /* Search attribute */ + struct FileFindBuf far *, /* Result buffer */ + unsigned, /* Result buffer length */ + unsigned far *, /* Number of entries to find */ + unsigned long ); /* Reserved (must be 0) */ + + + +/*** DosFindNext - Find Next Matching File + * + * Finds the next directory entry matching the name that was + * specified on the previous DosFindFirst or DosFindNext function + * call + */ + +extern unsigned far pascal DOSFINDNEXT ( + unsigned, /* Directory handle */ + struct FileFindBuf far *, /* Result buffer */ + unsigned, /* Result buffer length */ + unsigned far * ); /* Number of entries to find */ + + + +/*** DosFileLocks - File Lock Manager + * + * Unlock and/or lock multiple ranges in an opened file + */ + +extern unsigned far pascal DOSFILELOCKS ( + unsigned, /* File handle */ + long far *, /* Unlock Range */ + long far * ); /* Lock Range */ + + + +/*** DosGetInfoSeg - Get addresses of system variable segments + * + * Returns 2 selectors: one for the global information segment, + * the other for a process information segment + */ + +extern unsigned far pascal DOSGETINFOSEG ( + unsigned far *, /* Selector for Global Info Seg */ + unsigned far * ); /* Selector for Process Info Seg */ + + + +/*** DosMkdir - Make Subdirectory + * + * Creates the specified directory + */ + +extern unsigned far pascal DOSMKDIR ( + char far *, /* New directory name */ + unsigned long ); /* Reserved (must be 0) */ + + + +/*** DosMove - Move a file or SubDirectory + * + * Moves the specified file or directory + */ + +extern unsigned far pascal DOSMOVE ( + char far *, /* Old path name */ + char far *, /* New path name */ + unsigned long ); /* Reserved (must be 0) */ + + + +/*** DosNewSize - Change File's Size + * + * Changes a file's size + */ + +extern unsigned far pascal DOSNEWSIZE ( + unsigned, /* File handle */ + unsigned long ); /* File's new size */ + + + +/*** DosOpen - Open a File + * + * Creates the specified file (if necessary) and opens it + */ + +extern unsigned far pascal DOSOPEN ( + char far *, /* File path name */ + unsigned far *, /* New file's handle */ + unsigned far *, /* Action taken - 1=file existed, */ + /* 2=file was created */ + unsigned long, /* File primary allocation */ + unsigned, /* File attributes */ + unsigned, /* Open function type */ + unsigned, /* Open mode of the file */ + unsigned long ); /* Reserved (must be zero) */ + + + +/*** DosQCurDir - Query Current Directory + * + * Get the full path name of the current directory for the + * requesting process for the specified drive + */ + +extern unsigned far pascal DOSQCURDIR ( + unsigned, /* Drive number - 1=A, etc */ + char far *, /* Directory path buffer */ + unsigned far * ); /* Directory path buffer length */ + + + +/*** DosQCurDisk - Query Current Disk + * + * Determine the current default drive for the requesting process + */ + +extern unsigned far pascal DOSQCURDISK ( + unsigned far *, /* Default drive number */ + unsigned long far * ); /* Drive-map area */ + + + + +/*** DosQFHandState - Query file handle state + * + * Query the state of the specified handle + */ + +extern unsigned far pascal DOSQFHANDSTATE ( + unsigned, /* File Handle */ + unsigned far * ); /* File handle state */ + + + +/*** DosQFileInfo - Query a File's Information + * + * Returns information for a specific file + */ + +extern unsigned far pascal DOSQFILEINFO ( + unsigned, /* File handle */ + unsigned, /* File data required */ + char far *, /* File data buffer */ + unsigned ); /* File data buffer size */ + + +/*** DosQFileMode - Query File Mode + * + * Get the mode (attribute) of the specified file + */ + +extern unsigned far pascal DOSQFILEMODE ( + char far *, /* File path name */ + unsigned far *, /* Data area */ + unsigned long ); /* Reserved (must be zero) */ + + + +/*** DosQFSInfo - Query File System Information + * + * Gets information from a file system device + */ + +extern unsigned far pascal DOSQFSINFO ( + unsigned, /* Drive number - 0=default, 1=A, etc */ + unsigned, /* File system info required */ + char far *, /* File system info buffer */ + unsigned ); /* File system info buffer size */ + + + +/*** DosQHandType - Query Handle type + * + * Returns a flag as to whether a handle references a device or + * a file, and if a device, returns device driver attribute word + */ + +extern unsigned far pascal DOSQHANDTYPE ( + unsigned, /* File Handle */ + unsigned far *, /* Handle Type (0=file, 1=device) */ + unsigned far * ); /* Device Driver Attribute Word */ + + + +/*** DosQSwitChar - Query Switch Character + * + * Returns the system switch character + */ + +extern unsigned far pascal DOSQSWITCHAR ( + unsigned char far * ); /* Switch Character (returned) */ + + + +/*** DosQVerify - Query Verify Setting + * + * Returns the value of the Verify flag + */ + +extern unsigned far pascal DOSQVERIFY ( + unsigned far * ); /* Verify setting - 0=verify mode */ + /* not active, 1=verify mode active */ + + + +/*** DosRead - Read from a File + * + * Reads the specified number of bytes from a file to a + * buffer location + */ + +extern unsigned far pascal DOSREAD ( + unsigned, /* File handle */ + char far *, /* Address of user buffer */ + unsigned, /* Buffer length */ + unsigned far * ); /* Bytes read */ + + + +/*** DosReadAsync - Async Read from a File + * + * Reads the specified number of bytes from a file to a buffer + * location asynchronously with respect to the requesting process's + * execution + */ + +extern unsigned far pascal DOSREADASYNC ( + unsigned, /* File handle */ + unsigned long far *, /* Address of Ram semaphore */ + unsigned far *, /* Address of I/O error return code */ + char far *, /* Address of user buffer */ + unsigned, /* Buffer length */ + unsigned far * ); /* Number of bytes actually read */ + + + +/*** DosRmDir - Remove Subdirectory + * + * Removes a subdirectory from the specified disk + */ + +extern unsigned far pascal DOSRMDIR ( + char far *, /* Directory name */ + unsigned long ); /* Reserved (must be zero) */ + + + +/*** DosSelectDisk - Select Default Drive + * + * Select the drive specified as the default drive for the + * calling process + */ + +extern unsigned far pascal DOSSELECTDISK ( + unsigned ); /* Default drive number */ + + + +/*** DosSetFHandState - Set File Handle State + * + * Get the state of the specified file + */ + +extern unsigned far pascal DOSSETFHANDSTATE ( + unsigned, /* File handle */ + unsigned); /* File handle state */ + + +/*** DosSetFSInfo - Set File System Information + * + * Set information for a file system device + */ + +extern unsigned far pascal DOSSETFSINFO ( + unsigned, /* Drive number - 0=default, 1=A, etc */ + unsigned, /* File system info required */ + char far *, /* File system info buffer */ + unsigned ); /* File system info buffer size */ + + + +/*** DosSetFileInfo - Set a File's Information + * + * Specifies information for a file + */ + +extern unsigned far pascal DOSSETFILEINFO ( + unsigned, /* File handle */ + unsigned, /* File info data required */ + char far *, /* File info buffer */ + unsigned ); /* File info buffer size */ + + + +/*** DosSetFileMode - Set File Mode + * + * Change the mode (attribute) of the specified file + */ + +extern unsigned far pascal DOSSETFILEMODE ( + char far *, /* File path name */ + unsigned, /* New attribute of file */ + unsigned long ); /* Reserved (must be zero) */ + + + +/*** DosSetMaxFH - Set Maximum File Handles + * + * Defines the maximum number of file handles for the + * current process + */ + +extern unsigned far pascal DOSSETMAXFH ( + unsigned ); /* Number of file handles */ + + + +/*** DosSetVerify - Set/Reset Verify Switch + * + * Sets the verify switch + */ + +extern unsigned far pascal DOSSETVERIFY ( + unsigned ); /* New value of verify switch */ + + + +/*** DosWrite - Synchronous Write to a File + * + * Transfers the specified number of bytes from a buffer to + * the specified file, synchronously with respect to the + * requesting process's execution + */ + +extern unsigned far pascal DOSWRITE ( + unsigned, /* File handle */ + char far *, /* Address of user buffer */ + unsigned, /* Buffer length */ + unsigned far * ); /* Bytes written */ + + + +/*** DosWriteAsync - Asynchronous Write to a File + * + * Transfers the specified number of bytes from a buffer to + * the specified file, asynchronously with respect to the + * requesting process's execution + */ + +extern unsigned far pascal DOSWRITEASYNC ( + unsigned, /* File handle */ + unsigned long far *, /* Address of RAM semaphore */ + unsigned far *, /* Address of I/O error return code */ + char far *, /* Address of user buffer */ + unsigned, /* Buffer length */ + unsigned far * ); /* Bytes written */ + + + + +/*** Hard Error Handling + * + * DosError + */ + + + +/*** DosError - Enable Hard Error Processing + * + * Allows a CP/DOS process to receive hard error notification + * without generating a hard error signal. Hard errors generated + * under a process which has issued a DosError call are FAILed and + * the appropriate error code is returned. + */ + +extern unsigned far pascal DOSERROR ( + unsigned ); /* Action flag */ + + + +/*** Machine Exception Handling + * + * DosSetVector + */ + + + +/*** DosSetVec - Establish a handler for an Exception + * + * Allows a process to register an address to be + * called when a 286 processor exception occurs. + */ + +extern unsigned far pascal DOSSETVEC ( + unsigned, /* Exception Vector */ + void (far *)(void), /* Address of exception handler */ + void (far * far *)(void) ); /* Address to store previous handler */ + + + +/*** Message Functions + * + * DosGetMessage + * DosInsMessage + * DosPutMessage + */ + + + +/*** DosGetMessage - Return System Message With Variable Text + * + * Retrieves a message from the specified system message file + * and inserts variable information into the body of the message + */ + +extern unsigned far pascal DOSGETMESSAGE ( + char far * far *, /* Table of variables to insert */ + unsigned, /* Number of variables */ + char far *, /* Address of message buffer */ + unsigned, /* Length of buffer */ + unsigned, /* Number of the message */ + char far *, /* Message file name */ + unsigned far * ); /* Length of returned message */ + + + +/*** DosInsMessage - Insert Variable Text into Message + * + * Inserts variable text string information into the body ofa message. + */ + +extern unsigned far pascal DOSINSMESSAGE ( + char far * far *, /* Table of variables to insert */ + unsigned, /* Number of variables */ + char far *, /* Address of output buffer */ + unsigned, /* Length of output buffer */ + unsigned, /* Length of message */ + char far *, /* Address of input string */ + unsigned far * ); /* Length of returned message */ + + + +/*** DosPutMessage - Output Message Text to Indicated Handle + * + * Outputs a message in a buffer passed by a caller to the + * specified handle. The function formats the buffer to + * prevent words from wrapping if displayed to a screen. + */ + +extern unsigned far pascal DOSPUTMESSAGE ( + unsigned, /* Handle of output file/device */ + unsigned, /* Length of message buffer */ + char far * ); /* Message buffer */ + + + +/*** RAS Services + * + * DosSysTrace + */ + + + +/*** DosSysTrace - Add a Trace record to the System Trace Buffer + * + * Allows a subsystem or system extension to add information to the + * System trace buffer. This call can only be made from protected + * mode. + */ + +extern unsigned far pascal DOSSYSTRACE ( + unsigned, /* Major trace event code (0-255) */ + unsigned, /* Length of area to be recorded */ + unsigned, /* Minor trace event code (0-FFFFH) */ + char far * ); /* Pointer to area to be traced */ + + + +/*** Program Startup Conventions + * + * DosGetEnv + * DosGetVersion + */ + + + +/*** DosGetEnv - Get the Address of Process' Environment String + * + * Return the address of the current process' environment string + */ + +extern unsigned far pascal DOSGETENV ( + unsigned far *, /* Address to place segment handle */ + unsigned far * ); /* Address for command line start */ + + + +/*** DosGetVersion - Get DOS Version + * + * Returns the DOS version number + */ + +extern unsigned far pascal DOSGETVERSION ( + unsigned far * ); /* Address to put version number */ + + + +/*** World Trade Support + * + * All of these functions declarations have the string NLS in a comment. + * This is required in the generation of the Imports Library DOSCALLS.LIB + * + * DosGetCtryInfo + * DosSetCtryCode + * DosGetDBCSEv + * DosCaseMap + * DosGetSpecChar + * DosCollate + */ + + + +/*** DosGetCtryInfo + * + * Returns the country dependant formatting information that + * resides in the NLSCDIT.SYS World Trade Support file + */ + +extern unsigned far pascal DOSGETCTRYINFO ( /**/ + unsigned, /* Length of data area provided */ + unsigned long far *, /* Country code */ + char far *, /* Memory buffer */ + unsigned far * ); /* Length of returned data */ + + + +/*** DosSetCrtyCode + * + * Sets the current country code for the system + */ + +extern unsigned far pascal DOSSETCTRYCODE ( /**/ + unsigned long far * ); /* Country code */ + + + +/*** DosGetDBCSEv - Get the DBCS Environment Vector + * + * Used to obtain the DBCS environmental vector that resides in + * the NLSDBCS.SYS World Trade Support file. + */ + +extern unsigned far pascal DOSGETDBCSEV ( /**/ + unsigned, /* Length of data area provided */ + unsigned long far *, /* Country code */ + char far * ); /* Pointer to data area */ + + + +/*** DosCaseMap + * + * Used to perform case mapping on a string of binary values which + * represent ASCII characters. + */ + +extern unsigned far pascal DOSCASEMAP ( /**/ + unsigned, /* Length of string to case map */ + unsigned long far *, /* Country code */ + char far * ); /* Address of string of binary values */ + + + +/*** DosGetSpecChar + * + * Gets a list of special characters that are valid in file names, etc. + * The list corresponds to the byte values 128-255. + */ + +extern unsigned far pascal DOSGETSPECCHAR ( /**/ + unsigned, /* Length of data area provided */ + unsigned long far *, /* Country Code */ + unsigned char far * ); /* Data area */ + + + +/*** DosCollate + * + * Undocumented NLS feature + */ + +extern unsigned far pascal DOSCOLLATE ( /**/ + unsigned, /* Buffer Length */ + unsigned long far *, /* Country Code */ + char far * ); /* Buffer Address */ + + + +/* End of File */ diff --git a/v4.0/src/CMD/FDISK/D_MENUS.C b/v4.0/src/CMD/FDISK/D_MENUS.C new file mode 100644 index 0000000..3ebfff9 --- /dev/null +++ b/v4.0/src/CMD/FDISK/D_MENUS.C @@ -0,0 +1,941 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "string.h" /* AN000 */ +#include "ctype.h" /* AN000 */ +#include "stdio.h" /* AN000 */ + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DELETE_PARTITION */ +/* */ +/* DESCRIPTIVE NAME: Delete partition selection menu */ +/* */ +/* FUNCTION: User is prompted as to what type of DOS partition */ +/* he wishes to delete. */ +/* */ +/* NOTES: The delete volume option is only displayed if some */ +/* disk volumes exist */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Delete DOS Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Enter the type of DOS partition you ³ */ +/* 09³wish to delete..............? ³ */ +/* 10³ ³ */ +/* 11³ 1. Normal DOS partition ³ */ +/* 12³ 2. EXTENDED DOS Partition ³ */ +/* 13³ 3. Disk volume in the EXTENDED ³ */ +/* 14³ DOS Partition ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Enter choice: [#] ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Delete_Partition */ +/* LINKAGE: delete_partition() */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* wait_for_ESC */ +/* get_num_input */ +/* internal_program_error */ +/* dos_delete */ +/* ext_delete */ +/* vol_delete */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void delete_partition() + +BEGIN + + unsigned i; + char input; + char temp; + char max_input; + + + input = c(NUL); /* AC000 */ + /* clear_screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display(menu_25); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* check to see if there is an avail partition */ + temp = c(0); /* AC000 */ + for (i = u(0); i < u(4);i++) /* AC000 */ + BEGIN + + /* See if any non - zero system id bytes */ + temp = temp | part_table[cur_disk][i].sys_id ; + END + /* Any entry that isn't zero means */ + if (temp != c(0)) /* AC000 */ + BEGIN + /* ############# ADD CODE HERE FOR THIS FUNCTION ############## */ + /* Do something about defaults and highlighting */ + /* */ + /* ############################################################ */ + + /* Display enter prompts */ + /* display dos delete menu without input prompt */ + display(menu_3); + display(menu_25); + display(menu_26); + display(menu_7); + + display(menu_27); /* AC000 */ + max_input = c(3); /* AC000 */ + + input = get_num_input(c(NUL),max_input,input_row,input_col); /* AC000 */ + /* Go branch to the requested function */ + switch(input) + BEGIN + case '1': + if (find_partition_type(uc(DOS12)) || /* AN016 AC016 */ + find_partition_type(uc(DOS16)) || /* AN016 AC016 */ + find_partition_type(uc(DOSNEW))) /* AN016 AC016 */ + dos_delete(); + else /* AN000 */ + BEGIN /* AN000 */ + /* No Pri partition to delete */ + clear_screen(u(17),u(0),u(17),u(79)); /* AN000 */ + display(error_6); /* AN000 */ + wait_for_ESC(); /* AN000 */ + END /* AN000 */ + break; + + case '2': + if (find_partition_type(uc(EXTENDED))) /* AN000 */ + ext_delete(); + else /* AN000 */ + BEGIN /* AN000 */ + /* No Ext partition to delete */ + clear_screen(u(17),u(0),u(17),u(79)); /* AN000 */ + display(error_7); /* AN000 */ + wait_for_ESC(); /* AN000 */ + END /* AN000 */ + break; + + case '3': + if ((find_partition_type(uc(EXTENDED))) && (find_logical_drive())) /* AC000 */ + volume_delete(); + else + BEGIN + clear_screen(u(17),u(0),u(17),u(79)); /* AN000 */ + display(error_36); /* AN000 */ + wait_for_ESC(); /* AN000 */ + END /* AN000 */ + break; + + case ESC: break; + + default : internal_program_error(); + break; + END + END + else + BEGIN + display(error_14); + wait_for_ESC(); + END + /* clear the screen before going back to main menu */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DOS_DELETE */ +/* */ +/* DESCRIPTIVE NAME: Delete DOS partition */ +/* */ +/* FUNCTION: Delete the DOS partition. Prompt user with dire */ +/* warning first. Default entry on prompt is (N) */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is deleted and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Delete DOS Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ # # ####### #### #### ####³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Warning! Data in the DOS partition ³ */ +/* 19³will be lost. Do you wish to ³ */ +/* 20³continue..........................? [N] ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: DOS_Delete */ +/* LINKAGE: dos_delete */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if invalid input */ +/* returned to this level */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES */ +/* table_display */ +/* clear_screen */ +/* wait_for_ESC */ +/* get_yn_input */ +/* display */ +/* Write_Boot_Record */ +/* find_part_free_space */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void dos_delete() + +BEGIN + + char input; + unsigned i; + + + input = c(NUL); /* AC000 */ + /* clear screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display(menu_28); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* Display partition data and double check if partition exists*/ + if (table_display()) + BEGIN + + sprintf(insert,"%4.0d",total_mbytes[cur_disk]); + display(menu_15); + + /* See if drive 1 and extended partition exists */ + + if (!(find_partition_type(uc(EXTENDED)) && (cur_disk == c(0)))) /* AC000 */ + BEGIN + + /* Nope, we can keep going */ + /* Display Y/N prompt */ + display(menu_29); + + /* Get yes/no prompt */ + input = get_yn_input(c(No),input_row,input_col); /* AC000 AC011 */ + switch(input) + BEGIN + case 1: /* AC000 */ + BEGIN + for (i=u(0); i < u(4); i++) /* AC000 */ + BEGIN + + if ( (part_table[cur_disk][i].sys_id==uc(DOS12)) || + (part_table[cur_disk][i].sys_id==uc(DOS16)) || + (part_table[cur_disk][i].sys_id==uc(DOSNEW)) ) /* AC000 */ + + BEGIN + /* Set Partition entry to zero */ + part_table[cur_disk][i].boot_ind = uc(0); /* AC000 */ + part_table[cur_disk][i].start_head = uc(0); /* AC000 */ + part_table[cur_disk][i].start_sector = uc(0); /* AC000 */ + part_table[cur_disk][i].start_cyl = u(0); /* AC000 */ + part_table[cur_disk][i].sys_id = uc(0); /* AC000 */ + part_table[cur_disk][i].end_head = uc(0); /* AC000 */ + part_table[cur_disk][i].end_sector = uc(0); /* AC000 */ + part_table[cur_disk][i].end_cyl = u(0); /* AC000 */ + part_table[cur_disk][i].rel_sec = ul(0); /* AC000 */ + part_table[cur_disk][i].num_sec = ul(0); /* AC000 */ + part_table[cur_disk][i].changed = (FLAG)TRUE; /* AC000 */ + part_table[cur_disk][i].mbytes_used = f(0); /* AN000 */ + part_table[cur_disk][i].percent_used = u(0); /* AN000 */ + + strcpy(part_table[cur_disk][i].system,c(NUL)); /* AN000 */ + strcpy(part_table[cur_disk][i].vol_label,c(NUL)); /* AN000 */ + + /* Redisplay the partition info */ + table_display(); + + /* clear the prompt off */ + clear_screen(u(16),u(0),u(23),u(79)); /* AC000 */ + + /* Set the reboot flag */ + reboot_flag = (FLAG)TRUE; /* AC000 */ + + /* Say that you deleted it */ + display(status_1); + + wait_for_ESC(); + break; + END + END + END + break; + + case 0: break; /* AC000 */ + + case ESC: break; + + default: + BEGIN + internal_program_error(); + break; + END + END + END + else + BEGIN + /* Tell user he can't do it while extended exists on drive 1 */ + display(error_32); + wait_for_ESC(); + END + END + + else + BEGIN + internal_program_error(); + END + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: EXT_DELETE */ +/* */ +/* DESCRIPTIVE NAME: Delete EXTENDED DOS partition */ +/* */ +/* FUNCTION: Delete the EXTENDED DOS partition. Prompt with */ +/* warning first. Default entry on prompt is (N) */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is deleted and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Delete EXTENDED DOS Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ # # ####### #### #### ####³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Warning! Data in the EXTENDED DOS ³ */ +/* 19³partition will be lost. Do you wish ³ */ +/* 20³to continue.......................? [N] ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Ext_Delete */ +/* LINKAGE: ext_delete () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if invalid input */ +/* returned to this routine */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* table_display */ +/* clear_screen */ +/* wait_for_ESC */ +/* get_yn_input */ +/* display */ +/* Write_Boot_Record */ +/* Internal_Program_Error */ +/* Find_Free_Space */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void ext_delete() + + +BEGIN + + char input; + unsigned i; + unsigned j; /* AN000 */ + + + input = c(NUL); /* AC000 */ + /* Clear the screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display(menu_30); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* Display partition data and double check if partition exists*/ + table_display(); /* AC000 */ + sprintf(insert,"%4.0d",total_mbytes[cur_disk]); + display(menu_15); + + BEGIN + /* See if there are still volumes */ + if (!find_logical_drive()) + BEGIN + /* Display Y/N prompt */ + display(menu_31); + + /* Get yes/no prompt */ + input = get_yn_input(c(No),input_row,input_col); /* AC000 AC011 */ + switch(input) + BEGIN + case 1: /* AC000 */ + BEGIN + for (i=u(0); i < u(4); i++) /* AC000 */ + /* Note: This will delete all occurances of EXTENDED DOS partitions found */ + BEGIN + if (part_table[cur_disk][i].sys_id == uc(EXTENDED)) /* AC000 */ + BEGIN + /* Set Partition entry to zero */ + part_table[cur_disk][i].boot_ind = uc(0); /* AC000 */ + part_table[cur_disk][i].start_head = uc(0); /* AC000 */ + part_table[cur_disk][i].start_sector = uc(0); /* AC000 */ + part_table[cur_disk][i].start_cyl = u(0); /* AC000 */ + part_table[cur_disk][i].sys_id = uc(0); /* AC000 */ + part_table[cur_disk][i].end_head = uc(0); /* AC000 */ + part_table[cur_disk][i].end_sector = uc(0); /* AC000 */ + part_table[cur_disk][i].end_cyl = u(0); /* AC000 */ + part_table[cur_disk][i].rel_sec = ul(0); /* AC000 */ + part_table[cur_disk][i].num_sec = ul(0); /* AC000 */ + part_table[cur_disk][i].changed = (FLAG)TRUE; /* AC000 */ + part_table[cur_disk][i].mbytes_used = f(0); /* AN000 */ + part_table[cur_disk][i].percent_used = u(0); /* AN000 */ + + strcpy(part_table[cur_disk][i].system,c(NUL)); /* AN000 */ + strcpy(part_table[cur_disk][i].vol_label,c(NUL)); /* AN000 */ + + /* Redisplay the partition info */ + table_display(); + + /* clear the prompt off */ + clear_screen(u(17),u(0),u(23),u(79)); /* AC000 */ + + /* Say that you deleted it */ + display(status_2); + + /* Set the reboot flag */ + reboot_flag = (FLAG)TRUE; /* AC000 */ + END + END + wait_for_ESC(); + break; + END + + case 0: break; /* AC000 */ + + case ESC: break; + + default: internal_program_error(); + break; + END + END + else + BEGIN + /* Logical drives still exist, can't delete partition */ + display(error_21); + wait_for_ESC(); + END + END + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: VOL_DELETE */ +/* */ +/* DESCRIPTIVE NAME: Delete DOS disk Volume */ +/* */ +/* FUNCTION: Prompts user to delete a DOS disk volume */ +/* */ +/* NOTES: Screen can be exited via the ESC command before */ +/* partition is deleted and nothing will change */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³Delete DOS Disk Volume ³ */ +/* 01³ ³ */ +/* 02³Vol Start End Size ³ */ +/* 03³ # #### #### #### ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ ³ */ +/* 07³ ³ */ +/* 08³ ³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³Total partition size is #### cylinders. ³ */ +/* 17³ ³ */ +/* 18³Warning! Data in the DOS disk volume ³ */ +/* 19³will be lost. What volume do you wish ³ */ +/* 20³to delete.........................? [#] ³ */ +/* 21³ ³ */ +/* 22³Are you sure......................? [N] ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Vol_Delete */ +/* LINKAGE: vol_delete () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if invalid input */ +/* returned to this routine */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* display */ +/* volume_display */ +/* get_num_input */ +/* wait_for_ESC */ +/* get_yn_input */ +/* Write_Boot_Record */ +/* Find_Free_Space */ +/* Internal_Program_Error */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void volume_delete() + +BEGIN + + char input; + char drive_input; + char high_drive; + char low_drive; + char error_low_drive; + char error_high_drive; + char drives_reassigned; + int list_index; + int i; + int j; /* AN011 */ + int point; + FLAG delete_drive; + unsigned char drive_list[23][2]; + int column; + int row; + FLAG drives_exist; + FLAG vol_matches; + char temp; + unsigned char drive_temp; + char far *s; + unsigned char string_input[12]; /* AN000 */ + + input = c(NUL); + string_input[0] = uc(NUL); /* AN000 */ + + /* Clear screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display(menu_32); + + /* print ESC prompt */ + display(menu_11); + + /* Display logical drives and get the highest drive letter assigned*/ + high_drive = volume_display(); + + /* Get the first avail drive letter to be deleted */ + low_drive = (high_drive - get_num_logical_dos_drives()+1); + temp = low_drive; + + /* Initialize array of drive letters that exist at this point */ + for (i=(int)0; i < (int)23; i++) /* AC000 */ + BEGIN + /* See if we've exceeded the drive letter range */ + if (temp <= high_drive) + BEGIN + /* Put in drive letter */ + drive_list[i][0] = ((unsigned char)(temp)); + /* Initialize the offsets into the array to something harmless */ + drive_list[i][1] = uc(INVALID); /* AC000 */ + END + else + BEGIN + /* No drive there, put in NUL */ + drive_list[i][0] = uc(NUL); /* AC000 */ + drive_list[i][1] = uc(INVALID); /* AC000 */ + END + + /* Check for next drive */ + temp++; + END + + /* Set up partition size message */ + sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) ); + display(menu_21); + + /* Assume no drives deleted */ + drives_reassigned = (FLAG)FALSE; /* AC000 */ + + /* Loop until ESC or all deleted */ + while (input != c(ESC)) /* AC000 */ + BEGIN + + /* Are there any drives left?*/ + drives_exist = (FLAG)FALSE; /* AC000 */ + error_low_drive = ((char)(NUL)); + error_high_drive = ((char)(NUL)); + + for (i=(int)0;i < (int)23; i++) /* AC000 */ + BEGIN + drive_temp = drive_list[i][0]; + if ((drive_temp != uc(NUL)) && (drive_list[i][1] != uc(DELETED))) /* AC011 */ + BEGIN + drives_exist = (FLAG)TRUE; /* AC000 */ + + /* Find last existing drive letter */ + error_high_drive = ((char)(drive_temp)); + + /* See if we've found the first drive yet */ + if (error_low_drive == ((char)(NUL))) + error_low_drive = ((char)(drive_temp)); + END + END + + /* If there are drives, go let user try to delete them */ + if (drives_exist) + BEGIN + + /* Get input until given a correct drive */ + valid_input = (FLAG)FALSE; /* AC000 */ + while ( (!valid_input) && (input != c(ESC)) ) + BEGIN + + /* Prompt for input */ + display(menu_33); + + /* Get input between first and highest drive letters */ + clear_screen( u(21), u(0), u(21), u(79) ); + input = get_alpha_input(low_drive,high_drive,input_row,input_col,error_low_drive,error_high_drive); + drive_input = input; + + /* See if it has been deleted already or ESC pressed */ + drives_exist = FALSE; + for (i=(int)0;i < (int)23; i++) /* AC000 */ + BEGIN + if (drive_list[i][0] == ((unsigned char)(drive_input)) && + (drive_list[i][1] != ((unsigned char) DELETED))) /* AC013 */ + BEGIN + drives_exist = TRUE; + list_index = i; + END + if (ext_table[cur_disk][i].drive_letter == c(drive_input) ) + point = i; + END + END + + /* Input volume string to confirm delete */ + vol_matches = FALSE; + if (input != c(ESC)) + BEGIN + if (drives_exist) + BEGIN + /* delete privious volume mismatch message */ + string_input[0] = uc(NUL); /* AN000 */ + clear_screen( u(22), u(0), u(23), u(79) ); + /* Get input volume label */ + display(menu_41); /* AN000 */ + get_string_input(input_row,input_col,string_input); /* AN000 */ + if (string_input[0] == uc(ESC)) input = c(ESC); + + /* See if the volume id matches the selected drive */ /* AN000 */ + if (strcmp(ext_table[cur_disk][point].vol_label,string_input) == (int)ZERO) + vol_matches = TRUE; /* AN000 */ + else if (input != c(ESC)) display(error_34); + END + else + BEGIN + /* Tell user the drive has already been deleted */ + insert[0] = dos_upper(drive_input); /* AC000 */ + insert[1] = c(DRIVE_INDICATOR); /* AC000 */ + clear_screen( u(21), u(0), u(22), u(79) ); /* AN000 */ + display(error_29); + END + + END + + /* If it is a valid drive indicate that the input was ok */ + if ( (input != c(ESC)) && (drives_exist) && (vol_matches) ) /* AC000 */ + BEGIN + valid_input = TRUE; + + /* At this point we have a valid drive letter to delete */ + + /* Get the offset into the array for the drive to be deleted */ + delete_drive = find_ext_drive(drive_input - low_drive); + + /* Got a drive letter - prompt are you sure */ + display(menu_34); + + /* Get Y/N input, default is NO */ + input = get_yn_input(c(No),input_row,input_col); /* AC000 AC011 */ + + /* Clear everything out on screen in prompt area */ + clear_screen(u(23),u(0),u(23),u(79)); /* AC000 */ + + /* Go handle the delete */ + switch(input) + BEGIN + case 1: /* AC000 */ + BEGIN + /* Go ahead and mark it deleted in list array */ + + /* Throw up a flag to indicate we need to delete this one for real later */ + /* This is because if we change the ext_table array now, we lose the ability */ + /* to match up drive letters with locations, or at least it become more */ + /* complicated than I felt like figuring out, so mark it now and do it later */ + drive_list[list_index][1] = (unsigned char)DELETED; /* AC011 */ + + drives_reassigned = TRUE; + + /* Put prompt up on screen */ + for (i=(int)0; i < (int)23; i++) /* AC000 */ + BEGIN + /* See if drive deleted */ + if (drive_list[i][1] == uc(DELETED)) /* AC011 */ + BEGIN + /* Wipe out the drive info and print deleted message */ + /* See what column it is in */ + if (i < (int)12) /* AC000 */ + BEGIN + column = (int)4; /* AC000 */ + row = (int)(4 + i - (int)0); + clear_screen( (unsigned)row, (unsigned)column, + (unsigned)row, (unsigned)39 ); + END + else + BEGIN + column = (int)45; /* AC000 */ + row = (int)(4 + i - (int)12); + clear_screen( (unsigned)row, (unsigned)column, + (unsigned)row, (unsigned)79 ); + END + + /* Put the start row,col of message in the message string */ + s=status_3; + s++; + *s++ = ((char)(row/10))+'0'; + *s++ = ((char)(row%10))+'0'; + *s++ = ((char)(column/10))+'0'; + *s = ((char)(column%10))+'0'; + display(status_3); + END + END + /* Set the reboot flag */ + reboot_flag = TRUE; + clear_screen( u(21), u(0), u(23), u(79) ); /* AN000 */ + break; + END + + case ESC: + case 0: + clear_screen( u(21), u(0), u(23), u(79) ); /* AN000 */ + break; /* AC000 */ + + default: + internal_program_error(); + break; + END + END + + END + else /* drives do not exist! */ + BEGIN + /* No more logical drives to delete */ + clear_screen(u(16),u(0),u(21),u(79)); /* AC000 */ + display(error_22); + input = wait_for_ESC(); + END + END /* while input != esc */ + + if (drives_reassigned) + BEGIN + /* If anything got deleted, lets go do it for real */ + for (i=(int)0; i < (int)23;i++) /* AC000 */ + BEGIN + if (drive_list[i][1] == uc(DELETED)) /* AC011 */ + BEGIN /* AN011 */ + for (j=(int)0; j < (int)23;j++) /* AN011 */ + BEGIN /* AN011 */ + if (drive_list[i][0] == ext_table[cur_disk][j].drive_letter) /* AN011 */ + BEGIN + /* Zero sys id and show it changed */ + ext_table[cur_disk][j].boot_ind = uc(0); /* AC000 */ + ext_table[cur_disk][j].start_head = uc(0); /* AC000 */ + ext_table[cur_disk][j].start_sector = uc(0); /* AC000 */ + ext_table[cur_disk][j].start_cyl = u(0); /* AC000 */ + ext_table[cur_disk][j].sys_id = uc(0); /* AC000 */ + ext_table[cur_disk][j].end_head = uc(0); /* AC000 */ + ext_table[cur_disk][j].end_sector = uc(0); /* AC000 */ + ext_table[cur_disk][j].end_cyl = u(0); /* AC000 */ + ext_table[cur_disk][j].rel_sec = ul(0); /* AC000 */ + ext_table[cur_disk][j].num_sec = ul(0); /* AC000 */ + ext_table[cur_disk][j].mbytes_used = f(0); /* AN000 */ + ext_table[cur_disk][j].percent_used = u(0); /* AN000 */ + ext_table[cur_disk][j].changed = TRUE; /* AN000 */ + ext_table[cur_disk][j].drive_letter = NUL; /* AN000 */ + strcpy(ext_table[cur_disk][j].system,c(NUL)); /* AN000 */ + strcpy(ext_table[cur_disk][j].vol_label,c(NUL)); /* AN000 */ + END /* AN011 */ + END /* AN011 */ + END + END + + /* Show new drive letters */ + volume_display(); + + /* Say that drive letters changed */ + clear_screen(u(16),u(0),u(23),u(79)); /* AC000 */ + display(status_10); + wait_for_ESC(); + END + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + return; + +END + diff --git a/v4.0/src/CMD/FDISK/EXTERN.H b/v4.0/src/CMD/FDISK/EXTERN.H new file mode 100644 index 0000000..6975f67 --- /dev/null +++ b/v4.0/src/CMD/FDISK/EXTERN.H @@ -0,0 +1,82 @@ + +/* */ +/* */ +/****************************************************************************/ +/* Declare Global variables */ +/****************************************************************************/ +/* */ + + + +extern char cur_disk; +extern FLAG good_disk[2]; +extern unsigned char number_of_drives; +extern FLAG reboot_flag; +extern char errorlevel; +extern char max_partition_size; +extern char sort[24]; +extern FLAG no_fatal_error; /* AC000 */ +extern char valid_input; +extern unsigned char video_mode; +extern unsigned char display_page; +extern unsigned char video_attribute; /* AN006 */ + +extern unsigned total_disk[2]; /* AN000 */ +extern XFLOAT total_mbytes[2]; /* AN000 */ +extern unsigned char max_sector[2]; +extern unsigned max_head[2]; /* AC004 */ +extern unsigned required_cyls[2]; + +extern unsigned input_row; +extern unsigned input_col; +extern char insert[800]; /* AC000 */ +extern char *pinsert; + +extern unsigned char master_boot_record[2][512]; +extern unsigned char boot_record[512]; + +extern char next_letter; /* AN000 */ +extern FLAG primary_flag; /* AN000 */ +extern FLAG extended_flag; /* AN000 */ +extern FLAG logical_flag; /* AN000 */ +extern FLAG disk_flag; /* AN000 */ +extern FLAG quiet_flag; /* AN000 */ +extern unsigned primary_buff; /* AN000 */ +extern unsigned extended_buff; /* AN000 */ +extern unsigned logical_buff; /* AN000 */ +extern char cur_disk_buff; /* AN000 */ +extern unsigned long NOVAL; /* AN000 */ +extern char next_letter; /* AN000 */ +extern FLAG PercentFlag; /* AN000 */ + +extern FLAG mono_flag; /* AN006 */ + +extern char Yes; /* AN012 */ +extern char No; /* AN012 */ + +extern unsigned Parse_Ptr; /* AN010 */ +/* */ +/* */ +/****************************************************************************/ +/* Define Global structures */ +/****************************************************************************/ +/* */ + +extern struct entry part_table[2][4]; +extern struct entry ext_table[2][24]; +extern struct freespace free_space[24]; +extern struct KeyData *input_data; +extern struct dx_buffer_ioctl dx_buff; /* AN000 */ +extern struct SREGS segregs; +extern struct subst_list sublist; /* AN000 */ +extern struct diskaccess disk_access; /* AN002 */ +extern struct sublistx sublistp[1]; /* AN010 */ + +/* */ +/****************************************************************************/ +/* Define UNIONS */ +/****************************************************************************/ +/* */ + +extern union REGS regs; + diff --git a/v4.0/src/CMD/FDISK/FDBOOT.ASM b/v4.0/src/CMD/FDISK/FDBOOT.ASM new file mode 100644 index 0000000..4d6aaf0 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDBOOT.ASM @@ -0,0 +1,119 @@ +; BOOT - IBM hard disk boot record 6/8/82 +; +; +; This is the standard boot record that will be shipped on all hard disks. It contains: +; +; 1. Code to load (and give control to) the boot record for 1 of 4 possible +; operating systems. +; +; 2. A partition table at the end of the boot record, followed by the required signature. +; +; +_data segment public + assume cs:_data,ds:_data + + org 600h + + cli ;no interrupts for now + xor ax,ax + mov ss,ax + mov sp,7c00h ;new stack at 0:7c00 + mov si,sp ;where this boot record starts - 0:7c00 + push ax + pop es ;seg regs the same + push ax + pop ds + sti ;interrupts ok now + cld + mov di,0600h ;where to relocate this boot record to + mov cx,100h + repnz movsw ;relocate to 0:0600 +; jmp entry2 + db 0eah + dw $+4,0 +entry2: + mov si,offset tab ;partition table + mov bl,4 ;number of table entries +next: + cmp byte ptr[si],80h ;is this a bootable entry? + je boot ;yes + cmp byte ptr[si],0 ;no, is boot indicator zero? + jne bad ;no, it must be x"00" or x"80" to be valid + add si,16 ;yes, go to next entry + dec bl + jnz next + int 18h ;no bootable entries - go to rom basic +boot: + mov dx,[si] ;head and drive to boot from + mov cx,[si+2] ;cyl, sector to boot from + mov bp,si ;save table entry address to pass to partition boot record +next1: + add si,16 ;next table entry + dec bl ;# entries left + jz tabok ;all entries look ok + cmp byte ptr[si],0 ;all remaining entries should begin with zero + je next1 ;this one is ok +bad: + mov si,offset m1 ;oops - found a non-zero entry - the table is bad +msg: + lodsb ;get a message character + cmp al,0 + je hold + push si + mov bx,7 + mov ah,14 + int 10h ;and display it + pop si + jmp msg ;do the entire message +; +hold: jmp hold ;spin here - nothing more to do +tabok: + mov di,5 ;retry count +rdboot: + mov bx,7c00h ;where to read system boot record + mov ax,0201h ;read 1 sector + push di + int 13h ;get the boot record + pop di + jnc goboot ;successful - now give it control + xor ax,ax ;had an error, so + int 13h ;recalibrate + dec di ;reduce retry count + jnz rdboot ;if retry count above zero, go retry + mov si,offset m2 ;all retries done - permanent error - point to message, + jmp msg ;go display message and loop +goboot: + mov si,offset m3 ;prepare for invalid boot record + mov di,07dfeh + cmp word ptr [di],0aa55h ;does the boot record have the + ; required signature? + jne msg ;no, display invalid system boot record message + mov si,bp ;yes, pass partition table entry address + db 0eah + dw 7c00h,0 + +include fdisk5.cl1 + + org 7beh +tab: ;partition table + dw 0,0 ;partition 1 begin + dw 0,0 ;partition 1 end + dw 0,0 ;partition 1 relative sector (low, high parts) + dw 0,0 ;partition 1 # of sectors (low, high parts) + dw 0,0 ;partition 2 begin + dw 0,0 ;partition 2 end + dw 0,0 ;partition 2 relative sector + dw 0,0 ;partition 2 # of sectors + dw 0,0 ;partition 3 begin + dw 0,0 ;partition 3 end + dw 0,0 ;partition 3 relative sector + dw 0,0 ;partition 3 # of sectors + dw 0,0 ;partition 4 begin + dw 0,0 ;partition 4 end + dw 0,0 ;partition 4 relative sector + dw 0,0 ;partition 4 # of sectors +signa db 55h,0aah ;signature + +_data ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/FDCHNG.INC b/v4.0/src/CMD/FDISK/FDCHNG.INC new file mode 100644 index 0000000..198cf79 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDCHNG.INC @@ -0,0 +1,88 @@ +.xlist +; +; +;***************************************************************************** +;* * +;* Change list to FDISK modules * +;* * +;* Lines are tagged ANxxx for new, ACxxx for changed * +;* --------------------------------------------------------------------------* +;* 000 - DOS 4.0 Spec additions and DCR's thru unit/function test * +;* Date: 12/31/87 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 001 - DOS 4.0 DCR D468 Add errorlevel 1 on exit if there is no PRIMARY * +;* partition and the /Q switch is specified. This was done for * +;* SELECT. * +;* Date: 02/06/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 002 - DOS 4.0 PTM P3383 Add logic to use undocumented int 21 to check * +;* media to see if it has been formatted or not. CHECK_FORMAT added. * +;* Date: 02/08/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 003 - DOS 4.0 PTM P3589 Change CONVERT.C to compare for a period in the * +;* get_volume_string routine. It does a find first on the logical * +;* drive for the volume name and must copy it without the period. * +;* Date: 02/22/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 004 - DOS 4.0 PTM P3744 Change FDISK logic to display and handle a hard * +;* file of up to 4,000 MB. * +;* Date: 03/04/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 005 - DOS 4.0 PTM P3618 Add errorlevel 2 on exit if there is no changes * +;* made and the /Q switch is specified. This was done for * +;* SELECT. * +;* Date: 02/25/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 006 - DOS 4.0 PTM P3617 Change FDISK to color screens. This is done for * +;* SELECT. * +;* Date: 02/25/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 007 - DOS 4.0 DCR D490 Change FDISK IOCTL 63 to 66 in FDISK.H. * +;* Date: 02/26/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 008 - DOS 4.0 PTM P3698 Logic change for PTM 3618 was bad and had to * +;* to be corrected. * +;* Also changed FDISK IOCTL 64 to 67 in FDISK.H. * +;* Date: 02/26/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 009 - DOS 4.0 PTM P3938 A variable (temp) in subroutine * +;* write_info_to_disk was not initialized on entry. * +;* Date: 03/22/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 010 - DOS 4.0 PTM P4071 Changed the parsar logic to output the correct * +;* error message when parse is not correct. * +;* Date: 03/30/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 011 - DOS 4.0 PTM P4837 When deleting and allocating FDISK logical drives* +;* FDISK was deleting the wrong drives. * +;* Date: 05/12/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 012 - DOS 4.0 PTM P4835 FDISK had Y and N hard coded for YES and NO. * +;* Need to pick up 'Y' and 'N' translations from message file. * +;* Date: 05/12/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 013 - DOS 4.0 PTM P4883 FDISK will allow the deletion of a logical * +;* drive that has already been deleted. This error was caused by * +;* the logic change of P4837. * +;* Date: 05/17/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 014 - DOS 4.0 PTM P4953 FDISK displays too many files open error message * +;* when Cannot FDISK with Network Loaded message should be displayed.* +;* Date: 05/23/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 015 - DOS 4.0 PTM P5019 FDISK displays Insufficient memory error message * +;* when Invalid Parameter should be displayed. * +;* Logic has also been added to only get the volume ID of a logical * +;* drive by doing a Int 21 11h instead of IOCTL call 0866h. * +;* Date: 06/02/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 016 - DOS 4.0 PTM P5031 FDISK displays the wrong error message with 4 * +;* partitions allocated on same disk and trying to delete primary * +;* partition. * +;* Date: 06/06/88 Developer: Dennis M * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;***************************************************************************** +;* Note: This is file FDCHNG.INC for updating purposes * +;***************************************************************************** +.list + diff --git a/v4.0/src/CMD/FDISK/FDISK.C b/v4.0/src/CMD/FDISK/FDISK.C new file mode 100644 index 0000000..b39baad --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK.C @@ -0,0 +1,1121 @@ + +/* */ + + + +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SOURCE FILE NAME: FDISK */ +/* */ +/* DESCRIPTIVE NAME: FIXED DISK PARTITIONING UTILITY */ +/* */ +/* FUNCTION: */ +/* Allows creation and deletion of DOS related partitions */ +/* on fixed disk devices 80-81h (int 13h BIOS defined, */ +/* DOS). Also allows display of all partitions, and will */ +/* allow a partition to be marked active (bootable). The */ +/* user will be prompted for action thru a full screen */ +/* interface. The user can also create, delete and display */ +/* logical DOS drives within a EXTENDED DOS Partition. If a*/ +/* regular DOS partition is created, the beginning of the */ +/* partition will be scanned to insure a contiguous area of*/ +/* good sectors on the disk large enough to satisfy the */ +/* DOS system requirements. If a bad spot is found, the */ +/* start of the partition will be moved out until a good */ +/* area is located */ +/* */ +/* NOTES: The program will work by setting up a logical image */ +/* of all relevant disk information at initilization */ +/* time. All operations will be performed on this */ +/* logical image, thus reducing disk accesses to only */ +/* those required to initially set up the logical image,*/ +/* and to write the changed information at the end. The */ +/* user will be informed if there is a problem writing */ +/* the logical image back to the disk. */ +/* */ +/* FDISK will interface with the partition table in the */ +/* master boot record as defined in the PC-DOS technical*/ +/* reference manual. It will also create and manage the */ +/* EXTENDED DOS partition architecture as defined in the*/ +/* PC-DOS 3.30 functional spec (CP/DOS spec dcr pending)*/ +/* */ +/* ENTRY POINTS: MAIN */ +/* LINKAGE: [d:] [path] FDISK */ +/* */ +/* EXTERNAL REFERENCES: */ +/* Fixed Disk Master Boot Record */ +/* EXTENDED Partition Volume Boot Records */ +/* Note: Both of the above are physical data structures on */ +/* the surface of the disk */ +/* */ +/* P.S. - To whoever winds up maintaining this, I will */ +/* apoligize in advance. I had just learned 'C' when */ +/* writing this, so out of ignorance of the finer points*/ +/* of the langauge I did a lot of things by brute force.*/ +/* Hope this doesn't mess you up too much - MT 5/20/86 */ +/******************** END OF SPECIFICATIONS ********************/ + +#include +#include +#include +#include +#include +#include +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ + +/* */ +/**************************************************************************/ +/* */ +/* UTILITY NAME: FDISK.com */ +/* SOURCE FILE NAME: FDISK.c */ +/* STATUS: FDISK utility, DOS 3.3 */ +/* CHANGE HISTORY: UPDATED 5-29-87 DOS4.0 DRM */ +/* SYNTAX (Command line) */ +/* */ +/* [d:][path]FDISK */ +/* */ +/* or */ +/* */ +/* [d:][path]FDISK d [/PRI:m | /EXT:n | /LOG:o ...] */ +/* */ +/* d: Drive to load FDISK utility from */ +/* */ +/* path path to the directory on specified drive to */ +/* load FDISK from */ +/* */ +/* d Drive (1 or 2) that FDISK should operate on */ +/* */ +/* /PRI:m Size of Primary DOS partition to create in K */ +/* */ +/* /EXT:n Size of Extended DOS partition to create in K */ +/* */ +/* /LOG:o Size of Logical drive to create in K in the */ +/* extended partition */ +/* */ +/* UTILITY FUNCTION: */ +/* Allows you to create, set up, display, and delete the */ +/* DOS partitions on a fixed disk. */ +/* */ +/**************************************************************************/ + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: CHANGE_ACTIVE_PARTITION */ +/* */ +/* DESCRIPTIVE NAME: Change bootable partition */ +/* */ +/* FUNCTION: Will allow user to select the partition that will */ +/* recieve control when system is IPL'd. This is */ +/* only for the first hardfile as far as booting is */ +/* concerned, although partitions can be set active */ +/* the second. There are reserved partitions that may*/ +/* not be set active and this routine will enforce */ +/* that. */ +/* */ +/* NOTES: If no valid partition is specified, then the active */ +/* partition setting is left unchanged. Screen can be */ +/* exited via the ESC command before active partition */ +/* is changed and no action will take place */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Change Active Partition ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ # # ####### #### #### ####³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Enter the number of the partition you ³ */ +/* 19³want to make active...............: [#] ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Change_Active_Partition */ +/* LINKAGE: change_active_partition () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if invalid num */ +/* input is returned to this level */ +/* */ +/* EFFECTS: Display prompts needed to guide user input, and */ +/* gets input from user. */ +/* */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* display */ +/* get_num_input */ +/* table_display */ +/* wait_for_ESC */ +/* internal_program_error */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void change_active_partition() + +BEGIN + + char temp; + char default_value; + char input; + unsigned i; + unsigned x; + char num_partitions; + char valid_partitions; + char num_of_bootable_partitions; + char valid_input; + char input_default; + + + + input = c(NUL); + /* Clear screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display header */ + display(menu_23); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* Only allow active partitions on the first (and bootable) disk */ + if (cur_disk == c(0)) /* AC000 */ + + BEGIN + /* Display partition info and see if any partitions exist*/ + if (table_display()) + + BEGIN + /* See if active partition is bootable */ + for (i=u(0); i < u(4); i++) /* AC000 */ + BEGIN + if (part_table[0][i].sys_id != uc(0) && + part_table[0][i].boot_ind == uc(0x80)) /* AC000 */ + BEGIN + if ((part_table[0][i].sys_id == uc(BAD_BLOCK)) || + (part_table[0][i].sys_id==uc(EXTENDED))) /* AC000 */ + BEGIN + /* The active partition is not bootable, so warn user */ + display(error_24); + END + END + END + + /* Check to see if only one partition */ + num_partitions = c(0) ; /* AC000 */ + num_of_bootable_partitions = c(0); /* AC000 */ + for (i=u(0); i < u(4); i++) /* AC000 */ + + BEGIN + if (part_table[0][i].sys_id != uc(0)) /* AC000 */ + BEGIN + /* Get a count of partitions */ + num_partitions++; + + /* Get a count of the number of defined partitions but don't*/ + /* count those we know aren't bootable */ + if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) && + (part_table[0][i].sys_id != uc(EXTENDED))) /* AC000 */ + BEGIN + num_of_bootable_partitions++; + END + END + END + /* If only one partition found, see if it is active already */ + if (num_of_bootable_partitions == c(1)) /* AC000 */ + BEGIN + + /* Find the partition and see if it is already active */ + for (i=u(0); i < u(4); i++) /* AC000 */ + + BEGIN + if (part_table[0][i].sys_id !=uc(0) && + part_table[0][i].boot_ind == uc(0x80)) /* AC000 */ + + BEGIN + /* Make sure it is not unbootable partition again*/ + if ((part_table[0][i].sys_id != uc(BAD_BLOCK)) && + (part_table[0][i].sys_id!=uc(EXTENDED))) /* AC000 */ + + BEGIN + /* Once it is found, put out the message */ + display(error_15); + + /* Wait for ESC, then get out */ + wait_for_ESC(); + + /* clear the screen before going back to main menu*/ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; + END + END + END + END + /* See if any bootable partitions exist */ + if (num_of_bootable_partitions == c(0)) /* AC000 */ + BEGIN + /* At this point, we know at least one partition does exist due to*/ + /* getting past the table_display call, so the only ones around */ + /* must be unbootable */ + + /* Display this fact then get out of here */ + display(error_25); + END + else + BEGIN + /* All is okay to go and set one, do display prompts */ + number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */ + display(menu_15); + + /* Put up input prompt*/ + display(menu_24); + + /* Assume bad input until proven otherwise */ + valid_input = FALSE; + valid_partitions = num_partitions; + input_default = c(NUL); /* AC000 */ + + while (!valid_input) + BEGIN + /* Go get partition to make active */ + input = get_num_input(input_default,num_partitions,input_row,input_col); + + /* Save the input for next time in case CR pressed */ + input_default = input-'0'; + + clear_screen(u(18),u(0),u(23),u(79)); /* AC000 */ + + if (input != c(ESC)) /* AC000 */ + BEGIN + /* See if known unbootable partition */ + /* Set the new one */ + valid_partitions = c(0); /* AC000 */ + + /* Make sure the partitions are in physical order*/ + sort_part_table(c(4)); /* AC000 */ + + /* Go find existing partitiona */ + for (i=u(0);i < u(4); i++) /* AC000 */ + BEGIN + /* First we have to find it */ + if (part_table[0][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + /* If this is the 'input'th one, then we got it */ + if (valid_partitions == (input-'1')) + BEGIN + /* See if it is an unbootable partition */ + if ((part_table[0][sort[i]].sys_id != uc(BAD_BLOCK)) && + (part_table[0][sort[i]].sys_id != uc(EXTENDED))) /* AC000 */ + + BEGIN + /* Its bootable, so we have good input */ + valid_input = c(TRUE); /* AC000 */ + + /* Remove the active indicator from the old partition */ + for (x=u(0); x < u(4); x++) /* AC000 */ + BEGIN + + if (part_table[0][x].boot_ind == uc(0x80)) /* AC000 */ + BEGIN + part_table[0][x].changed = TRUE; + part_table[0][x].boot_ind = uc(0); /* AC000 */ + END + END + + /* Put in new active indicator */ + part_table[0][sort[i]].boot_ind = uc(0x80); /* AC000 */ + + /* Indicate that it is changed */ + part_table[0][sort[i]].changed = TRUE; + + /* Update the partition info display */ + table_display(); + + /* Clear off the old prompts */ + clear_screen(u(16),u(0),u(21),u(79)); /* AC000 */ + + /* Say you did it */ + insert[0] = input; + display(status_4); + break; + END + else + BEGIN + /* It is, so setup message and tell user */ + insert[0] = input; + display(error_17); + break; + END + END + else + BEGIN + /* Indicate we found one but keep going */ + valid_partitions++; + END + END + END + END + else + BEGIN + /* Mark ESC as ok input so we can get out of here */ + valid_input = c(TRUE); /* AC000 */ + END + END /* While loop */ + END + END /* table display test endif */ + else + BEGIN + /* No partitions to make active */ + display(error_16); + END + END + else + BEGIN + display(error_26); + END + /* clear the screen before going back to main menu */ + if (input != c(ESC)) /* AC000 */ + BEGIN + wait_for_ESC(); + END + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DISPLAY_PARTITION_INFORMATION */ +/* */ +/* DESCRIPTIVE NAME: Display partition information */ +/* */ +/* FUNCTION: Displays defined partition information and prompt */ +/* user to display disk volumes if they exist */ +/* */ +/* NOTES: */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³Display Partition Information ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Partition Status Type Start End Size³ */ +/* 09³ # # ####### #### #### ####³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³Total disk space is #### cylinders. ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³The EXTENDED DOS partition contains DOS ³ */ +/* 19³disk volumes. Do you want to display ³ */ +/* 20³the volume information............? [Y] ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Display_Partition_Information */ +/* LINKAGE: display_partition_information () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if invalid input */ +/* returned to this routine */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* wait_for_ESC */ +/* display */ +/* table_display */ +/* get_yn_input */ +/* find_partition_type */ +/* display_volume_information */ +/* internal_program_error */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void display_partition_information() + +BEGIN + + char input; + char temp; + + input = c(NUL); /* AC000 */ + /* Clear_screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display Header */ + display(menu_35); + + /* Setup and print current disk */ + insert[0] = cur_disk+1+'0'; + display(menu_5); + + /* print ESC prompt */ + display(menu_11); + + /* Display information */ + if (table_display()) + BEGIN + + /* Setup and print disk space msg */ + number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0)); /* AC000 */ + display(menu_15); + + /* See if any logical drive stuff to display */ + if (find_partition_type(uc(EXTENDED))) /* AC000 */ + BEGIN + /* See if any logical drives exist */ + if (find_logical_drive()) + BEGIN + + /* Prompt to see if they want to see EXTENDED info */ + display(menu_36); + + /* Get Y/N input, default is YES */ + input = get_yn_input(c(Yes),input_row,input_col); /* AC000 AC011 */ + switch(input) + BEGIN + + case 1: display_volume_information(); /* AC000 */ + break; + + case 0: break; /* AC000 */ + + case ESC: break; + + default: internal_program_error(); + break; + END + END + else + input = wait_for_ESC(); + END + else + input = wait_for_ESC(); + END + else + input = wait_for_ESC(); + /* clear the screen before going back to main menu */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return; +END + + + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DISPLAY_VOLUME_INFORMATION */ +/* */ +/* DESCRIPTIVE NAME: Display DOS disk Volume Information */ +/* */ +/* FUNCTION: Displays disk volume size and existence */ +/* */ +/* NOTES: */ +/* */ +/* The following screen is managed */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 01³Display DOS Disk Volume Information ³ */ +/* 02³ ³ */ +/* 03³Vol Start End Size Vol Start End Size³ */ +/* 04³ # #### #### #### # #### #### ####³ */ +/* 05³ ³ */ +/* 06³ ³ */ +/* 07³ ³ */ +/* 08³ ³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to FDISK Options ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: Display_Volume_Information */ +/* LINKAGE: display_volume_information () */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* wait_for_ESC */ +/* display */ +/* volume_display */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void display_volume_information() + +BEGIN + + char input; + char temp; + + input = c(NUL); /* AC000 */ + /* clear the screen */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + + /* Display Header */ + display(menu_37); + + /* Display information */ + temp = volume_display(); + + /* Set up partition size message */ + sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) ); + display(menu_21); + + /* print ESC prompt */ + display(menu_11); + + /* Wait to exit */ + input = wait_for_ESC(); + return; +END + +/* */ +char check_valid_environment() +BEGIN + + /* See if the net is there */ + regs.x.ax = u(INSTALLATION_CHECK); /* AC000 */ + int86((int)NETWORK,®s,®s); /* AC000 */ + +#ifdef DEBUG /* AN006 */ + regs.h.al = uc(0); /* AN006 */ +#endif /* AN006 */ + + /* Is it ? */ + if (regs.h.al != uc(0)) /* AC000 */ + BEGIN + + /* See if server is loaded, otherwise okay */ + if ((regs.x.bx & SERVER_CHECK) != u(0)) /* AC000 */ + BEGIN + no_fatal_error = FALSE; + display_msg((int)4,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class)); /* AN000 AC014*/ + return(FALSE); + END + END + return(TRUE); +END + + + +/* */ +void init_partition_tables() +BEGIN + +unsigned i; +unsigned char j; +unsigned k; +unsigned l; +unsigned partition_location; +char temp; +char more_drives_exist; +char num_logical_drives; +unsigned insert; +unsigned index; + + /* initialize first drive found to "C" */ + next_letter = c(SEA); /* AC000 */ + + /* Look at both disks */ + for (j = uc(0); j < number_of_drives; j++) /* AC000 */ + BEGIN + + /* Initialize the cur_disk field to the drive in question so */ + /* that the calls to the partition information routines will work */ + cur_disk = ((char)(j)); + + /* Read in the master boot record and see if it was okay */ + if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */ + BEGIN + + /* See if there was a valid boot record there */ + if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */ + BEGIN + + /* What was on the disk is a valid boot record, so save it */ + for (i=u(0);i < u(BYTES_PER_SECTOR); i++) /* AC000 */ + BEGIN + master_boot_record[j][i] = boot_record[i]; + END + END + /* We've now got a copy of the master boot record saved. Now we need */ + /* to translate what in the boot record to the area that it's going */ + /* to be worked on (part_table) */ + + /* Read in the data from the master boot record partition entries*/ + for (i=u(0); i < u(4); i++) /* AC000 */ + BEGIN + index = i*16; + + /* Get boot ind */ + part_table[j][i].boot_ind = master_boot_record[j][0x1BE+index]; + + /* Start head */ + part_table[j][i].start_head = master_boot_record[j][0x1BF+index]; + + /* Start sector - unscramble it from INT 13 format*/ + part_table[j][i].start_sector= (master_boot_record[j][0x1C0+index] & 0x3F); + + /* Start cyl - unscramble it from INT 13 format*/ + part_table[j][i].start_cyl= ((((unsigned)master_boot_record[j][0x1C0+index]) & 0x00C0) << 2) + + ((unsigned)master_boot_record[j][0x1C1+index]); + + /* System id */ + part_table[j][i].sys_id = master_boot_record[j][0x1C2+index]; + + /* End head */ + part_table[j][i].end_head = master_boot_record[j][0x1C3+index]; + + /* End sector - unscramble it from INT 13 format*/ + part_table[j][i].end_sector= (master_boot_record[j][0x1C4+index] & 0x3F); + + /* End cyl - unscramble it from INT 13 format*/ + part_table[j][i].end_cyl= ((((unsigned)master_boot_record[j][0x1C4+index]) & 0x00C0) << 2) + + ((unsigned)master_boot_record[j][0x1C5+index]); + + /* Relative sectors */ + + part_table[j][i].rel_sec = + ((unsigned long)master_boot_record[j][0x1C9+index]) << 24; + + part_table[j][i].rel_sec = part_table[j][i].rel_sec + + (((unsigned long)master_boot_record[j][0x1C8+index]) << 16); + + part_table[j][i].rel_sec = part_table[j][i].rel_sec + + (((unsigned long)master_boot_record[j][0x1C7+index]) << 8); + + part_table[j][i].rel_sec = part_table[j][i].rel_sec + + ((unsigned long)master_boot_record[j][0x1C6+index]); + + /* Number of sectors */ + part_table[j][i].num_sec = + ((unsigned long)master_boot_record[j][0x1CD+index]) << 24; + + part_table[j][i].num_sec = part_table[j][i].num_sec + + (((unsigned long)master_boot_record[j][0x1CC+index]) << 16); + + part_table[j][i].num_sec = part_table[j][i].num_sec + + (((unsigned long)master_boot_record[j][0x1CB+index]) << 8); + + part_table[j][i].num_sec = part_table[j][i].num_sec + + ((unsigned long)master_boot_record[j][0x1CA+index]); + + part_table[j][i].mbytes_used = + cylinders_to_mbytes(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1), + cur_disk); /* AN004 */ + + part_table[j][i].percent_used = + cylinders_to_percent(((part_table[j][i].end_cyl-part_table[j][i].start_cyl)+1), + total_disk[cur_disk]); /* AN000 */ + + /* Set drive letter */ + if ( (part_table[j][i].sys_id == DOS12) || /* AN000 */ + (part_table[j][i].sys_id == DOS16) || /* AN000 */ + (part_table[j][i].sys_id == DOSNEW) ) /* AN000 */ + part_table[j][i].drive_letter = next_letter++; /* AN000 */ + + /* Set changed flag */ + part_table[j][i].changed = FALSE; + END + END + else + BEGIN + return; + END + END + + /* Look at both disks */ + for (j = uc(0); j < number_of_drives; j++) /* AC000 */ + BEGIN + + /* Initialize the cur_disk field to the drive in question so */ + /* that the calls to the partition information routines will work */ + cur_disk = ((char)(j)); + + /* Read in the master boot record and see if it was okay */ + if (read_boot_record(u(0),j,uc(0),uc(1))) /* AC000 */ + BEGIN + /* Now, go read in extended partition info */ + if (find_partition_type(uc(EXTENDED))) /* AC000 */ + BEGIN + /* Initialize the array to zero's - include one dummy entry */ + for (i=u(0); i < u(24); i++) /* AC000 */ + BEGIN + ext_table[j][i].boot_ind = uc(0); /* AC000 */ + ext_table[j][i].start_head = uc(0); /* AC000 */ + ext_table[j][i].start_sector = uc(0); /* AC000 */ + ext_table[j][i].start_cyl = u(0); /* AC000 */ + ext_table[j][i].sys_id = uc(0); /* AC000 */ + ext_table[j][i].end_head = uc(0); /* AC000 */ + ext_table[j][i].end_sector = uc(0); /* AC000 */ + ext_table[j][i].end_cyl = u(0); /* AC000 */ + ext_table[j][i].rel_sec = ul(0); /* AC000 */ + ext_table[j][i].num_sec = ul(0); /* AC000 */ + ext_table[j][i].mbytes_used = f(0); /* AN000 */ + ext_table[j][i].percent_used = u(0); /* AN000 */ + ext_table[j][i].changed = FALSE; + ext_table[j][i].drive_letter = NUL; /* AN000 */ + + strcpy(ext_table[cur_disk][i].system,NUL); /* AN000 */ + strcpy(ext_table[cur_disk][i].vol_label,NUL); /* AN000 */ + + END + + /* Find where the first extended boot record is */ + temp = find_partition_location(uc(EXTENDED)); /* AC000 */ + partition_location = part_table[j][temp].start_cyl; + + /* Go find extended boot records as long as there are more of them */ + more_drives_exist = TRUE; + + /* Init the number of logical drives, for a array index */ + num_logical_drives = c(0); /* AC000 */ + + while (more_drives_exist) + BEGIN + /* Assume we won't find another logical drive */ + more_drives_exist = FALSE; + + /*Read in the extended boot record */ + if (read_boot_record(partition_location, + j, + uc(0), + uc(1))) /* AC000 */ + BEGIN + load_logical_drive(num_logical_drives,j); + + + /* find the next logical drive */ + for (i = u(0); i < u(4); i++) /* AC000 */ + BEGIN + index = i*16; + /* See if a sys id byte of exteneded exists */ + if (boot_record[0x1C2+index] == uc(EXTENDED)) /* AC000 */ + BEGIN + /* Found another drive, now get its location */ + partition_location= (((((unsigned)(boot_record[0x1C0 + index])) & 0x00C0) << 2)); + partition_location = partition_location + ((unsigned)(boot_record[0x1C1+index])); + + /* Indicate we found another one */ + more_drives_exist = TRUE; + + /* Up the count of found ones */ + num_logical_drives++; + break; + END + END + END + END + END + END + END + return; +END + + +/* */ +void load_logical_drive(point,drive) + +char point; +unsigned char drive; + +BEGIN + +char volume_label[13]; /* AC000 *//*Used be 11*/ +unsigned ext_part_num; /* AN000 */ +unsigned i; +unsigned j; /* AN000 */ +unsigned k; /* AN000 */ +unsigned length; /* AN000 */ +unsigned index; +unsigned dx_pointer; /* AN000 */ +unsigned partition_location; /* AN000 */ + + /* Check to see if anything is there */ + if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */ + BEGIN + /* The boot record is there - read in the logical drive if it is there */ + for (i = u(0); i < u(4); i++) /* AC000 */ + BEGIN + + index = i*16; + /* See if it is a defined extended drive*/ + if ((boot_record[0x1C2 + index] != uc(0)) && (boot_record[0x1C2 + index] != uc(EXTENDED))) /* AC000 */ + BEGIN + /* Get boot ind */ + ext_table[drive][point].boot_ind = boot_record[0x1BE + index]; + + /* Start head */ + ext_table[drive][point].start_head = boot_record[0x1BF + index]; + + /* Start sector - unscramble it from INT 13 format*/ + ext_table[drive][point].start_sector= (boot_record[0x1C0 + index] & 0x3F); + + /* Start cyl - unscramble it from INT 13 format*/ + ext_table[drive][point].start_cyl= ((((unsigned)boot_record[0x1C0+index]) & 0x00C0) << 2) + + ((unsigned)boot_record[0x1C1+index]); + + + /* System id */ + ext_table[drive][point].sys_id = boot_record[0x1C2+index]; + + /* End head */ + ext_table[drive][point].end_head = boot_record[0x1C3+index]; + + /* End sector - unscramble it from INT 13 format*/ + ext_table[drive][point].end_sector= (boot_record[0x1C4+index] & 0x3F); + + + /* End cyl - unscramble it from INT 13 format*/ + ext_table[drive][point].end_cyl= ((((unsigned)boot_record[0x1C4+index]) & 0x00C0) << 2) + + ((unsigned)boot_record[0x1C5+index]); + + /* Relative sectors */ + ext_table[drive][point].rel_sec = + ((unsigned long)boot_record[0x1C9+index]) << 24; + + ext_table[drive][point].rel_sec = + ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C8+index]) << 16); + + ext_table[drive][point].rel_sec = + ext_table[drive][point].rel_sec + (((unsigned long)boot_record[0x1C7+index]) << 8); + + ext_table[drive][point].rel_sec = + ext_table[drive][point].rel_sec + ((unsigned long)boot_record[0x1C6+index]); + + /* Number of sectors */ + + ext_table[drive][point].num_sec = + ((unsigned long)boot_record[0x1CD+index]) << 24; + + ext_table[drive][point].num_sec = + ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CC+index]) << 16); + + ext_table[drive][point].num_sec = + ext_table[drive][point].num_sec + (((unsigned long)boot_record[0x1CB+index]) << 8); + + ext_table[drive][point].num_sec = + ext_table[drive][point].num_sec + ((unsigned long)boot_record[0x1CA+index]); + + ext_table[drive][point].mbytes_used = + cylinders_to_mbytes(((ext_table[drive][point].end_cyl - ext_table[drive][point].start_cyl)+1), + cur_disk); /* AN004 */ + + ext_part_num = find_partition_location(uc(EXTENDED)); + + ext_table[drive][point].percent_used = + cylinders_to_percent(((ext_table[drive][point].end_cyl-ext_table[drive][point].start_cyl)+1), + ((part_table[drive][ext_part_num].end_cyl-part_table[drive][ext_part_num].start_cyl)+1)); /* AN000 */ + + ext_table[drive][point].drive_letter = next_letter++; /* AN000 */ + + partition_location = ext_table[drive][point].start_cyl; + + if (read_boot_record(ext_table[drive][point].start_cyl, + drive, + ext_table[drive][point].start_head, + ext_table[drive][point].start_sector)); + BEGIN /* AN000 */ + /* See if the disk has already been formated */ + if (check_format(ext_table[drive][point].drive_letter) == TRUE ) /* AN002 */ + BEGIN /* AN000 */ + /* get volume and system info */ + + /* AC000 Just for cleaning up purposes */ + + for (k = u(0); k < u(12); k++) /* AC000 */ + BEGIN /* AC000 */ + ext_table[drive][point].vol_label[k]=u(0); /* AC000 */ + END /* AC000 */ + + for (k = u(0); k < u(9); k++) /* AC000 */ + BEGIN /* AC000 */ + ext_table[drive][point].system[k]=u(0); /* AC000 */ + END /* AC000 */ + + get_volume_string(ext_table[drive][point].drive_letter,&volume_label[0]); /* AN000 AC015 */ + + for (k = u(0); k < strlen(volume_label); k++) /* AC000 AC015 */ + BEGIN /* AC000 AC015 */ + ext_table[drive][point].vol_label[k]=volume_label[k]; /* AC000 AC015 */ + END /* AC000 AC015 */ + + /* Now try to get it using GET MEDIA ID function */ + if (get_fs_and_vol(ext_table[drive][point].drive_letter)) /* AN000 */ + + BEGIN /* AN000 */ + /* AC000 Just use more conceptually simple logic */ + for (k=u(0); k < u(8); k++) /* AC000 */ + + BEGIN /* AC000 */ + if (dx_buff.file_system[k] != ' ') /* AC000 */ + length = k+1; /* AC000 */ + END /* AC000 */ + + strncpy(ext_table[drive][point].system,&dx_buff.file_system[0],u(length)); /* AN000 */ + END /* AN000 */ + + else /* AN000 */ + + BEGIN /* AN000 */ + if (ext_table[drive][point].num_sec > (unsigned long)FAT16_SIZE) /* AN000 */ + strcpy(ext_table[drive][point].system,FAT16); /* AN000 */ + else + strcpy(ext_table[drive][point].system,FAT12); /* AN000 */ + END /* AN000 */ + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + /* set up array to say no file system or volume label */ + strcpy(ext_table[drive][point].vol_label,NOVOLUME); /* AN000 */ + strcpy(ext_table[drive][point].system,NOFORMAT); /* AN000 */ + END /* AN000 */ + + regs.x.dx = u(0); + regs.x.ax = NETWORK_IOCTL; + regs.h.bl = ((ext_table[drive][point].drive_letter - 'A') + 1); + intdos(®s,®s); + if (regs.x.dx & 0x1000) strcpy(ext_table[drive][point].vol_label,"* Remote * "); + END + read_boot_record(ext_table[drive][point].start_cyl, + drive, + uc(0), + uc(1)); /* AN000 */ + END + END + END + + return; + +END + + + +/* */ +void reboot_system() +BEGIN + + + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + if (quiet_flag == FALSE) + BEGIN + display(menu_38); + getch(); + reboot(); + END + else + BEGIN + cur_disk = c(0); /* AN001 */ + reset_video_information(); /* AN006 */ + if ( (find_partition_type(uc(DOS12))) || + (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW))) ) /* AN001 */ + exit(ERR_LEVEL_0); /* AN001 */ + else /* AN001 */ + exit(ERR_LEVEL_1); /* AN001 */ + END +END + + +/* */ +void internal_program_error() + +BEGIN + display(internal_error); + DOSEXIT(u(0),u(0)); /* AC000 */ + return; +END + + diff --git a/v4.0/src/CMD/FDISK/FDISK.H b/v4.0/src/CMD/FDISK/FDISK.H new file mode 100644 index 0000000..5a0834f --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK.H @@ -0,0 +1,224 @@ +/* */ +/* */ +/****************************************************************************/ +/* Define statements */ +/****************************************************************************/ +/* */ + +#define FLAG char /* AN000 */ +#define BEGIN { +#define END } +#define ESC 0x1B +#define ESC_FLAG -2 /* AN000 */ +#define NUL 0x00 +#define NOT_FOUND 0xFF +#define DELETED -2 /* AC011 */ +#define INVALID 0xFF +#define PRIMARY 0x00 +#define EXTENDED 0x05 +#define BAD_BLOCK 0xFF +#define XENIX1 0x02 +#define XENIX2 0x03 +#define PCIX 0x75 +#define DOS12 0x01 +#define DOS16 0x04 +#define DOSNEW 0x06 /* AN000 */ +#define FAT16_SIZE 32680 +#define VOLUME 0x00 +#define FALSE (char) (1==0) /* AC000 */ +#define TRUE (char) !FALSE /* AC000 */ +#define LOGICAL 0x05 +#define CR 0x0D +#define BACKSPACE 0x08 +#define ACTIVE 0x80 +#define DOS_MAX 65535 /* Allow exactly 32mb worth of partitions */ +#define SYSTEM_FILE_SECTORS 250 +#define BYTES_PER_SECTOR 512 /* AN000 */ + +#include + +#define NETWORK 0x2F +#define INSTALLATION_CHECK 0xB800 +#define SERVER_CHECK 0x40 + + +#define FILE_NAME ":\\????????.???" /* AN000 */ +#define NOVOLUME "" /* AN000 */ +#define NOFORMAT "UNKNOWN " /* AN000 */ +#define FAT12 "FAT12 " /* AN000 */ +#define FAT16 "FAT16 " /* AN000 */ +#define SEA 'C' /* AN000 */ +#define ZERO 0 /* AN000 */ +#define NO_GOOD 0x02 /* AN000 */ +#define FIND_FIRST_MATCH 0x4E /* AN000 */ +#define GET_DTA 0x2F /* AN000 */ +#define NETWORK_IOCTL 0x4409 /* AN000 */ +#define GENERIC_IOCTL 0x440D /* AN000 */ +#define GET_MEDIA_ID 0x0866 /* AN007 */ +#define SPECIAL_FUNCTION 0x0867 /* AN002 AC008 */ +#define CAPCHAR 0x6520 /* AN000 */ +#define CAPSTRING 0x6521 /* AN000 */ +#define CAP_YN 0x6523 /* AN000 */ +#define INT21 0x21 /* AN000 */ +#define DISK 0x13 /* AN000 */ +#define NOERROR 0 /* AN000 */ +#define BLANKS " " /* AN000 */ +#define MAX_STRING_INPUT_LENGTH 11 /* AN000 */ +#define ERR_LEVEL_0 0 /* AN001 */ +#define ERR_LEVEL_1 1 /* AN001 */ +#define ERR_LEVEL_2 2 /* AN005 */ + +#define READ_DISK 2 +#define WRITE_DISK 3 +#define DISK_INFO 8 + +#define CURRENT_VIDEO_ATTRIBUTE 8 /* AN006 */ +#define CURRENT_VIDEO_STATE 15 +#define SET_ACTIVE_DISPLAY_PAGE 5 +#define SET_MODE 0 +#define SET_PAGE 5 +#define SET_CURSOR 0x02 /* AN006 */ +#define WRITE_ATTRCHAR 0x09 /* AN006 */ +#define VIDEO 0x10 +#define SCROLL_PAGE_UP 0x0600 /* AN006 */ +#define BW40_25 0 +#define Color40_25 1 +#define BW80_25 2 +#define Color80_25 3 +#define Color320_200 4 +#define BW320_200 5 +#define BW640_200 6 +#define MONO80_25 7 +#define MONO80_25A 15 /* AN006 */ + +#define NORMAL_PRELOAD 0 /* AN000 */ +#define ALL_UTILITY_MESSAGES -1 /* AN000 */ +#define NO_SUBST_TEXT 0 /* AN000 */ +#define NO_RESPONSE 0 /* AN000 */ +#define CLASS -1 /* AN000 */ * AN000 */ +#define NUL_POINTER 0 /* AN000 */ +#define SUBST_LIST 0 /* AN000 */ +#define SUBST_COUNT 0 /* AN000 */ + +#define VOL_LABEL 0x08 /* AN000 */ +#define PERCENT 0x25 /* AN000 */ +#define DECIMAL 0x2E /* AN000 */ +#define PERIOD 0x2E /* AN000 */ +#define ONE_MEG 1048576 /* AN000 */ + + #if IBMCOPYRIGHT +#define HIWHITE_ON_BLUE 0x1F /* AN006 */ +#define WHITE_ON_BLUE 0x17 /* AN006 */ +#define BLINK_HIWHITE_ON_BLUE 0x9F /* AN006 */ +#define HIWHITE_ON_BLACK 0x0F /* AN006 */ +#define GRAY_ON_BLACK 0x07 /* AN006 */ + #else +#define HIWHITE_ON_BLUE 0x0F /* AN006 */ +#define WHITE_ON_BLUE 0x07 /* AN006 */ +#define BLINK_HIWHITE_ON_BLUE 0x8F /* AN006 */ +#define HIWHITE_ON_BLACK 0x0F /* AN006 */ +#define GRAY_ON_BLACK 0x07 + #endif + + +#define BYTE unsigned char /* AN000 */ +#define WORD unsigned short /* AN000 */ +#define DWORD unsigned long /* AN000 */ +#define sw_type /* AN000 */ +#define sw_item_tag /* AN000 */ +#define sw_synonym /* AN000 */ +#define sw_value /* AN000 */ + +#define CARRY_FLAG 0x0001 /* mask for carry flag */ /* AN000 */ +#define PARITY_FLAG 0x0004 /* mask for parity flag */ /* AN000 */ +#define ACARRY_FLAG 0x0010 /* mask for aux carry flag */ /* AN000 */ +#define ZERO_FLAG 0x0040 /* mask for zero flag */ /* AN000 */ +#define SIGN_FLAG 0x0080 /* mask for sign flag */ /* AN000 */ +#define TRAP_FLAG 0x0100 /* mask for trap flag */ /* AN000 */ +#define INTERRUPT_FLAG 0x0200 /* mask for interrupt flag */ /* AN000 */ +#define DIRECTION_FLAG 0x0400 /* mask for direction flag */ /* AN000 */ +#define OVERFLOW_FLAG 0x0800 /* mask for overflow flag */ /* AN000 */ + +#define SEMICOLON 0x3B /* AN000 - VALID COMMAND LINE DELIMITER*/ + +#define XFLOAT unsigned + +#define u(c) ((unsigned)(c)) /* AN000 */ +#define f(c) ((XFLOAT)(c)) /* AN000 */ +#define c(c) ((char)(c)) /* AN000 */ +#define d(c) ((double)(c)) /* AN004 */ +#define uc(c) ((unsigned char)(c)) /* AN000 */ +#define ui(c) ((unsigned int)(c)) /* AN000 */ +#define ul(c) ((unsigned long)(c)) /* AN000 */ + + +struct entry + BEGIN + unsigned char boot_ind; + unsigned char start_head; + unsigned char start_sector; + unsigned start_cyl; + unsigned char sys_id; + unsigned char end_head; + unsigned char end_sector; + unsigned end_cyl; + unsigned long rel_sec; + unsigned long num_sec; + char order; + FLAG changed; + unsigned mbytes_used; /* AN000 */ + unsigned percent_used; /* AN000 */ + char vol_label[12]; /* AN000 */ + char system[9]; /* AN000 */ + char drive_letter; /* AN000 */ + END; + +struct freespace + BEGIN + unsigned space; + unsigned start; + unsigned end; + unsigned mbytes_unused; /* AN000 */ + unsigned percent_unused; /* AN000 */ + char volume_id[12]; /* AN000 */ + END; + +struct diskaccess /* AN002 */ + BEGIN /* AN002 */ + char dac_special_func; /* AN002 */ + char dac_access_flag; /* AN002 */ + END; /* AN002 */ + +struct dx_buffer_ioctl /* AN000 */ + BEGIN /* AN000 */ + unsigned int info_level; /* Information level */ /* AN000 */ + unsigned long serial_num; /* serial number */ /* AN000 */ + char vol_label[11]; /* volume label */ /* AN000 */ + char file_system[8]; /* file system */ /* AN000 */ + END; /* AN000 */ + +struct subst_list /* AN000 */ + BEGIN /* AN000 */ + char sl_size1; /* Size of List */ /* AN000 */ + char zero1; /* Reserved */ /* AN000 */ + char far *value1; /* Time, date, or ptr to data item*/ /* AN000 */ + char one; /* n of %n */ /* AN000 */ + char flags1; /* Data Type flags */ /* AN000 */ + char max_width1; /* Maximum FIELD width */ /* AN000 */ + char min_width1; /* Minimum FIELD width */ /* AN000 */ + char pad_char1; /* Character for pad FIELD */ /* AN000 */ + END; /* AN000 */ + +struct sublistx /* ;an000; */ + BEGIN /* ;an000; */ + unsigned char size; /* sublist size */ /* ;an000; */ + unsigned char reserved; /* reserved for future growth */ /* ;an000; */ + unsigned far *value; /* pointer to replaceable parm */ /* ;an000; */ + unsigned char id; /* type of replaceable parm */ /* ;an000; */ + unsigned char flags; /* how parm is to be displayed */ /* ;an000; */ + unsigned char max_width; /* max width of replaceable field */ /* ;an000; */ + unsigned char min_width; /* min width of replaceable field */ /* ;an000; */ + unsigned char pad_char; /* pad character for replaceable field */ /* ;an000; */ + END; + /* ;an000; */ + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/FDISK.LNK b/v4.0/src/CMD/FDISK/FDISK.LNK new file mode 100644 index 0000000..cb495d6 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK.LNK @@ -0,0 +1,31 @@ +/DOSSEG /MAP /CPA:1000 /SEG:1024 /E+ + main.obj + + mainmenu.obj + + d_menus.obj + + c_menus.obj + + fdisk.obj + + reboot.obj + + bootrec.obj + + fdboot.obj + + display.obj + + input.obj + + tdisplay.obj + + vdisplay.obj + + space.obj + + partinfo.obj + + video.obj + + makepart.obj + + int13.obj + + diskout.obj + + messages.obj + + fdparse.obj + + convert.obj + + global.obj + + _parse.obj + + _msgret.obj + + fdiskm.obj +fdisk.exe, +fdisk.map, +..\..\mapper\MAPPER.lib + +..\..\inc\comsubs.lib; + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/FDISK.MSG b/v4.0/src/CMD/FDISK/FDISK.MSG new file mode 100644 index 0000000..7af7939 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK.MSG @@ -0,0 +1,1177 @@ +/* FDISK MESSAGE FILE */ + +/************************************************************************/ +/* Please log all modifications to this file: */ +/*----------------------------------------------------------------------*/ +/* Date: 04/04/86 */ +/* Changed by: Mark T */ +/* Message changed: menu_1 - menu_38 */ +/* Reason: Creation of file */ +/*----------------------------------------------------------------------*/ +/* Date: 05/04/87 */ +/* Changed by: Dennis M */ +/* Message changed: menu_1 - menu_44 */ +/* Reason: DOS 3.3 */ +/*----------------------------------------------------------------------*/ +/* Date: */ +/* Changed by: */ +/* Message changed: */ +/* Reason: */ +/*----------------------------------------------------------------------*/ +/***********************************************************************/ + +/************************************************************************/ +/* FDISK MESSAGES */ +/* */ +/* Portions of the screen that are handled in the msg are indicated on */ +/* the listing of the screen with the message name given. If the text */ +/* message is defined in another screen, then the name is followed by */ +/* a "#" character */ +/* */ +/* NOTE TO TRANSLATORS */ +/* The characters inside the <> and the ^^ are control characters and */ +/* should not be translated. The Control characters are defined as */ +/* follows: */ +/* */ +/* - Highlight the following text */ +/* - Regular text */ +/* - Underline the following text */ +/* - Blink the following text */ +/* - Turn off Blink */ +/* - Print YES character, as set by define */ +/* - Print NO character, as set by define */ +/* - Sound the beep */ +/* - Save cursor position for later use */ +/* - Cursor position left justified and regular proceed to right */ +/* - Clear the screen out from control char to end of line */ +/* - Insert character from Insert[] string. This string must be set */ +/* up prior to displaying the message. The first will insert */ +/* Insert[0], the second Insert[1], etc....This will move the */ +/* cursor one postition. The Insert%% string will be initialized */ +/* */ +/* */ +/* Multiple control characters can be between the <>. */ +/* */ +/* The ^^ indicates Row and column for the text and has the format of */ +/* ^rrcc^ where the numbers are decimal and zero based .first row/col */ +/* is 00. The numbers are in decimal, and must be 2 characters, which */ +/* means rows/cols 0-9 should be listed as 00-09. For example, the 5th */ +/* row, 3rd column on the screen would be listed as ^0402^. */ +/* */ +/* The column number is always the column desired. The row number is */ +/* an offset from the previous row. For example, if the text just */ +/* printed is on row 6, and the next text should be printed 2 rows */ +/* down in column 0, then the control strin would be ^0201^. The first */ +/* row specified in the message is assumed to be based off of row 0, */ +/* it would actually specify the actual row for the start of the msg */ +/* to be printed. */ +/* */ +/* NOTE: ALWAYS SAVE THIS FILE WITH NO TABS CHARACTERS */ +/************************************************************************/ + + +/************************************************************************/ +/* */ +/* Define Area for text variables */ +/* */ +/************************************************************************/ + +#define ACTIVE_PART 'A' /* Character to indicate active status */ +#define DRIVE_INDICATOR ':' /* Character displayed to indicate drive letter */ + +/* */ +/* */ +/* The following character strings are required to display the */ +/* menu screens for FDISK. The messages have a label type of: menu_xx */ +/* */ +/* */ + +/*******************************************************************************************************/ +/* Screen for DO_MAIN_MENU */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ IBM Personal Computer ³menu_1 */ +/* 01³ Fixed Disk Setup Program Version 3.40 ³menu_1 */ +/* 02³ (C%Copyright IBM Corp. 1983,1988 ³menu_1 */ +/* 03³ ³ */ +/* 04³ FDISK Options ³menu_2 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 */ +/* 09³ ³ */ +/* 10³ 1. Create DOS Partition or Logical DOS Drive ³menu_2 */ +/* 11³ 2. Set active partition ³menu_2 */ +/* 12³ 3. Delete DOS Partition or Logical DOS Drive ³menu_2 */ +/* 13³ 4. Display partition information ³menu_2 */ +/* 14³ 5. Select next fixed disk drive ³menu_4 */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [#] ³menu_7 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ Warning! No partitions are set active - disk 1 is not startable unless ³menu_6 */ +/* 21³ a partition is set active. ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to exit FDISK ³menu_2 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + + +/*-------------------------------------------------------------*/ + char far *menu_1 = + +"^0030^è1001\ + ^0128^è1002\ + ^0124^è1003"; + + + +/*-------------------------------------------------------------*/ + char far *menu_2 = + +"^0433^è1004\ + ^0604^è1005\ + ^0104^è1006\ + ^0104^è1007\ + ^0104^è1008\ + ^1104^è1009"; + +/*-------------------------------------------------------------*/ + char far *menu_3 = + +"^0804^è1010"; + +/*-------------------------------------------------------------*/ + char far *menu_4 = + +"^1404^è1011"; + +/*-------------------------------------------------------------*/ + char far *menu_5 = + +"^0604^è1012"; + +/*-------------------------------------------------------------*/ + char far *menu_6 = + +"^2004^è1013\ + ^0104^è1014"; + +/*-------------------------------------------------------------*/ + char far *menu_7 = + +"^1704^è1015"; + +/*******************************************************************************************************/ +/* Screen for CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create DOS Partition or Logical DOS Drive ³menu_8 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 # */ +/* 09³ ³ */ +/* 10³ 1. Create Primary DOS Partition ³menu_9 */ +/* 11³ 2. Create Extended DOS Partition ³menu_9 */ +/* 12³ 3. Create logical DOS Drive(s) in the Extended DOS Partition ³menu_10 */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [ ] ³menu_7 # */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_8 = + +"^0420^è1016"; + +/*-------------------------------------------------------------*/ + char far *menu_9 = + +"^1004^è1017\ + ^0104^è1018"; + +/*-------------------------------------------------------------*/ + char far *menu_10 = + +"^1204^è1019"; + +/*-------------------------------------------------------------*/ + char far *menu_11 = + +"^2404^è1020"; + + +/*******************************************************************************************************/ +/* Screen for DOS_CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Primary DOS Partition ³menu_12 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Do you wish to use the maximum available size for a Primary DOS Partition ³menu_13 */ +/* 09³ and make the partition active (Y/N).....................? [Y] ³menu_13 */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_12 = + +"^0427^è1021"; + +/*-------------------------------------------------------------*/ + char far *menu_13 = + +"^0804^è1022\ + ^0104^è1023"; + +/*-------------------------------------------------------------*/ + char far *menu_45 = + +"^0804^è1022\ + ^0104^è1024"; + + +/*******************************************************************************************************/ +/* Screen for INPUT_DOS_CREATE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Primary DOS Partition ³menu_12 # */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 */ +/* 15³ Maximum space available for partition is #### Mbytes (###%) ³menu_16 */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ Enter partition size in Mbytes or percent of disk space (%) to ³menu_39 */ +/* 19³ create a Primary DOS Partition..................................[####] ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/****************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_14 = + +"^0804^è1025\ + ^0104^ \ + ^0104^ \ + ^0104^ \ + ^0104^ "; + +/*-------------------------------------------------------------*/ + char far *menu_15 = + +"^1404^è1026"; + +/*-------------------------------------------------------------*/ + char far *menu_16 = + +"^1504^è1027"; + +/*-------------------------------------------------------------*/ + char far *menu_39 = + +"^1804^è1028\ + ^0104^è1029"; + + +/****************************************************************************************************/ +/* Screen for EXT_CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Extended DOS Partition ³menu_17 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ Maximum space available for partition is #### Mbytes (##%) ³menu_16 # */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ Enter partition size in Mbytes or percent of disk space (%) to ³menu_42 # */ +/* 19³ create an Extended DOS Partition................................[####] ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to continue ³menu_46 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/***************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_17 = + +"^0427^è1030"; + +/*-------------------------------------------------------------*/ + char far *menu_42 = + +"^1804^è1028\ + ^0104^è1031"; + + +/*-------------------------------------------------------------*/ + char far *menu_46 = + +"^2404^è1032"; + + + + +/*****************************************************************************************************/ +/* Screen for VOLUME_CREATE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Create Logical DOS Drive(s) in the Extended Partition ³menu_18 */ +/* 02³ ³ */ +/* 03³Drv Volume Label Mbytes System Usage Drv Volume Label Mbytes System Usage³menu_19/20 */ +/* 04³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 05³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 06³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 07³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 08³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 09³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 10³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 11³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 12³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 13³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 14³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 15³## ########### #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_17 */ +/* 18³ Maximum space available for logical drive is #### Mbytes (###%) ³menu_22 */ +/* 19³ ³ */ +/* 20³ Enter logical drive size in Mbytes or percent of disk space (%)...[####] ³menu_40 */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/***************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_18 = + +"^0112^è1033"; + +/*-------------------------------------------------------------*/ + char far *menu_19 = + +"^0300^è1034\ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ "; + +/*----------------------------------------------------------*/ + char far *menu_43 = + +"^1000^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ "; + +/*-------------------------------------------------------------*/ + char far *menu_20 = + +"^0341^è1034\ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ "; + +/*---------------------------------------------------------*/ + char far *menu_44 = + +"^1041^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ "; + +/*-------------------------------------------------------------*/ + char far *menu_21 = + +"^1704^è1035"; + +/*-------------------------------------------------------------*/ + char far *menu_22 = + +"^1804^è1036"; + +/*-------------------------------------------------------------*/ + char far *menu_40 = + +"^2004^è1037"; + + +/*****************************************************************************************************/ +/* Screen for CHANGE_ACTIVE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Set Active Partition ³menu_23 */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Enter the number of the partition you want to make active............:[#] ³menu_24 */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_23 = + +"^0430^è1038"; + +/*-------------------------------------------------------------*/ + char far *menu_24 = + +"^1604^è1039"; + + +/*****************************************************************************************************/ +/* Screen for DELETE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete DOS Partition or Logical DOS Drive ³menu_25 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 # */ +/* 09³ ³ */ +/* 10³ 1. Delete Primary DOS Partition ³menu_26 */ +/* 11³ 2. Delete Extended DOS Partition ³menu_26 */ +/* 12³ 3. Delete Logical DOS Drive(s) in the Extended DOS Partition ³menu_27 */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [ ] ³menu_7 # */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_25 = + +"^0419^è1040"; + +/*-------------------------------------------------------------*/ + char far *menu_26 = + +"^1004^è1041\ + ^0104^è1042"; + +/*-------------------------------------------------------------*/ + char far *menu_27 = + +"^1204^è1043"; + +/*****************************************************************************************************/ +/* Screen for DOS_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete Primary DOS Partition ³menu_28 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Warning! Data in the deleted Primary DOS Partition will be lost. ³menu_29 */ +/* 17³ Do you wish to continue (Y/N).................? [N] ³menu_29 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_28 = + +"^0426^è1044"; + +/*-------------------------------------------------------------*/ + char far *menu_29 = + +"^1604^è1045\ + ^0104^è1046"; + +/*****************************************************************************************************/ +/* Screen for EXT_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete Extended DOS Partition ³menu_30 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Warning! Data in the deleted Extended DOS partition will be lost. ³menu_31 */ +/* 17³ Do you wish to continue (Y/N).................? [N] ³menu_31 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_30 = + +"^0426^è1047"; + +/*-------------------------------------------------------------*/ + char far *menu_31 = + +"^1604^è1048\ + ^0104^è1049"; + +/******************************************************************************************************/ +/* Screen for VOL_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Delete Logical DOS Drive(s) in the Extended DOS Partition ³menu_32 */ +/* 02³ ³ */ +/* 03³Drv Volume Label MBytes System Usage Drv Volume Label MBytes System Usage³menu_19/20 # */ +/* 04³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 05³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 06³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 07³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 08³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 09³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 10³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 11³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 12³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 13³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 14³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 15³## ############# #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS Partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_21 */ +/* 18³ ³ */ +/* 19³ Warning! Data in a deleted Logical DOS Drive will be lost. ³menu_33 */ +/* 20³ What drive do you want to delete...........................? [ ] ³menu_33 */ +/* 21³ Enter Volume Label.............................? [ ] ³menu_41 */ +/* 22³ Are you sure (Y/N).............................? [N] ³menu_34 */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_32 = + +"^0112^è1050"; + +/*-------------------------------------------------------------*/ + char far *menu_33 = + +"^1904^è1051\ + ^0104^è1052"; + +/*-------------------------------------------------------------*/ + char far *menu_34 = + +"^2204^è1053"; + +/*-------------------------------------------------------------*/ + char far *menu_41 = + +"^2104^è1054"; + +/******************************************************************************************************/ +/* Screen for DISPLAY_PARTITION_INFORMATION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Display Partition Information ³menu_35 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ The Extended DOS partition contains Logical DOS Drives. ³menu_36 */ +/* 18³ Do you want to display the logical drive information (Y/N)......? [Y] ³menu_36 */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_35 = + +"^0426^è1055"; + +/*-------------------------------------------------------------*/ + char far *menu_36 = + +"^1704^è1056\ + ^0104^è1057"; + +/*****************************************************************************************************/ +/* Screen for DISPLAY_VOLUME_INFORMATION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Display Logical DOS Drive Information ³menu_37 */ +/* 02³ ³ */ +/* 03³Drv Volume Label Mbytes System Usage Drv Volume Label Mbytes System Usage³menu_19/20 */ +/* 04³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 05³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 16³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 17³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 18³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 19³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 10³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 11³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 12³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 13³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 14³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 15³## ############# #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_17 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_37 = + +"^0121^è1058"; + +/*****************************************************************************************************/ +/* Screen for SYSTEM_REBOOT */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ ³ */ +/* 07³ ³ */ +/* 08³ ³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ System will now restart ³menu_38 */ +/* 14³ ³ */ +/* 15³ Insert DOS diskette in drive A: ³menu_38 */ +/* 16³ Press any key when ready . . . ³menu_38 */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_38 = + +"^1304^è1059\ + ^0204^è1060\ + ^0104^è1061"; + + +/* */ +/* */ +/* The following character strings are required to display the */ +/* status messages indicating successful operation. These messages */ +/* have the form: status_xx */ +/* */ +/* Note: In order to overlay any previous message on the screen, these */ +/* messages are all 2 lines long. The second line may only be */ +/* a blank line. If 2 lines are needed for translation, use the */ +/* second line for text. Exceptions are those msgs on line 0, */ +/* and status_3. */ +/* */ + +/*-------------------------------------------------------------*/ + char far *status_1 = + +"^2104^è1062\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_2 = + +"^2104^è1063\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_3 = + +"^0004^è1064"; +/* NOTE - the ^rrcc^ must be the first thing in this string */ + +/*-------------------------------------------------------------*/ + char far *status_4 = + +"^2104^è1065\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_5 = + +"^2104^è1066\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_6 = + +"^2104^è1067\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_7 = + +"^2204^è1068"; + +/*-------------------------------------------------------------*/ + char far *status_8 = + +"^2104^è1069\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_9 = + +"^1004^è1070\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_10 = + +"^1804^è1071"; + +/*-------------------------------------------------------------*/ + char far *status_11 = + +"^0004^è1072"; +/* NOTE - the ^rrcc^ must be the first thing in this string */ + +/*-------------------------------------------------------------*/ + char far *status_12 = + +"^2104^è1073\ + ^0100^"; + +/*-------------------------------------------------------------*/ + +/* */ +/* */ +/* The following character strings are required to display the */ +/* error messages. These have form: error_xx */ +/* */ +/* Note: In order to overlay any previous message on the screen, these */ +/* messages are all 2 lines long. The second line may only be */ +/* a blank line. If 2 lines are needed for translation, use the */ +/* second line for text. Exceptions are those msgs on line 0. */ +/* and those messages that start on line 23 */ +/* */ + + +/*-------------------------------------------------------------*/ + char far *error_1 = + +"^0004^è1074\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_2 = + +"^2204^è1075\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_3 = + +"^2204^è1076\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_4 = + +"^0004^è1077"; + +/*-------------------------------------------------------------*/ + char far *error_5 = + +"^0004^è1078"; + +/*-------------------------------------------------------------*/ + char far *error_6 = + +"^2204^è1079\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_7 = + +"^2204^è1080\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_8 = + +"^2204^è1081\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_9 = + +"^2204^è1082\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_10 = + +"^2204^è1083\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_12 = + +"^2204^è1084\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_13 = + +"^2204^è1085\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_14 = + +"^2204^è1086\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_15 = + +"^2204^è1087\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_16 = + +"^2204^è1088\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_17 = + +"^2204^è1089"; + +/*-------------------------------------------------------------*/ + char far *error_19 = + +"^2204^è1090\ + ^0104^è1091"; + +/*-------------------------------------------------------------*/ + char far *error_20 = + +"^2204^è1092\ + ^0104^è1093"; + +/*-------------------------------------------------------------*/ + char far *error_21 = + +"^2204^è1094"; + +/*-------------------------------------------------------------*/ + char far *error_22 = + +"^2204^è1095"; + +/*-------------------------------------------------------------*/ + char far *error_23 = + +"^2204^\ + ^0104^è1096"; + +/*-------------------------------------------------------------*/ + char far *error_24 = + +"^2204^è1097"; + +/*-------------------------------------------------------------*/ + char far *error_25 = + +"^2204^è1098\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_26 = + +"^2204^è1099"; + +/*-------------------------------------------------------------*/ + char far *error_27 = + +"^2204^è1100"; + +/*-------------------------------------------------------------*/ + char far *error_28 = + +"^2204^è1101\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_29 = + +"^2204^è1102\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_30 = + +"^2204^è1103"; + +/*-------------------------------------------------------------*/ + char far *error_31 = + +"^2304^è1104"; + +/*-------------------------------------------------------------*/ + char far *error_32 = + +"^2204^è1105\ + ^0104^è1106"; + +/*-------------------------------------------------------------*/ + char far *error_33 = + +"^2200^\ + ^0104^è1107"; + +/*-------------------------------------------------------------*/ + char far *error_34 = + +"^2204^è1108"; + +/*-------------------------------------------------------------*/ + char far *error_35 = + +"^2204^è1109\ + ^0104^è1110"; + +/*-------------------------------------------------------------*/ + char far *error_36 = + +"^2204^è1111\ + ^0100^"; + +/*-------------------------------------------------------------*/ + + +/* */ +/* */ +/* The following message is only included as an aide to debug message */ +/* strings during translations. The FDISK message formatter will attempt*/ +/* to the best of its ability to catch invalid message strings and */ +/* print the error. This message should NEVER appear for a user, so it */ +/* is not neccessary to translate this message */ +/* */ +/* */ + + +/*-------------------------------------------------------------*/ + + char far *debug_msg = + +"^2200^è1112"; + +/*-------------------------------------------------------------*/ + char far *internal_error = + +"^2204^è1113"; +/* */ +/* The following are not translatable. They are the partition names */ +/* */ + + char *DOS_part = "PRI DOS"; + char *XENIX_part = " XENIX "; + char *EXTENDED_part = "EXT DOS"; + char *BAD_BLOCK_part= " Table "; + char *PCIX_part = " PC/IX "; + char *NON_DOS_part = "Non-DOS"; diff --git a/v4.0/src/CMD/FDISK/FDISK.SKL b/v4.0/src/CMD/FDISK/FDISK.SKL new file mode 100644 index 0000000..b50bb13 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK.SKL @@ -0,0 +1,18 @@ +:util FDISK ;utility name +:class A ;system messages +; +:use 1 COMMON1 ;"Incorrect DOS version" +:use 2 COMMON2 ;"Insufficient Memory" +:use 3 COMMON3 ;"Internal error loading messages" +:use 8 EXTEND87 ;"Invalid parameter" +:def 9 "Y",0 ;"Y" +:def 10 "N",0 ;"N" +; +:class B +:def 4 "Cannot FDISK with network loaded",CR,LF +:def 5 "No fixed disks present",CR,LF +:def 6 "Error reading fixed disk",CR,LF +:def 7 "Error writing fixed disk",CR,LF +; +; +:end diff --git a/v4.0/src/CMD/FDISK/FDISK5.SKL b/v4.0/src/CMD/FDISK/FDISK5.SKL new file mode 100644 index 0000000..e7f401d --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISK5.SKL @@ -0,0 +1,15 @@ +:class 1 +; +;******** messages for the Fixed Disk Boot Record ****** +; +;m1: db "Invalid partition table",0 ;23 +:use 1114 fdisk m1: +; +;m2: db "Error loading operating system",0 ;30 +:use 1115 fdisk m2: +; +;m3: db "Missing operating system",0 ;24 +:use 1116 fdisk m3: +; +:end + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/FDISKMSG.C b/v4.0/src/CMD/FDISK/FDISKMSG.C new file mode 100644 index 0000000..72e5567 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISKMSG.C @@ -0,0 +1,1181 @@ +/* FDISK MESSAGE FILE */ + +/************************************************************************/ +/* Please log all modifications to this file: */ +/*----------------------------------------------------------------------*/ +/* Date: 04/04/86 */ +/* Changed by: Mark T */ +/* Message changed: menu_1 - menu_38 */ +/* Reason: Creation of file */ +/*----------------------------------------------------------------------*/ +/* Date: 05/04/87 */ +/* Changed by: Dennis M */ +/* Message changed: menu_1 - menu_44 */ +/* Reason: DOS 3.3 */ +/*----------------------------------------------------------------------*/ +/* Date: */ +/* Changed by: */ +/* Message changed: */ +/* Reason: */ +/*----------------------------------------------------------------------*/ +/***********************************************************************/ + +/************************************************************************/ +/* FDISK MESSAGES */ +/* */ +/* Portions of the screen that are handled in the msg are indicated on */ +/* the listing of the screen with the message name given. If the text */ +/* message is defined in another screen, then the name is followed by */ +/* a "#" character */ +/* */ +/* NOTE TO TRANSLATORS */ +/* The characters inside the <> and the ^^ are control characters and */ +/* should not be translated. The Control characters are defined as */ +/* follows: */ +/* */ +/* - Highlight the following text */ +/* - Regular text */ +/* - Underline the following text */ +/* - Blink the following text */ +/* - Turn off Blink */ +/* - Print YES character, as set by define */ +/* - Print NO character, as set by define */ +/* - Sound the beep */ +/* - Save cursor position for later use */ +/* - Cursor position left justified and regular proceed to right */ +/* - Clear the screen out from control char to end of line */ +/* - Insert character from Insert[] string. This string must be set */ +/* up prior to displaying the message. The first will insert */ +/* Insert[0], the second Insert[1], etc....This will move the */ +/* cursor one postition. The Insert%% string will be initialized */ +/* */ +/* */ +/* Multiple control characters can be between the <>. */ +/* */ +/* The ^^ indicates Row and column for the text and has the format of */ +/* ^rrcc^ where the numbers are decimal and zero based .first row/col */ +/* is 00. The numbers are in decimal, and must be 2 characters, which */ +/* means rows/cols 0-9 should be listed as 00-09. For example, the 5th */ +/* row, 3rd column on the screen would be listed as ^0402^. */ +/* */ +/* The column number is always the column desired. The row number is */ +/* an offset from the previous row. For example, if the text just */ +/* printed is on row 6, and the next text should be printed 2 rows */ +/* down in column 0, then the control strin would be ^0201^. The first */ +/* row specified in the message is assumed to be based off of row 0, */ +/* it would actually specify the actual row for the start of the msg */ +/* to be printed. */ +/* */ +/* NOTE: ALWAYS SAVE THIS FILE WITH NO TABS CHARACTERS */ +/************************************************************************/ + + +/************************************************************************/ +/* */ +/* Define Area for text variables */ +/* */ +/************************************************************************/ + +#define YES 'Y' +#define NO 'N' +#define ACTIVE_PART 'A' /* Character to indicate active status */ +#define DRIVE_INDICATOR ':' /* Character displayed to indicate drive letter */ + +/* */ +/* */ +/* The following character strings are required to display the */ +/* menu screens for FDISK. The messages have a label type of: menu_xx */ +/* */ +/* */ + +/*******************************************************************************************************/ +/* Screen for DO_MAIN_MENU */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ IBM Personal Computer ³menu_1 */ +/* 01³ Fixed Disk Setup Program Version 3.40 ³menu_1 */ +/* 02³ (C%Copyright IBM Corp. 1983,1988 ³menu_1 */ +/* 03³ ³ */ +/* 04³ FDISK Options ³menu_2 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 */ +/* 09³ ³ */ +/* 10³ 1. Create DOS Partition or Logical DOS Drive ³menu_2 */ +/* 11³ 2. Set active partition ³menu_2 */ +/* 12³ 3. Delete DOS Partition or Logical DOS Drive ³menu_2 */ +/* 13³ 4. Display partition information ³menu_2 */ +/* 14³ 5. Select next fixed disk drive ³menu_4 */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [#] ³menu_7 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ Warning! No partitions are set active - disk 1 is not startable unless ³menu_6 */ +/* 21³ a partition is set active. ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to exit FDISK ³menu_2 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + + +/*-------------------------------------------------------------*/ + char far *menu_1 = + +"^0029^Microsoft DOS \ + ^0121^Fixed Disk Setup Program Version 4.00\ + ^0124^(C)Copyright 1988 Microsoft Corp"; + + + +/*-------------------------------------------------------------*/ + char far *menu_2 = + +"^0433^FDISK Options\ + ^0604^1. Create DOS Partition or Logical DOS Drive\ + ^0104^2. Set active partition\ + ^0104^3. Delete DOS Partition or Logical DOS Drive\ + ^0104^4. Display partition information\ + ^1104^Press Esc to exit FDISK"; + +/*-------------------------------------------------------------*/ + char far *menu_3 = + +"^0804^Choose one of the following:"; + +/*-------------------------------------------------------------*/ + char far *menu_4 = + +"^1404^5. Select next fixed disk drive"; + +/*-------------------------------------------------------------*/ + char far *menu_5 = + +"^0604^Current fixed disk drive: "; + +/*-------------------------------------------------------------*/ + char far *menu_6 = + +"^2004^Warning! No partitions are set active - disk 1 is not startable unless\ + ^0104^a partition is set active"; + +/*-------------------------------------------------------------*/ + char far *menu_7 = + +"^1704^Enter choice: [ ]"; + +/*******************************************************************************************************/ +/* Screen for CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create DOS Partition or Logical DOS Drive ³menu_8 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 # */ +/* 09³ ³ */ +/* 10³ 1. Create Primary DOS Partition ³menu_9 */ +/* 11³ 2. Create Extended DOS Partition ³menu_9 */ +/* 12³ 3. Create logical DOS Drive(s) in the Extended DOS Partition ³menu_10 */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [ ] ³menu_7 # */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_8 = + +"^0420^Create DOS Partition or Logical DOS Drive"; + +/*-------------------------------------------------------------*/ + char far *menu_9 = + +"^1004^1. Create Primary DOS Partition\ + ^0104^2. Create Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_10 = + +"^1204^3. Create Logical DOS Drive(s) in the Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_11 = + +"^2404^Press Esc to return to FDISK Options"; + + +/*******************************************************************************************************/ +/* Screen for DOS_CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Primary DOS Partition ³menu_12 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Do you wish to use the maximum available size for a Primary DOS Partition ³menu_13 */ +/* 09³ and make the partition active (Y/N).....................? [Y] ³menu_13 */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_12 = + +"^0427^Create Primary DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_13 = + +"^0804^Do you wish to use the maximum available size for a Primary DOS Partition\ + ^0104^and make the partition active (/).....................? [ ]"; + +/*-------------------------------------------------------------*/ + char far *menu_45 = + +"^0804^Do you wish to use the maximum available size for a Primary DOS Partition\ + ^0104^(/)...................................................? [ ]"; + + +/*******************************************************************************************************/ +/* Screen for INPUT_DOS_CREATE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Primary DOS Partition ³menu_12 # */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 */ +/* 15³ Maximum space available for partition is #### Mbytes (###%) ³menu_16 */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ Enter partition size in Mbytes or percent of disk space (%) to ³menu_39 */ +/* 19³ create a Primary DOS Partition..................................[####] ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/****************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_14 = + +"^0804^Partition Status Type Size in Mbytes Percentage of Disk Used\ + ^0104^ \ + ^0104^ \ + ^0104^ \ + ^0104^ "; + +/*-------------------------------------------------------------*/ + char far *menu_15 = + +"^1404^Total disk space is Mbytes (1 Mbyte = 1048576 bytes)"; + +/*-------------------------------------------------------------*/ + char far *menu_16 = + +"^1504^Maximum space available for partition is Mbytes ()"; + +/*-------------------------------------------------------------*/ + char far *menu_39 = + +"^1804^Enter partition size in Mbytes or percent of disk space (%) to\ + ^0104^create a Primary DOS Partition.................................: []"; + + +/****************************************************************************************************/ +/* Screen for EXT_CREATE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Create Extended DOS Partition ³menu_17 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ Maximum space available for partition is #### Mbytes (##%) ³menu_16 # */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³ Enter partition size in Mbytes or percent of disk space (%) to ³menu_42 # */ +/* 19³ create an Extended DOS Partition................................[####] ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to continue ³menu_46 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/***************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_17 = + +"^0427^Create Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_42 = + +"^1804^Enter partition size in Mbytes or percent of disk space (%) to\ + ^0104^create an Extended DOS Partition..............................: []"; + + +/*-------------------------------------------------------------*/ + char far *menu_46 = + +"^2404^Press Esc to continue"; + + + + +/*****************************************************************************************************/ +/* Screen for VOLUME_CREATE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Create Logical DOS Drive(s) in the Extended Partition ³menu_18 */ +/* 02³ ³ */ +/* 03³Drv Volume Label Mbytes System Usage Drv Volume Label Mbytes System Usage³menu_19/20 */ +/* 04³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 05³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 06³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 07³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 08³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 09³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 10³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 11³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 12³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 13³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 14³## ########### #### ######## ###% ## ########### #### ######## ###%³ */ +/* 15³## ########### #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_17 */ +/* 18³ Maximum space available for logical drive is #### Mbytes (###%) ³menu_22 */ +/* 19³ ³ */ +/* 20³ Enter logical drive size in Mbytes or percent of disk space (%)...[####] ³menu_40 */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/***************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_18 = + +"^0112^Create Logical DOS Drive(s) in the Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_19 = + +"^0300^Drv Volume Label Mbytes System Usage\ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ "; + +/*----------------------------------------------------------*/ + char far *menu_43 = + +"^1000^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ \ +^0100^ "; + +/*-------------------------------------------------------------*/ + char far *menu_20 = + +"^0341^Drv Volume Label Mbytes System Usage\ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ "; + +/*---------------------------------------------------------*/ + char far *menu_44 = + +"^1041^ \ +^0141^ \ +^0141^ \ +^0141^ \ +^0141^ "; + +/*-------------------------------------------------------------*/ + char far *menu_21 = + +"^1704^Total Extended DOS Partition size is Mbytes (1 MByte = 1048576 bytes)"; + +/*-------------------------------------------------------------*/ + char far *menu_22 = + +"^1804^Maximum space available for logical drive is Mbytes ()"; + +/*-------------------------------------------------------------*/ + char far *menu_40 = + +"^2004^Enter logical drive size in Mbytes or percent of disk space (%)...[]"; + + +/*****************************************************************************************************/ +/* Screen for CHANGE_ACTIVE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Set Active Partition ³menu_23 */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³ */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Enter the number of the partition you want to make active............:[#] ³menu_24 */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_23 = + +"^0430^Set Active Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_24 = + +"^1604^Enter the number of the partition you want to make active...........: [ ]"; + + +/*****************************************************************************************************/ +/* Screen for DELETE_PARTITION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete DOS Partition or Logical DOS Drive ³menu_25 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Choose one of the following: ³menu_3 # */ +/* 09³ ³ */ +/* 10³ 1. Delete Primary DOS Partition ³menu_26 */ +/* 11³ 2. Delete Extended DOS Partition ³menu_26 */ +/* 12³ 3. Delete Logical DOS Drive(s) in the Extended DOS Partition ³menu_27 */ +/* 13³ ³ */ +/* 14³ ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ Enter choice: [ ] ³menu_7 # */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_25 = + +"^0419^Delete DOS Partition or Logical DOS Drive"; + +/*-------------------------------------------------------------*/ + char far *menu_26 = + +"^1004^1. Delete Primary DOS Partition\ + ^0104^2. Delete Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_27 = + +"^1204^3. Delete Logical DOS Drive(s) in the Extended DOS Partition"; + +/*****************************************************************************************************/ +/* Screen for DOS_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete Primary DOS Partition ³menu_28 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Warning! Data in the deleted Primary DOS Partition will be lost. ³menu_29 */ +/* 17³ Do you wish to continue (Y/N).................? [N] ³menu_29 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_28 = + +"^0426^Delete Primary DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_29 = + +"^1604^Warning! Data in the deleted Primary DOS Partition will be lost.\ + ^0104^Do you wish to continue (/).................? [ ]"; + +/*****************************************************************************************************/ +/* Screen for EXT_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Delete Extended DOS Partition ³menu_30 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ Warning! Data in the deleted Extended DOS partition will be lost. ³menu_31 */ +/* 17³ Do you wish to continue (Y/N).................? [N] ³menu_31 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_30 = + +"^0426^Delete Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_31 = + +"^1604^Warning! Data in the deleted Extended DOS Partition will be lost.\ + ^0104^Do you wish to continue (/).................? [ ]"; + +/******************************************************************************************************/ +/* Screen for VOL_DELETE */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Delete Logical DOS Drive(s) in the Extended DOS Partition ³menu_32 */ +/* 02³ ³ */ +/* 03³Drv Volume Label MBytes System Usage Drv Volume Label MBytes System Usage³menu_19/20 # */ +/* 04³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 05³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 06³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 07³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 08³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 09³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 10³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 11³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 12³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 13³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 14³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 15³## ############# #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS Partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_21 */ +/* 18³ ³ */ +/* 19³ Warning! Data in a deleted Logical DOS Drive will be lost. ³menu_33 */ +/* 20³ What drive do you want to delete...........................? [ ] ³menu_33 */ +/* 21³ Enter Volume Label.............................? [ ] ³menu_41 */ +/* 22³ Are you sure (Y/N).............................? [N] ³menu_34 */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_32 = + +"^0112^Delete Logical DOS Drive(s) in the Extended DOS Partition"; + +/*-------------------------------------------------------------*/ + char far *menu_33 = + +"^1904^Warning! Data in a deleted Logical DOS Drive will be lost.\ + ^0104^What drive do you want to delete...............................? [ ]"; + +/*-------------------------------------------------------------*/ + char far *menu_34 = + +"^2204^Are you sure (/)..............................? [ ]"; + +/*-------------------------------------------------------------*/ + char far *menu_41 = + +"^2104^Enter Volume Label..............................? [ ]"; + +/******************************************************************************************************/ +/* Screen for DISPLAY_PARTITION_INFORMATION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ Display Partition Information ³menu_35 */ +/* 05³ ³ */ +/* 06³ Current fixed disk drive: # ³menu_5 # */ +/* 07³ ³ */ +/* 08³ Partition Status Type Size in Mbytes Percentage of Disk Used ³menu_14 # */ +/* 09³ ## # # ####### #### ###% ³menu_14 # */ +/* 10³ ## # # ####### #### ###% ³ */ +/* 11³ ## # # ####### #### ###% ³ */ +/* 12³ ## # # ####### #### ###% ³ */ +/* 13³ ³ */ +/* 14³ Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_15 # */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ The Extended DOS partition contains Logical DOS Drives. ³menu_36 */ +/* 18³ Do you want to display the logical drive information (Y/N)......? [Y] ³menu_36 */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/******************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_35 = + +"^0426^Display Partition Information"; + +/*-------------------------------------------------------------*/ + char far *menu_36 = + +"^1704^The Extended DOS Partition contains Logical DOS Drives.\ + ^0104^Do you want to display the logical drive information (/)......?[ ]"; + +/*****************************************************************************************************/ +/* Screen for DISPLAY_VOLUME_INFORMATION */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ Display Logical DOS Drive Information ³menu_37 */ +/* 02³ ³ */ +/* 03³Drv Volume Label Mbytes System Usage Drv Volume Label Mbytes System Usage³menu_19/20 */ +/* 04³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 05³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 16³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 17³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 18³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 19³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 10³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 11³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 12³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 13³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 14³## ############# #### ######## ###% ## ############# #### ######## ###%³ */ +/* 15³## ############# #### ######## ###% ³ */ +/* 16³ ³ */ +/* 17³ Total Extended DOS partition size is #### Mbytes (1 Mbyte = 1048576 bytes) ³menu_17 */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ Press ESC to return to FDISK Options ³menu_11 */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_37 = + +"^0121^Display Logical DOS Drive Information"; + +/*****************************************************************************************************/ +/* Screen for SYSTEM_REBOOT */ +/* */ +/* ³00000000001111111111222222222233333333334444444444555555555566666666667777777777³ */ +/* ³01234567890123456789012345678901234567890123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³ ³ */ +/* 01³ ³ */ +/* 02³ ³ */ +/* 03³ ³ */ +/* 04³ ³ */ +/* 05³ ³ */ +/* 06³ ³ */ +/* 07³ ³ */ +/* 08³ ³ */ +/* 09³ ³ */ +/* 10³ ³ */ +/* 11³ ³ */ +/* 12³ ³ */ +/* 13³ System will now restart ³menu_38 */ +/* 14³ ³ */ +/* 15³ Insert DOS diskette in drive A: ³menu_38 */ +/* 16³ Press any key when ready . . . ³menu_38 */ +/* 17³ ³ */ +/* 18³ ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³ ³ */ +/* 22³ ³ */ +/* 23³ ³ */ +/* 24³ ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/*****************************************************************************************************/ + +/*-------------------------------------------------------------*/ + char far *menu_38 = + +"^1304^System will now restart\ + ^0204^Insert DOS Startup diskette in drive A:\ + ^0104^Press any key when ready . . ."; + + +/* */ +/* */ +/* The following character strings are required to display the */ +/* status messages indicating successful operation. These messages */ +/* have the form: status_xx */ +/* */ +/* Note: In order to overlay any previous message on the screen, these */ +/* messages are all 2 lines long. The second line may only be */ +/* a blank line. If 2 lines are needed for translation, use the */ +/* second line for text. Exceptions are those msgs on line 0, */ +/* and status_3. */ +/* */ + +/*-------------------------------------------------------------*/ + char far *status_1 = + +"^2104^Primary DOS Partition deleted\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_2 = + +"^2104^Extended DOS Partition deleted\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_3 = + +"^0004^Drive deleted"; +/* NOTE - the ^rrcc^ must be the first thing in this string */ + +/*-------------------------------------------------------------*/ + char far *status_4 = + +"^2104^Partition made active\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_5 = + +"^2104^Primary DOS Partition created\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_6 = + +"^2104^Extended DOS Partition created\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_7 = + +"^2204^Logical DOS Drive created, drive letters changed or added"; + +/*-------------------------------------------------------------*/ + char far *status_8 = + +"^2104^No partitions defined\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_9 = + +"^1004^No logical drives defined\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *status_10 = + +"^1804^Drive letters have been changed or deleted"; + +/*-------------------------------------------------------------*/ + char far *status_11 = + +"^0004^Drive redirected"; +/* NOTE - the ^rrcc^ must be the first thing in this string */ + +/*-------------------------------------------------------------*/ + char far *status_12 = + +"^2104^Primary DOS Partition created, drive letters changed or added\ + ^0100^"; + +/*-------------------------------------------------------------*/ + +/* */ +/* */ +/* The following character strings are required to display the */ +/* error messages. These have form: error_xx */ +/* */ +/* Note: In order to overlay any previous message on the screen, these */ +/* messages are all 2 lines long. The second line may only be */ +/* a blank line. If 2 lines are needed for translation, use the */ +/* second line for text. Exceptions are those msgs on line 0. */ +/* and those messages that start on line 23 */ +/* */ + + +/*-------------------------------------------------------------*/ + char far *error_1 = + +"^0004^No fixed disks present.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_2 = + +"^2204^Error reading fixed disk.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_3 = + +"^2204^Error writing fixed disk.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_4 = + +"^0004^Incorrect DOS version."; + +/*-------------------------------------------------------------*/ + char far *error_5 = + +"^0004^Cannot FDISK with network loaded."; + +/*-------------------------------------------------------------*/ + char far *error_6 = + +"^2204^No Primary DOS Partition to delete.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_7 = + +"^2204^No Extended DOS Partition to delete.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_8 = + +"^2204^Primary DOS Partition already exists.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_9 = + +"^2204^Extended DOS Partition already exists.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_10 = + +"^2204^No space to create a DOS partition.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_12 = + +"^2204^Requested logical drive size exceeds the maximum available space.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_13 = + +"^2204^Requested partition size exceeds the maximum available space.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_14 = + +"^2204^No partitions to delete.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_15 = + +"^2204^The only startable partition on Drive 1 is already set active.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_16 = + +"^2204^No partitions to make active.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_17 = + +"^2204^Partition selected () is not startable, active partition not changed."; + +/*-------------------------------------------------------------*/ + char far *error_19 = + +"^2204^Cannot create Extended DOS Partition without\ + ^0104^Primary DOS Partition on disk 1."; + +/*-------------------------------------------------------------*/ + char far *error_20 = + +"^2204^All available space in the Extended DOS Partition\ + ^0104^is assigned to logical drives."; + +/*-------------------------------------------------------------*/ + char far *error_21 = + +"^2204^Cannot delete Extended DOS Partition while logical drives exist."; + +/*-------------------------------------------------------------*/ + char far *error_22 = + +"^2204^All logical drives deleted in the Extended DOS Partition."; + +/*-------------------------------------------------------------*/ + char far *error_23 = + +"^2204^\ + ^0104^ is not a choice. Please enter ."; + +/*-------------------------------------------------------------*/ + char far *error_24 = + +"^2204^Warning! The partition set active is not startable."; + +/*-------------------------------------------------------------*/ + char far *error_25 = + +"^2204^ Only non-startable partitions exist.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_26 = + +"^2204^Only partitions on Drive 1 can be made active."; + +/*-------------------------------------------------------------*/ + char far *error_27 = + +"^2204^Maximum number of Logical DOS Drives installed."; + +/*-------------------------------------------------------------*/ + char far *error_28 = + +"^2204^Cannot create a zero size partition.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_29 = + +"^2204^Drive already deleted.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + char far *error_30 = + +"^2204^Unable to access Drive ."; + +/*-------------------------------------------------------------*/ + char far *error_31 = + +"^2304^Invalid entry, please enter ."; + +/*-------------------------------------------------------------*/ + char far *error_32 = + +"^2204^Cannot delete Primary DOS Partition on drive 1 \ + ^0104^when an Extended DOS Partition exists."; + +/*-------------------------------------------------------------*/ + char far *error_33 = + +"^2200^\ + ^0104^Invalid entry, please press Enter."; + +/*-------------------------------------------------------------*/ + char far *error_34 = + +"^2204^Volume label does not match."; + +/*-------------------------------------------------------------*/ + char far *error_35 = + +"^2204^Cannot create Logical DOS Drive without\ + ^0104^an Extended DOS Partition on the current drive."; + +/*-------------------------------------------------------------*/ + char far *error_36 = + +"^2204^No Logical DOS Drive(s) to delete.\ + ^0100^"; + +/*-------------------------------------------------------------*/ + + +/* */ +/* */ +/* The following message is only included as an aide to debug message */ +/* strings during translations. The FDISK message formatter will attempt*/ +/* to the best of its ability to catch invalid message strings and */ +/* print the error. This message should NEVER appear for a user, so it */ +/* is not neccessary to translate this message */ +/* */ +/* */ + + +/*-------------------------------------------------------------*/ + char far *debug_msg = + +"^2200^Message string error . See header of FDISKC.MSG for error definition"; + +/*-------------------------------------------------------------*/ + char far *internal_error = + +"^2204^Internal error"; + +/* */ +/* The following are not translatable. They are the partition names */ +/* */ + + char *DOS_part = "PRI DOS"; + char *XENIX_part = " XENIX "; + char *EXTENDED_part = "EXT DOS"; + char *BAD_BLOCK_part= " Table "; + char *PCIX_part = " PC/IX "; + char *NON_DOS_part = "Non-DOS"; + + diff --git a/v4.0/src/CMD/FDISK/FDISKMSG.H b/v4.0/src/CMD/FDISK/FDISKMSG.H new file mode 100644 index 0000000..2c684a9 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDISKMSG.H @@ -0,0 +1,131 @@ +/* FDISK MESSAGE FILE */ + +/************************************************************************/ +/* Please log all modifications to this file: */ +/*----------------------------------------------------------------------*/ +/* Date: 04/04/86 */ +/* Changed by: Mark T */ +/* Message changed: menu_1 - menu_38 */ +/* Reason: Creation of file */ +/*----------------------------------------------------------------------*/ +/* Date: 05/04/87 */ +/* Changed by: Dennis M */ +/* Message changed: menu_1 - menu_44 */ +/* Reason: DOS 3.3 */ +/*----------------------------------------------------------------------*/ +/* Date: */ +/* Changed by: */ +/* Message changed: */ +/* Reason: */ +/*----------------------------------------------------------------------*/ +/************************************************************************/ + +#define ACTIVE_PART 'A' /* Character to indicate active status */ +#define DRIVE_INDICATOR ':' /* Character displayed to indicate drive letter */ + +/*-------------------------------------------------------------*/ + extern char far *menu_1; /* AN000 */ + extern char far *menu_2; /* AN000 */ + extern char far *menu_3 ; /* AN000 */ + extern char far *menu_4 ; /* AN000 */ + extern char far *menu_5 ; /* AN000 */ + extern char far *menu_6 ; /* AN000 */ + extern char far *menu_7 ; /* AN000 */ + extern char far *menu_8 ; /* AN000 */ + extern char far *menu_9 ; /* AN000 */ + extern char far *menu_10 ; /* AN000 */ + extern char far *menu_11 ; /* AN000 */ + extern char far *menu_12 ; /* AN000 */ + extern char far *menu_13 ; /* AN000 */ + extern char far *menu_14 ; /* AN000 */ + extern char far *menu_15 ; /* AN000 */ + extern char far *menu_16 ; /* AN000 */ + extern char far *menu_39 ; /* AN000 */ + extern char far *menu_17 ; /* AN000 */ + extern char far *menu_42 ; /* AN000 */ + extern char far *menu_18 ; /* AN000 */ + extern char far *menu_19 ; /* AN000 */ + extern char far *menu_43 ; /* AN000 */ + extern char far *menu_20 ; /* AN000 */ + extern char far *menu_44 ; /* AN000 */ + extern char far *menu_21 ; /* AN000 */ + extern char far *menu_22 ; /* AN000 */ + extern char far *menu_40 ; /* AN000 */ + extern char far *menu_23 ; /* AN000 */ + extern char far *menu_24 ; /* AN000 */ + extern char far *menu_25 ; /* AN000 */ + extern char far *menu_26 ; /* AN000 */ + extern char far *menu_27 ; /* AN000 */ + extern char far *menu_28 ; /* AN000 */ + extern char far *menu_29 ; /* AN000 */ + extern char far *menu_30 ; /* AN000 */ + extern char far *menu_31 ; /* AN000 */ + extern char far *menu_32 ; /* AN000 */ + extern char far *menu_33 ; /* AN000 */ + extern char far *menu_34 ; /* AN000 */ + extern char far *menu_41 ; /* AN000 */ + extern char far *menu_35 ; /* AN000 */ + extern char far *menu_36 ; /* AN000 */ + extern char far *menu_37 ; /* AN000 */ + extern char far *menu_38 ; /* AN000 */ + extern char far *menu_45 ; /* AN000 */ + extern char far *menu_46 ; /* AN000 */ +/*-------------------------------------------------------------*/ + extern char far *status_1 ; /* AN000 */ + extern char far *status_2 ; /* AN000 */ + extern char far *status_3 ; /* AN000 */ + extern char far *status_4 ; /* AN000 */ + extern char far *status_5 ; /* AN000 */ + extern char far *status_6 ; /* AN000 */ + extern char far *status_7 ; /* AN000 */ + extern char far *status_8 ; /* AN000 */ + extern char far *status_9 ; /* AN000 */ + extern char far *status_10 ; /* AN000 */ + extern char far *status_11 ; /* AN000 */ + extern char far *status_12 ; /* AN000 */ +/*-------------------------------------------------------------*/ + extern char far *error_1 ; /* AN000 */ + extern char far *error_2 ; /* AN000 */ + extern char far *error_3 ; /* AN000 */ + extern char far *error_4 ; /* AN000 */ + extern char far *error_5 ; /* AN000 */ + extern char far *error_6 ; /* AN000 */ + extern char far *error_7 ; /* AN000 */ + extern char far *error_8 ; /* AN000 */ + extern char far *error_9 ; /* AN000 */ + extern char far *error_10 ; /* AN000 */ + extern char far *error_12 ; /* AN000 */ + extern char far *error_13 ; /* AN000 */ + extern char far *error_14 ; /* AN000 */ + extern char far *error_15 ; /* AN000 */ + extern char far *error_16 ; /* AN000 */ + extern char far *error_17 ; /* AN000 */ + extern char far *error_19 ; /* AN000 */ + extern char far *error_20 ; /* AN000 */ + extern char far *error_21 ; /* AN000 */ + extern char far *error_22 ; /* AN000 */ + extern char far *error_23 ; /* AN000 */ + extern char far *error_24 ; /* AN000 */ + extern char far *error_25 ; /* AN000 */ + extern char far *error_26 ; /* AN000 */ + extern char far *error_27 ; /* AN000 */ + extern char far *error_28 ; /* AN000 */ + extern char far *error_29 ; /* AN000 */ + extern char far *error_30 ; /* AN000 */ + extern char far *error_31 ; /* AN000 */ + extern char far *error_32 ; /* AN000 */ + extern char far *error_33 ; /* AN000 */ + extern char far *error_34 ; /* AN000 */ + extern char far *error_35 ; /* AN000 */ + extern char far *error_36 ; /* AN000 */ +/*-------------------------------------------------------------*/ + extern char far *debug_msg ; /* AN000 */ + extern char far *internal_error ; /* AN000 */ +/*-------------------------------------------------------------*/ + extern char *DOS_part ; /* AN000 */ + extern char *XENIX_part ; /* AN000 */ + extern char *EXTENDED_part ; /* AN000 */ + extern char *BAD_BLOCK_part ; /* AN000 */ + extern char *PCIX_part ; /* AN000 */ + extern char *NON_DOS_part ; /* AN000 */ + diff --git a/v4.0/src/CMD/FDISK/FDPARSE.C b/v4.0/src/CMD/FDISK/FDPARSE.C new file mode 100644 index 0000000..7cf3143 --- /dev/null +++ b/v4.0/src/CMD/FDISK/FDPARSE.C @@ -0,0 +1,312 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "parse.h" /* AN000 */ +#include "string.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "msgret.h" /* AN000 */ + + +/* */ +/******************************************************************************/ +/*Routine name: PARSE_COMMAND_LINE */ +/******************************************************************************/ +/* */ +/*Description: Sets up flags, preloads messages, and parses the command */ +/* line for switchs. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 5/30/87 DRM */ +/* */ +/*Input: None */ +/* */ +/*Output: None */ +/* */ +/******************************************************************************/ + + +char parse_command_line(argc,argv) /* AN000 */ + +char *argv[]; /* array of pointer arguments AN000 */ +int argc; + +BEGIN /* AN000 */ + + + char cmd_line[128]; /* AN000 */ + char finished; /* AN000 */ + int i; /* AN000 */ + char parse_good; /* AN000 */ + char far *cmdline; + + parse_init(); /* AN000 */ + + /* Initialize parse_flag to true and don't change unless error */ + parse_good = TRUE; /* AN000 */ + + regs.h.ah = (unsigned char) 0x62; + intdosx(®s, ®s, &segregs); + + FP_OFF(cmdline) = 0x81; + FP_SEG(cmdline) = regs.x.bx; + + i = 0; + while ( *cmdline != (char) '\x0d' ) cmd_line[i++] = *cmdline++; + cmd_line[i++] = (char) '\x0d'; + cmd_line[i++] = (char) '\0'; + + regs.x.si = (unsigned)cmd_line; /* AN000 make DS:SI point to source */ + regs.x.cx = u(0); /* AN000 operand ordinal (whatever that means) */ + regs.x.dx = u(0); /* AN000 operand ordinal (whatever that means) */ + regs.x.di = (unsigned)&p_p; /* AN000 address of parm list */ + Parse_Ptr = (unsigned)cmd_line; /* AN010 */ + regs.x.si = (unsigned)cmd_line; /* AN010 */ + + finished = FALSE; + while ( !finished ) /* AN000 */ + BEGIN /* AN000 */ + + Parse_Ptr = regs.x.si; /* AN010 point to next parm */ + parse(®s,®s); /* AN000 Call DOS PARSE service routines*/ + + if (regs.x.ax == u(NOERROR)) /* AN000 If there was an error*/ + BEGIN + if (regs.x.dx == (unsigned)&p_buff) /* AN000 */ + check_disk_validity(); /* AN000 It's a drive letter */ + + if (regs.x.dx == (unsigned)&sp_buff) /* AN000 */ + process_switch(); /* AN000 It's a switch*/ + END + else + BEGIN + if (regs.x.ax == u(0xffff)) + finished = TRUE; /* AN000 Then we are done*/ + else + BEGIN + Parse_msg(regs.x.ax,STDERR,Parse_err_class); /* AN010 */ + parse_good = FALSE; + finished = TRUE; /* AN000 Then we are done*/ + END + END + END /* End WHILE */ /* AN000 */ + + return(parse_good); /* AN000 Return to caller*/ + +END /* end parser */ /* AN000 */ + + +/* */ +/******************************************************************************/ +/*Routine name: INIT_PARSE */ +/******************************************************************************/ +/* */ +/*Description: Sets up ALL VALUES AND STRUCTS FOR PARSER. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 6/15/87 DRM */ +/* */ +/*Input: None */ +/* */ +/*Output: None */ +/* */ +/******************************************************************************/ + + +void parse_init() /* AN000 */ + +BEGIN /* AN000 */ + + + primary_flag = FALSE; /* AN000 */ + extended_flag = FALSE; /* AN000 */ + logical_flag = FALSE; /* AN000 */ + disk_flag = FALSE; /* AN000 */ + quiet_flag = FALSE; /* AN000 */ + + p_p.p_parmsx_ptr = (unsigned)&p_px; /* AN000 Address of extended parm list */ + p_p.p_num_extra = uc(1); /* AN000 */ + p_p.p_len_extra_delim = uc(1); /* AN000 */ + p_p.p_extra_delim = c(SEMICOLON); /* AN000 */ + + p_px.p_minp = uc(0); /* AN000 1 required positional */ + p_px.p_maxp = uc(1); /* AN000 1 maximum positionals */ + p_px.p_con1_ptr = (unsigned)&p_con; /* AN000 pointer to next control blk */ + p_px.p_maxs = uc(2); /* AN000 number of switches */ + p_px.p_swi1_ptr = (unsigned)&p_swi1; /* AN000 pointer to next control blk */ + p_px.p_swi2_ptr = (unsigned)&p_swi2; /* AN000 pointer to next control blk */ + p_px.p_maxk = uc(NOVAL); /* AN000 no keywords */ + + p_con.p_match_flag = u(0x8001); /* AN000 DRIVE NUMBER 1 OR 2 optional */ + p_con.p_function_flag = u(0x0000); /* AN000 DO NOTHING FOR FUNCTION FLAG */ + p_con.p_buff1_ptr = (unsigned)&p_buff; /* AN000 */ + p_con.p_val1_ptr = (unsigned)&p_val; /* AN000 */ + p_con.p_nid = uc(0); /* AN000 */ + + p_swi1.sp_match_flag = u(0x8000); /* AN000 Optional (switch) */ + p_swi1.sp_function_flag = u(0x0000); /* AN000 DO NOTHING FOR FUNCTION FLAG */ + p_swi1.sp_buff1_ptr = (unsigned)&sp_buff; /* AN000 */ + p_swi1.sp_val1_ptr = (unsigned)&sp_val; /* AN000 */ + p_swi1.sp_nid = uc(3); /* AN000 3 switches allowed */ + strcpy((char *) p_swi1.sp_switch1,PRI); /* AN000 /a switch */ + strcpy((char *) p_swi1.sp_switch2,EXT); /* AN000 /a switch */ + strcpy((char *) p_swi1.sp_switch3,LOG); /* AN000 /a switch */ + + p_swi2.sp_match_flag = u(0x0001); /* AN000 Optional (switch) */ + p_swi2.sp_function_flag = u(0x0000); /* AN000 DO NOTHING FOR FUNCTION FLAG */ + p_swi2.sp_buff1_ptr = (unsigned)&sp_buff; /* AN000 */ + p_swi2.sp_val1_ptr = (unsigned)NOVAL; /* AN000 */ + p_swi2.sp_nid = uc(1); /* AN000 3 switches allowed */ + strcpy((char *) p_swi2.sp_switch4,QUIET); /* AN000 /a switch */ + + p_val.p_values = uc(1); /* AN000 - Number of values items returned */ + p_val.p_range = uc(1); /* AN000 - Number of ranges */ + p_val.p_range_one = uc(1); /* AN000 - range number one */ + p_val.p_low_range = ul(1); /* AN000 - low value for range */ + p_val.p_high_range = ul(2); /* AN000 - high value for range */ + + sp_val.p_values = uc(1); /* AN000 - Number of values items returned */ + sp_val.p_range = uc(1); /* AN000 - Number of ranges */ + sp_val.p_range_one = uc(1); /* AN000 - range number one */ + sp_val.p_low_range = ul(1); /* AN000 - low value for range */ + sp_val.p_high_range = ul(4000); /* AN000 - high value for range */ + + return; /* AN000 */ + +END + /* AN000 */ +/* */ +/******************************************************************************/ +/*Routine name: CHECK_DISK_VALIDITY */ +/******************************************************************************/ +/* */ +/*Description: Checks the return buffer from parse for the positional */ +/* value to be equal to 0 or 1. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 6/18/87 DRM */ +/* */ +/*Input: None */ +/* */ +/*Output: None */ +/* */ +/******************************************************************************/ + + +void check_disk_validity() /* AN000 */ + +BEGIN /* AN000 */ + + disk_flag = (FLAG)TRUE; /* AN000 */ + cur_disk_buff = ((char)p_buff.p_value - 1); /* AN000 */ + return; /* AN000 */ +END /* AN000 */ + +/* */ +/******************************************************************************/ +/*Routine name: PROCESS_SWITCH */ +/******************************************************************************/ +/* */ +/*Description: This function looks at the return buffer of the parse and */ +/* determins the switch, places value in buffer, and sets */ +/* flag for specific switch. */ +/* */ +/*Called Procedures: */ +/* */ +/*Change History: Created 6/18/87 DRM */ +/* */ +/*Input: None */ +/* */ +/*Output: None */ +/* */ +/******************************************************************************/ + + +void process_switch() /* AN000 */ + +BEGIN /* AN000 */ + + + BEGIN /* AN000 */ + if (sp_buff.p_synonym == (unsigned)p_swi1.sp_switch1) /* AN000 */ + BEGIN /* AN000 */ + primary_flag = (FLAG)TRUE; /* AN000 */ + primary_buff = (unsigned)sp_buff.p_value; /* AN000 */ + END /* AN000 */ + + if (sp_buff.p_synonym == (unsigned)p_swi1.sp_switch2) /* AN000 */ + BEGIN /* AN000 */ + extended_flag = (FLAG)TRUE; /* AN000 */ + extended_buff = (unsigned)sp_buff.p_value; /* AN000 */ + END /* AN000 */ + + if (sp_buff.p_synonym == (unsigned)p_swi1.sp_switch3) /* AN000 */ + BEGIN /* AN000 */ + logical_flag = (FLAG)TRUE; /* AN000 */ + logical_buff = (unsigned)sp_buff.p_value; /* AN000 */ + END /* AN000 */ + + if (sp_buff.p_synonym == (unsigned)p_swi2.sp_switch4) /* AN000 */ + BEGIN /* AN000 */ + quiet_flag = (FLAG)TRUE; /* AN000 */ + END /* AN000 */ + END /* AN000 */ + return; /* AN000 Return to caller*/ +END /* end parser */ /* AN000 */ + +/************************************************************************/ /* ;an000; */ +/* Parse_Message - This routine will print only those */ +/* messages that require 1 replaceable */ +/* parm. */ +/* */ +/* Inputs : Msg_Num - number of applicable message */ +/* Handle - display type */ +/* Message_Type - type of message to display */ +/* Replace_Parm - pointer to parm to replace */ +/* */ +/* Outputs : message */ +/* */ +/* Date : 03/28/88 */ +/* Version : DOS 4.00 */ +/************************************************************************/ + +void Parse_msg(Msg_Num,Handle,Message_Type) /* AN010 */ + /* AN010 */ +int Msg_Num; /* AN010 */ +int Handle; /* AN010 */ +unsigned char Message_Type; /* AN010 */ + +BEGIN /* AN010 */ +char far *Cmd_Ptr; /* AN010 */ + + + BEGIN /* AN010 */ + segread(&segregs); /* AN010 */ + FP_SEG(Cmd_Ptr) = segregs.ds; /* AN010 */ + FP_OFF(Cmd_Ptr) = regs.x.si; /* AN010 */ + *Cmd_Ptr = '\0'; /* AN010 */ + + FP_SEG(sublistp[0].value) = segregs.ds; /* AN010 */ + FP_OFF(sublistp[0].value) = Parse_Ptr; /* AN010 */ + sublistp[0].size = Sublist_Length; /* AN010 */ + sublistp[0].reserved = Reserved; /* AN010 */ + sublistp[0].id = 0; /* AN010 */ + sublistp[0].flags = Char_Field_ASCIIZ+Left_Align; /* AN010 */ + sublistp[0].max_width = 80; /* AN010 */ + sublistp[0].min_width = 01; /* AN010 */ + sublistp[0].pad_char = Blank; /* AN010 */ + + regs.x.ax = Msg_Num; /* AN010 */ + regs.x.bx = Handle; /* AN010 */ + regs.x.cx = SubCnt1; /* AN010 */ + regs.h.dl = No_Input; /* AN010 */ + regs.h.dh = Message_Type; /* AN010 */ + regs.x.si = (unsigned int)&sublistp[0]; /* AN010 */ + sysdispmsg(®s,®s); /* AN010 */ + END /* AN010 */ + return; /* AN010 */ +END /* AN010 */ + diff --git a/v4.0/src/CMD/FDISK/GLOBAL.C b/v4.0/src/CMD/FDISK/GLOBAL.C new file mode 100644 index 0000000..85b6e85 --- /dev/null +++ b/v4.0/src/CMD/FDISK/GLOBAL.C @@ -0,0 +1,84 @@ + +#include "fdisk.h" +#include "dos.h" + +/* */ +/* */ +/****************************************************************************/ +/* Declare Global variables */ +/****************************************************************************/ +/* */ + + + +char cur_disk; +char good_disk[2]; +unsigned char number_of_drives; +char reboot_flag; +char errorlevel; +char max_partition_size; +char sort[24]; +char no_fatal_error; +char valid_input; +unsigned char video_mode; +unsigned char display_page; +unsigned char video_attribute; /* AN006 */ + + +unsigned total_disk[2]; +unsigned total_mbytes[2]; /* AN000 */ +unsigned char max_sector[2]; +unsigned max_head[2]; /* AC004 */ +unsigned required_cyls[2]; + +unsigned input_row; +unsigned input_col; +char insert[800]; /* AC000 */ +char *pinsert = insert; + +extern unsigned char master_boot_record[2][512]; +unsigned char boot_record[512]; + +char next_letter; /* AN000 */ +char primary_flag; /* AC000 */ +char extended_flag; /* AC000 */ +char logical_flag; /* AC000 */ +char disk_flag; /* AC000 */ +char quiet_flag; /* AC000 */ +unsigned primary_buff; /* AC000 */ +unsigned extended_buff; /* AC000 */ +unsigned logical_buff; /* AC000 */ +char cur_disk_buff; /* AC000 */ +unsigned long NOVAL = (unsigned long) 0; /* AC000 */ +FLAG PercentFlag; /* AC000 */ + +FLAG mono_flag; /* AC006 */ + +char Yes; /* AC012 */ +char No; /* AC012 */ + +unsigned Parse_Ptr; /* AN010 */ +/* */ +/* */ +/****************************************************************************/ +/* Define Global structures */ +/****************************************************************************/ +/* */ + +struct entry part_table[2][4]; +struct entry ext_table[2][24]; +struct freespace free_space[24]; +struct KeyData *input_data; +struct dx_buffer_ioctl dx_buff; /* AN000 */ +struct diskaccess disk_access; /* AN002 */ +struct SREGS segregs; +struct sublistx sublistp[1]; /* AN010 */ + +/* */ +/****************************************************************************/ +/* Define UNIONS */ +/****************************************************************************/ +/* */ + +union REGS regs; + diff --git a/v4.0/src/CMD/FDISK/INPUT.C b/v4.0/src/CMD/FDISK/INPUT.C new file mode 100644 index 0000000..a818ef8 --- /dev/null +++ b/v4.0/src/CMD/FDISK/INPUT.C @@ -0,0 +1,673 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "ctype.h" /* AN000 */ +#include "string.h" /* AN000 */ +#include "stdio.h" +#include "fdiskmsg.h" /* AN000 */ +#include "doscall.h" /* AN000 */ + +/* */ +char get_num_input(input_default,max_num,row,col) + +char max_num; +unsigned row; +unsigned col; +char input_default; + +BEGIN + + char input; + char default_used; + char input_value; + + /* print default entry if there is one */ + if (input_default != c(NUL)) /* AC000 */ + + BEGIN + default_used = TRUE; + /* position the cursor */ + VIOSETCURPOS(row,col,u(0)); /* AC000 */ + + /* Display the default character */ + putch(((int)(input_default+'0'))); + END + + /* Assume bad input */ + valid_input = FALSE; + + /* Loop until we get good stuff */ + while (valid_input == FALSE) + BEGIN + + /* position the cursor */ + VIOSETCURPOS(row,col,u(0)); /* AC000 */ + + /* Flush the keyboard buffer and get the next pressed key */ + input = get_char_input(); + + /* Do world trade get country information */ + input = dos_upper(input); /* AN000 */ + + /* Go handle different inputs */ + switch(input) + BEGIN + case ESC: + BEGIN + valid_input = TRUE; + break; + END + + case CR: + BEGIN + /* Set the input to the default if there is one there */ + if (default_used) + BEGIN + if (input_default != c(NUL)) + BEGIN + input_value = input_default+'0'; + END + else + BEGIN + /* Make the enter look like a blank for error message */ + input_value = c(' '); /* AC000 */ + END + END + /* See if it is digit and less or equal to max */ + if ( (isdigit(input_value)) && + (input_value <= (max_num+'0')) && + (input_value != c('0')) ) + BEGIN + valid_input = TRUE; + input = input_value; + END + else + BEGIN + if (isdigit(input_value)) + BEGIN + /* Setup error message */ + insert[0] = input_value; + insert[1] = c('1'); /* AC000 */ + insert[2] = c('-'); /* AC000 */ + insert[3] = max_num+'0'; + display(error_23); + END + else + BEGIN + insert[0] = c('1'); /* AC000 */ + insert[1] = c('-'); /* AC000 */ + insert[2] = max_num+'0'; + display(error_31); + END + END + break; + END + + default: + BEGIN + putch(((int)(input))); + default_used = FALSE; + input_value = input; + break; + END + END + END + return(input); +END + + + +/* */ + +char get_yn_input(input_default,row,col) + +unsigned row; +unsigned col; +char input_default; + +BEGIN + + char input; + char default_used; + char input_value; + + /* print default entry if there is one */ + if (input_default != c(NUL)) /* AC000 */ + + BEGIN + default_used = TRUE; + /* position the cursor */ + VIOSETCURPOS(row,col,u(0)); /* AC000 */ + + /* Display the default character */ + putch(((int)(input_default))); + END + + /* Assume bad input */ + valid_input = FALSE; + + /* Loop until we get good stuff */ + while (valid_input == FALSE) + BEGIN + + /* position the cursor */ + VIOSETCURPOS(row,col,u(0)); /* AC000 */ + + /* Flush the keyboard buffer and get the next pressed key */ + input = get_char_input(); + input = dos_upper(input); + + /* Go handle different inputs */ + switch(input) + BEGIN + case ESC: + BEGIN + valid_input = TRUE; + break; + END + + case CR: + BEGIN + /* Set the input to the default if there is one there */ + if (default_used) + BEGIN + if (input_default != c(NUL)) /* AC000 */ + BEGIN + input_value = input_default; + END + else + BEGIN + internal_program_error(); + END + END + /* See if YES or NO */ + + /* Do world trade get country information */ + input = check_yn_input(input_value); /* AN000 */ + + if ((input == c(1)) || (input == c(0))) /* AC000 */ + BEGIN + valid_input = TRUE; + END + else + BEGIN + /* Setup error message */ + insert[0] = c(Yes); /* AC000 AC011 */ + insert[1] = c('-'); /* AC000 */ + insert[2] = c(No); /* AC000 AC011 */ + display(error_31); + END + break; + END + + default: + BEGIN + putch(((int)(input))); + default_used = FALSE; + input_value = input; + break; + END + END + END + return(input); +END + + +/* */ +char wait_for_ESC() + +BEGIN + char input; + + while (input != c(ESC)) /* AC000 */ + BEGIN + /* position the cursor at the end of the ESC prompt */ + VIOSETCURPOS(u(24),u(39),u(0)); /* AC000 */ + + /* Get input */ + input = get_char_input(); + + END + return(c(ESC)); /* AC000 */ +END + + + + +XFLOAT get_large_num_input(input_default,max_num,max_percent,input_message,prompt_location,error_message) + +unsigned input_default; /* AC000 */ +unsigned max_num; +unsigned max_percent; +char far *input_message; +char far *error_message; +unsigned prompt_location; + +BEGIN + +char input; +XFLOAT large_input; /* AC000 */ +char default_used; +unsigned long very_big_input; + + /* Assume bad input */ + valid_input = FALSE; + + /* Assume no input, and use default */ + default_used = TRUE; + + /* Initialize the input value */ + large_input = u(0); /* AC000 */ + + /* Loop until we get good stuff */ + while (valid_input == FALSE) + + BEGIN + /* position the cursor */ + VIOSETCURPOS(input_row,input_col,u(0)); /* AC000 */ + + /* Flush the keyboard buffer and get the next pressed key */ + + input = get_char_input(); + + /* Go handle different inputs */ + switch(input) + BEGIN + case ESC: + valid_input = TRUE; + large_input = ((unsigned)(ESC_FLAG)); + break; + + case CR: + BEGIN + if (PercentFlag) + BEGIN + /* Set the input to the default if there is one there and nothing else entered */ + if ((input_default != u(NUL)) && (default_used)) /* AC000 */ + large_input = input_default; + /* See if input is less or equal to max_value */ + if (large_input <= max_percent) + BEGIN + if (large_input != u(0)) + valid_input = TRUE; + else + display(error_28); + END + else + display(error_message); + END + else + BEGIN + /* Set the input to the default if there is one there and nothing else entered */ + if ((input_default != u(NUL)) && (default_used)) /* AC000 */ + large_input = input_default; + /* See if input is less or equal to max_value */ + if (large_input <= max_num) + BEGIN + if (large_input != u(0)) + valid_input = TRUE; + else + display(error_28); + END + else + display(error_message); + END + break; + END + + case BACKSPACE: + if (PercentFlag) + PercentFlag = (FLAG)FALSE; /* AN000 */ + else + large_input = large_input / 10; + + /* Indicate that we are not using the default */ + default_used = FALSE; + sprintf(&insert[prompt_location],"%4.0d",large_input); /* AN000 */ + display(input_message); + break; + + case PERCENT: /* AN000 */ + + if (PercentFlag == (FLAG)FALSE) + BEGIN /* AN000 */ + PercentFlag = (FLAG)TRUE; /* AN000 */ + /* Round down if > 999.9 */ + if (large_input > u(999)) /* AN000 */ + large_input = (large_input%1000); /* AN000 */ + sprintf(&insert[prompt_location],"%3.0d%%",large_input); /* AN000 */ + /* Indicate that we are not using the default */ + default_used = FALSE; /* AN000 */ + display(input_message); /* AN000 */ + END /* AN000 */ + else + display(error_33); /* AN000 */ + + break; /* AN000 */ + + + default: + BEGIN + + /* Make sure it is numerical input */ + + if ( (isdigit(input)) && ((!PercentFlag) || (default_used)) ) /* AN000 */ + BEGIN + /* Add this digit in */ + very_big_input= (((unsigned long)(large_input)) * 10) + ((unsigned long)input - '0'); /* AC000 */ + + /* Round down if > 9999.9 */ + large_input = ((unsigned)(very_big_input%10000)); + + /* Put it in the message */ + number_in_msg((XFLOAT)large_input,prompt_location); /* AN000 */ + display(input_message); + + /* Indicate that we are not using the default */ + default_used = FALSE; + PercentFlag = (FLAG)FALSE; /* AN000 */ + END + else + BEGIN + if (!PercentFlag) /* AN000 */ + BEGIN /* AN000 */ + /* Setup error message */ + insert[0] = c('0'); /* AC000 */ + insert[1] = c('-'); /* AC000 */ + insert[2] = c('9'); /* AC000 */ + display(error_31); + END /* AN000 */ + else /* AN000 */ + BEGIN /* AN000 */ + display(error_33); /* AN000 */ + END /* AN000 */ + END + END + END + END + + return(large_input); +END + + +/* */ +char get_alpha_input(low_letter,high_letter,row,col,error_low_letter,error_high_letter) + +unsigned row; +unsigned col; +char low_letter; +char high_letter; +char error_low_letter; +char error_high_letter; + +BEGIN + + char input; + char default_used; + char input_value; + + + /* Assume bad input */ + valid_input = FALSE; + + /* Init input_value to something non-alpha */ + input_value = c(0); /* AC000 */ + + /* Loop until we get good stuff */ + while (valid_input == FALSE) + BEGIN + + /* position the cursor */ + VIOSETCURPOS(row,col,u(0)); /* AC000 */ + + /* Flush the keyboard buffer and get the next pressed key */ + input = get_char_input(); + input = dos_upper(input); + + /* Go handle different inputs */ + switch(input) + BEGIN + case ESC: + BEGIN + valid_input = TRUE; + break; + END + + case CR: + BEGIN + /* See if it is digit and between given letters*/ + /* Do world trade get country information */ + input = dos_upper(input_value); /* AN000 */ + if ((isalpha(input)) && + (input >= low_letter) && + (input <= high_letter) && + (isalpha(input_value))) + BEGIN + valid_input = TRUE; + END + else + BEGIN + if (isalpha(input_value)) + BEGIN + /* Setup error message */ + insert[0] = input; + insert[1] = error_low_letter; + insert[2] = c('-'); /* AC000 */ + insert[3] = error_high_letter; + display(error_23); + END + else + BEGIN + insert[0] = error_low_letter; + insert[1] = c('-'); /* AC000 */ + insert[2] = error_high_letter; + display(error_31); + END + END + break; + END + + default: + BEGIN + putch(((int)(input))); + default_used = FALSE; + input_value = input; + break; + END + END + END + return(input); +END + + +/* */ +char get_char_input() + +BEGIN + regs.h.ah = uc(0x0C); /* AC000 */ + regs.h.al = uc(0x08); /* AC000 */ + intdos(®s,®s); + if (regs.h.al == uc(0)) /* AC000 */ + BEGIN + DOSBEEP(u(900),u(400)); /* AC000 */ + END + return(((char)(regs.h.al))); + +END + + + +/* */ /* AN000 */ + /* AN000 */ +void get_string_input(StartRow,StartCol,string_ptr) /* AN000 */ + /* AN000 */ +unsigned StartRow; /* AN000 */ +unsigned StartCol; /* AN000 */ +char far *string_ptr; /* AN000 */ + /* AN000 */ +BEGIN /* AN000 */ + +#define MAX_STRING_INPUT_LENGTH 11 + /* AN000 */ +unsigned char input; /* AN000 */ +char input_value; /* AN000 */ +char far *WorkingPtr; /* AN000 */ +char far *DeletePtr; /* AN000 */ +char Done; /* AN000 */ +unsigned Row; /* AN000 */ +unsigned Col; /* AN000 */ +int i; /* AN000 */ + /* AN000 */ + /* AN000 */ + WorkingPtr = string_ptr; /* AN000 */ + + Row = StartRow; /* AN000 */ + Col = StartCol; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + + while(*WorkingPtr != c(NUL)) /* AN000 */ + BEGIN /* AN000 */ + putch((int)(*WorkingPtr++)); /* AN000 */ + Col++; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + + regs.h.ah = uc(12); /* AN000 */ + regs.h.al = uc(8); /* AN000 */ + intdos(®s,®s); /* AN000 */ + input = regs.h.al; /* AN000 */ + + /* Loop until we get good stuff */ /* AN000 */ + Done = FALSE; /* AN000 */ + while (!Done) /* AN000 */ + BEGIN /* AN000 */ + + /* Go handle different inputs */ + + if (input < 32) /* AN000 */ + BEGIN /* AN000 */ + switch(input) /* AN000 */ + BEGIN /* AN000 */ + case ESC: /* AN000 */ + Done=TRUE; /* AN000 */ + *string_ptr++ = c(ESC); /* AN000 */ + *string_ptr++ = c('\0'); /* AN000 */ + break; /* AN000 */ + + case CR: /* AN000 */ + Done=TRUE; /* AN000 */ + break; /* AN000 */ + + case 8: /* backspace */ /* AN000 */ + if (Col > StartCol) /* AN000 */ + BEGIN /* AN000 */ + WorkingPtr--; /* AN000 */ + Col--; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + putch(' '); /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + DeletePtr = WorkingPtr; /* AN000 */ + while ( *(DeletePtr+1) != c('\0') ) /* AN000 */ + BEGIN /* AN000 */ + *DeletePtr = *(DeletePtr+1); /* AN000 */ + putch(*DeletePtr); /* AN000 */ + DeletePtr++; /* AN000 */ + END /* AN000 */ + *DeletePtr = c('\0'); /* AN000 */ + putch(' '); /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + else DOSBEEP(u(900),u(400)); /* AN000 */ + break; /* AN000 */ + + case 0: /* AN000 */ + regs.h.ah = uc(0x08); /* AN000 */ + intdos(®s,®s); /* AN000 */ + input = regs.h.al; /* AN000 */ + switch(input) /* AN000 */ + BEGIN /* AN000 */ + case 71: /* HOME */ /* AN000 */ + WorkingPtr = string_ptr; /* AN000 */ + Row = StartRow; /* AN000 */ + Col = StartCol; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + break; /* AN000 */ + + case 79: /* END */ /* AN000 */ + while (*WorkingPtr != c('\0') ) /* AN000 */ + BEGIN /* AN000 */ + WorkingPtr++; /* AN000 */ + Col++; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + break; /* AN000 */ + + + case 75: /* Cursor Left */ /* AN000 */ + if (Col > StartCol) /* AN000 */ + BEGIN /* AN000 */ + WorkingPtr--; /* AN000 */ + Col--; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + else DOSBEEP(u(900),u(400)); /* AN000 */ + break; /* AN000 */ + + + case 77: /* Cursor Right */ /* AN000 */ + if ( *WorkingPtr != c('\0') ) /* AN000 */ + BEGIN /* AN000 */ + WorkingPtr++; /* AN000 */ + Col++; /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + else DOSBEEP(u(900),u(400)); /* AN000 */ + break; /* AN000 */ + + + default: /* AN000 */ + DOSBEEP(u(900),u(400)); /* AN000 */ + break; /* AN000 */ + + END /* AN000 */ + break; /* AN000 */ + + default: /* AN000 */ + DOSBEEP(u(900),u(400)); /* AN000 */ + break; /* AN000 */ + END /* AN000 */ + + END /* AN000 */ + else /* input is >= 32 */ /* AN000 */ + BEGIN /* AN000 */ + input = dos_upper(input); /* AN000 */ + if ( (strchr(".\"/\\[]:|<>+=;,",input) == NULL) && + (Col < StartCol + MAX_STRING_INPUT_LENGTH) ) /* AN000 */ + BEGIN /* AN000 */ + putch(((int)(input))); /* AN000 */ + *WorkingPtr = input; /* AN000 */ + *(WorkingPtr+1) = c('\0'); /* AN000 */ + if (Col < (StartCol + MAX_STRING_INPUT_LENGTH - 1) ) /* AN000 */ + BEGIN /* AN000 */ + Col++; /* AN000 */ + WorkingPtr++; /* AN000 */ + END /* AN000 */ + VIOSETCURPOS(Row,Col,u(0)); /* AN000 */ + END /* AN000 */ + else DOSBEEP(u(900),u(400)); /* AN000 */ + END /* AN000 */ + + if (!Done) /* AN000 */ + BEGIN /* AN000 */ + /* Get a character */ /* AN000 */ + regs.h.ah = uc(0x08); /* AN000 */ + intdos(®s,®s); /* AN000 */ + input = regs.h.al; /* AN000 */ + END /* AN000 */ + END /* AN000 */ + + return; /* AN000 */ +END /* AN000 */ + diff --git a/v4.0/src/CMD/FDISK/INT13.C b/v4.0/src/CMD/FDISK/INT13.C new file mode 100644 index 0000000..ded7ff0 --- /dev/null +++ b/v4.0/src/CMD/FDISK/INT13.C @@ -0,0 +1,443 @@ +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ + +#include "string.h" +#include "stdio.h" +#include "stdlib.h" + +/* int printf(char *, ...); */ + +/* */ +char get_disk_info() + +BEGIN + +unsigned char i; + + /* Initialize values */ + number_of_drives = uc(0); /* AC000 */ + for (i=uc(0); i < uc(2); i++) /* AC000 */ + BEGIN + total_disk[i] = u(0); /* AC000 */ + total_mbytes[i] = f(0); /* AC000 */ + max_sector[i] = uc(0); /* AC000 */ + max_head[0] = u(0); /* AC004 */ + END + + /* See how many drives there are */ + if (get_drive_parameters(uc(0x80))) /* AC000 */ + + BEGIN + /* Get the drive parameters for all drives */ + for (i = uc(0); i < number_of_drives;i++) /* AC000 */ + + BEGIN + if (get_drive_parameters(uc(0x80)+i)) /* AC000 */ + + BEGIN + /* Save drive parameters */ + max_sector[i] = ((unsigned char)(regs.h.cl & 0x3F)); + max_head[i] = ((unsigned)(regs.h.dh +1)); /* AC004 */ +#if IBMCOPYRIGHT + total_disk[i] = ((((unsigned)(regs.h.cl & 0xC0 )) & 0x00C0) << 2)+ ((unsigned)regs.h.ch) +1; +#else + total_disk[i] = ((((unsigned)(regs.h.cl & 0xc0)) << 2) | regs.h.ch) + 1; +#endif + total_mbytes[i] = cylinders_to_mbytes(total_disk[i],i); /* AN004 */ + END + else + BEGIN + good_disk[i] = FALSE; + return(FALSE); + END + END + return(TRUE); + END + else + /* No drives present */ + BEGIN + no_fatal_error = FALSE; + return(FALSE); + END +END + + + +/* */ +char write_boot_record(cylinder,which_disk) + +unsigned cylinder; +unsigned char which_disk; + +BEGIN + +char i; +char j; +char far *buffer_pointer = boot_record; + + /* Setup read, always on a cylinder boundary */ + regs.h.ah = uc(WRITE_DISK); /* AC000 */ + regs.h.al = uc(1); /* AC000 */ + regs.h.dh = uc(0); /* AC000 */ + regs.h.cl = uc(0x01); /* AC000 */ + + /* Specify the disk */ + regs.h.dl = which_disk + 0x80; + + /* Need to scramble CX so that sectors and cyl's are in INT 13 format */ + + if (cylinder > u(255)) /* AC000 */ + BEGIN + regs.h.cl = regs.h.cl | ((unsigned char)((cylinder /256) << 6)); + END + regs.h.ch = (unsigned char)(cylinder & 0xFF); + + /* Point at the place to read the boot record */ + regs.x.bx = FP_OFF(buffer_pointer); + segregs.es = FP_SEG(buffer_pointer); + + /* write the boot record */ + DiskIo(®s,®s,&segregs); /* AC000 */ + + /* Check for error reading it */ + if ((regs.x.cflag & 1) != u(1)) /* AC000 */ + BEGIN + return(TRUE); + END + else + BEGIN + /* Tell user there was an error */ + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + display(error_2); + no_fatal_error = FALSE; + return(FALSE); + END +END + +/* */ +unsigned verify_tracks(pointer,type) + +char pointer; +char type; + +BEGIN +unsigned i; +unsigned location; +unsigned sectors_per_fat; +unsigned cur_cyl; +unsigned verify_cyl; +unsigned num_tracks; +unsigned long total_sectors; +char golden_tracks; +char retry; +unsigned char cur_head; /* AC004 */ + +char far *buffer_pointer = boot_record; +char head; + + + + for (i=u(0); i< u(BYTES_PER_SECTOR);i++) /* AC000 */ + BEGIN + /* Put something other then 0's so that unformatted FAT looks full */ + + boot_record[i] = uc(0xF6); /* AC000 */ + END + + /* Get the start cylinder for the sweep */ + cur_cyl = free_space[pointer].start; + + /* Also keep track of what it is */ + verify_cyl = cur_cyl; + + /* Initialize the start head -assume 0*/ + cur_head = uc(0); /* AC004 */ + if ((type == c(PRIMARY)) && (cur_cyl == u(0))) /* AC000 */ + BEGIN + + /* It's head 1 - NOTE: This is convience for PC-DOS because it is */ + /* always this way - This may have to be beefed up for IFS */ + cur_head = uc(1); /* AC004 */ + END + + /* Now go figure out the number of golden sectors needed. Use the */ + /* allocation equation in the fixed disk section of DOS Tech Ref. */ + /* */ + /* TS = Free cyl's * sector/track * track/cyl */ + /* RS = 1 */ + /* D = 512 */ + /* BPD = 32 */ + /* BPS = BYTES_PER_SECTOR */ + /* CF = 2 */ + /* SPF = Solve */ + /* SPC = 4 or 8 */ + /* BPC = 1.5 or 2 */ + /* */ + /* Golden Sectors = RS + 2(SPF) + BPD(D) + (DOSFILES) */ + /* ÄÄÄÄÄÄ if bootable */ + /* BPS */ + + total_sectors = ((unsigned long)free_space[pointer].space) * max_head[cur_disk] * max_sector[cur_disk]; + + /* Chop off one track if it starts on head 1 */ + if (cur_head == uc(1)) /* AC004 */ + BEGIN + total_sectors = total_sectors - max_sector[cur_disk]; + END + + /* See if 12 or 16 bit fat */ + if (total_sectors > (unsigned long)FAT16_SIZE) + BEGIN + /* 16 bit */ + sectors_per_fat = ((unsigned)((total_sectors -33)/(2 + ((BYTES_PER_SECTOR *4)/2)))); + END + else + BEGIN + /* 12 bit */ + sectors_per_fat = ((unsigned)((total_sectors -33)/(2 + ((BYTES_PER_SECTOR *8)/1.5)))); + END + + /* Round up one just to handle any rounding errors */ + sectors_per_fat++; + + /* Now see how many tracks */ + num_tracks = (sectors_per_fat*2) + 33; + + /* If primary and drive 0, add in enough for system files */ + if ((type == c(PRIMARY)) && (cur_disk == c(0))) /* AC000 */ + BEGIN + num_tracks = num_tracks + SYSTEM_FILE_SECTORS; + END + + #if IBMCOPYRIGHT + /* Now convert to tracks */ + num_tracks = num_tracks/max_sector[cur_disk]; + + /* Handle upward rounding */ + if (num_tracks%max_sector[cur_disk] != u(0)) /* AC000 */ + BEGIN + num_tracks++; + END + #else + /* Handle upward rounding */ /* The problem with the IBM code is */ + if (num_tracks%max_sector[cur_disk] != u(0)) /* that if num_tracks is < max_sector[cur_disk] */ + BEGIN /* the num_tracks becomes 0 due to the integer */ + num_tracks = num_tracks + max_sector[cur_disk]; /* division and num_tracks will not be inc'd . */ + END /* This section of code overcomes that. */ + + /* Now convert to tracks */ + num_tracks = num_tracks/max_sector[cur_disk]; + #endif + + + golden_tracks = FALSE; + while (!golden_tracks) + BEGIN + for (i = u(0);i < num_tracks; i++) /* AC000 */ + BEGIN + retry = c(0); /* AC000 */ + do + BEGIN + retry++; + /* Specify the operation */ + regs.h.ah = uc(WRITE_DISK); /* AC000 */ + + /* Specify number of sectors */ + regs.h.al = ((unsigned char)max_sector[cur_disk]); + + /* Specify the start sectors */ + regs.h.cl = uc(1); /* AC000 */ + + /* Need to scramble CX so that sectors and cyl's are in INT 13 format */ + if (cur_cyl > u(255)) /* AC000 */ + BEGIN + regs.h.cl = regs.h.cl | ((unsigned char)((cur_cyl/256) << 6)); + END + regs.h.ch = ((unsigned char)cur_cyl) & 0xFF; + + /* Specify the disk */ + regs.h.dl = ((unsigned char)cur_disk) + 0x80; + + /* Specify the head */ + regs.h.dh = cur_head; /* AC004 */ + + /* Point at the place to write */ + regs.x.bx = FP_OFF(buffer_pointer); + segregs.es = FP_SEG(buffer_pointer); + + /* write the track */ + DiskIo(®s,®s,&segregs); /* AC000 */ + + END + while (((regs.x.cflag & 1) == u(1)) && (retry != c(5))); /* AC000 */ + + /* See if we had a good read */ + if ((regs.x.cflag & 1) != u(1)) /* AC000 */ + BEGIN + golden_tracks = TRUE; + /* Get the next head */ + cur_head++; + if (cur_head == (uc(max_head[cur_disk] -1))) /* AC004 */ + BEGIN + /* Up to the next cylinder */ + cur_head = uc(0); /* AC004 */ + cur_cyl++; + + /* Check to see if we've reached the end of the free_space*/ + if (cur_cyl > free_space[pointer].end) + BEGIN + /* It is, so return with the cyl offset equal to the freespace */ + return(free_space[pointer].space); + END + END + END + else + BEGIN + /* Get out of the for loop, with a false flag */ + golden_tracks = FALSE; + + /* Bump up to the next cylinder boundary */ + cur_cyl++; + cur_head = uc(0); /* AC004 */ + + /* Save the new verify start point */ + verify_cyl = cur_cyl; + + break; + END + END /* for num_tracks */ + END /* while !golden_tracks */ + + /* All done, return the offset from original cyl to the new one */ + return(verify_cyl - free_space[pointer].start); +END + + +/* */ +char get_drive_parameters(drive) + +unsigned char drive; + +BEGIN + /* See how many drives there are */ + regs.h.ah = uc(DISK_INFO); /* AC000 */ + regs.h.dl = drive; + DiskIo(®s,®s,&segregs); /* AC000 */ + + /* See if any drives exist */ + if ((regs.h.dl == uc(0)) || ((regs.x.cflag & 1) == u(1))) /* AC000 */ + BEGIN + display(error_1); + return(FALSE); + END + else + BEGIN + /* Save the number of drives */ + number_of_drives = regs.h.dl; + return(TRUE); + END +END + +/* */ +char read_boot_record(cylinder,which_disk,which_head,which_sector) /* AC000 */ + +unsigned cylinder; +unsigned char which_disk; +unsigned char which_head; /* AN000 */ +unsigned char which_sector; /* AN000 */ + +BEGIN + +char far *buffer_pointer = boot_record; + + /* Setup read, always on a cylinder boundary */ + regs.h.ah = uc(READ_DISK); /* AC000 */ + regs.h.al = uc(1); /* AC000 */ + regs.h.dh = which_head; /* AC000 */ + regs.h.cl = which_sector; /* AC000 */ + + /* Specify the disk */ + regs.h.dl = which_disk + 0x80; + + /* Need to scramble CX so that sectors and cyl's are in INT 13 format */ + + if (cylinder > u(255)) /* AC000 */ + BEGIN + regs.h.cl = regs.h.cl | ((char)((cylinder /256) << 6)); + END + regs.h.ch = (unsigned char)(cylinder & 0xFF); + + /* Point at the place to write the boot record */ + regs.x.bx = FP_OFF(buffer_pointer); + segregs.es = FP_SEG(buffer_pointer); + + /* read in the boot record */ + DiskIo(®s,®s,&segregs); /* AC000 */ + /* Check for error reading it */ + if ((regs.x.cflag & 1) != u(1)) /* AC000 */ + BEGIN + return(TRUE); + END + else + BEGIN + /* Tell user there was an error */ + good_disk[which_disk] = FALSE; + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + return(FALSE); + END +END + +/* */ +void DiskIo(InRegs,OutRegs,SegRegs) +union REGS *InRegs; +union REGS *OutRegs; +struct SREGS *SegRegs; + +BEGIN + + char *WritePtr; + +#ifdef DEBUG + + switch(InRegs->h.ah) + { + case 0: + case 1: + case 2: + case 4: + case 8: + case 15: + case 16: + int86x((int)DISK,InRegs,OutRegs,SegRegs); /* AC000 */ + break; + + default: + WritePtr = getenv("WRITE"); + if (strcmpi(WritePtr,"ON") != 0) + BEGIN + printf("\nDisallowing Disk I/O Request\n"); + printf("AX:%04X BX:%04X CX:%04X DX:%04X ES:%04X\n", + InRegs->x.ax,InRegs->x.bx,InRegs->x.cx,InRegs->x.dx,SegRegs->es); + + OutRegs->h.ah = (unsigned char) 0; + OutRegs->x.cflag = (unsigned) 0; + END + else int86x((int)DISK,InRegs,OutRegs,SegRegs); + + break; + + } + +#else + + int86x((int)DISK,InRegs,OutRegs,SegRegs); /* AC000 */ + +#endif + + return; + +END + diff --git a/v4.0/src/CMD/FDISK/MAIN.C b/v4.0/src/CMD/FDISK/MAIN.C new file mode 100644 index 0000000..289d5cc --- /dev/null +++ b/v4.0/src/CMD/FDISK/MAIN.C @@ -0,0 +1,332 @@ + +/* */ + +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SOURCE FILE NAME: FDISK */ +/* */ +/* DESCRIPTIVE NAME: FIXED DISK PARTITIONING UTILITY */ +/* */ +/* FUNCTION: */ +/* Allows creation and deletion of DOS related partitions */ +/* on fixed disk devices 80-81h (int 13h BIOS defined, */ +/* DOS). Also allows display of all partitions, and will */ +/* allow a partition to be marked active (bootable). The */ +/* user will be prompted for action thru a full screen */ +/* interface. The user can also create, delete and display */ +/* logical DOS drives within a EXTENDED DOS Partition. If a*/ +/* regular DOS partition is created, the beginning of the */ +/* partition will be scanned to insure a contiguous area of*/ +/* good sectors on the disk large enough to satisfy the */ +/* DOS system requirements. If a bad spot is found, the */ +/* start of the partition will be moved out until a good */ +/* area is located */ +/* */ +/* NOTES: The program will work by setting up a logical image */ +/* of all relevant disk information at initilization */ +/* time. All operations will be performed on this */ +/* logical image, thus reducing disk accesses to only */ +/* those required to initially set up the logical image,*/ +/* and to write the changed information at the end. The */ +/* user will be informed if there is a problem writing */ +/* the logical image back to the disk. */ +/* */ +/* FDISK will interface with the partition table in the */ +/* master boot record as defined in the PC-DOS technical*/ +/* reference manual. It will also create and manage the */ +/* EXTENDED DOS partition architecture as defined in the*/ +/* PC-DOS 3.30 functional spec (CP/DOS spec dcr pending)*/ +/* */ +/* ENTRY POINTS: MAIN */ +/* LINKAGE: [d:] [path] FDISK */ +/* */ +/* EXTERNAL REFERENCES: */ +/* Fixed Disk Master Boot Record */ +/* EXTENDED Partition Volume Boot Records */ +/* Note: Both of the above are physical data structures on */ +/* the surface of the disk */ +/* */ +/* P.S. - To whoever winds up maintaining this, I will */ +/* apoligize in advance. I had just learned 'C' when */ +/* writing this, so out of ignorance of the finer points*/ +/* of the langauge I did a lot of things by brute force.*/ +/* Hope this doesn't mess you up too much - MT 5/20/86 */ +/******************** END OF SPECIFICATIONS ********************/ + +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN000 */ +#include /* AN001 */ +#include /* AN000 */ + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: MAIN */ +/* */ +/* DESCRIPTIVE NAME: Main control routine */ +/* */ +/* FUNCTION: Main will handle call routines to handle the */ +/* setup of the video for the full screen interface, */ +/* get physical data on the drive characteristics, */ +/* initilize all data fields with the current status */ +/* of the disk partitioning information. Before the */ +/* program is terminated, the video is reset to the */ +/* mode it was in previous to the routine entry. It */ +/* will also handle the case of an improper setup */ +/* */ +/* NOTES: FDISK requires at least 1 hardfile to operate */ +/* */ +/* ENTRY POINTS: main(); */ +/* LINKAGE: */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: Return Code = 0 */ +/* */ +/* EXIT-ERROR: Return Code = 1 */ +/* */ +/* EFFECTS: Sets up status variables, sets up video for full */ +/* screen interface, and then restores the video mode */ +/* before exiting program */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* init_video_information */ +/* get_disk_information */ +/* check_valid_environment */ +/* do_main_menu */ +/* init_partition_tables */ +/* reset_video_information */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* DosExit */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + + +/* */ +/**************************************************************************/ +/* */ +/* UTILITY NAME: FDISK.com */ +/* SOURCE FILE NAME: FDISK.c */ +/* STATUS: FDISK utility, DOS 3.3 */ +/* CHANGE HISTORY: UPDATED 5-29-87 DOS4.0 DRM */ +/* SYNTAX (Command line) */ +/* */ +/* [d:][path]FDISK */ +/* */ +/* or */ +/* */ +/* [d:][path]FDISK d [/PRI:m | /EXT:n | /LOG:o | /Q ...] */ +/* */ +/* d: Drive to load FDISK utility from */ +/* */ +/* path path to the directory on specified drive to */ +/* load FDISK from */ +/* */ +/* d Drive (1 or 2) that FDISK should operate on */ +/* */ +/* /PRI:m Size of Primary DOS partition to create in K */ +/* */ +/* /EXT:n Size of Extended DOS partition to create in K */ +/* */ +/* /LOG:o Size of Logical drive to create in K in the */ +/* extended partition */ +/* */ +/* /Q This suppresses the reboot screen and returns */ +/* FDISK to DOS even if partitons have changed. */ +/* */ +/* UTILITY FUNCTION: */ +/* Allows you to create, set up, display, and delete the */ +/* DOS partitions on a fixed disk. */ +/* */ +/**************************************************************************/ +/* */ +void main(argc,argv) /* AC000 */ + +int argc; /* AN000 */ +char *argv[]; /* AN000 */ + +BEGIN + + char temp; /* AN000 */ + unsigned input; + + /* DISABLE CNTL-BREAK HERE */ + /* Gets defines from signal.h */ + signal( (int) SIGINT, SIG_IGN ); /* AN000 */ + + no_fatal_error = TRUE; /* AN000 */ + + /* Preload messages and return */ + if ( preload_messages() && + get_yes_no_values() ) /* AN000 AC012 */ + BEGIN /* AN000 */ + + /* Parse the command line for syntax and switches */ + if(parse_command_line(argc,argv)) /* AN000 */ + + BEGIN /* AN000 */ + /* check to see if switches were set */ + if ((primary_flag == FALSE) && + (extended_flag == FALSE) && + (logical_flag == FALSE) && + (disk_flag == FALSE)) /* AN000 */ + + BEGIN /* AN000 */ + reboot_flag = FALSE; + /* See if running evironment is ok (Got hardfile, no network */ + if (check_valid_environment()) + BEGIN /* AN000 */ + /* Get and save screen mode information */ + init_video_information(); + clear_screen(u(0),u(0),u(24),u(79)); /* AC006 */ + + /* Get disk size information */ + good_disk[0] = TRUE; + good_disk[1] = TRUE; + + if (get_disk_info()) + BEGIN + /* build memory model of partitions */ + init_partition_tables(); + + /* Go do main screen */ + do_main_menu(); + write_info_to_disk(); + END + + if (reboot_flag) + BEGIN /* AN000 */ + reboot_system(); + DOSEXIT((unsigned) 0,(unsigned) 0); /* AC000 */ + END /* AN000 */ + + /* Nearly done, go reset screen mode */ + if (no_fatal_error) + BEGIN + reset_video_information(); + END /* AN000 */ + /* this is end of check valid environment */ + END /* AN000 */ + /* This is end for no switches set */ + END /* AN000 */ + + else /* AN000 */ + + BEGIN /* AN000 */ + if ( ((primary_flag == FALSE) && + (extended_flag == FALSE) && + (logical_flag == FALSE)) || + (disk_flag == FALSE) ) /* AN000 */ + display_msg((int)8,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class)); /*;AN000; AC014 AC015 */ + + else + BEGIN + reboot_flag = FALSE; /* AN000 */ + /* Get disk size information */ /* AN000 */ + good_disk[0] = TRUE; /* AN000 */ + good_disk[1] = TRUE; /* AN000 */ + if (get_disk_info()) /* AN000 */ + BEGIN + if (number_of_drives < (cur_disk_buff+1)) + display_msg((int)8,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class)); /*;AN000; AC014 AC015*/ + else + BEGIN /* AN000 */ + /* build memory model of partitions */ + init_partition_tables(); /* AN000 */ + + /* set cur_disk to current disk */ + cur_disk = cur_disk_buff; /* AN000 */ + + /* If /PRI: was specified, create primary partition */ + /* check to see if a primary partition already exists */ + if ( (primary_flag == TRUE) && /* AN000 */ + ( (!find_partition_type(uc(DOS12))) && + (!find_partition_type(uc(DOS16))) && + (!find_partition_type(uc(DOSNEW))) ) ) /* AC000 */ + BEGIN + temp = find_part_free_space((char) PRIMARY); /* AN000 */ + if (primary_buff >= free_space[temp].mbytes_unused) /* AN000 */ + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(primary_buff, + cur_disk_buff); /* AN004 */ + make_partition(input,temp,uc(ACTIVE),(char)PRIMARY); /* AN000 */ + END + + /* If /EXT: was specified, create extended partition */ + /* Check and see if there is a primary partition before you create an extended */ + if ( (extended_flag == TRUE) && /* AN000 */ + ( (cur_disk == c(1)) || + (find_partition_type(uc(DOS12))) || + (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW))) ) ) /* AC000 */ + BEGIN + /* Make sure there isn't an extended already there */ + if (!find_partition_type(uc(EXTENDED))) /* AC000 */ + BEGIN + temp = find_part_free_space((char) EXTENDED); /* AN000 */ + if (extended_buff >= free_space[temp].mbytes_unused) /* AN000 */ + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(extended_buff, + cur_disk_buff); /* AN004 */ + make_partition(input,temp,(unsigned char) NUL,(char) EXTENDED); /* AN000 */ + END + END + + /* If /LOG: was specified, create logical partition */ + if ( (logical_flag == TRUE) && + (find_partition_type(uc(EXTENDED))) ) /* AN000 */ + BEGIN /* AN000 */ + temp = find_ext_free_space(); /* AN000 */ + if (logical_buff >= free_space[temp].mbytes_unused) /* AN000 */ + input = free_space[temp].space; /* AN000 */ + else /* AN000 */ + input = (unsigned)mbytes_to_cylinders(logical_buff, + cur_disk_buff); /* AN004 */ + make_volume(input,temp); /* AN000 */ + END + + /* This is end of switch execution */ + write_info_to_disk(); /* AN000 */ + END /* AN000 */ + /* This is the end of compare cur_disk_buff for valid drive */ + END + /* This is the end of just disk_flag set */ + END + /* This is end of if switch is present */ + END + /* This is end of Parse command line */ + END /* AN000 */ + /* This end of Preload_messages function */ + END /* AN000 */ + cur_disk = c(0); /* AN001 */ + if ( (quiet_flag == TRUE) && + (!find_partition_type(uc(DOS12))) && + (!find_partition_type(uc(DOS16))) && + (!find_partition_type(uc(DOSNEW))) ) /* AN001 */ + exit(ERR_LEVEL_1); /* AN001 */ + else + BEGIN /* AN005 */ + if ((quiet_flag == TRUE) && /* AN005 */ + (primary_flag == FALSE) && /* AN008 */ + (extended_flag == FALSE) && /* AN008 */ + (logical_flag == FALSE)) /* AN008 */ + exit(ERR_LEVEL_2); /* AN005 */ + else /* AN005 */ + exit(ERR_LEVEL_0); /* AN001 */ + END /* AN005 */ +END + + diff --git a/v4.0/src/CMD/FDISK/MAINMENU.C b/v4.0/src/CMD/FDISK/MAINMENU.C new file mode 100644 index 0000000..c0a99c8 --- /dev/null +++ b/v4.0/src/CMD/FDISK/MAINMENU.C @@ -0,0 +1,231 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ + +/* */ +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DO_MAIN_MENU */ +/* */ +/* DESCRIPTIVE NAME: Main menu display and input routine */ +/* */ +/* FUNCTION: */ +/* Displays the main FDISK menu, accepts and validates */ +/* input from menu and passes control to requested function */ +/* */ +/* NOTES: The following screen is managed by this routine: */ +/* */ +/* ³0000000000111111111122222222223333333333³ */ +/* ³0123456789012345678901234567890123456789³ */ +/* ÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ */ +/* 00³IBM Personal Computer ³ */ +/* 01³Fixed Disk Setup Program Version 3.30 ³ */ +/* 02³(C)Copyright IBM Corp. 1983,1987 ³ */ +/* 03³ ³ */ +/* 04³FDISK Options ³ */ +/* 05³ ³ */ +/* 06³Current Fixed Disk Drive: # ³ */ +/* 07³ ³ */ +/* 08³Choose one of the following: ³ */ +/* 09³ ³ */ +/* 10³ 1. Create DOS partition ³ */ +/* 11³ 2. Change Active Partition ³ */ +/* 12³ 3. Delete DOS Partition ³ */ +/* 13³ 4. Display Partition Data ³ */ +/* 14³ 5. Select Next Fixed Disk Drive ³ */ +/* 15³ ³ */ +/* 16³ ³ */ +/* 17³ ³ */ +/* 18³Enter choice: [#] ³ */ +/* 19³ ³ */ +/* 20³ ³ */ +/* 21³WARNING! No partitions marked active ³ */ +/* 22³ ³ */ +/* 23³Press ESC to return to DOS ³ */ +/* ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */ +/* */ +/* ENTRY POINTS: do_main_menu */ +/* LINKAGE: do_main_menu(); */ +/* NEAR CALL */ +/* */ +/* INPUT: None */ +/* */ +/* EXIT-NORMAL: ERROR=FALSE */ +/* */ +/* EXIT-ERROR: ERROR=TRUE */ +/* GOTO internal_program_error if case statement */ +/* failure when branching to requested function */ +/* */ +/* EFFECTS: No data directly modified by this routine, but */ +/* child routines will modify data. */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* clear_screen */ +/* display */ +/* get_num_input */ +/* create_partition */ +/* change_active_partition */ +/* delete_partition */ +/* display_partition_information */ +/* find_active_partition */ +/* change_drive */ +/* internal_program_error */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/******************** END OF SPECIFICATIONS ********************/ + +/* */ +void do_main_menu() + +BEGIN + +char input; +char max_input; +unsigned temp; +unsigned i; + + + input = c(NUL); /* AC000 */ + PercentFlag = (FLAG)FALSE; /* AN000 */ + /* Intialize cur_disk indicator. It is 0 based for array usage */ + /* See if first disk readable */ + cur_disk = c(0); /* AC000 */ + if (!good_disk[0]) + BEGIN + cur_disk++; + END + + /* See if we have a valid combo of disk */ + if ((good_disk[0]) || ((good_disk[1]) && (number_of_drives == uc(2)))) /* AC000 */ + BEGIN + clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */ + /* Display the copyright */ + display(menu_1); + + /* See if we couldn't access drive 1 */ + if (!good_disk[0]) + BEGIN + insert[0] = c('1'); /* AC000 */ + display(error_30); + END + + /* Display the menu every time this routine is returned to until ESC */ + input = c(NUL); /* AC000 */ + while (input !=c(ESC)) /* AC000 */ + BEGIN + /* Put up most of the menu */ + display(menu_2); + display(menu_3); + display(menu_7); + + /* Put correct disk in current disk message */ + insert[0]=cur_disk+1+'0'; + display(menu_5); + + /* Display warning prompt if no active partitions */ + /* check to see if there is an avail partition */ + temp = u(0); /* AC000 */ + for (i = u(0); i < u(4);i++) /* AC000 */ + BEGIN + + /* See if any non - zero system id bytes */ + temp = temp | part_table[cur_disk][i].sys_id ; + END + /* Any entry that isn't zero means */ + if (temp != u(0)) /* AC000 */ + BEGIN + /* If there isn't an active partition and this is disk 1, then yell) */ + if ((!find_active_partition()) && (cur_disk == c(0))) /* AC000 */ + display(menu_6); + END + + /* Get the menu input */ + + /* See if more than one fixed disk */ + if (number_of_drives == uc(2)) /* AC000 */ + BEGIN + display(menu_4); + max_input = c(5); /* AC000 */ + END + else /* only 4 options */ + max_input = c(4); /* AC000 */ + /* Setup default and go get input */ + input = get_num_input(c(1),max_input,input_row,input_col); /* AC000 */ + switch(input) + BEGIN + case '1': create_partition(); + break; + + case '2': change_active_partition(); + break; + + case '3': delete_partition(); + break; + + case '4': display_partition_information(); + break; + + case '5': BEGIN + if (number_of_drives == uc(1)) /* AC000 */ + internal_program_error(); + else + BEGIN + /* Swap the number */ + if (cur_disk == c(0)) /* AC000 */ + BEGIN + if (good_disk[1]) + BEGIN + cur_disk++; + END + else + BEGIN + /* Disk has error reading */ + insert[0] = c('2'); /* AC000 */ + display(error_30); + END + END + else + BEGIN + + if (cur_disk == c(1)) /* AC000 */ + BEGIN + if (good_disk[0]) + BEGIN + cur_disk--; + END + else + BEGIN + /* Disk has error reading */ + insert[0] = c('1'); /* AC000 */ + display(error_30); + END + END + else + internal_program_error; + END + END + break; + END + + case ESC: break; /* ESC case */ + + default: internal_program_error(); + END + END + END + else + BEGIN + /* Can't read either drive, so quit */ + no_fatal_error = c(FALSE); /* AC000 */ + display(error_2); + END + return; +END + + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/MAKEFILE b/v4.0/src/CMD/FDISK/MAKEFILE new file mode 100644 index 0000000..2d4117e --- /dev/null +++ b/v4.0/src/CMD/FDISK/MAKEFILE @@ -0,0 +1,114 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +map =..\..\mapper +here =..\cmd\fdisk + +all: fdisk.exe + + +# Handle the FDISK 'C' source compilations first + +fdiskm.c : $(msg)\$(COUNTRY).msg fdisk.msg + menubld fdisk.msg $(msg)\$(COUNTRY).MSG + +fdisk5.cl1 : fdisk5.skl $(msg)\$(COUNTRY).msg + +fdisk.ctl : fdisk.skl $(msg)\$(COUNTRY).msg + +main.obj : main.c \ + fdisk.h subtype.h extern.h fdiskmsg.h msgret.h doscall.h + +fdisk.obj : fdisk.c \ + fdisk.h subtype.h extern.h fdiskmsg.h doscall.h msgret.h + +mainmenu.obj : mainmenu.c fdisk.h subtype.h extern.h fdiskmsg.h + +display.obj : display.c \ + fdisk.h subtype.h extern.h fdiskmsg.h doscall.h + +d_menus.obj : d_menus.c fdisk.h subtype.h extern.h fdiskmsg.h + +c_menus.obj : c_menus.c fdisk.h subtype.h extern.h fdiskmsg.h + +input.obj : input.c fdisk.h subtype.h extern.h fdiskmsg.h doscall.h + +tdisplay.obj : tdisplay.c fdisk.h subtype.h extern.h fdiskmsg.h + +vdisplay.obj : vdisplay.c fdisk.h subtype.h extern.h fdiskmsg.h + +space.obj : space.c fdisk.h subtype.h extern.h + +partinfo.obj : partinfo.c fdisk.h subtype.h extern.h + +makepart.obj : makepart.c fdisk.h subtype.h extern.h + +video.obj : video.c fdisk.h extern.h subtype.h fdiskmsg.h doscall.h + +int13.obj : int13.c fdisk.h subtype.h extern.h fdiskmsg.h + +diskout.obj : diskout.c fdisk.h subtype.h extern.h + +fdparse.obj : fdparse.c fdisk.h subtype.h extern.h parse.h msgret.h + +convert.obj : convert.c fdisk.h subtype.h extern.h + +global.obj : global.c fdisk.h makefile + +fdiskm.obj : fdiskm.c + +messages.obj : messages.c msgret.h extern.h subtype.h fdisk.h + + +# Handle the FDISK MASM source + + +fdboot.obj : fdboot.asm fdisk5.cl1 + +fdboot.inc: fdboot.obj + link fdboot; + exe2bin fdboot + del fdboot.exe + dbof fdboot.bin fdboot.inc 600 200 + +_parse.obj : _parse.asm $(inc)\psdata.inc $(inc)\parse.asm \ + makefile + +_msgret.obj : _msgret.asm $(inc)\psdata.inc \ + fdisk.ctl fdisk.cla fdisk.clb fdisk.cl1 fdisk.cl2 \ + makefile + +bootrec.obj : bootrec.asm fdboot.inc \ + makefile + +reboot.obj : reboot.asm \ + makefile + +$(map)\mapper.lib: + cd $(map) + nmake + cd $(here) + +# Do the link of FDISK + +fdisk.exe : fdisk.obj reboot.obj bootrec.obj fdboot.obj \ + display.obj input.obj tdisplay.obj vdisplay.obj \ + space.obj partinfo.obj video.obj makepart.obj \ + int13.obj diskout.obj messages.obj fdparse.obj \ + convert.obj global.obj fdiskm.obj main.obj \ + c_menus.obj d_menus.obj mainmenu.obj _msgret.obj \ + $(map)\mapper.lib makefile fdisk.lnk fdisk.ctl _parse.obj \ + $(inc)\comsubs.lib + cd $(inc) + nmake + cd $(here) + link @fdisk.lnk + diff --git a/v4.0/src/CMD/FDISK/MAKEPART.C b/v4.0/src/CMD/FDISK/MAKEPART.C new file mode 100644 index 0000000..b33e091 --- /dev/null +++ b/v4.0/src/CMD/FDISK/MAKEPART.C @@ -0,0 +1,282 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "string.h" /* AN000 */ + +/* */ + +void make_partition(size,free_pointer,bootable,type) + +unsigned size; +char free_pointer; +unsigned char bootable; +char type; + +BEGIN + +char table_pointer; +unsigned i; +unsigned char temp; +unsigned long total_sectors; + + /* Find a free spot to put it in */ + table_pointer = find_free_partition(); + + if (table_pointer != ((char)(NOT_FOUND))) + BEGIN + /* found a free partition, now lets go fill it up */ + + /* Do we need to make it active? */ + if (bootable == ((unsigned char)(ACTIVE))) + BEGIN + + /* Go clear out a previously active one */ + for (i=u(0); i +#include +#include +#include +#include + + +void main() + +BEGIN + +unsigned i; + + /* Main Menu */ + clear_screen(0,0,24,79); + display(menu_1); + display(menu_2); + display(menu_3); + display(menu_4); + insert[0] = 'C'; + display(menu_5); + display(menu_6); + display(menu_7); + + wait_for_ESC(); + + + /* Type of DOS partition for create */ + clear_screen(0,0,24,39); + display(menu_3); + insert[0] = 'C'; + display(menu_5); + display(menu_7); + display(menu_8); + display(menu_9); + display(menu_10); + display(menu_11); + wait_for_ESC(); + + /* Shortcut screen C:*/ + clear_screen(0,0,24,39); + display(menu_12); + insert[0] = 'C'; + display(menu_5); + display(menu_11); + display(menu_12); + display(menu_13); + wait_for_ESC(); + + /* Shortcut screen D:*/ + clear_screen(0,0,24,39); + display(menu_12); + insert[0] = 'C'; + display(menu_5); + display(menu_11); + display(menu_12); + display(menu_41); + wait_for_ESC(); + + +/* Create primary DOS partition screen */ + display(menu_12); + insert[0] = 'C'; + display(menu_5); + for (i=0;i < 92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_16); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_39); + display(menu_11); + wait_for_ESC(); + +/* Create Extended Partition */ + clear_screen(0,0,24,39); + display(menu_17); + insert[0] = 'C'; + display(menu_5); + for (i=0;i < 92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_16); + display(menu_39); + display(menu_11); + wait_for_ESC(); + + +/* Create logical drive screen */ + clear_screen(0,0,24,39); + display(menu_18); + for (i=0;i < 168;i++) + BEGIN + insert[i]= 'x'; + END + display(menu_19); + for (i=0;i < 168;i++) + BEGIN + insert[i]= 'x'; + END + display(menu_20); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_21); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_22); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_40); + display(menu_11); + wait_for_ESC(); + + +/* Change active partition screen */ + clear_screen(0,0,24,39); + display(menu_23); + insert[0] = 'C'; + display(menu_5); + for (i=0;i < 92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + display(menu_24); + display(menu_11); + wait_for_ESC(); + + +/* Delete Partition Screen */ + clear_screen(0,0,24,39); + display(menu_25); + insert[0] = 'C'; + display(menu_5); + display(menu_3); + display(menu_26); + display(menu_27); + display(menu_7); + display(menu_11); + wait_for_ESC(); + +/* Delete Primary Screen */ + clear_screen(0,0,24,39); + display(menu_28); + insert[0] = 'C'; + display(menu_5); + for (i=0;i < 92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + display(menu_29); + display(menu_11); + wait_for_ESC(); + + +/* Delete Extended Screen */ + clear_screen(0,0,24,39); + display(menu_30); + insert[0] = 'C'; + display(menu_5); + for (i=0;i<92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + display(menu_31); + display(menu_11); + wait_for_ESC(); + + +/* Delete Logical Drives */ + clear_screen(0,0,24,39); + display(menu_32); + display(menu_18); + for (i=0;i<168;i++) + BEGIN + insert[i]='x'; + END + display(menu_19); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_21); + display(menu_33); + display(menu_11); + wait_for_ESC(); + +/* Display Partition Information */ + clear_screen(0,0,24,39); + display(menu_35); + insert[0] = 'C'; + display(menu_5); + for (i=0;i<92;i++) + BEGIN + insert[i] = 'x'; + END + display(menu_14); + insert[0] = 'x'; + insert[1] = 'x'; + insert[2] = 'x'; + insert[3] = 'x'; + display(menu_15); + display(menu_36); + display(menu_11); + wait_for_ESC(); + +/* Display Logical Drive Info */ + clear_screen(0,0,24,39); + display(menu_37); + for (i=0;i<168;i++) + BEGIN + insert[i]='x'; + END + display(menu_19); + for (i=0;i<168;i++) + BEGIN + insert[i]='x'; + END + display(menu_20); + display(menu_11); + wait_for_ESC(); + +/* Reboot Screen */ + clear_screen(0,0,24,39); + display(menu_38); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_1); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_2); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_3); + wait_for_ESC(); + + clear_screen(0,0,24,39); + insert[0] = 'x'; + display(status_4); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_5); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_6); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_7); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_8); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_9); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(status_10); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_1); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_2); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_3); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_4); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_5); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_6); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_7); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_8); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_9); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_10); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_12); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_13); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_14); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_15); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_16); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_17); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_19); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_20); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_21); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_22); + wait_for_ESC(); + + clear_screen(0,0,24,39); + insert[0]='x'; + insert[1]='y'; + insert[2]='-'; + insert[3]='z'; + display(error_23); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_24); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_25); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_26); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_27); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_28); + wait_for_ESC(); + + clear_screen(0,0,24,39); + insert[0]='X'; + insert[1]=':'; + display(error_29); + wait_for_ESC(); + + clear_screen(0,0,24,39); + insert[0]='X'; + display(error_30); + wait_for_ESC(); + + clear_screen(0,0,24,39); + insert[0]='x'; + insert[1]='-'; + insert[2]='y'; + display(error_31); + wait_for_ESC(); + + clear_screen(0,0,24,39); + display(error_32); + wait_for_ESC(); + + clear_screen(0,0,24,39); + DOSEXIT(0,0); + +END + + +/******************* START OF SPECIFICATIONS *******************/ +/* */ +/* SUBROUTINE NAME: DISPLAY */ +/* */ +/* DESCRIPTIVE NAME: Display full screen interface messages */ +/* */ +/* FUNCTION: Displays messages and handles control characters */ +/* */ +/* NOTES: */ +/* FDISK MESSAGES */ +/* Portions of the screen that are handled in the msg are */ +/* indicated on the listing of the screen with the message */ +/* name given. If the text message is defined in another */ +/* screen, then the name is followed by a "#" character */ +/* */ +/* NOTE TO TRANSLATORS The characters inside the <> and the [] */ +/* are control characters and should not be translated. The */ +/* Control characters are defined as follows: */ +/* */ +/* - Highlight the following text */ +/* - Regular text */ +/* - Blink the following text */ +/* - Turn blinking off */ +/* - Print YES character, as set by define */ +/* - Print NO character, as set by define */ +/* - Sound the beep */ +/* - Save cursor position for later use */ +/* - Insert character from insert[] string. This string */ +/* must be set up prior to displaying the message. The */ +/* first will insert Insert[0], the second */ +/* insert[1], etc....This will move the cursor one */ +/* postition. The insert[] string will be initialized */ +/* */ +/* Multiple control characters can be between the <>. */ +/* */ +/* The %####%indicates Row and column for the text and has the */ +/* format of [rrcc] where the numbers are decimal and zero */ +/* based (first row/col is 00. The numbers are in decimal, */ +/* and must be 2 characters, which means rows/cols 0-9 should */ +/* be listed as 00-09. For example, the 5th row, 3rd column */ +/* on the screen would be listed as %0402%. */ +/* */ +/* The column number is always the column desired. The row */ +/* number is an offset from the previous row. For example, if */ +/* the text just printed is on row 6, and the next text should */ +/* be printed 2 rows down in column 0, then the control strin */ +/* would be %0201%. The first row specified in the message is */ +/* assumed to be based off of row 0, it would actually specify */ +/* the actual row for the start of the msg to be printed. */ +/* */ +/* ENTRY POINTS: display(*message_name); */ +/* LINKAGE: Near call */ +/* */ +/* INPUT: char *message_name */ +/* */ +/* EXIT-NORMAL: */ +/* */ +/* EXIT-ERROR: */ +/* */ +/* EFFECTS: */ +/* input_row changed if control character in message */ +/* input_col changed if control character in message */ +/* */ +/* INTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/* EXTERNAL REFERENCES: */ +/* ROUTINES: */ +/* */ +/* viowrtcharstratt(); */ +/******************** END OF SPECIFICATIONS ********************/ +void display(s) + +char far *s; + +BEGIN + unsigned row; + unsigned col; + char attribute; + char far *attribute_ptr = &attribute; + unsigned insert_count; + + + /* Initialize row and col, and index into array */ + row = 0; + col = 0; + insert_count = 0; + /* check for a request to display a null string */ + if (*s == '\0') + BEGIN + /* Message string error */ + insert[0] = '1'; + display(debug_msg); + END + else + BEGIN + /* There is data there, lets go handle it */ + + attribute = 0x00; + /* Go until end of string */ + while (*s != '\0') + BEGIN + + /* Check for any imbedded control strings */ + switch (*s) + BEGIN + /* Check for control characters */ + case '<': + BEGIN + s++; + while ( (*s != '>') && (*s != '\0') ) + BEGIN + switch (*s++) + BEGIN + case 'H': attribute = (attribute & 0x80) | 0x0F; + break; + + + case 'R': attribute = (attribute & 0x80) | 0x07; + break; + + case 'B': attribute |= 0x80; + break; + + case 'O': attribute &= 0x7F; + break; + + case 'W': DOSBEEP(900,400); + break; + + case 'I': + BEGIN + /* display next element in the array */ + if (attribute == 0x00) + attribute = 0x07; + VIOWRTCHARSTRATT(pinsert+insert_count++,1,row,col++,attribute_ptr,0); + break; + END + + + case 'Y': + BEGIN + /* display YES character in next location */ + *--s = YES; + if (attribute == 0x00) + attribute = 0x07; + VIOWRTCHARSTRATT(s++,1,row,col++,attribute_ptr,0); + break; + END + + case 'N': + BEGIN + /* display NO character in next location */ + *--s = NO; + if (attribute == 0x00) + attribute = 0x07; + VIOWRTCHARSTRATT(s++,1,row,col++,attribute_ptr,0); + break; + END + + + case 'S': + BEGIN + input_row = row; + input_col = col; + break; + END + + case 'C': + BEGIN + /* Clear from current position to end of line */ + clear_screen(row,col,row,39); + break; + END + + case '\0': + BEGIN + /* Message string error - string ended in the middle of control string*/ + insert[0] = '7'; + display(debug_msg); + break; + END + + default: + BEGIN + /* Message string error - no valid control char found */ + insert[0] = '6'; + display(debug_msg); + break; + END + END /* Switch */ + END /* While */ + /* Get the pointer past the '>' */ + s++; + break; + END /* control characters */ + + /* Check for row,col */ + case '%': + BEGIN + s++; + /* determine the row to put the message on */ + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = '2'; + display(debug_msg); + END + else + BEGIN + row = row+((unsigned)(((*s++ - '0')*10))); + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = '2'; + display(debug_msg); + END + else + BEGIN + row = row+((unsigned)(*s++ - '0')); + /* determine the col to put the message on */ + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = '3'; + display(debug_msg); + END + else + BEGIN + col = ((unsigned)(*s++ - '0')); + if ( !isdigit(*s) ) + BEGIN + /* Message string error */ + insert[0] = '3'; + display(debug_msg); + END + else + BEGIN + col = ((unsigned)((col* 10) + (*s++ - '0'))); + if (*s++ != '%') + BEGIN + /* Message string error */ + insert[0] = '4'; + display(debug_msg); + END /* 2nd sq bracket */ + END /* 2nd digit col */ + END /* 1st digit col */ + END /* 2nd digit row */ + END /* 1st digit row */ + break; + END + /* Handle anything else */ + + + default: + BEGIN + /* See if attribute set to anything */ + if (attribute == 0x00) + attribute = 0x07; + VIOWRTCHARSTRATT(s++,1,row,col++,attribute_ptr,0); + break; + END + END + END /* End of string check */ + END /* No characters in string check */ + return; + +END + +void number_in_msg(number,start) + +unsigned number; +unsigned start; + +BEGIN + +unsigned i; + + /* init the four spots to zero's */ + for (i = 0; i < 4;i++) + BEGIN + insert[start+i] = ' '; + END + /* Divide the space down and get it into decimal */ + if (number > 999) + BEGIN + insert[start] = ((char)(number/1000))+'0'; + insert[start+1] = '0'; + insert[start+2] = '0'; + insert[start+3] = '0'; + number = number%1000; + END + if (number > 99) + BEGIN + insert[start+1] = ((char)(number/100))+'0'; + insert[start+2] = '0'; + insert[start+3] = '0'; + number = number%100; + END + if (number > 9) + BEGIN + insert[start+2] = ((char)(number/10))+'0'; + insert[start+3] = '0'; + number = number%10; + END + insert[start+3] = ((char)(number +'0')); + return; +END + + + +void clear_screen(TopRow,LeftCol,BotRow,RightCol) + +unsigned TopRow; +unsigned LeftCol; +unsigned BotRow; +unsigned RightCol; + +BEGIN + +char attribute; +char *attribute_ptr = &attribute; + + attribute = 0x07; + VIOSCROLLUP(TopRow,LeftCol,BotRow,RightCol,0,attribute_ptr,0); + return; +END + + + +char wait_for_ESC() + +BEGIN + char input; + + while (input != ESC) + BEGIN + /* position the cursor at the end of the ESC prompt */ + VIOSETCURPOS(24,39,0); + + /* Get input */ + KBDFLUSHBUFFER(0); + /*KBDCHARIN(input_data,0,0);*/ + /*input = input_data->char_code;*/ + input = ((char)(getch())); + END + return(ESC); +END + + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/PROFILE.H b/v4.0/src/CMD/FDISK/PROFILE.H new file mode 100644 index 0000000..a15b72b --- /dev/null +++ b/v4.0/src/CMD/FDISK/PROFILE.H @@ -0,0 +1,44 @@ + +/* */ +/****************************************************************************/ +/* Define statements */ +/****************************************************************************/ +/* */ + +#define BEGIN { +#define END } +#define ESC 0x1B +#define NUL 0x00 +#define NOT_FOUND 0xFF +#define DELETED 0xFF +#define INVALID 0xFF +#define FALSE (1==0) +#define TRUE !FALSE +#define CR 0x0D + +/* */ +/****************************************************************************/ +/* Declare Global variables */ +/****************************************************************************/ +/* */ + + + + +unsigned input_row; +unsigned input_col; +char insert[200]; +char *pinsert = insert; + + +/* */ +/****************************************************************************/ +/* Subroutine Definitions */ +/****************************************************************************/ +/* */ + +void clear_screen(unsigned,unsigned,unsigned,unsigned); +void display(char far *); +char wait_for_ESC(void); + + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/REBOOT.ASM b/v4.0/src/CMD/FDISK/REBOOT.ASM new file mode 100644 index 0000000..272e607 --- /dev/null +++ b/v4.0/src/CMD/FDISK/REBOOT.ASM @@ -0,0 +1,43 @@ + + title Reboot Support for FDISK + +IF1 + %OUT ASSEMBLING: Reboot + %OUT +ENDIF + +ROMDATA segment at 040h + org 072h +BootType dw ? +ROMDATA ends + +ROMBIOS segment at 0ffffh + org 0 +POR label far +ROMBIOS ends + +_text segment byte public 'code' + assume cs:_TEXT + assume ds:nothing + assume es:nothing + assume ss:nothing + + public _reboot +_reboot proc near + + mov ax,ROMDATA + mov ds,ax + assume ds:ROMDATA + + mov BootType,1234h + + cli + cld + jmp POR + +_reboot endp + +_text ends + + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/SPACE.C b/v4.0/src/CMD/FDISK/SPACE.C new file mode 100644 index 0000000..21d10b5 --- /dev/null +++ b/v4.0/src/CMD/FDISK/SPACE.C @@ -0,0 +1,439 @@ + +#include "dos.h" +#include "fdisk.h" +#include "extern.h" +#include "subtype.h" + +/* */ +char find_part_free_space(type) + +char type; + +BEGIN + + +char i; +char partition_count; +char last_found_partition; +unsigned temp; +char freespace_count; +char any_partition; +unsigned temp_size; + + /* Sort the partition table */ + sort_part_table(c(4)); /* AC000 */ + + + /* Intialize free space to zero */ + for (i = c(0); i < c(5); i++) /* AC000 */ + BEGIN + free_space[i].space = u(0); /* AC000 */ + free_space[i].start = u(0); /* AC000 */ + free_space[i].end = u(0); /* AC000 */ + free_space[i].mbytes_unused = f(0); /* AC000 */ /* AN000 */ + free_space[i].percent_unused = u(0); /* AC000 */ /* AN000 */ + END + + /* Find space between start of disk and first partition */ + partition_count = c(0); /* AC000 */ + + any_partition = FALSE; + for (i = c(0); i < c(4); i++) /* AC000 */ + BEGIN + if (part_table[cur_disk][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + /* Found a partition, get the space */ + + free_space[0].start = u(0); /* AC000 */ + + /* This is a special case - the extended partition can not start */ + /* on cylinder 0 due too its archetecture. Protect against that here */ + if (type == c(EXTENDED)) /* AC000 */ + BEGIN + free_space[0].start = u(1); /* AC000 */ + END + + /* free space ends before start of next valid partition */ + if (part_table[cur_disk][sort[i]].start_cyl > u(0)) /* AC000 */ + BEGIN + free_space[0].end = part_table[cur_disk][sort[i]].start_cyl-1; + END + + free_space[0].space = part_table[cur_disk][sort[i]].start_cyl; + free_space[0].mbytes_unused = + cylinders_to_mbytes(free_space[0].space,cur_disk); /* AN004 */ + free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */ + + partition_count = i; + last_found_partition = sort[i]; + any_partition = TRUE; + break; + END + END + /* See if any partitions were there */ + if (any_partition) + BEGIN + /* Look for space between the rest of the partitions */ + freespace_count = c(1); /* AC000 */ + for (i = partition_count+1; i < c(4); i++) /* AC000 */ + BEGIN + if (part_table[cur_disk][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + + /* Check to see if more than one partition on a cylinder (i.e. XENIX bad block) */ + /* If so, leave the space at zero */ + + if (part_table[cur_disk][sort[i]].start_cyl != part_table[cur_disk][last_found_partition].end_cyl) + + BEGIN + /* No, things are normal */ + /* Get space between the end of the last one and the start of the next one */ + free_space[freespace_count].space = part_table[cur_disk][sort[i]].start_cyl + - (part_table[cur_disk][last_found_partition].end_cyl+1); + + temp_size = (part_table[cur_disk][sort[i]].start_cyl - + part_table[cur_disk][last_found_partition].end_cyl); + + if (temp_size != u(0) ) /* AC000 */ + BEGIN + free_space[freespace_count].space = temp_size - u(1); /* AC000 */ + END + END + + free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1; + free_space[freespace_count].end = part_table[cur_disk][sort[i]].start_cyl -1; + free_space[freespace_count].mbytes_unused = + cylinders_to_mbytes(free_space[freespace_count].space,cur_disk); /* AN004 */ + free_space[freespace_count].percent_unused = (unsigned) + cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */ + + + + /* update the last found partition */ + last_found_partition = sort[i]; + freespace_count++; + END + END + /* Find the space between the last partition and the end of the disk */ + free_space[freespace_count].space = (total_disk[cur_disk] + - part_table[cur_disk][last_found_partition].end_cyl)-1; + free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1; + free_space[freespace_count].end = total_disk[cur_disk]-1; + free_space[freespace_count].mbytes_unused = + cylinders_to_mbytes(free_space[freespace_count].space,cur_disk); /* AN004 */ + free_space[freespace_count].percent_unused = + cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */ + END + else + BEGIN + /* No partitions found, show entire space as free */ + free_space[0].start = u(0); /* AC000 */ + + /* This is a special case - the extended partition can not start */ + /* on cylinder 0 due too its architecture. Protect against that here */ + if (type == c(EXTENDED)) /* AC000 */ + BEGIN + free_space[0].start = u(1); /* AC000 */ + END + free_space[0].end = total_disk[cur_disk]-1; + free_space[0].space = (free_space[0].end - free_space[0].start)+1; + free_space[0].mbytes_unused = + cylinders_to_mbytes(free_space[0].space,cur_disk); /* AN004 */ + free_space[0].percent_unused = + cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */ + END + + + + /* Find largest free space, and verify the golden tracks while we are at it */ + do + BEGIN + temp = u(0); /* AC000 */ + + /* Zip thru the table */ + for (i = c(0); i < c(5); i++) /* AC000 */ + BEGIN + /* Is this one bigger ? */ + if (free_space[i].space > temp) + BEGIN + temp = free_space[i].space; + last_found_partition = i; + + END + END + + /* If there is any free space, go verify it */ + temp = u(0); + if (free_space[last_found_partition].space != u(0)) /* AC000 */ + BEGIN + + /* Go verify the tracks */ + temp = verify_tracks(last_found_partition,c(PRIMARY)); /* AC000 */ + END + /* Move up to next golden track */ + free_space[last_found_partition].start = free_space[last_found_partition].start+temp; + free_space[last_found_partition].space = free_space[last_found_partition].space-temp; + free_space[last_found_partition].mbytes_unused = + cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk); /* AN004 */ + free_space[last_found_partition].percent_unused = (unsigned) + cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]); /* AN000 */ + END + + /* Repeat the loop if the start was moved due to bad tracks */ + /* Unless we're past the end of the free space */ + while ((temp != u(0)) && (free_space[last_found_partition].space != u(0))); /* AC000 */ + + /* Return with the pointer to the largest free space */ + return(last_found_partition); +END + + + +/* */ +void sort_part_table(size) + +char size; + +BEGIN + +char changed; +char temp; +char i; + + /* Init the sorting parameters */ + + for (i=c(0); i < size; i++) /* AC000 */ + BEGIN + sort[i] = i; + END + + /* Do a bubble sort */ + changed = TRUE; + + /* Sort until we don't do a swap */ + while (changed) + + BEGIN + changed = FALSE; + for (i=c(1); i < size; i++) /* AC000 */ + BEGIN + + /* Does the partition entry start before the previous one, or */ + /* is it empty (0 ENTRY). If empty, it automatically gets shoved */ + /* to the front, if the previous entry isn't also empty */ + + if ((part_table[cur_disk][sort[i]].end_cyl < part_table[cur_disk][sort[i-1]].end_cyl) + || ((part_table[cur_disk][sort[i]].num_sec == ul(0)) + && (part_table[cur_disk][sort[i-1]].num_sec != ul(0)))) /* AC000 */ + + BEGIN + /* Swap the order indicators */ + temp = sort[i-1]; + sort[i-1] = sort[i]; + sort[i] = temp; + + /* printf("\nI-1 =%d\n",part_table[cur_disk][sort[i-1]].start_cyl);*/ + /* printf("I =%d\n",part_table[cur_disk][sort[i]].start_cyl);*/ + /* printf("Sort[i-1] = %d\n",sort[i-1]);*/ + /* printf("Sort[i] = %d\n",sort[i]); */ + /* wait_for_ESC(); */ + + + /* indicate we did a swap */ + changed = TRUE; + END + END + END + return; +END + + + + +/* */ +char find_ext_free_space() + + +BEGIN + + +char i; +char partition_count; +char last_found_partition; +unsigned temp; +char freespace_count; +char any_partition; +char ext_location; + + /* Sort the partition table */ + sort_ext_table(c(23)); /* AC000 */ + + + /* Initialize free space to zero */ + for (i = c(0); i < c(24); i++) /* AC000 */ + BEGIN + free_space[i].space = u(0); /* AC000 */ + free_space[i].start = u(0); + free_space[i].end = u(0); /* AC000 */ + free_space[i].mbytes_unused = f(0); /* AN000 */ + free_space[i].percent_unused = u(0); /* AN000 */ + END + + /* Find space between start of Extended partition and first volume */ + ext_location = find_partition_location(uc(EXTENDED)); /* AC000 */ + + partition_count = c(0); /* AC000 */ + + any_partition = FALSE; + for (i = c(0); i < c(23); i++) /* AC000 */ + BEGIN + if (ext_table[cur_disk][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + /* Found a partition, get the space */ + free_space[0].space = ext_table[cur_disk][sort[i]].start_cyl - part_table[cur_disk][ext_location].start_cyl; + free_space[0].start = part_table[cur_disk][ext_location].start_cyl; + free_space[0].end = ext_table[cur_disk][sort[i]].start_cyl-1; + free_space[0].mbytes_unused = + cylinders_to_mbytes(free_space[0].space,cur_disk); /* AN004 */ + free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */ + + partition_count = i; + last_found_partition = sort[i]; + any_partition = TRUE; + break; + END + END + /* See if any partitions were there */ + if (any_partition) + BEGIN + /* Look for space between the rest of the partitions */ + freespace_count = c(1); /* AC000 */ + for (i = partition_count+1; i < c(23); i++) /* AC000 */ + BEGIN + if (ext_table[cur_disk][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + + /* Get space between the end of the last one and the start of the next one */ + temp = ext_table[cur_disk][sort[i]].start_cyl - (ext_table[cur_disk][last_found_partition].end_cyl+1); + free_space[freespace_count].space = temp; + free_space[freespace_count].start = ext_table[cur_disk][last_found_partition].end_cyl+1; + free_space[freespace_count].end = ext_table[cur_disk][sort[i]].start_cyl -1; + free_space[freespace_count].mbytes_unused = + cylinders_to_mbytes(free_space[freespace_count].space,cur_disk); /* AN004 */ + free_space[freespace_count].percent_unused = (unsigned) + cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */ + + + /* update the last found partition */ + last_found_partition = sort[i]; + freespace_count++; + END + END + /* Find the space between the last partition and the end of the extended partition */ + temp = part_table[cur_disk][ext_location].end_cyl - ext_table[cur_disk][last_found_partition].end_cyl; + free_space[freespace_count].space = temp; + free_space[freespace_count].start = ext_table[cur_disk][last_found_partition].end_cyl+1; + free_space[freespace_count].end = part_table[cur_disk][ext_location].end_cyl; + free_space[freespace_count].mbytes_unused = + cylinders_to_mbytes(free_space[freespace_count].space,cur_disk); /* AN004 */ + free_space[freespace_count].percent_unused = (unsigned) + cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */ + + END + else + BEGIN + /* No partitions found, show entire space as free */ + free_space[0].space = (part_table[cur_disk][ext_location].end_cyl - part_table[cur_disk][ext_location].start_cyl) + 1; + free_space[0].start = part_table[cur_disk][ext_location].start_cyl; + free_space[0].end = part_table[cur_disk][ext_location].end_cyl; + free_space[0].mbytes_unused = + cylinders_to_mbytes(free_space[0].space,cur_disk); /* AN004 */ + free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */ + END + + /* Find largest free space */ + temp = u(0); /* AC000 */ + + + /* Find largest free space, and verify the golden tracks while we are at it */ + do + BEGIN + temp = u(0); /* AC000 */ + + /* Zip thru the table */ + for (i = c(0); i < c(24); i++) /* AC000 */ + BEGIN + /* Is this one bigger ? */ + if (free_space[i].space > temp) + BEGIN + temp = free_space[i].space; + last_found_partition = i; + END + END + /* If there is any free space, go verify it */ + temp = u(0); + if (free_space[last_found_partition].space != u(0)) /* AC000 */ + BEGIN + + /* Go verify the tracks */ + temp = verify_tracks(last_found_partition,c(EXTENDED)); /* AC000 */ + END + /* Move up to next golden track */ + free_space[last_found_partition].start = free_space[last_found_partition].start+temp; + free_space[last_found_partition].space = free_space[last_found_partition].space-temp; + free_space[last_found_partition].mbytes_unused = + cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk); /* AN004 */ + free_space[last_found_partition].percent_unused = + cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]); /* AN000 */ + END + /* Repeat the loop if the start was moved due to bad tracks */ + /* Unless we're past the end of the free space */ + while ((temp !=u(0)) && (free_space[last_found_partition].space!= u(0))); /* AC000 */ + + /* Return with the pointer to the largest free space */ + return(last_found_partition); +END + + +/* */ +void sort_ext_table(size) + +char size; + +BEGIN + +char changed; +char temp; +char i; + + /* Init the sorting parameters */ + + for (i=c(0); i < size; i++) /* AC000 */ + BEGIN + sort[i] = i; + END + + /* Do a bubble sort */ + changed = TRUE; + + /* Sort until we don't do a swap */ + while (changed) + + BEGIN + changed = FALSE; + for (i=c(1); i < size; i++) /* AC000 */ + BEGIN + + if (ext_table[cur_disk][sort[i]].start_cyl < ext_table[cur_disk][sort[i-1]].start_cyl) + BEGIN + + temp = sort[i-1]; + sort[i-1] = sort[i]; + sort[i] = temp; + /* indicate we did a swap */ + changed = TRUE; + END + END + END + return; +END diff --git a/v4.0/src/CMD/FDISK/SUBTYPE.H b/v4.0/src/CMD/FDISK/SUBTYPE.H new file mode 100644 index 0000000..60de3f6 --- /dev/null +++ b/v4.0/src/CMD/FDISK/SUBTYPE.H @@ -0,0 +1,158 @@ +/*************************************************************/ +/* DISPLAY.C ROUTINES */ +/*************************************************************/ +void display(char far *); +void number_in_msg(XFLOAT,unsigned); +void percent_in_msg(unsigned,unsigned); /* AN000 */ +void string_in_msg(char far *,unsigned); /* AN000 */ +void volume_in_msg(char far *,unsigned); /* AN000 */ + +/*************************************************************/ +/* VIDEO.C ROUTINES */ +/*************************************************************/ +void clear_screen(unsigned,unsigned,unsigned,unsigned); +void init_video_information(void); +void reset_video_information(void); +void get_video_attribute(void); /* AN006 */ + + +/*************************************************************/ +/* DISKOUT.C ROUTINES */ +/*************************************************************/ +void write_info_to_disk(void); +char write_master_boot_to_disk(unsigned char); +char write_ext_boot_to_disk(char,unsigned char); + + +/*************************************************************/ +/* PARTINFO.C ROUTINES */ +/*************************************************************/ +char find_free_partition(void); +char find_partition_type(unsigned char); +XFLOAT get_partition_size(unsigned char); +char find_active_partition(void); +char find_partition_location(unsigned char); +char find_free_ext(void); +char find_logical_drive(void); +char get_num_logical_dos_drives(void); +char find_ext_drive(char); +char find_previous_drive(char); + +/*************************************************************/ +/* MAKEPART.C ROUTINES */ +/*************************************************************/ +void make_partition(unsigned,char,unsigned char,char); +char make_volume(unsigned,char); + +/*************************************************************/ +/* INPUT.C ROUTINES */ +/*************************************************************/ +char get_num_input(char,char,unsigned,unsigned); +char get_yn_input(char,unsigned,unsigned); +char wait_for_ESC(void); +unsigned get_large_num_input(unsigned,unsigned,unsigned,char far *,unsigned,char far *); +char get_alpha_input(char,char,unsigned,unsigned,char,char); +char get_char_input(void); +void get_string_input(unsigned,unsigned,char far *); + + +/*************************************************************/ +/* SPACE.C ROUTINES */ +/*************************************************************/ +char find_part_free_space(char); +void sort_part_table(char); +char find_ext_free_space(void); +void sort_ext_table(char); + + +/*************************************************************/ +/* INT13.C ROUTINES */ +/*************************************************************/ +char get_disk_info(void); +char read_boot_record(unsigned,unsigned char,unsigned char,unsigned char); /* AC000 */ +char write_boot_record(unsigned,unsigned char); +unsigned verify_tracks(char,char); +char get_drive_parameters(unsigned char); +void DiskIo(union REGS *,union REGS *, struct SREGS *); + +/*************************************************************/ +/* VDISPLAY.C ROUTINES */ +/*************************************************************/ +char volume_display(void); + +/*************************************************************/ +/* TDISPLAY.C ROUTINES */ +/*************************************************************/ +char table_display(void); +char table_drive_letter(void); + +/*************************************************************/ +/* FDISK.C ROUTINES */ +/*************************************************************/ +void main(int,char * []); +void load_logical_drive(char,unsigned char); +void init_partition_tables(void); +char check_valid_environment(void); +void reboot_system(void); +void display_volume_information(void); +void display_partition_information(void); +void volume_delete(void); +void ext_delete(void); +void delete_partition(void); +void dos_delete(void); +void change_active_partition(void); +void volume_create(void); +void ext_create_partition(void); +void input_dos_create(void); +void dos_create_partition(void); +void create_partition(void); +void do_main_menu(void); +void internal_program_error(void); +void reboot(void); + +/*************************************************************/ +/* CONVERT ROUTINES */ +/*************************************************************/ +void get_volume_string(char,char *); /* AN000 */ +unsigned mbytes_to_cylinders(XFLOAT,char); /* AN004 */ +XFLOAT percent_to_cylinders(unsigned,XFLOAT); /* AN000 */ +XFLOAT cylinders_to_mbytes(unsigned,char); /* AN004 */ +unsigned cylinders_to_percent(unsigned,unsigned); /* AN000 */ +char dos_upper(char); /* AN000 */ +char check_yn_input(char); /* AN000 */ +FLAG get_fs_and_vol(char); /* AN000 */ +FLAG check_format(char); /* AN002 */ + +/*************************************************************/ +/* PARSE ROUTINES */ +/*************************************************************/ +char parse_command_line(int,char * []); /* AN000 */ +void parse_init(void); /* AN000 */ +void check_disk_validity(void); /* AN000 */ +void process_switch(void); /* AN000 */ +void parse(union REGS *, union REGS *); /* AN000 */ +void Parse_msg(int,int,unsigned char); /* AN010 */ + + +/*************************************************************/ +/* MESSAGES ROUTINES */ +/*************************************************************/ +char preload_messages(void); /* AN000 */ +void display_msg(int,int,int,int *,char,char); /* AN000 AC014 */ +void sysloadmsg(union REGS *, union REGS *); /* AN000 */ +void sysdispmsg(union REGS *, union REGS *); /* AN000 */ +void sysgetmsg(union REGS *, struct SREGS *, union REGS *); /* AN012 */ +char get_yes_no_values(void); /* AN012 */ + + +/*************************************************************/ +/* C ROUTINES */ +/*************************************************************/ + +int getch(void); +void putch(int); + +int int86x(int, union REGS *, union REGS *, struct SREGS *); +int int86(int, union REGS *, union REGS *); +int intdos(union REGS *, union REGS *); + diff --git a/v4.0/src/CMD/FDISK/TDISPLAY.C b/v4.0/src/CMD/FDISK/TDISPLAY.C new file mode 100644 index 0000000..7cc5e97 --- /dev/null +++ b/v4.0/src/CMD/FDISK/TDISPLAY.C @@ -0,0 +1,134 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "stdio.h" +#include "string.h" +#include "memory.h" + +/* */ +char table_display() + +BEGIN + + +unsigned i; +unsigned x; +unsigned io; +char *ThisPartitionType; +char ThisPartitionLetter[3]; +FLAG partition_found; +char partition_num; + + /* initialize all the inserts to blanks */ + memset(insert,c(' '),4*21); + io = u(0); + + /* Sort the partitions */ + sort_part_table(c(4)); /* AC000 */ + + /* loop thru the partitions, only print stuff if it is there */ + partition_found = FALSE; + partition_num = c(0); /* AC000 */ + + for (i=u(0); i < u(4); i++) /* AC000 */ + BEGIN + + if (part_table[cur_disk][sort[i]].sys_id != uc(0)) /* AC000 */ + BEGIN + + partition_found = TRUE; + + strcpy(ThisPartitionLetter," "); + switch(part_table[cur_disk][sort[i]].sys_id) + BEGIN + case DOSNEW: /* AN000 */ + case DOS16: + case DOS12: + ThisPartitionType = DOS_part; + part_table[cur_disk][sort[i]].drive_letter = table_drive_letter(); /* AN000 */ + sprintf(ThisPartitionLetter,"%c%c", + part_table[cur_disk][sort[i]].drive_letter, + ( part_table[cur_disk][sort[i]].drive_letter == c(' ') ) ? ' ' : ':'); + break; + case EXTENDED: + ThisPartitionType = EXTENDED_part; + break; + case BAD_BLOCK: + ThisPartitionType = BAD_BLOCK_part; + break; + case XENIX1: + ThisPartitionType = XENIX_part; + break; + case XENIX2: + ThisPartitionType = XENIX_part; + break; + case PCIX: + ThisPartitionType = PCIX_part; + break; + default: + ThisPartitionType = NON_DOS_part; + break; + END + + io += sprintf(&insert[io],"%-2.2s%c%c%-7.7s%4.0d%3.0d%%", + ThisPartitionLetter, + partition_num+'1', + (part_table[cur_disk][sort[i]].boot_ind == uc(0x80)) ? 'A' : ' ', + ThisPartitionType, + part_table[cur_disk][sort[i]].mbytes_used, + part_table[cur_disk][sort[i]].percent_used); + + partition_num++; + + END + + END + + /* Do a clearscreen to erase previous data */ + clear_screen(u(8),u(0),u(12),u(79)); /* AC000 */ + + if (partition_found) display(menu_14); + else display(status_8); + + /* Return true if partitions exist, false otherwise */ + if (partition_found) return(TRUE); + + return(FALSE); + +END + +/* */ +char table_drive_letter() + +BEGIN +char drive_letter; + + /* Put in drive letter in display */ + if (cur_disk == c(0)) /* AC000 */ + BEGIN + /* There is a primary partition on 80h, so drive C: */ + drive_letter = c('C'); /* AC000 */ + END + else + BEGIN + /* We are on drive 81h, so assume D: */ + drive_letter = c('D'); /* AC000 */ + + /* See if primary exists on 80h drive */ + /* First, set cur_drive to 0 */ + cur_disk = c(0); /* AC000 */ + + /* Check for primary on drive 80h */ + if (!(find_partition_type(uc(DOS12)) || find_partition_type(uc(DOS16)) || find_partition_type(uc(DOSNEW)))) /* AC000 */ + BEGIN + drive_letter = c('C'); /* AC000 */ + END + /* restore cur_disk to normal */ + cur_disk = c(1); /* AC000 */ + END + return(drive_letter); +END + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/TEST.H b/v4.0/src/CMD/FDISK/TEST.H new file mode 100644 index 0000000..ef12d9e --- /dev/null +++ b/v4.0/src/CMD/FDISK/TEST.H @@ -0,0 +1,26 @@ +test() + +BEGIN + +int i; +int x; + + for (i=0;i<24;i++) + BEGIN + for (x=0;x <2; x++) + BEGIN + ext_part_entry[i][x].boot_ind = 0; + ext_part_entry[i][x].start_head = 0; + ext_part_entry[i][x].start_sector = 0; + ext_part_entry[i][x].start_cyl = 0; + ext_part_entry[i][x].sys_id = 0; + ext_part_entry[i][x].end_head = 0; + ext_part_entry[i][x].end_sector = 0; + ext_part_entry[i][x].end_cyl = 0; + ext_part_entry[i][x].rel_sec = 0; + ext_part_entry[i][x].num_sec = 0; + END + END + return; +END + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/VDISPLAY.C b/v4.0/src/CMD/FDISK/VDISPLAY.C new file mode 100644 index 0000000..41b6285 --- /dev/null +++ b/v4.0/src/CMD/FDISK/VDISPLAY.C @@ -0,0 +1,180 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "subtype.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "string.h" +#include "stdio.h" +#include "memory.h" + +/* */ +char volume_display() + +BEGIN + +unsigned i; +unsigned x; +char drive_found; +char drive_letter; +char drive_num; +char temp; +char first_display; +char second_display; +char third_display; +char fourth_display; +unsigned insert_offset; + + first_display = FALSE; + second_display = FALSE; + third_display = FALSE; + fourth_display = FALSE; + + /* See what the starting drive letter is */ + drive_letter = c(SEA); /* AC000 */ + + /* See if primary on drive 1 */ + temp = cur_disk; + cur_disk = c(0); /* AC000 */ + if ( (find_partition_type(uc(DOS12))) || + (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW)))) /* AC000 */ + BEGIN + /* There is a Primary partition on drive 1, so increment for first logical drive */ + drive_letter++; + END + cur_disk = temp; + + /* See if there is a second drive */ + if (number_of_drives == uc(2)) /* AC000 */ + BEGIN + + /* Go see if DOS partition on drive 2 */ + temp = cur_disk; + cur_disk = c(1); /* AC000 */ + if ( (find_partition_type(uc(DOS12))) || + (find_partition_type(uc(DOS16))) || + (find_partition_type(uc(DOSNEW)))) /*AC000*/ + BEGIN + + /* There is a Primary partition on drive 2, so increment for first logical drive */ + drive_letter++; + END + /* Are we on drive 2? If so, we got to find all the drives on drive 1 */ + if (temp == c(1)) /* AC000 */ + BEGIN + /* Next, we need to see what is on drive 1 */ + for (i=u(0); i < u(23); i++) /* AC000 */ + BEGIN + /* See if there is a logical drive we understand in PC-DOS land */ + if ( (ext_table[0][i].sys_id == uc(DOS12)) || + (ext_table[0][i].sys_id == uc(DOS16)) || + (ext_table[0][i].sys_id == uc(DOSNEW)) ) /* AC000 */ + BEGIN + /* Found one, so kick up the first available drive letter */ + drive_letter++; + END + END + END + + /* Reset the cur_drive to where it was */ + cur_disk = temp; + END + + + + + /* loop thru the partitions, only print stuff if it is there */ + + /* Get the drives in order by location on disk */ + sort_ext_table(c(23)); /* AC000 */ + + /* initialize all the inserts to blanks */ + memset(insert,c(' '),(24*29)); + + drive_num = c(0); /* AC000 */ + drive_found = FALSE; + first_display = TRUE; + insert_offset = 0; + + for (i=u(0); i < u(23); i++) /* AC000 */ + BEGIN + + /* See if entry exists */ + if ( (ext_table[cur_disk][sort[i]].sys_id == uc(DOS12)) || + (ext_table[cur_disk][sort[i]].sys_id == uc(DOS16)) || + (ext_table[cur_disk][sort[i]].sys_id == uc(DOSNEW)) ) /* AC000 */ + BEGIN + + /* We found one, now get the info */ + drive_found = TRUE; + + /* Get the drive letter - make sure it is Z: or less*/ + /* Put it in the message, and set it up for next time */ + if (drive_letter > c('Z')) + ext_table[cur_disk][sort[i]].drive_letter = c(' '); + else ext_table[cur_disk][sort[i]].drive_letter = drive_letter; + + insert_offset += sprintf(&insert[insert_offset],"%c%c%-11.11s%4.0d%-8.8s%3.0d%%", + ext_table[cur_disk][sort[i]].drive_letter, + ( ext_table[cur_disk][sort[i]].drive_letter == c(' ') ) ? ' ' : ':', + ext_table[cur_disk][sort[i]].vol_label, + ext_table[cur_disk][sort[i]].mbytes_used, + ext_table[cur_disk][sort[i]].system, + ext_table[cur_disk][sort[i]].percent_used ); + + + drive_letter++; + drive_num++; + + END + END + + /* Display the column of drives */ + if (drive_found) + BEGIN + + clear_screen(u(2),u(0),u(15),u(79)); /* AC000 */ + + if ( drive_num > 0 ) + BEGIN + pinsert = &insert[0]; + display(menu_19); + END + + if ( drive_num > 6 ) + BEGIN + pinsert = &insert[6*29]; + display(menu_43); + END + + if ( drive_num > 12 ) + BEGIN + pinsert = &insert[12*29]; + display(menu_20); + END + + if ( drive_num > 18 ) + BEGIN + pinsert = &insert[18*29]; + display(menu_44); + END + pinsert = &insert[0]; + END + else + BEGIN + /* Didn't find any */ + if (first_display) + BEGIN + /* Wipe out display and put up message */ + clear_screen(u(2),u(0),u(15),u(79)); /* AC000 */ + display(status_9); + END + END + /* Return the highest drive letter found */ + drive_letter--; + return(drive_letter); + +END + + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/VIDEO.C b/v4.0/src/CMD/FDISK/VIDEO.C new file mode 100644 index 0000000..750a94a --- /dev/null +++ b/v4.0/src/CMD/FDISK/VIDEO.C @@ -0,0 +1,146 @@ + +#include "dos.h" /* AN000 */ +#include "fdisk.h" /* AN000 */ +#include "extern.h" /* AN000 */ +#include "doscall.h" /* AN000 */ +#include "fdiskmsg.h" /* AN000 */ +#include "subtype.h" + +/* */ + +void clear_screen(TopRow,LeftCol,BotRow,RightCol) + +unsigned TopRow; +unsigned LeftCol; +unsigned BotRow; +unsigned RightCol; + +BEGIN + +char attribute; +char *attribute_ptr = &attribute; + + if (mono_flag == TRUE) /* AN006 */ + attribute = GRAY_ON_BLACK; /* AN006 */ + else /* AN006 */ + attribute = WHITE_ON_BLUE; /* AC000 */ + VIOSCROLLUP(TopRow,LeftCol,BotRow,RightCol,u(0),attribute_ptr,u(0)); /* AC000 */ + return; +END + + + + + +/* */ +/* */ +/****************************************************************************/ +/* Initializes the screen and stores the lower right hand corner */ +/* of the screen in the global variable LowerRightHandCorner. This */ +/* is which is used for screen clears. If the screen is in grahpics mode, */ +/* it is changed to BW 40x25. This procedure is only called once at program*/ +/* start. Also saves the current screen */ +/****************************************************************************/ +/* */ + + +void init_video_information() + +BEGIN + mono_flag = FALSE; /* AN006 */ + + /* Get the current video state */ + regs.h.ah = uc(CURRENT_VIDEO_STATE); /* AC000 */ + int86((int)VIDEO,®s,®s); /* AC000 */ + + /* Save the mode and display page */ + video_mode = regs.h.al; + display_page = regs.h.bh; + + get_video_attribute(); /* AN006 */ + + BEGIN + /* assume color mode */ + regs.h.al = uc(Color80_25); /* AC000 */ + + /* See if we are in MONOCHROME mode */ + if ((video_mode == uc(MONO80_25)) || (video_mode == uc(MONO80_25A))) /* AC000 AC006 */ + BEGIN + + /* Nope,set to BW80x25*/ + regs.h.al = uc(BW80_25); /* AC000 */ + mono_flag = TRUE; /* AN006 */ + END + + /* go set the new mode */ + regs.h.ah = uc(SET_MODE); /* AC000 */ + int86((int)VIDEO,®s,®s); /* AC000 */ + END + + /* Set the display page */ + regs.h.ah = uc(SET_ACTIVE_DISPLAY_PAGE); /* AC000 */ + regs.h.al = uc(0); /* AC000 */ + int86((int)VIDEO,®s,®s); /* AC000 */ + + return; +END + +/* */ +/* */ +/* Resets the video mode to the original value */ +/* */ + +void reset_video_information() + +BEGIN + +char *attribute_ptr = &video_attribute; /* AN006 */ + + /* Clear display with colors that were present when FDISK was invoked */ + VIOSCROLLUP(u(0),u(0),u(24),u(79),u(0),attribute_ptr,u(0)); /* AN006 */ + + /* Reset the video mode */ + regs.h.ah = SET_MODE; + regs.h.al = video_mode; + int86((int)VIDEO,®s,®s); /* AC000 */ + + /* Set the page */ + regs.h.ah = SET_PAGE; + regs.h.al = display_page; + int86((int)VIDEO,®s,®s); /* AC000 */ + return; + +END + +/******************************************************************************/ +/*Routine name: GET_VIDEO_ATTRIBUTE */ +/******************************************************************************/ +/* */ +/*Description: This routine will invoke interrupt 10 function 08h to */ +/* get the current attributes at the cursor postition in order */ +/* to restore the correct colors when returning out of FDISK. */ +/* */ +/*Called Procedures: none */ +/* */ +/* */ +/*Change History: Created 3/11/88 DRM */ +/* */ +/*Input: None */ +/* */ +/*Output: None */ +/* */ +/******************************************************************************/ + +void get_video_attribute() /* AN006 */ + +BEGIN /* AN006 */ + + /* Get current attributes */ + regs.h.ah = CURRENT_VIDEO_ATTRIBUTE; /* AN006 */ + regs.h.bh = display_page; /* AN006 */ + int86((int)VIDEO,®s,®s); /* AN006 */ + video_attribute = regs.h.ah; /* AN006 */ + return; /* AN006 */ + +END /* AN006 */ + diff --git a/v4.0/src/CMD/FDISK/_MSGRET.ASM b/v4.0/src/CMD/FDISK/_MSGRET.ASM new file mode 100644 index 0000000..c19108f --- /dev/null +++ b/v4.0/src/CMD/FDISK/_MSGRET.ASM @@ -0,0 +1,263 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 message retriever +; +; CALLING FORMAT: +; msgret(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AC010; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AC010; + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' ;AC010; +_TEXT ENDS ;AC010; +_DATA SEGMENT WORD PUBLIC 'DATA' ;AC010; +_DATA ENDS ;AC010; +CONST SEGMENT WORD PUBLIC 'CONST' ;AC010; +CONST ENDS ;AC010; +_BSS SEGMENT WORD PUBLIC 'BSS' ;AC010; +_BSS ENDS ;AC010; + +DGROUP GROUP CONST, _BSS, _DATA ;AC010; + ASSUME CS: DGROUP, DS: DGROUP, SS: DGROUP, ES: NOTHING ;AC010; + + public data_sysloadmsg ;AC010; + public data_sysdispmsg ;AC010; + public data_sysgetmsg ;AC010; + +_DATA SEGMENT ;AC010; + + MSG_SERVICES ;AC010; + MSG_SERVICES ;AC010; + MSG_SERVICES ;AC010; + MSG_SERVICES ;AC010; ;AC010; + + +data_sysloadmsg proc far + + push bp ; save user's base pointer ;AC010; + mov bp,sp ; set bp to current sp ;AC010; + push di ; save some registers ;AC010; + push si ;AC010; + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) ;AC010; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AC010; + push ax ; the di value from inregs is now on stack ;AC010; + + mov ax,[di+00] ; get inregs.x.ax ;AC010; + mov bx,[di+02] ; get inregs.x.bx ;AC010; + mov cx,[di+04] ; get inregs.x.cx ;AC010; + mov dx,[di+06] ; get inregs.x.dx ;AC010; + mov si,[di+08] ; get inregs.x.si ;AC010; + pop di ; get inregs.x.di from stack ;AC010; + + push bp ; save base pointer ;AC010; + +;------------------------------------------------------------------- + + call sysloadmsg ; call the message retriever ;AC010; + +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AC010; + push di ; the di value from call is now on stack ;AC010; + mov di,[bp+6+4] ; fix di (arg 1) ;AC010; + + mov [di+00],ax ; load outregs.x.ax ;AC010; + mov [di+02],bx ; load outregs.x.bx ;AC010; + mov [di+04],cx ; load outregs.x.cx ;AC010; + mov [di+06],dx ; load outregs.x.dx ;AC010; + mov [di+08],si ; load outregs.x.si ;AC010; + + lahf ; get flags into ax ;AC010; + mov al,ah ; move into low byte ;AC010; + mov [di+0ch],ax ; load outregs.x.cflag ;AC010; + + pop ax ; get di from stack ;AC010; + mov [di+0ah],ax ; load outregs.x.di ;AC010; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AC010; + pop di ;AC010; + mov sp,bp ; restore sp ;AC010; + pop bp ; restore user's bp ;AC010; + ret + +data_sysloadmsg endp ;AC010; + + +data_sysdispmsg proc far ;AC010; + + push bp ; save user's base pointer ;AC010; + mov bp,sp ; set bp to current sp ;AC010; + push di ; save some registers ;AC010; + push si ;AC010; + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) ;AC010; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AC010; + push ax ; the di value from inregs is now on stack ;AC010; + + mov ax,[di+00] ; get inregs.x.ax ;AC010; + mov bx,[di+02] ; get inregs.x.bx ;AC010; + mov cx,[di+04] ; get inregs.x.cx ;AC010; + mov dx,[di+06] ; get inregs.x.dx ;AC010; + mov si,[di+08] ; get inregs.x.si ;AC010; + pop di ; get inregs.x.di from stack ;AC010; + + push bp ; save base pointer ;AC010; + +;------------------------------------------------------------------- + + call sysdispmsg ;AC010; + +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AC010; + push di ; the di value from call is now on stack ;AC010; + mov di,[bp+6+4] ; fix di (arg 1) ;AC010; + + mov [di+00],ax ; load outregs.x.ax ;AC010; + mov [di+02],bx ; load outregs.x.bx ;AC010; + mov [di+04],cx ; load outregs.x.cx ;AC010; + mov [di+06],dx ; load outregs.x.dx ;AC010; + mov [di+08],si ; load outregs.x.si ;AC010; + + lahf ; get flags into ax ;AC010; + mov al,ah ; move into low byte ;AC010; + mov [di+0ch],ax ; load outregs.x.cflag ;AC010; + + pop ax ; get di from stack ;AC010; + mov [di+0ah],ax ; load outregs.x.di ;AC010; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AC010; + pop di ;AC010; + mov sp,bp ; restore sp ;AC010; + pop bp ; restore user's bp ;AC010; + ret ;AC010; + +data_sysdispmsg endp ;AC010; + + +data_sysgetmsg proc far ;AC010; + + push bp ; save user's base pointer ;AC010; + mov bp,sp ; set bp to current sp ;AC010; + push di ; save some registers ;AC010; + push si ;AC010; + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) ;AC010; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AC010; + push ax ; the di value from inregs is now on stack ;AC010; + + mov ax,[di+00] ; get inregs.x.ax ;AC010; + mov bx,[di+02] ; get inregs.x.bx ;AC010; + mov cx,[di+04] ; get inregs.x.cx ;AC010; + mov dx,[di+06] ; get inregs.x.dx ;AC010; + mov si,[di+08] ; get inregs.x.si ;AC010; + pop di ; get inregs.x.di from stack ;AC010; + + push bp ; save base pointer ;AC010; + +;------------------------------------------------------------------- + + call sysgetmsg ; call the message retriever ;AC010; + +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AC010; + push di ; the di value from call is now on stack ;AC010; + mov di,[bp+6+4] ; fix di (arg 1) ;AC010; + + push ax ; save ax ;AC010; + mov [di+00],es ; load segregs.es ;AC010; + mov [di+06],ds ; load outregs.ds ;AC010; + pop ax ; restore ax ;AC010; + + pop di ; restore di ;AC010; + push di ; save it ;AC010; + mov di,[bp+8+4] ; fix di (arg 2) ;AC010; + mov [di+00],ax ; load outregs.x.ax ;AC010; + mov [di+02],bx ; load outregs.x.bx ;AC010; + mov [di+04],cx ; load outregs.x.cx ;AC010; + mov [di+06],dx ; load outregs.x.dx ;AC010; + mov [di+08],si ; load outregs.x.si ;AC010; + + lahf ; get flags into ax ;AC010; + mov al,ah ; move into low byte ;AC010; + mov [di+0ch],ax ; load outregs.x.cflag ;AC010; + + pop ax ; get di from stack ;AC010; + mov [di+0ah],ax ; load outregs.x.di ;AC010; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AC010; + pop di ;AC010; + mov sp,bp ; restore sp ;AC010; + pop bp ; restore user's bp ;AC010; + ret ;AC010; + +data_sysgetmsg endp ;AC010; + + +_DATA ends ; end code segment ;AC010; + +_TEXT SEGMENT ;AC010; + + assume cs:_TEXT ;AC010; + + public _sysdispmsg ;AC010; + public _sysloadmsg ;AC010; + public _sysgetmsg ;AC010; + +_sysdispmsg proc near ;AC010; + call data_sysdispmsg ;AC010; + ret ;AC010; +_sysdispmsg endp ;AC010; + +_sysloadmsg proc near ;AC010; + call data_sysloadmsg ;AC010; + ret ;AC010; +_sysloadmsg endp ;AC010; + +_sysgetmsg proc near ;AC010; + call data_sysgetmsg ;AC010; + ret ;AC010; +_sysgetmsg endp ;AC010; + +_TEXT ENDS ;AC010; + end ;AC010; + + \ No newline at end of file diff --git a/v4.0/src/CMD/FDISK/_PARSE.ASM b/v4.0/src/CMD/FDISK/_PARSE.ASM new file mode 100644 index 0000000..9e308af --- /dev/null +++ b/v4.0/src/CMD/FDISK/_PARSE.ASM @@ -0,0 +1,165 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 parser +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse + +;------------------------------------------------------------------- +FarSW equ 0 ; make sysparse be a NEAR proc +TimeSW equ 0 ; Check time format +FileSW equ 0 ; Check file specification +CAPSW equ 0 ; Perform CAPS if specified +CmpxSW equ 0 ; Check complex list +NumSW equ 1 ; Check numeric value +KeySW equ 0 ; Support keywords +SwSW equ 1 ; Support switches +Val1SW equ 1 ; Support value definition 1 +Val2SW equ 1 ; Support value definition 2 +Val3SW equ 0 ; Support value definition 3 +DrvSW equ 0 ; Support drive only format +QusSW equ 0 ; Support quoted string format +;------------------------------------------------------------------- + + + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + + +DGROUP GROUP CONST, _BSS, _DATA + + +_DATA segment word public 'DATA' + + assume cs:DGROUP + assume ss:dgroup + + public SysParse + +;------------------------------------------------------------------- +.xlist +include parse.asm ; include the parser +.list +;------------------------------------------------------------------- + + public CallParser +CallParser proc far + + push ds + PUSH ES + + push cs + pop ds + assume ds:DGROUP + + push cs + pop es + assume es:DGROUP + + nop + + call SysParse + + POP ES + pop ds + + ret + +CallParser endp + + + +_DATA ends + +_TEXT segment byte public 'CODE' + + ASSUME CS:_TEXT + ASSUME DS:DGROUP + ASSUME ES:NOTHING + ASSUME SS:DGROUP + +_parse proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + call CallParser ; call the parser + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + xor ax,ax ; clear ax + lahf ; get flags into ax + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_parse endp + +_TEXT ends ; end code segment + end + diff --git a/v4.0/src/CMD/FILESYS/FILESYS.C b/v4.0/src/CMD/FILESYS/FILESYS.C new file mode 100644 index 0000000..9ae7f41 --- /dev/null +++ b/v4.0/src/CMD/FILESYS/FILESYS.C @@ -0,0 +1,922 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| FILESYS provides an interface to IFSFUNC to allow assignment of | +| logical drive letters to various devices. | +| | +| FILESYS also allows the user to cancel the attach for a drive | +| or device or list the currently attched devices. | +| | +| | +| ALIAS provides an interface to IFSFUNC that allows the user | +| to cause automatic substitution of an alternate filename string | +| for a pseudo-device driver name. | +| | +| PROGRAM PROPERTY OF Microsoft, Copyright 1988 Microsoft Corp. | +| | +| INPUT: | +| Command line from user. | +| | +| OUTPUT: | +| Attached device, detached device, or list of attached devices. | +| | ++----------------------------------------------------------------------*/ + +#include "stdio.h" /* ;an000; */ +#include "stdlib.h" /* ;an000; */ +#include "dos.h" /* allows use of intdos calls */ /* ;an000; */ +#include "string.h" /* allows use of str* calls */ /* ;an000; */ +#include "parse.h" /* allows use of parser */ /* ;an000; */ +#include "msgret.h" /* allows use of msg ret */ /* ;an000; */ + /* ;an000; */ +#define ZERO 0 /* ;an002; */ +#define NULL 0 /* ;an000; */ +#define FALSE 0 /* ;an000; */ +#define TRUE 1 /* ;an000; */ + /* ;an000; */ +#define MORE_DEVICES 0x0000 /* more devices in list */ /* ;an000; */ +#define NO_MORE_FILES 0x0012 /* no more files DOS error */ /* ;an000; */ +#define INVALID_FUNCTION_NUM 0x0001 /* invalid function - Get RDR list */ /* ;an000; */ + /* ;an000; */ +#define IFS_DEVICE 0X01 /* IFS device type */ /* ;an000; */ +#define IFS_DRIVE 0X02 /* IFS drive type */ /* ;an000; */ +#define NET_PRINTER 0x03 /* network printer device type */ /* ;an000; */ +#define NET_DRIVE 0x04 /* network drive device type */ /* ;an000; */ + /* ;an000; */ +#define GET_PAUSE_STATUS 0x5f00 /* DOS call to get pause status */ /* ;an000; */ +#define GET_REDIR_LIST_ENTRY 0x5f02 /* DOS call to get redir entry */ /* ;an000; */ +#define REDIRECT_DEVICE 0x5f03 /* DOS call to redir device */ /* ;an000; */ +#define CANCEL_REDIRECTION 0x5f04 /* DOS call to cancel redirection */ /* ;an000; */ +#define GET_ATTACH_LIST 0x5f06 /* DOS call to get attached devices*/ /* ;an000; */ +#define GET_EXTENDED_ERROR 0x5900 /* DOS call to get extended error */ /* ;an000; */ + /* ;an000; */ +#define CARRY_FLAG 0x0001 /* mask for carry flag */ /* ;an000; */ +#define PARITY_FLAG 0x0004 /* mask for parity flag */ /* ;an000; */ +#define ACARRY_FLAG 0x0010 /* mask for aux carry flag */ /* ;an000; */ +#define ZERO_FLAG 0x0040 /* mask for zero flag */ /* ;an000; */ +#define SIGN_FLAG 0x0080 /* mask for sign flag */ /* ;an000; */ +#define TRAP_FLAG 0x0100 /* mask for trap flag */ /* ;an000; */ +#define INTERRUPT_FLAG 0x0200 /* mask for interrupt flag */ /* ;an000; */ +#define DIRECTION_FLAG 0x0400 /* mask for direction flag */ /* ;an000; */ +#define OVERFLOW_FLAG 0x0800 /* mask for overflow flag */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* */ /* ;an000; */ +/* Define subroutines */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ +void main(int, char *[]); /* ;an000; */ +void parse_init(void); /* ;an000; */ +void device_attach(int, char *, char *, char *); /* ;an000; */ +void device_detach(char *); /* ;an000; */ +void fs_status(char *); /* ;an000; */ +int get_pause_stat(unsigned char); /* ;an000; */ +void fs_error(int); /* ;an000; */ +void fs_build_print_message(int, char *, char *, char *); /* ;an000; */ +void string_build(void); /* ;an000; */ +void check_pause_status(unsigned char, int *, int *, int *); /* ;an000; */ +void print_status(int, int, int, int *); /* ;an000; */ +void Sub0_Message(int,int,unsigned char); /* ;an000; */ +void fs_strcpy(char *, char far *); /* ;an000; */ +int fs_strlen(char far *); /* ;an000; */ + /* ;an000; */ +extern void sysloadmsg(union REGS *, union REGS *); /* ;an000; */ +extern void sysdispmsg(union REGS *, union REGS *); /* ;an000; */ +extern void parse(union REGS *, union REGS *); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +struct p_parms p_p; /* ;an000; */ +struct p_parms p_p1; /* ;an000; */ + /* ;an000; */ +struct p_parmsx p_px; /* ;an000; */ +struct p_parmsx p_px1; /* ;an000; */ + /* ;an000; */ +struct p_control_blk p_con1; /* ;an000; */ +struct p_control_blk p_con1a; /* ;an000; */ +struct p_control_blk p_con2; /* ;an000; */ +struct p_control_blk p_con3; /* ;an000; */ +struct p_control_blk p_con4; /* ;an000; */ + /* ;an000; */ +struct p_control_blk p_swt1; /* ;an000; */ + /* ;an000; */ +struct p_result_blk p_result1; /* ;an000; */ +struct p_result_blk_D p_resultD; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +struct p_value_blk p_noval; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +char cmd_line[128]; /* ;an000; */ +char far *cmdline; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + struct sublistx /* sublist for replaceable parms. */ /* ;an000; */ + { /* ;an000; */ + unsigned char size; /* sublist size */ /* ;an000; */ + unsigned char reserved; /* reserved for future growth */ /* ;an000; */ + unsigned far *value; /* pointer to replaceable parm */ /* ;an000; */ + unsigned char id; /* type of replaceable parm */ /* ;an000; */ + unsigned char flags; /* how parm is to be displayed */ /* ;an000; */ + unsigned char max_width; /* max width of replaceable field */ /* ;an000; */ + unsigned char min_width; /* min width of replaceable field */ /* ;an000; */ + unsigned char pad_char; /* pad character for replaceable field */ /* ;an000; */ + } sublist[4]; /* end of sublis */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +struct /* ;an000; */ + { /* ;an000; */ + char *target_fs_name; /* ;an000; */ + unsigned int target_count; /* ;an000; */ + char target_string[128]; /* ;an000; */ + } GAL_Target; /* ;an000; */ + /* ;an000; */ +struct /* ;an000; */ + { /* ;an000; */ + char device_string[9]; /* ;an000; */ + } GAL_Device; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +struct /* ;an000; */ + { /* ;an000; */ + char *attach_system; /* pointer to filesys arg */ /* ;an000; */ + unsigned int attach_parms_num; /* number of additional parms */ /* ;an000; */ + char attach_addl_parms[128];/* additional parms */ /* ;an000; */ + /* ;an000; */ + } Attach_block; /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| define register variables | ++----------------------------------------------------------------------*/ +union REGS inregs, outregs; /* ;an000; */ +struct SREGS segregs; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| main - filesys and alias main routine | +| | +| handle parsing command line and calling all other routines | +| | ++----------------------------------------------------------------------*/ + /* ;an000; */ +void main(argc,argv) /* ;an000; */ + /* ;an000; */ +int argc; /* number of arguments passed on command line */ /* ;an000; */ +char *argv[]; /* array of pointer to arguments */ /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ +/*----------------------------------------------------------------------+ +| define some local variables | ++----------------------------------------------------------------------*/ + int arg_index; /* index used for stepping through args */ /* ;an000; */ + int more_arguments; /* flag used while looping calls to parser */ /* ;an000; */ + int i; /* loop counter */ /* ;an000; */ + int detach_flag; /* signal to detach device */ /* ;an000; */ + int good_parse; /* signal a good parse occurred */ /* ;an000; */ + /* ;an000; */ + char *string_ptr; /* pointer to a string */ /* ;an000; */ + char file_spec_buf[64]; /* buffer to hold drive or device name */ /* ;an000; */ + char fs_name_buf[64]; /* buffer to hold file system name */ /* ;an000; */ + char string_buf[128]; /* buffer to hold device parms */ /* ;an000; */ + char drive_letter; /* drive letter to attach/detach */ /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| get started by calling the parser | ++----------------------------------------------------------------------*/ + /* ;an000; */ + sysloadmsg(&inregs, &outregs); /* load the messages */ /* ;an000; */ + if ((outregs.x.cflag & CARRY_FLAG) == CARRY_FLAG) /* error? */ /* ;an000; */ + sysdispmsg(&outregs,&outregs); /* tell user error and exit */ /* ;an000; */ + else /* execute program */ /* ;an000; */ + { /* ;an000; */ + inregs.h.ah = (unsigned char) 0x62; /* ;an000; */ + intdosx(&inregs, &inregs, &segregs); /* ;an000; */ + /* ;an000; */ + FP_OFF(cmdline) = 0x81; /* ;an000; */ + FP_SEG(cmdline) = inregs.x.bx; /* ;an000; */ + /* ;an000; */ + i = 0; /* ;an000; */ + while ( *cmdline != (char) '\x0d' ) cmd_line[i++] = *cmdline++; /* ;an000; */ + cmd_line[i++] = (char) '\x0d'; /* ;an000; */ + cmd_line[i++] = (char) '\0'; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + file_spec_buf[0] = NULL; /* ;an000; */ + string_ptr = Attach_block.attach_addl_parms; /* ;an000; */ + detach_flag = FALSE; /* ;an000; */ + good_parse = TRUE; /* ;an000; */ + /* ;an000; */ + parse_init(); /* ;an000; */ + inregs.x.si = (unsigned)cmd_line; /* ;an000; */ + inregs.x.cx = (unsigned)0; /* ;an000; */ + inregs.x.dx = (unsigned)0; /* ;an000; */ + inregs.x.di = (unsigned)&p_p; /* point to drive spec block */ /* ;an000; */ + /* ;an000; */ + i = 0; /* ;an000; */ + parse(&inregs,&outregs); /* ;an000; */ + if (outregs.x.ax != p_no_error) /* ;an000; */ + { /* ;an000; */ + inregs.x.si = (unsigned)cmd_line; /* ;an000; */ + inregs.x.cx = (unsigned)0; /* ;an000; */ + inregs.x.dx = (unsigned)0; /* ;an000; */ + inregs.x.di = (unsigned)&p_p1; /* point to simple string block */ /* ;an000; */ + parse(&inregs,&outregs); /* ;an000; */ + } /* ;an000; */ + while ((outregs.x.ax == p_no_error) && (good_parse == TRUE)) /* ;an000; */ + { /* ;an000; */ + i++; /* ;an000; */ + if (p_resultD.D_Type == p_drive) /* ;an000; */ + { /* ;an000; */ + drive_letter = (char) p_resultD.D_Res_Drive + ('A'-1); /* ;an000; */ + file_spec_buf[0] = drive_letter; /* ;an000; */ + file_spec_buf[1] = (char) ':'; /* ;an000; */ + file_spec_buf[2] = (char) '\0'; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if ((p_result1.P_Type == p_string) && ( i == 1)) /* ;an000; */ + fs_strcpy(file_spec_buf,p_result1.p_result_buff); /* ;an000; */ + /* ;an000; */ + if ((p_result1.P_Type == p_string) && (i == 2)) /* ;an000; */ + fs_strcpy(fs_name_buf,p_result1.p_result_buff); /* ;an000; */ + /* ;an000; */ + if ((p_result1.P_Type == p_string) && (i > 2)) /* ;an000; */ + { /* ;an000; */ + fs_strcpy(string_ptr,p_result1.p_result_buff); /* ;an000; */ + string_ptr += fs_strlen(p_result1.p_result_buff); /* ;an000; */ + string_ptr++; /* ;an000; */ + } /* ;an000; */ + if (p_result1.P_SYNONYM_Ptr == (unsigned int)p_swt1.p_keyorsw) /* ;an000; */ + { /* ;an000; */ + if (i != 2) /* switch in wrong place */ /* ;an000; */ + { /* ;an000; */ + outregs.x.ax = p_syntax; /* signal error type */ /* ;an000; */ + good_parse = FALSE; /* ;an000; */ + } /* ;an000; */ + detach_flag = TRUE; /* ;an000; */ + } /* ;an000; */ + if (good_parse == TRUE) /* ;an000; */ + parse(&outregs,&outregs); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (outregs.x.ax != p_rc_eol) /* an000; dms; parse error */ /* ;an000; */ + { /* ;an000; */ + Sub0_Message(outregs.x.ax,STDOUT,Parse_Err_Class); /* an000; dms; tell user error */ /* ;an000; */ + exit(1); /* an000; dms; exit program */ /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* which routine to invoke? */ /* ;an000; */ + switch (i) /* ;an000; */ + { /* ;an000; */ + case 0: fs_status(file_spec_buf); /* an000; dms; no parms - status */ /* ;an000; */ + break; /* ;an000; */ + /* ;an000; */ + case 1: fs_status(file_spec_buf); /* an000; dms; 1 parm - selective status*/ /* ;an000; */ + break; /* ;an000; */ + /* ;an000; */ + default : if ((i == 2) && (detach_flag == TRUE)) /* an000; dms; detach request? */ /* ;an000; */ + device_detach(file_spec_buf); /* an000; dms; yes */ /* ;an000; */ + else /* ;an000; */ + device_attach(i,file_spec_buf,fs_name_buf,string_buf); /*an000; dms; attach request */ /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + } /* end FILESYS MAIN */ /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| SUBROUTINE NAME: PARSE_INIT | +| | +| SUBROUTINE FUNCTION: | +| | +| This routine is called by the FILESYS MAIN routine to initialize| +| the parser data structures. | +| | +| INPUT: | +| none | +| | +| OUTPUT: | +| properly initialized parser control blocks | +| | ++----------------------------------------------------------------------*/ +void parse_init() /* ;an000; */ + { /* ;an000; */ + p_p.p_parmsx_address = &p_px; /* address of extended parm list */ /* ;an000; */ + p_p.p_num_extra = 0; /* ;an000; */ + /* ;an000; */ + p_p1.p_parmsx_address = &p_px1; /* address of extended parm list */ /* ;an000; */ + p_p1.p_num_extra = 0; /* ;an000; */ + /* ;an000; */ + p_px.p_minp = 0; /* ;an000; */ + p_px.p_maxp = 4; /* ;an000; */ + p_px.p_control[0] = &p_con1; /* ;an000; */ + p_px.p_control[1] = &p_con2; /* ;an000; */ + p_px.p_control[2] = &p_con3; /* ;an000; */ + p_px.p_control[3] = &p_con4; /* ;an000; */ + p_px.p_maxswitch = 1; /* ;an000; */ + p_px.p_switch[0] = &p_swt1; /* ;an000; */ + p_px.p_maxkeyword = 0; /* ;an000; */ + /* ;an000; */ + p_px1.p_minp = 0; /* ;an000; */ + p_px1.p_maxp = 4; /* ;an000; */ + p_px1.p_control[0] = &p_con1a; /* ;an000; */ + p_px1.p_control[1] = &p_con2; /* ;an000; */ + p_px1.p_control[2] = &p_con3; /* ;an000; */ + p_px1.p_control[3] = &p_con4; /* ;an000; */ + p_px1.p_maxswitch = 1; /* ;an000; */ + p_px1.p_switch[0] = &p_swt1; /* ;an000; */ + p_px1.p_maxkeyword = 0; /* ;an000; */ + /* ;an000; */ + p_con1.p_match_flag = p_drv_only+ p_ig_colon+ p_optional; /* ;an000; */ + p_con1.p_function_flag = p_cap_char+ p_rm_colon; /* ;an000; */ + p_con1.p_result_buf = (unsigned int)&p_resultD; /* ;an000; */ + p_con1.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con1.p_nid = 0; /* ;an000; */ + p_con1.p_keyorsw[0] = 0; /* ;an000; */ + /* ;an000; */ + p_con1a.p_match_flag = p_simple_s+ p_optional; /* ;an000; */ + p_con1a.p_function_flag = p_cap_char; /* ;an000; */ + p_con1a.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_con1a.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con1a.p_nid = 0; /* ;an000; */ + p_con1a.p_keyorsw[0] = 0; /* ;an000; */ + /* ;an000; */ + p_con2.p_match_flag = p_simple_s+ p_optional; /* ;an000; */ + p_con2.p_function_flag = p_cap_char; /* ;an000; */ + p_con2.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_con2.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con2.p_nid = 0; /* ;an000; */ + p_con2.p_keyorsw[0] = 0; /* ;an000; */ + /* ;an000; */ + p_con3.p_match_flag = p_simple_s+ p_optional; /* ;an000; */ + p_con3.p_function_flag = p_cap_char; /* ;an000; */ + p_con3.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_con3.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con3.p_nid = 0; /* ;an000; */ + p_con3.p_keyorsw[0] = 0; /* ;an000; */ + /* ;an000; */ + p_con4.p_match_flag = p_simple_s+ p_optional; /* ;an000; */ + p_con4.p_function_flag = p_cap_char; /* ;an000; */ + p_con4.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_con4.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con4.p_nid = 0; /* ;an000; */ + p_con4.p_keyorsw[0] = 0; /* ;an000; */ + /* ;an000; */ + p_swt1.p_match_flag = p_none; /* ;an000; */ + p_swt1.p_function_flag = p_cap_char; /* ;an000; */ + p_swt1.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_swt1.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_swt1.p_nid = 1; /* ;an000; */ + strcpy(p_swt1.p_keyorsw,"/D"+NULL); /* ;an000; */ + /* ;an000; */ + p_noval.p_val_num = 0; /* ;an000; */ + /* ;an000; */ + p_result1.P_Type = 0; /* ;an000; */ + p_result1.P_Item_Tag = 0; /* ;an000; */ + p_result1.P_SYNONYM_Ptr = 0; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + p_resultD.D_Type = 0; /* ;an000; */ + p_resultD.D_Item_Tag = 0; /* ;an000; */ + p_resultD.D_SYNONYM_Ptr = 0; /* ;an000; */ + p_resultD.D_Res_Drive = 0; /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end parse_init */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| SUBROUTINE NAME: DEVICE_ATTACH | +| | +| SUBROUTINE FUNCTION: | +| | +| This routine is called by the FILESYS MAIN routine when it has | +| determined that a device attach request has been included | +| on the FILESYS command line. | +| | +| INPUT: | +| device to attach and ifs name | +| | +| OUTPUT: | +| None | +| | ++----------------------------------------------------------------------*/ +void device_attach(parm_cnt, drive_ptr, fs_name_ptr, parm_ptr) /* ;an000; */ + /* ;an000; */ + int parm_cnt; /* ;an000; */ + char *drive_ptr; /* ;an000; */ + char *fs_name_ptr; /* ;an000; */ + char *parm_ptr; /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + strcpy(GAL_Device.device_string,drive_ptr); /* ;an000; */ + Attach_block.attach_system = fs_name_ptr; /* ;an000; */ + Attach_block.attach_parms_num = parm_cnt - 2; /* ;an000; */ + /* ;an000; */ + if (strchr(drive_ptr,(char)':') != 0) /* ;an000; */ + inregs.h.bl = IFS_DRIVE; /* ;an000; */ + else /* ;an000; */ + inregs.h.bl = IFS_DEVICE; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + inregs.x.ax = REDIRECT_DEVICE; /* fcn code for redir device */ /* ;an000; */ + inregs.x.si = (unsigned int) &GAL_Device; /* ;an000; */ + inregs.x.di = (unsigned int) &Attach_block; /* point to dest */ /* ;an000; */ + inregs.x.cx = 0; /* = 0 for network compat. */ /* ;an000; */ + /* ;an000; */ + intdos(&inregs, &outregs); /* make the call */ /* ;an000; */ + /* ;an000; */ + if ((outregs.x.cflag & CARRY_FLAG) == CARRY_FLAG) fs_error(outregs.x.ax); /* ;an000; */ + return; /* ;an000; */ + } /* end of device attach */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| SUBROUTINE NAME: DEVICE_DETACH | +| | +| SUBROUTINE FUNCTION: | +| | +| This routine is called by the FILESYS MAIN routine when it has | +| determined that a device detach request has been included | +| on the FILESYS command line. | +| | +| INPUT: | +| device to detach | +| | +| OUTPUT: | +| None | +| | ++----------------------------------------------------------------------*/ +void device_detach(char *rd_source) /* source for detach (e.g. LPT1:, E:) */ /* ;an000; */ + { /* ;an000; */ + inregs.x.ax = CANCEL_REDIRECTION; /* fcn code for cancel redir */ /* ;an000; */ + inregs.x.si = (unsigned int) rd_source; /* point to source */ /* ;an000; */ + /* ;an000; */ + intdos(&inregs, &outregs); /* make the call */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if ((outregs.x.cflag & CARRY_FLAG) == CARRY_FLAG) fs_error(outregs.x.ax); /* ;an000; */ + } /* end of device detach */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| fs_status - display attach or alias list | +| | +| Inputs : name - pointer to a specific device | +| | +| Outputs : status report of current attached state | +| | ++----------------------------------------------------------------------*/ +void fs_status(char *name) /* ;an000; */ + { /* ;an000; */ + int redir_index; /* counter variable */ /* ;an000; */ + int first_net_entry; /* flag */ /* ;an000; */ + int np_paused; /* flag */ /* ;an000; */ + int nd_paused; /* flag */ /* ;an000; */ + int entry_type; /* save the device entry type */ /* ;an000; */ + int error_type; /* save the device error type */ /* ;an002; */ + int message_type; /* value of message to build*/ /* ;an000; */ + int search_flag; /* flag */ /* ;an000; */ + int header_flag; /* flag used to help decide if header should be displayed */ /* ;an000; */ + char fs_name_array[9]; /* ;an000; */ + /* ;an000; */ + /* initialize some things */ /* ;an000; */ + /* ;an000; */ + GAL_Target.target_fs_name = (char *)fs_name_array; /* ;an000; */ + redir_index = 0; /* always start with entry 0 */ /* ;an000; */ + first_net_entry = TRUE; /* so we don't check for pause on */ /* ;an000; */ + /* every net entry */ /* ;an000; */ + np_paused = FALSE; /* always assume NOT paused */ /* ;an000; */ + nd_paused = FALSE; /* ;an000; */ + header_flag = FALSE; /* always initialze as false */ /* ;an000; */ + /* ;an000; */ + if (name[0] == NULL) /* an000; dms;specific device search? */ /* ;an000; */ + /* ;an000; */ + search_flag = FALSE; /* an000; dms;no */ /* ;an000; */ + /* ;an000; */ + else /* ;an000; */ + search_flag = TRUE; /* an000; dms;yes */ /* ;an000; */ + /* ;an000; */ + /* search through redir list */ /* ;an000; */ + /* ;an000; */ + inregs.x.ax = GET_ATTACH_LIST; /* an000; dms;get list of devices */ /* ;an000; */ + inregs.x.bx = redir_index; /* an000; dms;list entry number */ /* ;an000; */ + inregs.x.si = (unsigned int)&GAL_Device; /* an000; dms;point to device buffer */ /* ;an000; */ + inregs.x.di = (unsigned int)&GAL_Target; /* an000; dms;point to target buffer */ /* ;an000; */ + intdos(&inregs,&outregs); /* an000; dms;invoke call */ /* ;an000; */ + while ((outregs.x.ax != NO_MORE_FILES) && /* ;an000; */ + ((outregs.x.cflag & CARRY_FLAG) != CARRY_FLAG)) /* ;an000; */ + { /* ;an000; */ + error_type = outregs.h.bh; /* an000; drm;save error type */ /* ;an002; */ + entry_type = outregs.h.bl; /* an000; dms;save device type */ /* ;an000; */ + if (search_flag == TRUE) /* an000; dms;specific device? */ /* ;an000; */ + { /* ;an000; */ + if (strcmpi(GAL_Device.device_string,name) == 0) /* an000; dms;found the device? */ /* ;an000; */ + { /* ;an000; */ + Sub0_Message(TITLE1,STDOUT,Utility_Msg_Class); /* an000; dms; print header for status */ /* ;an000; */ + Sub0_Message(TITLE2,STDOUT,Utility_Msg_Class); /* ;an000; */ + Sub0_Message(TITLE3,STDOUT,Utility_Msg_Class); /* ;an000; */ + header_flag = TRUE; /* ;an000; */ + /* ;an000; */ + check_pause_status(entry_type, /* ;an001; */ + &np_paused, /* ;an000; */ + &nd_paused, /* ;an000; */ + &first_net_entry); /* ;an000; */ + string_build(); /* an000; dms;build string */ /* ;an000; */ + if (error_type != ZERO) + message_type = ERROR_RDR_MSG; /* ;an002; */ + else /* ;an002; */ + print_status(entry_type, /* ;an000; */ + np_paused, /* ;an000; */ + nd_paused, /* ;an000; */ + &message_type); /* ;an000; */ + fs_build_print_message(message_type, /* ;an000; */ + GAL_Device.device_string, /* ;an000; */ + GAL_Target.target_fs_name, /* ;an000; */ + GAL_Target.target_string); /* ;an000; */ + } /* ;an000; */ + } /* ;an000; */ + else /* ;an000; */ + { /* ;an000; */ + if (!header_flag) /* logic to display headers only once */ /* ;an000; */ + { /* ;an000; */ + Sub0_Message(TITLE1,STDOUT,Utility_Msg_Class); /* an000; dms; print header for status */ /* ;an000; */ + Sub0_Message(TITLE2,STDOUT,Utility_Msg_Class); /* ;an000; */ + Sub0_Message(TITLE3,STDOUT,Utility_Msg_Class); /* ;an000; */ + header_flag = TRUE; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + check_pause_status(entry_type, /* ;an001; */ + &np_paused, /* ;an000; */ + &nd_paused, /* ;an000; */ + &first_net_entry); /* ;an000; */ + string_build(); /* an000; dms;build string */ /* ;an000; */ + if (error_type != ZERO) + message_type = ERROR_RDR_MSG; /* ;an002; */ + else /* ;an002; */ + print_status(entry_type, /* ;an000; */ + np_paused, /* ;an000; */ + nd_paused, /* ;an000; */ + &message_type); /* ;an000; */ + fs_build_print_message(message_type, /* ;an000; */ + GAL_Device.device_string, /* ;an000; */ + GAL_Target.target_fs_name, /* ;an000; */ + GAL_Target.target_string); /* ;an000; */ + } /* ;an000; */ + redir_index++; /* an000; dms;next entry */ /* ;an000; */ + inregs.x.ax = GET_ATTACH_LIST; /* an000; dms;get list of devices */ /* ;an000; */ + inregs.x.bx = redir_index; /* an000; dms;list entry number */ /* ;an000; */ + inregs.x.si = (unsigned int)&GAL_Device; /* an000; dms;point to device buffer */ /* ;an000; */ + inregs.x.di = (unsigned int)&GAL_Target; /* an000; dms;point to target buffer */ /* ;an000; */ + intdos(&inregs,&outregs); /* an000; dms;invoke call */ /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (header_flag == FALSE) /* ;an000; */ + Sub0_Message(NO_ENTRIES,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| get_pause_stat - check the pause status of network printing or disk | +| redirection. | +| | ++----------------------------------------------------------------------*/ +get_pause_stat (unsigned char type) /* ;an000; */ + { /* ;an000; */ + int return_flag; /* flag to return paused status */ /* ;an000; */ + /* ;an000; */ + inregs.x.ax = GET_PAUSE_STATUS; /* ;an000; */ + inregs.h.bl = type; /* ;an000; */ + intdos(&inregs, &outregs); /* ;an000; */ + /* ;an000; */ + if (outregs.h.bh == 0) return_flag = TRUE; /* ;an000; */ + else return_flag = FALSE; /* ;an000; */ + /* ;an000; */ + return(return_flag); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| SUBROUTINE NAME: FS_ERROR | +| | +| SUBROUTINE FUNCTION: | +| | +| This routine is called to handle any error conditions that | +| are detected by the FILESYS routines. | +| | +| INPUT: | +| Error code (word) | +| | +| OUTPUT: | +| The corresponding error message is displayed on the screen. | +| (STDERR) | +| | ++----------------------------------------------------------------------*/ +void fs_error(int error_ax) /* error_ax holds error code */ /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + inregs.x.ax = GET_EXTENDED_ERROR; /* get the extended error */ /* ;an000; */ + inregs.x.bx = NULL; /* clear bx to signal > DOS 3.0 */ /* ;an000; */ + intdos(&inregs, &outregs); /* INT 21h call */ /* ;an000; */ + /* ;an000; */ + inregs.x.ax = outregs.x.ax; /* get extended error in AX */ /* ;an000; */ + inregs.x.bx = STDERR; /* output to standard error */ /* ;an000; */ + inregs.x.cx = SubCnt0; /* no replaceables */ /* ;an000; */ + inregs.h.dl = No_Input; /* no keyboard input */ /* ;an000; */ + inregs.h.dh = Ext_Err_Class; /* extended error class */ /* ;an000; */ + sysdispmsg(&inregs,&outregs); /* display the message */ /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end of fs_error */ /* ;an000; */ + /* ;an000; */ +/*=======================================================================*/ /* ;an000; */ +/* FS_Build_Print_Message:This routine builds the applicable message and */ /* ;an000; */ +/* prints it. */ /* ;an000; */ +/* Input : Msg_Num - The message number of the applicable */ /* ;an000; */ +/* message */ /* ;an000; */ +/* Output : The printed message */ /* ;an000; */ +/* */ /* ;an000; */ +/*=======================================================================*/ /* ;an000; */ + /* ;an000; */ +void fs_build_print_message(msg_num, outline1, outline2, outline3) /* ;an000; */ +int msg_num; /* ;an000; */ +char *outline1; /* ;an000; */ +char *outline2; /* ;an000; */ +char *outline3; /* ;an000; */ + /* ;an000; */ +{ /* ;an000; */ + unsigned status; /* ;an000; */ + unsigned char function; /* type of input function */ /* ;an000; */ + unsigned char msg_class; /* ;an000; */ + unsigned int message, /* message number */ /* ;an000; */ + sub_cnt, /* num. of replaceable parameters */ /* ;an000; */ + handle; /* display handle */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + switch (msg_num) /* what message do we have? */ /* ;an000; */ + { /* ;an000; */ + case PAUSE_RDR_MSG: function = No_Input; /* no keyboard input */ /* ;an000; */ + message = PAUSE_RDR_MSG; /* message %1 REDIR %2 PAUSED */ /* ;an000; */ + msg_class = Utility_Msg_Class; /* utility message */ /* ;an000; */ + sub_cnt = SubCnt3; /* 2 replaceable parms */ /* ;an000; */ + handle = STDOUT; /* display to standard out */ /* ;an000; */ + break; /* end case statement */ /* ;an000; */ + /* ;an000; */ + case REDIR_MSG : function = No_Input; /* no keyboard input */ /* ;an000; */ + message = REDIR_MSG; /* message - %1 REDIR %2 */ /* ;an000; */ + msg_class = Utility_Msg_Class; /* utility message */ /* ;an000; */ + sub_cnt = SubCnt3; /* 2 replaceable parms */ /* ;an000; */ + handle = STDOUT; /* display to standard out */ /* ;an000; */ + break; /* end case statement */ /* ;an000; */ + + case ERROR_RDR_MSG: function = No_Input; /* no keyboard input */ /* ;an002; */ + message = ERROR_RDR_MSG; /* message %1 REDIR %2 ERROR */ /* ;an002; */ + msg_class = Utility_Msg_Class; /* utility message */ /* ;an002; */ + sub_cnt = SubCnt3; /* 2 replaceable parms */ /* ;an002; */ + handle = STDOUT; /* display to standard out */ /* ;an002; */ + break; /* end case statement */ /* ;an002; */ + } /* ;an000; */ + /* ;an000; */ + switch(msg_num) /* what message number to print? */ /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + case ERROR_RDR_MSG : /* message to print */ /* ;an002; */ + case PAUSE_RDR_MSG : /* message to print */ /* ;an000; */ + case REDIR_MSG : sublist[1].value = (unsigned far *)outline1; /* point to parm 1 */ /* ;an000; */ + sublist[1].size = Sublist_Length; /* length of sublist */ /* ;an000; */ + sublist[1].reserved = Reserved; /* reserved for future growth */ /* ;an000; */ + sublist[1].id = 1; /* number of replaceable parm */ /* ;an000; */ + sublist[1].flags = Char_Field_ASCIIZ+Left_Align; /* string input data */ /* ;an000; */ + sublist[1].max_width = 5; /* default max width - unlimited */ /* ;an000; */ + sublist[1].min_width = 5; /* min width of 1 */ /* ;an000; */ + sublist[1].pad_char = Blank; /* pad with blanks */ /* ;an000; */ + /* ;an000; */ + sublist[2].value = (unsigned far *)outline2; /* point to parm 2 */ /* ;an000; */ + sublist[2].size = Sublist_Length; /* length of sublist */ /* ;an000; */ + sublist[2].reserved = Reserved; /* reserved for future growth */ /* ;an000; */ + sublist[2].id = 2; /* number of replaceable parm */ /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Left_Align; /* string input data */ /* ;an000; */ + sublist[2].max_width = 9; /* default max width - unlimited */ /* ;an000; */ + sublist[2].min_width = 9; /* min width of 1 */ /* ;an000; */ + sublist[2].pad_char = Blank; /* pad with blanks */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + sublist[3].value = (unsigned far *)outline3; /* ;an000; */ + sublist[3].size = Sublist_Length; /* length of sublist */ /* ;an000; */ + sublist[3].reserved = Reserved; /* reserved for future growth */ /* ;an000; */ + sublist[3].id = 3; /* number of replaceable parm */ /* ;an000; */ + sublist[3].flags = Char_Field_ASCIIZ+Left_Align; /* string input data */ /* ;an000; */ + sublist[3].max_width = 0; /* default max width - unlimited */ /* ;an000; */ + sublist[3].min_width = 1; /* min width of 1 */ /* ;an000; */ + sublist[3].pad_char = Blank; /* pad with blanks */ /* ;an000; */ + /* ;an000; */ + inregs.x.ax = message; /* put message number in AX */ /* ;an000; */ + inregs.x.bx = handle; /* put handle in BX */ /* ;an000; */ + inregs.x.si = (unsigned int)&sublist[1]; /* put sublist pointer in SI */ /* ;an000; */ + inregs.x.cx = sub_cnt; /* put sublist count in CX */ /* ;an000; */ + inregs.h.dl = function; /* put function type in DL */ /* ;an000; */ + inregs.h.dh = msg_class; /* put message class in DH */ /* ;an000; */ + sysdispmsg(&inregs,&outregs); /* display the message */ /* ;an000; */ + break; /* end case statement */ /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* STRING_BUILD - This routine takes a buffer filled with */ /* ;an000; */ +/* multiple ASCIIZ strings and concatenates them */ /* ;an000; */ +/* into one string by convering all null chars. */ /* ;an000; */ +/* to a blank. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs - GAL_Target (struct) */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs - converted buffer */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void string_build() /* ;an000; */ + /* ;an000; */ +{ /* ;an000; */ + int x; /* ;an000; */ + int i; /* ;an000; */ + /* ;an000; */ + x = 0; /* an000; dms;index pointer */ /* ;an000; */ + i = 0; /* an000; dms;loop counter */ /* ;an000; */ + while (i != GAL_Target.target_count) /* an000; dms;while strings exist */ /* ;an000; */ + { /* ;an000; */ + while (GAL_Target.target_string[x] != NULL) /* an000; dms;while not end of string */ /* ;an000; */ + x++; /* an000; dms;increment pointer */ /* ;an000; */ + GAL_Target.target_string[x] = Blank; /* an000; dms;blank terminate string */ /* ;an000; */ + x++; /* an000; dms;increment pointer */ /* ;an000; */ + i++; /* an000; dms;next string */ /* ;an000; */ + } /* ;an000; */ + GAL_Target.target_string[x] = NULL; /* an000; null terminate buffer */ /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* CHECK_PAUSE_STATUS - This routine determines if the net drive or */ /* ;an000; */ +/* printer is paused. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : regbl - contents of register BL */ /* ;an000; */ +/* dr_pause - driver pause flag */ /* ;an000; */ +/* pr_pause - printer pause flag */ /* ;an000; */ +/* net_flag - signals 1st. occurrence */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : dr_pause - flag set appropriately */ /* ;an000; */ +/* pr_pause - flag set appropriately */ /* ;an000; */ +/* net_flag - flag set appropriately */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void check_pause_status(regbl, pr_pause, dr_pause, net_flag) /* ;an001; */ + /* ;an000; */ + unsigned char regbl; /* ;an000; */ + int *dr_pause; /* ;an000; */ + int *pr_pause; /* ;an000; */ + int *net_flag; /* ;an000; */ +{ /* ;an000; */ + if (((regbl == NET_PRINTER) || /* an000; dms; if net drive or printer */ /* ;an000; */ + (regbl == NET_DRIVE)) && /* ;an001; */ + (*net_flag == TRUE)) /* ;an001; */ + { /* ;an000; */ + *net_flag = FALSE; /* an000; dms; set flag to false */ /* ;an001; */ + *pr_pause = get_pause_stat(NET_PRINTER); /* an000; dms; see if printer paused */ /* ;an000; */ + *dr_pause = get_pause_stat(NET_DRIVE); /* an000; dms; see if drive paused */ /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* PRINT_STATUS - This routine determines the type of print */ /* ;an000; */ +/* message that is to be used. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : entry_type - type of device */ /* ;an000; */ +/* np_paused - flag */ /* ;an000; */ +/* nd_paused - flag */ /* ;an000; */ +/* message_type - type of message to print */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message_type - message type to be printed */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void print_status(entry_type, np_paused, nd_paused, message_type) /* ;an000; */ + /* ;an000; */ + int entry_type; /* ;an000; */ + int np_paused; /* ;an000; */ + int nd_paused; /* ;an000; */ + int *message_type; /* ;an000; */ +{ /* ;an000; */ + if ((entry_type == NET_PRINTER) && (np_paused == TRUE)) /* ;an000; */ + *message_type = PAUSE_RDR_MSG; /* ;an000; */ + else /* printing not paused, try disk redir */ /* ;an000; */ + { /* ;an000; */ + if ((entry_type == NET_DRIVE) && (nd_paused == TRUE)) /* ;an000; */ + *message_type = PAUSE_RDR_MSG; /* ;an000; */ + else /* ;an000; */ + *message_type = REDIR_MSG; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (entry_type == NET_PRINTER) /* always want to add ":" to LPTx */ /* ;an000; */ + strncat(GAL_Device.device_string,":",1); /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB0_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that do not require a */ /* ;an000; */ +/* a sublist. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub0_Message(Msg_Num,Handle,Message_Type) /* print messages with no subs */ /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ + { /* ;an000; */ + inregs.x.ax = Msg_Num; /* put message number in AX */ /* ;an000; */ + inregs.x.bx = Handle; /* put handle in BX */ /* ;an000; */ + inregs.x.cx = No_Replace; /* no replaceable subparms */ /* ;an000; */ + inregs.h.dl = No_Input; /* no keyboard input */ /* ;an000; */ + inregs.h.dh = Message_Type; /* type of message to display */ /* ;an000; */ + sysdispmsg(&inregs,&outregs); /* display the message */ /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* FS_STRCPY - This routine will provide the string copy */ /* ;an000; */ +/* capability for a far pointer. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : buffer - pointer to the destination */ /* ;an000; */ +/* parse_ptr - far pointer to source */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : buffer - new string */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void fs_strcpy(buffer, parse_ptr) /* ;an000; */ + /* ;an000; */ + char *buffer; /* ;an000; */ + char far *parse_ptr; /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + while ((*buffer = *parse_ptr) != NULL) /* ;an000; */ + { /* ;an000; */ + buffer++; /* ;an000; */ + parse_ptr++; /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* FS_STRLEN - This routine calculates the string's length. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : parse_ptr - pointer to the string to measure */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : i - string's length */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +int fs_strlen(parse_ptr) /* ;an000; */ + /* ;an000; */ + char far *parse_ptr; /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + int i; /* ;an000; */ + /* ;an000; */ + for (i = 0; *parse_ptr != NULL; parse_ptr++) /* ;an000; */ + i++; /* ;an000; */ + /* ;an000; */ + return(i); /* ;an000; */ + } /* ;an000; */ diff --git a/v4.0/src/CMD/FILESYS/FILESYS.SKL b/v4.0/src/CMD/FILESYS/FILESYS.SKL new file mode 100644 index 0000000..734246d --- /dev/null +++ b/v4.0/src/CMD/FILESYS/FILESYS.SKL @@ -0,0 +1,15 @@ + +:util FILESYS + +:class 1 + +:class A +:use COMMON1 ;"Incorrect DOS version",cr,lf +:def 10 " PAUSED %1 %2 %3",CR,LF +:def 11 " %1 %2 %3",CR,LF +:def 12 " Local IFS",CR,LF ;an001;bgb +:def 13 " Status Device Name Parameters",CR,LF ;an001;bgb +:def 14 " ______ ______ _________ ___________________",CR,LF,CR,LF +:def 15 "No entries found",CR,LF +:def 16 " ERROR %1 %2 %3",CR,LF +:end diff --git a/v4.0/src/CMD/FILESYS/FSCHNG.INC b/v4.0/src/CMD/FILESYS/FSCHNG.INC new file mode 100644 index 0000000..1145ea1 --- /dev/null +++ b/v4.0/src/CMD/FILESYS/FSCHNG.INC @@ -0,0 +1,24 @@ +.xlist +; +; +;***************************************************************************** +;* * +;* Change list to FILESYS modules * +;* * +;* Lines are tagged ANxxx for new, ACxxx for changed * +;* --------------------------------------------------------------------------* +;* 000 - DOS 4.00 Spec additions and DCR's thru unit/function test * +;* Date: 12/31/87 Developer: GA, DS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 001 - DOS 4.00 PTM P4249 FILESYS adds extra ":" on forth entry of display.* +;* Date: 04/22/88 Developer: DM * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 002 - DOS 4.00 PTM P4248 FILESYS does not show PAUSED in status field, * +;* also added was ERROR to the status field. * +;* Date: 04/22/88 Developer: DM * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;***************************************************************************** +;* Note: This is file FSCHNG.INC for updating purposes * +;***************************************************************************** +.list + diff --git a/v4.0/src/CMD/FILESYS/MAKEFILE b/v4.0/src/CMD/FILESYS/MAKEFILE new file mode 100644 index 0000000..f29975e --- /dev/null +++ b/v4.0/src/CMD/FILESYS/MAKEFILE @@ -0,0 +1,35 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: filesys.exe + +filesys.ctl: filesys.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +_msgret.obj: _msgret.asm \ + filesys.ctl \ + makefile \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc + +_parse.obj: _parse.asm \ + makefile \ + $(inc)\PARSE.ASM \ + $(inc)\PSDATA.INC + +filesys.obj: filesys.c parse.h + +filesys.exe: filesys.obj \ + _parse.obj \ + _msgret.obj + link filesys+ _parse+ _msgret; /NOI + diff --git a/v4.0/src/CMD/FILESYS/MSGRET.H b/v4.0/src/CMD/FILESYS/MSGRET.H new file mode 100644 index 0000000..778c079 --- /dev/null +++ b/v4.0/src/CMD/FILESYS/MSGRET.H @@ -0,0 +1,53 @@ +/************************************************************************/ +/* MSGRET.H - This include file defines each message type */ +/* that can occur in FILESYS. The defines will */ +/* be used to build the proper message. */ +/* */ +/* Date : 10/29/87 */ +/************************************************************************/ + +/************************************************************************/ +/* Message Retriever Standard Equates */ +/************************************************************************/ + +#define PAUSE_RDR_MSG 0x000A +#define REDIR_MSG 0x000B +#define TITLE1 0x000C +#define TITLE2 0x000D +#define TITLE3 0x000E +#define NO_ENTRIES 0x000F +#define ERROR_RDR_MSG 0x0010 + +#define Ext_Err_Class 0x0001 +#define Parse_Err_Class 0x0002 +#define Utility_Msg_Class 0x00ff +#define No_Handle 0xffff +#define No_Replace 0x0000 +#define Sublist_Length 0x000b +#define Reserved 0x0000 +#define Left_Align 0x0000 +#define Right_Align 0x0080 +#define Char_Field_Char 0x0000 +#define Char_Field_ASCIIZ 0x0010 +#define Unsgn_Bin_Byte 0x0011 +#define Unsgn_Bin_Word 0x0021 +#define Unsgn_Bin_DWord 0x0031 +#define Sgn_Bin_Byte 0x0012 +#define Sgn_Bin_Word 0x0022 +#define Sgn_Bin_DWord 0x0032 +#define Bin_Hex_Byte 0x0013 +#define Bin_Hex_Word 0x0023 +#define Bin_Hex_DWord 0x0033 +#define No_Input 0x0000 +#define STDIN 0x0000 +#define STDOUT 0x0001 +#define STDERR 0x0002 +#define Blank 0x0020 + +#define SubCnt0 0x0000 +#define SubCnt1 0x0001 +#define SubCnt2 0x0002 +#define SubCnt3 0x0003 +#define SubCnt4 0x0004 +#define SubCnt5 0x0005 + diff --git a/v4.0/src/CMD/FILESYS/PARSE.H b/v4.0/src/CMD/FILESYS/PARSE.H new file mode 100644 index 0000000..cbfc3c0 --- /dev/null +++ b/v4.0/src/CMD/FILESYS/PARSE.H @@ -0,0 +1,155 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the parser from a C program. | +| | +| | +| Date: 5-21-87 | +| | ++----------------------------------------------------------------------*/ + + +#define p_len_parms 4 /* length of p_parms */ +#define p_i_use_default 0 /* no extra stuff specified */ +#define p_i_have_delim 1 /* extra delimiter specified */ +#define p_i_have_eol 2 /* extra EOL specified */ + +struct p_parms + { + struct p_parmsx *p_parmsx_address; /* address of p_parmsx */ + unsigned char p_num_extra; /* number of extra stuff */ + unsigned char p_len_extra_delim; /* length of extra delimiter */ + char p_extra_delim[30]; /* extra delimiters */ + }; + +struct p_parmsx + { + unsigned char p_minp; /* Minimum positional number */ + unsigned char p_maxp; /* Maximum positional number */ + struct p_control_blk *p_control[4]; /* Address of the 1st CONTROL block */ + unsigned char p_maxswitch; /* Maximum switches */ + struct p_control_blk *p_switch[1]; /* Pointer to switch block */ + unsigned char p_maxkeyword; /* Maximum keywords */ + }; + + +struct p_control_blk + { + unsigned int p_match_flag; /* Controls type matched */ + unsigned int p_function_flag; /* Function should be taken */ + unsigned int p_result_buf; /* Result buffer address */ + unsigned int p_value_list; /* Value list address */ + unsigned char p_nid; /* # of keyword/SW synonyms */ + unsigned char p_keyorsw[20]; /* keyword or sw */ + }; + +/* Match_Flags */ + +#define p_num_val 0x8000 /* Numeric Value */ +#define p_snum_val 0x4000 /* Signed numeric value */ +#define p_simple_s 0x2000 /* Simple string */ +#define p_date_s 0x1000 /* Date string */ +#define p_time_s 0x0800 /* Time string */ +#define p_cmpx_s 0x0400 /* Complex string */ +#define p_file_spc 0x0200 /* File Spec */ +#define p_drv_only 0x0100 /* Drive Only */ +#define p_qu_string 0x0080 /* Quoted string */ +#define p_ig_colon 0x0010 /* Ignore colon at end in match */ +#define p_repeat 0x0002 /* Repeat allowed */ +#define p_optional 0x0001 /* Optional */ +#define p_none 0x0000 + +/*----------------------------------------------------------------------+ +| | +| Value block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_value_blk + { + unsigned char p_val_num; + }; + + +/*----------------------------------------------------------------------+ +| | +| Function flags | +| | ++----------------------------------------------------------------------*/ + +#define p_cap_file 0x0001 /* CAP result by file table */ +#define p_cap_char 0x0002 /* CAP result by character table */ +#define p_rm_colon 0x0010 /* Remove ":" at the end */ + + + +#define p_nval_none 0 /* no value list ID */ +#define p_nval_range 1 /* range list ID */ +#define p_nval_value 2 /* value list ID */ +#define p_nval_string 3 /* string list ID */ +#define p_len_range 9 /* Length of a range choice(two DD plus one DB) */ +#define p_len_value 5 /* Length of a value choice(one DD plus one DB) */ +#define p_len_string 3 /* Length of a string choice(one DW plus one DB) */ + + +/*----------------------------------------------------------------------+ +| | +| Result block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_result_blk + { + unsigned char P_Type; /* Type returned */ + unsigned char P_Item_Tag; /* Matched item tag */ + unsigned int P_SYNONYM_Ptr; /* pointer to Synonym list returned */ + char far *p_result_buff; /* result value */ + }; + + +struct p_result_blk_D + { + unsigned char D_Type; /* Type returned */ + unsigned char D_Item_Tag; /* Matched item tag */ + unsigned int D_SYNONYM_Ptr; /* pointer to Synonym list returned */ + unsigned int D_Res_Drive; /* drive value */ + }; + +/*----------------------------------------------------------------------+ +| | +| type | +| | ++----------------------------------------------------------------------*/ + +#define p_eol 0 /* End of line */ +#define p_number 1 /* Number */ +#define p_list_idx 2 /* List Index */ +#define p_string 3 /* String */ +#define p_complex 4 /* Complex */ +#define p_file_spec 5 /* File Spec */ +#define p_drive 6 /* Drive */ +#define p_date_f 7 /* Date */ +#define p_time_f 8 /* Time */ +#define p_quoted_string 9 /* Quoted String */ + +#define p_no_tag 0x0FF /* No ITEM_TAG found */ + +/*----------------------------------------------------------------------+ +| | +| following return code will be returned in the AX register. | +| | ++----------------------------------------------------------------------*/ + +#define p_no_error 0 /* No error */ +#define p_too_many 1 /* Too many operands */ +#define p_op_missing 2 /* Required operand missing */ +#define p_not_in_sw 3 /* Not in switch list provided */ +#define p_not_in_key 4 /* Not in keyword list provided */ +#define p_out_of_range 6 /* Out of range specified */ +#define p_not_in_val 7 /* Not in value list provided */ +#define p_not_in_str 8 /* Not in string list provided */ +#define p_syntax 9 /* Syntax error */ +#define p_rc_eol 0x0ffff /* End of command line */ + + diff --git a/v4.0/src/CMD/FILESYS/PSDATA.H b/v4.0/src/CMD/FILESYS/PSDATA.H new file mode 100644 index 0000000..569fc1c --- /dev/null +++ b/v4.0/src/CMD/FILESYS/PSDATA.H @@ -0,0 +1,146 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the parser from a C program. | +| | +| | +| Date: 5-21-87 | +| | ++----------------------------------------------------------------------*/ + + +#define P_Len_PARMS 4 /* length of p_parms */ +#define P_I_Use_Default 0 /* no extra stuff specified */ +#define P_I_Have_Delim 1 /* extra delimiter specified */ +#define P_I_Have_EOL 2 /* extra EOL specified */ + +struct p_parms + { + struct p_parmsx *p_parmsx_address; /* address of p_parmsx */ + unsigned char p_num_extra; /* number of extra stuff */ + unsigned char p_len_extra_delim; /* length of extra delimiter */ + }; + +struct p_parmsx + { + unsigned char p_minp; /* Minimum positional number */ + unsigned char p_maxp; /* Maximum positional number */ + unsigned int p_1st_control; /* Address of the 1st CONTROL block */ + }; + + +struct p_control_blk + { + unsigned int p_match_flag; /* Controls type matched */ + unsigned int p_function_flag; /* Function should be taken */ + unsigned int p_result_buf; /* Result buffer address */ + unsigned int p_value_list; /* Value list address */ + unsigned char p_nid; /* # of keyword/SW synonyms */ + unsigned char p_keyorsw; /* keyword or sw */ + }; + +/* Match_Flags */ + +#define P_Num_Val 0x8000 /* Numeric Value */ +#define P_SNum_Val 0x4000 /* Signed numeric value */ +#define P_Simple_S 0x2000 /* Simple string */ +#define P_Date_S 0x1000 /* Date string */ +#define P_Time_S 0x0800 /* Time string */ +#define P_Cmpx_S 0x0400 /* Complex string */ +#define P_File_Spc 0x0200 /* File Spec */ +#define P_Drv_Only 0x0100 /* Drive Only */ +#define P_Qu_String 0x0080 /* Quoted string */ +#define P_Ig_Colon 0x0010 /* Ignore colon at end in match */ +#define P_Repeat 0x0002 /* Repeat allowed */ +#define P_Optional 0x0001 /* Optional */ + +/*----------------------------------------------------------------------+ +| | +| Function flags | +| | ++----------------------------------------------------------------------*/ + +#define P_CAP_File 0x0001 /* CAP result by file table */ +#define P_CAP_Char 0x0002 /* CAP result by character table */ +#define P_Rm_Colon 0x0010 /* Remove ":" at the end */ + + + + + +#define P_nval_None 0 /* no value list ID */ +#define P_nval_Range 1 /* range list ID */ +#define P_nval_Value 2 /* value list ID */ +#define P_nval_String 3 /* string list ID */ +#define P_Len_Range 9 /* Length of a range choice(two DD plus one DB) */ +#define P_Len_Value 5 /* Length of a value choice(one DD plus one DB) */ +#define P_Len_String 3 /* Length of a string choice(one DW plus one DB) */ + + +/*----------------------------------------------------------------------+ +| | +| problem with doing this in C | +| | ++----------------------------------------------------------------------*/ +struct p_val_list + { + unsigned char P_NumofList; /* number of following choice */ + unsigned int P_Val_XL; /* lower word of value */ + unsigned int P_Val_XH; /* higher word of value */ + unsigned int P_Val_YL; /* lower word of another value */ + unsigned int P_Val_YH; /* higher word of another value */ + }; + + +/*----------------------------------------------------------------------+ +| | +| Result block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_result_blk + { + unsigned char P_Type; /* Type returned */ + unsigned char P_Item_Tag; /* Matched item tag */ + unsigned int P_SYNONYM_Ptr; /* pointer to Synonym list returned */ + unsigned char P_Picked_Val[4]; /* value */ + }; + +/*----------------------------------------------------------------------+ +| | +| type | +| | ++----------------------------------------------------------------------*/ + +#define P_EOL 0 /* End of line */ +#define P_Number 1 /* Number */ +#define P_List_Idx 2 /* List Index */ +#define P_String 3 /* String */ +#define P_Complex 4 /* Complex */ +#define P_File_Spec 5 /* File Spec */ +#define P_Drive 6 /* Drive */ +#define P_Date_F 7 /* Date */ +#define P_Time_F 8 /* Time */ +#define P_Quoted_String 9 /* Quoted String */ + +#define P_No_Tag 0x0FF /* No ITEM_TAG found */ + +/*----------------------------------------------------------------------+ +| | +| following return code will be returned in the AX register. | +| | ++----------------------------------------------------------------------*/ + +#define P_No_Error 0 /* No error */ +#define P_Too_Many 1 /* Too many operands */ +#define P_Op_Missing 2 /* Required operand missing */ +#define P_Not_In_SW 3 /* Not in switch list provided */ +#define P_Not_In_Key 4 /* Not in keyword list provided */ +#define P_Out_Of_Range 6 /* Out of range specified */ +#define P_Not_In_Val 7 /* Not in value list provided */ +#define P_Not_In_Str 8 /* Not in string list provided */ +#define P_Syntax 9 /* Syntax error */ +#define P_RC_EOL 0x0ffff /* End of command line */ + + diff --git a/v4.0/src/CMD/FILESYS/_MSGRET.ASM b/v4.0/src/CMD/FILESYS/_MSGRET.ASM new file mode 100644 index 0000000..832529c --- /dev/null +++ b/v4.0/src/CMD/FILESYS/_MSGRET.ASM @@ -0,0 +1,190 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 message retriever +; +; CALLING FORMAT: +; msgret(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + +DGROUP GROUP CONST, _BSS, _DATA + ASSUME CS: DGROUP, DS: DGROUP, SS: DGROUP, ES: NOTHING + + public data_sysloadmsg + public data_sysdispmsg + +_DATA SEGMENT + + MSG_SERVICES + MSG_SERVICES + MSG_SERVICES + MSG_SERVICES ;AN000; + + +data_sysloadmsg proc far + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + + call sysloadmsg ; call the message retriever + +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6+4] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +data_sysloadmsg endp + + +data_sysdispmsg proc far + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + + call sysdispmsg + +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6+4] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +data_sysdispmsg endp + +include msgdcl.inc + + +_DATA ends ; end code segment + +_TEXT SEGMENT + + assume cs:_TEXT + + public _sysdispmsg + public _sysloadmsg + +_sysdispmsg proc near + call data_sysdispmsg + ret +_sysdispmsg endp + +_sysloadmsg proc near + call data_sysloadmsg + ret +_sysloadmsg endp + +_TEXT ENDS + end + diff --git a/v4.0/src/CMD/FILESYS/_PARSE.ASM b/v4.0/src/CMD/FILESYS/_PARSE.ASM new file mode 100644 index 0000000..d1424b7 --- /dev/null +++ b/v4.0/src/CMD/FILESYS/_PARSE.ASM @@ -0,0 +1,165 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 parser +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse + +;------------------------------------------------------------------- +;FarSW equ 0 ; make sysparse be a NEAR proc +;TimeSW equ 0 ; Check time format +;FileSW equ 0 ; Check file specification +;CAPSW equ 0 ; Perform CAPS if specified +;CmpxSW equ 0 ; Check complex list +;NumSW equ 1 ; Check numeric value +;KeySW equ 0 ; Support keywords +;SwSW equ 1 ; Support switches +;Val1SW equ 1 ; Support value definition 1 +;Val2SW equ 1 ; Support value definition 2 +;Val3SW equ 0 ; Support value definition 3 +;DrvSW equ 0 ; Support drive only format +;QusSW equ 0 ; Support quoted string format +;------------------------------------------------------------------- + + + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + + +DGROUP GROUP CONST, _BSS, _DATA + + +_DATA segment word public 'DATA' + + assume cs:DGROUP + assume ss:dgroup + + public SysParse + +;------------------------------------------------------------------- +.xlist +include parse.asm ; include the parser +.list +;------------------------------------------------------------------- + + public CallParser +CallParser proc far + + push ds + PUSH ES + + push cs + pop ds + assume ds:DGROUP + + push cs + pop es + assume es:DGROUP + + nop + + call SysParse + + POP ES + pop ds + + ret + +CallParser endp + + + +_DATA ends + +_TEXT segment byte public 'CODE' + + ASSUME CS:_TEXT + ASSUME DS:DGROUP + ASSUME ES:NOTHING + ASSUME SS:DGROUP + +_parse proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + call CallParser ; call the parser + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + xor ax,ax ; clear ax + lahf ; get flags into ax + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_parse endp + +_TEXT ends ; end code segment + end + diff --git a/v4.0/src/CMD/FIND/FIND.ASM b/v4.0/src/CMD/FIND/FIND.ASM new file mode 100644 index 0000000..459765a --- /dev/null +++ b/v4.0/src/CMD/FIND/FIND.ASM @@ -0,0 +1,1664 @@ + title DOS FIND Utility +; 0 +;******************************************************************** +;* +;* UTILITY NAME: find.exe +;* +;* SOURCE FILE NAME: find.asm +;* +;* STATUS: Find utility, DOS Version 4.0 +;* +;* SYNTAX (Command line) +;* +;* FIND [/V][/C][/N] "string" [[d:][path]filename[.ext]...] +;* +;* where: +;* +;* /V - Display all lines NOT containing the string +;* /C - Display only a count of lines containing string +;* /N - Display number of line containing string +;* +;* +;* UTILITY FUNCTION: +;* +;* Searches the specified file(s) looking for the string the user +;* entered from the command line. If file name(s) are specifeied, +;* those names are displayed, and if the string is found, then the +;* entire line containing that string will be displayed. Optional +;* parameters modify that behavior and are described above. String +;* arguments have to be enclosed in double quotes. (Two double quotes +;* if a double quote is to be included). Only one string argument is +;* presently allowed. The maximum line size is determined by buffer +;* size. Bigger lines will bomb the program. If no file name is given +;* then it will asssume the input is coming from the standard Input. +;* No errors are reported when reading from standard Input. +;* +;* +;* EXIT: +;* The program returns errorlevel: +;* 0 - OK, and some matches +;* 1 - +;* 2 - Some Error +;* +;* +;* Revision History: +;* +;* V1.1 8/23/82 M.A.U. (Microsoft) +;* +;* V1.2 9/22/82 M.A.U. (Microsoft) +;* Added the -c and -n options +;* +;* 9/23/82 M.A.U. (Microsoft) +;* Added DOS version number control +;* +;* 10/07/82 Rev.2 M.A.U. (Microsoft) +;* Changed quote for double quotes, and added +;* file name printing +;* +;* 10/20/82 Rev.3 M.A.U. (Microsoft) +;* Modified IBM name to FIND, and changed the text +;* of some messages. +;* +;* 10/25/82 Rev.4 M.A.U. (Microsoft) +;* Changed name to FIND and all messages to the +;* IBM form. +;* +;* 10/27/82 Rev.5 M.A.U. (Microsoft) +;* Made the correct exit on version check in case +;* of a 1.x DOS. +;* +;* 11/4/82 Rev. 5 A.R. Reynolds (Microsoft) +;* Messages moved to external module +;* +;* 11/10/82 Rev. 6 M.A. U. (Microsoft) +;* Corrected problem with line numbers, and a problem +;* with seeking for 0 chars. +;* +;* 03/30/83 Rev. 7 M.A. U. (Microsoft) +;* Added patch area for bug fixing. +;* +;* 04/14/83 Rev. 8 M.A. U. (Microsoft) +;* Made changes for Kanji characters. (ugh!) +;* +;* 12/17/84 Rev. 9 Zibo (Microsoft) +;* Fix boundary case for buffer containing exact line +;* +;* V4.0 : 6/29/87 Russ W (IBM) +;* Lines commented with ;AN000; +;* Add support for IBM Parse service routines +;* Add support for IBM Message Retriever Service Routines +;* Add support for Code Page File Tags +;* Made PROCs out of all labels that were targets of a call (not commented with AN000) +;* Removed patch area for "bug fixing" +;* +;* V4.0 : 9/15/87 Bill L, (IBM) +;* ;AN001; = DCR 201, changes to extended attributes support +;* ;AN002; = PTM 1090 +;* ;AN003; = DCR 191 +;* ;AN004; = PTM 1630 +;* ;AN005; = PTM 1643, PTM 1675, PTM 1754 +;* ;AN006; = DBCS support +;* ;AN007; = Optimizations to save disk space on ship diskettes +;* +;********************************************************************** + +;-------------------------- +;- MACRO DEFINITIONS +;-------------------------- +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + + +;---------------------------; +;- INCLUDE FILES ; +;---------------------------; +.xlist ; +.xcref ; + INCLUDE SYSCALL.INC ; + INCLUDE sysmsg.inc ; ;AN000; Include message equates and MACROS + INCLUDE find.inc ; ;AN000; Include find equates and MACROS +.list ; +.cref ; +;---------------------------; + +MSG_UTILNAME ;AN000; + +;-------------------------- +;- EQUATES +;-------------------------- +FALSE equ 0 +TRUE equ NOT FALSE + +CR equ 0dh ;A Carriage Return +LF equ 0ah ;A Line Feed +quote_char equ 22h ;A double quote character + + +buffer_size equ 4096 ;file buffer size +st_buf_size equ 128 ;string arg. buffer size +fname_buf_size equ 64 ;file name buffer size + + +;----- DOS EQUATES -----; +STDIN equ 0 ;AN000; Handle +STDOUT equ 1 ;AN000; Handle +STDERR equ 2 ;AN000; Handle + +GetCPSW equ 03303h ;AN000; Int 021h function call +GetExtAttr equ 05702h ;AN000; Int 021h function call +SetExtAttr equ 05704h ;AN000; Int 021h function call + +ERROR_ACCESS_DENIED equ 5 ;AN000; Int 021h error return + +CPSWActive equ 1 ;AN000; Indicates Code Page support is active +CPSWNotActive equ 0 ;AN000; Just the opposite + +ERRORLEVEL_ZERO equ 0 ;AN000; Termination error level +ERRORLEVEL_ONE equ 1 ;AN000; Termination error level +ERRORLEVEL_TWO equ 2 ;AN000; Termination error level + +;------------------------ +;- MESSAGE EQUATES +;------------------------ + +msg_file_not_found equ 2 ;AN000; File not found %s +msg_access_denied equ 5 ;AN000; Access denied %s +msg_read_error equ 30 ;AN000; Read error in %s +msg_inv_num_parm equ 2 ;AN000; Invalid number of parameters +msg_inv_parm equ 10 ;AN000; Invalid Parameter %s +msg_required_missing equ 2 ;AN005; Required parameter missing +msg_find equ 4 ;AN000; FIND: +msg_code_page_mismatch equ 37 ;AN005; Code Page mismatch +msg_switch equ 3 ;AN005; Invalid switch + +;----------------------- +;-- Parser equates +;----------------------- + +FarSW equ 0 ;AN000; +DateSW equ 0 ;AN000; +TimeSW equ 0 ;AN000; +FileSW equ 1 ;AN000; +CAPSW equ 1 ;AN000; +CmpxSW equ 0 ;AN000; +DrvSW equ 0 ;AN000; +QusSW equ 1 ;AN000; +NumSW equ 0 ;AN000; +KeySW equ 0 ;AN000; +SwSW equ 1 ;AN000; +Val1SW equ 0 ;AN000; +Val2SW equ 0 ;AN000; +Val3SW equ 0 ;AN000; + +;------------------------ +; SUBLIST Equates +;------------------------ +Left_Align equ 0 ;AN000; 00xxxxxx +Right_Align equ 80h ;AN000; 10xxxxxx + +Char_Field_Char equ 0 ;AN000; a0000000 +Char_Field_ASCIIZ equ 10h ;AN000; a0010000 + +Unsgn_Bin_Byte equ 11h ;AN000; a0010001 - Unsigned Binary to Decimal character +Unsgn_Bin_Word equ 21h ;AN000; a0100001 +Unsgn_Bin_DWord equ 31h ;AN000; a0110001 + +Sgn_Bin_Byte equ 12h ;AN000; a0010010 - Signed Binary to Decimal character +Sgn_Bin_Word equ 22h ;AN000; a0100010 +Sgn_Bin_DWord equ 32h ;AN000; a0110010 + +Bin_Hex_Byte equ 13h ;AN000; a0010011 - Unsigned Binary to Hexidecimal character +Bin_Hex_Word equ 23h ;AN000; a0100011 +Bin_Hex_DWord equ 33h ;AN000; a0110011 + +;------------------------------ +; EXTENDED ATTRIBUTE Equates +;------------------------------ +File_Type_None equ 00000000b ;AN001; unspecified file type +File_Type_Text equ 00100000b ;AN001; ASCII text file +File_Type_Rtl equ 00100001b ;AN001; ASCII text file in RTL + +EAISBINARY equ 02h ;AN001; ea_type +EASYSTEM equ 8000h ;AN001; ea_flags + +;--------------------------------------- +;-------------- CODE SEGMENT ----------- +;--------------------------------------- + +code segment public + assume cs:code + assume ds:nothing + assume es:nothing + assume ss:stack + + jmp start + +; +;-------------------- +.xlist +.xcref +INCLUDE parse.asm +.list +.cref +;-------------------- + + EXTRN heading:byte,heading_len:byte + +;********************************* +;* Extended Attribute Structures * +;********************************* +querylist struc ;AN001; ;query general list +qea_num dw 1 ;AN001; +qea_type db EAISBINARY ;AN001; +qea_flags dw EASYSTEM ;AN001; +qea_namelen db ? ;AN001; +qea_name db " " ;AN001; +querylist ends ;AN001; + +cp_qlist querylist <1,EAISBINARY,EASYSTEM,2,"CP"> ;AN001; ;query code page attr. + +cp_list label word ;AN001; ;code page attr. get/set list + dw 1 ;AN001; ; # of list entries + db EAISBINARY ;AN001; ; ea type + dw EASYSTEM ;AN001; ; ea flags + db ? ;AN001; ; ea return code + db 2 ;AN001; ; ea name length + dw 2 ;AN001; ; ea value length + db "CP" ;AN001; ; ea name +cp dw ? ;AN001; ; ea value (code page) +cp_len equ ($ - cp_list) ;AN001; + +;-------Save area for Code Pages +src_cp dw ? ;AN000; Save area for source code page +tgt_cp dw ? ;AN000; Save area for target code page +str_cp dw ? ;AN005; Save area for search string code page + + + +;----------------------- +;----- Misc Data ------ +bufferDB db 6 dup(0) ;AN006; +dbcs_off dw 0 ;AN006; +dbcs_seg dw 0 ;AN006; +dbcs_len dw 0 ;AN006; + +ccolon db ": " +n1_buf db "[" +n2_buf db 8 dup(0) ;buffer for number conversion + +errlevel db ERRORLEVEL_ZERO ;AN000; Errrorlevel save area + +;----- OPTION FLAGS ---- +; If a flag is set (0ffh) then the option has been selected, if +;reset (0) then it has been not. All options are reset initially. +; NOTE: the order of this table has to remain consistent with the +;options dispatch code. If any changes are made they have to +;correspond with the code. + +opt_tbl: + +v_flag db FALSE ;AN000; Set to FALSE +c_flag db FALSE ;AN000; Set to FALSE +n_flag db FALSE ;AN000; Set to FALSE + + +;----- LINE COUNTERS +mtch_cntr dw 0 ;matched lines counter +line_cntr dw 0 ;line counter + +;------------------------------------------- +;- MESSAGE RETRIEVER SUBSTITUTION LIST +;------------------------------------------- + +MSG_SERVICES ;AN000; + +sublist label dword ;AN000; +sl_size db 11 ;AN000; SUBLIST Size, in bytes +sl_res db 0 ;AN000; reserved +sl_ptr_o dw ? ;AN000; Offset PTR to data item +sl_ptr_s dw ? ;AN000; Segment PTR to data item +sl_n db 0 ;AN000; n of %n +sl_flag db ? ;AN000; Data-Type flags +sl_maxw db 0 ;AN000; Max width +sl_minw db 0 ;AN000; Min width +sl_pad db ' ' ;AN000; Pad character + + +parm db ? ;AN000; Save area for invalid parm +cpsw_state db CPSWNotActive ;AN000; Save area indicating state of Code Page Support + +;****************************************************************************** +;* PARSER DATA STRUCTURES FOLLOW +;****************************************************************************** + +parms label byte ;AN000; + dw parmsx ;AN000; POINTER TO PARMS STRUCURE + db 1 ;AN000; DELIMITER LIST FOLLOWS + db 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS + db ";" ;AN000; ADDITIONAL DELIMITER + +parms1 label byte ;AN005; + dw parmsx1 ;AN005; POINTER TO PARMS STRUCURE + db 1 ;AN005; DELIMITER LIST FOLLOWS + db 1 ;AN005; NUMBER OF ADDITIONAL DELIMITERS + db ";" ;AN005; ADDITIONAL DELIMITER + +;------------------------------ +;- STRUCTURE TO DEFINE FIND SYNTAX REQUIREMENTS +;------------------------------ +parmsx label word ;AN000; + db 1,2 ;AN000; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS + dw pos1 ;AN000; POINTER TO POSITIONAL DEFINITION AREA + dw pos2 ;AN000; POINTER TO POSITIONAL DEFINITION AREA + db 1 ;AN000; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N" + dw sw1 ;AN000; POINTER TO FIRST SWITCH DEFINITION AREA + dw 0 ;AN000; THERE ARE NO KEYWORDS IN FIND SYNTAX + +parmsx1 label word ;AN005; + db 0,0 ;AN005; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS + db 1 ;AN005; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N" + dw sw1 ;AN005; POINTER TO FIRST SWITCH DEFINITION AREA + dw 0 ;AN005; THERE ARE NO KEYWORDS IN FIND SYNTAX + + ;------------------------------ + ;- STRUCTURE TO DEFINE POSITIONAL PARM + ;------------------------------ +pos1 label word ;AN000; + dw 0080h ;AN000; QUOTED STRING, REQUIRED + dw 0000h ;AN000; NO CAPITALIZE + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 0 ;AN000; NO KEYWORDS + + ;------------------------------ + ;- STRUCTURE TO DEFINE POSITIONAL PARM + ;------------------------------ +pos2 label word ;AN000; + dw 0203h ;AN000; FILE NAME, OPTIONAL, REPEATS ALLOWED + dw 0001h ;AN000; CAPITALIZE BY FILE TABLE + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 0 ;AN000; NO KEYWORDS + + + ;------------------------------ + ;- STRUCTURE TO DEFINE THE SWITCHES + ;------------------------------ +sw1 label word ;AN000; + dw 0 ;AN000; NO MATCH FLAGS + dw 2 ;AN005; capitalize + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 3 ;AN000; THREE SWITCHES IN FOLLOWING LIST +n_swch db "/N",0 ;AN000; +v_swch db "/V",0 ;AN000; +c_swch db "/C",0 ;AN000; + + + ;------------------------------ + ;- VALUE LIST DEFINITION FOR NO VALUES + ;------------------------------ +novals label word ;AN000; + db 0 ;AN000; VALUE LIST + + + ;------------------------------ + ;- RETURN BUFFER FOR POSITIONAL PARAMETERS + ;------------------------------ +ret_buff label word ;AN000; +rb_type db ? ;AN000; TYPE RETURNED +rb_item_tag db ? ;AN000; SPACE FOR ITEM TAG +rb_synonym dw ? ;AN000; ES:rb_synonym points to synonym +rb_value_lo dw ? ;AN000; SPACE FOR VALUE +rb_value_hi dw ? ;AN000; SPACE FOR VALUE + + + + +did_file db FALSE ;AN004; if true then already processed a file +got_eol db FALSE ;AN004; if false then possibly more filenames on command line +got_filename db FALSE ;AN004; if true then parser found a filename on command line +got_srch_str db FALSE ;AN000; if true then parser found search string on command line +ordinal dw 0 ;AN000; parser ordinal +crlf db CR,LF ;AN000; + + +; +;************************************************************ +;* +;* SUBROUTINE NAME: main +;* +;* SUBROUTINE FUNCTION: +;* Process the command line. If there are no errors, then open +;* the specified files, search for string, display it to the +;* standard output device. +;* +;* INPUT: Command line (described in program header) +;* +;* OUTPUT: +;* Files will be opened and read in. Regardless of the command +;* line parameters entered by the user, output will be written +;* to the standard output device handle 1. +;* +;* NORMAL EXIT: +;* File(s) opened (if not STDIN), read successfully, and closed. +;* Display requested information. +;* +;* ERROR CONDITIONS: +;* Incorrect DOS version +;* Invalid number of parameters +;* Syntax error +;* Access denied +;* File not found +;* Invalid Parameter +;* Read error in +;* +;* INTERNAL REFERENCES: +;* bin2asc +;* clr_cntrs +;* is_prefix +;* next_kchar +;* print_count +;* prout +;* prt_err +;* prt_err_2 +;* prt_file_name +;* prt_lcntr +;* +;************************************************************************** + + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN003; Make retriever services available +START: + + mov ax,cs ;load ES to the right area, + mov es,ax ; + mov ds,ax ; + + call sysloadmsg ;AN000; Preload messages, Check DOS Version. + jnc Set_for_parse ;AN000; If no error, parse command line + + call prt_find ;AN005; + call sysdispmsg ;AN005; + + mov ah,Exit ;AN000; Terminate new way + mov al,0 ;AN000; Errorlevel 0 (Compatible!) + int 021h ;AN000; Bye bye! + +;----------------------------------- +;- DOS version is ok. Parse cmd line +;----------------------------------- +Set_for_parse: + call get_dbcs_vector ;AN006; ;Get DOS dbcs table vector +; + mov ah,GetCurrentPSP ;AN000; Get PSP address, returned in BX + int 021h ;AN000; + mov ds,bx ;AN000; Put PSP Seg in DS + mov si,081h ;AN000; Offset of command line in PSP + xor cx,cx ;AN000; Number of args processed so far = 0 + mov cs:ordinal,cx ;AN000; init parser ordinal + +;-------------------------------------- +; See if there was nothing entered +;-------------------------------------- + cmp byte ptr ds:080h,0 ;AN000; Check length of command line, + jne p_parse ;AN005; Go process the parameters + mov ax,msg_inv_num_parm ;AN000; No parms, too bad! + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell the unfortunate user +p_parse: + mov cs:got_filename,FALSE ;AN004; input file default is STDIN + + push cs ;A0005; ensure es is correct + pop es ;AN005; + + call clr_cntrs ;AN005; set all counters to zero + mov cx,cs:ordinal ;AN005; init parser ordinal + call pre_parse ;AN005; +PARSER: + push cs ;A0000; ensure es is correct + pop es + + call clr_cntrs ; set all counters to zero + mov cx,cs:ordinal ;AN000; init parser ordinal + call parse ;AN000; Parse command line + + push si ;AN000; Save ptr to remaining command line + push ds + + push cs ;Load new DS with CS + pop ds + mov cs:ordinal,cx ;AN000; Save parser ordinal + +;--------------------- +; get filespec size +;--------------------- + mov cs:file_name_buf,di ;save buffer offset from parser + xor bx,bx ;AN000;indicate no save again + call get_length ;AN000;get filespec length + mov es:file_name_len,ax ;save the name length + +;--------------------- +;- Check current state of CPSW +;--------------------- +save_src_cp: + mov ax,GetCPSW ;AN000; Get CPSW state, assume support is OFF + int 021h ;AN000; DL: 0=NotSupported,1=Supported + jc open_read ;AN000; If error, assume CPSW inactive + mov cs:cpsw_state,dl ;AN000; Save current state + and dl,dl ;AN007; ;AN000; If inactive, (same as CMP dl,0) + je open_read ;AN000; do nothing + +;-------Code Page Switching is loaded and active! +;-------Save codepage of target handle ---------- + mov bx,STDOUT ;AN000; For Standard output device + call get_cp ;AN000; Get the current codepage + jc open_read ;AN000; Error condition + mov ax,cs:cp ;AN000; Save target code page + mov cs:tgt_cp,ax ;AN000; for later reference + xor bx,bx ;AN007; ;AN005; bx=STDIN. For search string + call get_cp ;AN005; Get the code page + jc open_read ;AN005; Error condition + mov ax,cs:cp ;AN005; Save code page value + mov cs:str_cp,ax ;AN005; .. + +;--------------------- +;- OPEN FILE FOR READING +;--------------------- +open_read: + push cs ;Load new DS with CS + pop ds + cmp cs:got_filename,TRUE ;AN004; using STDIN + je o_cont ;AN004; no, open the file + xor ax,ax ;AN007; ;AN004; file handle (ax) = STDIN + jmp short cp_check ;AN007; ;AN004; skip open of file +o_cont: ;AN004; + mov dx,cs:file_name_buf ;AC000;addrss. of the file name +openit: + mov ah,open + mov al,0 ;file open for reading + int 021h ;call the DOS + ljc do_open_error ;AN000; +;-------Open was successful. Make sure codepages are the same +cp_check: + cmp cs:cpsw_state,CPSWNotActive ;AN000; Is Code Page support active + je say_name ;AN000; No, continue + + push ax ;AN000; Save source handle + mov bx,ax ;AN000; Source handle in BX + call get_cp ;AN000; Get codepage of source file + + mov ax,cs:cp ;AN000; Place source CP in ax + cmp ax,cs:str_cp ;AN005; search string code page = src file code page ? + je c_cont ;AN005; yes, they are the same, ok + and ax,ax ;AN007; ;AN005; src filename cp = 0 + je c_cont ;AN005; yes, this cp=0 is ok. + mov ax,msg_code_page_mismatch ;AN005; Error, code page mismatch + mov dh,1 ;AN005; message class + call display_and_die ;AN005; bye! +c_cont: + cmp ax,cs:tgt_cp ;AN000; Is same as target cp ? + je cp_match ;AN000; Yes? Do nothing + + mov bx,STDOUT ;AN000; Standard output device + call set_cp ;AN000; Set codepage to that of source +cp_match: + pop ax ;AN000; Restore handle +;--------------------- +;- PRINT FILE NAME +;--------------------- +say_name: + push ax ;save file handle + cmp cs:got_filename,FALSE ;AN004; using STDIN + je xx1 ;AN004; yes, don't print a filename + mov dx,offset heading + mov cl,cs:heading_len + xor ch,ch + call prout + + mov dx,cs:file_name_buf ;AC000; + mov cx,cs:file_name_len + call prout + + cmp cs:c_flag,TRUE ;count only flag set? + je xx1 + + mov dx,offset crlf + mov cx,2 + call prout +xx1: + pop ax + +;--------------------- +;- Fill Buffer for Matching +;--------------------- +fill: + mov bx,ax ;retrieve handle +refill: + mov dx,offset buffer ;data buffer addrss. + mov cx,buffer_size + mov ah,read + int 021h + jnc no_read_error ;if carry then read error + jmp read_error +no_read_error: + or ax,ax ;if ax=0 then all done + jnz Truncate +DoNullRead: + cmp cs:c_flag,TRUE ;count only flag set? + jne sj2 + call print_count +sj2: + and bx,bx ;Using STD IN? + jnz regular + jmp foo ;if so: all done, exit +regular: + mov ah,close ;otherwise close the file + int 021h + jmp scan_rest ;get another file + +do_open_error: + jmp open_error ;AN000; +;--------------------------- +; We have read in an entire buffer. Scan for a ^Z and terminate the buffer +; there. Change only CX +;--------------------------- +Truncate: + push di + push cx + push es + mov di,dx + mov cx,ax + mov ax,ds + mov es,ax + mov al,1Ah + CLD + repnz scasb +;--------------------------- +; If zero is set, the the previous character is a ^Z. If it is reset then +; the previous character is the end of buffer. With ^Z, we back up over the +; char. +;--------------------------- + jnz chop + dec di +chop: + mov ax,di + sub ax,dx ; get true length of buffer + pop es + pop cx + pop di + or ax,ax + jz DoNullRead + +;--------------------------- +;----- MATCH ROUTINE +;--------------------------- +;Note: If input is being taken from a file the stack contains +; (from top to bottom): +; - Pointer to the next command in the command line +; - Pointer to the program segment prefix (to be loaded into +; DS to access the command line. +; if the input is from the standard input then NONE of it will be +; in the stack. +;--------------------------- + +go_match: + push bx ;save the file handle + mov bp,offset buffer ;ptr to first line of file +;--------------------------- +; At this point we must check to make sure there is AT LEAST one LF in the +; buffer. If there is not, then we must insert one at the end so we +; don't get stuck trying to get one complete line in the buffer when +; we can't cause the buffer ain't big enough. +;--------------------------- + push ax ; Save true buffer size + mov cx,ax ; scan whole buffer + mov al,LF ; for a LF + mov di,bp ; start of buffer + repnz scasb + pop ax ; recover buffer size + mov di,ax ;displacement from beg of buffer + jnz last_line ; No line feeds, must insert one +;--------------------------- +; Check to see if we reached EOF (return from READ less than buffer_size). +; If EOF we must make sure we end with a CRLF pair. +;--------------------------- + cmp ax,buffer_size-1 ;last line of the file? + jg no_last_line ;nope +last_line: ;if yes, add a CRLF just in case + mov bx,bp + cmp byte ptr[bx+di-1],LF ;finished with a LF? + je no_last_line ;yes, it's an OK line. + mov byte ptr[bx+di],CR ;put a CR at the end of the data + inc di + mov byte ptr[bx+di],LF ;put a LF ... + inc di + +no_last_line: + push di ;save the # of chars. in the buffer + push bp + mov dx,cs:st_length ;length of the string arg. + dec dx ;adjust for later use + jmp short try_again + +more_stuff_o: + jmp more_stuff + +;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------; +;Note: at this point the stack contains (from top to bottom): +; - Stuff mentioned before +; - File Handle +; - Number of chars. left in the buffer from the next line. +; - Addrs. of the next line in the buffer. +; +; plus, DX has the adjusted length of the string argument. +; +; We are about to begin scanning a line. We start by determining if there is +; a complete line in the buffer. If so, we scan for the char. If NOT, we go +; and grab new info. +;--------------------------- +try_again: + pop bp ;addrs. of next line in the buffer + mov di,bp ;points to beg. of a line + pop cx ;get # of chars left in the buffer + mov bx,cx ;save in case a non-complete line + mov al,LF ;search for a Line Feed + jcxz more_stuff_o ;no chars left in buffer + repnz scasb + jnz more_stuff_o ;no full line left in buffer + push cx ;save chars left in buffer + push di ;points to beg. of next line + mov cx,di + sub cx,bp ;length of the current line + mov bx,cx ;save in case it has a match + dec cx ;Discount the LF we found + cmp byte ptr ES:[DI-2],CR ; Is there a CR to discount too? + jnz NO_SECOND_DEC ; No there is not. + dec cx ;CR character discounted +NO_SECOND_DEC: + inc cs:line_cntr ;increment line counter + jcxz try_again_opt ;if line empty go to next line + mov di,bp ;pointer to the beg. of current line +another_char: +;--------------------------- +; On entry: +; BX line length +; CX adjusted line length +; DX adjusted string argument length +; DI points to beg. of line +;--------------------------- + push dx ;save for next line +lop: + pop dx + push dx + inc dx ;different algorithm! + mov si,offset st_buffer ;pointer to beg. of string argument + +comp_next_char: + push di + mov di,si + call is_prefix ;check for a prefix char + pop di + jnc nopre + lodsw + cmp cx,1 ; Can not compare a two byte char + jbe try_again_opt1 ; if there is only one available + cmp ax,word ptr [di] + jz kmatch1 + jmp short back_up ;AN007; + +nopre: + lodsb + cmp al,byte ptr [di] + jz kmatch +back_up: + pop ax ; Original length of comp string + push ax + inc ax +;--------------------------- + ; Our match failed IN THE MIDDLE of the string (partial match). We need + ; to back up in the line to the NEXT char after the one which matched + ; the first char of the search string and try again. The amount to + ; back up to where we started is ax-dx (the result MAY be 0, this is OK). + ; we then need to skip ONE char in the line. +;--------------------------- + sub ax,dx ; AX = AX-DX + sub di,ax ; Do the back up. + add cx,ax ; restore count too! + call next_kchar ;no match, advance di to next kanji + jc try_again_opt1 ;not enough chars left in line + jmp short lop ;try another char in line + +try_again_opt1: + pop dx + jmp short try_again_opt ;AN007; + + +kmatch1: + dec dx ;last char had prefix so it was + ; long. +kmatch: + dec dx + jz a_matchk ; no chars left: a match! + call next_kchar + jc try_again_opt1 + jmp comp_next_char ; loop if chars left in arg. + +a_matchk: + pop dx + cmp cs:v_flag,TRUE ;is flag set? + jne prt_line ;no, print the line + jmp try_again + +;--------------------------- +;- NO MATCH: CHECK FOR THE v OPTION +;--------------------------- +try_again_opt: + cmp cs:v_flag,TRUE ;is flag set? + jne try_again ;no goto next line + +;--------------------------- +;- PRINT THE LINE WITH THE MATCH +;Note: at this point the stack contains (top to bottom) +; - Stuff mentioned before +; +; plus, BP points to begginig of the current line, BX has the length +;of the current line including the CRLF, and DX the adjusted length of +;the string argument. +;--------------------------- + +prt_line: + cmp cs:c_flag,TRUE ;is count only flag set? + jne no_c_flg + inc cs:mtch_cntr ;yes, increment counter + jmp try_again + +no_c_flg: + push dx ;save the adjusted string arg. length + cmp cs:n_flag,TRUE ;is line number flag set? + jne no_n_flg + call prt_lcntr +no_n_flg: + mov dx,bp + mov cx,bx + call prout + pop dx ;restore + jmp try_again + +;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------; +; The scanning routines have detected that the buffer does not +;contain a full line any more. More lines have to be read into the +;buffer. But first perform a seek on the file in order to re-read +;the non-complete line into the begining of the buffer. +; Uppon entry BP contains points to the begining of the non-complete +;line, and BX has the number of characters left in the buffer. +; The Stack contains (top to bottom): +; - Pointer to the next command in the command line +; - Pointer to the program segment prefix (to be loaded into +; DS to access the command line). +; - File handle. + +more_stuff: + mov dx,bx ;get chars left in buffer + pop bx ;get the handle + or dx,dx ;are there 0 left? + jz no_seek ;yes, do not seek + neg dx ;form two's complement + mov cx,-1 + mov al,1 ;seek from the current position + mov ah,lseek ;seek on file + int 021h + jc read_error +no_seek: + jmp refill ;no errors: refill the buffer +read_error: + and bx,bx ;AN007; ;Using STD IN? + je foo ;if so: all done, exit + mov ah,close ;close the file + int 021h +;--------------- +;------ Set message number and go display it + + mov ax,msg_read_error ;AN000; Read error message + jmp short r_error ;AN007; + +;--------------------- +;- PRINT ERRORS +;--------------------- +open_error: + cmp ax,ERROR_ACCESS_DENIED ;AN000; + jnz DoNorm + + mov ax,msg_access_denied ;AN000; Message for Access Denied + jmp short r_error ;AN007; ;AN000; Do the rest + +DoNorm: ;AN000; + mov ax,msg_file_not_found ;AN000; Message for File Not Found + +r_error: + call prt_find ;AN005; + mov cs:sl_ptr_s,ds ;AN000; Save segment of subst text + mov cx,cs:file_name_buf ;AN000; + mov cs:sl_ptr_o,cx ;AN000; Save offset of subst text + mov cs:sl_flag,left_align+char_field_ASCIIZ ;AN000; Type of insertion text + mov bx,STDERR ;AN000; Sent to STD OUT + mov cx,1 ;AN000; One substitution string + mov dh,1 ;AN000; Its a utility message + + call display_msg ;AN000; Display rror message + +;--------------------- +;- SCAN THE REST OF THE COMMAND LINE +;--------------------- +scan_rest: + pop ds ;restore pointer to comm. line + pop si ;restore pointer to next comm. + mov cs:did_file,TRUE ;AN004; tell parser we did a file, so if it doesn't find another, ok! + cmp cs:got_eol,TRUE ;AN004; Check if nothing left on command line + je foo ;AN004; no, nothing left on command line, exit + jmp parser + +foo: + mov cs:errlevel,ERRORLEVEL_ZERO ;AN000; Proper code + call terminate ;AN000; reset codepage and terminate + + +;-------------------------- +; Clear Counters +;-------------------------- +clr_cntrs proc near + mov byte ptr cs:mtch_cntr,0 + mov byte ptr cs:line_cntr,0 + ret +clr_cntrs endp + + +;-------------------------- +; Print Count of Matched lines +; Modifies: AX,CX,DX and DI +;-------------------------- +print_count proc near + push bx ;save handle + and bx,bx ;AN007; ;using STDIN? + jz sj3 ;if so do not print file name + + mov dx,offset ccolon + mov cx,2 + call prout ;print colon +sj3: + mov ax,cs:mtch_cntr + mov di,offset n2_buf ;buffer for characters + call bin2asc ;convert to ascii + mov dx,offset n2_buf + call prout ;print the number + mov dx,offset crlf + mov cx,2 + call prout ;print an end of line + pop bx + ret +print_count endp + +;-------------------------- +; Print relative line number + +; Modifies: AX,CX and DI +;-------------------------- +prt_lcntr proc near + push bx + push dx + mov ax,cs:line_cntr + mov di,offset n2_buf + call bin2asc + mov byte ptr[di],"]" + inc cx + inc cx + mov dx,offset n1_buf + call prout + pop dx + pop bx + ret +prt_lcntr endp + +;-------------------------- +; Print string to STDOUT +;-------------------------- +prout proc near + mov bx,STDOUT + mov ah,write + int 021h + ret +prout endp + +;-------------------------- +; Binary to Ascii conversion routine +; Entry: +; AX Binary number +; DI Points to one past the last char in the +; result buffer. +; Exit: +; Result in the buffer MSD first +; CX Digit count +; Modifies: +; AX,BX,CX,DX and DI +;-------------------------- +bin2asc proc near + mov bx,0ah + xor cx,cx +go_div: + inc cx + cmp ax,bx + jb div_done + xor dx,dx + div bx + add dl,'0' ;convert to ASCII + push dx + jmp short go_div + +div_done: + add al,'0' + push ax + mov bx,cx +deposit: + pop ax + stosb + loop deposit + mov cx,bx + ret +bin2asc endp + +;-------------------------- +; CAPIALIZES THE CHARACTER IN AL +; entry: +; AL has the character to Capitalize +; exit: +; AL has the capitalized character +; modifies: +; AL +;-------------------------- +;make_caps proc near +; cmp al,'a' +; jb no_cap +; cmp al,'z' +; jg no_cap +; and al,0dfh +;no_cap: +; ret +;make_caps endp +; + + +;-------------------------- +; ADVANCE POINTER TO NEXT KANJI CHARACTER +; entry: DI points to a Kanji string +; CX length in bytes of the string +; exit: DI points to next Kanji char +; CX has number of bytes left +; modifies: AX +;-------------------------- +next_kchar proc near + jcxz no_kleft + call is_prefix + jnc no_p + inc di + dec cx + jcxz no_kleft ; for insurance +no_p: + inc di + dec cx + clc + ret + +no_kleft: + stc + ret +next_kchar endp + +;-------------------------- +; Get DOS dbcs table vector +; entry: none +; exit: none +; modifies: none +;-------------------------- +get_dbcs_vector proc near ;AN006; + push es ;AN006; + push di ;AN006; + push ax ;AN006; + push bx ;AN006; + push cx ;AN006; + push dx ;AN006; +; + mov ax,cs ;AN006; ;segment of return buffer + mov es,ax ;AN006; + mov di,offset bufferDB ;AN006; ;offset of return buffer + mov ah,65h ;AN006; ;get extended country info + mov al,07h ;AN006; ;get DBCS environment table + mov bx,0ffffh ;AN006; ;use active code page + mov cx,5 ;AN006; ;number of bytes returned + mov dx,0ffffh ;AN006; ;default country ID + int 21h ;AN006; ;DOS function call,vector returned + ;AN006; ; in ES:DI + inc di ;AN006; ;skip over id byte returned + mov ax,word ptr es:[di] ;AN006; ;get offset of DBCS table + mov cs:dbcs_off,ax ;AN006; ;save it +; + add di,2 ;AN006; ;skip over offset to get segment + mov bx,word ptr es:[di] ;AN006; ;get segment of DBCS table + mov cs:dbcs_seg,bx ;AN006; ;save it +; + mov di,ax ;AN006; ;Point to DBCS table to get length + mov es,bx ;AN006; + mov ax,word ptr es:[di] ;AN006; + mov cs:dbcs_len,ax ;AN006; + add cs:dbcs_off,2 ;AN006; ;change offset to point to table +; + pop dx ;AN006; + pop cx ;AN006; + pop bx ;AN006; + pop ax ;AN006; + pop di ;AN006; + pop es ;AN006; +; + ret ;AN006; +get_dbcs_vector endp ;AN006; + + +;-------------------------- +; FIND OUT IS THE BYTE IS A KANJI PREFIX +; entry: DI points to a kanji string +; exit: Carry set if it is a kanji prefix +; modifies: AX +;-------------------------- +is_prefix proc near ;AN006; + push es + push si + push ax +; + mov si,cs:dbcs_off ;ES:SI -> DOS dbcs table + mov ax,cs:dbcs_seg + mov es,ax +; + mov al,byte ptr cs:[di] ;get first byte of string +; +; Two consecutive 00 bytes signifies end of table +; + +is_loop: + cmp word ptr es:[si],00h ;Check for two consecutive 00 bytes + jne is_next1 ;no, continue + clc ;clear carry - byte is not lead byte of db char + jmp short is_exit ;AN007; ;yes, found them, quit + +; +; Check if byte is within range values of DOS dbcs table +; + +is_next1: + cmp al,byte ptr es:[si] ;is byte >= first byte in range? + jae is_next2 ;yes, continue + jmp short is_again ;AN007; ;no, loop again + +is_next2: + cmp al,byte ptr es:[si+1] ;is byte <= last byte in range? + jbe is_found ;yes, found a lead byte of db char + +is_again: + add si,2 ;no, increment ptr to next range + jmp is_loop + +is_found: + stc ;byte is lead byte of db char, set carry + +is_exit: + pop ax + pop si + pop es +; + ret +is_prefix endp + + +; +;--------------------- +;- Terminate process +;--------------------- +terminate proc near ;AN000; + mov ah,exit ;AN000; Terminate function call + mov al,cs:errlevel ;AN000; Errorlevel placed in AL + int 021h ;AN000; Terminate + ret ;AN000; Meaningless return +terminate endp ;AN000; + +; +;************************************************************ +;* +;* SUBROUTINE NAME: set_cp +;* +;* FUNCTION: Sets the cp of the handle in bx to the cp in LIST structure +;* +;* INPUT: +;* BX = handle +;* cp_list.cp = code page to set for the file handle in BX +;* +;* OUTPUT: +;* Codepage will be set to that requested, or an error will be +;* returned in AX with carry flag set. +;* +;************************************************************ +set_cp proc near ;AN000; + mov ax,SetExtAttr ;AN000; Set target codepage to that of source + mov di,offset cp_list ;AC001; Input buffer address + int 021h ;AN000; Call DOS + ret ;AN000; Return to caller +set_cp endp ;AN000; + + + +;************************************************************ +;* +;* SUBROUTINE NAME: get_cp +;* +;* FUNCTION: Gets the cp of the handle in bx +;* +;* INPUT: +;* BX = handle +;* +;* OUTPUT: +;* Codepage for the file handle in bx will be returned in +;* the CP_LIST.CP structure, or an error will be returned in +;* AX with carry flag set. +;* +;************************************************************ +get_cp proc near ;AN000; + push ds ;AN005; + + push cs ;AN005; + pop ds ;AN005; + + mov ax,GetExtAttr ;AN000; Get codepage + mov di,offset cp_list ;AN000; Input buffer address + mov si,offset cp_qlist ;AN001; which ea to select + mov cx,cp_len ;AN001; buffer length + int 021h ;AN000; Call to DOS + + pop ds ;AN005; + ret ;AN000; Return to caller +get_cp endp ;AN000; + + +; +;************************************************************ +;* +;* SUBROUTINE NAME: display_msg +;* +;* SUBROUTINE FUNCTION: +;* Display the requested message to the specified handle +;* +;* INPUT: +;* 1) AX = Number of the message to be displayed. +;* 2) BX = Handle to be written to. +;* 3) DH = Code indicating message class +;* +;* OUTPUT: +;* The message corresponding to the requested msg number will +;* be written to the requested handle. +;* +;* NORMAL EXIT: +;* Message will be successfully written to requested handle. +;* +;* ERROR EXIT: +;* None. Note that theoretically an error can be returned from +;* SYSDISPMSG, but there is nothing that the application can do. +;* +;* INTERNAL REFERENCES: +;* System Display Message service routines +;* +;* EXTERNAL REFERENCES: +;* None +;* +;************************************************************ +display_msg proc near ;AN000; + push ds ;AN000; Save DS + push cs ;AN000; Substitution list segment + pop ds ;AN000; + mov si,offset sublist ;AN000; Substitution list offset + ; mov dh,-1 ;AN000; Message class + ; 1=DOS Extended error + ; 2=DOS Parse error + ; -1=Utility message + mov dl,0 ;AN000; DOS INT 21H function number to use for input + ; 00H=No input, 01H=Keyboard input, + ; 07H=Direct Console Input Without Echo, + ; 08H=Console Input Without Echo, 0AH=Buffered Keyboard Input + call SYSDISPMSG ;AN000; AX=Extended key value if wait for key + ; jnc disp_done ;AN000; If CARRY SET then registers will contain extended error information + ; AX - Extended error Number + ; BH - Error Class + ; BL - Suggested action + ; CH - Locus +disp_done: ;AN000; + pop ds ;AN000; Restore DS + ret ;AN000; +display_msg ENDP ;AN000; + + PAGE +;************************************************************ +;* +;* SUBROUTINE NAME: parse +;* +;* SUBROUTINE FUNCTION: +;* Call the DOS PARSE Service Routines to process the command +;* line. Search for valid switches (/N, /V, and /C) and take +;* appropriate action for each. Extract the search string. +;* +;* INPUT: DS:SI points to string to parse +;* ES:DI parser parms +;* +;* OUTPUT: ES:DI points to filespec for text search +;* +;* NORMAL EXIT: +;* +;* If /V, /C, or /N entered, set appropriate flag. +;* Save the search string. +;* +;* ERROR EXIT: +;* +;* If user enters any invalid parameter or switch, then this +;* routine will display an error message and terminate with +;* errorlevel 1. +;* +;************************************************************ +EOL equ -1 ;AN000; Indicator for End-Of-Line +NOERROR equ 0 ;AN000; Return Indicator for No Errors +SYNTAX equ 9 ;AN000; Syntax error from parser + +SWITCH equ 3 ;AN000; +FILESPEC equ 5 ;AN000; +QUOTED_STRING equ 9 ;AN000; + +parse proc near ;AN000; +;-------------------------------------- +; address of command line in DS:SI +;-------------------------------------- +;------------------------------------------ +;- Look for the search string and switches +;------------------------------------------ +parse_loop: ;AN000; + mov di,offset parms ;AN000; Address of parse control block at ES:DI + xor dx,dx ;AN000; Reserved + call sysparse ;AN000; Parse parm at DS:SI + cmp ax,EOL ;AN000; Are we at End Of Line ?? + jne p_next ;AN004; No eol found + mov cs:got_eol,TRUE ;AN004; no more filenames to get! + cmp cs:did_file,TRUE ;AN004; did we do a file already ? + lje doexit ;AN004; yes, exit + jmp end_parse ;AN004; Yes, done here +p_next: ;AN004; continue + and ax,ax ;AN007; ;AN000; Was there an error? + je CONT2 ;AN000; No, continue processing + + mov dh,2 ;AN005; Its a PARSE message + call display_and_die ;AN005; +CONT2: ;AN000; Something valid was entered + cmp cs:rb_type,QUOTED_STRING ;AN000; Is it a quoted string ? + je its_a_quoted_string ;AN000; Yes, go process it + cmp cs:rb_type,FILESPEC ;AN000; Is it a filespec? + jne cont3 ;AN000; + mov di,cs:rb_value_lo ;AN000; Look for another + mov cs:got_filename,TRUE ;AN004; got a filename + jmp short end_parse ;AN007; ;AN000; Look for another +cont3: + cmp cs:rb_type,SWITCH ;AN000; Is it a switch ? + je its_a_switch ;AN000; Yes, go process it + mov ax,msg_inv_parm ;AN000; None of above, too bad + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell the poor user and terminate + +;----------------------------- +;- The search string was entered +;----------------------------- +its_a_quoted_string: ;AN000; Found a quoted string + cmp cs:got_srch_str,TRUE ;AN000; Do we already have one? + jne its_ok ;AN000; No, it's ok + mov ax,msg_inv_parm ;AN000; Yes, Invalid parm! + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell user and die gracefully +its_ok: ;AN000; + mov di,cs:rb_value_lo ;AN000; Get pointer to it + mov bx,offset st_buffer ;AN000; save buffer offset + call get_length ;AN000; get string length + mov cs:st_length,ax ;AN000; save length + mov cs:got_srch_str,TRUE ;AN000; Indicate that we have it + jmp parse_loop ;AN000; + +;----------------------------- +;- A valid switch was entered +;----------------------------- +its_a_switch: ;AN000; + mov bx,cs:rb_synonym ;AN000; Get offset of switch entered + cmp bx,offset n_swch ;AN000; Is it the /N switch? + jne chek_v ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +chek_v: ;AN000; + cmp bx,offset v_swch ;AN000; Is it the /N switch? + jne chek_c ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +chek_c: ;AN000; + cmp bx,offset c_swch ;AN000; Is it the /N switch? + jne whoops ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +whoops: ;AN000; None of the above (can we ever get here?) + mov ax,msg_switch ;AN000; Invalid parameter + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Yes, tell the poor user and terminate + +end_parse: ;AN000; A filename should be next + cmp cs:got_srch_str,TRUE ;AN000; Do we already have one? + je rett ;AN000; + mov ax,msg_required_missing ;AN005; + mov dh,-1 ;AN005; message class + call display_and_die ;AN000; Yes, tell the poor user and terminate +rett: ;AN000; + ret ;AN000; + +doexit: + mov cs:errlevel,ERRORLEVEL_ZERO;AN000; Proper code + call terminate ;AN000; reset codepage and terminate + +parse endp ;AN000; + + +;------------------------------------ +;- +;- Procedure name: pre_parse +;- +;- Purpose: parse for all switches now +;- so that they can be applied for +;- all filenames on command line. +;- +;- INPUT: none +;- +;------------------------------------ +pre_parse proc near ;AN005; + push ax ;AN005; + push bx ;AN005; + push cx ;AN005; + push dx ;AN005; + push di ;AN005; + push si ;AN005; + push es ;AN005; + push ds ;AN005; +; +pp_loop: ;AN005; + mov di,offset parms1 ;AN005; Address of parse control block at ES:DI + xor dx,dx ;AN005; Reserved + call sysparse ;AN005; Parse parm at DS:SI + + cmp ax,EOL ;AN005; Are we at End Of Line ?? + je pp_end ;AN005; No eol found + + cmp ax,SWITCH ;AN005; invalid switch ? + jne pp_next ;AN005; no +; error + mov ax,msg_switch ;AN005; Invalid switch + mov dh,2 ;AN005; message class + call display_and_die ;AN005; Yes, tell the poor user and terminate +pp_next: + and ax,ax ;AN007; ;AN005; Was there an error? + jne pp_loop ;AN005; No, continue processing + + cmp cs:rb_type,SWITCH ;AN005; Is it a switch ? + jne pp_loop ;AN005; + +; got a switch + mov bx,cs:rb_synonym ;AN005; Get offset of switch entered + cmp bx,offset n_swch ;AN005; Is it the /N switch? + jne pp_chek_v ;AN005: Yes, process it. + mov cs:n_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another +pp_chek_v: ;AN005; + cmp bx,offset v_swch ;AN005; Is it the /N switch? + jne pp_chek_c ;AN005: Yes, process it. + mov cs:v_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another +pp_chek_c: ;AN005; + cmp bx,offset c_swch ;AN005; Is it the /N switch? + jne pp_error ;AN005: Yes, process it. + mov cs:c_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another + +pp_error: ;AN005; None of the above (can we ever get here?) + mov ax,msg_switch ;AN005; Invalid parameter + mov dh,2 ;AN005; message class + call display_and_die ;AN005; Yes, tell the poor user and terminate + +pp_end: ;AN005; A filename should be next + pop ds ;AN005; + pop es ;AN005; + pop si ;AN005; + pop di ;AN005; + pop dx ;AN005; + pop cx ;AN005; + pop bx ;AN005; + pop ax ;AN005; +; + ret ;AN005; +pre_parse endp ;AN005; + + +;------------------------------------ +;- +;- Procedure name: prt_find +;- +;- Purpose: When FIND is used as a filter, +;- then display error messages with the +;- prefix: "FIND: ". +;- +;- INPUT: none +;- +;------------------------------------ +prt_find proc near ;AN005; + cmp cs:got_filename,TRUE ;AN005; Check if should print "FIND:" + je prt_ret ;AN005; + push ax ;AN005; Save error + push dx ;AN005; + mov dh,-1 ;AN005; Display FIND: + mov ax,msg_find ;AN005; + xor cx,cx ;AN007; ;AN005; No substitution text + mov bx,STDERR ;AN005; Sent to STD OUT + call display_msg ;AN005; Display the message + pop dx ;AN005; + pop ax ;AN005; Restore error +prt_ret: + ret ;AN005; +prt_find endp ;AN005; + + +;------------------------------------ +;- +;- Procedure name: display_and_die +;- +;- Purpose: Called when the parser finds that +;- required arguments were not entered +;- from the command line. +;- +;- INPUT: AX = Error number +;- +;------------------------------------ +display_and_die proc near + call prt_find ;AN005; + xor cx,cx ;AN007; ;AN000; No substitution text + mov cs:errlevel,ERRORLEVEL_TWO ;AC005; Error code for exit + + mov bx,STDERR ;AN000; Sent to STD OUT + call display_msg ;AN000; Display the message + call terminate ;AN000; and Terminate + ret ;AN000; +display_and_die endp + +;------------------------------------ +;- +;- Procedure name: get_length +;- +;- Purpose: determine the length of a null +;- ending string. +;- +;- INPUT: ES:DI = string address +;- ES:BX = save address (0=no save) +;- +;- OUTPUT: AX = length of string +;------------------------------------ +get_length proc near + push di + push bx + push dx + xor ax,ax ;init string length +look_str: + mov dl,es:[di] ;get character + or bx,bx ;save it? + jz no_save + mov es:[bx],dl ;save character + inc bx ;save next character +no_save: ;AN007; + and dl,dl ;AN007; ;check for eol (asciiz string) + je done_look ;if so, exit + cmp dl,0dh ;AN005; check for eol (carriage return) + je done_look ;AN005; + inc ax ;increment length + inc di ;look at next character + jmp look_str +done_look: + pop dx + pop bx + pop di + ret +get_length endp + + + + +; +;----- BUFFER AREA -------- +st_length dw 0 ;String argument length +st_buffer db st_buf_size dup(?) ;String argument buffer + +file_name_len dw 0 ;File name length +file_name_buf dw 0 ;File name buffer offset + +buffer db buffer_size+2 dup(?) ;file data buffer + +include msgdcl.inc + +code ends + +;-------------------------- +;--- STACK SEGMENT --- +;-------------------------- +stack segment para stack 'STACK' + dw (362 - 80h) +64 dup(?,?) ;(362 - 80h) == New - old IBM ROM +stack_top equ $ +stack ends + + end start + diff --git a/v4.0/src/CMD/FIND/FIND.INC b/v4.0/src/CMD/FIND/FIND.INC new file mode 100644 index 0000000..4434908 --- /dev/null +++ b/v4.0/src/CMD/FIND/FIND.INC @@ -0,0 +1,100 @@ +;; +;; Long Conditional Jump Macros +;; +lja macro Farlabel + local Nearlabel + jna Nearlabel + jmp Farlabel +Nearlabel: + endm +ljae macro Farlabel + local Nearlabel + jnae Nearlabel + jmp Farlabel +Nearlabel: + endm +ljb macro Farlabel + local Nearlabel + jnb Nearlabel + jmp Farlabel +Nearlabel: + endm +ljc macro Farlabel + local Nearlabel + jnc Nearlabel + jmp Farlabel +Nearlabel: + endm +ljbe macro Farlabel + local Nearlabel + jnbe Nearlabel + jmp Farlabel +Nearlabel: + endm +lje macro Farlabel + local Nearlabel + jne Nearlabel + jmp Farlabel +Nearlabel: + endm +ljz macro Farlabel + local Nearlabel + jnz Nearlabel + jmp Farlabel +Nearlabel: + endm +ljg macro Farlabel + local Nearlabel + jng Nearlabel + jmp Farlabel +Nearlabel: + endm +ljge macro Farlabel + local Nearlabel + jnge Nearlabel + jmp Farlabel +Nearlabel: + endm +ljl macro Farlabel + local Nearlabel + jnl Nearlabel + jmp Farlabel +Nearlabel: + endm +ljle macro Farlabel + local Nearlabel + jnle Nearlabel + jmp Farlabel +Nearlabel: + endm +ljnc macro Farlabel + local Nearlabel + jc Nearlabel + jmp Farlabel +Nearlabel: + endm +ljne macro Farlabel + local Nearlabel + je Nearlabel + jmp Farlabel +Nearlabel: + endm +ljnz macro Farlabel + local Nearlabel + jz Nearlabel + jmp Farlabel +Nearlabel: + endm +ljno macro Farlabel + local Nearlabel + jo Nearlabel + jmp Farlabel +Nearlabel: + endm +ljo macro Farlabel + local Nearlabel + jno Nearlabel + jmp Farlabel +Nearlabel: + endm + \ No newline at end of file diff --git a/v4.0/src/CMD/FIND/FIND.LNK b/v4.0/src/CMD/FIND/FIND.LNK new file mode 100644 index 0000000..a1fe82a --- /dev/null +++ b/v4.0/src/CMD/FIND/FIND.LNK @@ -0,0 +1,4 @@ +FIND+ +FINDMES +FIND.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/FIND/FIND.SKL b/v4.0/src/CMD/FIND/FIND.SKL new file mode 100644 index 0000000..071c9d1 --- /dev/null +++ b/v4.0/src/CMD/FIND/FIND.SKL @@ -0,0 +1,12 @@ +:util FIND + +:class 1 ;Extended errors ;AN005; + +:class 2 ;Parser errors ;AN005; + +:class A ;Utility specific errors ;AN005; +:use 1 COMMON1 ;AN005; ;"Incorrect DOS version" +:use 2 EXTEND8 ;AN005; ;"Insufficient memory" +:def 4 "FIND: " ;AN005; + +:end diff --git a/v4.0/src/CMD/FIND/FINDMES.ASM b/v4.0/src/CMD/FIND/FINDMES.ASM new file mode 100644 index 0000000..30713e2 --- /dev/null +++ b/v4.0/src/CMD/FIND/FINDMES.ASM @@ -0,0 +1,19 @@ + title FIND Messages + +Message macro sym,text +public sym,sym&_len +sym db text +sym&_len db $-sym +endm + +CR equ 0dh ;A Carriage Return +LF equ 0ah ;A Line Feed + +code segment public + + PUBLIC heading + message heading, + +code ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FIND/MAKEFILE b/v4.0/src/CMD/FIND/MAKEFILE new file mode 100644 index 0000000..3bb43c1 --- /dev/null +++ b/v4.0/src/CMD/FIND/MAKEFILE @@ -0,0 +1,34 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: find.exe + +find.ctl: find.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +find.obj: find.asm \ + makefile \ + find.ctl \ + find.cla \ + find.cl1 \ + find.cl2 \ + find.inc \ + $(inc)\parse.asm \ + $(inc)\psdata.inc \ + $(inc)\syscall.inc \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc + +findmes.obj: findmes.asm + +find.exe: find.obj findmes.obj + link find+findmes,find.exe/ex; diff --git a/v4.0/src/CMD/FORMAT/DISPLAY.ASM b/v4.0/src/CMD/FORMAT/DISPLAY.ASM new file mode 100644 index 0000000..10ea538 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/DISPLAY.ASM @@ -0,0 +1,177 @@ +; + +;***************************************************************************** +;***************************************************************************** +;UTILITY NAME: FORMAT.COM +; +;MODULE NAME: DISPLAY.ASM +; +; +; Change List: AN000 - New code DOS 3.3 spec additions +; AC000 - Changed code DOS 3.3 spec additions +;***************************************************************************** +;***************************************************************************** + + +; +;***************************************************************************** +; Define Segment ordering +;***************************************************************************** +; + + +.SEQ ; + +PSP segment public para 'DUMMY' +PSP ends + +data segment public para 'DATA' ; +Public Test_Data_Start +Test_Data_Start label byte +data ends ; + +stack segment para stack + db 62 dup ("-Stack!-") ; (362-80h) is the additionsal IBM ROM + assume ss:stack +stack ends + + +code segment public para 'CODE' ; + assume cs:code,ds:data ; +code ends + +End_Of_Memory segment public para 'BUFFERS' ; +Public Test_End +Test_End label byte +End_Of_Memory ends ; + + +; +;***************************************************************************** +; INCLUDE FILES +;***************************************************************************** +; + +.xlist +INCLUDE FORCHNG.INC +INCLUDE FOREQU.INC +INCLUDE FORMSG.INC +INCLUDE SYSMSG.INC +.list + +; +;***************************************************************************** +; Message Services +;***************************************************************************** +; + + +MSG_UTILNAME + + +data segment public para 'DATA' +Msg_Services +data ends + +code segment public para 'CODE' +Msg_Services +Msg_Services +Msg_Services +Msg_Services +code ends + +; +;***************************************************************************** +; Public Declarations +;***************************************************************************** +; + + Public SysDispMsg + Public SysLoadMsg + + +; +;*************************************************************************** +; Message Structures +;*************************************************************************** +; + + +Message_Table struc ; ;AN000; + ; +Entry1 dw 0 ; ;AN000; +Entry2 dw 0 ; ;AN000; +Entry3 dw 0 ; ;AN000; +Entry4 dw 0 ; ;AN000; +Entry5 db 0 ; ;AN000; +Entry6 db 0 ; ;AN000; +Entry7 dw 0 ; ;AN000; + ; +Message_Table ends ; ;AN000; + + + +code segment public para 'CODE' +;***************************************************************************** +;Routine name&gml Display_Interface +;***************************************************************************** +; +;DescriptioN&gml Save all registers, set up registers required for SysDispMsg +; routine. This information is contained in a message description +; table pointed to by the DX register. Call SysDispMsg, then +; restore registers. This routine assumes that the only time an +; error will be returned is if an extended error message was +; requested, so it will ignore error returns +; +;Called Procedures: Message (macro) +; +;Change History&gml Created 4/22/87 MT +; +;Input&gml ES&gmlDX = pointer to message description +; +;Output&gml None +; +;Psuedocode +;---------- +; +; Save all registers +; Setup registers for SysDispMsg from Message Description Tables +; CALL SysDispMsg +; Restore registers +; ret +;***************************************************************************** + +Public Display_Interface +Display_Interface proc ; ;AN000; + + push ds ; ;AN000; + push ax ;Save registers ;AN000; + push bx ; " " " " ;AN000; + push cx ; " " " " ;AN000; + push dx ; " " " " ;AN000; + push si ; " " " " ;AN000; + push di ; " " " " ;AN000; + mov di,dx ;Change pointer to table ;AN000; + mov dx,data ;Point to data segment + mov ds,dx ; + mov ax,[di].Entry1 ;Message number ;AN000; + mov bx,[di].Entry2 ;Handle ;AN000; + mov si,[di].Entry3 ;Sublist ;AN000; + mov cx,[di].Entry4 ;Count ;AN000; + mov dh,[di].Entry5 ;Class ;AN000; + mov dl,[di].Entry6 ;Function ;AN000; + mov di,[di].Entry7 ;Input ;AN000; + call SysDispMsg ;Display the message ;AN000; + pop di ;Restore registers ;AN000; + pop si ; " " " " ;AN000; + pop dx ; " " " " ;AN000; + pop cx ; " " " " ;AN000; + pop bx ; " " " " ;AN000; + pop ax ; " " " " ;AN000; + pop ds ; ;AN000; + ret ;All done ;AN000; + +Display_Interface endp ; ;AN000; +code ends + end + diff --git a/v4.0/src/CMD/FORMAT/FILESIZE.INC b/v4.0/src/CMD/FORMAT/FILESIZE.INC new file mode 100644 index 0000000..40f058d --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FILESIZE.INC @@ -0,0 +1,6 @@ + + %out ..filesize.inc + +BIOS_SIZE equ 35000 ;actually +DOS_SIZE equ 37000 ;actually + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORCHNG.INC b/v4.0/src/CMD/FORMAT/FORCHNG.INC new file mode 100644 index 0000000..2aef46c --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORCHNG.INC @@ -0,0 +1,135 @@ +.xlist +; +; +;***************************************************************************** +;* * +;* Change list to FORMAT modules * +;* * +;* Lines are tagged ANxxx for new, ACxxx for changed * +;* --------------------------------------------------------------------------* +;* 000 - DOS 4.00 Spec additions and DCR's thru unit/function test * +;* Date: 8/3/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 001 - DOS 4.00 DCR D146 Add support for /F switch * +;* Date: 8/13/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 002 - DOS 4.00 DCR D166 Add logic to detect that switches entered * +;* multiple times, and print error message * +;* Date: 8/13/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 003 - DOS 4.00 PTM P233 Do not allow Cntrl-Break when writing file * +;* system out, only during the actual format * +;* Date: 8/14/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 004 - DOS 4.00 PTM P229 Volume serial number displayed in reverse word * +;* order from command.com and diskcopy. Reverse order of words * +;* Date: 8/17/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 005 - DOS 4.00 DCR D64 Enable for 128k FAT * +;* Date: 8/19/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 006 - DOS 4.00 PTM P320 Not detecting write protect. Needed to use * +;* extended error messages * +;* Date 8/20/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 007 - DOS 4.00 PTM P170 Straighten out the switch check logic to allow * +;* /B with all diskette formats, add /B/S check, and remove /V/B * +;* check except for /8 sectored diskettes (old dir and boot record * +;* Date 8/21/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 008 - DOS 4.00 PTM P402 Fields that determine switch type not cleared, * +;* so switches got checked multiple times, causing error * +;* Date 8/23/87 Developer: MT , DS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 009 - DOS 4.00 PTM P341 Check to make sure /N entered with /T * +;* Date 8/23/87 Developer: MT * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 010 - DOS 4.00 PTM P233 Capture the CTRL-BREAK interrupt and disable * +;* it during the writing of the FAT, DIR, and SYSTEM. * +;* Date 8/25/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 012 - DOS 4.00 DCR 200 If the NumberOfFATs field of the BPB is 0 we need * +;* to calculate various values in the BPB to be used by FORMAT. * +;* Date 9/10/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 013 - DOS 4.00 DCR 208 Set FORMAT in order that the space available it * +;* reports is consistent with DIR. * +;* Date 9/11/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 014 - DOS 4.00 PTM 1535 Allow access to a non-formatted disk. * +;* Date 10/15/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 015 - DOS 4.00 DCR 390 Multi-Track format of hard media * +;* Date 12/9/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 016 - DOS 4.00 DCR 395 SELECT message support. Use INT 2Fh, function * +;* ADC1h to print FORMAT disk prompt from SELECT. * +;* Date 12/14/87 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 017 - DOS 4.00 PTM 3125 SELECT message support. Disable write protect * +;* message under SELECT option. Addition of exit codes 6 (Drive Not * +;* Ready" and 7 (Write Protect). * +;* Date 1/14/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 018 - DOS 4.00 PTM 3130 Provide for conditional assembly of the /FS: * +;* code, since it is not being shipped with DOS 4.00. * +;* Date 1/26/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 019 - DOS 4.00 PTM 3994 FORMAT now has a "heartbeat" when it verifies * +;* bad sectors. By doing so the user knows the FORMAT is still * +;* proceeding well. Without this heartbeat, an AT appears to hang * +;* when the sectors are being verified. This is caused by the slow * +;* head resets on an AT. * +;* Date 3/25/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 020 - DOS 4.00 PTM 4058 When an invalid Volume ID is entered at the * +;* volume prompt, FORMAT should go to the next line so that the * +;* user can see the invalid volume id. * +;* Date 3/29/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 021 - DOS 4.00 PTM 4081 FORMAT was marking the incorrect cluster as * +;* bad under certain situations. This caused that sector to fail * +;* when read or written to. * +;* Date 3/31/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 022 - DOS 4.00 PTM 4180 FORMAT was not performing an FCB Close after * +;* it had done an FCB Create. This caused the change line counter * +;* to go "haywire". Also a bug was found in the FORMAT retry logic. * +;* FORMAT was never entering the retry logic because of a CY flag * +;* always existing on entry to the routine. * +;* Date 4/15/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 023 - DOS 4.00 DCR 524 FORMAT must accept a blank or carriage return to * +;* allow for a blank volume label. * +;* Date 4/19/88 Developer: DRM * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 024 - DOS 4.00 PTM 4487 FORMAT trys to get the A: drive when formatting * +;* drive B: and then hitting enter for the volume label. There is a * +;* problem with FCB Close but logic was also changed in FORLABEL.SAL * +;* to eliminate this condition. * +;* Date 4/26/88 Developer: DRM * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 025 - DOS 4.00 PTM 4539 FORMAT accesses the default disk instead of the * +;* boot disk when the default disk is different than the boot disk. * +;* This is incorrect behavior because the user could receive a system * +;* other than what they wanted. * +;* Date 4/28/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 026 - DOS 4.00 PTM 4805 FORMAT A: /B gives invalid bad byte count and * +;* FORMAT A: /F:160 on an 1.2 Mb drive gives parm error. * +;* Date 5/10/88 Developer: DMS * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 027 - DOS 4.00 PTM 4913 FORMAT A: /B displays the serial number of the * +;* diskette but never writes it to the diskette. Format will no * +;* display the serial number when formatting with /8. * +;* Date 5/19/88 Developer: DRM * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* 028 - DOS 4.00 PTM 5023 FORMAT puts just the N of NO NAME in the volume * +;* label of the boot record. This is corrected in IBMFOR.SAL by * +;* setting up the CX register correctly. * +;* Date 6/09/88 Developer: DRM * +;***************************************************************************** +;* Note: This is file FORCHNG.INC for updating purposes * +;***************************************************************************** +.list + diff --git a/v4.0/src/CMD/FORMAT/FOREQU.INC b/v4.0/src/CMD/FORMAT/FOREQU.INC new file mode 100644 index 0000000..5d5d925 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FOREQU.INC @@ -0,0 +1,115 @@ +; ; ; ; + +NO equ 0 +YES equ not NO +FSExec equ NO ;an018; dms;conditional assembly +ShipDisk equ NO ;an000; dms;ship disk flag + +Boot_ID equ 0AA55h +DOS_Found equ 0 + +Not_Include equ 0 +Do_Include equ 1 + +INIT equ 0 + +FAT12_File_System equ 01h +FAT16_File_System equ 04h +New_File_System equ 06h + +FS_String_Max_Length equ 5 + +Paragraph_Size equ 16 ; ;AN005; +Len_FS_String_Buffer equ 13 + +Net_Check equ 1200h +Assign_Check equ 8000h + +Found_Yes equ 1 +Found_No equ 0 + +Asciiz_End equ 0 +DBCS equ 81h +DBCS_Blank equ 40h +DBCS_Vector_Size equ 2 +End_Of_Vector equ 0 + + +Blank equ " " + +Label_Length equ 11 +CR equ 13 + +DBCS_VECTOR equ NO + +;Limits +BIG_FAT_THRESHOLD equ 4086 + +;------------------------------------------------------------------------------- + + + + + +DRNUM EQU 5CH + + + +; Exit status defines +ExitOK equ 0 +ExitCtrlC equ 3 +ExitFatal equ 4 +ExitNo equ 5 + + +;------------------------------------------------------------------------------- +; These are the data structures which we will need + + +Media_ID struc +Media_ID_Info_Level dw 0 +Media_ID_Serial_Number dd 0 +Media_ID_Volume_Label db 11 dup(" ") +Media_ID_File_System db 8 dup(" ") +Media_ID ends + + +Relative_Sector_Buffer struc ; ;AN000; + +Start_Sector_Low dw ? ;Low word of RBA sector ;AN000; +Start_Sector_High dw ? ;High word of RBA sector ;AN000; +Number_Sectors dw ? ;Number of sectors ;AN000; +Buffer_Offset dw ? ;Address of data buffer ;AN000; +Buffer_Segment dw ? ; ;AN000; + +Relative_Sector_Buffer ends ; ;AN000; + + +;Per system file data structure + +a_FileStructure struc +fileHandle DW ? +fileSizeInParagraphs DW ? +fileSizeInBytes DD ? +fileOffset DD ? +fileStartSegment DW ? +fileDate DW ? +fileTime DW ? +a_FileStructure ends + +;------------------------------------------------------------------------------- + +LOGBOOTSECT equ 1 +Set_Drv_Owner equ 0Fh ; IOCTL subfunction +Custom_Media equ 0F0H ; Media byte for custom format +Dual_8_Media equ 0FFh ; Dual sided 8 sectored +Single_8_Media equ 0FEh ; Single sided 8 sectored +Dual_9_Media equ 0FDh ; Dual sided 9 sectored +Single_9_Media equ 0FCh ; Single sided 9 sectored +Dual_15_Media equ 0F9h ; Dual sided 15 sectored +Fixed_Disk equ 0F8h ; Fixed Disk +Invalid_Drive equ 000Fh ; Extended error 15 +Max_Format_Size equ 0FFFFh ; Max bytes to Format ;an015; dms; +Multi_Track_Format equ 02h ; Multi-track format ;an015; dms; +Single_Track_Format equ 00h ; Single track format ;an015; dms; +Select_Disk_Message equ 0ADC1h ; an016; dms; diff --git a/v4.0/src/CMD/FORMAT/FOREXEC.ASM b/v4.0/src/CMD/FORMAT/FOREXEC.ASM new file mode 100644 index 0000000..46026cb --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FOREXEC.ASM @@ -0,0 +1,637 @@ +page ,132 ; +; + +;***************************************************************************** +;***************************************************************************** +;UTILITY NAME: FORMAT.COM +; +;MODULE NAME: FOREXEC.SAL +; +; +; +; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³EXEC_FS_FORMAT³ +; ÀÄÂÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ +; ³ÚÄÄÄÄÄÄ¿ +; ôShrink³ +; ³ÀÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ +; ôSetup_EXEC³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôEXEC_ArgVÃÄÄÄÄÄÄÄÄÄÄ´EXEC_Program³ +; ³ÀÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôEXEC_Cur_DirectoryÃÄ´EXEC_Program³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; À´EXEC_RoutineÃÄÄÄÄÄÄÄ´Build_Path_And_EXECÃÄ´EXEC_Program³ +; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ +; +; Change List: AN000 - New code DOS 3.3 spec additions +; AC000 - Changed code DOS 3.3 spec additions +;***************************************************************************** +;***************************************************************************** + +title DOS 3.30 FORMAT EXEC Module + +IF1 + %OUT ASSEMBLING: DOS 3.3 FORMAT EXEC LOADER + %OUT +ENDIF + +code segment public para 'code' + assume cs:code +code ends + +; +;***************************************************************************** +; Include files +;***************************************************************************** +; + +.xlist +INCLUDE FORCHNG.INC +INCLUDE FORMACRO.INC +INCLUDE SYSCALL.INC +INCLUDE FOREQU.INC +.list + +; +;***************************************************************************** +; Public Data +;***************************************************************************** +; + + Public Drive_Letter_Msg + +; +;***************************************************************************** +; Public Routines +;***************************************************************************** +; + + +IF FSExec ;an018; dms;if /FS: desired + + Public EXEC_FS_Format + +ENDIF ;FSExec ;an018; dms;end /FS: conditional + + Extrn GetFSiz:near + + +; +;***************************************************************************** +; External Data Declarations +;***************************************************************************** +; + + extrn ExitStatus:Byte + extrn Fatal_Error:Byte + extrn FS_String_Buffer:Byte + extrn msgEXECFailure:Byte + extrn PSP_Segment:Word + extrn drive:byte + +; +;**************************************************************************** +; Structures +;**************************************************************************** +; + + +Exec_Block_Parms struc +Segment_Env dw 0 +Offset_Command dw 0 +Segment_Command dw 0 +Offset_FCB1 dw 0 +Segment_FCB1 dw 0 +Offset_FCB2 dw 0 +Segment_FCB2 dw 0 + +Exec_Block_Parms ends + + +; +;**************************************************************************** +; Equates +;**************************************************************************** +; + + +String_Done equ 0 +No_Error equ 0 +Error equ 1 +Stderr equ 2 +Stack_Space equ 02eh ;an000; dms; IBM addition ROM paras + +; +;**************************************************************************** +; PSP Area +;**************************************************************************** +; + +PSP segment public para 'DUMMY' + +org 2Ch +PSP_ENV_SEGMENT label word + +FCB1 equ 5Ch + +FCB2 equ 6Ch + +org 80h +Command_Line label byte + + +PSP ends + +; +;**************************************************************************** +; Data Area +;**************************************************************************** +; + +data segment public para 'DATA' + assume ds:data,es:nothing + +Exec_Block Exec_Block_Parms <> +EXEC_Path db 66 dup(0) + +Drive_Letter_Msg db "A:",0 ;Drive for exec fail message + +SP_Save dw ? ;an000; dms; +SS_Save dw ? ;an000; dms; + + +;These next two should stay togather +; --------------------------------------- + ; +Path_String db "PATH=" ; ;AN000; +Len_Path_String equ $ - Path_String ; ;AN000; + ; +;---------------------------------------- + + + + +;These should stay togather +; --------------------------------------- + ; +Search_FORMAT db "FORMAT" ; ;AC000; +Len_Search_FORMAT equ $ - Search_FORMAT ; ; ; +Search_Format_End equ $ + ; ; ; +;---------------------------------------- + + +;These next two should stay togather +; --------------------------------------- + + + + + +data ends + +code segment public para 'code' + assume cs:code,ds:data + +; +;**************************************************************************** +; Main Routine +;**************************************************************************** +; +; +; +; +; + +IF FSExec ;an018; dms;if /FS: desired + + +Procedure Exec_FS_Format ; ;AC000; + + Set_Data_Segment ; + call Set_FCB1_Drive ;an000;dms; + call Shrink ; ; ; + mov al,ExitStatus ;Setblock fail? ;AC000; + cmp al,Error ; " " " " ; ; +; $IF NE ;Nah, keep crusin! ;AN000; + JE $$IF1 + call Setup_Exec ; ; ; + call Exec_Argv ;try exec from dir BASIC loaded ; ; + mov al,ExitStatus ; ;AC000; + cmp al,Error ; ; ; +; $IF E,AND ; ;AC000; + JNE $$IF2 + call Exec_Cur_Directory ; ; ; + mov al,ExitStatus ;Try exec from cur directory ;AC000; + cmp al,Error ; ; ; +; $IF E,AND ; ;AC000; + JNE $$IF2 + call EXEC_Routine ; ; ; + mov al,ExitStatus ; ;AC000; + cmp al,Error ; ; ; +; $IF E ; ;AC000; + JNE $$IF2 + ; mov bl,FCB1 ;Get target drive from FCB + ; mov bl,Drive ;an000;dms; + push ds ;an000;dms;save ds + push si ;an000;dms;save si + mov si,PSP_Segment ;an000;dms;get psp + mov ds,si ;an000;dms;put psp in ds + assume ds:PSP ;an000;dms; + + mov si,FCB1 ;an000;dms;ptr to 1st. FCB + mov bl,byte ptr ds:[si] ;an000;dms;get drive ID + + pop si ;an000;dms;restore si + pop ds ;an000;dms;restore ds + Set_Data_Segment ;an000;dms;set segments + + cmp bl,0 ;Is it default drive? ;AN000; +; $IF E ;Yes, turn it into drive letter ;AN000; + JNE $$IF3 + push ax ;Save exit code ;AN000; + DOS_Call Get_Default_Drive ;Get the default drive ;AN000; + add al,"A" ;Turn into drive letter ;AN000; + mov Drive_Letter_Msg,al ;Save it in message ;AN000; + pop ax ;Get return code back ;AN000; +; $ELSE ;Not default, A=1 ;AN000; + JMP SHORT $$EN3 +$$IF3: + add bl,"A"-1 ;Convert to drive letter ;AN000; + mov Drive_Letter_Msg,bl ; ;AN000; +; $ENDIF ;AN000; +$$EN3: + Message msgEXECFailure ; ;AC000; +; $ELSE ; ;AN000; + JMP SHORT $$EN2 +$$IF2: + DOS_Call WaitProcess ; ;AC000; + mov ExitStatus,al ; ; ; +; $ENDIF ; ;AN000; +$$EN2: +; $ENDIF +$$IF1: + mov Fatal_Error,YES ;Not really, indicates FS used ;AN000; + ret ; ; ; + +Exec_FS_Format endp + + +; +;**************************************************************************** +; Shrink +;**************************************************************************** +; +; +; +; + + +Procedure Shrink ; ;AC000; + + mov ax,cs ;an000; dms;get code segment + mov bx,ds ;an000; dms;get data segment + sub ax,bx ;an000; dms;data seg size + mov bx,ax ;an000; dms;save paras + mov ax,offset End_Program ;Get the offset of end of loader; ; + mov cl,4 ;Div by 16 to get para's ; ; + shr ax,cl ; ; ; + add bx,ax ;an000; dms;add in code space + add bx,Stack_Space ;an000; dms;adjust for stack + add bx,11h ;an000; dms;give PSP space + mov ax,PSP_Segment + mov es,ax + assume es:nothing + + DOS_Call SetBlock ; ;AC000; +; $IF C ;If didn't work, quit ;AC000; + JNC $$IF9 + Message msgEXECFailure ; ; ; + mov ExitStatus,Error ;Bad stuff, time to quit ;AN000; +; $ENDIF ; ;AN000; +$$IF9: + ret ; ; ; + +Shrink endp ; ;AN000; + + +; +;**************************************************************************** +; Setup_Exec +;**************************************************************************** +; +; +; +; + +Procedure Setup_Exec ; ;AC000; + + Set_Data_Segment + mov ax,PSP_Segment ;Get segment of PSP ;AN000; + mov ds,ax ; " " " " ;AN000; + ; ; + assume ds:PSP + ;Setup dword pointer to command line to be passed + + mov es:Exec_Block.Segment_Command,ax ;Segment for command line ; ; + mov es:Exec_Block.Offset_Command,offset ds:Command_Line ; ; ; + + ;Setup dword pointer to first FCB to be passed + + mov es:Exec_Block.Segment_FCB1,ax ;Segment for FCB1 ; ; + mov es:Exec_Block.Offset_FCB1,offset ds:FCB1 ;Offset of FCB at 05Ch ; ; + + ;Setup dword pointer to second FCB to be passed ; ; + + mov es:Exec_Block.Segment_FCB2,ax ;Segment for FCB2 ; ; + mov es:Exec_Block.Offset_FCB2,offset ds:FCB2 ;Offset of FCB at 06Ch ; ; + + ;Setup segment of Environment string, get from PSP ; ; + + mov ax,ds:PSP_Env_Segment ; ; ; + mov es:Exec_Block.Segment_Env,ax ; ; ; + Set_Data_Segment + ret ; ; ; + + +Setup_EXEC endp ; ;AN000; + +; +;**************************************************************************** +; Exec_Argv +;**************************************************************************** +; +; Read the environment to get the Argv(0) string, which contains the drive, +; path and filename that was loaded for FORMAT.COM. This will be used to find +; the xxxxxfmt.exe, assuming that it is in the same location or path as +; FORMAT.COM +; + +Procedure EXEC_Argv ; ;AC000; + + Set_Data_Segment ;DS,ES = DATA + cld ; ; ; + mov ax,Exec_Block.Segment_Env ;Get the environment ; ; + mov ds,ax ;Get addressability ; ; + + assume ds:nothing + + xor si,si ;Start at beginning ; ; +; $DO ;Find argv(0) location ;AN000; +$$DO11: +; $DO ;Look for 0 ;AN000; +$$DO12: + inc si ;Get character ; ; + cmp byte ptr [si-1],0 ;Find string seperator? ; ; +; $ENDDO E ;Yep ;AC000; + JNE $$DO12 + inc si ;Get next char ; ; + cmp byte ptr [si-1],0 ;Are we at Argv(0)? (00?) ; ; +; $ENDDO E ;Yes if we found double 0's ;AC000; + JNE $$DO11 + add si,2 ;Skip the word count ; ; + mov di,si ;Save where string starts ; ; +; $DO ;Find length of Argv(0) string ;AN000; +$$DO15: + inc si ;Get char ; ; + cmp byte ptr [si-1],0 ;Is it the end? ; ; +; $ENDDO E ;End found if 0 found ;AC000; + JNE $$DO15 + mov cx,si ;Get number of bytes in string ; ; + sub cx,di ;Put in cx reg for rep count ; ; + mov si,di ;Point to path ; ; + mov di,offset es:EXEC_Path ;Point to where to put it ; ; + rep movsb ;Move the string ; ; + Set_Data_Segment ; ;AN000' + dec di ;Point at end of ArgV string ; ; + std ;Look backwards ;AN000; +; $DO ;Find 'FORMAT' in ARGV string ;AC000; +$$DO17: + mov cx,Len_Search_FORMAT ;Get length to compare ;AC000; + mov si,offset Search_FORMAT_End-1 ;Look at comp string from end ;AC000; + repe cmpsb ;See if same string ;AC000; +; $ENDDO E ; ;AC000; + JNE $$DO17 + mov si,offset FS_String_Buffer ; ;AN000; + inc di ;DI = replacement point-1 ;AC000; + cld ;Set direction flag back ;AN000; + mov cx,Len_FS_String_Buffer ;Length of string to move ;AN000; + rep movsb ;Build part of the path ; ; + call EXEC_Program ; ; ; + ret ; ; ; + +EXEC_ArgV endp ; ;AN000; + +; +;**************************************************************************** +; EXEC_Program +;**************************************************************************** +; +; +; +; + +Procedure EXEC_Program ; ;AC000; + + Set_Data_Segment ; ;AN000; + mov ExitStatus,No_Error ;Setup to Exec the file ; ; + mov dx,offset Exec_Path ; ; ; + mov bx,offset Exec_Block ; ; ; + mov al,0 ; ; ; + mov word ptr SP_Save,sp ;an000; dms;save sp + mov word ptr SS_Save,ss ;an000; dms;save ss + + DOS_Call Exec ; ;AC000; + + cli ;an000; dms;turn off int's + mov sp,word ptr SP_Save ;an000; dms;retrieve sp + mov ss,word ptr SS_Save ;an000; dms;retrieve ss + sti ;an000; dms;turn on int's + + +; $IF C ;CY means failure ;AC000; + JNC $$IF19 + mov ExitStatus,Error ;Set error code ; ; +; $ENDIF ; ;AN000; +$$IF19: + ret ; ; ; + +EXEC_Program endp ; ;AN000; + + +; +;**************************************************************************** +; EXEC_Routine +;**************************************************************************** +; +; +; +; + +Procedure EXEC_Routine ; ;AN000; + + Set_Data_Segment ; ;AN000; + mov ExitStatus,Error ;Assume the worst ; ; + cld ; ; ; + push ds ; ; ; + mov ax,Exec_Block.Segment_Env ;Get the environment ; ; + mov ds,ax ;Get addressability ; ; + assume ds:nothing ; + + xor si,si ;Start at beginning ; ; +; $SEARCH ; ;AC000; +$$DO21: + cmp word ptr ds:[si],0 ;End of the Evironment? ; ; +; $EXITIF E ;Reached end, no more look ;AC000; + JNE $$IF21 + ; ; ; +; $ORELSE ;Look for 'PATH=' in environment;AN000; + JMP SHORT $$SR21 +$$IF21: + mov di,offset Path_String ; " " " " ;AC000; + mov cx,Len_Path_String ; " " " " ;AC000; + repe cmpsb ; " " " " ;AC000; +; $LEAVE E ;Found if EQ ;AC000; + JE $$EN21 +; $ENDLOOP ;Found PATH in environment ;AC000; + JMP SHORT $$DO21 +$$EN21: + call Build_Path_And_Exec ; ;AN000; +; $ENDSRCH ; ; ; +$$SR21: + pop ds ; ; ; + ret ; ; ; + +EXEC_Routine endp + +; +;**************************************************************************** +; Build_Path_For_EXEC +;**************************************************************************** +; +; +; +; + +Procedure Build_Path_And_Exec ; ;AN000; + +; $DO ; ;AC000; +$$DO27: + cmp byte ptr ds:[si],0 ;All path entries done? ; ; +; $IF NE ; ;AC000; + JE $$IF28 + mov di,offset EXEC_Path ;Point at where to put path ; ; + mov byte ptr es:[di],0 ;End path just in case ; ; +; $DO ; ;AC000; +$$DO29: + cmp byte ptr ds:[si],0 ;End of Path? ; ; +; $LEAVE E ; ;AC000; + JE $$EN29 + cmp byte ptr ds:[si],';' ;End of entry? ; ; +; $if e ;yes ;an000; dms; + JNE $$IF31 + inc si ;point to next character ;an000; dms; + jmp EXIT_BPE_LOOP ;exit loop ;an000; dms; +; $endif ; ;an000; dms; +$$IF31: + movsb ;Put char in path string ; ; +; $ENDDO ; ;AN000; + JMP SHORT $$DO29 +$$EN29: + +EXIT_BPE_LOOP: ; ;an000; dms; + ;Path filled in,get backslash ; ; + cmp byte ptr ds:[si-1],0 ;Any path there? ; ; +; $IF NE ; ;AC000; + JE $$IF34 + ;Nope ; ; + cmp byte ptr ds:[si-1],"\" ;Need a backslash? ; ; +; $IF NE ; ;AC000; + JE $$IF35 + mov byte ptr es:[di],"\" ;Yes, put one in ; ; + inc di ;Line it up for next stuff ; ; + inc si ; ; ; +; $ENDIF ; ;AN000; +$$IF35: + push si ;Save place in path + push ds ;Save segment for environment ;AN000; + push es ;Xchange ds/es ;an000; dms; + pop ds ; ;an000; dms; + mov si,offset FS_String_Buffer ;Fill in filename ; ; + mov cx, Len_FS_String_Buffer ; ; ; + rep movsb ; ; ; + call Exec_Program ; ; ; + cmp ExitStatus,No_Error ;E if EXEC okay ;AN000; + pop ds ;Get Env segment back ; ; + pop si ;Get place in path back +; $ENDIF ;E if all paths done ;AN000; +$$IF34: +; $ENDIF ;E if all paths done ;AN000; +$$IF28: +; $ENDDO E ;Exit if E ;AN000; + JNE $$DO27 + ret ; ;AN000; + +Build_Path_And_EXEC Endp ; ;AN000; + + + +; +;**************************************************************************** +; Exec_Cur_Directory +;**************************************************************************** +; +; +; +; + +Procedure Exec_Cur_Directory ; ;AC000; + + Set_Data_Segment ; ;AN000; + mov si,offset FS_String_Buffer ;Setup path for current dir ; ; + mov di,offset EXEC_Path ; ; ; + mov cx,Len_FS_String_Buffer ; ; ; + rep movsb ; ; ; + call EXEC_Program ; ; ; + ret ; ; ; + +EXEC_Cur_Directory endp ; ;AN000; + +;========================================================================= +; Set_FCB1_Drive : This routine sets the 1st. byte of the FCB1, +; the drive identifier, to the default drive. +;========================================================================= + +Procedure Set_FCB1_Drive ;an000;dms;set drive ID + + push ds ;an000;dms;save ds + push si ;an000;dms;save si + + mov si,PSP_Segment ;an000;dms;get segment of PSP + mov ds,si ;an000;dms;put it in ds + assume ds:PSP ;an000;dms; + mov si,FCB1 ;an000;dms;ptr to FCB1 + mov byte ptr ds:[si],00h ;an000;dms;set drive ID to + ; default drive + pop si ;an000;dms;restore si + pop ds ;an000;dms;restore ds + Set_Data_Segment ;an000;dms;set up segmentation + ret ;an000;dms; + +Set_FCB1_Drive endp ;an000;dms; + +ENDIF ;FSExec ;an018; dms;end /FS: conditional + ; assembly + +public End_Program +End_Program label byte + +code ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORINIT.ASM b/v4.0/src/CMD/FORMAT/FORINIT.ASM new file mode 100644 index 0000000..f4fd274 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORINIT.ASM @@ -0,0 +1,1255 @@ + +; + + +;***************************************************************************** +;***************************************************************************** +;UTILITY NAME: FORMAT.COM +; +;MODULE NAME: FORINIT.SAL +; +; +; +; ÚÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ Main_Init ³ +; ÀÄÂÄÄÄÄÄÄÄÄÄÙ +; ³ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôInit_Input_OutputÃÄÄÄÄ´Preload_Messages³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ôCheck_For_FS_SwitchÃÄÄ´Parse_For_FS_Switch³ +; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ³ À´EXEC_FS_Format³ +; ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ À´Parse_Command_Line ÃÄÄÄ´Interpret_Parse³ +; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôValidate_Target_DriveôCheck_Target_Drive³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ ôCheck_For_Network³ +; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ À´Check_Translate_Drive³ +; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; À´Hook_CNTRL_C³ +; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ +; +; +; Change List: AN000 - New code DOS 3.3 spec additions +; AC000 - Changed code DOS 3.3 spec additions +;***************************************************************************** +;***************************************************************************** + +data segment public para 'DATA' + + +Command_Line db NO +PSP_Segment dw 0 + +;These should stay togather +; --------------------------------------- ; ;AN000; +FS_String_Buffer db 13 dup(" ") ; ;AN000; +FS_String_End db "FMT.EXE",0 ; ;AN000; +Len_FS_String_End equ $ - FS_String_End ; ;AN000; + ; ;AN000; +;---------------------------------------- + +Vol_Label_Count db 80h ;an000; dms;max. string length +Vol_Label_Len db 00h ;an000; dms;len. entered +Vol_Label_Buffer db 80h dup(0) ; ;AN000; +Vol_Label_Buffer_Length equ $ - Vol_Label_Buffer ; ;AN000; + +Command_Line_Buffer db 80h dup(0) ; ;AN000; +Command_Line_Length equ $ - Command_Line_Buffer ; ;AN000; +Fatal_Error db 0 ; ;AN000; + +Command_Old_Ptr dw ? + +data ends + +code segment public para 'CODE' + assume cs:code,ds:data,es:data +code ends + +; +;***************************************************************************** +; Include files +;***************************************************************************** +; + +.xlist +INCLUDE FORCHNG.INC +INCLUDE FORMACRO.INC +INCLUDE SYSCALL.INC +INCLUDE IOCTL.INC +INCLUDE FOREQU.INC +INCLUDE FORPARSE.INC +INCLUDE FORSWTCH.INC +.list + +; +;***************************************************************************** +; Public Data +;***************************************************************************** +; + + Public FS_String_Buffer + Public Command_Line + Public Fatal_Error + Public Vol_Label_Count + Public Vol_Label_Buffer + Public PSP_Segment + Public Command_Old_Ptr + + +; +;***************************************************************************** +; Public Routines +;***************************************************************************** +; + + + Public Main_Init + +; +;***************************************************************************** +; External Routine Declarations +;***************************************************************************** +; + + Extrn Main_Routine:Near + Extrn SysLoadMsg:Near + Extrn Get_11_Characters:Near + Extrn ControlC_Handler:Near + Extrn SysDispMsg:Near + Extrn SysLoadMsg:Near + +IF FSExec ;/FS: conditional assembly ;an018; dms; + + Extrn EXEC_FS_Format:Near + +ENDIF ;/FS: conditional assembly end ;an018;dms; + + Extrn GetDeviceParameters:Near +; +;***************************************************************************** +; External Data Declarations +;***************************************************************************** +; + + Extrn SwitchMap:Word + Extrn ExitStatus:Byte + Extrn Drive:Byte + Extrn DriveLetter:Byte + Extrn TranSrc:Byte + Extrn TrackCnt:Word + Extrn NumSectors:Word + Extrn BIOSFile:Byte + Extrn DOSFile:Byte + Extrn CommandFile:Byte + Extrn MsgNeedDrive:Byte + Extrn MsgBadVolumeID:Byte + Extrn MsgBadDrive:Byte + Extrn MsgAssignedDrive:Byte + Extrn MsgNetDrive:Byte + Extrn Parse_Error_Msg:Byte + Extrn Extended_Error_Msg:Byte + Extrn SizeMap:Byte + Extrn MsgSameSwitch:Byte + Extrn Org_AX:word ;an000; dms;AX on prog. entry + Extrn DeviceParameters:Byte ;an000; dms; + Extrn FAT_Flag:Byte ;an000; dms; + Extrn Sublist_MsgParse_Error:Dword ;an000; dms; + + +code segment public para 'CODE' + +;***************************************************************************** +;Routine name: Main_Init +;***************************************************************************** +; +;Description: Main control routine for init section +; +;Called Procedures: Message (macro) +; Check_DOS_Version +; Init_Input_Output +; Validate_Target_Drive +; Hook_CNTRL_C +; +;Input: None +; +;Output: None +; +;Change History: Created 5/1/87 MT +; +;Psuedocode +; --------- +; +; Get PSP segment +; Fatal_Error = NO +; Setup I/O (CALL Init_Input_Output) +; IF !Fatal_Error +; Check target drive letter (CALL Validate_Target_Drive) +; IF !Fatal_Error +; Set up Control Break (CALL Hook_CNTRL_C) +; IF !Fatal_Error +; CALL Main_Routine +; ENDIF +; ENDIF +; ENDIF +; Exit program +;***************************************************************************** + +Procedure Main_Init ; ;AN000; + + + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + DOS_Call GetCurrentPSP ;Get PSP segment address + mov PSP_Segment,bx ;Save it for later + mov Fatal_Error,No ;Init the error flag ;AN000; + call Init_Input_Output ;Setup messages and parse ;AN000; + cmp Fatal_Error,Yes ;Error occur? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF1 + call Validate_Target_Drive ;Check drive letter ;AN000; + cmp Fatal_Error,Yes ;Error occur? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF2 + call Hook_CNTRL_C ;Set CNTRL -Break hook ;AN000; + cmp Fatal_Error,Yes ;Error occur? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF3 + call Main_Routine ;Go do the real program ;AN000; +; $ENDIF ; ;AN000; +$$IF3: +; $ENDIF ; ;AN000; +$$IF2: +; $ENDIF ; ;AN000; +$$IF1: + mov al,ExitStatus ;Get Errorlevel ;AN000; + DOS_Call Exit ;Exit program ;AN000; + int 20h ;If other exit fails ;AN000; + +Main_Init endp ; ;AN000; + +;***************************************************************************** +;Routine name: Init_Input_Output +;***************************************************************************** +; +;Description: Initialize messages, Parse command line, allocate memory as +; needed. If there is a /FS switch, go handle it first as +; syntax of IFS format may be different from FAT format. +; +;Called Procedures: Preload_Messages +; Parse_For_FS_Switch +; Parse_Command_Line +; +;Change History: Created 4/1/87 MT +; +;Input: PSP command line at 81h and length at 80h +; Fatal_Error = No +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; +; Load messages (CALL Preload_Messages) +; IF !Fatal_Error +; See if EXEC another file system (CALL Parse_For_FS_Switch) +; IF !FATAL_Error (in this case means FS was found and exec'd) +; CALL Parse_Command_Line +; IF !Fatal_Error +; CALL Interpret_Parse +; ENDIF +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +Procedure Init_Input_Output ; ;AN000; + + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + call Preload_Messages ;Load up message retriever ;AN000; + +IF FSExec ;/FS: conditional assembly ;an018; dms; + + cmp Fatal_Error,YES ;Quit? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF7 + call Check_For_FS_Switch ;Specify FS other than FAT? ;AN000; + +ENDIF ;/FS: conditional assembly end ;an018;dms; + + cmp Fatal_Error,YES ;drive is invalid for format? ;an000; +; $if ne ;no ;an000; + JE $$IF8 + call Parse_Command_Line ;Parse in command line input ;AN000; + cmp Fatal_Error,YES ;Quit? ;AN000; +; $IF NE ;Nope, keep going ;AN000; + JE $$IF9 + call Determine_FAT_Non_FAT;see if drive was non_FAT ;an000; + call Check_For_Invalid_Drive;Drive joined? ;an000; +; $ENDIF ; ;AN000; +$$IF9: +; $ENDIF ; ;AN000; +$$IF8: + +IF FSExec ;/FS: conditional assembly ;an018; dms; + +; $ENDIF ; ;an000; +$$IF7: + +ENDIF ;/FS: conditional assembly end ;an018;dms; + + ret ; ;AN000; + +Init_Input_Output endp ; ;AN000; + +;***************************************************************************** +;Routine name: Preload_Messages +;***************************************************************************** +; +;Description: Preload messages using common message retriever routines. +; +;Called Procedures: SysLoadMsg +; +; +;Change History: Created 5/1/87 MT +; +;Input: Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; +; Preload All messages (Call SysLoadMsg) +; IF error +; Display SysLoadMsg error message +; Fatal_Error = YES +; ENDIF +; ret +;***************************************************************************** + +Procedure Preload_Messages ; ;AN000; + ; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + call SysLoadMsg ;Preload the messages ;AN000; +; $IF C ;Error? ;AN000; + JNC $$IF13 + call SysDispMsg ;Display preload msg ;AN000; + mov Fatal_Error, YES ;Indicate error exit ;AN000; +; $ENDIF ; ;AN000; +$$IF13: + ret ; ;AN000; + +Preload_Messages endp ; ;AN000; + + + + +IF FSExec ;/FS: conditional assembly ;an018; dms; + + +;***************************************************************************** +;Routine name: Check_For_FS_Switch +;***************************************************************************** +; +;Description: Parse to see if /FS switch entered, and if so, go EXEC the +; asked for file system. Set Fatal_Error = YES if FS found +; If we do find /FS, we need to build a string of xxxxxfmt.exe,0 +; where xxxxx is the first 5 characters or less of /FS:xxxxx +; +;Called Procedures: Parse_For_FS_Switch +; EXEC_FS_Format +; +;Change History: Created 6/21/87 MT +; +;Input: Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; Exit_Status set +; +;Psuedocode +;---------- +; +; Parse for /FS switch (CALL Parse_For_FS_Switch) +; IF !FATAL_ERROR +; IF /FS found +; Point at what was entered on /FS:xxxxx +; DO +; LEAVE end of entered string +; Got good char, move into path +; ENDDO already got 5 chars (max in xxxxxfmt.exe) +; Tack on the rest of the string (fmt.exe,0) +; Go exec the needed format (CALL EXEC_FS_Format) +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +Procedure Check_For_FS_Switch ; ;AN000; + ;AN000; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + call Parse_For_FS_Switch ;See if /FS entered ;AN000; + cmp Fatal_Error,YES ;Bad stuff entered?? ;AN000; +; $IF NE ;Nope, cruise onward ;AN000; + JE $$IF15 + cmp Switch_String_Buffer.Switch_Pointer,offset Switch_FS_Control.Keyword ; ;AN000; +; $IF E ;We got the switch ;AN000; + JNE $$IF16 + mov Switch_FS_Control.Keyword,20h ;an000; dms;remove switch from table + test SwitchMap,Switch_FS ;Have this already? ;AN002; +; $IF Z ;Nope ;AN002; + JNZ $$IF17 + push ds ;Get addressibility ;AN000; + pop es ; " " " " ;AN000; + ; + assume ds:nothing,es:data ; ;AN000; + ; + mov ax,Switch_String_Buffer.Switch_String_Seg ;Get the entered FS ;AN000; + mov ds,ax ; ;AN000; + mov si,es:Switch_String_Buffer.Switch_String_Off ; ;AN000; + mov cx,FS_String_Max_Length ; ;AN000; + mov di,offset es:FS_String_Buffer ; ;AN000; +; $DO ;Move whatever user entered ;AN000; +$$DO18: + cmp byte ptr [si],ASCIIZ_End ;End of the string? ;AN000; +; $LEAVE E ;Yep ;AN000; + JE $$EN18 + movsb ;Put character in buffer ;AN000; + dec cx ;Dec character counter + cmp cx,0 ;Nope, reached max # chars? ;AN000; +; $ENDDO E ;Yes ;AN000; + JNE $$DO18 +$$EN18: + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + mov cx,Len_FS_String_End ;Tack the FMT.EXE onto it ;AN000; + mov si,offset es:FS_String_End ;DI still points at string ;AN000; + rep movsb ;We now have Asciiz path! ;AN000; + call EXEC_FS_Format ;Go try to EXEC it..... ;AN000; +; $ELSE ; ;AN002; + JMP SHORT $$EN17 +$$IF17: + Message msgSameSwitch ; ;AN002; + mov Fatal_Error,Yes ; ;AN002; +; $ENDIF ; ;AN002; +$$EN17: +; $ENDIF ; ;AN000; +$$IF16: +; $ENDIF ; ;AN000; +$$IF15: + ret ; ;AN000; + +Check_For_FS_Switch endp ; ;AN000; + +;***************************************************************************** +;Routine name: Parse_For_FS_Switch +;***************************************************************************** +; +;Description: Copy the command line. Parse the new command line (Parse routines +; destroy the data being parsed, so need to work on copy so that +; complete command line can be passed to child format). +; The only thing we care about is if the /FS: switch exists, so +; parse until end of command line found. If there was an error, +; and it occurred on the /FS switch, then give parse error, +; otherwise ignore the parse error, because it might be something +; file system specific that doesn't meet DOS syntax rules. Also +; check for drive letter, as it is alway required. +; +;Called Procedures: Message (macro) +; SysLoadMsg +; Preload_Error +; SysParse +; +;Change History: Created 5/1/87 MT +; +;Input: Command line at 80h in PSP +; Fatal_Error = NO +; PSP_Segment +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; Copy command line to buffer +; DO +; Parse command line (Call SysParse) +; LEAVE end of parse +; ENDDO found /FS +; IF drive letter not found (This assumes drive letter before switches) +; Tell user +; Fatal_Error = YES +; ENDIF +; ret +;***************************************************************************** + +Procedure Parse_For_FS_Switch ; ;AN000; + ; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + mov Drive_Letter_Buffer.Drive_Number,Init ; ;AN000; + mov cx,PSP_Segment ;Get segment of PSP ;AN000; + mov ds,cx ; " " " " ;AN000; + assume ds:nothing ; + ; + mov si,Command_Line_Parms ;Point at command line ;AN000; + mov di,offset data:Command_Line_Buffer ;Where to put a copy of it ;AN000; + mov cx,Command_Line_Length ;How long was input? ;AN000; + repnz movsb ;Copy it ;AN000; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + xor cx,cx ; ;AN000; + xor dx,dx ;Required for SysParse call ;AN000; + mov si,offset Command_Line_Buffer ;Pointer to parse line ;AN000; + mov di,offset Switch_FS_Table ;Pointer to control table ;AN000; +; $DO ;Setup parse call ;AN000; +$$DO25: + call SysParse ;Go parse ;AN000; + cmp ax,End_Of_Parse ;Check for end of parse ;AN000; +; $LEAVE E,OR ;Exit if it is end, or ;AN000; + JE $$EN25 + cmp ax,Operand_Missing ; exit if positional missing ;AN000; +; $LEAVE E ;In other words, no drive letter;AN000; + JE $$EN25 + cmp Switch_String_Buffer.Switch_Pointer,offset Switch_FS_Control.Keyword ;AN000; +; $ENDDO E ;Exit if we find /FS ;AN000; + JNE $$DO25 +$$EN25: + cmp Drive_Letter_Buffer.Drive_Type,Type_Drive ;Check for drive letter found;AN000; +; $IF NE ;Did we not find one? ;AN000; + JE $$IF28 + MESSAGE msgNeedDrive ;Must enter drive letter ;AN000; + mov Fatal_Error,Yes ;Indicate error on exit ;AN000; +; $ENDIF ; ;AN000; +$$IF28: + ret ; ;AN000; + +Parse_For_FS_Switch endp ; ;AN000; + + +ENDIF ;/FS: conditional assembly end ;an018;dms; + + +;***************************************************************************** +;Routine name: Parse_Command_Line +;***************************************************************************** +; +;Description: Parse the command line. Check for errors, and display error and +; exit program if found. Use parse error messages except in case +; of no parameters, which has its own message +; +;Called Procedures: Message (macro) +; SysParse +; Interpret_Parse +; +;Change History: Created 5/1/87 MT +; +;Input: Fatal_Error = NO +; PSP_Segment +; +;Output: Fatal_Error = YES/NO +; +; +;Psuedocode +;---------- +; +; Assume Fatal_Error = NO on entry +; SEARCH +; EXITIF Fatal_Error = YES,OR (This can be set by Interpret_Parse) +; Parse command line (CALL SysParse) +; EXITIF end of parsing command line +; Figure out last thing parsed (Call Interpret_Parse) +; ORELSE +; See if parse error +; LEAVE parse error,OR +; See what was parsed (Call Interpret_Parse) +; LEAVE if interpret error such as bad volume label +; ENDLOOP +; Display parse error message and print error operand +; Fatal_Error = YES +; ENDSRCH +; ret +;***************************************************************************** + +Procedure Parse_Command_Line ; ;AN000; + + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + push ds + mov cx,PSP_Segment ;Get segment of PSP ;AN000; + mov ds,cx ; " " " " ;AN000; + + assume ds:nothing,es:data + + xor cx,cx ;Parse table @DI ;AN000; + xor dx,dx ;Parse line @SI ;AN000; + mov si,Command_Line_Parms ;Pointer to parse line ;AN000; + mov word ptr es:Command_Old_Ptr,si + mov di,offset es:Command_Line_Table ;Pointer to control table ;AN000; +; $SEARCH ;Loop until all parsed ;AN000; +$$DO30: + cmp es:Fatal_Error,Yes ;Interpret something bad? ;AN000; +; $EXITIF E,OR ;If so, don't parse any more ;AN000; + JE $$LL31 + call SysParse ;Go parse ;AN000; + cmp ax,End_Of_Parse ;Check for end of parse ;AN000; +; $EXITIF E ;Is it? ;AN000; + JNE $$IF30 +$$LL31: + ;All done ;AN000; +; $ORELSE ;Not end ;AN000; + JMP SHORT $$SR30 +$$IF30: + cmp ax,0 ;Check for parse error ;AN000; +; $LEAVE NE ;Stop if there was one ;AN000; + JNE $$EN30 + mov word ptr es:Command_Old_Ptr,si + call Interpret_Parse ;Go find what we parsed ;AN000; +; $ENDLOOP ;Parse error, see what it was ;AN000; + JMP SHORT $$DO30 +$$EN30: + mov byte ptr ds:[si],0 + push di + push ax + mov di,offset es:Sublist_MsgParse_Error + mov ax,word ptr es:Command_Old_Ptr + mov word ptr es:[di+2],ax + mov word ptr es:[di+4],ds + pop ax + pop di + PARSE_MESSAGE ;Display parse error ;AN000; + mov es:Fatal_Error,YES ;Indicate death! ;AN000; +; $ENDSRCH ; ;AN000; +$$SR30: + pop ds ; ;AN000; + ret ; ;AN000; + +Parse_Command_Line endp ; ;AN000; + +;***************************************************************************** +;Routine name: Interpret_Parse +;***************************************************************************** +; +;Description: Set the SwitchMap field with the switches found on the +; command line. Get the drive letter. /FS will be handled before +; here, will not be seen in this parse or accepted. Also, if /V +; see if volume label entered and verify it is good, setting up +; FCB for later create +; +;Called Procedures: Get_11_Characters +; +;Change History: Created 5/1/87 MT +; +;Input: Fatal_Error = NO +; +;Output: SwitchMap set +; DriveLetter set +; DriveNum set A=0,B=1 etc... +; Command_Line = YES/NO +; Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; +; IF Drive letter parsed +; Drive = Parsed drive number -1 +; DriveLetter = (Parsed drive number - 1) +'A' +; ENDIF +; IF /1 +; or SwitchMap,Switch_1 +; ENDIF +; IF /4 +; or SwitchMap,Switch_4 +; ENDIF +; IF /8 +; or SwitchMap,Switch_8 +; ENDIF +; IF /S +; or SwitchMap,Switch_S +; ENDIF +; IF /BACKUP +; or SwitchMap,Switch_BACKUP +; ENDIF +; IF /B +; or SwitchMap,Switch_B +; ENDIF +; IF /T +; or SwitchMap,Switch_T +; TrackCnt = entered value +; ENDIF +; IF /N +; or SwitchMap,Switch_N +; NumSectors = entered value +; ENDIF +; IF /SELECT +; or SwitchMap,Switch_SELECT +; ENDIF +; IF /V +; or SwitchMap,Switch_V +; IF string entered +; Build ASCIIZ string for next call (CALL Build_String) +; Verify DBCS and setup FCB (CALL Get_11_Characters) +; Command_Line = YES +; IF error +; Invalid label message +; Fatal_Error = YES +; ENDIF +; ENDIF +; ENDIF +; IF /AUTOTEST +; or SwitchMap,Switch_AUTOTEST +; ENDIF +; +; IF /F +; or SwitchMap,Switch_F +; or Size_Map,Item_Tag +; ENDIF +; IF /Z (only if assembled) +; or SwitchMap,Switch_Z +; ENDIF +; ret +;***************************************************************************** + +Procedure Interpret_Parse ; ;AN000; + + push ds ;Save segment ;AN000; + push si ;Restore SI for parser ;AN000; + push cx ; ;AN000; + push di ; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + cmp byte ptr Drive_Letter_Buffer.Drive_Type,Type_Drive ;Have drive letter? ;AN000; +; $IF E ;Yes, save info ;AN000; + JNE $$IF36 + mov al,Drive_Letter_Buffer.Drive_Number ;Get drive entered ;AN000; + dec al ;Make it 0 based ;AN000; + mov Drive,al ; " " " " ;AN000; + add al,'A' ;Make it a drive letter ;AN000; + mov DriveLetter,al ;Save it ;AN000; +; $ENDIF ; ;AN000; +$$IF36: + cmp Switch_Buffer.Switch_Pointer,offset Switch_1_Control.Keyword ;;AN000; +; $IF E ; ;AN000; + JNE $$IF38 + mov Switch_1_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_1 ; ;AN000; +; $ENDIF ; ;AN000; +$$IF38: + cmp Switch_Buffer.Switch_Pointer,offset Switch_4_Control.Keyword ;;AN000; +; $IF E ; ;AN000; + JNE $$IF40 + mov Switch_4_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_4 ; ;AN000; +; $ENDIF ; ;AN000; +$$IF40: + cmp Switch_Buffer.Switch_Pointer,offset Switch_8_Control.Keyword ;;AN000; +; $IF E ; ;AN000; + JNE $$IF42 + mov Switch_8_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_8 ; ;AN000; +; $ENDIF ; ;AN000; +$$IF42: + cmp Switch_Buffer.Switch_Pointer,offset Switch_S_Control.Keyword ;;AN000; +; $IF E ; ;AN000; + JNE $$IF44 + mov Switch_S_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_S ; ;AN000; +; $ENDIF ; ;AN000; +$$IF44: + cmp Switch_Buffer.Switch_Pointer,offset Switch_Backup_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF46 + mov Switch_Backup_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_Backup ; ;AN000; +; $ENDIF ; ;AN000; +$$IF46: + cmp Switch_Buffer.Switch_Pointer,offset Switch_Select_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF48 + mov Switch_Select_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_Select ; ;AN000; +; $ENDIF ; ;AN000; +$$IF48: + cmp Switch_Buffer.Switch_Pointer,offset Switch_B_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF50 + mov Switch_B_Control.Keyword,20H + or SwitchMap,Switch_B ; ;AN000; +; $ENDIF ; ;AN000; +$$IF50: + cmp Switch_Num_Buffer.Switch_Num_Pointer,offset es:Switch_T_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF52 + mov Switch_T_Control.Keyword,20h ;an000; dms;remove switch from table + mov Switch_Num_Buffer.Switch_Num_Pointer,0 ;Init for next switch ;AN008; + test SwitchMap,Switch_T ;Don't allow if switch already ;AN002; +; $IF Z ; entered ;AN002; + JNZ $$IF53 + or SwitchMap,Switch_T ; ;AN000; + mov ax,Switch_Num_Buffer.Switch_Number_Low ;Get entered tracks ;AN000; + mov TrackCnt,ax ;1024 or less, so always dw ;AN000; +; $ELSE ; ;AN002; + JMP SHORT $$EN53 +$$IF53: + Message msgSameSwitch ; ;AN002; + mov Fatal_Error,Yes ; ;AN002; +; $ENDIF ; ;AN000; +$$EN53: +; $ENDIF ; ;AN002; +$$IF52: + cmp Switch_Num_Buffer.Switch_Num_Pointer,offset Switch_N_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF57 + mov Switch_N_Control.Keyword,20h ;an000; dms;remove switch from table + mov Switch_Num_Buffer.Switch_Num_Pointer,0 ;Init for next switch ;AN008; + test SwitchMap,Switch_N ;Make sure switch not already ;AN002; +; $IF Z ; entered ;AN002; + JNZ $$IF58 + or SwitchMap,Switch_N ; ;AN000; + mov ax,Switch_Num_Buffer.Switch_Number_Low ;Get entered tracks ;AN000; + xor ah,ah ;clear high byte ;an000; + mov NumSectors,ax ;Save tracks per sector ;AN000; +; $ELSE ; ;AN002; + JMP SHORT $$EN58 +$$IF58: + Message msgSameSwitch ; ;AN002; + mov Fatal_Error,Yes ; ;AN002; +; $ENDIF ; ;AN000; +$$EN58: +; $ENDIF ; ;AN002; +$$IF57: + cmp Switch_String_Buffer.Switch_String_Pointer,offset Switch_V_Control.Keyword ;AN000; +; $IF E ;If /v and haven't already done ;AN000; + JNE $$IF62 + mov Switch_String_Buffer.Switch_String_Pointer,0 ;Init for next switch ;AN008; + mov Switch_V_Control.Keyword,20h ;an000; dms;remove switch from table + test SwitchMap,Switch_V ; it - Only allow one /V entry ;AN002; +; $IF Z ; ;AN002; + JNZ $$IF63 + or SwitchMap,Switch_V ;Set /v indicator ;AN000; + mov si,Switch_String_Buffer.Switch_String_Seg ;Get string address ;;AN000; + mov ds,si ; ;AN000; + + assume ds:nothing + + mov si,es:Switch_String_Buffer.Switch_String_Off ; ;AN000; + cmp byte ptr ds:[si],None ;Is there a string there? ;AN000; +; $IF NE ;Yep ;AN000; + JE $$IF64 + cld ; ;AN000; + mov di,offset es:Vol_Label_Buffer ;Point at buffer to move string;AN000; + mov cx,Label_Length+1 ;Max length of string ;AN000; + rep movsb ;This will copy string & always ;AN000; + ; leave ASCIIZ end in buffer, ; ; + ; which is init'd to 13 dup(0) ; ; + mov si,offset es:Vol_Label_Buffer ;Point at string ;AN000; + Set_Data_Segment ;Set DS,ES to Data segment ;AN000; + mov Command_Line,YES ;Set flag indicating vol label ;AN000; + call Get_11_Characters ;Check DBCS and build FCB ;AN000; +; $IF C ;Bad DBCS setup ;AN000; + JNC $$IF65 + Message msgBadVolumeID ;Tell user ;AN000; + mov es:Fatal_Error,YES ;Indicate time to quit ;AN000; +; $ENDIF ; ;AN000; +$$IF65: +; $ENDIF ; ;AN000; +$$IF64: +; $ELSE ; ;AN002; + JMP SHORT $$EN63 +$$IF63: + Message msgSameSwitch ; ;AN002; + mov Fatal_Error,Yes ; ;AN002; +; $ENDIF ; ;AN002; +$$EN63: +; $ENDIF ; ;AN000; +$$IF62: + cmp Switch_Buffer.Switch_Pointer,offset Switch_Autotest_Control.Keyword ;AN000; +; $IF E ; ;AN000; + JNE $$IF71 + mov Switch_Autotest_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_Autotest ; ;AN000; +; $ENDIF ; ;AN000; +$$IF71: + +IF ShipDisk + + cmp Switch_Buffer.Switch_Pointer,offset Switch_Z_Control.Keyword ;an000; dms;/Z switch? +; $IF E ; ;an000; dms;yes + JNE $$IF73 + mov Switch_Z_Control.Keyword,20h ;an000; dms;remove switch from table + or SwitchMap,Switch_Z ; ;an000; dms;signal switch found +; $ENDIF ; ;an000; dms; +$$IF73: + +ENDIF + + cmp Switch_String_Buffer.Switch_Pointer,offset Switch_F_Control.Keyword ; ;AN000; +; $IF E ; ;AN000; + JNE $$IF75 + mov Switch_F_Control.Keyword,20h ;an000; dms;remove switch from table + mov Switch_String_Buffer.Switch_Pointer,0 ;an000; dms; clear out ptr for next iteration + mov Switch_Num_Buffer.Switch_Num_Pointer,0 ;Init for next switch ;AN008; + test SwitchMap,Switch_F ; it - do this because SysParse ;AN002; +; $IF Z ; reuses string buffer each time;AN002; + JNZ $$IF76 + or SwitchMap,Switch_F ; ;AN000; + mov al,Switch_String_Buffer.Switch_String_Item_Tag ; Indicate what size;AN000; + or SizeMap,al ; ;AN000; +; $ELSE ; ;AN002; + JMP SHORT $$EN76 +$$IF76: + Message msgSameSwitch ; ;AN002; + mov Fatal_Error,Yes ; ;AN002; +; $ENDIF ; ;AN002; +$$EN76: +; $ENDIF ; ;AN000; +$$IF75: + pop di ;Restore parse regs ;AN000; + pop cx ; ;AN000; + pop si ; ;AN000; + pop ds ; ;AN000; + ret ; ;AN000; + +Interpret_Parse endp ; ;AN000; + + + +;***************************************************************************** +;Routine name: Validate_Target_Drive +;***************************************************************************** +; +;Description: Control routine for validating the specified format target drive. +; If any of the called routines find an error, they will print +; message and terminate program, without returning to this routine +; +;Called Procedures: Check_Target_Drive +; Check_For_Network +; Check_Translate_Drive +; +;Change History: Created 5/1/87 MT +; +;Input: Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; +; CALL Check_Target_Drive +; IF !Fatal_Error +; CALL Check_For_Network +; IF !Fatal_Error +; CALL Check_Translate_Drive +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +Procedure Validate_Target_Drive ; ;AN000; + ; + call Check_Target_Drive ;See if valid drive letter ;AN000; + cmp Fatal_Error,YES ;Can we continue? ;AN000; +; $IF NE ;Yep ;AN000; + JE $$IF80 + call Check_For_Network ;See if Network drive letter ;AN000; + cmp Fatal_Error,YES ;Can we continue? ;AN000; +; $IF NE ;Yep ;AN000; + JE $$IF81 + call Check_Translate_Drive ;See if Subst, Assigned ;AN000; +; $ENDIF ;- Fatal_Error passed back ;AN000; +$$IF81: +; $ENDIF ; ;AN000; +$$IF80: + ret ; ;AN000; + +Validate_Target_Drive endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_Target_Drive +;***************************************************************************** +; +;Description: Check to see if valid DOS drive by checking if drive is +; removable. If error, the drive is invalid. Save default +; drive info. +; +;Called Procedures: Message (macro) +; +;Change History: Created 5/1/87 MT +; +;Input: Fatal_Error = NO +; +;Output: BIOSFile = default drive letter +; DOSFile = default drive letter +; CommandFile = default drive letter +; Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; +; Get default drive (INT 21h, AH = 19h) +; Convert it to drive letter +; Save into BIOSFile,DOSFile,CommandFile +; See if drive removable (INT 21h, AX=4409h IOCtl) +; IF error - drive invalid +; Display Invalid drive message +; Fatal_Error= YES +; ENDIF +; ret +;***************************************************************************** + +Procedure Check_Target_Drive ; ;AN000; + ; + DOS_Call Get_Default_Drive ;Find the current drive ;AC000; + add al,'A' ;Convert to drive letter ; ; + mov BIOSFile,al ;Put it into path strings ; ; + mov DOSFile,al ; " " " " ; ; + mov CommandFile,al ; " " " " ; ; + mov bl,Drive ;Set up for next call ;AN000; + inc bl ;A=1,B=2 for IOCtl call ;AN000; + mov al,09h ;See if drive is local ;AC000; + DOS_Call IOCtl ;-this will fail if bad drive ;AC000; +; $IF C ;CY means invalid drive ;AC000; + JNC $$IF84 + Extended_Message ;Print message ;AC000; + mov Fatal_Error,Yes ;Indicate error ;AN000; +; $ENDIF ; ;AN000; +$$IF84: + ret ;And we're outa here ;AN000; + +Check_Target_Drive endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_For_Network +;***************************************************************************** +; +;Description: See if target drive isn't local, or if it is a shared drive. If +; so, exit with error message. The IOCtl call is not checked for +; an error because it is called previously in another routine, and +; invalid drive is the only error it can generate. That condition +; would not get this far +; +;Called Procedures: Message (macro) +; +;Change History: Created 5/1/87 MT +; +;Input: Drive +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; See if drive is local (INT 21h, AX=4409 IOCtl) +; IF not local +; Display network message +; Fatal_ERROR = YES +; ELSE +; IF 8000h bit set on return +; Display assign message +; Fatal_Error = YES +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +Procedure Check_For_Network ; ;AN000; + ; + mov bl,Drive ;Drive is 0=A, 1=B ; ; + inc bl ;Get 1=A, 2=B for IOCtl call ; ; + mov al,09h ;See if drive is local or remote;AC000; + DOS_CALL IOCtl ;We will not check for error ;AC000; + test dx,Net_Check ;if (x & 1200H)(redir or shared); ; +; $IF NZ ;Found a net drive ;AC000; + JZ $$IF86 + Message MsgNetDrive ;Tell 'em ;AC000; + mov Fatal_Error,Yes ;Indicate bad stuff ;AN000; +; $ELSE ;Local drive, now check assign ;AN000; + JMP SHORT $$EN86 +$$IF86: + test dx,Assign_Check ;8000h bit is bad news ; ; +; $IF NZ ;Found it ;AC000; + JZ $$IF88 + Message MsgAssignedDrive ;Tell error ;AC000; + mov Fatal_Error,Yes ;Indicate bad stuff ;AN000; +; $ENDIF ; ;AN000; +$$IF88: +; $ENDIF ; ;AN000; +$$EN86: + ret ; ;AN000; + +Check_For_Network endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_Translate_Drive +;***************************************************************************** +; +;Description: Do a name translate call on the drive letter to see if it is +; assigned by SUBST or ASSIGN +; +;Called Procedures: Message (macro) +; +;Change History: Created 5/1/87 MT +; +;Input: Drive +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; +;Psuedocode +;---------- +; Put drive letter in ASCIIZ string "d:\",0 +; Do name translate call (INT 21) +; IF drive not same +; Display assigned message +; Fatal_Error = YES +; ENDIF +; ret +;***************************************************************************** + +Procedure Check_Translate_Drive ; ;AN000; + ; + mov bl,Drive ;Get drive ; ; + add byte ptr [TranSrc],bl ;Make string "d:\" ; ; + mov si,offset TranSrc ;Point to translate string ; ; + push ds ;Set ES=DS (Data segment) ; ; + pop es ; " " " " ; ; + mov di,offset Command_Line_Buffer ;Point at output buffer ; ; + DOS_Call xNameTrans ;Get real path ;AC000; + mov bl,byte ptr [TranSrc] ;Get drive letter from path ; ; + cmp bl,byte ptr Command_Line_Buffer ;Did drive letter change? ; ; +; $IF NE ;If not the same, it be bad ;AC000; + JE $$IF91 + Message MsgAssignedDrive ;Tell user ;AC000; + mov Fatal_Error,Yes ;Setup error flag ;AN000; +; $ENDIF ; ;AN000; +$$IF91: + ret ; ;AN000; + +Check_Translate_Drive endp ; ;AN000; + +;***************************************************************************** +;Routine name: Hook_CNTRL_C +;***************************************************************************** +; +;Description: Change the interrupt handler for INT 13h to point to the +; ControlC_Handler routine +; +;Called Procedures: None +; +;Change History: Created 4/21/87 MT +; +;Input: None +; +;Output: None +; +;Psuedocode +;---------- +; +; Point at ControlC_Handler routine +; Set interrupt handler (INT 21h, AX=2523h) +; ret +;***************************************************************************** + +Procedure Hook_CNTRL_C ; ;AN000; + ; + mov al,23H ;Specify CNTRL handler ; ; + mov dx, offset ControlC_Handler ;Point at it ; ; + push ds ;Save data seg ; ; + push cs ;Point to code segment ; ; + pop ds ; ; ; + DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;AC000; + pop ds ;Get Data degment back ; ; + ret ; ;AN000; + +Hook_CNTRL_C endp ; ;AN000; + +;========================================================================= +; Check_For_Invalid_Drive : This routine checks the AX received by +; FORMAT on its entry. This value will +; tell us if we are attempting to format +; a JOINED drive. +; +; Inputs : Org_AX - AX on entry to FORMAT +; +; Outputs : Fatal_Error - Yes if AL contained FFh +;========================================================================= + +Procedure Check_For_Invalid_Drive ;an000; dms; + + push ax ;an000; dms;save ax + cmp FAT_Flag,Yes ;an000; dms;FAT system? +; $if e ;an000; dms;yes + JNE $$IF93 + mov ax,Org_AX ;an000; dms;get its org. value + cmp al,0ffh ;an000; dms;Invalid drive? +; $if e ;an000; dms;yes + JNE $$IF94 + mov Fatal_Error,YES ;an000; dms;flag an error + mov ax,Invalid_Drive;an000; dms;error message + Extended_Message ;an000; dms;tell error +; $endif ;an000; dms; +$$IF94: +; $endif ;an000; dms; +$$IF93: + pop ax ;an000; dms; + ret ;an000; dms; + +Check_For_Invalid_Drive endp ;an000; dms; + + +;========================================================================= +; Determine_FAT_Non_FAT - This routine determines whether or +; not a device is formatted to a FAT +; specification versus a Non-FAT +; specification. +; +; Inputs : DX - Pointer to device parameters buffer +; +; Outputs : DeviceParameters - buffer containing BPB. +; +; Date : 11/6/87 +;========================================================================= + +Procedure Determine_FAT_Non_FAT ;an012; dms; + + push ax ;an012; dms;save regs + push dx ;an012; dms; + + lea dx, deviceParameters ;an012; dms;point to buffer + mov deviceParameters.DP_SpecialFunctions, 0 ;an012; dms;get default BPB + call GetDeviceParameters ;an012; dms;make the call +; $if nc ;an012; dms;no error occurred + JC $$IF97 + cmp byte ptr DeviceParameters.DP_BPB.BPB_NumberOfFATS,00h ;an012; dms;non-FAT system? +; $if e ;an012; dms;yes + JNE $$IF98 + mov FAT_Flag,No ;an012; dms;signal system non-FAT + mov ax,5f07h ;an012; dms;allow access to disk + mov dl,Drive ;an012; dms;get 0 based driver number + int 21h ;an012; dms;allow access to the drive +; $else ;an012; dms;FAT system + JMP SHORT $$EN98 +$$IF98: + mov FAT_Flag,Yes ;an012; dms;flag FAT system +; $endif ;an012; dms; +$$EN98: +; $endif ;an012; dms; +$$IF97: + + pop dx ;an012; dms;restore regs + pop ax ;an012; dms; + + ret ;an012; dms; + +Determine_FAT_Non_FAT endp ;an012; dms; + + + + +code ends + end + + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORLABEL.ASM b/v4.0/src/CMD/FORMAT/FORLABEL.ASM new file mode 100644 index 0000000..a7d46a1 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORLABEL.ASM @@ -0,0 +1,771 @@ + +; +;***************************************************************************** +;***************************************************************************** +; +;UTILITY NAME: FORMAT.COM +; +;MODULE NAME: FORLABEL.SAL +; +; Interpret_Parse +; | +;* | +;³ÚÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿|ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;À´VolIDôGet_New_LabelÃÄ´Get_11_CharactersôChange_Blanks³ +; ÀÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôSkip_Blanks³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ôCheck_DBCS_OverrunôCheck_DBCS_Character³ +; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; À´Copy_FCB_String³ +; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +;***************************************************************************** +;***************************************************************************** + +data segment public para 'DATA' +data ends + +code segment public para 'CODE' + assume cs:code,ds:data +code ends + +.xlist +INCLUDE FORCHNG.INC +INCLUDE FORMACRO.INC +INCLUDE SYSCALL.INC +INCLUDE FOREQU.INC +INCLUDE FORSWTCH.INC +.list + +; +;***************************************************************************** +; Equates +;***************************************************************************** +; + +None equ 0 +StdIn equ 0 +StdOut equ 1 +StdErr equ 2 +Tab equ 09h +Label_Buffer_length equ 80h +Create_Worked equ 0 ;an024; + + +; +;***************************************************************************** +; External Data Declarations +;***************************************************************************** +; + + Extrn SwitchMap:Word + Extrn Switch_String_Buffer:Byte + Extrn VolFCB:Byte + Extrn MsgBadCharacters:Byte + Extrn MsgLabelPrompt:Byte + Extrn MsgBadVolumeID:Byte + Extrn MsgCRLF:Byte + Extrn VolNam:Byte + Extrn Vol_Label_Count:Byte + Extrn VolDrive:Byte + Extrn Drive:Byte + Extrn Command_Line:Byte + Extrn Vol_Label_Buffer:Byte + Extrn DelDrive:Byte + Extrn DelFCB:Byte + +code segment public para 'CODE' + +;************************************************************************************************ +;Routine name Volid +;************************************************************************************************ +; +;Description: Get volume id from command line /V:xxxxxxx if it is there, or +; else prompt user for volume label, parse the input. At this +; point setup the FCB and create the volume label. If failure, +; prompt user that they entered bad input, and try again. +; +; Note: This routine in 3.30 and prior used to check for /V +; switch. Volume labels are always required now, so /V +; is ignored, except to get volume label on command line. +; +;Called Procedures: Message (macro) +; Get_New_Label +; +;Change History: Created 5/1/87 MT +; +;Input: Switch_V +; Command_Line = YES/NO +; +;Output: None +; +;Psuedocode +;---------- +; +; Save registers +; IF /V switch entered +; IF /v:xxxxx form not entered +; CALL Get_New_Label ;Return string in Volume_Label +; ENDIF +; ELSE +; CALL Get_New_Label ;Return string in Volume_Label +; ENDIF +; DO +; Create volume label +; LEAVE Create Ok +; Display Bad Character message +; CALL Get_New_Label ;Return string in Volume_Label +; ENDDO +; Restore registers +; ret +;***************************************************************************** + +Procedure Volid ; ;AN000; + + push ds ;Save registers ;AN000; + push si ; " " " " ;AN000; + test SwitchMap,Switch_V ;Was /V entered ;AN000; +; $IF NZ ;Yes, see if label entered also ;AN000; + JZ $$IF1 + cmp Command_Line,YES ;Is there a string there? ;AN000; +; $IF NE ;Nope ;AN000; + JE $$IF2 + call Get_New_Label ;Go get volume label from user ;AN000; +; $ENDIF ; ;AN000; +$$IF2: +; $ELSE ;Label not entered on cmd line ;AN000; + JMP SHORT $$EN1 +$$IF1: + call Get_New_Label ;Go get label from user ;AN000; +; $ENDIF ; ;AN000; +$$EN1: + mov dl,drive ;Get drive number A=0 ;AN000; + inc dl ;Make it 1 based ;AN000; + mov DelDrive,dl ;Put into FCBs ;AN000; + mov VolDrive,dl ; ;AN000; + mov dx,offset DelFCB ;Point at FCB to delete label ;AN000; + DOS_Call FCB_Delete ;Do the delete ;AN000; + mov dx,offset VolFCB ;Point at FCB for create ;AN000; + DOS_CALL FCB_Create ;Go create it ;AN000; + cmp dl,Create_Worked ;See if the create worked ;an024; +; $IF E ;an024; + JNE $$IF6 + mov dx,offset VolFCB ;Point to the FCB created ;an022; dms; + DOS_Call FCB_Close ;Close the newly created FCB ;an022; dms; +; $ENDIF ;an024; +$$IF6: + + pop si ;Restore registers ;AN000; + pop ds ; " " " " ;AN000; + ret ; ;AN000; + +Volid endp ; ;AN000; + +;***************************************************************************** +;Routine name: Get_New_Label +;***************************************************************************** +; +;Description: Prompts, inputs and verifies a volume label string. Continues +; to prompt until valid vol label is input +; +;Called Procedures: Message (macro) +; Build_String +; Get_11_Characters +; +;Change History: Created 3/18/87 MT +; +;Input: None +; +;Output: Volume_Label holds +; +;Psuedocode +;---------- +; +; DO +; Display new volume label prompt +; Input vol label +; IF No error (NC) +; Build Asciiz string with label, pointer DS:SI (CALL Build_String) +; Call Get_11_Characters (Error returned CY) +; ENDIF +; LEAVE no error (NC) +; Display label error +; ENDDO +; ret +;***************************************************************************** + +Procedure Get_New_Label ; ;AN000; + +; $DO ;Loop until we get good one ;AN000; +$$DO8: + Message msgLabelPrompt ;Prompt to input Vol label ;AN000; + mov ax,(Std_Con_Input_Flush shl 8) + 0 ;an000; dms;clean out input + int 21h ;an000; dms; + mov dx,offset Vol_Label_Count ;an000; dms;beginning of buffer + mov ah,Std_Con_String_Input ;an000; dms;get input + int 21h ;an000; dms; + mov ax,(Std_Con_Input_Flush shl 8) + 0 ;an000; dms; clean out input + int 21h ;an000; dms; +; $IF NC ;Read ok if NC, Bad sets CY ;AN000; + JC $$IF9 + mov si,offset Vol_Label_Buffer ;Get pointer to string ;AN000; + call Get_11_Characters ;Handle DBCS stuff on input ;AN000; +; $ENDIF ;Ret CY if error ;AN000; +$$IF9: +; $LEAVE NC ;Done if NC ;AN000; + JNC $$EN8 + Message MsgCRLF ;next line ;an020; dms; + Message msgBadVolumeID ;Tell user error ;AN000; +; $ENDDO ;Try again ;AN000; + JMP SHORT $$DO8 +$$EN8: + Message MsgCRLF ;an000; dms;next line + ret ; ;AN000; + +Get_New_Label endp ; ;AN000; + +;***************************************************************************** +;Routine name: Get_11_Characters +;***************************************************************************** +; +;Description: Handle DBCS considerations, and build FCB to create vol label +; +; +;Called Procedures: Change_Blanks +; Skip_Blanks +; Check_DBCS_Overrun +; Copy_FCB_String +; +;Change History: Created 5/12/87 MT +; +;Input: DS:SI = Asciiz string containing volume label input +; Command_Line = YES/NO +; +;Output: Volname will contain an 8.3 volume label in FCB +; CY set on invalid label +; +;Psuedocode +;---------- +; Save regs used +; Scan line replacing all DBCS blanks with SBCS (CALL_Change_Blanks) +; Skip over leading blanks (Call Skip_Blanks) +; IF leading blanks ,AND +; IF Command line +; Indicate invalid label (STC) +; ELSE +; See if DBCS character at 11th byte (CALL Check_DBCS_Overrun) +; IF DBCS character at 11th byte +; Indicate invalid label (STC) +; ELSE +; Put string into FCB (CALL Copy_FCB_STRING) +; CLC +; ENDIF +; ENDIF +; Restore regs +; ret +;***************************************************************************** + +Procedure Get_11_Characters ; ;AN000; + + call Change_Blanks ;Change DBCS blanks to SBCS ;AN000; + call Skip_Blanks ;Skip over leading blanks ;AN000; +; $IF C,AND ;Find leading blanks? ;AN000; + JNC $$IF13 + cmp Command_Line,YES ;Is this command line input? ;AN000; +; $IF E ;Yes ;AN000; + JNE $$IF13 + stc ;Indicate error (CY set) ;AN000; +; $ELSE ;Leading blanks ok ;AN000; + JMP SHORT $$EN13 +$$IF13: + call Check_DBCS_Overrun ;Is DBCS char at 11th byte? ;AN000; +; $IF C ;Yes ;AN000; + JNC $$IF15 + stc ;Indicate invalid label ;AN000; +; $ELSE ;No, good characters ;AN000; + JMP SHORT $$EN15 +$$IF15: + call Copy_FCB_String ;Put string into FCB ;AN000; + clc ;Indicate everything A-OK! ;AN000; +; $ENDIF ; ;AN000; +$$EN15: +; $ENDIF ; ;AN000; +$$EN13: + ret ; ;AN000; + +Get_11_Characters endp ; ;AN000; + +;***************************************************************************** +;Routine name: Change_Blanks +;***************************************************************************** +; +;Description: Replace all DBCS blanks with SBCS blanks, end string with +; Asciiz character if one doesn't already exist +; +;Called Procedures: Check_DBCS_Character +; +;Change History: Created 6/12/87 MT +; +;Input: DS:SI = String containing volume label input +; +;Output: DS:SI = ASCIIZ string with all DBCS blanks replaced with 2 SBCS blanks +; +; +;Psuedocode +;---------- +; +; Save pointer to string +; DO +; LEAVE End of string (0) +; See if DBCS character (Check_DBCS_Character) +; IF CY (DBCS char found) +; IF first byte DBCS blank, AND +; IF second byte DBCS blank +; Convert to SBCS blanks +; ENDIF +; Point to next byte to compensate for DBCS character +; ENDIF +; ENDDO +; Tack on ASCIIZ character to string +; Restore pointer to string +; +;***************************************************************************** + +Procedure Change_Blanks ; ;AN000; + + push si ;Save pointer to string ;AN000; + push cx ; ;AN000; + push ax ; ;AN000; + xor cx,cx ; ;AN000; +; $DO ;Do while not CR ;AN000; +$$DO19: + cmp byte ptr [si],Asciiz_End ;Is it end of string? ;AN000; +; $LEAVE E,OR ;All done if so ;AN000; + JE $$EN19 + cmp byte ptr [si],CR ;Is it CR? ;AN000; +; $LEAVE E,OR ;Exit if yes,end of label ;AN000; + JE $$EN19 + inc cx ;Count the character ;AN000; + cmp cx,Label_Buffer_Length ;Reached max chars? (80h) ;AN000; +; $LEAVE E ;Exit if so ;AN000; + JE $$EN19 + mov al,byte ptr [si] ;Get char to test for DBCS ;AN000; + call Check_DBCS_Character ;Test for dbcs lead byte ;AN000; +; $IF C ;We have a lead byte ;AN000; + JNC $$IF21 + cmp byte ptr [si],DBCS ;Is it a lead blank? ;AN000; +; $IF E,AND ;If a dbcs char ;AN000; + JNE $$IF22 + cmp byte ptr [si+1],DBCS_Blank ;Is it an Asian blank? ;AN000; +; $IF E ;If an Asian blank ;AN000; + JNE $$IF22 + mov byte ptr [si+1],Blank ;set up moves ;AN000; + mov byte ptr [si],Blank ; to replace ;AN000; +; $ENDIF ; ;AN000; +$$IF22: + inc si ;Point to dbcs char ;AN000; +; $ENDIF ;End lead byte test ;AN000; +$$IF21: + inc si ;Point to si+1 ;AN000; +; $ENDDO ;End do while ;AN000; + JMP SHORT $$DO19 +$$EN19: + mov byte ptr [si],Asciiz_End ;Mark end of string ;AN000; + pop ax ;Restore regs ;AN000; + pop cx ; ;AN000; + pop si ; ;AN000; + ret ;return to caller ;AN000; + +Change_Blanks endp ; ;AN000; + +;***************************************************************************** +;Routine name: Skip_Blanks +;***************************************************************************** +; +;Description: Scan ASCIIZ string for leading blanks, return pointer to first +; non-blank character. Set CY if blanks found +; +;Called Procedures: None +; +;Change History: Created 6/12/87 MT +; +;Input: DS:SI = ASCIIZ string containing volume label input +; +;Output: DS:SI = Input string starting at first non-blank character +; CY set if blanks found +; +; +; +;Psuedocode +;---------- +; +; Save original pointer, DI register +; DO +; Look at character from string +; LEAVE End of string (0) +; IF character is blank,OR +; IF character is tab +; INC pointer (SI) +; Indicate blank +; ELSE +; Indicate non-blank +; ENDIF +; ENDDO non-blank +; Get back pointer +; Cmp string pointer to original pointer +; IF NE +; STC +; ELSE +; CLC +; ENDIF +; ret +;***************************************************************************** + +Procedure Skip_Blanks ; ;AN000; + + push di ;Preserve DI, just in case ;AN000; + push si ;Save pointer to string ;AN000; +; $DO ;Look at entire ASCIIZ string ;AN000; +$$DO26: + cmp byte ptr [si],ASCIIZ_End ;End of string? ;AN000; +; $LEAVE E ;Yep, exit loop ;AN000; + JE $$EN26 + cmp byte ptr [si],Blank ;Find a blank? ;AN000; +; $IF E,OR ;Yes ;AN000; + JE $$LL28 + cmp byte ptr [si],TAB ;Is it tab? ;AN000; +; $IF E ;Yes ;AN000; + JNE $$IF28 +$$LL28: + inc si ;Bump pointer to next character ;AN000; + clc ;Indicate found blank ;AN000; +; $ELSE ;Not blank or tab ;AN000; + JMP SHORT $$EN28 +$$IF28: + stc ;Force exit ;AN000; +; $ENDIF ; ;AN000; +$$EN28: +; $ENDDO C ;Go look at next character ;AN000; + JNC $$DO26 +$$EN26: + pop di ;Get back original pointer ;AN000; + cmp di,si ;Are they the same? ;AN000; +; $IF NE ;If not equal blanks were found ;AN000; + JE $$IF32 + stc ;Set CY ;AN000; +; $ELSE ;No leading blanks found ;AN000; + JMP SHORT $$EN32 +$$IF32: + clc ;Clear CY ;AN000; +; $ENDIF ; ;AN000; +$$EN32: + pop di ;Restore DI ;AN000; + ret ; ;AN000; + +Skip_Blanks endp ; ;AN000; + + +;***************************************************************************** +;Routine name: Copy_FCB_String +;***************************************************************************** +; +;Description: Build an 11 character string in the FCB from ASCIIZ string +; If nothing entered, than terminated with 0. Also add drive +; number in FCB +; +;Called Procedures: None +; +;Change History: Created 6/12/87 MT +; +;Input: DS:SI = String containing volume label input +; +;Output: VOLNAM is filled in with Volume label string +; +; +; +;Psuedocode +;---------- +; +; Save regs +; Init VolNam to blanks +; DO +; LEAVE if character is end of ASCIIZ string +; Mov character to FCB +; Inc counter +; ENDDO all 11 chars done +; Restore regs +;***************************************************************************** + +Procedure Copy_FCB_String ; ;AN000; + + push di ; ;AN000; + push cx ; ;AN000; + push si ;Save pointer to string ;AN000; + cld ;Set string direction to up ;AN000; + mov di,offset Volnam ;Init FCB field to blanks ;AN000; + mov al,Blank ; " " " " ;AN000; + mov cx,Label_Length ; " " " " ;AN000; + rep stosb ; " " " " ;AN000; + pop si ;Get back pointer to string ;AN000; + mov di,offset VolNam ;Point at FCB field ;AN000; + xor cx,cx ;Init counter ;AN000; +; $DO ;Copy characters over ;AN000; +$$DO35: + cmp byte ptr [si],ASCIIZ_End ;End of String? ;AN000; +; $LEAVE E ;Yes, don't copy - leave blanks ;AN000; + JE $$EN35 + movsb ;Nope, copy character ;AN000; + inc cx ;Bump up count ;AN000; + cmp cx,Label_Length ;Have we moved 11? ;AN000; +; $ENDDO E ;Quit if so ;AN000; + JNE $$DO35 +$$EN35: + pop cx ; ;AN000; + pop di ; ;AN000; + ret ; ;AN000; + +Copy_FCB_String endp ; ;AN000; + + +;***************************************************************************** +;Routine name: Check_DBCS_Overrun +;***************************************************************************** +; +;Description: Check 11th byte, if the string is that long, to see +; if it is a DBCS character that is split down the middle. Must +; scan entire string to properly find DBCS characters, due to +; the fact a second byte of a DBCS character can fall into +; the range of the first byte environment vector, and thus look +; like a DBCS char when it really isn't +; +;Called Procedures: Check_DBCS_Character +; +;Change History: Created 6/12/87 MT +; +;Input: DS:SI = String containing volume label input +; +;Output: CY set if DBCS character at bytes 11-12 in string +; +;***************************************************************************** + +Procedure Check_DBCS_Overrun ; ;AN000; + + push si ;Save pointer ;AN000; + push ax ;Save registers ;AN000; + push cx ; " " " " ;AN000; + mov cx,si ;Get start of string ;AN000; + add cx,Label_Length ;Find where to check for overrun;AN000; + +Check_DBCS_OverRun_Cont: ;Scan string for DBCS chars ;AN000; + + cmp byte ptr [si],ASCIIZ_End ;End of string? ;AN000; + je DBCS_Good_Exit ;Yep ;AN000; + + mov al,[si] ;Get character for routine ;AN000; + call Check_DBCS_Character ;See if DBCS leading character ;AN000; +; $if c ;DBCS if CY set ;AN000; + JNC $$IF38 + inc si ;Next byte to handle DBCS ;AN000; + cmp si,cx ;Is DBCS char spanning 11-12? ;AN000; +; $if e ;truncate string + JNE $$IF39 + mov byte ptr [si-1],20h;blank it out + mov byte ptr [si],20h ;blank it out + jmp DBCS_Good_Exit ;exit +; $endif ; +$$IF39: +; $else ;Not DBCS character ;an000; dms; + JMP SHORT $$EN38 +$$IF38: + mov al,[si] ;Get character for routine ;an000; dms; + call Scan_For_Invalid_Char ;See if invalid vol ID char ;an000; dms; + jc DBCS_Bad_Exit ;Bad char entered - exit ;an000; dms; +; $endif ; ;an000; dms; +$$EN38: + + inc si ;Point to next character ;an000; dms; + jmp Check_DBCS_OverRun_Cont ;Continue looping ;an000; dms; + +DBCS_Good_Exit: + ;an000; dms; + clc ;Signal no error ;an000; dms; + jmp DBCS_Exit ;Exit routine ;an000; dms; + +DBCS_Bad_Exit: ;an000; dms; + + stc ;Signal error ;an000; dms; + +DBCS_Exit: ;an000; dms; + + pop cx ;Restore registers ;AN000; + pop ax ; " " " " ;AN000; + pop si ;Restore string pointer ;AN000; + ret ; ;AN000; + +Check_DBCS_Overrun endp ; ;AN000; + +;***************************************************************************** +;Routine name: Check_DBCS_Character +;***************************************************************************** +; +;Description: Check if specified byte is in ranges of DBCS vectors +; +;Called Procedures: None +; +;Change History: Created 6/12/87 MT +; +;Input: AL = Character to check for DBCS lead character +; DBCS_Vector = YES/NO +; +;Output: CY set if DBCS character +; DBCS_VECTOR = YES +; +; +;Psuedocode +;---------- +; Save registers +; IF DBCS vector not found +; Get DBCS environmental vector (INT 21h +; Point at first set of vectors +; ENDIF +; SEARCH +; LEAVE End of DBCS vectors +; EXITIF Character > X1,AND (X1,Y1) are environment vectors +; EXITIF Character < Y1 +; STC (DBCS character) +; ORELSE +; Inc pointer to next set of vectors +; ENDLOOP +; CLC (Not DBCS character) +; ENDSRCH +; Restore registers +; ret +;***************************************************************************** + +Procedure Check_DBCS_Character ; ;AN000; + + push ds ;Save registers ;AN000; + push si ; " " " " ;AN000; + push ax ; " " " " ;AN000; + push ds ; " " " " ;AN000; + pop es ;Establish addressability ;AN000; + cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;AN000; + push ax ;Save input character ;AN000; +; $IF NE ;Nope ;AN000; + JE $$IF43 + mov al,0 ;Get DBCS environment vectors ;AN000; + DOS_Call Hongeul ; " " " " ;AN000; + mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector ;AN000; + mov es:DBCS_Vector_Off,si ;Save the vector ;AN000; + mov ax,ds ; ;AN000; + mov es:DBCS_Vector_Seg,ax ; ;AN000; +; $ENDIF ; for next time in ;AN000; +$$IF43: + pop ax ;Restore input character ;AN000; + mov si,es:DBCS_Vector_Seg ;Get saved vector pointer ;AN000; + mov ds,si ; ;AN000; + mov si,es:DBCS_Vector_Off ; ;AN000; +; $SEARCH ;Check all the vectors ;AN000; +$$DO45: + cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;AN000; +; $LEAVE E ;Yes, done ;AN000; + JE $$EN45 + cmp al,ds:[si] ;See if char is in vector ;AN000; +; $EXITIF AE,AND ;If >= to lower, and ;AN000; + JNAE $$IF45 + cmp al,ds:[si+1] ; =< than higher range ;AN000; +; $EXITIF BE ; then DBCS character ;AN000; + JNBE $$IF45 + stc ;Set CY to indicate DBCS ;AN000; +; $ORELSE ;Not in range, check next ;AN000; + JMP SHORT $$SR45 +$$IF45: + add si,DBCS_Vector_Size ;Get next DBCS vector ;AN000; +; $ENDLOOP ;We didn't find DBCS char ;AN000; + JMP SHORT $$DO45 +$$EN45: + clc ;Clear CY for exit ;AN000; +; $ENDSRCH ; ;AN000; +$$SR45: + pop ax ;Restore registers ;AN000; + pop si ; " " " " ;AN000; + pop ds ;Restore data segment ;AN000; + ret ; ;AN000; + +Check_DBCS_Character endp ; ;AN000; + +;========================================================================= +; Scan_For_Invalid_Char : This routine scans the bad character table +; to determine if the referenced character is +; invalid. +; +; Inputs : Bad_Char_Table - Table of bad characters +; Bad_Char_Table_Len - Length of table +; AL - Character to be searched for +; +; Outputs : CY - Bad character +; NC - Character good +;========================================================================= + +Procedure Scan_For_Invalid_Char ;an000; dms; + + push ax ;an000; dms;save ax + push cx ;an000; dms;save cx + push di ;an000; dms;save di + + lea di,Bad_Char_Table ;an000; dms;point to bad character table + mov cx,Bad_Char_Table_Len ;an000; dms;get its length + repnz scasb ;an000; dms;scan the table + cmp cx,0000h ;an000; dms;did we find the character +; $if e ;an000; dms;no - a good character + JNE $$IF51 + clc ;an000; dms;flag a good character +; $else ;an000; dms;yes - a bad character + JMP SHORT $$EN51 +$$IF51: + stc ;an000; dms;flag a bad character +; $endif ;an000; dms; +$$EN51: + + pop di ;an000; dms;restore di + pop cx ;an000; dms;restore cx + pop ax ;an000; dms;restore ax + + ret ;an000; dms; + +Scan_For_Invalid_Char endp ;an000; dms; + + +code ends + +data segment public para 'DATA' + +Bad_Char_Table label byte ;an000; dms;table of invalid vol ID chars + db "*" + db "?" + db "[" + db "]" + db ":" + db "<" + db "|" + db ">" + db "+" + db "=" + db ";" + db "," + db "/" + db "\" + db '.' + db '"' + db " " +Bad_Char_Table_Len equ $-Bad_Char_Table;an000; dms;length of table + +DBCS_Vector_Off dw 0 ; +DBCS_Vector_Seg dw 0 ; + +data ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORMACRO.INC b/v4.0/src/CMD/FORMAT/FORMACRO.INC new file mode 100644 index 0000000..63f17cf --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORMACRO.INC @@ -0,0 +1,102 @@ + + + + + + + +; +;****************************************************************************** +; Message Macro Definitions +;****************************************************************************** +; + + EXTRN Display_Interface:near + + +;----------------------------------------------------------------------------- + +Message macro Message_Name ; ;AN000; + ; + mov dx,offset data:Message_Name ; ;AN000; + call Display_Interface ; ;AN000; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Parse_Message macro ; ;AN000; + + ; + push ds + mov dx,data + mov ds,dx + mov word ptr Parse_Error_Msg,ax ; ;AN000; + mov dx,offset Parse_Error_Msg ; ;AN000; + call Display_Interface ; ;AN000; + pop ds ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Extended_Message macro ; ;AN000; + ; + + push ds + mov dx,data + mov ds,dx + mov word ptr Extended_Error_Msg,ax ; ;AN000; + mov dx,offset data:Extended_Error_Msg ; ;AN000; + call Display_Interface ; ;AN000; + pop ds + endm ; ;AN000; + +; +;***************************************************************************** +; General Macro's +;***************************************************************************** +; + +Procedure macro Proc_Name + +Public Proc_Name +Proc_Name proc + + endm +;----------------------------------------------------------------------------- + +DOS_Call macro Function + + mov ah,Function + int 21h + + endm +;----------------------------------------------------------------------------- + +Popff macro + + jmp $+3 + iret + push cs + call $-2 + + endm + + +;----------------------------------------------------------------------------- + +Set_Data_Segment macro + + push ax + mov ax,data ;Point to data segment + mov ds,ax ; + push ds + pop es + pop ax + +assume ds:data,es:data + + endm + + + + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORMAT.ASM b/v4.0/src/CMD/FORMAT/FORMAT.ASM new file mode 100644 index 0000000..c9034d7 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORMAT.ASM @@ -0,0 +1,4509 @@ +page 84,132 +; +; SCCSID = @(#)format.asm 1.26 85/10/20 +; SCCSID = @(#)format.asm 1.26 85/10/20 +;*************************************************************** +; +; 86-DOS FORMAT DISK UTILITY +; +; This routine formats a new disk,clears the FAT and DIRECTORY then +; optionally copies the SYSTEM and COMMAND.COM to this new disk +; +; SYNTAX: FORMAT [drive][/switch1][/switch2]...[/switch16] +; +; Regardless of the drive designator , the user will be prompted to +; insert the diskette to be formatted. +; +;*************************************************************** + +; 5/12/82 ARR Mod to ask for volume ID +; 5/19/82 ARR Fixed rounding bug in CLUSCAL: +; REV 1.5 +; Added rev number message +; Added dir attribute to DELALL FCB +; REV 2.00 +; Redone for 2.0 +; REV 2.10 +; 5/1/83 ARR Re-do to transfer system on small memory systems +; REV 2.20 +; 6/17/83 system size re-initialization bug -- mjb001 +; Rev 2.25 +; 8/31/83 16-bit fat insertion +; Rev 2.26 +; 11/2/83 MZ fix signed compare problems for bad sectors +; Rev 2.27 +; 11/8/83 EE current directories are always saved and restored +; Rev 2.28 +; 11/9/83 NP Printf and changed to an .EXE file +; Rev 2.29 +; 11/11/83 ARR Fixed ASSIGN detection to use NameTrans call to see +; if drive letter remapped. No longer IBM only +; Rev 2.30 +; 11/13/83 ARR SS does NOT = CS, so all use of BP needs CS override +; Rev 2.31 +; 12/27/83 ARR REP STOSB instruction at Clean: changed to be +; sure ES = CS. + + + + +code segment public para 'CODE' +code ends + + + +data segment public para 'DATA' +data ends + +End_Of_Memory segment public para 'BUFFERS' +End_Of_Memory ends + + +code segment public para 'CODE' + + assume cs:code,ds:nothing,es:nothing + +;------------------------------------------------------------------------------- +; Define as public for debugging + +; procedures + public GetSize + public AddToSystemSize + public Phase1Initialisation + public SetStartSector + public SetfBigFat + public Phase2Initialisation + public DiskFormat + public BadSector + public DisplayCurrentTrack + public WriteFileSystem + public Done + public CurrentLogicalSector + public PrintErrorAbort + public GetDeviceParameters + public SetDeviceParameters + public Multiply_32_Bits + + public START + public FatAllocated + public MEMERRJ + public MEM_OK + public RDFRST + public NEEDSYS + public INITCALL + public SWITCHCHK + public SYSLOOP + public FRMTPROB + public GETTRK + public TRKFND + public CLRTEST + public CMPTRKS + public BadClus +; public DoBig +; public DoSet + public DRTFAT + public CLEARED + public LOUSE + public LOUSEP + public FATWRT + public SYSOK + public STATUS + public REPORTC + public ONCLUS + public MORE + public FEXIT + public SYSPRM + public fexitJ + public DoPrompt + public TARGPRM + public IsRemovable + public CheckRemove + public IsRemove + public NotRemove + public DSKPRM + public GOPRNIT + public crlf + public PrintString + public std_printf + public READDOS + public RDFILS + public FILESDONE + public CLSALL + public GOTBIOS + public GOTDOS + public CLSALLJ + public GOTCOM + public WRITEDOS + public GOTALLBIO + public BIOSDONE + public GOTNDOS + public PARTDOS + public GOTALLDOS + public DOSDONE + public PARTCOM + public GOTALLCOM + public COMDONE + public MAKEFIL + public CheckMany + public CLOSETARG + public IOLOOP + public GOTTARG + public GSYS + public TESTSYS + public GETOFFS +; public TESTSYSDISK ; dcl 8/23/86 + public SETBIOS + public BIOSCLS + public SETBIOSSIZ + public DOSOPNOK + public DOSCLS + public SETDOSSIZ + public GotComHand + public COMCLS + public SETCOMSIZ + public GETFSIZ + public READFILE + public WRITEFILE + public FILIO + public NORMIO + public IORETP + public IORET + public NORMALIZE + public GotDeviceParameters + public LoadSectorTable + public NotBigTotalSectors + public NotBig + public FormatLoop + public FormatDone + public ContinueFormat + public ReportBadTrack + public NoMoreTracks + public WriteDIRloop + public Main_Routine + public ControlC_Handler + +; bytes + public fBigFat + public formatError + public ROOTSTR + public DBLFLG + public DRIVE + public FILSTAT + public USERDIRS + public VOLFCB + public VOLNAM + public TRANSRC + public TRANDST + public INBUFF + public driveLetter + public systemDriveLetter + public CommandFile + public ExitStatus + public VolDrive + public DelFCB + public DelDrive + +; words + public startSector + public fatSpace + public firstHead + public firstCylinder + public tracksLeft + public tracksPerDisk + public sectorsInRootDirectory + public directorySector + public printStringPointer + public MSTART + public MSIZE + public TempHandle + public BEGSEG + public SWITCHMAP + public SWITCHCOPY + public FAT + public CLUSSIZ + public SECSIZ + public SYSTRKS + public SECTORS + public currentHead + public currentCylinder + public PercentComplete + public Formatted_Tracks_High + public Formatted_Tracks_Low + +; other + public deviceParameters + public Disk_Access + public formatPacket +;------------------------------------------------------------------------------- + +data segment public para 'DATA' + extrn msgAssignedDrive:byte + extrn msgBadDosVersion:byte + extrn msgDirectoryWriteError:byte + extrn msgFormatComplete:byte + extrn msgFormatNotSupported:byte + extrn msgFATwriteError:byte + extrn msgInvalidDeviceParameters:byte + extrn msgLabelPrompt:byte + extrn msgNeedDrive:byte + extrn msgNoSystemFiles:byte + extrn msgNetDrive:byte + extrn msgInsertDisk:byte + extrn msgHardDiskWarning:byte + extrn msgSystemTransfered:byte + extrn msgFormatAnother?:byte + extrn msgBadCharacters:byte + extrn msgBadDrive:byte + extrn msgInvalidParameter:byte + extrn msgParametersNotSupported:byte + extrn msgReInsertDisk:byte + extrn msgInsertDosDisk:byte + extrn msgFormatFailure:byte + extrn ContinueMsg:Byte + extrn msgNotSystemDisk:byte + extrn msgDiskUnusable:byte + extrn msgOutOfMemory:byte + extrn msgCurrentTrack:byte + extrn msgWriteProtected:byte + extrn msgInterrupt:byte + extrn msgCRLF:byte + extrn Fatal_Error:Byte + extrn Read_Write_Relative:Byte + extrn PSP_Segment:Word + extrn Parse_Error_Msg:Byte + extrn Extended_Error_Msg:Byte + extrn MsgVerify:Byte + +data ends + + +debug equ 0 + .xlist + INCLUDE VERSIONA.INC + INCLUDE DOSMAC.INC + INCLUDE SYSCALL.INC + INCLUDE ERROR.INC + INCLUDE DPB.INC + INCLUDE CPMFCB.INC + INCLUDE DIRENT.INC + INCLUDE CURDIR.INC + INCLUDE PDB.INC + INCLUDE BPB.INC + INCLUDE FOREQU.INC + INCLUDE FORMACRO.INC + INCLUDE IOCTL.INC + INCLUDE FORSWTCH.INC + INCLUDE SYSVAR.INC + .list + + +;------------------------------------------------------------------------------- +; And this is the actual data + +data segment public para 'DATA' + public deviceParameters + public bios + public dos + public command + public FAT_Flag + +validSavedDeviceParameters db 0 +savedDeviceParameters a_DeviceParameters <> +deviceParameters a_DeviceParameters <> + +Disk_Access A_DiskAccess_Control <> ;an000; dms; + +formatPacket a_FormatPacket <> +RWPacket a_TrackReadWritePacket <> +RW_TRF_Area db 512 dup(0) + +startSector dw ? +fatSpace dd ? +fBigFat db FALSE + +firstHead dw ? +firstCylinder dw ? +tracksLeft dw ? +tracksPerDisk dw ? + +Formatted_Tracks_Low dw 0 +Formatted_Tracks_High dw 0 + + +public NumSectors ,TrackCnt +NumSectors dw 0FFFFh +TrackCnt dw 0FFFFh +PercentComplete dw 0FFFFh ;Init non-zero so msg will display first time + +public Old_Dir +Old_Dir db FALSE + +public fLastChance +fLastChance db FALSE ; Flags reinvocation from + ; LastChanceToSaveIt. Used by DSKPRM + +sectorsInRootDirectory dw ? + +directorySector dd 0 + +formatError db 0 + +printStringPointer dw 0 + +; Exit status defines +ExitStatus db 0 +ExitOK equ 0 +ExitCtrlC equ 3 +ExitFatal equ 4 +ExitNo equ 5 +ExitDriveNotReady equ 6 ;an017; dms;drive not ready error +ExitWriteProtect equ 7 ;an017; dms;write protect error + +ROOTSTR DB ? + DB ":\",0 +DBLFLG DB 0 ;Initialize flags to zero +IOCNT DD ? +MSTART DW ? ; Start of sys file buffer (para#) +MSIZE DW ? ; Size of above in paragraphs +TempHandle DW ? +FILSTAT DB ? ; In memory status of files + ; XXXXXX00B BIOS not in + ; XXXXXX01B BIOS partly in + ; XXXXXX10B BIOS all in + ; XXXX00XXB DOS not in + ; XXXX01XXB DOS partly in + ; XXXX10XXB DOS all in + ; XX00XXXXB COMMAND not in + ; XX01XXXXB COMMAND partly in + ; XX10XXXXB COMMAND all in + +USERDIRS DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory + +Paras_Per_Fat dw 0000h ;an000;holds fat para count +Fat_Init_Value dw 0000h ;an000;initializes the FAT + +bios a_FileStructure <> +BiosAttributes EQU attr_hidden + attr_system + attr_read_only + +dos a_FileStructure <> +DosAttributes EQU attr_hidden + attr_system + attr_read_only + +command a_FileStructure <> +CommandAttributes EQU 0 +CommandFile DB "X:\COMMAND.COM",0 +CommandFile_Buffer DB 127 dup(0) ;an000;allow room for copy + +Command_Com DB "COMMAND.COM",0 + +VOLFCB DB -1,0,0,0,0,0,8 +VOLDRIVE DB 0 +VOLNAM DB " " + DB 8 + DB 26 DUP(?) + +DelFCB DB -1,0,0,0,0,0,8 +DelDRIVE DB 0 +DelNAM DB "???????????" + DB 8 + DB 26 DUP(?) + +TRANSRC DB "A:CON",0,0 ; Device so we don't hit the drive +TRANDST DB "A:\",0,0,0,0,0,0,0,0,0,0 + +BEGSEG DW ? +SWITCHMAP DW ? +SWITCHCOPY DW ? +FAT DW ? + DW ? +CLUSSIZ DW ? +SECSIZ DW ? +SYSTRKS DW ? +SECTORS DW ? +INBUFF DB 80,0 + DB 80 DUP(?) + + +drive db 0 +driveLetter db "x" +systemDriveLetter db "x" + +CTRL_BREAK_VECTOR dd ? ;ac010; dms;Holds CTRL-Break + ; vector + +Command_Path dd ? ;an011; dms;hold pointer to + ; COMMAND's path + +Comspec_ID db "COMSPEC=",00 ;an011; dms;Comspec target + + +Environ_Segment dw ? ;an011; dms;hold segment of + ; environ. vector +;======== Disk Table ========== ;an012; dms; +;Used if NumberOfFATs in BPB +;is 0. + +DiskTable dw 0, 32680, 0803h, 512, 0 + dw 4h, 0000h, 0402h, 512, Fbig + dw 8h, 0000h, 0803h, 512, Fbig + dw 10h, 0000h, 1004h, 512, Fbig + dw 20h, 0000h, 2005h, 512, Fbig + +public Org_AX ;an000; dms;make it known +Org_AX dw ? ;an000; dms;AX on entry + +Cluster_Boundary_Adj_Factor dw ? ;an000; dms; +Cluster_Boundary_SPT_Count dw ? ;an000; dms; +Cluster_Boundary_Flag db False ;an000; dms; +Cluster_Boundary_Buffer_Seg dw ? ;an000; dms; + +Relative_Sector_Low dw ? ;an000; dms; +Relative_Sector_High dw ? ;an000; dms; + +FAT_Flag db ? ;an000; dms; +Tracks_To_Format dw ? ;an015; dms; +Track_Count dw ? ;an015; dms; +Format_End db FALSE ;an015; dms; + +public Msg_Allocation_Unit_Val + +Msg_Allocation_Unit_Val dd ? ;an019; dms; + + +data ends + +;For FORPROC and FORMES modules + + public secsiz,clussiz,inbuff + + PUBLIC crlf,std_printf + + public switchmap,drive,driveLetter,fatSpace + public fBigFat, PrintString,currentHead,currentCylinder + extrn CheckSwitches:near,LastChanceToSaveIt:near + extrn Volid:near + extrn WriteBootSector:near,OemDone:near + extrn AccessDisk:near + extrn Main_Init:near + extrn Read_Disk:near + extrn Write_Disk:near + +data segment public para 'DATA' + extrn BiosFile:byte,DosFile:byte +data ends + +;For FORPROC module + + EXTRN FormatAnother?:near,Yes?:near,REPORT:NEAR,USER_STRING:NEAR +data segment public para 'DATA' + extrn syssiz:dword,biosiz:dword +data ends + +DOSVER_LOW EQU 0300H+20 +DOSVER_HIGH EQU 0300H+20 + +RECLEN EQU fcb_RECSIZ+7 +RR EQU fcb_RR+7 + +PSP_Environ equ 2ch ;an011; dms;location of + ; environ. segment + ; in PSP + +Fbig equ 0ffh ;an000; dms;flag for big FAT + +START: + xor bx,bx ; ;AN000; + push bx ; ;AN000; + Set_Data_Segment ; ;AC000; + mov Org_AX,ax ;an000; dms;save ax on entry + jmp Main_Init ; ;AC000; + + +Main_Routine: ; ;AN000; +; Set memory requirements + mov bx,PSP_Segment ;Shrink to free space for FAT ;AC000; + mov es,bx ; ;AC000; + mov bx,End_Of_Memory ; ;AC000; + sub bx,PSP_Segment ; ;AC000; + DOS_Call Setblock ; ;AC000; + + call Get_Disk_Access ;an014; dms; + cmp Disk_Access.DAC_Access_Flag,0ffh ;an014; dms;is access already allowed? +; $if ne ;an014; dms;no, don't change status + JE $$IF1 + lea dx,Disk_Access ;an014; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,01h ;an014; dms;signal disk access + call Set_Disk_Access_On_Off ;an014;dms;allow disk access +; $endif ;an014; dms; +$$IF1: + + CALL Phase1Initialisation + jnc FatAllocated + + Message msgFormatFailure ; ;AC000; + jmp Fexit + +MEMERR: + mov ax, seg data + mov ds, ax + Message msgOutOfMemory ; ;AC000; + ;call PrintString + JMP FEXIT + +FatAllocated: + + TEST SWITCHMAP,SWITCH_S + JZ INITCALL + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H + OR BX,BX + JZ MEMERRJ ;No memory + MOV [MSIZE],BX + MOV AH,ALLOC + INT 21H + JNC MEM_OK +MEMERRJ: + JMP MEMERR ;No memory + +MEM_OK: + MOV [MSTART],AX + +RDFRST: + mov bios.fileSizeInParagraphs,0 ;mjb001 initialize file size + mov dos.fileSizeInParagraphs,0 ;mjb001 ... + mov command.fileSizeInParagraphs,0 ;mjb001 ... + CALL READDOS ;Read BIOS and DOS + JNC INITCALL ;OK -- read next file +NEEDSYS: + CALL SYSPRM ;Prompt for system disk + JMP RDFRST ;Try again + +INITCALL: + CALL Phase2Initialisation + +SWITCHCHK: + MOV DX,SWITCHMAP + MOV SWITCHCOPY,DX + +SYSLOOP: + ;Must intialize for each iteration + + MOV WORD PTR SYSSIZ,0 + MOV WORD PTR SYSSIZ+2,0 + MOV BYTE PTR DBLFLG,0 + mov ExitStatus, ExitOK + MOV DX,SWITCHCOPY + MOV SWITCHMAP,DX ;Restore original Switches +; DiskFormat will handle call for new disk + CALL DISKFORMAT ;Format the disk + JNC GETTRK +FRMTPROB: + + test SwitchMap,Switch_Select ;an017; dms;SELECT option? +; $if z ;an017; dms;no - display message + JNZ $$IF3 + Message msgFormatFailure ; ;AC000; + mov ExitStatus, ExitFatal ;an017; dms; +; $endif ;an017; dms; +$$IF3: + CALL MORE ;See if more disks to format + JMP SHORT SYSLOOP + +;Mark any bad sectors in the FATs +;And keep track of how many bytes there are in bad sectors + +GETTRK: + CALL BADSECTOR ;Do bad track fix-up + JC FRMTPROB ;Had an error in Formatting - can't recover + CMP AX,0 ;Are we finished? + JNZ TRKFND ;No - check error conditions + JMP DRTFAT ;Yes +TRKFND: + mov bx,word ptr Relative_Sector_Low ;get the low word of the sector ;an000; dms; + CMP BX,STARTSECTOR ;Are any sectors in the system area bad? + JAE CLRTEST ; MZ 2.26 unsigned compare + Message msgDiskUnusable ; ;AC000; + JMP FRMTPROB ;Bad disk -- try again +CLRTEST: + MOV SECTORS,AX ;Save the number of sectors on the track + TEST SWITCHMAP,SWITCH_S ;If system requested calculate size + JZ BAD100 + CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? + JNZ CMPTRKS ;Yes -- all ready for the compare + INC BYTE PTR DBLFLG ;No -- set the flag + CALL GETBIOSIZE ; Get the size of the BIOS + MOV DX,WORD PTR SYSSIZ+2 + MOV AX,WORD PTR SYSSIZ + MOV WORD PTR BIOSIZ+2,DX + MOV WORD PTR BIOSIZ,AX + CALL GETDOSSIZE + CALL GETCMDSIZE + MOV DX,WORD PTR BIOSIZ+2 + MOV AX,WORD PTR BIOSIZ + DIV deviceParameters.DP_BPB.BPB_BytesPerSector + ADD AX,STARTSECTOR + MOV SYSTRKS,AX ;Space FAT,Dir,and system files require +CMPTRKS: + mov bx,word ptr Relative_Sector_Low ;get the low word of the sector ;an000; dms; + CMP BX,SYSTRKS + JA BAD100 ; MZ 2.26 unsigned compare + mov ExitStatus, ExitFatal + Message msgNotSystemDisk ; ;AC000; + AND SWITCHMAP,NOT SWITCH_S ;Turn off system transfer switch + MOV WORD PTR SYSSIZ+2,0 ;No system to transfer + MOV WORD PTR SYSSIZ,0 ;No system to transfer +BAD100: + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK ;an000; dms;hard disk? +; $if e ;an000; dms; yes + JNE $$IF5 + call Get_Bad_Sector_Hard ;an000; dms;see if a sector is bad +; $else ;an000; dms;floppy disk + JMP SHORT $$EN5 +$$IF5: + call Get_Bad_Sector_Floppy ;an000; dms;mark entire track bad +; $endif ;an000; dms; +$$EN5: + + JMP GETTRK + +; Inputs: BX = Cluster number +; Outputs: The given cluster is marked as invalid +; Zero flag is set if the cluster was already marked bad +; Registers modified: DX,SI +; No other registers affected + +;========================================================================= +; BADCLUS : Marks off a bad cluster in the FAT +; If a cluster has already been marked bad it +; will return with ZR. +; +; Inputs : DX:AX - Cluster Number +; +; Outputs : Cluster is marked invalid +; ZR set if cluster already marked bad +;========================================================================= + +BadClus proc near ;an000; mark bad clusters + + push di ;an000; save affected regs + push ax + push bx + push cx + push dx + push es + + mov es, word ptr fatSpace + 2 ;an005; obtain seg of FAT + CMP fBigFat,TRUE ;an005; 16 bit fat? +; $if ne ;an005; no - 12-bit fat + JE $$IF8 + push ax ;an000; save ax - contains low cluster number + mov si,dx ;an000; pick up high word of cluster + mov di,ax ;an000; pick up low word of cluster + mov cx,2 ;an000; divide by 2 + call Divide_32_Bits ;an000; 32 bit divide + + add ax,di ;an000; add in low word of result + adc dx,si ;an000; pick up low word carry + ;cluster = cluster * 1.5 + add ax,word ptr fatspace ;an005; add 0 + adc dx,0 ;an000; pick up carry + + mov bx,dx ;an000; get high word for adjust + mov cx,es ;an005; place seg in ax + call BadClus_Address_Adjust ;an000; adjust segment offset + mov es,cx ;an000; new segment + mov si,ax ;an000; new offset + + MOV DX,0FF7h ;an005; bad cluster flag + MOV AX,0FFFh ;an005; mask value + + pop cx ;an000; restore ax in cx - low cluster number + test cx,1 ;an000; is old clus num odd? +; $if nz ;an005; yes + JZ $$IF9 + mov cl,4 ;an005; set shift count + SHL AX,cl ;an005; get only 12 bits - fff0 + mov cl,4 ;an005; set shift count + SHL DX,cl ;an005; get 12 bits - ff70 +; $endif ;an005; +$$IF9: +; $else ;an005; 16-bit fats here + JMP SHORT $$EN8 +$$IF8: + xor si,si ;an005; clear si + mov bx,dx ;an000; get high word for multiply + mov cx,2 ;an000; multiply by 2 + call Multiply_32_Bits ;an000; 32 bit multiply + ; due to 2 bytes per + ; FAT cell. This gives + ; us an offset into the + ; FAT. + + mov cx,es ;an005; place seg in cx + call BadClus_Address_Adjust ;an000; adjust segment:offset + mov es,cx ;an000; new segment + mov si,ax ;an000; new offset + + MOV DX,0FFF7h ;an005; bad cluster value + MOV AX,0FFFFh ;an005; mask value +; $endif +$$EN8: + + MOV CX,es:[SI] ;an005; get contents of fat cell + AND CX,AX ;an005; make it 12 or 16 bit + ; depending on value in AX + NOT AX ;an005; set AX to 0 + AND es:[SI],AX ;an005; clear FAT entry + OR es:[SI],DX ;an005; flag it a bad cluster + CMP DX,CX ; return op == badval; + + pop es + pop dx + pop cx + pop bx + pop ax + pop di + return + +badclus endp + +DRTFAT: + TEST SWITCHMAP,SWITCH_S ;If system requested, calculate size + JZ CLEARED + CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? + JNZ CLEARED ;Yes + INC BYTE PTR DBLFLG ;No -- set the flag + CALL GETSIZE ;Calculate the system size +CLEARED: + call Ctrl_Break_Save ;ac010; dms;save CTRL-Break + call Set_Ctrl_Break + CALL WriteFileSystem + + JNC FATWRT + + +LOUSE: + + call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break + Message msgDiskUnusable ; ;AC000; + JMP FRMTPROB + +LOUSEP: + POP DS + JMP LOUSE + +FATWRT: + + PUSH DS + MOV DL,DRIVE + INC DL + MOV AH,GET_DPB + INT 21H + CMP AL,-1 + JZ LOUSEP ;Something BAD has happened + MOV [BX.dpb_next_free],0 ; Reset allocation to start of disk + MOV [BX.dpb_free_cnt],-1 ; Force free space to be computed + POP DS + TEST SWITCHMAP,SWITCH_S ;System desired + JZ STATUS + mov al, drive + call AccessDisk ; note what is current logical drive + CALL WRITEDOS ;Write the BIOS & DOS + JNC SYSOK + Message msgNotSystemDisk ; ;AC000; + MOV WORD PTR SYSSIZ+2,0 ;No system transfered + MOV WORD PTR SYSSIZ,0 ;No system transfered + JMP SHORT STATUS + +SYSOK: + + + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display if EXEC'd by ;AN000; +; $IF Z ; Select ;AN000; + JNZ $$IF13 + Message msgSystemTransfered ; ;AC000; +; $ENDIF ;AN000; +$$IF13: +STATUS: + + call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break + + CALL CRLF + + + + + MOV AH,DISK_RESET + INT 21H + CALL DONE ;Final call to OEM module + JNC REPORTC + JMP FRMTPROB ;Report an error + +REPORTC: + +; +;TEMP FIX for /AUTOTEST +; + test SwitchMap,(Switch_Autotest or Switch_8) ;TEMP +; $IF Z + JNZ $$IF15 + CALL VOLID +; $ENDIF +$$IF15: + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Need to shut down the report? ;AN000; +; $IF Z ;If exec'd by Select, we do ;AN000; + JNZ $$IF17 + CALL REPORT ;Print report +; $ENDIF ; ;AN000; +$$IF17: + CALL MORE ;See if more disks to format + JMP SYSLOOP ;If we returned from MORE then continue + +;****************************************** +; Calculate the size in bytes of the system rounded up to sector and +; cluster boundries, Answer in SYSSIZ + +GetSize proc near + call GetBioSize + call GetDosSize + call GetCmdSize + return +GetSize endp + +GetBioSize proc near + MOV AX,WORD PTR bios.fileSizeInBytes + MOV DX,WORD PTR bios.fileSizeInBytes+2 + CALL AddToSystemSize + return +GetBioSize endp + +GetDosSize proc near + MOV AX,WORD PTR dos.fileSizeInBytes + MOV DX,WORD PTR dos.fileSizeInBytes+2 + CALL AddToSystemSize + return +GetDosSize endp + +GetCmdSize proc near + MOV AX,WORD PTR command.fileSizeInBytes + MOV DX,WORD PTR command.fileSizeInBytes+2 + call AddToSystemSize + return +GetCmdSize endp + +;Calculate the number of sectors used for the system +PUBLIC AddToSystemSize +AddToSystemSize proc near + push bx + DIV deviceParameters.DP_BPB.BPB_BytesPerSector + OR DX,DX + JZ FNDSIZ0 + INC AX ; Round up to next sector +FNDSIZ0: + PUSH AX + XOR DX,DX + xor bx,bx + mov bl, deviceParameters.DP_BPB.BPB_SectorsPerCluster + div bx + POP AX + OR DX,DX + JZ ONCLUS + SUB DX, bx + NEG DX + ADD AX,DX ; Round up sector count to cluster + ; boundry +ONCLUS: + MUL deviceParameters.DP_BPB.BPB_BytesPerSector + ADD WORD PTR SYSSIZ,AX + ADC WORD PTR SYSSIZ+2,DX + pop bx + return +AddToSystemSize endp + +MORE: + + mov Formatted_Tracks_Low,0 ;Reinit the track counter ;AN000; + mov Formatted_Tracks_High,0 ; in case of another format ;AN000; + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display if EXEC'd by ;AN000; + jnz ExitProgram ; Select ;AN000; + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK + je ExitProgram + test SwitchMap,(SWITCH_Select or SWITCH_AUTOTEST) ;If exec'd from select, then;AN000; + jnz ExitProgram ; don't give user choice ;AN000; + CALL FormatAnother? ;Get yes or no response + JC ExitProgram + CALL CRLF + JMP CRLF + + +FEXIT: + Set_Data_Segment ;Make sure have addressability ;AN000; + mov ExitStatus,ExitFatal + +ExitProgram: + test validSavedDeviceParameters, 0ffH + jz DoNotRestoreDeviceParameters + mov savedDeviceParameters.DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD + lea dx, savedDeviceParameters + call SetDeviceParameters +DoNotRestoreDeviceParameters: + + call Format_Access_Wrap_Up ;determine access status ;an000; dms;determine access status + mov al,ExitStatus ;Get Errorlevel ;AN000; + DOS_Call Exit ;Exit program ;AN000; + int 20h ;If other exit fails ;AN000; + +; Prompt the user for a system diskette in the default drive +SYSPRM: + MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive + INT 21H ;Default now in AL + MOV BL,AL + INC BL ; A = 1 + ADD AL,41H ;Now in Ascii + MOV systemDriveLetter,AL ;Text now ok + CALL IsRemovable + JNC DoPrompt +; +; Media is non-removable. Switch sys disk to drive A. Check, though, to see +; if drive A is removable too. +; + MOV AL,"A" + MOV BYTE PTR [systemDriveLetter],AL + MOV [BiosFile],AL + MOV [DosFile],AL + MOV [CommandFile],AL + MOV BX,1 + CALL IsRemovable + JNC DoPrompt + Message msgNoSystemFiles ; ;AC000; +fexitJ: + JMP FEXIT + +DoPrompt: + mov al, systemDriveLetter + sub al, 'A' + call AccessDisk + Message msgInsertDOSDisk ; ;AC000; + Message ContinueMsg + ;lea dx, ptr_msgInsertDosDisk + ;CALL std_printf ;Print first line + CALL USER_STRING ;Wait for a key + CALL CRLF + call crlf + return + +TARGPRM: + mov al, drive + call AccessDisk + Message MsgInsertDisk ; ;AC000; + Message ContinueMsg ; + ;lea DX, ptr_msgInsertDisk + ;CALL std_printf ;Print first line + CALL USER_STRING ;Wait for a key + CALL CRLF + return + +; +; Determine if the drive indicated in BX is removable or not. +; +; Inputs: BX has drive (0=def, 1=A) +; Outputs: Carry clear +; Removable +; Carry set +; not removable +; Registers modified: none + +IsRemovable: + SaveReg + MOV AX,(IOCTL SHL 8) OR 8 ; Rem media check + INT 21H + JNC CheckRemove + MOV AX,(IOCTL SHL 8) + 9 ; Is it a NET drive? + INT 21h + JC NotRemove ; Yipe, say non-removable + TEST DX,1000h + JNZ NotRemove ; Is NET drive, say non-removeable + JMP IsRemove ; Is local, say removable +CheckRemove: + TEST AX,1 + JNZ NotRemove +IsRemove: + CLC + RestoreReg + return +NotRemove: + STC + RestoreReg + return + + +; DiSKPRoMpt: +; +; This routine prompts for the insertion of the correct diskette +; into the Target drive, UNLESS we are being re-entrantly invoked +; from LastChanceToSaveIt. If the target is a Hardisk we issue a +; warning message. +; +; INPUTS: +; deviceParameters.DP_DeviceType +; fLastChance +; +; OUTPUTS: +; Prompt string +; fLastChance := FALSE +; +; Registers affected: +; Flags +; +DSKPRM: + CMP fLastChance,TRUE + JE PrmptRet + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK + jne goprnit + Message msgHardDiskWarning ; ;AC000; + ;lea dx, ptr_msgHardDiskWarning + ;call std_printf + CALL Yes? + jnc OkToFormatHardDisk + mov ExitStatus, ExitNo + jmp ExitProgram + +OkToFormatHardDisk: + CALL CRLF + CALL CRLF + return + +GOPRNIT: + mov al, drive + call AccessDisk + Message msgInsertDisk ; ;AC000; + Message ContinueMsg ; + ;lea dx,ptr_msgInsertDisk + ;CALL std_printf + CALL USER_STRING ;Wait for any key + CALL CRLF + CALL CRLF + +PrmptRet: + mov fLastChance, FALSE + return + + +;------------------------------------------------------------------------------- + +ControlC_Handler: + mov ax, seg data + mov ds, ax + Message msgInterrupt ; ;AC000; + mov ExitStatus, ExitCtrlC + jmp ExitProgram + + +crlf: + ;lea dx, msgCRLF + mov dx,offset msgCRLF ;CR,LF added to message ;AC000; +PrintString: + ;mov printStringPointer, dx + ;lea dx, PrintStringPointer + +std_printf: + ;push dx + ;call printf + call Display_Interface ; ;AC000; + return + +;------------------------------------------------------------------------------- + + +;**************************************** +;Copy IO.SYS, MSDOS.SYS and COMMAND.COM into data area. +; Carry set if problems + +READDOS: + push ax ;save regs ;an025; dms; + push bx ; ;an025; dms; + push es ; ;an025; dms; + + mov ah,Get_In_Vars ;Find out boot drive ;an025; dms; + int 21h ; ;an025; dms; + mov al,byte ptr es:[bx].SysI_Boot_Drive ;get 1 based drive ID ;an025; dms; + add al,40h ;Make it ASCII ;an025; dms; + mov [BiosFile],al ;Stuff it in file specs. ;an025; dms; + mov [DosFile],al ; ;an025; dms; + mov [CommandFile],al ; ;an025; dms; + + pop es ;restore regs ;an025; dms; + pop bx ; ;an025; dms; + pop ax ; ;an025; dms; + + call Get_BIOS ; dcl 8/23/86 + JNC RDFILS + return + +RDFILS: + MOV BYTE PTR [FILSTAT],0 + MOV BX,[bios.fileHandle] + MOV AX,[MSTART] + MOV DX,AX + ADD DX,[MSIZE] ; CX first bad para + MOV [bios.fileStartSegment],AX + MOV CX,[bios.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTBIOS + MOV BYTE PTR [FILSTAT],00000001B ; Got part of BIOS + MOV SI,[MSIZE] + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [bios.fileOffset],AX + MOV WORD PTR [bios.fileOffset+2],DX +FILESDONE: + CLC +CLSALL: + PUSHF +; CALL COMCLS ; dcl 8/23/86 + call FILE_CLS ; dcl 8/23/86 + POPF + return + +GOTBIOS: + MOV BYTE PTR [FILSTAT],00000010B ; Got all of BIOS + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + + push ax ; dcl 8/23/86 + push dx ; dcl 8/23/86 + call File_Cls ; dcl 8/23/86 + call Get_DOS ; dcl 8/23/86 + pop dx ; dcl 8/23/86 + pop ax ; dcl 8/23/86 + + JNC Found_IBMDOS ;mt 12/8/86 P894 + return ;mt 12/8/86 + +Found_IBMDOS: ;mt 12/8/86 + + MOV BX,[dos.fileHandle] + MOV [dos.fileStartSegment],AX + CMP AX,DX ; No room left? + JZ CLSALL ; Yes + MOV CX,[dos.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTDOS + OR BYTE PTR [FILSTAT],00000100B ; Got part of DOS + SUB DX,[dos.fileStartSegment] + MOV SI,DX + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [dos.fileOffset],AX + MOV WORD PTR [dos.fileOffset+2],DX + JMP FILESDONE + +GOTDOS: + OR BYTE PTR [FILSTAT],00001000B ; Got all of DOS + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + +CLSALLJ: JNC NOTCLSALL ;PTM P894 mt 12/8/86 + jmp clsall ; + +NotCLSALL: + push ax ; dcl 8/23/86 + + push dx ; dcl 8/23/86 + call File_cls ; dcl 8/23/86 + call Get_Command_Path ;ac011; dms; get path of + ; COMMAND.COM + call Get_COMMAND ;ac011; dms; Point to COMMAND + ; and read it + pop dx ; dcl 8/23/86 + pop ax ; dcl 8/23/86 + + JNC Found_COMMAND ;mt 12/8/86 P894 + return ;mt 12/8/86 + +Found_COMMAND: ;mt 12/8/86 + MOV BX,[command.fileHandle] + MOV [command.fileStartSegment],AX + CMP AX,DX ; No room left? + JZ CLSALLJ ; Yes + MOV CX,[command.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTCOM + OR BYTE PTR [FILSTAT],00010000B ; Got part of COMMAND + SUB DX,[command.fileStartSegment] + MOV SI,DX + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALLJ + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [command.fileOffset],AX + MOV WORD PTR [command.fileOffset+2],DX + JMP FILESDONE + +GOTCOM: + OR BYTE PTR [FILSTAT],00100000B ; Got all of COMMAND + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JMP CLSALL + +;************************************************** +;Write BIOS DOS COMMAND to the newly formatted disk. + +ASSUME DS:DATA +WRITEDOS: + MOV CX,BiosAttributes + MOV DX,OFFSET BiosFile + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00000010B + JNZ GOTALLBIO + call Get_BIOS ; dcl 8/23/86 + jnc Got_WBIOS ;mt 12/8/86 P894 + ret + +Got_WBIOS: + + push es + LES SI,[bios.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + MOV BP,OFFSET bios + CALL GOTTARG + retc + JMP SHORT BIOSDONE + +GOTALLBIO: + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +BIOSDONE: + MOV BX,[TempHandle] + MOV CX,bios.fileTime + MOV DX,bios.fileDate + CALL CLOSETARG + MOV CX,DosAttributes + MOV DX,OFFSET DosFile + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + +GOTNDOS: + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00001000B + JNZ GOTALLDOS + call Get_DOS ; dcl 8/23/86 + jnc Got_WDOS ;mt 12/8/86 P894 + ret + +Got_WDOS: + MOV BP,OFFSET dos + TEST BYTE PTR FILSTAT,00000100B + JNZ PARTDOS + MOV WORD PTR [dos.fileOffset],0 + MOV WORD PTR [dos.fileOffset+2],0 + CALL GETSYS3 + retc + JMP SHORT DOSDONE + +PARTDOS: + push es + LES SI,[dos.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + CALL GOTTARG + retc + JMP SHORT DOSDONE + +GOTALLDOS: + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +DOSDONE: + MOV BX,[TempHandle] + MOV CX,dos.fileTime + MOV DX,dos.fileDate + CALL CLOSETARG + MOV CX,CommandAttributes + call Command_Root ;an011; dms;adjust path for + ;COMMAND.COM creation + MOV DX,OFFSET CommandFile + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00100000B + JNZ GOTALLCOM + call Get_COMMAND ; dcl 8/23/86 + jnc Got_WCOM ;mt 12/8/86 P894 + ret + +Got_WCOM: + MOV BP,OFFSET command + TEST BYTE PTR FILSTAT,00010000B + JNZ PARTCOM + MOV WORD PTR [command.fileOffset],0 + MOV WORD PTR [command.fileOffset+2],0 + CALL GETSYS3 + retc + JMP SHORT COMDONE + +PARTCOM: + push es + LES SI,[command.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + CALL GOTTARG + retc + JMP SHORT COMDONE + +GOTALLCOM: + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +COMDONE: + MOV BX,[TempHandle] + MOV CX,command.fileTime + MOV DX,command.fileDate + CALL CLOSETARG +;**************************************************************** +; I don't see the need for the following code!! - RS 3.20 +; CMP BYTE PTR [FILSTAT],00101010B +; JZ NOREDOS +;RDFRST2: +; CALL READDOS ; Start back with BIOS +; JNC NOREDOS +; CALL SYSPRM ;Prompt for system disk +; JMP RDFRST2 ;Try again +;NOREDOS: +;**************************************************************** + CLC + return + +;********************************************* +; Create a file on target disk +; CX = attributes, DX points to name +; DI:SI is size file is to have +; +; There is a bug in DOS 2.00 and 2.01 having to do with writes +; from the end of memory. In order to circumvent it this routine +; must create files with the length in DI:SI +; +; On return BX is handle, carry set if problem + +MAKEFIL: + MOV BX,DX + PUSH WORD PTR [BX] + MOV AL,DriveLetter + MOV [BX],AL + MOV AH,CREAT + INT 21H + POP WORD PTR [BX] + MOV BX,AX + JC CheckMany + MOV CX,DI + MOV DX,SI + MOV AX,LSEEK SHL 8 + INT 21H ; Seek to eventual EOF + XOR CX,CX + MOV AH,WRITE + INT 21H ; Set size of file to position + XOR CX,CX + MOV DX,CX + MOV AX,LSEEK SHL 8 + INT 21H ; Seek back to start + return + +; +; Examine error code in AX to see if it is too-many-open-files. +; If it is, we abort right here. Otherwise we return. +; +CheckMany: + CMP AX,error_too_many_open_files + retnz + Extended_Message ; ;AC006; + JMP FEXIT + +;********************************************* +; Close a file on the target disk +; CX/DX is time/date, BX is handle + +CLOSETARG: + MOV AX,(FILE_TIMES SHL 8) OR 1 + INT 21H + MOV AH,CLOSE + INT 21H + return + +;**************************************** +; Transfer system files +; BP points to data structure for file involved +; offset is set to current amount read in +; Start set to start of file in buffer +; TempHandle is handle to write to on target + +IOLOOP: + MOV AL,[systemDriveLetter] + CMP AL,[DriveLetter] + JNZ GOTTARG + MOV AH,DISK_RESET + INT 21H + CALL TARGPRM ;Get target disk + +GOTTARG: +ASSUME DS:DATA +;Enter here if some of file is already in buffer, IOCNT must be set +; to size already in buffer. + MOV BX,[TempHandle] + MOV SI,WORD PTR [IOCNT] + MOV DI,WORD PTR [IOCNT+2] + push ds + MOV DS,ds:[BP.fileStartSegment] + assume ds:nothing + CALL WRITEFILE ; Write next part + pop ds + assume ds:data + retc + + push es + LES AX,ds:[BP.fileOffset] + CMP AX,WORD PTR ds:[BP.fileSizeInBytes] + JNZ GETSYS3 + MOV AX,ES + CMP AX,WORD PTR ds:[BP.fileSizeInBytes+2] + JNZ GETSYS3 + pop es + return ; Carry clear from CMP + +GETSYS3: +;Enter here if none of file is in buffer + pop es + MOV AH,DISK_RESET + INT 21H + MOV AX,[MSTART] ;Furthur IO done starting here + MOV ds:[BP.fileStartSegment],AX ;point to start of buffer + MOV AL,[systemDriveLetter] ;see if we have system disk + CMP AL,[DriveLetter] + JNZ TESTSYS +GSYS: + MOV AH,DISK_RESET + INT 21H + CALL SYSPRM ;Prompt for system disk +TESTSYS: +; CALL TESTSYSDISK ; dcl 8/23/86 + JC GSYS + MOV BX,word ptr DS:[BP.fileHandle] ; CS over ARR 2.30 + push es + LES DX,dword ptr DS:[BP.fileOffset] ; CS over ARR 2.30 + MOV CX,ES + pop es + PUSH DX + MOV AX,LSEEK SHL 8 + INT 21H + POP DX + push es + LES SI,dword ptr DS:[BP.fileSizeInBytes] ; CS over ARR 2.30 + MOV DI,ES ;put high word in di + pop es + SUB SI,DX ;get low word value + SBB DI,CX ; DI:SI is #bytes to go + PUSH DI + PUSH SI + ADD SI,15 ;round up 1 para + ADC DI,0 ;pick up carry + CALL DISID4 ;div 16 to get para count + MOV AX,SI ;put para count in ax + POP SI ;restore bytes remaining + POP DI ;restore bytes remaining + CMP AX,[MSIZE] ;enough memory to read remainder? + JBE GOTSIZ2 ;yes + MOV SI,[MSIZE] + XOR DI,DI + CALL DISIX4 +GOTSIZ2: + MOV WORD PTR [IOCNT],SI ;save byte count for read + MOV WORD PTR [IOCNT+2],DI + push ds + MOV DS,[MSTART] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JNC GETOFFS + CALL CLSALL + JMP GSYS +GETOFFS: + XOR DX,DX ;clear dx + MOV CX,DX ;clear cx + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR DS:[BP.fileOffset],AX ; CS over ARR 2.30 + MOV WORD PTR DS:[BP.fileOffset+2],DX ; CS over ARR 2.30 +;;;;;; CALL CLSALL + JMP IOLOOP + +;************************************************* +; Test to see if correct system disk. Open handles + +CRET12: + STC + return + +;TESTSYSDISK: ; dcl 8/23/86 +Get_BIOS: ; dcl 8/23/86 + MOV AX,OPEN SHL 8 + MOV DX,OFFSET BiosFile + INT 21H + JNC SETBIOS +; call CheckMany ; dcl 8/23/86 + jmp CheckMany ; dcl 8/23/86 + +SETBIOS: + MOV [Bios.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [bios.fileSizeInParagraphs],0 + JZ SETBIOSSIZ + CMP [bios.fileSizeInParagraphs],AX + JZ SETBIOSSIZ +BIOSCLS: + MOV AH,CLOSE + MOV BX,[Bios.fileHandle] + INT 21H +; JMP CRET12 ; dcl 8/23/86 + ret + +SETBIOSSIZ: + MOV [bios.fileSizeInParagraphs],AX + MOV WORD PTR [bios.fileSizeInBytes],SI + MOV WORD PTR [bios.fileSizeInBytes+2],DI + MOV [bios.fileDate],DX + MOV [bios.fileTime],CX + clc + ret ; dcl 8/23/86 + +Get_DOS: ; dcl 8/23/86 + MOV AX,OPEN SHL 8 + MOV DX,OFFSET DosFile + INT 21H + JNC DOSOPNOK +; call CheckMany ; dcl 8/23/86 +; JMP BIOSCLS ; dcl 8/23/86 Checkmany no ret. + jmp CheckMany ; dcl 8/23/86 + +DOSOPNOK: + MOV [dos.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [dos.fileSizeInParagraphs],0 + JZ SETDOSSIZ + CMP [dos.fileSizeInParagraphs],AX + JZ SETDOSSIZ + +DOSCLS: + MOV AH,CLOSE + MOV BX,[dos.fileHandle] + INT 21H +; JMP BIOSCLS ; dcl 8/23/86 + ret ; dcl 8/23/86 + +SETDOSSIZ: + MOV [dos.fileSizeInParagraphs],AX + MOV WORD PTR [dos.fileSizeInBytes],SI + MOV WORD PTR [dos.fileSizeInBytes+2],DI + MOV [dos.fileDate],DX + MOV [dos.fileTime],CX + clc + ret ; dcl 8/23/86 + + + +Get_COMMAND: + MOV AX,OPEN SHL 8 + MOV DX,OFFSET CommandFile + INT 21H + JNC GotComHand +; call CheckMany ; dcl 8/23/86 +; JMP DosCls ; dcl 8/23/86 + jmp Checkmany ; dcl 8/23/86 + +GotComHand: + MOV [command.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [command.fileSizeInParagraphs],0 + JZ SETCOMSIZ + CMP [command.fileSizeInParagraphs],AX + JZ SETCOMSIZ +COMCLS: + MOV AH,CLOSE + MOV BX,[command.fileHandle] + INT 21H +; JMP DOSCLS ; dcl 8/23/86 + ret ; dcl 8/23/86 + +SETCOMSIZ: + MOV [command.fileSizeInParagraphs],AX + MOV WORD PTR [command.fileSizeInBytes],SI + MOV WORD PTR [command.fileSizeInBytes+2],DI + MOV [command.fileDate],DX + MOV [command.fileTime],CX + CLC + return + +FILE_CLS: ; dcl 8/23/86 + MOV AH,CLOSE ; dcl 8/23/86 + INT 21H ; dcl 8/23/86 + ret ; dcl 8/23/86 + +;******************************************* +; Handle in BX, return file size in para in AX +; File size in bytes DI:SI, file date in DX, file +; time in CX. + +GETFSIZ: + MOV AX,(LSEEK SHL 8) OR 2 + XOR CX,CX + MOV DX,CX + INT 21H + MOV SI,AX + MOV DI,DX + ADD AX,15 ; Para round up + ADC DX,0 + AND DX,0FH ; If the file is larger than this it + ; is bigger than the 8086 address + ; space! + MOV CL,12 + SHL DX,CL + MOV CL,4 + SHR AX,CL + OR AX,DX + PUSH AX + MOV AX,LSEEK SHL 8 + XOR CX,CX + MOV DX,CX + INT 21H + MOV AX,FILE_TIMES SHL 8 + INT 21H + POP AX + return + +;******************************************** +; Read/Write file +; DS:0 is Xaddr +; DI:SI is byte count to I/O +; BX is handle +; Carry set if screw up +; +; I/O SI bytes +; I/O 64K - 1 bytes DI times +; I/O DI bytes + + +READFILE: +; Must preserve AX,DX + PUSH AX + PUSH DX + PUSH BP + MOV BP,READ SHL 8 + CALL FILIO + POP BP + POP DX + POP AX + return + +WRITEFILE: + PUSH BP + MOV BP,WRITE SHL 8 + CALL FILIO + POP BP + return + +FILIO: + XOR DX,DX + MOV CX,SI + JCXZ K64IO + MOV AX,BP + INT 21H + retc + ADD DX,AX + CMP AX,CX ; If not =, AX= 4086) +; +Phase1Initialisation proc near + +; Get device parameters + lea dx, deviceParameters + mov deviceParameters.DP_SpecialFunctions, 0 + call GetDeviceParameters + jnc GotDeviceParameters + Message msgFormatNotSupported ; ;AC000; + ;lea dx, ptr_msgFormatNotSupported + ;call std_printf + jmp fexit +GotDeviceParameters: + +; Save the device parameters for when we exit + lea si, deviceParameters + lea di, savedDeviceParameters + mov cx, size a_DeviceParameters + push ds + pop es + rep movsb + +; Ensure that there is a valid number of sectors in the track table + mov savedDeviceParameters.DP_TrackTableEntries, 0 + mov validSavedDeviceParameters, 1 + +; Initialise this to zero to know if CheckSwitches defined the track layout + mov deviceParameters.DP_TrackTableEntries, 0 + + call Set_BPB_Info ;an000; dms; Check to see if we are on + ; FAT system. If not set BPB to proper + ; values for format. +SetMTsupp: + +; Check switches against parameters and use switches to modify device parameters + call CheckSwitches + retc + +IF ShipDisk + + test SwitchMap,Switch_Z ;an000; dms;1 sector/cluster disk? +; $if nz ;an000; dms;yes + JZ $$IF19 + mov DeviceParameters.DP_BPB.BPB_SectorsPerCluster,01h ;an000; dms;set BPB accordingly + call Calc_Small_Fat ;an000; dms;calc FAT size +; $endif ;an000; dms; +$$IF19: + +ENDIF + + + cmp deviceParameters.DP_TrackTableEntries, 0 + jne TrackLayoutSet ; There is a good track layout + +; Store sector table info + mov cx, deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov deviceParameters.DP_TrackTableEntries, cx + mov ax, 1 + mov bx, deviceParameters.DP_BPB.BPB_bytesPerSector + lea di, deviceParameters.DP_SectorTable +LoadSectorTable: + stosw + xchg ax, bx + stosw + xchg ax, bx + inc ax + loop LoadSectorTable +TrackLayoutSet: + +; +; directorySector = malloc( Bytes Per Sector ) +; + mov bx, deviceParameters.DP_BPB.BPB_BytesPerSector + add bx, 0fH + shr bx, 1 + shr bx, 1 + shr bx, 1 + shr bx, 1 + mov ah, Alloc + int 21H + retc + mov word ptr directorySector+2, ax + xor ax,ax + mov word ptr directorySector, ax + +; +; fatSpace = malloc( Bytes Per Sector * Sectors Per FAT ) +; + mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector + add ax, 0fH + shr ax, 1 + shr ax, 1 + shr ax, 1 + shr ax, 1 + mul deviceParameters.DP_BPB.BPB_SectorsPerFAT + mov Paras_Per_Fat,ax ;AN005;128k FAT + mov bx,ax + mov ah,Alloc + int 21H + retc + mov word ptr fatSpace+2,ax + xor ax,ax + mov word ptr fatSpace,ax + + call SetStartSector + call SetfBigFat + + clc + return + +Phase1Initialisation endp + +;------------------------------------------------------------------------------- + +SetStartSector proc near + +; startSector = number of reserved sectors +; + number of FAT Sectors ( Number of FATS * Sectors Per FAT ) +; + number of directory sectors ( 32* Root Entries / bytes Per Sector ) +; ( above is rounded up ) + +; Calculate the number of directory sectors + mov ax, deviceParameters.DP_BPB.BPB_RootEntries + mov bx, size dir_entry + mul bx + add ax, deviceParameters.DP_BPB.BPB_bytesPerSector + dec ax + xor dx,dx + div deviceParameters.DP_BPB.BPB_bytesPerSector + mov sectorsInRootDirectory,ax + mov startSector, ax + +; Calculate the number of FAT sectors + mov ax, deviceParameters.DP_BPB.BPB_SectorsPerFAT + mul deviceParameters.DP_BPB.BPB_numberOfFATs +; Add in the number of boot sectors + add ax, deviceParameters.DP_BPB.BPB_ReservedSectors + add startSector, ax + + return + +SetStartSector endp + +;------------------------------------------------------------------------------- + +SetfBigFat proc near +; +; fBigFat = ( ( (Total Sectors - Start Sector) / Sectors Per Cluster) >= 4086 ) +; + cmp deviceParameters.DP_BPB.BPB_BigTotalSectors+2,0 ; > 32mb part? ;AN000; +; $IF NE ;Yes, big FAT ;AC000; + JE $$IF21 + mov fBigFat, TRUE ;Set flag ;AN000; +; $ELSE ;Nope, < 32,b ;AC000; + JMP SHORT $$EN21 +$$IF21: + mov ax,deviceParameters.DP_BPB.BPB_BigTotalSectors ;Assume this used ;AN000; + cmp ax,0 ;Was this field used? ;AN000; +; $IF E ;Nope, use the other sector field;AN000; + JNE $$IF23 + mov ax, deviceParameters.DP_BPB.BPB_TotalSectors ; ;AC000; + ;** Fix for PTM PCDOS P51 +; $ENDIF ; ;AN000; +$$IF23: + sub ax,startSector ;Get sectors in data area + xor dx,dx + xor bx,bx + mov bl,deviceParameters.DP_BPB.BPB_sectorsPerCluster + div bx ;Get total clusters + cmp ax,BIG_FAT_THRESHOLD ;Is clusters >= 4086? +; $IF AE + JNAE $$IF25 + mov fBigFAT,TRUE ;16 bit FAT if >=4096 + ;** END fix for PTM PCDOS P51 +; $ENDIF +$$IF25: +; $ENDIF +$$EN21: + return + +SetfBigFat endp + +;------------------------------------------------------------------------------- +; +; Phase2Initialisation: +; Use device parameters to build information that will be +; required for each format +; +; Algorithm: +; Calculate first head/cylinder to format +; Calculate number of tracks to format +; Calculate the total bytes on the disk and save for later printout +; First initialise the directory buffer +; +Phase2Initialisation proc near + +; Calculate first track/head to format (round up - kludge) + mov ax, deviceParameters.DP_BPB.BPB_HiddenSectors + mov dx, deviceParameters.DP_BPB.BPB_HiddenSectors + 2 + add ax, deviceParameters.DP_BPB.BPB_SectorsPerTrack + adc dx, 0 + dec ax + sbb dx, 0 + div deviceParameters.DP_BPB.BPB_SectorsPerTrack + xor dx,dx + div deviceParameters.DP_BPB.BPB_Heads + mov firstCylinder, ax + mov firstHead, dx + +; Calculate the total number of tracks to be formatted (round down - kludge) + mov ax, deviceParameters.DP_BPB.BPB_TotalSectors + xor dx,dx +; if (TotalSectors == 0) then use BigTotalSectors + or ax,ax + jnz NotBigTotalSectors + mov ax, deviceParameters.DP_BPB.BPB_BigTotalSectors + mov dx, deviceParameters.DP_BPB.BPB_BigTotalSectors + 2 + +NotBigTotalSectors: + div deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov tracksPerDisk, ax + +; Initialise the directory buffer +; Clear out the Directory Sector before any information is inserted. + mov cx, deviceParameters.DP_BPB.BPB_BytesPerSector + les di, directorySector + xor ax,ax + rep stosb + + mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector + xor dx, dx + mov bx, size dir_entry + div bx + mov cx, ax + + les bx, directorySector +; If Old_Dir = TRUE then put the first letter of each directory entry must be 0E5H + xor al, al + cmp old_Dir, TRUE + jne StickE5 + mov al, 0e5H +StickE5: + mov es:[bx], al + add bx, size dir_entry + loop stickE5 + + ret + +Phase2Initialisation endp + +;------------------------------------------------------------------------------- +; +; SetDeviceParameters: +; Set the device parameters +; +; Input: +; drive +; dx - pointer to device parameters +; +SetDeviceParameters proc near + + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or SET_DEVICE_PARAMETERS + int 21H + return + +SetDeviceParameters endp + +;------------------------------------------------------------------------------- +; +; GetDeviceParameters: +; Get the device parameters +; +; Input: +; drive +; dx - pointer to device parameters +; +GetDeviceParameters proc near + + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or GET_DEVICE_PARAMETERS + int 21H + return + +GetDeviceParameters endp + +;------------------------------------------------------------------------------- +; +; DiskFormat: +; Format the tracks on the disk +; Since we do our SetDeviceParameters here, we also need to +; detect the legality of /N /T if present and abort with errors +; if not. +; This routine stops as soon as it encounters a bad track +; Then BadSector is called to report the bad track, and it continues +; the format +; +; Algorithm: +; Initialise in memory FAT +; current track = first +; while not done +; if format track fails +; DiskFormatErrors = true +; return +; next track + +DiskFormat proc near + + +; +; Initialise fatSpace +; + + + push es + + call Fat_Init ;an000; initialize the FAT + + mov di, word ptr fatspace+2 ;an000; get segment of FAT + mov es, di ;an000; place it in es + mov di, word ptr fatSpace ;Should be 0 + mov al, deviceParameters.DP_BPB.BPB_MediaDescriptor + mov ah, 0ffH + stosw + mov ax, 00ffH + test fBigFat, TRUE + jz NotBig + mov ax, 0ffffH +NotBig: stosw + pop es + +; don't bother to do the formatting if /c was given + test switchmap, SWITCH_C + jz Keep_Going + jmp FormatDone ;FormatDone is to far away + +Keep_Going: +foofoo = INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD + mov deviceParameters.DP_SpecialFunctions, foofoo + lea dx, deviceParameters + + call SetDeviceParameters + + call Cluster_Buffer_Allocate ;an000; dms;get room for retry buffer + + call Prompt_User_For_Disk ;an016; dms; + + test switchmap,switch_8 ; DCL 5/12/86 avoid Naples AH=18h + jnz stdBpB ; lackof support for 8 sectors/track + + ; DCL 5/12/86 + ; Always do the STATUS_FOR_FORMAT test, as we don't know if the machine + ; has this support. For 3.2 /N: & /T: were not documented & therefore + ; not fully supported thru the ROM of Aquarius & Naples & Royal Palm + + ;test SwitchMap, SWITCH_N or SWITCH_T ; IF ( /N or /T ) ;; DCL 5/12/86 + ;jz StdBPB + ; THEN check if + ; supported + mov formatPacket.FP_SpecialFunctions, STATUS_FOR_FORMAT + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or FORMAT_TRACK + lea dx, formatPacket + int 21H + ; switch ( FormatStatusCall) + + ;cmp FormatPacket.FP_SpecialFunctions, Format_No_ROM_Support + ;jb NTSupported ; 0 returned from IBMBIO + ;ja IllegalComb ; 2 returned - ROM Support + ; Illegal Combination! + cmp FormatPacket.FP_SpecialFunctions,0 + je NTSupported + cmp FormatPacket.FP_SpecialFunctions,2 +; $IF E ; ;AC000; + JNE $$IF28 + Message msgInvalidParameter ; ;AC000; + mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000; +; $ELSE ; ; ; + JMP SHORT $$EN28 +$$IF28: + cmp FormatPacket.FP_SpecialFunctions,3 ; ; ; +; $IF E ; ;AC000; + JNE $$IF30 + mov ax,Error_Not_Ready ;flag not ready ;an000;dms; + call CheckError ; set error level ;an017; dms; + jmp FrmtProb ; exit program ;an017; dms; +; $ELSE ; DCL No ROM support is okay ; ; + JMP SHORT $$EN30 +$$IF30: + ; except for /N: & /T: ; ; + test SwitchMap, SWITCH_N or SWITCH_T ; DCL 5/12/86 ; ; +; $IF NZ ; ;AC000; + JZ $$IF32 + Message msgParametersNotSupported ; ;AC000; + mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000; +; $ENDIF ; ;AN000; +$$IF32: +; $ENDIF ; ;AN000; +$$EN30: +; $ENDIF ; ;AN000; +$$EN28: + cmp Fatal_Error,Yes ; ;AN000; + jne StdBPB ; ;AN000; + jmp Fexit +; +; We have the support to carry out the FORMAT +; +NTSupported: +StdBPB: + ;call DSKPRM ; prompt user for disk ;; DCL 5/12/86 + mov FormatPacket.FP_SpecialFunctions, 0 + mov ax, firstHead + mov formatPacket.FP_Head, ax + mov ax, firstCylinder + mov formatPacket.FP_Cylinder, ax + mov cx, tracksPerDisk + mov tracksLeft, cx + mov Format_End,False ;an015; dms;flag not at end of format + call Calc_Max_Tracks_To_Format ;an015; dms;max track count for FormatTrack call +FormatLoop: + call Format_Loop ;an015; dms;Format until CY occurs + + cmp Format_End,True ;an015; dms;End of Format? +; $if e ;an015; dms;yes + JNE $$IF36 + mov FormatError,0 ;an015; dms;signal good format + clc ;an015; dms;clear CY +; $else ;an015; dms;bad format + JMP SHORT $$EN36 +$$IF36: + call CheckError ;an015; dms;determine type of error +; $if nc ;an015; dms; + JC $$IF38 + call LastChanceToSaveIt ;an015; dms;acceptable error? +; $if c ;an015; dms;yes + JNC $$IF39 + mov FormatError,1 ;an015; dms;signal error type + clc ;an015; dms;clear CY +; $else ;an015; dms;not acceptable error + JMP SHORT $$EN39 +$$IF39: + call SetStartSector ;an015; dms;start from scratch + call SetFBigFat ;an015; dms; + push ax ;an015; dms; + call Phase2Initialisation ;an015; dms; + clc ;an015; dms; + pop ax ;an015; dms; + jmp DiskFormat ;an015; dms;try again +; $endif ;an015; dms; +$$EN39: +; $endif ;an015; dms; +$$IF38: +; $endif ;an015; dms; +$$EN36: + return + +FormatDone: + mov FormatError,0 + clc + return + +DiskFormat endp + + +;------------------------------------------------------------------------------- +; +; BadSector: +; Reports the bad sectors. +; Reports the track where DiskFormat stopped. +; From then on it formats until it reaches a bad track, or end, +; and reports that. +; +; Output: +; Carry: set --> fatal error +; if Carry not set +; ax - The number of consecutive bad sectors encountered +; ax == 0 --> no more bad sectors +; bx - The logical sector number of the first bad sector +; +; Algorithm: +; if DiskFormatErrors +; DiskFormatErrors = false +; return current track +; else +; next track +; while not done +; if format track fails +; return current track +; next track +; return 0 + +BadSector proc near + + +; don't bother to do the formatting if /c was given + test switchmap, SWITCH_C + jnz NoMoreTracks + + test formatError, 0ffH + jz ContinueFormat + mov formatError, 0 + jmp ReportBadTrack + +ContinueFormat: + call Adj_Track_Count ;an015; dms;decrease track counter + call NextTrack ;an015; dms;adjust head and cylinder + cmp Format_End,True ;an015; dms;end of format? +; $if ne ;an015; dms;no + JE $$IF44 + call Format_Loop ;an015; dms;format until CY + cmp Format_End,True ;an015; dms;end of format? +; $if ne ;an015; dms;no + JE $$IF45 + call CheckError ;an015; dms;must be error - which error? +; $if nc ;an015; dms;non-fatal error? + JC $$IF46 + call CurrentLogicalSector ;an015; dms;yes - get position + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an015; dms; set track size + clc ;an015; dms;signal O.K. to continue +; $endif ;an015; dms; +$$IF46: +; $else ;an015; dms; + JMP SHORT $$EN45 +$$IF45: + jmp NoMoreTracks ;an015; dms;end of format +; $endif ;an015; dms; +$$EN45: +; $else ;an015; dms; + JMP SHORT $$EN44 +$$IF44: + jmp NoMoreTracks ;an015; dms;end of format +; $endif ;an015; dms; +$$EN44: + return ;an015; dms; + +ReportBadTrack: + call CurrentLogicalSector + mov ax, deviceParameters.DP_BPB.BPB_SectorsPerTrack + clc + return + +NoMoreTracks: + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display done msg;AN000; +; $IF Z ; if EXEC'd by SELECT ;AN000; + JNZ $$IF52 + Message msgFormatComplete ; ;AC000; +; $ENDIF ; ;AN000; +$$IF52: + mov ax, 0 + clc + return + +BadSector endp + + + +;------------------------------------------------------------------------------- + +data segment public para 'DATA' + +;ptr_msgCurrentTrack dw offset msgCurrentTrack +currentHead dw 0 +currentCylinder dw 0 + +data ends + +;========================================================================= +; Calc_Current_Head_Cyl : Obtain the current head and cylinder of the +; track being formatted. +; +; Inputs: FP_Cylinder - Cylinder of track being formatted +; FP_Head - Head of track being formatted +;========================================================================= + +Procedure Calc_Current_Head_Cyl ;an000; dms; + + push cx ;an000; dms;save cx + mov cx,FormatPacket.FP_Cylinder ;an000; dms;get current cylinder + mov CurrentCylinder,cx ;an000; dms;put into variable + mov cx,FormatPacket.FP_Head ;an000; dms;get current head + mov CurrentHead,cx ;an000; dms;put into variable + pop cx ;an000; dms;restore cx + ret ;an000; dms; + +Calc_Current_Head_Cyl endp ;an000; dms; + + +DisplayCurrentTrack proc near + + push dx ; ;AN000; + push cx ; ;AN000; + push ax ;an015; dms; + + mov ax,Tracks_To_Format ;an015; dms;get track count + + add Formatted_Tracks_Low,ax ;Indicate formatted a track ;AN000; + adc Formatted_Tracks_High,0 ; ;AN000; + mov ax,Formatted_Tracks_Low ; ;AN000; + mov bx,Formatted_Tracks_High ; ;AN000; + mov cx,100 ;Make integer calc for div ;AN000; + call Multiply_32_Bits ; BX:AX = (Cyl * Head *100) ;AN000; + mov dx,bx ;Set up divide ;AN000; + div TracksPerDisk ;% = (Cyl * Head *100)/ # tracks;AN000; + cmp ax,PercentComplete ;Only print message when change ;AN000; +; $IF NE ;To avoid excess cursor splat ;AN000; + JE $$IF54 + mov PercentComplete,ax ;Save it if changed ;AN000; + Message msgCurrentTrack ; ;AC000; +; $ENDIF ; +$$IF54: + pop ax ;an015; dms; + pop cx ;Restore register ;AN000; + pop dx ; ;AN000; + return + +DisplayCurrentTrack endp + + +;------------------------------------------------------------------------------- +; CheckError: +; Input: +; ax - extended error code +; Ouput: +; carry set if error is fatal +; Message printed if Not Ready or Write Protect +; +CheckError proc near + cmp ax, error_write_protect + je WriteProtectError + cmp ax, error_not_ready + je NotReadyError + cmp currentCylinder, 0 + jne CheckRealErrors + cmp currentHead, 0 + je BadTrackZero + +CheckRealErrors: + cmp ax, error_CRC + je JustABadTrack + cmp ax, error_sector_not_found + je JustABadTrack + cmp ax, error_write_fault + je JustABadTrack + cmp ax, error_read_fault + je JustABadTrack + cmp ax, error_gen_failure + je JustABadTrack + + stc + ret + +JustABadTrack: + clc + ret + +WriteProtectError: + + test SwitchMap,Switch_SELECT ;an017; dms;SELECT option? +; $if z ;an017; dms;no - display messages + JNZ $$IF56 + Message msgCRLF ; ;AC006; + Message msgCRLF ; ;AC006; + Extended_Message ; ;AC006; +; $else ;an017; dms;yes - set error level + JMP SHORT $$EN56 +$$IF56: + mov ExitStatus,ExitWriteProtect ;an017; dms;signal write protect error +; $endif ;an017; dms; +$$EN56: + + stc ;an017; dms;signal fatal error + ret ;an017; dms;return to caller + +NotReadyError: + test SwitchMap,Switch_SELECT ;an017; dms; SELECT option? +; $if z ;an017; dms; no - display messages + JNZ $$IF59 + Message msgCRLF ; ;AC006; + Message msgCRLF ; ;AC006; + Extended_Message ; ;AC006; +; $else ;an017; dms;yes - set error level + JMP SHORT $$EN59 +$$IF59: + mov ExitStatus,ExitDriveNotReady ;an017; dms;signal drive not ready +; $endif ;an017; dms; +$$EN59: + stc + ret + + +BadTrackZero: + Message msgDiskUnusable ; ;AC000; + stc + ret + +CheckError endp + +;------------------------------------------------------------------------------- +; WriteFileSystem: +; Write the boot sector and FATs out to disk +; Clear the directory sectors to zero +; + +WriteFileSystem proc near + + + call WriteBootSector + retc + + Set_Data_Segment ;Set DS,ES = DATA ;AN000; +; Write out each of the FATs + push ds ;ac005; dms;save ds + xor cx, cx + mov cl, es:deviceParameters.DP_BPB.BPB_numberOfFATs ; ;AC000; + mov dx, es:deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AC000; + mov al, es:drive ; ;AC000; + mov bx,word ptr es:FatSpace+2 ;Get segment of memory Fat ;AC000; + mov ds,bx ; ;AN000; + mov bx,word ptr es:FatSpace ; ;AN000; + + mov si,bx ;ac005; dms;set up for add. calc + call SEG_ADJ ;ac005; dms;get adjusted seg:off + mov bx,si ;ac005; dms;get new off + assume ds:nothing,es:data ; ;AN000; + +; $do ;ac005; dms;while FATS > 0 +$$DO62: + cmp cx,00 ;ac005; dms;FATS remaining? +; $leave e ;ac005; dms;no + JE $$EN62 + push bx ;ac005; dms;save FAT offset + push ds ;ac005; dms;save FAT segment + push cx ;ac005; dms;save FAT count + push dx ;ac005; dms;reserved FAT sector + call WRITE_FAT ;ac005; dms;write the FAT + pop dx ;ac005; dms;get 1st. FAT sector + pop cx ;ac005; dms;get FAT count + pop ds ;ac005; dms;restore FAT segment + pop bx ;ac005; dms;restore FAT offset +; $if c ;ac005; dms;an error occurred + JNC $$IF64 + Message msgFATwriteError;ac005; dms;say why failed + jmp FEXIT ;ac005; dms;exit format +; $endif ;ac005; dms; +$$IF64: + add dx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + dec cx ;ac005; dms;decrease FAT count +; $enddo ;ac005; dms; + JMP SHORT $$DO62 +$$EN62: + + pop ds ;ac005; dms;restore ds + assume ds:data ;ac005; dms; + + +; Clear the directory + +; Now write the initialised directory sectors out to disk + mov ax, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + xor dx,dx + push bx ;an000; dms;save bx + xor bx,bx ;an000; dms;clear bx + mov bl,es:DeviceParameters.DP_BPB.BPB_NumberOfFATs ;an000; dms;get FAT count + mul bx ;an000; dms;get total FAT sectors + pop bx ;an000; dms;restore bx + + mov dx, es:deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AC000; + add dx, ax + mov cx, es:sectorsInRootDirectory ; ;AC000; +WriteDIRloop: + push cx + push dx + mov al, es:drive ; ;AC000; + mov cx, 1 + lds bx, es:directorySector ; ;AC000; + + assume ds:nothing,es:data ; ;AN000; + +;Assume dir is alway contined in first 32mb of partition + + mov es:Read_Write_Relative.Start_Sector_High,0 ; ;AC000; + Call Write_Disk ; ;AN000; + jnc Dir_OK ; ;AC000; + Message msgDirectoryWriteError ; ;AC000; + jmp FExit ; ;AN000; +Dir_OK: ; ;AN000; + pop dx + add dx, 1 + pop cx + loop WriteDIRLoop + + Set_Data_Segment ;Set DS to DATA segment ;AN000; +; Ok, we can tell the device driver that we are finished formatting + mov savedDeviceParameters.DP_TrackTableEntries, 0 + mov savedDeviceParameters.DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD + lea dx, savedDeviceParameters + call SetDeviceParameters + + MOV AH,DISK_RESET ; Flush any directories in + INT 21H ; buffers + + return + + +WriteFileSystem endp + +;========================================================================= +; WRITE_FAT : This routine writes the logical sector count requested. +; It will write a maximum of 40h sectors. If more +; than 40h exists it will continue looping until +; all sectors have been written. +; +; Inputs : AL - Drive letter +; DS:BX - Segment:offset of transfer address +; CX - Sector count +; DX - 1st. sector +; +; Outputs : Logical sectors written +;========================================================================= + +procedure write_fat + + mov cx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + +; $do ;an000;while sectors left +$$DO67: + cmp cx,00h ;an000;any sectors? +; $leave e ;an000;no + JE $$EN67 + + cmp cx,40h +; $if a ;an000;yes + JNA $$IF69 + push cx ;an000;save cx + mov cx,40h + push ax ;an000;save ax + call write_disk ;an000;write it + pop ax ;an000;restore ax + pop cx ;an000;restore cx + jc Write_Exit ;an000;exit if fail + mov si,8000h + call seg_adj ;an000;adjust segment + mov bx,si ;an000;new offset + add dx,40h + sub cx,40h +; $else ;an000;< 64k + JMP SHORT $$EN69 +$$IF69: + push ax ;an000;save ax + call write_disk ;an000;write it + pop ax ;an000;restore ax + xor cx,cx ;an000;set cx to 0 - last read +; $endif +$$EN69: +; $enddo + JMP SHORT $$DO67 +$$EN67: + + Write_Exit: + + ret + +write_fat endp + +;========================================================================= +; SEG_ADJ : This routine adjusts the segment:offset to prevent +; address wrap. +; +; Inputs : SI - Offset to adjust segment with +; DS - Segment to be adjusted +; +; Outputs : SI - New offset +; DS - Adjusted segment +;========================================================================= + +procedure seg_adj + + push ax + push cx + push dx + mov ax,si ;an000;get offset + mov bx,0010h ;an000;16 + xor dx,dx ;an000;clear dx + div bx ;an000;get para count +; $if c ;an000;overflow? + JNC $$IF73 + adc bx,0 ;an000;pick it up +; $endif ;an000; +$$IF73: + mov bx,ds ;an000;get seg + add bx,ax ;an000;adjust for paras + mov ds,bx ;an000;save new seg + mov si,dx ;an000;new offset + pop dx + pop cx + pop ax + ret + +seg_adj endp + +;------------------------------------------------------------------------------- +; format is done... so clean up the disk! +; +Done proc near + + + call OemDone + return + +Done endp + +;------------------------------------------------------------------------------- +; CurrentLogicalSector: +; Get the current logical sector number +; +; Input: +; current track = tracksPerDisk - tracksLeft +; SectorsPerTrack +; +; Output: +; BX = logical sector number of the first sector in the track we +; just tried to format +; +CurrentLogicalSector proc near + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push dx ;an000; dms; + + mov ax, tracksPerDisk + sub ax, tracksLeft + xor dx,dx ;an000; dms;clear dx + mul deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov word ptr Relative_Sector_High,dx ;an000; dms;save high word of sector # + mov word ptr Relative_Sector_Low,ax ;an000; dms;save low word of sector # + + pop dx ;an000; dms;restore regs + pop bx ;an000; dms; + pop ax ;an000; dms; + + return + +CurrentLogicalSector endp + +;------------------------------------------------------------------------------- +; PrintErrorAbort: +; Print an error message and abort +; +; Input: +; dx - Pointer to error message string +; +PrintErrorAbort proc near + + push dx + call crlf + pop dx + call PrintString + + jmp fexit + +PrintErrorAbort endp + + + + +;***************************************************************************** +;Routine name: Multiply_32_Bits +;***************************************************************************** +; +;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding +; the 32 bit number to itself for each power of 2 contained in the +; 16 bit number. Whenever a bit that is set in the multiplier (CX) +; gets shifted to the bit 0 spot, it means that that amount has +; been multiplied so far, and it should be added into the total +; value. Take the example CX = 12 (1100). Using the associative +; rule, this is the same as CX = 8+4 (1000 + 0100). The +; multiply is done on this principle - whenever a bit that is set +; is shifted down to the bit 0 location, the value in BX:AX is +; added to the running total in DI:SI. The multiply is continued +; until CX = 0. The routine will exit with CY set if overflow +; occurs. +; +; +;Called Procedures: None +; +;Change History: Created 7/23/87 MT +; +;Input: BX:AX = 32 bit number to be multiplied +; CX = 16 bit number to be multiplied. (Must be even number) +; +;Output: BX:AX = output. +; CY set if overflow +; +;Psuedocode +;---------- +; +; Point at ControlC_Handler routine +; Set interrupt handler (INT 21h, AX=2523h) +; ret +;***************************************************************************** + +Public Multiply_32_Bits +Multiply_32_Bits proc ; ;AN000; + + push di ; ;AN000; + push si ; ;AN000; + xor di,di ;Init result to zero + xor si,si ; + cmp cx,0 ;Multiply by 0? ;AN000; +; $IF NE ;Keep going if not ;AN000; + JE $$IF75 +; $DO ;This works by adding the result;AN000; +$$DO76: + test cx,1 ;Need to add in sum of this bit?;AN000; +; $IF NZ ;Yes ;AN000; + JZ $$IF77 + add si,ax ;Add in the total so far for ;AN000; + adc di,bx ; this bit multiplier (CY oflow);AN000; +; $ELSE ;Don't split multiplier ;AN000; + JMP SHORT $$EN77 +$$IF77: + clc ;Force non exit ;AN000; +; $ENDIF ; ;AN000; +$$EN77: +; $LEAVE C ;Leave on overflow ;AN000; + JC $$EN76 + shr cx,1 ;See if need to multiply value ;AN000; + cmp cx,0 ;by 2 ;AN000; +; $LEAVE E ;Done if cx shifted down to zero;AN000; + JE $$EN76 + add ax,ax ;Each time cx is shifted, add ;AN000; + adc bx,bx ;value to itself (Multiply * 2) ;AN000; +; $ENDDO C ;CY set on overflow ;AN000; + JNC $$DO76 +$$EN76: +; $IF NC ;If no overflow, add in DI:SI ;AN000; + JC $$IF83 + mov ax,si ; which contains the original ;AN000; + mov bx,di ; value if odd, 0 if even. This ;AN000; + clc ;Set no overflow flag ;AN000; +; $ENDIF ; ;AN000; +$$IF83: +; $ELSE ; + JMP SHORT $$EN75 +$$IF75: + xor ax,ax ; + xor bx,bx ; +; $ENDIF ;Multiply by 0 ;AN000; +$$EN75: + pop si ; ;AN000; + pop di ; ;AN000; + ret ; ;AN000; + +Multiply_32_Bits endp + + +;========================================================================= +; Divide_32_Bits - This routine will perform 32bit division +; +; Inputs : SI:DI - value to be divided +; CX - divisor +; +; Outputs : SI:DI - result +; CX - remainder +;========================================================================= + +Procedure Divide_32_Bits ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push dx ;an000; dms; + + xor dx,dx ;an000; dms;clear dx + mov ax,si ;an000; dms;get high word + div cx ;an000; dms;get high word result + mov si,ax ;an000; dms;save high word result + + mov ax,di ;an000; dms;get low word + div cx ;an000; dms;get low word result + mov di,ax ;an000; dms;save low word result + mov cx,dx ;an000; dms;pick up remainder + + pop dx ;an000; dms;restore regs + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Divide_32_Bits endp ;an000; dms; + + + + +;========================================================================= +; FAT_INIT: This routine initializes the FAT based on the +; number of paragraphs. +; +; +; input - fatspace +; fatspace+2 +; paras_per_fat +; fat_init_value +; output - fat space is initialized +; +;========================================================================= +Public Fat_Init +Fat_Init proc near + + push es + push di + push ax + push bx + push cx + mov di, word ptr FatSpace+2 ;Get segment of Fat space ;AC000; + mov es,di ; ;AN000; + mov di, word ptr FatSpace ; ;AN000; + mov bx,Paras_Per_Fat ;an000;get number of paras + mov ax,fat_init_value ;an000; + push dx ;an000;save bx + mov dx,es ;an000;grab es into dx +; $do +$$DO87: + cmp bx,0 ;an000;do while bx not = 0 +; $leave e ;an000;exit if 0 + JE $$EN87 + mov cx,10h ;an000;word move of paragraph + rep stosb ;an000;move the data to FAT + xor di,di ;an000;offset always init to 0 + inc dx ;an000;next paragraph + mov es,dx ;an000;put next para in es + dec bx ;an000;loop iteration counter +; $enddo ;an000; + JMP SHORT $$DO87 +$$EN87: + pop dx ;an000; + pop cx ;an000; + pop bx ;an000; + pop ax ;an000; + pop di ;an000; + pop es ;an000; + + ret ;an000; + +Fat_Init endp ;an000; + + +;========================================================================= +; Ctrl_Break_Write : This routine takes the control break request +; an returns. In essence, it disables the CTRL-BREAK. +; This routine is used during the writing of the +; FAT, DIR, and SYSTEM. +;========================================================================= + +Ctrl_Break_Write: ;ac010; dms; + + iret ;ac010; dms;return to caller + + +;========================================================================= +; Ctrl_Break_Save : This routine gets the current vector of +; INT 23h and saves it in CTRL_BREAK_VECTOR. +; +; Inputs : none +; +; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +;========================================================================= + +Ctrl_Break_Save proc near ;ac010; dms; + + push es ;ac010; dms;save es + push bx ;ac010; dms;save bx + push ax ;ac010; dms;save ax + + mov ax,3523h ;ac010; dms;get CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + mov word ptr Ctrl_Break_Vector,bx ;ac010; dms;get vector offset + mov word ptr Ctrl_Break_Vector+2,es ;ac010; dms;get vector segment + + pop ax ;ac010; dms;restore ax + pop bx ;ac010; dms;restore bx + pop es ;ac010; dms;restore es + + ret ;ac010; dms; + + +Ctrl_Break_Save endp ;ac010; dms; + + +;========================================================================= +; Set_Ctrl_Break : This routine sets the CTRL-Break vector to one +; defined by the user. +; +; Inputs : none +; +; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +;========================================================================= + +Set_Ctrl_Break proc near ;ac010; dms; + + push ds ;ac010; dms;save ds + push ax ;ac010; dms;save ax + push bx ;ac010; dms;save bx + push dx ;ac010; dms;save dx + + push cs ;ac010; dms;swap cs with ds + pop ds ;an000; dms;point to code seg + + mov dx,offset Ctrl_Break_Write ;ac010; dms;get interrupt vec. + mov ax,2523h ;ac010; dms;set CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + pop dx ;ac010; dms;restore dx + pop bx ;ac010; dms;restore bx + pop ax ;ac010; dms;restore ax + pop ds ;ac010; dms;restore ds + + ret ;ac010; dms; + + +Set_Ctrl_Break endp ;ac010; dms; + + +;========================================================================= +; Reset_Ctrl_Break : This routine resets the CTRL-Break vector to that +; originally defined. +; +; Inputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +; +; Outputs : none +;========================================================================= + +Reset_Ctrl_Break proc near ;ac010; dms; + + push ds ;ac010; dms;save ds + push ax ;ac010; dms;save ax + push bx ;ac010; dms;save bx + push dx ;ac010; dms;save ds + + mov ax,word ptr Ctrl_Break_Vector+2 ;ac010; dms;get seg. of vector + mov bx,word ptr Ctrl_Break_Vector ;ac010; dms;get off. of vector + mov ds,ax ;ac010; dms;get seg. + mov dx,bx ;ac010; dms;get off. + mov ax,2523h ;ac010; dms;set CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + pop dx ;ac010; dms;restore dx + pop bx ;ac010; dms;restore bx + pop ax ;ac010; dms;restore ax + pop ds ;ac010; dms;restore ds + + ret ;ac010; dms; + + +Reset_Ctrl_Break endp ;ac010; dms; + +;========================================================================= +; Get_Command_Path : This routine finds the path where +; COMMAND.COM resides based on the +; environmental vector. Once the +; path is found it is copied to +; CommandFile. +; +; Inputs : Exec_Block.Segment_Env - Segment of environmental vector +; Comspec_ID - "COMSPEC=" +; +; Outputs : CommandFile - Holds path to COMMAND.COM +;========================================================================= + +Procedure Get_Command_Path ;an011; dms; + + push ds ;an011; dms;save ds + push es ;an011; dms;save es + + Set_Data_Segment ;an011; dms; DS,ES = Data + call Get_PSP_Parms ;an011; dms; gets PSP info. + cld ;an011; dms; clear direction + mov ax,es:Environ_Segment ;an011; dms; get seg. of + ; environ. vector + mov ds,ax ;an011; dms; put it in DS + assume ds:nothing ;an011; dms; + xor si,si ;an011; dms; clear si + mov bx,si ;an011; dms; save si + mov di,offset Comspec_ID ;an011; dms; point to target + mov cx,127 ;an011; dms; loop 127 times +; $do ;an011; dms; while cx not 0 +$$DO90: + ; and target not found + cmp cx,00h ;an011; dms; end of env.? +; $leave e ;an011; dms; yes + JE $$EN90 + + push cx ;an011; dms; save cx + mov cx,0008h ;an011; dms; loop 8 times + repe cmpsb ;an011; dms; "COMSPEC=" ? + pop cx ;an011; dms; restore cx +; $if z ;an011; dms; yes + JNZ $$IF92 + push di ;an011; dms; save di + mov di,offset es:CommandFile ;an011; dms + lodsb ;an011; dms; priming read + mov dl,al ;an011; dms; prepare for capitalization + call Cap_Char ;an011; dms; capitalize character in DL + cmp dl,es:CommandFile ;an011; dms;COMSPEC same as default drive? +; $if e ;an000; dms; yes + JNE $$IF93 +; $do ;an011; dms; while AL not = 0 +$$DO94: + cmp al,00h ;an011; dms; at end? +; $leave e ;an011; dms; yes + JE $$EN94 + stosb ;an011; dms; save it + lodsb ;an011; dms; get character +; $enddo + JMP SHORT $$DO94 +$$EN94: +; $endif ;an011; dms; +$$IF93: + pop di ;an011; dms; restore di + mov cx,0ffffh ;an011; dms; flag target found +; $endif ;an011; dms; +$$IF92: + + cmp cx,0ffffh ;an011; dms; target found? +; $leave e ;an011; dms; yes + JE $$EN90 + + mov di,offset Comspec_ID ;an011; dms; point to target + mov si,bx ;an011; dms; restore si + inc si ;an011; dms; point to next byte + mov bx,si ;an011; dms; save si + + dec cx ;an011; dms; decrease counter +; $enddo ;an011; dms; + JMP SHORT $$DO90 +$$EN90: + + pop es ;an011; dms; restore es + pop ds ;an011; dms; restore ds + + ret ;an011; dms; + +Get_Command_Path endp ;an011; dms; + + +; +;**************************************************************************** +; Get_PSP_Parms +;**************************************************************************** +; +; +; +; + +Procedure Get_PSP_Parms ; ;AC000; + + Set_Data_Segment + mov ax,PSP_Segment ;Get segment of PSP ;AN000; + mov ds,ax ; " " " " ;AN000; + ; ; + assume ds:nothing + ;Setup segment of Environment string, get from PSP ; ; + + mov ax,ds:PSP_Environ ; ; ; + mov es:Environ_Segment,ax ; ; ; + Set_Data_Segment + ret ; ; ; + + +Get_PSP_Parms endp ; ;AN000; + + +;========================================================================= +; Command_Root : This routine sets up CommandFile so that the +; COMMAND.COM will be written to the root. +; It does this by copying at offset 3 of CommandFile +; the literal COMMAND.COM. This effectively +; overrides the original path, but maintains the +; drive letter that is to be written to. +; +; Inputs : CommandFile - Holds full path to default COMMAND.COM +; Outputs : CommandFile - Holds modified path to new COMMAND.COM +; on target drive. +;========================================================================= + +Procedure Command_Root ;an011; dms; + + push ds ;an011; dms; save ds + push es ;an011; dms; save es + push di ;an011; dms; save di + push si ;an011; dms; save si + push cx ;an011; dms; save cx + Set_Data_Segment ;an011; + + mov di,offset CommandFile+3 ;an011; dms; point to path + ; past drive spec + mov si,offset Command_Com ;an011; dms; holds the literal + ; COMMAND.COM + mov cx,000ch ;an011; dms; len. of literal + rep movsb ;an011; dms; move it + + pop cx ;an011; dms; restore cx + pop si ;an011; dms; restore si + pop di ;an011; dms; restore di + pop es ;an011; dms; restore es + pop ds ;an011; dms; restore ds + + ret ;an011; dms; + +Command_Root endp ;an011; dms; + + +;========================================================================= +; Set_BPB_Info : When we have a FAT count of 0, we must calculate +; certain parts of the BPB. The following code +; will do just that. +; +; Inputs : DeviceParameters +; +; Outputs : BPB information +;========================================================================= + +Procedure Set_BPB_Info ;an012; dms;calc new BPB + + Set_Data_Segment ;an012; dms;set up addressibility + cmp DeviceParameters.DP_BPB.BPB_NumberOfFats,00h ;an012; dms;see if we have 0 FATS specified +; $if e ;an012; dms;yes, 0 FATS specified + JNE $$IF101 + call Scan_Disk_Table ;an012; dms;access disk table + mov bl,byte ptr ds:[si+8] ;an012; dms;get FAT type + mov cx,word ptr ds:[si+4] ;an012; dms;get sectors/cluster + mov dx,word ptr ds:[si+6] ;an012; dms;number of entries for the root DIR + + mov DeviceParameters.DP_BPB.BPB_RootEntries,dx ;an012; dms;save root entries + mov DeviceParameters.DP_BPB.BPB_SectorsPerCluster,ch ;an012; dms;save sectors/cluster + mov DeviceParameters.DP_BPB.BPB_BytesPerSector,0200h ;an012; dms;save bytes/sector + mov DeviceParameters.DP_BPB.BPB_ReservedSectors,0001h ;an012; dms;save reserved sectors + mov DeviceParameters.DP_BPB.BPB_NumberOfFats,02h ;an012; dms;FAT count + + cmp bl,FBIG ;an012; dms;Big FAT? +; $if e ;an012; dms;yes + JNE $$IF102 + call Calc_Big_FAT ;an012; dms;calc big FAT info +; $else ;an012; dms; + JMP SHORT $$EN102 +$$IF102: + call Calc_Small_FAT ;an012; dms;calc small FAT info +; $endif ;an012; dms; +$$EN102: +; $endif ;an012; dms; +$$IF101: + + ret ;an012; dms; + +Set_BPB_Info endp ;an012; dms; + + + +;========================================================================= +; Scan_Disk_Table : Scans the table containing information on +; the disk's attributes. When it finds the +; applicable data, it returns a pointer in +; DS:SI for reference by the calling proc. +; +; Inputs : DiskTable - Contains data about disk types +; +; Outputs : DS:SI - Points to applicable disk data +;========================================================================= + +Procedure Scan_Disk_Table ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF106 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN106 +$$IF106: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN106: + + mov si,offset DiskTable ;an012; dms;point to disk data +Scan: + + cmp dx,word ptr ds:[si] ;an012; dms;below? + jb Scan_Disk_Table_Exit ;an012; dms;yes, exit + ja Scan_Next ;an012; dms;no, continue + cmp ax,word ptr ds:[si+2] ;an012; dms;below or equal? + jbe Scan_Disk_Table_Exit ;an012; dms;yes, exit + +Scan_Next: + + add si,5*2 ;an012; dms;adjust pointer + jmp Scan ;an012; dms;continue scan + +Scan_Disk_Table_Exit: + + ret ;an012; dms; + +Scan_Disk_Table endp ;an012; dms; + + + +;========================================================================= +; Calc_Big_FAT : Calculates the sectors per FAT for a 16 bit FAT. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or +; DeviceParameters.DP_BPB.BPB_TotalSectors +; +; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat +;========================================================================= + +Procedure Calc_Big_FAT ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF109 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN109 +$$IF109: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN109: + + mov cl,04h ;an012; dms;16 DIR entries per sector + push dx ;an012; dms;save total sectors (high) + mov dx,DeviceParameters.DP_BPB.BPB_RootEntries ;an012; dms;get root entry count + shr dx,cl ;an012; dms;divide by 16 + sub ax,dx ;an012; dms; + pop dx ;an012; dms;restore dx + sbb dx,0 ;an012; dms; + sub ax,1 ;an012; dms;AX = T - R - D + sbb dx,0 ;an012; dms; + mov bl,02h ;an012; dms; + mov bh,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an012; dms;get sectors per cluster + add ax,bx ;an012; dms;AX = T-R-D+256*SPC+2 + adc dx,0 ;an012; dms; + sub ax,1 ;an012; dms;AX = T-R-D+256*SPC+1 + sbb dx,0 ;an012; dms; + div bx ;an012; dms; sec/FAT = CEIL((TOTAL-DIR-RES)/ + ; (256*SECPERCLUS+2) + mov word ptr DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax ;an012; dms;Sectors/cluster + ret ;an012; dms; + +Calc_Big_FAT endp ;an012; dms; + + +;========================================================================= +; Calc_Small_FAT: Calculates the sectors per FAT for a 12 bit FAT. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or +; DeviceParameters.DP_BPB.BPB_TotalSectors +; +; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat +;========================================================================= + +Procedure Calc_Small_FAT ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF112 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN112 +$$IF112: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN112: + + xor bx,bx ;an012; dms;clear bx + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an012; dms;get sectors/cluster + div bx ;an012; dms; +; now multiply by 3/2 + mov bx,3 ;an012; dms; + mul bx ;an012; dms;div by log 2 of sectors/cluster + mov bx,2 ;an012; dms; + div bx ;an012; dms; + xor dx,dx ;an012; dms; +; now divide by 512 + mov bx,512 ;an012; dms; + div bx ;an012; dms; + inc ax ;an012; dms; +; dx:ax contains number of FAT sectors necessary + mov DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax ;an012; dms;save sectors/FAT + ret ;an012; dms; + +Calc_Small_FAT endp ;an012; dms; + +;========================================================================= +; Get_Bad_Sector_Hard : Determine the bad sector. +; +; Inputs : Head of failing track +; Cylinder of failing track +; Relative_Sector_Low - 1st. sector in track +; Relative_Sector_High +; +; Cluster_Boundary_Adj_Factor - The number of sectors +; that are to be read +; at one time. +; Cluster_Boundary_SPT_Count - Used by Calc_Cluster_Boundary +; to track how many sectors +; have been read. +; Cluster_Boundary_Flag - True (Use cluster buffer) +; - False (Use internal buffer) +; Cluster_Boundary_Buffer_Seg - Segment of buffer +; +; Outputs : Marked cluster as bad +;========================================================================= + +Procedure Get_Bad_Sector_Hard ;an000; dms; + + push cx ;an000; dms;save cx + mov cx,0001h ;an000; dms;set counter to start at 1 + mov Cluster_Boundary_SPT_Count,00h ;an000; dms;clear sector counter + mov Cluster_Boundary_Adj_Factor,01h ;an000; dms;default value +; $do ;an000; dms;while sectors left +$$DO115: + cmp cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;at end? +; $leave a ;an000; dms;yes,exit + JA $$EN115 + push cx ;an000; dms;save cx + + cmp Cluster_Boundary_Flag,True ;an000; dms;full buffer there? +; $if e ;an000; dms;yes + JNE $$IF117 + call Calc_Cluster_Boundary ;an000; dms;see if on boundary + mov ax,Cluster_Boundary_Buffer_Seg + mov word ptr RWPacket.TRWP_TransferAddress[0],0 ;an000; dms;point to transfer area + mov word ptr RWPacket.TRWP_TransferAddress[2],ax ;an000; dms; +; $else ;an000; dms;default to internal buffer + JMP SHORT $$EN117 +$$IF117: + mov word ptr RWPacket.TRWP_TransferAddress[0],offset RW_TRF_Area ;an000; dms;point to transfer area + mov word ptr RWPacket.TRWP_TransferAddress[2],DS ;an000; dms; +; $endif ;an000; dms; +$$EN117: + + call Verify_Structure_Set_Up ;an019; dms; set up verify vars + + mov ax,(IOCTL shl 8) or GENERIC_IOCTL ;an000; dms; + xor bx,bx ;an000; dms;clear bx + mov bl,drive ;an000; dms;get drive + inc bl ;an000; dms;adjust it + mov cx,(IOC_DC shl 8) or READ_TRACK ;an000; dms;read track + lea dx,RWPacket ;an000; dms;point to parms + int 21h ;an000; dms; + + pop cx ;an000; dms;restore cx + + push cx ;an000; dms;save cx + +; $if c ;an000; dms;an error occurred + JNC $$IF120 + call Calc_Cluster_Position ;an000; dms;determine which cluster + call BadClus ;an000; dms;mark the cluster as bad +; $endif ;an000; dms; +$$IF120: + + pop cx ;an000; dms;restore cx + + add cx,Cluster_Boundary_Adj_Factor ;an000; dms;adjust loop counter + mov ax,Cluster_Boundary_Adj_Factor ;an000; dms;get adjustment factor + xor dx,dx ;an000; dms;clear dx + add ax,Relative_Sector_Low ;an000; dms;add in low word + adc dx,Relative_Sector_High ;an000; dms;pick up carry in high word + mov Relative_Sector_Low,ax ;an000; dms;save low word + mov Relative_Sector_High,dx ;an000; dms;save high word + + +; $enddo ;an000; dms; + JMP SHORT $$DO115 +$$EN115: + + pop cx ;an000; dms;restore cx + + ret ;an000; dms; + +Get_Bad_Sector_Hard endp ;an000; dms; + + +;========================================================================= +; Verify_Structure_Set_Up : Set up the fields for the Read IOCTL +; to verify the sectors in a failing +; track. Also, it displays the +; message notifying the user of the +; sectors it is verifying. +;========================================================================= + +Procedure Verify_Structure_Set_Up ;an019; dms;set up verify structure + + mov RWPacket.TRWP_SpecialFunctions,00h ;an000; dms;reset special functions + + mov ax,FormatPacket.FP_Head ;an000; dms;get current head + mov RWPacket.TRWP_Head,ax ;an000; dms;get current head + + mov ax,FormatPacket.FP_Cylinder ;an000; dms;get current cylinder + mov RWPacket.TRWP_Cylinder,ax ;an000; dms;get current cylinder + + dec cx ;an000; dms;make sector 0 based + mov RWPacket.TRWP_FirstSector,cx ;an000; dms;get sector to read + + mov ax,Cluster_Boundary_Adj_Factor ;an000; dms;get # of sectors to read + mov RWPacket.TRWP_SectorsToReadWrite,ax ;an000; dms;read only # sector(s) + + call Calc_Cluster_Position ;an019; dms;determine cluster number + mov word ptr Msg_Allocation_Unit_Val[+2],dx ;an019; dms;save high word of cluster + mov word ptr Msg_Allocation_Unit_Val[+0],ax ;an019; dms;save low word of cluster + message MsgVerify + + ret + +Verify_Structure_Set_Up endp ;an019; dms; + + +;========================================================================= +; Get_Bad_Sector_Floppy : This routine marks an entire track as bad +; since it is a floppy disk. +; +; Inputs : Relative_Sector_Low - first sector +; +; Outputs : FAT marked with bad sectors +;========================================================================= + +Procedure Get_Bad_Sector_Floppy ;an000; dms; + + push bx ;an000; dms;save regs + push cx ;an000; dms; + + mov cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;get sectors/track +; $do ;an000; dms;while sectors left +$$DO123: + cmp cx,00 ;an000; dms;at end +; $leave e ;an000; dms;yes + JE $$EN123 + push bx ;an000; dms;save bx we destroy it + push cx ;an000; dms;save cx we destroy it + call Calc_Cluster_Position ;an000; dms;get cluster position + call BadClus ;an000; dms;mark it as bad + pop cx ;an000; dms;restore regs + pop bx ;an000; dms; + dec cx ;an000; dms;decrease loop counter + inc Relative_Sector_Low ;an000; dms;next sector +; $enddo ;an000; dms; + JMP SHORT $$DO123 +$$EN123: + + pop cx ;an000; dms;restore regs + pop bx ;an000; dms; + + ret ;an000; dms; + +Get_Bad_Sector_Floppy endp ;an000; dms; + + +;========================================================================= +; Calc_Cluster_Position : This routine calculates which cluster the +; failing sector falls in. +; +; Inputs : Relative_Sector_High - high word of sector position +; Relative_Sector_Low - low word of sector position +; +; Outputs : DX:AX - Cluster position +;========================================================================= +Procedure Calc_Cluster_Position ;an000; dms; + + push cx ;an000; dms;save regs + push di ;an000; dms; + push si ;an000; dms; + + xor dx,dx ;an000; dms;clear high word + mov dx,word ptr Relative_Sector_High ;an000; dms;get the high sector word + mov ax,word ptr Relative_Sector_Low ;an000; dms;get the low sector word + sub ax,StartSector ;an000; dms;get relative sector # + sbb dx,0 ;an000; dms;pick up borrow + + mov si,dx ;an000; dms;get high word + mov di,ax ;an000; dms;get low word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + call Divide_32_Bits ;an000; dms;32 bit division + + mov dx,si ;an000; dms;get high word of result + mov ax,di ;an000; dms;get low word of result + add ax,2 ;an000; dms;adjust for cluster bias + adc dx,0 ;an000; dms;pick up carry + + pop si ;an000; dms;restore regs + pop di ;an000; dms; + pop cx ;an000; dms; + + ret ;an000 ;dms; + +Calc_Cluster_Position endp ;an000; dms; + + +;========================================================================= +; Cap_Char : This routine will capitalize the character passed in +; DL. +; +; Inputs : DL - Character to be capitalized +; +; Outputs : DL - Capitalized character +;========================================================================= + +Procedure Cap_Char ;an011; dms; + + push ax ;an011; dms;save ax + mov ax,6520h ;an011; dms;capitalize character + int 21h ;an011; dms; + pop ax ;an011; dms;restore ax + ret ;an011; dms; + +Cap_Char endp ;an011; dms; + +;========================================================================= +; Set_Disk_Access_On_Off: This routine will either turn access on or off +; to a disk depending on the contents of the +; buffer passed in DX. +; +; Inputs : DX - pointer to buffer +; +;========================================================================= + +Procedure Set_Disk_Access_On_Off ;an014; dms; + + push ax ;an014; dms;save regs + push bx ;an014; dms; + push cx ;an014; dms; + push dx ;an014; dms; + + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get driver number + inc bl ;an014; dms;make it 1 based + call IsRemovable ;an014; dms;see if removable media +; $if c ;an014; dms;not removable + JNC $$IF126 + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an014; dms;generic ioctl + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get drive letter + inc bl ;an014; dms;make it 1 based + mov cx,(RAWIO shl 8) or Set_Access_Flag ;an014; dms;allow access to disk + int 21h ;an014; dms; +; $endif ;an014; dms; +$$IF126: + + pop dx ;an014; dms;restore regs + pop cx ;an014; dms; + pop bx ;an014; dms; + pop ax ;an014; dms; + + ret ;an014; dms; + +Set_Disk_Access_On_Off endp ;an014; dms; + + +;========================================================================= +; Get_Disk_Access : This routine will determine the access state of +; the disk. +; +; Inputs : DX - pointer to buffer +; Outputs : Disk_Access.DAC_Access_Flag - 0ffh signals access allowed +; to the disk previously. +; +;========================================================================= + +Procedure Get_Disk_Access ;an014; dms; + + push ax ;an014; dms;save regs + push bx ;an014; dms; + push cx ;an014; dms; + push dx ;an014; dms; + + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get driver number + inc bl ;an014; dms;make it 1 based + call IsRemovable ;an014; dms;see if removable media +; $if c ;an014; dms;not removable + JNC $$IF128 + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an014; dms;generic ioctl + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get drive letter + inc bl ;an014; dms;make it 1 based + mov cx,(RAWIO shl 8) or Get_Access_Flag ;an014; dms;determine disk access + lea dx,Disk_Access ;an014; dms;point to parm list + int 21h ;an014; dms; + cmp Disk_Access.DAC_Access_Flag,01h ;an014; dms;access is currently allowed? +; $if e ;an014; dms;yes + JNE $$IF129 + mov Disk_Access.DAC_Access_Flag,0ffh ;an014; dms;signal access is currently allowed +; $endif ;an014; dms; +$$IF129: +; $endif ;an014; dms; +$$IF128: + + pop dx ;an014; dms;restore regs + pop cx ;an014; dms; + pop bx ;an014; dms; + pop ax ;an014; dms; + + ret ;an014; dms; + +Get_Disk_Access endp ;an014; dms; + +;========================================================================= +; Calc_Cluster_Boundary : This routine will determine where, within a +; cluster, a sector resides. +; +; Inputs : Relative_Sector_Low - Sector +; Relative_Sector_High +; +; Outputs : Cluster_Boundary_Adj_Factor - The number of sectors +; remaining in the cluster. +; Cluster_Boundary_SPT_Count - The count of sectors +; having been accessed for +; a track. +;========================================================================= + +Procedure Calc_Cluster_Boundary ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push cx ;an000; dms; + push dx ;an000; dms; + push si ;an000; dms; + push di ;an000; dms; + + xor dx,dx ;an000; dms;clear high word + mov dx,word ptr Relative_Sector_High ;an000; dms;get the high sector word + mov ax,word ptr Relative_Sector_Low ;an000; dms;get the low sector word + sub ax,StartSector ;an000; dms;get relative sector # + sbb dx,0 ;an000; dms;pick up borrow + + mov si,dx ;an000; dms;get high word + mov di,ax ;an000; dms;get low word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + call Divide_32_Bits ;an000; dms;32 bit division + + or cx,cx ;an000; dms;see if remainder exists +; $if nz ;an000; dms;remainder exists + JZ $$IF132 + xor bx,bx ;an021; dms; + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an021; dms;get sectors/cluster + sub bx,cx ;an021; dms;get number of sectors to read + mov Cluster_Boundary_Adj_Factor,bx ;ac021; dms;remainder = sector count +; $else ;an000; dms;no remainder + JMP SHORT $$EN132 +$$IF132: + xor bx,bx ;an000; dms;clear bx + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + mov Cluster_Boundary_Adj_Factor,bx ;an000; dms;get sectors/cluster +; $endif ;an000; dms; +$$EN132: + + mov ax,Cluster_Boundary_SPT_Count ;an000; dms;get current sector count + xor dx,dx ;an000; dms;clear high word + add ax,Cluster_Boundary_Adj_Factor ;an000; dms;get next sector count + cmp ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;exceeded sectors/track? +; $if a ;an000; dms;yes + JNA $$IF135 + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;only use difference + sub ax,Cluster_Boundary_SPT_Count ;an000; dms;get next sector count + mov Cluster_Boundary_Adj_Factor,ax ;an000; dms; +; $endif ;an000; dms; +$$IF135: + + mov ax,Cluster_Boundary_SPT_Count ;an000; dms;get sector count + xor dx,dx ;an000; dms;clear high word + add ax,Cluster_Boundary_Adj_Factor ;an000; dms;get new sector count + mov Cluster_Boundary_SPT_Count,ax ;an000; dms;save it + + pop di ;an000; dms;restore regs + pop si ;an000; dms; + pop dx ;an000; dms;restore regs + pop cx ;an000; dms; + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Calc_Cluster_Boundary endp ;an000; dms; + +;========================================================================= +; Cluster_Buffer_Allocate : This routine will allocate a buffer +; based on a cluster's size. If enough +; space does not exist, a cluster will +; be redefined to a smaller size for +; purposes of sector retries. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BytesPerSector +; DeviceParameters.DP_BPB.BPB_SectorsPerCluster +; +; Outputs : Cluster_Boundary_Flag - True (space available) +; False(not enough space) +; Cluster_Boundary_Buffer_Seg - Pointer to buffer +;========================================================================= + +Procedure Cluster_Buffer_Allocate ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push cx ;an000; dms; + push dx ;an000; dms; + + mov ax,(Alloc shl 8) ;an000; dms;allocate memory + mov bx,0ffffh ;an000; dms;get available memory + int 21h ;an000; dms; + + mov ax,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an000; dms;get bytes/sector + xor dx,dx ;an000; dms;clear high word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sector count + mul cx ;an000; dms;get total byte count + mov cl,4 ;an000; dms;set up shift count + shr ax,cl ;an000; dms;divide by 16 + inc ax ;an000; dms;round up + + cmp bx,ax ;an000; dms;enough room +; $if a ;an000; dms;yes + JNA $$IF137 + mov bx,ax ;an000; dms;allocate needed memory + mov ax,(Alloc shl 8) ;an000; dms; + int 21h ;an000; dms; + mov Cluster_Boundary_Buffer_Seg,ax ;an000; dms;save pointer to buffer + mov Cluster_Boundary_Flag,True ;an000; dms;signal space available +; $else ;an000; dms;not enough room + JMP SHORT $$EN137 +$$IF137: + mov Cluster_Boundary_Flag,False ;an000; dms;signal not enough space +; $endif ;an000; dms; +$$EN137: + + pop dx ;an000; dms;restore regs + pop cx ;an000; dms; + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Cluster_Buffer_Allocate endp ;an000; dms; + + +;========================================================================= +; Set_CDS_Off - This routine disallows access to a +; disk if a format fails on a non-FAT +; formatted disk. +; +;========================================================================= + +Procedure Set_CDS_Off ;an000; dms; + + push ax ;an000; dms;save regs + push dx ;an000; dms; + + mov ax,5f08h ;an000; dms;reset CDS + mov dl,Drive ;an000; dms;drive to reset + int 21h ;an000; dms; + + pop dx ;an000; dms;restore regs + pop ax ;an000; dms; + + ret ;an000; dms; + +Set_CDS_Off endp ;an000; dms; + + +;========================================================================= +; Format_Access_Wrap_Up - This routine determines whether or +; not access should be allowed to the +; disk based on the exit status of +; format. +; +;========================================================================= + +Procedure Format_Access_Wrap_Up ;an000; dms; + + cmp Disk_Access.DAC_Access_Flag,0ffh ;an015; dms;access prev. allowed? +; $if ne ;an015; dms;no + JE $$IF140 + cmp ExitStatus,ExitOK ;an015; dms;good exit? +; $if ne ;an015; dms;no + JE $$IF141 + lea dx,Disk_Access ;an015; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,00h ;an015; dms;signal no disk access + call Set_Disk_Access_On_Off ;an015; dms;don't allow disk access +; $else ;an015; dms;bad exit + JMP SHORT $$EN141 +$$IF141: + lea dx,Disk_Access ;an015; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,01h ;an015; dms;signal disk access + call Set_Disk_Access_On_Off ;an015; dms;allow disk access +; $endif ;an015; dms; +$$EN141: +; $endif ;an015; dms; +$$IF140: + + cmp FAT_Flag,No ;an012; dms;non-FAT format? +; $if e ;an012; dms;yes + JNE $$IF145 + cmp ExitStatus,ExitOK ;an012; dms;good exit? +; $if ne ;an012; dms;no + JE $$IF146 + call Set_CDS_Off ;an012; dms;disallow FAT access +; $endif ;an012; dms; +$$IF146: +; $endif ;an012; dms; +$$IF145: + + ret ;an000; dms; + +Format_Access_Wrap_Up endp ;an000; dms; + +;========================================================================= +; BadClus_Address_Adjust - This routine adjusts the segment and +; offset to provide addressibility into +; the FAT table. +; +; Inputs : bx - high word to adjust segment for +; ax - low word to adjust segment for +; cx - segment to be adjusted +; +; Outputs : cx - new segment value +; ax - new offset value +;========================================================================= + +Procedure BadClus_Address_Adjust ;an000; dms; + + push bx ;an000; save regs + push dx ;an000; + push di ;an000; + push si ;an000; + + mov dx,cx ;an000; save segment value + mov si,bx ;an000; get high word for divide + mov di,ax ;an000; get low word for divide + xor cx,cx ;an000; clear cx + mov cl,Paragraph_Size ;an000; divide by 16 + call Divide_32_Bits ;an000; perform division + + add dx,di ;an000; adjust segment for result + mov ax,cx ;an000; pick up the remainder + mov cx,dx ;an000; pass back new segment + + pop si ;an000; restore regs + pop di ;an000; + pop dx ;an000; + pop bx ;an000; + + ret ;an000; dms; + +BadClus_Address_Adjust endp ;an000; dms; + + + +;========================================================================= +; NextTrack : This routine determines the next track to be +; formatted. +; +; Inputs : TracksLeft - # of tracks remaining +; Tracks_To_Format - # of tracks to format in 1 call +; FP_Head - disk head +; FP_Cylinder - disk cylinder +; +; Outputs : TracksLeft - # of tracks remaining +; FP_Head - disk head +; FP_Cylinder - disk cylinder +; CY - no tracks left to format +; NC - tracks left to format +;========================================================================= + +Procedure NextTrack ;an015; dms; + + + cmp TracksLeft,00 ;an015; dms;end of format? +; $if e ;an015; dms;yes + JNE $$IF149 + stc ;an015; dms;signal end of format + mov Format_End,True +; $else + JMP SHORT $$EN149 +$$IF149: + mov cx,Tracks_To_Format ;an015; dms;get max track count for call +; $do ;an015; dms;while tracks remain +$$DO151: + cmp TracksLeft,00 ;an015; dms;end of format? +; $leave e ;an015; dms;yes + JE $$EN151 + cmp cx,00 ;an015; dms;end of head/cyl. adjustment? +; $leave e ;an015; dms;yes + JE $$EN151 + inc FormatPacket.FP_Head ;an015; dms;next head + mov ax,FormatPacket.FP_Head ;an015; dms;get head for comp + cmp ax,DeviceParameters.DP_BPB.BPB_Heads ;an015; dms;exceeded head count? +; $if e ;an015; dms;yes + JNE $$IF154 + mov FormatPacket.FP_Head,00 ;an015; dms;reinit. head + inc FormatPacket.FP_Cylinder ;an015; dms;next cylinder +; $endif ;an015; dms; +$$IF154: + + dec cx ;an015; dms;decrease counter +; $enddo ;an015; dms; + JMP SHORT $$DO151 +$$EN151: + + clc ;an015; dms;clear CY +; $endif ;an015; dms; +$$EN149: + + ret ;an015; dms; + +NextTrack endp ;an015; dms; + +;========================================================================= +; Determine_Format_Type : This routine determines the type of format +; that is to occur based on the media type. +; +; Inputs : Dev_HardDisk - Media type (harddisk) +; Multi_Track_Format - EQU 02h +; Single_Track_Format - EQU 00h +; +; Outputs : FP_SpecialFunctions - Set appropriately for single +; or multi track format +;========================================================================= + +Procedure Determine_Format_Type ;an015; dms; + + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF158 + mov FormatPacket.FP_SpecialFunctions,Multi_Track_Format ;an015; dms;set for multi track format +; $else ;an015; dms; + JMP SHORT $$EN158 +$$IF158: + mov FormatPacket.FP_SpecialFunctions,Single_Track_Format ;an015; dms;set for single track format +; $endif ;an015; dms; +$$EN158: + ret ;an015; dms; + +Determine_Format_Type endp ;an015; dms; + + +;========================================================================= +; FormatTrack : This routine performs multi track or single +; track formatting based on the state of the +; SpecialFunctions byte. +; +; Inputs : Tracks_To_Format - # of tracks to format in 1 call +; FormatPacket - Parms for IOCTL call +; +; Outputs : NC - formatted track(s) +; CY - error in format +; AX - extended error on CY +;========================================================================= + +Procedure FormatTrack ;an015; dms; + + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an015; dms;Generic IOCTL + mov bl,drive ;an015; dms;get drive number + inc bl ;an015; dms;make it 1 based + mov cx,(RawIO shl 8) or Format_Track ;an015; dms;Format track(s) + mov dx,Tracks_To_Format ;an015; dms;get track count + mov FormatPacket.FP_TrackCount,dx ;an015; dms;put count in parms list + lea dx,FormatPacket ;an015; dms;ptr to parms + int 21h ;an015; dms; + +; $if c ;an015; dms;error? + JNC $$IF161 + mov ah,59h ;an015; dms;get extended error + xor bx,bx ;an015; dms;clear bx + int 21h ;an015; dms; + stc ;an015; dms;flag an error +; $endif ;an015; dms; +$$IF161: + + ret ;an015; dms; + +FormatTrack endp ;an015; dms; + + +;========================================================================= +; Determine_Track_Count : This routine determines the number of +; tracks to be formatted, based on whether +; or not we have a hard disk. If we have +; a hard disk we can use multi-track +; format/verify, otherwise we use the +; single track format/verify. +; +; Inputs : Device_Type - Media type +; +; Outputs : Tracks_To_Format - Max. number of tracks +; to be formatted in one +; call +;========================================================================= + +Procedure Determine_Track_Count ;an015; dms; + + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF163 + call Calc_Track_Count ;an015; dms;calc Tracks_To_Format +; $else ;an015; dms;removable media + JMP SHORT $$EN163 +$$IF163: + mov Tracks_To_Format,0001h ;an015; dms;default to 1 track +; $endif ;an015; dms; +$$EN163: + + ret ;an015; dms; + +Determine_Track_Count endp ;an015;dms; + + +;========================================================================= +; Calc_Track_Count : This routine determines if we have enough tracks +; remaining to use the max. number of tracks +; in the FormatTrack call. If the tracks remaining +; to be formatted is less that the max. number of +; allowable tracks for the call, the max. number +; of allowable tracks is set to the remaining track +; count. +; +; Inputs : Track_Count - Max. number of allowable tracks to be +; formatted in 1 FormatTrack call. +; TracksLeft - Track count of remaining tracks to be +; formatted. +; +; Outputs : Tracks_To_Format - Count of the tracks to be formatted +; in the next FormatTrack call. +; +; +;========================================================================= + +Procedure Calc_Track_Count ;an015; dms; + + push ax ;an015; dms;save regs + mov ax,Track_Count ;an015; dms;max bytes to format + cmp ax,TracksLeft ;an015; dms;too many tracks? +; $if a ;an015; dms;yes + JNA $$IF166 + mov ax,TracksLeft ;an015; dms;format remaining tracks +; $endif ;an015; dms; +$$IF166: + mov Tracks_To_Format,ax ;an015; dms;save track count + + pop ax ;an015; dms; + + ret ;an015; dms; + +Calc_Track_Count endp ;an015; dms; + +;========================================================================= +; Calc_Max_Tracks_To_Format : This routine determines the maximum +; number of tracks to format at 1 time. +; +; Inputs : DeviceParameters - SectorsPerTrack +; BytesPerSector +; +; Outputs : Track_Count - Max. # of tracks to format in 1 call +; to FormatTrack +;========================================================================= + +Procedure Calc_Max_Tracks_To_Format + + push ax ;an015; dms;save regs + push bx ;an015; dms; + push dx ;an015; dms; + + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an015; dms;get sectors per track + mov bx,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an015; dms;get byte count + xor dx,dx ;an015; dms;clear dx + mul bx ;an015; dms;get total byte count + mov bx,ax ;an015; dms;put count in bx + mov ax,Max_Format_Size ;an015; dms;max bytes to format + div bx ;an015; dms;get track count + mov Track_Count,ax + + pop dx ;an015; dms; + pop bx ;an015; dms; + pop ax ;an015; dms; + + ret + +Calc_Max_Tracks_To_Format endp + + + + + +;========================================================================= +; Format_Track_Retry : This routine performs the retry logic for +; the format multi-track. It will retry each track +; until the failing track is encountered through +; a CY condition. +; +; Inputs : none +; +; Outputs : CY - indicates either a failing track or end of format +; +; +;========================================================================= + +Procedure Format_Track_Retry + + clc ;an022; dms; clear existing CY + mov Tracks_To_Format,1 ;an015; dms; only format 1 track +; $do ;an015; dms; while we have good tracks +$$DO168: +; $leave c ;an015; dms; exit on bad track + JC $$EN168 + call FormatTrack ;an015; dms; format the track +; $if nc ;an015; dms;error? + JC $$IF170 + call DisplayCurrentTrack ;an022; dms;adjust percent counter + call Adj_Track_Count + call NextTrack ;an015; dms;calc next track +; $endif ;an015; dms; +$$IF170: +; $enddo ;an015; dms; + JMP SHORT $$DO168 +$$EN168: + + ret ;an015; dms; + +Format_Track_Retry endp ;an015; dms; + +;========================================================================= +; Format_Loop : This routine provides the main template +; for the formatting of a disk. A disk +; will be formatted as long as there are +; tracks remaining to be formatted. +; This routine can be exited on a carry +; condition; i.e., bad track, last track, etc. +; +; Inputs : none +; +; Outputs : CY - Set on exit from this routine +; AX - Possible error condition code +;========================================================================= + +Procedure Format_Loop ;an015; dms; + + clc ;an015; dms;initialize to NC +; $do ;an015; dms;while NC +$$DO173: +; $leave c ;an015; dms;exit on CY + JC $$EN173 + call Calc_Current_Head_Cyl ;an015; dms;head and cylinder calc. + call Determine_Format_Type ;an015; dms;floppy/hard media? + call Determine_Track_Count ;an015; dms;how many tracks? + call FormatTrack ;an015; dms;format track(s) +; $if c ;an015; dms;formattrack failed + JNC $$IF175 + pushf ;an015; dms;save flags + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF176 + popf ;an015; dms;restore flags + call Format_Track_Retry ;an015; dms;find failing track +; $else ;an015; dms; + JMP SHORT $$EN176 +$$IF176: + popf ;an015; dms;restore flags +; $endif ;an015; dms; +$$EN176: +; $endif ;an015; dms; +$$IF175: + +; $if c ;an015; dms;format error? + JNC $$IF180 + pushf ;an015; dms;yes - save flags + push ax ;an015; dms;save return code + call CheckRealErrors ;an015; dms;check error type +; $if nc ;an015; dms;if non-fatal + JC $$IF181 + call DisplayCurrentTrack ;an015; dms;display % formatted +; $endif ;an015; dms; +$$IF181: + pop ax ;an015; dms;restore regs + popf ;an015; dms; +; $endif ;an015; dms; +$$IF180: + +; $leave c ;an015; dms;exit on CY + JC $$EN173 + + call DisplayCurrentTrack ;an015; dms;tell how much formatted + call Adj_Track_Count ;an015; dms;decrease track counter + call NextTrack ;an015; dms;adjust head and cylinder +; $enddo ;an015; dms; + JMP SHORT $$DO173 +$$EN173: + ret ;an015; dms; + +Format_Loop endp ;an015; dms; + +;========================================================================= +; Adj_Track_Count : This routine adjusts the track count by the +; number of tracks that have been formatted +; in one FormatTrack call. +; +; Inputs : TracksLeft - # of tracks remaining to be formatted +; Tracks_To_Format - Tracks formatted in 1 call +; +; Outputs : TracksLeft - # of tracks remaining to be formatted +;========================================================================= + +Procedure Adj_Track_Count ;an015; dms; + + push ax ;an015; dms; save regs + mov ax,TracksLeft ;an015; dms; get tracks remaining + sub ax,Tracks_To_Format ;an015; dms; subtract amount formatted + mov TracksLeft,ax ;an015; dms; save new tracks remaining value + pop ax ;an015; dms; restore regs + ret ;an015; dms; + +Adj_Track_Count endp ;an015; dms; + +;========================================================================= +; Prompt_User_For_Disk : This routine prompts the user for the +; disk to be formatted. An appropriate +; message is chosen based on the type +; of switch entered. If the /SELECT +; switch is entered, the disk prompt is +; issued through the INT 2fh services +; provided by SELECT. +; +; Inputs : Switchmap - Switches chosen for format +; +; Outputs : Message printed as appropriate. +;========================================================================= + +Procedure Prompt_User_For_Disk ;an016;dms; + + push ax ;an016;dms;save ax + test switchmap, (SWITCH_Backup or SWITCH_Select or SWITCH_AUTOTEST) ;Suppress prompt? ;AC000; +; $IF Z ; ;AC000; + JNZ $$IF186 + call DSKPRM ; prompt user for disk +; $ENDIF ; ;AC000; +$$IF186: + + test switchmap, (Switch_Select) ;an016;dms;/SELECT requested? +; $if nz ;an016;dms;yes + JZ $$IF188 + mov al, drive ;an016;dms;get drive to access for format + call AccessDisk ;an016;dms;access the disk + mov ax,Select_Disk_Message ;an016;dms;display disk prompt + int 2fh ;an016;dms; through INT 2fh services +; $endif ;an016;dms; +$$IF188: + pop ax ;an016;dms;restore ax + + ret ;an016;dms; + +Prompt_User_For_Disk endp ;an016;dms; + + +code ends + END START + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORMAT.LNK b/v4.0/src/CMD/FORMAT/FORMAT.LNK new file mode 100644 index 0000000..4798cf9 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORMAT.LNK @@ -0,0 +1,8 @@ +DISPLAY.OBJ+ +FORINIT.OBJ+ +FORLABEL.OBJ+ +FORMAT.OBJ+ +FORPROC.OBJ+ +MSFOR.OBJ+ +FOREXEC.OBJ +FORMAT.exe,FORMAT.MAP; diff --git a/v4.0/src/CMD/FORMAT/FORMAT.SKL b/v4.0/src/CMD/FORMAT/FORMAT.SKL new file mode 100644 index 0000000..11f18fd --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORMAT.SKL @@ -0,0 +1,229 @@ + +:util FORMAT + +:class 1 +:use EXTEND2 ;File not found +:use EXTEND4 ;Too many open files +:use EXTEND5 ;Access denied +:use EXTEND8 ;Insufficient memory +:use EXTEND15 ;Invalid drive was specified +:use EXTEND26 ;Unknown media type + +:class A +;msgBadDosVersion +;"Incorrect DOS version",CR,LF,"$" +:use COMMON1 + +;msgCurrentTrack +;"Head: %3d Cylinder: %4d", CR, 0 +;:def 2 "Head: %1 Cylinder: %2",CR +:def 2 CR,"%1 percent of disk formatted ",CR + +;msgDataSpace +;"%l10d bytes available on disk",CR,LF,0 +:use COMMON3 + +;msgFormatComplete +;"Format complete ",CR,LF,0 +:def 4 CR,"Format complete ",CR,LF + +;msgBadSpace +;"%l10d bytes in bad sectors", CR, LF, 0 +:use COMMON5 + +;msgTotalDiskSpace +;"%l10d bytes total disk space", CR, LF, 0 +:use COMMON6 + +;msgInsertDisk +;"Insert new diskette for drive %c:",CR,LF +:def 7 "Insert new diskette for drive %1:",CR,LF + +;msgSystemSpace +;"%l10d bytes used by system", CR, LF, 0 +:use COMMON8 + +;msgReInsertDisk +;"Re-insert diskette for drive %c:",0 +:def 9 "Re-insert diskette for drive %1:",CR,LF + +;msgLabelPrompt +;"Volume label (11 characters, ENTER for none)? ",0 +:use 10 COMMON35 + +;msgFormatNotSupported +;"Format not supported on drive %c:", CR,LF,0 +:def 11 CR,"Format not supported on drive %1:", CR,LF + +;msgInvalidDeviceParameters +;"Invalid device parameters from device driver",CR,LF,0 +:def 12 CR,"Invalid device parameters from device driver",CR,LF + +;msgErrorInIOCTL +;"Error in IOCTL call", CR, LF, 0 +:def 13 CR,"Error in IOCTL call ",CR,LF + +;msgNotBlockDevice +;"Not a block device", CR, LF +:def 14 CR,"Not a block device ",CR,LF + +;msgFATwriteError +;"Error writing FAT", CR, LF, 0 +:def 15 CR,"Error writing FAT ",CR,LF + +;msgDirectoryWriteError +;"Error writing directory ", CR, LF, 0 +:def 16 CR,"Error writing directory",CR,LF + +;msgAssignedDrive +;"Cannot format an ASSIGNed, SUBSTed, or JOINed drive. ", CR, LF, 0 +:def 17 CR,"Cannot format an ASSIGNed, SUBSTed, or JOINed drive. ",CR,LF + + +;msgNoSystemFiles +;"Cannot find System Files",CR,LF,0 +:def 18 CR,"Cannot find System Files",CR,LF + + +;msgNetDrive +;"Cannot FORMAT a Network drive", CR, LF, 0 +:def 19 CR,"Cannot FORMAT a Network drive",CR,LF + +;msgBadCharacters +;"Invalid characters in volume label ", CR, LF, 0 +:use 20 COMMON21 + + +:CLASS B + +;msgParametersNotSupported +;"Parameters not supported",CR,LF,0 +:def 21 CR,"Parameters not supported",CR,LF + +;msgFormatFailure +; Note: This message must be long enough to wipe out message msgCurrentTrack +;"Format terminated ",CR,LF,0 +:def 22 CR,"Format terminated ",CR,LF + +;msgNotSystemDisk +;"Disk unsuitable for system disk", CR, LF, 0 +:def 23 CR,"Disk unsuitable for system disk",CR,LF + +;msgDiskUnusable +;"Invalid media or Track 0 bad - disk unusable", CR, LF, 0 +:def 24 CR,"Invalid media or Track 0 bad - disk unusable",CR,LF + +;msgBootWriteError +;"Unable to write BOOT", CR, LF, 0 +:def 25 CR,"Unable to write BOOT ",CR,LF + +;msgDirectoryReadError +;"Error reading directory", CR, LF, 0 +:def 26 CR,"Error reading directory",CR,LF + +;msgNeedDrive +;"No target drive specified",CR,LF,0 +:use COMMON27 + +;ContinueMsg +;Press any key to continue +:def 28 CR,"and press ENTER when ready..." + +;msgBadVolumeId +;"Invalid Volume ID", CR, LF, 0 +:def 29 CR,"Invalid Volume ID ",CR,LF + +;msgSystemTransfered +;"System transferred",CR,LF,0 +:use COMMON30 + +;msgWhatIsVolumeId? +;"Enter current Volume Label for drive %c: ", 0 +:def 31 CR,"Enter current Volume Label for drive %1: " + + +;msgIncompatibleParametersForHardDisk +;" with fixed disk", CR,LF,0 +:def 32 CR,"Parameters not compatible",CR,LF,"with fixed disk",CR,LF + +;msgPartitionTableReadError +;"Error reading partition table", CR, LF, 0 +:def 35 CR,"Error reading partition table",CR,LF + +;msgSerialNumber +:use COMMON36 + +;msgFormatBroken +;"Format Broken", CR, LF, 0 +:def 37 CR,"Format Broken",CR,LF + +;msgEXECFailure +:def 38 CR,"Format not available on drive %1",CR,LF + +;NO_SYS_MESS: +; THIS IS A SPECIAL MESSAGE WHICH IS INCLUDED IN THE "FAKE" IBMBIO.COM +; FILE PLACED ON DISKS FORMATTED /B or /R. NOTE THAT IT IS NUL TERMINATED. +;"Non-System disk or disk error",13,10,0 +:def 39 CR,"Non-System disk or disk error",CR,LF + +;msgbadpartitiontable +;"Bad Partition Table", CR, LF, 0 +:def 40 CR,"Bad Partition Table ",CR,LF + +:CLASS C + +;msgParametersNotSupportedByDrive +;"Parameters not Supported by Drive",CR, LF, 0 +:def 41 CR,"Parameters not Supported by Drive",CR,LF + +;msgCRLF +:def 42 CR,LF + +;msgInterrupt +:def 43 CR,LF,LF + +;msgInsertDosDisk db "Insert DOS disk in drive %c:", CR, LF +:def 44 CR,"Insert DOS disk in drive %1:",CR,LF + + +;msgHardDiskWarning db CR,LF +; db "WARNING, ALL DATA ON NON-REMOVABLE DISK",CR,LF +; db "DRIVE %c: WILL BE LOST!",CR,LF +; db "Proceed with Format (Y/N)?",0 +:def 45 CR,LF,"WARNING, ALL DATA ON NON-REMOVABLE DISK",CR,LF +"DRIVE %1: WILL BE LOST!",CR,LF +"Proceed with Format (Y/N)?" + +;msgFormatAnother? db "Format another (Y/N)?",0 +:def 46 CR,"Format another (Y/N)?" + +;msgPartitionTableReadError db "Error reading partition table", CR, LF, 0 +:def 47 CR,"Error reading partition table",CR,LF + +;msgPartitionTableWriteError db "Error writing partition table", CR, LF, 0 +:def 48 CR,"Error writing partition table",CR,LF + +;msgIncompatibleParametere forproc.sal not compatible", CR,LF +;"Parameters not compatible", CR,LF,0 +:def 49 CR,"Parameters not compatible", CR,LF + +;msgNumAlloc +:def 50 "%1 allocation units available on disk",CR,LF + +;msgAllocSize +:def 51 "%1 bytes in each allocation unit",CR,LF + +;msgPartitionTableWriteError +; "Error writing partition table", CR, LF, 0 +:def 52 CR, "Error writing partition table",CR,LF + +;msgSameSwitch +:def 53 CR,"Same parameter entered twice",CR,LF + +;msgBad_T_N +:def 54 CR,"Must enter both /T and /N parameters",CR,LF ;AN009; + +;MsgVerify +:def 55 CR,"Attempting to recover allocation unit %1 ",CR +:end + diff --git a/v4.0/src/CMD/FORMAT/FORMSG.INC b/v4.0/src/CMD/FORMAT/FORMSG.INC new file mode 100644 index 0000000..09ec9f2 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORMSG.INC @@ -0,0 +1,861 @@ +; + +; +;***************************************************************************** +; Macro's +;***************************************************************************** +; + + +Define_Msg macro Message_Name ; ;AN000; + ; +Create_Msg Message_Name,Message_Number,Handle,Sublist,Count,Class,Function,Input;AN000; + ; + endm ; ;AN000; + +;----------------------------------------------------------------------------- + +Create_Msg macro Parm1,Parm2,Parm3,Parm4,Parm5,Parm6,Parm7,Parm8; ;AN000; + +Public Parm1 +Parm1 label word ; ;AN000; + dw Parm2 ; ;AN000; + dw Parm3 ; ;AN000; + dw Parm4 ; ;AN000; + dw Parm5 ; ;AN000; + db Parm6 ; ;AN000; + db Parm7 ; ;AN000; + dw Parm8 ; ;AN000; + endm ; ;AN000; + + +; +;***************************************************************************** +; External data declarations +;***************************************************************************** +; + + Extrn DriveLetter:Byte + Extrn SystemDriveLetter:Byte + Extrn CurrentHead:Byte + Extrn CurrentCylinder:Word + Extrn FdskSiz:Word + Extrn SysSiz:Word + Extrn BadSiz:Word + Extrn DataSiz:Word + Extrn Drive_Letter_Msg:Byte + Extrn PercentComplete:Byte + Extrn AllocSize:Dword + Extrn AllocNum:Word + Extrn Serial_Num_Low:Word + Extrn Serial_Num_High:Word + Extrn Command_Old_Ptr:Word + Extrn Msg_Allocation_Unit_Val:Dword + +; +;***************************************************************************** +; Publics +;***************************************************************************** +; + + + +; +;***************************************************************************** +; Message Retriever equates +;***************************************************************************** +; + +Format_Msg equ 'C' + +N_A equ 0 +Sublist_Length equ 11 +None equ 0 + +Blank equ " " +No_Function equ 0 +No_Replace equ 0 + +Msg_Ser_Class equ 0 +Ext_Err_Class equ 1 +Parse_Err_Class equ 2 +Utility_Msg_Class equ 0FFh + +Reserved equ 0 + + + + +data segment public para 'DATA' + assume ds:data + + +; +;***************************************************************************** +; Message Sublist Tables +;***************************************************************************** +; +;The following control blocks are used for messages with +;replaceable paramaters. These control blocks are used by the +;SysDispMsg routine. +; + +;--------------------------- ; +Sublist_msgCurrentTrack label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset PercentComplete ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_Word ; ;AN000; + db 3 ;Max % is 100 ;AN000; + db 3 ;Min % is 0 ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgInsertDisk label dword ; ;AN000; +Sublist_msgReInsertDisk label dword ; ;AN000; +Sublist_MsgHardDiskWarning label dword ; +Sublist_msgFormatNotSupported label dword ; ;AN000; + + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset DriveLetter ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Left_Align+Char_Field_Char ; ;AN000; + db 1 ; ;AN000; + db 1 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgInsertDOSDisk label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset SystemDriveLetter; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Left_Align+Char_Field_Char ; ;AN000; + db 1 ; ;AN000; + db 1 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgTotalDiskSpace label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset FdskSiz ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_Dword ; ;AN000; + db 10 ; ;AN000; + db 10 ;4,000,000,000 limit ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgSystemSpace label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset SysSiz ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_DWord ; ;AN000; + db 10 ; ;AN000; + db 10 ;64k*3 max ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgBadSpace label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset BadSiz ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_DWord ; ;AN000; + db 10 ; ;AN000; + db 10 ;4,000,000,000 max ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgDataSpace label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw Offset DataSiz ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_DWord ; ;AN000; + db 10 ; ;AN000; + db 10 ;4,000,000,000 max ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgWhatIsVolumeId? label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset DriveLetter ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Left_Align+Char_Field_Char ; ;AN000; + db 1 ; ;AN000; + db 1 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgEXECFailure label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw Drive_Letter_Msg ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;AN000; + db 2 ; ;AN000; + db 2 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgAllocNum label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset AllocNum ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_Word ; ;AN000; + db 10 ; ;AN000; + db 10 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgAllocSize label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset AllocSize ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_DWord ; ;AN000; + db 10 ; ;AN000; + db 10 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_msgSerialNumber label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset Serial_Num_Low ; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Bin_Hex_Word ; ;AN000; + db 4 ; ;AN000; + db 4 ; ;AN000; + db '0' ;Display leading 0's ;AN000; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset Serial_Num_High ; ;AN000; + dw data ; ;AN000; + db 2 ; ;AN000; + db Right_Align+Bin_hex_Word ; ;AN000; + db 4 ; ;AN000; + db 4 ; ;AN000; + db '0' ; ;AN000; + +Public Sublist_MsgParse_Error +Sublist_msgParse_Error label dword ; ;AN000; + + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw 0 ; ;AN000; + dw Data ; ;AN000; + db 0 ; ;AN000; + db Left_Align+Char_Field_ASCIIZ ; ;AN000; + db 20 ; ;AN000; + db 01 ; ;AN000; + db Blank ; ;AN000; +;--------------------------- ; +Sublist_MsgVerify label dword ; ;AN000; + ; + db Sublist_Length ; ;AN000; + db Reserved ; ;AN000; + dw offset Msg_Allocation_Unit_Val; ;AN000; + dw data ; ;AN000; + db 1 ; ;AN000; + db Right_Align+Unsgn_Bin_DWord; ;AN000; + db 8 ; ;AN000; + db 8 ; ;AN000; + db Blank +; +;***************************************************************************** +; Message Description Tables +;***************************************************************************** +; + +;---------------------- ; +Message_Number = 1 ; ;AN000; +Handle = No_Handle ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadDOSVersion ; ;AN000; +;---------------------- ; +Message_Number = 2 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgCurrentTrack ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgCurrentTrack ; ;AN000; +;---------------------- ; +Message_Number = 3 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgDataSpace ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgDataSpace ; ;AN000; +;---------------------- ; +Message_Number = 4 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFormatComplete ; ;AN000; +;---------------------- ; +Message_Number = 5 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgBadSpace ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadSpace ; ;AN000; +;---------------------- ; +Message_Number = 6 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgTotalDiskSpace ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgTotalDiskSpace ; ;AN000; +;---------------------- ; +Message_Number = 7 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgInsertDisk ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgInsertDisk ; ;AN000; +;---------------------- ; +Message_Number = 8 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgSystemSpace ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgSystemSpace ; ;AN000; +;---------------------- ; +Message_Number = 9 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgReInsertDisk ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgReInsertDisk ; ;AN000; +;---------------------- ; +Message_Number = 10 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgLabelPrompt ; ;AN000; +;---------------------- ; +Message_Number = 11 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgFormatNotSupported ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFormatNotSupported ; ;AN000; +;---------------------- ; +Message_Number = 12 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgInvalidDeviceParameters; ;AN000; +;---------------------- ; +Message_Number = 13 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgErrorInIOCTL ; ;AN000; +;---------------------- ; +Message_Number = 14 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNotBlockDevice ; ;AN000; +;---------------------- ; +Message_Number = 15 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFATwriteError ; ;AN000; +;---------------------- ; +Message_Number = 16 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgDirectoryWriteError ; ;AN000; +;---------------------- ; +Message_Number = 17 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgAssignedDrive ; ;AN000; +;---------------------- ; +Message_Number = 18 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNoSystemFiles ; ;AN000; +;---------------------- ; +Message_Number = 19 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNetDrive ; ;AN000; +;---------------------- ; +Message_Number = 20 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadCharacters ; ;AN000; +;---------------------- ; +Message_Number = 21 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgParametersNotSupported ; ;AN000; +;---------------------- ; +Message_Number = 22 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFormatFailure ; ;AN000; +;---------------------- ; +Message_Number = 23 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNotSystemDisk ; ;AN000; +;---------------------- ; +Message_Number = 24 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgDiskUnusable ; ;AN000; +;---------------------- ; +Message_Number = 25 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBootWriteError ; ;AN000; +;---------------------- ; +Message_Number = 26 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgDirectoryReadError ; ;AN000; +;---------------------- ; +Message_Number = 27 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNeedDrive ; ;AN000; +;---------------------- ; +Message_Number = 28 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg ContinueMsg ; ;AN000; +;---------------------- ; +Message_Number = 29 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadVolumeId ; ;AN000; +;---------------------- ; +Message_Number = 30 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgSystemTransfered ; ;AN000; +;---------------------- ; +Message_Number = 31 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgWhatIsVolumeId? ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgWhatIsVolumeId? ; ;AN000; +;---------------------- ; +Message_Number = 32 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgIncompatibleParametersForHardDisk ; ;AN000; +;---------------------- ; + +Message_Number = 33 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgWriteProtected ; ;AN000; +;---------------------- ; +Message_Number = 34 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgNotReady ; ;AN000; +;---------------------- ; + +Message_Number = 35 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgPartitionTableReadErr ; ;AN000; +;---------------------- ; +Message_Number = 36 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgSerialNumber ; ;AN000; +Count = 2 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgSerialNumber ; ;AN000; +;---------------------- ; +Message_Number = 37 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFormatBroken ; ;AN000; +;---------------------- ; +Message_Number = 38 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_msgEXECFailure ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgEXECFailure ; ;AN000; +;---------------------- ; +Message_Number = 39 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg NO_SYS_MESS ; ;AN000; +;---------------------- ; +Message_Number = 40 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgbadpartitiontable ; ;AN000; +;---------------------- ; +Message_Number = 41 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgParametersNotSupportedByDrive ; ;AN000; +;---------------------- ; +Message_Number = 42 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgCRLF ; ;AN000; +;---------------------- ; +Message_Number = 43 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgInterrupt ; ;AN000; +;---------------------- ; +Message_Number = 44 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_MsgInsertDOSDisk ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgInsertDOSDisk ; ;AN000; +;---------------------- ; +Message_Number = 45 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_MsgHardDiskWarning ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgHardDiskWarning ; ;AN000; +;---------------------- ; +Message_Number = 46 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgFormatAnother? ; ;AN000; +;---------------------- ; +Message_Number = 47 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgPartitionTableReadError ; ;AN000; +;---------------------- ; +Message_Number = 48 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgPartitionTableWriteError ; ;AN000; +;---------------------- ; +Message_Number = 49 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgIncompatibleParameters ; ;AN000; +;---------------------- ; +Message_Number = 50 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_MsgAllocNum ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgAllocNum ; ;AN000; +;---------------------- ; +Message_Number = 51 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = Sublist_MsgAllocSize ; ;AN000; +Count = 1 ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgAllocSize ; ;AN000; +;---------------------- ; +Message_Number = 52 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgPartitionTableWriteErr ; ;AN000; +;---------------------- ; +Message_Number = 53 ; ;AN002; +Handle = STDOUT ; ;AN002; +Sublist = No_Replace ; ;AN002; +Count = N_A ; ;AN002; +Class = Utility_Msg_Class ; ;AN002; +Function = No_Function ; ;AN002; +Input = N_A ; ;AN002; + Define_Msg msgSameSwitch ; ;AN002; +;---------------------- ; +Message_Number = 54 ; ;AN009; +Handle = STDOUT ; ;AN009; +Sublist = No_Replace ; ;AN009; +Count = N_A ; ;AN009; +Class = Utility_Msg_Class ; ;AN009; +Function = No_Function ; ;AN009; +Input = N_A ; ;AN009; + Define_Msg msgBad_T_N ; ;AN009; +;---------------------- ; +Message_Number = 55 ; ;an019; dms; +Handle = STDOUT ; ;an019; dms; +Sublist = Sublist_MsgVerify ; ;an019; dms; +Count = 1 ; ;an019; dms; +Class = Utility_Msg_Class ; ;an019; dms; +Function = No_Function ; ;an019; dms; +Input = N_A ; ;an019; dms; + Define_Msg MsgVerify ; ;an019; dms; +;---------------------- ; +Message_Number = 0 ; ;AN000; +Handle = STDERR ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Ext_Err_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg Extended_Error_Msg ; ;AN000; +;---------------------- +Message_Number = 0 ; ;AN000; +Handle = STDERR ; ;AN000; +Sublist = Sublist_MsgParse_Error ; ;AN000; +Count = 1 ; ;AN000; +Class = Parse_Err_Class ; ;AN000; +Function = No_Function ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg Parse_Error_Msg ; ;AN000; +;----------------------- + + + +; +;These need to be coded as extended an parse errors, but left here to link. +; + + + +Message_Number = 70 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgOutOfMemory ; ;AN000; +;---------------------- ; +Message_Number = 71 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgBadDrive ; ;AN000; +;---------------------- ; +Message_Number = 10 ; ;AN000; +Handle = StdErr ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Parse_Err_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgInvalidParameter ; ;AN000; +;---------------------- ; +Message_Number = 73 ; ;AN000; +Handle = STDOUT ; ;AN000; +Sublist = No_Replace ; ;AN000; +Count = N_A ; ;AN000; +Class = Utility_Msg_Class ; ;AN000; +Function = No_Input ; ;AN000; +Input = N_A ; ;AN000; + Define_Msg msgLoadFailure ; ;AN000; + + + + + + + + + +data ends + + diff --git a/v4.0/src/CMD/FORMAT/FORPARSE.INC b/v4.0/src/CMD/FORMAT/FORPARSE.INC new file mode 100644 index 0000000..393b425 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORPARSE.INC @@ -0,0 +1,523 @@ +; + + + +data segment public para 'DATA' + +; +;***************************************************************************** +; Publics +;***************************************************************************** +; + + Public Drive_Letter_Buffer + Public Switch_Buffer + Public Switch_Num_Buffer + Public Switch_String_Buffer + + +; +;*************************************************************************** +; Equates +;*************************************************************************** +; + +;Match Flags + +Numeric_Value equ 8000h ; ;AN000; +Signed_Numeric_Value equ 4000h ; ;AN000; +Simple_String equ 2000h ; ;AN000; +Date_String equ 1000h ; ;AN000; +Time_String equ 0800h ; ;AN000; +Complex_List equ 0400h ; ;AN000; +Filespec equ 0200h ; ;AN000; +Drive_Only equ 0100h ; ;AN000; +Quoted_String equ 0080h ; ;AN000; +Ignore_Colon equ 0010h ; ;AN000; +Repeats_Allowed equ 0002h ; ;AN000; +Optional equ 0001h ; ;AN000; + +;Function_Flags + +File_Table_Capitalize equ 1 ; ;AN000; +Char_Table_Capitalize equ 2 ; ;AN000; +Remove_Colon equ 10h ; ;AN000; + +;Extra delimeters and EOL + +Delimiters_Only equ 1 ; ;AN000; +EOL_Or_Delimiters equ 2 ; ;AN000; + +Semi_Colon equ ";" ; ;AN000; +Tab equ 09h ; ;AN000; +Colon equ ":" ; ;AN000; + + +;Parse Errors + +No_Error equ 0 ; ;AN000; +Too_Many_Operands equ 1 ; ;AN000; +Operand_Missing equ 2 ; ;AN000; +Not_In_Switch_List equ 3 ; ;AN000; +Not_In_Keyword_List equ 4 ; ;AN000; +Out_Of_Range equ 6 ; ;AN000; +Not_In_Value_List equ 7 ; ;AN000; +Not_In_String_List equ 8 ; ;AN000; +Syntax_Error equ 9 ; ;AN000; +End_Of_Parse equ -1 ; ;AN000; + +;Return types + +Type_Reserved equ 0 ; ;AN000; +Type_Number equ 1 ; ;AN000; +Type_List_Index equ 2 ; ;AN000; +Type_String equ 3 ; ;AN000; +Type_Complex equ 4 ; ;AN000; +Type_Filespec equ 5 ; ;AN000; +Type_Drive equ 6 ; ;AN000; +Type_Date equ 7 ; ;AN000; +Type_Time equ 8 ; ;AN000; +Type_Quoted_String equ 9 ; ;AN000; + +;Other + +None equ 0 ; ;AN000; +No_Error equ 0 ; ;AN000; +Switch_Found equ 0FFFFh ; ;AN000; +Range_Ok equ 1 ; ;AN000; +Command_Line_Parms equ 81h ; ;AN000; + +; +;***************************************************************************** +; Parse Structures +;***************************************************************************** +; + +Control struc + +Match_Flags dw ? +Function_Flags dw ? +Result dw ? +Values dw ? +Num_Keywords db ? +Keyword db ? + +Control ends + +Drive_Letter_Return struc ; ;AN000; + +Drive_Type db 0 ; ;AN000; +Drive_Item_Tag db 0 ; ;AN000; +Drive_Pointer dw 0 ; ;AN000; +Drive_Number db 0 ;A=1, B=2, C=3 ;AN000; +Drive_debug db 8 dup(0) + +Drive_Letter_Return ends ; ;AN000; + +Switch_Return struc ; ;AN000; + +Switch_Type db 0 ; ;AN000; +Switch_Item_Tag db 0 ; ;AN000; +Switch_Pointer dw 0 ; ;AN000; +Switch_Debug db 4 dup(0) + +Switch_Return ends ; ;AN000; + +Switch_Num_Return struc ; ;AN000; + +Switch_Num_Type db 0 ; ;AN000; +Switch_Num_Item_Tag db 0 ; ;AN000; +Switch_Num_Pointer dw 0 ; ;AN000; +Switch_Number_Low dw 0 ; ;AN000; +Switch_Number_High dw 0 ; ;AN000; + +Switch_Num_Return ends ; ;AN000; + +Switch_String_Return struc ; ;AN000; + +Switch_String_Type db 0 ; ;AN000; +Switch_String_Item_Tag db 0 ; ;AN000; +Switch_String_Pointer dw 0 ; ;AN000; +Switch_String_Off dw 0 ; ;AN000; +Switch_String_Seg dw 0 ; ;AN000; + +Switch_String_Return ends ; ;AN000; + + +; +;************************************************************************** +; Parse tables +;************************************************************************** +; + +IF FSExec ;conditionally assemble /FS: ;an018; dms; + +Switch_FS_Table label byte ; ;AN000; + + dw Drive_Control_Definition ;Point to next level ;AN000; + db 0 ; ;AN000; + +ENDIF ;end conditional assembly /FS: ;an018; dms; + +Command_Line_Table label byte ; ;AN000; + + dw Command_Control ;Point to next level ;AN000; + db 0 ; ;AN000; + +; +;************************************************************************** +;Define Positionals, Switches and Keywords +;************************************************************************** +; + + +IF FSExec ;conditionally assemble /FS: ;an018; dms; + +Drive_Control_Definition label byte ; ;AN000; + + db 1,1 ;Only drive letter posistional ;AN000; + dw Positional_Control ;Pointer to control table ;AN000; + db 1 ;1 switch ;AN000; + dw Switch_FS_Control ; ;AN000; + db None ;No Keywords (maxk) ;AN000; + +ENDIF ;end conditional assembly /FS: ;an018; dms; + +Command_Control label byte ; ;AN000; + + db 1,1 ;Only drive letter posistional ;AN000; + dw Positional_Control ;Pointer to control table ;AN000; +IF ShipDisk + db 13 ;if /Z switch needed ;an000; dms; +ELSE + db 12 ; ;AC001; +ENDIF + dw Switch_V_Control ;Without quotes AN000; + dw Switch_S_Control ; ;AN000; + dw Switch_4_Control ; ;AN000; + dw Switch_1_Control ; ;AN000; + dw Switch_8_Control ; ;AN000; + dw Switch_B_Control ; ;AN000; + dw Switch_T_Control ; ;AN000; + dw Switch_N_Control ; ;AN000; + dw Switch_Select_Control ; ;AN000; + dw Switch_Backup_Control ; ;AN000; + dw Switch_Autotest_Control ; ;AN000; + dw Switch_F_Control ; ;AC001; +IF ShipDisk + dw Switch_Z_Control ;1 sector/cluster switch ;an000; dms; +ENDIF + db None ;No Keywords (maxk) ;AN000; + +; +;************************************************************************** +;Control Tables +;************************************************************************** +; + +Positional_Control label byte ; ;AN000; + + dw Drive_Only ;Match_Flag ;AN000; + dw None ;No function flags ;AN000; + dw Drive_Letter_Buffer ;Where it will be returned ;AN000; + dw No_Value ;No value ranges defined ;AN000; + db None ;No defined switches/keywords ;AN000; + +IF FSExec ;conditionally assemble /FS: ;an018; dms; + +Switch_FS_Control label byte + dw Simple_String ;/FS:xxxxx ;AN000; + dw File_Table_Capitalize ;Make it uppercase ;AN000; + dw Switch_String_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/FS",0 ; ;AN000; + +ENDIF ;end conditional assembly /FS: ;an018; dms; + +Switch_V_Control label byte ; ;AN000; + + dw Simple_String+Quoted_String+Optional ;/v:xxxxxxxx ;AN000; + dw File_Table_Capitalize ; ;AN000; + dw Switch_String_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/V",0 ; ;AN000; + +Switch_S_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/S",0 ; ;AN000; + +Switch_4_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/4",0 ; ;AN000; + +Switch_1_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/1",0 ; ;AN000; + +Switch_8_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/8",0 ; ;AN000; + +Switch_B_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/B",0 ; ;AN000; + +Switch_T_Control label byte ; ;AN000; + + dw Numeric_Value ; ;AN000; + dw None ; ;AN000; + dw Switch_Num_Buffer ; ;AN000; + dw Switch_T_Value ; ;AN000; + db 1 ; ;AN000; + db "/T",0 ; ;AN000; + +Switch_N_Control label byte ; ;AN000; + + dw Numeric_Value ; ;AN000; + dw None ; ;AN000; + dw Switch_Num_Buffer ; ;AN000; + dw Switch_N_Value ; ;AN000; + db 1 ; ;AN000; + db "/N",0 ; ;AN000; + +Switch_Select_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/SELECT",0 ; ;AN000; + +Switch_Backup_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/BACKUP",0 ; ;AN000; + +Switch_Autotest_Control label byte ; ;AN000; + + dw None ; ;AN000; + dw None ; ;AN000; + dw Switch_Buffer ; ;AN000; + dw No_Value ; ;AN000; + db 1 ; ;AN000; + db "/AUTOTEST",0 ; ;AN000; + +Switch_F_Control label byte ; ;AN001; + dw Simple_String ;/F:xxxxx ;AN001; + dw File_Table_Capitalize ;Make it uppercase ;AN001; + dw Switch_String_Buffer ; ;AN001; + dw Switch_Size_Value ; ;AN001; + db 1 ; ;AN001; + db "/F",0 ; ;AN001; + +IF ShipDisk + +Switch_Z_Control label byte ;control structure for /Z ;an000; dms; + dw None ; ;an000; dms; + dw None ; ;an000; dms; + dw Switch_Buffer ; ;an000; dms; + dw No_Value ; ;an000; dms; + db 1 ; ;an000; dms; + db "/Z",0 ; ;an000; dms; + +ENDIF + +; +;************************************************************************ +; PARSE Value Lists +;************************************************************************ +; + +Switch_T_Value label byte ; ;AN000; + + db 1 ;Range only ;ANOOO; + db 1 ;1 range ;ANOOO; + db Range_OK ;Item_Tag ;ANOOO; + dd 1 ;1 is low bound ;ANOOO; + dd 1024 ;2**10 is max ;AN000; + +Switch_N_Value label byte ; ;AN000; + + db 1 ;Range only ;ANOOO; + db 1 ;1 range ;ANOOO; + db Range_OK ;Item_Tag ;ANOOO; + dd 1 ;1 is low bound ;ANOOO; + dd 64 ;2**6 is max ;AN000; + +Switch_Size_Value label byte ; ;AN001; + + db 3 ;Look for strings ;AN001; + db 0 ;No ranges ;AN001; + db 0 ;No numerics ;AN001; + db 27 ;16 possible strings ;AN001; + db Size_160 ; ;AN001; + dw String_160k_1 ;/F:160 ;AN001; + db Size_160 ; ;AN001; + dw String_160k_2 ;/F:160K ;AN001; + db Size_160 ; ;AN001; + dw String_160k_3 ;/F:160KB ;AN001; + db Size_180 ; ;AN001; + dw String_180k_1 ;/F:180 ;AN001; + db Size_180 ; ;AN001; + dw String_180k_2 ;/F:180K ;AN001; + db Size_180 ; ;AN001; + dw String_180k_3 ;/F:180KB ;AN001; + db Size_320 ; ;AN001; + dw String_320k_1 ;/F:320 ;AN001; + db Size_320 ; ;AN001; + dw String_320k_2 ;/F:320K ;AN001; + db Size_320 ; ;AN001; + dw String_320k_3 ;/F:320KB ;AN001; + db Size_360 ; ;AN001; + dw String_360k_1 ;/F:360 ;AN001; + db Size_360 ; ;AN001; + dw String_360k_2 ;/F:360K ;AN001; + db Size_360 ; ;AN001; + dw String_360k_3 ;/F:360KB ;AN001; + db Size_720 ; ;AN001; + dw String_720k_1 ;/F:720 ;AN001; + db Size_720 ; ;AN001; + dw String_720k_2 ;/F:720K ;AN001; + db Size_720 ; ;AN001; + dw String_720k_3 ;/F:720KB ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_1 ;/F:1200 ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_2 ;/F:1200K ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_3 ;/F:1200KB ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_4 ;/F:1.2 ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_5 ;/F:1.2M ;AN001; + db Size_1200 ; ;AN001; + dw String_1200k_6 ;/F:1.2MB ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_1 ;/F:1440 ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_2 ;/F:1440K ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_3 ;/F:1440KB ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_4 ;/F:1.44 ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_5 ;/F:1.44M ;AN001; + db Size_1440 ; ;AN001; + dw String_1440k_6 ;/F:1.44MB ;AN001; + + +No_Value label byte ; ;AN000; + db 0 ; ;AN000; + +; +;***************************************************************************** +; Data Area for value lists +;***************************************************************************** +; + +; +;The following are a list of the allowed strings for the /F:xxxxx switch. +; + +String_160k_1 db "160" ,Asciiz_End ; ;AN001; +String_160k_2 db "160K" ,Asciiz_End ; ;AN001; +String_160k_3 db "160KB" ,Asciiz_End ; ;AN001; +String_180k_1 db "180" ,Asciiz_End ; ;AN001; +String_180k_2 db "180K" ,Asciiz_End ; ;AN001; +String_180k_3 db "180KB" ,Asciiz_End ; ;AN001; +String_320k_1 db "320" ,Asciiz_End ; ;AN001; +String_320k_2 db "320K" ,Asciiz_End ; ;AN001; +String_320k_3 db "320KB" ,Asciiz_End ; ;AN001; +String_360k_1 db "360" ,Asciiz_End ; ;AN001; +String_360k_2 db "360K" ,Asciiz_End ; ;AN001; +String_360k_3 db "360KB" ,Asciiz_End ; ;AN001; +String_720k_1 db "720" ,Asciiz_End ; ;AN001; +String_720k_2 db "720K" ,Asciiz_End ; ;AN001; +String_720k_3 db "720KB" ,Asciiz_End ; ;AN001; +String_1200k_1 db "1200" ,Asciiz_End ; ;AN001; +String_1200k_2 db "1200K",Asciiz_End ; ;AN001; +String_1200k_3 db "1200KB",Asciiz_End ; ;AN001; +String_1200k_4 db "1.2" ,Asciiz_End ; ;AN001; +String_1200k_5 db "1.2M" ,Asciiz_End ; ;AN001; +String_1200k_6 db "1.2MB" ,Asciiz_End ; ;AN001; +String_1440k_1 db "1440" ,Asciiz_End ; ;AN001; +String_1440k_2 db "1440K",Asciiz_End ; ;AN001; +String_1440k_3 db "1440KB",Asciiz_End ; ;AN001; +String_1440k_4 db "1.44",Asciiz_End ; ;AN001; +String_1440k_5 db "1.44M",Asciiz_End ; ;AN001; +String_1440k_6 db "1.44MB",Asciiz_End ; ;AN001; + +; +;************************************************************************ +; PARSE Return Buffers +;************************************************************************ +; + +Drive_Letter_Buffer Drive_Letter_Return <> ;Example of structure ;AN000; +Switch_Buffer Switch_Return <> ; ;AN000; +Switch_Num_Buffer Switch_Num_Return <> ; ;AN000; +Switch_String_Buffer Switch_String_Return <> ; ;AN000; + +data ends + +; +;***************************************************************************** +; SysParse Routines +;***************************************************************************** +; + + +code segment public para 'CODE' + assume cs:code,ds:Data + +FarSW equ Not_Include ;AN000; +DateSW equ Not_Include ; ;AN000; +TimeSW equ Not_Include ; ;AN000; +FileSW equ Do_Include ; ;AN000; +CAPSW equ Do_Include ; ;AN000; +CmpxSW equ Not_Include ; ;AN000; +NumSW equ Do_Include ; ;AN000; +KeySW equ Not_Include ; ;AN000; +SwSW equ Do_Include ; ;AN000; +Val1SW equ DO_Include ; ;AN000; +Val2SW equ Not_Include ; ;AN000; +Val3SW equ Do_Include ; ;AN001; +DrvSW equ Do_Include ; ;AN000; +QusSW equ Do_Include ; ;AN000; + +INCLUDE PARSE.ASM ; ;AN000; + + +code ends diff --git a/v4.0/src/CMD/FORMAT/FORPROC.ASM b/v4.0/src/CMD/FORMAT/FORPROC.ASM new file mode 100644 index 0000000..bbf139a --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORPROC.ASM @@ -0,0 +1,521 @@ +; SCCSID = @(#)forproc.asm 1.2 85/07/25 +; +.xlist +.xcref +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + + INCLUDE FORCHNG.INC + INCLUDE SYSCALL.INC + INCLUDE FOREQU.INC + INCLUDE FORMACRO.INC + INCLUDE FORSWTCH.INC + INCLUDE IOCTL.INC +.cref +.list +data segment public para 'DATA' +data ends + +code segment public para 'CODE' + assume cs:code,ds:data + + PUBLIC FormatAnother?,Yes?,REPORT,USER_STRING + public fdsksiz,badsiz,syssiz,datasiz,biosiz + public AllocSize,AllocNum + + extrn std_printf:near,crlf:near,PrintString:near + extrn Multiply_32_Bits:near + extrn AddToSystemSize:near + +data segment public para 'DATA' + extrn driveLetter:byte + extrn msgInsertDisk:byte + extrn msgFormatAnother?:byte + extrn msgTotalDiskSpace:byte + extrn msgSystemSpace:byte + extrn msgBadSpace:byte + extrn msgDataSpace:byte + extrn Read_Write_Relative:byte + extrn msgAllocSize:byte + extrn MsgAllocNum:Byte + extrn deviceParameters:byte + extrn bios:byte + extrn dos:byte + extrn command:byte + extrn Serial_Num_Low:Word + extrn Serial_Num_High:Word + extrn msgSerialNumber:Byte + extrn SwitchMap:Word + + + extrn inbuff:byte + +fdsksiz dd 0 + +syssiz dd 0 +biosiz dd 0 + +badsiz dd 0 + +datasiz dd 0 + +AllocSize dd 0 ; ;AN000; +AllocNum dw 0 ; ;AN000; + dw offset driveLetter +data ends + +FormatAnother? proc near +; Wait for key. If yes return carry clear, else no. Insures +; explicit Y or N answer. + Message msgFormatAnother? ; ;AC000; + CALL Yes? + JNC WAIT20 + JZ WAIT20 + CALL CRLF + JMP SHORT FormatAnother? +WAIT20: ; ;AC000; + RET ; ;AC000; +FormatAnother? endp + +;***************************************************************************** +;Routine name:Yes? +;***************************************************************************** +; +;Description: Validate that input is valid Y/N for the country dependent info +; Wait for key. If YES return carry clear,else carry set. +; If carry is set, Z is set if explicit NO, else key was not Yes or No. +; +;Called Procedures: Message (macro) +; User_String +; +;Change History: Created 4/32/87 MT +; +;Input: None +; +;Output: CY = 0 Yes is entered +; CY = 1, Z = No +; CY = 1, NZ = other +; +;Psuedocode +;---------- +; +; Get input (CALL USER STRING) +; IF got character +; Check for country dependent Y/N (INT 21h, AX=6523h Get Ext Country) +; IF Yes +; clc +; ELSE (No) +; IF No +; stc +; Set Zero flag +; ELSE (Other) +; stc +; Set NZ +; ENDIF +; ENDIF +; ELSE (nothing entered) +; stc +; Set NZ flag +; ENDIF +; ret +;***************************************************************************** + +Procedure YES? ; ;AN000; + + call User_String ;Get character ; ; +; $IF NZ ;Got one if returned NZ ;AC000; + JZ $$IF1 + mov al,23h ;See if it is Y/N ;AN000; + mov dl,[InBuff+2] ;Get character ;AN000; + DOS_Call GetExtCntry ;Get country info call ;AN000; + cmp ax,Found_Yes ;Which one? ;AC000; +; $IF E ;Got a Yes ;AC000; + JNE $$IF2 + clc ;Clear CY for return ;AN000; +; $ELSE ;Not a Yes ;AN000; + JMP SHORT $$EN2 +$$IF2: + cmp ax,Found_No ;Is it No? ;AC000; +; $IF E ;Yep ;AN000; + JNE $$IF4 + stc ;Set CY for return ;AC000; +; $ELSE ;Something else we don't want ;AN000; + JMP SHORT $$EN4 +$$IF4: + xor al,al ;Set NZ flag for ret ;AC000; + cmp al,1 ; " " " " ;AC000; + stc ;And CY flag for good measure ;AN000; +; $ENDIF ; ;AN000; +$$EN4: +; $ENDIF ; ;AN000; +$$EN2: +; $ELSE ;No char found at all ;AN000; + JMP SHORT $$EN1 +$$IF1: + xor al,al ;Set NZ flag for ret ;AN000; + cmp al,1 ; " " " " ;AN000; + stc ;And CY flag for good measure ;AN000; +; $ENDIF ; ;AN000; +$$EN1: + ret ; ; ; + +Yes? endp ; ;AN000; + + +USER_STRING: +; Get a string from user. Z is set if user typed no chars (imm CR) +; We need to flush a second time to get rid of incoming Kanji characters also. + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 ; Clean out input + INT 21H + MOV DX,OFFSET INBUFF + MOV AH,STD_CON_STRING_INPUT + INT 21H + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 ; Clean out input + INT 21H + CMP BYTE PTR [INBUFF+1],0 + RET + +;********************************************* +; Make a status report including the following information: +; Total disk capacity +; Total system area used +; Total bad space allocated +; Total data space available +; Number of allocation units +; Size of allocation units + +REPORT: + call crlf + + call Calc_System_Space ;an013; dms;calc system space + call Calc_Total_Addressible_Space ;an013; dms;calc total space + + Message msgTotalDiskSpace ; ;AC000; + ;call std_printf + cmp WORD PTR SYSSIZ,0 + JNZ SHOWSYS + cmp WORD PTR SYSSIZ+2,0 + JZ CHKBAD +SHOWSYS: + Message msgSystemSpace ; ;AC000; + ;CALL std_printf ;Report space used by system +CHKBAD: + cmp WORD PTR BADSIZ,0 + JNZ SHOWBAD + cmp WORD PTR BADSIZ+2,0 + JZ SHOWDATA +SHOWBAD: + Message msgBadSpace ; ;AC000; + ;call std_printf +SHOWDATA: + + + MOV CX,WORD PTR Fdsksiz + MOV BX,WORD PTR Fdsksiz+2 + SUB CX,WORD PTR BADSIZ + SBB BX,WORD PTR BADSIZ+2 + SUB CX,WORD PTR SYSSIZ + SBB BX,WORD PTR SYSSIZ+2 + MOV word ptr datasiz,CX + MOV word ptr datasiz+2,BX + Message msgDataSpace ; ;AC000; + ;call std_printf + + call crlf ; ;AN000; + mov ax,deviceParameters.DP_BPB.BPB_BytesPerSector ; ;AN000; + mov cl,deviceParameters.DP_BPB.BPB_SectorsPerCluster ; ;AN000; + xor ch,ch ; ;AN000; + mul cx ;Get bytes per alloc ;AN000; + + mov word ptr AllocSize,ax ;Save allocation size ;AN000; + mov word ptr AllocSize+2,dx ; for message ;AN000; + Message msgAllocSize ;Print size of cluster ;AN000; + call Get_Free_Space ;an013; dms;get disk space + + mov word ptr AllocNum,bx ;Put result in msg ;AN000; + Message msgAllocNum ; = cluster/disk ;AN000; + call crlf ; ;AN000; + test switchmap, SWITCH_8 ;If 8 tracks, don't display ;AN027; + jnz NOSERIALNUMBER ;serial number ;AN027; + Message msgSerialNumber ;Spit out serial number ;AN000; + call crlf ; +NOSERIALNUMBER: ;AN027; + RET ; + +;***************************************************************************** +;Routine name: Read_Disk +;***************************************************************************** +; +;description: Read in data using Generic IOCtl +; +;Called Procedures: None +; +; +;Change History: Created 5/13/87 MT +; +;Input: AL = Drive number (0=A) +; DS:BX = Transfer address +; CX = Number of sectors +; Read_Write_Relative.Start_Sector_High = Number of sectors high +; DX = logical sector number low +; +;Output: CY if error +; AH = INT 25h error code +; +;Psuedocode +;---------- +; Save registers +; Setup structure for function call +; Read the disk (AX=440Dh, CL = 6Fh) +; Restore registers +; ret +;***************************************************************************** + +Procedure Read_Disk ; ;AN000; + + ;This is setup for INT 25h right;AN000; + ;Change it to Read relative sect;AN000; + push bx ;Save registers ;AN000; + push cx ; ;AN000; + push dx ; ;AN000; + push si ; ;AN000; + push di ; ;AN000; + push bp ; ;AN000; + push es ; ;AN000; + push ds ; + mov si,data ; ;AN000; + mov es,si ; ;AN000; + + assume es:data,ds:nothing ; ;AN000; + + mov es:Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add;AN000; + mov bx,ds ; ;AN000; + mov es:Read_Write_Relative.Buffer_Segment,bx ;Get segment ;AN000; + mov bx,data ;Point DS at parameter list ;AN000; + mov ds,bx ; ;AN000; + + assume ds:data,es:data + + mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to read ;AN000; + mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;AN000; + mov bx,offset Read_Write_Relative ; ;AN000; + mov cx,0FFFFh ;Read relative sector ;AN000; + INT 25h ;Do the read ;AN000; + pop dx ;Throw away flags on stack ;AN000; + pop ds ; + pop es ; ;AN000; + pop bp ; ;AN000; + pop di ; ;AN000; + pop si ; ;AN000; + pop dx ;Restore registers ;AN000; + pop cx ; ;AN000; + pop bx ; ;AN000; + ret ; ;AN000; + + +Read_Disk endp ; ;AN000; + +;***************************************************************************** +;Routine name: Write_Disk +;***************************************************************************** +; +;description: Write Data using Generic IOCtl +; +;Called Procedures: None +; +; +;Change History: Created 5/13/87 MT +; +;Input: AL = Drive number (0=A) +; DS:BX = Transfer address +; CX = Number of sectors +; Read_Write_Relative.Start_Sector_High = Number of sectors high +; DX = logical sector number low +; +;Output: CY if error +; AH = INT 26h error code +; +;Psuedocode +;---------- +; Save registers +; Setup structure for function call +; Write to disk (AX=440Dh, CL = 4Fh) +; Restore registers +; ret +;***************************************************************************** + +Procedure Write_Disk ; ;AN000; + + + ;This is setup for INT 26h right + ;Change it to Read relative sect + + push bx ;Save registers ;AN000; + push cx ; ;AN000; + push dx ; ;AN000; + push si ; ;AN000; + push di ; ;AN000; + push bp ; ;AN000; + push es ; ;AN000; + push ds ; + mov si,data ; ;AN000; + mov es,si ; ;AN000; + + assume es:data,ds:nothing ; ;AN000; + + mov es:Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add;AN000; + mov bx,ds ; ;AN000; + mov es:Read_Write_Relative.Buffer_Segment,bx ;Get segment ;AN000; + mov bx,data ;Point DS at parameter list ;AN000; + mov ds,bx ; ;AN000; + + assume ds:data,es:data + + mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to write ;AN000; + mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;AN000; + mov bx,offset Read_Write_Relative ; ;AN000; + mov cx,0FFFFh ;Write relative sector ;AN000; + INT 26h ;Do the write ;AN000; + pop dx ;Throw away flags on stack ;AN000; + pop ds ; ;AN000; + pop es ; ;AN000; + pop bp ; ;AN000; + pop di ; ;AN000; + pop si ; ;AN000; + pop dx ;Restore registers ;AN000; + pop cx ; ;AN000; + pop bx ; ;AN000; + ret ; ;AN000; + +Write_Disk endp ; ;AN000; + +;========================================================================= +; Calc_Total_Addressible_Space : Calculate the total space that is +; addressible on the the disk by DOS. +; +; Inputs : none +; +; Outputs : Fdsksiz - Size in bytes of the disk +;========================================================================= + +Procedure Calc_Total_Addressible_Space ;an013; dms; + + push ax ;an013; dms;save affected regs + push dx ;an013; dms; + push bx ;an013; dms; + + call Get_Free_Space ;an013; dms;get free disk space + + push bx ;an013; dms;save avail. cluster + push dx ;an013; dms;save total. cluster + + mov ax,dx ;an013; dms;get total clusters + + xor bx,bx ;an013; dms;clear bx + xor cx,cx ;an013; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an013; dms;get total sectors + call Multiply_32_Bits ;an013; dms;multiply + + xor cx,cx ;an013; dms;clear cx + mov cx,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an013; dms;get total bytes + call Multiply_32_Bits ;an013; dms; multiply + + mov word ptr Fdsksiz,ax ;an013; dms;save high word + mov word ptr Fdsksiz+2,bx ;an013; dms;save low word + + pop dx ;an000; dms;get total clusters + pop bx ;an000; dms;get avail clusters + + mov ax,dx ;an013; dms;get total clusters + sub ax,bx ;an013; dms;get bad clusters + + xor bx,bx ;an013; dms;clear bx + xor cx,cx ;an013; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an013; dms;get total sectors + call Multiply_32_Bits ;an013; dms;multiply + + xor cx,cx ;an013; dms;clear cx + mov cx,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an013; dms;get total bytes + call Multiply_32_Bits ;an013; dms; multiply + + sub ax,word ptr syssiz ;an013; dms;account for system + sbb bx,word ptr syssiz+2 ;an013; dms;size + + mov word ptr Badsiz,ax ;an013; dms;save high word + mov word ptr Badsiz+2,bx ;an013; dms;save low word + + pop bx ;an013; dms; + pop dx ;an013; dms;restore regs + pop ax ;an013; dms; + + ret ;an013; dms; + +Calc_Total_Addressible_Space endp ;an013; dms; + + +;========================================================================= +; Get_Free_Space : Get the free space on the disk. +; +; Inputs : none +; +; Outputs : BX - Available space in clusters +; DX - Total space in clusters +;========================================================================= + +Procedure Get_Free_Space ;an013; dms; + + xor ax,ax ;an013; dms;clear ax + mov ah,36h ;an013; dms;Get disk free space + mov dl,driveletter ;an013; dms;get drive letter + sub dl,"A" ;an013; dms;get 0 based number + inc dl ;an013; dms;make it 1 based + int 21h ;an013; dms; + ret ;an013; dms; + +Get_Free_Space endp ;an013; dms; + +;========================================================================= +; Calc_System_Space : This routine calculates the space occupied by +; the system on the disk. +; +; Inputs : DOS.FileSizeInBytes +; BIOS.FileSizeInBytes +; Command.FileSizeInBytes +; +; Outputs : SysSiz - Size of the system +;========================================================================= + +Procedure Calc_System_Space ;an013; dms; + + push ax ;an013; dms;save regs + push dx ;an013; dms; + + mov word ptr SysSiz+0,00h ;an013; dms;clear variable + mov word ptr SysSiz+2,00h ;an013; dms; + + mov ax,word ptr [DOS.FileSizeInBytes+0] ;an013; dms;get low word + mov dx,word ptr [DOS.FileSizeInBytes+2] ;an013; dms;get high word + call AddToSystemSize ;an013; dms;add in values + + mov ax,word ptr [BIOS.FileSizeInBytes+0] ;an013; dms;get bios size + mov dx,word ptr [BIOS.FileSizeInBytes+2] ;an013; dms; + call AddToSystemSize ;an013; dms;add in values + + mov ax,word ptr [COMMAND.FileSizeInBytes+0] ;an013; dms;get command size + mov dx,word ptr [COMMAND.FileSizeInBytes+2] ;an013; dms; + call AddToSystemSize ;an013; dms;add in values + + pop dx ;an013; dms;restore regs + pop ax ;an013; dms; + + ret ;an013; dms; + +Calc_System_Space endp ;an013; dms; + + + +code ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/FORMAT/FORSWTCH.INC b/v4.0/src/CMD/FORMAT/FORSWTCH.INC new file mode 100644 index 0000000..a795395 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/FORSWTCH.INC @@ -0,0 +1,38 @@ +; +;FORMAT Pre-defined switches + SWITCH_S EQU 0001h ; System transfer + SWITCH_V EQU 0002h ; Volume ID prompt + SWITCH_BACKUP EQU 0004h + SWITCH_C EQU 0008h + SWITCH_T EQU 0010h + SWITCH_N EQU 0020h + SWITCH_1 EQU 0040h + SWITCH_4 EQU 0080h + SWITCH_8 EQU 0100h + SWITCH_B EQU 0200h + SWITCH_SELECT EQU 0400h + SWITCH_AUTOTEST EQU 0800h + SWITCH_F EQU 1000h + SWITCH_FS EQU 2000h + +IF ShipDisk + + SWITCH_Z EQU 4000h ;an000; dms;1 sector/cluster switch + +ENDIF + +; +; The following is a list of equates to define each IBM defined diskette size +; for use with the /F switch + + +Size_160 equ 0001h ;Flag settings for size switch ;AN000; +Size_180 equ 0002h ; ;AN000; +Size_320 equ 0004h ; ;AN000; +Size_360 equ 0008h ; ;AN000; +Size_720 equ 0010h ; ;AN000; +Size_1200 equ 0020h ; ;AN000; +Size_1440 equ 0040h ; ;AN000; + + + diff --git a/v4.0/src/CMD/FORMAT/MAKEFILE b/v4.0/src/CMD/FORMAT/MAKEFILE new file mode 100644 index 0000000..17742c4 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/MAKEFILE @@ -0,0 +1,55 @@ +#************************ makefile for cmd\format ************************* + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h +boot =..\..\boot + +# +####################### dependencies begin here. ######################### +# + +all: format.com + +boot.cl1: + copy $(boot)\boot.cl1 + +format.ctl: format.skl $(msg)\$(COUNTRY).msg + +display.obj: display.asm forequ.inc formsg.inc formacro.inc makefile \ + format.ctl format.cl1 format.cl2 format.cla $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm \ + format.clb format.clc formacro.inc + +forexec.obj: forexec.asm forequ.inc makefile $(inc)\syscall.inc \ + formacro.inc + +forlabel.obj: forlabel.asm forequ.inc formacro.inc makefile \ + $(inc)\syscall.inc $(inc)\ioctl.inc $(inc)\dosmac.inc \ + forswtch.inc + +format.obj: format.asm $(inc)\dosmac.inc $(inc)\bpb.inc \ + $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\cpmfcb.inc $(inc)\pdb.inc makefile \ + $(inc)\error.inc $(inc)\syscall.inc $(inc)\ioctl.inc \ + forequ.inc formacro.inc forswtch.inc + +forinit.obj: forinit.asm forequ.inc formacro.inc makefile \ + $(inc)\syscall.inc $(inc)\ioctl.inc forparse.inc \ + forswtch.inc $(inc)\parse.asm $(inc)\psdata.inc + +msfor.obj: msfor.asm $(inc)\dosmac.inc $(inc)\syscall.inc $(inc)\bpb.inc \ + $(inc)\dirent.inc boot.cl1 $(inc)\ioctl.inc \ + $(inc)\boot.inc $(inc)\boot11.inc makefile \ + $(inc)\bootform.inc filesize.inc forequ.inc formacro.inc forswtch.inc + +forproc.obj: forproc.asm $(inc)\syscall.inc makefile forequ.inc \ + formacro.inc forswtch.inc + + +format.com: format.obj forproc.obj msfor.obj forexec.obj display.obj \ + forinit.obj forlabel.obj + link @format.lnk + convert format.exe + del format.exe diff --git a/v4.0/src/CMD/FORMAT/MSFOR.ASM b/v4.0/src/CMD/FORMAT/MSFOR.ASM new file mode 100644 index 0000000..6931115 --- /dev/null +++ b/v4.0/src/CMD/FORMAT/MSFOR.ASM @@ -0,0 +1,1936 @@ +; e forproc.sal= @(#)ibmfor.asm 1.28 85/10/15 + name OemFormatRoutines +; +;****************************************************************************** +;AN001 - ??? +;AN002 - D304 Modify Boot record structure for OS2 11/09/87 J.K. +;****************************************************************************** + +INCLUDE FORCHNG.INC +debug equ 0 +;------------------------------------------------------------------------------- +; Public for debugging only + + public CheckSwitches + public LastChanceToSaveIt + public WriteBootSector + public OemDone + public WriteBogusDos + public ConvertToOldDirectoryFormat + public SetPartitionTable + public ReadSector + public WriteSector + public SectorIO + public GetVolumeId + + public customBPBs + public NotSlashB + public NotSingleSided + public EndSwitchCheck + public WeCanNotIgnoreThisError + public HardDisk? + public BogusDos + public sys_mess_loop + public end_sys_loop + public DirectoryRead + public wrtdir + public DirectoryWritten + public FCBforVolumeIdSearch + public CopyVolumeId + public CompareVolumeIds + public BadVolumeId + + public boot2 + public boot + public scratchBuffer + public biosFilename + public dosFilename + public oldDrive + public oldVolumeId + public Read_Write_Relative + public Serial_Num_Low + public Serial_Num_High + public SizeMap + + public ptr_msgWhatIsVolumeId? + + public trackReadWritePacket + + public BPB81 + public BPB82 + public BPB91 + public BPB92 + +;------------------------------------------------------------------------------- + +data segment public para 'DATA' +data ends + +code segment public para 'CODE' + assume cs:code,ds:data + + Public AccessDisk + public CheckSwitches + public LastChanceToSaveIt + public OemDone + public BiosFile + public DosFile + +data segment public para 'DATA' + extrn AddToSystemSize:near + extrn currentCylinder:word + extrn currentHead:word + extrn deviceParameters:byte + extrn drive:byte + extrn driveLetter:byte + extrn fBigFAT:byte + extrn inbuff:byte + extrn switchmap:word + extrn Old_Dir:byte + extrn fLastChance:byte + extrn Fatal_Error:Byte + extrn Bios:Byte + extrn Dos:Byte + extrn Command:Byte + + extrn msgBad_T_N:byte + extrn msgBadVolumeId:byte + extrn msgBadPartitionTable:byte + extrn msgBootWriteError:byte + extrn msgDirectoryReadError:byte + extrn msgDirectoryWriteError:byte + extrn msgInvalidParameter:byte + extrn msgIncompatibleParameters:byte + extrn msgIncompatibleParametersForHardDisk:byte + extrn msgParametersNotSupportedByDrive:byte + extrn msgPartitionTableReadError:byte + extrn msgPartitionTableWriteError:byte + extrn msgWhatIsVolumeId?:byte + extrn NumSectors:word, TrackCnt:word + +IF DEBUG + extrn msgFormatBroken:byte +ENDIF + +data ends + + extrn PrintString:near + extrn std_printf:near + extrn crlf:near + extrn user_string:near + extrn Read_Disk:near + extrn Write_Disk:near + + +;------------------------------------------------------------------------------- +; Constants + +.xlist +INCLUDE DOSMAC.INC +INCLUDE FORMACRO.INC +INCLUDE FOREQU.INC +INCLUDE FORSWTCH.INC + +; This defines all the int 21H system calls +INCLUDE SYSCALL.INC + +; Limits + +INCLUDE filesize.inc + +;------------------------------------------------------------------------------- +; These are the data structures which we will need + +INCLUDE DIRENT.INC +INCLUDE ioctl.INC +INCLUDE version.inc + +.list + +;------------------------------------------------------------------------------- +; And this is the actual data +data segment public para 'DATA' + +Read_Write_Relative Relative_Sector_Buffer <> ; ;AN000; + + + IF IBMCOPYRIGHT +BiosFile db "x:\IBMBIO.COM", 0 +DosFile db "x:\IBMDOS.COM", 0 + ELSE +BiosFile db "x:\IO.SYS", 0 +DosFile db "x:\MSDOS.SYS", 0 + ENDIF + +Dummy_Label db "NO NAME " +Dummy_Label_Size dw 11 ;AN028 + +Serial_Num_Low dw 0 ; ;AN000; +Serial_Num_High dw 0 ; ;AN000; + +SizeMap db 0 ; ;AN000; + +trackReadWritePacket a_TrackReadWritePacket <> + + +; BIOS parameter blocks for various media +customBPBs label byte +BPB92 a_BPB <512, 2, 1, 2, 112, 2*9*40, 0fdH, 2, 9, 2, 0, 0, 0, 0> +BPB91 a_BPB <512, 1, 1, 2, 64, 1*9*40, 0fcH, 2, 9, 1, 0, 0, 0, 0> +BPB82 a_BPB <512, 2, 1, 2, 112, 2*8*40, 0ffH, 1, 8, 2, 0, 0, 0, 0> +BPB81 a_BPB <512, 1, 1, 2, 64, 1*8*40, 0feH, 1, 8, 1, 0, 0, 0, 0> +BPB720 a_BPB <512, 2, 1, 2, 112, 2*9*80, 0F9h, 3, 9, 2, 0, 0, 0, 0> + + + +boot2 db 0,0,0, "Boot 1.x" + db 512 - 11 dup(?) + +REORG2 LABEL BYTE + ORG BOOT2 + INCLUDE BOOT11.INC + ORG REORG2 + + + +INCLUDE BOOTFORM.INC + + +BOOT LABEL BYTE + INCLUDE BOOT.INC + +scratchBuffer db 512 dup(?) + +ptr_msgWhatIsVolumeId? dw offset msgWhatIsVolumeId? + dw offset driveLetter + + +FAT12_String db "FAT12 " +FAT16_String db "FAT16 " + +Media_ID_Buffer Media_ID <> + + +data ends +;------------------------------------------------------------------------------- +; AccessDisk: +; Called whenever a different disk is about to be accessed +; +; Input: +; al - drive letter (0=A, 1=B, ...) +; +; Output: +; none +AccessDisk proc near + + push ax ; save drive letter + mov bl,al ; Set up GENERIC IOCTL REQUEST preamble + inc bl + mov ax,(IOCTL SHL 8) + Set_Drv_Owner ; IOCTL function + int 21h + pop ax + return + +AccessDisk endp + +;------------------------------------------------------------------------------- +; CheckSwitches: +; Check switches against device parameters +; Use switches to modify device parameters +; +; Input: +; deviceParameters +; +; Output: +; deviceParameters may be modified +; Carry set if error +; +; +; /B <> /S +; /B/8 <> /V +; /1 or /8 <> /T/N +; + + +Public CHeckSwitches +CheckSwitches proc near + + +; Disallow /C + ;lea dx, msgInvalidParameter ;AC000; + test switchmap, SWITCH_C + jz CheckExcl + Message msgInvalidParameter ;AC000; +SwitchError: + ;call PrintString ;AC000; + stc + ret + +CheckExcl: + + test SwitchMap,Switch_F ;Specify size? ;AN001; +; $IF NZ ;Yes ;AN001; + JZ $$IF1 + test SwitchMap,(Switch_1+Switch_8+Switch_4+Switch_N+Switch_T) ;AN001; +; $IF NZ ;/F replaces above switches ;AN001; + JZ $$IF2 + Message msgIncompatibleParameters ;Print error ;AN001; + mov Fatal_Error,Yes ;Force exit ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN2 +$$IF2: + call Size_To_Switch ;Go set switches based ;AN001; +; $ENDIF ; on the size ;AN001; +$$EN2: +; $ENDIF ; ;AN001; +$$IF1: + cmp Fatal_Error,NO ; ;AN007; +; $IF E ; ;AN007; + JNE $$IF6 + call Check_Switch_8_B ; ;ac007 + call Check_T_N +; $ENDIF ; ;AN009; +$$IF6: + cmp Fatal_Error,Yes ; ;AN007; + jne ExclChkDone ; ;AN007; + stc ; ;AN007; + ret ; ;AN007; + +ExclChkDone: +; Patch the boot sector so that the boot strap loader knows what disk to +; boot from +; mov Boot.Boot_PhyDrv, 00H ;AC000; + mov Boot.EXT_PHYDRV, 00H ;AN00?; + + cmp deviceParameters.DP_DeviceType, DEV_HARDDISK + jne CheckFor5InchDrives + +; Formatting a hard disk so we must repatch the boot sector +; mov Boot.Boot_PhyDrv, 80H ;AC000; + mov Boot.EXT_PHYDRV, 80H ;AN00?; + test switchmap, not (SWITCH_S or SWITCH_V or SWITCH_Select or SWITCH_AUTOTEST or Switch_B) ;AN007; + jz SwitchesOkForHardDisk + + Message msgIncompatibleParametersForHardDisk ; ;AC000; + stc + ret + +; Before checking the Volume Id we need to verify that a valid one exists +; We assume that unless a valid boot sector exists on the target disk, no +; valid Volume Id can exist. + +SwitchesOkForHardDisk: + SaveReg + mov al,drive + mov cx,LogBootSect + xor dx,dx + lea bx,scratchBuffer ; ScratchBuffer := Absolute_Read_Disk( + ;INT 25h ; Logical_sec_1 ) + + ;Assume Dir for vol ID exists in 1st 32mb of partition + + mov Read_Write_Relative.Start_Sector_High,0 + call Read_Disk ; ;AC000; + ; on the stack. We throw them away + + jnc CheckSignature + stc + RestoreReg + ret + +CheckSignature: ; IF (Boot.Boot_Signature != aa55) + + mov ax, word ptr ScratchBuffer.Boot_Signature ;AC000; + cmp ax, 0aa55h ;Find a valid boot record? + RestoreReg + clc ;No, so no need to check label +; $IF Z ;No further checking needed ;AC000; + JNZ $$IF8 + test SwitchMap,(SWITCH_Select or SWITCH_AUTOTEST) ;Should we prompt for vol label?;AN000; +; $IF Z ;Yes, if /Select not entered ;AN000; + JNZ $$IF9 + call CheckVolumeId ;Go ask user for vol label ; ; +; $ELSE ;/Select entered ;AN000; + JMP SHORT $$EN9 +$$IF9: + clc ;CLC indicates passed label test;AN000; +; $ENDIF ; for the return ;AN000; +$$EN9: +; $ENDIF +$$IF8: + return + +Incomp_Message: ;an000; fix PTM 809 + + Message msgIncompatibleParameters ;an000; print incompatible parms + stc ;an000; signal error + return ;an000; return to caller + +Print_And_Return: + ;call PrintString ; ;AC000; + stc + return + + +CheckFor5InchDrives: + + ;If drive type is anything other than 48 or 96, then only /V/S/H/N/T allowed + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI + je Got96 + + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH + je Got48 + + xor ax,ax ;an000; dms;clear reg + or ax,(Switch_V or Switch_S or Switch_N or Switch_T or Switch_B) ;an000; dms;set up switch mask + or ax,(Switch_Backup or Switch_Select or Switch_Autotest) ;an000; dms; +IF ShipDisk + or ax,Switch_Z ;an000; dms; +ENDIF + not ax ;an000; dms; + test switchmap,ax ;an000; dms;invalid switch? + jz Goto_Got_BPB1 ;an000;dms;continue format + Message msgParametersNotSupportedByDrive ; ;AC000; + jmp short Print_And_Return + +Goto_Got_BPB1: + jmp Goto_Got_BPB + ; We have a 96tpi floppy drive + ; /4 allows just about all switches however, /1 requires /4 +Got96: +;;;DMS;;test switchmap, SWITCH_8 ;an000; If /8 we have an error +;;;DMS;;jnz Incomp_message ;an000; tell user error + + test switchmap, SWITCH_4 + jnz CheckForInterestingSwitches ;If /4 check /N/T/V/S + + test switchmap, SWITCH_1 ;If /1 and /4 check others + jz Got48 + + ;If only /1 with no /4, see if /N/T + test SwitchMap,(Switch_N or Switch_T) + jnz CheckForInterestingSwitches + + jmp Incomp_message ;an000; tell user error occurred + +Got48: + ;Ignore /4 for non-96tpi 5 1/4" drives + and switchmap, not SWITCH_4 + + ;Ignore /1 if drive has only one head and not /8 + cmp word ptr deviceParameters.DP_BPB.BPB_Heads, 1 + ja CheckForInterestingSwitches + test switchmap, SWITCH_8 + jz CheckForInterestingSwitches + and switchmap, not SWITCH_1 + + ;Are any interesting switches set? +CheckForInterestingSwitches: + test switchmap, not (SWITCH_V or SWITCH_S or Switch_Backup or SWITCH_SELECT or SWITCH_AUTOTEST or Switch_B) + jz Goto_EndSwitchCheck ;No, everything ok + + ;At this point there are switches other than /v/s/h + test SwitchMap,(SWITCH_N or SWITCH_T) + jz Use_48tpi ;Not /n/t, so must be /b/1/8/4 + + ;We've got /N/T, see if there are others + test SwitchMap, not (SWITCH_N or SWITCH_T or SWITCH_V or SWITCH_S or Switch_Backup or SWITCH_SELECT or SWITCH_AUTOTEST) + jz NT_Compatible ;Nope, all is well + + ;If 96tpi drive and /1 exists with /N/T, then okay, otherwise error + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI + jne Bad_NT_Combo + + test SwitchMap, not (SWITCH_1 or SWITCH_N or SWITCH_T or SWITCH_V) + jnz Bad_NT_Combo + test SwitchMap, not (SWITCH_S or Switch_Backup or SWITCH_SELECT or Switch_Autotest) + jz Goto_Got_BPB + +Bad_NT_Combo: + Message msgIncompatibleParameters ; ;AC000; + jmp Print_And_Return + +Goto_Got_BPB: + jmp Got_BPB_Ok ;Sleazy, but je won't reach it + +Goto_EndSwitchCheck: + jmp EndSwitchCheck + ;There is a problem with /N/T in that IBMBIO will default to a BPB with the + ;media byte set to F0 (other) if the /N/T combo is used for the format. This + ;will cause problems if we are creating a media that has an assigned media + ;byte, i.e. 160,180,320,360, or 720k media using /N/T. To avoid this problem, + ;if we detect a /N/T combo that would correspond to one of these medias, then + ; we will set things up using the /4/1/8 switches instead of the /N/T + ; MT - 7/17/86 PTR 33D0110 + + ; Combo's that we look for - 96tpi drive @ /T:40, /N:9 + ; 96tpi drive @ /T:40, /N:8 + ; + ; Look for this combo after we set everything up with the /T/N routine + ; 1.44 drive @ /T:80, /N:9 + +NT_Compatible: + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI + jne Goto_Got_BPB + + cmp TrackCnt,40 ;Look for 40 tracks + jne Got_BPB_Ok + + cmp NumSectors,9 ;9 sectors? + je Found_48tpi_Type + + cmp NumSectors,8 ;8 sectors? + jne Goto_Got_BPB ;Nope, different type, let it go thru + + or SwitchMap,SWITCH_8 ;Yes, turn on /8 switch + +Found_48tpi_Type: + and SwitchMap,not (SWITCH_N or SWITCH_T) ;Turn off /T/N + +;******End PTR fix + +; if we have a 96 tpi drive then we will be using it in 48 tpi mode +Use_48tpi: + cmp byte ptr deviceParameters.DP_DeviceType, DEV_5INCH96TPI + jne Not96tpi + + mov byte ptr deviceParameters.DP_MediaType, 1 + mov word ptr deviceParameters.DP_Cylinders, 40 +Not96tpi: + +; Since we know we are formatting in 48 tpi mode turn on /4 switch +; (We use this info in LastChanceToSaveIt) + or switchmap, SWITCH_4 + +; At this point we know that we will require a special BPB +; It will be one of: +; 0) 9 track 2 sides - if no switches +; 1) 9 track 1 side - if only /1 specified +; 2) 8 track 2 sides - if only /8 specified +; 3) 8 track 1 side - if /8 and /1 specified +; +Get_BPBs: +; ax is used to keep track of which of the above BPB's we want + xor ax, ax + +NotSlashB: + + test switchmap, SWITCH_1 + jz NotSingleSided + add ax, 1 +NotSingleSided: + + test switchmap, SWITCH_8 + jz Not8SectorsPerTrack + add ax, 2 +; /8 implies Old_Dir = TRUE + mov Old_Dir,TRUE +Not8SectorsPerTrack: + +; Ok now we know which BPB to use so lets move it to the device parameters + + mov bx, size a_BPB + mul bx + lea si, CustomBPBs + add si, ax + lea di, deviceParameters.DP_BPB + mov cx, size a_BPB + push ds + pop es + repnz movsb + +;***************************************************************** +;* /N/T DCR stuff. Possible flaw exists if we are dealing with a +;* HardDisk. If they support the "custom format" features for +;* Harddisks too, then CheckForInterestingSwitches should +;* consider /n/t UNinteresting, and instead of returning +;* after setting up the custom BPB we fall through and do our +;* Harddisk Check. +Got_BPB_OK: + test switchmap,SWITCH_N+SWITCH_T + jnz Setup_Stuff + jmp EndSwitchCheck +Setup_Stuff: +; Set up NumSectors and SectorsPerTrack entries correctly + test switchmap,SWITCH_N + jz No_Custom_Seclim + mov ax,word ptr NumSectors + mov DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax + jmp short Handle_Cyln +No_Custom_Seclim: + mov ax,deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov NumSectors,ax + +Handle_Cyln: + test switchmap,SWITCH_T + jz No_Custom_Cyln +; Set up TrackCnt and Cylinders entries correctly + mov ax,TrackCnt + mov DeviceParameters.DP_Cylinders,ax + jmp short Check_720 +No_Custom_Cyln: + mov ax,DeviceParameters.DP_Cylinders + mov TrackCnt,ax + +;****PTM P868 - Always making 3 1/2 media byte 0F0h. If 720, then set to +; 0F9h and use the DOS 3.20 BPB. Should check all drives +; at this point (Make sure not 5 inch just for future +; protection) +; We will use the known BPB info for 720 3 1/2 diskettes for +; this special case. All other new diskette media will use the +; calculations that follow Calc_Total for BPB info. +; Fix MT 11/12/86 + +Check_720: + + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI + je Calc_Total + + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH + je Calc_Total + + cmp TrackCnt,80 + jne Calc_Total + + cmp NumSectors,9 + jne Calc_Total + +; At this point we know we have a 3 1/2 720kb diskette to format. Use the +; built in BPB rather than the one handed to us by DOS, because the DOS one +; will be based on the default for that drive, and it can be different from +; what we used in DOS 3.20 for the 720's. Short sighted on our part to use +; 0F9h as the media byte, should have use 0F0h (OTHER) and then we wouldn't +; have this problem. + + SaveReg + + + mov cx,seg data ;Setup seg regs, just in case they ain't! + mov ds,cx + mov es,cx + + mov si,offset BPB720 ;Copy the BPB! + mov di,offset deviceParameters.DP_BPB + mov cx,size a_BPB + rep movsb + RestoreReg + jmp EndSwitchCheck + +;End PTM P868 fix **************************************** + +Calc_Total: + mov ax,NumSectors + mov bx,DeviceParameters.DP_BPB.BPB_Heads + mul bl ; AX = # of sectors * # of heads + mul TrackCnt ; DX:AX = Total Sectors + or dx,dx + jnz Got_BigTotalSectors + mov DeviceParameters.DP_BPB.BPB_TotalSectors,ax + jmp short Set_BPB +Got_BigTotalSectors: + mov DeviceParameters.DP_BPB.BPB_BigTotalSectors,ax + mov DeviceParameters.DP_BPB.BPB_BigTotalSectors+2,dx + push dx ; preserve dx for further use + xor dx,dx + mov DeviceParameters.DP_BPB.BPB_TotalSectors,dx + pop dx + +Set_BPB: +; We calculate the number of sectors required in a FAT. This is done as: +; # of FAT Sectors = TotalSectors / SectorsPerCluster * # of bytes in FAT to +; represent one cluster (i.e. 3/2) / BytesPerSector (i.e. 512) + xor bx,bx + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster + div bx ; DX:AX contains # of clusters +; now multiply by 3/2 + mov bx,3 + mul bx + mov bx,2 + div bx + xor dx,dx ; throw away modulo +; now divide by 512 + mov bx,512 + div bx +; dx:ax contains number of FAT sectors necessary + inc ax ; Go one higher + mov DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax + mov DeviceParameters.DP_MediaType,0 + mov DeviceParameters.DP_BPB.BPB_MediaDescriptor,Custom_Media + + +EndSwitchCheck: + clc + return + +CheckSwitches endp + +;***************************************************************************** +;Routine name: Size_To_Switch +;***************************************************************************** +; +;Description: Given the SizeMap field as input indicating the SIZE= value +; entered, validate that the specified size is valid for the +; drive, and if so, turn on the appropriate data fields and +; switches that would be turned on by the equivilent command line +; using only switchs. All defined DOS 4.00 sizes are hardcoded, +; in case a drive type of other is encountered that doesn't +; qualify as a DOS 4.00 defined drive. Exit with error message if +; unsupported drive. The switches will be setup for the CheckSwitches +; routine to sort out, using existing switch matrix logic. +; +;Called Procedures: Low_Density_Drive +; High_Capacity_Drive +; 720k_Drives +; Other_Drives +; +;Change History: Created 8/1/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; SwitchMap = appropriate Switch_?? values turned on +; TrackCnt, NumSectors set if Switch_T,Switch_N turned on +;***************************************************************************** + + +Procedure Size_To_Switch + + cmp SizeMap,0 ;Are there sizes entered? ;AN001; +; $IF NE ;Yes ;AN001; + JE $$IF13 + cmp deviceParameters.DP_DeviceType,DEV_HARDDISK ;AN000; ;AN001; +; $IF E ;No size for fixed disk ;AN001; + JNE $$IF14 + Message msgIncompatibleParametersForHardDisk ; ;AN001; +; $ELSE ;Diskette, see what type ;AN001; + JMP SHORT $$EN14 +$$IF14: + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH ; ;AN001; +; $IF E ;Found 180/360k drive ;AN001; + JNE $$IF16 + call Low_Density_Drive ;Go set switches ;AN001; +; $ELSE ;Check for 96TPI ;AN001; + JMP SHORT $$EN16 +$$IF16: + cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI ;AN001; ; +; $IF E ;Found it ;AN001; + JNE $$IF18 + call High_Capacity_Drive ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN18 +$$IF18: + cmp byte ptr deviceParameters.DP_DeviceType,DEV_3INCH720KB ;AN0001; +; $IF E ;Found 720k drive ;AN001; + JNE $$IF20 + call Small_Drives ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN20 +$$IF20: + cmp byte ptr deviceParameters.DP_DeviceType,DEV_OTHER ;AN001; +; $IF E ;Must be 1.44mb ;AN001; + JNE $$IF22 + call Other_Drives ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN22 +$$IF22: + Message msgParametersNotSupportedByDrive ; ;AN001; + mov Fatal_Error,Yes ; ;AN001; +; $ENDIF ; ;AN001; +$$EN22: +; $ENDIF ; ;AN001; +$$EN20: +; $ENDIF ; ;AN001; +$$EN18: +; $ENDIF ; ;AN001; +$$EN16: +; $ENDIF ; ;AN001; +$$EN14: +; $ENDIF ; ;AN001; +$$IF13: + cmp Fatal_Error,Yes ; ;AN001; +; $IF E ; ;AN001; + JNE $$IF30 + Message msgIncompatibleParameters ; ;AN001; +; $ENDIF ; ;AN001; +$$IF30: + + cmp deviceParameters.DP_DeviceType,DEV_HARDDISK ;an001; +; $if e ;an001; + JNE $$IF32 + mov Fatal_Error,Yes ;an001; +; $endif ;an001; +$$IF32: + + and SwitchMap,not Switch_F ;Turn off /F so doesn't effect ;AN001; + ret ; following logic ;AN001; + +Size_To_Switch endp + +;***************************************************************************** +;Routine name: High_Capacity_Drive +;***************************************************************************** +; +;Description: See if 1.2mb diskette, or one of the other 5 1/4 sizes. Turn +; on /4 if 360k or lower +; +;Called Procedures: Low_Density_Drive +; +;Change History: Created 8/1/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; SwitchMap = Switch_4 if 360k or lowere +;***************************************************************************** + +Procedure High_Capacity_Drive ; + + test SizeMap,Size_1200 ;1.2mb diskette? ;AN001; +; $IF Z ;Nope ;AN001; + JNZ $$IF34 + call Low_Density_Drive ;Check for /4 valid types ;AN001; + cmp Fatal_Error, No ;Find 160/180/320/360k? ;AN001; +; $IF E ;Yes ;AN001; + JNE $$IF35 + or SwitchMap,Switch_4 ;Turn on /4 switch ;AN001; +; $ELSE ;Did not find valid size ;AN001; + JMP SHORT $$EN35 +$$IF35: + mov Fatal_Error,Yes ;Indicate invalid device ;AN001; +; $ENDIF ; ;AN001; +$$EN35: +; $ENDIF ; ;AN001; +$$IF34: + ret ; ;AN001; + +High_Capacity_Drive endp + +;***************************************************************************** +;Routine name: Low_Density_Drive +;***************************************************************************** +; +;Description: See if 360k diskete or one of the other 5 1/4 sizes. Turn +; on the /1/8 switch to match sizes +; +;Called Procedures: Low_Density_Drive +; +;Change History: Created 8/1/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; SwitchMap = Switch_1, Switch_8 to define size +; +; 360k = No switch +; 320k = Switch_8 +; 180k = Switch_1 +; 160k = Switch_1 + Switch_8 +;***************************************************************************** + + +Procedure Low_Density_Drive ; ;AN000; + ; + test SizeMap,Size_160 ; ;AN001; +; $IF NZ ; ;AN001; + JZ $$IF39 + or SwitchMap,Switch_1+Switch_8 ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN39 +$$IF39: + test SizeMap,Size_180 ; ;AN001; +; $IF NZ ; ;AN001; + JZ $$IF41 + or SwitchMap,Switch_1 ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN41 +$$IF41: + test SizeMap,Size_320 ; ;AN001; +; $IF NZ ; ;AN001; + JZ $$IF43 + or SwitchMap,Switch_8 ; ;AN001; +; $ELSE ; ;AN001; + JMP SHORT $$EN43 +$$IF43: + test SizeMap,Size_360 ; ;AN001; +; $IF Z ;None of the above, not valid ;AN001; + JNZ $$IF45 + mov Fatal_Error,Yes ; ;AN001; +; $ENDIF ; ;AN001; +$$IF45: +; $ENDIF ; ;AN001; +$$EN43: +; $ENDIF ; ;AN001; +$$EN41: +; $ENDIF ; ;AN001; +$$EN39: + ret ; ;AN001; + +Low_Density_Drive endp + +;***************************************************************************** +;Routine name: Small_Drives +;***************************************************************************** +; +;Description: See if 720k media in 720 drive, set up /T/N if so, otherwise +; error +; +;Called Procedures: None +; +;Change History: Created 8/1/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; SwitchMap +; TrackCnt +; NumSectors +; 720k = /T:80 /N:9 +;***************************************************************************** + +Procedure Small_Drives ; ;AN000; + + test SizeMap,Size_720 ;Ask for 720k? ;AN001; +; $IF Z ;Nope, thats all drive can do ;AN001; + JNZ $$IF50 + mov Fatal_Error,Yes ;Indicate error ;AN001; +; $ENDIF ; ;AN001; +$$IF50: + ret ; ;AN001; + +Small_Drives endp + + +;***************************************************************************** +;Routine name: Other_Drives +;***************************************************************************** +; +;Description: See if 1.44 media or 720k media, setup /t/n, otherwise error +; +;Called Procedures: Small_Drives +; +;Change History: Created 8/1/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +; SwitchMap +; TrackCnt +; NumSectors +; 720k = /T:80 /N:9 +;***************************************************************************** + +Procedure Other_Drives ; ;AN001; + + test SizeMap,Size_1440 ;Ask for 1.44mb diskette? ;AN001; +; $IF Z ;Nope ;AN001; + JNZ $$IF52 + call Small_Drives ;See if 720k ;AN001; + cmp Fatal_Error,No ;Fatal_error=Yes if not ;AN001; +; $IF E ;Got 720k ;AN001; + JNE $$IF53 + or SwitchMap,Switch_T+Switch_N ;Turn on /T:80 /N:9 ;AN001; + mov TrackCnt,80 ; ;AN001; + mov NumSectors,9 ; ;AN001; +; $ENDIF ; ;AN001; +$$IF53: +; $ELSE ;Asked for 1.44mb ;AN001; + JMP SHORT $$EN52 +$$IF52: + or SwitchMap,Switch_T+Switch_N ;Turn on /T:80 /N:18; ;AN001; + mov TrackCnt,80 ;This will protect SIZE=1440 ;AN001; + mov NumSectors,18 ; from non-standard drives with ;AN001; +; $ENDIF ; type of 'other' ;AN001; +$$EN52: + ret ; ;AN001; + +Other_Drives endp + + +;***************************************************************************** +;Routine name:Check_T_N +;***************************************************************************** +; +;Description: Make sure than if /T is entered, /N is also entered +; +;Called Procedures: None +; +;Change History: Created 8/23/87 MT +; +;Input: SizeMap +; Fatal_Error = NO +; +;Output: Fatal_Error = YES/NO +;***************************************************************************** + +Procedure Check_T_N + + test SwitchMap,Switch_N ;Make sure /T entered if /N ;AN009; +; $IF NZ,AND ; ;AN009; + JZ $$IF57 + test SwitchMap,Switch_T ; ;AN009; +; $IF Z ; ;AN009; + JNZ $$IF57 + Message msgBad_T_N ;It wasn't, so barf ;AN009; + mov Fatal_Error,Yes ;Indicate error ;AN009; +; $ELSE ; ;AN009; + JMP SHORT $$EN57 +$$IF57: + test SwitchMap,Switch_T ;Make sure /N entered if /T ;AN009; +; $IF NZ,AND ; ;AN009; + JZ $$IF59 + test SwitchMap,Switch_N ; ;AN009; +; $IF Z ;It wasn't, so also barf ;AN009; + JNZ $$IF59 + Message msgBad_T_N ; ;AN009; + mov Fatal_Error,Yes ;Indicate error ;AN009; +; $ENDIF ; ;AN009; +$$IF59: +; $ENDIF ; ;AN009; +$$EN57: + ret + +Check_T_N endp + + + +;------------------------------------------------------------------------------- +; LastChanceToSaveIt: +; This routine is called when an error is detected in DiskFormat. +; If it returns with carry not set then DiskFormat is restarted. +; It gives the oem one last chance to try formatting differently. +; fLastChance gets set Then to prevent multiple prompts from being +; issued for the same diskette. +; +; Algorithm: +; IF (error_loc == Track_0_Head_1) & +; ( Device_type < 96TPI ) +; THEN +; fLastChance := TRUE +; try formatting 48TPI_Single_Sided +; ELSE return ERROR +; +LastChanceToSaveIt proc near + + cmp currentCylinder, 0 + jne WeCanNotIgnoreThisError + cmp currentHead, 1 + jne WeCanNotIgnoreThisError + + cmp deviceParameters.DP_DeviceType, DEV_5INCH + ja WeCanNotIgnoreThisError + + mov fLastChance, TRUE + + or switchmap, SWITCH_1 + call CheckSwitches + clc + ret + +WeCanNotIgnoreThisError: + stc + ret + +LastChanceToSaveIt endp + +;------------------------------------------------------------------------------- + + +;***************************************************************************** +;Routine name WriteBootSector +;***************************************************************************** +; +;DescriptioN: Copy EBPB information to boot record provided by Get recommended +; BPB, write out boot record, error +; if can write it, then fill in new fields (id, etc..). The volume +; label will not be added at this time, but will be set by the +; create volume label call later. +; +;Called Procedures: Message (macro) +; +;Change History: Created 4/20/87 MT +; +;Input: DeviceParameters.DP_BPB +; +;Output: CY clear if ok +; CY set if error writing boot or media_id info +; +;Psuedocode +;---------- +; +; Copy recommended EBPB information to canned boot record +; Write boot record out (INT 26h) +; IF error +; Display boot error message +; stc +; ELSE +; Compute serial id and put into field (CALL Create_Serial_ID) +; Point at 'FAT_12' string for file system type +; IF fBIGFat ;16 bit FAT +; Point at 'FAT_16' for file system type +; ENDIF +; Copy file system string into media_id field +; Write info to boot (INT 21h AX=440Dh, CX=0843h SET MEDIA_ID) +; IF error (CY set) +; Display boot error message +; stc +; ELSE +; clc +; ENDIF +; ENDIF +; ret +;***************************************************************************** + +Procedure WriteBootSector ; ;AN000; + + lea si, deviceParameters.DP_BPB ;Copy EBPB to the boot record ; + lea di, Boot.EXT_BOOT_BPB ; " " " " ;AC000: + mov cx, size EXT_BPB_INFO ; " " " " ;AC000: + push ds ;Set ES=DS (data segment) ; ; + pop es ; " " " " ; ; + repnz movsb ;Do the copy ; ; + ;Write out the boot record ; ; + mov al, drive ;Get drive letter ; ; + mov cx, 1 ;Specify 1 sector ; ; + xor dx, dx ;Logical sector 0 ; ; + lea bx, boot ;Point at boot record ; ; +;Boot record in 1st 32mb of partition + mov Read_Write_Relative.Start_Sector_High,0 ; ;AN000; + call Write_Disk ; ;AC000; +; $IF C ;Error on write ;AC000; + JNC $$IF62 + Message msgBootWriteError ;Print error ; ; + stc ;CY=1 means error ; ; +; $ELSE ;Good write of boot record! ;AN000; + JMP SHORT $$EN62 +$$IF62: + mov cx,Dummy_Label_Size ;Put in dummy volume label size ;ac026;ac028; + lea si,Dummy_Label ; " " " " ;AN000; + lea di,Media_ID_Buffer.Media_ID_Volume_Label ; " " " " ;AN000; + rep movsb ; " " " " ;AN000; + call Create_Serial_ID ;Go create unique ID number ;AN000; + lea si,FAT12_String ;Assume 12 bit FAT ;AN000; + cmp fBigFAT,TRUE ;Is it? ;AN000; +; $IF E ;Not if fBigFat is set.... ;AN000; + JNE $$IF64 + lea si,FAT16_String ;Got 16 bit FAT ;AN000; +; $ENDIF ; ;AN000; +$$IF64: + ;Copy file system string ; ; + mov cx,8 ; to buffer ;AN000; + lea di,Media_ID_Buffer.Media_ID_File_System ; " " ;AN000; + repnz movsb ; " " " " ;AN000; + mov al,Generic_IOCtl ;Generic IOCtl call ;AN000; + mov bl,Drive ;Get drive ;AN000; + inc bl ;Make it 1 based ;AN000; + xor bh,bh ;Set bh=0 ;AN000; + mov ch,RawIO ;Set Media ID call ;AN000; + mov cl,Set_Media_ID + mov dx,offset Media_ID_Buffer ;Point at buffer ;AN000; + DOS_Call IOCtl ;Do function call ;AN000; +; $IF C ;Error ? (Write or old boot rec);AN000; + JNC $$IF66 + Message msgBootWriteError ;Indicate we couldn't write it ;AN000; + stc ;CY=1 for error return ;AN000; +; $ELSE ;Set Media ID okay ;AN000; + JMP SHORT $$EN66 +$$IF66: + clc ;CY=0 for good return ;AN000; +; $ENDIF ; ;AN000; +$$EN66: +; $ENDIF ; ;AN000; +$$EN62: + ret ; ;AN000; + +WriteBootSector endp ; ;AN000; + + +;***************************************************************************** +;Routine name Create_Serial_ID +;***************************************************************************** +; +;DescriptioN&gml Create unique 32 bit serial number by getting current date and +; time and then scrambling it around. +; +;Called Procedures: Message (macro) +; +;Change History&gml Created 4/20/87 MT +; +;Input&gml None +; +;Output&gml Media_ID_Buffer.Serial_Number = set +; AX,CX,DX destroyed +; Serial_Num_Low/High = Serial number generated +; +;Psuedocode +;---------- +; +; Get date (INT 21h, AH=2Bh) +; Get time (INT 21h, AH=2Ch) +; Serial_ID+0 = DX reg date + DX reg time +; Serial_ID+2 = CX reg date + CX reg time +; Serial_Num_Low = Serial_ID+2 +; Serial_Num_High = Serial_ID+0 +; ret +;***************************************************************************** + +Procedure Create_Serial_ID ; ;AN000; + + DOS_Call Get_Date ;Get date from DOS ;AN000; + push cx ;Save results ;AN000; + push dx ; ;AN000; + DOS_Call Get_Time ;Get_Time ;AN000; + mov ax,dx ;Scramble it ;AN000; + pop dx ; ;AN000; + add ax,dx ; ;AN000; + mov word ptr Media_ID_Buffer.Media_ID_Serial_Number+2,ax ; ;AC004; + mov Serial_Num_Low,ax ; ;AN000; + mov ax,cx ; ;AN000; + pop cx ; ;AN000; + add ax,cx ; ;AN000; + mov word ptr Media_ID_Buffer.Media_ID_Serial_Number,ax ; ;AC004; + mov Serial_Num_High,ax ; ;AN000; + ret ; ;AN000; + +Create_Serial_ID endp ; ;AN000; + +;------------------------------------------------------------------------------- + +; OemDone: +; +OemDone proc near + +; if /b write out a fake dos & bios + test switchmap, SWITCH_B + jz Switch8? + call WriteBogusDos + retc + +Switch8?: + test switchmap, SWITCH_8 + jz HardDisk? + call ConvertToOldDirectoryFormat + retc + +HardDisk?: + cmp deviceParameters.DP_DeviceType, DEV_HARDDISK + clc + retnz + call SetPartitionTable + + return + +OemDone endp + +;------------------------------------------------------------------------------ + +data segment public para 'DATA' + + if IBMCOPYRIGHT +biosFilename db "x:\ibmbio.com",0 +dosFilename db "x:\ibmdos.com",0 + else +biosFilename db "x:\io.sys",0 +dosFilename db "x:\msdos.sys",0 + endif + +data ends + +; simple code to stuff bogus dos in old-style diskette. + +BogusDos: + push cs + pop ds + mov al,20h + out 20h,al ; turn on the timer so the disk motor + mov si,mesofs ; shuts off +sys_mess_loop: + lodsb +if ibmcopyright +end_sys_loop: +endif + or al,al + jz end_sys_loop + mov ah,14 + mov bx,7 + int 16 + jmp sys_mess_loop +if not ibmcopyright +end_sys_loop: + xor ah, ah ; get next char function + int 16h ; call keyboard services + int 19h ; reboot +endif + + include BOOT.CL1 +mesofs equ sysmsg - BogusDos + +WriteBogusDos proc near + + mov al,driveLetter + mov biosFilename,al + mov dosFilename,al + mov cx, ATTR_HIDDEN or ATTR_SYSTEM + lea dx, biosFilename + mov ah,CREAT + int 21h + mov bx,ax + mov cx, BIOS_SIZE + push ds + push cs + pop ds + assume ds:code + lea dx, BogusDos + mov ah,WRITE + int 21h + pop ds + assume ds:data + mov ah,CLOSE + int 21h + mov cx, ATTR_HIDDEN or ATTR_SYSTEM + lea dx, dosFilename + mov ah,CREAT + int 21h + mov bx,ax + mov cx, DOS_SIZE + lea dx, BogusDos + mov ah,WRITE + int 21h + mov ah,CLOSE + int 21h +; Comunicate system size to the main format program + mov word ptr DOS.FileSizeInBytes,DOS_SIZE ;an000; dms;get size of DOS + mov word ptr DOS.FileSizeInBytes+2,00h ;an000; dms; + + xor dx,dx + mov ax,DOS_SIZE + call AddToSystemSize + + mov word ptr Bios.FileSizeInBytes,BIOS_SIZE ;an000; dms;get size of BIOS + mov word ptr Bios.FileSizeInBytes+2,00h ;an000; dms; + + xor dx,dx + mov ax,BIOS_SIZE + call AddToSystemSize + + clc + return + +WriteBogusDos endp + +;------------------------------------------------------------------------------- + +ConvertToOldDirectoryFormat proc near + +; +; convert to 1.1 directory +; + mov al,drive ; Get 1st sector of directory + mov cx,1 ; 1.1 directory always starts on + mov dx,3 ; sector 3 + lea bx,scratchBuffer +;Root Directory always in 1st 32mb of partition + mov Read_Write_Relative.Start_Sector_High,0 ; ;AN000; + call Read_Disk ; ;AC000; + jnc DirectoryRead + Message msgDirectoryReadError ; ;AC000; + stc + ret +DirectoryRead: + +; fix attribute of ibmbio and ibmdos + lea bx,scratchBuffer + mov byte ptr [bx].dir_attr, ATTR_HIDDEN or ATTR_SYSTEM + add bx, size dir_entry + mov byte ptr [bx].dir_attr, ATTR_HIDDEN or ATTR_SYSTEM + +wrtdir: + mov al,[drive] ; write out the directory + cbw + mov cx,1 + mov dx,3 + lea bx,scratchBuffer +;Root Directory always in 1st 32mb of partition + mov Read_Write_Relative.Start_Sector_High,0 ; ;AN000; + call Write_Disk ; ;AC000; + jnc DirectoryWritten + Message msgDirectoryWriteError ; ;AC000; + stc + ret +DirectoryWritten: + + test switchmap, SWITCH_S ; Was system requested? + retnz ; yes, don't write old boot sector + mov al,drive + cbw + mov bx,offset boot2 ; no, write old boot sector + cmp deviceParameters.DP_BPB.BPB_Heads, 1 + je bootset8 + mov word ptr [bx+3],0103h ; start address for double sided drives +bootset8: + mov cx,1 + xor dx,dx +;Boot record in 1st 32mb of partition + mov Read_Write_Relative.Start_Sector_High,0 ; ;AN000; + call Write_Disk ; ;AC000; + retnc + + Message msgBootWriteError ; ;AC000; + stc + ret + +ConvertToOldDirectoryFormat endp + +;------------------------------------------------------------------------------- + +a_PartitionTableEntry struc +BootInd db ? +BegHead db ? +BegSector db ? +BegCylinder db ? +SysInd db ? +EndHead db ? +EndSector db ? +EndCylinder db ? +RelSec dd ? +CSec dd ? +a_PartitionTableEntry ends + +; structure of the IBM hard disk boot sector: +IBMBoot STRUC + db 512 - (4*size a_PartitionTableEntry + 2) dup(?) +PartitionTable db 4*size a_PartitionTableEntry dup(?) +Signature dw ? +IBMBoot ENDS + + +;***************************************************************************** +;Routine name: SetPartitionTable +;***************************************************************************** +; +;Description: Find location for DOS partition in partition table, get the +; correct system indicator byte, and write it out. If can not +; read/write boot record or can't find DOS partition, display +; error +; +;Called Procedures: Message (macro) +; Determine_Partition_Type +; ReadSector +; WriteSector +; +;Change History: Created 4/20/87 MT +; +;Input: None +; +;Output: CY set if error +; +;Psuedocode +;---------- +; +; Read the partition table (Call ReadSector) +; IF ok +; IF boot signature of 55AAh +; Point at system partition table +; SEARCH +; Assume DOS found +; IF System_Indicator <> 1,AND +; IF System_Indicator <> 4,AND +; IF System_Indicator <> 6 +; STC (DOS not found) +; ELSE +; CLC +; ENDIF +; EXITIF DOS found (CLC) +; CALL Determine_Partition_Type +; Write the partition table (CALL WriteSector) +; IF error +; Display boot write error message +; stc +; ELSE +; clc +; ENDIF +; ORELSE +; Point at next partition entry (add 16 to partition table ptr) +; ENDLOOP if checked all 4 partition entries +; Display Bad partition table message +; stc +; ENDSRCH +; ELSE invalid boot record +; Display Bad partition table message +; stc +; ENDIF +; ELSE error +; Display Partition table error +; stc +; ENDIF +; ret +;***************************************************************************** + +Procedure SetPartitionTable ; ;AN000; + + xor ax, ax ;Head ;AC000; + xor bx, bx ;Cylinder ;AC000; + xor cx, cx ;Sector ;AC000; + lea dx, boot2 ;Never use 1.x boot on hardfile,; ; + call ReadSector ;this will use space as buffer ; ; +; $IF NC ;If read okay ;AN000; + JC $$IF70 + cmp Boot2.Boot_Signature,Boot_ID ; ;AC000; +; $IF E ;Does signature match? ;AN000; + JNE $$IF71 + lea bx, boot2.PartitionTable ;Yes, point at partition table ;AN000; +; $SEARCH ;Look for DOS partition ;AN000; +$$DO72: + cmp [bx].sysind,FAT12_File_System ; ;AC000; +; $IF NE,AND ; ;AN000; + JE $$IF73 + cmp [bx].sysind,FAT16_File_System ; ;AC000; +; $IF NE,AND ; ;AN000; + JE $$IF73 + cmp [bx].sysind,New_File_System ; ;AC000; +; $IF NE ; ;AN000; + JE $$IF73 + stc ;We didn't find partition ;AN000; +; $ELSE ; ;AN000; + JMP SHORT $$EN73 +$$IF73: + clc ;Indicate found partition ;AN000; +; $ENDIF ; ;AN000; +$$EN73: +; $EXITIF NC ;Get correct id for it ;AN000; + JC $$IF72 + CALL Determine_Partition_Type ; ;AN000; + mov ax, 0 ;Head ; ; + mov bx, 0 ;Cylinder ; ; + mov cx, 0 ;Sector ; ; + lea dx, boot2 ; ; ; + call WriteSector ;Write out partition table ; ; +; $IF C ;Error writing boot record ;AN000; + JNC $$IF77 + MESSAGE msgPartitionTableWriteError ; ;AC000; + stc ;Set CY to indicate error ; ; +; $ELSE ; ;AN000; + JMP SHORT $$EN77 +$$IF77: + clc ;No error means no CY ; ; +; $ENDIF ; ;AN000; +$$EN77: +; $ORELSE ; ;AN000; + JMP SHORT $$SR72 +$$IF72: + add bx,size a_PartitionTableEntry ; ; ; + cmp bx,(offset Boot2.PartitionTable)+4*size a_PartitionTableEntry ; ; +; $ENDLOOP ;Checked all 4 partition entries;AN000; + JMP SHORT $$DO72 + MESSAGE msgBadPartitionTable ;Tell user bad table ;AC000; + stc ;Set CY for exit ; ; +; $ENDSRCH ; ;AN000; +$$SR72: +; $ELSE ;Invalid boot record ;AN000; + JMP SHORT $$EN71 +$$IF71: + MESSAGE msgBadPartitionTable ; ;AC000; + stc ;Set CY for error return ; ; +; $ENDIF ; ;AN000; +$$EN71: +; $ELSE ;Couldn't read boot record ;AN000; + JMP SHORT $$EN70 +$$IF70: + MESSAGE msgPartitionTableReadError ; ;AC000; + stc ;Set CY for error return ; ; +; $ENDIF ; ;AN000; +$$EN70: + ret ; ; ; + +SetPartitionTable endp ; ;AN000; + +;***************************************************************************** +;Routine name: Determine_Partition_Type +;***************************************************************************** +; +;DescriptioN: Set the system indicator field to its correct value as +; determined by the following rules: +; +; - Set SysInd = 01h if partition or logical drive size is < 10mb +; and completely contained within the first 32mb of DASD. +; - Set SysInd = 04h if partition or logical drive size is >10mb, +; <32mb, and completely contained within the first 32mb of DASD +; - Set SysInd to 06h if partition or logical drive size is > 32mb, +; +;Called Procedures: Message (macro) +; +;Change History: Created 3/18/87 MT +; +;Input: BX has offset of partition table entry +; fBigFAT = TRUE if 16bit FAT +; +;Output: BX.SysInd = correct partition system indicator value (1,4,6) +; +;Psuedocode +;---------- +; Add partition start location to length of partition +; IF end > 32mb +; BX.SysInd = 6 +; ELSE +; IF fBigFat +; BX.SysInd = 4 +; ELSE +; BX.SysInd = 1 +; ENDIF +; ret +;***************************************************************************** + +Procedure Determine_Partition_Type ;AN000; + + mov dx,word ptr [bx].Csec+2 ;an000; dms;Get high word of sector count + cmp dx,0 ;AN000; ;> 32Mb? +; $IF NE ;AN000; ;yes + JE $$IF87 + mov [BX].SysInd,New_File_System ;AN000; ;type 6 +; $ELSE ;AN000; + JMP SHORT $$EN87 +$$IF87: + call Calc_Total_Sectors_For_Partition ;an000; dms;returns DX:AX total sectors + cmp DeviceParameters.DP_BPB.BPB_HiddenSectors[+2],0 ;an000; dms;> 32Mb? +; $if ne ;an000; dms;yes + JE $$IF89 + mov [bx].SysInd,New_File_System ;an000; dms; type 6 +; $else ;an000; dms; + JMP SHORT $$EN89 +$$IF89: + cmp dx,0 ;an000; dms; partition > 32 Mb? +; $if ne ;an000; dms; yes + JE $$IF91 + mov [bx].SysInd,New_File_System ;an000; dms; type 6 +; $else ;an000; dms; < 32 Mb partition + JMP SHORT $$EN91 +$$IF91: + cmp fBigFat,True ;an000; ;16 bit FAT +; $IF E ;AC000; ;yes + JNE $$IF93 + mov [BX].SysInd,FAT16_File_System ;an000; ;type 4 +; $ELSE ;an000; ;12 bit FAT + JMP SHORT $$EN93 +$$IF93: + mov [bx].SysInd,FAT12_File_System ;an000; ;type 1 +; $ENDIF ;AN000; +$$EN93: +; $ENDIF ;an000; +$$EN91: +; $ENDIF ;an000; +$$EN89: +; $endif ;an000; +$$EN87: + ret ;an000; + +Determine_Partition_Type endp ; ;AN000; + + +;========================================================================= +; Calc_Total_Sectors_For_Partition : This routine determines the +; total number of sectors within +; this partition. +; +; Inputs : DeviceParameters +; +; Outputs : DX:AX - Double word partition size +;========================================================================= + +Procedure Calc_Total_Sectors_For_Partition ;an000; dms; + + mov ax,word ptr DeviceParameters.DP_BPB.BPB_HiddenSectors[+0] ;an000; dms; low word + mov dx,word ptr DeviceParameters.DP_BPB.BPB_HiddenSectors[+2] ;an000; dms; high word + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,0 ;an000; dms; extended BPB? +; $if e ;an000; dms; yes + JNE $$IF99 + add ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an000; dms; add in low word + adc dx,0 ;an000; dms; pick up carry if any + add dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an000; dms; add in high word +; $else ;an000; dms; standard BPB + JMP SHORT $$EN99 +$$IF99: + add ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an000; dms; add in total sector count + adc dx,0 ;an000; dms; pick up carry if any +; $endif ;an000; dms; +$$EN99: + + ret + +Calc_Total_Sectors_For_Partition endp + + +;------------------------------------------------------------------------------- +; ReadSector: +; Read one sector +; +; Input: +; ax - head +; bx - cylinder +; cx - sector +; dx - transfer address + +ReadSector proc near + + mov TrackReadWritePacket.TRWP_FirstSector, cx + mov cx,(RAWIO shl 8) or READ_TRACK + call SectorIO + return + +ReadSector endp + +;------------------------------------------------------------------------------- +; WriteSector: +; Write one sector +; +; Input: +; ax - head +; bx - cylinder +; cx - sector +; dx - transfer address + +WriteSector proc near + + mov TrackReadWritePacket.TRWP_FirstSector, cx + mov cx,(RAWIO shl 8) or WRITE_TRACK + call SectorIO + return + +WriteSector endp + +;------------------------------------------------------------------------------- +; SectorIO: +; Read/Write one sector +; +; Input: +; ax - head +; bx - cylinder +; cx - (RAWIO shl 8) or READ_TRACK +; - (RAWIO shl 8) or WRITE_TRACK +; dx - transfer address + +SectorIO proc near + + mov TrackReadWritePacket.TRWP_Head, ax + mov TrackReadWritePacket.TRWP_Cylinder, bx + mov WORD PTR TrackReadWritePacket.TRWP_TransferAddress, dx + mov WORD PTR TrackReadWritePacket.TRWP_TransferAddress + 2, ds + mov TrackReadWritePacket.TRWP_SectorsToReadWrite, 1 + + mov bl, drive + inc bl + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + lea dx, trackReadWritePacket + int 21H + return + +SectorIO endp + +;------------------------------------------------------------------------------- + +data segment public para 'DATA' + +oldDrive db ? + +FCBforVolumeIdSearch db 0ffH + db 5 dup(0) + db 08H + db 0 + db "???????????" + db 40 DUP(0) + +data ends + +GetVolumeId proc near +; Input: +; dl = drive +; di = name buffer + +; Save current drive + mov ah,19H + int 21H + mov oldDrive, al + +; Change current drive to the drive that has the volume id we want + mov ah, 0eH + int 21H + +; Search for the volume id + mov ah, 11H + lea dx, FCBforVolumeIdSearch + int 21H + push ax + +; Restore current drive + mov ah, 0eH + mov dl,oldDrive + int 21H + +; Did the search succeed? + pop ax + or al,al + jz CopyVolumeId + stc + ret + +CopyVolumeId: +; Find out where the FCB for the located volume id was put + mov ah,2fH + int 21H + +; Copy the Volume Id + mov si, bx + add si, 8 + push es + push ds + pop es + pop ds + mov cx, 11 + rep movsb + push es + pop ds + + clc + ret + +GetVolumeId endp + +data segment public para 'DATA' +oldVolumeId db 11 dup(0) +data ends + +CheckVolumeId proc near + +; Get the volume id that's on the disk + lea di, oldVolumeId + mov dl, drive + call GetVolumeId + jnc Ask_User ;Did we find one? + clc ;No, return with no error + ret + +; Ask the user to enter the volume id that he/she thinks is on the disk +; (first blank out the input buffer) +Ask_User: + + Message msgWhatIsVolumeId? ; ;AC000; + ;lea dx, ptr_msgWhatIsVolumeId? + ;call std_printf + call user_string + call crlf + +; If the user just pressed ENTER, then there must be no label + cmp inbuff+1, 0 + jne CompareVolumeIds + cmp oldVolumeId, 0 + jne BadVolumeId + ret + +CompareVolumeIds: +; pad the reponse with blanks +; The buffer is big enough so just add 11 blanks to what the user typed in + push ds + pop es + mov cx, Label_Length ;AC000; + xor bx,bx + mov bl, inbuff + 1 + lea di, inbuff + 2 + add di, bx + mov al, ' ' + rep stosb +; Make the reply all uppercase + mov byte ptr Inbuff+2+Label_Length,ASCIIZ_End ;Make string ASCIIZ ;AN000; + mov dx, offset inbuff + 2 ;Start of buffer ;AC000; + mov al,22h ;Capitalize asciiz ;AC000; + DOS_Call GetExtCntry ;Do it ;AC000; + +; Now compare what the user specified with what is really out there + mov cx, Label_Length ; ;AC000; + lea si, inbuff + 2 + lea di, oldVolumeId + repe cmpsb + jne BadVolumeId + ret + +BadVolumeId: + Message msgBadVolumeID ; ;AC000; + stc + ret + +CheckVolumeId endp + + +Check_Switch_8_B proc near + + test SwitchMap, SWITCH_B ;/8/B <> /V because ;AC007; +; $IF NZ,AND ; old directory type ;AC007; + JZ $$IF102 + test SwitchMap, Switch_8 ; used which didn't support ;AC007; +; $IF NZ,AND ; volume labels. ;AC007; + JZ $$IF102 + test SwitchMap, SWITCH_V ; ;AC007; +; $IF NZ ; ;AC007; + JZ $$IF102 + Message msgIncompatibleParameters ;Tell user ;AC007; + mov Fatal_Error,Yes ;Bad stuff ;AC007; +; $ELSE ;No problem so far ;AC007; + JMP SHORT $$EN102 +$$IF102: + test SwitchMap, Switch_B ;Can't reserve space and ;AC007; +; $IF NZ,AND ; install sys files at the ;AC007; + JZ $$IF104 + test SwitchMap, Switch_S ; same time. ;AC007; +; $IF NZ ; No /S/B ;AC007; + JZ $$IF104 + Message msgIncompatibleParameters ;Tell user ;AC007; + mov Fatal_Error,Yes ;Bad stuff ;AC007; +; $ELSE ;Still okay ;AC007; + JMP SHORT $$EN104 +$$IF104: + test SwitchMap,Switch_1 ;/1/8/4 not okay with /N/T ;AC007; +; $IF NZ,OR ; ;AC007; + JNZ $$LL106 + test SwitchMap,Switch_8 ; ;AC007; +; $IF NZ,OR ; ;AC007; + JNZ $$LL106 + test SwitchMap,Switch_4 ; ;AC007; +; $IF NZ ; ;AC007; + JZ $$IF106 +$$LL106: + test SwitchMap,(Switch_T or Switch_N) ; ;AC007; +; $IF NZ ;Found /T/N <> /1/8 ;AC007; + JZ $$IF107 + Message msgIncompatibleParameters ;Tell user ;AC007; + mov Fatal_Error,Yes ;Bad stuff ;AC007; +; $ELSE ; ;ac007; + JMP SHORT $$EN107 +$$IF107: + test SwitchMap,Switch_V ;ac007; +; $IF NZ,AND ;ac007; + JZ $$IF109 + test SwitchMap,Switch_8 ;ac007; +; $IF NZ ;ac007; + JZ $$IF109 + Message msgIncompatibleParameters ;ac007; + mov Fatal_Error,Yes ;ac007; +; $ENDIF ;ac007; +$$IF109: +; $ENDIF ; ;AC007; +$$EN107: +; $ENDIF ; ;AC007; +$$IF106: +; $ENDIF ; ;AC007; +$$EN104: +; $ENDIF ; ;AC007; +$$EN102: + ret + +Check_Switch_8_B endp + + +code ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRAFTABL.LNK b/v4.0/src/CMD/GRAFTABL/GRAFTABL.LNK new file mode 100644 index 0000000..ebc5869 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRAFTABL.LNK @@ -0,0 +1,12 @@ + GRTABHAN+ + GRTABUS+ + GRTABML+ + GRTABPO+ + GRTABCF+ + GRTABNO+ + GRTABSM+ + GRTABPAR+ + GRTABP+ + GRTAB + GRAFTABL.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRAFTABL.SKL b/v4.0/src/CMD/GRAFTABL/GRAFTABL.SKL new file mode 100644 index 0000000..e148585 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRAFTABL.SKL @@ -0,0 +1,28 @@ +:util GRAFTABL ;AN000;utility name +:class A ;AN000;system messages +:use 1 COMMON1 ;AN000;MSG 1 is always "Incorrect DOS version" + +;In these next 2 messages, %1 will be replaced with one from list, 4-5, ;AN000; +; or with one entry of the list at "CPID". (see GRTABMS.INC) ;AN000; + +:def 2 "Active Code Page: %1",CR,LF ;AN000; +:def 3 "Previous Code Page: %1",CR,LF ;AN000; + +:def 4 "None",NULL ;AN000; +:def 5 "Non-standard",NULL ;AN000; + +:def 6 CR,LF,"DOS command line parameters supported",COLON,CR,LF,LF ;AC007; + +:def 7 " /STA - Request Status only",CR,LF ;AC007; +" ? - Display this summary of parameters",CR,LF,CR,LF ;AC007; + +:def 8 " Code Pages available",COLON,CR,LF ;AC007; +" 437 - USA Graphic Character Set",CR,LF ;AC007; + +:def 9 " 850 - Multi-lingual Graphic Character Set",CR,LF ;AC007; +" 860 - Portuguese Graphic Character Set",CR,LF ;AC007; + +:def 10 " 863 - Canadian French Graphic Character Set",CR,LF ;AC007; +" 865 - Nordic Graphic Character Set",CR,LF ;AC007; +:end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTAB.ASM b/v4.0/src/CMD/GRAFTABL/GRTAB.ASM new file mode 100644 index 0000000..b0ef30c --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTAB.ASM @@ -0,0 +1,1218 @@ + PAGE 90,132 ;A2 + TITLE GRTAB - DEFINE ROM GRAPHIC CHARACTERS FOR 128-255 + IF1 + %OUT GRTAB.SAL... + ELSE +; %OUT GRTAB.SAL... + ENDIF +LISTPARM = 1 ;0=SUPPRESS LIST; 1=ALLOW LIST ;AN000; +;.XLIST ; ;AN000; +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: GRTAB +; (MAIN ROUTINE FOR UTILITY "GRAFTABL") + +; DESCRIPTIVE NAME: Makes resident a 1K block of data defining the +; graphic character set when in graphics mode. + +;FUNCTION: When in normal text mode (BASIC SCREEN 0), the CGA will properly +; handle all 255 characters in the screen display. +; However, when in graphics mode (BASIC SCREEN 1), then only the +; first 128 characters are properly shown on the screen. +; The upper 128 characters are defined in graphics mode by +; the 8 by 128 byte table pointed to by interrupt 1FH +; vector, which is normally set to 0:0, thus producing +; garbage on the screen for the upper set of characters. + +; The purpose of this routine is to define an 8 by 128 byte +; table that defines each of these graphic characters in +; the upper 128 byte range, and also to put the vector +; pointer to this table into the interrupt 1FH. Once +; loaded, this table remains resident. + +; An interrupt handler is hooked into the INT 2FH vector that +; screens INT 2FH calls for the MULTIPLEX ID value of hex B0, +; as defined by an equate, MY_MULTIPLEX_NUMBER, in GRATABHAN. +; The response indicates that GRAFTABL has been loaded, thus +; permitting the redefinition of the original 1K table with +; some new specification. + +; ENTRY POINT: Entry_Point, JMP from GRTABHAN.SAL at his ORG 100H. +; LINKAGE: [d:][path] GRAFTABL [437 | 850 | 860 | 863 | 865 | ? | /STATUS] + +; INPUT: (DOS COMMAND LINE PARAMETERS) +; '/STATUS'- (OR /STA) Identify the table already loaded, if any. +; '?' - Display the list of operands supported by GRAFTABL. +; 437 - Install the USA Graphic Character Set +; (BLANK) - Means same as '437', the 'USA' definition table +; 850 - Install the Multi-lingual Graphic Character Set +; 860 - Install the Portuguese Graphic Character Set +; 863 - Install the Canadian French Graphic Character Set +; 865 - Install the Nordic Graphic Character Set + +; EXIT-NORMAL: ERRORLEVEL 0 - Leaving the 1K block of newly defined +; characters resident. There was no +; previously defined character table. +; Available RAM reduced by hex 1360 bytes. + +; ERRORLEVEL 1 - No change in size of available RAM storage. +; A previously loaded character table exists. +; If a new table was requested, it has replaced +; the previous table at its original location. + +; ERRORLEVEL 2 - No change in size of available RAM storage. +; No previously loaded character table exists. +; +; (The request for status, with parm="/sta[tus]", +; or the request for HELP, with parm="?", +; will result in either code 1 or 2.) + +; EXIT-ERROR: ERRORLEVEL 3 - Incorrect parameter. +; No action taken, assumes "?" requested HELP. +; No change in size of available RAM storage. + +; ERRORLEVEL 4 - Incorrect version of DOS, DOS 4.0 required + +; EFFECTS: Either the desired table is hooked into Interrupt 1FH, +; or the identity of the previously loaded table is +; displayed. + +; INTERNAL REFERENCES: +; ROUTINES: +; FINDTYPE - Scan existing table to see who is already loaded +; MOVTAB - Moves the specified table to overlay a portion of the PSP +; BADPARMS - Displays error message, and sets error ERRORLEVEL code +; SENDMSG - passes parms to regs and invokes the system message routine. + +; DATA AREAS: +; PSP - Contains the DOS command line parameters. Partly overlayed +; with the installation of the character table. +; WORKAREA - Temporary storage + +; EXTERNAL REFERENCES: +; ROUTINES: +; GRTABHAN (ENTRY is "HANDLER") - hooked into INT 2FH to identify +; that GRAFTABL is loaded and resident. +; SYSDISPMSG - Uses the MSG parm lists to construct the messages +; on STDOUT. +; SYSLOADMSG - Loads messages, makes them accessable. +; SYSPARSE - Processes the DOS Command line, finds parms. +; PARSE - Interfaces with the system Parser. + +; DATA AREAS: +; GRTABUS - 1k binary table of the USA graphic character set +; GRTABML - 1k binary table of the Multi-Lingual graphic +; character set +; GRTABPO - 1k binary table of the Portuguese graphic +; character set +; GRTABCF - 1k binary table of the Canada French graphic +; character set +; GRTABNO - 1k binary table of the Nordic graphic character +; set +; GRTABSM - Definition of messages, text and MSG parm lists, +; and COPYRIGHT notice +; GRTABPAR - Control blocks to define the DOS command line parms. +; MPEXNUM - Byte containing the value of the multiplex number +; (For ease of patching, if such should ever become needed, +; this byte is immediately just before the interrupt 2FH +; handler's entry point, after that handler is loaded. To +; change this value here in these source modules, that value +; is defined in GRTABHAN as the equate: MY_MULTIPLEX_NUMBER. +; For purposes of patching the GRAFTABL.EXE file, this byte +; is at offset 5FH into the module.) + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT GRTAB,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; Sample LINK command: + +; LINK @GRTABLK.ARF + +; Where the GRTABLK.ARF is defined as: +; GRTABHAN+ (must be first in this list) +; GRTABUS+ (these languages must be linked in this order) +; GRTABML+ (Multi-Lingual) +; GRTABPO+ (Portuguese) +; GRTABCF+ (Canadian French) +; GRTABNO+ (Nordic) +; GRTABSM+ (contains COPYRIGHT, SYSDISPMSG, SYSLOADMSG code) +; GRTABPAR+ (contains PARSE control blocks, code to call SYSPARSE) +; GRTABP+ (contains SYSPARSE to decode COMMAND line parms) +; GRTAB (MAIN ROUTINE) +; GRAFTABL; + +; These modules must be linked in this order. The load module is +; a COM file, to be converted to COM with EXE2BIN. + +; REVISION HISTORY: +; A000 Version 4.00: add PARSER, System Message Handler, +; A001 PTM 382 display "ACTIVE" OR "PREVIOUS" CP. +; A002 PTM 474 Avoid duplicate switches +; A003 PTM 538 Display parm in error +; A004 PTM1821 INCLUDE COPYRIGH.INC moved to msg_service macro. +; A005 PTM3262 specify BASESW EQU 1 before PARSE.ASM +; A006 PTM3512 PATHGEN START/END LABELS +; A007 PTM3621 break up large help msg into smaller messages +; A008 PTM3899 Free Environment, close all STDxxx handles +; when leaving a resident portion +; +; COPYRIGHT: The following notice is found in the OBJ code generated from +; the "GRTABSM.ASM" module: + +; "Version 4.00 (C) Copyright Microsoft Corp 1981, 1988" +; "Licensed Material - Program Property of Microsoft" + +;****************** END OF SPECIFICATIONS ***************************** + HEADER + INCLUDE PATHMAC.INC ;AN006; +; $SALUT (0,36,41,52) +DOSCALL MACRO FN,SF ;; ;AN000; + IFNB ;;ARE THERE ANY PARMS AT ALL?;AN000; + IFNB ;; ;AN000; + MOV AX,(FN SHL 8)+SF ;;AH=FN;AH=SF ;AN000; + ELSE ;;SINCE THERE IS NO SUB FUNC ;AN000; + MOV AH,FN ;; ;AN000; + ENDIF ;; ;AN000; + ENDIF ;; ;AN000; + INT 21H ;; ;AN000; + ENDM ;; ;AN000; +; = = = = = = = = = = = = +; $SALUT (4,19,23,36) +FIXLIST MACRO LP,DOIT ;; ;AN000; +IF LP ;; ;AN000; +DOIT ;; ;AN000; +ENDIF ;; ;AN000; + ENDM ;; ;AN000; +; = = = = = = = = = = = = +HEADER MACRO TEXT ;; ;AN000; + FIXLIST LISTPARM,.XLIST ;; ;AN000; + SUBTTL TEXT ;; ;AN000; + FIXLIST LISTPARM,.LIST ;; ;AN000; + PAGE ;; ;AN000; + ENDM ;; ;AN000; +; = = = = = = = = = = = = +; DEFINITION OF FUNCTIONS TO BE REQUESTED OF INT 2FH +GET_INST_STATE EQU 0 ;FUNCTION = "GET INSTALLED STATE" +WHERE_R_U EQU 1 ;FUNCTION = "WHERE ARE YOU?" + ; REQUESTS VECTOR OF LOADED TABLE BE + ; PUT IN VECTOR POINTED TO BY DS:[BX] + +; DOS FUNCTIONS: +SHOW_MSG EQU 09H ;"SEND MESSAGE TO CONSOLE" DOS FUNCTION +SET_VECT EQU 25H ;"SET VECTOR" DOS FUNCTION +GET_VERSION EQU 30H ;"GET DOS VERSION" +RET_RES EQU 31H ;"RETURN TO DOS" REMAIN RESIDENT +GET_VECT EQU 35H ;"GET VECTOR" DOS FUNCTION +CLOSE EQU 3EH ;AN008; CLOSE A FILE HANDLE +FREE_AL_MEM EQU 49H ;AN008; FREE ALLOCATED MEM +RET_FN EQU 4CH ;"RETURN TO DOS" NOT REMAIN RESIDENT + +; VECTOR TABLE ENTRIES USED +VEC_GRAF_CHAR EQU 1FH ;VECTOR THAT POINTS TO GRAPHIC CHAR TABLE +VEC_MULTIPLX EQU 2FH ;VECTOR OF MULTIPLEX HANDLER +VEC_DOS EQU 21H ;VECTOR POINTS TO DOS FUNCTIONS +VEC_RET EQU 20H ;RETURN TO DOS, WITHOUT RET CODE ;AN000; + +; DOS COMMAND LINE PARAMETERS +RETCODE_QUESTION EQU -1 ;VALUE IN BX, IF PARM=? +ZERO EQU 0 ;VALUE IN BX IF PARM=/STATUS OR /STA + FIXLIST LISTPARM,.XLIST ; ;AN000; +;SLASH EQU "/" ;REQUEST FOR STATUS +;PARM? EQU "?" ;REQUEST FOR HELP +; THE PARM THAT ASKS FOR A PARTICULAR LANGUAGE +; IS THE TWO CHAR PAIR, DEFINED AS "LANID" +; IN THE STRUC, "LANGUAGE" + FIXLIST LISTPARM,.LIST ; ;AN000; + +; STANDARD FILE HANDLES +STDIN EQU 0 ;AN008; STANDARD INPUT DEVICE +STDOUT EQU 1 ;STANDARD OUTPUT DEVICE +STDERR EQU 2 ;STANDARD ERROR OUTPUT DEVICE +STDAUX EQU 3 ;AN008; STANDARD AUX DEVICE +STDPRN EQU 4 ;AN008; STANDARD PRINTER DEVICE + +; OTHER EQUATES +BLANK EQU " " ;BLANK CHARACTER +NIBBLE_SIZE EQU 4 ;SHIFT COUNT TO MOVE ONE NIBBLE ;AN000; + FIXLIST LISTPARM,.XLIST ; ;AN000; +;CASEBIT EQU 0FFH-20H ;TURN OFF THIS BIT TO MAKE UPPER CASE +;LOWERA EQU 'a' ;LOWER CASE CHARACTER 'a' +;LOWERZ EQU "z" ;LOWER CASE CHARACTER 'z' + FIXLIST LISTPARM,.LIST ; ;AN000; + + EXTRN HANDLER_SIZE:ABS ;THE BYTE SIZE REQUIREMENTS + EXTRN CPID_L:ABS ;NO. BYTES IN EACH CPID ENTRY + +VECTOR STRUC ;DEFINITION OF ANY DOUBLE WORD VECTOR POINTER +VECOFF DW ? ;OFFSET PORTION OF VECTOR POINTER +VECSEG DW ? ;SEGMENT PORTION OF VECTOR POINTER +VECTOR ENDS +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +LANGUAGE STRUC ;DEFINITION OF EACH LANGUAGE TABLE +LANCHAR DB 1024 DUP(?) ;8 BYTES PER EACH OF 128 CHARACTERS +LANID DW ? ;TWO BYTE CODEPAGE ID, TO MATCH + ; GRAFTABL CMD LINE PARM +LANNAME DB 14 DUP(?) ;ASCIIZ STRING NAME OF LANGUAGE +LANGUAGE ENDS + +TABSIZE EQU SIZE LANCHAR + SIZE LANID + SIZE LANNAME ;SIZE OF + ; EACH GRAPHIC CHAR TABLE + ID + NAME +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; VALUES FOR THE MSG_DESC CONTROL BLOCK +ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE ;AN000; +TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE ;AN000; +CLASS_1 EQU 0100H ;CLASS 1 (DOS EXTENDED ERRORS) ;AN000; +CLASS_2 EQU 0200H ;CLASS 2 (PARSE ERRORS) ;AN000; +CLASS_A EQU 0A00H ;CLASS A TYPE MESSAGE ;AN000; + +;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, +;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN +;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. + +MSG_DESC STRUC ; ;AN000; +MSG_NUM DW 0 ;MESSAGE NUMBER (TO AX) ;AN000; +MSG_HANDLE DW STDOUT ;HANDLE OF OUTPUT DEVICE (TO BX) ;AN000; +MSG_SUBLIST DW 0 ;POINTER TO SUBLIST (TO SI) ;AN000; +MSG_COUNT DW 0 ;SUBSTITUTION COUNT (TO CX) ;AN000; +MSG_CLASS DW CLASS_A ;MESSAGE CLASS (IN HIGH BYTE, TO DH) ;AN000; + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) +MSG_DESC ENDS ; ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +SUBLIST STRUC ; ;AN000; +SUB_SIZE DB TYPE SUBLIST ;SUBLIST SIZE (POINTER TO NEXT SUBLIST) ;AN000; +SUB_RES DB 0 ;RESERVED ;AN000; + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD +SUB_VALUE DW 0 ;TIME, DATE, OR PTR TO DATA ITEM ;AN000; +SUB_VALUE_SEG DW 0 ;SEG ID OF PTR ;AN000; + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME + ; IF THIS IS A .COM FILE) +SUB_ID DB 0 ;N OF %N ;AN000; +SUB_FLAGS DB 0 ;DATA TYPE FLAGS ;AN000; +SUB_MAX_WIDTH DB 0 ;MAXIMUM FIELD WIDTH (0=UNLIMITED) ;AN000; +SUB_MIN_WIDTH DB 0 ;MINIMUM FIELD WIDTH ;AN000; +SUB_PAD_CHAR DB " " ;CHARACTER FOR PAD FIELD ;AN000; +SUBLIST ENDS ; ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +DEFPSP STRUC + DB 2CH DUP(?) ;AN008; +ENVIRON_SEG DW ? ;AN008; SEG ID OF ENVIRONMENT + DB 32H DUP(?) ;AN008; SET WHERE +MOV_DEST DB 20H DUP(?) ; INT HANDLER IS TO BE MOVED TO + ;AT MOV_DEST+HANDLER_SIZE WILL GO THE + ; TABLE ITSELF +PARMCNT DB ? ;COUNT OF CHARS IN DOS COMMAND LINE PARM LIST +PARMDOS DB 127 DUP(?) ;DOS COMMAND LINE PARM TEXT +DEFPSP ENDS + +PSPSIZE EQU SIZE DEFPSP ;SIZE OF THE PSP ITSELF +SHIFT_SIZE EQU PSPSIZE - MOV_DEST ; HOW FAR HANDLER/TABLE MOVED + ;WHEN THEY BECAME RESIDENT +SHIFT_SIZE_SEG EQU SHIFT_SIZE SHR NIBBLE_SIZE ;DIVIDE BY 16 ;AN000; + ; TO CONVERT BYTES TO SEGS +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.LIST + HEADER +; $SALUT (4,6,12,28) + +CSEG SEGMENT WORD PUBLIC + ASSUME CS:CSEG ;AS A .COM FILE, THE DOS + ASSUME DS:CSEG ; LOADER HAS ALREADY + ASSUME ES:CSEG ; INITIALIZED ALL THESE + ASSUME SS:CSEG ; SEGMENT REGISTERS + +GRTAB_BASE EQU $ ;FOR EASE IN DEBUGGING ;AN000; + PUBLIC GRTAB_BASE ; TELL LINK MAP WHERE THIS IS ;AN000; + + EXTRN END_PSP:BYTE ;MOVE RESIDENT CODE FROM HERE TO "MOV_DEST" + EXTRN MPEXNUM:BYTE ;MULTIPLEXOR ID VALUE + EXTRN HANDLER:NEAR ;ENTRY TO INT2FH HANDLER + EXTRN PREV_OWN:DWORD ;VECTOR TO SAVE PREVIOUS INT2FH OWNER + EXTRN PATCH_OFF:WORD ;THESE TWO PATCH LOCATION IN GRTABHAN.SAL + EXTRN PATCH_SEG:WORD ; ARE TO RECEIVE LOCATION WHERE TABLE IS MOVED TO + EXTRN TABLEUS:BYTE ;START OF THE USA CHAR TABLE + EXTRN COPYRIGHT:BYTE ;USED TO MARK THE END OF THE ARRAY OF CHAR TABLES + ; THE COPYRIGHT TEXT IS ITSELF UN-REFERENCED + FIXLIST LISTPARM,.XLIST ; ;AN000; +; EXTRN MSG1:WORD ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED +; EXTRN MSG2:WORD ;XXX VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED +; EXTRN MSG3:WORD ;XXX VER OF GRAPHIC CHAR SET HAS JUST BEEN LOADED +; EXTRN MSG4:WORD ;INCORRECT PARAMETER +; EXTRN MSG5:WORD ;NO VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED +; EXTRN MSG6:WORD ;INCORRECT DOS VERSION +; EXTRN MSG7:WORD ;DOS COMMAND LINE PARAMETERS SUPPORTED: +; EXTRN MSG8:WORD ;ID - LANGUAGE NAME +; EXTRN LANGUAGE_NAME:BYTE ;14 BYTE AREA TO RECEIVE ASCIIZ OF LANGUAGE NAME + FIXLIST LISTPARM,.LIST ; ;AN000; + EXTRN MSGNUM_EXTERR:WORD ;ALL DOS EXTENDED ERRORS ;AN000; + EXTRN MSGNUM_PARSE:WORD ;ALL PARSING ERRORS ;AN000; + EXTRN SUBLIST_PARSE:WORD ;DEFINES THE BAD PARM AS %0 ;AN003; + EXTRN MSGNUM_VER:WORD ;"Incorrect DOS Version" ;AN000; + EXTRN MSGNUM_ACTIVE:WORD ;"Active Code Page: %1" ;AN000; + EXTRN MSGNUM_PREVIOUS:WORD ;"Previous Code Page: %1" ;AN000; + EXTRN CPID:BYTE ;4 BYTE STRING OF CODE PAGE ID ;AN000; + EXTRN SLIST_23:WORD ;SET VECTOR TO POINT TO "NONE" OR "NON-STANDARD", ;AN000; + ; OR TO ONE OF THE "CPID" ENTRIES + EXTRN MSGNUM_NONE:WORD ;"None" ;AN000; + EXTRN MSGNUM_NSTD:WORD ;"Non-Standard" ;AN000; + EXTRN MSGNUM_HELP_TITLE:WORD ;"DOS command line parameters supported:" ;AN000; + EXTRN MSGNUM_HELP_TITLE7:WORD ;AN007; + EXTRN MSGNUM_HELP_TITLE8:WORD ;AN007; + EXTRN MSGNUM_HELP_TITLE9:WORD ;AN007; + EXTRN MSGNUM_HELP_TITLE10:WORD ;AN007; + EXTRN SYSDISPMSG:NEAR ;DISPLAY MESSAGE SUBROUTINE ;AN000; + EXTRN SYSLOADMSG:NEAR ;LOAD MESSAGE SUBROUTINE ;AN000; + EXTRN SYSGETMSG:NEAR ;GET MESSAGE SUBROUTINE ;AN000; + EXTRN PARSER:NEAR ;INVOKES SYSTEM DOS COMMAND LINE PARSER ;AN000; +; $SALUT (4,17,22,32) +WHERE DD 0 ;VECTOR POINTING TO PREVIOUS GRAFTABL TABLE + ; VECTOR AS SET BY "GRTABHAN" MULTIPLEX HANDLER. + ;THIS IS NOT NECESSARILY WHAT INT 1FH HAS. +ADPSP DW 0 ;SEG ID OF PSP. + ; CHANGED TO SHOW ITS SHIFTED LOCATION + FIXLIST LISTPARM,.XLIST ; ;AN000; +;ACC DW 0 ;ACCUMULATES VALUE OF CODEPAGE ID +;TEN DW 10 ;CONSTANT TO CONVERT ASCII DECIMAL TO BINARY +;TOKEN DB " " ;RECEIVES THE TEXT OF DOS PARMS, AND OVERFLOW AREA +;TOKEN_SIZE EQU $-TOKEN + FIXLIST LISTPARM,.LIST ; ;AN000; +RESSIZE_PARA DW 0 ;SIZE OF RESIDENT PORTION, HANDLER+TABLE, IN PARAGRAPHS +RESSIZE_BYTE DW 0 ;SIZE OF RESIDENT PORTION, HANDLER+TABLE, IN BYTES +SAVESI DW 0 ;REMEMBER WHERE CURRENT TABLE STARTS +CPIDPOINTER DW CPID ;POINTER TO ENTRY IN CPID TABLE OF PREVIOUS ENTRY +ACTIVECPID DW CPID ;POINTER TO ENTRY IN CPID TABLE OF ACTIVE ENTRY + PUBLIC ACTIVECPID +IDXXX DW 0 ;ID OF PREVIOUSLY LOADED TABLE +INSTALLED DB 0 ;OUTPUT OF INT 2FH, "FF"=GRAFTABL ALREADY INSTALLED + ; AND 'WHERE' WILL POINT TO PREVIOUS TABLE + ;"00"=GRAFTABL NOT INSTALLED + +; DEFINITIONS OF VALUES OF CONTENTS OF "INSTALLED". +LOADED EQU 0FFH ;GRAFTABLE IS ALREADY IN VECTOR + + +; DEFINITIONS OF VALUES OF CONTENTS OF 'EXITFL'. +; THESE VALUES ARE THE RETURN CODES CHECKED BY ERRORLEVEL. +EXVER EQU 4 ;RETURN TO DOS, INVALID DOS VERSION +EXPAR EQU 3 ;RETURN TO DOS, INVALID DOS COMMAND LINE PARMS + ; OR SYSTEM MESSAGE HANDLER ERROR +EXNONE EQU 2 ;RETURN TO DOS, NO TABLE WAS LOADED +EXDOS EQU 1 ;RETURN TO DOS, CHAR TABLE PREVIOUSLY LOADED +EXRES EQU 0 ;RETURN TO DOS, LEAVING THE 1K BLOCK OF CHAR RESIDENT + +EXITFL DB EXDOS ;ERRORLEVEL RETURN CODE, INITIALLY SET TO "EXDOS" + PUBLIC EXITFL +BAD1F DB 0 ;FLAG, GET SET TO "RESET" IF GRAFTABL FONT IS +RESET EQU 1 ; LOADED, BUT 1FH DOES NOT POINT TO IT +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + PATHLABL GRTAB ;AN006; +; $SALUT (3,4,9,32) + HEADER +MAIN PROC NEAR +ENTRY_POINT LABEL NEAR ;JUMPED TO FROM ENTRY POINT IN GRTABHAN + PUBLIC ENTRY_POINT +;VERSION CHECKING AND SYSTEM MESSAGE INITIALIZATION + + CALL SYSLOADMSG ; INIT SYSMSG HANDLER ;AN000; + +; $IF C ; IF THERE WAS A PROBLEM ;AN000; + JNC $$IF1 + CALL SYSDISPMSG ; LET HIM SAY WHY HE HAD A PROBLEM ;AN000; + + MOV EXITFL,EXVER ; TELL ERRORLEVEL BAD DOS VERSION ;AN000; + MOV AH,RET_FN ;RETURN TO DOS, DO NOT STAY RESIDENT ;AN000; +; $ELSE ; SINCE SYSDISPMSG IS HAPPY ;AN000; + JMP SHORT $$EN1 +$$IF1: + CLD ;CLEAR DIRECTION TO AUTO-INCREMENT ;AN000; + CALL MAIN_GRTAB ;PERFORM REST OF GRAFTABL FUNCTIONS ;AN000; + ;AH=DOS FUNCTION OF TYPE OF RETURN TO DOS +; $ENDIF ;LOAD OF SYS MSGS OK? ;AN000; +$$EN1: + MOV AL,EXITFL ;PASS BACK ERRORLEVEL RET CODE + INT VEC_DOS ;(21H) RETURN TO DOS WITH RET CODE + + INT VEC_RET ;(20H) IF ABOVE NOT WORK, EXIT ANYWAY ;AN000; +MAIN ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +MAIN_GRTAB PROC NEAR + PUBLIC MAIN_GRTAB +;INPUT: SYSTEM MESSAGE HANDLER IS LOADED, DOS VERSION IS CORRECT. +;OUTPUT: AH=FUNCTION NUMBER FOR PROPER TYPE OF RETURN TO DOS. + + MOV SLIST_23.SUB_VALUE_SEG,CS ;DO MY OWN SEGMENT FIXUPS ;AN000; + MOV SUBLIST_PARSE.SUB_VALUE_SEG,CS ; ;AN003; + + MOV ADPSP,ES ;SAVE SEG ID OF PSP + SUB ADPSP,SHIFT_SIZE_SEG ;WHERE THE SEG BASE OF MOVED INT HANDLER WILL BE + PUSH ES ;SAVE PSP SEGID + + MOV AX,HANDLER_SIZE ;GET SIZE OF MULTIPLEX HANDLER (NOT PSP) ;AN000; + ADD AX,TABSIZE ;ADD THE SIZE OF THE CHAR TABLE + MOV RESSIZE_BYTE,AX ;SAVE BYTE LENGTH OF HANDLER + CHAR TABLE + ; THIS IS THE AMOUNT TO BE SHIFTED + ADD AX,OFFSET MOV_DEST ;ADD ON PART OF PSP NOT OVERLAID BY CODE MOVE ;AN000; + MOV CL,NIBBLE_SIZE ;DIVIDE ;AN000; + SHR AX,CL ; BYTE SIZE BY 16 + MOV RESSIZE_PARA,AX ;SAVE PARA LENGTH OF HANDLER + CHAR TABLE + ; AND FIRST PART OF PSP + ;THIS IS THE AMOUNT TO STAY RESIDENT + + ;PATCH INT2FH HANDLER IN CASE LATER + ; IT BECOMES RESIDENT AND IS ASKED + ; TO TELL WHERE ITS CHAR TABLE WENT + MOV AX,ADPSP ;TELL INT2FH HANDLER WHERE TO SAY HIS TABLE IS + MOV PATCH_SEG,AX + MOV PATCH_OFF,OFFSET TABLEUS ;TELL INT2FH HANDLER + ; WHERE TO SAY HIS TABLE IS + MOV AH,GET_VECT ;REQUEST "GET VECTOR" FUNCTION + MOV AL,VEC_MULTIPLX ; FOR INTERRUPT 2FH + INT VEC_DOS ;OUTPUT: ES:BX = VECTOR OF CONTENTS + + ASSUME ES:NOTHING ;SINCE ORIG PSP POINTER IS LOST + ;PATCH INT2FH HANDLER TO TELL HIM WHERE + ; THE CURRENT INT2FH HANDLER IS IN CASE + ; THIS NEW HANDLER REPLACES THE OLD ONE + MOV PREV_OWN.VECOFF,BX ;REMEMBER WHERE THE PREVIOUS + MOV PREV_OWN.VECSEG,ES ; OWNER OF INT 2FH WAS + + POP ES ;RESTORE THE PSP SEGID BAS ;AN000; + ASSUME ES:CSEG ;REG IS RESET BACK LIKE IT WAS + CALL FINDTYPE ;SET 'IDXXX' TO SHOW + ; WHAT IS IN THE LOW RAM TABLE NOW + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; CALL PROCESS ;RESPOND TO REQUEST DEFINED BY PARMS +; ; SETTING 'EXITFL' TO INDICATE RESULTS + FIXLIST LISTPARM,.LIST ; ;AN000; + CALL PARSER ;LOOK AT DOS COMMAND LINE PARMS ;AN000; + + ;IF A CODEPAGE NUMBER WAS SPECIFIED + ; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED + ; DX = INTEGER VALUE OF CODEPAGE SPECIFIED + ;IF /STATUS WAS SPECIFIED + ; BX = 0 + ;IF QUESTION MARK WAS SPECIFIED + ; BX=-1 + + CALL DOFUNCTION ; RESPOND TO PARMS ;AN000; + ; SETTING 'EXITFL' TO INDICATE RESULTS + + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; $ELSE ;SINCE THE DOS VERSION IS NOT ACCEPTABLE, +; THE LOCATION, "MSG6", CONTAINS OFFSET TO TEXT OF +; MOV DX,MSG6 ;"INCORRECT DOS VERSION" (THIS MSG ENDS WITH "$") +; ;GET POINTER TO MESSAGE TEXT TO DS:DX +; MOV AH,SHOW_MSG ;'WRITE TO CONSOLE' DOS FUNCTION +; INT VEC_DOS +; +; MOV EXITFL,EXVER ;SET ERROR CODE TO ERROR TERMINATION, BAD VERSION +; $ENDIF ;CHECK DOS VERSION NUMBER + FIXLIST LISTPARM,.LIST ; ;AN000; + + CMP EXITFL,EXRES ;CHECK THE EXIT TYPE FLAG +; $IF E ;IF NEW TABLE HAS JUST BEEN LOADED + JNE $$IF4 +;THE INT2FH HANDLER AND THE CHAR TABLE HAVE ALREADY BEEN MOVED INTO THE PSP. +;CHANGE THE TWO VECTORS TO POINT TO WHERE THEN WENT. +;THE TWO VECTORS ARE: +; 2FH - MULTIPLEX INTERRUPT HANDLER +; 1FH - 128 CHAR DEFINITION TABLE + + PUSH DS + + MOV AX,ADPSP + MOV DS,AX ;FIND SEG WHERE TABLE WENT + ASSUME DS:NOTHING + +;SET INTERRUPT VECTOR 1FH TO POINT TO WHERE THE CHAR TABLE IS + LEA DX,TABLEUS ;WHERE CHAR TABLE IS + ; DS:DX = VECTOR POINTING TO CHAR TABLE AFTER MOVE + MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 1FH + MOV AL,VEC_GRAF_CHAR ;INTERRUPT NUMBER TO RECEIVE NEW CONTENTS + INT VEC_DOS ;CHANGE THE VECTOR + +;SET INTERRUPT VECTOR 2FH (MULTIPLEXOR) TO WHERE THE INTERRUPT HANDLER IS + LEA DX,HANDLER ;SET DS:DX = INT 2FH INTERRUPT HANDLER + MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 2FH + MOV AL,VEC_MULTIPLX ;CHANGE THE CONTENTS OF THE MULTIPLEX INTERRUPT + INT VEC_DOS ;HOOK IN THE INTERRUPT HANDLER + + POP DS ;RESTORE SEG REG + ASSUME DS:CSEG + +;FREE THE SEGMENT CONTAINING THE ENVIRONMENT + PUSH ES ;AN008; SAVE NORMAL ES + MOV AX,DS:ENVIRON_SEG ;AN008; FROM PSP GET SEG OF ENVIRONMENT + MOV ES,AX ;AN008; SET SEGREG TO POINT TO ENVIRONMENT SEG + ASSUME ES:NOTHING ;AN008; ES NOW HAS SEG OF ENVIRONMENT + + MOV AH,FREE_AL_MEM ;AN008; (49H) FREE MEM ALLOC TO ENVIRON + ;ES = SEGID OF BLOCK BEING RETURNED + INT VEC_DOS ;AN008; FREE ENVIRONMENT + ;IF CARRY IS SET, THERE WAS A PROBLEM + ;THIS IS NOT CHECKED, IGNORING ANY ERROR + + POP ES ;AN008; RESTORE ES TO NORMAL VALUE + ASSUME ES:CSEG ;AN008; + +;LOOP THRU ALL THE STANDARD EXTERNALLY OPENED HANDLES, 0-4, +; AND CLOSE EACH ONE BEFORE RETURNING TO DOS, STAYING RESIDENT. + MOV BX,STDIN ;AN008; START WITH FIRST STANDARD HANDLE +; $DO COMPLEX + JMP SHORT $$SD5 +$$DO5: + INC BX ;AN008; SELECT NEXT HANDLE +; $STRTDO +$$SD5: + MOV AH,CLOSE ;AN008; (3EH) CLOSE A FILE HANDLE + ; BX=FILE HANDLE + INT VEC_DOS ;AN008; CLOSE THE HANDLE + ;CARRY IS SET IF A PROBLEM WITH CLOSE + ;IN THIS CASE, ERRORS ARE IGNORED. + + CMP BX,STDPRN ;AN008; WAS THIS THE LAST ONE? +; $ENDDO E ;AN008; QUIT IF LAST ONE + JNE $$DO5 + +;SET UP TO LEAVE A PORTION OF GRAFTABL RESIDENT: +; THE MULTIPLEXOR INTERRUPT HANDLER, AND +; THE FIRST 1K PIXEL TABLE. + + MOV DX,RESSIZE_PARA ;MARK END OF AREA TO REMAIN RESIDENT + MOV AH,RET_RES ;FUNCTION TO RETURN TO DOS, BUT STAY RESIDENT +; $ELSE ;SINCE NEW TABLE NOT LOADED + JMP SHORT $$EN4 +$$IF4: + ; MAYBE BECAUSE TABLE ALREADY LOADED + ; OR MAYBE BECAUSE BAD DOS COMMAND LINE PARMS + MOV AH,RET_FN ;RETURN TO DOS, DO NOT STAY RESIDENT +; $ENDIF +$$EN4: + RET ;RETURN TO CALLER +MAIN_GRTAB ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +FINDTYPE PROC NEAR + PUBLIC FINDTYPE +;OUTPUT = IDXXX HAS 2 CHAR ID OF WHATEVER IS ALREADY LOADED +; OR IS JUST 0 IF 1FH DOES NOT POINT TO A GRAFTABL DEFINED FONT. +; SUBLIST_23 IS SET TO CONTAIN THE ORIGINAL CP PREVIOUSLY LOADED +; OR "NONE". THIS SUBLIST IS USED BY BOTH MESSAGES 2 AND 3 +; WHICH STATE THE "ACTIVE CODEPAGE" AND "PREVIOUS CODEPAGE". +; THE MESSAGE ACTUALLY TO USE THIS SUBLIST IS SELECTED IN "DOFUNCTION" +; AFTER INTERROGATING THE PARMS, SO THAT "/STATUS" & "?" WILL REFER TO +; THE "ACTIVE CODEPAGE", AND OTHER REQUESTS WILL SAY "PREVIOUS CP". + + ASSUME ES:NOTHING + MOV AH,MPEXNUM ;REQUEST "GET INSTALLED STATE" + MOV AL,GET_INST_STATE ;IDENTIFY THAT IT IS ME I AM LOOKING FOR + ;AH=MULTIPLEXOR NUMBER, AL=FUNCTION REQUEST + INT VEC_MULTIPLX ;SEE IF I AM ALREADY LOADED + + MOV INSTALLED,AL ;SAVE THE "INSTALLED?" INDICATOR + CMP AL,LOADED +; $IF E ;IF I AM ALREADY INSTALLED + JNE $$IF10 +; GRAFTABL HAS BEEN LOADED. SEVERAL CONDITIONS MAY EXIST: +; INT 1FH STILL POINTS TO THE TABLE GRAFTABL LOADED +; AND THAT TABLE HAS NOT BEEN ALTERED. +; INT 1FH STILL POINTS TO THE TABLE GRAFTABL LOADED +; BUT THE CONTENTS OF THAT TABLE HAS BEEN ALTERED. +; INT 1FH NO LONGER POINTS TO THE TABLE GRAFTABL LOADED, +; BUT POINTS TO SOME OTHER CHARACTER TABLE. + +; NOW WE ASK THE MULTIPLEXOR HANDLER OF GRAFTABLE, SINCE WE +; KNOW HE HAS BEEN LOADED, TO TELL US WHERE HIS GRAFTABL +; CHARACTER FONT TABLE IS IN RESIDENT RAM, BY SETTING THE +; DWORD AT "WHERE" TO POINT TO THE OLD GRAFTABL FONT TABLE. + + ;AH STILL SHOULD HAVE "MY_MULTIPLEX_NUMBER" + MOV AL,WHERE_R_U ;ASK "WHERE ARE YOU" + LEA BX,WHERE ;PASS POINTER TO VECTOR TO RECEIVE ANSWER + ;AH=MULTIPLEXOR NUMBER, AL=FUNCTION REQUEST + ;DS:BX POINTS TO "WHERE", TO RECEIVE RESPONSE + INT VEC_MULTIPLX ;SET VECTOR "WHERE" TO POINT TO HIS TABLE + +; COMPARE THE CONTENTS OF VECTOR 1FH WITH THE VECTOR AT "WHERE" +; WHICH POINTS TO THE CURRENTLY LOADED TABLE OF GRAFTABL. +; THE USER MAY HAVE ALTERED THE CONTENTS OF VECTOR 1FH AFTER +; HAVING PREVIOUSLY LOADED A GRAFTABL CHARACTER FONT. + XOR AX,AX ;ZERO A REG + MOV ES,AX ;LOOK AT THE VECTOR TABLE + ;ES IS STILL ASSUMED "NOTHING" + MOV AX,ES:[VEC_GRAF_CHAR * DWORD] ;AN000; + CMP AX,WHERE.VECOFF +; $IF E,AND + JNE $$IF11 + MOV AX,ES:[VEC_GRAF_CHAR * 4]+2 ;AN000; + CMP AX,WHERE.VECSEG +; $IF E ;IF THE 1FH VECTOR IS POINTING TO A GRAFTABLE + JNE $$IF11 + ; DEFINED CHARACTER TABLE. + ;NOW TO FIND OUT WHICH TABLE HE IS POINT TO. + LEA SI,TABLEUS ;GET WHERE NEW TABLE IS IN THIS LOAD MODULE + ; DS:SI POINT TO NEW TABLE +; IN THIS SEARCH, WE ARE GOING TO STEP THRU THE ARRAY OF +; TABLES WE HAVE DEFINED, COMPARING EACH ONE WITH WHATEVER "WHERE" +; POINTS TO, TO SEE IF WHAT WAS PREVIOUSLY LOADED IS LIKE ONE +; OF THE TABLES WE HAVE DEFINED HERE. A MATCH LETS US IDENTIFY +; THE ONE PREVIOUSLY LOADED; A NON-MATCH MEANS THAT WHATEVER +; THAT WAS PREVIOUSLY LOADED HAS APPARENTLY BEEN ALTERED, +; SO WHATEVER IT WAS, WE CANNOT SAY WHICH TABLE IT IS, AND SO WE +; IDENTIFY IT AS SIMPLY A NON-STANDARD TABLE. THIS SEARCH WILL +; SELECT WHICH OF TWO MESSAGES TO BE DISPLAYED. + MOV SAVESI,SI ;SAVE WHERE TABLE STARTS +; $SEARCH COMPLEX + JMP SHORT $$SS12 +$$DO12: + ADD CPIDPOINTER,CPID_L ;BUMP TO NEXT ENTRY IN CPID TABLE. ;AN000; + MOV SI,SAVESI ;GO BACK TO START OF TABLE ;AN000; + ADD SI,TABSIZE ;BUMP TO NEXT TABLE ;AN000; + MOV SAVESI,SI ;SAVE WHERE TABLE STARTS ;AN000; +; $STRTSRCH +$$SS12: +; THIS CHANGES ES TO PREVIOUSLY LOADED TABLE + + LES DI,WHERE ;GET THE CONTENTS OF THE VECTOR + ;ES:DI POINTS TO THE OLD TABLE OF CHARACTERS + ;ES IS STILL ASSUMED "NOTHING" + MOV CX,TABSIZE ;GET SIZE OF TABLE + REP CMPSB ;COMPARE ES:[DI] WITH DS:[SI] +; $EXITIF E ;IF THIS TABLE ALREADY LOADED + JNE $$IF12 + LES DI,WHERE ;RESTORE THE POINTERS TO RESIDENT TABLE + MOV AX,ES:[DI].LANID ;PICK UP 2 CHAR ID OF PREVIOUS TABLE + MOV IDXXX,AX ;REMEMBER WHAT THAT WAS PREVIOUSLY LOADED + + PUSH DS ;SET UP THE ES REG TO ;AN000; + POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; + ASSUME ES:CSEG ; ;AN000; + + MOV AX,CPIDPOINTER ;GET OFFSET TO CURRENT CPID ENTRY ;AN000; + MOV SLIST_23.SUB_VALUE,AX ;PUT CP NAME IN MSG ;AN000; + ;SO MSG IS "PREVIOUS CODE PAGE: XXX" + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA DI,LANGUAGE_NAME ;TO THE MESSAGES' VARIABLE NAME OF LANGUAGE FIELD +; MOV SI,SAVESI ;FROM THE NAME OF THE LANGUAGE +; ADD SI,OFFSET LANNAME ; IN THE NEW TABLE +; MOV CX,SIZE LANNAME ;PASS NAME OF LANGUAGE +; REP MOVSB ; TO THE MESSAGES +; ; AND THEN TELL THE OPERATOR WHAT WAS FOUND +; LEA AX,MSG2 ;XXX VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED + FIXLIST LISTPARM,.LIST ; ;AN000; +; $ORELSE ;SINCE THIS VERSION IS NOT ALREADY LOADED + JMP SHORT $$SR12 +$$IF12: + ASSUME ES:NOTHING ;SINCE BASE REG NOT RESET YET, + LEA AX,COPYRIGHT ;WHICH IS IMMEDIATELY FOLLOWING THE LAST TABLE + CMP AX,SI ;HAVE WE INCREMENTED THE INDEX TO BE BEYOND + ; THE LAST TABLE TO BE CHECKED +; $ENDLOOP BE ;QUIT IF NO NEXT TABLE TO BE LOOKED AT + JNBE $$DO12 + PUSH DS ;SET UP THE ES REG TO ;AN000; + POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; + ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA AX,MSG1 ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED + FIXLIST LISTPARM,.LIST ; ;AN000; + CALL PREV_NONSTD ;SET MSG TO SAY "NON STANDARD" ;AN000; + ; SO MSG IS "PREVIOUS CODE PAGE: NON-STANDARD" +; $ENDSRCH +$$SR12: +; $ELSE ;SINCE THE 1FH VECTOR DOES NOT POINT TO + JMP SHORT $$EN11 +$$IF11: + ; THE SAME PLACE AS "WHERE" + ; THEN THE USER MUST HAVE USED GRAFTABL TO + ; LOAD A CHAR FONT, THEN LOADED SOME OTHER + ; TABLE AND CHANGED VECTOR 1FH TO POINT TO THE NEW ONE. + PUSH DS ;SET UP THE ES REG TO ;AN000; + POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; + ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; + + CALL PREV_NONSTD ;SET MSG TO SAY "NON STANDARD" ;AN000; + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA AX,MSG1 ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED + FIXLIST LISTPARM,.LIST ; ;AN000; + MOV BAD1F,RESET ;INDICATE THAT THE 1FH VECTOR DOES NOT POINT + ; TO THE GRAFTABL FONT +; $ENDIF ;HAS 1Fh BEEN CHANGED? +$$EN11: +; $ELSE ;SINCE GRAFTABLE IS NOT LOADED, + JMP SHORT $$EN10 +$$IF10: + PUSH DS ;SET UP THE ES REG TO ;AN000; + POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; + ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; + + CALL PREV_NONE ;SET MSG TO SAY "NONE" ;AN000; + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA AX,MSG5 ;NO VER OF CHAR TABLE IS ALREADY LOADED + FIXLIST LISTPARM,.LIST ; ;AN000; +; $ENDIF ;ALREADY INSTALLED? +$$EN10: + RET +FINDTYPE ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ; ;AN000; +PREV_NONSTD PROC NEAR ; ;AN000; + PUBLIC PREV_NONSTD ; ;AN000; +;SET UP SUBLIST FOR MSGS 2-3 TO HAVE THE VARIABLE TEXT: "NON-STANDARD". + ASSUME ES:CSEG ; ;AN000; + + MOV AX,MSGNUM_NSTD.MSG_NUM ;PASS MESSAGE NUMBER OF "NON-STANDARD" ;AN000; + MOV DH,BYTE PTR MSGNUM_NSTD.MSG_CLASS+BYTE ;PASS MSG'S CLASS ;AN000; + CALL SYSGETMSG ;FIND WHERE THE TEXT OF "NON-STANDARD" IS ;AN000; + ;ES:SI=VECTOR TO MESSAGE TEXT + MOV SLIST_23.SUB_VALUE,SI ;PUT OFFSET INTO SUBLIST ;AN000; + RET ;RETURN TO CALLER ;AN000; +PREV_NONSTD ENDP ; ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ; ;AN000; +PREV_NONE PROC NEAR ; ;AN000; + PUBLIC PREV_NONE ; ;AN000; +;SET UP SUBLIST FOR MSGS 2-3 TO HAVE THE VARIABLE TEXT: "NONE". + ASSUME ES:CSEG ; ;AN000; + + MOV AX,MSGNUM_NONE.MSG_NUM ;PASS MESSAGE NUMBER OF "NONE" ;AN000; + MOV DH,BYTE PTR MSGNUM_NONE.MSG_CLASS+BYTE ;PASS MSG'S CLASS ;AN000; + CALL SYSGETMSG ;FIND WHERE THE TEXT OF "NONE" IS ;AN000; + ;ES:SI=VECTOR TO MESSAGE TEXT + MOV SLIST_23.SUB_VALUE,SI ;PUT OFFSET INTO SUBLIST ;AN000; + RET ;RETURN TO CALLER ;AN000; +PREV_NONE ENDP ; ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + FIXLIST LISTPARM,.XLIST ; ;AN000; +; HEADER +;PROCESS PROC NEAR ;LOOK AT RESPONSE TO DOS COMMAND LINE PARMS +; PUBLIC PROCESS +;INPUT: DS, ES - PSP SEG ID +;OUTPUT:EXITFL IS SET TO REFLECT EXISTING CONDITIONS + +; CALL PARSER ;LOOK AT DOS COMMAND LINE PARMS +; +; ;IF A CODEPAGE NUMBER WAS SPECIFIED +; ; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED +; ; DX = INTEGER VALUE OF CODEPAGE SPECIFIED +; ;IF /STATUS WAS SPECIFIED +; ; BX = 0 +; ;IF QUESTION MARK WAS SPECIFIED +; ; BX=-1 +; +; CALL DOFUNCTION ; RESPOND TO PARMS +; ; SETTING 'EXITFL' TO INDICATE RESULTS +; +; ASSUME ES:CSEG +; PUSH ES ;SAVE BASE REG +; MOV SI,OFFSET PARMDOS ;GET WHERE DOS PARMS START +; SUB DI,DI ;INIT INDEX TO ZERO, WHERE TO PUT PARMS IN TOKEN +; MOV CL,DS:PARMCNT ;GET HOW MANY CHARS ARE IN THE DOS COMMAND LINE +; XOR CH,CH ;CLEAR COUNTER OF OUTPUT CHARS +; CALL UPCASE ;CONVERT ANY LOWER CASE CHARS TO UPPERCASE +; +; $SEARCH +; CMP CL,0 ;ANY DOS PARMS? +; $LEAVE BE ;QUIT IF NOT PARMS +; MOV DL,BYTE PTR [SI] ;SET DL TO A PARM CHAR FROM PARMDOS IN PSP +; CMP DL,BLANK ;IGNORE THE SPECIAL CHARS: +; $IF A ; BLANK AND LOWER NUMBERED CONTROL CHARS +; CMP DL,"?" ;IS THE SPECIFIED PARAMETER +; $IF E ; A QUESTION MARK? +; MOV BYTE PTR TOKEN[DI],DL ;PUT DL CONVERTED TO TOKEN +; INC DI ;BUMP TO NEXT AVAIL SPOT IN TOKEN +; ADD CH,3 ;COUNT THIS AS AN OUTPUT CHAR,WITH NO ROOM FOR MORE +; $ELSE ;SINCE NOT "?" +; CMP DL,'0' ;IF CHAR IN RANGE OF NUMERICS +; $IF AE,AND ;UNSIGNED TEST +; CMP DL,'9' +; $IF BE +; PUSH DX +; MOV AX,ACC +; IMUL TEN ;CLOBBERS DX +; POP DX ;FIX IT BACK +; SUB DL,'0' ;CONVERT FROM NUMERIC CHAR TO BINARY +; ADD AL,DL ;ADD NEW NUMBER FROM PARM +; ADC AH,0 ;PROPOGATE CARRY +; MOV ACC,AX ;SAVE RESULTS SO FAR +; INC CH ;COUNT THIS AS AN OUTPUT CHAR +; $ELSE ;SINCE NOT A NUMERIC CHARACTER +; MOV CH,TOKEN_SIZE ;FORCE PARM ERROR, MAY BE CHANGED TO OK +; CMP CL,4 +; $IF AE ;IF AT LEAST 4 CHARS ARE PRESENT +; CMP WORD PTR [SI],"S/" ;FIRST TWO CHARS OF "/STA" +; $IF E,AND +; CMP WORD PTR [SI]+WORD,"AT" ;NEXT TWO CHARS OF "/STA" +; $IF E +; MOV BYTE PTR TOKEN[DI],'/' ;PUT "/" CONVERTED TO TOKEN +; INC DI ;BUMP TO NEXT AVAIL SPOT IN TOKEN +; MOV CH,3 ;COUNT THIS AS AN OUTPUT CHAR,WITH NO ROOM FOR MORE +; MOV CL,1 ;PRETEND THAT IS ALL OF THE COMMAND LINE THERE IS +; $ENDIF ;"/STA"? +; $ENDIF ;LENGTH 4? +; $ENDIF ;IS CHAR IN NUMERIC RANGE? +; $ENDIF ;IS PARM A QUESTION MARK? +; $ENDIF ;BLANK OR LOWER VALUED CONTROL CHARS? +; CMP CH,TOKEN_SIZE ;IS OUTPUT AREA OVERLY FULL? +; $EXITIF GE +; CALL BADPARMS ;FUSS ABOUT INVALID PARMS +; $ORELSE +; INC SI ;BUMP INDEX TO NEXT PARM CHAR IN PSP +; DEC CL ;DEC COUNT OF INPUT CHARS FROM PARMS +; $ENDLOOP +; ;SINCE CL COUNT WENT TO ZERO, +; CMP CH,0 ;ANY DOS PARMS LEFT AFTER CLEANUP? +; $IF E ;IF NONE, +; MOV WORD PTR TOKEN,437 ;MAKE IT LOOK LIKE "US" WAS SPECIFIED +; $ELSE ;SOME PARM WAS SPECIFIED +; CMP BYTE PTR TOKEN,PARM? +; $IF NE,AND ;IF NOT A QUESTION MARK, AND +; CMP BYTE PTR TOKEN,SLASH +; $IF NE ;IF NOT A SLASH (FOR /STATUS) +; MOV AX,ACC ;GET ACCUMULATOR +; MOV WORD PTR TOKEN,AX ; TO TOKEN +; $ENDIF ;QUESTION MARK? +; $ENDIF ;ANY DOS PARMS? +; CALL DOFUNCTION ;RESPOND TO PARAMETER IN "TOKEN" +; +; $ENDSRCH ;SCANNING DOS COMMAND LINE FOR PARMS +; +; POP ES ;RESTORE BASE REG +; ASSUME ES:CSEG +; +; RET +;PROCESS ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +;UPCASE PROC NEAR +;;CONVERT CHARACTERS IN PARMLIST TO UPPER CASE +;;INPUT: SI=OFFSET IN DS: TO PARM TEXT +;; CX=NUMBER OF CHARS OF PARMS +; +; OR CX,CX ;IF THERE ARE CHARS IN PARMLIST +; $IF NZ ; THEN GO LOOK AT EACH CHAR +; PUSH SI ;SAVE POINTER TO PARMS +; PUSH CX ;SAVE COUNTER OF PARMS +; $DO ;STEP THRU ALL CHARS OF PARM LIST, CONVERTING TO UPPER CASE +; MOV AL,[SI] ;GET CHAR FROM PARMLIST TO AL +; CMP AL,LOWERA ;COMPARE WITH LOWER CASE "a" +; $IF AE,AND ;UNSIGNED TEST +; CMP AL,LOWERZ ;COMPARE WITH LOWER CASE "z" +; $IF BE ;IF CHAR IS LOWER CASE +; AND AL,CASEBIT ;CONVERT TO UPPER CASE BY DELETING THE 20H BIT +; MOV [SI],AL ;RESTORE CHAR TO PARMLIST +; $ENDIF +; INC SI ;BUMP INDEX TO LOOK AT NEXT CHAR +; $ENDDO LOOP +; POP CX ;RESTORE COUNTER OF PARMS +; POP SI ;RESTORE POINTER TO PARMS +; $ENDIF ;ANY CHARS IN PARMLIST? +; +; RET +;UPCASE ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + FIXLIST LISTPARM,.LIST ; ;AN000; + HEADER ;AC000; +DOFUNCTION PROC NEAR ;RESPOND TO PARM ;AC000; + PUBLIC DOFUNCTION +;INPUT: IF A CODEPAGE NUMBER WAS SPECIFIED +; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED +; DX = INTEGER VALUE OF CODEPAGE SPECIFIED +; IF /STATUS WAS SPECIFIED +; BX = 0 +; IF QUESTION MARK WAS SPECIFIED +; BX=-1 + + ASSUME ES:CSEG + CMP BX,RETCODE_QUESTION ;IS QUESTION MARK SPECFIED? +; $IF E + JNE $$IF22 + CALL HELP ;DISPLAY RESULTS OF "?" SPECIFICATION + +; $ELSE ;SINCE QUESTION MARK IS NOT PARM SPECIFIED + JMP SHORT $$EN22 +$$IF22: + CMP BX,ZERO ;IS /STATUS SPECIFIED? +; $IF NE ;IF NOT STATUS, MUST BE REQUEST TO LOAD A TABLE + JE $$IF24 + LEA DI,MSGNUM_PREVIOUS ;"Previous Code Page: xxx" ;AN001; + CALL SENDMSG ;SEND THE MSG TO STDOUT ;AN001; + + MOV DX,[BX].LANID ;FETCH THE TWO CHAR ID FROM TABLE + CMP DX,IDXXX ;IS THIS ONE ALREADY LOADED? +; $IF NE ;IF NOT, LOAD IT + JE $$IF25 + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; MOV CX,LENGTH LANNAME ;GET LENGTH OF NAME FIELD +; LEA SI,[BX].LANNAME ;GET WHERE NAME FIELD IS IN THE NEW TABLE +; LEA DI,LANGUAGE_NAME ;WHERE WHERE TO PUT NAME IN VARIABLE MESSAGE FIELD +; REP MOVSB ;MOVE LANGUAGE NAME TO PRINTF VARIABLE FIELD + FIXLIST LISTPARM,.LIST ; ;AN000; + + MOV SI,BX ;PASS START OF CHAR TABLE + CALL MOVTAB ;PUT THIS TABLE INTO THE USA POSITION + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA AX,MSG3 ;XXXXX VER OF GRAPHIC CHAR SET HAS JUST BEEN LOADED + FIXLIST LISTPARM,.LIST ; ;AN000; + LEA DI,MSGNUM_ACTIVE ;"ACTIVE CODE PAGE: XXX" ;AN000; + MOV AX,ACTIVECPID ;GET POINTER TO CP JUST ACTIVATED ;AN000; + MOV SLIST_23.SUB_VALUE,AX ;INTO SUBLIST ;AN000; + CALL SENDMSG ;SHOW "ACTIVE CODE PAGE: XXX" ;AN000; + + CMP BAD1F,RESET ;THIS FLAG SET TO '1' MEANS INT 1FH POINTS TO +; $IF E ; A TABLE OTHER THAN ONE LOADED BY GRAFTABL + JNE $$IF26 + PUSH DS + ASSUME DS:NOTHING + LDS DX,WHERE ;SET DS:DX POINT TO PREVIOUSLY LOADED GRAFTABL FONT + MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 1FH + MOV AL,VEC_GRAF_CHAR ;INTERRUPT NUMBER TO RECEIVE NEW CONTENTS + INT VEC_DOS ;CHANGE THE VECTOR + + POP DS + ASSUME DS:CSEG +; $ENDIF ;BAD 1FH? +$$IF26: +; $ENDIF ;THIS TABLE ALREADY LOADED? +$$IF25: + FIXLIST LISTPARM,.XLIST ; ;AN000; +; ADD BX,TYPE LANGUAGE ;STEP BASE TO NEXT TABLE +; LEA AX,COPYRIGHT ;AT START OF MSGS, BEYOND LAST TABLE +; CMP BX,AX +; $ENDLOOP AE ;GO TRY THE NEXT TABLE, IF ANY +; ;NOT ANY NEXT TABLE +; CALL BADPARMS ;FUSS ABOUT INVALID PARMS +; +; $ENDSRCH ;COMPARING TOKEN WITH ID IN TABLES + FIXLIST LISTPARM,.LIST ; ;AN000; +; $ELSE ;SINCE /STATUS SPECIFIED, + JMP SHORT $$EN24 +$$IF24: + LEA DI,MSGNUM_ACTIVE ;POINT TO "ACTIVE CODE PAGE: XXX" ;AN001; + CALL SENDMSG ; VARIABLE FILLED BY "FINDTYPE" ;AN001; + + CMP IDXXX,ZERO ;SEE WHO IS LOADED, IF ANYBODY +; $IF E + JNE $$IF30 + MOV EXITFL,EXNONE ;SET EXIT CODE TO SAY NO TABLE LOADED AT ALL +; $ELSE ;SINCE SOMEONE IS LOADED, + JMP SHORT $$EN30 +$$IF30: + MOV EXITFL,EXDOS ;SAY A TABLE IS LOADED +; $ENDIF ;ANY TABLE PREVIOUSLY LOADED? +$$EN30: + +; $ENDIF ;/STATUS? +$$EN24: +; $ENDIF ;QUESTION MARK? +$$EN22: + RET +DOFUNCTION ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +MOVTAB PROC NEAR + PUBLIC MOVTAB +;INPUT: SI = OFFSET OF SOURCE TABLE +; ES = PSP + ASSUME ES:CSEG +;OUTPUT: THE SOURCE TABLE WILL BE MOVED TO ONE OF TWO PLACES, +; EITHER +; (IF THIS IS THE FIRST TIME FOR GRAFTABL) +; TO THE "TABLEUS" IN THE PSP (IF USA NOT SPECIFIED), +; AND THEN BOTH INT2FH AND TABLEUS MOVED TO MOV_DEST IN THE PSP, +; OR +; ON TOP OF THE PREVIOUS TABLE LEFT BY A PREVIOUS GRAFTABL CALL, +; AS POINTED TO BY THE VECTOR, "WHERE". + + PUSH ES ;SAVE THE PSP + CMP INSTALLED,LOADED ;IF A PREVIOUS COPY OF GRAFTABL +; $IF E ; HAS ALREADY BEEN LOADED + JNE $$IF35 + + LES DI,WHERE ;REMEMBER WHERE PREVIOUSLY TABLE WENT + ASSUME ES:NOTHING ;ES IS BASE OF OLD PREVIOUSLY LOADED TABLE + MOV CX,TABSIZE ;THE TABLE,2 CHAR ID,& LANGUAGE NAME ARE TO BE MOVED + REP MOVSB ;MOVE NEW TABLE ON TOP OF OLD TABLE + ;WHEN EXITING, LEAVE NOTHING RESIDENT +; $ELSE ;SINCE NO PREVIOUS LOAD OF GRAFTABL EXISTS, + JMP SHORT $$EN35 +$$IF35: + ASSUME ES:CSEG ;SINCE ES WAS NOT CHANGED, + MOV EXITFL,EXRES ;WHEN EXITING, LEAVE TABLE RESIDENT + ; ALONG WITH THE INT2FH HANDLER + + ;SINCE IT IS THE USA TABLE THAT IS + ; PHYSICALLY NEXT TO THE INTERRUPT HANDLER, + ; THAT PAIR OF AREAS IS WHAT WILL STAY + ; RESIDENT. IF THE USA TABLE IS NOT THE + ; DESIRED VERSION, THEN FIRST MOVE THE + ; VERSION DESIRED ON TOP OF THE USA VERSION, + ; THEN MOVE THE PAIR DOWN ON TOP OF THE PSP + ; WHERE THEY WILL STAY RESIDENT. + + LEA DI,TABLEUS ;FIND WHERE FIRST TABLE NOW IS + CMP SI,DI +; $IF NE ;IF NOT THE USA TABLE, + JE $$IF37 + MOV CX,TABSIZE ;SIZE OF THE TABLE + REP MOVSB ;MOVE THE XX TABLE ONTO THE USA TABLE +; $ENDIF +$$IF37: + MOV DI,OFFSET MOV_DEST ;WHERE TO MOVE EVERYTHING TO + LEA SI,END_PSP ;START WITH THE INT2FH HANDLER, ON THRU THE TABLE + ;ES:DI POINT TO DESTINATION, DS:SI POINT TO SOURCE + MOV CX,RESSIZE_BYTE ;GET SIZE OF TABLE + RESIDENT CODE INT HANDLER + REP MOVSB ;MOVE THE TABLE ONTO THE PSP OF THIS LOAD +; $ENDIF +$$EN35: + POP ES ;RESTORE THE PSP POINTER TO ES + RET +MOVTAB ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +HELP PROC NEAR ;RESPOND TO "?" PARM SPECIFIED + PUBLIC HELP +;INPUT: DS, ES = POINTS TO PSP +; IDXXX = CP OF WHO IS ALREADY LOADED +; EXITFL = ERROR LEVEL RET CODE +; NORMAL VALUE SAYS SOME TABLE HAS BEEN LOADED, BUT +; INVALID PARMS COULD HAVE ALREADY ALTERED THIS VALUE. +;OUTPUT: EXITFL MAY BE CHANGED TO "EXNONE", IF NO TABLE LOADED + + ASSUME ES:CSEG + LEA DI,MSGNUM_ACTIVE ;POINT TO "ACTIVE CODE PAGE: XXX" ;AN001; + CALL SENDMSG ; VARIABLE FILLED BY "FINDTYPE" ;AN001; + + CMP EXITFL,EXDOS ;IS RET CODE UNTOUCHED SO FAR? +; $IF E ;IF SO, REPORT WHO IS LOADED + JNE $$IF40 + CMP IDXXX,ZERO ;SEE WHO IS LOADED, IF ANYBODY +; $IF E + JNE $$IF41 + MOV EXITFL,EXNONE ;SET EXIT CODE TO SAY NO TABLE LOADED AT ALL +; $ENDIF ;ANY TABLE PREVIOUSLY LOADED? +$$IF41: +; $ENDIF ;RET CODE UNTOUCHED? +$$IF40: + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA AX,MSG7 ;"DOS command line parameters supported:" + FIXLIST LISTPARM,.LIST ; ;AN000; + LEA DI,MSGNUM_HELP_TITLE ;"DOS command line parameters supported:" ;AN000; + CALL SENDMSG ;DISPLAY MSG IN STDOUT ;AN000; + + LEA DI,MSGNUM_HELP_TITLE7 ;AN007; + CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; + + LEA DI,MSGNUM_HELP_TITLE8 ;AN007; + CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; + + LEA DI,MSGNUM_HELP_TITLE9 ;AN007; + CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; + + LEA DI,MSGNUM_HELP_TITLE10 ;AN007; + CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; + + FIXLIST LISTPARM,.XLIST ; ;AN000; +; LEA SI,TABLEUS ;START WITH THE FIRST TABLE +; $DO +; LEA DI,LANGUAGE_NAME ;FIND WHERE NAME OF LANGUAGE GOES +; MOV CX,LENGTH LANNAME ;HOW LONG IS THIS FIELD +; SUB BX,BX ;CLEAR INDEX TO NAME FIELD TO ZERO +; $DO +; MOV AL,[SI][BX].LANNAME ;GET CHAR FROM LANGUAGE NAME IN TABLE +; MOV [DI][BX],AL ;MOVE THAT CHAR TO MSG VARIABLE FIELD +; INC BX ;POINT TO NEXT POSITION +; $ENDDO LOOP +; MOV AX,[SI].LANID ;PICK UP THE 2 CHAR ID +; MOV IDXXX,AX ;PUT IT WHERE MSG8 IS LOOKING FOR IT +; LEA AX,MSG8 ;"%d - %s" +; CALL SENDMSG ;DISPLAY "IDXXX" AND "LANGUAGE_NAME" +; +; ADD SI,TYPE LANGUAGE ;BUMP TO THE NEXT TABLE +; LEA AX,COPYRIGHT ;IT IMMEDIATELY FOLLOWS THE LAST TABLE +; CMP SI,AX +; $ENDDO AE + FIXLIST LISTPARM,.LIST ; ;AN000; + RET +HELP ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + FIXLIST LISTPARM,.XLIST ; ;AN000; +;BADPARMS PROC NEAR +; LEA AX,MSG4 ;"INCORRECT PARAMETER" +; CALL SENDMSG +; +; CALL HELP ;DISPLAY RESULTS OF "?" SPECIFICATION +; +; MOV EXITFL,EXPAR ;ERRORLEVEL CODE TO "PARM ERROR" +; RET +;BADPARMS ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + FIXLIST LISTPARM,.LIST + + HEADER ;AN000; +SENDMSG PROC NEAR ; ;AN000; + PUBLIC SENDMSG ; ;AN000; +;INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE +;OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED +; IF CARRY CLEAR, ALL OK +; IN EITHER CASE, DI AND AX ALTERED, OTHERS OK +; = = = = = = = = = = = = + + PUSH BX ; SAVE CALLER'S REGS ;AN000; + PUSH CX ; ;AN000; + PUSH DX ; ;AN000; + PUSH SI ; ;AN000; + +; PASS PARMS TO MESSAGE HANDLER IN +; THE APPROPRIATE REGISTERS IT NEEDS. + MOV AX,[DI].MSG_NUM ;MESSAGE NUMBER ;AN000; + MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; + MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; + MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; + MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; + CALL SYSDISPMSG ;DISPLAY THE MESSAGE ;AN000; + +; $IF C ;IF THERE IS A PROBLEM ;AN000; + JNC $$IF44 + ;AX=EXTENDED ERROR NUMBER ;AN000; + LEA DI,MSGNUM_EXTERR ;GET REST OF ERROR DESCRIPTOR ;AN000; + MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; + MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; + MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; + MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; + CALL SYSDISPMSG ;TRY TO SAY WHAT HAPPENED ;AN000; + + STC ;REPORT PROBLEM ;AN000; +; $ENDIF ;PROBLEM WITH DISPLAY? ;AN000; +$$IF44: + + POP SI ;RESTORE CALLER'S REGISTERS ;AN000; + POP DX ; ;AN000; + POP CX ; ;AN000; + POP BX ; ;AN000; + FIXLIST LISTPARM,.XLIST ; ;AN000; +;;INPUT: AX = OFFSET OF MSG PARM LIST +; PUSH AX +; PUSH CS ;MATCH REQUIREMENTS OF PRINTF, WHICH IS "FAR" +; CALL PRINTF ;USING MSG PARM LIST, BUILD MSG, DISPLAY MSG +; ;PRINTF WILL POP OFF THE PARM, PUSHED FROM AX +; + FIXLIST LISTPARM,.LIST ; ;AN000; + + RET ; ;AN000; +SENDMSG ENDP ; ;AN000; + PATHLABL GRTAB ;AN006; +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABCF.ASM b/v4.0/src/CMD/GRAFTABL/GRTABCF.ASM new file mode 100644 index 0000000..a456896 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABCF.ASM @@ -0,0 +1,1196 @@ + PAGE 90,132 ;A2 + TITLE GRTABCF - CANADIAN FRENCH CHARACTER SET FOR GRAFTABL COMMAND +;This module is to be linked with the OBJ of GRTAB.SAL. Refer to the +;Prolog of that module for more complete description. + +;This module contains the binary description of the pixels that are used +;in graphics mode to define the Canadian French character set when loaded to +;interrupt 1FH by the GRAFTABL command in DOS 3.3. + IF1 + %OUT GRTABCF.ASM... + ELSE +; $OUT GRTABCF.ASM... + ENDIF +CSEG SEGMENT PARA PUBLIC +TABLECF EQU THIS BYTE + PUBLIC TABLECF + +;(note: the display of the character to the right of the decimal number +;value of this location is not necessarily the graphic that these pixels +;will produce. The displayed character is from the USA character set, and +;does not represent the language character set generated by this table.) + +;These fonts are as defined in the Canadian French Code Page = 863. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; 8 x 8 Character Set information +; for the 5153 A/N and low-res APA +; +; CODE NAME: CARIBOU (L'ACCENT) +; CODE PAGE: 863 +; DATE: 12-06-86 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 128 € + DB 01111000B + DB 11001100B + DB 11000000B + DB 11000000B + DB 11001100B + DB 01111000B + DB 00011000B + DB 01110000B +; 129 + DB 00000000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 130 ‚ + DB 00110000B + DB 01100000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B +; 131 ƒ + DB 01111100B + DB 11000110B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 132 „ + DB 01111100B + DB 11000110B + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 00000000B +; 133 … + DB 00110000B + DB 00011000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 134 † + DB 01111111B + DB 11011011B + DB 11011011B + DB 01111011B + DB 00011011B + DB 00011011B + DB 00011011B + DB 00000000B +; 135 ‡ + DB 00000000B + DB 00000000B + DB 01111100B + DB 11000000B + DB 11000000B + DB 01111100B + DB 00011000B + DB 01110000B +; 136 ˆ + DB 01111110B + DB 11000011B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; 137 ‰ + DB 01100110B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; 138 Š + DB 00011000B + DB 00001100B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; 139 ‹ + DB 01100110B + DB 00000000B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; 140 Œ + DB 01111100B + DB 11000110B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; 141 + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B +; 142 Ž + DB 00011000B + DB 00001100B + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 00000000B +; 143 + DB 00111110B + DB 01100011B + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 11001100B + DB 01111000B +; 144 + DB 00011000B + DB 00110000B + DB 11111100B + DB 11000000B + DB 11111000B + DB 11000000B + DB 11111100B + DB 00000000B +; 145 ‘ + DB 01100000B + DB 00110000B + DB 11111100B + DB 11000000B + DB 11111000B + DB 11000000B + DB 11111100B + DB 00000000B +; 146 ’ + DB 01111100B + DB 11000110B + DB 11111100B + DB 11000000B + DB 11111000B + DB 11000000B + DB 11111100B + DB 00000000B +; 147 “ + DB 01111000B + DB 11001100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 148 ” + DB 11001100B + DB 00000000B + DB 11111100B + DB 11000000B + DB 11111000B + DB 11000000B + DB 11111100B + DB 00000000B +; 149 • + DB 11001100B + DB 00000000B + DB 01111000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B +; 150 – + DB 01111000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 151 — + DB 01100000B + DB 00110000B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 152 ˜ + DB 00000000B + DB 11000110B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 11000110B + DB 00000000B +; 153 ™ + DB 01111100B + DB 10000010B + DB 00111000B + DB 01101100B + DB 11000110B + DB 01101100B + DB 00111000B + DB 00000000B +; 154 š + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 155 › + DB 00011000B + DB 00011000B + DB 01111110B + DB 11000000B + DB 11000000B + DB 01111110B + DB 00011000B + DB 00011000B +; 156 œ + DB 00111000B + DB 01101100B + DB 01100100B + DB 11110000B + DB 01100000B + DB 11100110B + DB 11111100B + DB 00000000B +; 157 + DB 01100000B + DB 00110000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 158 ž + DB 01111000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 159 Ÿ + DB 00001110B + DB 00011011B + DB 00011000B + DB 00111100B + DB 00011000B + DB 00011000B + DB 11011000B + DB 01110000B +; 160   + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00011000B +; 161 ¡ + DB 00001100B + DB 00011000B + DB 00110000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 162 ¢ + DB 00011000B + DB 00110000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 163 £ + DB 00011000B + DB 00110000B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 164 ¤ + DB 00000000B + DB 11000110B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 165 ¥ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00001100B + DB 01111000B +; 166 ¦ + DB 01110000B + DB 00011000B + DB 01110000B + DB 00011000B + DB 01110000B + DB 00000000B + DB 00000000B + DB 00000000B +; 167 § + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 168 ¨ + DB 01111110B + DB 10000001B + DB 00111100B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; 169 © + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 11000000B + DB 11000000B + DB 00000000B + DB 00000000B +; 170 ª + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 00000110B + DB 00000110B + DB 00000000B + DB 00000000B +; 171 « + DB 11100001B + DB 01100010B + DB 01100100B + DB 01101110B + DB 00010011B + DB 00100110B + DB 01001100B + DB 10001111B +; 172 ¬ + DB 11100001B + DB 01100010B + DB 01100100B + DB 01101010B + DB 00010110B + DB 00101010B + DB 01011111B + DB 10000010B +; 173 ­ + DB 11100001B + DB 00110010B + DB 01100100B + DB 00111010B + DB 11110110B + DB 00101010B + DB 01011111B + DB 10000010B +; 174 ® + DB 00000000B + DB 00110011B + DB 01100110B + DB 11001100B + DB 01100110B + DB 00110011B + DB 00000000B + DB 00000000B +; 175 ¯ + DB 00000000B + DB 11001100B + DB 01100110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00000000B + DB 00000000B +; 176 ° + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B +; 177 ± + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B +; 178 ² + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B +; 179 ³ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; 180 ´ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 181 µ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 182 ¶ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 183 · + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 00110110B + DB 00110110B + DB 00110110B +; 184 ¸ + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 185 ¹ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 186 º + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 187 » + DB 00000000B + DB 00000000B + DB 11111110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 188 ¼ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; 189 ½ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; 190 ¾ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 191 ¿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 192 À + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; 193 Á + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 194  + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 195 à + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 196 Ä + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 197 Å + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 198 Æ + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 199 Ç + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 200 È + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 201 É + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 202 Ê + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 203 Ë + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 204 Ì + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 205 Í + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 206 Î + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 207 Ï + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 208 Ð + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 209 Ñ + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 210 Ò + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 211 Ó + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 212 Ô + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; 213 Õ + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 214 Ö + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 215 × + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 216 Ø + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 217 Ù + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 218 Ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 219 Û + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; 220 Ü + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; 221 Ý + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B +; 222 Þ + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B +; 223 ß + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 224 à + DB 00000000B + DB 00000000B + DB 01110110B + DB 11011100B + DB 11001000B + DB 11011100B + DB 01110110B + DB 00000000B +; 225 á + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111000B + DB 11001100B + DB 11111000B + DB 11000000B + DB 11000000B +; 226 â + DB 00000000B + DB 11111100B + DB 11001100B + DB 11000000B + DB 11000000B + DB 11000000B + DB 11000000B + DB 00000000B +; 227 ã + DB 00000000B + DB 11111110B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B +; 228 ä + DB 11111100B + DB 11001100B + DB 01100000B + DB 00110000B + DB 01100000B + DB 11001100B + DB 11111100B + DB 00000000B +; 229 å + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011000B + DB 11011000B + DB 11011000B + DB 01110000B + DB 00000000B +; 230 æ + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01111100B + DB 01100000B + DB 11000000B +; 231 ç + DB 00000000B + DB 01110110B + DB 11011100B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B +; 232 è + DB 11111100B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00110000B + DB 11111100B +; 233 é + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 01101100B + DB 00111000B + DB 00000000B +; 234 ê + DB 00111000B + DB 01101100B + DB 11000110B + DB 11000110B + DB 01101100B + DB 01101100B + DB 11101110B + DB 00000000B +; 235 ë + DB 00011100B + DB 00110000B + DB 00011000B + DB 01111100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 236 ì + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 00000000B + DB 00000000B +; 237 í + DB 00000110B + DB 00001100B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 01100000B + DB 11000000B +; 238 î + DB 00111000B + DB 01100000B + DB 11000000B + DB 11111000B + DB 11000000B + DB 01100000B + DB 00111000B + DB 00000000B +; 239 ï + DB 01111000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 00000000B +; 240 ð + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00000000B +; 241 ñ + DB 00110000B + DB 00110000B + DB 11111100B + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B +; 242 ò + DB 01100000B + DB 00110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 00000000B + DB 11111100B + DB 00000000B +; 243 ó + DB 00011000B + DB 00110000B + DB 01100000B + DB 00110000B + DB 00011000B + DB 00000000B + DB 11111100B + DB 00000000B +; 244 ô + DB 00001110B + DB 00011011B + DB 00011011B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; 245 õ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11011000B + DB 11011000B + DB 01110000B +; 246 ö + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00110000B + DB 00110000B + DB 00000000B +; 247 ÷ + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 00000000B +; 248 ø + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 249 ù + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B +; 250 ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 251 û + DB 00001111B + DB 00001100B + DB 00001100B + DB 00001100B + DB 11101100B + DB 01101100B + DB 00111100B + DB 00011100B +; 252 ü + DB 01111000B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B + DB 00000000B + DB 00000000B +; 253 ý + DB 01110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 01111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 254 þ + DB 00000000B + DB 00000000B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00000000B + DB 00000000B +; 255 ÿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DW 863 ;TABLE ID +; include graftcfm.inc + DB "Can. French",0 ;LANGUAGE NAME, IN ASCIIZ FORMAT +;(the above "DB" is an example of the ENGLISH version of the above include file) + IF ($-CSEG) MOD 16 ;IF NOT ALREADY ON 16 BYTE BOUNDARY + DB (16-(($-CSEG) MOD 16)) DUP(0) ;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABHAN.ASM b/v4.0/src/CMD/GRAFTABL/GRTABHAN.ASM new file mode 100644 index 0000000..d94ede4 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABHAN.ASM @@ -0,0 +1,223 @@ + PAGE 90,132 ;A2 + TITLE GRTABHAN - INTERRUPT HANDLER FOR INT 2FH, GRAFTABL LOADED +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: GRTABHAN.SAL + +; DESCRIPTIVE NAME: For GRAFTABL, this is the Multiplexor Interrupt Handler + +;FUNCTION: This module contains the Interrupt Handler that will be hooked +; into the INT 2FH vector. When invoked with AL=0, it responds +; that GRAFTABL is loaded by changing AL to contain hex FF. If +; option AL=1 specified, it puts into the vector at DS:[BX] the +; pointer to the previously loaded table. + +; NOTES: +; This module should be processed with the SALUT preprocessor: + +; SALUT GRTABHAN + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; GRTAB.SAL. This module, containing a resident interrupt handler, +; should be first in the list of .OBJ to be linked. + +; At the time this handler code is made resident, the loader, GRTAB, +; made certain instruction modifications. PATCH_OFF and PATCH_SEG +; are the immediate word fields of two move word immediate to +; storage type of instructions. The loaded Revised these to +; contain the offset and the segid respectively of where the +; resident font table would be that is to stay resident. + +; Also at load time, GRTAB made another instruction modification by +; changing the JUMP DUMMY instruction's DWORD immediate field to +; contain the vector pointing to the previous owner of the +; Multiplexor Interrupt Vector. + +; ENTRY POINT: There are two entry points: one, from DOS at 100H, is +; END_PSP. The jump instruction there has nothing to do with +; the interrupt handler, but merely jumps to the GRTAB module to +; what is effectively the real DOS entry point, ENTRY_POINT. + +; The other is where the interrupt vector will be set to point, +; the entry point to the interrupt handler code: HANDLER. + +; For the rest of this module description, the HANDLER entry +; point conditions are being described. + +; INPUT: AH = Multiplexor Number. I do nothing if this is not my own. +; The value of the Multiplexor Number is defined in the EQU: +; MY_MULTIPLEXOR_NUMBER as being the value, B0H. +; AL = Function Request. There are two functions recognized: +; 0 = "GET INSTALLED STATE" +; 1 = "WHERE ARE YOU?" +; and DS:BX points to vector to receive pointer +; to the previously installed GRAFTABL table. +; If Function request is not '1', it is assumed to be '0'. + +; EXIT-NORMAL: If the proper multiplexor number is presented, respond with +; AH = 0FFH, otherwise, pass control to previous owner +; of this interrupt. + +; EXIT-ERROR: None + +; INTERNAL REFERENCES: +; ROUTINES: none + +; DATA AREAS: +; PUBLIC symbols: +; PREV_OWN Far jump direct to previous owner of interrupt 2FH. +; PATCH_OFF Offset portion of vector pointing to loaded char cable. +; PATCH_SEG Segment portion of vector pointing to loaded char table. +; HANDLER Entry point pointed to by the vector at interrupt 2FH. +; HANDLER_SIZE Location of the end of the resident code portion of the +; interrupt 2FH handler, including the 60H bytes left of +; the PSP, so this offset is relative to the start of the PSP +; after the code has been relocated downward into the PSP. +; MPEXNUM The byte containing the value defined +; as being the id checked for when INT 2FH is called used +; to identify this GRAFTABL member of the multiplexor chain. +; + +; EXTERNAL REFERENCES: +; ROUTINES: none + +; DATA AREAS: none + +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=GRAFTABL, MODULE=GRTABHAN.SAL... + ENDIF +; $SALUT (4,21,25,41) + HEADER + INCLUDE PATHMAC.INC ;AN006; +HEADER MACRO TEXT +.XLIST + SUBTTL TEXT +.LIST + PAGE + ENDM +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +VECTOR STRUC +VECOFF DW ? ;OFFSET PORTION OF VECTOR POINTER +VECSEG DW ? ;SEGMENT PORTION OF VECTOR POINTER +VECTOR ENDS +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +; DEFINITION OF FUNCTIONS TO BE REQUESTED OF INT 2FH +GET_INST_STATE EQU 0 ;FUNCTION = "GET INSTALLED STATE" +WHERE_R_U EQU 1 ;FUNCTION = "WHERE ARE YOU?" + ; REQUESTS VECTOR OF LOADED TABLE BE + ; PUT IN VECTOR POINTED TO BY DS:[BX] +RES_FUNC EQU 0F8H ;RESERVED FUNCTIONS IN RANGE OF F8 TO FF, IGNORE + +; OTHER EQUATES +PATCHED EQU 0 ;DUMMY VALUE, TO BE REPLACED AT EXECUTION TIME +INSTALLED EQU 0FFH ;RESPONSE, INDICATES THIS HANDLER IS INSTALLED +MY_MULTIPLEX_NUMBER EQU 0B0H ;THE UNIQUE IDENTIFICATION NUMBER ASSIGNED + ; TO "GRAFTABL" FOR INT 2FH +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +DUMMY_SEG SEGMENT AT 0 +DUMMY LABEL FAR ;NOTHING HERE REALLY, ONLY + ; USED TO MAKE MASM GENERATE A FAR CALL DIRECT + ; THE ABSOLUTE VECTOR IN THAT INS WILL BE PATCHED + +DUMMY_SEG ENDS +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +CSEG SEGMENT PARA PUBLIC +;THIS SEGMENT IS ALIGNED ON PARA SINCE IT IS THE START OF THE LOAD MODULE, +; WHICH IS ON A PARA BOUNDARY ANYWAY. THIS MODULE IS PADDED AT THE END +; TO A MULTIPLE OF 16 BYTES, SO THE NEXT SEGMENT WILL ALSO START +; ON A PARA BOUNDARY, WHICH WILL BE THE US CHARACTER SET TABLE. + + ASSUME CS:CSEG + + EXTRN ENTRY_POINT:NEAR + + ORG 60H + PUBLIC MOV_DEST +MOV_DEST LABEL BYTE ;WHERE THIS INTERRUPT HANDLER + ; WILL BE MOVED TO, FOLLOWED BY THE 1K TABLE. + ORG 100H + PUBLIC END_PSP ;BEGINNING HERE, THIS WILL BE MOVED TO "MOV_DEST" +END_PSP EQU $ ;ENTRY POINT FROM DOS + JMP ENTRY_POINT ;INIT THE INT HANDLER, SET UP CHAR TABLES + ; THIS JUMP TARGET IS DEFINED + ; IN THE GRTAB.SAL MODULE +; AREAS TO BE PATCHED WITHIN THIS MODULE + + PUBLIC PREV_OWN ;PATCH IS IN JMP INSTR TO PREVIOUS OWNER +;THE ABOVE PATCH IS FIXED BY THE GRTAB.SAL MODULE, JUST BEFORE ALTERING THE 2FH VECTOR + + PUBLIC PATCH_OFF ;OFFSET PORTION OF VECTOR POINTING TO LOADED CHAR TABLE + PUBLIC PATCH_SEG ;SEGMENT PORTION OF VECTOR POINTING TO LOADED CHAR TABLE +;THE ABOVE TWO PATCHES ARE FIXED BY THE GRTAB.SAL MODULE, AT THE VERY BEGINNING. + +;THIS NEXT ONE BYTE FIELD SHOULD BE KEPT AS THE BYTE JUST PREVIOUS TO THE +;INTERRUPT HANDLER ENTRY POINT AT "HANDLER". + PUBLIC MPEXNUM +MPEXNUM DB MY_MULTIPLEX_NUMBER ;PATCHING THIS ONE BYTE WILL CHANGE FOR ALL THE VALUE + HEADER +;CONDITIONS OF REGS AT ENTRY TO HANDLER: +;INPUT: AH = MULTIPLEXOR NUMBER. I DO NOTHING IF THIS IS NOT MY OWN. +; AL = FUNCTION REQUEST. THERE ARE TWO FUNCTIONS RECOGNIZED: +; 0 = "GET INSTALLED STATE" +; 1 = "WHERE ARE YOU?" +; AND DS:BX POINTS TO VECTOR TO RECEIVE POINTER +; TO THE PREVIOUSLY INSTALLED GRAFTABL TABLE. +; IF FUNCTION REQUEST IS NOT '1', IT IS ASSUMED TO BE '0'. + + PUBLIC HANDLER +HANDLER PROC FAR ;INTERRUPT HANDLER ENTRY POINT +; $SALUT (4,3,9,41) + PATHLABL GRTABHAN ;AN006; + CMP AH,MPEXNUM ;IS THIS MULTIPLEXOR REQUEST IS FOR ME? +; $IF E ;IF MY MULTIPLEX NUMBER IS CALLED + JNE $$IF1 + CMP AL,RES_FUNC ;IF IN RANGE F8-FF, DO NOTHING, JUST RETURN +; $IF B + JNB $$IF2 + CMP AL,WHERE_R_U ;IF REQUEST FOR "WHERE ARE YOU?" +; $IF E + JNE $$IF3 + ;FOR THIS REQUEST, DS:BX POINTS TO A VECTOR + ; WHICH IS TO RECEIVE THE POINTER TO + ; WHERE THE ORIGINAL TABLE WAS LOADED + + ;PASS OFFSET OF WHERE TABLE IS + MOV [BX].VECOFF,PATCHED ; TO FIRST WORD OF RESPONSE AREA +PATCH_OFF EQU WORD PTR $-2 ;THE ACTUAL VALUE OF THE IMMEDIATE IS PATCHED IN + + ;PASS SEGID OF WHERE TABLE IS + MOV [BX].VECSEG,PATCHED ; TO SECOND WORD OF RESPONSE AREA +PATCH_SEG EQU WORD PTR $-2 ;THE ACTUAL VALUE OF THE IMMEDIATE IS PATCHED IN +; $ENDIF +$$IF3: + MOV AL,INSTALLED ;SAY "INSTALLED" +; $ENDIF +$$IF2: + IRET ;RETURN TO INTERRUPT INVOKER +; $ENDIF +$$IF1: +;SINCE THE MULTIPLEX NUMBER IS FOR SOMEBODY ELSE, PASS THE CALL ON TO PREVIOUS OWNER +JMPREV: ;REFERENCED WHEN PATCHING OUT "DUMMY" + JMP DUMMY ;CHAIN ON TO THE PREVIOUS OWNER + ; OF THE VECTOR AT 1FH*4. + ; USAGE OF "DUMMY" HERE IS JUST A PLACE-HLDER + ; WHICH WILL BE REPLACED DURING EXECUTION OF LOADER + PATHLABL GRTABHAN ;AN006; +;================================================================= + HEADER +; $SALUT (4,14,20,41) +PREV_OWN EQU DWORD PTR JMPREV+1 ;REFERENCED DURING REPLACEMENT OF "HANDLER" + ; IN THE ABOVE JMP INSTRUCTION +HANDLER ENDP + IF ($-CSEG) MOD 16 ;IF NOT ALREADY ON 16 BYTE BOUNDARY + ORG ($-CSEG)+16-(($-CSEG) MOD 16) ;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF +HANDLER_SIZE EQU ($-CSEG)-(END_PSP-CSEG) ;MARK THE END OF RESIDENT EXECUTABLE ;AN000; + PUBLIC HANDLER_SIZE ; PORTION, NOT INCLUDING THE PSP ;AN000; +CSEG ENDS + END END_PSP + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABML.ASM b/v4.0/src/CMD/GRAFTABL/GRTABML.ASM new file mode 100644 index 0000000..123e9c3 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABML.ASM @@ -0,0 +1,1187 @@ + PAGE 90,132 ;AN000;A2 + TITLE GRTABML - MULTI-LINGUAL EUROPEAN STANDARD ;AN000; +;This module is to be linked with the OBJ of GRTAB.SAL. Refer to the +;Prolog of that module for more complete description. + +;This module contains the binary description of the pixels that are used +;in graphics mode to define the multi-lingual character set when loaded to +;interrupt 1FH by the GRAFTABL command in DOS 3.3. + IF1 ;AN000; + %OUT GRTABML.ASM... ;AN000; + ELSE ;AN000; +; %OUT GRTABML.ASM... + ENDIF ;AN000; +CSEG SEGMENT PARA PUBLIC ;AN000; +TABLEML EQU THIS BYTE ;AN000; + PUBLIC TABLEML ;AN000; + +;(note: the display of the character to the right of the decimal number +;value of this location is not necessarily the graphic that these pixels +;will produce. The displayed character is from the USA character set, and +;does not represent the language character set generated by this table.) + +;These fonts are as defined in the Multi-lingual Code Page = 850. + +; 128 € + DB 00000000B ;AN000; + DB 00111110B ;AN000; + DB 01100000B ;AN000; + DB 01100000B ;AN000; + DB 01100000B ;AN000; + DB 00111110B ;AN000; + DB 00001100B ;AN000; + DB 00111110B ;AN000; +; 129 + DB 00000000B ;AN000; + DB 11001100B ;AN000; + DB 00000000B ;AN000; + DB 11001100B ;AN000; + DB 11001100B ;AN000; + DB 11001100B ;AN000; + DB 01110110B ;AN000; + DB 00000000B ;AN000; +.XLIST ;AN000; +; 130 ‚ + DB 00000000B ;AN000; + DB 00011110B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11111100B ;AN000; + DB 01111110B ;AN000; + DB 00000000B ;AN000; +; 131 ƒ + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00011110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 132 „ + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 00011110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 133 … + DB 00000000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 00011110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 134 † + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 00111000B ;AN000; + DB 01111100B ;AN000; + DB 00011110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 135 ‡ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00111110B ;AN000; + DB 01100000B ;AN000; + DB 01100000B ;AN000; + DB 00111110B ;AN000; + DB 00001100B ;AN000; + DB 00111110B ;AN000; +; 136 ˆ + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11111100B ;AN000; + DB 01111110B ;AN000; + DB 00000000B ;AN000; +; 137 ‰ + DB 00000000B ;AN000; + DB 11001100B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11111100B ;AN000; + DB 01111110B ;AN000; + DB 00000000B ;AN000; +; 138 Š + DB 00000000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11111100B ;AN000; + DB 01111110B ;AN000; + DB 00000000B ;AN000; +; 139 ‹ + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 00111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 140 Œ + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 141 + DB 00000000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 00111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 142 Ž + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 143 + DB 00011000B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 144 + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 11111110B ;AN000; + DB 01100000B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11111110B ;AN000; + DB 00000000B ;AN000; +; 145 ‘ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11101110B ;AN000; + DB 00110011B ;AN000; + DB 11011110B ;AN000; + DB 01111111B ;AN000; + DB 00000000B ;AN000; +; 146 ’ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 01111111B ;AN000; + DB 11001100B ;AN000; + DB 11111111B ;AN000; + DB 11001100B ;AN000; + DB 11001111B ;AN000; + DB 00000000B ;AN000; +; 147 “ + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 148 ” + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 149 • + DB 00000000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 150 – + DB 00000000B ;AN000; + DB 01111110B ;AN000; + DB 11000011B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 151 — + DB 00000000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 152 ˜ + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111110B ;AN000; + DB 00000110B ;AN000; + DB 01111100B ;AN000; +; 153 ™ + DB 11000110B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; +; 154 š + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 155 › + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000010B ;AN000; + DB 01111100B ;AN000; + DB 11011110B ;AN000; + DB 11110110B ;AN000; + DB 01111100B ;AN000; + DB 10000000B ;AN000; +; 156 œ + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 01100100B ;AN000; + DB 11110000B ;AN000; + DB 01100000B ;AN000; + DB 11100110B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; +; 157 + DB 00000000B ;AN000; + DB 00000010B ;AN000; + DB 01110100B ;AN000; + DB 11001110B ;AN000; + DB 11010110B ;AN000; + DB 11100110B ;AN000; + DB 01011100B ;AN000; + DB 10000000B ;AN000; +; 158 ž + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 159 Ÿ + DB 00001110B ;AN000; + DB 00011011B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 11011000B ;AN000; + DB 01110000B ;AN000; +; 160   + DB 00000000B ;AN000; + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 00011110B ;AN000; + DB 01100110B ;AN000; + DB 00111011B ;AN000; + DB 00000000B ;AN000; +; 161 ¡ + DB 00000000B ;AN000; + DB 00011110B ;AN000; + DB 00000000B ;AN000; + DB 00111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 162 ¢ + DB 00000000B ;AN000; + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 163 £ + DB 00000000B ;AN000; + DB 00011110B ;AN000; + DB 00000000B ;AN000; + DB 11001100B ;AN000; + DB 11001100B ;AN000; + DB 11001100B ;AN000; + DB 01110110B ;AN000; + DB 00000000B ;AN000; +; 164 ¤ + DB 00000000B ;AN000; + DB 01110110B ;AN000; + DB 11011100B ;AN000; + DB 01111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 165 ¥ + DB 01110110B ;AN000; + DB 11011100B ;AN000; + DB 01100110B ;AN000; + DB 01110110B ;AN000; + DB 01111110B ;AN000; + DB 01101110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 166 ¦ + DB 00111100B ;AN000; + DB 01101100B ;AN000; + DB 01101100B ;AN000; + DB 00111110B ;AN000; + DB 00000000B ;AN000; + DB 01111110B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 167 § + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 01101100B ;AN000; + DB 00111000B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 168 ¨ + DB 00110000B ;AN000; + DB 00000000B ;AN000; + DB 00110000B ;AN000; + DB 01100000B ;AN000; + DB 11000000B ;AN000; + DB 11001100B ;AN000; + DB 01111000B ;AN000; + DB 00000000B ;AN000; +; 169 © + DB 00111100B ;AN000; + DB 01000010B ;AN000; + DB 10111001B ;AN000; + DB 10101101B ;AN000; + DB 10111001B ;AN000; + DB 10101101B ;AN000; + DB 01000010B ;AN000; + DB 00111100B ;AN000; +; 170 ª + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 00001100B ;AN000; + DB 00001100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 171 « + DB 11000011B ;AN000; + DB 11000110B ;AN000; + DB 11001100B ;AN000; + DB 11011110B ;AN000; + DB 00110011B ;AN000; + DB 01100110B ;AN000; + DB 11001100B ;AN000; + DB 00001111B ;AN000; +; 172 ¬ + DB 11000011B ;AN000; + DB 11000110B ;AN000; + DB 11001100B ;AN000; + DB 11011011B ;AN000; + DB 00110111B ;AN000; + DB 01101111B ;AN000; + DB 11001111B ;AN000; + DB 00000011B ;AN000; +; 173 ­ + DB 00000000B ;AN000; + DB 00011000B ;AN000; + DB 00000000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00000000B ;AN000; +; 174 ® + DB 00000000B ;AN000; + DB 00110011B ;AN000; + DB 01100110B ;AN000; + DB 11001100B ;AN000; + DB 01100110B ;AN000; + DB 00110011B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 175 ¯ + DB 00000000B ;AN000; + DB 11001100B ;AN000; + DB 01100110B ;AN000; + DB 00110011B ;AN000; + DB 01100110B ;AN000; + DB 11001100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 176 ° + DB 00100010B ;AN000; + DB 10001000B ;AN000; + DB 00100010B ;AN000; + DB 10001000B ;AN000; + DB 00100010B ;AN000; + DB 10001000B ;AN000; + DB 00100010B ;AN000; + DB 10001000B ;AN000; +; 177 ± + DB 01010101B ;AN000; + DB 10101010B ;AN000; + DB 01010101B ;AN000; + DB 10101010B ;AN000; + DB 01010101B ;AN000; + DB 10101010B ;AN000; + DB 01010101B ;AN000; + DB 10101010B ;AN000; +; 178 ² + DB 11011011B ;AN000; + DB 01110111B ;AN000; + DB 11011011B ;AN000; + DB 11101110B ;AN000; + DB 11011011B ;AN000; + DB 01110111B ;AN000; + DB 11011011B ;AN000; + DB 11101110B ;AN000; +; 179 ³ + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 180 ´ + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 11111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 181 µ + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 182 ¶ + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 183 · + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 184 ¸ + DB 00111100B ;AN000; + DB 01000010B ;AN000; + DB 10111101B ;AN000; + DB 10100001B ;AN000; + DB 10100001B ;AN000; + DB 10111101B ;AN000; + DB 01000010B ;AN000; + DB 00111100B ;AN000; +; 185 ¹ + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 11110110B ;AN000; + DB 00000110B ;AN000; + DB 11110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 186 º + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 187 » + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111110B ;AN000; + DB 00000110B ;AN000; + DB 11110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 188 ¼ + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 11110110B ;AN000; + DB 00000110B ;AN000; + DB 11111110B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 189 ½ + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 01111110B ;AN000; + DB 11000000B ;AN000; + DB 11000000B ;AN000; + DB 01111110B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 190 ¾ + DB 11001100B ;AN000; + DB 11001100B ;AN000; + DB 01111000B ;AN000; + DB 11111100B ;AN000; + DB 00110000B ;AN000; + DB 11111100B ;AN000; + DB 00110000B ;AN000; + DB 00110000B ;AN000; +; 191 ¿ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 192 À + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 193 Á + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 194  + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 195 à + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011111B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 196 Ä + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 197 Å + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 11111111B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 198 Æ + DB 00000000B ;AN000; + DB 01110110B ;AN000; + DB 11011100B ;AN000; + DB 11111000B ;AN000; + DB 00111100B ;AN000; + DB 11001100B ;AN000; + DB 01110110B ;AN000; + DB 00000000B ;AN000; +; 199 Ç + DB 00110110B ;AN000; + DB 01101100B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01111110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00000000B ;AN000; +; 200 È + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110111B ;AN000; + DB 00110000B ;AN000; + DB 00111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 201 É + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00111111B ;AN000; + DB 00110000B ;AN000; + DB 00110111B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 202 Ê + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 11110111B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 203 Ë + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 11110111B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 204 Ì + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110111B ;AN000; + DB 00110000B ;AN000; + DB 00110111B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 205 Í + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 206 Î + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 11110111B ;AN000; + DB 00000000B ;AN000; + DB 11110111B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; + DB 00110110B ;AN000; +; 207 Ï + DB 00000000B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 00000000B ;AN000; +; 208 Ð + DB 00000000B ;AN000; + DB 00011000B ;AN000; + DB 00111110B ;AN000; + DB 00001100B ;AN000; + DB 01111110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; +; 209 Ñ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 01100110B ;AN000; + DB 11110110B ;AN000; + DB 01100110B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; +; 210 Ò + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 11111110B ;AN000; + DB 01100000B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11111110B ;AN000; + DB 00000000B ;AN000; +; 211 Ó + DB 11000110B ;AN000; + DB 00000000B ;AN000; + DB 11111110B ;AN000; + DB 01100000B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11111110B ;AN000; + DB 00000000B ;AN000; +; 212 Ô + DB 11111000B ;AN000; + DB 00000000B ;AN000; + DB 01111111B ;AN000; + DB 00110000B ;AN000; + DB 00111110B ;AN000; + DB 00110000B ;AN000; + DB 01111111B ;AN000; + DB 00000000B ;AN000; +; 213 Õ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00111000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 214 Ö + DB 00011110B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 215 × + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 216 Ø + DB 01100110B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 217 Ù + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 11111000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 218 Ú + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00011111B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; +; 219 Û + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; +; 220 Ü + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; +; 221 Ý + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00000000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00000000B ;AN000; +; 222 Þ + DB 01111000B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 223 ß + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 11111111B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 224 à + DB 00011111B ;AN000; + DB 00000000B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; +; 225 á + DB 00000000B ;AN000; + DB 01111000B ;AN000; + DB 11001100B ;AN000; + DB 11111000B ;AN000; + DB 11001100B ;AN000; + DB 11111000B ;AN000; + DB 11000000B ;AN000; + DB 11000000B ;AN000; +; 226 â + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; +; 227 ã + DB 11111000B ;AN000; + DB 00000000B ;AN000; + DB 00111110B ;AN000; + DB 01100011B ;AN000; + DB 01100011B ;AN000; + DB 01100011B ;AN000; + DB 00111110B ;AN000; + DB 00000000B ;AN000; +; 228 ä + DB 00000000B ;AN000; + DB 01110110B ;AN000; + DB 11011100B ;AN000; + DB 00111100B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 229 å + DB 01110110B ;AN000; + DB 11011100B ;AN000; + DB 01111100B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 11000110B ;AN000; + DB 01111100B ;AN000; + DB 00000000B ;AN000; +; 230 æ + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11000000B ;AN000; +; 231 ç + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11100000B ;AN000; + DB 01111100B ;AN000; + DB 01100110B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11111000B ;AN000; +; 232 è + DB 11110000B ;AN000; + DB 01100000B ;AN000; + DB 01111100B ;AN000; + DB 01100110B ;AN000; + DB 01111100B ;AN000; + DB 01100000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; +; 233 é + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 234 ê + DB 01111110B ;AN000; + DB 11000011B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 235 ë + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 236 ì + DB 00000000B ;AN000; + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111110B ;AN000; + DB 00000110B ;AN000; + DB 01111100B ;AN000; +; 237 í + DB 00001111B ;AN000; + DB 00000000B ;AN000; + DB 01100110B ;AN000; + DB 01100110B ;AN000; + DB 00111100B ;AN000; + DB 00011000B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; +; 238 î + DB 11111100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 239 ï + DB 00001100B ;AN000; + DB 00011000B ;AN000; + DB 00110000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 240 ð + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 241 ñ + DB 00110000B ;AN000; + DB 00110000B ;AN000; + DB 11111100B ;AN000; + DB 00110000B ;AN000; + DB 00110000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; +; 242 ò + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; +; 243 ó + DB 11100011B ;AN000; + DB 00010110B ;AN000; + DB 01110100B ;AN000; + DB 00010011B ;AN000; + DB 11100111B ;AN000; + DB 00001111B ;AN000; + DB 01101111B ;AN000; + DB 11000011B ;AN000; +; 244 ô + DB 01111111B ;AN000; + DB 11011011B ;AN000; + DB 11011011B ;AN000; + DB 01111011B ;AN000; + DB 00011011B ;AN000; + DB 00011011B ;AN000; + DB 00011011B ;AN000; + DB 00000000B ;AN000; +; 245 õ + DB 00111110B ;AN000; + DB 01100011B ;AN000; + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 01101100B ;AN000; + DB 00111000B ;AN000; + DB 11001100B ;AN000; + DB 01111000B ;AN000; +; 246 ö + DB 00110000B ;AN000; + DB 00110000B ;AN000; + DB 00000000B ;AN000; + DB 11111100B ;AN000; + DB 00000000B ;AN000; + DB 00110000B ;AN000; + DB 00110000B ;AN000; + DB 00000000B ;AN000; +; 247 ÷ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00111000B ;AN000; + DB 00001100B ;AN000; + DB 11111000B ;AN000; +; 248 ø + DB 00111000B ;AN000; + DB 01101100B ;AN000; + DB 01101100B ;AN000; + DB 00111000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 249 ù + DB 11000110B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 250 ú + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00011000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 251 û + DB 00110000B ;AN000; + DB 01110000B ;AN000; + DB 00110000B ;AN000; + DB 00110000B ;AN000; + DB 01111000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 252 ü + DB 11110000B ;AN000; + DB 00011000B ;AN000; + DB 01110000B ;AN000; + DB 00011000B ;AN000; + DB 11110000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 253 ý + DB 01110000B ;AN000; + DB 11011000B ;AN000; + DB 00110000B ;AN000; + DB 01100000B ;AN000; + DB 11111000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +.LIST ;AN000; +; 254 þ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00111100B ;AN000; + DB 00111100B ;AN000; + DB 00111100B ;AN000; + DB 00111100B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; +; 255 ÿ + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + DB 00000000B ;AN000; + + DW 850 ;AN000;TABLE ID + DB "Multi-lingual",0 ;AN000;LANGUAGE NAME, IN ASCIIZ FORMAT + IF ($-CSEG) MOD 16 ;AN000;IF NOT ALREADY ON 16 BYTE BOUNDARY + DB (16-(($-CSEG) MOD 16)) DUP(0) ;AN000;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF ;AN000; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABMS.INC b/v4.0/src/CMD/GRAFTABL/GRTABMS.INC new file mode 100644 index 0000000..79c7e85 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABMS.INC @@ -0,0 +1,115 @@ +;:util GRAFTABL ;utility name ;AN000; +;:class 1 ;DOS extended errors: +;:class 2 ;parse errors: +;1 Too many parameters +;2 Required parameter missing +;3 Invalid switch +;4 Invalid keyword +;5 Parameter value not in allowed range +;6 Parameter value not allowed [parse ret codes 6 and 7] +;7 (undefined) +;8 Parameter format not correct +;9 (undefined) +;10 Invalid parameter [no corresponding parse ret code] +;11 Invalid parameter combination [no corresponding parse ret code] +;; +;:class A ;system messages +;:use 1 COMMON1 ;MSG 1 is always "Incorrect DOS version" +;; +;;In these next 2 messages, %1 will be replaced with one from list, 4-5, +;; or with one entry of the list at "CPID". (see GRTABMS.INC) +;; +;:def 2 "Active Code Page: %1",CR,LF +;:def 3 "Previous Code Page: %1",CR,LF + +;:def 4 "None",NULL +;:def 5 "Non-standard",NULL +;; +;:def 6 CR,LF,"DOS command line parameters supported:",CR,LF,LF +; +;:def 7 " /STA - Request Status only",CR,LF +;" ? - Display this summary of parameters",CR,LF,CR,LF + +;:def 8 " Code Pages available:",CR,LF +;" 437 - USA Graphic Character Set",CR,LF + +;:def 9 " 850 - Multi-lingual Graphic Character Set",CR,LF +;" 860 - Portuguese Graphic Character Set",CR,LF + +;:def 10 " 863 - Canadian French Graphic Character Set",CR,LF +;" 865 - Nordic Graphic Character Set",CR,LF +; +; +;:end +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + IF1 ;AN000; + %OUT COMPONENT=GRAFTABL, MODULE=GRTABMS.INC...;AN000; + ENDIF ;AN000; +;THIS MODULE IS INCLUDED IN GRTABSM.SAL. +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +SUBLIST_PARSE SUBLIST <,,FILL_OFF,FILL_SEG,PC_ID_0,SF_BITS ,MAX_0,MIN_1,PAD_BLK> ;AN003; + PUBLIC SUBLIST_PARSE ;AN003; + +; THE NEXT GROUP ARE ADDITIONAL CLASS "A" MESSAGES +; SPECIFICALLY DEFINED FOR THE GRAFTABL UTILITY +MSGNUM_ACTIVE MSG_DESC <2,,SLIST_23,ONE_SUBS> ;AN000;"Active Code Page: %1",CR,LF + PUBLIC MSGNUM_ACTIVE ;AN000; + +MSGNUM_PREVIOUS MSG_DESC <3,,SLIST_23,ONE_SUBS> ;AN000;"Previous Code Page: %1",CR,LF + PUBLIC MSGNUM_PREVIOUS ;AN000; + +;BEFORE USING THE NEXT SUBLIST, THE SEG ID OF CPID +;(OR OF "NONE" OR "NON-STANDARD") MUST BE FILLED IN +;SINCE COM FILE CANNOT HAVE SEGMENT FIXUP. + +;THIS NEXT SUBLIST IS USED BOTH MY MESSAGE 2 AND MESSAGE 3. + +SLIST_23 SUBLIST <,,,,PC_ID_1,SF_BITS ,MAX_0,MIN_1,PAD_BLK> ;AN000; + PUBLIC SLIST_23 ;AN000; +;NOTE: IN THE ABOVE SUBLIST, ID=1, THE VECTOR POINTING TO THE MSG NO. 2-3. +; WILL NEED TO BE PUT INTO THE SUBLIST DURING MESSAGES INITIALIZATION. +; TO SELECT "None" OR "Non Standard", OR TO POINT TO ELEMENT OF "CPID". + + PUBLIC CPID,CPID_L ;AN000; +CPID DB "437",NULL ;AN000; +CPID_L EQU $-CPID ;AN000;NUMBER OF CHARS IN CPID + DB "850",NULL ;AN000; + DB "860",NULL ;AN000; + DB "863",NULL ;AN000; + DB "865",NULL ;AN000; + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +MSGNUM_NONE MSG_DESC <4> ;AN000;"None",NULL + PUBLIC MSGNUM_NONE ;AN000; + +MSGNUM_NSTD MSG_DESC <5> ;AN000;"Non-Standard",NULL + PUBLIC MSGNUM_NSTD ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +;CR,LF,"DOS command line parameters supported:",CR,LF,LF ;AN000; +;" /STA - Request Status only",CR,LF ;AN000; +;" ? - Display this summary of parameters",CR,LF ;AN000; +;" Code Pages available:",CR,LF +;" 437 - USA Graphic Character Set",CR,LF ;AN000; +;" 850 - Multi-lingual Graphic Character Set",CR,LF ;AN000; +;" 860 - Portuguese Graphic Character Set",CR,LF ;AN000; +;" 863 - Canadian French Graphic Character Set",CR,LF ;AN000; +;" 865 - Nordic Graphic Character Set",CR,LF ;AN000; + +MSGNUM_HELP_TITLE MSG_DESC <6> ;AN000;NO SUBSTITUTIONS + PUBLIC MSGNUM_HELP_TITLE ;AN000; + +MSGNUM_HELP_TITLE7 MSG_DESC <7> ;AN007;NO SUBSTITUTIONS + PUBLIC MSGNUM_HELP_TITLE7 ;AN007; + +MSGNUM_HELP_TITLE8 MSG_DESC <8> ;AN007;NO SUBSTITUTIONS + PUBLIC MSGNUM_HELP_TITLE8 ;AN007; + +MSGNUM_HELP_TITLE9 MSG_DESC <9> ;AN007;NO SUBSTITUTIONS + PUBLIC MSGNUM_HELP_TITLE9 ;AN007; + +MSGNUM_HELP_TITLE10 MSG_DESC <10> ;AN007;NO SUBSTITUTIONS + PUBLIC MSGNUM_HELP_TITLE10 ;AN007; + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +;end of GRTABMS.INC diff --git a/v4.0/src/CMD/GRAFTABL/GRTABNO.ASM b/v4.0/src/CMD/GRAFTABL/GRTABNO.ASM new file mode 100644 index 0000000..d1e9333 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABNO.ASM @@ -0,0 +1,1188 @@ + PAGE 90,132 ;A2 + TITLE GRTABNO - NORDIC CHARACTER SET FOR GRAFTABL COMMAND +;This module is to be linked with the OBJ of GRTAB.SAL. Refer to the +;Prolog of that module for more complete description. + +;This module contains the binary description of the pixels that are used +;in graphics mode to define the Nordic character set when loaded to +;interrupt 1FH by the GRAFTABL command in DOS 3.3. + IF1 + %OUT GRTABNO.ASM... + ELSE +; %OUT GRTABNO.ASM... + ENDIF +CSEG SEGMENT PARA PUBLIC +TABLENO EQU THIS BYTE + PUBLIC TABLENO + +;(note: the display of the character to the right of the decimal number +;value of this location is not necessarily the graphic that these pixels +;will produce. The displayed character is from the USA character set, and +;does not represent the language character set generated by this table.) + +;These fonts are as defined in the Nordic Code Page = 865. + + DB 00111100B ;128 € + DB 01100110B + DB 01100000B + DB 01100110B + DB 00111100B + DB 00001100B + DB 00000110B + DB 00111100B +; + DB 00000000B ;129 + DB 01100110B + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00111111B + DB 00000000B +.XLIST +; + DB 00001110B ;130 ‚ + DB 00000000B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; + DB 01111110B ;131 ƒ + DB 11000011B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 01100110B ;132 „ + DB 00000000B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 01110000B ;133 … + DB 00000000B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00011000B ;134 † + DB 00011000B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00000000B ;135 ‡ + DB 00000000B + DB 00111100B + DB 01100000B + DB 01100000B + DB 00111100B + DB 00000110B + DB 00011100B +; + DB 01111110B ;136 ˆ + DB 11000011B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; + DB 01100110B ;137 ‰ + DB 00000000B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; + DB 01110000B ;138 Š + DB 00000000B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; + DB 01100110B ;139 ‹ + DB 00000000B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; + DB 01111100B ;140 Œ + DB 11000110B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; + DB 01110000B ;141 + DB 00000000B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; + DB 01100011B ;142 Ž + DB 00011100B + DB 00110110B + DB 01100011B + DB 01111111B + DB 01100011B + DB 01100011B + DB 00000000B +; + DB 00011000B ;143 + DB 00011000B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100110B + DB 00000000B +; + DB 00001110B ;144 + DB 00000000B + DB 01111110B + DB 00110000B + DB 00111100B + DB 00110000B + DB 01111110B + DB 00000000B +; + DB 00000000B ;145 ‘ + DB 00000000B + DB 01111111B + DB 00001100B + DB 01111111B + DB 11001100B + DB 01111111B + DB 00000000B +; + DB 00011111B ;146 ’ + DB 00110110B + DB 01100110B + DB 01111111B + DB 01100110B + DB 01100110B + DB 01100111B + DB 00000000B +; + DB 00111100B ;147 “ + DB 01100110B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;148 ” + DB 01100110B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;149 • + DB 01110000B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00111100B ;150 – + DB 01100110B + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00000000B ;151 — + DB 01110000B + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00000000B ;152 ˜ + DB 01100110B + DB 00000000B + DB 01100110B + DB 01100110B + DB 00111110B + DB 00000110B + DB 01111100B +; + DB 11000011B ;153 ™ + DB 00011000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00011000B + DB 00000000B +; + DB 01100110B ;154 š + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;155 › * + DB 00000000B + DB 00000000B + DB 00111100B + DB 01101110B + DB 01110110B + DB 00111100B + DB 00000000B +; + DB 00011100B ;156 œ + DB 00110110B + DB 00110010B + DB 01111000B + DB 00110000B + DB 01110011B + DB 01111110B + DB 00000000B +; + DB 01111100B ;157 * + DB 11000110B + DB 11001110B + DB 11011110B + DB 11110110B + DB 11100110B + DB 01111100B + DB 00000000B +; + DB 11111000B ;158 ž + DB 11001100B + DB 11001100B + DB 11111010B + DB 11000110B + DB 11001111B + DB 11000110B + DB 11000111B +; + DB 00001110B ;159 Ÿ + DB 00011011B + DB 00011000B + DB 00111100B + DB 00011000B + DB 00011000B + DB 11011000B + DB 01110000B +; + DB 00001110B ;160   + DB 00000000B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00011100B ;161 ¡ + DB 00000000B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; + DB 00000000B ;162 ¢ + DB 00001110B + DB 00000000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;163 £ + DB 00001110B + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00111111B + DB 00000000B +; + DB 00000000B ;164 ¤ + DB 01111100B + DB 00000000B + DB 01111100B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00000000B +; + DB 01111110B ;165 ¥ + DB 00000000B + DB 01100110B + DB 01110110B + DB 01111110B + DB 01101110B + DB 01100110B + DB 00000000B +; + DB 00111100B ;166 ¦ + DB 01101100B + DB 01101100B + DB 00111110B + DB 00000000B + DB 01111110B + DB 00000000B + DB 00000000B +; + DB 00111000B ;167 § + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 01111100B + DB 00000000B + DB 00000000B +; + DB 00011000B ;168 ¨ + DB 00000000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;169 © + DB 00000000B + DB 00000000B + DB 11111100B + DB 11000000B + DB 11000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;170 ª + DB 00000000B + DB 00000000B + DB 11111100B + DB 00001100B + DB 00001100B + DB 00000000B + DB 00000000B +; + DB 11000011B ;171 « + DB 11000110B + DB 11001100B + DB 11011110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00001111B +; + DB 11000011B ;172 ¬ + DB 11000110B + DB 11001100B + DB 11011011B + DB 00110111B + DB 01101111B + DB 11001111B + DB 00000011B +; + DB 00011000B ;173 ­ + DB 00011000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B +; + DB 00000000B ;174 ® + DB 00110011B + DB 01100110B + DB 11001100B + DB 01100110B + DB 00110011B + DB 00000000B + DB 00000000B +; + DB 00000000B ;175 ¯ * + DB 11000110B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 11000110B + DB 00000000B +; + DB 00100010B ;176 ° + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B +; + DB 01010101B ;177 ± + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B +; + DB 11011011B ;178 ² + DB 01110111B + DB 11011011B + DB 11101110B + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B +; + DB 00011000B ;179 ³ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;180 ´ + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;181 µ + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00110110B ;182 ¶ + DB 00110110B + DB 00110110B + DB 00110110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00000000B ;183 · + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00000000B ;184 ¸ + DB 00000000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00110110B ;185 ¹ + DB 00110110B + DB 11110110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;186 º + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00000000B ;187 » + DB 00000000B + DB 11111110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;188 ¼ + DB 00110110B + DB 11110110B + DB 00000110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00110110B ;189 ½ + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00011000B ;190 ¾ + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;191 ¿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;192 À + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00011000B ;193 Á + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;194  + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;195 à + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00000000B ;196 Ä + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00011000B ;197 Å + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;198 Æ + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00110110B ;199 Ç + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;200 È + DB 00110110B + DB 00110111B + DB 00110000B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;201 É + DB 00000000B + DB 00111111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;202 Ê + DB 00110110B + DB 11110111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;203 Ë + DB 00000000B + DB 11111111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;204 Ì + DB 00110110B + DB 00110111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00000000B ;205 Í + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00110110B ;206 Î + DB 00110110B + DB 11110111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00011000B ;207 Ï + DB 00011000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00110110B ;208 Ð + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;209 Ñ + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00000000B ;210 Ò + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;211 Ó + DB 00110110B + DB 00110110B + DB 00110110B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00011000B ;212 Ô + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;213 Õ + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00000000B ;214 Ö + DB 00000000B + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00110110B ;215 × + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; + DB 00011000B ;216 Ø + DB 00011000B + DB 11111111B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;217 Ù + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;218 Ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 11111111B ;219 Û + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; + DB 00000000B ;220 Ü + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; + DB 11110000B ;221 Ý + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B +; + DB 00001111B ;222 Þ + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B +; + DB 11111111B ;223 ß + DB 11111111B + DB 11111111B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;224 à + DB 00000000B + DB 00111011B + DB 01101110B + DB 01100100B + DB 01101110B + DB 00111011B + DB 00000000B +; + DB 00000000B ;225 á + DB 00111100B + DB 01100110B + DB 01111100B + DB 01100110B + DB 01111100B + DB 01100000B + DB 01100000B +; + DB 00000000B ;226 â + DB 01111110B + DB 01100110B + DB 01100000B + DB 01100000B + DB 01100000B + DB 01100000B + DB 00000000B +; + DB 00000000B ;227 ã + DB 01111111B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00000000B +; + DB 01111110B ;228 ä + DB 01100110B + DB 00110000B + DB 00011000B + DB 00110000B + DB 01100110B + DB 01111110B + DB 00000000B +; + DB 00000000B ;229 å + DB 00000000B + DB 00111111B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B +; + DB 00000000B ;230 æ + DB 00110011B + DB 00110011B + DB 00110011B + DB 00110011B + DB 00111110B + DB 00110000B + DB 01100000B +; + DB 00000000B ;231 ç + DB 00111011B + DB 01101110B + DB 00001100B + DB 00001100B + DB 00001100B + DB 00001100B + DB 00000000B +; + DB 01111110B ;232 è + DB 00011000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00011000B + DB 01111110B +; + DB 00011100B ;233 é + DB 00110110B + DB 01100011B + DB 01111111B + DB 01100011B + DB 00110110B + DB 00011100B + DB 00000000B +; + DB 00011100B ;234 ê + DB 00110110B + DB 01100011B + DB 01100011B + DB 00110110B + DB 00110110B + DB 01110111B + DB 00000000B +; + DB 00001110B ;235 ë + DB 00011000B + DB 00001100B + DB 00111110B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00000000B +; + DB 00000000B ;236 ì + DB 00000000B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 00000000B + DB 00000000B +; + DB 00000110B ;237 í + DB 00001100B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 01100000B + DB 11000000B +; + DB 00011100B ;238 î + DB 01100000B + DB 11000000B + DB 11111100B + DB 11000000B + DB 01100000B + DB 00011100B + DB 00000000B +; + DB 00111100B ;239 ï + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 00000000B +; + DB 00000000B ;240 ð + DB 01111110B + DB 00000000B + DB 01111110B + DB 00000000B + DB 01111110B + DB 00000000B + DB 00000000B +; + DB 00011000B ;241 ñ + DB 00011000B + DB 01111110B + DB 00011000B + DB 00011000B + DB 00000000B + DB 01111110B + DB 00000000B +; + DB 00110000B ;242 ò + DB 00011000B + DB 00001100B + DB 00011000B + DB 00110000B + DB 00000000B + DB 01111110B + DB 00000000B +; + DB 00001100B ;243 ó + DB 00011000B + DB 00110000B + DB 00011000B + DB 00001100B + DB 00000000B + DB 01111110B + DB 00000000B +; + DB 00001110B ;244 ô + DB 00011011B + DB 00011011B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; + DB 00011000B ;245 õ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11011000B + DB 11011000B + DB 01110000B +; + DB 00011000B ;246 ö + DB 00011000B + DB 00000000B + DB 01111110B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00000000B +; + DB 00000000B ;247 ÷ + DB 01110110B + DB 11011100B + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 00000000B +; + DB 00111000B ;248 ø + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;249 ù + DB 00000000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00000000B ;250 ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 00001111B ;251 û + DB 00001100B + DB 00001100B + DB 00001100B + DB 11101100B + DB 01101100B + DB 00111100B + DB 00011100B +; + DB 01111000B ;252 ü + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B + DB 00000000B + DB 00000000B +; + DB 01110000B ;253 ý + DB 00011000B + DB 00110000B + DB 01100000B + DB 01111000B + DB 00000000B + DB 00000000B + DB 00000000B +.LIST +; + DB 00000000B ;254 þ + DB 00000000B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00000000B + DB 00000000B +; + DB 00000000B ;255 + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DW 865 ;TABLE ID +; include graftnom.inc + DB "Nordic",0 ;LANGUAGE NAME, IN ASCIIZ FORMAT +;(the above "DB" is an example of the ENGLISH version of the above include file) + IF ($-CSEG) MOD 16 ;IF NOT ALREADY ON 16 BYTE BOUNDARY + DB (16-(($-CSEG) MOD 16)) DUP(0) ;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABP.ASM b/v4.0/src/CMD/GRAFTABL/GRTABP.ASM new file mode 100644 index 0000000..76503ac --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABP.ASM @@ -0,0 +1,144 @@ + PAGE 90,132 ;AN000;A2 + TITLE GRTABP.SAL - GRAFTABL SYSTEM COMMAND LINE PARSER ;AN000; +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: GRTABP.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of GRAFTABL. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .COM. +; The Common PARSER is then INCLUDEd. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.ASM statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.ASM statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.ASM) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT GRTABP,NUL,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; GRTAB.SAL. +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=GRAFTABL, MODULE=GRTABP.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; + INCLUDE PATHMAC.INC ;AN006; +; = = = = = = = = = = = = + +HEADER MACRO TEXT ;;AN000; +.XLIST ;AN000; + SUBTTL TEXT ;AN000; +.LIST ;AN000; + PAGE ;AN000; + ENDM ;;AN000; + +; = = = = = = = = = = = = + HEADER ;AN000; +CSEG SEGMENT PARA PUBLIC ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + +FARSW EQU 0 ;AN000;CALL THE PARSER BY NEAR CALL +DATESW EQU 0 ;AN000;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;AN000;SUPPRESS TIME CHECKING +FILESW EQU 0 ;AN000;SUPPRESS CHECKING FILE SPECIFICATION +CAPSW EQU 0 ;AN000;SUPPRESS FILE TABLE CAPS +CMPXSW EQU 0 ;AN000;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 0 ;AN000;SUPPRESS SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;AN000;SUPPRESS SUPPORT OF QUOTED STRING FORMAT +NUMSW EQU 0 ;AN000;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;AN000;SUPPRESS KEYWORD SUPPORT +SWSW EQU 1 ;AN000;DO SUPPORT SWITCHES +VAL1SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;AN000;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 1 ;AN000;DO SUPPORT VALUE DEFINITION 3 +BASESW EQU 1 ;AN005;SPECIFY, PSDATA POINTED TO BY "DS" +INCSW EQU 0 ;AN006;DO NOT INCLUDE PSDATA.INC + + +; INCLUDE PSDATA.INC ;AN006; WORK AREA FOR PARSER +.XLIST ;AN000; +.XCREF ;AN000; + INCLUDE PSDATA.INC ;AN006; WORK AREA FOR PARSER +.LIST ;AN000; +.CREF ;AN000; + PATHLABL GRTABP ;AN006; + + PUBLIC SYSPARSE ;AN000;SUBROUTINE ENTRY POINT + +; INCLUDE PARSE.ASM ;GENERATED CODE SUPPRESSED FROM LISTING ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; + INCLUDE PARSE.ASM ;AN000; +.LIST ;AN000; +.CREF ;AN000; + PATHLABL GRTABP ;AN006; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABPAR.ASM b/v4.0/src/CMD/GRAFTABL/GRTABPAR.ASM new file mode 100644 index 0000000..320161d --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABPAR.ASM @@ -0,0 +1,538 @@ + PAGE 90,132 ;AN000;A2 + TITLE GRTABPAR.SAL - LOOK AT COMMAND LINE PARMS ;AN000; +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: GRTABPAR.SAL + +; DESCRIPTIVE NAME: Handle the definition of the DOS command line parameters +; and the interface to the DOS system PARSER. + +;FUNCTION: The static data areas are prescribed by the DOS system PARSER +; to define the several parameters presented to GRAFTABL. These +; data areas are passed to the PARSER, and its responses checked +; to determine the nature of the user's specifications. Any errors +; found in the user's parameters are defined in messages back +; to the user. + +; ENTRY POINT: PARSER, near + +; INPUT: (DOS COMMAND LINE PARAMETERS) + +; [d:][path] GRAFTABL [cp|?|/STA|/STATUS] + +; WHERE +; [d:][path] - Path where the GRAFTABL command resides. + +; [cp] - Codepage number to be loaded. If blank, +; 437 is assumed + +; [?] - This requests a display of the parameters +; supported by the GRAFTABL command. + +; [/STATUS] - (May be shortened to just /STA.) This +; requests the current codepage already +; loaded by a previous GRAFTABL, if any, +; be displayed. + +; Upon entry to PARSER in this module, +; "CURRENT_PARM" = offset to start of parm text in command string +; "ORDINAL" = initialized to zero +; PSP+81H = text of DOS command line parms string + +; EXIT-NORMAL: If a Code Page number was specified +; BX = Offset to language table to be loaded +; DX = Integer value of Code Page specified +; If /STATUS (or /STA) was specified +; BX = 0 +; If Question mark was specified +; BX=-1 + +; EXIT-ERROR: If there was any problem with the parms, +; the question mark is assumed, and the appropriate +; PARSE error message is displayed. +; The Errorlevel code of "EXPAR" (3), meaning: "PARM ERROR", +; set in "EXITFL", is requested to be returned to the user. + +; INTERNAL REFERENCES: +; ROUTINES: +; PARSE_ERROR:NEAR Display the appropriate Parse error message. + +; DATA AREAS: +; The several parameter control blocks, defined by the System +; PARSER interface, defining the GRAFTABL parameters. + +; EXTERNAL REFERENCES: +; ROUTINES: +; SENDMSG:NEAR Uses Msg Descriptor to drive message handler. +; SYSPARSE:NEAR System Command Line Common Parser. + +; DATA AREAS: +; TABLEUS:BYTE First table of Fonts, happens to be the USA version. +; (Format of language Font defined in LANGUAGE STRUC.) +; EXITFL:BYTE Errorlevel return code. +; MSGNUM_PARSE:WORD Message descriptor for all parse errors. +; ACTIVECPID:WORD Pointer to CPID entry of active entry, where the +; CPID table is a set of 4 byte asciiz strings, +; each defining the number of a Code Page font. + +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: + +; SALUT GRTABPAR,NUL + +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. + +; For LINK instructions, refer to the PROLOG of the main module, +; GRTAB.SAL. + +; REVISION HISTORY: +; A001 PTM 382 display "ACTIVE" OR "PREVIOUS" CP. +; A002 PTM 474 Avoid duplicate switches +; A003 PTM 538 Display parm in error + +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=GRAFTABL, MODULE=GRTABPAR.SAL... ;AN000; + ENDIF ;AN000; +; = = = = = = = = = = = = + INCLUDE PATHMAC.INC ;AN006; +; = = = = = = = = = = = = +HEADER MACRO TEXT ;;AN000; +.XLIST ;AN000; + SUBTTL TEXT ;AN000; +.LIST ;AN000; + PAGE ;AN000; + ENDM ;;AN000; +; = = = = = = = = = = = = +; $SALUT (4,23,28,36) ;AN000; + EXTRN CPID_L:ABS ;AN000;BYTES PER CPID ENTRY + +MSG_DESC STRUC ;AN003; +MSG_NUM DW ? ;AN003;MESSAGE NUMBER (TO AX) +MSG_HANDLE DW ? ;AN003;HANDLE OF OUTPUT DEVICE (TO BX) +MSG_SUBLIST DW ? ;AN003;POINTER TO SUBLIST (TO SI) +MSG_COUNT DW ? ;AN003;SUBSTITUTION COUNT (TO CX) +MSG_CLASS DW ? ;AN003;MESSAGE CLASS (IN HIGH BYTE, TO DH) + ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL);AN003; +MSG_DESC ENDS ;AN003; + +ONE_SUBS EQU 1 ;AN003;NUMBER OF VARIABLES + +SUBLIST STRUC ;AN000; +SUB_SIZE DB ? ;AN003;SUBLIST SIZE (POINTER TO NEXT SUBLIST) +SUB_RES DB ? ;AN003;RESERVED + ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD ;AN003; +SUB_VALUE DW ? ;AN003;TIME, DATE, OR PTR TO DATA ITEM +SUB_VALUE_SEG DW ? ;AN003;SEG ID OF PTR + ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME ;AN003; + ; IF THIS IS A .COM FILE) ;AN003; +SUB_ID DB ? ;AN003;N OF %N +SUB_FLAGS DB ? ;AN003;DATA TYPE FLAGS +SUB_MAX_WIDTH DB ? ;AN003;MAXIMUM FIELD WIDTH (0=UNLIMITED) +SUB_MIN_WIDTH DB ? ;AN003;MINIMUM FIELD WIDTH +SUB_PAD_CHAR DB ? ;AN003;CHARACTER FOR PAD FIELD + ; CAN BE " ", "0" OR ",". ;AN003; + ; "," CAUSES INSERTION OF THE ACTIVE ;AN003; + ; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS. ;AN003; +SUBLIST ENDS ;AN003; + +; LOCAL EQUATES +ZERO EQU 0 ;AN000;COMPARAND FOR MISSING PARMS +RETCODE_QUESTION EQU -1 ;AN000;VALUE IN BX, IF PARM=? +EXPAR EQU 3 ;AN000;RETURN TO DOS, INVALID DOS COMND LINE PARMS +CR EQU 13 ;AN000;CARRIAGE RETURN +BLANK EQU " " ;AN002;AVOIDS DUPLICATES SWITCHES +NUL EQU 0 ;AN003;ASCIIZ DELIMITER +; = = = = = = = = = = = = +; EXIT CODES FROM SYSPARSE (WHEN CY=0) + +SYSPRM_EX_OK EQU 0 ;AN000; no error +SYSPRM_EX_MANY EQU 1 ;AN000; too many operands +SYSPRM_EX_MISSING EQU 2 ;AN000; required operand missing +SYSPRM_EX_NOT_SWLIST EQU 3 ;AN000; not in switch list provided +SYSPRM_EX_NOT_KEYLIST EQU 4 ;AN000; not in keyword list provided +SYSPRM_EX_RANGE EQU 6 ;AN000; out of range specified +SYSPRM_EX_VALUE EQU 7 ;AN000; not in value list provided +SYSPRM_EX_STRING EQU 8 ;AN000; not in string list provided +SYSPRM_EX_SYNTAX EQU 9 ;AN000; syntax error +SYSPRM_EX_EOL EQU -1 ;AN000; end of command line +; = = = = = = = = = = = = + HEADER ;AN000; +LANGUAGE STRUC ;AN000;DEFINITION OF EACH LANGUAGE TABLE +LANCHAR DB 1024 DUP(?) ;AN000;8 BYTES PER EACH OF 128 CHARACTERS +LANID DW ? ;AN000;TWO BYTE CODEPAGE ID, TO MATCH + ; GRAFTABL CMD LINE PARM +LANNAME DB 14 DUP(?) ;AN000;ASCIIZ STRING NAME OF LANGUAGE +LANGUAGE ENDS ;AN000; +; = = = = = = = = = = = = +PSP STRUC ;AN000; + DB 80H DUP (?) ;AN000;SKIP OVER FIRST HALF OF PSP +PSP_PARMLEN DB ? ;AN000;NUMBER OF BYTES IN DOS COMMAND LINE +PSP_COMMAND DB 127 DUP(?) ;AN000;TEXT OF DOS COMMAND LINE +PSP ENDS ;AN000; +; = = = = = = = = = = = = + HEADER ;AN000; +; $SALUT (4,14,19,36) ;AN000; +CSEG SEGMENT PARA PUBLIC ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + + EXTRN SENDMSG:NEAR ;AN000;USES MSG DESCRIPTOR TO DRIVE MESSAGE HANDLR + EXTRN SYSPARSE:NEAR ;AN000;SYSTEM COMMAND LINE PARSER + + EXTRN TABLEUS:BYTE ;AN000;FIRST TABLE OF FONTS + EXTRN EXITFL:BYTE ;AN000;ERRORLEVEL RETURN CODE + EXTRN MSGNUM_PARSE:WORD ;AN000;MESSAGE DESCRIPTOR FOR ALL PARSE ERRORS + EXTRN SUBLIST_PARSE:WORD ;AN003;POINTS TO INVALID PARM + EXTRN ACTIVECPID:WORD ;AN000;POINTER TO CPID ENTRY OF ACTIVE ENTRY +; = = = = = = = = = = = = + +CURRENT_PARM DW 81H ;AN000;POINTER INTO COMMAND OF NEXT OPERAND + PUBLIC CURRENT_PARM ;AN000; + +ORDINAL DW 0 ;AN000;ORDINAL NUMBER OF WHICH PARM TO PARSE + PUBLIC ORDINAL ;AN000; + +FIRST_TIME DB 0 ;AN000;INDICATES IF A PARM ALREADY FOUND +PARSE_RESULT DW 0 ;AN000;TEMP, HOLDS BX TO BE RETURNED +; If a Code Page number was specified +; BX = Offset to language table to be loaded +; DX = Integer value of Code Page specified +; If /STATUS (or /STA) was specified +; BX = 0 +; If Question mark was specified +; BX=-1 +; = = = = = = = = = = = = + HEADER ;AN000; + +;INPUT PARAMETERS CONTROL BLOCK, POINTED TO BY ES:DI WHEN CALLING PARSER + + PUBLIC PARMS ;AN000;LET LINK MAKE PARMS BLOCK ADDRESSABLE +PARMS LABEL BYTE ;AN000;PARMS CONTROL BLOCK + DW PARMSX ;AN000;POINTER TO PARMS EXTENSION + DB 0 ;AN000; NUMBER OF STRINGS (0, 1, 2) + ; NEXT LIST WOULD BE EXTRA DELIM LIST + ; (,& WHITESPACE ALWAYS) + ; NEXT LIST WOULD BE EXTRA END OF LINE LIST + ; (CR,LF,0 ALWAYS) + +;SYSTEM PARSER PARAMETER EXTENSION CONTROL BLOCK +PARMSX LABEL BYTE ;AN000;PARMS EXTENSION CONTROL BLOCK + DB 0,1 ;AN000; MIN, MAX POSITIONAL OPERANDS ALLOWED + DW CONTROL_POS ;AN000; DESCRIPTION OF POSITIONAL 1 + + DB 1 ;AN000; MAX SWITCH OPERANDS ALLOWED + DW CONTROL_SW ;AN000; DESCRIPTION OF SWITCH 1 + + DB 0 ;AN000; MAX KEYWORD OPERANDS ALLOWED + ; THERE IS NO CONTROL BLOCK + ; DEFINING KEYWORDS + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY POSITIONAL PARAMETER, OPTIONAL + +;FIRST POSITIONAL PARAMETER IS: +; [cp|?] THE CODEPAGE NUMBER, OR THE QUESTION MARK + + PUBLIC CONTROL_POS ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_POS LABEL BYTE ;AN000;FIRST POSITIONAL DESCRIPTOR FOR FILESPEC, + ; OPTIONAL + DW 2001H ;AN000; CONTROLS TYPE MATCHED + ; SELECTED BITS: "SIMPLE STRING" AND "OPTIONAL" + + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0000H ;AN000;FUNCTION_FLAGS ("NO CAPS") + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + DW RESULT ;AN000; RESULT BUFFER + DW VALS ;AN000; VALUE LISTS + DB 0 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST + +;VALUE CONTROL BLOCK FOR THE POSITIONAL PARAMETERS +VALS DB 3 ;AN000;NUMBER OF VALS DEFINITIONS (0-3) + DB 0 ;AN000;NUMBER OF RANGES (NONE) + DB 0 ;AN000;NUMBER OF NUMERIC CHOICES (NONE) + DB 6 ;AN000;NUMBER OF CHOICE STRINGS + + +;THE ORDER OF THESE VALUE DEFINITIONS IS SIGNIFICANT. THEIR ORDER MUST +;MATCH THE ORDER IN WHICH THE CORRESPONDING FONT TABLE MODULES ARE +;LINKED TOGETHER. THUE THE "VALUE RETURNED" OF 1 MEANS THE FIRST LINKED +;FONT TABLE, THE VALUE OF 5 MEANS THE FIFTH LINKED FONT TABLE, ETC. + +VAL_437 EQU 1 ;AN000;VALUE RETURNED + DB VAL_437 ;AN000; FOR: + DW S437 ;AN000;SPECIFIC CHOICE IF STRING + +VAL_850 EQU 2 ;AN000;VALUE RETURNED + DB VAL_850 ;AN000; FOR: + DW S850 ;AN000;SPECIFIC CHOICE IF STRING + +VAL_860 EQU 3 ;AN000;VALUE RETURNED + DB VAL_860 ;AN000; FOR: + DW S860 ;AN000;SPECIFIC CHOICE IF STRING + +VAL_863 EQU 4 ;AN000;VALUE RETURNED + DB VAL_863 ;AN000; FOR: + DW S863 ;AN000;SPECIFIC CHOICE IF STRING + +VAL_865 EQU 5 ;AN000;VALUE RETURNED + DB VAL_865 ;AN000; FOR: + DW S865 ;AN000;SPECIFIC CHOICE IF STRING + +VAL_QUESTION EQU 6 ;AN000;VALUE RETURNED + DB VAL_QUESTION ;AN000; FOR: + DW SQU ;AN000;SPECIFIC CHOICE IF STRING + +; SET OF ASCIIZ STRINGS, DEFINING THE POSITIONAL PARAMETER +S437 DB "437",0 ;AN000;USA +S850 DB "850",0 ;AN000;MULTI-LINGUAL +S860 DB "860",0 ;AN000;PORTUGUESE +S863 DB "863",0 ;AN000;CANADIAN FRENCH +S865 DB "865",0 ;AN000;NORDIC +SQU DB "?",0 ;AN000; + +;RESULTS CONTROL BLOCK FOR THE POSITIONAL PARAMETER, AND SWITCH PARAMETER +RESULT LABEL BYTE ;AN000; BELOW FILLED IN FOR DEFAULTS + DB 3 ;AN000; TYPE RETURNED: 0=RESERVED, + ; 1=NUMBER, 2=LIST INDEX, + ; 3=STRING, 4=COMPLEX, + ; 5=FILESPEC, 6=DRIVE + ; 7=DATE, 8=TIME + ; 9=QUOTED STRING +RESULT_TAG DB 0FFH ;AN000; MATCHED ITEM TAG +RESULT_SYN DW 0 ;AN000;POINTER TO SYNONYM + +RESULT_PTR DD ? ;AN000;OFFSET OF STRING VALUE + +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;PARSER CONTROL BLOCK DEFINING THE ONLY SWITCH, OPTIONAL + +;THE SWITCH IS "/STA" OR "/STATUS". WHEN REQUESTED, IT MEANS TO IDENTIFY +;WHAT CODEPAGE IS CURRENTLY SUPPORTED BY THE PREVIOUS GRAFTABL, IF ANY. + PUBLIC CONTROL_SW ;AN000;LET LINK MAKE THIS ADDRESSABLE +CONTROL_SW LABEL BYTE ;AN000;SWITCH DESCRIPTOR FOR /STA + DW 0001H ;AN000; CONTROLS TYPE MATCHED + ;SELECTED BITS: "OPTIONAL" + ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED) + ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE + ; CHECKED) + ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED) + ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED) + ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED) + ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED) + ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED) + ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED) + ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED) + ; 0010H=IGNORE ":" AT END IN MATCH + ; 0002H=REPEATS ALLOWED + ; 0001H=OPTIONAL + + DW 0000H ;AN000;FUNCTION_FLAGS ("NO CAPS") + ; 0001H=CAP RESULT BY FILE TABLE + ; 0002H=CAP RESULT BY CHAR TABLE + ; 0010H=REMOVE ":" AT END + + DW RESULT ;AN000; RESULT BUFFER + ;(USE SAME RESULT BUF AS DID POSITIONAL PARM) + DW NOVALS ;AN000; VALUE LISTS + DB 2 ;AN000; NUMBER OF KEYWORD/SWITCH SYNONYMS + ; IN FOLLOWING LIST +SW_STA DB "/STA",0 ;AN000; IF n >0, KEYWORD 1 +SW_STATUS DB "/STATUS",0 ;AN000;SECOND KEYWORD + +;VALUE CONTROL BLOCK FOR THE SWITCHES +NOVALS LABEL BYTE ;AN000; + DB 0 ;AN000; NUMBER OF VALUE DEFINITIONS (0 - 3) +; = = = = = = = = = = = = + PATHLABL GRTABPAR ;AN006; + HEADER ;AN000; +; $SALUT (4,4,9,36) ;AN000; +PARSER PROC NEAR ;AN000; + PUBLIC PARSER ;AN000; + +;INPUT: "CURRENT_PARM" = OFFSET TO NEXT PARM IN COMMAND STRING +; "ORDINAL" = COUNT OF NEXT PARM TO PARSE +; PSP+81H = TEXT OF DOS COMMAND LINE PARMS STRING +;OUTPUT: IF A CODEPAGE NUMBER WAS SPECIFIED +; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED +; DX = INTEGER VALUE OF CODEPAGE SPECIFIED +; IF /STATUS WAS SPECIFIED +; BX = 0 +; IF QUESTION MARK WAS SPECIFIED +; BX=-1 + +;IF THERE WAS ANY PROBLEM WITH THE PARMS, THE QUESTION MARK IS ASSUMED, +;AND "EXITFL" SET TO "EXPAR" TO INDICATE PARM ERROR. + +;IT A CP IS SPECIFIED, A STATUS REPORT IS ALWAYS GIVEN TO SAY WHAT WHAT +;THERE PREVIOUSLY, SO IF THE USER SPECIFIED A CP AND THE /STATUS SWITCH, +;THEN THE /STATUS DOES NOTHING BEYOND WHAT WOULD HAVE BEEN DONE ALREADY +;WITH JUST THE CP SPECIFICATION. I ALWAYS REPORT STATUS. THE ONLY +;REASON TO HAVE /STATUS IS TO BE ABLE TO SEE WHAT IS THERE ALREADY +;WITHOUT INVOKING THE DEFAULT OF 437 (USA) BY NOT SPECIFYING A CP. +; = = = = = = = = = = = = + +; $SEARCH COMPLEX ;AN000;LOOP THRU COMMAND LINE + JMP SHORT $$SS1 +$$DO1: + ;LOOKING AT RET CODE IN AX SET BY SYSPARSE + CMP AX,ZERO ;AN000;WERE THERE ANY ERRORS? +; $EXITIF NE ;AN000;HAD A PROBLEM + JE $$IF1 + CALL PARSE_ERROR ;AN000;DISPLAY REASON FOR ERROR + +; $ORELSE LONG ;AN000;SINCE NO PROBLEM, SO FAR + JMP $$SR1 +$$IF1: + MOV ORDINAL,CX ;AN000;SAVE UPDATED COUNT + CMP FIRST_TIME,ZERO ;AN000;DO I HAVE A PARM YET? +; $IF E ;AN000;NOT YET, LOOK AT THIS ONE JUST FOUND + JNE $$IF4 + MOV CURRENT_PARM,SI ;AN000;REMEMBER HOW FAR I GOT + CMP RESULT_SYN,ZERO ;AN000;WAS POSITIONAL PARM SPECIFIED? +; $IF E ;AN000;IF POSITIONAL PARM SPECIFIED, + JNE $$IF5 + MOV CL,RESULT_TAG ;AN000;GET ID OF SPECIFIED PARM + XOR CH,CH ;AN000;CLEAR HIGH BYTE + CMP CL,VAL_QUESTION ;AN000;WAS "?" SPECIFIED? +; $IF E ;AN000;IF "?" SPECIFIED + JNE $$IF6 + MOV BX,RETCODE_QUESTION ;AN000;INDICATE THAT "?" SPECIFIED +; $ELSE ;AN000;SINCE "?" NOT SPECIFIED + JMP SHORT $$EN6 +$$IF6: + LEA BX,TABLEUS ;AN000;GET WHERE FIRST CODEPAGE STARTS, USING CX + ; AS A COUNTER, STEP THRU THE LANGUAGE TABLES + ; UNTIL GETTING TO THE SPECIFIED ONE +; $DO COMPLEX ;AN000; + JMP SHORT $$SD8 +$$DO8: + ADD BX,TYPE LANGUAGE ;AN000;POINT TO NEXT TABLE + ADD ACTIVECPID,CPID_L ;AN000;SELECT NEXT CPID ENTRY +; $STRTDO ;AN000; +$$SD8: +; $ENDDO LOOP ;AN000;DECREMENT INDEX + LOOP $$DO8 + ;BX-OFFSET TO LANGUAGE TABLE + ; INDICATED BY POSITIONAL PARM +; $ENDIF ;AN000;"?" SPECIFIED? +$$EN6: +; $ELSE ;AN000;SINCE NOT POSITIONAL PARM SPECIFIED + JMP SHORT $$EN5 +$$IF5: + ;RESULT_SYN POINTS TO A SWITCH + XOR BX,BX ;AN000; MUST HAVE BEEN THE SWITCH, /STATUS + MOV SW_STA,BLANK ;AN002;AVOID THE DUPLICATION OF THIS SWITCH + MOV SW_STATUS,BLANK ;AN002;AVOID THE DUPLICATION OF THIS SWITCH +; $ENDIF ;AN000;POSITIONAL? +$$EN5: + INC FIRST_TIME ;AN000;INDICATE A PARM HAS BEEN FOUND +; $ELSE ;AN000;SINCE ALREADY HAVE A PARM + JMP SHORT $$EN4 +$$IF4: + PUSH SI ;AN003;SAVE NEW INDEX TO COMMAND LINE + CALL PARSE_ERROR ;AN000;FUSS ABOUT TOO MANY PARMS + + POP CURRENT_PARM ;AN000;REMEMBER HOW FAR I GOT + +; $ENDIF ;AN000;ALREADY HAVE A PARM? +$$EN4: + MOV PARSE_RESULT,BX ;AN000;SAVE THE RESULT OF THIS PARSE +; $STRTSRCH ;AN000; +$$SS1: + LEA DI,PARMS ;AN000; ES:DI = PARSE CONTROL DEFINITON + MOV SI,CURRENT_PARM ;AN000; DS:SI = COMMAND STRING, NEXT PARM + XOR DX,DX ;AN000; RESERVED, INIT TO ZERO + MOV CX,ORDINAL ;AN000; OPERAND ORDINAL, INITIALLY ZERO + CALL SYSPARSE ;AN000;LOOK AT DOS PARMS + ; AX=EXIT CODE + ; BL=TERMINATED DELIMETER CODE + ; CX=NEW OPERAND ORDINAL + ; SI=SET TO PAST SCANNED OPERAND + ; DX=SELECTED RESULT BUFFER + CMP AX,SYSPRM_EX_EOL ;AN000; IS THAT THE END OF THE PARMS? + ;IF NOT, LOOP BACK AND FIND OUT + ; WHAT THAT PARM IS +; $ENDLOOP E ;AN000;END OF LIST + JNE $$DO1 + CMP FIRST_TIME,ZERO ;AN000;FIND ANYTHING YET? +; $IF E ;AN000;IF NO PARM SPECIFIED + JNE $$IF18 + LEA BX,TABLEUS ;AN000;SPECIFY 437 (USA) AS DEFAULT +; $ELSE ;AN000;SINCE A PARM WAS FOUND + JMP SHORT $$EN18 +$$IF18: + MOV BX,PARSE_RESULT ;AN000;REMEMBER PARM ALREADY FOUND +; $ENDIF ;AN000; +$$EN18: + ;BX=-1, "?"; BX=0, "/STATUS";BX>0, CP TABLE + CMP BX,ZERO ;AN000;WAS A CP TABLE FOUND? +; $IF A ;AN000;IF A CP TABLE FOUND + JNA $$IF21 + MOV DX,[BX].LANID ;AN000;FETCH THE TWO CHAR ID FROM TABLE +; $ENDIF ;AN000; +$$IF21: +; $ENDSRCH ;AN000;FINISHED WITH DOS COMMAND LINE +$$SR1: + RET ;AN000;RETURN TO CALLER +PARSER ENDP ;AN000; +; = = = = = = = = = = = = ;AN000; + HEADER ;AN000; +PARSE_ERROR PROC NEAR ;AN000; +;INPUT: "FIRST_TIME" - IF NON-ZERO, FORCE ERROR CODE TO "TOO MANY PARMS" +; AX - ERROR NUMBER RETURNED FROM PARSE. +; SI - OFFSET INTO COMMAND OF FIRST BYTE BEYOND PARM IN ERROR +; "CURRENT_PARM" - OFFSET INTO COMMAND OF WHERE TO START LOOKING FOR PARM +;OUTPUT: APPROPRIATE ERROR MESSAGE IS DISPLAYED. +; BX IS SET TO PRETEND THAT THE "?" WAS SPECIFIED. +; "EXITFL" SET TO "EXPAR" TO INDICATE PARM ERROR. +; = = = = = = = = = = = = + + CMP FIRST_TIME,ZERO ;AN000;ANY PARMS FOUND YET? +; $IF NE ;AN000;IF PARM ALREADY FOUND + JE $$IF24 + MOV AX,SYSPRM_EX_MANY ;AN000;CHANGE RETURN CODE TO "TOO MANY PARMS" +; $ENDIF ;AN000;PARMS FOUND? +$$IF24: + MOV MSGNUM_PARSE,AX ;AN000;PASS MESSAGE NUMBER TO DESCRIPTOR + MOV AX,CURRENT_PARM ;AN003;GET POINTER TO START OF BAD PARM + CMP SI,AX ;AN003;HAS THE INDEX TO COMMAND LINE MOVED? +; $IF NE ;AN003;YES, THERE IS A FAULTY PARM + JE $$IF26 + MOV BYTE PTR [SI],NUL ;AN003;DELIMIT THE BAD PARM + MOV SUBLIST_PARSE.SUB_VALUE,AX ;AN000;POINT SUBLIST TO BAD PARM + + MOV MSGNUM_PARSE.MSG_SUBLIST,OFFSET SUBLIST_PARSE ;AN003;POINT TO SUBLIST + MOV MSGNUM_PARSE.MSG_COUNT,ONE_SUBS ;AN003;SET COUNT OF SUBLISTS TO ONE +; $ENDIF ;AN003;INDEX MOVED? +$$IF26: + LEA DI,MSGNUM_PARSE ;AN000;PASS MESSAGE DESCRIPTOR + CALL SENDMSG ;AN000;DISPLAY ERROR MESSAGE + + MOV BX,RETCODE_QUESTION ;AN000;INDICATE THAT "?" SPECIFIED + MOV EXITFL,EXPAR ;AN000;ERRORLEVEL CODE TO "PARM ERROR" + RET ;AN000;RETURN TO CALLER +PARSE_ERROR ENDP ;AN000; +; = = = = = = = = = = = = + PATHLABL GRTABPAR ;AN006; +CSEG ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABPO.ASM b/v4.0/src/CMD/GRAFTABL/GRTABPO.ASM new file mode 100644 index 0000000..e81e54b --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABPO.ASM @@ -0,0 +1,1316 @@ + PAGE 90,132 ;A2 + TITLE GRTABPO - PORTUGUESE CHARACTER SET FOR GRAFTABL COMMAND +;This module is to be linked with the OBJ of GRTAB.SAL. Refer to the +;Prolog of that module for more complete description. + +;This module contains the binary description of the pixels that are used +;in graphics mode to define the Portuguese character set when loaded to +;interrupt 1FH by the GRAFTABL command in DOS 3.3. + IF1 + %OUT GRTABPO.ASM... + ELSE +; %OUT GRTABPO.ASM... + ENDIF +CSEG SEGMENT PARA PUBLIC +TABLEPO EQU THIS BYTE + PUBLIC TABLEPO + +;(note: the display of the character to the right of the decimal number +;value of this location is not necessarily the graphic that these pixels +;will produce. The displayed character is from the USA character set, and +;does not represent the language character set generated by this table.) + +;These fonts are as defined in the Portugal Code Page = 860. + +; 128 € + DB 01111000B + DB 11001100B + DB 11000000B + DB 11001100B + DB 01111000B + DB 00011000B + DB 00001100B + DB 01111000B + +; 129 + DB 00000000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01110110B + DB 00000000B +.XLIST + +; 130 ‚ + DB 00011100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B + +; 131 ƒ + DB 01111110B + DB 10000001B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111011B + DB 00000000B + +; 132 „ + DB 01110010B + DB 10001100B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01110110B + DB 00000000B + +; 133 … + DB 11100000B + DB 00000000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01110110B + DB 00000000B + +; 134 † + DB 00011100B + DB 00000000B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11001100B + DB 00000000B + +; 135 ‡ + DB 00000000B + DB 00000000B + DB 01111000B + DB 11000000B + DB 11000000B + DB 01111100B + DB 00011000B + DB 00111000B + +; 136 ˆ + DB 01111110B + DB 10000001B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B + +; 137 ‰ + DB 01111110B + DB 10000001B + DB 01111110B + DB 00110000B + DB 00111100B + DB 00110000B + DB 01111110B + DB 00000000B + +; 138 Š + DB 11100000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B + +; 139 ‹ + DB 00011100B + DB 00000000B + DB 01111000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B + +; 140 Œ + DB 01111100B + DB 10000010B + DB 00000000B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 00000000B + +; 141 + DB 11100000B + DB 00000000B + DB 01110000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B + +; 142 Ž + DB 01110110B + DB 11011100B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11001100B + DB 00000000B + +; 143 + DB 01111000B + DB 10000100B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11001100B + DB 00000000B + +; 144 + DB 00011100B + DB 00000000B + DB 11111100B + DB 01100000B + DB 01111000B + DB 01100000B + DB 11111100B + DB 00000000B + +; 145 ‘ + DB 11100000B + DB 00000000B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11001100B + DB 00000000B + +; 146 ’ + DB 11100000B + DB 00000000B + DB 11111100B + DB 01100000B + DB 01111000B + DB 01100000B + DB 11111100B + DB 00000000B + +; 147 “ + DB 01111000B + DB 11001100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 148 ” + DB 01101100B + DB 11011000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 149 • + DB 00000000B + DB 11100000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 150 – + DB 00011100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 151 — + DB 00000000B + DB 11100000B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01110110B + DB 00000000B + +; 152 ˜ + DB 11100000B + DB 00000000B + DB 01111000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B + +; 153 ™ + DB 01110110B + DB 11011100B + DB 00000000B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 00000000B + +; 154 š + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 155 › + DB 00011000B + DB 00011000B + DB 01111110B + DB 11000000B + DB 11000000B + DB 01111110B + DB 00011000B + DB 00011000B + +; 156 œ + DB 00111000B + DB 01101100B + DB 01100100B + DB 11110000B + DB 01100000B + DB 11100110B + DB 11111100B + DB 00000000B + +; 157 * + DB 11100000B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 158 ž + DB 11111000B + DB 11001100B + DB 11001100B + DB 11111010B + DB 11000110B + DB 11001111B + DB 11000110B + DB 11000111B + +; 159 Ÿ * + DB 00011110B + DB 00000000B + DB 00000000B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 00000000B + +; 160   + DB 00011100B + DB 00000000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01110110B + DB 00000000B + +; 161 ¡ + DB 00011100B + DB 00000000B + DB 01110000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B + +; 162 ¢ + DB 00000000B + DB 00011100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 163 £ + DB 00000000B + DB 00011100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01110110B + DB 00000000B + +; 164 ¤ + DB 00000000B + DB 11111000B + DB 00000000B + DB 11111000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 00000000B + +; 165 ¥ + DB 11111100B + DB 00000000B + DB 11001100B + DB 11101100B + DB 11111100B + DB 11011100B + DB 11001100B + DB 00000000B + +; 166 ¦ + DB 00111100B + DB 01101100B + DB 01101100B + DB 00111110B + DB 00000000B + DB 01111110B + DB 00000000B + DB 00000000B + +; 167 § + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 01111100B + DB 00000000B + DB 00000000B + +; 168 ¨ + DB 00110000B + DB 00000000B + DB 00110000B + DB 01100000B + DB 11000000B + DB 11001100B + DB 01111000B + DB 00000000B + +; 169 © * + DB 11110000B + DB 00000000B + DB 00000000B + DB 01111100B + DB 11000110B + DB 11000110B + DB 01111100B + DB 00000000B + +; 170 ª + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111100B + DB 00001100B + DB 00001100B + DB 00000000B + DB 00000000B + +; 171 « + DB 11000011B + DB 11000110B + DB 11001100B + DB 11011110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00001111B + +; 172 ¬ + DB 11000011B + DB 11000110B + DB 11001100B + DB 11011011B + DB 00110111B + DB 01101111B + DB 11001111B + DB 00000011B + +; 173 ­ + DB 00011000B + DB 00011000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B + +; 174 ® + DB 00000000B + DB 00110011B + DB 01100110B + DB 11001100B + DB 01100110B + DB 00110011B + DB 00000000B + DB 00000000B + +; 175 ¯ + DB 00000000B + DB 11001100B + DB 01100110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00000000B + DB 00000000B + +; 176 ° + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + +; 177 ± + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + +; 178 ² + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B + +; 179 ³ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 180 ´ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 181 µ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 182 ¶ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B + +; 183 · + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 00110110B + DB 00110110B + DB 00110110B + +; 184 ¸ + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 185 ¹ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B + +; 186 º + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + +; 187 » + DB 00000000B + DB 00000000B + DB 11111110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B + +; 188 ¼ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B + +; 189 ½ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B + +; 190 ¾ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 191 ¿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 192 À + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 193 Á + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 194  + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 195 à + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 196 Ä + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 197 Å + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 198 Æ + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 199 Ç + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 200 È + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 201 É + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 202 Ê + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 203 Ë + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 204 Ì + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 205 Í + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 206 Î + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 207 Ï + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 208 Ð + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 209 Ñ + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 210 Ò + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 211 Ó + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 212 Ô + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B + +; 213 Õ + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 214 Ö + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 215 × + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B + +; 216 Ø + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 217 Ù + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 218 Ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B + +; 219 Û + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + +; 220 Ü + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + +; 221 Ý + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + +; 222 Þ + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + +; 223 ß + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 224 à + DB 00000000B + DB 00000000B + DB 01110110B + DB 11011100B + DB 11001000B + DB 11011100B + DB 01110110B + DB 00000000B + +; 225 á + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111000B + DB 11001100B + DB 11111000B + DB 11000000B + DB 11000000B + +; 226 â + DB 00000000B + DB 11111100B + DB 11001100B + DB 11000000B + DB 11000000B + DB 11000000B + DB 11000000B + DB 00000000B + +; 227 ã + DB 00000000B + DB 11111110B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B + +; 228 ä + DB 11111100B + DB 11001100B + DB 01100000B + DB 00110000B + DB 01100000B + DB 11001100B + DB 11111100B + DB 00000000B + +; 229 å + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011000B + DB 11011000B + DB 11011000B + DB 01110000B + DB 00000000B + +; 230 æ + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01111100B + DB 01100000B + DB 11000000B + +; 231 ç + DB 00000000B + DB 01110110B + DB 11011100B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B + +; 232 è + DB 11111100B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00110000B + DB 11111100B + +; 233 é + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 01101100B + DB 00111000B + DB 00000000B + +; 234 ê + DB 00111000B + DB 01101100B + DB 11000110B + DB 11000110B + DB 01101100B + DB 01101100B + DB 11101110B + DB 00000000B + +; 235 ë + DB 00011100B + DB 00110000B + DB 00011000B + DB 01111100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B + +; 236 ì + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 00000000B + DB 00000000B + +; 237 í + DB 00000110B + DB 00001100B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 01100000B + DB 11000000B + +; 238 î + DB 00111000B + DB 01100000B + DB 11000000B + DB 11111000B + DB 11000000B + DB 01100000B + DB 00111000B + DB 00000000B + +; 239 ï + DB 01111000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 00000000B + +; 240 ð + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00000000B + +; 241 ñ + DB 00110000B + DB 00110000B + DB 11111100B + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B + +; 242 ò + DB 01100000B + DB 00110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 00000000B + DB 11111100B + DB 00000000B + +; 243 ó + DB 00011000B + DB 00110000B + DB 01100000B + DB 00110000B + DB 00011000B + DB 00000000B + DB 11111100B + DB 00000000B + +; 244 ô + DB 00001110B + DB 00011011B + DB 00011011B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + +; 245 õ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11011000B + DB 11011000B + DB 01110000B + +; 246 ö + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00110000B + DB 00110000B + DB 00000000B + +; 247 ÷ + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 00000000B + +; 248 ø + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 249 ù + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 250 ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B + +; 251 û + DB 00001111B + DB 00001100B + DB 00001100B + DB 00001100B + DB 11101100B + DB 01101100B + DB 00111100B + DB 00011100B + +; 252 ü + DB 01111000B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B + DB 00000000B + DB 00000000B + +; 253 ý + DB 01110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 01111000B + DB 00000000B + DB 00000000B + DB 00000000B +.LIST + +; 254 þ + DB 00000000B + DB 00000000B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00000000B + DB 00000000B + +; 255 ÿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; + DW 860 ;TABLE ID +; include graftpom.inc + DB "Portuguese",0 ;LANGUAGE NAME, IN ASCIIZ FORMAT +;(the above "DB" is an example of the ENGLISH version of the above include file) + IF ($-CSEG) MOD 16 ;IF NOT ALREADY ON 16 BYTE BOUNDARY + DB (16-(($-CSEG) MOD 16)) DUP(0) ;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABSM.ASM b/v4.0/src/CMD/GRAFTABL/GRTABSM.ASM new file mode 100644 index 0000000..bcb4c9e --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABSM.ASM @@ -0,0 +1,152 @@ + PAGE 90,132 ;AN000;A2 + TITLE GRTABSM.SAL - GRAFTABL SYSTEM MESSAGES ;AN000; +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: GRTABSM.SAL +; +; DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT +; configuration expected by the modules of GRAFTABL. +; +;FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is made a +; part of the GRAFTABL module by using INCLUDE to bring in the +; common portion, in SYSMSG.INC. This included code contains +; the routines to initialize for message services, to find +; where a particular message is, and to display a message. +; +; ENTRY POINT: SYSDISPMSG:near +; SYSGETMSG:near +; SYSLOADMSG:near +; +; INPUT: +; AX = MESSAGE NUMBER +; BX = HANDLE TO DISPLAY TO (-1 means use DOS functions 1-12) +; SI = OFFSET IN ES: OF SUBLIST, OR 0 IF NONE +; CX = NUMBER OF %PARMS, 0 IF NONE +; DX = CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW +; CALL SYSDISPMSG ;DISPLAY THE MESSAGE + +; If carry set, extended error already called: +; AX = EXTENDED MESSAGE NUMBER +; BH = ERROR CLASS +; BL = SUGGESTED ACTION +; CH = LOCUS +; _ _ _ _ _ _ _ _ _ _ _ _ + +; AX = MESSAGE NUMBER +; DH = MESSAGE CLASS (1=DOS EXTENDED ERROR, 2=PARSE ERROR, -1=UTILITY MSG) +; CALL SYSGETMSG ;FIND WHERE A MSG IS + +; If carry set, error +; CX = 0, MESSAGE NOT FOUND +; If carry NOT set, ok, and resulting regs are: +; CX = MESSAGE SIZE +; DS:SI = MESSAGE TEXT +; _ _ _ _ _ _ _ _ _ _ _ _ + +; CALL SYSLOADMSG ;SET ADDRESSABILITY TO MSGS, CHECK DOS VERSION +; If carry not set: +; CX = SIZE OF MSGS LOADED + +; If carry is set, regs preset up for SYSDISPMSG, as: +; AX = ERROR CODE IF CARRY SET +; AX = 1, INCORRECT DOS VERSION +; DH =-1, (Utility msg) +; OR, +; AX = 1, Error loading messages +; DH = 0, (Message manager error) +; BX = STDERR +; CX = NO_REPLACE +; DL = NO_INPUT +; +; EXIT-NORMAL: CARRY is not set +; +; EXIT-ERROR: CARRY is set +; Call Get Extended Error for reason code, for SYSDISPMSG and +; SYSGETMSG. +; +; INTERNAL REFERENCES: +; ROUTINES: (Generated by the MSG_SERVICES macro) +; SYSLOADMSG +; SYSDISPMSG +; SYSGETMSG +; +; DATA AREAS: +; INCLUDE GRTABMS.INC ;message defining control blocks +; INCLUDE SYSMSG.INC ;Permit System Message handler definition +; INCLUDE COPYRIGH.INC ;Standard copyright notice +; INCLUDE MSGHAN.INC ;Defines message control blocks STRUCs +; INCLUDE VERSIONA.INC ;INCLUDEd by code generated by SYSMSG.INC +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the SALUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT GRTABSM,NUL,; +; +; To assemble these modules, the alphabetical or sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; GRTAB.SAL. +; +; COPYRIGHT: "Version 4.00 (C)Copyright Microsoft Corp 1981,1988 " +; "Licensed Material - Program Property of Microsoft" +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 ;AN000; + %OUT COMPONENT=GRAFTABL, MODULE=GRTABSM.SAL... ;AN000; + ENDIF ;AN000; + INCLUDE PATHMAC.INC ;AN006; +; INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; +.XLIST ;AN000; + INCLUDE SYSMSG.INC ;AN000;PERMIT SYSTEM MESSAGE HANDLER DEFINITION +.LIST ;AN000; + MSG_UTILNAME ;AN000;IDENTIFY THE COMPONENT +; = = = = = = = = = = = = +; $SALUT (4,12,18,36) ;AN000; +CSEG SEGMENT PARA PUBLIC ;AN000; + ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000; + +;THIS MODULE IS EXPECTED TO BE LINKED DIRECTLY FOLLOWING THE LAST +;FONT DEFINITION MODULE, SINCE THE VARIABLE, "COPYRIGHT", IS USED +;TO DETERMINE THE END OF THE ARRAY OF FONT TABLES. + + PUBLIC COPYRIGHT ;AN000; +COPYRIGHT LABEL BYTE ;AN006; +;(deleted ;AN004;) INCLUDE COPYRIGH.INC ;(this is now being done in MSG_SERVICES) + + INCLUDE MSGHAN.INC ;AN000;DEFINE MESSAGE HANDLER CONTROL BLOCKS + INCLUDE GRTABMS.INC ;AN000;DEFINE THE MESSAGES, AND CONTROL BLOCKS + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; +; = = = = = = = = = = = = + PUBLIC SYSLOADMSG ;AN000; + PUBLIC SYSDISPMSG ;AN000; + PUBLIC SYSGETMSG ;AN000; + PATHLABL GRTABSM ;AN006; + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=NO INPUTmsg + ;DEFAULT=NO NUMmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg +; MSG_SERVICES ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; + MSG_SERVICES ;AN000; +.LIST ;AN000; +.CREF ;AN000; +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + PATHLABL GRTABSM ;AN006; + + +CSEG ENDS ;AN000; + +include msgdcl.inc + + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/GRTABUS.ASM b/v4.0/src/CMD/GRAFTABL/GRTABUS.ASM new file mode 100644 index 0000000..f3a4536 --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/GRTABUS.ASM @@ -0,0 +1,1182 @@ + PAGE 90,132 ;A2 + TITLE GRTABUS - USA CHARACTER SET FOR THE GRAFTABL COMMAND +;This module is to be linked with the OBJ of GRTAB.SAL. Refer to the +;Prolog of that module for more complete description. + +;This module contains the binary description of the pixels that are used +;in graphics mode to define the USA character set when loaded to +;interrupt 1FH by the GRAFTABL command in DOS 3.3. + IF1 + %OUT GRTABUS.ASM... + ELSE +; %OUT GRTABUS.ASM... + ENDIF +CSEG SEGMENT PARA PUBLIC +TABLEUS EQU THIS BYTE + PUBLIC TABLEUS + +; 128 € + DB 01111000B + DB 11001100B + DB 11000000B + DB 11001100B + DB 01111000B + DB 00011000B + DB 00001100B + DB 01111000B +; 129 + DB 00000000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 130 ‚ + DB 00011100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B +; 131 ƒ + DB 01111110B + DB 11000011B + DB 00111100B + DB 00000110B + DB 00111110B + DB 01100110B + DB 00111111B + DB 00000000B +; 132 „ + DB 11001100B + DB 00000000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 133 … + DB 11100000B + DB 00000000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 134 † + DB 00110000B + DB 00110000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 135 ‡ + DB 00000000B + DB 00000000B + DB 01111000B + DB 11000000B + DB 11000000B + DB 01111000B + DB 00001100B + DB 00111000B +; 136 ˆ + DB 01111110B + DB 11000011B + DB 00111100B + DB 01100110B + DB 01111110B + DB 01100000B + DB 00111100B + DB 00000000B +; 137 ‰ + DB 11001100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B +; 138 Š + DB 11100000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11000000B + DB 01111000B + DB 00000000B +; 139 ‹ + DB 11001100B + DB 00000000B + DB 01110000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B +; 140 Œ + DB 01111100B + DB 11000110B + DB 00111000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00111100B + DB 00000000B +; 141 + DB 11100000B + DB 00000000B + DB 01110000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B +; 142 Ž + DB 11000110B + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 11000110B + DB 00000000B +; 143 + DB 00110000B + DB 00110000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111100B + DB 11001100B + DB 00000000B +; 144 + DB 00011100B + DB 00000000B + DB 11111100B + DB 01100000B + DB 01111000B + DB 01100000B + DB 11111100B + DB 00000000B +; 145 ‘ + DB 00000000B + DB 00000000B + DB 01111111B + DB 00001100B + DB 01111111B + DB 11001100B + DB 01111111B + DB 00000000B +; 146 ’ + DB 00111110B + DB 01101100B + DB 11001100B + DB 11111110B + DB 11001100B + DB 11001100B + DB 11001110B + DB 00000000B +; 147 “ + DB 01111000B + DB 11001100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 148 ” + DB 00000000B + DB 11001100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 149 • + DB 00000000B + DB 11100000B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 150 – + DB 01111000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 151 — + DB 00000000B + DB 11100000B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 152 ˜ + DB 00000000B + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 01111100B + DB 00001100B + DB 11111000B +; 153 ™ + DB 11000011B + DB 00011000B + DB 00111100B + DB 01100110B + DB 01100110B + DB 00111100B + DB 00011000B + DB 00000000B +; 154 š + DB 11001100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 155 › + DB 00011000B + DB 00011000B + DB 01111110B + DB 11000000B + DB 11000000B + DB 01111110B + DB 00011000B + DB 00011000B +; 156 œ + DB 00111000B + DB 01101100B + DB 01100100B + DB 11110000B + DB 01100000B + DB 11100110B + DB 11111100B + DB 00000000B +; 157 + DB 11001100B + DB 11001100B + DB 01111000B + DB 11111100B + DB 00110000B + DB 11111100B + DB 00110000B + DB 00110000B +; 158 ž + DB 11111000B + DB 11001100B + DB 11001100B + DB 11111010B + DB 11000110B + DB 11001111B + DB 11000110B + DB 11000111B +; 159 Ÿ + DB 00001110B + DB 00011011B + DB 00011000B + DB 00111100B + DB 00011000B + DB 00011000B + DB 11011000B + DB 01110000B +; 160   + DB 00011100B + DB 00000000B + DB 01111000B + DB 00001100B + DB 01111100B + DB 11001100B + DB 01111110B + DB 00000000B +; 161 ¡ + DB 00111000B + DB 00000000B + DB 01110000B + DB 00110000B + DB 00110000B + DB 00110000B + DB 01111000B + DB 00000000B +; 162 ¢ + DB 00000000B + DB 00011100B + DB 00000000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 163 £ + DB 00000000B + DB 00011100B + DB 00000000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 01111110B + DB 00000000B +; 164 ¤ + DB 00000000B + DB 11111000B + DB 00000000B + DB 11111000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 00000000B +; 165 ¥ + DB 11111100B + DB 00000000B + DB 11001100B + DB 11101100B + DB 11111100B + DB 11011100B + DB 11001100B + DB 00000000B +; 166 ¦ + DB 00111100B + DB 01101100B + DB 01101100B + DB 00111110B + DB 00000000B + DB 01111110B + DB 00000000B + DB 00000000B +; 167 § + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 01111100B + DB 00000000B + DB 00000000B +; 168 ¨ + DB 00110000B + DB 00000000B + DB 00110000B + DB 01100000B + DB 11000000B + DB 11001100B + DB 01111000B + DB 00000000B +; 169 © + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111100B + DB 11000000B + DB 11000000B + DB 00000000B + DB 00000000B +; 170 ª + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111100B + DB 00001100B + DB 00001100B + DB 00000000B + DB 00000000B +; 171 « + DB 11000011B + DB 11000110B + DB 11001100B + DB 11011110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00001111B +; 172 ¬ + DB 11000011B + DB 11000110B + DB 11001100B + DB 11011011B + DB 00110111B + DB 01101111B + DB 11001111B + DB 00000011B +; 173 ­ + DB 00011000B + DB 00011000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B +; 174 ® + DB 00000000B + DB 00110011B + DB 01100110B + DB 11001100B + DB 01100110B + DB 00110011B + DB 00000000B + DB 00000000B +; 175 ¯ + DB 00000000B + DB 11001100B + DB 01100110B + DB 00110011B + DB 01100110B + DB 11001100B + DB 00000000B + DB 00000000B +; 176 ° + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B + DB 00100010B + DB 10001000B +; 177 ± + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B + DB 01010101B + DB 10101010B +; 178 ² + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B + DB 11011011B + DB 01110111B + DB 11011011B + DB 11101110B +; 179 ³ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; 180 ´ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 181 µ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 182 ¶ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 183 · + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111110B + DB 00110110B + DB 00110110B + DB 00110110B +; 184 ¸ + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 185 ¹ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 186 º + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 187 » + DB 00000000B + DB 00000000B + DB 11111110B + DB 00000110B + DB 11110110B + DB 00110110B + DB 00110110B + DB 00110110B +; 188 ¼ + DB 00110110B + DB 00110110B + DB 11110110B + DB 00000110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; 189 ½ + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111110B + DB 00000000B + DB 00000000B + DB 00000000B +; 190 ¾ + DB 00011000B + DB 00011000B + DB 11111000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 191 ¿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111000B + DB 00011000B + DB 00011000B + DB 00011000B +; 192 À + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; 193 Á + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 194  + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 195 à + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 196 Ä + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 197 Å + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 198 Æ + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 199 Ç + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 200 È + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 201 É + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 202 Ê + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 203 Ë + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 204 Ì + DB 00110110B + DB 00110110B + DB 00110111B + DB 00110000B + DB 00110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 205 Í + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 206 Î + DB 00110110B + DB 00110110B + DB 11110111B + DB 00000000B + DB 11110111B + DB 00110110B + DB 00110110B + DB 00110110B +; 207 Ï + DB 00011000B + DB 00011000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 208 Ð + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 209 Ñ + DB 00000000B + DB 00000000B + DB 11111111B + DB 00000000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 210 Ò + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 211 Ó + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 00111111B + DB 00000000B + DB 00000000B + DB 00000000B +; 212 Ô + DB 00011000B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00000000B + DB 00000000B + DB 00000000B +; 213 Õ + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 214 Ö + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 215 × + DB 00110110B + DB 00110110B + DB 00110110B + DB 00110110B + DB 11111111B + DB 00110110B + DB 00110110B + DB 00110110B +; 216 Ø + DB 00011000B + DB 00011000B + DB 11111111B + DB 00011000B + DB 11111111B + DB 00011000B + DB 00011000B + DB 00011000B +; 217 Ù + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 218 Ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011111B + DB 00011000B + DB 00011000B + DB 00011000B +; 219 Û + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; 220 Ü + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B +; 221 Ý + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B + DB 11110000B +; 222 Þ + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B + DB 00001111B +; 223 ß + DB 11111111B + DB 11111111B + DB 11111111B + DB 11111111B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 224 à + DB 00000000B + DB 00000000B + DB 01110110B + DB 11011100B + DB 11001000B + DB 11011100B + DB 01110110B + DB 00000000B +; 225 á + DB 00000000B + DB 01111000B + DB 11001100B + DB 11111000B + DB 11001100B + DB 11111000B + DB 11000000B + DB 11000000B +; 226 â + DB 00000000B + DB 11111100B + DB 11001100B + DB 11000000B + DB 11000000B + DB 11000000B + DB 11000000B + DB 00000000B +; 227 ã + DB 00000000B + DB 11111110B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B +; 228 ä + DB 11111100B + DB 11001100B + DB 01100000B + DB 00110000B + DB 01100000B + DB 11001100B + DB 11111100B + DB 00000000B +; 229 å + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011000B + DB 11011000B + DB 11011000B + DB 01110000B + DB 00000000B +; 230 æ + DB 00000000B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01100110B + DB 01111100B + DB 01100000B + DB 11000000B +; 231 ç + DB 00000000B + DB 01110110B + DB 11011100B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00000000B +; 232 è + DB 11111100B + DB 00110000B + DB 01111000B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00110000B + DB 11111100B +; 233 é + DB 00111000B + DB 01101100B + DB 11000110B + DB 11111110B + DB 11000110B + DB 01101100B + DB 00111000B + DB 00000000B +; 234 ê + DB 00111000B + DB 01101100B + DB 11000110B + DB 11000110B + DB 01101100B + DB 01101100B + DB 11101110B + DB 00000000B +; 235 ë + DB 00011100B + DB 00110000B + DB 00011000B + DB 01111100B + DB 11001100B + DB 11001100B + DB 01111000B + DB 00000000B +; 236 ì + DB 00000000B + DB 00000000B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 00000000B + DB 00000000B +; 237 í + DB 00000110B + DB 00001100B + DB 01111110B + DB 11011011B + DB 11011011B + DB 01111110B + DB 01100000B + DB 11000000B +; 238 î + DB 00111000B + DB 01100000B + DB 11000000B + DB 11111000B + DB 11000000B + DB 01100000B + DB 00111000B + DB 00000000B +; 239 ï + DB 01111000B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 11001100B + DB 00000000B +; 240 ð + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00000000B +; 241 ñ + DB 00110000B + DB 00110000B + DB 11111100B + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B +; 242 ò + DB 01100000B + DB 00110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 00000000B + DB 11111100B + DB 00000000B +; 243 ó + DB 00011000B + DB 00110000B + DB 01100000B + DB 00110000B + DB 00011000B + DB 00000000B + DB 11111100B + DB 00000000B +; 244 ô + DB 00001110B + DB 00011011B + DB 00011011B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B +; 245 õ + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 00011000B + DB 11011000B + DB 11011000B + DB 01110000B +; 246 ö + DB 00110000B + DB 00110000B + DB 00000000B + DB 11111100B + DB 00000000B + DB 00110000B + DB 00110000B + DB 00000000B +; 247 ÷ + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 01110110B + DB 11011100B + DB 00000000B + DB 00000000B +; 248 ø + DB 00111000B + DB 01101100B + DB 01101100B + DB 00111000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; 249 ù + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B +; 250 ú + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00011000B + DB 00000000B + DB 00000000B + DB 00000000B +; 251 û + DB 00001111B + DB 00001100B + DB 00001100B + DB 00001100B + DB 11101100B + DB 01101100B + DB 00111100B + DB 00011100B +; 252 ü + DB 01111000B + DB 01101100B + DB 01101100B + DB 01101100B + DB 01101100B + DB 00000000B + DB 00000000B + DB 00000000B +; 253 ý + DB 01110000B + DB 00011000B + DB 00110000B + DB 01100000B + DB 01111000B + DB 00000000B + DB 00000000B + DB 00000000B +; 254 þ + DB 00000000B + DB 00000000B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00111100B + DB 00000000B + DB 00000000B +; 255 ÿ + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B + DB 00000000B +; +ENDTABL EQU THIS BYTE + PUBLIC ENDTABL + DW 437 ;TABLE ID +; include graftusm.inc + DB "USA",0 ;LANGUAGE NAME, IN ASCIIZ FORMAT +;(the above "DB" is an example of the ENGLISH version of the above include file) + IF ($-CSEG) MOD 16 ;IF NOT ALREADY ON 16 BYTE BOUNDARY + DB (16-(($-CSEG) MOD 16)) DUP(0) ;ADD PADDING TO GET TO 16 BYTE BOUNDARY + ENDIF +CSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAFTABL/MAKEFILE b/v4.0/src/CMD/GRAFTABL/MAKEFILE new file mode 100644 index 0000000..5fa792b --- /dev/null +++ b/v4.0/src/CMD/GRAFTABL/MAKEFILE @@ -0,0 +1,74 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: graftabl.com + +graftabl.ctl: graftabl.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +grtab.obj: grtab.asm \ + makefile + +grtabp.obj: grtabp.asm \ + makefile \ + $(inc)\psdata.inc \ + $(inc)\parse.asm + +grtabsm.obj: grtabsm.asm \ + makefile \ + $(inc)\copyrigh.inc \ + $(inc)\versiona.inc \ + $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm \ + graftabl.ctl \ + graftabl.cl1 \ + graftabl.cl2 \ + graftabl.cla \ + $(inc)\msghan.inc \ + grtabms.inc + +grtabpar.obj: grtabpar.asm \ + makefile + +grtabhan.obj: grtabhan.asm \ + makefile + +grtabus.obj: grtabus.asm \ + makefile + +grtabno.obj: grtabno.asm \ + makefile + +grtabpo.obj: grtabpo.asm \ + makefile + +grtabcf.obj: grtabcf.asm \ + makefile + +grtabml.obj: grtabml.asm \ + makefile + +graftabl.com: grtab.obj \ + makefile \ + graftabl.lnk \ + grtabp.obj \ + grtabsm.obj \ + grtabpar.obj \ + grtabhan.obj \ + grtabus.obj \ + grtabno.obj \ + grtabpo.obj \ + grtabcf.obj \ + grtabml.obj + link @graftabl.lnk + exe2bin graftabl.exe graftabl.com + del graftabl.exe diff --git a/v4.0/src/CMD/GRAPHICS/GRAPHICS.ASM b/v4.0/src/CMD/GRAPHICS/GRAPHICS.ASM new file mode 100644 index 0000000..8b401b9 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRAPHICS.ASM @@ -0,0 +1,76 @@ + PAGE ,132 ;AN000; + TITLE DOS GRAPHICS Command - Command Entry Point + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; MS DOS GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRAPHICS.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the GRAPHICS command entry point. ;AN000; +;; A jump is made to the GRAPHICS_INSTALL procedure ;AN000; +;; in file GRINST.ASM to begin installation processing. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; None ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRINST.EXT - Externals for GRINST.ASM ;AN000; +;; ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRINST.ASM: ;AN000; +;; GRAPHICS_INSTALL - Main module for installation. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; LINK GRAPHICS GRINT2FH GRPATTRN GRCTRL GRCPSD GRCOLPRT GRBWPRT ;AN000; +;; GRINST GRPARSE grparms GRLOAD GRLOAD2 GRLOAD3; ;AN000; +;; EXE2BIN GRAPHICS.EXE GRAPHICS.COM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; A000 - Denotes 4.00 level source. ;AN000; +;; A001 - PTM1779 - invalid parm msg followed by garbage ;AN001; +;; Module affected: GRPARMS.ASM ;AN001; +;; A002 - PTM2666 - Release environment string before terminating. ;AN002; +;; Module affected: GRINST.ASM ;AN002; +;; A003 - PTM3915 - Change to include common copyright file. +;; Module affected: GRAPHICS.ASM +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ORG 100H ;; required for .COM ;AN000; + ;; ;AN000; + ;; ;AN000; + INCLUDE GRINST.EXT ;; Bring in external declarations ;AN000; + ;; for transient command processing ;AN000; +START: ;; ;AN000; + ;; ;AN000; + JMP GRAPHICS_INSTALL ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; +; INCLUDE COPYRIGH.INC ;; included in message services ;AN003; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +CODE ENDS ;AN000; + END START ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRAPHICS.LNK b/v4.0/src/CMD/GRAPHICS/GRAPHICS.LNK new file mode 100644 index 0000000..6c3f5bb --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRAPHICS.LNK @@ -0,0 +1,15 @@ +GRAPHICS+ +GRINT2FH+ +GRPATTRN+ +GRCTRL+ +GRCPSD+ +GRCOLPRT+ +GRBWPRT+ +GRINST+ +GRPARSE+ +grparms+ +GRLOAD+ +GRLOAD2+ +GRLOAD3 +GRAPHICS.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/GRAPHICS/GRAPHICS.OB b/v4.0/src/CMD/GRAPHICS/GRAPHICS.OB new file mode 100644 index 0000000..a10128d --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRAPHICS.OB @@ -0,0 +1,32 @@ +€PRINTç–CODECODE_SEGÚ˜(š Œ géûé¸ è¸ +R+Ò2äÍZöÄ%uË&ƒ>}‹´Íën¸è è¡÷&‹ØèŠÇë¼¢œq„; „´Ä „ Ä"kÄ&\Ä-ÏÄ6Ä8:„>ÄAN„DÄGmÄKo„PÄV…, îe +^_][YZX.ÿ.¾ü¬ +Àtèëö€>u è¸è3ÀŽØ¢^_][YZXÏPRQSUWV´Í$¢¿¹üò®t €>u›<}—ëP€>uIƒ>tB <~ < +tÇë/Ç3ÀŽØ fŠà"&±Òè¨tdžà»×‹ˆ3ÀŽØþÀð†¨té‰&èƒ>|¾ü¬ +Àtèëö‹þÀƒû +u ¢Ñ㋇£Ã3Òÿ'¹ƒ>}¹?QºÇYQ»´ Í2"u IKuîJ}æYéB‰èYQ»´ ÍŠà2"ƒ>}Ðì +Ĉ‡IKuß¿¹ý3Àó«GG¹»ŠŠàÐèÒàEŠÄ$ÒàEŠÄþÀÐèÐèÒàEKI}Ù‹Š€û +ƒ×Šè€û +ƒßÿâóYB;téèƒé}éé4œmÄaÄ!S„*Ä0_„6„<Äc\ÄfqÄr_Ä_ĆXÄŒ\Ę3Äš=Ä 3Ä¢5ı"Ľ3Ä¿9ÄÄ=ÄÉ3„ߪÄãk„æ Äê\ÄðO„ùÄÿ\Å ZÅSÅoÅiÅ#\Å:^Å>Z…K@ÅPm…S:Åb^ÅfZÅj\ÅuÅ|ŠÅŒ‡Å·oÅ»\…ÆÅÔm…Ù»…Ü …ä……ç Ï‡ !2 -( 3" -ML3<3$Oœ2ÄÄÄÄ!Ä#ÑÄ%ÑÄ'ƒ0  +xÙœÄÑÄÑăɠíÎ3Û¹?€>u¹ŸR‡é¹‡é´ Í2$uB‡éâí‡éZI}áÿƒÂúÈuÇÿ&A‰ÿZ+ÉR¾‡é¹‡é´ Í2$ˆNB‡éâì¹¾ÐàÐà€<| Nâò¢ÿ¹¾ÐàÐàöt Nâò‹øÿ ÿ€>u ÿ‹Çÿ ÿZ‡éA;u‚éK1<2ïœ¢Ä \Ä^Ä2Ä?VÄDmÄH8ÄO‚Ä^^Än‚Ä[ă6ĉ‚Ä6Ä [Ĥ6Ĩ\Ä®[IJ6ĸ6Ä»[Ä¿6ÄÇm„Ìþˆ  +¿‘œÄÄăQ  +ljœÄÄăQ ÿÛ°´€>u°´£3Û¹?€>u¹ŸQºÇYQŠ´ Í2$uIþËuïJ}æYÿ ˜+È}Õÿ&B‰ÿYQ¾‡éŠ2í‡é´ Í2$ˆNI‡éâìŠ2í¾QŠÒà€<|µÒåþÍ +ÅNYâèÿ¾Š2í2ÀQŠÒàŠ,ÐéÐéÐáÒå +, +ÅYNâçÿYB;u‹éL3<3?UœÓÄ\ÄwÄ\Ä)xÄ1^ÄBÄExÄNVÄSmÄW8Ä\‚ÄbxÄn^Ä|xÄ‚ĆwÄ6Ä ‚ĤxÄ­wÄÅ6ÄËm„ÐÄíoÄïoÄñoÄóoÄõMÄ÷MÄùƒ}  +ØwœÄMÄMÄXö .$ €Т„»  ŒymcbœÄ5W ˜ª ¬RÆƹ?€>u¹ŸZR¾´ 3ÛÍ +Àu€>t ‹× +Àu&BNuâI}Úöt‰ëMÿZƒÂúÈ|§ÿ&QRV3ÛºA‹é¹‡é…Ât‹ó;ˆ~‰ˆ‡éCÑââã^ZY 4u¥Çÿÿÿ‹ƒû}¦²‹ËÒ∋ó‹ˆãáÇ€¸ÿŠ‡ÿ‰ÿZ3ÉR¾ÐàÐàP´ 3ÛÍ +Àu€>t ‹×"Xt BNuØQ‹ÿâúYZA;uÀ¸ ÿRé´ÍŠÌµQ´ÍY‰3Ò3ö2Û´Í´Í +Àu° ˆ„ƒ>t€ä†à˜‹øŠ…ˆ„ +ØFþÂ:ÊuÎSR3ÒŠÓ3Ûƒ>t'3ÿOÆ€Gƒÿ}eÐÐêsò3Û¸ÿŠ…ÿ¸ÿ¸\ÿŠÁÿ3Àÿƒ>t +Š‡„tŠ‡ë° ÿC:ÙuÞƒ>t ¸ ÿë•ÿZ[þÆ2Ò:îté‹´Íÿ&¹QºÇÆÆYQ¾´ 3ÛÍ +Àu€>t ‹× +Àu"INuâJ}Úöt‰ëEÿYƒé}µÿ&‹úGQRV3Ûº¹…Ât‹ó;¸~‰¸CÑââç^ZY 4u­Çÿÿÿ‹ƒû}®²‹ËÒ∋ó‹ ÒtßÇ€¸ÿŠ‡ÿ‰ÿYQ¾ÐàP´ 3ÛÍ +Àu€>t ‹×"Xt INuÚ‹ÿâúYB;uĸ ÿQé +COLOR8COLOR4COLOR1COMPACTGRAPHICSTHERMAL/R/r/B/b/LCD/lcdé.Æü¿€Š 2íãíG° ó®O€= tâ¾WV¬ +Àt'ŠÈQŠŠ$u¸.£.£¿¸¹üó«¸.£.¢+ÀŽØ¡.£¡.£¡4.£.‹ƒë|w.‰¾t¾Ku9¿¹.Š.ˆGFâö¾¿.ŠD.ˆE.ŠD.ˆE.ŠD.ˆE¿.ŠD.ˆE.Ç.öÿt».ŠO.Š/.ˆo.ˆo.ˆo.ˆ.ÆÇŒÈ- diff --git a/v4.0/src/CMD/GRAPHICS/GRAPHICS.PRO b/v4.0/src/CMD/GRAPHICS/GRAPHICS.PRO new file mode 100644 index 0000000..5ccc7b2 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRAPHICS.PRO @@ -0,0 +1,231 @@ +;---------------------------------------------------------------------------- + ;DOS (C)Copyright 1988 Microsoft + ;Licensed Material - Program Property of Microsoft +;---------------------------------------------------------------------------- +PRINTER GRAPHICS,THERMAL ;; 5152, 4201, 4202(8"), 5201-002(8"), 5202, 3812 + ;; 4207, 4208, 5140 + + ; Maximum Print width: 8" + ; Horizontal BPI: 120 Vertical BPI: 72 + ; SETUP Statements contain the following escape sequences: + ; 27,51,24 = set line spacing to 24/216 + ; GRAPHICS Statements use ESC "L" with the last two bytes being + ; the data count (low,high) + + DISPLAYMODE 4,5,13,19 ;; 320x200 > 6.7"x8.9" rotated + SETup 27,51,24 + GRAPHICS 32,32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,2,ROTATE + PRINTBOX LCD,2,2,ROTATE + + DISPLAYMODE 6,14 ;; 640x200 > 6.7"x8.9" rotated + SETup 27,51,24 + GRAPHICS 32,32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,1,ROTATE + PRINTBOX LCD,2,1,ROTATE + + DISPLAYMODE 15,16 ;; 640x350 > 5.8"x8.9" rotated + SETup 27,51,24 + GRAPHICS 32,32,32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,2,1,ROTATE + PRINTBOX LCD ;; PC/Convertible doesn't support these modes + + DISPLAYMODE 17,18 ;; 640x480 > 8"x8.9" rotated + SETup 27,51,24 + GRAPHICS 27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,2,1,ROTATE + PRINTBOX LCD ;; PC/Convertible doesn't support these modes + + +;--------------------------------------------------------------------------- +PRINTER COLOR8 ;; 5182 CMY Ribbon + + ; Maximum Print width: 8" + ; Horizontal BPI: 168 in 1:1 aspect ratio, 140 in 5:6 aspect ratio + ; Vertical BPI: 84 + ; SETUP Statements contain the following escape sequences: + ; 27,51,14 = set line spacing to 14/144 + ; 27,110,[0|1] = 0 sets aspect ratio to 5:6, 1 sets it to 1:1 + ; GRAPHICS Statements use ESC "L" with the last two bytes being + ; the data count (low,high) + + COLORSELECT Y,27,121 ;; yellow band + COLORSELECT M,27,109 ;; magenta band + COLORSELECT C,27,99 ;; cyan band + COLORSELECT B,27,98 ;; black band + ;; + ;; Following RGB's represent the first 16 + ;; screen colors. + ;; SCREEN COLOR PRINT COLOR + ;; ------------ ----------- + COLORPRINT 0,0,0,B ;; BLACK BLACK + COLORPRINT 0,0,42,C ;; BLUE CYAN + COLORPRINT 0,42,0,Y,C ;; GREEN GREEN + COLORPRINT 0,42,42,C ;; CYAN CYAN + COLORPRINT 42,0,0,Y,M ;; RED RED + COLORPRINT 42,0,42,C,M ;; PURPLE PURPLE + COLORPRINT 42,21,0,Y,C,M ;; BROWN BROWN + COLORPRINT 42,42,42 ;; LOW WHITE WHITE (NOTHING) + COLORPRINT 21,21,21,B ;; GREY BLACK + COLORPRINT 21,21,63,C ;; HIGH BLUE CYAN + COLORPRINT 21,63,21,Y,C ;; HIGH GREEN GREEN + COLORPRINT 21,63,63,C ;; HIGH CYAN CYAN + COLORPRINT 63,21,21,Y,M ;; HIGH RED RED + COLORPRINT 63,21,63,M ;; MAGENTA MAGENTA + COLORPRINT 63,63,21,Y ;; YELLOW YELLOW + COLORPRINT 63,63,63 ;; HIGH WHITE WHITE (NOTHING) + + COLORPRINT 42,42,0,Y ;; This statement maps the "yellow" in CGA + ;; palette 0 to yellow + ;; + DISPLAYMODE 4,5,13,19 ;; 320x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,2,ROTATE + DISPLAYMODE 6,14 ;; 640x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,1,ROTATE + DISPLAYMODE 15,16 ;; 640x350 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,3,1,ROTATE + DISPLAYMODE 17,18 ;; 640x480 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,2,1 + +;--------------------------------------------------------------------------- +PRINTER COLOR4 ;; 5182 RGB Ribbon + + ; Maximum Print width: 8" + ; Horizontal BPI: 168 in 1:1 aspect ratio, 140 in 5:6 aspect ratio + ; Vertical BPI: 84 + ; SETUP Statements contain the following escape sequences: + ; 27,51,14 = set line spacing to 14/144 + ; 27,110,[0|1] = 0 sets aspect ratio to 5:6, 1 sets it to 1:1 + ; GRAPHICS Statements use ESC "L" with the last two bytes being + ; the data count (low,high) + + COLORSELECT R,27,121 ;; red band + COLORSELECT G,27,109 ;; green band + COLORSELECT B,27,99 ;; blue band + COLORSELECT X,27,98 ;; black band + ;; + ;; Following RGB's represent the first 16 + ;; screen colors. + ;; SCREEN COLOR PRINT COLOR + ;; ------------ ----------- + COLORPRINT 0,0,0,X ;; BLACK BLACK + COLORPRINT 0,0,42,B ;; BLUE BLUE + COLORPRINT 0,42,0,G ;; GREEN GREEN + COLORPRINT 0,42,42,B ;; CYAN BLUE + COLORPRINT 42,0,0,R ;; RED RED + COLORPRINT 42,0,42,R ;; PURPLE RED + COLORPRINT 42,21,0,X ;; BROWN BLACK + COLORPRINT 42,42,42 ;; LOW WHITE WHITE (NOTHING) + COLORPRINT 21,21,21,X ;; GREY BLACK + COLORPRINT 21,21,63,B ;; HIGH BLUE BLUE + COLORPRINT 21,63,21,G ;; HIGH GREEN GREEN + COLORPRINT 21,63,63,B ;; HIGH CYAN BLUE + COLORPRINT 63,21,21,R ;; HIGH RED RED + COLORPRINT 63,21,63,R ;; MAGENTA RED + COLORPRINT 63,63,21 ;; YELLOW WHITE (NOTHING) + COLORPRINT 63,63,63 ;; HIGH WHITE WHITE (NOTHING) + + COLORPRINT 42,42,0,B ;; This statement maps the "yellow" in CGA + ;; palette 0 to blue as was done in + ;; versions of GRAPHICS + ;; + DISPLAYMODE 4,5,13,19 ;; 320x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,2,ROTATE + DISPLAYMODE 6,14 ;; 640x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,1,ROTATE + DISPLAYMODE 15,16 ;; 640x350 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,3,1,ROTATE + DISPLAYMODE 17,18 ;; 640x480 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,2,1 + +;--------------------------------------------------------------------------- +PRINTER GRAPHICSWIDE ;; 4202(13.5"), 5201-002(13.5") + + ; Maximum Print width: 13.5" + ; Horizontal BPI: 120 Vertical BPI: 72 + ; SETUP Statements contain the following escape sequences: + ; 27,88,1,255 = enable 13.5" printing + ; 27,51,24 = set line spacing to 24/216 + ; 27,51,18 = set line spacing to 18/216 (320x200 MODES ONLY!!) + ; GRAPHICS Statements use ESC "L" with the last two bytes being + ; the data count (low,high) + + DISPLAYMODE 4,5,13,19 ;; 320x200 > 10.7"x8.3" non-rotated + SETup 27,88,1,255,27,51,18 + GRAPHICS 27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,3 + + DISPLAYMODE 6,14 ;; 640x200 - same as for 8" printing + SETup 27,88,1,255,27,51,24 + GRAPHICS 27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,1,ROTATE + + DISPLAYMODE 15,16 ;; 640x350 > 11.7"x17.8" rotated + SETup 27,88,1,255,27,51,24 + GRAPHICS 27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,2,ROTATE + + DISPLAYMODE 17,18 ;; 640x480 > 12"x17.8" rotated + SETup 27,88,1,255,27,51,24 + GRAPHICS 27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,3,2,ROTATE + +;--------------------------------------------------------------------------- +PRINTER COLOR1 ;; 5182 with black ribbon + + ; Maximum Print width: 8" + ; Horizontal BPI: 168 in 1:1 aspect ratio, 140 in 5:6 aspect ratio + ; Vertical BPI: 84 + ; SETUP Statements contain the following escape sequences: + ; 27,51,14 = set line spacing to 14/144 + ; 27,110,[0|1] = 0 sets aspect ratio to 5:6, 1 sets it to 1:1 + ; GRAPHICS Statements use ESC "L" with the last two bytes being + ; the data count (low,high) + + DARKADJUST 0 ; Code a positive number to lighten + ; printing. Suggested value = 10 + + DISPLAYMODE 4,5,13,19 ;; 320x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,2,ROTATE + PRINTBOX LCD,2,2,ROTATE + + DISPLAYMODE 6,14 ;; 640x200 + SETUP 27,51,14,27,110,0 ;; aspect ratio = 5:6 + GRAPHICS 32,32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,4,1,ROTATE + PRINTBOX LCD,2,1,ROTATE + + DISPLAYMODE 15,16 ;; 640x350 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,3,1,ROTATE + PRINTBOX LCD ;; PC/Convertible doesn't support these modes + + DISPLAYMODE 17,18 ;; 640x480 + SETUP 27,51,14,27,110,1 ;; aspect ratio = 1:1 + GRAPHICS 32,32,32,32,27,76,LOWCOUNT,HIGHCOUNT + PRINTBOX STD,2,1 + PRINTBOX LCD ;; PC/Convertible doesn't support these modes + + +;=========================================================================== +; End of Profile +;=========================================================================== diff --git a/v4.0/src/CMD/GRAPHICS/GRAPHICS.SKL b/v4.0/src/CMD/GRAPHICS/GRAPHICS.SKL new file mode 100644 index 0000000..8e6dd15 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRAPHICS.SKL @@ -0,0 +1,66 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; MS DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRAPHICS.MSG ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; DOS GRAPHICS Command - Message skeleton file +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the skeleton file for using the DOS message ;AN000; +;; retriever with GRAPHICS.COM ;AN000; +;; ;AN000; +;; This skeleton file is processed by "FASTBLD" in order to create ;AN000; +;; the following message files wich are included from GRINST.ASM: ;AN000; +;; ;AN000; +;; GRAPHICS.CL1 ; Class 1 messages ;AN000; +;; GRAPHICS.CL2 ; Class 2 messages ;AN000; +;; GRAPHICS.CLA ; Class A messages ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; DOS 3.3 Message Retriever Interface Supplement. ;AN000; +;; DOS 3.3 Approved Functional Specification Message Supplement. ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRINST.ASM: ;AN000; +;; GRAPHICS_INSTALL - Main module for GRAPHICS install. ;AN000; +;; (NOTE: Reference is made to the include file generated from this ;AN000; +;; skeleton file). ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AC001 - Changed message 15 to match D307 request ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +:util GRAPHICS ; Utility name ;AN000; + ;AN000; + ;AN000; +:class A ; Class A messages (General messages) ;AN000; +:use 1 COMMON1 ; 'Incorrect DOS version' ;AN000; +:use 2 EXTEND8 ; 'Insufficient memory' ;AN000; + ;AN000; + ;AN000; +:class B ; Class B messages: (Profile loading) ;AN000; +:def 9 'Cannot find GRAPHICS profile',CR,LF ;AN000; +:def 10 'Required profile statement missing before line %1',CR,LF ;AN000; +:def 11 'Invalid profile statement on line %1',CR,LF ;AN000; +:def 12 'Profile statement out of sequence on line %1',CR,LF ;AN000; +:def 13 'Error reading GRAPHICS profile',CR,LF ;AN000; +:def 14 'Syntax errors in GRAPHICS profile',CR,LF ;AN000; +:def 15 'Printbox ID not in GRAPHICS profile',CR,LF ;AC001; +:def 16 'Printer type not in GRAPHICS profile',CR,LF ;AN000; + ;AN000; +:class C ; Class C messages: (Command line parsing) ;AN000; +:use 3 PARSE1 ; 'Too many parameters' ;AN000; +:use 4 PARSE6 ; 'Parameter value not allowed' ;AN000; +:def 5 'Invalid parameter: %1',CR,LF ;AN000; +:use 6 PARSE11 ; 'Invalid parameter combination' ;AN000; +:def 7 'Duplicate parameters not allowed',CR,LF ;AN000; +:use 8 PARSE8 ; 'Parameter format not correct' ;AN000; +:def 17 '/B invalid with a black and white printer',CR,LF ;AN000; +:def 18 'Unable to reload with profile supplied',CR,LF ;AN000; +:end ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM b/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM new file mode 100644 index 0000000..7b09ffd --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM @@ -0,0 +1,631 @@ + PAGE ,132 ;AN000; + TITLE DOS GRAPHICS Command - Black and White printing modules +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRBWPRT.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the code for printing a GRAPHICS screen on a ;AN000; +;; BLACK and WHITE printer. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; ;AN000; +;; PRINT_BW_APA ;AN000; +;; FILL_BUFFER ;AN000; +;; INT2PAT ;AN000; +;; PAT2BOX ;AN000; +;; ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRCTRL.EXT - Externals for print screen control ;AN000; +;; GRCTRL.STR - Structures and equates for print screen control ;AN000; +;; GRPATTRN.STR - Structures for the printer patterns. ;AN000; +;; ;AN000; +;; GRSHAR.STR - Shared Data Area Structure ;AN000; +;; ;AN000; +;; STRUC.INC - Macros for using structured assembly language ;AN000; +;; ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRCTRL.ASM: ;AN000; +;; PRT_SCR - Main module for printing the screen. ;AN000; +;; TO FILE GRCOMMON.ASM ;AN000; +;; Common modules - tools for printing a screen. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; This file is included by GRCTRL.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +PAGE ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;AN000; + ASSUME CS:CODE,DS:CODE ;AN000; + ;AN000; + PUBLIC PRINT_BW_APA ;AN000; + PUBLIC LEN_OF_BW_MODULES ;AN000; + ;AN000; +.XLIST ;AN000; +INCLUDE GRCTRL.STR ; Stuctures needed ;AN000; +INCLUDE GRSHAR.STR ; for both set of print modules ;AN000; +INCLUDE GRPATTRN.STR ; ;AN000; +INCLUDE GRCTRL.EXT ; Externals from PRT_SCR control module ;AN000; +INCLUDE STRUC.INC ; ;AN000; + ;AN000; + PUBLIC PRINT_BW_APA ; Black and white modules, ;AN000; +.LIST ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_BW_APA : PRINT A GRAPHIC MODE SCREEN ON A BLACK AND WHITE PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; XLT_TAB = Color translation table ;AN000; +; BIOS_INT_5H = Pointer to BIOS int 5h ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: This procedure maps each pixel of the screen to a box ;AN000; +; of dots on the printer. The box size depends on the screen resolution ;AN000; +; and the number of bytes per printer line. It is chosen in order to ;AN000; +; respect the screen ratio and is documented in each printer profile. ;AN000; +; ;AN000; +; For efficiency and space considerations, the print buffer does not ;AN000; +; hold a full print line. Bytes representing pixels are printed as soon ;AN000; +; as they are ready to be printed. However, the print buffer is wide ;AN000; +; enough to hold complete boxes. ;AN000; +; ;AN000; +; The order for reading pixels off the screen is driven by the ;AN000; +; order bytes are expected by the printer. To print the screen in its ;AN000; +; original orientation we must begin reading it from the top left corner ;AN000; +; and send the pixels line by line; to print it sideways, reading will ;AN000; +; start from the bottom left corner and a "LINE" will now be a vertical ;AN000; +; screen column read from bottom to top. ;AN000; +; ;AN000; +; There is more to it however, the printer head is printing a ;AN000; +; vertical column of 8 dots at a time and each pixel read is mapped to ;AN000; +; a box of dots that is less than 8 dots high (e.g., 2 cols x 1 row) ;AN000; +; therefore, many boxes must be stored in the bytes sent to the printer. ;AN000; +; ;AN000; +; These boxes represent pixels that are one above each other on the ;AN000; +; screen. We must read enough pixels on one column of the screen to use ;AN000; +; all 8 bits of the vertical printer head (e.g., if the box size is 2x1 ;AN000; +; then 8 pixels must be read and 2 bytes of the print buffer will be ;AN000; +; filled). ;AN000; +; ;AN000; +; The PRINT BUFFER for any box size will be 8 bits high by "BOX ;AN000; +; WIDTH" bits wide. ;AN000; +; ;AN000; +; After the buffer is filled, it is printed and the next "column" ;AN000; +; of 8 pixels is read. Therefore, the screen is read "line by line" ;AN000; +; where a line is 8 pixels high for a 2x1 box (4 pixels high for a 3x2 ;AN000; +; box). ONE SUCH LINE IS CALLED A SCAN LINE. ;AN000; +; ;AN000; +PAGE ;AN000; +; ;AN000; +; A 350X200 screen mapping to a 3x2 box is read in the following order: ;AN000; +; ;AN000; +; SCREEN: ;AN000; +; ;AN000; +; column column . . . column ;AN000; +; no. 0 no. 1 no. 349 ;AN000; +; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +; scan º1(0,0) 5(0,1) 1397(0,349)º ;AN000; +; line º2(1,0) 6(1,1) . . . . . . . 1398(1,349)º ;AN000; +; no. 1 º3(2,0) 7(2,1) 1399(2,349)º ;AN000; +; º4(3,0) 8(3,1) 1400(3,349)º ;AN000; +; º º ;AN000; +; scan º1401(4,0) 1405(4,1) º LEGEND: n(X,Y) ;AN000; +; line º1402(5,0) etc, º ;AN000; +; no. 2 º1403(6,0) . . . . . º n = READ RANK ;AN000; +; º1404(7,0) º X = ROW NUMBER ;AN000; +; º . º Y = COLUMN NUMBER ;AN000; +; etc, º . º ;AN000; +; º . 70000(199,349)º ;AN000; +; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; +; ;AN000; +; ;AN000; +; LOGIC : ;AN000; +; ;AN000; +; Initialize printer and local variables. ;AN000; +; CALL LOC_MODE_PRT_INFO ; Get printer info related to current mode. ;AN000; +; CALL GET_SCREEN_INFO ; Get info. about how to read the screen ;AN000; +; CALL SETUP_PRT ; Set up the printer (Line spacing, etc) ;AN000; +; ;AN000; +; FOR each scan line on the screen (NB_SCAN_LINES) ;AN000; +; (Note: One scan line maps to one print line) ;AN000; +; BEGIN ;AN000; +; CALL DET_CUR_SCAN_LNE_LENGTH ; Determine length in pels of the current ;AN000; +; ; scan line. ;AN000; +; IF CUR_SCAN_LNE_LENGTH NE 0 THEN ;AN000; +; CALL NEW_PRT_LINE ; Initialize a new printer line ;AN000; +; DO CUR_SCAN_LNE_LENGTH times ; For each column ;AN000; +; BEGIN ;AN000; +; CALL FILL_BUFFER ; Read top-down enough pels to fill the buffer ;AN000; +; CALL PRINT_BUFFER ; Print the buffer ;AN000; +; IF printing sideways THEN INC CUR_ROW ; Get coordinates of next ;AN000; +; ELSE INC CUR_COLUMN ; "column" (vertical chunk of ;AN000; +; END (for each column) ; a scan line). ;AN000; +; PRINT_BYTE CR ; Print a CR and a LF ;AN000; +; PRINT_BYTE LF ;AN000; +; ; Get coordinates of next scan line: ;AN000; +; IF printing sideways THEN ;AN000; +; ADD CUR_COLUMN,NB_BOXES_PER_PRT_BUF ;AN000; +; MOV CUR_ROW,SCREEN_HEIGHT - 1 ;AN000; +; ELSE ;AN000; +; ADD CUR_ROW,NB_BOXES_PER_PRT_BUF ;AN000; +; MOV CUR_COLUMN,0 ;AN000; +; END (for each scan line) ;AN000; +; ;AN000; +PRINT_BW_APA PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INITIALIZATION: ;AN000; +; ;AN000; +; 1) Locate and extract printer DISPLAYMODE information from ;AN000; +; the shared data area, calculate the number of boxes fitting ;AN000; +; in the printer buffer. ;AN000; +; 2) Determine where to start reading the screen: ;AN000; +; If printing sideways, start in LOW LEFT corner. ;AN000; +; If normal printing, start in TOP LEFT corner. ;AN000; +; Determine the maximum length for a scan line: ;AN000; +; If printing sideways, it is the height of the screen. ;AN000; +; For normal printing, it is the width of the screen. ;AN000; +; Determine the number of scan lines on the screen. ;AN000; +; 3) Set up the Printer for printing Graphics. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL LOC_MODE_PRT_INFO ; Get printer info related to curr. mode;AN000; +; ;AN000; +;-------Test if DISPLAYMODE info record was found: ;AN000; + .IF ;AN000; + .THEN ;AN000; + MOV ERROR_CODE,UNABLE_TO_PRINT ; IF no record found, ;AN000; + JMP PRINT_BW_APA_END ; then, return error code ;AN000; + .ENDIF ; and quit procedure ;AN000; +; ;AN000; +;-------Get the box size from the DISPLAYMODE info record: ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Offset current DISPLAYMODE info.;AN000; + MOV AH,[BX].BOX_WIDTH ; Take local copy of the box size. ;AN000; + MOV BOX_W,AH ; in BOX_W and BOX_H ;AN000; + MOV AL,[BX].BOX_HEIGHT ;AN000; + MOV BOX_H,AL ;AN000; +; ;AN000; +;-------Verify if the box size obtained from DISPLAYMODE info. is valid ;AN000; + .IF OR ; IF height of the box is 0 ;AN000; + .IF ; OR width of the box is 0 ;AN000; + .THEN ; THEN we can't print: ;AN000; + MOV ERROR_CODE,UNABLE_TO_PRINT ; return error code ;AN000; + JMP PRINT_BW_APA_END ; and quit ;AN000; + .ENDIF ;AN000; +; ;AN000; +;-------Get the Print Orientation from the DISPLAYMODE info record ;AN000; + .IF <[BX].PRINT_OPTIONS EQ ROTATE>; If printing sideways ;AN000; + .THEN ; then: ;AN000; + MOV ROTATE_SW,ON ; Rotate switch := "ON" ;AN000; + .ENDIF ;AN000; + ;AN000; +; ;AN000; +;-------Initialize print variables and the printer: ;AN000; + CALL GET_SCREEN_INFO ; Get info. about how to read the screen;AN000; + CALL SETUP_PRT ; Set up the printer (Line spacing, etc);AN000; + .IF ;AN000; + .THEN ; A printer error occurred: quit ;AN000; + JMP PRINT_BW_APA_END ; ;AN000; + .ENDIF ;AN000; + ;AN000; + MOV CX,NB_SCAN_LINES ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; FOR EACH SCAN LINE ON THE SCREEN: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_1_SCAN_LINE: ;AN000; + CALL DET_CUR_SCAN_LNE_LENGTH ; Determine how many non-blanks on line ;AN000; +.IF ; If line is not empty ;AN000; +.THEN ; then, ;AN000; + CALL NEW_PRT_LINE ; Send escape sequence to the printer ;AN000; + .IF ; for starting a new line. ;AN000; + .THEN ; If a printer error occurred: ;AN000; + JMP PRINT_BW_APA_END ; Quit ! ;AN000; + .ENDIF ;AN000; + ;AN000; + PUSH CX ; Save scan line counter ;AN000; + MOV CX,CUR_SCAN_LNE_LENGTH ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; FOR each column on the current scan line (up to the last non-blank): ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_1_SCAN_COLUMN: ;AN000; + CALL FILL_BUFFER ; Read all pixels on this column, ;AN000; + ; convert each to a printer box, ;AN000; + ; store boxes in the print buffer ;AN000; + ; (a buffer contains one "column" ;AN000; + ; of pixels). ;AN000; + CALL PRINT_BUFFER ; Print the buffer. ;AN000; + .IF ;AN000; + .THEN ; A printer error occurred: ;AN000; + POP CX ; Restore scan line counter and quit ;AN000; + JMP PRINT_BW_APA_END ; ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; +;-------Get coordinates of next "column": ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + DEC CUR_ROW ; then, get row above on screen ;AN000; + .ELSE ; ;AN000; + INC CUR_COLUMN ; else, get column next right ;AN000; + .ENDIF ; ;AN000; + ;AN000; + LOOP PRINT_1_SCAN_COLUMN ; Print next column ;AN000; + ;AN000; + POP CX ; Restore scan line counter ;AN000; +.ENDIF ; Endif line is not empty ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Print a carriage return and a line feed: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AL,CR ;AN000; + CALL PRINT_BYTE ; Send CR ;AN000; + JC PRINT_BW_APA_END ; If printer error, leave ;AN000; + MOV AL,LF ;AN000; + CALL PRINT_BYTE ; Send LF ;AN000; + JC PRINT_BW_APA_END ; If printer error, leave ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Get coordinates of next scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then: ;AN000; + MOV AL,NB_BOXES_PER_PRT_BUF ; AX := Numbers of pels read on row ;AN000; + CBW ; ;AN000; + ADD CUR_COLUMN,AX ; CUR_COLUMN + Number of pels read ;AN000; + MOV AX,SCREEN_HEIGHT ; CUR_ROW := SCREEN_HEIGHT - 1 ;AN000; + DEC AX ; ;AN000; + MOV CUR_ROW,AX ; ;AN000; + .ELSE ; else, printing NOT rotated: ;AN000; + MOV AL,NB_BOXES_PER_PRT_BUF ; AX := Number of pels read on colum;AN000; + CBW ; ;AN000; + ADD CUR_ROW,AX ; CUR_ROW + Number of pels read ;AN000; + MOV CUR_COLUMN,0 ; CUR_COLUMN := 0 ;AN000; + .ENDIF ; ;AN000; + LOOP PRINT_1_SCAN_LINE ; ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Restore the printer. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL RESTORE_PRT ;AN000; +PRINT_BW_APA_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_BW_APA ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; FILL_BUFFER : READS ENOUGH PIXELS TO FILL UP THE PRINT BUFFER. ;AN000; +; THESE PIXELS ARE MAPPED TO A PRINTER DOT BOX. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_COLUMN, ;AN000; +; CUR_ROW = Coordinates of the first pixel to be read ;AN000; +; BOXES_PER_PRT_BUF = Number of boxes fitting in the print ;AN000; +; buffer ;AN000; +; XLT_TAB = Color translation table ;AN000; +; ;AN000; +; OUTPUT: PRT_BUF = PRINT BUFFER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: ;AN000; +; ;AN000; +; 1) Pixels are read one by one vertically from top to bottom in ;AN000; +; the current column of the screen scan line. ;AN000; +; NOTE: What is called here a 'column' can actually be a line ;AN000; +; on the physical display. ;AN000; +; 2) Each pixel is mapped to a printer dot box. ;AN000; +; 3) Each Dot box is stored in the printer buffer. ;AN000; +; 4) The coordinates in input are those of the "top" pixel ;AN000; +; and restored when leaving this procedure. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Save coordinates of the current "column" (slice of a screen scan line) ;AN000; +; DO for BOXES_PER_PRT_BUF (8 / BOX_H) ;AN000; +; BEGIN ;AN000; +; CALL READ_DOT ; Read a pixel, get index in XLT_TAB ;AN000; +; Get pixel intensity from XLT_TAB ;AN000; +; CALL INT2PAT ; Locate pattern corresponding to int. ;AN000; +; CALL PAT2BOX ; Extract box from pattern ;AN000; +; CALL STORE_BOX ; Store the box in the printer buffer ;AN000; +; ; Get coordinates of next pixel below: ;AN000; +; IF printing is sideways THEN INC CUR_COLUMN ;AN000; +; ELSE INC CUR_ROW ;AN000; +; END ;AN000; +; Restore initial coordinates. ;AN000; +; ;AN000; +FILL_BUFFER PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Save initial coordinates: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + PUSH CUR_ROW ;AN000; + PUSH CUR_COLUMN ;AN000; + ;AN000; +;-------Clear the print buffer: ;AN000; + XOR BX,BX ; For each byte in the PRT_BUF: ;AN000; +CLEAR_PRT_BUF: ;AN000; + MOV PRT_BUF[BX],0 ; Initialize byte to blanks ;AN000; + INC BX ; Get next byte ;AN000; + CMP BL,BOX_W ; All bytes cleared ? ;AN000; + JL CLEAR_PRT_BUF ; No, clear next one. ;AN000; + ;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000; + ;AN000; +;-------Fill the print buffer with one box for each pixel read: ;AN000; + XOR CX,CX ; CL := Number of pixels to read ;AN000; + MOV CL,NB_BOXES_PER_PRT_BUF ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; For each pixel within the current column of the scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +READ_AND_STORE_1_PIXEL: ;AN000; + CALL READ_DOT ; AL := Index into translation table ;AN000; + XLAT XLT_TAB ; AL := Intensity ;AN000; + CALL INT2PAT ; SI := Offset of matching Pattern ;AN000; + CALL PAT2BOX ; Extract CUR_BOX from the pattern. ;AN000; + MOV SI,OFFSET CUR_BOX ; Store it in the PRT_BUF ;AN000; + CALL STORE_BOX ;AN000; + ;AN000; +;-------Get coordinates of next pixel: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + INC CUR_COLUMN ; then, increment column number ;AN000; + .ELSE ; ;AN000; + INC CUR_ROW ; else, increment row number ;AN000; + .ENDIF ; ;AN000; + LOOP READ_AND_STORE_1_PIXEL ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Restore initial coordinates: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + POP CUR_COLUMN ;AN000; + POP CUR_ROW ;AN000; + ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +FILL_BUFFER ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; INT2PAT : MAP AN INTENSITY TO A PATTERN. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: AL = GREY INTENSITY (0 - 63 = BLACK to WHITE) ;AN000; +; BOX_W = Number of columns in a box ;AN000; +; CUR_MODE_PTR = Offset of current DISPLAYMODE info record ;AN000; +; ;AN000; +; OUTPUT: SI = OFFSET OF THE PATTERN MATCHING THE INTENSITY ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Performs a sequential search in the table of patterns ;AN000; +; until the proper pattern is found. ;AN000; +; ;AN000; +; ;AN000; +; SI = 0 ; FOUND = FALSE ;AN000; +; DO UNTIL FOUND = TRUE ;AN000; +; BEGIN ;AN000; +; IF AL <= Maximum intensity of the current pattern in the table ;AN000; +; THEN ;AN000; +; FOUND = TRUE ;AN000; +; ELSE ;AN000; +; SI = SI + (BOX_W * 2) ;AN000; +; END ;AN000; +; ;AN000; +INT2PAT PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH DX ;AN000; + ;AN000; +;-------Calculate the size in bytes of one pattern STRUCTURE: (see GRPATTRN.STR);AN000; + MOV DL,BOX_W ; DX := Number of columns in the box ;AN000; + XOR DH,DH ;AN000; + SHL DL,1 ; (DX * 2) = Number of columns in the pattern ;AN000; + INC DL ; DL := Size in bytes of one pattern ;AN000; + ; (includes intensity field) ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Offset of current mode ;AN000; + ; SI := Offset of the first pattern ;AN000; + MOV SI,[BX].PATTERN_TAB_PTR ;AN000; + ADD SI,BP ;AN000; + ;AN000; +COMPARE_INTENSITY: ;AN000; + CMP AL,[SI] ; Within the range of this pattern ? ;AN000; + JLE FOUND_PATTERN ; Yes, use this pattern. ;AN000; + ; No, look at next pattern: ;AN000; + ADD SI,DX ; SI := SI + Number columns in pattern) ;AN000; + JMP SHORT COMPARE_INTENSITY ;AN000; + ;AN000; +FOUND_PATTERN: ;AN000; + ;AN000; + POP DX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; + ;AN000; +INT2PAT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PAT2BOX : SELECT AND EXTRACT THE PROPER BOX FROM THE PATTERN ACCORDING ;AN000; +; TO THE COORDINATES OF THE PIXEL. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SI = OFFSET OF CURRENT PATTERN ;AN000; +; CUR_COLUMN, ;AN000; +; CUR_ROW = COORDINATES OF THE CURRENT PIXEL ;AN000; +; ;AN000; +; OUTPUT: CUR_BOX = PORTION OF THE PATTERN TO BE PRINTED ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: If the pixel is on even-even coordinates, then the ;AN000; +; top-left box of the pattern is extracted. ;AN000; +; If its Even-odd --> extract the top-right box. ;AN000; +; Odd-even --> low-left box, and Odd-odd --> low-right box. ;AN000; +; ;AN000; +PAGE ;AN000; +; For example., (with a 3x2 box): ;AN000; +; ;AN000; +; PATTERN (over 6 bytes): ;AN000; +; ;AN000; +; ;AN000; +; byte1 byte2 byte3 byte4 byte5 byte6 ;AN000; +; ;AN000; +; 0 0 0 0 0 0 ;AN000; +; 0 0 0 0 0 0 ;AN000; +; 0 0 0 0 0 0 ;AN000; +; 0 0 0 0 0 0 ;AN000; +; even-even --> dot1 dot2 dot3 | dot1 dot2 dot3 <-- even-odd ;AN000; +; (row-column) dot4 dot5 dot6 | dot4 dot5 dot6 box ;AN000; +; box. ------------------------------------------------ ;AN000; +; odd-even --> dot1 dot2 dot3 | dot1 dot2 dot3 <-- odd-odd ;AN000; +; box dot4 dot5 dot6 | dot4 dot5 dot6 box ;AN000; +; ;AN000; +; ;AN000; +; The selected box is then stored as follow: ;AN000; +; ;AN000; +; CUR_BOX: ;AN000; +; byte1 byte2 byte3 ;AN000; +; MSB ------> 0 0 0 ;AN000; +; (bit7) 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; dot1 dot2 dot3 <-- box ;AN000; +; LSB ------>dot4 dot5 dot6 ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; IF CUR_ROW is odd ;AN000; +; THEN SI := SI + BOX_W ; Access right portion of pattern ;AN000; +; Build a bit mask in BL of BOX_H bits, right justified. ;AN000; +; FOR each column in the box (BOX_W) ;AN000; +; Get the pattern column in AL ;AN000; +; IF CUR_COLUMN is even ;AN000; +; THEN ;AN000; +; Move down the column of the top box. ;AN000; +; AND BL,AL ; BL <-- Column of the desired box ;AN000; +; ;AN000; +; ;AN000; +PAT2BOX PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + ;AN000; + ; SI := Offset of current pattern ;AN000; + INC SI ; Skip the MAX INTENSITY field ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Set SI to either the left or right set of 2 boxes in the pattern: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + TEST CUR_ROW,1 ; Odd row ? ;AN000; + JZ EXTRACT_BOX ; No, access left portion of pattern ;AN000; + MOV AL,BOX_W ; ;AN000; + CBW ; ;AN000; + ADD SI,AX ; Yes, access right portion of pattern;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Extract the box: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +EXTRACT_BOX: ;AN000; +;-------Build a bit mask that will be used to keep only BOX_H bits ;AN000; +;-------of the bytes where CUR_BOX is stored. ;AN000; + XOR AH,AH ; AH := Box column bit mask ;AN000; + MOV AL,BOX_H ; For each row of the box: ;AN000; +INIT_MASK: ; ;AN000; + SHL AH,1 ; ;AN000; + OR AH,1 ; Insert one bit in the mask. ;AN000; + DEC AL ; ;AN000; + CMP AL,0 ; ;AN000; + JG INIT_MASK ;AN000; + ;AN000; + XOR BX,BX ; BL := Column number within the box ;AN000; +; ;AN000; +;-------For each column of the box: ;AN000; +EXTRACT_1_BOX_COLUMN: ;AN000; + MOV AL,[SI] ; AL := Current column of pattern ;AN000; + TEST CUR_COLUMN,1 ; If the pixel is on ODD column ;AN000; + JNZ BOTTOM_BOX ; Then, need bottom box portion ;AN000; + MOV CL,BOX_H ; Else, need top box portion ;AN000; +TOP_BOX: ; Need top box: ;AN000; + SHR AL,CL ; Shift top box over bottom box ;AN000; +BOTTOM_BOX: ; The box we want is now at bottom ;AN000; + AND AL,AH ; Keep only bits from the box ;AN000; + MOV CUR_BOX[BX],AL ; Store this box column ;AN000; + INC SI ; Access next column of the pattern ;AN000; + INC BX ; One more column stored. ;AN000; + CMP BL,BOX_W ; All stored ? ;AN000; + JL EXTRACT_1_BOX_COLUMN ; No, continue ;AN000; + ;AN000; + POP SI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PAT2BOX ENDP ;AN000; +INCLUDE GRCOMMON.ASM ;AN000; +LEN_OF_BW_MODULES EQU $-PRINT_BW_APA ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRBWPRT.EXT b/v4.0/src/CMD/GRAPHICS/GRBWPRT.EXT new file mode 100644 index 0000000..4d7526c --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRBWPRT.EXT @@ -0,0 +1,24 @@ +.XLIST ;AN000; +PAGE ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRBWPRT.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing external declarations for ;AN000; +;; the code and data defined in GRBWPRT.ASM. ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; + EXTRN PRINT_BW_APA:NEAR ;AN000; + EXTRN LEN_OF_BW_MODULES:ABS ;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCOLPRT.ASM b/v4.0/src/CMD/GRAPHICS/GRCOLPRT.ASM new file mode 100644 index 0000000..0c1d0a2 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCOLPRT.ASM @@ -0,0 +1,1122 @@ + PAGE ,132 ;AN000; + TITLE DOS GRAPHICS Command - Color printing modules +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCOLPRT.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the code for printing a screen (text and graphics) ;AN000; +;; on a COLOR printer. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; ;AN000; +;; PRINT_COLOR ;AN000; +;; SCAN_FOR_BANDS_APA ;AN000; +;; SCAN_FOR_BANDS_TXT ;AN000; +;; PRINT_BAND_APA ;AN000; +;; PRINT_BAND_TXT ;AN000; +;; SET_CURSOR ;AN000; +;; SET_COLOR_BAND ;AN000; +;; INIT_BLACK_BOX ;AN000; +;; ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; ;AN000; +;; GRCTRL.EXT - Externals for print screen control ;AN000; +;; GRCTRL.STR - Structures and equates for print screen control ;AN000; +;; GRPATTRN.STR - Structures for the printer patterns. ;AN000; +;; ;AN000; +;; GRSHAR.STR - Shared Data Area Structure ;AN000; +;; ;AN000; +;; STRUC.INC - Macros for using structured assembly language ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRCTRL.ASM: ;AN000; +;; PRT_SCR - Main module for printing the screen. ;AN000; +;; TO FILE GRCOMMON.ASM ;AN000; +;; Common modules - tools for printing a screen. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; Date last updated 5/26/87. ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +PAGE ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;AN000; + ASSUME CS:CODE,DS:CODE ;AN000; + ;AN000; + PUBLIC PRINT_MODULE_START ;; Color modules public ;AN000; + PUBLIC PRINT_COLOR ;; procedures ;AN000; + PUBLIC LEN_OF_COLOR_MODULES ;; ;AN000; + ;; ;AN000; +.XLIST ; ;AN000; +INCLUDE GRCTRL.STR ; Stuctures needed ;AN000; +INCLUDE GRSHAR.STR ; for both set of print modules ;AN000; +INCLUDE GRPATTRN.STR ; ;AN000; + ; ;AN000; +INCLUDE GRCTRL.EXT ; Externals from PRT_SCR control module ;AN000; +INCLUDE STRUC.INC ; ;AN000; +.LIST ; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AN000; +;; ;AN000; +;; ;AN000; +;; PRINT_COLOR : PRINT TEXT AND APA MODE SCREEN ON A COLOR PRINTER ;AN000; +;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; XLT_TAB = Color translation table ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Main control module for printing of text and graphics ;AN000; +;; on color printers. ;AN000; +;; ;AN000; +;; Calls either the text or graphics mode routine. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; PRINT_SCREEN ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; LOC_MODE_PRT_INFO, PRINT_COLOR_APA, PRINT_COLOR_TXT ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; IF MODE_TYPE = TXT ;AN000; +;; THEN CALL PRINT_COLOR_TXT ;AN000; +;; ELSE (MODE_TYPE = APA) ;AN000; +;; CALL LOC_MODE_PRT_INFO ; Get DISPLAYMODE record from the SHARED AREA ;AN000; +;; CALL PRINT_COLOR_APA ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +PRINT_MODULE_START LABEL BYTE ;AN000; +PRINT_COLOR PROC NEAR ;AN000; + JMP SHORT PRINT_COLOR_BEGIN ;AN000; +WHITE_BOX DB 0,0,0,0 ; Print boxes for APA mode ;AN000; +BLACK_BOX DB ?,?,?,? ; NOTE: 1 print box = 1 screen pixel ;AN000; + ; only BOX_W bytes are used out of these 2 ;AN000; + ; boxes. ;AN000; + ;AN000; +REQ_BAND_MASK DB ? ; Mask = "All color bands needed for the current;AN000; + ; print line". ;AN000; + ;AN000; +PRINT_COLOR_BEGIN: ;AN000; +.IF ;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; The screen is in a text mode: ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL PRINT_COLOR_TXT ; Print a text screen on a color printer;AN000; +.ELSE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; The screen is in All Points Addressable mode: ;AN000; +; Locate and extract printer DISPLAYMODE information from ;AN000; +; the shared data area. ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL LOC_MODE_PRT_INFO ; Get printer info related to curr. mode;AN000; +; ;AN000; +;-------Test if DISPLAYMODE info record was found: ;AN000; + .IF ;AN000; + .THEN ;AN000; + MOV ERROR_CODE,UNABLE_TO_PRINT ; IF no record found, ;AN000; + JMP SHORT PRINT_COLOR_END ; then, return error code ;AN000; + .ENDIF ; and quit procedure ;AN000; +; ;AN000; +;-------Get the box size from the DISPLAYMODE info record: ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Offset current DISPLAYMODE info.;AN000; + MOV AH,[BX].BOX_WIDTH ; Take local copy of the box size. ;AN000; + MOV BOX_W,AH ; in BOX_W and BOX_H ;AN000; + MOV AL,[BX].BOX_HEIGHT ;AN000; + MOV BOX_H,AL ;AN000; +; ;AN000; +;-------Verify if the box size obtained from DISPLAYMODE info. is valid ;AN000; + .IF OR ; IF height of the box is 0 ;AN000; + .IF ; OR width of the box is 0 ;AN000; + .THEN ; THEN we can't print: ;AN000; + MOV ERROR_CODE,UNABLE_TO_PRINT ; return error code ;AN000; + JMP SHORT PRINT_COLOR_END ; and quit ;AN000; + .ENDIF ;AN000; +; ;AN000; +;-------Get the Print Orientation from the DISPLAYMODE info record ;AN000; + .IF <[BX].PRINT_OPTIONS EQ ROTATE>; If printing sideways ;AN000; + .THEN ; then: ;AN000; + MOV ROTATE_SW,ON ; Rotate switch := "ON" ;AN000; + .ENDIF ;AN000; + CALL PRINT_COLOR_APA ; Print APA screen on a color printer ;AN000; +.ENDIF ;AN000; +PRINT_COLOR_END: ;AN000; + RET ;AN000; +PRINT_COLOR ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_COLOR_TXT: PRINT A TEXT MODE SCREEN ON A COLOR PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; XLT_TAB = Color translation table ;AN000; +; SCREEN_WIDTH = Maximum length of Screen scan line. ;AN000; +; SCREEN_HEIGHT = Number of SCAN LINES on the screen ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: The screen is read and printed line by line; character by ;AN000; +; character. ;AN000; +; Each line is first scanned in order to determine what colors are present on ;AN000; +; it and what printer bands will be needed to approximate these colors. ;AN000; +; ;AN000; +; For each printer color band needed for the current line, this screen line ;AN000; +; is READ AGAIN character by character; If the color of the ;AN000; +; current character must use the current color band to be ;AN000; +; approximated; then, the character is printed. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC : ;AN000; +; ;AN000; +; Save current coordinates of the cursor. ;AN000; +; Initialize the cursor to the first character to be read (Top-left of screen) ;AN000; +; FOR each row on the screen (SCREEN_HEIGHT) ;AN000; +; BEGIN ;AN000; +; CALL SCAN_FOR_BANDS_TXT(CUR_ROW,CUR_COLUMN,REQ_BAND_MASK) ;AN000; +; CUR_BAND_MASK := 01H ;AN000; +; IF REQ_BAND_MASK <> 0 THEN ;AN000; +; DO 8 TIMES ;AN000; +; IF (REQ_BAND_MASK AND CUR_BAND_MASK)=1 THEN ;AN000; +; CALL PRINT_BAND_TXT(CUR_ROW,CUR_COLUMN,CUR_BAND_MASK) ;AN000; +; CALL PRINT_BYTE(CARRIAGE_RETURN) ;AN000; +; ENDIF ;AN000; +; Shift CUR_BAND_MASK one bit left ;AN000; +; ENDDO ;AN000; +; CALL PRINT_BYTE(LINE_FEED) ;AN000; +; ENDIF ;AN000; +; CUR_COLUMN := 0 ; Get next row coordinates ;AN000; +; CUR_ROW := CUR_ROW + 1 ;AN000; +; END ; FOR each row on the screen ;AN000; +; Restore initial coordinates of the cursor ;AN000; +; ;AN000; +PRINT_COLOR_TXT PROC ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; +; ;AN000; +;-------Save coordinates of the cursor on the stack: ;AN000; + MOV AH,READ_CURSOR_CALL ; Read position of the cursor on the screen;AN000; + MOV BH,CUR_PAGE ; for the current page ;AN000; + INT 10H ; Call BIOS ;AN000; + PUSH DX ; DH := Row number, DL := Column number ;AN000; + ; CX := Top line and bottom line for cursor;AN000; + ; (not needed) ;AN000; +; ;AN000; +;-------Initialize the cursor to the first character to be read ;AN000; + MOV CUR_ROW,0 ; cursor = position (0,0) on the screen ;AN000; + MOV CUR_COLUMN,0 ; (top-left corner) ;AN000; + CALL SET_CURSOR ;AN000; + ;AN000; + MOV CX,SCREEN_HEIGHT ; CX := Number of rows on the screen ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; FOR EACH ROW ON THE SCREEN: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_1_TEXT_LINE: ;AN000; + CALL SCAN_FOR_BANDS_TXT ; REQ_BAND_MASK := Print bands needed ;AN000; + ; for this line ;AN000; + MOV DL,01H ; DL :="Current Band printed" mask ;AN000; + ;AN000; + ; NOTE: The COLORSELECT records are stored sequentially in the ;AN000; + ; Shared Data area. The band mask 00000001 corresponds to the first ;AN000; + ; record, 00000010 to the second, etc. ;AN000; + ; The COLORSELECT record indicates: "How to select the color band" ;AN000; + ; on the printer (It contains the bytes that must be sent to the printer;AN000; + ;AN000; + MOV BX,DS:[BP].COLORSELECT_PTR; BX := relative offset of COLORSELECT;AN000; + ADD BX,BP ; BX := absolute offset of COLORSELECT ;AN000; + PUSH CX ; Save row counter ;AN000; + MOV CX,8 ; For up to the maximum number of print ;AN000; + ; bands with this printer ;AN000; + ;-----------------------------------------------------------------------;AN000; + ; ;AN000; + ; FOR each Color Band available with the ribbon installed on the printer;AN000; + ; ;AN000; + ;-----------------------------------------------------------------------;AN000; + PRINT_1_COLOR_BAND_TXT: ; Do one pass of the printer head: ;AN000; + .IF ; IF this color band is needed ;AN000; + .THEN ; by any character on the line ;AN000; + CALL SET_COLOR_BAND ; then, select the color band ;AN000; + CALL PRINT_BAND_TXT ; and do one Print Pass for it. ;AN000; + .IF ;AN000; + .THEN ; A printer error occurred: ;AN000; + POP CX ; Restore the line counter ;AN000; + JMP PRINT_COLOR_TXT_END ; and quit. ;AN000; + .ENDIF ;AN000; + MOV AL,CR ; Print a carriage return ;AN000; + CALL PRINT_BYTE ;AN000; + .IF C ;AN000; + .THEN ; A printer error occurred: ;AN000; + POP CX ; Restore the line counter ;AN000; + JMP PRINT_COLOR_TXT_END ; and quit. ;AN000; + .ENDIF ; ENDIF printer error ;AN000; + .ENDIF ; ENDIF this color band is needed ;AN000; + SHL DL,1 ; Get next Color Band mask ;AN000; + ; [BX] := Next COLORSELECT record: ;AN000; + MOV AL,[BX].NUM_SELECT_ESC ; skip the escape bytes ;AN000; + XOR AH,AH ; ;AN000; + ADD BX,AX ; ;AN000; + INC BX ; skip the NUM_SELECT_ESC field ;AN000; + LOOP PRINT_1_COLOR_BAND_TXT ;AN000; + POP CX ; Restore row counter ;AN000; +; ;AN000; +;-----Print a line feed: ;AN000; + MOV AL,LF ;AN000; + CALL PRINT_BYTE ; Send the LF ;AN000; + JC PRINT_COLOR_TXT_END ; If printer error, quit ;AN000; +; ;AN000; +;-------Get coordinates of the first character in the next scan line: ;AN000; + INC CUR_ROW ; CUR_ROW + 1 ;AN000; + MOV CUR_COLUMN,0 ; CUR_COLUMN := 0 ;AN000; +; ;AN000; +;-------Point CURSOR to first character in the next scan line: ;AN000; + CALL SET_CURSOR ;AN000; + ;AN000; + LOOP PRINT_1_TEXT_LINE ; Print next scan line ;AN000; + ;AN000; +; ;AN000; +;-------Restore CURSOR to its original location (saved on the stack) ;AN000; +PRINT_COLOR_TXT_END: ;AN000; + POP DX ; DH := Row number, DL := Column number ;AN000; + MOV CL,DH ;AN000; + MOV CUR_ROW,CX ; CUR_ROW := Original row number ;AN000; + MOV CL,DL ;AN000; + MOV CUR_COLUMN,CX ; CUR_COLUMN := Original column number ;AN000; + CALL SET_CURSOR ; Set the cursor back there ;AN000; + ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +PRINT_COLOR_TXT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SCAN_FOR_BANDS_TEXT: DETERMINE WHAT PRINTER COLOR BANDS ARE NEEDED FOR ;AN000; +; PRINTING THE COLORS ON THE CURRENT SCREEN LINE. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW = row to start scanning ;AN000; +; CUR_COLUMN = column to start scanning ;AN000; +; ROTATE_SW = ON if printing is sideways ;AN000; +; ;AN000; +; OUTPUT: REQ_BAND_MASK ;AN000; +; ;AN000; +; ;AN000; +; DATA STRUCTURE REFERENCED: ;AN000; +; XLT_TAB = Color translation table ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Read all characters on the current line from left to right. ;AN000; +; For each character, extract its band mask from the color translation table. ;AN000; +; Add the band mask required for this character to the "Required Bands" mask. ;AN000; +; ;AN000; +; LOGIC : ;AN000; +; Save current coordinates ;AN000; +; DO (SCREEN_WIDTH) TIMES ;AN000; +; Read a character ;AN000; +; Get its Band Mask from the color translation table in AL ;AN000; +; OR REQ_BAND_MASK,AL ; Add its band mask to the "Required bands" mask;AN000; +; ; Get coordinates of the next character: ;AN000; +; INC CUR_COLUMN ;AN000; +; Restore initial coordinates ;AN000; +; ;AN000; +SCAN_FOR_BANDS_TXT PROC NEAR ;AN000; + PUSH CUR_ROW ; Save coordinates ;AN000; + PUSH CUR_COLUMN ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV REQ_BAND_MASK,0 ; No Color bands needed so far... ;AN000; + MOV CX,SCREEN_WIDTH ; For each character on the screen row ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; FOR each character on the current scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SCAN_1_CHAR: ;AN000; +; ;AN000; +;-------Read the character at the current cursor position ;AN000; + CALL SET_CURSOR ; Set cursor at character to be read ;AN000; + MOV AH,READ_CHAR_CALL ; Read one character ;AN000; + MOV BH,CUR_PAGE ; at CUR_PAGE, CUR_COLUMN and CUR_ROW ;AN000; + INT 10H ; Call BIOS ;AN000; + ; AL:=Character read, AH:=Byte attribute;AN000; + AND AH,00001111B ; AH := Foreground color attribute ;AN000; + XCHG AL,AH ; AL := AH, used as index in the XLT_TAB;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of translation table ;AN000; + XLAT XLT_TAB ; AL = Band mask ;AN000; +; ;AN000; +;-------Obtain what Print bands are required to print the color of this char: ;AN000; + OR REQ_BAND_MASK,AL ;AN000; + ;AN000; + INC CUR_COLUMN ; Get coordinates of next character ;AN000; + LOOP SCAN_1_CHAR ; Scan next character ;AN000; + ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + POP CUR_COLUMN ; Restore initial coordinates ;AN000; + POP CUR_ROW ;AN000; + RET ;AN000; +SCAN_FOR_BANDS_TXT ENDP ;AN000; +PAGE ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AN000; +;; ;AN000; +;; PRINT_BAND_TXT: PRINT ALL CHARACTERS ON THE CURRENT LINE THAT ARE THE SAME ;AN000; +;; COLOR AS THE CURRENT PRINT BAND. ;AN000; +;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW, ;AN000; +; CUR_COLUMN : Coordinates of the first character to be read in ;AN000; +; the current scan line. ;AN000; +; DL : Band mask indicating what print band to use ;AN000; +; for this print pass. ;AN000; +; SCAN_LINE_LENGTH: Length of the current scan line. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; LOGIC: ;AN000; +; DO (SCAN_LINE_LENGTH) TIMES ;AN000; +; CALL BIOS INT 10H Read Character - returns CHAR, COLOR_NUM ;AN000; +; IF (CUR_BAND_MASK AND XLAT_TAB[COLOR_NUM])=1 ;AN000; +; THEN IF Background color is same as Foreground color ;AN000; +; THEN ;AN000; +; CALL PRINT_BYTE(SOLID_BOX) ;AN000; +; ELSE ;AN000; +; CALL PRINT_BYTE(CHAR) ;AN000; +; ELSE ;AN000; +; CALL PRINT_BYTE(blank) ;AN000; +; Get coordinates of the next character ;AN000; +; ;AN000; +PRINT_BAND_TXT PROC ;AN000; +SOLID_BOX EQU 219 ; ASCII Code for printing a solid box ;AN000; +BLANK EQU 32 ; ASCII code for printing a space ;AN000; + PUSH CUR_COLUMN ; Save column number ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + MOV CX,SCREEN_WIDTH ; CX := Number of character on one screen row ;AN000; +;===============================================================================;AN000; +; ;AN000; +; FOR each character on the current row: ;AN000; +; ;AN000; +;===============================================================================;AN000; +PRINT_1_CHAR: ;AN000; +; ;AN000; +;-------Read the character at the current cursor position ;AN000; + CALL SET_CURSOR ; Set cursor at character to be read ;AN000; + MOV AH,READ_CHAR_CALL ; Read one character ;AN000; + MOV BH,CUR_PAGE ; at CUR_PAGE, CUR_COLUMN and CUR_ROW ;AN000; + INT 10H ; Call BIOS ;AN000; + ; AL:=Character read, AH:=Byte attribute;AN000; + MOV CUR_CHAR,AL ;AN000; + MOV DH,AH ; DH := Byte attribute ;AN000; + AND DH,11110000B ; DH := Background color ;AN000; + SHR DH,1 ; DH := Background color right justified;AN000; + SHR DH,1 ;AN000; + SHR DH,1 ;AN000; + SHR DH,1 ;AN000; + AND AH,00001111B ; AH := Foreground color right justified;AN000; +; ;AN000; +;-------Test if this character should be printed (need color of the current band;AN000; + MOV AL,AH ; AL:=color used as index in the XLT_TAB;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of translation table ;AN000; + XLAT XLT_TAB ; AL := Band mask (DL=current band mask);AN000; + .IF ;If needs this band to print the color ;AN000; + .THEN ; of this character ;AN000; + .IF ; then: when foreground = background ;AN000; + .THEN ; send a solid box ;AN000; + MOV AL,SOLID_BOX ; ;AN000; + .ELSE ; when foreground <> background ;AN000; + MOV AL,CUR_CHAR ; send the character ;AN000; + .ENDIF ; Endif foreground = background ;AN000; + .ELSE ; else: send a blank ;AN000; + MOV AL,BLANK ; ;AN000; + .ENDIF ; Endif color band needed ;AN000; + CALL PRINT_BYTE ; Print the byte ;AN000; + JC PRINT_BAND_TXT_END ; If printer error occurred: QUIT ;AN000; + INC CUR_COLUMN ; Else, Get next column; keep going ;AN000; + LOOP PRINT_1_CHAR ;AN000; + ;AN000; +PRINT_BAND_TXT_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + POP CUR_COLUMN ; Restore column number ;AN000; + RET ;AN000; +CUR_CHAR DB ? ;AN000; +PRINT_BAND_TXT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_COLOR_APA: PRINT AN APA MODE SCREEN ON A COLOR PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; XLT_TAB = Color translation table ;AN000; +; CUR_MODE_PTR = Coordinates of current DISPLAYMODE info. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Each pixel on the screen is printed as a "box" of dots on the ;AN000; +; printer. For a screen pixel of a given color, the best color approximation ;AN000; +; is chosen among the color available on the printer. ;AN000; +; ;AN000; +; The printer colors are obtained by selecting a print band. A few more printer ;AN000; +; color are obtained by printing twice (or more times) with different color ;AN000; +; bands. ;AN000; +; ;AN000; +; For example, let's say we have a ribbon on the printer with a YELLOW CYAN ;AN000; +; MAGENTA ribbon and we read a GREEN pixel on the screen. ;AN000; +; ;AN000; +; We first determine what "box" size will be used to represent this pixel. ;AN000; +; Let's say it's a 3x2 box (this is obtained from the DISPLAYMODE record) ;AN000; +; In all cases, we will print this pixel as a 3x2 box of printer dots. ;AN000; +; That is, we will print 6 dots on the printer for one on the screen. ;AN000; +; We do not use any kind of patterns (e,g,. printing only 2 dots out of 6) ;AN000; +; for printing on the color printer. A screen pixel is either printed ;AN000; +; as a "full" box of printer dots or not printed at all (e,g,. if it's white).;AN000; +; ;AN000; +; Now, from the COLORPRINT records, we know all the colors availables on the ;AN000; +; printer, and what print bands must be used (or overlaid) in order to ;AN000; +; obtain them. ;AN000; +; ;AN000; +; So, we consult these COLORPRINT records one by one comparing how close ;AN000; +; the color of each of them is to our GREEN pixel. (the colors for our pixel ;AN000; +; AND for the printer color are both indicated in terms of RGB values) ;AN000; +; WE PICK THE CLOSEST PRINTER COLOR. ;AN000; +; ;AN000; +; To conclude, our GREEN pixel will be printed by first selecting the YELLOW ;AN000; +; band, then sending to the printer a "box". Then, the BLUE band is selected ;AN000; +; and the "box" is sent again. ;AN000; +; ;AN000; +; This process is carried line by line. ;AN000; +; ;AN000; +; For each line, we first read each pixel to see what color bands are going ;AN000; +; to be needed for this line. ;AN000; +; ;AN000; +; Then, we loop for each band available on the printer. ;AN000; +; ;AN000; +; IF the current line needs the current printer band (i.e.,if any pixel on ;AN000; +; the line needs this color band in order to achieve its color. ;AN000; +; THEN, we select this color band (we know how to do it from the COLORSELECT ;AN000; +; record in the Shared Data area) ;AN000; +; AND we must read the line again; for each pixel that needs the current ;AN000; +; band a "box" is sent to the printer. ;AN000; +; ;AN000; +; LOGIC : ;AN000; +; CALL INIT_BLACK_BOX ; Initialize a print box ;AN000; +; CALL GET_SCREEN_INFO ;AN000; +; CALL SETUP_PRT ;AN000; +; DO (NB_SCAN_LINES) TIMES ;AN000; +; CALL DET_CUR_SCAN_LNE_LENGTH ;AN000; +; IF CUR_SCAN_LNE_LENGTH NE 0 THEN ;AN000; +; CALL SCAN_FOR_BANDS_APA(CUR_ROW,CUR_COLUMN,REQ_BAND_MASK) ;AN000; +; CUR_BAND_MASK := 01H ;AN000; +; IF REQ_BAND_MASK <> 0 THEN ;AN000; +; DO 8 TIMES ;AN000; +; IF (REQ_BAND_MASK AND CUR_BAND_MASK)=1 THEN ;AN000; +; CALL NEW_PRT_LINE ;AN000; +; CALL PRINT_BAND_APA(CUR_ROW,CUR_COLUMN,CUR_BAND_MASK) ;AN000; +; CALL PRINT_BYTE(CARRIAGE_RETURN) ;AN000; +; ENDIF ;AN000; +; Shift CUR_BAND_MASK one bit left ;AN000; +; ENDDO ;AN000; +; ENDIF ; Should make a print pass for this color band ;AN000; +; CALL PRINT_BYTE(LINE_FEED) ;AN000; +; ENDIF ; Current scan line is not empty ;AN000; +; IF rotated print THEN ;AN000; +; CUR_COLUMN := CUR_COLUMN - BOXES_PER_PRT_BUF ;AN000; +; CUR_ROW := SAVE_START_ROW ;AN000; +; ELSE ;AN000; +; CUR_ROW := CUR_ROW + BOXES_PER_PRT_BUF ;AN000; +; CUR_COLUMN := SAVE_START_COLUMN ;AN000; +; ENDIF ;AN000; +; ENDDO ; Number of Scan lines ;AN000; +; CALL RESTORE_PRT ;AN000; +; ;AN000; +PRINT_COLOR_APA PROC ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; + ;AN000; +;-------Initialize print box (A "box" represents one screen pel on the printer) ;AN000; + CALL INIT_BLACK_BOX ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Determine where to start reading the screen: ;AN000; +; If printing sideways, start in LOW LEFT corner. ;AN000; +; If normal printing, start in TOP LEFT corner. ;AN000; +; Determine the maximum length for a scan line: ;AN000; +; If printing sideways, it is the height of the screen. ;AN000; +; For normal printing, it is the width of the screen. ;AN000; +; Determine the number of scan lines on the screen. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL GET_SCREEN_INFO ; Get info. about how to read the screen;AN000; + CALL SETUP_PRT ; Set up the printer (Line spacing, etc);AN000; + .IF ;AN000; + .THEN ; A printer error occurred: quit ;AN000; + JMP PRINT_COLOR_APA_END ; ;AN000; + .ENDIF ;AN000; + ;AN000; + MOV CX,NB_SCAN_LINES ;AN000; +;---------------------------------------------------------------------------- ;AN000; +; ;AN000; +; FOR EACH SCAN LINE ON THE SCREEN (and each print line): ;AN000; +; ;AN000; +;---------------------------------------------------------------------------- ;AN000; +PRINT_SCAN_LINE: ;AN000; + CALL DET_CUR_SCAN_LNE_LENGTH ; Determine length of the scan line ;AN000; + .IF ; If line is not empty ;AN000; + .THEN ;AN000; + CALL SCAN_FOR_BANDS_APA ; REQ_BAND_MASK := Mask for what print;AN000; + ; bands are needed. ;AN000; + MOV DL,01H ; DL := "Current Band to be printed" ;AN000; + MOV BX,DS:[BP].COLORSELECT_PTR; BX := Offset of COLORSELECT record;AN000; + ADD BX,BP ; ("How to select the color band");AN000; + PUSH CX ; Save scan line counter ;AN000; + MOV CX,8 ; For up to the maximum number of prin;AN000; + ; bands with this printer ;AN000; + ;---------------------------------------------------------------------;AN000; + ; ;AN000; + ; FOR each Color Band needed: ;AN000; + ; ;AN000; + ;---------------------------------------------------------------------;AN000; + PRINT_1_COLOR_BAND_APA: ; Only if this color band is needed: ;AN000; + .IF ; Do one pass of the printer head ;AN000; + .THEN ; ;AN000; + CALL SET_COLOR_BAND ; Select the color band on the printer;AN000; + CALL NEW_PRT_LINE ; Send escape sequence to the printer ;AN000; + ; for starting a new graphics line ;AN000; + .IF ;AN000; + .THEN ; A printer error occurred: ;AN000; + POP CX ; Restore the line counter and ;AN000; + JMP PRINT_COLOR_APA_END ; return ;AN000; + .ENDIF ; Endif printer error occurred ;AN000; + ;AN000; + CALL PRINT_BAND_APA ; Do one Print Pass for current band ;AN000; + MOV AL,CR ; Print a carriage return ;AN000; + CALL PRINT_BYTE ;AN000; + .IF C ; If a printer error occurred ;AN000; + .THEN ;AN000; + POP CX ; Restore the line counter and ;AN000; + JMP PRINT_COLOR_APA_END ; return ;AN000; + .ENDIF ; End if printer error occurred ;AN000; + .ENDIF ; End if this color band is needed ;AN000; + SHL DL,1 ; Get next Color Band mask ;AN000; + ; Locate next COLORSELECT record: ;AN000; + MOV AL,[BX].NUM_SELECT_ESC; skip the escape bytes ;AN000; + XOR AH,AH ;AN000; + ADD BX,AX ;AN000; + INC BX ; skip the NUM_SELECT_ESC field ;AN000; + LOOP PRINT_1_COLOR_BAND_APA ;AN000; + POP CX ; Restore scan line counter ;AN000; + .ENDIF ; Scan line length <> 0 ;AN000; +; ;AN000; +;-----Print a line feed: ;AN000; + MOV AL,LF ;AN000; + CALL PRINT_BYTE ;AN000; + JC PRINT_COLOR_APA_END ; If a printer error occurred: quit ;AN000; +; ;AN000; +;-------Get coordinates of next scan line: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then: ;AN000; + MOV AL,NB_BOXES_PER_PRT_BUF; AX := Numbers of pels read on row ;AN000; + CBW ; ;AN000; + ADD CUR_COLUMN,AX ; CUR_COLUMN + Number of pels read ;AN000; + MOV AX,SCREEN_HEIGHT ; CUR_ROW := SCREEN_HEIGHT - 1 ;AN000; + DEC AX ; ;AN000; + MOV CUR_ROW,AX ; ;AN000; + .ELSE ; else, printing NOT rotated: ;AN000; + MOV AL,NB_BOXES_PER_PRT_BUF ; AX := Number of pels read on column ;AN000; + CBW ; ;AN000; + ADD CUR_ROW,AX ; CUR_ROW + Number of pels read ;AN000; + MOV CUR_COLUMN,0 ; CUR_COLUMN := 0 ;AN000; + .ENDIF ; End if printing sideways ;AN000; + LOOP PRINT_SCAN_LINE ; ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Restore the printer (send a Page Eject, etc.) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL RESTORE_PRT ;AN000; +PRINT_COLOR_APA_END: ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_COLOR_APA ENDP ;AN000; +PAGE ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AN000; +;; ;AN000; +;; ;AN000; +;; SCAN_FOR_BANDS_APA : DETERMINE WHAT PRINT BANDS ARE NEEDED FOR THE CURRENT ;AN000; +;; PRINT PASS. ;AN000; +;; ;AN000; +;;------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW : row to start scanning (word) ;AN000; +; CUR_COLUMN : column to start scanning (word) ;AN000; +; CUR_SCAN_LNE_LENGTH : length of the current scan line (word) ;AN000; +; ROTATE_SW = ON if printing is sideways ;AN000; +; ;AN000; +; OUTPUT: REQ_BAND_MASK : band mask for required bands (byte) ;AN000; +; ;AN000; +;;------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Shared Data Area ;AN000; +;; Print Info ;AN000; +;; Color Translate Table ;AN000; +;; ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Read all the dots required for one print line to determine ;AN000; +;; the print bands required. The print line corresponds to several ;AN000; +;; screen rows (or columns if rotated printing). The number of ;AN000; +;; rows / columns per print line is stored in NB_BOXES_PER_PRT_BUF. ;AN000; +;; The band information is obtained from the Color Translate Table. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; PRINT_COLOR_APA ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; READ_DOT, BIOS INT 10H ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; Save initial coordinates ;AN000; +;; SAVE_START_COLUMN := CUR_COLUMN ;AN000; +;; REQ_BAND_MASK := 00H ;AN000; +;; DO (SCAN_LINE_LENGTH) TIMES ;AN000; +;; Save coordinates of the "column" ;AN000; +;; DO (BOXES_PER_PRT_BUF) TIMES ;AN000; +;; CALL READ_DOT(IN CUR_ROW,CUR_COLUMN; OUT COLOR_NUM) ;AN000; +;; REQ_BAND_MASK := REQ_BAND_MASK OR COLOR_XLAT_TAB[BX] ;AN000; +;; IF rotated print THEN ;AN000; +;; Increment CUR_COLUMN ;AN000; +;; ELSE ;AN000; +;; Increment CUR_ROW ;AN000; +;; ENDIF ;AN000; +;; Restore coordinates of the "column" ;AN000; +;; ENDDO ;AN000; +;; IF rotated print THEN ;AN000; +;; Decrement CUR_ROW ;AN000; +;; ELSE ;AN000; +;; Increment CUR_COLUMN ;AN000; +;; ENDIF ;AN000; +;; ENDDO ;AN000; +;; Restore initial coordinates ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +SCAN_FOR_BANDS_APA PROC NEAR ;AN000; + PUSH CUR_ROW ;AN000; + PUSH CUR_COLUMN ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV REQ_BAND_MASK,0 ; No Color bands needed so far... ;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of translation table ;AN000; + MOV CX,CUR_SCAN_LNE_LENGTH ;AN000; +;===============================================================================;AN000; +; ;AN000; +; FOR each column on the current scan line (up to the last non=blank): ;AN000; +; ;AN000; +;===============================================================================;AN000; +SCAN_1_COLUMN: ;AN000; + PUSH CX ; Save column counter ;AN000; + PUSH CUR_ROW ; Save coordinates of the "column" ;AN000; + PUSH CUR_COLUMN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; For each pixel within the current column of the scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR CX,CX ; CX := Number of pixels to read ;AN000; + MOV CL,NB_BOXES_PER_PRT_BUF ; within the current "column" ;AN000; +SCAN_1_PIXEL: ;AN000; + CALL READ_DOT ; AL := Index into translation table ;AN000; + XLAT XLT_TAB ; AL := Band mask ;AN000; + OR REQ_BAND_MASK,AL ; Add bands required for this pixel ;AN000; + ;AN000; +;-------Get coordinates of next pixel: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + INC CUR_COLUMN ; then, increment column number ;AN000; + .ELSE ; ;AN000; + INC CUR_ROW ; else, increment row number ;AN000; + .ENDIF ; ;AN000; + LOOP SCAN_1_PIXEL ;AN000; + POP CUR_COLUMN ; Restore coordinates of the "column" ;AN000; + POP CUR_ROW ; ;AN000; + POP CX ; Restore column counter ;AN000; + ;AN000; + ;AN000; +;-------Get coordinates of next "column": ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + DEC CUR_ROW ; then, get row above on screen ;AN000; + .ELSE ; ;AN000; + INC CUR_COLUMN ; else, get column next right ;AN000; + .ENDIF ; ;AN000; + LOOP SCAN_1_COLUMN ;AN000; + ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + POP CUR_COLUMN ;AN000; + POP CUR_ROW ;AN000; + RET ;AN000; +SCAN_FOR_BANDS_APA ENDP ;AN000; +PAGE ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AN000; +;; ;AN000; +;; PRINT_BAND_APA : PRINT ALL DOTS ON CURRENT LINE THAT NEED THE CURRENT BAND ;AN000; +;; TO APPROXIMATE THEIR COLOR. ;AN000; +;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW, ;AN000; +; CUR_COLUMN : Coordinates of the first pixel to be read in the ;AN000; +; current scan line. ;AN000; +; DL : Band mask indicating what print band to use ;AN000; +; for this print pass. ;AN000; +; CUR_SCAN_LNE_LENGTH: Length of the current scan line. ;AN000; +; ROTATE_SW = ON if printing is sideways ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Shared Data Area ;AN000; +;; Print Info ;AN000; +;; Color Translate Table ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Print all dots on this print line which need the current ;AN000; +;; band. The print line corresponds to several ;AN000; +;; screen rows (or columns if rotated printing). The number of ;AN000; +;; rows / columns per print line is stored in NB_BOXES_PER_PRT_BUF. ;AN000; +;; The band information is obtained from the Color Translate Table. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; PRINT_COLOR_APA ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; READ_DOT, BIOS INT 10H, STORE_BOX, PRT_BUFFER, PRINT_BYTE ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; SAVE_START_ROW := CUR_ROW ;AN000; +;; SAVE_START_COLUMN := CUR_COLUMN ;AN000; +;; ;AN000; +;; CALL SET_COLOR_BAND ; Select the color for this print pass ;AN000; +;; DO (SCAN_LINE_LENGTH) TIMES ;AN000; +;; Save coordinates of the "column" ;AN000; +;; Clear the print buffer ;AN000; +;; DO (BOXES_PER_PRT_BUF) TIMES ;AN000; +;; CALL READ_DOT(CUR_ROW,CUR_COLUMN,COLOR_NUM) ;AN000; +;; IF (CUR_BAND_MASK AND XLAT_TAB[COLOR_NUM])=1 THEN ;AN000; +;; CALL STORE_BOX(black box) ;AN000; +;; ELSE ;AN000; +;; CALL STORE_BOX(white box) ;AN000; +;; ENDIF ;AN000; +;; IF rotated print THEN ;AN000; +;; Decrement CUR_COLUMN ;AN000; +;; ELSE ;AN000; +;; Increment CUR_ROW ;AN000; +;; ENDIF ;AN000; +;; ENDDO ;AN000; +;; CALL PRINT_BUFFER ;AN000; +;; Restore coordinates of the "column" ;AN000; +;; ; Get coordinates of the next "column"; ;AN000; +;; IF rotated print THEN ;AN000; +;; Decrement CUR_ROW ;AN000; +;; CUR_COLUMN := SAVE_START_COLUMN ;AN000; +;; ELSE ;AN000; +;; Increment CUR_COLUMN ;AN000; +;; CUR_ROW := SAVE_START_ROW ;AN000; +;; ENDIF ;AN000; +;; ENDDO ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AN000; +PRINT_BAND_APA PROC NEAR ;AN000; + PUSH CUR_ROW ; Save coordinates ;AN000; + PUSH CUR_COLUMN ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of translation table ;AN000; + MOV CX,CUR_SCAN_LNE_LENGTH ;AN000; +;===============================================================================;AN000; +; ;AN000; +; FOR each column on the current scan line (up to the last non=blank): ;AN000; +; (One "column" contains the number of pixels required to fill the Print buffer);AN000; +; ;AN000; +;===============================================================================;AN000; +PRINT_1_COLUMN: ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Clear the print buffer "PRT_BUF" ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR DI,DI ; DI := Number of bytes cleared in the buffer ;AN000; + XOR AX,AX ;AN000; + MOV AL,BOX_W ; AX := Number of bytes in the print buffer ;AN000; +CLEAR_BUF: ; For each byte in the PRT_BUF: ;AN000; + MOV PRT_BUF[DI],0 ; Initialize byte to blanks ;AN000; + INC DI ; One more has been cleared ;AN000; + CMP DI,AX ; All bytes cleared ? ;AN000; + JL CLEAR_BUF ; No, clear next one. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Fill up the print buffer "PRT_BUF" ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + PUSH CX ; Save column counter ;AN000; + XOR CX,CX ; CX := Number of pixels to read ;AN000; + MOV CL,NB_BOXES_PER_PRT_BUF ; within the current "column" ;AN000; + ; of the scan line ;AN000; + PUSH CUR_ROW ; Save coordinates of the "column" ;AN000; + PUSH CUR_COLUMN ;AN000; +; ;AN000; +; For each pixel within the current column of the scan line: ;AN000; +STORE_1_PIXEL: ;AN000; + CALL READ_DOT ; AL := Index into translation table ;AN000; + XLAT XLT_TAB ; AL := Band mask ;AN000; + .IF ; If color of the current pixel needs ;AN000; + .THEN ; the current printer band ;AN000; + MOV SI,OFFSET BLACK_BOX ; then, store a box in the ;AN000; + CALL STORE_BOX ; PRT_BUF ;AN000; + .ELSE ; ;AN000; + MOV SI,OFFSET WHITE_BOX ; else, store an empty box ;AN000; + CALL STORE_BOX ; in the PRT_BUF ;AN000; + .ENDIF ;AN000; +; ;AN000; +;-------Get coordinates of next pixel: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + INC CUR_COLUMN ; then, increment column number ;AN000; + .ELSE ; ;AN000; + INC CUR_ROW ; else, increment row number ;AN000; + .ENDIF ; ;AN000; + LOOP STORE_1_PIXEL ;AN000; + ;AN000; + POP CUR_COLUMN ; Restore coordinates of the "column" ;AN000; + POP CUR_ROW ; ;AN000; + POP CX ; Restore column counter ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Print the PRT_BUF: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL PRINT_BUFFER ;AN000; + .IF ;AN000; + .THEN ; A printer error occurred: QUIT ;AN000; + JMP SHORT PRINT_BAND_APA_END ; ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Get coordinates of next "column": ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + DEC CUR_ROW ; then, get row above on screen ;AN000; + .ELSE ; ;AN000; + INC CUR_COLUMN ; else, get column next right ;AN000; + .ENDIF ; ;AN000; + LOOP PRINT_1_COLUMN ;AN000; + ;AN000; +PRINT_BAND_APA_END: ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + POP CUR_COLUMN ; Restore initial coordinates ;AN000; + POP CUR_ROW ;AN000; + RET ;AN000; +PRINT_BAND_APA ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SET_CURSOR : SET THE CURSOR TO CUR_ROW, CUR_COLUMN AND CUR_PAGE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW, ;AN000; +; CUR_COLUMN = Coordinates for the cursor (word) ;AN000; +; CUR_PAGE = Page for which to set the cursor (byte) ;AN000; +; ;AN000; +; OUTPUT: SCREEN ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SET_CURSOR PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH DX ;AN000; + MOV DH,BYTE PTR CUR_ROW ;AN000; + MOV DL,BYTE PTR CUR_COLUMN ;AN000; + MOV BH,CUR_PAGE ;AN000; + MOV AH,SET_CURSOR_CALL ; Set cursor request ;AN000; + INT 10H ; Call BIOS ;AN000; + POP DX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +SET_CURSOR ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SET_COLOR_BAND : SET THE PRINTER TO THE CURRENT COLOR BAND ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BX = Offset of current COLORSELECT record in the ;AN000; +; Shared data area. ;AN000; +; DS:[BP] = Offset of shared data area ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SET_COLOR_BAND PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; +;-------Send the escape sequence for selecting this color band to the printer: ;AN000; + XOR CX,CX ;AN000; + MOV CL,[BX].NUM_SELECT_ESC ; CX := Number of bytes to send ;AN000; + ADD BX,OFFSET SELECT_ESC ; BX := Offset of bytes to send ;AN000; +SEND_1_COLORSELECT_BYTE: ;AN000; + MOV AL,[BX] ; AL := Byte to send to printer ;AN000; + CALL PRINT_BYTE ; Send it ;AN000; + JC SET_COLOR_BAND_END ; If printer error: return ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_COLORSELECT_BYTE ;AN000; + ;AN000; +SET_COLOR_BAND_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +SET_COLOR_BAND ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; INIT_BLACK_BOX: INIT. THE BOX FOR PRINTING APA MODE DOTS ON A COLOR PRINTER. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BOX_W, ;AN000; +; BOX_H = Size of the print box for one pixel. ;AN000; +; ;AN000; +; OUTPUT: BLACK_BOX = A box for which all dots are on. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Initialize the print box used to print a screen pixel. ;AN000; +; ;AN000; +; For example, ;AN000; +; with a size of 3x2 the BLACK_BOX will use 3 bytes: ;AN000; +; ;AN000; +; ;AN000; +; byte1 byte2 byte3 ;AN000; +; (column1) (column2) (column3) ;AN000; +; bit 7 -->0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 1 1 1 ;AN000; +; bit 0 -->1 1 1 ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +INIT_BLACK_BOX PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; +;-------Build one box column: ;AN000; + XOR CX,CX ;AN000; + MOV CL,BOX_H ; CX := Height in bits of the print box ;AN000; + XOR AL,AL ; AX := Bit mask for creating box column ;AN000; + .REPEAT ; For height of the box: ;AN000; + SHL AL,1 ; ;AN000; + OR AL,1 ; Insert one bit in the box column ;AN000; + .LOOP ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; AL now contains one box column. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +;-------Replicate this column over all columns of the box. ;AN000; + XOR BX,BX ; BX := Index into the BOX ;AN000; +INIT_1_BLACK_COLUMN: ;AN000; + MOV BLACK_BOX[BX],AL; Init current column to black box column ;AN000; + INC BX ; Get next column ;AN000; + CMP BL,BOX_W ;AN000; + JL INIT_1_BLACK_COLUMN ;AN000; + ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +INIT_BLACK_BOX ENDP ;AN000; +INCLUDE GRCOMMON.ASM ;AN000; +LEN_OF_COLOR_MODULES EQU $-PRINT_COLOR ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCOLPRT.EXT b/v4.0/src/CMD/GRAPHICS/GRCOLPRT.EXT new file mode 100644 index 0000000..5e07eaa --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCOLPRT.EXT @@ -0,0 +1,25 @@ +.XLIST +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCOLPRT.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing external declarations for ;AN000; +;; the code and data defined in GRCOLPRT.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; + EXTRN PRINT_MODULE_START:NEAR ;; ;AN000; + EXTRN PRINT_COLOR:NEAR ;AN000; + EXTRN LEN_OF_COLOR_MODULES:ABS ;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM b/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM new file mode 100644 index 0000000..56d1b08 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM @@ -0,0 +1,858 @@ + PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCOMMON.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; ;AN000; +;; This file contains the modules common to the Print Screen ;AN000; +;; process of GRAPHICS.COM. ;AN000; +;; This file is included by both set of Print modules. ;AN000; +;; ;AN000; +;; This file MUST BE COMPILED WITH EACH SET OF MODULES since, ;AN000; +;; one set is relocated in memory at installation time; all ;AN000; +;; references to the common procedures must be resolved from ;AN000; +;; within each set of print modules. ;AN000; +;; ;AN000; +;; The set of common modules is relocated in memory along with ;AN000; +;; the selected set of print modules. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; READ_DOT ;AN000; +;; LOC_MODE_PRT_INFO ;AN000; +;; STORE_BOX ;AN000; +;; PRINT_BUFFER ;AN000; +;; GET_SCREEN_INFO ;AN000; +;; SETUP_PRT ;AN000; +;; RESTORE_PRT ;AN000; +;; NEW_PRT_LINE ;AN000; +;; PRINT_BYTE ;AN000; +;; DET_CUR_SCAN_LNE_LENGTH ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; none ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRCTRL.ASM: ;AN000; +;; PRT_SCR - Main module for printing the screen. ;AN000; +;; FROM FILE GRBWPRT.ASM: ;AN000; +;; PRT_BW_APA - Main module for printing on BW printer. ;AN000; +;; FROM FILE GRCOLPRT.ASM: ;AN000; +;; PRINT_COLOR - Main module for printing on COLOR printer. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; ;AN000; +;; This file is included by both GRBWPRT.ASM and GRCOLPRT.ASM and is ;AN000; +;; compiled with each of them. However, only one copy is made resident. ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; LOC_MODE_PRT_INFO: LOCATE DISPLAYMODE PRINTER INFO. FOR THE CURRENT ;AN000; +; MODE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; CUR_MODE = Current video mode ;AN000; +; ;AN000; +; OUTPUT: CUR_MODE_PTR = Absolute Offset of the ;AN000; +; current DISPLAYMODE INFO record. ;AN000; +; ;AN000; +; ERROR_CODE = DISPLAYMODE_INFO_NOT_FOUND if not found. ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRINT_BW_APA ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: DISPLAYMODE_PTR is pointing to the first DISPLAYMODE ;AN000; +; INFO record within the Shared Data Area. ;AN000; +; ;AN000; +; This (chained) list of DISPLAYMODE records is scanned until the record ;AN000; +; for the current mode is found. ;AN000; +; ;AN000; +; Note: All pointers in the DISPLAYMODE records are relative to the beginning ;AN000; +; of the shared data area. Therefore, we must add the offset of the ;AN000; +; shared data area (in BP) in order to access the data these pointers ;AN000; +; are referencing. ;AN000; +; ;AN000; +; The CUR_MODE_PTR is relative to the segment and references the ;AN000; +; DISPLAYMODE record for the video mode currently set at print screen ;AN000; +; time. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; FOUND := FALSE ;AN000; +; DO UNTIL FOUND OR END_OF_LIST ;AN000; +; Get a display mode information record ;AN000; +; IF record.DISP_MODE = CUR_MODE ;AN000; +; THEN FOUND := TRUE ;AN000; +; ELSE ;AN000; +; CUR_MODE_PTR := record.NEXT_DISP_MODE ;AN000; +; ;AN000; +; ;AN000; + ;AN000; +LOC_MODE_PRT_INFO PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + ;AN000; + MOV BX,DS:[BP].DISPLAYMODE_PTR ; [BX] := Current DISPLAYMODE ;AN000; + ADD BX,BP ; record ;AN000; + MOV DL,CUR_MODE ; DL := Current mode ;AN000; + ;AN000; +SCAN_1_DISPLAYMODE_RECORD: ;AN000; + MOV SI,[BX].DISP_MODE_LIST_PTR ; [SI] : First mode covered ;AN000; + ADD SI,BP ; by this DISPLAYMODE record ;AN000; + MOV CL,[BX].NUM_DISP_MODE ; Scan each mode in the list ;AN000; + XOR CH,CH ;AN000; +SCAN_LIST_OF_MODES: ;AN000; + CMP CS:[SI],DL ; FOUND ? ;AN000; + JE FOUND ;AN000; + INC SI ; NO, get next mode in ;AN000; + LOOP SCAN_LIST_OF_MODES ; DISPLAYMODE record ;AN000; + ;AN000; + CMP [BX].NEXT_DISP_MODE,-1 ; END OF DISPLAYMODE LIST ? ;AN000; + JE NOT_FOUND ; Yes, this mode not supported ;AN000; +NEXT_RECORD: ; No, ;AN000; + MOV BX,[BX].NEXT_DISP_MODE ; [BX] := Next record ;AN000; + ADD BX,BP ; ;AN000; + JMP SHORT SCAN_1_DISPLAYMODE_RECORD ;AN000; + ;AN000; +FOUND: ; Found: ;AN000; + MOV CUR_MODE_PTR,BX ; Update pointer to current ;AN000; + JMP SHORT LOC_MODE_PRT_INFO_END ; DISPLAYMODE record. ;AN000; + ;AN000; +NOT_FOUND: ; Not found: ;AN000; + MOV ERROR_CODE,DISPLAYMODE_INFO_NOT_FOUND ; Return error condition ;AN000; + ;AN000; +LOC_MODE_PRT_INFO_END: ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +LOC_MODE_PRT_INFO ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; STORE_BOX : STORE ONE BOX IN THE PRINT BUFFER. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SI = OFFSET OF THE BOX TO BE PRINTED ;AN000; +; BOX_W = BOX WIDTH IN BITS ;AN000; +; BOX_H = BOX HEIGHT IN BITS ;AN000; +; ;AN000; +; OUTPUT: PRT_BUF = THE PRINT BUFFER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: The print buffer is first shifted left in order to make ;AN000; +; room for the new box (Note: the MSB's are lost; they are assumed to ;AN000; +; have been printed), then the box is inserted in the low-order bits of ;AN000; +; the printer buffer. ;AN000; +; ;AN000; +PAGE ;AN000; +; EXAMPLE ;AN000; +; ------- ;AN000; +; BEFORE: AFTER: ;AN000; +; ;AN000; +; BOX: 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; b1 b2 b3 ;AN000; +; b4 b5 b6 ;AN000; +; ;AN000; +; PRT_BUF: byte1 byte2 byte3 PRT_BUF: byte1 byte2 byte3 ;AN000; +; 0 1 0 1 1 1 ;AN000; +; 1 0 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 b1 b2 b3 ;AN000; +; LSB --> 1 1 1 b4 b5 b6 ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; FOR each byte of the buffer (BOX_W) ;AN000; +; BEGIN ;AN000; +; Make room for the box to be inserted ;AN000; +; Insert the box ;AN000; +; END ;AN000; +; ;AN000; +STORE_BOX PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV DI,OFFSET PRT_BUF ; DI := Offset of the Print buffer ;AN000; + XOR BX,BX ; BX := Byte index number ;AN000; + ;AN000; + MOV CL,BOX_H ; CL := Number of BITS to be shifted ;AN000; +; FOR each column (byte) of the box to be stored in the buffer: ;AN000; +STORE_1_BYTE: ;AN000; + SHL BYTE PTR [BX][DI],CL ; Make room for the bits to be inserted ;AN000; + MOV CH,[BX][SI] ; CH := column of the box to be inserted;AN000; + OR [BX][DI],CH ; Insert the box column in the buffer ;AN000; + INC BL ; Get next column (byte) of the box ;AN000; + CMP BL,BOX_W ; All columns (bytes) of box stored ? ;AN000; + JL STORE_1_BYTE ; No, store next one. ;AN000; + ;AN000; +STORE_BOX_END: ;AN000; + POP DI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +STORE_BOX ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_BUFFER : PRINT THE BUFFER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: PRT_BUF = BYTES TO BE PRINTED ;AN000; +; BOW_W = BOX WIDTH ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Prints BOX_W bytes. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; DO for each column in one pattern ;AN000; +; BEGIN ;AN000; +; Print one byte from the buffer ;AN000; +; END ;AN000; +; ;AN000; +PRINT_BUFFER PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,OFFSET PRT_BUF ;AN000; + XOR CX,CX ;AN000; + MOV CL,BOX_W ;AN000; +PRINT_1_BUF_COLUMN: ;AN000; + MOV AL,[BX] ; Print one byte ;AN000; + CALL PRINT_BYTE ;AN000; + JC PRINT_BUFFER_END; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP PRINT_1_BUF_COLUMN ;AN000; +PRINT_BUFFER_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_BUFFER ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; GET_SCREEN_INFO : GET INFORMATION ABOUT HOW TO READ THE SCREEN. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SCREEN_HEIGHT = Number of pixel rows on the screen ;AN000; +; SCREEN_WIDTH = Number of pixel columns on screen ;AN000; +; CUR_MODE_PTR = Offset of the current DISPLAYMODE info rec. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; SCAN_LINE_MAX_LENGTH = Maximum length of Screen scan line. ;AN000; +; NB_SCAN_LINES = Number of SCAN LINES on the screen ;AN000; +; CUR_ROW,CUR_COLUMN = Coordinates of the first pixel to be ;AN000; +; read on the screen ;AN000; +; NB_BOXES_PER_PRT_BUF = Number of boxes fitting in the Print ;AN000; +; buffer ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: ;AN000; +; ;AN000; +; 1) Determine where to start reading the screen. ;AN000; +; For non-rotated printing, it should start with the top-left ;AN000; +; corner pixel. ;AN000; +; For rotated printing, it should start with the low-left corner ;AN000; +; pixel. ;AN000; +; ;AN000; +; 2) Determine the length of a scan line. ;AN000; +; For non-rotated printing, it is the WIDTH of the screen. ;AN000; +; For rotated printing, it is the HEIGHT of the screen. ;AN000; +; ;AN000; +; 3) Determine the number of scan lines on the screen. ;AN000; +; For non-rotated printing, it is the HEIGHT of the screen divided ;AN000; +; by the number of boxes fitting in the print buffer. ;AN000; +; For rotated printing, it is the WIDTH of the screen divided by ;AN000; +; the number of boxes fitting in the print buffer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; CUR_COLUMN := 0 ;AN000; +; IF printing is sideways ;AN000; +; THEN ;AN000; +; CUR_ROW := SCREEN_HEIGHT - 1 ; Low-left pixel ;AN000; +; SCAN_LINE_MAX_LENGTH := SCREEN_HEIGHT ;AN000; +; NB_SCAN_LINES := SCREEN_WIDTH / NB_BOXES_PER_PRT_BUF ;AN000; +; ELSE ;AN000; +; CUR_ROW := 0 ; Top-left pixel ;AN000; +; SCAN_LINE_MAX_LENGTH := SCREEN_WIDTH ;AN000; +; NB_SCAN_LINES := SCREEN_HEIGHT / NB_BOXES_PER_PRT_BUF ;AN000; +; ;AN000; +; ;AN000; +GET_SCREEN_INFO PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ; Used for DIV ;AN000; + PUSH DX ; Used for DIV ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Offset DISPLAYMODE info record ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Calculate how many printer boxes fit in the print buffer: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,8 ; Num := 8 bits / Box heigth ;AN000; + MOV DL,[BX].BOX_HEIGHT ;AN000; + DIV DL ;AN000; + MOV NB_BOXES_PER_PRT_BUF,AL ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Determine where to start reading the screen: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CUR_COLUMN,0 ; Reading always start from left of scr ;AN000; +.IF <[BX].PRINT_OPTIONS EQ ROTATE> ;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Printing is sideways; screen must be read starting in low-left corner. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,SCREEN_HEIGHT ;AN000; + MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen height ;AN000; + DEC AX ;AN000; + MOV CUR_ROW,AX ; First row := screen height - 1 ;AN000; + ;AN000; +;-------Calculate the number of scan lines: ;AN000; + MOV AX,SCREEN_WIDTH ; DX AX = Screen width ;AN000; + CWD ; ;AN000; + XOR BX,BX ; BX = Number of boxes per print buf ;AN000; + MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000; + DIV BX ; Screen width / number boxes per buff ;AN000; + MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000; +.ELSE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Printing is not sideways; screen must be read starting in top-left corner ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,SCREEN_WIDTH ;AN000; + MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen width ;AN000; + MOV CUR_ROW,0 ; First row := 0 ;AN000; + ;AN000; +;-------Calculate the number of scan lines: ;AN000; + MOV AX,SCREEN_HEIGHT ; DX AX = Screen height ;AN000; + CWD ; ;AN000; + XOR BX,BX ; BX = Number of boxes per print buff ;AN000; + MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000; + DIV BX ; Screen height/number boxes per buff. ;AN000; + MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000; +.ENDIF ;AN000; + POP DX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +GET_SCREEN_INFO ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; DET_CUR_SCAN_LNE_LENGTH : Determine where is the last non-blank "scan line ;AN000; +; column" on the current scan line. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW, ;AN000; +; CUR_COLUMN = Coordinates of the top pixel of the current ;AN000; +; scan line. ;AN000; +; XLT_TAB = Color translation table ;AN000; +; ;AN000; +; OUTPUT: CUR_SCAN_LNE_LENGTH = Number of "columns" of pixels from the ;AN000; +; beginning of the scan line up to ;AN000; +; the last non-blank pixel. ;AN000; +; ;AN000; +; DATA SCREEN_WIDTH, ;AN000; +; REFERENCED: SCREEN_HEIGHT = Dimensions of the screen in pels ;AN000; +; SCAN_LINE_MAX_LENGTH= Maximum length of the scan line ;AN000; +; ROTATE_SW = ON if printing is sideways ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Determine where is the last non-blank "column" by reading ;AN000; +; the scan line backwards, one column at a time. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; ; Obtain coordinates for the top pixel of the last column on the current ;AN000; +; ; scan line: ;AN000; +; IF printing is sideways ;AN000; +; THEN ;AN000; +; CUR_ROW := 0 ;AN000; +; ELSE ;AN000; +; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000; +; ;AN000; +; CUR_SCAN_LNE_LENGTH := SCAN_LINE_MAX_LENGTH ;AN000; +; ; Read a column of pixels on the scan line until a non-blank is found: ;AN000; +; For each column on the screen ;AN000; +; CALL FILL_BUFF ;AN000; +; ; Check if PRT_BUF is empty ;AN000; +; IF buffer is empty ;AN000; +; THEN DEC CUR_SCAN_LNE_LENGTH ;AN000; +; ; Get next column ;AN000; +; IF printing sideways THEN DEC CUR_ROW ;AN000; +; ELSE DEC CUR_COLUMN ;AN000; +; ELSE quit the loop ;AN000; +; ;AN000; +DET_CUR_SCAN_LNE_LENGTH PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH CUR_COLUMN ;AN000; + PUSH CUR_ROW ;AN000; + ;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Obtain coordinates of the top pixel for the last column of the current ;AN000; +; scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then, ;AN000; + MOV CUR_ROW,0 ; CUR_ROW := 0 ;AN000; + .ELSE ; else, ;AN000; + MOV CX,SCREEN_WIDTH ; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000; + DEC CX ; ;AN000; + MOV CUR_COLUMN,CX ; ;AN000; + .ENDIF ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Read the scan line backwards "column" by "column" until a non-blank is found: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CX,SCAN_LINE_MAX_LENGTH ; CX := current length ;AN000; +; ;AN000; +;-------For each "column" ;AN000; +CHECK_1_COLUMN: ;AN000; + MOV SI,CUR_ROW ; Save coordinates of the column ;AN000; + MOV DI,CUR_COLUMN ; in SI, DI ;AN000; + XOR DL,DL ; DL := Number of pixels verified in ;AN000; + ; one "column" ;AN000; +; ;AN000; +;-------For each pixel within that "column" ;AN000; +CHECK_1_PIXEL: ;AN000; + CALL READ_DOT ; AL := Index into translation table ;AN000; + XLAT XLT_TAB ; AL := Band mask or Intensity ;AN000; + ;AN000; +;-------Check if pixel will map to an empty box: ;AN000; + .IF ; If BLACK AND WHITE printer ;AN000; + .THEN ; then, check for intensity of white ;AN000; + CMP AL,WHITE_INT ; If curent pixel not blank ;AN000; + JNE DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000; + .ELSE ; else, COLOR printer ;AN000; + OR AL,AL ; IF Band mask not blank ;AN000; + JNZ DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------All pixels so far on this "column" are blank, get next pixel: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + INC CUR_COLUMN ; then, increment column number ;AN000; + .ELSE ; ;AN000; + INC CUR_ROW ; else, increment row number ;AN000; + .ENDIF ; ;AN000; + INC DL ; One more pixel checked ;AN000; + CMP DL,NB_BOXES_PER_PRT_BUF ; All pixels for that column done ? ;AN000; + JL CHECK_1_PIXEL ; No, check next one. ;AN000; + ;AN000; +;-------Nothing to print for this column, get next column ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then, ;AN000; + MOV CUR_COLUMN,DI ; Restore column number ;AN000; + INC CUR_ROW ; Get next row ;AN000; + .ELSE ; else, ;AN000; + MOV CUR_ROW,SI ; Restore row number ;AN000; + DEC CUR_COLUMN ; Get next column ;AN000; + .ENDIF ; ;AN000; + LOOP CHECK_1_COLUMN ; CX (length) := CX - 1 ;AN000; + ;AN000; +DET_LENGTH_END: ;AN000; + MOV CUR_SCAN_LNE_LENGTH,CX ; Get current length ;AN000; + ;AN000; + POP CUR_ROW ;AN000; + POP CUR_COLUMN ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +DET_CUR_SCAN_LNE_LENGTH ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SETUP_PRT : SET UP THE PRINTER FOR PRINTING IN GRAPHIC MODE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the SETUP escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_SETUP_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; SI := CUR_MODE_PTR.SETUP_ESC_PTR ;AN000; +; ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +SETUP_PRT PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; + XOR CX,CX ; CX := Number of bytes to print ;AN000; + MOV CL,[BX].NUM_SETUP_ESC ; ;AN000; +.IF ; If there is at least one ;AN000; +.THEN ; byte to be printed: ;AN000; + MOV BX,[BX].SETUP_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_SETUP_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC SETUP_PRT_END ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_SETUP_BYTE ;AN000; +.ENDIF ;AN000; +SETUP_PRT_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +SETUP_PRT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; RESTORE_PRT : RESTORE THE PRINTER TO ITS INITIAL STATUS ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the RESTORE escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_RESTORE_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; SI := CUR_MODE_PTR.RESTORE_ESC_PTR ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +RESTORE_PRT PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; + XOR CX,CX ; CX := Number of bytes to print ;AN000; + MOV CL,[BX].NUM_RESTORE_ESC ;AN000; +.IF ; If there is at least one ;AN000; +.THEN ; byte to be printed: ;AN000; + MOV BX,[BX].RESTORE_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_RESTORE_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC RESTORE_PRT_END ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_RESTORE_BYTE ;AN000; +.ENDIF ;AN000; +RESTORE_PRT_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +RESTORE_PRT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; NEW_PRT_LINE : INITIALIZE THE PRINTER FOR A GRAPHIC LINE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; CUR_SCAN_LNE_LENGTH = Number of bytes to send to the printer. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_BAND ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the GRAPHICS escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; Then, send the number of bytes that will follow. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_GRAPHICS_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; Set up the 2 bytes containing the number of bytes to send in this sequence. ;AN000; +; SI := CUR_MODE_PTR.GRAPHICS_ESC_PTR ;AN000; +; ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +; Send the byte count ;AN000; +; ;AN000; + ;AN000; +NEW_PRT_LINE PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set up the 2 bytes containing the number of bytes to send in the GRAPHICS seq.;AN000; +; NOTE: number of bytes to send is "CUR_SCAN_LNE_LENGTH * BOX_W" ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AL,BOX_W ; cur_scan_lne_length * ;AN000; + CBW ; printer box width = nb bytes to send;AN000; + MUL CUR_SCAN_LNE_LENGTH ; (result in DX AX) ;AN000; + ; ;AN000; +;-------AX := Number of bytes to print ;AN000; + MOV DI,[BX].LOW_BYT_COUNT_PTR; DI := Offset of LOW byte of ;AN000; + ADD DI,BP ; byte count ;AN000; + MOV [DI],AL ; Store low byte ;AN000; + MOV DI,[BX].HGH_BYT_COUNT_PTR; DI := Offset of HIGH byte of ;AN000; + ADD DI,BP ; byte count ;AN000; + MOV [DI],AH ; Store high byte ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Send the GRAPHICS escape sequence to the printer: ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR CX,CX ; CX := Length of the escape seq;AN000; + MOV CL,[BX].NUM_GRAPHICS_ESC ;AN000; + MOV BX,[BX].GRAPHICS_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_GRAPHICS_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC NEW_PRT_LINE_ENDP ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_GRAPHICS_BYTE ;AN000; + ;AN000; +NEW_PRT_LINE_ENDP: ;AN000; + POP DI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +NEW_PRT_LINE ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_BYTE : SEND A BYTE TO THE PRINTER AT LPT1 ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: AL = Byte to be printed ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ERROR_CODE = PRINTER_ERROR if an error is detected. ;AN000; +; Carry flag is set in case of error. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_BYTE PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH DX ;AN000; + ;AN000; + MOV DX,0000 ; PRINTER NUMBER ;AN000; + MOV AH,00 ; REQUEST PRINT ;AN000; + INT 17H ; CALL BIOS : SEND THE CHARACTER ;AN000; + ;AN000; + AND AH,00101001B ; Test error code returned in AH for ;AN000; + ; "Out of paper", "I/O error" and "Time-out". ;AN000; + JNZ PRINT_BYTE_ERROR; Set the error code if error ;AN000; + JMP SHORT PRINT_BYTE_END ; else, return normally ;AN000; +PRINT_BYTE_ERROR: ;AN000; + MOV ERROR_CODE,PRINTER_ERROR ;AN000; + STC ; Set the carry flag to indicate ERROR ;AN000; +PRINT_BYTE_END: ;AN000; + POP DX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_BYTE ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; READ_DOT: READ A PIXEL - RETURN A COLOR TRANSLATION TABLE INDEX ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE = Current video mode. ;AN000; +; CUR_ROW, ;AN000; +; CUR_COLUMN = Coordinates of the pixel to be read. ;AN000; +; CUR_PAGE = Active page number ;AN000; +; ;AN000; +; OUTPUT: AL = Index into COLOR TRANSLATION TABLE. ;AN000; +; ;AN000; +; DEPENDENCIES : COLOR TRANSLATION TABLE entries must be bytes ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Use VIDEO BIOS INTERRUPT 10H "READ DOT CALL". ;AN000; +; ;AN000; +; Depending on the video hardware, the dot returned by BIOS has ;AN000; +; different meanings. ;AN000; +; With an EGA it is an index into the Palette registers, ;AN000; +; With a CGA it is a number from 0 to 3, mapping to a specific color ;AN000; +; depending on the background color and the color palette currently ;AN000; +; selected. ;AN000; +; ;AN000; +; The Color Translation table has been set up to hold the correct color ;AN000; +; mapping for any "dot" in any mode. Therefore, the dot number returned ;AN000; +; by INT 10H can be used with any mode as a direct index within that ;AN000; +; table. ;AN000; +; ;AN000; +; With APA Monochrome mode 0FH there are 4 different dots: white, ;AN000; +; blinking white, high-intensity white, and black. ;AN000; +; ;AN000; +; For mode 0FH, the dot returned by interrupt 10 "read dot" call is a byte ;AN000; +; where only bits 0 and 2 are significant. These 2 bits must be appended ;AN000; +; together in order to obtain a binary number (from 0 to 3) that will be used ;AN000; +; as an index in the Color Translation table. ;AN000; +; ;AN000; +; For mode 11H, the dot is either 0 (for background color) or 7 (for the ;AN000; +; foreground color) only the LSB is returned. That is, we return either ;AN000; +; 0 or 1. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Call VIDEO BIOS "READ DOT" ;AN000; +; IF CUR_MODE = 0FH ;AN000; +; THEN ;AN000; +; Append bits 1 and 3. ;AN000; +; IF CUR_MODE = 11H ;AN000; +; THEN ;AN000; +; Wipe out bits 1 and 2. ;AN000; +; ;AN000; +READ_DOT PROC NEAR ;AN000; + PUSH BX ; Save registers ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; + MOV BH,CUR_PAGE ;AN000; + MOV DX,CUR_ROW ;AN000; + MOV CX,CUR_COLUMN ;AN000; + MOV AH,READ_DOT_CALL ;AN000; + INT 10H ; Call BIOS: AL <-- Dot read ;AN000; + ;AN000; + CMP CUR_MODE,0FH ; Is it Mode 0fH ? ;AN000; + JNE MODE_11H? ; No, look for mode 11h. ;AN000; +;-------Mode 0Fh is the current mode: ;AN000; +;-------Convert bits 2 and 0 into a 2 bit number: ;AN000; + MOV BL,AL ; BL := AL = "Pixel read" ;AN000; + AND BL,00000100B ; Wipe off all bits but bit 2 in BL ;AN000; + AND AL,00000001B ; Wipe off all bits but bit 0 in AL ;AN000; + SHR BL,1 ; Move bit 2 to bit 1 in BL ;AN000; + OR AL,BL ; Append bit 1 and bit 0 ;AN000; + JMP SHORT READ_DOT_END ; Quit. ;AN000; + ;AN000; +MODE_11H?: ;AN000; + CMP CUR_MODE,11H ; Is it Mode 0fH ? ;AN000; + JNE READ_DOT_END ; No, quit ;AN000; + ;AN000; +;-------Mode 11H is the current mode: ;AN000; + AND AL,00000001B ; Keep only the Least significant bit ;AN000; + ;AN000; +READ_DOT_END: ;AN000; + POP DX ; Restore registers ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +READ_DOT ENDP ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCOMMON.EXT b/v4.0/src/CMD/GRAPHICS/GRCOMMON.EXT new file mode 100644 index 0000000..8414070 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCOMMON.EXT @@ -0,0 +1,32 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCOMMON.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing external declarations for ;AN000; +;; the code and data defined in GRCOMMON.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; +EXTRN READ_DOT:NEAR ;AN000; +EXTRN LOC_MODE_PRT_INFO:NEAR ;AN000; +EXTRN STORE_BOX:NEAR ;AN000; +EXTRN PRINT_BUFFER:NEAR ;AN000; +EXTRN GET_SCREEN_INFO:NEAR ;AN000; +EXTRN SETUP_PRT:NEAR ;AN000; +EXTRN RESTORE_PRT:NEAR ;AN000; +EXTRN NEW_PRT_LINE:NEAR ;AN000; +EXTRN PRINT_BYTE:NEAR ;AN000; +EXTRN DET_CUR_SCAN_LNE_LENGTH:NEAR ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCPSD.ASM b/v4.0/src/CMD/GRAPHICS/GRCPSD.ASM new file mode 100644 index 0000000..28c2d10 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCPSD.ASM @@ -0,0 +1,109 @@ + PAGE ,132 ;AN000; + TITLE DOS GRAPHICS Command - Copy Shared Data + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCPSD.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the COPY_SHARED_DATA module. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; PLACID Functional Specifications ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; COPY_SHARED_DATA - Copy the Shared Data Area from temporary ;AN000; +;; build area to resident memory & exit to DOS ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; None ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; None ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; --------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + INCLUDE GRCTRL.EXT ;; Bring in external declarations ;AN000; + INCLUDE GRCTRL.STR ;; for transient command processing ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Public Symbols ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + PUBLIC COPY_SHARED_DATA ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; COPY_SHARED_DATA ;AN000; +;; ;AN000; +;; Input Parameters: ;AN000; +;; DS : SI - points to the Temporary Shared Data Area ;AN000; +;; ES : DI - destination for resident Shared Data Area ;AN000; +;; BP - offset for new Shared Data Area (same as DI) ;AN000; +;; AH - Function code for exiting to DOS: ;AN000; +;; 31H : Terminate & Stay Resident - if first time ;AN000; +;; 4CH : Terminate - if already installed ;AN000; +;; DX - resident data segment size in paragraphs ;AN000; +;; ;AN000; +;; Output Parameters: ;AN000; +;; NONE ;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Control Variables ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Copy the Temporary Shared Data area over the installation modules ;AN000; +;; and terminate (stay resident). The data is copied immediately ;AN000; +;; following this module. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; GRAPHICS_INSTALL ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; NONE ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; Copy Temporary Shared Data Area ;AN000; +;; Set PRINT_SCREEN_ALLOWED to YES ;AN000; +;; Exit to DOS (Function Code 31 or 4C setup by caller) ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +COPY_SHARED_DATA PROC NEAR ;; ;AN000; + ;; ;AN000; + REP MOVSB ;; Copy Shared Data from temporary ;AN000; + ;; build area to resident memory ;AN000; + ;; Allow print screens now ;AN000; + MOV ES:PRINT_SCREEN_ALLOWED,YES ;AN000; + ;; ;AN000; + INT 21H ;; Exit ;AN000; + ;; ;AN000; +COPY_SHARED_DATA ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +CODE ENDS ;AN000; + END COPY_SHARED_DATA ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCPSD.EXT b/v4.0/src/CMD/GRAPHICS/GRCPSD.EXT new file mode 100644 index 0000000..fb3857f --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCPSD.EXT @@ -0,0 +1,24 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCPSD.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRCPSD.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN COPY_SHARED_DATA:NEAR ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCTRL.ASM b/v4.0/src/CMD/GRAPHICS/GRCTRL.ASM new file mode 100644 index 0000000..1deff0a --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCTRL.ASM @@ -0,0 +1,2162 @@ + PAGE ,132 ;AN000; + ;AN000; + TITLE DOS GRAPHICS Command - Print screen Control module +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCTRL.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the code for the Print Screen control module. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; PRT_SCR ;AN000; +;; DET_HW_CONFIG ;AN000; +;; DET_MODE_STATE ;AN000; +;; GET_MODE_ATTR ;AN000; +;; SET_UP_XLT_TAB ;AN000; +;; SET_CGA_XLT_TAB ;AN000; +;; CGA_COL2RGB ;AN000; +;; RGB2XLT_TAB ;AN000; +;; SET_EGA_XLT_TAB ;AN000; +;; EGA_COL2RGB ;AN000; +;; SET_MODE_F_XLT_TAB ;AN000; +;; SET_MODE_13H_XLT_TAB ;AN000; +;; SET_ROUNDUP_XLT_TAB ;AN000; +;; SET_BACKG_IN_XLT_TAB ;AN000; +;; RGB2BAND ;AN000; +;; RGB2INT ;AN000; +;; ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRINST.EXT - Externals for GRINST.ASM ;AN000; +;; ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRINST.ASM: ;AN000; +;; GRAPHICS_INSTALL - Main module for installation. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;AN000; + ASSUME CS:CODE,DS:CODE ;AN000; + ;AN000; +.XLIST ;AN000; +INCLUDE GRINT2FH.EXT ;AN000; +INCLUDE GRBWPRT.EXT ;AN000; +INCLUDE GRCOLPRT.EXT ;AN000; +INCLUDE GRSHAR.STR ;AN000; +INCLUDE GRPATTRN.STR ;AN000; +INCLUDE GRPATTRN.EXT ;AN000; +INCLUDE STRUC.INC ;AN000; +.LIST ;AN000; +PRT_SCR PROC NEAR ;AN000; + JMP PRT_SCR_BEGIN ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; GRAPHICS INTERRUPT DRIVER'S DATA: ;AN000; +; ;AN000; +;===============================================================================;AN000; +.xlist ;AN000; +PUBLIC PRT_SCR,ERROR_CODE,XLT_TAB,MODE_TYPE ;AN000; +PUBLIC CUR_MODE_PTR,CUR_MODE,NB_COLORS,SCREEN_HEIGHT,SCREEN_WIDTH ;AN000; +PUBLIC CUR_PAGE,CUR_COLUMN,CUR_ROW,NB_SCAN_LINES,SCAN_LINE_MAX_LENGTH ;AN000; +PUBLIC CUR_SCAN_LNE_LENGTH ;AN000; +PUBLIC PRT_BUF,NB_BOXES_PER_PRT_BUF,CUR_BOX,BOX_H,BOX_W ;AN000; +PUBLIC PRINT_SCREEN_ALLOWED,RGB ;AN000; +PUBLIC BIOS_INT_5H ;AN000; +PUBLIC ROTATE_SW ;AN000; +PUBLIC DET_HW_CONFIG ;AN000; +PUBLIC NB_CHAR_COLUMNS ;AN000; +PUBLIC RGB2INT ;AN000; +PUBLIC RGB2BAND ;AN000; +.list ;AN000; +INCLUDE GRCTRL.STR ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; ENTRY POINT TO BIOS HARDWARE INTERRUPT 5 HANDLER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +BIOS_INT_5H DW ? ; Pointer to BIOS int 5h ;AN000; + DW ? ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PRINT SCREEN ERROR CODE (Used at print screen time, see GRCTRL.STR for ;AN000; +; error codes allowed) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +ERROR_CODE DB 0 ; ERROR CODE 0 = NO ERROR ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; SCREEN PIXEL: INTERNAL REPRESENTATION ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +RGB PIXEL_STR < , , > ; PIXEL := RED, GREEN, BLUE Values ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; COLOR TRANSLATION TABLE: ;AN000; +; ;AN000; +; This table is used to translate the color numbers returned by ;AN000; +; Interrupt 10H Read Dot and Read Character calls into print ;AN000; +; information. The table consists of 256 entries, one byte each, ;AN000; +; indexed by color number. ;AN000; +; In the case of black and white printing, the table ;AN000; +; entries are grey scale intensities from 0 to 63. In the case ;AN000; +; of color printing each table entry contains a "band mask" indicating ;AN000; +; which color print bands are required to generate the required color. ;AN000; +; The band masks are simply bit masks where each bit corresponds to one ;AN000; +; of the printer bands. ;AN000; +; ;AN000; +; The table is set up at the beginning of the print screen processing, ;AN000; +; before any data is read from the screen. From then on, translating ;AN000; +; from screen information into print information is done quickly by ;AN000; +; accessing this table. Not all 256 entries are initialized for each ;AN000; +; screen print. The number of entries used is equal to the number ;AN000; +; of colors available concurrently with the given display mode. ;AN000; +;-------------------------------------------------------------------------------;AN000; +XLT_TAB DB 256 DUP(32) ; COLOR TRANSLATION TABLE ;AN000; + ; This table is used to translate the Color Dot ;AN000; + ; or Byte Attribute to a Band Mask for color ;AN000; + ; printing or to a Grey Intensity for Mono- ;AN000; + ; chrome printing. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; CURRENT VIDEO MODE ATTRIBUTES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +MODE_TYPE DB ? ; Mode types (bit mask) APA or TXT ;AN000; + ;AN000; +CUR_MODE_PTR DW ? ; DISPLAYMODE INFO RECORD for the current ;AN000; + ; mode (defined in the shared data area). ;AN000; +CUR_MODE DB ? ; Current video mode number ;AN000; +NB_COLORS DW ? ; Number of colors supported by this mode ;AN000; +SCREEN_HEIGHT DW ? ; Number of rows on the screen (chars or pixels);AN000; +SCREEN_WIDTH DW ? ; Number of columns on the screen (chars/pixels);AN000; + ; (for text modes is equal to NB_CHAR_COLUMNS) ;AN000; +NB_CHAR_COLUMNS DB ? ; Number of columns on the screen if in txt mode;AN000; +CUR_PAGE DB ? ; Active page number ;AN000; +ROTATE_SW DB ? ; Switch: if "ON" then, must print sideways ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; ACTIVE SCREEN ATTRIBUTES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +CUR_COLUMN DW ? ; Current pixel/char column number ;AN000; +CUR_ROW DW ? ; Current pixel/char row number ;AN000; +NB_SCAN_LINES DW ? ; Number of screen scan lines ;AN000; +SCAN_LINE_MAX_LENGTH DW ? ; Maximum number of dots/chars per scan line ;AN000; +CUR_SCAN_LNE_LENGTH DW ? ; Length in pels/chars of the current scan line ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PRINTER VARIABLES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRT_BUF DB ?,?,?,? ; PRINT BUFFER ;AN000; +NB_BOXES_PER_PRT_BUF DB ? ; Number of boxes fitting in the print buffer ;AN000; +CUR_BOX DB ?,?,?,? ; BOX = PRINTER REPRESENTATION OF 1 PIXEL ;AN000; +BOX_H DB ? ; HEIGHT OF THE BOX ;AN000; +BOX_W DB ? ; WIDTH OF THE BOX ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; CONTROL VARIABLES: ;AN000; +; ;AN000; +; This data is used to communicate between the Installation Modules ;AN000; +; and the Resident Print Screen Modules. ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_SCREEN_ALLOWED DB YES; Used to avoid print screens ;AN000; + ; while the GRAPHICS installation ;AN000; + ; (or re-install) is in progress ;AN000; + ; Set by GRAPHICS_INSTALL module. ;AN000; + ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; INTERRUPT 5 DRIVER'S CODE: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRT_SCR : PRINT THE ACTIVE SCREEN ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SHARED_DATA_AREA_PTR = Offset of the data area used for ;AN000; +; passing data between the ;AN000; +; Installation process and the Print ;AN000; +; Screen process. ;AN000; +; PRINT_SCREEN_ALLOWED = Switch. Set to "No" if currently ;AN000; +; installing GRAPHICS.COM ;AN000; +; ;AN000; +; NOTE: These 2 variables are declared within ;AN000; +; PRT_SCR but initialized by the ;AN000; +; Installation process GRAPHICS_INIT ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: INTERRUPT 5 ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: ;AN000; +; ;AN000; +; PRINT THE ACTIVE SCREEN for all TEXT and All Points Addressable (APA) ;AN000; +; display modes available with either a MONO, CGA, EGA, or VGA video ;AN000; +; adapter on a Black and White or Color printer. ;AN000; +; ;AN000; +; INITIALIZATION: ;AN000; +; ;AN000; +; Each pixel or character on the screen has a color attribute. These ;AN000; +; colors must be translated into different internal representations: ;AN000; +; ;AN000; +; For printing in colors, each color is translated to a BAND MASK. ;AN000; +; The Band Mask indicates how to obtain this color on the printer. ;AN000; +; ;AN000; +; For printing in Black and White, each color is translated to a ;AN000; +; GREY INTENSITY number between 0 (black) and 63 (white). ;AN000; +; ;AN000; +; The BAND MASK or the GREY INTENSITIES are found in the COLOR ;AN000; +; TRANSLATION TABLE. This table is initialized before calling any of ;AN000; +; the print screen modules. ;AN000; +; ;AN000; +; PRINT SCREEN TIME: ;AN000; +; ;AN000; +; When a pixel or character is read off the screen by one of the print ;AN000; +; screen modules, its color is used as an index into the translation ;AN000; +; table. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; IF SCREEN_PRINTS_ALLOWED=NO ; Block print screens until Installation ;AN000; +; THEN IRET ; Process (or re-install!) is finished. ;AN000; +; ELSE ;AN000; +; ;AN000; +; CALL DET_HW_CONFIG ; Determine hardware configuration ;AN000; +; CALL DET_MODE_STATE ; Determine video mode and active page ;AN000; +; CALL GET_MODE_ATTR ; Get video attributes (TXT or APA, etc) ;AN000; +; ;AN000; +; IF MODE_TYPE = TXT AND Number of colors = 0 ;AN000; +; THEN Invoke BIOS INTERRUPT 5 ;AN000; +; ELSE ;AN000; +; IF PRINTER_TYPE = BLACK_WHITE ;AN000; +; THEN ;AN000; +; IF MODE_TYPE = TXT ;AN000; +; THEN Invoke BIOS INTERRUPT 5 ;AN000; +; ELSE ; Mode is APA ;AN000; +; CALL SET_UP_XLT_TAB ; Set up the color translation table ;AN000; +; CALL PRINT_BW_APA ; Print the active screen on a B&W printer ;AN000; +; ELSE ; Color printer attached ;AN000; +; CALL SET_UP_XLT_TAB ; Set up the color translation table ;AN000; +; CALL PRINT_COLOR ; Print the active screen on a Color prt. ;AN000; +; IRET ;AN000; +; ;AN000; +PRT_SCR_BEGIN: ;AN000; + PUSH AX ; Save Registers ;AN000; + PUSH BX ; ;AN000; + PUSH CX ; ;AN000; + PUSH DX ; ;AN000; + PUSH SI ; ;AN000; + PUSH DI ; ;AN000; + PUSH BP ; ;AN000; + PUSH DS ; ;AN000; + PUSH ES ; ;AN000; + ; ;AN000; + CLD ; Clear direction flag ;AN000; + PUSH CS ; DS := CS ;AN000; + POP DS ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Verify if we are allowed to print (not allowed if currently installing ;AN000; +; GRAPHICS or printing a screen): ;AN000; +;-------------------------------------------------------------------------------;AN000; + CMP PRINT_SCREEN_ALLOWED,NO ; IF not allowed to print ;AN000; + JE PRT_SCR_RETURN ; THEN quit ;AN000; + ; ELSE print the screen: ;AN000; +;-------------------------------------------------------------------------------;AN000; +; INITIALIZATION: ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRT_SCR_INIT: ; Disable print screen while ;AN000; + MOV PRINT_SCREEN_ALLOWED,NO ; we are printing the current ;AN000; + ; screen. ;AN000; + MOV BP,SHARED_DATA_AREA_PTR ; BP := Offset Shared Data Area ;AN000; + MOV ERROR_CODE,NO_ERROR ; No error so far. ;AN000; + CALL DET_HW_CONFIG ; Determine the type of display adapter ;AN000; + CALL DET_MODE_STATE ; Init CUR_PAGE, CUR_MODE ;AN000; + CALL GET_MODE_ATTR ; Determine if APA or TXT, nb. of colors, ;AN000; + ; and screen dimensions in pels or characters. ;AN000; + ; ;AN000; + ; Test the error code returned by GET_MODE_ATTR: ;AN000; + ; ;AN000; + TEST ERROR_CODE,MODE_NOT_SUPPORTED ;If mode not supported then, ;AN000; + JNZ EXIT_TO_BIOS ; let BIOS give it a try. ;AN000; + ;AN000; + ;------------------------------------------------------------------------------;AN000; + ; Check the printer type: ;AN000; + ;------------------------------------------------------------------------------;AN000; + .IF ; Is a black and white printer ;AN000; + .THEN ; attached ? ;AN000; + ;------------------------------------------------------------------------------;AN000; + ; A Black and White printer is attached ;AN000; + ;------------------------------------------------------------------------------;AN000; + CMP MODE_TYPE,TXT ; Is the screen in text mode ? ;AN000; + JNE INVOKE_PRINT_ROUTINE ; No, call GRAPHICS B&W routine ;AN000; + JMP SHORT EXIT_TO_BIOS ; Yes, give control to BIOS INTERRUPT 5 ;AN000; + .ELSE ;AN000; + ;------------------------------------------------------------------------------;AN000; + ; A Color printer is attached ;AN000; + ;------------------------------------------------------------------------------;AN000; + CMP NB_COLORS,0 ; Is the screen in a Monochrome ;AN000; + JNE INVOKE_PRINT_ROUTINE ;AN000; + TEST MODE_TYPE,TXT ; text mode ? ;AN000; + JNZ INVOKE_PRINT_ROUTINE ;AN000; + JMP SHORT EXIT_TO_BIOS ; Yes, let BIOS INTERRUPT 5 handle it ;AN000; + ; No, we handle it. ;AN000; +.ENDIF ; ENDIF black and white or color printer ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Call the print routine (which is either PRINT_COLOR or PRINT_BW_APA) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +INVOKE_PRINT_ROUTINE: ;AN000; + CALL SET_UP_XLT_TAB ; Set up the color translation table ;AN000; + CALL PRINT_MODULE_START ; Call the print modules that were ;AN000; + ; made resident at Install time. ;AN000; + MOV PRINT_SCREEN_ALLOWED,YES; Enable PrtScr for next calls ;AN000; + ;-----------------------------------------------------------------------------;AN000; + ; Test the error code returned by either PRINT_COLOR or PRT_BW_APA ;AN000; + ;-----------------------------------------------------------------------------;AN000; + TEST ERROR_CODE,UNABLE_TO_PRINT ; If unable to print the screen ;AN000; + JNZ SHORT EXIT_TO_BIOS ; then, let BIOS give it a try ;AN000; + ;AN000; +PRT_SCR_RETURN: ;AN000; + ; Restore registers ;AN000; + POP ES ; ;AN000; + POP DS ; ;AN000; + POP BP ; ;AN000; + POP DI ; ;AN000; + POP SI ; ;AN000; + POP DX ; ;AN000; + POP CX ; ;AN000; + POP BX ; ;AN000; + POP AX ; ;AN000; + ; ;AN000; + IRET ; Return control to interrupted ;AN000; + ; process ;AN000; +EXIT_TO_BIOS: ;AN000; + ; Restore registers ;AN000; + POP ES ; ;AN000; + POP DS ; ;AN000; + POP BP ; ;AN000; + POP DI ; ;AN000; + POP SI ; ;AN000; + POP DX ; ;AN000; + POP CX ; ;AN000; + POP BX ; ;AN000; + POP AX ; ;AN000; + CLI ; Disable interrupts ;AN000; + MOV CS:PRINT_SCREEN_ALLOWED,YES ; Enable PrtScr for next calls ;AN000; + JMP DWORD PTR CS:BIOS_INT_5H ; Exit to BIOS INTERRUPT 5 ;AN000; + ;AN000; +PRT_SCR ENDP ;AN000; + ;AN000; + ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRT_SCR MODULES: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; DET_HW_CONFIG : DETERMINE WHAT TYPE OF VIDEO HARDWARE IS PRESENT ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; ;AN000; +; OUTPUT: HARDWARE_CONFIG is updated in the shared data area ;AN000; +; ;AN000; +; CALLED BY: PRT_SCR ;AN000; +; ;AN000; +; EXTERNAL CALLS: BIOS INT 10H ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; LOGIC: ;AN000; +; Issue BIOS INT10H Get Display Configuration Code (AX=1A00H) ;AN000; +; IF AL = 1AH THEN /* VGA (PS/2 OR BRECON-B) */ ;AN000; +; /* BL = active DCC */ ;AN000; +; /* BH = alternate DCC */ ;AN000; +; /* Display Code: */ ;AN000; +; /* 1 - Mono Adapter */ ;AN000; +; /* 2 - CGA */ ;AN000; +; /* 4 - EGA with Mono Display */ ;AN000; +; /* 5 - EGA with Color Display */ ;AN000; +; /* 7 - PS/2 Mod 50,60,80 OR BRECON-B with Mono Display */ ;AN000; +; /* 8 - PS/2 Mod 50,60,80 OR BRECON-B with Color Display */ ;AN000; +; /* B - PS/2 Mod 30 with Mono Display */ ;AN000; +; /* C - PS/2 Mod 30 with Color Display */ ;AN000; +; IF AL = 1AH THEN /* Call is supported */ ;AN000; +; Set HARDWARE_CONFIG byte based on DCC returned in DL ;AN000; +; ELSE ;AN000; +; Issue INT 10H EGA Info (AH=12H BL=10H) ;AN000; +; IF BL <> 10H THEN /* EGA */ ;AN000; +; Set EGA bit in HARDWARE_CONFIG ;AN000; +; ELSE /* CGA or */ ;AN000; +; Issue INT 10H PC CONVERTIBLE Physical display description param. ;AN000; +; request. (AH=15H) ;AN000; +; IF ES:[DI] = 5140H ;AN000; +; THEN ;AN000; +; Set PC_CONVERTIBLE bit in HARDWARE_CONFIG ;AN000; +; ELSE ;AN000; +; Set OLD_ADAPTER bit in HARDWARE_CONFIG ;AN000; +; ENDIF ;AN000; +; ENDIF ;AN000; +; ENDIF ;AN000; +; RETURN ;AN000; +; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +DET_HW_CONFIG PROC NEAR ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Try to read display combination code (PS/2 call): ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,READ_CONFIG_CALL ;AN000; + INT 10H ; Call video BIOS ;AN000; + ;AN000; + .IF ; If call is supported ;AN000; + .THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Call is supported, PS/2 BIOS is present (Model 39,50,60,80 or BRECON-B card), ;AN000; +; Determine what is the primary video adapter: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .SELECT ;AN000; + .WHEN OR ; MONO or ;AN000; + .WHEN ; CGA ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,OLD_ADAPTER ;AN000; + .WHEN OR ; EGA with Mono or ;AN000; + .WHEN ; EGA with Color ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,EGA ;AN000; + .WHEN OR ; BRECON-B with Mono or ;AN000; + .WHEN ; BRECON-B with Color ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,ROUNDUP ;AN000; + .WHEN OR ; PS/2 Model 30 with Mono or ;AN000; + .WHEN ; PS/2 Model 30 with Color ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,PALACE ;AN000; + .ENDSELECT ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PS/2 call is not supported, try the EGA info call: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .ELSE ;AN000; + MOV AH,ALT_SELECT_CALL ; Request Alternate select's ;AN000; + MOV BL,EGA_INFO_CALL ; "return EGA information call" ;AN000; + INT 10H ; Call video BIOS ;AN000; + .IF ; If a memory value is returned ;AN000; + .THEN ; then, there is an EGA ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,EGA ;AN000; + .ELSE ; else, call is not supported: ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; EGA call is not supported, try the PC CONVERTIBLE display description call: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AH,DISP_DESC_CALL ;AN000; + INT 10H ; Call BIOS, ES:DI :=Offset of parms;AN000; + .IF ; If LCD display type, ;AN000; + .THEN ; set LCD bit in Shared Data area ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,PC_CONVERTIBLE ;AN000; + .ELSE ; else, we have an old adapter. ;AN000; + MOV DS:[BP].HARDWARE_CONFIG,OLD_ADAPTER ; (either MONO or CGA);AN000; + .ENDIF ; Display type is LCD ;AN000; + .ENDIF ; EGA BIOS is present ;AN000; + .ENDIF ; PS/2 BIOS is present ;AN000; + RET ;AN000; +DET_HW_CONFIG ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; DET_MODE_STATE : Determine the current video mode and the active page. ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: HARDWARE_CONFIG = Type of video hardware attached ;AN000; +; ;AN000; +; OUTPUT: CUR_MODE = Video mode number (0-13H) ;AN000; +; CUR_PAGE = Video page number (0-8) ;AN000; +; NB_CHAR_COLUMNS = Number of columns if in a text mode. ;AN000; +; ;AN000; +; ;AN000; +; CALLED BY: PRT_SCR ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Use the BIOS interface to ;AN000; +; obtain the current mode and active page. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Call BIOS INTERRUPT 10H: "Return current video state" (AH = 0fh) ;AN000; +; ;AN000; +DET_MODE_STATE PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + MOV AH,GET_STATE_CALL ;AN000; + INT 10H ; CALL BIOS ;AN000; + MOV CUR_MODE,AL ;AN000; + MOV NB_CHAR_COLUMNS,AH ;AN000; + MOV CUR_PAGE,BH ;AN000; + ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +DET_MODE_STATE ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; GET_MODE_ATTR: Obtain attributes of current video mode. ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: CUR_MODE = Current video mode (1 BYTE) ;AN000; +; ;AN000; +; OUTPUT: MODE_TYPE = Video mode type (TXT or APA) ;AN000; +; NB_COLORS = Maximum number of colors (0-256) (0=B&W) ;AN000; +; ERROR_CODE = Error code if error occurred. ;AN000; +; SCREEN_HEIGHT= Number of rows (in pixels if APA or char if TEXT);AN000; +; SCREEN_WIDTH = Number of columns (in pixels/char) ;AN000; +; ;AN000; +; CALLED BY: PRT_SCR ;AN000; +; ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; DESCRIPTION: Scan the 2 local video mode attribute tables until the ;AN000; +; current mode is located. Return the attributes. ;AN000; +; For APA modes SCREEN_HEIGHT and SCREEN_WIDTH are in pixels, ;AN000; +; for TEXT modes they are in characters. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Scan the APA_ATTR_TABLE ;AN000; +; IF FOUND ;AN000; +; MODE_TYPE := APA ;AN000; +; NB_COLORS := mode.MAX_COLORS ;AN000; +; SCREEN_HEIGHT := mode.NB_L ;AN000; +; SCREEN_WIDTH := mode.NB_C ;AN000; +; ELSE ;AN000; +; Scan the TXT_ATTR_TABLE ;AN000; +; When FOUND ;AN000; +; MODE_TYPE := TXT ;AN000; +; NB_COLORS := mode.NUM_COLORS ;AN000; +; SCREEN_WIDTH := NB_CHAR_COLUMNS ;AN000; +; SCREEN_HEIGHT := Byte in ROM BIOS at 40:84 ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +GET_MODE_ATTR PROC NEAR ;AN000; + JMP SHORT GET_MODE_ATTR_BEGIN ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; LOCAL DATA ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; + ;AN000; +APA_ATTR STRUC ; ATTRIBUTES FOR APA MODES: ;AN000; + APA_MODE DB ? ; Mode number ;AN000; + NB_C DW ? ; Number of columns ;AN000; + NB_L DW ? ; Number of lines ;AN000; + MAX_COLORS DW ? ; Maximum number of colors available (0=B&W) ;AN000; +APA_ATTR ENDS ;AN000; + ;AN000; +TXT_ATTR STRUC ; ATTRIBUTES FOR TXT MODES: ;AN000; + TXT_MODE DB ? ; Mode number ;AN000; + NUM_COLORS DB ? ; Number of colors ;AN000; +TXT_ATTR ENDS ;AN000; + ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; APA MODE ATTRIBUTES: ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +NB_APA_MODES DW 10 ;AN000; +APA_ATTR_TABLE LABEL WORD ;AN000; +MODE04 APA_ATTR < 4,320,200, 4> ;AN000; +MODE05 APA_ATTR < 5,320,200, 4> ;AN000; +MODE06 APA_ATTR < 6,640,200, 2> ;AN000; +MODE0D APA_ATTR <0DH,320,200, 16> ;AN000; +MODE0E APA_ATTR <0EH,640,200, 16> ;AN000; +MODE0F APA_ATTR <0FH,640,350, 4> ;AN000; +MODE10H APA_ATTR <10H,640,350, 16> ;AN000; +MODE11H APA_ATTR <11H,640,480, 2> ;AN000; +MODE12H APA_ATTR <12H,640,480, 16> ;AN000; +MODE13H APA_ATTR <13H,320,200,256> ;AN000; + ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; TXT MODE ATTRIBUTES: ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +NB_TXT_MODES DW 5 ;AN000; +TXT_ATTR_TABLE LABEL WORD ;AN000; +MODE00 TXT_ATTR < 0, 16> ;AN000; +MODE01 TXT_ATTR < 1, 16> ;AN000; +MODE02 TXT_ATTR < 2, 16> ;AN000; +MODE03 TXT_ATTR < 3, 16> ;AN000; +MODE07 TXT_ATTR < 7, 0> ;AN000; + ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; BEGIN OF GET_MODE_ATTR ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +GET_MODE_ATTR_BEGIN: ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + MOV DL,CUR_MODE ; DL = CURRENT MODE ;AN000; +; ;AN000; +; Scan the APA_ATTR_TABLE ;AN000; +; ;AN000; + MOV CX,NB_APA_MODES ; CS <-- Number of APA modes ;AN000; + MOV BX,OFFSET APA_ATTR_TABLE; BX <-- Offset of APA mode table ;AN000; + SCAN_APA: ;AN000; + CMP DL,[BX].APA_MODE ; IF mode found ;AN000; + JE SHORT ITS_APA ; THEN get its attributes ;AN000; + ADD BX,SIZE APA_ATTR ;AN000; + LOOP SCAN_APA ; ELSE keep scanning ;AN000; + JMP SHORT SCAN_TXT_INIT ; NOT in this table: scan txt modes ;AN000; +ITS_APA: ;AN000; + MOV MODE_TYPE,APA ; MODE = APA ;AN000; + MOV AX,[BX].MAX_COLORS ;AN000; + MOV NB_COLORS,AX ; Get number of colors ;AN000; + MOV AX,[BX].NB_L ;AN000; + MOV SCREEN_HEIGHT,AX ; Get number of lines ;AN000; + MOV AX,[BX].NB_C ;AN000; + MOV SCREEN_WIDTH,AX ; Get number of columns ;AN000; + JMP SHORT GET_MODE_ATTR_END ;AN000; + ;AN000; +; ;AN000; +; Scan the TXT_ATTR_TABLE ;AN000; +; ;AN000; +SCAN_TXT_INIT: ;AN000; + MOV CX,NB_TXT_MODES ; CX <-- Number of TXT modes ;AN000; + MOV BX,OFFSET TXT_ATTR_TABLE; BX <-- Offset of TXT mode table ;AN000; + SCAN_TXT: ;AN000; + CMP DL,[BX].TXT_MODE ; IF mode found ;AN000; + JE SHORT ITS_TXT ; THEN get its attributes ;AN000; + ADD BX,SIZE TXT_ATTR ;AN000; + LOOP SCAN_TXT ; ELSE keep scanning ;AN000; +ITS_TXT: ;AN000; + MOV MODE_TYPE,TXT ; MODE = TXT ;AN000; + MOV AL,[BX].NUM_COLORS ;AN000; + CBW ;AN000; + MOV NB_COLORS,AX ; Get number of colors ;AN000; + MOV AL,NB_CHAR_COLUMNS ; Get number of columns ;AN000; + CBW ;AN000; + MOV SCREEN_WIDTH,AX ;AN000; + .IF ; If an old adapter is there;AN000; + .THEN ; The number of lines is 25 ;AN000; + MOV SCREEN_HEIGHT,25 ;AN000; + .ELSE ;AN000; + MOV AX,BIOS_SEG ; Get number of rows ;AN000; + MOV ES,AX ; from BIOS Data Area ;AN000; + MOV BX,NB_ROWS_OFFSET ; at 0040:0084 ;AN000; + MOV AL,ES:[BX] ;AN000; + CBW ;AN000; + INC AX ;AN000; + MOV SCREEN_HEIGHT,AX ;AN000; + .ENDIF ;AN000; + JMP SHORT GET_MODE_ATTR_END ;AN000; + ;AN000; +; ;AN000; +; The current mode was not found in any of the tables ;AN000; +; ;AN000; + MOV ERROR_CODE,MODE_NOT_SUPPORTED ;AN000; + ;AN000; +GET_MODE_ATTR_END: ;AN000; + POP AX ;AN000; + POP BX ;AN000; + POP CX ;AN000; + POP DX ;AN000; + RET ;AN000; +GET_MODE_ATTR ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; SET_UP_XLT_TABLE : SET UP A COLOR MAPPING FOR EACH COLOR AVAILABLE ;AN000; +; WITH THE CURRENT MODE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: CUR_MODE = Current video mode. ;AN000; +; HARDWARE_CONFIG = Type of display adapter. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; XLT_TAB = Color translation table. ;AN000; +; CUR_PAGE = Active page number ;AN000; +; BP = Offset of the shared data area ;AN000; +; ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: PRT_SCR ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; DESCRIPTION: The table is updated to hold a mapping for each color ;AN000; +; available in the current video mode either TEXT or APA. ;AN000; +; ;AN000; +; For example, if the current mode supports 16 colors then the first ;AN000; +; sixteen bytes of the table will hold the corresponding Color printer ;AN000; +; or Black and White printer mappings for these colors. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; IF HARDWARE_CONFIG = CGA OR HARDWARE_CONFIG = PC_CONVERTIBLE ;AN000; +; THEN ;AN000; +; CALL SET_CGA_XLT_TAB ;AN000; +; ;AN000; +; ELSE IF HARDWARE_CONFIG = EGA ;AN000; +; THEN ;AN000; +; CALL SET_EGA_XLT_TAB ;AN000; +; ;AN000; +; ELSE IF CUR_MODE = 0FH ;AN000; +; THEN ;AN000; +; CALL SET_MODE_F_XLT_TAB ;AN000; +; ;AN000; +; ELSE IF CUR_MODE = 19 ;AN000; +; THEN ;AN000; +; CALL SET_MODE_13H_XLT_TAB ;AN000; +; ;AN000; +; ELSE ;AN000; +; CALL SET_ROUNDUP_XLT_TAB ;AN000; +; ;AN000; +; CALL SET_BACKG_IN_XLT_TAB ; Update the background in the translation table ;AN000; +; ;AN000; +SET_UP_XLT_TAB PROC NEAR ;AN000; +;-------------------------------------------------------------------------------;AN000; +; For old display modes: set up translation table as for a Color Graphics Adapt.;AN000; +; Either 4 or 16 colors are set up depending if the mode is an APA or text mode.;AN000; +; ;AN000; +; NOTE: SET_UP_XLT_TAB cannot be invoked if the display adater is a Monochrome ;AN000; +; display adater. (When a Mono. adapter is attached, a jump is made to ;AN000; +; the ROM BIOS for printing the screen, and no translation table is set). ;AN000; +;-------------------------------------------------------------------------------;AN000; +.IF OR ; IF it is a CGA ;AN000; +.IF ; or a PC convertible ;AN000; +.THEN ; THEN set up CGA colors ;AN000; + CALL SET_CGA_XLT_TAB ; ;AN000; +.ELSEIF ; ELSEIF it is an EGA ;AN000; + CALL SET_EGA_XLT_TAB ; set up EGA colors. ;AN000; +.ELSEIF ; ELSEIF we are in mode 15 ;AN000; + CALL SET_MODE_F_XLT_TAB ; set up its 4 shades ;AN000; +;-------------------------------------------------------------------------------;AN000; +; A PS/2 system is attached: (we either have a PALACE [Model 30] or a ROUNDUP) ;AN000; +;-------------------------------------------------------------------------------;AN000; +.ELSEIF ; ELSEIF current mode is 13h;AN000; + CALL SET_MODE_13H_XLT_TAB ; set up 256 colors ;AN000; +.ELSEIF ; ELSEIF PS/2 Model 30(MCGA);AN000; + CALL SET_CGA_XLT_TAB ; handle it like a CGA ;AN000; +.ELSE ; ELSE we have a ROUNDUP ;AN000; +;-------------------------------------------------------------------------------;AN000; +; A PS/2 model 50, 60 or 80 or an ADA 'B' card is attached (in 16 color mode): ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL SET_ROUNDUP_XLT_TAB ; set up 16 colors ;AN000; +.ENDIF ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Finish setting up the translation table: ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +CALL SET_BACKG_IN_XLT_TAB ; Update the background in the translation table ;AN000; + ; according to the command line switch setting ;AN000; + ; (i.e.,/R /B) ;AN000; + RET ;AN000; +SET_UP_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SET_BACKG_IN_XLT_TAB : ADJUST THE MAPPING FOR THE BACKGROUND COLOR IN THE ;AN000; +; XLT_TAB ACCORDING TO PRINTER TYPE AND /R /B. ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of shared data area (SWITCHES) ;AN000; +; XLT_TAB = The color translation table. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: If there is a black and white printer and /R is NOT specified ;AN000; +; then the background color should not be printed and it is replaced in the ;AN000; +; translation table by the Intensity for white (will print nothing). ;AN000; +; ;AN000; +; If a color printer is attached and /B is not specified then the background ;AN000; +; color is replaced by the Print Band mask for white. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; IF (a black and white printer is attached) AND (/R is OFF) ;AN000; +; THEN ;AN000; +; MOV XLT_TAB, WHITE_INT ; Store white in translation table ;AN000; +; ELSE (a color printer is attached) ;AN000; +; IF (/B is ON) ;AN000; +; THEN ;AN000; +; RGB.R := MAX_INT ;AN000; +; RGB.G := MAX_INT ;AN000; +; RGB.B := MAX_INT ;AN000; +; CALL RGB2BAND ; Convert RGB for white to a Band Mask ;AN000; +; MOV XLT_TAB,AL ; Store the band mask in the xlt table ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SET_BACKG_IN_XLT_TAB PROC NEAR ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Test if a black and white printer is attached. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.IF AND ; IF black and white ;AN000; +.IF ; printer and not /R ;AN000; +.THEN ; then, map background ;AN000; + MOV XLT_TAB,WHITE_INT ; to white. ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; A Color printer is attached: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.ELSEIF AND ; else, if color printer ;AN000; +.IF ; and /B if OFF ;AN000; +.THEN ; ;AN000; + ; Store a null band mask ;AN000; + MOV XLT_TAB,0 ; the translation table. ;AN000; +.ENDIF ;AN000; + RET ;AN000; +SET_BACKG_IN_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; SET_EGA_XLT_TAB : SET UP COLOR TRANSLATION TABLE FOR ENHANCED GRAPHIC ;AN000; +; ADAPTER ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: XLT_TAB = Color translation table. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; SWITCHES = GRAPHICS command line parameters. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: SET_UP_XLT_TABLE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; NOTES: With the EGA, "VIDEO BIOS READ DOT call" returns an index into ;AN000; +; the 16 EGA palette registers. ;AN000; +; ;AN000; +; These registers contain the actual colors stored as rgbRGB components ;AN000; +; (see EGA_COL2RGB for details) for mode hex 10. Under mode hex E these ;AN000; +; registers contain the actual colors as I0RGB components (see CGA_COL2RGB ;AN000; +; for details). ;AN000; +; ;AN000; +; These registers can be Revised by the user but, are 'WRITE ONLY'. ;AN000; +; However, it is possible to define a SAVE AREA where BIOS will maintain ;AN000; +; a copy of the palette registers. ;AN000; +; ;AN000; +; This area is called the "DYNAMIC SAVE AREA" and is defined via the ;AN000; +; BIOS EGA SAVE_PTR AREA. Whenever the palette registers are changed by ;AN000; +; the user, BIOS updates the EGA_SAVE_AREA. ;AN000; +; ;AN000; +; The 16 palette registers are the first 16 bytes of the DYNAMIC SAVE AREA. ;AN000; +; ;AN000; +; This program takes advantage of this feature and consults the EGA DYNAMIC ;AN000; +; SAVE AREA in order to obtain the colors used in the active screen. ;AN000; +; ;AN000; +; ;AN000; +; DESCRIPTION: Obtain each color available with an EGA by reading its ;AN000; +; palette register in the EGA_SAVE_AREA: ;AN000; +; ;AN000; +; Calculate the mapping for this color, either a BAND_MASK or a ;AN000; +; GREY INTENSITY and store it in the color translation table. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Obtain the DYNAMIC EGA SAVE AREA offset from the BIOS SAVE_PTR_AREA. ;AN000; +; ;AN000; +; If current mode is either 4,5 or 6 ;AN000; +; Then, ;AN000; +; CALL SET_CGA_XLT_TAB ;AN000; +; Get the background color by reading palette register number 0 ;AN000; +; Else, ;AN000; +; For each register number (0 to 15): ;AN000; +; Get the register contents (rgbRGB values) from the EGA SAVE AREA ;AN000; +; CALL EGA_COL2RGB ; Obtain the Red, Green, Blue values ;AN000; +; CALL RGB2XLT_TAB ; Obtain a Band Mask or a Grey Intensity ;AN000; +; ; and store the result in the XLT_TAB ;AN000; +; ;AN000; +SET_EGA_XLT_TAB PROC NEAR ;AN000; + PUSH AX ; Save the registers used ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH DI ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Obtain the pointer to the DYNAMIC SAVE AREA from the SAVE AREA POINTER TABLE: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +EGA_SAVE_PTR EQU 4A8H ; EGA BIOS pointer to table of ;AN000; + ; pointer to save areas. ;AN000; + XOR AX,AX ; ES segment := paragraph 0 ;AN000; + MOV ES,AX ;AN000; + ;AN000; + LES BX,ES:DWORD PTR EGA_SAVE_PTR ; ES:BX := Pointer to ptr table ;AN000; + LES BX,ES:[BX]+4 ; ES:BX := Pointer to dynamic save area;AN000; + ; (NOTE: It is the second pointer in ;AN000; + ; the table) ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Set up one entry in the translation table for each color available. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.IF OR ; If the current mode is an old CGA ;AN000; +.IF OR ; GRAPHICS mode: ;AN000; +.IF ;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Current mode is either mode 4, 5 or 6; ;AN000; +; Store each color of the old CGA All Points Addressable mode: ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL SET_CGA_XLT_TAB ; Set up colors in the translation ;AN000; + ; table, NOTE: The background color ;AN000; + ; will not be set properly since the ;AN000; + ; EGA BIOS does not update memory ;AN000; + ; location 40:66 with the value ;AN000; + ; of the background color as CGA ;AN000; + ; does. ;AN000; +;------Adjust the background color in the translation table: ;AN000; +;------The background color is obtained from the EGA DYNAMIC SAVE AREA ;AN000; +;------ES:BX = Address of the EGA DYNAMIC SAVE AREA ;AN000; +;------NOTE : For CGA compatible modes EGA BIOS stores the color in the ;AN000; +;------DYNAMIC SAVE AREA as a I0RGB value. ;AN000; + XOR DI,DI ; DI:=register number = index in XLT_TAB;AN000; + MOV AL,ES:[BX][DI] ; AL:=Palette register 0 = Back. color ;AN000; + MOV AH,AL ; Convert I0RGB to IRGB (CGA color) ;AN001; + AND AL,111B ; Isolate RGB bits ;AN001; + AND AH,10000B ; Isolate I bit ;AN001; + SHR AH,1 ; Move I bit from position 5 to 4 ;AN001; + OR AL,AH ; Get IRGB byte. ;AN001; + CALL CGA_COL2RGB ; Convert IRGB to R,G,B values ;AN001; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; + ;AN000; +.ELSE ; ELSE, we have an EGA graphics mode: ;AN000; +;-------------------------------------------------------------------------------;AN000; +; The current mode is a either a text mode or one of the EGA enhanced mode; ;AN000; +; Store in the translation table each color available (these modes have 16 col.);AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CX,16 ; CX := Number of palette registers ;AN000; + ; to read ;AN000; + XOR DI,DI ; DI := Palette register number ;AN000; + ; and index in the translation table ;AN000; +STORE_1_EGA_COLOR: ;AN000; + MOV AL,ES:[BX][DI] ; AL := Palette register ;AN000; + .IF OR ; If mode E (hex) OR mode D (hex) ;AN000; + .IF ; the colors are ;AN000; + .THEN ; stored as I0CGA colors ;AN000; + MOV AH,AL ; Convert I0RGB to IRGB (CGA color) ;AN000; + AND AL,111B ; Isolate RGB bits ;AN000; + AND AH,10000B ; Isolate I bit ;AN000; + SHR AH,1 ; Move I bit from position 5 to 4 ;AN000; + OR AL,AH ; Get IRGB byte. ;AN000; + CALL CGA_COL2RGB ; Convert IRGB to R,G,B values ;AN000; + .ELSE ; Else, they are stored as (rgbRGB); ;AN000; + CALL EGA_COL2RGB ; Convert register to R,G,B values ;AN000; + .ENDIF ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; + INC DI ; Get next palette register number ;AN000; + LOOP STORE_1_EGA_COLOR ;AN000; +.ENDIF ; ENDIF 4 colors or 16 colors ;AN000; + ;AN000; + POP DI ; Restore the registers ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +SET_EGA_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; SET_CGA_XLT_TAB : SET UP COLOR TRANSLATION TABLE FOR COLOR GRAPHIC ;AN000; +; ADAPTER ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: XLT_TAB = Color translation table. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; SWITCHES = GRAPHICS command line parameters. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: SET_UP_XLT_TABLE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; NOTES: With the CGA, the "VIDEO BIOS READ DOT call" returns a number ;AN000; +; from 0 to 3. A dot of value 0 is of the background color. ;AN000; +; ;AN000; +; The actual value of the background color is stored in BIOS VIDEO ;AN000; +; DISPLAY DATA AREA as a PIIRGB value (see CGA_COL2RGB for details) and ;AN000; +; can be any of 16 colors. ;AN000; +; ;AN000; +; A dot of value 1,2, or 3 represents any of 2 specific colors depending ;AN000; +; on the current color palette. ;AN000; +; ;AN000; +; The palette number is obtained from the BIOS VIDEO DISPLAY DATA AREA ;AN000; +; (It is the "P" bit or bit number 5) ;AN000; +; ;AN000; +; The dot values 1,2,3 expressed in binary actually represent the RG ;AN000; +; (Red, Green) components of the color. ;AN000; +; ;AN000; +; The palette number represents the B (Blue) component therefore, when ;AN000; +; the palette number is appended to the color number we obtain the RGB ;AN000; +; components for that color. ;AN000; +; ;AN000; +; (E.G., COLOR = 010 ; COLOR # 2 ;AN000; +; PALETTE= 0 ; PALETTE # 0 ;AN000; +; ;AN000; +; IRGB = 0100 ; Intensity = 0 Ä¿ ;AN000; +; ; Red = 1 ÃÄÄÄ> color = Red ;AN000; +; ; Green = 0 ³ ;AN000; +; ; Blue = 0 ÄÙ ;AN000; +; ;AN000; +; ;AN000; +; DESCRIPTION: ;AN000; +; ;AN000; +; For each color available with a CGA: ;AN000; +; Calculate the color mapping, either a BAND_MASK or a GREY ;AN000; +; INTENSITY and store it in the color translation table. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; ; Obtain the background color from VIDEO BIOS DATA AREA ;AN000; +; ; and the paletter number ;AN000; +; ;AN000; +; ; Store the Background color: ;AN000; +; CALL CGA_COL2RGB ; Convert IRGB components to RGB values ;AN000; +; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation ;AN000; +; ; table ;AN000; +; ; Store all other colors: ;AN000; +; FOR IRG := 1 TO 3 ; Obtain the color number ;AN000; +; Append palette number (B) to IRG ;AN000; +; CALL CGA_COL2RGB ; Convert color to RGB values ;AN000; +; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation ;AN000; +; ; table ;AN000; +; ;AN000; +SET_CGA_XLT_TAB PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DI ;AN000; + PUSH ES ;AN000; + ;AN000; +.IF OR ;AN000; +.IF ;AN000; +;===============================================================================;AN000; +; ;AN000; +; THE CURRENT MODE IS MODE 4 OR 5 ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Read the CRT palette from the BIOS ROM to obtain the background color and ;AN000; +; the current palette number; store the palette number in BL ;AN000; +;-------------------------------------------------------------------------------;AN000; +ROM_BIOS_SEG EQU 40H ; CGA BIOS SEGMENT ;AN000; +CRT_PALETTE_OFF EQU 66H ; BIOS Current palette setting ;AN000; +P_BIT_MASK EQU 100000B ; bit 5 = Current palette ;AN000; +I_BIT_MASK EQU 1000B ; bit 4 = Intensity bit ;AN000; +R_BIT_MASK EQU 100B ; bit 2 = Red bit ;AN000; +G_BIT_MASK EQU 10B ; bit 1 = Green bit ;AN000; +B_BIT_MASK EQU 1B ; bit 0 = Blue bit ;AN000; + ;AN000; + MOV AX,ROM_BIOS_SEG ; ES := ROM BIOS SEGMENT ;AN000; + PUSH AX ;AN000; + POP ES ;AN000; + ;AN000; + MOV AL,ES:CRT_PALETTE_OFF; AL := CRT Palette (00PIIRGB) ;AN000; + MOV BL,P_BIT_MASK ; LOW NIBBLE = BACKGROUND COLOR ;AN000; + AND BL,AL ; BL := Palette number ;AN000; + MOV CL,5 ;AN000; + SHR BL,CL ;AN000; + ;AN000; + XOR DI,DI ; DI := Index in the XLT_TAB ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Store the background color, (obtained from low 4 bits of the byte at 40:66) ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Store the 3 foreground colors for mode 4 and 5 ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CX,3 ; For each color, but the background: ;AN000; +STORE_1_CGA_MODE4_COLOR: ;AN000; + INC DI ; Increment index in the translation table ;AN000; + MOV AX,DI ; AL := IRG ;AN000; + SHL AL,1 ;AN000; + OR AL,BL ; AL := IRGB ;AN000; + CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; + LOOP STORE_1_CGA_MODE4_COLOR ;AN000; +.ELSEIF ;AN000; +;===============================================================================;AN000; +; ;AN000; +; THE CURRENT MODE IS MODE 6 ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Store background color for mode 6 (mode 6 is a 2 colors, APA mode) ;AN000; +; Background is stored as BLACK ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR DI,DI ; DI := Index of color in translation table ;AN000; + MOV RGB.R,BLACK_INT ; Foreground color is white ;AN000; + MOV RGB.G,BLACK_INT ; RGB := RGB of white ;AN000; + MOV RGB.B,BLACK_INT ; ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Store foreground color for mode 6 (mode 6 is a 2 colors, APA mode) ;AN000; +;-------------------------------------------------------------------------------;AN000; + INC DI ; DI := Index of color in translation table ;AN000; + MOV RGB.R,WHITE_INT ; Background color is BLACK ;AN000; + MOV RGB.G,WHITE_INT ; RGB := RGB of BLACK ;AN000; + MOV RGB.B,WHITE_INT ; ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; +.ELSE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; THE CURRENT MODE IS A TEXT MODE: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR DI,DI ; DI := Index in the translation table ;AN000; + MOV CX,16 ; For each of the 16 colors: ;AN000; +STORE_1_CGA_TEXT_COLOR: ;AN000; + MOV AX,DI ; AL := IRGB ;AN000; + CALL CGA_COL2RGB ; Convert color (in AL) to R, G, B values ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; + INC DI ; Increment index in the translation table ;AN000; + LOOP STORE_1_CGA_TEXT_COLOR ;AN000; +.ENDIF ; ;AN000; + ;AN000; + POP ES ;AN000; + POP DI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + ;AN000; + RET ;AN000; +SET_CGA_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; RGB2XLT_TAB: CONVERT R,G,B VALUES TO EITHER A BAND MASK OR AN INTENSITY ;AN000; +; STORE THE RESULT IN THE TRANSLATION TABLE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: DI = Index in the translation table ;AN000; +; RGB = Red Green Blue values of the color to be stored. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB is updated ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; DESCRIPTION: Convert the RGB values to either a Band mask or an intensity ;AN000; +; depending on the printer type; store the result in the translation table. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; IF PRINTER_TYPE = COLOR ;AN000; +; THEN ;AN000; +; CALL RGB2BAND ; Obtain a Band Mask ;AN000; +; ELSE ; Printer is Monochrome ;AN000; +; CALL RGB2INT ; Obtain a Grey Intensity ;AN000; +; Store the result in the XLT_TAB ;AN000; +; ;AN000; +RGB2XLT_TAB PROC NEAR ;AN000; + .IF ; Color printer ? ;AN000; + .THEN ;AN000; +;-------A color printer is attached: ;AN000; + CALL RGB2BAND ; Yes, convert RGB to color band (in AL);AN000; + .ELSE ;AN000; +;-------A black and white printer is attached: ;AN000; + CALL RGB2INT ; No, RGB to an intensity in AL ;AN000; + .ENDIF ;AN000; +;-------Store the result ;AN000; + MOV XLT_TAB[DI],AL ;AN000; + RET ;AN000; +RGB2XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; CGA_COL2RGB : CONVERT A COLOR FROM THE CGA TO RED GREEN BLUE VALUES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: AL = 0000IRGB ONE BYTE WHERE BIT: ;AN000; +; ;AN000; +; I = Intensity bit ;AN000; +; R = Red component ;AN000; +; G = Green component ;AN000; +; B = Blue component ;AN000; +; ;AN000; +; ;AN000; +; OUTPUT: RGB.R = RED component (0-63) ;AN000; +; RGB.G = GREEN component (0-63) ;AN000; +; RGB.B = BLUE component (0-63) ;AN000; +; ;AN000; +; CALLED BY: SET_UP_CGA_XLT_TABLE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; DESCRIPTION: If either the RED, GREEN, or BLUE bit is on (in an IRGB ;AN000; +; byte) then, the corresponding color gun on the display is firing 2/3 ;AN000; +; of its capacity, giving a color intensity of "2/3". ;AN000; +; ;AN000; +; If the INTENSITY bit is on, then 1/3 is added to EACH color. ;AN000; +; ;AN000; +; (E.G., IRGB R G B ;AN000; +; BLACK = 00000000 ( 0, 0, 0) ;AN000; +; WHITE = 00001111 (3/3, 3/3, 3/3) ;AN000; +; RED = 00000100 (2/3, 0, 0) ;AN000; +; HIGH INT. RED = 00001100 (3/3, 1/3, 1/3) ;AN000; +; ;AN000; +; Since we want an intensity from 0 to 63, ;AN000; +; "2/3" of RED means: ;AN000; +; 2/3 * 63 = 42 ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; Get the intensity. ;AN000; +; Get the red component ;AN000; +; Get the green component ;AN000; +; Get the blue component ;AN000; +; ;AN000; +CGA_COL2RGB PROC NEAR ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; Init the R,G,B values: ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; + MOV RGB.R,0 ;AN000; + MOV RGB.G,0 ;AN000; + MOV RGB.B,0 ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; Test the Intensity bit: ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; + .IF ; IF, I is on ;AN000; + .THEN ;AN000; + ADD RGB.R,ONE_THIRD ; Then, add one third to each ;AN000; + ADD RGB.G,ONE_THIRD ; color. ;AN000; + ADD RGB.B,ONE_THIRD ;AN000; + .ENDIF ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; Test the RGB bits: ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; + .IF ; If, Red is on ;AN000; + .THEN ;AN000; + ADD RGB.R,TWO_THIRD ; then, add two third RED ;AN000; + .ENDIF ;AN000; + ;AN000; + .IF ; If, Green is on ;AN000; + .THEN ;AN000; + ADD RGB.G,TWO_THIRD ; then, add two third GREEN ;AN000; + .ENDIF ;AN000; + ;AN000; + .IF ; If, Blue is on ;AN000; + .THEN ;AN000; + ADD RGB.B,TWO_THIRD ; then, add two third BLUE ;AN000; + .ENDIF ;AN000; + ;AN000; + RET ;AN000; +CGA_COL2RGB ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; SET_MODE_F_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR MONOCHROME ;AN000; +; MODE "F" ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: XLT_TAB = Color translation table. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; SWITCHES = GRAPHICS command line parameters. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: SET_UP_XLT_TABLE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; NOTES: In mode F the "VIDEO BIOS READ DOT call" returns a byte where ;AN000; +; bit 1 and 3 represent the value of plane 1 and 3. ;AN000; +; The following colors are available using this mode: ;AN000; +; ;AN000; +; plane 2: plane 0: color: ;AN000; +; 0 0 black ;AN000; +; 0 1 white ;AN000; +; 1 0 blinking white ;AN000; +; 1 1 high-intensity white ;AN000; +; ;AN000; +; ;AN000; +; DESCRIPTION: A local table holds the Red, Green, Blue values for each of ;AN000; +; the 4 Mono colors available in Mode Fh. ;AN000; +; Each color is stored as either a Grey intensity if printing in Monochrome ;AN000; +; or as a Band Mask if printing in color. ;AN000; +; Black is stored as black. ;AN000; +; White is stored as a light gray ;AN000; +; High-intensity white and blinking white are stored as white. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; FOR EACH "COLOR" AVAILABLE WITH MODE F ;AN000; +; GET ITS R,G,B VALUES ;AN000; +; CALL RGB2XLT_TAB ; Convert RGB to an entry in the translation ;AN000; +; ; table ;AN000; +; ;AN000; +SET_MODE_F_XLT_TAB PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + JMP SHORT SET_MODE_F_BEGIN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; TABLE OF R,G,B VALUES WE ASSIGN TO THE 4 COLORS AVAILABLE IN MODE F: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +MODE_F_RGB LABEL BYTE ;AN000; + DB BLACK_INT,BLACK_INT,BLACK_INT ; Black is mapped to black. ;AN000; + DB TWO_THIRD,TWO_THIRD,TWO_THIRD ; White --> light grey ;AN000; + DB WHITE_INT,WHITE_INT,WHITE_INT ; Blinking --> white ;AN000; + DB WHITE_INT,WHITE_INT,WHITE_INT ; High-int. White --> white ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; STORE THE COLORS AVAILABLE WITH MODE F ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SET_MODE_F_BEGIN: ;AN000; + MOV SI,OFFSET MODE_F_RGB ; SI <-- Offset of RGB table ;AN000; + XOR DI,DI ; DI <-- Index into translation table ;AN000; + ;AN000; +;-------For each color available in mode F: ;AN000; +STORE_1_MODE_F_COLOR: ;AN000; + MOV AL,[SI] ; Get the Red component ;AN000; + MOV RGB.R,AL ;AN000; + MOV AL,[SI]+1 ; Get the Green component ;AN000; + MOV RGB.G,AL ;AN000; + MOV AL,[SI]+2 ; Get the Blue component ;AN000; + MOV RGB.B,AL ;AN000; + ;AN000; +;-------Convert pixel to either a Color band or an Intensity: ;AN000; + CALL RGB2XLT_TAB ; Convert and store in the xlt table ;AN000; + ;AN000; + ADD SI,3 ; Get next R,G,B values ;AN000; + INC DI ; One more color has been stored ;AN000; + CMP DI,NB_COLORS ; All stored ? ;AN000; + JL STORE_1_MODE_F_COLOR ;AN000; + ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP AX ;AN000; + RET ;AN000; +SET_MODE_F_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; SET_MODE_13H_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR PALACE VIDEO ;AN000; +; ADAPTER IN MODE 13H ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: XLT_TAB = Color translation table. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; SWITCHES = GRAPHICS command line parameters. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: SET_UP_XLT_TABLE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; NOTES: With the PALACE the "VIDEO BIOS READ DOT call" returns a direct ;AN000; +; index to the 256 COLOR REGISTERS. ;AN000; +; ;AN000; +; These COLORS REGISTERS hold the R,G,B (Red, Green, Blue) values for ;AN000; +; each of the 256 colors available at the same time on the screen. ;AN000; +; Color register number 0 holds the background color. ;AN000; +; ;AN000; +; DESCRIPTION: Store a color mapping for each color register. ;AN000; +; If the REVERSE_SW is off, exchange white and black. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; For each color (0 to 255) ;AN000; +; Read the color register ; get the RGB values for this color num. ;AN000; +; Store the result in the XLT_TAB ;AN000; +; ;AN000; +SET_MODE_13H_XLT_TAB PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV NB_COLORS_TO_READ,256 ; Read 256 color registers ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Store in the translation table each color available for mode 13h: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR DI,DI ; DI := Palette register number ;AN000; + ; and index in the translation table ;AN000; +STORE_1_M13H_COLOR: ;AN000; + MOV BX,DI ; BX := Color register to be read ;AN000; + MOV AX,GET_C_REG_CALL ; AX := BIOS Get color register call ;AN000; + INT 10H ; Call BIOS ;AN000; + MOV RGB.R,DH ; Get Red value ;AN000; + MOV RGB.G,CH ; Get Green value ;AN000; + MOV RGB.B,CL ; Get Blue value ;AN000; + CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; + INC DI ; Get next palette register number ;AN000; + CMP DI,NB_COLORS_TO_READ ; All colors stored ? ;AN000; + JL STORE_1_M13H_COLOR ; No, get next one ;AN000; + ;AN000; + ;AN000; + POP DI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +NB_COLORS_TO_READ DW ? ; Number of colors registers to read with a PS/2;AN000; +SET_MODE_13H_XLT_TAB ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SET_ROUNDUP_XLT_TAB: SET UP COLOR TRANSLATION TABLE FOR ROUNDUP VIDEO ;AN000; +; ADAPTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: XLT_TAB = Color translation table. ;AN000; +; PRINTER_TYPE = Type of printer attached (Color or B&W) ;AN000; +; SWITCHES = GRAPHICS command line parameters. ;AN000; +; ;AN000; +; OUTPUT: XLT_TAB IS UPDATED ;AN000; +; ;AN000; +; CALLED BY: SET_UP_XLT_TABLE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; NOTES: With the ROUNDUP the "VIDEO BIOS READ DOT call" returns an ;AN000; +; index into the 16 PALETTE REGISTERS. ;AN000; +; ;AN000; +; Each palette register holds an index into the current "color page" ;AN000; +; within the 256 COLOR REGISTERS. ;AN000; +; ;AN000; +; These "color pages" represent all the colors from WHICH TO CHOOSE the ;AN000; +; screen colors for an active page; 16 colors can be displayed at the ;AN000; +; same time on the screen. ;AN000; +; ;AN000; +; There are 2 paging modes: either 64 color pages or 16 color pages: ;AN000; +; ;AN000; +; In 64 color mode, there are 4 color pages available (the 256 palette ;AN000; +; registers are partitioned in 4 blocks of 64 colors). ;AN000; +; ;AN000; +; The 16 screen colors for the active page are selected from these 64 ;AN000; +; color registers. ;AN000; +; ;AN000; +; This scheme allows for quickly changing the contents of the screen by ;AN000; +; changing the active page. ;AN000; +; ;AN000; +; The COLOR REGISTERS contains the color information stored as RGB (Red, ;AN000; +; Green, Blue) components. There is one byte for each of these 3 ;AN000; +; components. The value for each component ranges from 0 to 63 (where ;AN000; +; 0 = color not present). ;AN000; +; ;AN000; +; ;AN000; +; DESCRIPTION: Determine the paging mode and the active color page. ;AN000; +; For each color available with the current mode, get the palette ;AN000; +; register and then, read the corresponding color register in order to ;AN000; +; obtain its RGB components. ;AN000; +; ;AN000; +; For mode 11h, 2 colors only are available. These colors are obtained from ;AN000; +; palette register 0 (background) and 7 (foreground color). The contents ;AN000; +; of these 2 palette registers is also used as an index within the color ;AN000; +; registers. ;AN000; +; ;AN000; +; If printing is Monochrome, map the RGB to a Grey Intensity. ;AN000; +; If printing is in colors, map the RGB to a Band Mask. ;AN000; +; Store the result in the translation table ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Read color page state (BIOS INT 10H - AL = 1AH) ;AN000; +; ;AN000; +; If mode 4,5 or 6 ;AN000; +; Then ;AN000; +; CALL SET_CGA_XLT_TAB ;AN000; +; Adjust the background color. ;AN000; +; else ;AN000; +; If mode 11h ;AN000; +; then ;AN000; +; For PALETTE_INDEX := 0 to 15 ;AN000; +; IF PAGE_MODE = PAGE_64_REGISTERS ;AN000; +; THEN ;AN000; +; Read the palette register number "PALETTE_INDEX" ;AN000; +; COLOR_INDEX := Palette register contents ;AN000; +; COLOR_INDEX := (CUR_PAGE_NUM * 64) + COLOR_INDEX ;AN000; +; Read color register number "COLOR_INDEX" ; Obtain R,G,B values. ;AN000; +; CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; +; ;AN000; +; ELSE IF PAGE_MODE = PAGE_16_REGISTERS ;AN000; +; COLOR_INDEX := (CUR_PAGE_NUM * 16) + PALETTE_INDEX ;AN000; +; Read color register number "COLOR_INDEX" ;AN000; +; CALL RGB2XLT_TAB ; Convert RGB to an entry in XLT_TAB ;AN000; +; ;AN000; +; ;AN000; +SET_ROUNDUP_XLT_TAB PROC NEAR ;AN000; +PAGING_MODE_64 EQU 0 ;AN000; + ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DI ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Obtain the color page state ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,PAGE_STATE_CALL ; Call BIOS ;AN000; + INT 10H ; BL := Paging mode ;AN000; + ; BH := Current page ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Check the video mode: ;AN000; +;-------------------------------------------------------------------------------;AN000; +.SELECT ;AN000; +.WHEN OR ; If the current mode is an old CGA ;AN000; +.WHEN OR ; mode: ;AN000; +.WHEN ; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Old CGA graphics mode (mode 4, 5 or 6) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;-------------------------------------------------------------------------------;AN000; +; Store colors of the old CGA modes: ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL SET_CGA_XLT_TAB ; Set up colors in the translation ;AN000; + ; table, NOTE: The background color ;AN000; + ; will not be set properly since the ;AN000; + ; PS/2 BIOS does not update memory ;AN000; + ; location 40:66 with the value ;AN000; + ; of the background color as CGA ;AN000; + ; does for modes 4 and 5. However ;AN000; + ; 40:66 holds the current palette;AN000; + ; selected. ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Adjust the background color for modes 4,5 or 6 ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV PAL_REGISTER_NB,0 ; Read the palette register number 0 ;AN000; + CALL GET_PALETTE_RGB ; this register points to the color ;AN000; + ; register that contains the RGB ;AN000; + ; values of the BACKGROUND color. ;AN000; + MOV DI,0 ; DI := Index in the translation table ;AN000; + CALL RGB2XLT_TAB ; Store mapping in the translation table;AN000; + ;AN000; +.WHEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Mode 11h (2 colors out of 256,000 colors) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get the background color: ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV PAL_REGISTER_NB,0 ; Read the palette register number 0 ;AN000; + CALL GET_PALETTE_RGB ; Get the RGB values for this color ;AN000; + MOV DI,0 ; DI := Index in translation table ;AN000; + CALL RGB2XLT_TAB ; Store mapping in the translation table;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get the foreground color: ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV PAL_REGISTER_NB,7 ; Read the palette register for the ;AN000; + ; FOREGROUND color (palette register 7);AN000; + CALL GET_PALETTE_RGB ; Get the RGB values for this color ;AN000; + MOV DI,1 ; DI := Index in translation table ;AN000; + CALL RGB2XLT_TAB ; Store mapping in the translation table;AN000; +.OTHERWISE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; The current mode is a 16 color mode ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR DI,DI ; DI := Index in translation table ;AN000; + MOV CX,16 ; 16 colors to read and store ;AN000; + MOV PAL_REGISTER_NB,0 ; Palette register to read ;AN000; +STORE_1_PS2_COLOR: ;AN000; + CALL GET_PALETTE_RGB ; Get the RGB values for this color ;AN000; +; ;AN000; +;-------Convert the RGB values to band mask or intensity and store in XLT_TAB: ;AN000; + ;AN000; + CALL RGB2XLT_TAB ; Store mapping in the translation table;AN000; + INC DI ; Get next palette register number ;AN000; + INC PAL_REGISTER_NB ; ;AN000; + LOOP STORE_1_PS2_COLOR ; Read it. ;AN000; +.ENDSELECT ;AN000; + ;AN000; + POP DI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PAL_REGISTER_NB DB ? ; Number of the palette register to read;AN000; +SET_ROUNDUP_XLT_TAB ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; GET_PALETTE_RGB: ON THE PS/2 MODEL 50, 60 AND 80, GET THE RGB VALUES FOR A ;AN000; +; PALETTE REGISTER BY READING THE CORRESPONDING COLOR REGISTER;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: PAL_REGISTER_NB = Palette register number ;AN000; +; BH = Current page number ;AN000; +; BL = Current paging mode ;AN000; +; ;AN000; +; OUTPUT: RGB.R = The RGB values obtained from the color register;AN000; +; RGB.G corresponding to the palette register specified;AN000; +; RGB.B ;AN000; +; ;AN000; +; CALLED BY: SET_ROUNDUP_XLT_TAB ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_PALETTE_RGB PROC ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + ;AN000; + MOV AL,BH ; SI := Current page number ;AN000; + CBW ; ;AN000; + MOV SI,AX ; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Calculte the absolute number of the first Color Register for the current page:;AN000; +; (calculated in SI) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +.IF ; If mode is 64 Color page ;AN000; +.THEN ; then ;AN000; + MOV CL,6 ; SI := Current page num * 64 ;AN000; + SHL SI,CL ; ;AN000; +.ELSE ; else, Mode is 16 Color page ;AN000; + MOV CL,4 ; SI := Current page num * 16 ;AN000; + SHL SI,CL ; ;AN000; +.ENDIF ;AN000; + ;AN000; +; ;AN000; +;-------Read the PALETTE REGISTER ;AN000; + MOV BL,PAL_REGISTER_NB ; BL := Palette register to be read ;AN000; + MOV AX,GET_P_REG_CALL ; Read palette register call ;AN000; + INT 10H ; Call BIOS, ;AN000; + ; BH := Color register index ;AN000; + ; WITHIN the current page and is;AN000; + ; either (0-15) or (0-63) ;AN000; + ; NOTE: SI = Absolute index (0-255) to ;AN000; + ; the first color register of the ;AN000; + ; current page and is a multiple of ;AN000; + ; either 16 or 64 ;AN000; + MOV BL,BH ; BX := Index within current color page ;AN000; + XOR BH,BH ; ;AN000; + ;AN000; +; ;AN000; +;-------Read the Color register: ;AN000; + OR BX,SI ; BX := Index of Color register to read ;AN000; + MOV AX,GET_C_REG_CALL ; Read the color register ;AN000; + INT 10H ; Call BIOS, ;AN000; + MOV RGB.R,DH ; DH := Red value read ;AN000; + MOV RGB.G,CH ; CH := Green value read ;AN000; + MOV RGB.B,CL ; CL := Blue value read ;AN000; + ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +GET_PALETTE_RGB ENDP ;AN000; +PAGE ;AN000; +;======================================================================= ;AN000; +; ;AN000; +; EGA_COL2RGB : CONVERT A COLOR FROM THE EGA TO RED GREEN BLUE VALUES ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; INPUT: AL = 00rgbRGB ONE BYTE WHERE BIT: ;AN000; +; ;AN000; +; r = 1/3 of Red component ;AN000; +; g = 1/3 of Green component ;AN000; +; b = 1/3 of Blue component ;AN000; +; R = 2/3 of Red component ;AN000; +; G = 2/3 of Green component ;AN000; +; B = 3/3 of Blue component ;AN000; +; ;AN000; +; ;AN000; +; OUTPUT: RGB.R = RED component (0-63) ;AN000; +; RGB.G = GREEN component (0-63) ;AN000; +; RGB.B = BLUE component (0-63) ;AN000; +; ;AN000; +; CALLED BY: SET_UP_EGA_XLT_TABLE ;AN000; +; ;AN000; +;----------------------------------------------------------------------- ;AN000; +; ;AN000; +; DESCRIPTION: Sums up the values for each color component. ;AN000; +; "2/3 of RED" means that the red gun in the display attached to the EGA ;AN000; +; is firing at 2/3 of full intensity. ;AN000; +; ;AN000; +; Since the color intensities range from 0 to 63, "1/3" means an ;AN000; +; intensity of: ;AN000; +; 1/3 * 63 = 21 ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Get the red component ;AN000; +; Get the green component ;AN000; +; Get the blue component ;AN000; +; ;AN000; +EGA_COL2RGB PROC NEAR ;AN000; +; ;AN000; +;-------Get the RED component (bit 5 and 2) ;AN000; +; ;AN000; +;-------Check bit 2 ;AN000; + MOV RGB.R,0 ;AN000; + TEST AL,100B ; "R" is on ? ;AN000; + JZ CHECK_BIT_5 ; No, check "r" ;AN000; + ADD RGB.R,TWO_THIRD ; Yes, add 2/3 RED ;AN000; +CHECK_BIT_5: ;AN000; + TEST AL,100000B ; "r" is on ? ;AN000; + JZ CHECK_BIT_1 ; No, check Green ;AN000; + ADD RGB.R,ONE_THIRD ; Yes, add 1/3 RED ;AN000; +; ;AN000; +;-------Get the GREEN component (bit 4 and 1) ;AN000; +; ;AN000; +CHECK_BIT_1: ;AN000; + MOV RGB.G,0 ;AN000; + TEST AL,10B ; "G" is on ? ;AN000; + JZ CHECK_BIT_4 ; No, check "g" ;AN000; + ADD RGB.G,TWO_THIRD ; Yes, add 2/3 GREEN ;AN000; +CHECK_BIT_4: ;AN000; + TEST AL,10000B ; "g" is on ? ;AN000; + JZ CHECK_BIT_0 ; No, check for Blue ;AN000; + ADD RGB.G,ONE_THIRD ; Yes, add 1/3 GREEN ;AN000; +; ;AN000; +;-------Get the BLUE component (bit 3 and 0) ;AN000; +; ;AN000; +CHECK_BIT_0: ;AN000; + MOV RGB.B,0 ;AN000; + TEST AL,1B ; "B" is on ? ;AN000; + JZ CHECK_BIT_3 ; No, check "b" ;AN000; + ADD RGB.B,TWO_THIRD ; Yes, add 2/3 BLUE ;AN000; +CHECK_BIT_3: ;AN000; + TEST AL,1000B ; "b" is on ? ;AN000; + JZ EGA_COL2RGB_RETURN ; No, return ;AN000; + ADD RGB.B,ONE_THIRD ; Yes, add 1/3 BLUE ;AN000; +EGA_COL2RGB_RETURN: ;AN000; + RET ;AN000; +EGA_COL2RGB ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; RGB2INT : MAP RED GREEN BLUE VALUES TO AN INTENSITY. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: RGB.R = A RED value (0-63) ;AN000; +; RGB.G = A GREEN value (0-63) ;AN000; +; RGB.B = A BLUE value (0-63) ;AN000; +; DARKADJUST_VALUE= THE DARKNESS VALUE (In shared data area). ;AN000; +; SWITCHES = Command line switches ;AN000; +; ;AN000; +; OUTPUT: AL = THE INTENSITY (0-63) NOTE: 0 = BLACK ;AN000; +; 63 = BRIGHT WHITE ;AN000; +; ;AN000; +; WARNING: AH IS LOST ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: When the RGB values for a pixel are at their maximum ;AN000; +; value, what we obtain is a bright white pixel on the screen; this is ;AN000; +; the brightest color achievable and therefore, its intensity is 63. ;AN000; +; ;AN000; +; When no color gun is firing on the display: RGB values are 0,0,0 this ;AN000; +; is no color at all and therefore maps to intensity 0. ;AN000; +; ;AN000; +; For intermediate colors, experimentation has shown that the eye will ;AN000; +; see blue as darker than red and red as darker than green. ;AN000; +; ;AN000; +; On a grey rainbow from 0 - 10 where 0 is black and 10 is white: ;AN000; +; ;AN000; +; Blue corresponds to a grey of intensity 1 ;AN000; +; Red corresponds to a grey of intensity 3 ;AN000; +; Green corresponds to a grey of intensity 6 ;AN000; +; ;AN000; +; Therefore, if we mix all 3 colors we obtain a grey of ;AN000; +; intensity 1 + 3 + 6 = 10 (i.e.,white). ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Calculate the intensity ;AN000; +; ;AN000; +; AL = (.6 * G) + (.3 * R) + (.1 * B) ;AN000; +; ;AN000; +; Adjust Darkness ;AN000; +; ;AN000; +; AL = AL + DARKADJUST_VALUE ;AN000; +; ;AN000; +RGB2INT PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; + XOR AX,AX ; AL := Current component intensity ;AN000; + XOR BX,BX ; BX is used for calculations ;AN000; + XOR DX,DX ; DL := Running sum for grey intensity ;AN000; + ;AN000; +;-------Process /R (Reverse black and white) ;AN000; +.IF ; IF reverse is OFF ;AN000; +.THEN ; THEN REVERSE BLACK AND WHITE: ;AN000; +;-------Test if the color is BLACK ;AN000; + .IF AND ; If black ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with white ;AN000; + MOV AL,WHITE_INT ;AN000; + JMP SHORT RGB2INT_END ;AN000; + .ELSEIF AND ; else if, high-intensity white ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with black ;AN000; + MOV AL,BLACK_INT ;AN000; + JMP SHORT RGB2INT_END ;AN000; + .ELSEIF AND ; else if, white ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with black ;AN000; + MOV AL,BLACK_INT ;AN000; + JMP SHORT RGB2INT_END ;AN000; + .ENDIF ;AN000; +.ENDIF ;AN000; + ;AN000; +;-------Calculate Green component ;AN000; + MOV AL,RGB.G ; AL := Green component ;AN000; + MOV BH,6 ; ;AN000; + MUL BH ; AX := Green * 6 ;AN000; + MOV BH,10 ; ;AN000; + DIV BH ; AL := (GREEN * 6) / 10 ;AN000; + ADD DL,AL ; DL := Cumulative intensity ;AN000; + MOV CH,AH ; CH := Cumulative remainder ;AN000; + ;AN000; +;-------Calculate Red component ;AN000; + MOV AL,RGB.R ; AL := Red component ;AN000; + MOV BH,3 ; ;AN000; + MUL BH ; AX := Red * 3 ;AN000; + MOV BH,10 ; ;AN000; + DIV BH ; AL := (RED * 3) / 10 ;AN000; + ADD DL,AL ; DL := Cumulative intensity ;AN000; + ADD CH,AH ; CH := Cumulative remainder ;AN000; + ;AN000; +;-------Calculate Blue component ;AN000; + MOV AL,RGB.B ; AX := Blue component ;AN000; + XOR AH,AH ; ;AN000; + DIV BH ; AL := BLUE / 10 ;AN000; + ADD DL,AL ; DL := Cumulative intensity ;AN000; + ADD CH,AH ; CH := Cumulative remainder ;AN000; + ;AN000; +;-------Adjust intensity with cumulative remainder ;AN000; + XOR AX,AX ;AN000; + MOV AL,CH ; AX := Cumulative remainder ;AN000; + MOV BH,10 ; BH := 10 ;AN000; + DIV BH ; AL := Total remainder / 10 ;AN000; + ADD DL,AL ; DL := Cumulative intensity ;AN000; + .IF ; If remainder > 4 ;AN000; + .THEN ; Then, add 1 ;AN000; + INC DL ; to the intensity ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------Adjust darkness ;AN000; + ADD DL,DS:[BP].DARKADJUST_VALUE ;AN000; + ;AN000; +;-------Return result ;AN000; + MOV AL,DL ; AL := sum of R,G,B intensities ;AN000; + ;AN000; +RGB2INT_END: ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +RGB2INT ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;============================================================================== ;AN000; +; ;AN000; +; RGB2BAND: MAP RED GREEN BLUE VALUES TO A "SELECT COLOR BAND" MASK FOR ;AN000; +; THE COLOR PRINTER. ;AN000; +; ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; ;AN000; +; INPUT: RGB.R = A RED value (0-63) ;AN000; +; RGB.G = A GREEN value (0-63) ;AN000; +; RGB.B = A BLUE value (0-63) ;AN000; +; BP = Offset of the Shared Data Area. ;AN000; +; ;AN000; +; OUTPUT: AL = The Band Mask, one byte where: ;AN000; +; ;AN000; +; bit 0 = Color Band 1 is needed ;AN000; +; bit 1 = Color Band 2 is needed ;AN000; +; bit 2 = Color Band 3 is needed ;AN000; +; bit 3 = Color Band 4 is needed ;AN000; +; ;AN000; +; ;AN000; +; CALLED BY: SET_CGA_XLT_TAB ;AN000; +; SET_EGA_XLT_TAB ;AN000; +; SET_ROUNDUP_XLT_TAB ;AN000; +; SET_MODE_13H_XLT_TAB ;AN000; +; SET_MODE_F_XLT_TAB ;AN000; +; ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; ;AN000; +; NOTES: The RGB values in input describe a color from the screen. ;AN000; +; Up to 256K different colors can be described with these RGB values. ;AN000; +; ;AN000; +; On the color printer, the print ribbon is composed of 4 color bands, ;AN000; +; each of a different color. By overlapping these 4 bands when ;AN000; +; printing, more colors can be obtained. However, the number of colors ;AN000; +; that can be achieved by overlapping print bands is very limited (4 or ;AN000; +; 8 colors). ;AN000; +; ;AN000; +; THIS MODULE SELECT THE PRINTER COLOR THAT IS THE CLOSEST TO THE ;AN000; +; DESIRED SCREEN COLOR. ;AN000; +; ;AN000; +; The Band Mask specifies which color bands have to be overlapped to ;AN000; +; obtain a color on the printer. ;AN000; +; ;AN000; +; ;AN000; +; DESCRIPTION: Go through the list of printer colors in the SHARED DATA ;AN000; +; AREA, for each of these colors, compare its RGB values with those in ;AN000; +; input. ;AN000; +; Get the BAND_MASK of the closest printer color. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Locate the printer colors info structure in the shared data area: ;AN000; +; COLORPRINT_PTR := BP + COLORPRINT_PTR ;AN000; +; ;AN000; +; Get the number of printer colors from the COLORPRINT info in the Shared ;AN000; +; data area: ;AN000; +; Number of colors := COLORPRINT_PTR.NUM_PRT_COLOR ;AN000; +; ;AN000; +; CURRENT_COLOR_PTR : First record in the COLORPRINT info structure ;AN000; +; BEST_CHOICE := CURRENT_RECORD_PTR.BAND_MASK ;AN000; +; MIN_DIFF := Maximum positive value ;AN000; +; ;AN000; +; FOR each printer color: ;AN000; +; CUR_DIFF := 0 ;AN000; +; (* Calculate the geometric distance between the RGB values from the *) ;AN000; +; (* input and those of the printer color. *) ;AN000; +; Red difference := (R - CURRENT_COLOR_PTR.RED) ;AN000; +; Red difference := Red difference * Red difference ;AN000; +; CUR_DIFF := CUR_DIFF + Red difference ;AN000; +; ;AN000; +; Green difference := (G - CURRENT_COLOR_PTR.GREEN) ;AN000; +; Green difference := Green difference * Green difference ;AN000; +; CUR_DIFF := CUR_DIFF + Green difference ;AN000; +; ;AN000; +; Blue difference := (B - CURRENT_COLOR_PTR.BLUE) ;AN000; +; Blue difference := Blue difference * Blue difference ;AN000; +; CUR_DIFF := CUR_DIFF + Blue difference ;AN000; +; ;AN000; +; IF CUR_DIFF < MIN_DIFF ;AN000; +; THEN BEGIN ;AN000; +; MIN_DIFF := CUR_DIFF ;AN000; +; BEST_CHOICE := printer color.BAND_MASK ;AN000; +; END ;AN000; +; ;AN000; +; CURRENT_COLOR_PTR := Offset of next color ;AN000; +; END (For each printer color) ;AN000; +; ;AN000; +; Return BEST_CHOICE ;AN000; +; ;AN000; +; ;AN000; +RGB2BAND PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; +;-------Process /R (Reverse black and white) ;AN000; +.IF ; IF reverse is OFF ;AN000; +.THEN ; THEN REVERSE BLACK AND WHITE: ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; ;AN000; +; REVERSE BLACK AND WHITE: ;AN000; +; ;AN000; +;------------------------------------------------------------------------------ ;AN000; +;-------Test if the color is BLACK ;AN000; + .IF AND ; If black ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with the ;AN000; + MOV BEST_CHOICE,0 ; band mask for white ;AN000; + JMP RGB2BAND_END ; return this band mask ;AN000; + .ELSEIF AND ; else if, high-intensity white ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with the ;AN000; + MOV RGB.R,BLACK_INT ; RGB values of black ;AN000; + MOV RGB.G,BLACK_INT ;AN000; + MOV RGB.B,BLACK_INT ;AN000; + .ELSEIF AND ; else if, white ;AN000; + .IF AND ; ;AN000; + .IF ; ;AN000; + .THEN ; then, replace it with the ;AN000; + MOV RGB.R,BLACK_INT ; RGB values of black ;AN000; + MOV RGB.G,BLACK_INT ;AN000; + MOV RGB.B,BLACK_INT ;AN000; + .ENDIF ;AN000; +.ENDIF ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; ;AN000; +; CALCULATE THE GEOMETRIC DISTANCE BETWEEN THE COLORS OF THE PIXEL AND THOSE OF ;AN000; +; THE PRINTER: ;AN000; +; ;AN000; +;------------------------------------------------------------------------------ ;AN000; + MOV BX,DS:[BP].COLORPRINT_PTR ; BX := OFFSET of COLORPRINT ;AN000; + ADD BX,BP ;AN000; + MOV MIN_DIFF,7FFFh ; No match yet, minimum diff. ;AN000; + ; is maximum POSITIVE value. ;AN000; + XOR CX,CX ;AN000; + MOV CL,DS:[BP].NUM_PRT_COLOR ; CX := Number of print colors ;AN000; + ;AN000; + ;AN000; +INSPECT_1_PRINT_COLOR: ;AN000; + MOV CUR_DIFF,0 ; Current difference := 0 ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; Calculate the Red difference: ;AN000; +;------------------------------------------------------------------------------ ;AN000; + MOV AL,RGB.R ;AN000; + SUB AL,[BX].RED ;AN000; +;-------Elevate at the power of two ;AN000; + MOV DL,AL ; DX := Red difference ;AN000; + IMUL DL ; AX := Red diff. square ;AN000; + ADD CUR_DIFF,AX ; CURR_DIF + Red diff. ;AN000; + ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; Calculate the Green difference: ;AN000; +;------------------------------------------------------------------------------ ;AN000; + MOV AL,RGB.G ;AN000; + SUB AL,[BX].GREEN ;AN000; +;-------Elevate at the power of two ;AN000; + MOV DL,AL ; DX := Red difference ;AN000; + IMUL DL ; AX := Red diff. square ;AN000; + ADD CUR_DIFF,AX ; CURR_DIF + Green diff. ;AN000; + ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; Calculate the Blue difference: ;AN000; +;------------------------------------------------------------------------------ ;AN000; + MOV AL,RGB.B ;AN000; + SUB AL,[BX].BLUE ;AN000; +;-------Elevate at the power of two ;AN000; + MOV DL,AL ; DX := Red difference ;AN000; + IMUL DL ; AX := Red diff. square ;AN000; + ADD CUR_DIFF,AX ; CURR_DIF + Blue diff. ;AN000; + ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; Check how close is this print color to the screen color: ;AN000; +;------------------------------------------------------------------------------ ;AN000; + MOV AX,CUR_DIFF ; If this color is better than what we ;AN000; + .IF ; had before. ;AN000; + .THEN ; ;AN000; + MOV MIN_DIFF,AX ; then, new minimum distance; ;AN000; + MOV AL,[BX].SELECT_MASK ; get its band mask. ;AN000; + MOV BEST_CHOICE,AL ; ;AN000; + .ENDIF ; ;AN000; + ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; Get offset of next COLORPRINT info record: ;AN000; +;------------------------------------------------------------------------------ ;AN000; + ADD BX,SIZE COLORPRINT_STR ;AN000; + LOOP INSPECT_1_PRINT_COLOR ;AN000; + ;AN000; +;------------------------------------------------------------------------------ ;AN000; +; BEST_CHOICE contains the print color with the closest RGB values ;AN000; +;------------------------------------------------------------------------------ ;AN000; +RGB2BAND_END: ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + MOV AL,BEST_CHOICE ;AN000; + RET ;AN000; +BEST_CHOICE DB ? ;AN000; +MIN_DIFF DW ? ;AN000; +CUR_DIFF DW ? ;AN000; +RGB2BAND ENDP ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCTRL.EXT b/v4.0/src/CMD/GRAPHICS/GRCTRL.EXT new file mode 100644 index 0000000..2d756fd --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCTRL.EXT @@ -0,0 +1,47 @@ +PAGE ,132 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCTRL.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing external declarations for ;AN000; +;; the code and data defined in GRCTRL.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +EXTRN DET_HW_CONFIG:NEAR ;AN000; +EXTRN RGB:BYTE ;AN000; +EXTRN BIOS_INT_5H:WORD ;AN000; +EXTRN PRT_SCR:NEAR ;AN000; +EXTRN PRINT_SCREEN_ALLOWED:BYTE ;AN000; +EXTRN XLT_TAB:BYTE ;AN000; +EXTRN MODE_TYPE:BYTE ;AN000; +EXTRN CUR_MODE_PTR:WORD ;AN000; +EXTRN CUR_MODE:BYTE ;AN000; +EXTRN MODE_TYPE:BYTE ;AN000; +EXTRN NB_COLORS:WORD ;AN000; +EXTRN SCREEN_HEIGHT:WORD ;AN000; +EXTRN SCREEN_WIDTH:WORD ;AN000; +EXTRN NB_CHAR_COLUMNS:BYTE ;AN000; +EXTRN CUR_PAGE:BYTE ;AN000; +EXTRN CUR_COLUMN:WORD ;AN000; +EXTRN CUR_ROW:WORD ;AN000; +EXTRN NB_SCAN_LINES:WORD ;AN000; +EXTRN SCAN_LINE_MAX_LENGTH:WORD ;AN000; +EXTRN CUR_SCAN_LNE_LENGTH:WORD ;AN000; +EXTRN PRT_BUF:BYTE ;AN000; +EXTRN NB_BOXES_PER_PRT_BUF:BYTE ;AN000; +EXTRN CUR_BOX:BYTE ;AN000; +EXTRN BOX_H:BYTE ;AN000; +EXTRN BOX_W:BYTE ;AN000; +EXTRN ERROR_CODE:BYTE ;AN000; +EXTRN ROTATE_SW:BYTE ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRCTRL.STR b/v4.0/src/CMD/GRAPHICS/GRCTRL.STR new file mode 100644 index 0000000..fb913df --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCTRL.STR @@ -0,0 +1,111 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCTRL.STR ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing structures and equates for ;AN000; +;; the Print Screen process. ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PRINT SCREEN INTERNAL ERROR CODES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +NO_ERROR EQU 0 ;AN000; +UNABLE_TO_PRINT EQU 1 ; The procedure was unable to print the ;AN000; + ; screen ;AN000; +DISPLAYMODE_INFO_NOT_FOUND EQU 2 ; There was no DISPLAYMODE info record ;AN000; + ; in the Shared Area for the current mode ;AN000; +MODE_NOT_SUPPORTED EQU 4 ; This mode is not supported by this version ;AN000; + ; of GRAHICS. ;AN000; +PRINTER_ERROR EQU 8 ; An error occurred while printing a byte ;AN000; + ; (i.e., Out of paper, etc) ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PIXEL INTERNAL REPRESENTATION ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PIXEL_STR STRUC ;AN000; + R DB ? ; RED component (0 to MAX_INT) ;AN000; + G DB ? ; GREEN component (0 to MAX_INT) ;AN000; + B DB ? ; BLUE component (0 to MAX_INT) ;AN000; +PIXEL_STR ENDS ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; VIDEO MODE TYPES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +TXT EQU 0 ; Text ;AN000; +APA EQU 1 ; All Points Addressable ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; BIOS INTERRUPT 10H CALL EQUATES ;AN000; +; Note: Either AX or AH must be initialized, depending if the call is ;AN000; +; a sub-call or not. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +READ_DOT_CALL EQU 0DH ; Read dot ;AN000; +SET_CURSOR_CALL EQU 02H ; Set cursor on the screen ;AN000; +READ_CURSOR_CALL EQU 03H ; Read position of the cursor on the screen ;AN000; +READ_CHAR_CALL EQU 08H ; Read attribute/character ;AN000; +GET_STATE_CALL EQU 0FH ; Return current video state ;AN000; +GET_P_REG_CALL EQU 1007H ; Read a palette register (EGA, VGA) ;AN000; +GET_C_REG_CALL EQU 1015H ; Read a color register (VGA) ;AN000; +READ_CONFIG_CALL EQU 1A00H ; Read display adapter configuration (PS/2) ;AN000; +PAGE_STATE_CALL EQU 101AH ; Read color page state call (PS/2) ;AN000; +ALT_SELECT_CALL EQU 12H ; Alternate select call (AH = 12h) ;AN000; +EGA_INFO_CALL EQU 10H ; Return EGA information (AH=12H,BH = 10H) ;AN000; +DISP_DESC_CALL EQU 15H ; PC CONVERTIBLE display description call ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; BIOS DATA AREA EQUATES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +BIOS_SEG EQU 40H ; BIOS segment ;AN000; +NB_ROWS_OFFSET EQU 84H ; Number of rows displayed when in a text mode ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; CONSTANT DEFINITIONS ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +NO EQU 0 ;AN000; +YES EQU 1 ;AN000; +OFF EQU 0 ;AN000; +ON EQU 1 ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; TRANSLATION TABLE DEFINITIONS ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +WHITE_INT EQU 63 ; Intensity for WHITE on the printer ;AN000; +BLACK_INT EQU 0 ; Intensity for BLACK on the printer ;AN000; +MAX_INT EQU WHITE_INT ; Maximum intensity for a RGB value, ;AN000; + ; (Red, Green, or Blue). ;AN000; +ONE_THIRD EQU MAX_INT*1/3 ; Used to calculate Red, Green, Blue intensity ;AN000; +TWO_THIRD EQU MAX_INT*2/3 ; values. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PRINTER CONTROL ASCII CODES ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +CR EQU 0DH ; Carriage return ;AN000; +LF EQU 0AH ; Line feed ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRINST.ASM b/v4.0/src/CMD/GRAPHICS/GRINST.ASM new file mode 100644 index 0000000..cdb8b17 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRINST.ASM @@ -0,0 +1,973 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Installation Modules ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINST.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the installation modules for the ;AN000; +;; GRAPHICS command. ;AN000; +;; ;AN000; +;; GRAPHICS_INSTALL is the main module. ;AN000; +;; ;AN000; +;; GRAPHICS_INSTALL calls modules in GRLOAD.ASM to load ;AN000; +;; the GRAPHICS profile and GRPARMS.ASM to parse the command line. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; DOS 3.3 Message Retriever Interface Supplement. ;AN000; +;; TUPPER I0 Document - PARSER HIGH LEVEL DESIGN REVIEW ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; GRAPHICS_INSTALL - Main installation module ;AN000; +;; CHAIN_INTERRUPTS - Chain interrupts 5, 2F, EGA Save Pointers ;AN000; +;; COPY_PRINT_MODULES - Throw away one set of print modules ;AN000; +;; ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRLOAD.EXT - Externals for profile load ;AN000; +;; GRLOAD2.EXT - Externals for profile load ;AN000; +;; GRCTRL.EXT - Externals for print screen control ;AN000; +;; GRPRINT.EXT - Externals for print modules ;AN000; +;; GRCPSD.EXT - Externals for COPY_SHARED_DATA module ;AN000; +;; GRPARMS.EXT - External for GRAPHICS command line parsing ;AN000; +;; GRPARSE.EXT - External for DOS parser ;AN000; +;; GRBWPRT.EXT - Externals for Black and white printing modules ;AN000; +;; GRCOLPRT.EXT - Externals for color printing modules ;AN000; +;; GRINT2FH.EXT - Externals for Interrupt 2Fh driver. ;AN000; +;; ;AN000; +;; GRMSG.EQU - Equates for the GRAPHICS error messages ;AN000; +;; SYSMSG.INC - DOS message retriever ;AN000; +;; ;AN000; +;; GRSHAR.STR - Shared Data Area Structure ;AN000; +;; ;AN000; +;; STRUC.INC - Macros for using structured assembly language ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRLOAD.ASM: ;AN000; +;; LOAD_PROFILE - Main module for profile loading ;AN000; +;; SYSPARSE - DOS system parser ;AN000; +;; SYSDISPMSG - DOS message retriever ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; +.XLIST ;; ;AN000; + INCLUDE GRSHAR.STR ;; Include the Shared data area structure;AN000; + INCLUDE SYSMSG.INC ;; Include DOS message retriever ;AN000; + INCLUDE STRUC.INC ;; Include macros - Structured Assembler ;AN000; + INCLUDE GRLOAD.EXT ;; Bring in external declarations ;AN000; + INCLUDE GRLOAD2.EXT ;; ;AN000; + INCLUDE GRLOAD3.EXT ;; ;AN000; + INCLUDE GRCTRL.EXT ;; ;AN000; + INCLUDE GRBWPRT.EXT ;; ;AN000; + INCLUDE GRCOLPRT.EXT ;; ;AN000; + INCLUDE GRCPSD.EXT ;; ;AN000; + INCLUDE GRINT2FH.EXT ;; ;AN000; + INCLUDE GRCTRL.EXT ;; ;AN000; + INCLUDE GRPARSE.EXT ;; ;AN000; + INCLUDE GRPARMS.EXT ;; ;AN000; + INCLUDE GRMSG.EQU ;; ;AN000; + ;; ;AN000; +MSG_UTILNAME ;; Identify ourself to Message retriever.;AN000; + ;; Include messages ;AN000; +MSG_SERVICES ;; ;AN000; +MSG_SERVICES ;; ;AN000; +MSG_SERVICES ;AN000; +.LIST ;; ;AN000; + ;; ;AN000; +PUBLIC GRAPHICS_INSTALL ;; ;AN000; +PUBLIC TEMP_SHARED_DATA_PTR ;; ;AN000; +PUBLIC PRINTER_TYPE_PARM ;; ;AN000; +PUBLIC PRINTER_TYPE_LENGTH ;; ;AN000; +PUBLIC PROFILE_PATH ;; ;AN000; +PUBLIC PRINTBOX_ID_PTR ;; ;AN000; +PUBLIC PRINTBOX_ID_LENGTH ;; ;AN000; +PUBLIC DEFAULT_BOX ;; ;AN000; +PUBLIC LCD_BOX ;; ;AN000; +PUBLIC NB_FREE_BYTES ;; ;AN000; +PUBLIC SYSDISPMSG ;; ;AN000; +PUBLIC DISP_ERROR ;; ;AN000; +PUBLIC INSTALLED ;; ;AN000; +PUBLIC ERROR_DEVICE ;; ;AN000; +PUBLIC STDERR ;; ;AN000; +PUBLIC STDOUT ;; ;AN000; +PUBLIC RESIDENT_SHARED_DATA_SIZE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Install Variables ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +NO EQU 0 ;; ;AN000; +YES EQU 1 ;; ;AN000; +INSTALLED DB NO ;; YES if GRAPHICS already installed ;AN000; + ;; ;AN000; + ;; ;AN000; +BYTES_AVAIL_PSP_OFF EQU 6 ;; Word number 6 of the PSP is the ;AN000; + ;; number of bytes available in the ;AN000; + ;; current segment ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; GRLOAD (PROFILE LOADING) INPUT PARMS: ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +PRINTER_TYPE_PARM DB "GRAPHICS",9 DUP(0) ; Printer type ;AN000; + ;; (default=GRAPHICS) ;AN000; +PRINTER_TYPE_LENGTH DB 17 ;; Printer type maximum length of ASCIIZ ;AN000; +PROFILE_PATH DB 128 DUP(0) ;; Profile name with full path ;AN000; + ;; (Max size for ASCIIZ is 128) ;AN000; +PRINTBOX_ID_PTR DW DEFAULT_BOX ;; Offset of ASCIIZ string containing ;AN000; +DEFAULT_BOX DB "STD",14 DUP(0); the printbox id. (DEFAULT = STD) ;AN000; +LCD_BOX DB "LCD",14 DUP(0); ASCIIZ string for the LCD printboxID;AN000; +PRINTBOX_ID_LENGTH DB 17 ;; Max. length for the printbox id. ;AN000; + ;; ASCIIZ string ;AN000; +NB_FREE_BYTES DW ? ;; Number of bytes available in our ;AN000; + ;; resident segment ;AN000; +RESIDENT_SHARED_DATA_SIZE DW ? ;; Size in bytes of the RESIDENT Shared ;AN000; + ;; data area (if GRAPHICS already ;AN000; + ;; installed). ;AN000; +END_OF_RESIDENT_CODE DW ? ;; Offset of the end of the code that ;AN000; + ;; has to be made resident. ;AN000; +TEMP_SHARED_DATA_PTR DW ? ;; Offset of the temporary Shared area ;AN000; + ;; ;AN000; +ERROR_DEVICE DW STDERR ;; Device DISP_ERROR will output ;AN000; + ;; messages to (STDERR or STDOUT) ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; GRAPHICS_INSTALL : INSTALL GRAPHICS.COM ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: Command line parameters ;AN000; +; GRAPHICS profile - A file describing printer characteristics and ;AN000; +; attributes. ;AN000; +; ;AN000; +; OUTPUT: If first time invoked: ;AN000; +; INT 5 VECTOR and INT 2FH VECTOR are replaced; only the required ;AN000; +; code for printing the screen is made resident. ;AN000; +; else, ;AN000; +; The resident code is updated to reflect changes in printing ;AN000; +; options. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; DESCRIPTION: ;AN000; +;; ;AN000; +;; This module intalls GRAPHICS code and data. ;AN000; +;; ;AN000; +;; An INT 2FH driver is also installed. ;AN000; +;; ;AN000; +;; If this driver is already present then, we assume GRAPHICS was installed ;AN000; +;; and do not install it again but, simply update the resident code. ;AN000; +;; ;AN000; +;; The resident code contains ONLY the code and data needed for Printing ;AN000; +;; the screen. The code needed is determined according to the command line ;AN000; +;; parameters and the information extracted from the printer profile. ;AN000; +;; ;AN000; +;; The printer profile is parsed according to the current hardware setting ;AN000; +;; and also to the command line options. The information extracted from ;AN000; +;; the profile is stored in a Data area shared between the installation ;AN000; +;; process and the Print Screen process. ;AN000; +;; ;AN000; +;; A temporary Shared Data Area is FIRST built at the end of the .COM file ;AN000; +;; Before building it, we verify that there is ;AN000; +;; enough memory left in the current segment. If not, the installation ;AN000; +;; process is aborted. ;AN000; +;; ;AN000; +;; This temporary Data area when completed will be copied over the ;AN000; +;; installation code. Therefore, the file comprising GRAPHICS must be ;AN000; +;; linked in a specific order with the installation modules being last. ;AN000; +;; ;AN000; +;; These modules will be overwritten by the Shared Data area and the EGA ;AN000; +;; dynamic save area before we exit and stay resident. ;AN000; +;; ;AN000; +;; The end of the resident code is the end of the Shared Data area, anything ;AN000; +;; else beyond that is not made resident. ;AN000; +;; ;AN000; +;; The pointer to the resident Shared Data area is declared within the ;AN000; +;; Interrupt 2Fh driver. This pointer is initialized by the installation ;AN000; +;; process and points to the shared data area at Print Screen time. ;AN000; +;; ;AN000; +;; Depending on the type of printer attached (i.e., Black and white or Color) ;AN000; +;; only one set of modules is made resident during the installation. ;AN000; +;; ;AN000; +;; The set of print modules required is copied over the previous one at ;AN000; +;; location "PRINT_MODULE_START". This location is declared within ;AN000; +;; GRCOLPRT which must be linked before GRBWPRT ;AN000; +;; ;AN000; +;; When copying one of the 2 sets of print modules we reserve enough space ;AN000; +;; for the larger of them. Therefore, if GRAPHICS is already installed but ;AN000; +;; is reinvoked with a different printer type which needs a bigger set of ;AN000; +;; modules: this new set of modules is simply recopied over the existing ;AN000; +;; one in the resident code. ;AN000; +;; ;AN000; +;; The Shared Data area is copied rigth after the set of modules that we keep ;AN000; +;; that is, over the unused set of modules. ;AN000; +;; ;AN000; +;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Register Conventions: ;AN000; +;; BP - points to start of Temp Shared Data (Transiant code) ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; Entry point for GRAPHICS command processing. ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; INT 2FH, LOAD_MESSAGES, LOAD_PROFILE, PARSE_PARMS ;AN000; +;; CHAIN_INTERRUPTS, COPY_SHARED_DATA, DISPLAY_MESSAGE ;AN000; +;; COPY_PRINT_MODULES ;AN000; +;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; LOGIC: ;AN000; +;; Load the message retriever ;AN000; +;; IF carry flag is set (incorrect DOS version) THEN ;AN000; +;; Issue message (COMMON1) ;AN000; +;; Exit ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;; Get number of bytes available in the segment from PSP (word 6) ;AN000; +;; /* This is needed since we construct a temporary Shared data area at the ;AN000; +;; of the .COM file */ ;AN000; +;; ;AN000; +;; /* Build Shared Data in temporary area */ ;AN000; +;; END_OF_RESIDENT_CODE := (end of .COM file) ;AN000; +;; NB_FREE_BYTES := Number of bytes availables ;AN000; +;; ;AN000; +;; CALL PARSE_PARMS ;AN000; +;; IF error THEN /* PARSE_PARMS will issue messages */ ;AN000; +;; Exit ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;; CALL LOAD_PROFILE ;AN000; +;; IF profile errors THEN ;AN000; +;; Exit /* LOAD_PROFILE will issue messages */ ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;; Issue INT 2FH Install Check call (AX=1500H) ;AN000; +;; /* INT 2FH returns ES:[DI] pointing to the shared data area */ ;AN000; +;; IF already installed THEN ;AN000; +;; THEN ;AN000; +;; Move NO to PRINT_SCREEN_ALLOWED in resident Shared Data ;AN000; +;; SHARED_DATA_AREA_PTR := DI ;AN000; +;; ELSE ;AN000; +;; MOV PRINT_SCREEN_ALLOWED,NO ;AN000; +;; CALL CHAIN_INTERRUPTS /* Install INT 5 and INT 2FH vectors */ ;AN000; +;; ES := Our segment ;AN000; +;; ENDIF ;AN000; +;; /* Keep only Print Black and White or Print Color: */ ;AN000; +;; CALL COPY_PRINT_MODULES ;AN000; +;; /* COPY_SHARED_DATA will terminate & stay resident */ ;AN000; +;; Set up registers for copy & terminate call ;AN000; +;; /* reserve enough memory to handle any printer in the profile*/ ;AN000; +;; jump to COPY_SHARED_DATA module ;AN000; +;; ELSE ;AN000; +;; /* Shared Data has been built in place */ ;AN000; +;; move YES to PRINT_SCREEN_ALLOWED ;AN000; +;; Return to DOS ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +GRAPHICS_INSTALL PROC NEAR ; ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Load the error messages ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL SYSLOADMSG ; Load messages ;AN000; + .IF C ; If error when loading messages ;AN000; + .THEN ; then, ;AN000; + MOV CX,0 ; CX := No substitution in message ;AN000; + MOV AX,1 ; AX := msg nb. for "Invalid DOS version" ;AN000; + CALL DISP_ERROR ; Display error message ;AN000; + JMP ERROR_EXIT ; and quit ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get offset of where to build the TEMPORARY Shared Data area (always built) ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV BP,OFFSET LIMIT ; Build it at the end of this .COM file ;AN000; + ; (LIMIT = the offset of the last byte ;AN000; + ; of the last .OBJ file linked with ;AN000; + ; GRAPHICS) ;AN000; + MOV TEMP_SHARED_DATA_PTR,BP ; ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Determine if GRAPHICS is already installed; get the resident segment value ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AH,PRT_SCR_2FH_NUMBER ; Call INT 2FH (the Multiplex interrupt) ;AN000; + XOR AL,AL ; for Print Screen handler ;AN000; + INT 2FH ; ;AN000; + ;AN000; + .IF ; IF already installed ;AN000; + .THEN ; then, ;AN000; + ;----------------------------------------------------------------------------;AN000; + ; GRAPHICS is already installed: Get pointer to the EXISTING Shared Data area;AN000; + ;----------------------------------------------------------------------------;AN000; + MOV INSTALLED,YES ; Say it's installed ;AN000; + MOV AX,ES ; Get the segment and offset of the ;AN000; + MOV SHARED_DATA_AREA_PTR,DI; resident Shared Data area. ;AN000; + MOV RESIDENT_CODE_SEG,AX ; (returned in ES:DI) ;AN000; + ; Disable print screen because we will ;AN000; + MOV ES:PRINT_SCREEN_ALLOWED,NO ; be updating the resident code. ;AN000; + .ELSE ; ELSE, not installed: ;AN000; + ;------------------------------------------------------------------------ ;AN000; + ; GRAPHICS is NOT installed: RESIDENT shared data area is in OUR segment ;AN000; + ;------------------------------------------------------------------------ ;AN000; + PUSH CS ; The Shared Data area will be in our ;AN000; + POP RESIDENT_CODE_SEG ; segment. ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Determine in AX how many bytes are available for building the TEMPORARY SHARED;AN000; +; DATA AREA: ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,ES:BYTES_AVAIL_PSP_OFF;AX := Number of bytes availables in ;AN000; + ; the current segment (as indicated in PSP);AN000; + .IF > ; If there is no bytes available past ;AN000; + .THEN ; the end of our .COM file ;AN000; + XOR AX,AX ; then, AX := 0 bytes available ;AN000; + .ELSE ; ;AN000; + SUB AX,OFFSET LIMIT ; else, AX := Number of FREE bytes ;AN000; + .ENDIF ; in this segment ;AN000; + ;AN000; +;---AX = Number of bytes in our segment available for building the Temp Shared ;AN000; +;---data area. ;AN000; +;---IF ALREADY INSTALLED: Get the size of the existing Shared data area. ;AN000; +;---Since the temporary shared data area will be copied over the resident ;AN000; +;---shared data area, we do not want to build it any bigger than the one ;AN000; +;---it will overwrite. Therefore we do not give to LOAD_PROFILE more space ;AN000; +;---than the size of the existing Shared data area. ;AN000; + .IF ; If already installed then, ;AN000; + .THEN ;AN000; + PUSH CS:RESIDENT_CODE_SEG ; ES:[DI] := Resident Shared data area ;AN000; + POP ES ; ;AN000; + MOV DI,SHARED_DATA_AREA_PTR ; ;AN000; + MOV CX,ES:[DI].SD_TOTAL_SIZE ; CX := Size of the existing Shared area ;AN000; + MOV RESIDENT_SHARED_DATA_SIZE,CX ; Save size for LOAD_PROFILE ;AN000; + .IF ; If AX > size of existing SDA ;AN000; + MOV AX,CX ; then, AX := Size of existing Shared area ;AN000; + .ENDIF ; ;AN000; + .ENDIF ;AN000; + ; NB_FREE_BYTES := Number of bytes ;AN000; + MOV NB_FREE_BYTES,AX ; available for ;AN000; + ; building the TEMPORARY shared area ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Parse the command line parameters ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV BYTE PTR CS:[BP].SWITCHES,0 ; Init. the command line switches ;AN000; + PUSH CS ; Set ES to segment containing the PSP ;AN000; + POP ES ;AN000; + CALL PARSE_PARMS ; Set switches in the Temp. Shared Area ;AN000; + .IF C ; If error when parsing the command ;AN000; + .THEN ; line then, EXIT ;AN000; + JMP ERROR_EXIT ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Parse the printer profile - Build the temporary Shared data area ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL LOAD_PROFILE ; Builds profile info in Temporary Shared ;AN000; + ; Data ;AN000; + .IF C ; If error when loading the profile ;AN000; + .THEN ; then, EXIT ;AN000; + JMP ERROR_EXIT ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Check if /B was specified with a BLACK and WHITE printer:(invalid combination);AN000; +;-------------------------------------------------------------------------------;AN000; + .IF AND ;AN000; + .IF ;AN000; + .THEN ;AN000; + MOV AX,INVALID_B_SWITCH ; Error := /B invalid with B&W prt. ;AN000; + MOV CX,0 ; No substitution ;AN000; + CALL DISP_ERROR ; Display error message ;AN000; + JMP ERROR_EXIT ; and quit ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; RELOCATE THE TEMPORARY SHARED DATA AREA AND THE SET OF REQUIRED PRINT MODULES ;AN000; +; ;AN000; +; (Discard the set of print modules not needed with the printer attached and ;AN000; +; discard all the code not used at print screen time). ;AN000; +; ;AN000; +; If GRAPHICS is already installed then, we copy the ;AN000; +; Shared Data area and the print modules over the previous ones installed in ;AN000; +; resident memory. ;AN000; +; ;AN000; +; If we are installed for the first time then, we copy those over the ;AN000; +; installation modules before we exit and stay resident. ;AN000; +; ;AN000; +; A temporaty Shared Data area is always created even if a resident one ;AN000; +; already exist (it is then, copied over), a set of print modules is recopied ;AN000; +; only if needed. ;AN000; +; ;AN000; +; NOTE: END_OF_RESIDENT_CODE points to the first location over which code ;AN000; +; may be relocated. After data or code is relocated, END_OF_RESIDENT_CODE;AN000; +; is updated and points to the next available location for copying code ;AN000; +; that will stay resident. ;AN000; +;-------------------------------------------------------------------------------;AN000; +;-------------------------------------------------------------------------------;AN000; +; Initialize the pointer to the next available location for resident code: ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If not installed ;AN000; + .THEN ; then, ;AN000; + MOV END_OF_RESIDENT_CODE,OFFSET PRINT_MODULE_START ;AN000; + .ENDIF ; we make everything up to the print ;AN000; + ; modules resident code. ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Keep only the set of print modules that is needed: ;AN000; +;-------------------------------------------------------------------------------;AN000; + CALL COPY_PRINT_MODULES ; Updates END_OF_RESIDENT_CODE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Replace the interrupt vectors and install the EGA dynamic area (if needed) ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If not already installed ;AN000; + .THEN ; then, ;AN000; +;------Release evironment vector ;AN002; + CALL RELEASE_ENVIRONMENT ; release unneeded environment vector ;AN002; +;------Replace the interrupt vectors ;AN000; + MOV PRINT_SCREEN_ALLOWED,NO ; Disable Print Screen ;AN000; + CALL CHAIN_INTERRUPTS ; Replace the interrupt vectors ;AN000; + ; (END_OF_RESIDENT_CODE is updated) ;AN000; + CALL DET_HW_CONFIG ; Find what display adapter we got ;AN000; + .IF ;If EGA is present ;AN000; + .THEN ; then, ;AN000; + CALL INST_EGA_SAVE_AREA ; Install the EGA dynamic save area ;AN000; + .ENDIF ; (END_OF_RESIDENT_CODE is updated) ;AN000; +;------Calculate the size of the resident code ;AN000; + MOV DX,END_OF_RESIDENT_CODE ; DX := End of resident code ;AN000; + ADD DX,CS:[BP].SD_TOTAL_SIZE; Add size of Shared Data area ;AN000; + MOV CL,4 ; ;AN000; + SHR DX,CL ; convert to paragraphs ;AN000; + INC DX ; and add 1 ;AN000; +;------Set AX to DOS exit function call - (COPY_SHARED_DATA will exit to DOS) ;AN000; + MOV AH,31H ; Function call to terminate but stay ;AN000; + XOR AL,AL ; resident ;AN000; + .ELSE ;AN000; + MOV AH,4CH ; Function call to terminate ;AN000; + XOR AL,AL ; (EXIT to calling process) ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Copy the temporary shared data area in the resident code ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CX,CS:[BP].SD_TOTAL_SIZE; CX := MOVSB count for COPY_SHARED_DATA ;AN000; + MOV SI,BP ; DS:SI := Temporary Shared data area ;AN000; + PUSH RESIDENT_CODE_SEG ; ES:DI := Resident Shared data area: ;AN000; + POP ES ; ;AN000; + .IF ; If not installed ;AN000; + .THEN ; then, ;AN000; + MOV DI,END_OF_RESIDENT_CODE; DI := End of resident code ;AN000; + MOV BP,DI ; BP := New resident Shared data area ;AN000; + MOV SHARED_DATA_AREA_PTR,DI; Update pointer to resident Shar. area ;AN000; + .ELSE ; else, ;AN000; + MOV DI,SHARED_DATA_AREA_PTR ; DI := Existing Shared data area ;AN000; + MOV BP,DI ; BP = DI:= Existing Shared data area ;AN000; + .ENDIF ;AN000; + JMP COPY_SHARED_DATA ; Jump to proc that copies area in new ;AN000; + ; part of memory and exits to DOS ;AN000; +ERROR_EXIT: ;AN000; + .IF ; If we are already installed, re-enable ;AN000; + MOV ES,RESIDENT_CODE_SEG ; print screens ;AN000; + MOV ES:PRINT_SCREEN_ALLOWED,YES ;AN000; + .ENDIF ; ;AN000; + ; ;AN000; + MOV AH,4CH ; Function call to terminate ;AN000; + MOV AL,1 ; (EXIT to calling process) ;AN000; + INT 21H ;AN000; +GRAPHICS_INSTALL ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; INST_EGA_SAVE_AREA : INSTALL A DYNAMIC SAVE AREA FOR THE EGA PALETTE REGISTERS;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: DS = Data segment for our code ;AN000; +; END_OF_RESIDENT_CODE = Offset of the end of the resident code ;AN000; +; ;AN000; +; OUTPUT: END_OF_RESIDENT_CODE is updated to point to the end of the code ;AN000; +; that will stay resident. ;AN000; +; SAVE_AREA_PTR in BIOS segment is updated. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Shared Data Area ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ************* The EGA Dynamic Save Area will be built over top ;AN000; +;; ** NOTE ** of the profile loading modules (file GRLOAD.ASM) ;AN000; +;; ************* to avoid having to relocate this area just before ;AN000; +;; terminating. This is safe since the maximum memory used is ;AN000; +;; 288 bytes and the profile loading modules are MUCH larger than ;AN000; +;; this. So GRLOAD.ASM MUST be linked before GRINST.ASM and after ;AN000; +;; GRPRINT.ASM. ;AN000; +;; ;AN000; +;; BIOS will update the dynamic save area whenener it's aware the palette ;AN000; +;; registers have been updated. ;AN000; +;; ;AN000; +;; BIOS 4A8H BIOS SAVE EGA DYNAMIC ;AN000; +;; POINTER: POINTER TABLE SAVE AREA ;AN000; +;; ÚÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ (16 first bytes are the 16 ;AN000; +;; ³ *ÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄ>³ ³ EGA palette registers) ;AN000; +;; ÀÄÄÄÄÄÄÄÄÙ ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ ;AN000; +;; ³ *ÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ>ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ . ;AN000; +;; ³ ³ . ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ . 256 bytes ;AN000; +;; ³ ³ . ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ . ;AN000; +;; ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ÃÄÄÄÄÄÄÄÄÄÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ;AN000; +;; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÙ ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; GRAPHICS_INSTALL ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; IF EGA Dynamic Save Area NOT established THEN ;AN000; +;; /* Required since default table is in ROM */ ;AN000; +;; IF Save Table is in ROM ;AN000; +;; Replicate all the Save Area Table in resident RAM just before ;AN000; +;; the Shared Data Area ;AN000; +;; ENDIF ;AN000; +;; Allocate 256 bytes for EGA Dynamic Save Area just before the ;AN000; +;; Shared Data Area ;AN000; +;; Update END_OF_RESIDENT_CODE ;AN000; +;; ENDIF ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +BIOS_SAVE_PTR EQU 4A8H ;; Offset of the BIOS Save Ptr area ;AN000; +SAVE_AREA_LEN EQU 8*4 ;; There are 8 pointers in the Save area ;AN000; +EGA_DYNAMIC_LEN EQU 256 ;; Length of the EGA dynamic save area ;AN000; +; Standard default colours for the Enhanced Graphics Adapter: (rgbRGB values) ;AN000; +; The following table is necessary in order to initialize the EGA DYNAMIC ;AN000; +; SAVE AREA when creating it. ;AN000; +EGA_DEFAULT_COLORS DB 00h ;; Black ;AN000; + DB 01h ;; Blue ;AN000; + DB 02h ;; Green ;AN000; + DB 03h ;; Cyan ;AN000; + DB 04h ;; Red ;AN000; + DB 05h ;; Magenta ;AN000; + DB 14h ;; Brown ;AN000; + DB 07h ;; White ;AN000; + DB 38h ;; Dark Grey ;AN000; + DB 39h ;; Light Blue ;AN000; + DB 3Ah ;; Light Green ;AN000; + DB 3Bh ;; Light Cyan ;AN000; + DB 3Ch ;; Light Red ;AN000; + DB 3Dh ;; Light Magenta ;AN000; + DB 3Eh ;; Yellow ;AN000; + DB 3Fh ;; Bright white ;AN000; + DB 00h ;; OVERSCAN register ;AN000; + ;AN000; +INST_EGA_SAVE_AREA PROC NEAR ;AN000; +PUSH AX ;AN000; +PUSH CX ;AN000; +PUSH DX ;AN000; +PUSH SI ;AN000; +PUSH DI ;AN000; +PUSH ES ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get the BIOS save pointer table ;AN000; +;-------------------------------------------------------------------------------;AN000; +XOR AX,AX ; ES := segment 0 ;AN000; +MOV ES,AX ;AN000; +LES SI,ES:DWORD PTR BIOS_SAVE_PTR ; ES:[SI] =Current BIOS save table ;AN000; +.IF < EQ 0> AND ; IF the dynamic save are pointer is ;AN000; +.IF < EQ 0> ; null then, it's not defined ;AN000; +.THEN ; and we have to define it: ;AN000; + ;---------------------------------------------------------------------------;AN000; + ; The Dynamic EGA save area is NOT DEFINED: ;AN000; + ;---------------------------------------------------------------------------;AN000; + MOV BYTE PTR ES:[SI]+4,0FFH ; Try to write a byte in the table ;AN000; + PUSH AX ; (PUSH AX, POP AX used to create a ;AN000; + POP AX ; small delay) ;AN000; + .IF < NE 0FFH>;If we can't read our byte back then, ;AN000; + .THEN ; the Save Ptrs table is in ROM ;AN000; + ;------------------------------------------------------------------------;AN000; + ; The Save pointer table is in ROM; ;AN000; + ; Copy the BIOS save pointer table from ROM to within our .COM file ;AN000; + ;------------------------------------------------------------------------;AN000; + PUSH ES ; DS:SI := Offset of BIOS save ptrs table ;AN000; + POP DS ; ;AN000; + PUSH CS ; ES:DI := The next available location ;AN000; + POP ES ; for installing resident code ;AN000; + MOV DI,CS:END_OF_RESIDENT_CODE ; within our .COM file ;AN000; + MOV CS:OUR_SAVE_TAB_OFF,DI ; ;AN000; + MOV CX,SAVE_AREA_LEN ; CX := Length of the table to copy ;AN000; + REP MOVSB ; Replicate the Save Table ;AN000; + PUSH CS ;AN000; + POP DS ; Reestablish our data segment ;AN000; + ;------------------------------------------------------------------------;AN000; + ; Adjust END_OF_RESIDENT_CODE to the next offset available for copying ;AN000; + ; resident code and data. ;AN000; + ;------------------------------------------------------------------------;AN000; + ADD END_OF_RESIDENT_CODE,SAVE_AREA_LEN ;AN000; + ;------------------------------------------------------------------------;AN000; + ; Set the pointer in OUR Save ptr table to our EGA dynamic save area ;AN000; + ; which we create right after the Save pointer table. ;AN000; + ;------------------------------------------------------------------------;AN000; + MOV DI,OUR_SAVE_TAB_OFF ; DS:[DI] := Our BIOS save ptr tab ;AN000; + MOV AX,END_OF_RESIDENT_CODE; Store its offset ;AN000; + MOV DS:[DI]+4,AX ; ;AN000; + MOV WORD PTR DS:[DI]+6,DS ; Store its segment ;AN000; + ;------------------------------------------------------------------------;AN000; + ; Initialize our DYNAMIC SAVE AREA with the 16 standard EGA colors ;AN000; + ;------------------------------------------------------------------------;AN000; + ;AN000; + LEA SI,EGA_DEFAULT_COLORS ; DS:[SI] := EGA 16 Default colors ;AN000; + MOV DI,END_OF_RESIDENT_CODE ; ES:[DI] := DYNAMIC SAVE AREA ;AN000; + MOV CX,17 ; CX := Number of colors ;AN000; + REP MOVSB ; Initialize the Dynamic save area ;AN000; + ;------------------------------------------------------------------------;AN000; + ; Set the BIOS Save Pointer to our table of Save pointers: ;AN000; + ;------------------------------------------------------------------------;AN000; + CLI ;AN000; + XOR AX,AX ; ES:BIOS_SAVE_PTR := Our save table: ;AN000; + MOV ES,AX ;AN000; + MOV AX,OUR_SAVE_TAB_OFF ;AN000; + MOV ES:BIOS_SAVE_PTR,AX ;AN000; + MOV ES:BIOS_SAVE_PTR+2,DS ;AN000; + STI ;AN000; + .ELSE ; ELSE save pointer table is in RAM ;AN000; + ;------------------------------------------------------------------------;AN000; + ; ELSE, the BIOS save pointer table is in RAM: ;AN000; + ;------------------------------------------------------------------------;AN000; + ;------------------------------------------------------------------------;AN000; + ; Set the pointer in THEIR Save ptr table to OUR EGA dynamic save area ;AN000; + ;------------------------------------------------------------------------;AN000; + MOV WORD PTR ES:[SI]+6,DS ; ES:[SI] = The existing table in RAM ;AN000; + MOV AX,END_OF_RESIDENT_CODE ;AN000; + MOV ES:[SI]+4,AX ;AN000; + .ENDIF ; ENDIF save pointer table is in ROM ;AN000; + ;-----------------------------------------------------------------------------;AN000; + ; Adjust END_OF_RESIDENT_CODE to the next offset available for copying ;AN000; + ; resident code and data. ;AN000; + ;-----------------------------------------------------------------------------;AN000; + ADD END_OF_RESIDENT_CODE,EGA_DYNAMIC_LEN ;AN000; +.ENDIF ;AN000; +POP ES ;AN000; +POP DI ;AN000; +POP SI ;AN000; +POP DX ;AN000; +POP CX ;AN000; +POP AX ;AN000; + ;AN000; +RET ;AN000; +OUR_SAVE_TAB_OFF DW ? ;AN000; +INST_EGA_SAVE_AREA ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; CHAIN_INTERRUPTS : INSTALL INT 5 AND INT 2FH VECTORS ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: DS = Data segment for our code ;AN000; +; END_OF_RESIDENT_CODE = Offset of the end of the resident code ;AN000; +; ;AN000; +; OUTPUT: OLD_INT_2FH (within INT_2FH_DRIVER) ;AN000; +; BIOS_INT_5H (within PRT_SCR module) ;AN000; +; END_OF_RESIDENT_CODE is updated to point to the end of the code ;AN000; +; that will stay resident. ;AN000; +; SAVE_AREA_PTR in BIOS segment is updated if an EGA adapter is found ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Shared Data Area ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Install Interrupts 5 and 2FH. The old vectors are saved. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; GRAPHICS_INSTALL ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; DOS INT 21H Replace vector AH=25h ;AN000; +;; DOS INT 21H Get vector AH=35h ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; Save interrupt 5 vector in BIOS_INT_5H ;AN000; +;; Point interrupt 5 to PRT_SCR module ;AN000; +;; Save interrupt 2FH vector in BIOS_INT_2FH ;AN000; +;; Point interrupt 2FH to INT_2FH_DRIVER module ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +CHAIN_INTERRUPTS PROC NEAR ;; ;AN000; + PUSH ES ;AN000; + PUSH BX ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Replace INTERRUPT 5 vector ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AH,35H ; Get vector for ;AN000; + MOV AL,5 ; interrupt 5 request ;AN000; + INT 21H ; Call DOS ;AN000; + ;AN000; + MOV BIOS_INT_5H,BX ; Save the old vector ;AN000; + MOV BIOS_INT_5H+2,ES ;AN000; + ;AN000; + MOV DX,OFFSET PRT_SCR ; DS:DX := Offset of our Print Screen ;AN000; + ;AN000; + MOV AH,25H ; Replace vector for ;AN000; + MOV AL,5 ; interrupt 5 request ;AN000; + INT 21H ; Call DOS ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Replace INTERRUPT 2FH vector ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AH,35H ; Get vector for ;AN000; + MOV AL,2FH ; interrupt 2FH request ;AN000; + INT 21H ; Call DOS ;AN000; + ;AN000; + MOV WORD PTR OLD_INT_2FH,BX ; Save the old vector ;AN000; + MOV WORD PTR OLD_INT_2FH+2,ES ;AN000; + ;AN000; + MOV DX,OFFSET INT_2FH_DRIVER; DS:DX := Offset of our 2FH handler ;AN000; + ;AN000; + MOV AH,25H ; Replace vector for ;AN000; + MOV AL,2FH ; interrupt 2FH request ;AN000; + INT 21H ; Call DOS ;AN000; + ;AN000; + POP BX ;AN000; + POP ES ;AN000; + RET ;AN000; +CHAIN_INTERRUPTS ENDP ;AN000; + ;AN000; +;===============================================================================;AN000; +; ;AN000; +; COPY_PRINT_MODULES: COPY THE SET OF PRINT MODULES NEEDED OVER THE PREVIOUS ONE;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the temporary Shared Data area ;AN000; +; END_OF_RESIDENT_CODE = Location of the set of COLOR modules ;AN000; +; (if first time installed) ;AN000; +; CS:[BP].PRINTER_TYPE = Printer type NEEDED ;AN000; +; RESIDENT_CODE_SEG = Segment containing the resident code ;AN000; +; ;AN000; +; OUTPUT: END_OF_RESIDENT_CODE = End of the print modules IS UPDATED ;AN000; +; (If first time installed) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Control Variables ;AN000; +;; Shared Data Area ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; This module trashes one set of print modules (Color or Black & White) ;AN000; +;; depending on the type of printer attached. Since the Shared Data ;AN000; +;; (resident version) will reside immediately after the print modules, ;AN000; +;; END_OF_RESIDENT_CODE will be set by this modules. ;AN000; +;; ;AN000; +;; The set of COLOR modules is already at the rigth located when installing ;AN000; +;; GRAPHICS for the first time. This is true since, the color modules are ;AN000; +;; linked before the black and white modules. ;AN000; +;; ;AN000; +;; Therefore, if we are installing GRAPHICS for the first time and we need ;AN000; +;; the color modules then, we do not need to relocate any print modules. ;AN000; +;; ;AN000; +;; When installing GRAPHICS again we first check what is the resident set, ;AN000; +;; we recopy a new set only if needed. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; GRAPHICS_INSTALL ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; IF color printer THEN ;AN000; +;; SI := Offset of BW_PRINT_MODULES ;AN000; +;; ELSE ;AN000; +;; SI := Offset of COLOR_PRINT_MODULES ;AN000; +;; ENDIF ;AN000; +;; REP MOVSB ; Copy the set of modules ;AN000; +;; END_OF_RESIDENT_CODE := end of the set of modules ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +COPY_PRINT_MODULES PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH ES ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Determine if we need to relocate the set of print modules, if so, set the ;AN000; +; source address (DS:SI), the destination address (ES:DI) and the number of ;AN000; +; bytes to copy (CX). ;AN000; +;-------------------------------------------------------------------------------;AN000; + PUSH CS:RESIDENT_CODE_SEG ; ES := Segment containing the resident ;AN000; + POP ES ; code (Where to copy modules) ;AN000; + MOV DI,OFFSET PRINT_MODULE_START ; ES:[DI] := Resident print modules ;AN000; + ;AN000; + .IF ; IF not installed ;AN000; + .THEN ; THEN, ;AN000; + ; We relocate the print modules ;AN000; + ; at the end of the resident code: ;AN000; + ; (this is where the color set is) ;AN000; + .IF ; IF we don't want the color set ;AN000; + .THEN ; THEN, ;AN000; + MOV NEED_NEW_PRINT_MODULES,YES ; Say we need new modules ;AN000; + MOV SI,OFFSET PRINT_BW_APA ; DS:[SI] := Black and white modules;AN000; + MOV CX,LEN_OF_BW_MODULES ; CX := Length of B&W modules ;AN000; + .ENDIF ; ;AN000; + ;AN000; + .ELSE ; ELSE, (We are already installed) ;AN000; + MOV BX,SHARED_DATA_AREA_PTR ; BX := Offset of Shared Data area ;AN000; + MOV AL,ES:[BX].PRINTER_TYPE ; AL := Type of the resident set ;AN000; + .IF ; IF resident set is not the one ;AN000; + .THEN ; we need THEN, ;AN000; + MOV NEED_NEW_PRINT_MODULES,YES ; Say we need a new set. ;AN000; + .IF ; IF its color we need then, ;AN000; + MOV SI,OFFSET PRINT_COLOR ; DS:[SI] := Color set ;AN000; + MOV CX,LEN_OF_COLOR_MODULES ; CX := Length of color mod. ;AN000; + .ELSE ; ELSE ;AN000; + MOV SI,OFFSET PRINT_BW_APA ; DS:[SI] := B&W set ;AN000; + MOV CX,LEN_OF_BW_MODULES ; CX := Length of B&W mod. ;AN000; + .ENDIF ; ENDIF we need the color set ;AN000; + .ENDIF ; ENDIF we need a new set ;AN000; + .ENDIF ; ENDIF we are not installed ;AN000; + ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; If needed: Copy the required set of print modules ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ;AN000; + .THEN ;AN000; + CLD ; Clear the direction flag ;AN000; + REP MOVSB ; Copy the set of print modules ;AN000; + .ENDIF ; ENDIF needs to copy the print modules ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set END_OF_RESIDENT_CODE pointer to the end of the print modules: ;AN000; +; (Reserve enough space to store the larger set of modules on a ;AN000; +; subsequent install) ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; IF first time installed ;AN000; + .THEN ; THEN, ;AN000; + MOV CX,LEN_OF_COLOR_MODULES ; Adjust END_OF_RESIDENT_CODE to ;AN000; + .IF ; contains the larger set of modules. ;AN000; + .THEN ; ;AN000; + ADD END_OF_RESIDENT_CODE,LEN_OF_COLOR_MODULES ;AN000; + .ELSE ;AN000; + ADD END_OF_RESIDENT_CODE,LEN_OF_BW_MODULES ;AN000; + .ENDIF ; ;AN000; + .ENDIF ;AN000; + ;AN000; + POP ES ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +NEED_NEW_PRINT_MODULES DB NO ; True if print modules needed must be ;AN000; + ; copied over the other set of print ;AN000; + ; modules ;AN000; +COPY_PRINT_MODULES ENDP ;AN000; + ;AN002; +PAGE ;AN002; +;===============================================================================;AN002; +; ;AN002; +; PROCEDURE_NAME: RELEASE_ENVIRONMENT ;AN002; +; ;AN002; +; INPUT: None. ;AN002; +; ;AN002; +; OUTPUT: Environment vector released. ;AN002; +; ;AN002; +;-------------------------------------------------------------------------------;AN002; +RELEASE_ENVIRONMENT PROC NEAR ;AN002; + PUSH AX ; save regs ;AN002; + PUSH BX ;AN002; + PUSH ES ;AN002; + MOV AH,62H ; function for get the PSP segment ;AN002; + INT 21H ; invoke INT 21h ;AN002; + MOV ES,BX ; BX contains PSP segment - put in ES ;AN002; + MOV BX,WORD PTR ES:[2CH] ; get segment of environmental vector ;AN002; + MOV ES,BX ; place segment in ES for Free Memory ;AN002; + MOV AH,49H ; Free Allocated Memory function call ;AN002; + INT 21H ; invoke INT 21h ;AN002; + POP ES ; restore regs ;AN002; + POP BX ;AN002; + POP AX ;AN002; + RET ;AN002; +RELEASE_ENVIRONMENT ENDP ;AN002; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: DISP_ERROR ;AN000; +; ;AN000; +; INPUT: AX := GRAPHICS message number (documented in GRMSG.EQU) ;AN000; +; CX := Number of substitutions (Needed by SYSDISPMSG) ;AN000; +; DS:[SI] := Substitution list (needed only if CX <> 0) ;AN000; +; ;AN000; +; OUTPUT: Error message is displayed on STANDARD ERROR OUTPUT (STDERR) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +DISP_ERROR PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH DI ;AN000; + PUSH SI ;AN000; + PUSH BP ;AN000; + ;AN000; + MOV BX,ERROR_DEVICE ; Issue message to standard error ;AN000; + XOR DL,DL ; No input ;AN000; + MOV DH,UTILITY_MSG_CLASS;It's one of our messages ;AN000; + CALL SYSDISPMSG ; display error message ;AN000; + ;AN000; + POP BP ;AN000; + POP SI ;AN000; + POP DI ;AN000; + POP BX ;AN000; + RET ;AN000; +DISP_ERROR ENDP ;AN000; + +include msgdcl.inc ;AN000; + ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRINST.EXT b/v4.0/src/CMD/GRAPHICS/GRINST.EXT new file mode 100644 index 0000000..75b8137 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRINST.EXT @@ -0,0 +1,43 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINST.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRINIT.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN GRAPHICS_INSTALL:NEAR ;; ;AN000; + EXTRN SYSDISPMSG:NEAR ;; ;AN000; + EXTRN DISP_ERROR:NEAR ;; ;AN000; + EXTRN TEMP_SHARED_DATA_PTR:WORD ;; ;AN000; + ;; ;AN000; + EXTRN PRINTER_TYPE_PARM:BYTE ;; ;AN000; + EXTRN PRINTER_TYPE_LENGTH:BYTE ;; ;AN000; + EXTRN INSTALLED:BYTE ;; ;AN000; + EXTRN PROFILE_PATH:BYTE ;; ;AN000; + EXTRN PRINTBOX_ID_PTR:WORD ;; ;AN000; + EXTRN PRINTBOX_ID_LENGTH:BYTE ;; ;AN000; + EXTRN DEFAULT_BOX:BYTE ;; ;AN000; + EXTRN LCD_BOX:BYTE ;; ;AN000; + EXTRN ERROR_DEVICE:WORD ;; ;AN000; + ;; ;AN000; + EXTRN STDERR:ABS ;; ;AN000; + EXTRN STDOUT:ABS ;; ;AN000; + ;; ;AN000; + EXTRN NB_FREE_BYTES:WORD ;; ;AN000; + EXTRN RESIDENT_SHARED_DATA_SIZE:WORD;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRINT2FH.ASM b/v4.0/src/CMD/GRAPHICS/GRINT2FH.ASM new file mode 100644 index 0000000..b195c25 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRINT2FH.ASM @@ -0,0 +1,146 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Interrupt 2FH Driver ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINT2FH.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the Interrupt 2FH driver. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; INT_2FH_DRIVER - Interrupt 2FH driver ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRLOAD.EXT - Externals for profile load ;AN000; +;; GRCTRL.EXT - Externals for print screen control ;AN000; +;; GRPRINT.EXT - Externals for print modules ;AN000; +;; GRCPSD.EXT - Externals for COPY_SHARED_DATA module ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; Calls next Int 2FH handler in the chain. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; + PUBLIC OLD_INT_2FH ;; ;AN000; + PUBLIC INT_2FH_DRIVER ;; ;AN000; + PUBLIC PRT_SCR_2FH_NUMBER ;; ;AN000; + PUBLIC RESIDENT_CODE_SEG ;; ;AN000; + PUBLIC SHARED_DATA_AREA_PTR ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +.XLIST ;AN000; +INCLUDE STRUC.INC ;AN000; +INCLUDE GRINST.EXT ;AN000; +INCLUDE GRCTRL.EXT ;AN000; +INCLUDE GRCPSD.EXT ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module: INT_2FH_DRIVER ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Respond to GRAPHICS Int 2FH calls. ;AN000; +;; The following calls are handled: ;AN000; +;; ;AN000; +;; AL = 0 ù Install Check ;AN000; +;; ;AN000; +;; Invoked By: ;AN000; +;; INT 2FH instruction. ;AN000; +;; ;AN000; +;; Modules Called: ;AN000; +;; Lower level INT 2FH handlers. ;AN000; +;; ;AN000; +;; Input Registers: ;AN000; +;; Install Check - AH=15H AL=0 ;AN000; +;; ;AN000; +;; ;AN000; +;; Output Registers: ;AN000; +;; Install Check: IF GRAPHICS installed ;AN000; +;; AH=FFH AL=FFH ;AN000; +;; ES : DI points to Shared Data Area ;AN000; +;; ELSE ;AN000; +;; AH=15H AL=0 ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; IF AH=15H THEN ;AN000; +;; IF AL=0 THEN ;AN000; +;; AH,AL := -1 ;AN000; +;; ES : DI := SHARED_DATA_AREA_PTR ;AN000; +;; ENDIF ;AN000; +;; IRET ;AN000; +;; ELSE ;AN000; +;; IF OLD_INT_2FH is a valid pointer THEN ;AN000; +;; Jump to Old Int 2FH ;AN000; +;; ELSE ;AN000; +;; IRET ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +INT_2FH_DRIVER PROC NEAR ;AN000; + JMP INT_2FH ;AN000; +PRT_SCR_2FH_NUMBER EQU 15H ; 2FH Multiplex interrupt number ;AN000; + ; assigned to Print Screen. ;AN000; +OLD_INT_2FH DD ? ; Pointer to next 2FH interrupt handler ;AN000; +RESIDENT_CODE_SEG DW ? ; Segment for installed stuff ;AN000; +SHARED_DATA_AREA_PTR DW ? ; Offset of the start of the ;AN000; + ; Shared Data Area ;AN000; + ;AN000; +INT_2FH: ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Verify if the 2FH Interrupt call is for our interrupt handler: ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF AND;If 2FH call is for us ;AN000; + .IF ; and request is "Get install state" ;AN000; + .THEN ; then, ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Yes: return results ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV DI,CS:SHARED_DATA_AREA_PTR ; ES:DI := Pointer to shared ;AN000; + PUSH CS:RESIDENT_CODE_SEG ; data area ;AN000; + POP ES ; ;AN000; + MOV AH,0FFH ; AL and AH := "We are installed" ;AN000; + MOV AL,AH ; ;AN000; + IRET ; Return to interrupted process ;AN000; +;-------------------------------------------------------------------------------;AN000; +; No, pass control to next 2FH interrupt handler: ;AN000; +;-------------------------------------------------------------------------------;AN000; + .ELSE ; else, this call is not for us: ;AN000; + .IF < NE 0> AND ;if there is another ;AN000; + .IF < NE 0> ; 2FH driver ;AN000; + .THEN ; below us then, ;AN000; + JMP CS:OLD_INT_2FH ; pass control to it ;AN000; + .ELSE ; else, there is nobody to pass ;AN000; + IRET ; control to, just return. ;AN000; + .ENDIF ; END If there is a driver below us.;AN000; + .ENDIF ; END If this call is for us. ;AN000; +INT_2FH_DRIVER ENDP ;AN000; + ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRINT2FH.EXT b/v4.0/src/CMD/GRAPHICS/GRINT2FH.EXT new file mode 100644 index 0000000..54d69c2 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRINT2FH.EXT @@ -0,0 +1,26 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINT2FH.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRINT2FH.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN OLD_INT_2FH:DWORD ;; ;AN000; + EXTRN INT_2FH_DRIVER:NEAR ;; ;AN000; + EXTRN PRT_SCR_2FH_NUMBER:ABS ;; ;AN000; + EXTRN SHARED_DATA_AREA_PTR:WORD ;AN000; + EXTRN RESIDENT_CODE_SEG:WORD ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD.ASM b/v4.0/src/CMD/GRAPHICS/GRLOAD.ASM new file mode 100644 index 0000000..dd16ca4 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD.ASM @@ -0,0 +1,840 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Profile Load Modules ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRLOAD.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the modules used to load the ;AN000; +;; GRAPHICS profile into resident memory. ;AN000; +;; ;AN000; +;; ************* The EGA Dynamic Save Area will be built (by ;AN000; +;; ** NOTE ** CHAIN_INTERRUPTS in file GRINST.ASM) over top of these ;AN000; +;; ************* modules to avoid having to relocate this save just before ;AN000; +;; terminating. This is safe since the maximum memory used is ;AN000; +;; 288 bytes and the profile loading modules are MUCH larger than ;AN000; +;; this. So GRLOAD.ASM MUST be linked before GRINST.ASM and after ;AN000; +;; GRPRINT.ASM. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; PLACID Functional Specifications ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; LOAD_PROFILE - Main module for profile loading ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; ?????????? - Externals for profile loading modules ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; None ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; --------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' BYTE ;; ;AN000; + ;; ;AN000; + INCLUDE STRUC.INC ;; ;AN000; + INCLUDE GRINST.EXT ;; Bring in external declarations ;AN000; + ;; for transient command processing ;AN000; + INCLUDE GRSHAR.STR ;; ;AN000; + INCLUDE GRPARSE.EXT ;; ;AN000; + INCLUDE GRLOAD2.EXT ;; ;AN000; + INCLUDE GRLOAD3.EXT ;; ;AN000; + INCLUDE GRMSG.EQU ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Public Symbols ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + PUBLIC LOAD_PROFILE ;AN000; + PUBLIC GROW_SHARED_DATA ;AN000; + PUBLIC BLOCK_START ;AN000; + PUBLIC BLOCK_END ;AN000; + PUBLIC FIRST_BLOCK ;AN000; + PUBLIC MAX_BLOCK_END ;AN000; + PUBLIC GROUPS_DONE ;AN000; + PUBLIC STMTS_DONE ;AN000; + PUBLIC STMTS_DONE ;AN000; + PUBLIC PTD_FOUND ;AN000; + PUBLIC BUILD_STATE ;AN000; + PUBLIC STMT_ERROR ;AN000; + PUBLIC FILE_ERROR ;AN000; + PUBLIC PARSE_ERROR ;AN000; + PUBLIC END_OF_FILE ;AN000; + PUBLIC MEM_OVERFLOW ;AN000; + PUBLIC STMT_BUFFER ;AN000; + PUBLIC CUR_STMT ;AN000; + PUBLIC PREV_STMT ;AN000; + PUBLIC PRT_BOX_ERROR ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Profile Load Variables ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +NO EQU 0 ;; ;AN000; +YES EQU 1 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; LOAD_PROFILE ;AN000; +;; ;AN000; +;; Input Parameters: ;AN000; +;; DS,ES,SS - points to our transient segment ;AN000; +;; ;AN000; +;; Output Parameters: ;AN000; +;; Temporary Shared Data Area ;AN000; +;; Carry flag set if errors in profile. ;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; Shared Data Area ;AN000; +;; Profile Load Variables ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Build the profile information in the Temporary Shared Data Area. ;AN000; +;; The information will be built for the printer type parsed off ;AN000; +;; the command line. ALL Printer Type Descriptions will be ;AN000; +;; parsed to issue error messages and determine the maximum ;AN000; +;; amount of resident memory required for initial load. ;AN000; +;; The Shared Data Area begins with a fixed length section ;AN000; +;; and then has several variable length sections. PROFILE_BUILD_PTR ;AN000; +;; is used to build the variable length sections by serving ;AN000; +;; as a running pointer to the sections as they are built. ;AN000; +;; ;AN000; +;; Register Usage: ;AN000; +;; BP - points to beginning of Temp Shared Data ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; GRAPHICS_INSTALL ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; PARSE_PRINTER, PARSE_DISPLAYMODE, PARSE_SETUP, PARSE_RESTORE ;AN000; +;; PARSE_PRINTBOX, PARSE_GRAPHICS, PARSE_COLORSELECT, ;AN000; +;; PARSE_COLORPRINT, GET_STATEMENT ;AN000; +;; SYSPARSE ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; IF profile path not specified THEN ;AN000; +;; PROFILE_PATH := "GRAPHICS.PRO" /* Current directory */ ;AN000; +;; Open profile using PROFILE_PATH ;AN000; +;; IF error during open THEN ;AN000; +;; PROFILE_PATH := ARG(V0) with "GRAPHICS.COM" replaced ;AN000; +;; by "GRAPHICS.PRO" ;AN000; +;; Open profile using PROFILE_PATH ;AN000; +;; IF error during open THEN ;AN000; +;; Issue "Cannot find profile" msg ;AN000; +;; Set carry flag ;AN000; +;; RETURN ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ELSE ;AN000; +;; Open profile using specified path ;AN000; +;; IF error during open THEN ;AN000; +;; Issue "Cannot find profile" msg ;AN000; +;; Set carry flag ;AN000; +;; RETURN ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; /* don't start building until we find our printer type*/ ;AN000; +;; PARSE_MODE := NOBUILD ;AN000; +;; MAX_BUILD_PTR := 0 ;AN000; +;; CALL GROW_SHARED_DATA(PROFILE-BUILD_PTR,size of FIXED PART ;AN000; +;; of Shared Data Area) ;AN000; +;; WHILE (not end of file) AND (no I/O error) DO ;AN000; +;; CALL GET_STATEMENT ;AN000; +;; IF I/O error THEN ;AN000; +;; Issue error message ;AN000; +;; ELSE ;AN000; +;; CALL SYSPARSE to parse the statement verb ;AN000; +;; IF verb found THEN ;AN000; +;; IF invalid verb THEN ;AN000; +;; Issue error message ;AN000; +;; PARSE_MODE := ERROR ;AN000; +;; ELSE ;AN000; +;; CASE statement verb ;AN000; +;; PRINTER: ;AN000; +;; CALL PARSE_PRINTER ;AN000; +;; DISPLAYMODE: ;AN000; +;; CALL PARSE_DISPLAYMODE ;AN000; +;; PRINTBOX: ;AN000; +;; CALL PARSE_PRINTBOX ;AN000; +;; SETUP: ;AN000; +;; CALL PARSE_SETUP ;AN000; +;; RESTORE: ;AN000; +;; CALL PARSE_RESTORE ;AN000; +;; GRAPHICS: ;AN000; +;; CALL PARSE_GRAPHICS ;AN000; +;; COLORPRINT: ;AN000; +;; CALL PARSE_COLORPRINT ;AN000; +;; COLORSELECT: ;AN000; +;; CALL PARSE_COLORSELECT ;AN000; +;; ENDCASE ;AN000; +;; IF error on statement THEN ;AN000; +;; IF OVERFLOW bit set in RETURN_CODE THEN ;AN000; +;; Issue "Insufficient memory" message ;AN000; +;; RETURN to caller ;AN000; +;; ELSE ;AN000; +;; IF MISSING bit set in RETURN_CODE THEN ;AN000; +;; Issue "required statement missing" message ;AN000; +;; ENDIF ;AN000; +;; IF INVALID bit set in RETURN_CODE THEN ;AN000; +;; Issue "statement invalid" message ;AN000; +;; ENDIF ;AN000; +;; IF SEQUENCE bit set in RETURN_CODE THEN ;AN000; +;; Issue "out of sequence" message ;AN000; +;; ENDIF ;AN000; +;; display the statement in error ;AN000; +;; ENDIF ;AN000; +;; PARSE_MODE := ERROR ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ENDWHILE ;AN000; +;; ;AN000; +;; /* Check length of last PTD */ ;AN000; +;; IF PROFILE_BUILD_PTR > MAX_BUILD_PTR THEN ;AN000; +;; MAX_BUILD_PTR := PROFILE_BUILD_PTR ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;; /* Make sure all required statements were in previous */ ;AN000; +;; /* Printer Type Description */ ;AN000; +;; /* Must have completed PRINTER, DISPLAYMODE, PRINTBOX and */ ;AN000; +;; /* GRAPHICS statements */ ;AN000; +;; IF PRT+DISP+BOX+GR bits not all set in STMTS_DONE THEN ;AN000; +;; Issue "required statement missing" message ;AN000; +;; Display "END OF FILE." ;AN000; +;; ENDIF ;AN000; +;; ;AN000; +;; IF errors during build THEN ;AN000; +;; set carry flag ;AN000; +;; ELSE ;AN000; +;; SD_TOTAL_SIZE := MAX_BUILD_PTR - TEMP_SHARED_DATA_PTR ;AN000; +;; ENDIF ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +FILE_NOT_FOUND EQU 2 ;; DOS Int21H error codes ;AN000; +PATH_NOT_FOUND EQU 3 ;; ;AN000; + ;; ;AN000; +SUBLIST LABEL BYTE ;; Message substituion list for stmt # ;AN000; + DB 11 ;; sublist size ;AN000; + DB 0 ;; ;AN000; + DW STMT_NUM ;; \ Dword pointer to item ;AN000; +SUBLIST_SEG DW ? ;; / ;AN000; + DB 1 ;; Substitution # ;AN000; +;; Flag format a0sstttt ;; ;AN000; + DB 00100001B ;; Unsigned binary word - left align ;AN000; +;;;; DB 00000000B ;; charcater ;AN000; + DB 0 ;; max field width ;AN000; + DB 1 ;; min width width ;AN000; + DB ' ' ;; pad characeter ;AN000; + ;; ;AN000; +STMT_NUM DW 0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +FILE_ERROR DB 0 ;; Error opening or reading PROFILE ;AN000; +PARSE_ERROR DB 0 ;; Syntax errors in PROFILE ;AN000; +END_OF_FILE DB 0 ;; 1 if end of file ;AN000; +MEM_OVERFLOW DB 0 ;; 1 if insufficient memory ;AN000; + ;; ;AN000; +STMT_ERROR DB 0 ;; Error flag for individual stmt errors ;AN000; +MISSING EQU 1 ;; Required statement missing ;AN000; +INVALID EQU 2 ;; Invalid statement format ;AN000; +SEQUENCE EQU 4 ;; Statement out of sequence ;AN000; + ;; ;AN000; +DEFAULT_PATH DB "GRAPHICS.PRO",0 ;; ;AN000; +BUFFER DB 64 DUP("$") ;; ;AN000; + ;; ;AN000; +HANDLE DW 0 ;; Profile handle ;AN000; + ;; ;AN000; +BUILD_STATE DB 0 ;; 1 if we are currently building ;AN000; + ;; data. 0 means syntax checking ;AN000; + ;; only ;AN000; + ;; ;AN000; + ;; Keep track of whether this PTD ;AN000; + ;; matches the type requested ;AN000; +PTD_FOUND DB 0 ;; Values are NO (0), YES (1) and ;AN000; +PROCESSED EQU 2 ;; PROCESSED (2) ;AN000; + ;; ;AN000; +VERB DB 0 ;; PTR into VERB_JMP_TAB ;AN000; + ;; ;AN000; +VERB_JMP_TAB LABEL WORD ;; ;AN000; + DW OFFSET PARSE_PRINTER ;; ;AN000; + DW OFFSET PARSE_DISPLAYMODE ;; ;AN000; + DW OFFSET PARSE_PRINTBOX ;; ;AN000; + DW OFFSET PARSE_SETUP ;; ;AN000; + DW OFFSET PARSE_RESTORE ;; ;AN000; + DW OFFSET PARSE_GRAPHICS ;; ;AN000; + DW OFFSET PARSE_COLORPRINT ;; ;AN000; + DW OFFSET PARSE_COLORSELECT ;; ;AN000; + DW OFFSET PARSE_DARKADJUST ;; ;AN000; + ;; ;AN000; +STMTS_DONE DW 0 ;; ;AN000; +GROUPS_DONE DW 0 ;; ;AN000; +PREV_STMT DW 0 ;; ;AN000; +CUR_STMT DW 0 ;; ;AN000; + ;; ;AN000; +PRT EQU 1 ;; Bit masks for STMTS_DONE and ;AN000; +DISP EQU 2 ;; GROUPS_DONE. There is one ;AN000; +BOX EQU 4 ;; bit for each statement except ;AN000; +GR EQU 8 ;; DARKADJUST ;AN000; +SET EQU 10H ;; ;AN000; +REST EQU 20H ;; ;AN000; +COLS EQU 40H ;; ;AN000; +COLP EQU 80H ;; ;AN000; +DARK EQU 100H ;; ;AN000; + ;; ;AN000; +BLOCK_START DW ? ;; Extents of the variable size block ;AN000; +BLOCK_END DW ? ;; currently being built ;AN000; + ;; These are relative to the ;AN000; + ;; start of the Shared Data Area ;AN000; + ;; so the area can be relocated ;AN000; +MAX_BLOCK_END DW 0 ;; End of largest PTD contained ;AN000; + ;; in profile ;AN000; +FIRST_BLOCK DW ? ;; Pointer to first variable block ;AN000; + ;; (end of fixed part) ;AN000; +PRT_BOX_ERROR DB 0 ;; ;AN000; + ;; ;AN000; +LOAD_PROFILE PROC NEAR ;; ;AN000; + ;; ;AN000; + PUSH CS ;; ;AN000; + POP SUBLIST_SEG ;; setup segment for message sublist ;AN000; + ;; ;AN000; + CALL OPEN_FILE ;; ;AN000; + .IF ;; Check for error during open ;AN000; + STC ;; ;AN000; + RET ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV BP,TEMP_SHARED_DATA_PTR ;; BP points to START of Shared Data ;AN000; + MOV AX,SIZE SHARED_DATA_AREA_STR ;; size of fixed part of Shared Data ;AN000; + MOV BLOCK_END,0 ;; Initialize BLOCK_START,BLOCK_END ;AN000; + MOV [BP].DARKADJUST_VALUE,0 ;; Init some values in the fixed ;AN000; + MOV [BP].NUM_PRT_COLOR,0 ;; area ;AN000; + MOV [BP].COLORPRINT_PTR,-1 ;; ;AN000; + MOV [BP].NUM_PRT_BANDS,0 ;; ;AN000; + MOV [BP].COLORSELECT_PTR,-1 ;; ;AN000; + MOV [BP].PRINTER_TYPE,BLACK_WHITE ;; ;AN000; + CALL GROW_SHARED_DATA ;; to the first byte after the ;AN000; + ;; fixed part of Shared Data ;AN000; + MOV AX,BLOCK_END ;; Variable size data will be built ;AN000; + MOV BLOCK_START,AX ;; starting at BLOCK_START ;AN000; + MOV FIRST_BLOCK,AX ;; Save start of variable data ;AN000; + ;; ;AN000; + MOV SI,BUFFER_PTR ;; Set up SI for GET_BYTE ;AN000; + CALL GET_BYTE ;; Get first byte from file ;AN000; + MOV NEXT_BYTE,AL ;; and store it ;AN000; + MOV BUFFER_PTR,SI ;; Save SI for next GET_BYTE ;AN000; + .WHILE AND ;; Keep parsing until end of file or ;AN000; + .WHILE ;; file error occurs ;AN000; + MOV STMT_ERROR,0 ;; Clear parse error flags ;AN000; + CALL GET_STATEMENT ;; Get next profile statement ;AN000; + INC STMT_NUM ;; ;AN000; + .IF NC ;; Carry flag set if get unsuccessful ;AN000; + CALL PARSE_VERB ;; Index into verb jump table returned ;AN000; + ;; in BX ;AN000; + .IF THEN ;; AX=0 if there is a recognized ;AN000; + MOV AX,CUR_STMT ;; ;AN000; + MOV PREV_STMT,AX ;; Save last statement verb ;AN000; + CALL VERB_JMP_TAB[BX] ;; statement to parse ;AN000; + .ELSEIF THEN ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .IF ;; An error was detected ;AN000; + CALL SHOW_PARSE_ERROR ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV STMT_ERROR,0 ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDWHILE ;; ;AN000; + ;; ;AN000; + .IF ;; Must have at least one PRINTER ;AN000; + CALL TERMINATE_DISPLAYMODE ;; Terminate the last PRINTER and ;AN000; + CALL TERMINATE_PRINTER ;; DISPLAYMODE sections ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + .ENDIF ;; ;AN000; + .IF ;; ;AN000; + CALL SHOW_PARSE_ERROR ;; Issue Profile syntax messages ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + MOV AX,3E00H ;; Close the file ;AN000; + MOV BX,HANDLE ;; ;AN000; + INT 21H ;; ;AN000; + ;; ;AN000; + .IF ;; ;AN000; + MOV AX,SYNTAX_ERRORS ;; Issue "Syntax errors found in ;AN000; + MOV CX,0 ;; profile" message. ;AN000; + CALL DISP_ERROR ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; Did we find the requested printer ;AN000; + MOV AX,INVALID_PRT ;; type? If not issue error ;AN000; + MOV CX,0 ;; message. ;AN000; + CALL DISP_ERROR ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF OR ;; ;AN000; + .IF OR ;; ;AN000; + .IF ;; Set carry flag if profile load ;AN000; + STC ;; was unsuccessful ;AN000; + .ELSE ;; ;AN000; + .IF ;; Everthing else was OK BUT we ran ;AN000; + .IF ;; out of memory!!! ;AN000; + MOV AX,NB_FREE_BYTES ;; ;AN000; + .IF ;AN000; + MOV AX,NO_MEMORY ;; We ran out of physical memory! ;AN000; + .ELSE ;; ;AN000; + MOV AX,UNABLE_RELOAD ;; Allocated shared data is too small ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + MOV AX,NO_MEMORY ;; We ran out of physical memory ;AN000; + .ENDIF ;; ;AN000; + MOV CX,0 ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + STC ;; Indicate unsuccessful ;AN000; + .ELSE ;; ;AN000; + MOV AX,MAX_BLOCK_END ;; Extent of largest PRINTER section ;AN000; + MOV [BP].SD_TOTAL_SIZE,AX ;; we parsed. ;AN000; + CLC ;; SUCCESSFUL LOAD!!!! ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +LOAD_PROFILE ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; SHOW_PARSE_ERROR ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +CARRAIGE_RET EQU 13 ;; ;AN000; +LINE_FEED EQU 10 ;; ;AN000; + ;; ;AN000; +SHOW_PARSE_ERROR PROC ;; ;AN000; + ;; ;AN000; + MOV ERROR_DEVICE,STDOUT ;; profile syntax messages to STDOUT ;AN000; + ;; ;AN000; + .IF ;AN000; + PUSH SI ;; ;AN000; + MOV AX,MISSING_STMT ;; ;AN000; + MOV CX,1 ;; ;AN000; + MOV SI,OFFSET SUBLIST ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + POP SI ;; ;AN000; + .ENDIF ;; ;AN000; + .IF ;AN000; + PUSH SI ;; ;AN000; + MOV AX,INVALID_STMT ;; ;AN000; + MOV CX,1 ;AN000; + MOV SI,OFFSET SUBLIST ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + POP SI ;; ;AN000; + .ENDIF ;; ;AN000; + .IF ;AN000; + PUSH SI ;; ;AN000; + MOV AX,OUT_SEQ_STMT ;; ;AN000; + MOV CX,1 ;AN000; + MOV SI,OFFSET SUBLIST ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + POP SI ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV DI,STMT_END_INDEX ;; ;AN000; + MOV STMT_BUFFER[DI],'$' ;; For display ;AN000; + MOV AH,9 ;; ;AN000; + MOV DX,OFFSET STMT_BUFFER ;AN000; + INT 21H ;; ;AN000; + MOV DL,CARRIAGE_RET ;; ;AN000; + MOV AH,2 ;; ;AN000; + INT 21H ;; ;AN000; + MOV DL,LINE_FEED ;; ;AN000; + MOV AH,2 ;; ;AN000; + INT 21H ;; ;AN000; + ;; ;AN000; + MOV ERROR_DEVICE,STDERR ;; reset to STDERR ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +SHOW_PARSE_ERROR ENDP ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; OPEN_FILE ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +OPEN_FILE PROC NEAR ;; ;AN000; + ;; ;AN000; + .IF ;; If a path was specified then ;AN000; + MOV DX,OFFSET PROFILE_PATH ;; try and open it ;AN000; + MOV AX,3D00H ;; ;AN000; + INT 21H ;; Open it ;AN000; + .IF C ;; Open error if carry flag set ;AN000; + .IF OR ;; Check for error other than ;AN000; + .IF ;; file not found ;AN000; + MOV AX,PROFILE_NOT_FOUND ;; ;AN000; + MOV CX,0 ;; ;AN000; + CALL DISP_ERROR ;; Issue "File not found" common msg ;AN000; + MOV FILE_ERROR,YES ;; ;AN000; + .ELSE ;; ;AN000; + CALL FILE_ERROR_PROC ;; Issue "Open error" ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + MOV HANDLE,AX ;; ;AN000; + .ENDIF ;; File opened OK ;AN000; + .ELSE ;; No path parameter ;AN000; + MOV DX,OFFSET DEFAULT_PATH ;; Try and open "GRAPHICS.PRO" ;AN000; + MOV AX,3D00H ;; ;AN000; + INT 21H ;; Open it ;AN000; + .IF C ;; Open error if carry flag set ;AN000; + .IF OR ;; Check for file not found error ;AN000; + .IF ;; ;AN000; + CALL COPY_ARGV0 ;; ;AN000; + MOV DX,OFFSET PROFILE_PATH ;; Try and open "GRAPHICS.PRO" in ;AN000; + MOV AX,3D00H ;; ARGV0 directory ;AN000; + INT 21H ;; ;AN000; + .IF C ;; Issue "File not found" common msg ;AN000; + .IF OR ;AN000; + .IF ;AN000; + MOV AX,PROFILE_NOT_FOUND ;; ;AN000; + MOV CX,0 ;; ;AN000; + CALL DISP_ERROR ;; Issue "File not found"common MSG;AN000; + MOV FILE_ERROR,YES ;; ;AN000; + .ELSE ;; ;AN000; + CALL FILE_ERROR_PROC ;; Issue "Open error" ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + MOV HANDLE,AX ;; ;AN000; + .ENDIF ;; File opened OK ;AN000; + .ELSE ;; ;AN000; + CALL FILE_ERROR_PROC ;; Issue "Open error" ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + MOV HANDLE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; +OPEN_FILE ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; COPY_ARGV0 ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +COPY_ARGV0 PROC ;; ;AN000; + ;; ;AN000; + PUSH ES ;; ;AN000; + PUSH DI ;; ;AN000; + PUSH SI ;; ;AN000; + ;; ;AN000; + MOV DI,2CH ;; Locate environment string ;AN000; + MOV ES,[DI] ;; ;AN000; + XOR SI,SI ;; ;AN000; + .WHILE < NE 0> ;; ;AN000; + INC SI ;; ;AN000; + .ENDWHILE ;; ;AN000; + ADD SI,4 ;; ;AN000; + LEA DI,PROFILE_PATH ;; Move string to work area ;AN000; + .REPEAT ;; ;AN000; + MOV AL,ES:[SI] ;; ;AN000; + MOV [DI],AL ;; ;AN000; + INC SI ;; ;AN000; + INC DI ;; ;AN000; + .UNTIL < EQ 0> ;; ;AN000; + MOV BYTE PTR [DI],0 ;; ;AN000; + MOV BYTE PTR [DI]-3,"P" ;; Change COM to PRO ;AN000; + MOV BYTE PTR [DI]-2,"R" ;; ;AN000; + MOV BYTE PTR [DI]-1,"O" ;; ;AN000; + ;; ;AN000; + POP SI ;; ;AN000; + POP DI ;; ;AN000; + POP ES ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +COPY_ARGV0 ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; FILE_ERROR_PROC ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +FILE_ERROR_PROC PROC ;; ;AN000; + MOV AX,FILE_ERRORS ;; ;AN000; + MOV CX,0 ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + MOV FILE_ERROR,YES ;; ;AN000; + RET ;; ;AN000; +FILE_ERROR_PROC ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; GET_STATEMENT ;AN000; +;; ;AN000; +;; Input Parameters: ;AN000; +;; NONE ;AN000; +;; ;AN000; +;; Output Parameters: ;AN000; +;; PROFILE_LINE ;AN000; +;; RETURN CODE : 0 - successfull read ;AN000; +;; : 1 - end of file ;AN000; +;; : 2 - error during read ;AN000; +;; ;AN000; +;; ;AN000; +;; Data Structures Referenced: ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; Get a statement from the profile. ;AN000; +;; The file read in 512 byte buffers and parsed into ;AN000; +;; lines by the presence of a carriage return at the end of each line. ;AN000; +;; ;AN000; +;; Called By: ;AN000; +;; LOAD_PROFILE ;AN000; +;; ;AN000; +;; External Calls: ;AN000; +;; NONE ;AN000; +;; ;AN000; +;; Logic: ;AN000; +;; FOUND := FALSE ;AN000; +;; RETURN_CODE := 0 ;AN000; +;; WHILE NOT FOUND DO ;AN000; +;; IF end of buffer THEN ;AN000; +;; Read next profile record into buffer ;AN000; +;; IF successful read THEN ;AN000; +;; point to first byte in buffer ;AN000; +;; ELSE ;AN000; +;; IF end of file THEN ;AN000; +;; Close profile ;AN000; +;; RETURN_CODE := 1 ;AN000; +;; FOUND := TRUE ;AN000; +;; ELSE ;AN000; +;; RETURN_CODE := 2 ;AN000; +;; FOUND := TRUE ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; ENDIF ;AN000; +;; copy byte to PROFILE_LINE ;AN000; +;; IF byte in buffer is a CR THEN ;AN000; +;; FOUND := TRUE ;AN000; +;; ENDIF ;AN000; +;; ENDWHILE ;AN000; +;; RETURN ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +FOUND DB 0 ;; ;AN000; + ;; ;AN000; +CARRIAGE_RET EQU 13 ;; ;AN000; +LINE_FEED EQU 10 ;; ;AN000; +NEXT_BYTE DB 0 ;; Save area for byte just read ;AN000; +BUFFER_SIZE EQU 512 ;; ;AN000; +FILE_BUFFER DB 512 DUP(0) ;; ;AN000; +BUFFER_PTR DW 512 ;; ;AN000; +BUFFER_END DW 512 ;; ;AN000; +STMT_BUFFER DB 255 DUP(0) ;; ;AN000; + DB ? ;; In case we have to insert a CR ;AN000; + DB ? ;; and a LF ;AN000; + DB ? ;; Too put the "$" for displaying the ;AN000; + ;; line. ;AN000; + ;; ;AN000; +STMT_END_INDEX DW ? ;; ;AN000; +MAX_STMT_LEN EQU 255 ;; ;AN000; +CR_FOUND DB 0 ;; 1 if we found a line terminator ;AN000; + ;; ;AN000; +GET_STATEMENT PROC ;; ;AN000; + ;; ;AN000; + MOV FOUND,NO ;; ;AN000; + MOV STMT_ERROR,0 ;; Clear error flags ;AN000; + XOR DI,DI ;; Index for extracted statement ;AN000; + MOV SI,BUFFER_PTR ;; Init file buffer ptr ;AN000; + ;; ;AN000; + MOV AL,NEXT_BYTE ;; Restore current byte ;AN000; + MOV CR_FOUND,NO ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + .WHILE AND ;; Keep parsing until we find a stmt ;AN000; + .WHILE AND ;; or a file error occurs ;AN000; + .WHILE ;; or we reach end of file ;AN000; + .IF ;; ;AN000; + .IF ;; Return the line feed as well ;AN000; + .IF ;; Truncate lines longer than MAX ;AN000; + MOV STMT_BUFFER[DI],AL ;; MOVE TO statement buffer ;AN000; + INC DI ;; Point to next byte in file buffr ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; Line has been truncated > ERROR ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + CALL GET_BYTE ;; Get the first byte of next statement ;AN000; + .ENDIF ;; ;AN000; + MOV FOUND,YES ;; Time to leave this WHILE ;AN000; + MOV NEXT_BYTE,AL ;; Save the byte we just read ;AN000; + .ELSE ;; ;AN000; + .IF ;; Truncate lines longer than MAX ;AN000; + MOV STMT_BUFFER[DI],AL ;; move byte to statement buffer ;AN000; + INC DI ;; Point to next byte in file buffer ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; Line has been truncated > ERROR ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .IF ;; Found a line terminator ;AN000; + MOV CR_FOUND,YES ;; Indicate carriage return found ;AN000; + .ENDIF ;; and go through once more to ;AN000; + CALL GET_BYTE ;; check for a line feed ;AN000; + .ENDIF ;; ;AN000; + .ENDWHILE ;; ;AN000; + ;; ;AN000; + .IF AND ;; ;AN000; + .IF ;; ;AN000; + MOV STMT_BUFFER[DI],CARRIAGE_RET ;; ;AN000; + MOV STMT_BUFFER[DI+1],LINE_FEED ;; ;AN000; + INC DI ;; ;AN000; + INC DI ;; ;AN000; + .ENDIF ;; ;AN000; + MOV STMT_END_INDEX,DI ;; ;AN000; + MOV BUFFER_PTR,SI ;; Save buffer ptr for next time ;AN000; + ;; ;AN000; + .IF ;; ;AN000; + .IF ;; Clear carry if we read something ;AN000; + STC ;; and no file error occured otherwise ;AN000; + .ELSE ;; set carry indicating unsuccessful ;AN000; + CLC ;; get. ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + STC ;; ;AN000; + .ELSE ;; ;AN000; + CLC ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +GET_STATEMENT ENDP ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; GET_BYTE ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +GET_BYTE PROC ;; ;AN000; + ;; ;AN000; + .IF ;; If buffer empty do another read ;AN000; + MOV AH,3FH ;; ;AN000; + MOV DX,OFFSET FILE_BUFFER ;; ;AN000; + MOV CX,BUFFER_SIZE ;; ;AN000; + MOV BX,HANDLE ;; ;AN000; + INT 21H ;; ;AN000; + .IF C ;; Carry set by DOS if file error ;AN000; + CALL FILE_ERROR_PROC ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; End of file if AX=0 ;AN000; + MOV END_OF_FILE,YES ;; ;AN000; + MOV AH,3EH ;; Close the file ;AN000; + MOV BX,HANDLE ;; ;AN000; + INT 21H ;; ;AN000; + .ELSE ;; ;AN000; + MOV BUFFER_END,AX ;; Number of bytes read ;AN000; + XOR SI,SI ;; Buffer pointer := 0 ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF OR ;; ;AN000; + .IF ;; ;AN000; + STC ;; Unsuccessful get ;AN000; + .ELSE ;; ;AN000; + .IF < EQ 1AH> ;; cHECK for EOF marker ;AN000; + MOV END_OF_FILE,YES ;; ;AN000; + STC ;; ;AN000; + .ELSE ;; ;AN000; + MOV AL,FILE_BUFFER[SI] ;; Return byte in AL ;AN000; + INC SI ;; ;AN000; + CLC ;; Successful get ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +GET_BYTE ENDP ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; GROW_SHARED_DATA ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +GROW_SHARED_DATA PROC ;; ;AN000; + PUSH BX ;; ;AN000; + ADD BLOCK_END,AX ;; Grow the current block by AX ;AN000; + MOV BX,BLOCK_END ;; ;AN000; + .IF ;; Check for overflow ;AN000; + MOV BUILD_STATE,NO ;; Stop building shared data ;AN000; + MOV MEM_OVERFLOW,YES ;; ;AN000; + .ENDIF ;; ;AN000; + POP BX ;; ;AN000; + RET ;; ;AN000; +GROW_SHARED_DATA ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +CODE ENDS ;; ;AN000; + END ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD.EXT b/v4.0/src/CMD/GRAPHICS/GRLOAD.EXT new file mode 100644 index 0000000..ab48e9a --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD.EXT @@ -0,0 +1,55 @@ +.XLIST ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRLOAD.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRLOAD.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN LOAD_PROFILE:NEAR ;; ;AN000; + EXTRN GROW_SHARED_DATA:NEAR ;; ;AN000; + EXTRN BLOCK_START:WORD ;AN000; + EXTRN BLOCK_END:WORD ;AN000; + EXTRN FIRST_BLOCK:WORD ;AN000; + EXTRN MAX_BLOCK_END:WORD ;AN000; + EXTRN GROUPS_DONE:WORD ;AN000; + EXTRN STMTS_DONE:WORD ;AN000; +PRT EQU 1 ;; ;AN000; +DISP EQU 2 ;; ;AN000; +BOX EQU 4 ;; ;AN000; +GR EQU 8 ;; ;AN000; +SET EQU 10H ;; ;AN000; +REST EQU 20H ;; ;AN000; +COLS EQU 40H ;; ;AN000; +COLP EQU 80H ;; ;AN000; +DARK EQU 100H ;; ;AN000; + EXTRN PTD_FOUND:BYTE ;AN000; + PROCESSED EQU 2 ;; ;AN000; + EXTRN BUILD_STATE:BYTE ;AN000; + EXTRN STMT_ERROR:BYTE ;AN000; +MISSING EQU 1 ;; Required statement missing ;AN000; +INVALID EQU 2 ;; Invalid statement format ;AN000; +SEQUENCE EQU 4 ;; Statement out of sequence ;AN000; + EXTRN FILE_ERROR:BYTE ;AN000; + EXTRN PARSE_ERROR:BYTE ;AN000; + EXTRN END_OF_FILE:BYTE ;AN000; + EXTRN MEM_OVERFLOW:BYTE ;AN000; + EXTRN STMT_BUFFER:BYTE ;AN000; + EXTRN CUR_STMT:WORD ;AN000; + EXTRN PREV_STMT:WORD ;AN000; + EXTRN PRT_BOX_ERROR:BYTE ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD2.ASM b/v4.0/src/CMD/GRAPHICS/GRLOAD2.ASM new file mode 100644 index 0000000..68041ba --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD2.ASM @@ -0,0 +1,910 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Profile Load Modules #2 ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRLOAD.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the modules used to load the ;AN000; +;; GRAPHICS profile into resident memory. ;AN000; +;; ;AN000; +;; ************* The EGA Dynamic Save Area will be built (by ;AN000; +;; ** NOTE ** CHAIN_INTERRUPTS in file GRINST.ASM) over top of these ;AN000; +;; ************* modules to avoid having to relocate this save just before ;AN000; +;; terminating. This is safe since the maximum memory used is ;AN000; +;; 288 bytes and the profile loading modules are MUCH larger than ;AN000; +;; this. So GRLOAD.ASM MUST be linked before GRINST.ASM and after ;AN000; +;; GRPRINT.ASM. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; PLACID Functional Specifications ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; LOAD_PROFILE - Main module for profile loading ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; ?????????? - Externals for profile loading modules ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; None ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; --------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' BYTE ;; ;AN000; + ;; ;AN000; + INCLUDE STRUC.INC ;; ;AN000; + INCLUDE GRINST.EXT ;; Bring in external declarations ;AN000; + ;; for transient command processing ;AN000; + INCLUDE GRSHAR.STR ;; ;AN000; + INCLUDE GRMSG.EQU ;; ;AN000; + INCLUDE GRINST.EXT ;; ;AN000; + INCLUDE GRLOAD.EXT ;; ;AN000; + INCLUDE GRPARSE.EXT ;; ;AN000; + INCLUDE GRPATTRN.STR ;; ;AN000; + INCLUDE GRPATTRN.EXT ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Public Symbols ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + PUBLIC PARSE_VERB ;; ;AN000; + PUBLIC PARSE_PRINTER ;; ;AN000; + PUBLIC PARSE_DISPLAYMODE ;; ;AN000; + PUBLIC PARSE_PRINTBOX ;; ;AN000; + PUBLIC PARSE_SETUP ;; ;AN000; + PUBLIC PARSE_RESTORE ;; ;AN000; + PUBLIC TERMINATE_DISPLAYMODE ;; ;AN000; + PUBLIC TERMINATE_PRINTER ;; ;AN000; + PUBLIC CUR_PRINTER_TYPE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Profile Load Variables ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +NO EQU 0 ;; ;AN000; +YES EQU 1 ;; ;AN000; + ;; ;AN000; +RESULT_BUFFER LABEL BYTE ;; general purpose result buffer ;AN000; + DB ? ;; operand type ;AN000; +RESULT_TAG DB 0 ;; operand tag ;AN000; + DW ? ;; pointer to synonym/keyword ;AN000; +RESULT_VAL DB ?,?,?,? ;; returned numeric value ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; TERMINATE_DISPLAYMODE ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +TERMINATE_DISPLAYMODE PROC ;; ;AN000; + ;; ;AN000; + MOV AX,STMTS_DONE ;; ;AN000; + .IF AND ;; For the matched PTD ;AN000; + .IF AND ;; issue "Invalid parm value" ;AN000; + .IF ;; message if PRINTBOX ID not ;AN000; + ;; matched in each DISPLAYMODE section ;AN000; + PUSH AX ;; Save STMT_DONE flags ;AN000; + MOV AX,INVALID_PB ;; ;AN000; + MOV CX,0 ;; ;AN000; + CALL DISP_ERROR ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + MOV PRT_BOX_ERROR,YES ;; Issue this message only once ;AN000; + POP AX ;; ;AN000; + .ENDIF ;; ;AN000; + AND AX,GR ;; Check for missing statements is last ;AN000; + .IF ;; DISPLAYMODE section: ;AN000; + OR STMT_ERROR,MISSING ;; GRAPHICS stmt is required ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +TERMINATE_DISPLAYMODE ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; TERMINATE_PRINTER ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +TERMINATE_PRINTER PROC ;; ;AN000; + ;; ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + .IF ;; Keep track of the largest PRINTER ;AN000; + MOV MAX_BLOCK_END,AX ;; section so we can allow space for ;AN000; + .ENDIF ;; reload with a different printer ;AN000; + ;; type. ;AN000; + ;; ;AN000; + ;; Check for missing statements ;AN000; + MOV AX,STMTS_DONE ;; ;AN000; + AND AX,DISP ;; At least one DISPLAYMODE ;AN000; + .IF ;; must have been found in last ;AN000; + OR STMT_ERROR,MISSING ;; PRINTER section ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +TERMINATE_PRINTER ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_PRINTER ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +PRINTER_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW PRINTER_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +PRINTER_P DB 0,1 ;; Required, max parms ;AN000; + DW PRINTER_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +PRINTER_P1 DW 2000H ;; simple string ;AN000; + DW 0002H ;; Capitalize using character table ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW PRINTER_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +PRINTER_P1V DB 3 ;; # of value lists ;AN000; + DB 0 ;; # of range numerics ;AN000; + DB 0 ;; # of discrete numerics ;AN000; + DB 1 ;; # of strings ;AN000; + DB 1 ;; tag: index into verb jump table ;AN000; +PRINTER_P1V1 DW ? ;; string offset ;AN000; + ;; ;AN000; + ;; ;AN000; +CUR_PRINTER_TYPE DB 0 ;; Type of printer currently being ;AN000; + ;; parsed: 1-color 2-b&w ;AN000; + ;; ;AN000; +PARSE_PRINTER PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,PRT ;; ;AN000; + MOV CUR_PRINTER_TYPE,BLACK_WHITE ;; Assume black & white until we hit ;AN000; + ;; a COLORPRINT ;AN000; + ;; ;AN000; + .IF ;; If not the first PRINTER section ;AN000; + CALL TERMINATE_DISPLAYMODE ;; then clean up the last one and ;AN000; + CALL TERMINATE_PRINTER ;; the last DISPLAYMODE section. ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV AX,FIRST_BLOCK ;; ;AN000; + MOV BLOCK_START,AX ;; Reset block pointers to start ;AN000; + MOV BLOCK_END,AX ;; of variable area ;AN000; + ;; ;AN000; + MOV STMTS_DONE,PRT ;; Clear all bits except for PRT ;AN000; + MOV GROUPS_DONE,0 ;; Clear ;AN000; + ;; ;AN000; + .IF ;; PRINTER statement marks the end of ;AN000; + MOV PTD_FOUND,PROCESSED ;; the previous PTD ;AN000; + MOV BUILD_STATE,NO ;; Stop building shared data ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV CL,TAB_DIR_NB_ENTRIES ;; Reset the pattern table copy ;AN000; + XOR CH,CH ;; pointers. These pointers ;AN000; + MOV BX,OFFSET TAB_DIRECTORY ;; are established when a pattern ;AN000; + .REPEAT ;; table is copied to the shared ;AN000; + MOV [BX].TAB_COPY,-1 ;; data area. Initially they ;AN000; + ADD BX,SIZE TAB_ENTRY ;; are -1. ;AN000; + .LOOP ;; ;AN000; + ;; ;AN000; + MOV AX,OFFSET PRINTER_TYPE_PARM ;; Store printer type from command ;AN000; + MOV PRINTER_P1V1,AX ;; line in value list ;AN000; + MOV DI,OFFSET PRINTER_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + ;; ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; Don't worry about number of operands ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; Syntax error is the only thing ;AN000; + OR STMT_ERROR,INVALID ;; which can go wrong ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL OR ;; ;AN000; + .UNTIL ;; ;AN000; + ;; Printer type parm matched one coded ;AN000; + ;; on the PRINTER statement ;AN000; + .IF ;; ;AN000; + .IF ;; ;AN000; + MOV PTD_FOUND,YES ;; If the printer type matches and ;AN000; + .IF AND ;; no errors have been found yet ;AN000; + .IF AND ;; ;AN000; + .IF ;; ;AN000; + MOV BUILD_STATE,YES ;; then start building the shared ;AN000; + .ENDIF ;; data ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; No match ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .IF ;; Error during parse ;AN000; + OR STMT_ERROR,INVALID ;; set error flag for caller ;AN000; + MOV PARSE_ERROR,YES ;; set error flag for caller ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;AN000; + ;; ;AN000; +PARSE_PRINTER ENDP ;AN000; + ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_DISPLAYMODE ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +DISPMODE_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW DISPMODE_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +DISPMODE_P DB 0,1 ;; Required, max parms ;AN000; + DW DISPMODE_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +DISPMODE_P1 DW 8000H ;; Numeric ;AN000; + DW 0 ;; No Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW DISPMODE_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +DISPMODE_P1V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 0,19 ;; range 0..19 ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_DISPLAYMODE PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,DISP ;; ;AN000; + ;; Check for a preceeding PRINTER ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + .IF ;; If first DISPLAYMODE... ;AN000; + .IF ;; ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + MOV [BP].DISPLAYMODE_PTR,AX ;; Set pointer to first DISPLAYMODE ;AN000; + MOV BLOCK_START,AX ;; New block starts after last one ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + CALL TERMINATE_DISPLAYMODE ;; If not the first DISPLAYMODE then ;AN000; + ;; clean up the last one. ;AN000; + MOV DI,BLOCK_START ;; DI=pointer to DISPLAYMODE block just ;AN000; + MOV AX,BLOCK_END ;; built ;AN000; + .IF ;; ;AN000; + MOV [BP+DI].NEXT_DISP_MODE,AX ;; Add new block to DISPLAYMODE chain ;AN000; + .ENDIF ;; ;AN000; + MOV BLOCK_START,AX ;; New block starts after last one ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV AX,SIZE DISPLAYMODE_STR ;; Allocate space for new DISPLAYMODE ;AN000; + CALL GROW_SHARED_DATA ;; block ;AN000; + .IF ;; ;AN000; + MOV DI,BLOCK_START ;; Start of new block ;AN000; + MOV [BP+DI].NUM_SETUP_ESC,0 ;; SETUP, RESTORE are optional so set ;AN000; + MOV [BP+DI].NUM_RESTORE_ESC,0 ;; to defaults ;AN000; + MOV [BP+DI].SETUP_ESC_PTR,-1 ;; ;AN000; + MOV [BP+DI].RESTORE_ESC_PTR,-1 ;; ;AN000; + MOV [BP+DI].BOX_WIDTH,0 ;; ;AN000; + MOV [BP+DI].BOX_HEIGHT,0 ;; ;AN000; + MOV [BP+DI].PRINT_OPTIONS,0 ;; Default to NO print options ;AN000; + MOV [BP+DI].NUM_DISP_MODE,0 ;; Get ready to INC this sucker ;AN000; + MOV [BP+DI].NEXT_DISP_MODE,-1 ;; This is the last DISPLAYMODE for now! ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + MOV [BP+DI].DISP_MODE_LIST_PTR,AX;; Start mode list at end of new block ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,DISP ;; Indicate DISPLAYMODE found ;AN000; + AND STMTS_DONE,NOT (BOX+GR+SET+REST) ;; Reset flags for PRINTBOX, GRAPHICS ;AN000; + ;; stmts found ;AN000; + AND GROUPS_DONE,NOT (GR+SET+REST) ;; Reset flags for GRAPHICS, SETUP, ;AN000; + ;; RESTORE groups processed ;AN000; + MOV DI,OFFSET DISPMODE_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; If mode is valid ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a mode to the list ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_DISP_MODE ;; Bump number of modes in list ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV AL,RESULT_VAL ;; Get mode from result buffer ;AN000; + MOV [BP+DI-1],AL ;; Store the mode at end of list ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; Mode is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL ;; ;AN000; + ;; ;AN000; + RET ;AN000; + ;; ;AN000; +PARSE_DISPLAYMODE ENDP ;AN000; + ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_SETUP ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +SETUP_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW SETUP_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +SETUP_P DB 0,1 ;; Required, max parms ;AN000; + DW SETUP_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +SETUP_P1 DW 08000H ;; Numeric ;AN000; + DW 0 ;; nO Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW SETUP_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; + ;; ;AN000; +SETUP_P1V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 0,255 ;; range 0..255 ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_SETUP PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,SET ;; ;AN000; + .IF ;; DISPLAYMODE must preceed this ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; Check for previous group of SETUP ;AN000; + OR STMT_ERROR,SEQUENCE ;; stmts ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; If first SETUP... ;AN000; + .IF ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + MOV [BP+DI].SETUP_ESC_PTR,AX ;; Set pointer to SETUP seq ;AN000; + MOV [BP+DI].NUM_SETUP_ESC,0 ;; Init sequence size ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,SET ;; Indicate SETUP found ;AN000; + .IF THEN ;; Terminate any preceeding groups ;AN000; + MOV AX,PREV_STMT ;; except for SETUP group ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET SETUP_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; If esc byte is valid ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_SETUP_ESC ;; Bump number of bytes in sequence ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV AL,RESULT_VAL ;; Get esc byte from result buffer ;AN000; + MOV [BP+DI-1],AL ;; Store at end of sequence ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; parm is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL NEAR ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_SETUP ENDP ;; ;AN000; + ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_RESTORE ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +RESTORE_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW RESTORE_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +RESTORE_P DB 0,1 ;; Required, max parms ;AN000; + DW RESTORE_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +RESTORE_P1 DW 08000H ;; Numeric ;AN000; + DW 0 ;; nO Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW RESTORE_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; + ;; ;AN000; +RESTORE_P1V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 0,255 ;; range 0..255 ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_RESTORE PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,SET ;; ;AN000; + .IF ;; DISPLAYMODE must preceed this ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; Check for previous group of RESTORE ;AN000; + OR STMT_ERROR,SEQUENCE ;; stmts ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; If first RESTORE... ;AN000; + .IF ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + MOV [BP+DI].RESTORE_ESC_PTR,AX ;; Set pointer to RESTORE seq ;AN000; + MOV [BP+DI].NUM_RESTORE_ESC,0 ;; Init sequence size ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,REST ;; Indicate RESTORE found ;AN000; + .IF THEN ;; Terminate any preceeding groups ;AN000; + MOV AX,PREV_STMT ;; except for RESTORE group ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET RESTORE_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; If esc byte is valid ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_RESTORE_ESC ;; Bump number of bytes in sequence ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV AL,RESULT_VAL ;; Get esc byte from result buffer ;AN000; + MOV [BP+DI-1],AL ;; Store at end of sequence ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; parm is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL NEAR ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_RESTORE ENDP ;; ;AN000; + ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_PRINTBOX ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +PRINTBOX_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW PRINTBOX_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +PRINTBOX_P DB 1,4 ;; Required, max parms ;AN000; + DW PRINTBOX_P0 ;; LCD/STD ;AN000; + DW PRINTBOX_P1 ;; width ;AN000; + DW PRINTBOX_P1 ;; height ;AN000; + DW PRINTBOX_P2 ;; rotate ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +PRINTBOX_P0 DW 2000H ;; sTRING - display type ;AN000; + DW 2 ;; Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW PRINTBOX_P0V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +PRINTBOX_P0V DB 3 ;; # of value lists ;AN000; + DB 0 ;; # of range numerics ;AN000; + DB 0 ;; # of discrete numerics ;AN000; + DB 1 ;; # of strings ;AN000; + DB 1 ;; tag ;AN000; +PRINTBOX_P0V1 DW ? ;; string ;AN000; + ;; ;AN000; +PRINTBOX_P1 DW 8001H ;; Numeric - BOX DIMENSIONS ;AN000; + DW 0 ;; No Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW PRINTBOX_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +PRINTBOX_P1V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 1,9 ;; range 1..9 ;AN000; + ;; ;AN000; + ;; ;AN000; +PRINTBOX_P2 DW 2001H ;; sTRING - ROTATE PARM ;AN000; + DW 2 ;; Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW PRINTBOX_P2V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +PRINTBOX_P2V DB 3 ;; # of value lists ;AN000; + DB 0 ;; # of range numerics ;AN000; + DB 0 ;; # of discrete numerics ;AN000; + DB 1 ;; # of strings ;AN000; + DB 1 ;; tag ;AN000; + DW ROTATE_STR ;; string ;AN000; +ROTATE_STR DB 'ROTATE',0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PROF_BOX_W DB 0 ;; Box width and height extracted from ;AN000; +PROF_BOX_H DB 0 ;; the profile ;AN000; +PRINTBOX_MATCH DB 0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_PRINTBOX PROC ;; ;AN000; + ;; ;AN000; + MOV PRINTBOX_MATCH,NO ;; Start out assuming the PRINTBOX ID ;AN000; + MOV PROF_BOX_W,0 ;; does not match the one requested ;AN000; + MOV PROF_BOX_H,0 ;; ;AN000; + MOV CUR_STMT,BOX ;; ;AN000; + .IF ;; DISPLAYMODE must preceed PRINTBOX ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; Multiple PRINTBOX stmts may be coded ;AN000; + ;; We must decide if this one ;AN000; + ;; matches the requested display type ;AN000; + ;; If not, ignore the statement ;AN000; + MOV DI,OFFSET PRINTBOX_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + XOR CX,CX ;; ;AN000; + ;; ;AN000; + MOV AX,PRINTBOX_ID_PTR ;; Insert requested display type in ;AN000; + MOV PRINTBOX_P0V1,AX ;; parser value list ;AN000; + CALL SYSPARSE ;; PARSE display type ;AN000; + .IF ;; If ID matches then set this flag. ;AN000; + MOV PRINTBOX_MATCH,YES ;; ;AN000; + OR STMTS_DONE,BOX ;; Indicate PRINTBOX found ;AN000; + MOV AX,PREV_STMT ;; Terminate any preceeding groups ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE horizontal dimension ;AN000; + .IF ;; ;AN000; + MOV BL,RESULT_VAL ;; ;AN000; + MOV PROF_BOX_W,BL ;; Save in local var ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + JMP PRINTBOX_DONE ;; ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE vertical dimension ;AN000; + .IF ;; ;AN000; + MOV BL,RESULT_VAL ;; ;AN000; + MOV PROF_BOX_H,BL ;; Save in local var ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + JMP PRINTBOX_DONE ;; ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; Parse ROTATE parm ;AN000; + .IF ;; ;AN000; + .IF AND ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + OR [BP+DI].PRINT_OPTIONS,ROTATE ;; ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + JMP PRINTBOX_DONE ;; ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; CHECK FOR EXTRA PARMS ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PRINTBOX_DONE: ;; ;AN000; + ;; ;AN000; + .IF AND ;; Store the PRINTBOX dimensions ;AN000; + .IF ;; ;AN000; + PUSH DI ;; in the DISPLAYMODE block ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,PROF_BOX_W ;; ;AN000; + MOV [BP+DI].BOX_WIDTH,AL ;; ;AN000; + MOV AL,PROF_BOX_H ;; ;AN000; + MOV [BP+DI].BOX_HEIGHT,AL ;; ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + ;; If we have a B&W printer then ;AN000; + ;; load the grey patterns for the ;AN000; + ;; requested print box size. ;AN000; + .IF NEAR ;AN000; + ;; ;AN000; + .IF AND NEAR ;; Dimensions could also be 0 if the ;AN000; + .IF NEAR ;; printbox ID does not apply to this;AN000; + ;; displaymode, so don't try for ;AN000; + ;; a pattern! ;AN000; + MOV BX,OFFSET TAB_DIRECTORY ;; ;AN000; + MOV CL,TAB_DIR_NB_ENTRIES ;; ;AN000; + XOR CH,CH ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,PROF_BOX_W ;; Requested box width ;AN000; + MOV AH,PROF_BOX_H ;; Requested box height ;AN000; + .REPEAT ;; ;AN000; + .IF <[BX].BOX_W_PAT EQ AL> AND ;; ;AN000; + .IF <[BX].BOX_H_PAT EQ AH> ;; ;AN000; + .LEAVE ;; ;AN000; + .ELSE ;; ;AN000; + ADD BX,SIZE TAB_ENTRY ;; ;AN000; + .ENDIF ;; ;AN000; + .LOOP ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; Unsupported box size ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE NEAR ;; Box size OK - pattern tab found ;AN000; + .IF <[BX].TAB_COPY NE -1> ;; Pointer is NOT null if the table ;AN000; + MOV AX,[BX].TAB_COPY ;; has already been copied to ;AN000; + ;; the shared data area. ;AN000; + .IF AND ;; Point to the copy. ;AN000; + .IF ;; Establish pointer to table ONLY ;AN000; + MOV [BP+DI].PATTERN_TAB_PTR,AX ;; if the PB ID matched. ;AN000; + MOV AL,[BX].NB_INT ;; Number of table entries (intensitie;AN000; + MOV [BP+DI].NUM_PATTERNS,AL ;; ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; Otherwise we have to copy it. ;AN000; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; Copy the table even if the printbox ID didn't match! ;AN000; + ;; This is a simple way to reserve enough space to allow reloading ;AN000; + ;; with a different PRINTBOX ID specified on the command line. ;AN000; + ;; This scheme avoids storing ;AN000; + ;; duplicate tables but may reserve slightly more space ;AN000; + ;; (probably only a hundred bytes or so) than ;AN000; + ;; could ever be required. The optimal solution (too ;AN000; + ;; complicated!) would involve keeping running totals for each ;AN000; + ;; PRINTBOX ID coded. ;AN000; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + MOV DI,BLOCK_END ;; Copy it onto the end of the ;AN000; + ;; current block ;AN000; + MOV DX,DI ;; Save start addr of the copy ;AN000; + MOV [BX].TAB_COPY,DX ;; Store ptr to copy in the directory ;AN000; + MOV AX,[BX].TAB_SIZE ;; ;AN000; + CALL GROW_SHARED_DATA ;; Allocate room for the table ;AN000; + .IF ;; ;AN000; + MOV CX,AX ;; Number of bytes to copy ;AN000; + PUSH SI ;; Save parse pointer ;AN000; + MOV SI,[BX].TAB_OFFSET ;; Source pointer ;AN000; + ADD DI,BP ;; make DI an absolute pointer (dest) ;AN000; + REP MOVSB ;; Move it! ;AN000; + POP SI ;; ;AN000; + .IF ;; Establish pointer to table ONLY ;AN000; + MOV DI,BLOCK_START ;; Establish pointer in DISPLAYMODE;AN000; + MOV [BP+DI].PATTERN_TAB_PTR,DX ;; info ;AN000; + MOV AL,[BX].NB_INT ;; Number of table entries (intens);AN000; + MOV [BP+DI].NUM_PATTERNS,AL ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_PRINTBOX ENDP ;AN000; + ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_VERB ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +VERB_PARSE_PARMS LABEL WORD ;; Parser control blocks to parse verb ;AN000; + DW VERB_P ;; Parser control blocks to parse verb ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +VERB_P DB 0,1 ;; Required, max parms ;AN000; + DW VERB_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +VERB_P1 DW 2000H ;; simple string ;AN000; + DW 0002H ;; Capitalize using character table ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW VERB_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +VERB_P1V DB 3 ;; # of value lists ;AN000; + DB 0 ;; # of range numerics ;AN000; + DB 0 ;; # of discrete numerics ;AN000; + DB 9 ;; # of strings ;AN000; + DB 0 ;; tag: index into verb jump table ;AN000; + DW PRINTER_STRING ;; string offset ;AN000; + DB 2 ;; tag ;AN000; + DW DISPLAYMODE_STRING ;; string offset ;AN000; + DB 4 ;; tag ;AN000; + DW PRINTBOX_STRING ;; string offset ;AN000; + DB 6 ;; tag ;AN000; + DW SETUP_STRING ;; string offset ;AN000; + DB 8 ;; tag ;AN000; + DW RESTORE_STRING ;; string offset ;AN000; + DB 10 ;; tag ;AN000; + DW GRAPHICS_STRING ;; string offset ;AN000; + DB 12 ;; tag ;AN000; + DW COLORPRINT_STRING ;; string offset ;AN000; + DB 14 ;; tag ;AN000; + DW COLORSELECT_STRING ;; string offset ;AN000; + DB 16 ;; tag ;AN000; + DW DARKADJUST_STRING ;; string offset ;AN000; +PRINTER_STRING DB 'PRINTER',0 ;; ;AN000; +DISPLAYMODE_STRING DB 'DISPLAYMODE',0 ;; ;AN000; +PRINTBOX_STRING DB 'PRINTBOX',0 ;; ;AN000; +SETUP_STRING DB 'SETUP',0 ;; ;AN000; +RESTORE_STRING DB 'RESTORE',0 ;; ;AN000; +GRAPHICS_STRING DB 'GRAPHICS',0 ;; ;AN000; +COLORPRINT_STRING DB 'COLORPRINT',0 ;; ;AN000; +COLORSELECT_STRING DB 'COLORSELECT',0 ;; ;AN000; +DARKADJUST_STRING DB 'DARKADJUST',0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_VERB PROC ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET VERB_PARSE_PARMS ;; parse parms ;AN000; + MOV SI,OFFSET STMT_BUFFER ;; the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; ;AN000; + MOV BL,RESULT_TAG ;; ;AN000; + XOR BH,BH ;; return tag in BX ;AN000; + .ELSE ;; ;AN000; + .IF ;; syntax error ;AN000; + OR STMT_ERROR,INVALID ;; set error flag for caller ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + RET ;AN000; +PARSE_VERB ENDP ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +LIMIT LABEL NEAR ;; ;AN000; +CODE ENDS ;; ;AN000; + END ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD2.EXT b/v4.0/src/CMD/GRAPHICS/GRLOAD2.EXT new file mode 100644 index 0000000..7c4d04f --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD2.EXT @@ -0,0 +1,32 @@ +.XLIST ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINST.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRLOAD.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN PARSE_VERB:NEAR ;; ;AN000; + EXTRN PARSE_PRINTER:NEAR ;; ;AN000; + EXTRN PARSE_DISPLAYMODE:NEAR ;; ;AN000; + EXTRN PARSE_PRINTBOX:NEAR ;; ;AN000; + EXTRN PARSE_SETUP:NEAR ;; ;AN000; + EXTRN PARSE_RESTORE:NEAR ;; ;AN000; + EXTRN TERMINATE_PRINTER:NEAR ;; ;AN000; + EXTRN TERMINATE_DISPLAYMODE:NEAR ;; ;AN000; + EXTRN CUR_PRINTER_TYPE:BYTE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD3.ASM b/v4.0/src/CMD/GRAPHICS/GRLOAD3.ASM new file mode 100644 index 0000000..ce9d1d4 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD3.ASM @@ -0,0 +1,729 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Profile Load Modules #2 ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRLOAD.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the modules used to load the ;AN000; +;; GRAPHICS profile into resident memory. ;AN000; +;; ;AN000; +;; ************* The EGA Dynamic Save Area will be built (by ;AN000; +;; ** NOTE ** CHAIN_INTERRUPTS in file GRINST.ASM) over top of these ;AN000; +;; ************* modules to avoid having to relocate this save just before ;AN000; +;; terminating. This is safe since the maximum memory used is ;AN000; +;; 288 bytes and the profile loading modules are MUCH larger than ;AN000; +;; this. So GRLOAD.ASM MUST be linked before GRINST.ASM and after ;AN000; +;; GRPRINT.ASM. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; PLACID Functional Specifications ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; LOAD_PROFILE - Main module for profile loading ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; ?????????? - Externals for profile loading modules ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; None ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; --------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' BYTE ;; ;AN000; + ;; ;AN000; + INCLUDE STRUC.INC ;; ;AN000; + INCLUDE GRINST.EXT ;; Bring in external declarations ;AN000; + ;; for transient command processing ;AN000; + INCLUDE GRSHAR.STR ;; ;AN000; + INCLUDE GRMSG.EQU ;; ;AN000; + INCLUDE GRINST.EXT ;; ;AN000; + INCLUDE GRLOAD.EXT ;; ;AN000; + INCLUDE GRLOAD2.EXT ;; ;AN000; + INCLUDE GRPARSE.EXT ;; ;AN000; + INCLUDE GRPATTRN.STR ;; ;AN000; + INCLUDE GRPATTRN.EXT ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Public Symbols ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + PUBLIC PARSE_GRAPHICS ;; ;AN000; + PUBLIC PARSE_COLORSELECT ;; ;AN000; + PUBLIC PARSE_COLORPRINT ;; ;AN000; + PUBLIC PARSE_DARKADJUST ;; ;AN000; + PUBLIC LIMIT ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Profile Load Variables ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +NO EQU 0 ;; ;AN000; +YES EQU 1 ;; ;AN000; + ;; ;AN000; +RESULT_BUFFER LABEL BYTE ;; general purpose result buffer ;AN000; + DB ? ;; operand type ;AN000; +RESULT_TAG DB 0 ;; operand tag ;AN000; + DW ? ;; pointer to synonym/keyword ;AN000; +RESULT_VAL DB ?,?,?,? ;; returned numeric value ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_GRAPHICS ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +GRAPHICS_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW GRAPHICS_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; +GRAPHICS_P DB 0,1 ;; Required, max parms ;AN000; + DW GRAPHICS_P1 ;; ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +GRAPHICS_P1 DW 0A000H ;; Numeric OR string ;AN000; + DW 2 ;; Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW GRAPHICS_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; + ;; ;AN000; +GRAPHICS_P1V DB 3 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 0,255 ;; range 0..255 ;AN000; + DB 0 ;; 0 - no actual numerics ;AN000; + DB 2 ;; 2 STRING VALUES ;AN000; + DB 2 ;; tag ;AN000; + DW LOWCOUNT_STR ;; ptr ;AN000; + DB 3 ;; tag ;AN000; + DW HIGHCOUNT_STR ;; ptr ;AN000; + ;; ;AN000; +lowcount_str db 'LOWCOUNT',0 ;; ;AN000; +HIGHcount_str db 'HIGHCOUNT',0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +LOWCOUNT_FOUND DB NO ;; ;AN000; +HIGHCOUNT_FOUND DB NO ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_GRAPHICS PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,GR ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,MISSING ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AX,BLOCK_END ;; ;AN000; + MOV [BP+DI].GRAPHICS_ESC_PTR,AX ;; Set pointer to GRAPHICS seq ;AN000; + MOV [BP+DI].NUM_GRAPHICS_ESC,0 ;; Init sequence size ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV LOWCOUNT_FOUND,NO ;; Flags to indicate whether the LOW ;AN000; + MOV HIGHCOUNT_FOUND,NO ;; and HIGHCOUNT parms were found ;AN000; + ;; ;AN000; + OR STMTS_DONE,GR ;; Indicate GRAPHICS found ;AN000; + ;; ;AN000; + MOV AX,PREV_STMT ;; Terminate any preceeding groups ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET GRAPHICS_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + ;; ;AN000; + .IF NEAR ;; If PARM is valid ;AN000; + MOV BL,RESULT_TAG ;; ;AN000; + .SELECT ;; ;AN000; + .WHEN ;; Escape byte ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_GRAPHICS_ESC ;; Bump number of bytes in sequence ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV AL,RESULT_VAL ;; Get esc byte from result buffer ;AN000; + MOV [BP+DI-1],AL ;; Store at end of sequence ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .WHEN ;; LOWCOUNT ;AN000; + .IF ;; ;AN000; + MOV LOWCOUNT_FOUND,YES ;; ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_GRAPHICS_ESC ;; Bump number of bytes in seq. ;AN000; + MOV AX,BLOCK_END ;; Save pointer to low byte ;AN000; + DEC AX ;; ;AN000; + MOV [BP+DI].LOW_BYT_COUNT_PTR,AX ;AN000; + MOV DI,AX ;; ;AN000; + MOV BYTE PTR[BP+DI],0 ;; Store 0 in place of count ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + ;; ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; Duplicate LOWCOUNT parms ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .WHEN ;; HIGHCOUNT ;AN000; + .IF ;; ;AN000; + MOV HIGHCOUNT_FOUND,YES ;; ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + INC [BP+DI].NUM_GRAPHICS_ESC ;; Bump number of bytes in sequen;AN000; + MOV AX,BLOCK_END ;; Save pointer to high byte ;AN000; + DEC AX ;; Block end always points 1 ahead ;AN000; + MOV [BP+DI].HGH_BYT_COUNT_PTR,AX ;AN000; + MOV DI,AX ;; ;AN000; + MOV BYTE PTR[BP+DI],0 ;; Store 0 in place of count ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .ELSE ;; ;AN000; + OR STMT_ERROR,INVALID ;; Duplicate HIGHCOUNT parms ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDSELECT ;; ;AN000; + .ELSE NEAR ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; parm is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL NEAR ;; ;AN000; + ;; ;AN000; + .IF OR ;; ;AN000; + .IF ;; Missing LOWCOUNT/HIGHCOUNT parms ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_GRAPHICS ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_COLORSELECT ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +COLORSELECT_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW COLORSELECT_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; + ;; ;AN000; +COLORSELECT_P LABEL BYTE ;; ;AN000; +CS_NUM_REQ DB 1,1 ;; Required, max parms ;AN000; +COLORSELECT_PARM LABEL WORD ;; ;AN000; +CS_POSITIONAL DW ? ;; Pointer to our positional ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +COLORSELECT_P0 DW 2000H ;; sTRING - display type ;AN000; + DW 2 ;; Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW COLORSELECT_P0V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +COLORSELECT_P0V DB 0 ;; # of value lists ;AN000; +; DB 0 ;; # of range numerics ;AN000; +; DB 0 ;; # of discrete numerics ;AN000; +; DB 1 ;; # of strings ;AN000; +; DB 1 ;; tag ;AN000; +;COLORSELECT_P0V1 DW ? ;; string ;AN000; + ;; ;AN000; +COLORSELECT_P1 DW 8001H ;; Numeric - escape sequence byte ;AN000; + DW 0 ;; No Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW COLORSELECT_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +COLORSELECT_P1V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 1,255 ;; range 1..255 ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +SEQ_LENGTH_PTR DW 0 ;; Number of colorselect statements ;AN000; + ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_COLORSELECT PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,COLS ;; ;AN000; + .IF ;; PRINTER statemnet must have been ;AN000; + OR STMT_ERROR,MISSING ;; processed ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; DISDPLAYMODE and COLORPRINT stmts ;AN000; + OR STMT_ERROR,SEQUENCE ;; should NOT have been processed ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; Check for a previous group of ;AN000; + OR STMT_ERROR,SEQUENCE ;; COLORSELECTS within this PTD ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; If first COLORSELECT... ;AN000; + MOV NUM_BANDS,0 ;; Init number of COLORSELECT bands ;AN000; + .IF ;; Update count and pointer in the ;AN000; + MOV AX,BLOCK_END ;; Shared Data Area header ;AN000; + MOV [BP].COLORSELECT_PTR,AX ;; Set pointer to COLORSELECT info ;AN000; + MOV [BP].NUM_PRT_BANDS,0 ;; Init NUMBER OF COLORSELECTS ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,COLS ;; Indicate found ;AN000; + .IF THEN ;; Terminate any preceeding groups ;AN000; + MOV AX,PREV_STMT ;; except for COLORSELECT ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV AX,1 ;; Make room for sequence length field ;AN000; + CALL GROW_SHARED_DATA ;; ;AN000; + .IF ;; ;AN000; + INC [BP].NUM_PRT_BANDS ;; Inc number of selects ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV BYTE PTR [BP+DI-1],0 ;; Init sequence length field ;AN000; + LEA AX,[DI-1] ;; ;AN000; + MOV SEQ_LENGTH_PTR,AX ;; Save pointer to length of sequence ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET COLORSELECT_PARSE_PARMS ;; parse parms ;AN000; + MOV CS_NUM_REQ,1 ;; Change to 1 required parameters ;AN000; + MOV AX,OFFSET COLORSELECT_P0 ;; Point to control block for the band ;AN000; + MOV CS_POSITIONAL,AX ;; ID. (Dealing with only 1 positional ;AN000; + ;; parameter at a time was the only way ;AN000; + ;; I could get SYSPARSE to handle ;AN000; + ;; the COLORSELECT syntax!) ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + XOR CX,CX ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE the band ID ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + RET ;; statement. ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + PUSH ES ;; We got a band id........ ;AN000; + PUSH DI ;; ;AN000; + ;; ;AN000; + LES DI,DWORD PTR RESULT_VAL ;; Get pointer to the parsed band id ;AN000; + .IF < NE 0> ;; Make sure the band id is only ;AN000; + OR STMT_ERROR,INVALID ;; one byte long ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV BL,NUM_BANDS ;; ;AN000; + XOR BH,BH ;; ;AN000; + .IF THEN ;; Watch out for too many COLORSELECTs ;AN000; + OR STMT_ERROR,SEQUENCE ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE ;; ;AN000; + SHL BX,1 ;; calc index to store band in value list;AN000; + MOV AL,ES:[DI] ;; get BAND ID FROM PARSEr ;AN000; + MOV BAND_VAL_LIST[BX],AL ;; ;AN000; + INC NUM_BANDS ;; bump number of bands ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + POP DI ;; ;AN000; + POP ES ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + MOV AX,OFFSET COLORSELECT_P1 ;; Switch to numeric positional parm!!! ;AN000; + MOV CS_POSITIONAL,AX ;; ;AN000; + MOV CS_NUM_REQ,0 ;; Change to 0 required parameters ;AN000; + XOR DX,DX ;; PARSE the sequence of escape bytes ;AN000; + .REPEAT ;; ;AN000; + XOR CX,CX ;; ;AN000; + CALL SYSPARSE ;; ;AN000; + .IF ;; If esc byte is valid ;AN000; + PUSH AX ;; ;AN000; + MOV AX,1 ;; Add a byte to the sequence ;AN000; + CALL GROW_SHARED_DATA ;; Update block end ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,SEQ_LENGTH_PTR ;; ;AN000; + INC byte ptr [BP+DI] ;; Bump number of bytes in sequence ;AN000; + MOV DI,BLOCK_END ;; ;AN000; + MOV AL,RESULT_VAL ;; Get esc byte from result buffer ;AN000; + MOV [BP+DI-1],AL ;; Store at end of sequence ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + POP AX ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; parm is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL NEAR ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_COLORSELECT ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_COLORPRINT ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +COLORPRINT_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW COLORPRINT_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; + ;; ;AN000; +COLORPRINT_P LABEL BYTE ;; ;AN000; + DB 3,4 ;; Required,MAX ;AN000; + DW COLORPRINT_P0 ;; Numeric: Red value ;AN000; + DW COLORPRINT_P0 ;; Green value ;AN000; + DW COLORPRINT_P0 ;; Blue value ;AN000; + DW COLORPRINT_P1 ;; Band ID ... REPEATING ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +COLORPRINT_P0 DW 8000H ;; Numeric - RGB value ;AN000; + DW 0 ;; No Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW COLORPRINT_P0V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +COLORPRINT_P0V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD 0,63 ;; range 0..63 ;AN000; + ;; ;AN000; +COLORPRINT_P1 DW 2001H ;; sTRING - Band ID ;AN000; + DW 2 ;; Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW COLORPRINT_P1V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +COLORPRINT_P1V DB 3 ;; # of value lists ;AN000; + DB 0 ;; 0 - no range numerics ;AN000; + DB 0 ;; 0 - no actual numerics ;AN000; +NUM_BANDS DB 0 ;; number of band values ;AN000; + DB 01H ;; tag: TAGS ARE BAND MASKS ;AN000; + DW BAND_PTR_1 ;; ptr ;AN000; + DB 02H ;; tag ;AN000; + DW BAND_PTR_2 ;; ptr ;AN000; + DB 04H ;; tag ;AN000; + DW BAND_PTR_3 ;; ptr ;AN000; + DB 08H ;; tag ;AN000; + DW BAND_PTR_4 ;; ptr ;AN000; + DB 10H ;; tag ;AN000; + DW BAND_PTR_5 ;; ptr ;AN000; + DB 20H ;; tag ;AN000; + DW BAND_PTR_6 ;; ptr ;AN000; + DB 40H ;; tag ;AN000; + DW BAND_PTR_7 ;; ptr ;AN000; + DB 80H ;; tag ;AN000; + DW BAND_PTR_8 ;; ptr ;AN000; + ;; ;AN000; +MAX_BANDS EQU 8 ;; ;AN000; + ;; ;AN000; +BAND_VAL_LIST LABEL BYTE ;; ;AN000; +BAND_PTR_1 DB ?,0 ;; ;AN000; +BAND_PTR_2 DB ?,0 ;; ;AN000; +BAND_PTR_3 DB ?,0 ;; ;AN000; +BAND_PTR_4 DB ?,0 ;; ;AN000; +BAND_PTR_5 DB ?,0 ;; ;AN000; +BAND_PTR_6 DB ?,0 ;; ;AN000; +BAND_PTR_7 DB ?,0 ;; ;AN000; +BAND_PTR_8 DB ?,0 ;; ;AN000; + ;; ;AN000; + ;; ;AN000; +PARSE_COLORPRINT PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,COLP ;; ;AN000; + .IF ;; PRINTER statemnet must have been ;AN000; + OR STMT_ERROR,MISSING ;; processed ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; DISPLAYMODE stmts ;AN000; + OR STMT_ERROR,SEQUENCE ;; should NOT have been processed ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; Check for a previous group of ;AN000; + OR STMT_ERROR,SEQUENCE ;; COLORPRINTS within this PTD ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV CUR_PRINTER_TYPE,COLOR ;; ;AN000; + ;; ;AN000; + .IF ;; If first COLORPRINT... ;AN000; + .IF ;; Update count and pointer in the ;AN000; + MOV AX,BLOCK_END ;; Shared Data Area header ;AN000; + MOV [BP].COLORPRINT_PTR,AX ;; Set pointer to COLORPRINT info ;AN000; + MOV [BP].PRINTER_TYPE,COLOR ;; ;AN000; + MOV [BP].NUM_PRT_COLOR,0 ;; Init NUMBER OF COLORPRINTS ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; ;AN000; + INC [BP].NUM_PRT_COLOR ;; Inc number of selects ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,COLP ;; Indicate found ;AN000; + .IF THEN ;; Terminate any preceeding groups ;AN000; + MOV AX,PREV_STMT ;; except for COLORPRINT ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + MOV AX,BLOCK_END ;; Start a new block ;AN000; + MOV BLOCK_START,AX ;; ;AN000; + MOV AX,SIZE COLORPRINT_STR ;; Make room for COLORPRINT info ;AN000; + CALL GROW_SHARED_DATA ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET COLORPRINT_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + XOR CX,CX ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE the RED value ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,RESULT_VAL ;; Store RED value in COLORPRINT info ;AN000; + MOV [BP+DI].RED,AL ;; ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE the GREEN value ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,RESULT_VAL ;; Store GREEN value in COLORPRINT info ;AN000; + MOV [BP+DI].GREEN,AL ;; ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE the BLUE value ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,RESULT_VAL ;; Store BLUE value in COLORPRINT info ;AN000; + MOV [BP+DI].BLUE,AL ;; ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV [BP+DI].SELECT_MASK,0 ;; Initialize band select mask ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + XOR DX,DX ;; For each band found "OR" the item ;AN000; + .REPEAT ;; tag into the select mask ;AN000; + MOV CX,3 ;; Avoid getting too many parms error ;AN000; + CALL SYSPARSE ;; from parser ;AN000; + .IF ;; ;AN000; + .IF ;; ;AN000; + PUSH DI ;; ;AN000; + MOV DI,BLOCK_START ;; ;AN000; + MOV AL,RESULT_TAG ;; ;AN000; + OR [BP+DI].SELECT_MASK,AL ;; OR the mask for this band into the ;AN000; + ;; select mask for this color ;AN000; + POP DI ;; ;AN000; + .ENDIF ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; parm is invalid ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + .UNTIL NEAR ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_COLORPRINT ENDP ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Module Name: ;AN000; +;; PARSE_DARKADJUST ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +DARKADJUST_PARSE_PARMS LABEL WORD ;; Parser control blocks ;AN000; + DW DARKADJUST_P ;; ;AN000; + DB 2 ;; # of lists ;AN000; + DB 0 ;; # items in delimeter list ;AN000; + DB 1 ;; # items in end-of-line list ;AN000; + DB ';' ;; ';' used for comments ;AN000; + ;; ;AN000; + ;; ;AN000; +DARKADJUST_P LABEL BYTE ;; ;AN000; + DB 1,1 ;; Required,MAX ;AN000; + DW DARKADJUST_P0 ;; Numeric: adjust value ;AN000; + DB 0 ;; # Switches ;AN000; + DB 0 ;; # keywords ;AN000; + ;; ;AN000; +DARKADJUST_P0 DW 4000H ;; Signed Numeric - adjust value ;AN000; + DW 0 ;; No Capitalize ;AN000; + DW RESULT_BUFFER ;; Result buffer ;AN000; + DW DARKADJUST_P0V ;; Value list ;AN000; + DB 0 ;; Synomyms ;AN000; + ;; ;AN000; +DARKADJUST_P0V DB 1 ;; # of value lists ;AN000; + DB 1 ;; # of range numerics ;AN000; + DB 1 ;; tag ;AN000; + DD -63,63 ;; range -63,63 ;AN000; +;;;;***********************************;; ;AN000; + ;; ;AN000; + ;AN000; +PARSE_DARKADJUST PROC ;; ;AN000; + ;; ;AN000; + MOV CUR_STMT,DARK ;; ;AN000; + .IF ;; PRINTER statemnet must have been ;AN000; + OR STMT_ERROR,MISSING ;; processed ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + ;; ;AN000; + OR STMTS_DONE,DARK ;; Indicate found ;AN000; + ;; Terminate any preceeding groups ;AN000; + MOV AX,PREV_STMT ;; ;AN000; + OR GROUPS_DONE,AX ;; ;AN000; + ;; ;AN000; + MOV DI,OFFSET DARKADJUST_PARSE_PARMS ;; parse parms ;AN000; + ;; SI => the line to parse ;AN000; + XOR DX,DX ;; ;AN000; + XOR CX,CX ;; ;AN000; + ;; ;AN000; + CALL SYSPARSE ;; PARSE the ADJUST VALUE ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ELSE ;; ;AN000; + .IF ;; ;AN000; + MOV AL,RESULT_VAL ;; ;AN000; + MOV [BP].DARKADJUST_VALUE,AL ;; ;AN000; + .ENDIF ;; ;AN000; + CALL SYSPARSE ;; CHECK FOR EXTRA PARMS ;AN000; + .IF ;; ;AN000; + OR STMT_ERROR,INVALID ;; ;AN000; + MOV PARSE_ERROR,YES ;; ;AN000; + MOV BUILD_STATE,NO ;; ;AN000; + .ENDIF ;; ;AN000; + .ENDIF ;; ;AN000; + ;; ;AN000; + RET ;; ;AN000; + ;; ;AN000; +PARSE_DARKADJUST ENDP ;; ;AN000; + ;AN000; +LIMIT LABEL NEAR ;; ;AN000; +CODE ENDS ;; ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRLOAD3.EXT b/v4.0/src/CMD/GRAPHICS/GRLOAD3.EXT new file mode 100644 index 0000000..6c1b8e5 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRLOAD3.EXT @@ -0,0 +1,28 @@ +.XLIST ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINST.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRLOAD.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN PARSE_GRAPHICS:NEAR ;; ;AN000; + EXTRN PARSE_COLORSELECT:NEAR ;; ;AN000; + EXTRN PARSE_COLORPRINT:NEAR ;; ;AN000; + EXTRN PARSE_DARKADJUST:NEAR ;; ;AN000; + EXTRN LIMIT:NEAR ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRMSG.EQU b/v4.0/src/CMD/GRAPHICS/GRMSG.EQU new file mode 100644 index 0000000..60b4c0e --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRMSG.EQU @@ -0,0 +1,84 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRMSG.EQU ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; DOS GRAPHICS Command - Message number AN000;equates +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the numbers assigned to the error messages ;AN000; +;; issued by GRAPHICS.COM ;AN000; +;; ;AN000; +;; These messages are defined in GRAPHICS.MSG ;AN000; +;; (The message skeleton file for GRAPHICS.COM) ;AN000; +;; ;AN000; +;; This file also contains equates for the error codes returned by ;AN000; +;; the DOS parser. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; ;AN000; +;; DOS 3.3 Message Retriever Interface Supplement. ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRINST.ASM: ;AN000; +;; GRAPHICS_INSTALL - Main module for GRAPHICS install. ;AN000; +;; PARSE_PARMS - Parse the command line parameters. ;AN000; +;; FROM FILE GRLOAD.ASM AND GRLOAD2.ASM ;AN000; +;; All modules ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; GRAPHICS MESSAGE NUMBERS ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +; Class A messages: ;AN000; +INCORRECT_DOS EQU 1 ; 'Incorrect DOS version' ;AN000; +NO_MEMORY EQU 2 ; 'Insufficient memory' ;AN000; + ;AN000; +; Class B messages: (Profile loading) ;AN000; +PROFILE_NOT_FOUND EQU 9 ; 'Cannot find GRAPHICS profile' ;AN000; +MISSING_STMT EQU 10 ; 'Required profile statement missing ;AN000; + ; before line %1' ;AN000; +INVALID_STMT EQU 11 ; 'Invalid profile statement on line %1' ;AN000; +OUT_SEQ_STMT EQU 12 ; 'Profile statement out of sequence on line %1';AN000; +FILE_ERRORS EQU 13 ; 'Error reading GRAPHICS profile' ;AN000; +SYNTAX_ERRORS EQU 14 ; 'Syntax errors in GRAPHICS profile' ;AN000; +INVALID_PB EQU 15 ; 'PRINTBOX id not in GRAPHICS profile' ;AN000; +INVALID_PRT EQU 16 ; 'Printer type not in GRAPHICS profile' ;AN000; + ;AN000; +; Class C messages: (Command line parsing) ;AN000; +TOO_MANY_PARMS EQU 3 ; 'Too many parameters' ;AN000; +VALUE_NOT_ALLOWED EQU 4 ; 'Parameter value not allowed' ;AN000; +INVALID_PARM EQU 5 ; 'Invalid parameter %1' ;AN000; +INVALID_COMBINATION EQU 6 ; 'Invalid parameter combination' ;AN000; +DUPLICATE_PARM EQU 7 ; 'Duplicate parameters not allowed' ;AN000; +FORMAT_NOT_CORRECT EQU 8 ; 'Parameter format not correct' ;AN000; +INVALID_B_SWITCH EQU 17 ; '/B invalid with a Black and White printer' ;AN000; +UNABLE_RELOAD EQU 18 ; 'Unable to reload with profile supplied' ;AN000; + ;AN000; + ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; PARSER ERROR CODES AND OUR OWN PARSING ERROR CODES ;AN000; +; *** ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +RC_NO_ERROR EQU 0 ;AN000; +RC_EOL EQU -1 ;AN000; +RC_TOO_MANY EQU 1 ;AN000; +RC_NOT_IN_SW EQU 3 ;AN000; +RC_NOT_IN_VAL EQU 7 ;AN000; +RC_NOT_IN_STR EQU 8 ;AN000; + ;AN000; +RC_INVLD_COMBINATION EQU 99 ;AN000; +RC_DUPLICATE_PARMS EQU 100 ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPARMS.ASM b/v4.0/src/CMD/GRAPHICS/GRPARMS.ASM new file mode 100644 index 0000000..8cebf2e --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPARMS.ASM @@ -0,0 +1,717 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Command line parsing module ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPARMS.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; ;AN000; +;; This file contains modules for parsing the GRAPHICS.COM ;AN000; +;; command line; using the DOS PARSER. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; DOS 3.3 Message Retriever Interface Supplement. ;AN000; +;; TUPPER I0 Document - PARSER HIGH LEVEL DESIGN REVIEW ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; PARSE_PARMS - Parse the command line ;AN000; +;; GET_R - Get /R ;AN000; +;; GET_B - Get /B ;AN000; +;; GET_LCD - Get /LCD ;AN000; +;; GET_PRINTBOX - Get /PRINTBOX ;AN000; +;; GET_PROFILE - Get the profile path and file name ;AN000; +;; GET_TYPE - Get the printer type ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRINST.EXT - Externals for installation modules ;AN000; +;; GRPARSE.EXT - Externals for the DOS parser code ;AN000; +;; GRSHAR.STR - Shared Data Area Structure ;AN000; +;; GRMSG.EQU - Equates for GRAPHICS.COM error messages ;AN000; +;; STRUC.INC - Macros for using structured assembly language ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRINST.ASM: ;AN000; +;; GRAPHICS_INSTALL - Main module for the installation of GRAPHICS ;AN000; +;; SYSPARSE - DOS system parser ;AN000; +;; SYSDISPMSG - DOS message retriever ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;AN000; + ASSUME CS:CODE,DS:CODE ;AN000; +PARSE_PARMS PROC NEAR ;AN000; + jmp PARSE_PARMS_START ;AN000; +PUBLIC PARSE_PARMS ;AN000; +.XLIST ;AN000; +INCLUDE GRMSG.EQU ; Include GRAPHICS error messages equates ;AN000; +INCLUDE GRSHAR.STR ; Include the Shared data area structure ;AN000; +INCLUDE GRINST.EXT ; Include externals for the installation module ;AN000; +INCLUDE GRPARSE.EXT ; Include externals for the DOS parse code ;AN000; +INCLUDE STRUC.INC ; Include macros for using STRUCTURES ;AN000; +.LIST ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PARSE_PARMS : PARSE THE COMMAND LINE PARAMETERS. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: DS,ES = SEGMENT CONTAINING THE PROGRAM PREFIX SEGMENT ;AN000;(PSP) +; ;AN000; +; OUTPUT: SWITCHES = A bit mask in the shared data area indicating ;AN000; +; which command line switches are set. ;AN000; +; PROFILE_PATH = The profile file name and path (ASCIIZ string);AN000; +; PRINTBOX_ID_PTR = Offset of the printbox id (ASCIIZ string) ;AN000; +; PRINTER_TYPE_PARM = printer type (ASCIIZ string) ;AN000; +; CARRY FLAG IS SET if an error occurred ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Call the DOS parser to parse the command line parameters ;AN000; +; of the GRAPHICS command line which is obtained from the PSP (Program Segment ;AN000; +; Prefix). ;AN000; +; ;AN000; +; The format of the command line is: ;AN000; +; ;AN000; +; ;AN000; +; GRAPHICS {prt_type {profile}} {/R} {/B} {[/LCD | /PRINTBOX:id]} ;AN000; +; ;AN000; +; (All arguments are optional, /PRINTBOX can be spelled /PB.) ;AN000; +; ;AN000; +; If no printer type is specified then, a null pointer is returned. ;AN000; +; If no profile name is supplied then, a null string is returned. ;AN000; +; If "/LCD" is specified then, a pointer to the printbox id: "LCD" is returned. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; Set addressibility to the command line parameters in the PSP ;AN000; +; CALL SYSPARSE ; Call the system parser ;AN000; +; While not (End Of Line) AND no error ;AN000; +; IF argument is the profile name ;AN000; +; THEN Get the profile name ;AN000; +; IF argument is the printbox switch ;AN000; +; THEN Get the printbox id ;AN000; +; IF argument is a /r ;AN000; +; THEN Get /r ;AN000; +; IF argument is /b ;AN000; +; THEN Get /b ;AN000; +; IF argument /lcd ;AN000; +; THEN Get /lcd ;AN000; +; CALL SYSPARSE ;AN000; +; If error ;AN000; +; Then display the appropriate error message ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; BIT MASK INDICATING THE COMMAND LINE SWITCHES PARSED SO FAR: ;AN000; +;-------------------------------------------------------------------------------;AN000; +SWITCH_PARSED DB 0 ;AN000; +GOT_R EQU 1 ; Found /R ;AN000; +GOT_B EQU 2 ; Found /B ;AN000; +GOT_LCD EQU 4 ; Found /LCD ;AN000; +GOT_PRINTBOX EQU 8 ; Found /PB:id or /PRINTBOX:id ;AN000; + ;AN000; +;===============================================================================;AN000; +; ;AN000; +; CONTROL BLOCK DEFINITIONS FOR THE PARSER: ;AN000; +; ;AN000; +;===============================================================================;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; PARMS INPUT BLOCK ;AN000; +;-------------------------------------------------------------------------------;AN000; +PARMS LABEL WORD ;AN000; + DW PARMSX ; Offset of parms extension block ;AN000; + DB 0 ; No delimiters to define ;AN000; + ; or end of line markers. ;AN000; + ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; PARMS EXTENSION BLOCK : Describe what's on the command line ;AN000; +;-------------------------------------------------------------------------------;AN000; +PARMSX LABEL BYTE ;AN000; + DB 0,2 ; Max. 2 positional parameters ;AN000; + DW TYPE_CTL ; Offset of type control block ;AN000; + DW PROF_CTL ; Offset of profile control block ;AN000; + ;AN000; + DB 4 ; Max. 4 switch types ;AN000; + DW PRINTBOX_CTL ; Offset of control for Printbox ;AN000; + DW R_CTL ; Offset of control for /R ;AN000; + DW B_CTL ; Offset of control for /B ;AN000; + DW LCD_CTL ; Offset of control for /LCD ;AN000; + ;AN000; + DB 0 ; No keywords ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the printer type parameter: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +TYPE_CTL LABEL WORD ;AN000; + DW 2001H ; Optional simple string ;AN000; + DW 0002H ; Capitalize it ;AN000; + DW TYPE_RESULT ; Offset of result buffer for printer type ;AN000; + DW NO_VALUES ; No values (NOTE: The type returned is checked;AN000; + DB 0 ; for validity by LOAD_PROFILE);AN000; + ;AN000; +NO_VALUES DB 0 ;AN000; + ;AN000; +TYPE_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Pointer to string found ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the format of the PROFILE parameter: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +PROF_CTL LABEL WORD ;AN000; + DW 0201H ; File spec. - Optional ;AN000; + DW 0001h ; Capitalize ;AN000; + DW PROFILE_RESULT ; Offset of result buffer for Profile ;AN000; + DW NO_VALUES ; No values needed ;AN000; + DB 0 ;AN000; + ;AN000; + ;AN000; +PROFILE_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Offset of string ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the format of /R ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +R_CTL LABEL WORD ;AN000; + DW 0 ; ;AN000; + DW 0 ; ;AN000; + DW R_RESULT ; Offset of result buffer for a simple switch ;AN000; + DW NO_VALUES ; No values can be given with these switches. ;AN000; + DB 1 ; 1 name for this switch ;AN000; + DB "/R",0 ; Reverse ;AN000; + ;AN000; +R_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Offset of value ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the format of /B ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +B_CTL LABEL WORD ;AN000; + DW 0 ; ;AN000; + DW 0 ; ;AN000; + DW B_RESULT ; Offset of result buffer for a simple switch ;AN000; + DW NO_VALUES ; No values can be given with these switches. ;AN000; + DB 1 ; 1 name allowed for this switch ;AN000; + DB "/B",0 ; Background ;AN000; + ;AN000; +B_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Offset of value ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the format of /LCD ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +LCD_CTL LABEL WORD ;AN000; + DW 0 ; ;AN000; + DW 0 ; ;AN000; + DW LCD_RESULT ; Offset of result buffer for a /LCD ;AN000; + DW NO_VALUES ; No values can be given with these switches. ;AN000; + DB 1 ; 1 name: ;AN000; + DB "/LCD",0 ; /LCD ;AN000; + ;AN000; +LCD_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Offset of value ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Describe the format of the PRINTBOX switch: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINTBOX_CTL LABEL WORD ;AN000; + DW 2001H ; Optional simple string ;AN000; + DW 0001H ; Capitalize ;AN000; + DW PRINTBOX_RESULT ; Offset of result buffer for Printbox ;AN000; + DW NO_VALUES ; Values will be validated when loading profile ;AN000; + DB 2 ; 2 synomym for this switch: ;AN000; + DB "/PRINTBOX",0 ; ;AN000; + DB "/PB",0 ;AN000; + ;AN000; +PRINTBOX_RESULT LABEL BYTE ;AN000; + DB ? ; Type ;AN000; + DB ? ; Item tag ;AN000; + DW ? ; Offset of synomym ;AN000; + DD ? ; Offset of value ;AN000; + ;AN000; +;===============================================================================;AN000; +; ;AN000; +; DOS "MESSAGE RETRIEVER" Substitution list control block: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +SUBLIST LABEL DWORD ; List for substitution: ;AN000; + DB 11 ; Size of this list ;AN000; + DB 0 ; Reserved ;AN000; +SAVE_SI DD ? ; Ptr to data item ;AN001; + DB 1 ; Variable to be substitued: %1 ;AN000; + DB 00010000B ; %1 is an ASCIIZ string left justifi;AN000;ed + DB 0 ; Unlimited size for %1 ;AN000; + DB 1 ; Minimum size is 1 character ;AN000; + DB " " ; Delimiter is "space" ;AN000; + ;AN000; +;===============================================================================;AN000; +; ;AN000; +; START OF EXECUTABLE CODE: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +PARSE_PARMS_START: ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH ES ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set up addressibility for the parser ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV SI,81H ; DS:SI := Command line parameters ;AN000; + ; to be parsed ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; + LEA DI,PARMS ; ES:DI := Parms control block ;AN000; +;(deleted ;AN001;) XOR DX,DX ; CX,DX must be zero for the ;AN000; + XOR CX,CX ; Initially, CX should be zero ;AN001; + MOV AX,0 ; No error yet ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Parse FIRST argument ;AN000; +;-------------------------------------------------------------------------------;AN000; +;(deleted ;AN001;) CALL SYSPARSE ; Get one argument from the command line;AN000; + CALL CALL_SYSPARSE ; Get one argument from the command line;AN001; +;(deleted ;AN001;) MOV BX,DX ; BX := Offset of result block ;AN000; +.WHILE ; While there is no error ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get the argument: ;AN000; +;-------------------------------------------------------------------------------;AN000; + .SELECT ;AN000; + .WHEN > ;AN000; + CALL GET_TYPE ;AN000; + .WHEN > ;AN000; + CALL GET_PROFILE_NAME ;AN000; + .WHEN > ;AN000; + CALL GET_LCD ;AN000; + .WHEN > ;AN000; + CALL GET_REVERSE ;AN000; + .WHEN > ;AN000; + CALL GET_BACKGROUND ;AN000; + .WHEN > ;AN000; + CALL GET_PRINTBOX_ID ;AN000; + .OTHERWISE ;AN000; +;-------No result block was returned by the parser ;AN000; + STC ; Set error ;AN000; + .ENDSELECT ;AN000; + .LEAVE C ; IF error occurred while parsing the ;AN000; + ; previous argument, exit the loop: ;AN000; + ; stop parsing the command line. ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Parse next argument: ;AN000; +;-------------------------------------------------------------------------------;AN000; +;(deleted ;AN001;) XOR DX,DX ; ;AN000; +;(deleted ;AN001;) CALL SYSPARSE ; Get one argument from the command line;AN000; + CALL CALL_SYSPARSE ; Get one argument from the command line;AN001; +;(deleted ;AN001;) MOV BX,DX ; ES:BX := Offset of result block ;AN000; +.ENDWHILE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Check for error, select and display an error message ;AN000; +;-------------------------------------------------------------------------------;AN000; +.IF ; IF an error occurred ;AN000; +.THEN ; then, display error message ;AN000; + MOV CX,0 ; Assume no substitutions ;AN000; + .SELECT ; (CX := Number of substitutions ;AN000; + .WHEN ; When RC = Too many parameters ;AN000; + MOV AX,TOO_MANY_PARMS ; (AL = Message number to display) ;AN000; + .WHEN ; When RC = Not in value list provided ;AN000; + MOV AX,VALUE_NOT_ALLOWED ; (AL = Message number to display) ;AN000; + .WHEN ; When RC = Not in switch list provided ;AN000; + MOV CX,1 ; 1 substitution in this message ;AN000; + MOV BYTE PTR [SI],0 ; PUT NUL AT END OF THIS PARM ;AN001; + LEA SI,SUBLIST ; DS:[SI]:="Invalid parm" Substitution;AN000; list +;(deleted ;AN001;) LES DX,ES:[BX+4] ; ES:DX := Offset of offending parm. ;AN000; +;(deleted ;AN001;) MOV [SI]+2,DX ; Store offset to this offender in the;AN000; + MOV [SI]+4,ES ; substitution list control block ;AN000; + MOV AX,INVALID_PARM ; AL := 'Invalid parameter' msg number;AN000; + .WHEN ; When RC = Invalid combination of parms;AN000; + MOV AX,INVALID_COMBINATION ; (AL = Message number to display) ;AN000; + .WHEN ; When RC = Invalid combination of parms;AN000; + MOV AX,DUPLICATE_PARM ; (AL = Message number to display) ;AN000; + .OTHERWISE ; ;AN000; + MOV AX,FORMAT_NOT_CORRECT ; RC = Anything else, tell the user ;AN000; + ; something is wrong with his ;AN000; + .ENDSELECT ; command line. ;AN000; + CALL DISP_ERROR ; Display the selected error message ;AN000; + STC ; Indicate parse error occurred ;AN000; +.ENDIF ;AN000; + ;AN000; + POP ES ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ; Return to GRAPHICS_INSTALL ;AN000; + ;AN000; +PARSE_PARMS ENDP ;AN000; +CALL_SYSPARSE PROC NEAR ;COMMON INVOCATION OF SYSPARSE ;AN001; +;INPUT: - CX=ORDINAL VALUE ;AN001; +; DS:SI=WHERE COMMAND LINE IS, SAVED IN "SAVE_SI" ;AN001; +; ES:DI=WHERE PARMS DESCRIPTOR BLOCK IS ;AN001; +;OUTPUT: CX=NEW ORDINAL VALUE ;AN001; +; BX=OFFSET OF RESULT BLOCK, IF ONE IS RETURNED ;AN001; +; SI=OFFSET OF CHAR BEYOND PARSED PARM IN COMMAND LINE ;AN001; + ;AN001; + XOR DX,DX ;CLEAR DX FOR PARSER ;AN001; + MOV WORD PTR SAVE_SI,SI ;REMEMBER WHERE TO START LOOKING ;AN001; + CALL SYSPARSE ;GO PARSE THE NEXT PARM ;AN001; + ;AN001; + MOV BX,DX ; BX := Offset of result block ;AN001; + RET ;RETURN TO CALLER ;AN001; +CALL_SYSPARSE ENDP ;AN001; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_PROFILE ;AN000; +; ;AN000; +; INPUT: ES:[BX] := Result block ;AN000; +; ;AN000; +; OUTPUT: PROFILE_PATH = The profile file name and path (ASCIIZ string) ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_PROFILE_NAME PROC ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Get the name of the profile path found on the command line: ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV DI,ES:[BX+4] ; DI := Offset of filename found ;AN000; + XOR BX,BX ; BX := Byte index ;AN000; + MOV SI,OFFSET PROFILE_PATH ; [BX][SI] := Where to store it ;AN000; + ;AN000; +.IF < NE 0> ; Don't copy a NULL parm ;AN000; + .REPEAT ; While not end of path name (NULL terminated) ;AN000; + MOV AL,[BX][DI] ; Copy the byte (including the NULL) ;AN000; + MOV [BX][SI],AL ;AN000; + INC BX ; Get next one ;AN000; + .UNTIL < EQ 0> ; ;AN000; +.ENDIF ;AN000; + ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + CLC ;AN000; + RET ;AN000; +GET_PROFILE_NAME ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_TYPE ;AN000; +; ;AN000; +; INPUT: ES:[BX] := Result block ;AN000; +; PRINTER_TYPE_LENGTH := Maximum length for the printer type string ;AN000; +; ;AN000; +; OUTPUT: PRINTER_TYPE_PARM = ASCIIZ string containing ;AN000; +; the Printer type. ;AN000; +; AX = Error code ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_TYPE PROC ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ;AN000; +;---------------------------------------------------------------------- ;AN000; +; Overwrite the DEFAULT TYPE with the type found on the command line ;AN000; +;---------------------------------------------------------------------- ;AN000; + MOV SI,ES:[BX+4] ; DS:SI := Offset of printer type found ;AN000; + .IF < NE 0> ; Do not copy an empty string ;AN000; + .THEN ; ;AN000; + MOV CL,PRINTER_TYPE_LENGTH ; CX := Maximum number of bytes ;AN000; + XOR CH,CH ; to copy ;AN000; + MOV DI,OFFSET PRINTER_TYPE_PARM; ES:DI := Where to store it ;AN000; + REP MOVSB ; Copy the string ;AN000; + ;---------------------------------------------------------------------- ;AN000; + ; Verify that the string supplied is not too long: ;AN000; + ;---------------------------------------------------------------------- ;AN000; + .IF < EQ 0> ; If the last byte is a null ;AN000; + .THEN ; then, the string was not longer ;AN000; + ; than the maximum ;AN000; + CLC ; Clear the carry flag = No error ;AN000; + .ELSE ; else, string provided is too long ;AN000; + MOV AX,RC_Not_In_Sw ; Error := RC for Invalid parm ;AN000; + STC ; Set error ;AN000; + .ENDIF ; ENDIF string too long ;AN000; + .ENDIF ; ENDIF string provided ;AN000; + ;AN000; +GET_TYPE_END: ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +GET_TYPE ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_REVERSE ;AN000; +; ;AN000; +; INPUT: ES:[BX] := Result block ;AN000; +; SWITCH_PARSED := The command line switches parsed so far (bit mask) ;AN000; +; ;AN000; +; OUTPUT: CS:[BP].SWITCHES (Bit mask in the Shared data area) is updated ;AN000; +; with the value of the switch found. ;AN000; +; GOT_R is set in SWITCH_PARSED ;AN000; +; AX := Error message number. ;AN000; +; CARRY FLAG IS SET IF ERROR FOUND ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_REVERSE PROC ;AN000; + ;AN000; + TEST SWITCH_PARSED,GOT_R ; If already parsed this switch ;AN000; + JNZ DUPLICATE_R ; then, error ;AN000; + OR SWITCH_PARSED,GOT_R ; else, say we parsed it. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set the Reverse switch in the Shared data area ;AN000; +;-------------------------------------------------------------------------------;AN000; + OR CS:[BP].SWITCHES,REVERSE_SW ; Set the command line switch ;AN000; + CLC ; Clear the error flag ;AN000; + JMP SHORT GET_REVERSE_END ; Return ;AN000; + ;AN000; +DUPLICATE_R: ; Already got this switch ;AN000; + MOV AX,RC_DUPLICATE_PARMS ; AX := error message number ;AN000; + STC ; SET ERROR ;AN000; +GET_REVERSE_END: ;AN000; + ;AN000; + RET ;AN000; +GET_REVERSE ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_BACKGROUND ;AN000; +; ;AN000; +; INPUT: ES:[BX] := Result block ;AN000; +; SWITCH_PARSED := The command line switches parsed so far (bit mask) ;AN000; +; ;AN000; +; OUTPUT: CS:[BP].SWITCHES (Bit mask in the Shared data area) is updated ;AN000; +; with the value of the switch found. ;AN000; +; ;AN000; +; GOT_B is set in SWITCH_PARSED ;AN000; +; AX := Error message number. ;AN000; +; CARRY FLAG IS SET IF ERROR FOUND ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_BACKGROUND PROC ;AN000; + ;AN000; + TEST SWITCH_PARSED,GOT_B ; If already parsed this switch ;AN000; + JNZ DUPLICATE_B ; then, error ;AN000; + OR SWITCH_PARSED,GOT_B ; else, say we parsed it. ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set the switch in the Shared data area ;AN000; +;-------------------------------------------------------------------------------;AN000; + OR CS:[BP].SWITCHES,BACKGROUND_SW ; Set the command line switch ;AN000; + CLC ; Clear the error flag ;AN000; + JMP SHORT GET_BACKGROUND_END ; Return ;AN000; + ;AN000; +DUPLICATE_B: ; Already got this switch ;AN000; + MOV AX,RC_DUPLICATE_PARMS ; AX := error message number ;AN000; + STC ; SET ERROR ;AN000; + ;AN000; +GET_BACKGROUND_END: ;AN000; + RET ;AN000; +GET_BACKGROUND ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_LCD ;AN000; +; ;AN000; +; INPUT: SWITCH_PARSED := The command line switches parsed so far (bit mask) ;AN000; +; ;AN000; +; OUTPUT: PRINTBOX_ID_PTR := Point to /LCD ASCIIZ string. ;AN000; +; GOT_B is set in SWITCH_PARSED ;AN000; +; AX := Error message number. ;AN000; +; CARRY FLAG IS SET IF ERROR FOUND ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Data Referenced: ;AN000; +; ;AN000; +; LCD_BOX = An ASCIIZ string representing the LCD printbox id. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_LCD PROC ;AN000; + ;AN000; + TEST SWITCH_PARSED,GOT_LCD ; If already parsed this switch ;AN000; + JNZ DUPLICATE_LCD ; then, error: Duplicate switch ;AN000; + TEST SWITCH_PARSED,GOT_PRINTBOX ; If printbox already mentioned ;AN000; + JNZ BAD_COMBINATION ; then, error: Invalid combination ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set the pointer to the print box id to "LCD" ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,OFFSET LCD_BOX ; PRINTBOX id := LCD ;AN000; + MOV PRINTBOX_ID_PTR,AX ; Save pointer to this printbox id. ;AN000; + OR SWITCH_PARSED,GOT_LCD ; Say we found this switch ;AN000; + CLC ; Clear the error flag ;AN000; + JMP SHORT GET_LCD_END ; Return ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; /LCD was already parsed: ;AN000; +;-------------------------------------------------------------------------------;AN000; +DUPLICATE_LCD: ; Already got this switch ;AN000; + MOV AX,RC_DUPLICATE_PARMS ; AX := error message number ;AN000; + STC ; SET ERROR ;AN000; + JMP SHORT GET_LCD_END ; Return ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; /PRINTBOX was already parsed: ;AN000; +;-------------------------------------------------------------------------------;AN000; +BAD_COMBINATION: ; /LCD and /PRINTBOX invalid at same ;AN000; + MOV AX,RC_INVLD_COMBINATION ; time, Set the error flag ;AN000; + STC ; AX := Error code ;AN000; + ;AN000; +GET_LCD_END: ;AN000; + RET ;AN000; +GET_LCD ENDP ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PROCEDURE_NAME: GET_PRINTBOX ;AN000; +; ;AN000; +; INPUT: ES:[BX] := Result block ;AN000; +; SWITCH_PARSED := The command line switches parsed so far (bit mask) ;AN000; +; ;AN000; +; OUTPUT: DEFAULT_BOX := Is overwritten to contain the printbox id. found on ;AN000; +; the command line. ;AN000; +; GOT_PRINTBOX is set in SWITCH_PARSED ;AN000; +; AX := Error message number. ;AN000; +; CARRY FLAG IS SET IF ERROR FOUND ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +GET_PRINTBOX_ID PROC ;AN000; + ;AN000; + PUSH CX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Test for error in the printbox statement: ;AN000; +;-------------------------------------------------------------------------------;AN000; + TEST SWITCH_PARSED,GOT_LCD ; If /LCD already mentioned ;AN000; + JNZ BAD_COMBINATION2 ; then, error: Invalid combination ;AN000; + TEST SWITCH_PARSED,GOT_PRINTBOX ; If already parsed this switch ;AN000; + JNZ DUPLICATE_PRINTBOX ; then, error: Duplicate switch ;AN000; + ;AN000; + MOV DI,ES:[BX+4] ; DI := Offset of switch VALUE found;AN000; + ;AN000; + .IF < EQ 0> ; IF no printbox id ;AN000; + .THEN ; then, ;AN000; + ;----------------------------------------------------------------------;AN000; + ; No printbox id. was found: ;AN000; + ;----------------------------------------------------------------------;AN000; + MOV AX,FORMAT_NOT_CORRECT ; AX := Error code ;AN000; + STC ; Set the error flag ;AN000; + .ELSE ; else, ;AN000; + OR SWITCH_PARSED,GOT_PRINTBOX; Say we found this switch ;AN000; + ;----------------------------------------------------------------------;AN000; + ; Overwrite DEFAULT_BOX with the Printbox id. found ;AN000; + ;----------------------------------------------------------------------;AN000; + MOV CL,PRINTBOX_ID_LENGTH ; CX := Maximum number of bytes ;AN000; + XOR CH,CH ; to copy ;AN000; + MOV SI,DI ; [DS][SI] := Value found ;AN000; + MOV DI,OFFSET DEFAULT_BOX ; [ES][DI] := Default value ;AN000; + REP MOVSB ; Copy the string ;AN000; + ;----------------------------------------------------------------------;AN000; + ; Verify that the Printbox id. string is not too long: ;AN000; + ;----------------------------------------------------------------------;AN000; + .IF < EQ 0> ; If the last byte is a null ;AN000; + .THEN ; then, the string was not longer ;AN000; + ; than the maximum ;AN000; + CLC ; Clear the carry flag = No error ;AN000; + .ELSE ; else, string provided is too long ;AN000; + MOV AX,RC_Not_In_Sw ; Error := RC for Invalid parm ;AN000; + STC ; Set error ;AN000; + .ENDIF ; ENDIF printbox id. too long ;AN000; + .ENDIF ; ENDIF printbox id. provided ;AN000; + ;AN000; + JMP SHORT GET_PRINTBOX_END ; Return ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; /PRINTBOX was already parsed: ;AN000; +;-------------------------------------------------------------------------------;AN000; +DUPLICATE_PRINTBOX: ; Already got this switch ;AN000; + MOV AX,RC_DUPLICATE_PARMS ; AX := error message number ;AN000; + STC ; SET ERROR ;AN000; + JMP SHORT GET_PRINTBOX_END ; Return ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; /LCD was already parsed: ;AN000; +;-------------------------------------------------------------------------------;AN000; +BAD_COMBINATION2: ; /LCD and /PRINTBOX invalid at same;AN000; + MOV AX,RC_INVLD_COMBINATION ; time, Set the error flag ;AN000; + STC ; AX := Error code ;AN000; + ;AN000; +GET_PRINTBOX_END: ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP CX ;AN000; + RET ;AN000; +GET_PRINTBOX_ID ENDP ;AN000; + ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPARMS.EXT b/v4.0/src/CMD/GRAPHICS/GRPARMS.EXT new file mode 100644 index 0000000..3587787 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPARMS.EXT @@ -0,0 +1,24 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPARMS.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRPARMS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN PARSE_PARMS:NEAR ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPARSE.ASM b/v4.0/src/CMD/GRAPHICS/GRPARSE.ASM new file mode 100644 index 0000000..3d837bb --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPARSE.ASM @@ -0,0 +1,87 @@ + PAGE ,132 ;AN000; + TITLE DOS GRAPHICS Command - Profile Load Modules #2 + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRLOAD.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the modules used to load the ;AN000; +;; GRAPHICS profile into resident memory. ;AN000; +;; ;AN000; +;; ************* The EGA Dynamic Save Area will be built (by ;AN000; +;; ** NOTE ** CHAIN_INTERRUPTS in file GRINST.ASM) over top of these ;AN000; +;; ************* modules to avoid having to relocate this save just before ;AN000; +;; terminating. This is safe since the maximum memory used is ;AN000; +;; 288 bytes and the profile loading modules are MUCH larger than ;AN000; +;; this. So GRLOAD.ASM MUST be linked before GRINST.ASM and after ;AN000; +;; GRPRINT.ASM. ;AN000; +;; ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; PLACID Functional Specifications ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; LOAD_PROFILE - Main module for profile loading ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; ?????????? - Externals for profile loading modules ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; None ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; --------------------- ;AN000; +;; Refer to GRAPHICS.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;; ;AN000; + ;; ;AN000; + INCLUDE STRUC.INC ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; Public Symbols ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + ASSUME CS:CODE,DS:CODE ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set assemble switches for parse code that is not required!! ;AN000; +;-------------------------------------------------------------------------------;AN000; +DateSW EQU 0 ;AN000; +TimeSW EQU 0 ;AN000; +CmpxSW EQU 0 ;AN000; +DrvSW EQU 0 ;AN000; +QusSW EQU 0 ;AN000; +KeySW EQU 0 ;AN000; +;Val1SW EQU 0 ;AN000; +;Val2SW EQU 0 ;AN000; + ;AN000; + PUBLIC SYSPARSE ;; ;AN000; + INCLUDE PARSE.ASM ;; parser code ;AN000; + ;; ;AN000; +CODE ENDS ;; ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPARSE.EXT b/v4.0/src/CMD/GRAPHICS/GRPARSE.EXT new file mode 100644 index 0000000..416c664 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPARSE.EXT @@ -0,0 +1,24 @@ +.XLIST ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRINST.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRLOAD.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN SYSPARSE:NEAR ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPATTRN.ASM b/v4.0/src/CMD/GRAPHICS/GRPATTRN.ASM new file mode 100644 index 0000000..06aed1b --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPATTRN.ASM @@ -0,0 +1,217 @@ + PAGE ,132 ;AN000; + TITLE DOS - GRAPHICS Command - Common modules ;AN000; +.xlist ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPATTRN.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; This file contains the grey patterns used by PRT_BW_APA for printing ;AN000; +;; on a Black and White printer. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; none ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; GRPATTRN.STR - Structures for patterns. ;AN000; +;; ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; ;AN000; +;; Called by PRT_BW_APA from file GRBWPRT.ASM ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.list ;AN000; +CODE SEGMENT PUBLIC 'CODE' ;AN000; + ASSUME CS:CODE,DS:CODE ;AN000; +INCLUDE GRPATTRN.STR ;AN000; + ;AN000; +PUBLIC TAB_DIRECTORY ;AN000; +PUBLIC TAB_DIR_NB_ENTRIES ;AN000; +PUBLIC PAT_4X2 ;AN000; +PUBLIC PAT_4X4 ;AN000; +PUBLIC PAT_6X2 ;AN000; +PUBLIC PAT_8X2 ;AN000; +PUBLIC PAT_6X4 ;AN000; +PUBLIC PAT_8X4 ;AN000; +PUBLIC PAT_8X6 ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; PATTERN DIRECTORY: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +TAB_DIR_NB_ENTRIES DB 7 ;AN000; +TAB_DIRECTORY LABEL BYTE ;AN000; +; ENTRY = ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; + TAB_ENTRY ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 4X2 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_4X2 LABEL BYTE ;AN000; +; PATTERN= ;AN000; + PAT_4X2_STR < 5,11B,11B,11B,11B> ;AN000; + PAT_4X2_STR <13,11B,10B,01B,11B> ;AN000; + PAT_4X2_STR <20,10B,11B,01B,10B> ;AN000; + PAT_4X2_STR <28,10B,01B,01B,10B> ;AN000; + PAT_4X2_STR <36,10B,00B,01B,10B> ;AN000; + PAT_4X2_STR <47,10B,00B,01B,00B> ;AN000; + PAT_4X2_STR <58,10B,00B,00B,00B> ;AN000; + PAT_4X2_STR <63,00B,00B,00B,00B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 4X4 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_4X4 LABEL BYTE ;AN000; +; PATTERN= ;AN000; + PAT_4X4_STR < 5,1111B,1111B,1111B,1111B> ;AN000; + PAT_4X4_STR <13,1111B,1010B,0101B,1111B> ;AN000; + PAT_4X4_STR <20,1010B,1111B,0101B,1010B> ;AN000; + PAT_4X4_STR <28,1010B,0101B,0101B,1010B> ;AN000; + PAT_4X4_STR <36,1010B,0000B,0101B,1010B> ;AN000; + PAT_4X4_STR <47,1010B,0000B,0101B,0000B> ;AN000; + PAT_4X4_STR <58,1010B,0000B,0000B,0000B> ;AN000; + PAT_4X4_STR <63,0000B,0000B,0000B,0000B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 6X2 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_6X2 LABEL BYTE ;AN000; + PAT_6X2_STR < 3,11B,11B,11B,11B,11B,11B> ;AN000; + PAT_6X2_STR < 8,11B,11B,10B,11B,11B,01B> ;AN000; + PAT_6X2_STR <15,10B,01B,10B,11B,10B,01B> ;AN000; + PAT_6X2_STR <21,01B,10B,10B,01B,10B,10B> ;AN000; + PAT_6X2_STR <28,01B,10B,10B,01B,10B,00B> ;AN000; + PAT_6X2_STR <36,10B,01B,00B,10B,01B,00B> ;AN000; + PAT_6X2_STR <45,00B,10B,00B,01B,00B,10B> ;AN000; + PAT_6X2_STR <53,10B,00B,00B,01B,00B,00B> ;AN000; + PAT_6X2_STR <60,10B,00B,00B,00B,00B,00B> ;AN000; + PAT_6X2_STR <63,00B,00B,00B,00B,00B,00B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 8X2 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_8X2 LABEL BYTE ;AN000; + PAT_8X2_STR < 3,11B,11B,11B,11B,11B,11B,11B,11B> ;AN000; + PAT_8X2_STR < 9,11B,11B,10B,11B,11B,10B,11B,01B> ;AN000; + PAT_8X2_STR <15,10B,11B,01B,11B,10B,11B,00B,11B> ;AN000; + PAT_8X2_STR <21,10B,01B,11B,10B,01B,10B,01B,10B> ;AN000; + PAT_8X2_STR <27,10B,01B,01B,10B,10B,01B,01B,10B> ;AN000; + PAT_8X2_STR <33,00B,10B,01B,10B,00B,01B,10B,01B> ;AN000; + PAT_8X2_STR <39,10B,00B,10B,01B,00B,10B,00B,01B> ;AN000; + PAT_8X2_STR <45,10B,00B,01B,00B,10B,00B,01B,00B> ;AN000; + PAT_8X2_STR <51,10B,00B,00B,01B,00B,00B,10B,00B> ;AN000; + PAT_8X2_STR <56,10B,00B,00B,00B,01B,00B,00B,00B> ;AN000; + PAT_8X2_STR <61,10B,00B,00B,00B,00B,00B,00B,00B> ;AN000; + PAT_8X2_STR <63,00B,00B,00B,00B,00B,00B,00B,00B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 6X4 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_6X4 LABEL BYTE ;AN000; + PAT_6X4_STR < 3,1111B,1111B,1111B,1111B,1111B,1111B> ;AN000; + PAT_6X4_STR < 8,1111B,1111B,1101B,1111B,1111B,1011B> ;AN000; + PAT_6X4_STR <13,1111B,1111B,0101B,1011B,1111B,1010B> ;AN000; + PAT_6X4_STR <16,0101B,1111B,0101B,1010B,0101B,1010B> ;AN000; + PAT_6X4_STR <20,0101B,1110B,0101B,1010B,0101B,1010B> ;AN000; + PAT_6X4_STR <24,1010B,0101B,1010B,0101B,0010B,0101B> ;AN000; + PAT_6X4_STR <28,1010B,0101B,1000B,0101B,0010B,0101B> ;AN000; + PAT_6X4_STR <32,1010B,0101B,1000B,1001B,0010B,0100B> ;AN000; + PAT_6X4_STR <37,1010B,0000B,1010B,0101B,0000B,0101B> ;AN000; + PAT_6X4_STR <40,0100B,0001B,1000B,0010B,1000B,0101B> ;AN000; + PAT_6X4_STR <45,0100B,0010B,1000B,0010B,0100B,0001B> ;AN000; + PAT_6X4_STR <49,1010B,0000B,1000B,0101B,0000B,0000B> ;AN000; + PAT_6X4_STR <52,1010B,0000B,0000B,0101B,0000B,0000B> ;AN000; + PAT_6X4_STR <55,0000B,1000B,0000B,0010B,0000B,0100B> ;AN000; + PAT_6X4_STR <58,1000B,0000B,0000B,0010B,0000B,0000B> ;AN000; + PAT_6X4_STR <61,1000B,0000B,0000B,0000B,0000B,0000B> ;AN000; + PAT_6X4_STR <63,0000B,0000B,0000B,0000B,0000B,0000B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 8X4 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_8X4 LABEL BYTE ;AN000; + PAT_8X4_STR < 1,1111B,1111B,1111B,1111B,1111B,1111B,1111B,1111B> ;AN000; + PAT_8X4_STR < 4,1010B,1111B,1111B,1111B,1010B,1111B,1111B,1111B> ;AN000; + PAT_8X4_STR < 7,1010B,1111B,1101B,1111B,1010B,1111B,0111B,1111B> ;AN000; + PAT_8X4_STR <10,1010B,0111B,1110B,0101B,1010B,1101B,1011B,0101B> ;AN000; + PAT_8X4_STR <13,1001B,1110B,0110B,1001B,0110B,1011B,1001B,0110B> ;AN000; + PAT_8X4_STR <18,1010B,0101B,1110B,0101B,1010B,0101B,1010B,0101B> ;AN000; + PAT_8X4_STR <24,1010B,0101B,0101B,1010B,1010B,0101B,0101B,1010B> ;AN000; + PAT_8X4_STR <30,1010B,0101B,1010B,0000B,0101B,1010B,0101B,0000B> ;AN000; + PAT_8X4_STR <36,1010B,0000B,1010B,0101B,0000B,1010B,0000B,0101B> ;AN000; + PAT_8X4_STR <42,1010B,0000B,0101B,0000B,1010B,0000B,0101B,0000B> ;AN000; + PAT_8X4_STR <46,0010B,1000B,0000B,0010B,1000B,0001B,0100B,0001B> ;AN000; + PAT_8X4_STR <48,1010B,0000B,0101B,0000B,0000B,1010B,0000B,0000B> ;AN000; + PAT_8X4_STR <50,0010B,0000B,1000B,0010B,0000B,0100B,0001B,0000B> ;AN000; + PAT_8X4_STR <53,1010B,0000B,0000B,0000B,0101B,0000B,0000B,0000B> ;AN000; + PAT_8X4_STR <56,0000B,1000B,0000B,0000B,0100B,0000B,0000B,0010B> ;AN000; + PAT_8X4_STR <59,1000B,0000B,0000B,0000B,0010B,0000B,0000B,0000B> ;AN000; + PAT_8X4_STR <62,1000B,0000B,0000B,0000B,0000B,0000B,0000B,0000B> ;AN000; + PAT_8X4_STR <63,0000B,0000B,0000B,0000B,0000B,0000B,0000B,0000B> ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; 8X6 GREY PATTERNS: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PAT_8X6 LABEL BYTE ;AN000; + PAT_8X6_STR < 1,111111B,111111B,111111B,111111B,111111B,111111B,111111B,111111B>;AN000; + PAT_8X6_STR < 4,011011B,111111B,111111B,111111B,110110B,111111B,111111B,111111B>;AN000; + PAT_8X6_STR < 7,101010B,011111B,111111B,110101B,101010B,011111B,111111B,110101B>;AN000; + PAT_8X6_STR <10,101010B,010101B,111111B,101010B,010101B,101010B,111111B,010101B>;AN000; + PAT_8X6_STR <13,011011B,100100B,111011B,100100B,011011B,100100B,011111B,100100B>;AN000; + PAT_8X6_STR <17,101010B,010101B,101010B,010101B,101010B,010101B,101010B,010101B>;AN000; + PAT_8X6_STR <21,101010B,010101B,101010B,010101B,001010B,010101B,101010B,010101B>;AN000; + PAT_8X6_STR <25,010100B,101010B,010101B,001010B,100100B,010001B,101110B,000001B>;AN000; + PAT_8X6_STR <29,000000B,010101B,101010B,010101B,000000B,101010B,010101B,101010B>;AN000; + PAT_8X6_STR <33,010010B,100101B,011000B,100010B,001101B,100000B,001010B,100100B>;AN000; + PAT_8X6_STR <37,100100B,001010B,010000B,001001B,100010B,001101B,010000B,001010B>;AN000; + PAT_8X6_STR <41,100000B,010010B,100100B,000010B,101000B,000101B,010000B,001010B>;AN000; + PAT_8X6_STR <45,100010B,001000B,000010B,100000B,010100B,000001B,100100B,000000B>;AN000; + PAT_8X6_STR <49,101000B,000001B,000100B,010000B,000010B,100000B,001000B,000101B>;AN000; + PAT_8X6_STR <53,101010B,000000B,000000B,000000B,010101B,000000B,000000B,000000B>;AN000; + PAT_8X6_STR <57,000000B,010000B,000000B,000100B,000000B,100000B,000000B,000010B>;AN000; + PAT_8X6_STR <60,100000B,000000B,000000B,000000B,000100B,000000B,000000B,000000B>;AN000; + PAT_8X6_STR <62,100000B,000000B,000000B,000000B,000000B,000000B,000000B,000000B>;AN000; + PAT_8X6_STR <63,000000B,000000B,000000B,000000B,000000B,000000B,000000B,000000B>;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPATTRN.EXT b/v4.0/src/CMD/GRAPHICS/GRPATTRN.EXT new file mode 100644 index 0000000..cfe1dad --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPATTRN.EXT @@ -0,0 +1,31 @@ +PAGE ,132 ;AN000; +.XLIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPATTRN.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing external declarations for ;AN000; +;; the data defined in GRPATTRN.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; +EXTRN PAT_4X2:BYTE ;AN000; +EXTRN PAT_4X4:BYTE ;AN000; +EXTRN PAT_6X2:BYTE ;AN000; +EXTRN PAT_8X2:BYTE ;AN000; +EXTRN PAT_6X4:BYTE ;AN000; +EXTRN PAT_8X4:BYTE ;AN000; +EXTRN PAT_8X6:BYTE ;AN000; +EXTRN TAB_DIRECTORY:NEAR ;AN000; +EXTRN TAB_DIR_NB_ENTRIES:BYTE ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPATTRN.STR b/v4.0/src/CMD/GRAPHICS/GRPATTRN.STR new file mode 100644 index 0000000..1e2947d --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPATTRN.STR @@ -0,0 +1,125 @@ +.XLIST ;AN000; +PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPATTRN.STR ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing structures for ;AN000; +;; the Printer grey patterns. ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; + ;AN000; +TAB_ENTRY STRUC ; TABLE DIRECTORY ENTRY USED TO LOCATED ;AN000; + ; WHAT TABLE OF PATTERNS TO USE ;AN000; + TAB_OFFSET DW ? ; ADDRESS OF THE PATTERN TABLE ;AN000; + TAB_COPY DW ? ; ADDRESS OF PATTERN TABLE COPY IN SHARED DATA ;AN000; + TAB_SIZE DW ? ; SIZE OF THE PATTERN TABLE ;AN000; + BOX_W_PAT DB ? ; BOX WIDTH FOR PATTERNS IN THIS TABLE ;AN000; + BOX_H_PAT DB ? ; BOX HEIGHT FOR PATTERNS IN THIS TABLE ;AN000; + NB_INT DB ? ; NUMBER OF INTENSITIES IN THIS TABLE ;AN000; +TAB_ENTRY ENDS ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; PATTERN TYPES: ;AN000; +; ;AN000; +; The maximum intensity field represents the upper bound for using ;AN000; +; a pattern (e.g., the acual intensity of a specific pattern may be ;AN000; +; 25 but, it will be used for printing intensities of up to 32). ;AN000; +; Intensities range from 0 = Black to 63 = White. ;AN000; +; ;AN000; +; For example, a 4x2 structure represents the following pattern: ;AN000; +; --- ;AN000; +; ;AN000; +; BYTES: C1_4X2 C2_4X2 C3_4X2 C4_4X2 ;AN000; +; ;AN000; +; Top dot to print ------> 0 0 0 0 ;AN000; +; ;AN000; +; Least significatnt bit ------> 0 0 0 0 ;AN000; +; of the byte is the dot ;AN000; +; printed below. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + ;AN000; +PAT_4X2_STR STRUC ; PATTERN MADE OF 2X1 BOXES ;AN000; + MAX_4X2 DB ? ; Maximum intensity ;AN000; + C1_4X2 DB 00B ; Column 1 (Leftmost column) ;AN000; + C2_4X2 DB 00B ; Column 2 ;AN000; + C3_4X2 DB 00B ; Column 3 ;AN000; + C4_4X2 DB 00B ; Column 4 (Rightmost column) ;AN000; +PAT_4X2_STR ENDS ;AN000; + ;AN000; +PAT_4X4_STR STRUC ; PATTERN MADE OF 2X2 BOXES ;AN000; + MAX_4X4 DB ? ; Maximum intensity ;AN000; + C1_4X4 DB 0000B ; Column 1 (Leftmost column) ;AN000; + C2_4X4 DB 0000B ; Column 2 ;AN000; + C3_4X4 DB 0000B ; Column 3 ;AN000; + C4_4X4 DB 0000B ; Column 4 (Rightmost column) ;AN000; +PAT_4X4_STR ENDS ;AN000; + ;AN000; +PAT_6X2_STR STRUC ; PATTERN MADE OF 3X1 BOXES ;AN000; + MAX_6X2 DB ? ; Maximum intensity ;AN000; + C1_6X2 DB 00B ; Column 1 (Leftmost column) ;AN000; + C2_6X2 DB 00B ; Column 2 ;AN000; + C3_6X2 DB 00B ; Column 3 ;AN000; + C4_6X2 DB 00B ; Column 4 ;AN000; + C5_6X2 DB 00B ; Column 5 ;AN000; + C6_6X2 DB 00B ; Column 6 (Rightmost column) ;AN000; +PAT_6X2_STR ENDS ;AN000; + ;AN000; +PAT_8X2_STR STRUC ; PATTERN MADE OF 4X1 BOXES ;AN000; + MAX_8X2 DB ? ; Maximum intensity ;AN000; + C1_8X2 DB 00B ; Column 1 (Leftmost column) ;AN000; + C2_8X2 DB 00B ; Column 2 ;AN000; + C3_8X2 DB 00B ; Column 3 ;AN000; + C4_8X2 DB 00B ; Column 4 ;AN000; + C5_8X2 DB 00B ; Column 5 ;AN000; + C6_8X2 DB 00B ; Column 6 ;AN000; + C7_8X2 DB 00B ; Column 7 ;AN000; + C8_8X2 DB 00B ; Column 8 (Rightmost column) ;AN000; +PAT_8X2_STR ENDS ;AN000; + ;AN000; +PAT_8X4_STR STRUC ; PATTERN MADE OF 4X2 BOXES ;AN000; + MAX_8X4 DB ? ; Maximum intensity ;AN000; + C1_8X4 DB 0000B ; Column 1 (Leftmost column) ;AN000; + C2_8X4 DB 0000B ; Column 2 ;AN000; + C3_8X4 DB 0000B ; Column 3 ;AN000; + C4_8X4 DB 0000B ; Column 4 ;AN000; + C5_8X4 DB 0000B ; Column 5 ;AN000; + C6_8X4 DB 0000B ; Column 6 ;AN000; + C7_8X4 DB 0000B ; Column 7 ;AN000; + C8_8X4 DB 0000B ; Column 8 (Rightmost column) ;AN000; +PAT_8X4_STR ENDS ;AN000; + ;AN000; +PAT_6X4_STR STRUC ; PATTERN MADE OF 3X2 BOXES ;AN000; + MAX_6X4 DB ? ; Maximum intensity ;AN000; + C1_6X4 DB 0000B ; Column 1 (Leftmost column) ;AN000; + C2_6X4 DB 0000B ; Column 2 ;AN000; + C3_6X4 DB 0000B ; Column 3 ;AN000; + C4_6X4 DB 0000B ; Column 4 ;AN000; + C5_6X4 DB 0000B ; Column 5 ;AN000; + C6_6X4 DB 0000B ; Column 6 (Rightmost column) ;AN000; +PAT_6X4_STR ENDS ;AN000; + ;AN000; +PAT_8X6_STR STRUC ; PATTERN MADE OF 4X3 BOXES ;AN000; + MAX_8X6 DB ? ; Maximum intensity ;AN000; + C1_8X6 DB 000000B ; Column 1 (Leftmost column) ;AN000; + C2_8X6 DB 000000B ; Column 2 ;AN000; + C3_8X6 DB 000000B ; Column 3 ;AN000; + C4_8X6 DB 000000B ; Column 4 ;AN000; + C5_8X6 DB 000000B ; Column 5 ;AN000; + C6_8X6 DB 000000B ; Column 6 ;AN000; + C7_8X6 DB 000000B ; Column 7 ;AN000; + C8_8X6 DB 000000B ; Column 8 (Rightmost column) ;AN000; +PAT_8X6_STR ENDS ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRPRINT.EXT b/v4.0/src/CMD/GRAPHICS/GRPRINT.EXT new file mode 100644 index 0000000..a4d0732 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRPRINT.EXT @@ -0,0 +1,29 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRPRINT.EXT ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; External declarations for code and data defined in ;AN000; +;; GRPRINT.ASM ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; + EXTRN PRINT_MODULE_START:NEAR ;; ;AN000; + EXTRN LEN_OF_BW_MODULES:ABS ;; ;AN000; + EXTRN LEN_OF_COLOR_MODULES:ABS ;; ;AN000; + EXTRN COLOR_PRINT_MODULES:NEAR ;; ;AN000; + EXTRN BW_PRINT_MODULES:NEAR ;; ;AN000; + EXTRN PRINT_COLOR:NEAR ;; ;AN000; + EXTRN RGB2BAND:NEAR ;; ;AN000; + EXTRN PRINT_BW_APA:NEAR ;; ;AN000; + EXTRN RGB2INT:NEAR ;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/GRSHAR.STR b/v4.0/src/CMD/GRAPHICS/GRSHAR.STR new file mode 100644 index 0000000..5e62727 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRSHAR.STR @@ -0,0 +1,127 @@ +.XLIST ;AN000; +PAGE ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (C) Copyright IBM Corp 198?,... ;AN000; +;; ;AN000; +;; File Name: GRSHAR.STR ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; Include file containing structures and equates for ;AN000; +;; Shared Data Area. ;AN000; +;; ;AN000; +;; This area is used for communication between the installation process ;AN000; +;; and the Print Screen process; it contains all the information ;AN000; +;; extracted from the printer profile. ;AN000; +;; ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +.LIST ;AN000; + ; ;AN000; +SHARED_DATA_AREA_STR STRUC ; ;AN000; + SD_TOTAL_SIZE DW ? ; Total # bytes ALLOCATED to the ;AN000; + ; the Shared Data Area. ;AN000; + ;;;;;;;;;;;; Environment ;;;;;;;;;;;;;; ;AN000; + SWITCHES DB 0 ; Command line switches ;AN000; + HARDWARE_CONFIG DB ? ; Type of video hardware ;AN000; + PRINTER_TYPE DB ? ; Type of printer attached ;AN000; + ; ;AN000; + ;;;;;;;;;;;; Profile Data ;;;;;;;;;;;;; ;AN000; + DARKADJUST_VALUE DB 0 ; Darkness adjustment value ;AN000; + ; ;AN000; + NUM_PRT_COLOR DB ? ; Number of print colors ;AN000; + COLORPRINT_PTR DW ? ; Pointer to COLORPRINT info ;AN000; + ; ;AN000; + NUM_PRT_BANDS DB ? ; Number of selectable print bands ;AN000; + COLORSELECT_PTR DW ? ; Pointer to COLORSELECT info ;AN000; + ; bands ;AN000; + DISPLAYMODE_PTR DW ? ; Pointer to start of DISPLAYMODE ;AN000; + ; info ;AN000; +SHARED_DATA_AREA_STR ENDS ;; ;AN000; + ;AN000; + ;AN000; +;;;;;;;;; COLORSELECT info structure ;;;; ;AN000; + ; ;AN000; +COLORSELECT_STR STRUC ; ;AN000; + NUM_SELECT_ESC DB ? ; number of escape bytes to ;AN000; + ; select this band ;AN000; + SELECT_ESC DB ? ; Escape bytes to select band ;AN000; +COLORSELECT_STR ENDS ;; ;AN000; + ;AN000; + ;AN000; + ;AN000; +;;;;;;;;; COLORPRINT info structure ;;;;; ;AN000; + ; ;AN000; +COLORPRINT_STR STRUC ; ;AN000; + RED DB ? ; RGB value ;AN000; + GREEN DB ? ; ;AN000; + BLUE DB ? ; ;AN000; + ; Bit mask indicating color ;AN000; + SELECT_MASK DB ? ; bands required: ;AN000; + ; Bit 0: first band in table ;AN000; +COLORPRINT_STR ENDS ;; Bit 1: second band... ;AN000; + ;AN000; + ;AN000; +;;;;;;;;; DISPLAYMODE info structure ;;;; ;AN000; + ; A new block is built when a ;AN000; +DISPLAYMODE_STR STRUC ; DISPLAYMODE statement is ;AN000; + ; found ;AN000; + NEXT_DISP_MODE DW ? ; Pointer to info for next ;AN000; + ; display mode; -1 if last ;AN000; + NUM_DISP_MODE DB ? ; Number of display modes for ;AN000; + DISP_MODE_LIST_PTR DW ? ; this record - list of them ;AN000; + ; ;AN000; + BOX_WIDTH DB ? ; Print box size - horizontal ;AN000; + BOX_HEIGHT DB ? ; Print box size - vertical ;AN000; + ; ;AN000; + NUM_PATTERNS DB ? ; Number of grey patterns for ;AN000; + ; this box size ;AN000; + PATTERN_TAB_PTR DW ? ; pointer to grey pattern table ;AN000; + ; for this display mode ;AN000; + NUM_GRAPHICS_ESC DB ? ; # of escape byte for GRAPHICS ;AN000; + GRAPHICS_ESC_PTR DW ? ; pointer to GRAPHICS escape ;AN000; + LOW_BYT_COUNT_PTR DW ? ; pointers to number of bytes sent ;AN000; + HGH_BYT_COUNT_PTR DW ? ; to the printer (1 word holds this ;AN000; + ; number but, must be send 1 byte ;AN000; + ; at a time). ;AN000; + NUM_SETUP_ESC DB ? ; # of escape byte for SETUP ;AN000; + SETUP_ESC_PTR DW ? ; pointer to SETUP escape seq ;AN000; + ; for this display mode ;AN000; + NUM_RESTORE_ESC DB ? ; # of escape byte for RESTORE ;AN000; + RESTORE_ESC_PTR DW ? ; pointer to RESTORE escape ;AN000; + ; seq for this display mode ;AN000; + PRINT_OPTIONS DB ? ; ;AN000; + ; ;AN000; +DISPLAYMODE_STR ENDS ;; ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; ;AN000; +;; SHARED DATA AREA - EQUATES ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +; SWITCHES DB ; Command line switches: ;AN000; + REVERSE_SW EQU 1 ; /R ;AN000; + BACKGROUND_SW EQU 2 ; /B ;AN000; + ; ;AN000; +; HARDWARE_CONFIG DB ; Type of video hardware ;AN000; + PALACE EQU 1 ; attached ;AN000; + ROUNDUP EQU 2 ; PS 2 MODEL 50 60 AND 80 ;AN000; + EGA EQU 4 ; Enhance Graphics Adapter ;AN000; + PC_CONVERTIBLE EQU 8 ; PC Convertible LCD ;AN000; + OLD_ADAPTER EQU 16 ; Color Graph. Adater or MONO ;AN000; + ; ;AN000; +; PRINTER_TYPE DB ; Type of printer attached ;AN000; + COLOR EQU 1 ; ;AN000; + BLACK_WHITE EQU 2 ; ;AN000; + ; ;AN000; +; PRINT_OPTIONS DB ; ;AN000; + ROTATE EQU 1 ; ;AN000; diff --git a/v4.0/src/CMD/GRAPHICS/MAKEFILE b/v4.0/src/CMD/GRAPHICS/MAKEFILE new file mode 100644 index 0000000..af52400 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/MAKEFILE @@ -0,0 +1,64 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: graphics.com + + +graphics.ctl: graphics.skl $(msg)\$(COUNTRY).msg + +graphics.obj: graphics.asm grinst.ext makefile + +grinst.obj: grinst.asm grload.ext grload2.ext grctrl.ext grprint.ext \ + grcpsd.ext grparms.ext grparse.ext grbwprt.ext grcolprt.ext \ + grint2fh.ext grmsg.equ graphics.ctl graphics.cla graphics.cl1 \ + graphics.clb \ + graphics.cl2 graphics.clc \ + $(inc)\sysmsg.inc $(inc)\struc.inc grshar.str makefile + +grcpsd.obj: grparse.asm makefile $(inc)\parse.asm + +grparse.obj: grcpsd.asm makefile + +grpattrn.obj: grpattrn.asm grpattrn.str makefile + +grbwprt.obj: grbwprt.asm grcommon.ext grctrl.str grshar.str makefile \ + grpattrn.str $(inc)\struc.inc makefile + +grint2fh.obj: grint2fh.asm grload.ext grctrl.ext grprint.ext \ + grcpsd.ext makefile + +grctrl.obj: grctrl.asm grint2fh.ext grbwprt.ext grcolprt.ext grshar.str \ + grpattrn.str grpattrn.ext grctrl.str $(inc)\struc.inc \ + makefile + +grcolprt.obj: grctrl.str grshar.str grpattrn.str grctrl.ext \ + $(inc)\struc.inc grcommon.asm makefile + +grload.obj: grload.asm $(inc)\struc.inc grinst.ext grshar.str grparse.ext \ + grload2.ext grload3.ext grmsg.equ makefile + +grload2.obj: grload2.asm $(inc)\struc.inc grinst.ext grshar.str grmsg.equ \ + grinst.ext grload.ext grparse.ext grpattrn.str grpattrn.ext \ + makefile + +grload3.obj: grload3.asm $(inc)\struc.inc grinst.ext grshar.str grmsg.equ \ + grinst.ext grload.ext grload2.ext grparse.ext grpattrn.str \ + grpattrn.ext makefile + +grparms.obj: grparms.asm grmsg.equ grshar.str grinst.ext grparse.ext \ + $(inc)\struc.inc makefile + +graphics.com: graphics.obj grint2fh.obj grpattrn.obj grctrl.obj grcpsd.obj \ + grcolprt.obj grbwprt.obj grinst.obj grparse.obj grparms.obj \ + grload.obj grload2.obj grload3.obj graphics.lnk + link @graphics.lnk + exe2bin graphics.exe graphics.com + del graphics.exe diff --git a/v4.0/src/CMD/IFSFUNC/IFSDEV.ASM b/v4.0/src/CMD/IFSFUNC/IFSDEV.ASM new file mode 100644 index 0000000..1ad88ff --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSDEV.ASM @@ -0,0 +1,1267 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsdev.asm 1.0 87/05/11 ;AN000; +TITLE IFSFUNC DEVICE ROUTINES - Device/IOCTL routines ;AN000; +NAME IFSDEV ;AN000; + ;AN000; +;****************************************************************************** +; +; Device related IFS calls +; +; Printer_GetSet_String +; IFS_Device_Check +; IFS_Device_Close +; IFS_Device_Oper +; IFS_Spool_Echo_Check +; IFS_DEPENDENT_IOCTL +; DEVICE_IOCTL +; GET_DFL_FROM_INDEX +; +; Programming notes: +; Old redirector segmentation and DOS interface preserved. +; Routine prologues are accurate for input/output. +; However, the pseudocode was not kept up to date. +; Use it for a rough idea of the routine function. +; +; REVISION HISTORY: +; A000 Original version 4.00 May 1987 +; A001 DCR 187 - ctrl req renumber, make attach type byte 8/87 RGAZZIA +; A002 PTM 764 - printer attach problems 8/87 RGAZZIA +; A003 PTM 849 - printer open problems 8/87 RGAZZIA +; A004 PTM 1244- Net Print problems 8/87 RGAZZIA +; A005 PTM 1600- dev ioctl ds bug 8/87 RGAZZIA +; A006 PTM 3619- thiscds,thissft not set in ifs dep ioctl 2/88 RGazzia +; A007 PTM 3971 Austin Print bug raid 3/88 RMG +; A008 PTM 4055 UNC problems (make sure thisdfl null on error) 3/30/88 RMG +; A009 PTM 4188 Names=0 problems 4/08/88 RMG +; A010 PTM 4554 Echo across network in vitt alt task 5/12/88 RMG +; A011 PTM 4841 Ctrl ptrsc problems 5/13/88 RMG +; A012 PTM 4885 ifs dept ioctl not recog non-ifs drive 5/17/88 RMG +; A013 PTM 4791 problem with ax error code overwrite 5/19/88 RMG +; A014 PTM 4946 net - no ptrs 5E02 doesn't return error 5/20/88 RMG +; A015 PTM 5005 get truncate flag faulty - ret on user stack 6/02/88 RMG +; LOC - 477 +; +;****************************************************************************** + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; include THE REST Of the segment definitions for normal MSDOS ;AN000; + ;AN000; +.xlist ;AN000; +include dosseg.asm ;AN000; +.list ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ; DOSGROUP Data ;AN000; + Extrn THISCDS:DWORD ;AN000; + Extrn THISSFT:DWORD ;AN000; + Extrn CDSAddr:DWORD ;AN000; + Extrn CDSCount:BYTE ;AN000; + Extrn CurrentPDB:WORD ;AN000; +DATA ENDS ;AN000; + ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ; IFS data ;AN000; +;;;aliasExtrn NLAddr:DWORD ;AN000; + Extrn TEMPBUF:BYTE ;AN000; + Extrn UNC_FS_HDR:DWORD ;AN000; + Extrn THISIFS:DWORD ;AN000; + Extrn THISDFL:DWORD ;AN000; + Extrn DFLCount:BYTE ;AN000; + Extrn DFLAddr:DWORD ;AN000; + Extrn IFSDRV:BYTE ;AN000; + Extrn fAssign:BYTE ;AN000; + Extrn CDSAlt:DWORD ;AN000; + Extrn TRUNCATE_FLAG:BYTE ;AN000; + Extrn IFSPROC_FLAGS:WORD ;AN000; + Extrn IFSFUNC_FLAGS:WORD ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn LPT1_NAME:BYTE ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; PRINTER_GETSET_STRING Get or Set the printer string and flag word ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS DOS: Get_User_Stack ;AN000; +; GET_DFL_FROM_INDEX ;AN000; +; DF_TO_DFL ;AN000; +; ;AN000; +; Inputs: ;AN000; +; AL has function type (2-printer-set 3-printer-get ;AN000; +; 4-printer-set-flags 5-printer-get-flags ;AN000; +; VALUE ALREADY RANGE CHECKED BY CALLER ;AN000; +; DS:SI is user string pointer (call 2) ;AN000; +; ES:DI is user buffer (call 3) ;AN000; +; BX is assign index (calls 2,3,4,5) ;AN000; +; CX is length DS:SI (call 2) ;AN000; +; DX is flag word (call 4) ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; REDIR IOCTL (Printer Getset String) ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; DFL entry found by IFSFUNC ;AN000; +; ; Step through CDS & DFL lists counting ;AN000; +; ; (0,1,2,...) ones with IFS bit set. ;AN000; +; ; Stop at BXth one. Pass that in ;AN000; +; ; IFSR_DEVICE_CB@. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB 0 ; subfunction: ;AN000; +; ; 00 Generic IOCTL by device number ;AN000; +; IFSR_RESV3 DB 0 ;AN000; +; * IFSR_BUFFER@ DD ? ; user buffer (see below) ;AN000; +; * IFSR_BUFSIZE DW ? ; length ;AN000; +; * IFSR_CATEGORY DB 1 ; category 1 for REDIR ;AN000; +; * IFSR_CTLFUNC DB ? ; For AL=2,3 00F00001H F=0 GET,F=1 SET ;AN000; +; ; printer string ;AN000; +; ; For AL=4,5 00F00010H F=0 GET,F=1 SET ;AN000; +; ; printer flag ;AN000; +; ;AN000; +; BUFFER LABEL WORD ; AL=2,3 ;AN000; +; DATA DB ... ;AN000; +; ;AN000; +; BUFFER LABEL WORD ; AL=4,5 ;AN000; +; DW FLAGS ; Printer mode flags ;AN000; +; ; 8000H=binary (vs.ascii) ;AN000; +; ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to UNC capable IFS header ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; IF AL=5 THEN DX = Flags ;AN000; +; Call DF_TO_DFL ;AN000; +; ENDDO ;AN000; +; ELSE ;AN000; +; Set carry ;AN000; +; Put error code in AX ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; If AL = 3 then CX bytes have been put at input ES:DI ;AN000; +; If AL = 5 then DX is the flag word ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +; Notes: This request is a REDIR.SYS dependent ioctl request ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure PRINTER_GETSET_STRING,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + TEST CS:IFSFUNC_FLAGS,UNC_INSTALLED ; unc (redir.sys) must be ;AN000; + JNZ PGS_05 ; installed, else do nothing ;AN000; + MOV AX,error_invalid_function ;AN000; + transfer ifs_980 ;AN000; + ;AN000; +PGS_05: ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ; make sure this positioned ;AN000; + ; right ;AN000; + SaveReg ; preserve input es since ;AC007; + ; next call destroys it ;AN000; + ; preserve ax too ;AN007; + CALL GET_DFL_FROM_INDEX ; sets [THISDFL], ;AN000; + ; ifsr_device_cb@ & ;AN000; + ; [THISIFS] ;AN000; + JNC PGS_10 ; error on carry - no dfl ;AN000; + ADD SP,4 ; restore stack and ;AC007; + transfer IFS_980 ; go return in ifsutil ;AC007; + ;AN000; +PGS_10: ;AN000; + RestoreReg ; restore input al ;AN007; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_CATEGORY],CATEGORY_REDIR ;AN000; + CMP AL,PRINTER_SET_STRING ;AN000; + JNE PGS_20 ;AN000; + ; printer set string ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],SI ; ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],DS ; ;AN000; + MOV ES:[BX.IFSR_BUFSIZE],CX ; ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINTER_SET_STRING ;AN000; + ADD SP,2 ; restore stack (es) & ;AN000; + JMP SHORT PGS_100 ; go call redir.sys ;AN000; + ;AN000; +PGS_20: ;AN000; + CMP AL,PRINTER_GET_STRING ; printer get string ;AN000; + JNE PGS_40 ;AN000; + POP CX ; retrieve es in cx ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],DI ; ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],CX ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINTER_GET_STRING ;AN000; + JMP SHORT PGS_100 ;AN000; + ;AN000; +PGS_40: ; flags ;AN000; + ADD SP,2 ; 1st clean stack of es ;AN000; + PUSH CS ; not needed here ;AN000; + POP DS ; must set up buffer ;AN000; +ASSUME DS:IFSSEG ; to hold flag word ;AN000; + MOV SI,OFFSET TEMPBUF ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],SI ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],DS ;AN000; + CMP AL,PRINTER_SET_FLAGS ;AN000; + JNE PGS_60 ;AN000; + MOV DS:[SI],DX ; printer set flags ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINTER_SET_FLAGS ;AN000; + JMP PGS_100 ;AN000; + ;AN000; +PGS_60: ; printer get flags ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINTER_GET_FLAGS ;AN000; + ;AN000; +PGS_100: ;AN000; + PUSH AX ; save function ;AN000; + ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + invoke SET_THISIFS_UNC ; set thisifs to unc ;AN000; + ;AN000; + invoke CALL_IFS ; call ifs driver w/request ;AN000; + ;AN000; + JNC PGS_120 ;AN000; + ADD SP,2 ; clean stack of ax (fcn #) ;AN013; + transfer ifs_980 ; go ret on error ;AN000; + ;AN000; +PGS_120: ;AN000; + POP AX ; restore original input fcn ;AN000;;AM013; + invoke DF_TO_DFL ; Update dfl entry ;AN000; + ;AN000; + CMP AL,PRINTER_GET_FLAGS ; if printer get flags ;AN000; + JE PGS_140 ; put flags in DX ;AN000; + CMP AL,PRINTER_GET_STRING ; if printer get string ;AN000; + JE PGS_160 ; put stg size in CX ;AN000; + ;AN000; + transfer ifs_990 ;AN000; +PGS_140: ;AN000; + LES DI,ES:[BX.IFSR_BUFFER@] ;AN000; + MOV DX,WORD PTR ES:[DI] ;AC004; + CallInstall Get_User_Stack,multDOS,24 ;AN000; + MOV [SI].User_DX,DX ; return user flags to dos ;AN000; + transfer ifs_990 ; go return with no carry ;AN000; + ;AN000; +PGS_160: ;AN000; + MOV CX,ES:[BX.IFSR_BUFSIZE] ;AN000; + CallInstall Get_User_Stack,multDOS,24 ;AN000; + MOV [SI].User_CX,CX ; Size of pre string just transferred ;AN000; + transfer ifs_990 ; go return with no carry ;AN000; + ;AN000; +EndProc PRINTER_GETSET_STRING ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_DEVICE_CHECK ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: DFL_MATCH DOS: PathChrCmp ;AN000; +; DFL_TO_DF StrCpy ;AN000; +; CALL_IFS ;AN000; +; Inputs: ;AN000; +; DS:SI -> name ;AN000; +; ES:DI -> buffer ;AN000; +; ;AN000; +; Function: ;AN000; +; Search DFL for match on name. ;AN000; +; IF match found THEN ;AN000; +; DO /* match found */ ;AN000; +; IF DFL_TYPE = 3 (net device) THEN ;AN000; +; ES:DI -> parms ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE /* no match found */ ;AN000; +; Set carry ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; no match: carry set ;AN000; +; match: carry clear, es:di -> parms if unc ;AN000; +; ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +; Programming notes: Most of this code lifted right out of the Redirector. ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_DEVICE_CHECK,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def ATTSTAT ;AN000; + ;AN000; + LocalVar Src,DWORD ; ** netprn parse code begins ;AN000; + LocalVar Dst,DWORD ;AN000; + LocalVar DotPos,WORD ;AN000; + Enter ;AN000; +; ;AN000; +; Preserve all of the input quantities ;AN000; +; ;AN000; + MOV SrcL,SI ;AN000; + MOV SrcH,DS ;AN000; + MOV DstL,DI ;AN000; + MOV DstH,ES ;AN000; + MOV DotPos,-1 ;AN000; +; ;AN000; +; Check for a UNC string. If UNC, is not spooled. ;AN000; +; ;AN000; + MOV AX,[SI] ;AN000; + CallInstall PathChrCmp,multDOS,4,, ;AN000; + JNZ NOT_UNC ;AN000; + XCHG AH,AL ;AN000; + CallInstall PathChrCmp,multDOS,4,, ;AN000; + JZ NOTSpool ;AN000; +NOT_UNC: ;AN000; +; ;AN000; +; Scan string remembering previous path separator char. ;AN000; +; ;AN000; + MOV DI,SI ; remember first character ;AN000; +PathSkip: ;AN000; + LODSB ;AN000; + OR AL,AL ;AN000; + JZ FoundEnd ;AN000; +IF Kanji ;AN000; + kanji load of next char too ;AN000; +ENDIF ;AN000; + CallInstall PathChrCmp,multDOS,4,, ;AN000; + JZ SaveSI ;AN000; + CMP AL,':' ;AN000; + JNZ TestDot ;AN000; +SaveSI: ;AN000; + MOV DI,SI ;AN000; + JMP PathSkip ;AN000; +TestDot: ;AN000; + CMP AL,'.' ;AN000; + JNZ PathSkip ;AN000; + MOV DotPos,SI ;AN000; + JMP PathSkip ;AN000; + ;AN000; +; ;AN000; +; Better check for trailing :. They are ILLEGAL (read this comment, IBM) in ;AN000; +; file names. ;AN000; +; ;AN000; +FoundEnd: ;AN000; + CMP BYTE PTR [SI-2],':' ;AN000; + JNZ NOCOL ;AN000; +NotSpool: ;AN000; + SaveReg ;AN008; + RestoreReg ;AN008; + MOV AX,NULL_PTR ;AN008; + MOV WORD PTR [THISDFL],AX ;AN008; + MOV WORD PTR [THISDFL+2],AX ;AN008; + RestoreReg ;AN008; + LDS SI,Src ;AN000; + STC ;AN000; +Done: ;AN000; + LES DI,Dst ;AN000; + Leave ;AN000; + return ;AN000; + ;AN000; +NotSpoolLv: ;AN000; + LeaveCrit critNet ;AN000; + JMP NotSpool ;AN000; + ;AN000; +NOCOL: ;AN000; + XCHG SI,DI ;AN000; +; ;AN000; +; DS:SI points to remainder of string. DS:DI points to 1 past NUL. AL = 0 ;AN000; +; ;AN000; + CMP DotPos,-1 ;AN000; + JZ GetP ;AN000; + MOV DI,DotPos ;AN000; + XCHG AL,[DI-1] ;AN000; +; ;AN000; +; DI points to 1 past either former . (now NUL) or terminating NUL. AL has ;AN000; +; former character (. or NUL) ;AN000; +; ;AN000; + ; ** end of netprn code ;AN000; +GETP: ; ds:si -> parsed string ;AN000; + invoke DFL_MATCH ;AN000; + MOV ES,SrcH ;AN000; + MOV ES:[DI-1],AL ; replace original character ;AN000; + JNC IDC_100 ; not in dfl; set bl=ff ;AN000; + JMP NotSpool ;AN000; + ;AN000; +IDC_100: ; match found ;AN000; + LES DI,[THISDFL] ;AN000; + CMP ES:[DI.DFL_TYPE],TYPE_NET_DEVICE ;AN000; + JE IDC_120 ;AN000; + LES DI,Dst ;AN000; + JMP IDC_220 ;AN000; + ;AN000; +IDC_120: ; ifs: get parms ;AN000; + invoke PREP_IFSR ; clear ifsr ;AN003; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN003; + invoke DFL_TO_DF ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTSTAT ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSATTSTAT ;AN000; + invoke SET_CATEGORY ; this has nothing to do w/catrgory ;AN000; + ; want to determine if unc or not ;AN000; + OR CL,CL ; unc cl=1, other cl=0 ;AN000; + JNE IDC_140 ;AN000; + MOV ES:[BX.IFSR_TYPE],TYPE_DEVICE ;AN000; + JMP SHORT IDC_160 ;AN000; +IDC_140: ;AN000; + MOV ES:[BX.IFSR_TYPE],TYPE_NET_DEVICE ;AN000; +IDC_160: ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV SI,OFFSET TEMPBUF ;AN000; + MOV WORD PTR ES:[BX.IFSR_PARMS@],SI ;AN000; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DS ;AN000; + ;AN000; + invoke CALL_IFS ;AN000; + JNC IDC_200 ;AN008; + JMP NotSpool ;AC008; + ;AN000; +IDC_200: ;AN000; + MOV SI,ES:WORD PTR [BX.IFSR_PARMS@] ;AN000; + MOV DS,ES:WORD PTR [BX.IFSR_PARMS@+2] ;AN000; + MOV BL,ES:[BX.IFSR_TYPE] ;AC001; + XOR BH,BH ;AN001; + INC SI ; ds:si -> parms returned by redir ;AN000; + INC SI ;AN000; + LES DI,Dst ;AN000; + CallInstall StrCpy,multDOS,17 ;AN000; + DEC DI ; now append device name to net path ;AN003; + MOV AL,'\' ; | ;AN003; + STOSB ; | ;AN003; + LDS SI,CS:[THISDFL] ; | ;AN003; + ADD SI,2 ; | ;AN003; + invoke CONVERT_NAME_ASCIIZ ; | mov name string over ;AN003; + +IDC_220: ;AN000; + LDS SI,Dst ;AN000; + CLC ;AN000; + JMP DONE ;AN000; + ;AN000; + ;AN000; +EndProc IFS_DEVICE_CHECK ;AN000; + ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_DEVICE_CLOSE ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: ;AN000; +; SFT_TO_SFF ;AN000; +; SFF_TO_SFT ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ES:DI -> SFT ;AN000; +; ;AN000; +; Function: ;AN000; +; Send request below to IFS specified if SFT. ;AN000; +; ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; DF ;AN000; +; * IFSR_OPEN_CB@ DD ? ; SF ;AN000; +; * IFSR_FUNC DB 0 ; generic IOCTL by handle ;AN000; +; IFSR_RESV3 DB 0 ;AN000; +; IFSR_BUFFER@ DD ? ;AN000; +; IFSR_BUFSIZE DW ? ;AN000; +; IFSR_CATEGORY DB 1 for UNC, 0 for all other FSs ;AN000; +; IFSR_CTLFUNC DB 00000101B ; device spool close ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry set - error code in AX ;AN000; +; ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_DEVICE_CLOSE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + SaveReg ; preserve these for dos - guesing ;AN011; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN002; + MOV CS:IFSPROC_FLAGS,SETDEVICECB ; init processing flags ;AN000; + ;AN000; + Context DS ;AN000; + MOV WORD PTR [THISSFT],DI ;AN000; + MOV WORD PTR [THISSFT+2],ES ;AN000; + + invoke PREP_IFSR ; & ifsr ;AM011; + invoke SFT_TO_SFF ; sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AN000; +;;;;;;;;INC ES:[BX.IFSR_FUNC] ; inc func from gen_ioctl_by_devnum ;AD011; +;;;;;;;; ; to gen_ioctl_by_handle ;AD011; + invoke SET_CATEGORY ;AN000; + MOV ES:[BX.IFSR_CATEGORY],CL ;AN002; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_DEVCLOSE ;AN000; + ;AN000; + invoke CALL_IFS ; call ifs w/device close request ;AN000; + ;AN000; + JNC IDCL_60 ;AN000; + JMP IDCL_1000 ; go ret w/carry already set ;AC011; + ;AN000; +IDCL_60: ;AN000; + invoke SFF_TO_SFT ;AN000; +;;;;;;;;transfer ifs_990 ;AD011; +IDCL_1000: ;AN011; + RestoreReg ;AN011; + XOR CX,CX ; set zero flag ;AN011;;AC013; + return ;AN011; + ;AN000; + ;AN000; +EndProc IFS_DEVICE_CLOSE ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_DEVICE_OPER ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: PREP_IFSR ;AN000; +; CALL_IFS ;AN000; +; DFL_TO_DF ;AN000; +; ;AN000; +; Inputs: AL = 7 Get truncate flag ;AN000; +; AL = 8 Set truncate flag ;AN000; +; DL = value ;AN000; +; AL = 9 Close all spool files ;AN000; +; ;AN000; +; Function: ;AN000; +; IF AL=7 THEN DL = [TRUNCATE_FLAG] ;AN000; +; ELSE DO ;AN000; +; Get addr of 1st DFL entry. ;AN000; +; FOR I = 1 to last DFL entry in use ;AN000; +; Send request below to IFS specified if DFL. ;AN000; +; ENDDO ;AN000; +; ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; DF ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB 0 ; 00 Generic IOCTL by device number ;AN000; +; IFSR_RESV3 DB 0 ;AN000; +; * IFSR_BUFFER@ DD ? ;AN000; +; * IFSR_BUFSIZE DW 1 ;AN000; +; IFSR_CATEGORY DB 1 for UNC, 0 for other FSs ;AN000; +; IFSR_CTLFUNC DB 00000110 ; device_oper ;AN000; +; ;AN000; +; BUFFER LABEL BYTE ;AN000; +; DB function ; 8 set truncate flag ;AN000; +; ; 9 close all spool files ;AN000; +; DB truncate flag on set ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry clear - DL = truncate flag on get ;AN000; +; Carry set - AX = error code ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +; Notes: DFL not updated ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_DEVICE_OPER,NEAR ;AN000; + ;AN000; + CMP AL,GET_TRUNCATE_FLAG ;AN000; + JNE IDO_20 ;AN000; + MOV DL,[TRUNCATE_FLAG] ; Get truncate flag ;AN000; + XOR DH,DH ;AN015; + CallInstall Get_User_Stack,multDOS,24 ;AN015; + MOV [SI].User_DX,DX ;AN015; + transfer ifs_990 ; go ret no carry ;AN000; + ;AN000; +IDO_20: ; Set truncate flag or close all ;AN000; + ifsr_fcn_def EXECAPI ; spool files ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + PUSH CS ; get addressability to IFSSEG ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG,ES:NOTHING ;AN000; + ;AN000; + MOV DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN002; + CMP AL,SET_TRUNCATE_FLAG ; Set local storage of truncate_flag ;AN000; + JNE IDO_30 ;AN000; + MOV [TRUNCATE_FLAG],DL ;AC002; + MOV AH,DL ; for safekeeping ;AN002; + ;AN000; +IDO_30: ;AN000; + MOV CL,[DFLCount] ; Prep loop through DFL list ;AN000; + OR CL,CL ; check for no dfl ;AN009; + JNZ IDO_35 ;AN009; + transfer ifs_990 ; no dfl - just go successfully ;AN009; +IDO_35: + XOR CH,CH ;AN000; + MOV DX,SIZE DFLL_LIST ;AN000; + LDS SI,[DFLAddr] ;AN000; + ;AN000; +IDO_40: ; ** Loop here thru DFL list entries ;AN000; +;;;aliasCMP DS:[SI.DFLL_TYPE],TYPE_ALIAS ;AN000; +;;;aliasJE IDO_100 ; skip alias dfl entries ;AN000; +;;;alias ;AN000; + TEST DS:[SI.DFLL_FLAGS],DFL_INUSE ; skip unused dfl entries ;AN000; + JZ IDO_100 ;AN000; + MOV WORD PTR [THISDFL],SI ; Prep IFSRH ;AN000; + MOV WORD PTR [THISDFL+2],DS ;AN000; + invoke PREP_IFSR ;AN000; + invoke DFL_TO_DF ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AN000; + MOV SI,OFFSET TEMPBUF ; prep devoper buffer ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],SI ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],DS ;AN000; + MOV BYTE PTR DS:[SI],AL ; buffer contains: db fcn ;AN000; + MOV ES:[BX.IFSR_BUFSIZE],1 ;AN002; + CMP AL,CLOSE_SPOOL_FILES ; db truncate flag ;AN000; + JE IDO_60 ;AN000; + MOV BYTE PTR DS:[SI+1],AH ;AC002; + INC ES:[BX.IFSR_BUFSIZE] +IDO_60: ;AN000; + invoke SET_CATEGORY ;AN000; + MOV ES:[BX.IFSR_CATEGORY],CL ;AN002; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_DEVOPER ;AN000; + ;AN000; + SaveReg ; save count ;AN000; + invoke CALL_IFS ; call ifs with device oper request ;AN000; + RestoreReg ; restore count ;AN000; + ;AN000; +IDO_100: ;AN000; + ADD SI,DX ; prep for next dfl ;AN000; + LOOP IDO_40 ; go process next dfl ;AN000; + transfer ifs_990 ; Finished. Go ret no carry. ;AN000; + ;AN000; + ;AN000; +EndProc IFS_DEVICE_OPER ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_SPOOL_ECHO_CHECK ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: DFL_MATCH ;AN000; +; DFL_TO_DF ;AN000; +; CALL_IFS ;AN000; +; Inputs: None ;AN000; +; ;AN000; +; Function: ;AN000; +; Call DFL_MATCH for match on "LPT1". ;AN000; +; IF match found THEN ;AN000; +; DO ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; DF ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB 0 ; 00 Generic IOCTL by devnum ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; * IFSR_BUFFER@ DD ? ;AN000; +; * IFSR_BUFSIZE DW ? ;AN000; +; IFSR_CATEGORY DB ? ; 0 non-unc, 1 unc ;AN000; +; IFSR_CTLFUNC DB 00000011B ;AN000; +; ;AN000; +; BUFFER LABEL BYTE ;AN000; +; DB VALUE,0 ; 0 echo allowed ;AN000; +; ; 1 echo not allowed ;AN000; +; ;AN000; +; ;AN000; +; Call routine, CALL_IFS, with DFL_IFSR_HDR ;AN000; +; ENDDO ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry clear - echo allowed ;AN000; +; Carry set - echo NOT allowed ;AN000; +; ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +; Programming notes: DFL FSDA not updated ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_SPOOL_ECHO_CHECK,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + SaveReg ; save these for ibmdos (guessing which) ;AN011; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ; make sure this positioned ;AN000; + ; right ;AN000; + PUSH CS ; Set ds:si -> "lpt1",0 ;AN000; + POP DS ; want to find dfl entry with ;AN000; +ASSUME DS:IFSSEG ; this dev name ;AN000; + MOV SI,OFFSET LPT1_NAME ;AN000; + ;AN000; + invoke DFL_MATCH ;AN000; + JNC ISEC_10 ;AN000; + CLC ; not in dfl; assume echo ok ;AN011; + JMP ISEC_1000 ;AC011; + ;AN000; +ISEC_10: ;AN000; + LES DI,[THISDFL] ;AN000; +;;;aliasCMP ES:[DI.DFL_TYPE],TYPE_ALIAS ;AN000; +;;;aliasJNE ISEC_15 ;AN000; +;;;aliastransfer ifs_980 ; lpt1 is alias, assume no echo ;AN000; + ;AN000; +ISEC_15: ;AN000; + invoke PREP_IFSR ; zero out ifsr ;AN000; + invoke DFL_TO_DF ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AN000; + MOV SI,OFFSET TEMPBUF ;AN000; + MOV WORD PTR ES:[BX.IFSR_BUFFER@],SI ; use tempbuf for ;AN000; + MOV WORD PTR ES:[BX.IFSR_BUFFER@+2],DS ; return byte value ;AN000; + MOV ES:[BX.IFSR_BUFSIZE],LENGTH_DEVECHOCHECK_BUFFER ; (1) ;AN000; + ;AN000; + invoke SET_CATEGORY ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_DEVECHOCHECK ; (00000011) ;AN000; + ;AN000; + invoke CALL_IFS ;AN000; + ;AN000; + JNC ISEC_60 ;AN000; + JMP SHORT ISEC_1000 ; no echo on err, cf set ;AC011; + ;AN000; +ISEC_60: ;AN000; + CMP BYTE PTR DS:[SI],0 ; else byte returned in buffr ;AN000; + JE ISEC_80 ; determines echo (0-yes,1-no) ;AN000; + STC ;AN011; + JMP SHORT ISEC_1000 ; no echo ret ;AC011; +ISEC_80: ;AN000; + CLC ;AN011; + + +ISEC_1000: ; echo ret ;AN011; + RestoreReg ;AN011; + RET ;AN011; + + ;AN000; +EndProc IFS_SPOOL_ECHO_CHECK ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_DEPENDENT_IOCTL ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS ;AN000; +; CDS_TO_CD SFT_TO_SFF ;AN000; +; CD_TO_CDS SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; AL = 0 - Generic by device number ;AN000; +; BH = 0, BL = device number (0-def,1=a,2=b,...) [THISCDS] set ;AN000; +; CX = private subfunction ;AN000; +; DS:DX -> buffer ;AN000; +; AL = 1 - Generic by handle ;AN000; +; BX = handle [THISSFT] set ;AN000; +; CX = private subfunction ;AN000; +; DS:DX -> buffer ;AN000; +; AL = 2 - Query OS type ;AN000; +; BH = 0, BL = device number (0-def,1=a,2=b,...) [THISCDS] set ;AN000; +; CX = buffer size ;AN000; +; ES:DI -> buffer ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; Set by CDS_TO_CD (subfs 0,2) ;AN000; +; * IFSR_OPEN_CB@ DD ? ; Set by SFT_TO_SFF (subf 1) ;AN000; +; * IFSR_FUNC DB 0 ; AL - 0,1,or 2 ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; * IFSR_BUFFER@ DD ? ; al-2 es:di, else ds:dx ;AN000; +; * IFSR_BUFSIZE DW ? ; al-2 cx, else ??? ;AN000; +;;;; for al=0,1 ;AN000; +; * IFSR_CATEGORY DB 1 ; 1 for UNC, 0 for non-UNC ;AN000; +; * IFSR_CTLFUNC DB ? ; al-2 ???, else cx ;AN000; +; ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to IFS header ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; IF CDS THEN ;AN000; +; Call CD_TO_CDS ;AN000; +; ELSE Call SFF_TO_SFT ;AN000; +; ENDDO ;AN000; +; ELSE ;AN000; +; Set carry ;AN000; +; Put error code in AX ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: function dependent ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_DEPENDENT_IOCTL,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ; make sure this positioned ;AN000; + ; right ;AN000; + SaveReg ; save input es for query os type ;AC006; + ; and bx for drive # / handle ;AN006; + ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; init ifsfunc flags ;AN000; + invoke PREP_IFSR ; & IFSR ;AN000; + ;AN000; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNC],AL ; 0,1, or 2 ;AN000; + CMP AL,QUERY_OS_TYPE ;AN000; + JE IDI_10 ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],DX ; ioctl generic ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],DS ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CL ;AN000; + ADD SP,2 ; ditch es stored on stack ;AN000; + JMP SHORT IDI_15 ;AN000; +IDI_10: ; query os type ;AN000; + MOV ES:[BX.IFSR_BUFSIZE],CX ; cx is bufsize ;AN000; + POP CX ; pop input es in cx ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],DI ;AN000; + MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],CX ;AN000; +IDI_15: ;AN000; + CMP AL,GEN_IOCTL_BY_HANDLE ;AN000; + RestoreReg ; restore input bx into ax, no cx ;AN006;;AC012; + ; (drive # or handle) ;AN006; + JE IDI_20 ;AN000; + ;AN000; +;;;;;;; LDS SI,[THISCDS] ; have device number (block only???) ;AD006; + ; Now get CDS: ;AN006; + SaveReg ; function 0,1,2 ;AN012; + MOV AX,CX ; input bx ;AN012; + DEC AL ; make 0-based ;AN006; + MOV CS:[IFSDRV],AL ; set this for possible i24 ;AN006; + CallInstall GetCDSFromDrv,multDOS,23,AX,AX ;AN006; + RestoreReg ; fcn 0,1,2 ;AN012; + JNC IDI_17 ;AN006; +IDI_16: ;AN012; + MOV AX,error_invalid_drive ; no cds, set error & ret ;AN006; + JMP IDI_120 ; ret up in FA to preserve DS ;AN006; +IDI_17: ; (welcome lock) ;AN006; + TEST DS:[SI.curdir_flags],curdir_isifs ; check if drive ifs ;AN012; + JZ IDI_16 + SaveReg ; save cds ptr al=0,2 ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - netwrk ;AN000; + CMP AL,QUERY_OS_TYPE ;AN000; + JNE IDI_40 ;AN000; + JMP SHORT IDI_60 ;AN000; + ;AN000; +IDI_20: ; al=1 ;AN000; + Context DS ;AN000; + OR IFSPROC_FLAGS,SETDEVICECB ;AN000; + ; Now, need to get THISSFT set: ;AN006; + SaveReg ; these about to be clobbered ;AN006; + MOV BX,CX ; put handle in bx ;AC012; + CallInstall pJFNFromHandle,multDOS,32 ; intermediate step to getting sft ;AN006; + JC IDI_25 ;AN006; + CMP BYTE PTR ES:[DI],-1 ; unused handle ;AN006; + JE IDI_25 ;AN006; + MOV BL,BYTE PTR ES:[DI] ; get SFN ;AN006; + XOR BH,BH ; ignore upper half ;AN006; + CallInstall SFFromSFN,multDOS,22 ; get real sf spot ;AN006; + MOV WORD PTR [THISSFT],DI ;AN006; + MOV WORD PTR [THISSFT+2],ES ;AN006; + RestoreReg ;AN006; + JMP SHORT IDI_30 ;AN006; +IDI_25: ; sft error ;AN006; + RestoreReg ; restore regs ;AN006; + MOV AX,error_invalid_handle ;AN006; + JMP IDI_120 ;AN006; + +IDI_30: ;AN006; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - netwrk ;AN000; +IDI_40: ;AN000; + invoke SET_CATEGORY ; set category 1-unc 0-other ;AN000; + MOV ES:[BX.IFSR_CATEGORY],CL ;AN000; +IDI_60: + MOV DX,IFSIOCTL ; check if fs supports fs ioctl + invoke CHECK_IFS_ATTRIBUTE + JZ IDI_80 ; Z = no support, NZ = yes support + JMP DI_70 ; continues in device_ioctl ;AN000; + ;AN000; +IDI_80: ; error invalid fcn - fs doesn't support ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; if cds, must clean stack of ;AN000; + JZ IDI_100 ; cds ptr ;AN000; + ADD SP,4 ;AN000; +IDI_100: ;AN000; + MOV AX,error_invalid_function ;AN000; +IDI_120: ;AN006; + invoke SET_EXTERR_INFO ; set error info ;AN006; + transfer ifs_980 ; go to general error return ;AN000; + ;AN000; +EndProc IFS_DEPENDENT_IOCTL ;AN000; + + +BREAK ;AN000; + ;AN000; +;****************************************************************************** +; +; DEVICE_IOCTL +; +; Called by: Dispatcher +; +; Routines called: CALL_IFS +; CDS_TO_CD SFT_TO_SFF +; CD_TO_CDS SFF_TO_SFT +; +; Inputs: +; AL = 02H(03H0 Read from(Write to) character device +; BX = handle [THISSFT] set +; CX = number of bytes to read(write) +; DS:DX -> buffer +; AL = 0CH Character Generic IOCTL +; CH = 1-async, 3-display, 5-printer +; CL = 5F-set, 7F-get +; DS:DX -> buffer +; AL = 0DH Block Generic IOCTL +; BH = 0 +; BL = Drive number [THISCDS] set (0-based) +; CH = 08 +; CL = 43-set, 63-get media id +; DS:DX -> buffer +; +; Function: +; Prep IFSRH: +; * IFSR_LENGTH DW 48 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; IFSR_RETCODE DW ? +; IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 17 ; IFS device IOCTL +; IFSR_ERROR_CLASS DB ? +; IFSR_ERROR_ACTION DB ? +; IFSR_ERROR_LOCUS DB ? +; IFSR_ALLOWED DB ? +; IFSR_I24_RETRY DB ? +; IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; * IFSR_DEVICE_CB@ DD ? ; Set by CDS_TO_CD (0DH) +; * IFSR_OPEN_CB@ DD ? ; Set by SFT_TO_SF (0CH) +; * IFSR_FUNC DB 0 ; AL 2,3,12,or 13 +; IFSR_RESV2 DB 0 +; * IFSR_BUFFER@ DD ? ; ds:dx +; * IFSR_BUFSIZE DW ? ; cx for al=2,3 +; * IFSR_CATEGORY DB 1 ; ch for al=12,13 +; * IFSR_CTLFUNC DB ? ; cl for al=12,13 +; +; +; CALL routine, CALL_IFS +; IF IFSR_RETCODE = 0 THEN +; DO +; IF CDS THEN +; Call CD_TO_CDS +; ELSE Call SFF_TO_SFT +; ENDDO +; ELSE +; Set carry +; Put error code in AX +; ENDIF +; +; Outputs: function dependent +; +; Regs: nothing preserved +; +;****************************************************************************** + ;AN000; + procedure DEVICE_IOCTL,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; +; mov ax,26 ; these two instrs temporary +; transfer ifs_980 + + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEVIOCTL ;AN000; + ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ; make sure this positioned ;AN000; + ; right ;AN000; + PUSH DS ; save input ds ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; init processing flags ;AN000; + invoke PREP_IFSR ; & ifsr ;AN000; + POP ES:WORD PTR [BX.IFSR_BUFFER@+2] ; put input ds in now before clobber it ;AN005; + ;AN000; + CMP AL,BLOCK_GENERIC ;AN000; + JNE DI_20 ;AN000; + ;AN000; + LDS SI,[THISCDS] ; block generic - cds processing ;AN000; + SaveReg ; save cds ptr ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - netwrk ;AN000; + JMP SHORT DI_40 ;AN000; + ;AN000; +DI_20: ; handle function ;AN000; + OR CS:IFSPROC_FLAGS,SetDeviceCB ; to get possible related cd or df ;AN000; + Context DS ;AN000; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - netwrk ;AN000; +DI_40: ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_DEVIOCTL ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSDEVIOCTL ;AN000; + MOV ES:[BX.IFSR_FUNC],AL ; 2,3,12 or 13 ;AN000; +;;;;; POP DS ; retrieve input ds ;AD005; + MOV ES:WORD PTR [BX.IFSR_BUFFER@],DX ;AN000; +;;;;; MOV ES:WORD PTR [BX.IFSR_BUFFER@+2],DS ;AD005; + CMP AL,CHAR_GENERIC ; fork 2,3 vs 12,13 ;AN000; + JGE DI_60 ; go if 12,13 + MOV ES:[BX.IFSR_BUFSIZE],CX ; 2,3 processing + JMP SHORT DI_70 +DI_60: ; 12,13 processing + MOV ES:[BX.IFSR_CATEGORY],CH ; 1,3,5,or 8 + MOV ES:[BX.IFSR_CTLFUNC],CL ; 5F,7F,4E,or 6E + ;AN000; +DI_70: ;AN000; +;----------------------------------------------------------------------------------------- + invoke CALL_IFS ; call ifs driver w/request ;AN000; +;----------------------------------------------------------------------------------------- + ;AN000; + JNC DI_100 ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; error return ;AN000; + JNZ DI_80 ; if cds clean up stack ;AN000; + transfer ifs_1000 ; go return in ifsutil ;AN000; +DI_80: ;AN000; + ADD SP,4 ; restore stack ;AN000; + transfer ifs_980 ;AN000; + ;AN000; +DI_100: ;AN000; + TEST IFSPROC_FLAGS,ISCDS ;AN000; + JNZ DI_120 ;AN000; + MOV AX,ES:[BX.IFSR_BUFSIZE] ; set return size for 2,3 (won't hurt ;AN000; + invoke SFF_TO_SFT ; for 12 either ;AN000; + transfer ifs_990 ;AN000; +DI_120: ;AN000; + MOV CX,ES:[BX.IFSR_BUFSIZE] ;AN000; + RestoreReg ; restore cds ptr into esdi ;AN000; + invoke CD_TO_CDS ;AN000; + transfer ifs_990 ;AN000; + ;AN000; + ;AN000; +EndProc DEVICE_IOCTL ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; GET_DFL_FROM_INDEX ;AN000; +; ;AN000; +; Called by: PRINTER_GETSET_STRING ;AN000; +; ;AN000; +; Routines called: none ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BX is index number (as in GetIFSFUNCItem) ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry Clear ;AN000; +; [THISDFL] set ;AN000; +; Carry Set ;AN000; +; Bad index number ;AN000; +; ;AN000; +; Regs: Preserves Printer Get/Set String input regs ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure GET_DFL_FROM_INDEX,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save Ptr GetSet Str input regs ;AC007; + ; (removed ax from above) ;AN007; + PUSH BX ;AN000; +; Compute index # of first device ;AN000; + XOR BX,BX ;AN000; + MOV CX,BX ;AN000; + Context DS ; DS-Dosgroup ;AN003; + MOV CL,[CDSCount] ;AN000; + LDS SI,[CDSAddr] ; Assume not paused ;AN000; + CMP CS:[fAssign],0 ;AN000; + JNZ GDFI_20 ;AN000; + LDS SI,CS:[CDSAlt] ; Paused, get REAL CDSs from here ;AN000; +GDFI_20: ;AN000; + TEST [SI.CURDIR_FLAGS],CURDIR_ISIFS ;AN000; + JZ GDFI_40 ;AN000; + INC BX ;AN000; +;;; TEST [SI.CURDIR_TYPE],TYPE_NET_DRIVE ;AD003; +;;; JZ GDFI_40 ; count 2 for redir ;AD003; +;;; INC BX ;AD003; +GDFI_40: ;AN000; + ADD SI,SIZE CURDIR_LIST ; Next CDS ;AN000; + LOOP GDFI_20 ;AN000; + ; BX is index # of first device ;AN000; + POP AX ; Get user index # ;AN000; + SUB AX,BX ;AN000; + JB GDFI_60 ; if carry set (JB), user index < ;AN000; + ; 1st device index - too low ;AN000; + ; go return w/carry already set ;AN000; + MOV CL,CS:[DFLCount] ;AN000; + CMP CL,AL ; AL is now device index # ;AN000; + JAE GDFI_80 ;AN000; +GDFI_60: ;AN000; + MOV AX,error_invalid_parameter ; user index too high ;AN000; + JMP GDFI_980 ; go return w/carry already set ;AN000; +GDFI_80: ;AN000; + LDS SI,CS:[DFLAddr] ;AN000; + MOV BL,SIZE DFLL_list ; size in convenient spot ;AN000; +;;; DEC AX ;AD003 + MUL BL ; get net offset ;AN000; + ADD SI,AX ; convert to true pointer ;AN000; + TEST DS:[SI.DFLL_FLAGS],dfl_inuse ; is this device attached????? ;AN014; + JZ GDFI_60 ; error if not + ;AN000; + PUSH DS ;AN000; + POP DX ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV WORD PTR [THISDFL],SI ;AN000; + MOV WORD PTR [THISDFL+2],DX ;AN000; + invoke PREP_IFSR ; init ifsr ;AN000; + invoke DFL_TO_DF ;AN000; + JMP GDFI_990 ;AN000; + ;AN000; + ;AN000; +GDFI_980: ; Return area ;AN000; + SaveReg ; set thisdfl null on error ;AN008; + RestoreReg ;AN008; + MOV AX,NULL_PTR ;AN008; + MOV WORD PTR [THISDFL],AX ;AN008; + MOV WORD PTR [THISDFL+2],AX ;AN008; + RestoreReg ;AN008; + STC ;AN000; + JMP GDFI_1000 ;AN000; +GDFI_990: ;AN000; + CLC ;AN000; +GDFI_1000: ;AN000; + RestoreReg ; restore regs ;AC007; + ; (removed ax from above) ;AN007; + return ;AN000; + ;AN000; +EndProc GET_DFL_FROM_INDEX ;AN000; + ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSDIR.ASM b/v4.0/src/CMD/IFSFUNC/IFSDIR.ASM new file mode 100644 index 0000000..dc64893 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSDIR.ASM @@ -0,0 +1,313 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsdir.asm 1.0 87/05/11 ;AN000; +TITLE IFSFUNC DIRECTORY ROUTINES - Routines for IFS driver dispatch ;AN000; +NAME NETDIR ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DIRECTORY related IFS driver calls ;AN000; +; ;AN000; +; IFS_RMDIR ;AN000; +; IFS_MKDIR ;AN000; +; IFS_CHDIR ;AN000; +; ;AN000; +; Programming notes: ;AN000; +; Old redirector segmentation preserved. ;AN000; +; Directory routines do not generate critical errors. ;AN000; +; ;AN000; +; REVISION HISTORY: ;AN000; +; A000 Original version 4.00 May 1987 +; A001 PTM 3671- check for null cds 3/88 RPS/RMG +; ;AN000; +; LOC - 67 ;AN000; +; LOD - 4 ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +ifsseg SEGMENT BYTE PUBLIC 'ifsseg' ;AN000; +ifsseg ENDS ;AN000; + ;AN000; +; include the rest of the segment definitions for normal MSDOS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ;AN000; + ; DOSGROUP data ;AN000; + Extrn WFP_START:WORD ;AN000; + Extrn THISCDS:DWORD ;AN000; + ;AN000; +DATA ENDS ;AN000; + ;AN000; + ;AN000; +; define our own code segment ;AN000; + ;AN000; +ifsseg SEGMENT BYTE PUBLIC 'ifsseg' ;AN000; + ASSUME SS:DOSGROUP,CS:ifsseg ;AN000; + ;AN000; + ;IFS Data ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + ;AN000; +BREAK ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_RMDIR ;AN000; +; ;AN000; +;Called by: ;AN000; +; IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: ;AN000; +; CDS_TO_CD ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH as follows: (* indicate which fields set) ;AN000; +; * IFSR_LENGTH DW 42 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 4 ; Remove Directory ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; Call CDS_TO_CD to convert CDS to CD ;AN000; +; ; and set this as pointer to it. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_NAME@ DD ? ; [WFP_START] ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; Call CD_TO_CDS ;AN000; +; Clear carry ;AN000; +; ELSE ;AN000; +; Set carry ;AN000; +; Put error code in AX ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry clear: CDS FSDA updated ;AN000; +; Carry set on error: error_path_not_found (bad path) ;AN000; +; error_access_denied (file/device not empty) ;AN000; +; ;AN000; +; Notes: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + ;AN000; + procedure IFS_RMDIR,NEAR ;AN000; + ;AN000; + entry IFS_SEQ_RMDIR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr fields for rmdir ;AN000; + ifsr_api_def RMDIR ;AN000; + ;AN000; + PUSH DS ; preserve DS ;AN000; + ;AN000; + invoke PREP_IFSR ; init ifsr, sets es:bx -> ifsr ;AN000; + ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSRMDIR ;AN000; + JMP SHORT CHDIR_10 ; go finish in ifs_chdir ;AN000; + ;AN000; +EndProc IFS_RMDIR ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_MKDIR ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: CDS_TO_CD ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ;AN000; +; [THISCDS] Points to CDS being used. Not NULL. ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH as follows: (* indicate which fields set) ;AN000; +; * IFSR_LENGTH DW 42 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 3 ; Create Directory ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; Call CDS_TO_CD to convert CDS to CD ;AN000; +; ; and set this as pointer to it. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_NAME@ DD ? ; [WFP_START] ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; Call CD_TO_CDS ;AN000; +; Clear carry ;AN000; +; ELSE ;AN000; +; Set carry ;AN000; +; Put error code in AX ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry clear: CDS FSDA updated ;AN000; +; Carry set on error: error_path_not_found (bad path) ;AN000; +; error_access_denied ;AN000; +; (Attempt to re-create read only file , or ;AN000; +; create a second volume id or create a dir) ;AN000; +; ;AN000; +; Notes: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_MKDIR,NEAR ;AN000; + ;AN000; + entry IFS_SEQ_MKDIR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr fields for mkdir ;AN000; + ifsr_api_def MKDIR ;AN000; + ;AN000; + PUSH DS ; preserve DS ;AN000; + ;AN000; + invoke PREP_IFSR ; init ifsr, sets es:bx -> ifsr ;AN000; + ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSMKDIR ;AN000; + JMP SHORT CHDIR_10 ; go finish in ifs_chdir ;AN000; + ;AN000; +EndProc IFS_MKDIR ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_CHDIR ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: CDS_TO_CD ;AN000; +; CD_TO_CDS ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ;AN000; +; [THISCDS] Points to CDS being used. Not NUL. ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH as follows: (* indicate which fields set) ;AN000; +; * IFSR_LENGTH DW 42 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 5 ; Change Directory ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; Call CDS_TO_CD to convert CDS to CD ;AN000; +; ; and set this as pointer to it. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_NAME@ DD ? ; [WFP_START] ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; Call CD_TO_CDS to update CDS ;AN000; +; Clear carry ;AN000; +; ELSE ;AN000; +; Set carry ;AN000; +; Put error code in AX ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry clear: CDS updated. ;AN000; +; Carry set on error: error_path_not_found (bad path) ;AN000; +; error_access_denied ;AN000; +; ;AN000; +; Notes: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_CHDIR,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr fields for chdir ;AN000; + ifsr_api_def CHDIR ;AN000; + ;AN000; + PUSH DS ; preserve DS ;AN000; + ;AN000; + invoke PREP_IFSR ; init ifsr, sets es:bx -> ifsr ;AN000; + ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSCHDIR ;AN000; + ;AN000; +CHDIR_10: ; Welcome rmdir/mkdir code ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_CHDIR ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + ; ds -> dosgroup ;AN000; + MOV SI,WORD PTR [WFP_START] ; to access thiscds & wfp ;AN000; + invoke STRIP_WFP_START ; ditch leading d:\ ;AN000; + MOV WORD PTR ES:[BX.IFSR_NAME@],SI ;AN000; + MOV WORD PTR ES:[BX.IFSR_NAME@+2],DS ;AN000; + LDS SI,[THISCDS] ;AN000; + SaveReg ;AN000; + MOV DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + CMP SI,NULL_PTR ; skip cds work if cds null ;AN001; + JE CHDIR_20 ;AN001; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - ifsseg ;AN000; +CHDIR_20: ;AN001; + SaveReg ; make sure ds = ifsseg ;AN001; + RestoreReg ;AN001; +;************************************************ + invoke CALL_IFS ; call fs with dir request ;AN000; +;************************************************ + ;AN000; + RestoreReg ; restore cds ptr into es:di ;AN000; + JC CHDIR_1000 ;AN000; + CMP DI,NULL_PTR ; skip cds work if cds null ;AN001; + JE CHDIR_40 ;AN001; + invoke CD_TO_CDS ; update cds ;AN000; + +CHDIR_40: ;AN001; + CLC ;AN000; + ;AN000; +CHDIR_1000: ; finished ;AN000; + POP DS ; restore DS ;AN000; + return ;AN000; + ;AN000; +EndProc IFS_CHDIR ;AN000; + ;AN000; +ifsseg ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSERROR.ASM b/v4.0/src/CMD/IFSFUNC/IFSERROR.ASM new file mode 100644 index 0000000..5240556 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSERROR.ASM @@ -0,0 +1,637 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)IFSERROR.INC 1.0 87/05/11 ;AN000; +TITLE IFSFUNC ERROR ROUTINES ;AN000; +NAME IFSERROR ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS error Routines ;AN000; +; ;AN000; +; INT_2F_5 ;AN000; +; ;AN000; +; IFS_I24 ;AN000; +; SET_EXTERR_INFO ;AN000; +; PHONEY_DPB ;AN000; +; ;AN000; +; REVISION HISTORY: ;AN000; +; Evolved from Network Redirector NETERROR: MAY 11 1987 ;AN000; +; A000 - Original version 4.00 MAY 1987 ;AN000; +; A001 - PTM 842 Messages +; A002 - PTM 1602 INT 2f-5 interface ds bug RG 10/87 +; A003 - PTM 1683/1769 error msg problems RG 10/87 +; A004 - PTM 2827 error proc chgs RG 1/88 +; A005 - PTM 4140 int 2f 5 interface change RMG 4/12/88 +; A006 - P4789 message problems w/no ifs drivers loaded 5/18/88 RMG +; A007 - P4962 I24 AH not set right for printer 5/24/88 RMG +; A008 - P5030 I24 tempbuf conflict 6/03/88 RMG +; ;AN000; +; LOC - 167 ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +INCLUDE SYSMSG.INC +msg_utilname +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; include the rest of the segment definitions for normal MSDOS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ; DOSGROUP Data ;AN000; + Extrn THISDPB:DWORD ;AN000; + Extrn EXTERR:WORD ;AN000; + Extrn EXTERR_ACTION:BYTE ;AN000; + Extrn EXTERR_CLASS:BYTE ;AN000; + Extrn EXTERR_LOCUS:BYTE ;AN000; + Extrn ALLOWED:BYTE ;AN000; + Extrn ExitHold:DWORD ;AN000; + Extrn ERR_TABLE_21:BYTE +DATA ENDS ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ; IFS Data ;AN000; + Extrn IFSDRV:BYTE ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn TEMPBUF:BYTE ;AN003; + Extrn IFSPROC_FLAGS:WORD ;AN003; + Extrn SYSGetMsg:NEAR + Extrn IFSSEM:BYTE + Extrn THISIFS:DWORD ;AN006; + ;AN000; +; Phoney DPB used by IFS Share/Lock errors ;AN000; + ;AN000; +DUMMY_DPB LABEL BYTE ;AN000; + DB 0 ; dpb_drive ;AN000; + DB 0 ; dpb_UNIT ;AN000; + DW 512 ; dpb_sector_size ;AN000; + DB 0 ; dpb_cluster_mask ;AN000; + DB 0 ; dpb_cluster_shift ;AN000; + DW 1 ; dpb_first_FAT ;AN000; + DB 1 ; dpb_FAT_count ;AN000; + DW 16 ; dpb_root_entries ;AN000; + DW 3 ; dpb_first_sector ;AN000; + DW 3 ; dpb_max_cluster ;AN000; + DB 1 ; dpb_FAT_size ;AN000; + DW 2 ; dpb_dir_sector ;AN000; + DD ? ; dpb_driver_addr ;AN000; + DB 0F8H ; dpb_media ;AN000; + DB -1 ; dpb_first_access ;AN000; + DW -1 ; dpb_next_dpb low ;AN000; + DW -1 ; dpb_next_dpb high ;AN000; + DW 0 ; dpb_next_free ;AN000; + DW -1 ; dpb_free_cnt ;AN000; + ;AN000; +; Phoney device headers used by IFS INT 24H ;AN000; + ;AN000; +PHONEY_BLOCK LABEL BYTE ;AN000; + DD ? ; Pointer ;AN000; + DW ISNET ; Block net dev ;AN000; + DW ? ; Strat entry ;AN000; + DW ? ; Int entry ;AN000; + DB 8 DUP (0) ;AN000; + ;AN000; +PHONEY_DEVICE LABEL BYTE ;AN000; + DD ? ; Pointer ;AN000; + DW DEVTYP + ISNET ; Char net dev ;AN000; + DW ? ; Strat entry ;AN000; + DW ? ; Int entry ;AN000; + ;AN000; + PUBLIC PHONEY_NAME ;AN000; +PHONEY_NAME DB " " ;AN000; + ;AN000; + ;AN000; +NEXT_2F_5 DD ? ;AN000; +PUBLIC NEXT_2F_5 ;AN000; + ;AN000; +; ;AN000; +; ;AN000; +MAXERR EQU 89 ; Don't know errors above 79 ;AN000; + ;AN000; + PUBLIC RODS_LABEL +RODS_LABEL LABEL BYTE +.xcref ;AN000; +.xlist +MSG_SERVICES +.cref ;AN000; +.list + +; +; The following table defines CLASS ACTION and LOCUS info for the INT 21H/24H +; errors. Each entry is 5 bytes long: +; +; Err#,Class,Action,Locus,Allowed_Val +; + +ERR_TABLE_IFS LABEL BYTE + DB errCLASS_BadFmt, errACT_User, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;50 ;AN003; + DB errCLASS_TempSit, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;51 ;AN003; + DB errCLASS_Already, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;52 ;AN003; + DB errCLASS_NotFnd, errACT_User, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;53 ;AN003; + DB errCLASS_TempSit, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;54 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;55 ;AN003; + DB errCLASS_OutRes, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;56 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;57 ;AN003; + DB errCLASS_BadFmt, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;58 ;AN003; + DB errCLASS_SysFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;59 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;60 ;AN003; + DB errCLASS_OutRes, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;61 ;AN003; + DB errCLASS_OutRes, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;62 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;63 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;64 ;AN003; + DB errCLASS_Auth, errACT_User, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;65 ;AN003; + DB errCLASS_BadFmt, errACT_User, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;66 ;AN003; + DB errCLASS_NotFnd, errACT_User, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;67 ;AN003; + DB errCLASS_OutRes, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;68 ;AN003; + DB errCLASS_OutRes, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;69 ;AN003; + DB errCLASS_TempSit, errACT_DlyRet, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;70 ;AN003; + DB errCLASS_BadFmt, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;71 ;AN003; + DB errCLASS_TempSit, errACT_Retry, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;72 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;73 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;74 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;75 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;76 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;77 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;78 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;79 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;80 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;81 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;82 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;83 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;84 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;85 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;86 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;87 ;AN003; + DB errCLASS_HrdFail, errACT_Abort, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;88 ;AN003; + DB errCLASS_Unk, errACT_Panic, errLOC_Disk, Allowed_FAIL+Allowed_RETRY ;?? ;AN003; + +; +; We need to map old int 24 errors and device driver errors into the new set +; of errors. The following table is indexed by the new errors +; +ErrMap24 Label BYTE + DB error_write_protect ; 0 + DB error_bad_unit ; 1 + DB error_not_ready ; 2 + DB error_bad_command ; 3 + DB error_CRC ; 4 + DB error_bad_length ; 5 + DB error_Seek ; 6 + DB error_not_DOS_disk ; 7 + DB error_sector_not_found ; 8 + DB error_out_of_paper ; 9 + DB error_write_fault ; A + DB error_read_fault ; B + DB error_gen_failure ; C + DB error_gen_failure ; D RESERVED + DB error_gen_failure ; E RESERVED + DB error_wrong_disk ; F + +ErrMap24End LABEL BYTE + + +BREAK + +;************************************************************************************ +; +; INT_2F_5 +; +; Called by: COMMAND.COM +; +; Routines called: CALL_IFS +; +; Input: [THISIFS] set +; BX = extended error number ;AN005; +; AL = component ID 0 - install check ;AN005; +; 1 - command.com ;AN005; +; 2 - message retriever ;AN005; +; Function: +; This handler uses 2F multiplex number 5. It allows the INT 24H +; Handler in COMMAND to get message texts for NET extended errors. +; +; IF AH = 5 THEN +; DO +; IF AL < 0F8H THEN +; DO +; ³ IF AL .NE. 0 THEN +; ³ DO +; ³ ³ IF AL >= 50 .AND. AL <= 74 THEN /* or AL = 88 */ +; ³ ³ DO +; ³ ³ ³ Prep IFSRH below +; ³ ³ ³ * IFSR_LENGTH DW 28 ; Request length +; ³ ³ ³ * IFSR_FUNCTION DB 6 ; Get Criter Text +; ³ ³ ³ *+ IFSR_RETCODE DB ? ; AL +; ³ ³ ³ IFSR_RETCLASS DB ? +; ³ ³ ³ IFSR_RESV1 DB 17 DUP(0) +; ³ ³ ³ *+ IFSR_MSG@ DD ? ; Msg buffer address +; ³ ³ ³ *+ IFSR_MSG_TYPE DB ? ; Msg type +; ³ ³ ³ IFSR_RESV2 DB ? +; ³ ³ ³ +; ³ ³ ³ Call IFS specified in [THISIFS] +; ³ ³ ³ IF IFSR_RETCODE = 0 THEN +; ³ ³ ³ DO +; ³ ³ ³ ES:DI = IFSR_MSG@ +; ³ ³ ³ AL = IFSR_MSG_TYPE +; ³ ³ ³ ENDDO +; ³ ³ ³ ELSE get ifsfunc standard msg +; ³ ³ ³ ENDIF +; ³ ³ ³ RET 2 +; ³ ³ ENDDO +; ³ ³ ELSE RET 2 +; ³ ³ ENDIF +; ³ ENDDO +; ³ ELSE DO +; ³ AL = 0FFH /* install check */ +; ³ iret +; ³ ENDDO +; ³ ENDIF +; ENDDO +; ELSE iret +; ENDIF +; ENDDO +; ELSE jump far to [NEXT_2F_5] +; ENDIF +; +; Output: carry clear - AL = msg type (0 or 1) +; If EType is 1 then message is printed in form +; +; Abort, Retry Ignore +; If EType is 0 then message is printed in form +; error (read/writ)ing (drive/device) XXX +; Abort, Retry Ignore +; The message is ASCIZ and DOES NOT +; include a trailing CR,LF +; ES:DI -> message text +; carry set - no message +; +; Notes: all destroyed +; +;************************************************************************************ + ;AN000; + procedure INT_2F_5,FAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def CRITMSG ;AN000; + ;AN000; + CMP AH,5 ; check for IFS error 2F call ;AN000; + JZ I2F5_20 ;AN000; + JMP [NEXT_2F_5] ;AN000; + ;AN000; +I2F5_20: ; call ok ;AN000; + STI ; INTs OK ;AN000; + CMP AL,0F8H ;AN000; + JB I2F5_40 ;AN000; + IRET ; IRET on reserved functions ;AN000; +I2F5_40: ;AN000; + OR AL,AL ;AN000; + JNZ I2F5_60 ;AN000; + MOV AL,0FFH ; Tell Ellen I'm here ;AN000; + IRET ;AN000; +I2F5_60: ;AN000; +;;;;;;;;CMP AL,error_NET_write_fault ; check for special error ;AN000; +;;;;;;;;JE I2F5_80 ;AN000; + CMP BX,50 ;AC005; + JAE I2F5_70 + JMP I2F5_1000 ; Carry set ;AN000; +I2F5_70: + CMP BX,MAXERR ;AC005; + JBE I2F5_80 ;AN000; +I2F5_75: ;AN005; + STC ;AN000; + JMP I2F5_1000 ;AN000; + ;AN000; +I2F5_80: ;AN000; + CMP WORD PTR CS:[THISIFS+2],NULL_PTR ;if no ifs driver set, quit w/carry ;AN006; + JNE I2F5_85 ;AN006; + CMP WORD PTR CS:[THISIFS],NULL_PTR ;AN006; + JZ I2F5_75 ;AN006; +I2F5_85: ;AN006; + TEST CS:IFSSEM,MR_ERRMSG_SEM ; if already in msgret loop, exit fast ;AN005; + JNZ I2F5_75 ;AN005; + MOV CS:IFSPROC_FLAGS,0 ;AN005; + CMP AL,I2F5_MsgRet ;AN005; + JNE I2F5_90 ;AN005; + OR CS:IFSPROC_FLAGS,IsMsgRet ;AN005; + OR CS:IFSSEM,MR_ERRMSG_SEM ; set msgret error msg semaphore ;AN005; +I2F5_90: ;AN005; + SaveReg ; save command.com regs ;AN002;AC003; + RestoreReg ; set ds-ifsseg ;AN002; + MOV AX,BX ; whole ax now ext error ;AN003;;AC005; + SaveReg ; save ext err # ;AN000; + invoke PREP_IFSR ; zero out ifsr, sets es:bx -> ifsr ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_CRITMSG ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSCRITMSG ;AN000; + MOV ES:[BX.IFSR_RETCODE],AX ;AN003; + +;*********************************************************************************************** + invoke CALL_IFS ; call ifs with chance to set errmsg ;AN000; +;*********************************************************************************************** + + JNC I2F5_200 ;AN000; + POP AX ; fs error set - get ifsfunc msg ;AN000; + TEST CS:IFSPROC_FLAGS,IsMsgRet ; if msg ret don't call msg ret for ;AN005; + JZ I2F5_95 ; default msg - just fail ;AN005; + STC ;AN005; + JMP SHORT I2F5_220 ;AN005; +I2F5_95: ;AN005; + MOV DH,1 ;AN000; + CALL SYSGETMSG ; puts msg in dssi,cx=msg size ;AN000; + MOV AH,1 ; set al = msg type 0 or 1 ;AN000; + CMP AL,55 ; all but 55,64,65,88 are 1 ;AN000; + JL I2F5_120 ;AN000; + JE I2F5_100 ;AN000; + CMP AL,64 ;AN000; + JL I2F5_120 ;AN000; + JE I2F5_100 ;AN000; + CMP AL,65 ;AN000; + JE I2F5_100 ;AN000; + CMP AL,88 ;AN000; + JNE I2F5_120 ;AN000; + ;AN000; +I2F5_100: ;AN000; + DEC AH ;AN000; + ;AN000; +I2F5_120: ;AN000; + MOV AL,AH ;AN000; + SaveReg ; msg ret has 0D0A24 at end of msg ;AN003; + RestoreReg ; must change this to asciiz ;AN003; + MOV DI,OFFSET CS:TEMPBUF+80 ; move to temp buff and put 0 at 0DH ;AN003;;AC008;(80) + SaveReg ; preserve msg offset and msg type ;AN003; + REP MOVSB ; move msg to temp buff ;AN003; + XOR AL,AL ;AN003; + STOSB ; store zero at end ;AN003; +I2F5_160: ;AN003; + RestoreReg ; msg type/ msg offset ;AN003; + JMP SHORT I2F5_220 ;AN000; + ;AN000; + ;AN000; +I2F5_200: ; fs supplies error msg ;AN000; + MOV AL,ES:[BX.IFSR_MSG_TYPE] ; grab ifs msg info ;AN000; + MOV DI,WORD PTR ES:[BX.IFSR_MSG@] ;AN000; + MOV ES,WORD PTR ES:[BX.IFSR_MSG@+2] ;AN000; + ADD SP,2 ; restore stack ;AN000; +I2F5_220: ;AN000; + PUSHF ; save carry ;AN005; + TEST CS:IFSPROC_FLAGS,IsMsgRet ; if msgret reset semaphore ;AN005; + JZ I2F5_240 ;AN005; + AND CS:IFSSEM,NOT MR_ERRMSG_SEM ;AN005; +I2F5_240: ;AN005; + POPF ; restore carry ;AN005; + RestoreReg ; retrieve command.com regs ;AN002;AC003; + ;AN000; +I2F5_1000: ;AN000; + RET 2 ; Fakey IRET ;AN000; + ;AN000; +EndProc INT_2F_5 ;AN000; + ;AN000; +ASSUME SS:DOSGROUP ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SET_EXTERR_INFO ;AN000; +; ;AN000; +; Inputs: ;AN000; +; AL is extended error ;AN000; +; IFSR ;AN000; +; ;AN000; +; Function: ;AN000; +; Set all the EXTERR stuff and ALLOWED ;AN000; +; ;AN000; +; Outputs: ;AN000; +; following set: ;AN000; +; EXTERR word ;AN000; +; EXTERR_ACTION byte ;AN000; +; EXTERR_CLASS " ;AN000; +; EXTERR_LOCUS " ;AN000; +; ALLOWED " ;AN000; +; ;AN000; +; Regs: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SET_EXTERR_INFO,NEAR ;AN000; + ASSUME DS:IFSSEG,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ;AN000; + PUSHF ;AN000; + SaveReg ;AC003; + ;AN000; + XOR AH,AH ; set unknown ah=0 ;AN003; + MOV SS:[EXTERR],AX ; Set extended error ;AC003; + MOV SI,OFFSET ERR_TABLE_IFS ;AC003; + SaveReg ;AN003; + RestoreReg ; ds-ifsseg to access err_table_ifs ;AN003; + CMP AL,50 ; if err not in range, set to ?? ;AN003; + JL SEI_10 ;AN003; + CMP AL,88 ;AN003; + JLE SEI_20 ;AN003; +SEI_10: ;AN003; + MOV AL,89 ;AN003; + ;AN003; +SEI_20: ;AN003; + SUB AL,50 ; space to correct table entry ;AN003; + MOV CL,4 + MUL CL ;AN003; + ADD SI,AX ;AN003; + +SEI_40: ;AN003; + LODSW ; AL is CLASS, AH is ACTION ;AN003; + MOV [EXTERR_ACTION],AH ; Set ACTION ;AN003; + MOV [EXTERR_CLASS],AL ; Set CLASS ;AN003; + LODSW ; al- LOCUS ah- ALLOWED ;AN003; + TEST IFSPROC_FLAGS,ISCDS ;AN003; + JNZ SEI_50 ;AN003; + ADD AL,2 ;AN003; +SEI_50: ;AN003; + MOV [EXTERR_LOCUS],AL ;AN003; + MOV [ALLOWED],AH ;AN003; + ;AN003; + MOV SI,BX ; Set ds:si -> ifsr so can use ;AN003; + SaveReg ; lodsw to get cl,act,loc,allowed ;AN003; + RestoreReg ;AN003; + ADD SI,IFSR_ERROR_CLASS ;AN003; + ; only set if ifs set (not -1) ;AN000; + LODSW ; AH = action, AL = class ;AN000; + CMP AL,ERROR_INFO_NOT_SET ;AN000; + JE SEI_60 ;AN000; + MOV [EXTERR_CLASS],AL ; set class ;AN000; +SEI_60: ;AN000; + CMP AH,ERROR_INFO_NOT_SET ;AN000; + JE SEI_80 ;AN000; + MOV [EXTERR_ACTION],AH ; set action ;AN000; +SEI_80: ;AN000; + LODSW ; AH = allowed, AL = locus ;AN000; + CMP AL,ERROR_INFO_NOT_SET ;AN000; + JE SEI_100 ;AN000; + MOV [EXTERR_LOCUS],AL ; Set locus ;AN000; +SEI_100: ;AN000; + CMP AH,ERROR_INFO_NOT_SET ;AN000; + JE SEI_1000 ;AN000; + MOV [ALLOWED],AH ;AN000; + +SEI_1000: ;AN003; + RestoreReg ;AN000; + POPF ;AN000; + return ;AN000; + +EndProc SET_EXTERR_INFO ;AN000; + + +BREAK ;AN004; + +;************************************************************************************ +; +; DEVICE2EXTERR +; +; Inputs: +; AX is device error +; +; Function: +; Convert device error to extended error +; This is essentially the same routine as in IBMDOS +; +; Outputs: +; AX = extended error +; +; Regs: all preserved +; +;************************************************************************************ + + procedure DEVICE2EXTERR,NEAR ;AN004; + ;AN004; + SaveReg ;AN004; + MOV DI,AX ;AN004; + MOV AX,OFFSET ErrMap24End ;AN004; + SUB AX,OFFSET ErrMap24 ; AX is the index of the first ;AN004; + ; unavailable error. ;AN004; + ; Do not translate if >= AX. ;AN004; + CMP DI,AX ;AN004; + MOV AX,DI ;AN004; + JAE D2E_20 ;AN004; + MOV AL,ErrMap24[DI] ;AN004; + XOR AH,AH ;AN004; +D2E_20: ;AN004; + RestoreReg ;AN004; + return ;AN004; + ;AN004; +EndProc DEVICE2EXTERR ;AN004; + +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_I24 ;AN000; +; ;AN000; +; Called by: CALL_IFS ;AN000; +; ;AN000; +; Routines called: DOS: NET_I24_ENTRY ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [IFSDRV] set (-1 = device, PHONEY_NAME set) ;AN000; +; [EXTERR...] Set ;AN000; +; [ALLOWED] Set ;AN000; +; IFSR ;AN000; +; ;AN000; +; Function: ;AN000; +; DI = Mapped I 24 error code (0-12) ;AN000; +; AH is bit info (if block) ;AN000; +; Perform I 24 error to get user response ;AN000; +; ;AN000; +; Outputs: ;AN000; +; AL = 0 ;AN000; +; Ignore ;AN000; +; AL = 1 ;AN000; +; Retry ;AN000; +; AL = 3 ;AN000; +; Fail ;AN000; +; ;AN000; +; Regs: DI, AX Revised ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_I24,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + XOR AH,AH ; AL - extended error (retcode) ;AD007; + MOV DI,AX ; set DI = i24 error code C-general fail ;AC007; + MOV WORD PTR [EXITHOLD+2],ES ; save es:bp here since fetchi ;AN000; + MOV WORD PTR [EXITHOLD],BP ; restores in NET_I24_ENTRY ;AN000; + PUSH CS ;AN000; + POP BP ; BP=seg part of BP:SI dev ptr ;AN000; + ;AN000; + MOV AL,[IFSDRV] ; set dev hdr offset ;AN000; + CMP AL,-1 ;AN000; + JZ I24_20 ;AN000; + MOV SI,OFFSET PHONEY_BLOCK ; block device ;AN000; + JMP SHORT I24_40 ;AN000; +I24_20: ;AN000; + MOV SI,OFFSET PHONEY_DEVICE ; char device ;AN000; + MOV AH,87H ; char dev, write, data area ;AN007; + ;AN000; +I24_40: ;AN000; + OR AH,ES:[BX.IFSR_ALLOWED] ; bit 7 = 0-disk or 1(other),... ;AC007; + ;AN000; + CallInstall NET_I24_ENTRY,MultDOS,6,, ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc IFS_I24 ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; PHONEY_DPB ;AN000; +; ;AN000; +; Input: ;AN000; +; [IFSDRV] Set ;AN000; +; ;AN000; +; Function: ;AN000; +; Build a phoney DPB for IFS Share/Lock errors ;AN000; +; ;AN000; +; Outputs: ;AN000; +; [THISDPB] Set ;AN000; +; ;AN000; +; Regs: ALL preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure PHONEY_DPB,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + PUSH AX ;AN000; + MOV WORD PTR [THISDPB],OFFSET DUMMY_DPB ;AN000; + MOV WORD PTR [THISDPB+2],CS ;AN000; + MOV AL,[IFSDRV] ;AN000; + MOV BYTE PTR [DUMMY_DPB + dpb_drive],AL ;AN000; + MOV WORD PTR [DUMMY_DPB + dpb_driver_addr],OFFSET PHONEY_BLOCK ;AN000; + MOV WORD PTR [DUMMY_DPB + dpb_driver_addr + 2],CS ;AN000; + POP AX ;AN000; + return ;AN000; + ;AN000; +EndProc PHONEY_DPB ;AN000; + +include msgdcl.inc ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSFDOS.ASM b/v4.0/src/CMD/IFSFUNC/IFSFDOS.ASM new file mode 100644 index 0000000..6f3ff2d --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFDOS.ASM @@ -0,0 +1,476 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsfdos.asm 1.0 87/08/29 ;AN000; +TITLE IFSFUNC DOS CALLBACK ROUTINES - Routines for ifs ;AN000; +NAME IFSFDOS ;AN000; +;*********************************************************************************** ;AN000; +; ;AN000; +; IFS DOS Callback Routines ;AN000; +; ;AN000; +; IFSFDOS ;AN000; +; ;AN000; +; REVISION HISTORY: ;AN000; +; A000 - Original version 4.00 AUG 1987 DCR - 96 ;AN000; +; A001 - DCR 47 Get disk/device pause status AUG '87 RG ;AN000; +; A002 - PTM 2610 Time/date problems DEC '87 RG ;AN000; +; ;AN000; +; LOC - ;AN000; +; ;AN000; +;*********************************************************************************** ;AN000; + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +.cref ;AN000; +.list ;AN000; +.sall ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ; DOSGROUP data ;AN000; + Extrn YEAR:WORD + Extrn YRTAB:BYTE + Extrn MONTAB:BYTE +DATA ENDS ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data ;AN000; + ;AN000; + Extrn IFSFUNC_FLAGS:WORD ;AN000; + Extrn DOSCALL@:DWORD ;AN000; + Extrn fAssign:BYTE ;AN001; + Extrn fPrint:BYTE ;AN001; + ;AN000; + ;AN000; +BREAK ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SET_IFS_DOSCALL@ ;AN000; +; ;AN000; +;Called by: ;AN000; +; IFSFUNCINIT ;AN000; +; ;AN000; +; Routines called: ;AN000; +; none ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS-ifsseg ;AN000; +; ;AN000; +; Function: ;AN000; +; replace ifs_doscall@ addresses in all ifs driver headers with ;AN000; +; ifsfunc address ;AN000; +; ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; ;AN000; +; Notes: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SET_IFS_DOSCALL@,NEAR ;AN000; +ASSUME DS:IFSSEG ;AN000; + TEST IFSFUNC_FLAGS,NO_IFS_DRIVERS ;AN000; + JZ SID_20 ;AN000; + transfer ifs_1000 ;AN000; +SID_20: ;AN000; + SaveReg ;AN000; + MOV AH,Get_In_Vars ; Get ptr to ifs hdr chain ;AN000; + INT 21h ; es:bx -> sysinitvars ;AN000; + LES DI,ES:[BX.SYSI_IFS] ; es:di -> 1st ifs driver ;AN000; + SaveReg ;AN000; + LES DI,ES:[DI.IFS_DOSCALL@] ;AN000; + MOV WORD PTR [DOSCALL@],DI ;AN000; + MOV WORD PTR [DOSCALL@+2],ES ;AN000; + RestoreReg ; 1st driver addr ;AN000; + MOV SI,OFFSET IFSFUNC_DOSCALL@ ;AN000; +SID_40: ; *** loop here on ifs_doscall@ fixing ;AN000; + MOV WORD PTR ES:[DI.IFS_DOSCALL@],SI ;AN000; + MOV WORD PTR ES:[DI.IFS_DOSCALL@+2],DS ;AN000; + LES DI,ES:[DI.IFS_NEXT] ; check next fs driver ;AN000; + CMP DI,NULL_PTR ; if ptr null, end of ifs drivers ;AN000; + JNE SID_40 ;AN000; + MOV AX,ES ;AN000; + CMP AX,NULL_PTR ;AN000; + JNE SID_40 ;AN000; + ;AN000; +SID_1000: ;AN000; + RestoreReg ;AN000; + return ;AN000; + ;AN000; +EndProc SET_IFS_DOSCALL@ ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFSFUNC_DOSCALL@ ;AN000; +; ;AN000; +;Called by: ;AN000; +; IFS Drivers ;AN000; +; ;AN000; +; Routines called: ;AN000; +; none ;AN000; +; ;AN000; +; Inputs: ;AN000; +; SS-dosgroup ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; ;AN000; +; Notes: none preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFSFUNC_DOSCALL@,FAR ;AN000; + ;AN000; + CMP AH,33 ;AN001; + JNE ID_20 ;AN000; + CALL DOS_RETURN_ASSIGN_MODE ;AN001; + JMP SHORT ID_1000 ;AN001; +ID_20: ;AN001; + CMP AH,34 ;AN000; + JNE ID_40 ;AN000; + CALL DOS_TO_NET_DATE ;AN000; + JMP SHORT ID_1000 ;AN000; +ID_40: ;AN000; + CMP AH,35 ;AN000; + JNE ID_100 ;AN000; + CALL NET_TO_DOS_DATE ;AN000; + JMP SHORT ID_1000 ;AN000; +ID_100: ;AN000; + CALL CS:[DOSCALL@] ;AN000; + ;AN000; +ID_1000: ;AN000; + RET ;AN000; + ;AN000; + ;AN000; +EndProc IFSFUNC_DOSCALL@ ;AN000; + + +BREAK ;AN000; + +;************************************************************************************ +; +; DOS_RETURN_ASSIGN_MODE +; +; Called by: IFSFUNC_DOSCALL@ +; +; Routines called: None +; +; Inputs: +; BL = macro type +; 3 - device +; 4 - drive +; Function: +; If macro type = 3 (network printer) THEN +; BX = fPrint .AND. 1 +; Elseif macro type = 4 (network disk) THEN +; BX = fAssign .AND. 1 +; Else set error_invalid_function +; +; Output: +; Carry clear - BH = mode (0 - off, 1 - on) +; Carry set - AL error code +; +; Notes: This routine needed only for UNC file system. This is the +; only FS that supports pause. +; +;************************************************************************************ + + Procedure DOS_RETURN_ASSIGN_MODE,NEAR ;AN001; +ASSUME DS:NOTHING,ES:NOTHING ;AN001; + ;AN001; + CMP BL,3 ; if (type == drive) ;AN001; + JZ DRAM_20 ;AN001; + CMP BL,4 ;AN001; + JNZ DRAM_60 ;AN001; + MOV BH,fAssign ; t = fAssign; ;AN001; + JMP Short DRAM_40 ; else ;AN001; +DRAM_20: ; if (type == print) ;AN001; + MOV BH,fPrint ; t = fPrint; ;AN001; +DRAM_40: ;AN001; + AND BH,1 ; return t&1; ;AN001; + transfer ifs_990 ; go to general good ret in util ;AN001; + ;AN001; +DRAM_60: ;AN001; + MOV AL,error_invalid_function ;AN001; + transfer ifs_980 ; go to general bad ret in util ;AN001; + ;AN001; +EndProc DOS_RETURN_ASSIGN_MODE ;AN001; + +BREAK ;AN000; + +;************************************************************************************ +; +; DOS_TO_NET +; +; Called by: IFSFUNC_DOSCALL@ +; +; Routines called: None +; +; Inputs: ;AN000; +; DX = MS-DOS Date ;AN000; +; CX = MS-DOS Time ;AN000; +; Function: ;AN000; +; Convert DOS Date Time to Network date ;AN000; +; Outputs: ;AN000; +; DX:CX = Seconds since 1-1-70 ;AN000; +; No other registers Revised ;AN000; +; +;************************************************************************************ + +FOURYEARS = (3*365) + 366 ; Days in four years ;AN000; + + procedure DOS_TO_NET_DATE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + OR AL,AL ; check where to get dos date/time ;AN002; + JNZ DTND_20 ;AN002; + CallInstall DATE16,MultDOS,13 ; Get local date/time ;AN000; + MOV CX,DX ;AN000; + XCHG AX,DX ;AN000; + ;AN000; +DTND_20: ;AN002; + PUSH DS ;AN000; + PUSH SS ;AN000; + POP DS ;AN000; +ASSUME DS:DOSGROUP ;AN000; + PUSH [YEAR] ; The routines in DOS (in particular ;AN000; + ; GET_DATE) do not like [YEAR] ;AN000; + ; getting changed by the call ;AN000; + ; to SETYEAR. ;AN000; + PUSH SI ;AN000; + PUSH BX ;AN000; + PUSH AX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; + MOV CL,9 ;AN000; + SHR DX,CL ; Year to DL ;AN000; + MOV CX,DX ; Year in CX (CL) ;AN000; + POP DX ;AN000; + AND DX,1FFH ; Mask off year ;AN000; + SHL DX,1 ;AN000; + SHL DX,1 ;AN000; + SHL DX,1 ; Month in DH ;AN000; + SHR DL,1 ;AN000; + SHR DL,1 ;AN000; + SHR DL,1 ; Right justify day in DL ;AN000; + CallInstall SetYear,MultDOS,27 ; Set [YEAR] and # days in FEB ;AN000; + SHR CX,1 ;AN000; + SHR CX,1 ; Divide year by 4, chuck remainder ;AN000; + MOV AX,FOURYEARS ;AN000; + MOV BX,DX ; Get DX out of way ;AN000; + MUL CX ; # days in AX ;AN000; + MOV CL,BYTE PTR [YEAR] ;AN000; + AND CL,3 ; Get remainder from / by 4 ;AN000; + MOV SI,OFFSET DOSGROUP:YRTAB ;AN000; + MOV DX,AX ;AN000; + SHL CX,1 ; Two entries/year ;AN000; + CallInstall DSum,MultDOS,28,, ;AN000; + MOV CL,BH ; Month ;AN000; + DEC CX ; Make 0 indexed ;AN000; + MOV SI,OFFSET DOSGROUP:MONTAB ;AN000; + CallInstall DSum,MultDOS,28,, ;AN000; + MOV CL,BL ; day of month ;AN000; + DEC CX ; Make 0 indexed ;AN000; + ADD CX,DX ; CX is days since 1-1-80 ;AN000; +; ;AN000; +; The following three instructions implement this: ;AN000; +; ;AN000; +; CX * 15180H sec/day = (CX * 5180H) + (CX * 10000H) ;AN000; +; ;AN000; + MOV AX,5180h ;AN000; + MUL CX ; (DX:AX) = days * 5180h ;AN000; + ADD DX,CX ; (DX:AX) = days * 15180h = seconds ;AN000; + ;AN000; + ADD AX,0A600H ;AN000; + ADC DX,012CEH ; Bias by # seconds from 1-1-70 to ;AN000; + ; 1-1-80 (12CEA600H) ;AN000; + POP BX ; Get DOS time ;AN000; + PUSH AX ;AN000; + PUSH DX ; Save date seconds ;AN000; + PUSH BX ;AN000; + MOV CL,11 ;AN000; + SHR BX,CL ; BX is hours ;AN000; + MOV AX,60 ;AN000; + MUL BX ; AX hours converted to minutes ;AN000; + ; 5A0H min/day so DX = 0 ;AN000; + POP BX ;AN000; + PUSH BX ;AN000; + AND BX,7FFH ; Mask off hours ;AN000; + MOV CL,5 ;AN000; + SHR BX,CL ; BX is minutes ;AN000; + ADD AX,BX ; AX is minutes ;AN000; + MOV BX,60 ;AN000; + MUL BX ; DX:AX is hours:min converted to sec ;AN000; + POP BX ;AN000; + AND BX,1FH ; BX is seconds/2 ;AN000; + SHL BX,1 ; BX is seconds ;AN000; + ADD AX,BX ;AN000; + ADC DX,0 ;AN000; + MOV CX,AX ; DX:CX is DOS time in seconds ;AN000; + POP BX ;AN000; + POP SI ; BX:SI is DOS Date in seconds ;AN000; + ADD CX,SI ;AN000; + ADC DX,BX ; DX:CX is NET time ;AN000; + POP AX ;AN000; + POP BX ;AN000; + POP SI ;AN000; + POP [YEAR] ;AN000; + POP DS ;AN000; + return ;AN000; + ;AN000; +EndProc DOS_TO_NET_DATE ;AN000; + ;AN000; +; Inputs: ;AN000; +; DX:CX = Seconds since 1-1-70 ;AN000; +; Function: ;AN000; +; Convert Network date to DOS Date Time ;AN000; +; NOTE: WARNING!!!!!!! ;AN000; +; This routine WILL NOT convert network times > 92CEA5FFH ;AN000; +; (7FFFFFFF + 12CEA600). If such a time is encountered this ;AN000; +; routine returns 1-1-80 0:0:0. ;AN000; +; Outputs: ;AN000; +; DX = MS-DOS Date ;AN000; +; CX = MS-DOS Time ;AN000; +; No other registers Revised ;AN000; + ;AN000; + procedure NET_TO_DOS_DATE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + SUB CX,0A600H ;AN000; + SBB DX,012CEH ; UnBias by # seconds from 1-1-70 to ;AN000; + ; 1-1-80 (12CEA600H) ;AN000; + JNC GO_ON ;AN000; + ; Date is before 1-1-80 ;AN000; +TO_BIG_LITTLE_TIME: ;AN000; + XOR DX,DX ;AN000; + MOV CX,DX ; Set 1-1-80 0:0:0 ;AN000; + return ;AN000; + ;AN000; +GO_ON: ;AN000; + TEST DX,8000H ; Check for high bit ;AN000; + JNZ TO_BIG_LITTLE_TIME ;AN000; + PUSH DS ;AN000; + PUSH SS ;AN000; + POP DS ;AN000; +ASSUME DS:DOSGROUP ;AN000; + PUSH [YEAR] ; The routines in DOS (in particular ;AN000; + ; GET_DATE) do not like [YEAR] ;AN000; + ; getting changed by the call ;AN000; + ; to SETYEAR. ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH SI ;AN000; + PUSH BP ;AN000; + XCHG AX,CX ; DX:AX # seconds ;AN000; + MOV SI,0A8C0h ; (si) = seconds in a half day ;AN000; + ; 15180H/2 ;AN000; +; ;AN000; +; NOTE: The following DIV is the reason we can't convert times with the ;AN000; +; high bit set (after they're unbiased by 1-1-80 - 1-1-70). ;AN000; +; If we tried one it MIGHT overflow. The cutoff is ;AN000; +; actually (A8C0 * FFFF) + A8BF = A8BFFFFF but we choose a smaller ;AN000; +; number (7FFFFFFF) because it's easier to test for. 7FFFFFFF = ;AN000; +; about 68 years from 1-1-80 which is 1-1-2048. ;AN000; +; ;AN000; + DIV SI ; (AX) = 2*days ;AN000; + ; (CX) = half-day remainder ;AN000; + MOV BX,DX ;AN000; + XOR DX,DX ;AN000; + MOV CX,DX ;AN000; + SHR AX,1 ; DX:AX = days ;AN000; + JNC NTDD1 ; didn't shift off a bit, no extra rem ;AN000; + ADD BX,0A8C0h ; did shift bit, adjust remainder ;AN000; + ADC CX,0 ; by extra 1/2 day of seconds ;AN000; + ;AN000; + ;DX:AX is # days since 1-1-80 ;AN000; + ;CX:BX is seconds into that day ;AN000; +NTDD1: ;AN000; + PUSH DX ;AN000; + PUSH AX ;AN000; + MOV DX,CX ;AN000; + MOV AX,BX ;AN000; + MOV CX,60 ; 60 sec/min ;AN000; + DIV CX ;AN000; + ;AX is min, DX(DL) is secs ;AN000; + DIV CL ; 60 min/hr ;AN000; + ;AH is Min, AL is hrs ;AN000; + SHR DL,1 ; Div seconds by 2 ;AN000; + AND DL,1FH ; DL is seconds/2 ;AN000; + MOV DH,AH ; Copy min to DH ;AN000; + MOV CL,5 ;AN000; + SHL AH,CL ; Low 3 bits of min in high 3 bits ;AN000; + OR DL,AH ; DL is now low byte of time ;AN000; + MOV CL,3 ;AN000; + SHR DH,CL ; High 3 bits of min to low 3 bits ;AN000; + AND DH,7 ;AN000; + MOV CL,3 ;AN000; + SHL AL,CL ; Hours to high 5 bits ;AN000; + AND AL,0F8H ;AN000; + OR DH,AL ; DX is now DOS time ;AN000; + MOV CX,DX ;AN000; + POP AX ;AN000; + POP DX ; DX:AX days since 1-1-80 ;AN000; + PUSH CX ; Stash time ;AN000; + MOV CX,FOURYEARS ;AN000; + DIV CX ; AX # four year increments ;AN000; + ; DX remainder days ;AN000; + SHL AX,1 ;AN000; + SHL AX,1 ;AN000; + SHL AX,1 ; Mult by 8 (AX # 1/2 years) ;AN000; + MOV CX,AX ;AN000; + MOV SI,OFFSET DOSGROUP:YRTAB ;AN000; + CallInstall DSlide,MultDOS,29,, ;AN000; + SHR CX,1 ; 1/2 years to whole years ;AN000; + JNC SK ;AN000; + ADD DX,200 ; Extra 1/2 year ;AN000; +SK: ;AN000; + CallInstall SetYear,multDOS,27 ;AN000; + PUSH CX ;AN000; + MOV CL,1 ; At least at first month in year ;AN000; + MOV SI,OFFSET DOSGROUP:MONTAB ;AN000; + CallInstall DSlide,MultDOS,29,, ;AN000; + INC DX ; Days start at 1 ;AN000; + POP AX ;AN000; + MOV CH,CL ;AN000; + ; DL is day, CH is month, AL is year ;AN000; + SHL AL,1 ; Year to high 7 bits ;AN000; + AND AL,0FEH ;AN000; + MOV AH,CH ;AN000; + MOV CL,3 ;AN000; + SHR AH,CL ; High bit of month to bit 0 ;AN000; + AND AH,1 ;AN000; + OR AH,AL ; AH is high byte of date ;AN000; + AND DL,1FH ; Day is low 5 bits ;AN000; + MOV CL,5 ;AN000; + SHL CH,CL ; Low 3 bits of month to high 3 bits ;AN000; + AND CH,0E0H ;AN000; + OR DL,CH ;AN000; + MOV DH,AH ; Date in DX ;AN000; + POP CX ; Time to CX ;AN000; + POP BP ;AN000; + POP SI ;AN000; + POP BX ;AN000; + POP AX ;AN000; + POP [YEAR] ;AN000; + POP DS ;AN000; + return ;AN000; + ;AN000; +EndProc NET_TO_DOS_DATE ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; +END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSFILE.ASM b/v4.0/src/CMD/IFSFUNC/IFSFILE.ASM new file mode 100644 index 0000000..5b0188f --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFILE.ASM @@ -0,0 +1,1778 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsfile.asm 1.0 87/05/11 ;AN000; +TITLE IFS FILE ROUTINES - Routines for IFS dispatch ;AN000; +NAME IFSFILE ;AN000; +;************************************************************************************ +; +; FILE (WFP_START) related Network calls +; +; IFS_DISK_INFO +; IFS_SEQ_SET_FILE_ATTRIBUTE +; IFS_SET_FILE_ATTRIBUTE +; IFS_SEQ_GET_FILE_INFO +; IFS_GET_FILE_INFO +; IFS_SEQ_RENAME +; IFS_RENAME +; IFS_SEQ_DELETE +; IFS_DELETE +; IFS_SEQ_OPEN +; IFS_OPEN +; IFS_SEQ_CREATE +; IFS_CREATE +; IFS_SEQ_XOPEN +; IFS_XOPEN +; IFS_SEQ_SEARCH_FIRST +; IFS_SEQ_SEARCH_NEXT +; IFS_SEARCH_FIRST +; IFS_SEARCH_NEXT +; OPEN_CHECK_SEQ +; +; Programming notes: +; Old redirector segmentation and DOS interface preserved. +; Routine prologues are accurate for input/output. +; However, the pseudocode was not kept up to date. +; Use it for a rough idea of the routine function. +; +; REVISION HISTORY: +; A000 Original version 4.00 - May 1987 +; A001 PTM 316 - Fix search next drive byte interpretation +; Set drive number in DMAADD +; A002 PTM 845 - Disk info ignored +; A003 PTM 869 - Lock failure due to sf_ifs_hdr not set +; A004 DCR 213 - SFT Serial number +; A005 PTM 849 - Printer open problems +; A006 PTM 1518- open mode/flag finalized +; A007 PTM ????- Action Taken not set on Extended open 10/27 FEIGENBAUM +; A008 PTM ????- Old Open/Creates pass parms list 10/27 FEIGENBAUM +; A009 PTM 2247- Delete does not return carry on error 11/3 RG +; A010 PTM 2248- Old Create mode incorrect - must be 2 11/3 RG +; A011 DCR 285 - Remove Extended Attribute/Lock support 1/88 RG +; A012 PTM 3968- set sft time/date on create 3/25/88 RMG +; A013 - sft analysis changes 3/25/88 RMG +; A014 Austin Deviceless Attach problems 3/28/88 RMG +; A015 P4392 SFT change - attr_hi gone 4/19/88 RMG +; A016 P4801 File size segment not right 5/10/88 RMG +; A017 P???? DS not preserved during CALLBACK 5/13/88 RPS +; LOC - 486 +; +;************************************************************************************ + +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +INCLUDE DOSCNTRY.INC +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; then define the base code segment of the ifsfunc support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; include the rest of the segment definitions for normal MSDOS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ;DOSGROUP Data ;AN000; + Extrn REN_WFP:WORD ;AN000; + Extrn WFP_START:WORD ;AN000; + Extrn SATTRIB:BYTE ;AN000; + Extrn ATTRIB:BYTE ;AN000; + Extrn THISCDS:DWORD ;AN000; + Extrn THISSFT:DWORD ;AN000; + Extrn DMAADD:DWORD ;AN000; + Extrn CDSADDR:DWORD ;AN000; + Extrn SAVE_BX:WORD ;AN000; + Extrn SAVE_CX:WORD ;AN000; + Extrn SAVE_DX:WORD ;AN000; + Extrn SAVE_SI:WORD ;AN000; + Extrn SAVE_DI:WORD ;AN000; + Extrn SAVE_DS:WORD ;AN000; + Extrn SAVE_ES:WORD ;AN000; + Extrn Name1:BYTE ;AN000; + Extrn DEVPT:DWORD ;AN000; + Extrn CPSWFLAG:BYTE + Extrn COUNTRY_CDPG:BYTE +if debug ;AN000; + Extrn BugLev:WORD ;AN000; + Extrn BugTyp:WORD ;AN000; + include bugtyp.asm ;AN000; +endif ;AN000; +DATA ENDS ;AN000; + ;AN000; + ;AN000; +; define our own code segment ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn IFSDRV:BYTE ;AN000; + Extrn IFSPROC_FLAGS:WORD ;AN000; + Extrn UNC_FS_HDR:DWORD ;AN000; + Extrn THISIFS:DWORD ;AN000; + Extrn THISDFL:DWORD ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + Extrn SFT_SERIAL_NUMBER:WORD ;AN004; + Extrn fAssign:BYTE ;AN014; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_DISK_INFO ;AN000; +; ;AN000; +; Input: ;AN000; +; ES:DI -> CDS (not NULL) ;AN000; +; DS -> DOSGROUP ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Total length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 2 ; Disk Attributes ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ; Call CDS_TO_CD to convert CDS to CD ;AN000; +; ; and set this as pointer to it. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; + IFSR_ALLOCUNITS DW number of allocation units ;AN000; +; + IFSR_ALLOCSIZE DW allocation unit sectors ;AN000; +; + IFSR_SECTSIZE DW sector size ;AN000; +; + IFSR_AVAILALLOC DW free allocation units ;AN000; +; + IFSR_FSID DB file system media id ;AN000; +; IFSR_RESV3 DB 0 ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call CD_TO_CDS to update CDS ;AN000; +; Set: ;AN000; +; DX = IFSR_AVAILALLOC ;AN000; +; BX = IFSR_ALLOCUNITS ;AN000; +; CX = IFSR_SECTSIZE ;AN000; +; AL = IFSR_ALLOCSIZE ;AN000; +; AH = IFSR_FSID ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Put error code in AX ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Output: ;AN000; +; DX = Number of free allocation units ;AN000; +; BX = Total Number of allocation units on disk ;AN000; +; CX = Sector size ;AN000; +; AL = Sectors per allocation unit ;AN000; +; AH = Media ID BYTE ;AN000; +; Carry set if error ;AN000; +; ;AN000; +; Regs: Segs and DI preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_DISK_INFO,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + MOV AX,DI ; set ifsDrv for possible I24 ;AN000; + invoke IFSDrvFromCDS ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for diskattr ;AN000; + ifsr_api_def DISKATTR ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; & processing flags ;AN000; + ;AN000; + PUSH ES ; set ds:si -> cds ;AN000; + POP DS ;AN000; + MOV SI,DI ;AN000; + ;AN000; + invoke PREP_IFSR ; init ifsr ;AN000; + SaveReg ; save for cd_to_cds ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_DISKATTR ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSDISKATTR ;AN000; + ;AN000; + invoke CALL_IFS ; call fs with diskattr request ;AN000; + ;AN000; + JNC DA_20 ;AN000; + RestoreReg ; error - restore stack ;AN000; + JMP FA_1000 ; go return ;AN000; +DA_20: ;AN000; + MOV DX,ES:[BX.IFSR_AVAILALLOC] ; no error - load return regs ;AN000; + MOV CX,ES:[BX.IFSR_SECTSIZE] ;AN000; + MOV AX,ES:[BX.IFSR_ALLOCSIZE] ;AN000; + MOV AH,ES:[BX.IFSR_FSID] ;AN000; + MOV BX,ES:[BX.IFSR_ALLOCUNITS] ;AM002; + RestoreReg ; restore cds into es:di ;AN000; + invoke CD_TO_CDS ;AN000; + CLC ;AN000; + JMP FA_1000 ; go ret in file attr routine ;AN000; + ; since it restores ds-dosgroup ;AN000; + ;AN000; +EndProc IFS_DISK_INFO ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_SET_FILE_ATTRIBUTE ;AN000; +; ;AN000; +; see IFS_GET_FILE_INFO for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_SET_FILE_ATTRIBUTE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def FILEATTR ;AN000; + ;AN000; + PUSH AX ; save file attrs ;AN000; + ;AN000; + invoke CHECK_SEQ ; check if this is unc or ifs device ;AN000; + JC SA_20 ; cf=0 unc, cf=1 device ;AN000; + ;AN000; + PUSH CS ; get addressability to IFSSEG ;AN000; + POP DS ; prep ifsflags for set ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV IFSPROC_FLAGS,ZERO ;AN000; + JMP SHORT SFA_20 ; cont. in ifs_seq_get_fa ;AN000; + ;AN000; +EndProc IFS_SEQ_SET_FILE_ATTRIBUTE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SET_FILE_ATTRIBUTE ;AN000; +; ;AN000; +; see IFS_GET_FILE_INFO for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SET_FILE_ATTRIBUTE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def FILEATTR ;AN000; + ;AN000; + PUSH AX ; save file attrs ;AN000; +SA_20: ;AN000; + MOV CS:IFSPROC_FLAGS,0 ; prep ifsflags ;AN000; + JMP SHORT FA_20 ; cont. in ifs_get_file_info ;AN000; + ;AN000; +EndProc IFS_SET_FILE_ATTRIBUTE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_GET_FILE_ATTRIBUTE ;AN000; +; ;AN000; +; see IFS_GET_FILE_INFO for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_GET_FILE_INFO,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def FILEATTR ;AN000; + ;AN000; + invoke CHECK_SEQ ; check if this is unc or ifs device ;AN000; + JC FA_10 ; cf=0 unc, cf=1 device ;AN000; + ;AN000; + PUSH CS ; prep ifsflags for get & seq ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV IFSPROC_FLAGS,ISGET ;AN000; + ;AN000; +SFA_20: ;AN000; + OR IFSPROC_FLAGS,ISSEQ ; SEQ - UNC ;AN000; + invoke SET_THISIFS_UNC ; set thisifs = unc ;AN000; + invoke PREP_IFSR ; init ifsr ;AN000; + JMP SHORT FA_200 ; cont. in ifs_get_file_info ;AN000; + ;AN000; +EndProc IFS_SEQ_GET_FILE_INFO ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; GET_FILE_INFO ;AN000; +; ;AN000; +; Routines called: DFL_SINGLE_FILE_CHECK ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ("//" must be first 2 chars, NUL ;AN000; +; terminated) ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; (Low word = -1 if NUL CDS (dfl)) ;AN000; +; [SATTRIB] is attribute of search (determines what files may be found) ;AN000; +; AX is new attributes to give to file (already checked for bad bits) ;AN000; +; Function: ;AN000; +; ;AN000; +; IF seq call THEN ;AN000; +; DO ;AN000; +; Set IFS Header pointer to UNC IFS ;AN000; +; Set IFSR_DEVICE_CB@ = null ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; IF [THISCDS] .NOT. NULL THEN ;AN000; +; CALL CDS_TO_CD ;AN000; +; ELSE DO ;AN000; +; CALL DFL_SINGLE_FILE_CHECK ;AN000; +; IF have DFL that supports single file fcns THEN ;AN000; +; call DFL_TO_DF ;AN000; +; ELSE set error - device not IFS or no single file support ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; IF no error THEN ;AN000; +; DO ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 66 ; Total length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 15 ; File Attributes - get/set by name ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ; CD/DF ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB ? ; 2=get 3=set depends on INT 2FH ;AN000; +; * IFSR_RESV3 DB ? +; * IFSR_SUBFUNC DB 0 ; in-line parms ;AN000; +; * IFSR_RESV4 DB ? +; IFSR_BUFFER1@ DD ? ; not used here +; IFSR_BUFFER2@ DD ? ; not used here +; IFSR_COUNT DW ? ; not used here +; * IFSR_MATCHATTR DW ? ; format 0000000re0advshr ;AN000; +; * IFSR_NAME@ DD ? ; ASCIIZ file name ptr ;AN000; +; + IFSR_SIZE DD ? ; file size ;AN000; +; + IFSR_DATE DW ? ; file date ;AN000; +; + IFSR_TIME DW ? ; file time ;AN000; +; *+ IFSR_ATTR DW ? ; file attribute ;AN000; +; ; format 0000000re0advshr ;AN000; +; ; Set to AX on set ;AN000; +; ;AN000; +; IF set THEN ;AN000; +; DO ;AN000; +; IFSR_FUNC = 3 ;AN000; +; IFSR_ATTR = AX ;AN000; +; ENDDO ;AN000; +; ELSE IFSR_FUNC = 2 ;AN000; +; ENDIF ;AN000; +; CALL routine, CALL_IFS, with pointer to IFS Header ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; IF cds THEN Call CD_TO_CDS ;AN000; +; IF dfl THEN Call DF_TO_DFL ;AN000; +; IF get THEN ;AN000; +; DO ;AN000; +; AX = IFSR_ATTR ;AN000; +; CX = IFSR_TIME ;AN000; +; DX = IFSR_DATE ;AN000; +; BX:DI = IFSR_SIZE ;AN000; +; ENDDO ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; AX = IFSR_RETCODE ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ELSE Set carry ;AN000; +; ENDIF ;AN000; +; Outputs: ;AN000; +; CARRY CLEAR ;AN000; +; AX = ATTR ;AN000; +; CX = TIME ;AN000; +; DX = DATE ;AN000; +; BX:DI = SIZE ;AN000; +; CARRY SET ;AN000; +; AX is error code ;AN000; +; error_file_not_found ;AN000; +; Last element of path not found ;AN000; +; error_path_not_found ;AN000; +; Bad path (not in curr dir part if present) ;AN000; +; error_access_denied ;AN000; +; Attempt to set an attribute which cannot be set ;AN000; +; (attr_directory, attr_volume_ID) ;AN000; +; error_sharing_violation ;AN000; +; Sharing mode of file did not allow the change ;AN000; +; (this request requires exclusive write/read access) ;AN000; +; (INT 24H generated) ;AN000; +; ;AN000; +; Regs: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_GET_FILE_INFO,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for fileattr ;AN000; + ifsr_api_def FILEATTR ;AN000; + ;AN000; +FA_10: ;AN000; + MOV CS:IFSPROC_FLAGS,ISGET ; set for get ;AN000; + ;AN000; +FA_20: ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + CMP WORD PTR [THISCDS],NULL_PTR ; determine CDS or DFL ;AN000; + JE FA_100 ;AN000; + LDS SI,[THISCDS] ;AN000; +ASSUME DS:NOTHING ;AN000; + TEST CS:IFSPROC_FLAGS,ISGET ;AN000; + JZ FA_40 ;AN000; + SaveReg ; preserve ds:si -> cds ;AN000; + JMP SHORT FA_60 ;AN000; +FA_40: ;AN000; + RestoreReg ; want attr on stack to stay on top ;AN000; + SaveReg ; stack - ax,si,ds ;AN000; + ;AN000; +FA_60: ;AN000; + invoke PREP_IFSR ; clear ifsrh ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; DS - IFSSEG ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + JMP FA_200 ;AN000; + ;AN000; +FA_100: ;AN000; + invoke DFL_SINGLE_FILE_CHECK ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; DS - IFSSEG ;AN000; + JNC SHORT FA_200 ;AN000; + MOV AX,error_invalid_function ; error - invalid fcn ;AN000; + invoke SET_EXTERR_INFO ; set error info & ;AN000; + JMP FA_980 ; go return ;AN000; + ;AN000; +FA_200: ;AN000; + invoke DRIVE_FROM_CDS ; set IFSDrv for possible I24 ;AN000; + ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_FILEATTR ; continue prepping ifsr ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSFILEATTR ;AN000; + TEST IFSPROC_FLAGS,ISGET ;AN000; + JNZ FA_220 ;AN000; + MOV ES:[BX.IFSR_FUNC],FUNC_SET_BY_NAME ;AN000; + POP ES:[BX.IFSR_ATTR] ; retrieve attr from stack ;AN000; + JMP SHORT FA_240 ;AN000; +FA_220: ;AN000; + MOV ES:[BX.IFSR_FUNC],FUNC_GET_BY_NAME ; get file info ;AN000; + ;AN000; +FA_240: ;AN000; + PUSH DS ; save ds - IFSSEG ;AN000; + PUSH SS ; get ds = dosgroup so can access ;AN000; + POP DS ; wfp_start, sattrib ;AN000; +ASSUME DS:DOSGROUP ;AN000; + ;AN000; + MOV SI,[WFP_START] ;AN000; + invoke STRIP_WFP_START ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME@],SI ; ifsr_name@ ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME@+2],DS ;AN000; + MOV AL,[SATTRIB] ;AN000; + XOR AH,AH ;AN000; + MOV ES:[BX.IFSR_MATCHATTR],AX ; ifsr_matchattr ;AN000; + ;AN000; + POP DS ; restore ds=IFSSEG ;AN000; +ASSUME DS:IFSSEG ;AN000; + +;************************************************ + invoke CALL_IFS ; call ifs with file attr request ;AN000; +;************************************************ + ;AN000; + JNC FA_260 ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; request failed - ;AN000; + JZ FA_980 ; go set carry & return ;AN000; + ADD SP,4 ; if cds, restore stack first ;AN000; + JMP FA_980 ;AN000; + ;AN000; +FA_260: ; request successful ;AN000; + TEST IFSPROC_FLAGS,ISGET ; if get - prep return regs with ;AN000; + JZ FA_270 ; file info ;AN000; + MOV AX,ES:[BX.IFSR_ATTR] ;AN000; + MOV CX,ES:[BX.IFSR_TIME] ;AN000; + MOV DX,ES:[BX.IFSR_DATE] ;AN000; + MOV DI,ES:WORD PTR [BX.IFSR_SIZE] ;AN000; + MOV BX,ES:WORD PTR [BX.IFSR_SIZE+2] ;AC016; +FA_270: ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; if cds - update cds w/cd ;AN000; + JZ FA_280 ;AN000; + RestoreReg ; restore cds ptr into es:di ;AN000; + invoke CD_TO_CDS ; cd-cds ;AN000; + JMP SHORT FA_990 ; go clc & return ;AN000; +FA_280: ;AN000; + TEST IFSPROC_FLAGS,ISSEQ ;AN000; + JNZ FA_990 ;AN000; + invoke DF_TO_DFL ; update dfl w/df ;AN000; + JMP SHORT FA_990 ;AN000; + ;AN000; +FA_980: ;AN000; + STC ;AN000; + JMP SHORT FA_1000 ;AN000; +FA_990: ;AN000; + CLC ;AN000; +FA_1000: ;AN000; + PUSH SS ; restore original ds (dosgroup) ;AN000; + POP DS ; since this routine preserves ds ;AN000; + return ;AN000; + ;AN000; + ;AN000; +EndProc IFS_GET_FILE_INFO ;AN000; + ;AN000; +BREAK ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_RENAME ;AN000; +; ;AN000; +; see ifs_rename for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + procedure IFS_SEQ_RENAME,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def RENFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ISREN ; set for rename and cont. ;AN000; + JMP SHORT SD_10 ; in ifs_seq_delete ;AN000; + ;AN000; + ;AN000; +EndProc IFS_SEQ_RENAME ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_RENAME ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to SOURCE WFP string ("//" must be first 2 ;AN000; +; chars, NUL terminated) ;AN000; +; [REN_WFP] Points to DEST WFP string ("//" must be first 2 ;AN000; +; chars, NUL terminated) ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; [SATTRIB] Is attribute of search, determines what files can be found ;AN000; +; Function: ;AN000; +; same processing as delete except for following parms: ;AN000; +; * IFSR_LENGTH DB 48 ;AN000; +; * IFSR_APIFUNC DB 7 ; Rename file ;AN000; +; * IFSR_NAME1@ DD ? ; addr of WFP_START ;AN000; +; * IFSR_NAME2@ DD ? ; addr of REN_WFP ;AN000; +; ;AN000; +; Outputs: ;AN000; +; CARRY CLEAR ;AN000; +; OK ;AN000; +; CARRY SET ;AN000; +; AX is error code ;AN000; +; error_file_not_found ;AN000; +; No match for source, or dest path invalid ;AN000; +; error_not_same_device ;AN000; +; Source and dest are on different devices ;AN000; +; error_access_denied ;AN000; +; Directory specified (not simple rename), ;AN000; +; Device name given, Destination exists. ;AN000; +; NOTE: In third case some renames may have ;AN000; +; been done if metas. ;AN000; +; error_path_not_found ;AN000; +; Bad path (not in curr dir part if present) ;AN000; +; SOURCE ONLY ;AN000; +; error_sharing_violation ;AN000; +; Deny both access required, generates an INT 24. ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_RENAME,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def RENFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ISREN ; set for rename ;AN000; + JMP SHORT D_20 ; processing continues in ifs_delete ;AN000; + ;AN000; +EndProc IFS_RENAME ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_DELETE ;AN000; +; ;AN000; +; see ifs_delete for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + procedure IFS_SEQ_DELETE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DELFILE ;AN000; + ;AN000; + MOV IFSPROC_FLAGS,0 ; Clear IFS processing flags ;AN000; +SD_10: ;AN000; + invoke CHECK_SEQ ; check if this is unc or ifs device ;AN000; + JC D_20 ; cf=0 unc, cf=1 device ;AN000; + ;AN000; +SD_20: ; welcome ifs_seq_rename code ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + OR IFSPROC_FLAGS,ISSEQ ; SEQ - UNC ;AN000; + invoke SET_THISIFS_UNC ; set [THISIFS] = UNC IFS ;AN000; + JMP SHORT D_30 ; cont. in ifs_delete ;AN000; + ;AN000; +EndProc IFS_SEQ_DELETE ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_DELETE ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: CDS_TO_CD ;AN000; +; CD_TO_CDS CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ("//" must be first 2 chars, NUL ;AN000; +; terminated) ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; [SATTRIB] Is attribute of search, determines what files can be found ;AN000; +; Function: ;AN000; +; IF INT 2FH call .NOT. SEQ version THEN ;AN000; +; DO ;AN000; +; IF [THISCDS] .NOT. NULL THEN ;AN000; +; DO ;AN000; +; CALL CDS_TO_CD ;AN000; +; Set IFS_DEVICE_CB@ as pointer to CD ;AN000; +; Set IFS_HDR_PTR = CURDIR_IFS_HDR ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Set AX = invalid function ;AN000; +; Set extended error info ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Set IFS_DEVICE_CB@ to NULL ;AN000; +; Set IFS_HDR_PTR = [UNC_FS_HDR] ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; IF no error THEN ;AN000; +; DO ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 44 ; Total length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 6 ; Delete file ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ; CD ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_MATCHATTR DW ? ; attribute - format 00000000e0a00shr ;AN000; +; * IFSR_NAME@ DD ? ; filename to delete ;AN000; +; ;AN000; +; Call routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call CD_TO_CDS or DF_TO_DFL ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; AX = IFSR_RETCODE ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ELSE set carry ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; CARRY CLEAR ;AN000; +; OK ;AN000; +; CARRY SET ;AN000; +; AX is error code ;AN000; +; error_file_not_found ;AN000; +; Last element of path not found ;AN000; +; error_path_not_found ;AN000; +; Bad path ;AN000; +; error_access_denied ;AN000; +; Attempt to delete device or directory ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_DELETE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DELFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; Clear IFS processing flags ;AN000; + ;AN000; +D_20: ; (Welcome ifs_ren) ;AN000; +ASSUME DS:DOSGROUP ;AN000; + invoke DRIVE_FROM_CDS ; ds - dosgroup ;AN000; + CMP WORD PTR [THISCDS],NULL_PTR ; CDS must not be null ;AN000; + JNE D_30 ;AN000; + MOV AX,error_invalid_function ;AN000; + invoke SET_EXTERR_INFO ;AN000; + JMP FA_980 ; go up, preserve ds, ret w/carry ;AN000; +D_30: ; (Welcome seq ren/del code) ;AN000; + invoke PREP_IFSR ; zero ifsr, es:bx -> ifsr ;AN000; + MOV SI,[WFP_START] ;AN000; + invoke STRIP_WFP_START ;AN000; + TEST CS:IFSPROC_FLAGS,ISREN ;AN000; + JZ D_40 ; rename ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME1@],SI ; ifsr_name1@ & 2@ ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME1@+2],DS ;AN000; + MOV SI,[REN_WFP] ;AN000; + CMP BYTE PTR DS:[SI+1],":" ;AN000; + JNE D_36 ;AN000; + ADD SI,2 ;AN000; +D_36: ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME2@],SI ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME2@+2],DS ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_RENFILE ; ifsr_length ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSRENFILE ; ifsr_apifunc ;AN000; + JMP SHORT D_60 ;AN000; +D_40: ; delete ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME@],SI ; ifsr_name@ ;AN000; + MOV ES:WORD PTR [BX.IFSR_NAME@+2],DS ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_DELFILE ; ifsr_length ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSDELFILE ; ifsr_apifunc ;AN000; +D_60: ;AN000; + MOV AL,[SATTRIB] ;AN000; + XOR AH,AH ;AN000; + MOV ES:[BX.IFSR_MATCHATTR],AX ; ifsr_matchattr ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ; ifsr_function ;AN000; + ;AN000; + TEST CS:IFSPROC_FLAGS,ISSEQ ; if unc, don't do cds stuff ;AN000; + JNZ D_70 ;AN000; + LDS SI,[THISCDS] ;AN000; +ASSUME DS:NOTHING ;AN000; + SaveReg ; preserve ds:si -> cds ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + ;AN000; +D_70: ;AN000; + invoke CALL_IFS ; call ifs w/request ;AN000; + ;AN000; + JNC D_80 ;AN000; + TEST IFSPROC_FLAGS,ISSEQ ; fs error - restore stack ;AN000; + JZ D_75 ; if not unc - go ret ;AN000; + JMP FA_980 ;AC009; +D_75: ;AN000; + ADD SP,4 ;AN000; + JMP FA_980 ;AC009; + ;AN000; +D_80: ;AN000; + TEST IFSPROC_FLAGS,ISSEQ ; fs successful ;AN000; + JZ D_90 ; if seq, just ret ;AN000; + JMP FA_990 ;AN000; +D_90: ; else - ;AN000; + RestoreReg ; restore cds ptr into es:di ;AN000; + invoke CD_TO_CDS ;AN000; + JMP FA_990 ; go up & ret in fa to preserve ds ;AN000; + ;AN000; + ;AN000; +EndProc IFS_DELETE ;AN000; + ;AN000; +BREAK ;AN000; +;************************************************************************************ ;AN000; +; see IFS_OPEN for details ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_OPEN,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + PUSH AX ; save access/share byte ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ISOLDOPEN ; remember this is old open ;AN000; + JMP SHORT SXO_10 ; cont. in ifs_seq_xopen ;AN000; + ;AN000; +EndProc IFS_SEQ_OPEN ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_OPEN ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ("//" must be first 2 chars, NUL ;AN000; +; terminated) ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; [THISSFT] Points to SFT to fill in if file found ;AN000; +; (sf_mode field set so that FCB may be detected) ;AN000; +; ES:DI = [THISSFT] ;AN000; +; [SATTRIB] Is attribute of search, determines what files can be found ;AN000; +; AX is Access and Sharing mode ;AN000; +; High NIBBLE of AL (Sharing Mode) ;AN000; +; sharing_compat file is opened in compatibility mode ;AN000; +; sharing_deny_none file is opened Multi reader, Multi writer ;AN000; +; sharing_deny_read file is opened Only reader, Multi writer ;AN000; +; sharing_deny_write file is opened Multi reader, Only writer ;AN000; +; sharing_deny_both file is opened Only reader, Only writer ;AN000; +; Low NIBBLE of AL (Access Mode) ;AN000; +; open_for_read file is opened for reading ;AN000; +; open_for_write file is opened for writing ;AN000; +; open_for_both file is opened for both reading and writing. ;AN000; +; ;AN000; +; For FCB SFTs AL should = -1 ;AN000; +; (not checked) ;AN000; +; Function: ;AN000; +; see IFS_XOPEN ;AN000; +; Outputs: ;AN000; +; sf_ref_count is NOT altered ;AN000; +; CARRY CLEAR ;AN000; +; THISSFT filled in. ;AN000; +; CARRY SET ;AN000; +; AX is error code ;AN000; +; error_file_not_found ;AN000; +; Last element of path not found ;AN000; +; error_path_not_found ;AN000; +; Bad path ;AN000; +; error_access_denied ;AN000; +; Attempt to open read only file for writting, or ;AN000; +; open a directory ;AN000; +; error_sharing_violation ;AN000; +; The sharing mode was correct but not allowed ;AN000; +; generates an INT 24 on compatibility mode SFTs ;AN000; +; Regs: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_OPEN,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + PUSH AX ; save access/share mode ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ISOLDOPEN ; set for old open ;AN000; + JMP SHORT XO_20 ; Rest of processing in ;AN000; + ; extended open routine. ;AN000; +EndProc IFS_Open ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_CREATE ;AN000; +; ;AN000; +; see IFS_CREATE for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_CREATE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + PUSH AX ; save attribute ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,IsOldCreate + IsCreate ; remember is old create ;AN012; + JMP SHORT SXO_10 ; cont. in ifs_seq_xopen ;AN000; + ;AN000; +EndProc IFS_SEQ_CREATE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_CREATE ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL ;AN000; +; terminated) ;AN000; +; [CURR_DIR_END] Points to end of Current dir part of string ;AN000; +; ( = -1 if current dir not involved, else ;AN000; +; Points to first char after last "/" of current dir part) ;AN000; +; [THISCDS] Points to CDS being used ;AN000; +; [THISSFT] Points to SFT to fill in if file created ;AN000; +; (sf_mode field set so that FCB may be detected) ;AN000; +; ES:DI = [THISSFT] ;AN000; +; [SATTRIB] Is attribute of search, determines what files can be found ;AN000; +; AL is Attribute to create ;AN000; +; AH is 0 if CREATE, non zero if CREATE_NEW ;AN000; +; Function: ;AN000; +; See IFS_XOPEN for details ;AN000; +; Outputs: ;AN000; +; sf_ref_count is NOT altered ;AN000; +; CARRY CLEAR ;AN000; +; THISSFT filled in. ;AN000; +; sf_mode = sharing_compat + open_for_both for Non-FCB SFT ;AN000; +; CARRY SET ;AN000; +; AX is error code ;AN000; +; error_path_not_found ;AN000; +; Bad path (not in curr dir part if present) ;AN000; +; error_access_denied ;AN000; +; Attempt to re-create read only file , or ;AN000; +; create a second volume id or create a dir ;AN000; +; error_sharing_violation ;AN000; +; The sharing mode was correct but not allowed ;AN000; +; generates an INT 24 ;AN000; +; Regs: DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_CREATE,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + PUSH AX ; save attribute ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ISOLDCREATE ; remember is old create ;AN000; + JMP SHORT XO_20 ; cont. in ifs_xopen ;AN000; + ;AN000; +EndProc IFS_Create ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_XOPEN ;AN000; +; ;AN000; +; see IFS_XOPEN for details ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_XOPEN,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + MOV IFSPROC_FLAGS,0 ; Clear IFS processing flags ;AN000; +SXO_10: ;AN000; + invoke CHECK_SEQ ; check if this is unc or ifs device ;AN000; + JC XO_20 ; cf=0 unc, cf=1 device ;AN000; + ;AN000; +SXO_20: ;AN000; + PUSH CS ; ds-ifsseg ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + OR IFSPROC_FLAGS,ISSEQ ; SEQ = UNC ;AN000; + invoke SET_THISIFS_UNC ; set [THISIFS] = UNC IFS ;AN000; + invoke PREP_IFSR ; zero out ifsr ;AN000; + JMP XO_200 ; cont. in ifs_xopen ;AN000; + ;AN000; +EndProc IFS_SEQ_XOPEN ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ +; +; IFS_XOPEN +; +; Called by: IFSFUNC dispatcher +; +; Routines called: CALL_IFS DFL_MATCH +; CD_TO_CDS DFL_TO_DF +; CDS_TO_CD DF_TO_DFL +; SFT_TO_SFF +; SF_TO_SFT +; +; Inputs: +; [THISCDS] Set +; [THISSFT] Set +; [SAVE_DX] = FLAG: FUNCTION CONTROL, FORMAT=0000000C NNNN EEEE +; C 0=VALIDATE CODE PAGE, 1=NO CODE PAGE CHECK +; NNNN=DOES NOT EXIST ACTION: 0=FAIL, 1=CREATE +; EEEE=EXISTS ACTION : 0=FAIL, 1=OPEN, 2=REPLACE/OPEN +; [SAVE_BX] = MODE OPEN MODE FORMAT : 0WF00000ISSS0AAA +; AAA = ACCESS CODE: 0=READ, 1=WRITE, 2=READ/WRITE +; 3=EXECUTE (UNDOCUMENTED) +; 7=FCB (UNDOCUMENTED) +; SSS=SHARING MODE : 0=COMPATIBILITY, 1=DENY READ/WRITE +; 2=DENY WRITE, 3=DENY READ, +; 4=DENY NONE +; I 0=PASS HANDLE TO CHILD, 1=NO INHERIT +; F 0=INT 24H, 1=RETURN ERROR +; ON THIS OPEN AND ANY IO TO THIS HANDLE +; W 0=NO COMMIT, 1=AUTO-COMMIT ON WRITE +; AX = ATTR SEARCH/CREATE ATTRIBUTE +; [SAVE_DS]:[SAVE_SI] = Full path name +; [SAVE_ES]:[SAVE_DI] = Parameter list +; Null list if DI=-1 +; +; Function: +; IF SEQ THEN +; prep for UNC +; ELSE DO +; IF [THISCDS] .NOT. NULL THEN +; DO +; Call CDS_TO_CD +; Set IFSR_DEVICE_CB@ as pointer to CD +; Set IFS pointer to CURDIR_IFSR_HDR +; DFL_FLAG = 0 +; ENDDO +; ELSE DO +; Call DFL_TO_DF +; Set IFSR_DEVICE_CB@ as pointer to DF +; Set IFS pointer to DFL_IFSR_HDR +; DFL_FLAG = 1 +; ENDDO +; ENDIF +; ENDDO +; ENDIF +; Prep IFSRH: +; * IFSR_LENGTH DW 62 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; + IFSR_RETCODE DW ? +; + IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 9 ; Open/Create File +; + IFSR_ERROR_CLASS DB ? +; + IFSR_ERROR_ACTION DB ? +; + IFSR_ERROR_LOCUS DB ? +; + IFSR_ALLOWED DB ? +; + IFSR_I24_RETRY DB ? +; + IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; *+ IFSR_DEVICE_CB@ DD ? ; CD/DF +; *+ IFSR_OPEN_CB@ DD ? ; convert SFT to SFF +; ; and set this as pointer to it. +; * IFSR_MODE DW ? ; BX - open mode +; * IFSR_FLAG DW ? ; AL +; * IFSR_CP DW ? ; Global code page +; * IFSR_CPSW DB 0 ; Code page switch flag +; IFSR_RESV3 DB 0 +; * IFSR_NAME@ DD ? ; ptr to full asciiz filename +; * IFSR_PARMS@ DD ? ; ES:DI +; * IFSR_MATCHATTR DW ? ; CX +; + IFSR_ACTION DW 0 ; Action taken code: 1=file opened +; ; 2=file created/opened +; ; 3=file replaced/opened +; +; CALL routine, CALL_IFS, with IFS pointer +; IF IFSR_RETCODE = 0 THEN +; DO +; IF DFL_FLAG = 0 THEN +; Call CD_TO_CDS +; ELSE Call DF_TO_DFL +; Call SF_TO_SFT +; CX = IFSR_ACTION +; ENDDO +; ELSE DO /* error */ +; AX = IFSR_RETCODE +; Set carry +; ENDDO +; ENDIF +; +; Outputs: +; CX=ACTION TAKEN CODE +; 1 = FILE OPENED +; 2 = FILE CREATED/OPENED +; 3 = FILE REPLACED/OPENED +; sf_ref_count is NOT altered +; THISSFT filled in or updated +; AX set on error: +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path +; error_access_denied +; Attempt to open read only file for writing, +; or open a directory +; error_sharing_violation +; The sharing mode was correct but not allowed +; generates an INT 24 on compatibility mode SFTs +; DS preserved, others destroyed +; +;************************************************************************************ + ;AN000; + procedure IFS_XOPEN,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for open/create ;AN000; + ifsr_api_def OPENFILE ;AN000; + ;AN000; + PUSH AX ; srch attr/create attr + MOV CS:IFSPROC_FLAGS,ZERO ; Clear IFS processing flags ;AN000; + JMP SHORT XO_25 ;AN008; BAF + ;AN000; +XO_20: ; (welcome all old open/create calls) ;AN000; +ASSUME DS:DOSGROUP ;AN000; + MOV [SAVE_DI],-1 ; set no parms list on old calls ;AN008; BAF +XO_25: ;AN008; BAF + invoke PREP_IFSR ; zero out ifsr ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + ;AN000; + LEA SI,COUNTRY_CDPG ; load cp and cpsw ;AN000; + MOV AX,DS:[SI.ccDosCodePage] ; | ;AN000; + MOV ES:[BX.IFSR_CP],AX ; | ;AN000; + MOV AL,[CPSWFLAG] ; | ;AN000; + MOV ES:[BX.IFSR_CPSW],AL ; | ;AN000; + + CMP WORD PTR [THISCDS],NULL_PTR ; determine CDS or DFL ;AN000; + JE XO_100 ;AN000; + ;AN000; + LDS SI,[THISCDS] ; cds--cds--cds--cds--cds--cds ;AN000; + MOV AX,SI ; set ifsDrv for possible I24 ;AN000; + invoke IFSDrvFromCDS ;AN000; + RestoreReg ; must have ax 1st on stack ;AN000; + SaveReg ; cds ptr, attr ;AN000; +XO_60: ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + JMP SHORT XO_200 ; go prep IFSRH ;AN000; + ;AN000; +XO_100: ;AN000; + SaveReg ; if deviceless attach, skip device stuff;AN014; + LES DI,CS:[THISDFL] ;AN014; + CMP WORD PTR [THISDFL],NULL_PTR ;AN014; + RestoreReg ;AN014; + JNE XO_110 ;AN014; + OR CS:IFSPROC_FLAGS,IsSeq ;AN014; + CMP CS:[fAssign],ZERO + JNE XO_200 + ADD SP,2 + MOV AX,72 + JMP XO_120 ;AN014; +XO_110: ;AN014; + invoke DFL_SINGLE_FILE_CHECK ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + JNC XO_200 ;AN000; +;;;;;;;;TEST IFSPROC_FLAGS,ISOLDOPEN+ISOLDCREATE ; new open also pushes ax ;AD014; +;;;;;;;;JZ XO_120 ; dfl error ;AD014; + ADD SP,2 ; get saved ax off stack if old ;AN000; +;XO_120: ;AD014; + MOV AX,error_invalid_function ; set error info and quit ;AN000; +XO_120: ;AN014; + invoke SET_EXTERR_INFO ;AN000; + JMP FA_980 ; ret up in FA to preserve DS ;AN000; + ;AN000; +XO_200: ; (welcome seq open/create) ;AN000; + Context DS ; get addressability to dosgroup ;AN000; + invoke SFT_TO_SFF ; SFT: sets IFSR_OPEN_CB@ ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; ds - IFSSEG ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_OPENFILE ; prep IFRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSOPENFILE ;AN000; + POP AX ; restore input AX ;AN000; + TEST IFSPROC_FLAGS,ISOLDOPEN ; check for old open/create ;AN000; + JZ XO_220 ;AN000; +;;;;;; OR AX,OLDOPEN_MODE ; why did I do this???? scrap ;AD006; + + SaveReg ; old redirector does this ;AN013; + Context DS ;AN013; + LDS SI,[THISSFT] ;AN013; + TEST DS:[SI.SF_MODE],sf_isFCB ;AN013; + RestoreReg ;AN013; + JZ XO_210 ;AN013; + MOV AL,-1 ;AN013; +XO_210: ;AN013; + + MOV ES:[BX.IFSR_MODE],AX ;AN000; + MOV ES:[BX.IFSR_FLAG],OLDOPEN_FLAG ;AN000; + XOR AH,AH ;AN000; + JMP SHORT XO_240 ;AN000; +XO_220: ;AN000; + TEST IFSPROC_FLAGS,ISOLDCREATE ;AN000; + JZ XO_260 ;AN000; + MOV ES:[BX.IFSR_MODE],OLDCREATE_MODE ; old create ;AC006;AC010; + MOV ES:[BX.IFSR_FLAG],OLDCREATE_FLAG ;AN000; + OR AH,AH ; is this create new?? ;AN000; + JZ XO_230 ;AN000; + MOV ES:[BX.IFSR_FLAG],OLDCREATENEW_FLAG ;AN000; +XO_230: ;AN000; + XCHG AH,AL ;AN000; +XO_240: ;AN000; + PUSH SS ; get ds = dosgroup so can access ;AN000; + POP DS ; wfp_start ;AN000; +ASSUME DS:DOSGROUP ;AN000; + MOV AL,[SATTRIB] ;AN000; + MOV ES:[BX.IFSR_MATCHATTR],AX ;AN000; + JMP SHORT XO_280 ; go call FS ;AN000; + ;AN000; +XO_260: ; -------extended open/create------------;AN000; + Context DS ; set ds-dosgroup ;AN000; +;;;;;;;;PUSH [SAVE_DX] ;AD012; +;;;;;;;;POP ES:[BX.IFSR_FLAG] ; input dx - flag ;AD012; + SaveReg ; check if create, if so set flag ;AN012; + MOV AX,[SAVE_DX] ;AN012; + MOV ES:[BX.IFSR_FLAG],AX + MOV AH,AL ;AN012; + AND AX,0FF0H ;AN012; + CMP AL,NOTEXIST_ACT_CREATE*16 ;AN012; + RestoreReg ;AN012; + JNE XO_270 ;AN012; + OR IFSPROC_FLAGS,IsCreate ;AN012; +XO_270: ;AN012; + + PUSH [SAVE_BX] ;AN000; + POP ES:[BX.IFSR_MODE] ; input bx - mode ;AN000; + XCHG AH,AL ; attr ;AN000; + MOV AL,[SATTRIB] ;AN000; + MOV ES:[BX.IFSR_MATCHATTR],AX ;AN000; +; MOV DI,[SAVE_DI] ; parm list ;AD011; +; CMP DI,NULL_PTR ; if offset -1, then no parm list ;AD011; +; JE XO_280 ; | ;AD011; +; MOV ES:WORD PTR[BX.IFSR_PARMS@],DI ; | ;AD011; +; PUSH [SAVE_ES] ; | ;AD011; +; POP ES:WORD PTR[BX.IFSR_PARMS@+2] ; | ;AD011; + +XO_280: ;AN000; + MOV SI,[WFP_START] ;AN000; + invoke STRIP_WFP_START ;AN000; + MOV WORD PTR ES:[BX.IFSR_NAME@],SI ;AN000; + MOV WORD PTR ES:[BX.IFSR_NAME@+2],DS ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; +;****************************************************************************** ;AN000; + invoke CALL_IFS ; call fs with open/create request ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + JNC XO_300 ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; request FAILED - ;AN000; + JNZ XO_290 ;AN000; + JMP FA_980 ; go up, set carry & return ;AN000; +XO_290: ;AN000; + RestoreReg ; if cds, restore stack first ;AN000; + JMP FA_980 ;AN000; + ;AN000; +XO_300: ; request SUCCEEDED - ;AN000; + TEST IFSPROC_FLAGS,ISOLDOPEN+ISOLDCREATE ; check for old open/create ;AN007; BAF + JNZ XO_310 ;AN007; BAF + SaveReg ;AN007; BAF + CallInstall Get_User_Stack,multDOS,24 ; Set action take back into CX ;AN007; BAF ;AN000; +ASSUME DS:DOSGROUP ;AN007; BAF + MOV AX,ES:[BX.IFSR_ACTION] ; action take only if Ext Open ;AN007; BAF + MOV DS:[SI].USER_CX,AX ;AN007; BAF + RestoreReg ;AN007; BAF +ASSUME DS:IFSSEG ;AN007; BAF +XO_310: ; request SUCCEEDED - ;AN007; BAF + MOV AX,ES:[BX.IFSR_MATCHATTR] ;AN000; + ;AN000; + invoke SFF_TO_SFT ; update sft ;AN000; + TEST IFSPROC_FLAGS,ISCDS ;AN000; + JZ XO_320 ;AN000; + RestoreReg ; cds-restore cds ptr into es:di ;AN000; + invoke CD_TO_CDS ; update cds ;AN000; + JMP XO_360 ;AN000; +XO_320: ;AN000; + TEST IFSPROC_FLAGS,ISSEQ ;AN000; + JZ XO_340 ;AN000; + MOV DI,NULL_PTR ; set seq devptr to null ;AN000; + SaveReg ; this for sf_devptr ;AN000; + RestoreReg ;AN000; + JMP SHORT XO_360 ;AN000; + ;AN000; +XO_340: ;AN000; + invoke DF_TO_DFL ; update dfl ;AN000; + LES DI,[THISDFL] ; this for sf_devptr ;AN000; + XOR AX,AX ; attr 0 for devices ;AN000; + ;AN000; +XO_360: ;AN000; + Context DS ;AN000; + LDS SI,[THISSFT] ; set some fields in sft ;AN000; + MOV DS:[SI.sf_attr],AL ;AN000; +;;;;;;;;MOV DS:[SI.sf_attr_hi],AH ;AD015; + MOV WORD PTR DS:[SI.sf_devptr],DI ;AN000; + MOV WORD PTR DS:[SI.sf_devptr+2],ES ;AN000; + TEST CS:IFSPROC_FLAGS,IsCDS + IsSeq ; let deviceless attach stuff thru here ;AC014; + JZ XO_380 ;AN000; + MOV AL,CS:[IFSDRV] ; drive ;AN000; + AND AX,devid_file_mask_drive ; Drive in correct bits ;AN000; + OR AX,sf_isnet + devid_file_clean ;AN000; + MOV DS:[SI.sf_flags],AX ;AN000; + ; now set sf_name to filename in form: ;AN000; + ; filename ext (8 char fn spaced out - ;AN000; + ; 3 char ext spaced out) ;AN000; + SaveReg ; save dssi->sf for later pop & action ;AN000; + RestoreReg ;AN000; + MOV DI,SI ; esdi->sft ;AN000; + ;AN000; + ADD DI,sf_name ; blank out sf_name ;AN000; + SaveReg ; | ;AN000; + MOV AX,2020H ; | ;AN000; + MOV CX,5 ; | ;AN000; + CLD ; | ;AN000; + REP STOSW ; | ;AN000; + STOSB ; | ;AN000; + RestoreReg ; | ;AN000; + ;AN000; + Context DS ;AN000; + MOV SI,[WFP_START] ; dssi->wfp_start ;AN000; + CallInstall DStrlen,multDOS,37 ; get length of full path name (in cx) ;AN000; + ADD SI,CX ; mov si to end of name ;AN000; + DEC SI ; si now on null ;AN000; +XO_362: ;AN000; + DEC SI ; mov back one ;AN000; + CMP BYTE PTR DS:[SI],"\" ; looking for \ just before fn ;AN000; + JNE XO_362 ;AN000; + ;AN000; + INC SI ; si now pointing to 1st char fn ;AN000; + MOV CX,8 ; esdi -> sf_name ;AN000; +XO_364: ;AN000; + LODSB ;AN000; + STOSB ;AN000; + DEC CX ;AN000; + CMP AL,"." ;AN000; + JE XO_368 ;AN000; + OR AL,AL ;AN000; + JZ XO_366 ;AN000; + JCXZ XO_369 ;AN000; + JMP SHORT XO_364 ;AN000; + ;AN000; +XO_366: ;AN000; + MOV BYTE PTR ES:[DI-1]," " ;AN000; + JMP SHORT XO_378 ;AN000; + ;AN000; +XO_368: ;AN000; + MOV BYTE PTR ES:[DI-1]," " ;AN000; + ADD DI,CX ;AN000; +XO_369: ;AN000; + MOV CX,3 ;AN000; +XO_370: ;AN000; + LODSB ;AN000; + STOSB ;AN000; + DEC CX ;AN000; + OR AL,AL ;AN000; + JZ XO_372 ;AN000; + JCXZ XO_378 ;AN000; + JMP SHORT XO_370 ;AN000; +XO_372: ;AN000; + MOV BYTE PTR ES:[DI-1]," " ;AN000; + ;AN000; +XO_378: ;AN000; + RestoreReg ; dssi -> sft, cx=action code ;AN000; + JMP SHORT XO_500 ;AN000; + ;AN000; +XO_380: ;AN000; +;;;;;;;;TEST CS:IFSPROC_FLAGS,ISSEQ ;AD014; +;;;;;;;;JNZ XO_500 ;AD014; + MOV DS:[SI.sf_flags],sf_isnet+devid_file_clean+sf_net_spool+devid_device ;AN000; + SaveReg ; sft ptr, action ;AN003; + invoke XCHGP ; dssi -> dfl, esdi -> sft ;AN000; + ADD DI,sf_name ;AN000; + ADD SI,DFL_DEV_NAME ; Skip over path sep, now pointing to name ;AN000; + MOV CX,4 ;AN000; + REP MOVSW ;AN000; + MOV AX,2020H ;AN000; + STOSW ;AN000; + STOSB ;AN000; + RestoreReg ; sft ptr, action ;AN003/AC005; + +XO_500: ;AN000; + MOV AX,WORD PTR CS:[THISIFS] ; set sf_ifs_hdr ;AN003; + MOV WORD PTR DS:[SI.SF_IFS_HDR],AX ;AN003; + MOV AX,WORD PTR CS:[THISIFS+2] ;AN003; + MOV WORD PTR DS:[SI.SF_IFS_HDR+2],AX ;AN003; + + MOV AX,CS:[SFT_SERIAL_NUMBER] ; give new sft serial number for ;AN004; + MOV DS:[SI.SF_FIRCLUS],AX ; fcb processing ;AN004; + INC CS:[SFT_SERIAL_NUMBER] ;AN004; + + MOV WORD PTR DS:[SI.SF_POSITION],0 ;AN012; + MOV WORD PTR DS:[SI.SF_POSITION+2],0 ;AN012; + + TEST CS:IFSPROC_FLAGS,IsCreate ; if create, set sf time/date ;AN012; + JZ XO_520 ;AN012; + push ds ;AN017: SAVE DS **RPS + CallInstall DATE16,MultDOS,13 ;AN012; + pop ds ;AN017: SAVE DS **RPS + MOV DS:[SI.SF_TIME],DX ;AN012; + MOV DS:[SI.SF_DATE],AX ;AN012; + MOV WORD PTR DS:[SI.SF_SIZE],0 ;AN012; + MOV WORD PTR DS:[SI.SF_SIZE+2],0 ;AN012; +XO_520: ;AN012; + + PUSH SS ; Preserve input DS ;AN000; + POP DS ;AN000; + MOV AX,(multDOS SHL 8) OR 12 ;AN000; + INT 2FH ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc IFS_XOPEN ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_SEARCH ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL ;AN000; +; terminated) ;AN000; +; [SATTRIB] Is attribute of search, determines what files can be found ;AN000; +; [DMAADD] Points to 53 byte buffer ;AN000; +; Function: ;AN000; +; BECAUSE OF THE STRUCTURE OF SEARCH IT MUST BE RELATIVE TO A CDS SESSION ;AN000; +; Outputs: ;AN000; +; CARRY SET ;AN000; +; AX = error_path_not_found ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_SEARCH_FIRST,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + MOV AX,error_path_not_found ;AN000; + STC ;AN000; + return ;AN000; + ;AN000; +EndProc IFS_SEQ_SEARCH_FIRST ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEQ_SEARCH_NEXT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [DMAADD] Points to 53 byte buffer returned by DOS_SEARCH_FIRST ;AN000; +; (only first 21 bytes must have valid information) ;AN000; +; Function: ;AN000; +; BECAUSE OF THE STRUCTURE OF SEARCH IT MUST BE RELATIVE TO A CDS SESSION ;AN000; +; Outputs: ;AN000; +; CARRY SET ;AN000; +; AX = error_no_more_files ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEQ_SEARCH_NEXT,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + JMP IFS_SEQ_SEARCH_FIRST ;AN000; + ;AN000; +EndProc IFS_SEQ_SEARCH_NEXT ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ +; +; IFS_SEARCH_FIRST +; +; Inputs: +; [WFP_START] Points to WFP string ("//" must be first 2 chars, NUL +; terminated) +; [THISCDS] Points to CDS being used may not be NUL +; [SATTRIB] Is attribute of search, determines what files can be found +; [DMAADD] Points to 53 byte buffer +; DS - dosgroup +; +; Function: +; Prep IFSRH: +; * IFSR_LENGTH DW 50 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; + IFSR_RETCODE DW ? +; + IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 8 ; Search file +; + IFSR_ERROR_CLASS DB ? +; + IFSR_ERROR_ACTION DB ? +; + IFSR_ERROR_LOCUS DB ? +; + IFSR_ALLOWED DB ? +; + IFSR_I24_RETRY DB ? +; + IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; *+ IFSR_DEVICE_CB@ DD ? ; CD +; IFSR_OPEN_CB@ DD ? ; null +; * IFSR_SUBFUNC DB subfunction ; 1=first, 2=next +; ; 4=last (CP/DOS only) +; * IFSR_RESV3 DB ? ; DOS Reserved +; *+ IFSR_CONTINFO@ DD continuation info address (always set): +; * DB 8 DUP(?) ; SEARCH FILE NAME +; * DB 3 DUP(?) ; SEARCH FILE EXTENSION +; * DB ? ; SEARCH ATTRIBUTE +; DB 8 DUP(?) ; FSDA +; DIRECTORY ENTRY +; + DB 8 DUP(?) ; FOUND FILE NAME +; + DB 3 DUP(?) ; FOUND FILE EXTENSION +; + DB ? ; FOUND ATTRIBUTE LOW ??? DB/DD +; + DW ? ; FILE CODE PAGE (OR 0) +; + DW ? ; RESERVED +; + DB ? ; FOUND ATTRIBUTE HIGH +; + DB 5 DUP(?) ; RESERVED +; + DW ? ; FILE TIME +; + DW ? ; FILE DATE +; + DW ? ; MEANING FILE SYSTEM SPECIFIC +; ; (STARTING CLUSTER IN FAT) +; + DD ? ; FILE SIZE +; following on search first only +; * IFSR_MATCHATTR DW ; search attribute ; format 0000000re0advshr +; * IFSR_NAME@ DD ; asciiz name to process +; +; IF search first THEN +; DO +; IFSR_SUBFUNC = 1 +; Get CDS from [THISCDS] +; Call CDS_TO_CD +; ENDDO +; ELSE DO +; IFSR_SUBFUNC = 2 +; Get CDS from drive byte in DMAADD +; Call CDS_TO_CD +; ENDDO +; ENDIF +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR +; IF IFSR_RETCODE = 0 THEN +; DO +; Call CD_TO_CDS +; DMAADD = IFSR_CONTINFO +; Clear carry +; ENDDO +; ELSE DO {error} +; AX = error code +; Set carry +; ENDDO +; ENDIF +; +; Outputs: +; CARRY CLEAR +; The 53 bytes ot DMAADD are filled in as follows: +; +; Drive Byte (A=1, B=2, ...) High bit = 1 --| +; 11 byte search name with Meta chars in it | From +; Search Attribute Byte, attribute of search | Server +; WORD LastEnt value | +; WORD DirStart ------------------------------| +; DWORD Local CDS +; 32 bytes of the directory entry found +; CARRY SET +; AX = error code +; error_no_more_files +; No match for this file +; error_access_denied +; Device name given +; error_path_not_found +; Bad path +; DS preserved, others destroyed +; +;************************************************************************************ + ;AN000; + procedure IFS_SEARCH_FIRST,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for search ;AN000; + ifsr_api_def SEARCHFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ;AN000; + invoke PREP_IFSR ; zero ifsr ;AN000; + ;AN000; +ASSUME DS:DOSGROUP ;AN000; + LES DI,[DMAADD] ; esdi -> dmaadd ;AN001; + LDS SI,[THISCDS] ; dssi -> cds ;AN000; + + invoke DRIVE_FROM_CDS ; set ifsdrv (0-based) ;AN001; + MOV AL,CS:[IFSDRV] ; put 1-based drive # in dmaadd ;AN001; + INC AL ;AN001; + OR AL,80H ; turn on ifs indicator ;AN001; + STOSB ;AN001; + + SaveReg ; preserve ds:si -> cds ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + PUSH DS ; save ds-ifsseg ;AN000; + Context DS ; ds-dosgroup ;AN000; + ;AN000; + MOV SI,[WFP_START] ;AN000; + invoke STRIP_WFP_START ; remove leading d:\ if present ;AN000; + MOV ES:WORD PTR[BX.IFSR_NAME@],SI ;AN000; + MOV ES:WORD PTR[BX.IFSR_NAME@+2],DS ;AN000; + MOV AL,[SATTRIB] ;AN000; + XOR AH,AH ;AN000; + MOV ES:[BX.IFSR_MATCHATTR],AX ;AN000; + ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG,ES:IFSSEG ;AN000; + ;AN000; + MOV AL,IFSSEARCH_FIRST ;AN000; + JMP SHORT SN_60 ; rest of processing is in ;AN000; + ; search_next routine ;AN000; + ;AN000; +EndProc IFS_SEARCH_FIRST ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_SEARCH_NEXT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [DMAADD] Points to 53 byte buffer returned by DOS_SEARCH_FIRST ;AN000; +; (only first 21 bytes must have valid information) ;AN000; +; Function: ;AN000; +; Look for subsequent matches ;AN000; +; Outputs: ;AN000; +; CARRY CLEAR ;AN000; +; The 53 bytes at DMAADD are updated for next call ;AN000; +; (see NET_SEARCH_FIRST) ;AN000; +; CARRY SET ;AN000; +; AX = error code ;AN000; +; error_no_more_files ;AN000; +; No more files to find ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFS_SEARCH_NEXT,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for search ;AN000; + ifsr_api_def SEARCHFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; clear processing flags ;AN000; + invoke PREP_IFSR ; zero out ifsr ;AN000; + ;AN000; +SN_20: ;AN000; + LDS SI,[DMAADD] ;AN000; + LODSB ;AN000; + AND AL,NOT 80H ; turn off ifs indicator ;AN000; + DEC AL ; make 0-based ;AN000; + MOV CS:[IFSDRV],AL ; set this for possible i24 ;AN000; + CallInstall GetCDSFromDrv,multDOS,23,AX,AX ;AN000; +ASSUME DS:NOTHING ;AN000; + JNC SN_40 ;AN000; + MOV AX,error_invalid_drive ; no cds, set error & ;AN000; + invoke SET_EXTERR_INFO ;AN000; + JMP FA_1000 ; ret up in FA to preserve DS ;AN000; +SN_40: ; (welcome lock) ;AN000; + SaveReg ; save cds ptr ;AN000; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + MOV AL,IFSSEARCH_NEXT ; start with subfunc=search next ;AN000; +; TEST IFSPROC_FLAGS,ISADD ;AD011; +; JZ SN_60 ;AD011; +; INC AL ; inc subfunc to search same ;AD011; +SN_60: ;AN000; + MOV ES:[BX.IFSR_SUBFUNC],AL ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_SEARCHFILE ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSSEARCHFILE ;AN000; + ;AN000; + PUSH DS ;AN000; + Context DS ;AN000; + MOV AX,WORD PTR [DMAADD] ;AN000; + INC AX ;AN000; + MOV ES:WORD PTR[BX.IFSR_CONTINFO@],AX ;AN000; + MOV AX,WORD PTR [DMAADD+2] ;AN000; + MOV ES:WORD PTR[BX.IFSR_CONTINFO@+2],AX ;AN000; + ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + invoke CALL_IFS ; call FS ;AN000; + RestoreReg ; restore cds ptr into es:di ;AN000; + JC SN_1000 ;AN000; + invoke CD_TO_CDS ;AN000; + CLC ;AN000; + ;AN000; +SN_1000: ;AN000; + JMP FA_1000 ; go up & preserve ds, ret ;AN000; + ;AN000; +EndProc IFS_SEARCH_NEXT ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CHECK_OPEN_DEVICE ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [WFP_START] ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Outputs: ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure OPEN_CHECK_DEVICE,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + MOV SI,[WFP_START] ; dssi -> path to open ;AN000; +; invoke PARSE_DEVICE_PATH ; dssi -> device name (asciiz) ;AN000; + ;AN000; + PUSH SS ; Now check if this device is real ;AN000; + POP ES ;AN000; + MOV DI,OFFSET DOSGROUP:NAME1 ;AN000; + MOV CX,4 ;AN000; + REP MOVSW ; Transfer name to NAME1 ;AN000; + MOV AX,2020H ;AN000; + STOSW ;AN000; + STOSB ;AN000; + ;AN000; + PUSH ES ;AN000; + POP DS ;AN000; +ASSUME DS:DOSGROUP ;AN000; + MOV [ATTRIB],attr_hidden + attr_system + attr_directory ;AN000; + ; Must set this to something interesting ;AN000; + ; to call DEVNAME. ;AN000; + CallInstall DEVNAME,multDOS,35 ;AN000; + JNC OCD_120 ;AN000; + MOV AX,error_file_not_found ;AN000; + transfer ifs_980 ;AN000; + ;AN000; +OCD_120: ;AN000; + transfer ifs_990 ;AN000; + ;AN000; +EndProc OPEN_CHECK_DEVICE ;AN000; + ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSFLINK.ASM b/v4.0/src/CMD/IFSFUNC/IFSFLINK.ASM new file mode 100644 index 0000000..7649951 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFLINK.ASM @@ -0,0 +1,202 @@ + PAGE ,132 ;  +; SCCSID = @(#)ifsflink.asm 1.0 87/05/11 +TITLE IFSFUNC LINK FIX ROUTINES - Routines to resolve ifsfunc externals +NAME IFSFLINK + +.xlist +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +CODE SEGMENT BYTE PUBLIC 'CODE' +code ENDS + +include dosseg.asm + +code SEGMENT BYTE PUBLIC 'code' + ASSUME CS:dosgroup + + procedure OUTT,FAR + entry $DUP + entry MSG_RETRIEVAL + entry $ECS_CALL + entry $EXTENDED_OPEN + entry FASTINIT + entry $IFS_IOCTL + entry IFS_DOSCALL + entry $QUERY_DOS_VALUE + entry $STD_AUX_INPUT,FAR + entry LCRITDEVICE,FAR + entry $ABORT,FAR + entry $SET_TIME,FAR + entry $ALLOC,FAR + entry SETMEM,FAR + entry SKIPONE,FAR + entry $SET_DMA,FAR + entry $PARSE_FILE_DESCRIPTOR,FAR + entry $CREATETEMPFILE,FAR + entry $SLEAZEFUNCDL,FAR + entry $CHDIR,FAR + entry TWOESC,FAR + entry $GET_INTERRUPT_VECTOR,FAR + entry $FCB_SEQ_WRITE,FAR + entry DEVNAME,FAR + entry $GET_DEFAULT_DRIVE,FAR + entry $STD_CON_STRING_INPUT,FAR + entry $CLOSE,FAR + entry $RAW_CON_IO,FAR + entry $INTERNATIONAL,FAR + entry IDLE,FAR + entry $STD_CON_INPUT_NO_ECHO,FAR + entry $ASSIGNOPER,FAR + entry $LOCKOPER,FAR + entry $FCB_CLOSE,FAR + entry $STD_CON_STRING_OUTPUT,FAR + entry $DUP_PDB,FAR + entry GETCH,FAR + entry STRLEN,FAR + entry INITCDS,FAR + entry COPYONE,FAR + entry PJFNFROMHANDLE,FAR + entry $GET_VERIFY_ON_WRITE,FAR + entry $KEEP_PROCESS,FAR + entry STRCMP,FAR + entry $SET_INTERRUPT_VECTOR,FAR + entry $FCB_DELETE,FAR + entry $RAW_CON_INPUT,FAR + entry $RENAME,FAR + entry $FIND_FIRST,FAR + entry $FCB_RANDOM_WRITE,FAR + entry $SET_DEFAULT_DRIVE,FAR + entry $SETDPB,FAR + entry $STD_PRINTER_OUTPUT,FAR + entry $MKDIR,FAR + entry $DUP2,FAR + entry SET_SFT_MODE,FAR + entry $GET_DATE,FAR + entry $FCB_RENAME,FAR + entry $CREATE_PROCESS_DATA_BLOCK,FAR + entry $CREAT,FAR + entry ECRITDISK,FAR + entry PLACEBUF,FAR + entry $IOCTL,FAR + entry $READ,FAR + entry PATHCHRCMP,FAR + entry $GET_VERSION,FAR + entry COPYLIN,FAR + entry LCRITDISK,FAR + entry $LSEEK,FAR + entry STRCPY,FAR + entry $FILE_TIMES,FAR + entry BACKSP,FAR + entry $SET_VERIFY_ON_WRITE,FAR + entry SETYEAR,FAR + entry FASTRET,FAR + entry $RMDIR,FAR + entry DIVOV,FAR + entry $GET_FCB_POSITION,FAR + entry $DISK_RESET,FAR + entry $DIR_SEARCH_FIRST,FAR + entry $WAIT,FAR + entry FASTOPENCOM,FAR + entry STAY_RESIDENT,FAR + entry $ALLOCOPER,FAR + entry $GET_DEFAULT_DPB,FAR + entry DSTRLEN,FAR + entry CTRLZ,FAR + entry $USEROPER,FAR + entry $SET_DATE,FAR + entry $FCB_RANDOM_WRITE_BLOCK,FAR + entry EXITINS,FAR + entry $GET_IN_VARS,FAR + entry GETDEVLIST,FAR + entry DATE16,FAR + entry POINTCOMP,FAR + entry SFFROMSFN,FAR + entry SKIPSTR,FAR + entry FREE_SFT,FAR + entry SHARE_ERROR,FAR + entry NLS_IOCTL,FAR + entry $CURRENT_DIR,FAR + entry $FCB_CREATE,FAR + entry $WRITE,FAR + entry $GET_INDOS_FLAG,FAR + entry RECSET,FAR + entry $CREATENEWFILE,FAR + entry $STD_CON_INPUT_STATUS,FAR + entry REEDIT,FAR + entry GETTHISDRV,FAR + entry DSUM,FAR + entry $GETEXTENDEDERROR,FAR + entry $EXTHANDLE,FAR + entry $NAMETRANS,FAR + entry NLS_LSEEK,FAR + entry SCANPLACE,FAR + entry GETCDSFROMDRV,FAR + entry DSLIDE,FAR + entry UCASE,FAR + entry $STD_CON_OUTPUT,FAR + entry $FCB_RANDOM_READ_BLOCK,FAR + entry CHECKFLUSH,FAR + entry COPYSTR,FAR + entry $GETSETCDPG,FAR + entry $DIR_SEARCH_NEXT,FAR + entry $OPEN,FAR + entry SKIPVISIT,FAR + entry $EXEC,FAR + entry $DEALLOC,FAR + entry DOS_CLOSE,FAR + entry $STD_CON_INPUT,FAR + entry NLS_GETEXT,FAR + entry BUFWRITE,FAR + entry $GET_TIME,FAR + entry $SLEAZEFUNC,FAR + entry $CHAR_OPER,FAR + entry NET_I24_ENTRY,FAR + entry $COMMIT,FAR + entry $SETBLOCK,FAR + entry $FCB_OPEN,FAR + entry NLS_OPEN,FAR + entry $GET_DMA,FAR + entry $UNLINK,FAR + entry $FCB_SEQ_READ,FAR + entry $STD_CON_INPUT_FLUSH,FAR + entry $GET_DRIVE_FREESPACE,FAR + entry DRIVEFROMTEXT,FAR + entry $GETEXTCNTRY,FAR + entry SETVISIT,FAR + entry $EXIT,FAR + entry $STD_AUX_OUTPUT,FAR + entry KILNEW,FAR + entry $CHMOD,FAR + entry $FCB_RANDOM_READ,FAR + entry SHARE_VIOLATION,FAR + entry ECRITDEVICE,FAR + entry $GET_DPB,FAR + entry $FIND_NEXT,FAR + entry $GET_FCB_FILE_LENGTH,FAR + entry ENTERINS,FAR + entry DEVIOCALL2,FAR + entry $SERVERCALL,FAR + entry $GSETMEDIAID,FAR + entry FETCHI_CHECK,FAR + entry TABLEDISPATCH,FAR + entry DSKSTATCHK,FAR + entry SET_RQ_SC_PARMS,FAR + entry SAVE_MAP,FAR + entry RESTORE_MAP,FAR + entry DSKREAD,FAR + entry FAST_DISPATCH,FAR + entry DSKWRITE,FAR + entry INTCNE0,FAR + entry SHARE_INSTALL,FAR ;P3568 + entry FAKE_VERSION,FAR ;D503 + NOP +EndProc OUTT + + code ENDS + END + + diff --git a/v4.0/src/CMD/IFSFUNC/IFSFSYM.INC b/v4.0/src/CMD/IFSFUNC/IFSFSYM.INC new file mode 100644 index 0000000..70a0a65 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFSYM.INC @@ -0,0 +1,162 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsfsym.inc 1.0 87/05/11 ;AN000; + +;************************************************************************************ +; +; IFSFUNC Symbols +; +; Modification history: +; Created: MAY 11 1987 +; +; LOD = 80 (IFS added) +; REVISION HISTORY: +; A000 Original version 4.00 May 1987 +; A001 DCR 188 - design correction of Get IFSFUNC Item 8/87 RGAZZIA +; A002 PTM ??? - 80H bit on Lock functions ignorred 10/27 FEIGENBAUM +; A003 PTM 2270- filesys/network attach problem 11/27 RGAZZIA +; A004 DCR 285 - remove Extended Attribute/Lock support 1/88 RGAZZIA +; A005 PTM 2827- error msg problems 1/88 RMG +; A006 PTM 3334- new ifsresetenv call 2/88 RMG +; A007 PTM 3657- don't want val code page in flag 2/88 RGazzia +; A008 PTM 3692- net use xxx /d error msg wrong 3/88 RGazzia +; A009 PTM 3673- filesys problems again, undo a003 3/14/88 RMG +; A010 PTM 3968- time/date stamping problems 3/25/88 RMG +; A011 PTM 4140- INT 2F 5 interface change 4/12/88 RMG +; A012 PTM 5006- need save original device ptr - new dfl field 6/02/88 RMG +; +;************************************************************************************ +; ;AN000; +; Old Redirector Stuff ;AN000; +; ;AN000; +TRUE EQU 0FFFFh ;AN000; +FALSE EQU 0 ;AN000; + ;AN000; +PATHGEN = TRUE ;AN000; +DEBUG = FALSE ;AN000; +REDIRECTOR = TRUE ;AN000; +Installed = TRUE ;AN000; + ;AN000; +MSNET_TIMING = FALSE ;AN000; + ;AN000; + ;AN000; +IF1 ;AN000; + IF MSNET_TIMING ;AN000; + %out MSNET_TIMING version ;AN000; + ENDIF ;AN000; + IF DEBUG ;AN000; + %out DEBUGGING version ;AN000; + ENDIF ;AN000; + %out INSTALLED version ;AN000; +ENDIF ;AN000; +; Structures and equates for the network support ;AN000; + ;AN000; +;Net call interrupt - used to generate critical sections ;AN000; +NET_CALL_INT EQU 2AH ;AN000; + ;AN000; +;Max size of PRINT_PRE_STRING ;AN000; +MAX_PRE_STRING EQU 64 ;AN000; + ;AN000; + ;AN000; +;AH function code for $GET_IN_VARS INT 21 function ;AN000; +GET_IN_VAR EQU 52H ;AN000; + ;AN000; + ;AN000; +; The following EQUates control the replacement of the FCB SFT cache by ;AN000; +; IFSFUNC. If the current FCB Cache Size,Keepcount is DefNumFCB,DefKeepVal ;AN000; +; then IFSFUNC will set up a new cache of NewNumFCB,NewKeepVal. ;AN000; +DefNumFCB EQU 4 ;AN000; +DefKeepVal EQU 0 ;AN000; + ;AN000; +NewNumFCB EQU 16 ;AN000; +NewKeepVal EQU 8 ;AN000; + ;AN000; +SUBTTL IFSFUNC Data ;AN000; +PAGE ;AN000; +; miscellaneous IFS equates ;AN000; +MINUS_ONE EQU -1 ;AN000; +NULL_PTR EQU -1 ;AN000; +ERROR_INFO_NOT_SET EQU -1 ;AN000; +CHECK_REMOVABLE EQU 4408H ;AN000; +ICOLON EQU ":" ;AN000; +ZERO EQU 0 ;AN000; +OLDOPEN_MODE EQU 2180H ;AN000; +OLDOPEN_FLAG EQU 0101H ;AN000; +OLDCREATE_MODE EQU 0002H ;AC007; +OLDCREATE_FLAG EQU 0112H ;AC007; +OLDCREATENEW_FLAG EQU 10H ;AN000; +;INT21AL_LOCK_READ EQU 4 ;AD004; +;INT21AL_WRITE_UNLOCK EQU 5 ;AD004; +IFSFINSTALLED EQU 0FFH ;AN000; +GET_TRUNCATE_FLAG EQU 7 ;AN000; +SET_TRUNCATE_FLAG EQU 8 ;AN000; +;;;alias COMPLEX EQU 4 ;AN000; +PARSE_ERR_1 EQU 1 ;AN000; +PARSE_ERR_5 EQU 5 ;AN000; +PARSE_ERR_6 EQU 6 ;AN000; +PARSE_ERR_10 EQU 10 ;AN000; +COMMON_ERR_2 EQU 2 ;AN000; +COMMON_ERR_3 EQU 3 ;AN000; +UTIL_ERR_4 EQU 4 ;AN000; +RETRY EQU 1 ;AN000; +I2F5_MsgRet EQU 2 ;AN011; + ;AN000; +; ifsproc flags ;AN000; +IsCDS EQU 80H ;AN000; +IsSFT EQU 40H ;AN000; +IsSEQ EQU 20H ;AN000; +IsGet EQU 10H ; vs. set ;AN000; +IsOldOpen EQU 10H ;AN000; +IsOldCreate EQU 08H ;AN000; +IsCreate EQU 8000H ; used in IFS_OPEN in setting sf date/time ;AN010; +IsClose EQU 10H ; vs. commit ;AN000; +IsRen EQU 10H ; vs. delete ;AN000; +;IsLockRead EQU 10H ;AD005; +;IsWriteUnlock EQU 08H ;AD005; +;IsAdd EQU 04H ;AD005; +THISIFS_SET EQU 02H ;AN000; +IsShare EQU 80H ; used by auto-attach ;AN000; +IsCTLFCN EQU 01H ; used by IFS_UPDATE_CB@ ;AN000; +IsCritIFS EQU 02H ; indicates ifs cs ;AN000; +Print_On EQU 80H ; sess ;AN000; +SetDeviceCB EQU 0100H ; indicates to sft_to_sff to set ifs_device_cb@ ;AN000; +IsDummyCDS EQU 0200H ; used to indicate dummy cds (AttStrt/CDS-CD) ;AN000; +IsNetwork EQU 0400H ; indicates types 3 or 4 attach ;AN001; +SetBP EQU 0800H ; set if return lsn ;AN001; +Filesys_Status EQU 1000H ; indicates new style get ifsfunc item ;AN001; +;Filesys_Network_Attach EQU 1000H ; flag used to determine if move ptr direct to parms ;AN003;;AD009; +;IsWOLock EQU 2000H ; write operation only lock - flag moved RMG ;AD004; +IsInit EQU 2000H ; this set in AutoAttach for CI-error area ;AN005; +IsResetEnvirn EQU 4000H ; used in sess - diff abort from reset environment ;AN006; +IsMsgRet EQU 8000H ; used in ifserror - int2f5 to distinguish msg ret ;AN011; + ; from command.com ;AN011; +; ifsfunc flags ;AN000; +UNC_INSTALLED EQU 80H ; unc file system installed ;AN000; +NO_IFS_DRIVERS EQU 40H ; no ifs drivers installed ;AN000; + +; ifs semaphores IFSSEM equates ;AN011; +MR_ERRMSG_SEM EQU 80H ; used by ifserror INT2F AH=5 as gate for msgret entry ;AN011; +; ;AN000; +; DFL - This structure stores IFS/NETUSE/ALIAS Device information ;AN000; +; to IFS driver. ;AN000; + +DFLL_LIST STRUC ;AN000; +DFLL_FLAGS DB ? ; Flags ;AN000; +DFLL_TYPE DB ? ; 1=IFS, 3=NETUSE, 0=ALIAS ;AN000; +DFLL_DEV_NAME DB 8 DUP (?) ; Device name ;AN000; +DFLL_USER_WORD DW ? ; attach user word ;AN001; +DFLL_ALIAS_INDEX DW ? ; Byte index into alias names list (resv) ;AN000; +DFLL_IFS_HDR DD ? ; Pointer to IFSHDR ;AN000; +DFLL_FSDA DB 8 DUP (?) ; File System Dependent Data Area ;AN000; +DFLL_DEVPTR DD ? ; sft_devptr ;AN012; +DFLL_LIST ENDS ;AN000; + ;AN000; +; dfl flags ;AN000; +DFL_INPROG EQU 80H ; in progress ;AN000; +DFL_INUSE EQU 40H ; in use ;AN000; +DFL_PAUSED EQU 20H ; device is paused ;AN000; +DFL_DEV_REAL EQU 10H ; device is real ;AN000; + ;AN000; +; error codes ;AN000; +device_not_attached equ 0FH ; ;AC008; +fs_driver_not_found equ 67 ; ;AN000; +error_out_of_structs equ 56 ; ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSFUNC.LNK b/v4.0/src/CMD/IFSFUNC/IFSFUNC.LNK new file mode 100644 index 0000000..f7b9623 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFUNC.LNK @@ -0,0 +1,12 @@ +IFSSESS.OBJ IFSDIR.OBJ IFSFILE.OBJ IFSHAND.OBJ + +IFSDEV.OBJ IFSUTIL.OBJ IFSERROR.OBJ IFSFDOS.OBJ IFSINIT.OBJ + +..\..\inc\NIBDOS.OBJ+ +..\..\inc\CONST2.OBJ+ +..\..\inc\msDATA.OBJ+ +..\..\inc\msTABLE.OBJ+ +..\..\dos\msDISP.OBJ + +..\..\dos\msCODE.OBJ + +..\..\inc\msDOSME.OBJ+ +IFSFLINK.OBJ +IFSFUNC.EXE,IFSFUNC.MAP /EX; + \ No newline at end of file diff --git a/v4.0/src/CMD/IFSFUNC/IFSFUNC.SKL b/v4.0/src/CMD/IFSFUNC/IFSFUNC.SKL new file mode 100644 index 0000000..4188c7f --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSFUNC.SKL @@ -0,0 +1,49 @@ +:util IFSFUNC ;AN000; +:class 1 ;Extended Error messages ;AN007; +:use EXTEND50 ; file system extended error msg #s ;AN007; +:use EXTEND51 ;AN007; +:use EXTEND52 ;AN007; +:use EXTEND53 ;AN007; +:use EXTEND54 ;AN007; +:use EXTEND55 ;AN007; +:use EXTEND56 ;AN007; +:use EXTEND57 ;AN007; +:use EXTEND58 ;AN007; +:use EXTEND59 ;AN007; +:use EXTEND60 ;AN007; +:use EXTEND61 ;AN007; +:use EXTEND62 ;AN007; +:use EXTEND63 ;AN007; +:use EXTEND64 ;AN007; +:use EXTEND65 ;AN007; +:use EXTEND66 ;AN007; +:use EXTEND67 ;AN007; +:use EXTEND68 ;AN007; +:use EXTEND69 ;AN007; +:use EXTEND70 ;AN007; +:use EXTEND71 ;AN007; +:use EXTEND72 ;AN007; +:use EXTEND73 ;AN007; +:use EXTEND74 ;AN007; +:use EXTEND80 ;AN007; +:use EXTEND82 ;AN007; +:use EXTEND83 ;AN007; +:use EXTEND84 ;AN007; +:use EXTEND85 ;AN007; +:use EXTEND86 ;AN007; +:use EXTEND87 ;AN007; +:use EXTEND88 ;AN007; +:use EXTEND89 ;AN007; +:class 2 ;parse errors: ;AN000; +:use PARSE1 ;Too many parameters ;AN000; +:use PARSE4 ;Invalid keyword ;AN000; +:use PARSE6 ;Parameter value not in allowed range ;AN002; +:use PARSE7 ;Parameter value not allowed ;AN002; +:use PARSE9 ;Parameter format not correct ;AN002; +:use PARSE10 ;Invalid parameter ;AN000; +:class A ;AN000; +:use 1 COMMON1 ;Incorrect DOS version ;AN000; +:use 2 COMMON2 ;%1 already installed ;AN000; +:use 3 COMMON10 ;%1 not installed ;AN000; +:def 4 "Invalid configuration",CR,LF ;AN00?; +:end ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSHAND.ASM b/v4.0/src/CMD/IFSFUNC/IFSHAND.ASM new file mode 100644 index 0000000..19a997f --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSHAND.ASM @@ -0,0 +1,903 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifshand.asm 1.0 87/05/11 ;AN000; +TITLE IFSFUNC HANDLE ROUTINES - Routines for FS dispatch ;AN000; +NAME IFSHANDLE ;AN000; +;****************************************************************************** +; +; HANDLE (SFT) related FS calls +; +; +; IFS_CLOSE +; IFS_COMMIT +; IFS_LSEEK +; IFS_READ +; IFS_WRITE +; IFS_LOCK +; IFS_XATTR +; +; REVISION HISTORY: +; A000 Original version 4.00 May 1987 +; A001 P635 - Correct Read problem - restore es:di -> sft +; RG Sept 1,1987 +; A002 P659 - Copy cmd problems (xattr) +; RG Sept 1,1987 +; A003 P868 - Lock problems R.G +; A004 P849 - Printer problems R.G +; A005 P1601- lock/xattr problems R.G +; A006 P????- Write Only Lock support in Lock Read/Write 10/27 FEIGENBAUM +; A007 P2339- Not getting count back to user in xattr call 11/09 RG +; A008 P2433- redir copy problem (Xattr) 11/17 RG +; A009 P2566- xattrs not propagated across network 12/3 RG +; (due to size check on set that does not offer size) +; A010 D285 - Remove Extended Attributes/Lock 1/88 RG +; A011 P2994- double close problem 1/88 RG +; A012 P3149- basica file redirection - seek problem 1/88 RMG +; A013 P3185- get ea cx check 1/88 RMG +; A014 P3249- lock problem 1/88 RMG +; A015 P3432- copy to remote ptr problem - write 2/88 RMG +; A016 P3513- return cx on xattr wrong 2/88 RMG +; A017 P3968- set sf time/date on close 3/25/88 RMG +; A018 P4839- fcb open/ren/term problem on abort close 5/13/88 RMG +; A019 P4791- don't overwrite ax on error 5/19/88 RMG +; A020 P5003- LSEEK hang using Austin Test tool 6/01/88 RPS +; +; LOC - 251 +; Programming note: In the prologues to the routines, the input/output are +; accurate. The pseudocode, however, is outdated and does +; not reflect the code. +; +;****************************************************************************** + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; + ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; include THE REST of the segment definitions for normal MSDOS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ;DOSGROUP Data ;AN000; + Extrn THISSFT:DWORD ;AN000; + Extrn DMAADD:DWORD ;AN000; + Extrn CurrentPDB:WORD ;AN000; + Extrn SAVE_BX:WORD + Extrn SAVE_CX:WORD + Extrn SAVE_DS:WORD + Extrn SAVE_SI:WORD + Extrn SAVE_ES:WORD + Extrn SAVE_DI:WORD +DATA ENDS ;AN000; + ;AN000; + ;AN000; +; define our own code segment ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data ;AN000; + Extrn THISDFL:DWORD ;AN000; + Extrn THISIFS:DWORD ;AN000; + Extrn IFSPROC_FLAGS:WORD ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_CLOSE - see IFS_COMMIT for details ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_CLOSE,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for close ;AN000; + ifsr_api_def CLOSEFILE ;AN000; + ;AN000; + TEST ES:[DI.SF_FLAGS],devid_file_clean + sf_close_nodate ;AN017; + JNZ C_05 ;AN017; + CallInstall DATE16,MultDOS,13 ; set sf date/time on close ;AN017; + MOV ES:[DI.SF_DATE],AX ;AN017; + MOV ES:[DI.SF_TIME],DX ;AN017; +C_05: ;AN017; + + SaveReg ; save SFT ptr ;AN000; + CallInstall FREE_SFT,MultDOS,8 ; set SFT busy ;AN000; + PUSH AX ; save old ref count ;AN000; + ;AN000; + TEST ES:[DI.SF_MODE],SF_ISFCB ; always close fcb ;AN011; + JNZ C_10 ; only do real close when ;AN011; + CMP AX,1 ; sft being freed ;AN011; + JE C_10 ;AN011; + JMP C_80 ;AN011; +C_10: ;AN011; + MOV CS:IFSPROC_FLAGS,ISCLOSE + SETDEVICECB ;AN000; + ; 2nd flag causes sft_to_sff to ;AN000; + ; set device cb@ ;AN000; + JMP C_20 ; cont. in ifs_commit ;AN000; + ;AN000; +EndProc IFS_CLOSE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_COMMIT ;AN000; +; ;AN000; +; Called by: IFSFUNC dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS DRIVE_FROM_SFT ;AN000; +; SFT_TO_SFF ;AN000; +; SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISSFT] set to the SFT for the file being used ;AN000; +; ES:DI = [THISSFT] (date time are NOT correct) ;AN000; +; SFT must never be for an FCB on commit (error not detected) ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 40 ; Total length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 14 ; Close/commit file ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ;AN000; +; *+ IFSR_OPEN_CB@ DD ? ; SF ;AN000; +; * IFSR_FUNC DB ? ; 0=CLOSE, 1=COMMIT ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; ;AN000; +; IF close THEN ;AN000; +; IFSR_FUNC = 0 ;AN000; +; ELSE IFSR_FUNC = 1 ;AN000; +; CALL routine, CALL_IFS, with pointer to SF_IFS_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call SFF_TO_SFT ;AN000; +; Decrement SF_REF_COUNT if close ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO {error} ;AN000; +; AX = IFSR_RETCODE ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; sf_ref_count decremented on close unless FAIL ;AN000; +; (AX has old value for COMMIT) ;AN000; +; ES:DI point to SFT ;AN000; +; Carry set if error (file deleted or disk changed) ;AN000; +; ;AN000; +; DS preserved, others destroyed ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_COMMIT,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def CLOSEFILE ;AN000; + ;AN000; + MOV CS:IFSPROC_FLAGS,SETDEVICECB ; set ifsproc_flags ;AN000; +C_20: ; (welcome ifs_close) ;AN000; + invoke DRIVE_FROM_SFT ; set IFSDRV for possible criter ;AN000; + invoke PREP_IFSR ; clear ifsrh ;AN000; + MOV DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_CLOSEFILE ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSCLOSEFILE ;AN000; + XOR AL,AL ;AN000; + TEST IFSPROC_FLAGS,ISCLOSE ;AN000; + JNZ C_40 ;AN000; + INC AL ;AN000; +C_40: ;AN000; + MOV ES:[BX.IFSR_FUNC],AL ;AN000; + ;AN000; + invoke CALL_IFS ; *** call fs with close request ;AN000; + ;AN000; + JNC C_60 ;AN000; + TEST IFSPROC_FLAGS,ISCLOSE ; ifs error ;AN000; + JZ C_980 ; return w/carry, if close ;AN000; +;;;;;;;;ADD SP,6 ; restore stack first ;AD018; + RestoreReg ; old ref count & sft ;AN018;;AC019; + CMP CX,1 ;AN018;;AC019; + JNE C_980 ;AN018; + MOV ES:[DI.sf_ref_count],0 ; If freeing, need to zap ;AN018; + JMP C_980 ;AN000; +C_60: ;AN000; + invoke SFF_TO_SFT ;AN000; + TEST IFSPROC_FLAGS,ISCLOSE ;AN000; + JZ C_990 ; finished w/commit ;AN000; +C_80: ;AN011; + RestoreReg ; old ref count & sft ;AN000; + CMP AX,1 ;AN000; + JNE C_990 ;AN000; + MOV ES:[DI.sf_ref_count],0 ; If freeing, need to zap ;AN000; + JMP C_990 ; busy mark ;AN000; + ;AN000; + ;AN000; +C_980: ; Return area ;AN000; + STC ;AN000; + JMP C_1000 ;AN000; +C_990: ;AN000; + CLC ;AN000; +C_1000: ; preserve ds - dosgroup ;AN000; + PUSH SS ;AN000; + POP DS ;AN000; + return ;AN000; + ;AN000; +EndProc IFS_COMMIT ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_LSEEK ;AN000; +; ;AN000; +; Inputs: ;AN000; +; ES:DI -> SFT ;AN000; +; CX:DX = Input CX:DX to $Lseek (offset) ;AN000; +; NOTE: THIS LSEEK IS ALWAYS ASSUMED TO BE A TYPE 2 (relative to EOF) ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 44 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 10 ; Lseek file ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; IFSR_DEVICE_CB@ DD ? ;AN000; +; *+ IFSR_OPEN_CB@ DD ? ; Call SFT_TO_SFFto convert SFT to SF ;AN000; +; ; and set this as pointer to it. ;AN000; +; * IFSR_MODE DB 2 ; Position mode: - BL ;AN000; +; ; 2 = ptr moved eof + offset ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; * IFSR_POSITION DD ? ; displacement of LSEEK - CX:DX ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to SF_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call SFF_TO_SFT ;AN000; +; Set DX:AX = IFSR_POSITION ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO {error} ;AN000; +; AX = IFSR_RETCODE ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Returns: ;AN000; +; ES:DI -> SFT ;AN000; +; Carry clear ;AN000; +; DX:AX return as with local $Lseek ;AN000; +; Carry Set ;AN000; +; AX is error code ;AN000; +; All destroyed ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_LSEEK,NEAR ;AN000; +ASSUME DS:Nothing,ES:NOTHING ; Initially DS is unknown ;AN020; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for lseek ;AN000; + ifsr_api_def LSEEKFILE ;AN000; + ;AN000; + PUSH SS ; Set DS to DOSGROUP ;AN020; + POP DS ; ;AN020; +ASSUME DS:DOSGROUP ; ;AN020; + + MOV CS:IFSPROC_FLAGS,SETDEVICECB ; init processing flags ;AN000; + MOV WORD PTR [THISSFT],DI ;AN020; + MOV WORD PTR [THISSFT+2],ES ;AN020; + SaveReg ; save for later restore before leave ;AN012;;AN020; + + invoke PREP_IFSR ;AN000; + ;AN000; + invoke DRIVE_FROM_SFT ; set IFSDRV for possible criter ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_LSEEKFILE ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSLSEEKFILE ;AN000; + MOV ES:[BX.IFSR_MODE],MODE2 ;AN000; + MOV WORD PTR ES:[BX.IFSR_POSITION],DX ;AN000; + MOV WORD PTR ES:[BX.IFSR_POSITION+2],CX ;AN000; + ;AN000; + invoke CALL_IFS ; call fs with lseek request ;AN000; + ;AN000; + JC LS_1000 ;AN000; + MOV AX,WORD PTR ES:[BX.IFSR_POSITION] ;AN000; + MOV DX,WORD PTR ES:[BX.IFSR_POSITION+2] ;AN000; + invoke SFF_TO_SFT ;AN000; + ;AN000; + CLC ;AN000; +LS_1000: ;AN000; + RestoreReg ; restore sft ptr for ibmdos ;AN012; + return ;AN000; + ;AN000; +EndProc IFS_LSEEK ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_READ ;AN000; +; ;AN000; +; Called by: IFSFUNC dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS ;AN000; +; SFT_TO_SFF ;AN000; +; SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; Outputs of SETUP: ;AN000; +; CX = byte count ;AN000; +; ES:DI Points to SFT ;AN000; +; [DMAADD] = transfer addr ;AN000; +; SFT checked for access mode ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 46 ; Total length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 11 ; Read Byte Block ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ; CD/DF - specified in SF_DEVPTR ;AN000; +; *+ IFSR_OPEN_CB@ DD ? ; Call SFT_TO_SFFto convert SFT to SF ;AN000; +; ; and set this as pointer to it. ;AN000; +; IFSR_RESV3 DW 0 ;AN000; +; IFSR_COUNT DW 0 ;AN000; +; *+ IFSR_BUFFER@ DD ? ; [DMAADD] ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to SF_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call SFF_TO_SFT ;AN000; +; CX = IFSR_COUNT ;AN000; +; ES:DI -> SFT ;AN000; +; ENDDO ;AN000; +; ELSE DO {error} ;AN000; +; AX = IFSR_RETCODE ;AN000; +; CX = 0 ;AN000; +; ES:DI -> SFT ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Outputs: ;AN000; +; Carry clear ;AN000; +; SFT Position updated ;AN000; +; CX = No. of bytes read ;AN000; +; ES:DI point to SFT ;AN000; +; [DMAADD] filled with info read ;AN000; +; Carry set ;AN000; +; AX is error code ;AN000; +; CX = 0 ;AN000; +; ES:DI point to SFT ;AN000; +; DS preserved, all other registers destroyed ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_READ,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for read ;AN000; + MOV CS:IFSPROC_FLAGS,SetDeviceCB ;AN000; + MOV WORD PTR [THISSFT],DI ; set thissft ;AN000; + MOV WORD PTR [THISSFT+2],ES ;AN000; + ;AN000; +R_20: ; (welcome lock/read) ;AN000; + ifsr_api_def READFILE ;AN000; + invoke PREP_IFSR ; zero out ifsr, es:bx -> ifsr ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_READFILE ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSREADFILE ;AN000; +; XOR AL,AL ; for now, set mode = read (0) ;AD010; +; TEST CS:IFSPROC_FLAGS,ISLOCKREAD ;AD010; +; JZ W_80 ;AD010; +; INC AL ; inc mode to mode_lock_read ;AD010; + JMP W_80 ; cont. read/write common code ;AN000; + ; in ifs_write below ;AN000; + ;AN000; +EndProc IFS_READ ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_WRITE ;AN000; +; ;AN000; +; Called by: IFSFUNC dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS ;AN000; +; SFT_TO_SFF ;AN000; +; SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; Outputs of SETUP: ;AN000; +; CX = byte count ;AN000; +; ES:DI Points to SFT ;AN000; +; [DMAADD] = transfer addr ;AN000; +; SFT checked for access mode ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 46 ; Length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 12 ; Write Byte Block ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ;AN000; +; *+ IFSR_OPEN_CB@ DD ? ; call SFT_TO_SFF & set this as ptr ;AN000; +; IFSR_RESV3 DW 0 ;AN000; +; * IFSR_COUNT DW ? ; # bytes to write - CX ;AN000; +; * IFSR_BUFFER@ DD ? ; Data buffer - [DMAADD] ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to SF_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call SFF_TO_SFT ;AN000; +; CX = IFSR_COUNT ;AN000; +; ES:DI -> SFT ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO {error} ;AN000; +; AX = IFSR_RETCODE ;AN000; +; CX = 0 ;AN000; +; ES:DI -> SFT ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Outputs: ;AN000; +; Carry clear ;AN000; +; SFT Position updated ;AN000; +; CX = No. of bytes written ;AN000; +; ES:DI point to SFT ;AN000; +; Carry set ;AN000; +; AX is error code ;AN000; +; CX = 0 ;AN000; +; ES:DI point to SFT ;AN000; +; DS preserved, all other registers destroyed ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_WRITE,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for write ;AN000; + MOV CS:IFSPROC_FLAGS,SetDeviceCB ; init processing flags ;AN000; + MOV WORD PTR [THISSFT],DI ; set thissft ;AN000; + MOV WORD PTR [THISSFT+2],ES ;AN000; + ;AN000; +W_20: ; (welcome write/unlock) ;AN000; + ifsr_api_def WRITEFILE ;AN000; + invoke PREP_IFSR ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_WRITEFILE ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSWRITEFILE ;AN000; +; XOR AL,AL ; for now set mode to write (bit0=0) ;AD010; +; TEST CS:IFSPROC_FLAGS,ISWRITEUNLOCK ;AD010; +; JZ W_40 ;AD010; +; INC AL ; set mode to write/unlock (bit0=1) ;AD010; +;W_40: ;AD010; +; TEST CS:IFSPROC_FLAGS,ISADD ;AD010; +; JZ W_80 ;AD010; +; OR AL,MODE_ADD_MASK ; set mode to add (bit 1) ;AD010; +;W_80: ; (welcome read) ;AD010; +; TEST CS:IFSPROC_FLAGS,ISWOLOCK ;AD010; BAF +; JZ W_90 ;AD010; BAF +; OR AL,MODE_WO_MASK ; set mode to Write Only Lock ;AD010; BAF +;W_90: ;AD010; BAF +; MOV ES:[BX.IFSR_MODE],AL ;AD010; +W_80: ; (welcome read) ;AN010; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AC015; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_COUNT],CX ;AN000; + ;AN000; + MOV AX,WORD PTR [DMAADD] ; to access dmaadd ;AN000; + MOV WORD PTR ES:[BX.IFSR_BUFFER@],AX ;AN000; + MOV AX,WORD PTR [DMAADD+2] ;AN000; + MOV WORD PTR ES:[BX.IFSR_BUFFER@+2],AX ;AN000; + ;AN000; + invoke DRIVE_FROM_SFT ; set IFSDRV for possible criter ;AN000; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + ;AN000; + invoke CALL_IFS ; *** call fs with read/write request ;AN000; + ;AN000; + JNC W_100 ;AN000; + Context DS ; restore ds-dosgroup ;AN001; + LES DI,[THISSFT] ; restore esdi-sft ;AN001; + transfer ifs_1000 ; transfer to general ret as carry set ;AC001; +W_100: ;AN000; + MOV CX,ES:[BX.IFSR_COUNT] ; prep reg output ;AN000; + invoke SFF_TO_SFT ;AN000; + + Context DS ; restore ds-dosgroup ;AN001; + LES DI,[THISSFT] ; restore esdi-sft ;AN001; + transfer ifs_990 ; transfer to general good ret in util ;AN001; + ;AN000; +EndProc IFS_WRITE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_XLOCK ;AN000; +; ;AN000; +; Called by: IFSFUNC dispatcher ;AN000; +; ;AN000; +; Routines called: CALL_IFS DRIVE_FROM_SFT ;AN000; +; SFT_TO_SFF ;AN000; +; SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BL = 80H bit: 0 lock all operations ;AN000; +; 1 lock write operations only ;AN000; +; 0 Lock +; 1 Unlock +; 2 lock multiple range ;AN000; +; 3 unlock multiple range ;AN000; +; 4 lock/read ;AN000; +; 5 write/unlock ;AN000; +; 6 add (lseek eof/lock/write/unlock) ;AN000; +; ES:DI -> SFT ;AN000; +; CX = count/size Number of ranges/block size ;AN000; +; DS:DX -> BUFFER LABEL DWORD ;AN000; +; DD POSITION ; lock range, repeats CX times ;AN000; +; DD LENGTH ; ;AN000; +; ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 46+ ; Length of request ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 13 ; Lock Function ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ;AN000; +; *+ IFSR_OPEN_CB@ DD ? ; Call SFT_TO_SFFto convert SFT to SFF ;AN000; +; ; and set this as pointer to it. ;AN000; +; * IFSR_FUNC DB subfunction ; 0=LOCK, 1=UNLOCK ;AN000; +; IFSR_RESV3 DB DOS reserved ;AN000; +; * IFSR_POSITION DD range start ; single range ;AN000; +; * IFSR_LENGTH DD range length ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to SF_IFSR_HDR ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; Call SFF_TO_SFT ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO {error} ;AN000; +; AX = IFSR_RETCODE ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: ;AN000; +; AX set on error: Lock conflict ;AN000; +; Too many locks ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_XLOCK,NEAR ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def LOCKFILE ;AN000; + ;AN000; + SaveReg ; save input bl ;AN014; + MOV CS:IFSPROC_FLAGS,SetDeviceCB ;AC002; +;;;;;;;;TEST BL,80H ;AN006;AD010; +; JZ L_10 ;AN006;AD010; +; OR CS:IFSPROC_FLAGS,IsWOLock ; This is Write Only lock ;AN006;AD010; +;L_10: ;AN006;AD010; +; SaveReg ; save function (int 21h al value) ;AD010; +; AND BL,07FH ; ditch 80h bit for now ;AD010; +; CMP BL,INT21AL_LOCK_READ ; Check for special case locks ;AD010; +; JB L_60 ; these generate different ;AD010; +; JNE L_20 ; ifsrh's. ;AD010; +; OR CS:IFSPROC_FLAGS,IsLockRead ; This is lock/read request ;AD010; +; RestoreReg ; restore bx with 80 bit ;AD010; +; Context DS ;AD010; +; JMP R_20 ; let ifs_read above handle this ;AD010; +;L_20: ;AD010; +; CMP BL,INT21AL_WRITE_UNLOCK ;AD010; +; RestoreReg ; restore bx with 80 bit ;AD010; +; JNE L_40 ;AD010; +; OR CS:IFSPROC_FLAGS,IsWriteUnlock ; This is write/unlock request ;AD010; +; JMP SHORT L_50 ; cont. ifs_write above ;AD010; +;L_40: ;AD010; +; OR IFSPROC_FLAGS,IsAdd ;AD010; +;L_50: ;AD010; +; Context DS ;AD010; +;;;;;;;;JMP W_20 ; cont. in ifs_write above ;AD010; + ;AN000; +L_60: ;AN000; + SaveReg ; save input ds (buffer ptr) ;AN000; + Context DS ; ds-dosgroup to access thissft ;AN000; + MOV WORD PTR [THISSFT],DI ; set [THISSFT] ;AN000; + MOV WORD PTR [THISSFT+2],ES ;AN000; + invoke DRIVE_FROM_SFT ; set IFSDRV for possible criter ;AN000; + invoke PREP_IFSR ; clear ifsrh ;AM003; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_OPEN_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_LOCKFILE ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSLOCKFILE ;AN000; +;;;;;;;;MOV ES:[BX.IFSR_COUNT],CX ;AN003;AD010; + RestoreReg ; range segment, mode (input bl) ;AC003;AC010; +;;;;;;;;MOV AL,CL ;AN003;AD010; +; AND AL,07FH ; mask off hi 80 bit ;AN003;AD010; +; CMP AL,2 ;AN003;AD010; +; JGE L_70 ;AN003;AD010; +; ADD CL,2 ;AN003;AD010; +;L_70: ;AN003;AD010; +; MOV ES:[BX.IFSR_MODE],CL ;AN000;AD010; +; AND ES:[BX.IFSR_MODE],80H ; ditch input bl in low nibble ;AN005;AD010; +; AND CL,07FH ;AN003;AD010; +;;;;;;;;SUB CL,2 ; set func (0-lock,1-unlock) ;AC003;AD010; + RestoreReg ; restore input bl into al ;AN014; + MOV ES:[BX.IFSR_FUNC],AL ;AC003;AC010; +;;;;;;;;MOV WORD PTR ES:[BX.IFSR_RANGE@],DX ;AD010; +;;;;;;;;MOV WORD PTR ES:[BX.IFSR_RANGE@+2],DS ;AD010; + SaveReg ;AN010; + RestoreReg ;AN010; + MOV AX,WORD PTR DS:[SI] ;AN010; + MOV WORD PTR ES:[BX.IFSR_LK_POSITION],AX ;AN010; + MOV AX,WORD PTR DS:[SI+2] ;AN010; + MOV WORD PTR ES:[BX.IFSR_LK_POSITION+2],AX ;AN010; + MOV AX,WORD PTR DS:[SI+4] ;AN010; + MOV WORD PTR ES:[BX.IFSR_LK_LENGTH],AX ;AN010; + MOV AX,WORD PTR DS:[SI+6] ;AN010; + MOV WORD PTR ES:[BX.IFSR_LK_LENGTH+2],AX ;AN010; + RestoreReg + SaveReg ; set ds=ifsseg for ifs call ;AN003; + RestoreReg ;AN003; + + invoke CALL_IFS ; *** call fs with lock request ;AN000; + ;AN000; + JNC L_100 ;AN000; + transfer ifs_1000 ; go to general return (util) ;AN000; +L_100: ;AN000; + invoke SFF_TO_SFT ;AN000; + transfer ifs_990 ; go to general good ret (util) ;AN000; + ;AN000; + ;AN000; +EndProc IFS_XLOCK ;AN000; + ;AN000; +BREAK ;AN000; + +;****************************************************************************** +; +; IFS_FILE_XATTRIBUTES +; +; Called by: IFSFUNC dispatcher +; +; Routines called: CALL_IFS DRIVE_FROM_SFT +; SFT_TO_SFF +; SFF_TO_SFT +; +; Inputs: +; [THISSFT] Points to SFT being used +; [SAVE_ES:DI] -> Buffer for EA or EA names list +; [SAVE_DS:SI] -> Query List (BL=2) +; [SAVE_CX] = buffer size (BL=2,3) +; BL = function - 2=Get EA +; 3=Get EA Names +; 4=Set EA +; +; Function: +; This call is driven by the new INT 21H call 57H. *** REMOVED +; Prep IFSRH: +; * IFSR_LENGTH DW 50 ; Total length of request +; * IFSR_FUNCTION DB 4 ; Execute API function +; + IFSR_RETCODE DW ? +; + IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 15 ; File Attributes - get/set by name +; + IFSR_ERROR_CLASS DB ? +; + IFSR_ERROR_ACTION DB ? +; + IFSR_ERROR_LOCUS DB ? +; + IFSR_ALLOWED DB ? +; + IFSR_I24_RETRY DB ? +; + IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; IFSR_DEVICE_CB@ DD ? +; *+ IFSR_OPEN_CB@ DD ? +; * IFSR_FUNC DB ? ; 0-get 1-set +; * IFSR_SUBFUNC DB ? ; 2-EA 3-EA names +; *+ IFSR_BUFFER1@ DD ? ; Query List +; *+ IFSR_BUFFER2@ DD ? ; EA List +; *+ IFSR_COUNT DW ? ; count +; +; CALL routine, CALL_IFS, with pointer to SF_IFSR_HDR +; IF IFSR_RETCODE = 0 THEN +; DO +; Call SFF_TO_SFT +; Clear carry +; ENDDO +; ELSE DO +; AX = IFSR_RETCODE +; Set carry +; ENDDO +; ENDIF +; ENDDO +; +; Outputs: +; Carry clear: On Get: +; QUERY LIST or LIST filled in. +; On Set: +; Extended attributes set. All SFTs are updated. +; CARRY SET +; Carry set: AX is error code +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_access_denied +; Attempt to set an attribute which cannot be set +; (attr_directory, attr_volume_ID) +; error_sharing_violation +; Sharing mode of file did not allow the change +; (this request requires exclusive write/read access) +; (INT 24H generated) +; DS preserved, others destroyed +; +;****************************************************************************** + ;AN000; + procedure IFS_FILE_XATTRIBUTES,NEAR ;AN000; + ;AN000; +;;;;;;;;ifsr_fcn_def EXECAPI ; define ifsr for fileattr ;AN000; +; ifsr_api_def FILEATTR ;AN000; +; ;AN000; +; MOV CS:IFSPROC_FLAGS,SetDeviceCB ; init processing flags ;AN000; +; SaveReg ; save input function (2,3,4) ;AN000; +; ;AN000; +; invoke PREP_IFSR ; init ifsr ;AN000; +; Context DS ; ds - dosgroup ;AN000; +; ;AN000; +; invoke DRIVE_FROM_SFT ; set IFSDRV for possible criter ;AN000; +; MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; +; MOV ES:[BX.IFSR_LENGTH],LENGTH_FILEATTR ; prep IFSRH ;AN000; +; MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; +; MOV ES:[BX.IFSR_APIFUNC],IFSFILEATTR ;AN000; +; MOV AL,FUNC_GET_BY_HANDLE ; start ifsr_func with get ;AN000; +;;;;;;;;RestoreReg ; get original BX - func ;AN000; + + CMP BL,4 ; ;AC010; + JNE XFA_40 ; ;AC010; + JMP C_990 ; just ret success if set ;AC010; +XFA_40: ;AN000; + +;;;;;;;;MOV ES:[BX.IFSR_FUNC],AL ;AN000; +; MOV AL,SUBFUNC_EA ; start ifsr_subfunc w/ea list ;AN000; +; CMP CL,3 ; (input get ea names) ;AN000; +; JNE XFA_80 ;AN000; +; INC AL ; inc ifsr_subfunc to ea names ;AN000; +;FA_80: ;AN000; +; MOV ES:[BX.IFSR_SUBFUNC],AL ;AN000; +; CMP CL,4 ; no size offered on set so don't check ;AN009; +; JE XFA_82 ;AN009; +; +;FA_82: ;AN009; +; MOV AX,[SAVE_DI] ;AN000; +; MOV WORD PTR ES:[BX.IFSR_BUFFER2@],AX ; get list ptr into buffer2@ ;AC002; +; MOV AX,[SAVE_ES] ;AN000; +; MOV WORD PTR ES:[BX.IFSR_BUFFER2@+2],AX ; get list ptr into buffer2@ ;AC002; +;FA_85: ;AN008; +; CMP CL,2 ; get ea list with qlist ;AN000; +; JNE XFA_90 ;AN000; +; MOV AX,[SAVE_SI] ;AN000; +; CMP AX,NULL_PTR ; if null, don't set buffer1 ;AN005; +; JE XFA_90 ;AN005; +; MOV WORD PTR ES:[BX.IFSR_BUFFER1@],AX ; get list ptr into buffer2@ ;AC002; +; MOV AX,[SAVE_DS] ;AN000; +; MOV WORD PTR ES:[BX.IFSR_BUFFER1@+2],AX ; get list ptr into buffer2@ ;AC002; +;FA_90: ;AN000; +; PUSH [SAVE_CX] ; buffer size ;AN000; +; POP ES:[BX.IFSR_COUNT] ;AN000; +; invoke SFT_TO_SFF ; sets: [THISIFS] ;AN000; +; ; ES:BX -> IFSRH ;AN000; +; ; IFSR_OPEN_CB@ ;AN000; +; ; ds - IFSSEG ;AN000; +;************************************************ +; invoke CALL_IFS ; *** call fs with fileattr request ;AN000; +;************************************************ +; JNC XFA_100 ;AN000; +; JMP C_1000 ;AN000; +;FA_100: ;AN000; +;;;;;;;;invoke SFF_TO_SFT ;AN000; + + + Context DS ; on get - set size to 2 and count=0 ;AN010; + MOV AX,[SAVE_CX] ; if count < 2 than no buffer2 ;AN008;;AC013; + CMP AX,2 ;AN008;;AC013; + JGE XFA_120 ;AN008;;AC013; + XOR AX,AX + JMP SHORT XFA_140 +XFA_120: ;AN013; + PUSH [SAVE_ES] ;AN010; + POP ES ;AN010; + MOV DI,[SAVE_DI] ;AN010; + XOR AX,AX ;AN010; + STOSW ; count in buffer ;AN010; + MOV AX,2 ;AN007;AC010; +XFA_140: ;AN013; + SaveReg ; preserve future cx ;AN016; + CallInstall Get_User_Stack,multDOS,24 ; put size in user cx ;AN007; + RestoreReg ; restore future cx ;AN016; + MOV DS:[SI.USER_CX],AX ;AN007; + JMP C_990 ; go ret in close to get ds-dosgroup ;AN000; + ;AN000; + ;AN000; +EndProc IFS_FILE_XATTRIBUTES ;AN000; + ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSINIT.ASM b/v4.0/src/CMD/IFSFUNC/IFSINIT.ASM new file mode 100644 index 0000000..96fb591 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSINIT.ASM @@ -0,0 +1,1373 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsinit.asm 1.0 87/05/11 ;AN000; +TITLE IFSFUNC INITIALIZATION ROUTINES - Routines for ifs ;AN000; +NAME IFSINIT ;AN000; +;*********************************************************************************** ;AN000; +; ;AN000; +; IFS Initialization Routines ;AN000; +; ;AN000; +; IFSINIT ;AN000; +; ;AN000; +; REVISION HISTORY: ;AN000; +; A000 - Original version 4.00 MAY 1987 ;AN000; +; A001 - PTM 331 Entry point for device ioctl +; A002 - PTM 430 Renumber parse errors +; A003 - DCR 96 Transfer IFS DOS callbacks to IFSFUNC +; A004 - PTM 696 IFSFUNC hang w/no drivers +; A005 - PTM 541 Parse problem +; A006 - PTM 1227 DOS Version Check problem +; A007 - PTM 842 Error messages in ifsfunc +; A008 - PTM 1950 Autoattach when 2 ifs drivers loaded & 1st fails attach +; A009 - PTM 2249 Autoattach must set isifs bit in cds +; A010 - PTM 2827 Error proc problems 1/88 RMG +; A011 - PTM 3334 put back reset environment call 2/88 rmg +; A012 - PTM 4140 dos ext error msg enhancement - semaphore processing 4/19/88 RMG +; A013 - DCR 526 New INT 2FH Share interface not to trigger logic install 4/19/88 RMG +; +; LOC - +; +;*********************************************************************************** + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +include sysmsg.inc ;AN000; +msg_utilname ; resident msgret stuff ;AN000; +.cref ;AN000; +.list ;AN000; +.sall ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ; DOSGROUP data ;AN000; + extrn DataVersion:WORD ; version number of DOS data. ;AN000; + extrn SFTFCB:DWORD ; FCB SFT cache ;AN000; + extrn KeepCount:WORD ; FCB SFT cache ;AN000; + Extrn CDSAddr:DWORD ;AN000; + Extrn CDSCount:BYTE ;AN000; + Extrn DummyCDS:BYTE ;AN000; + Extrn CritPatch:WORD ;AN000; +DATA ENDS ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data ;AN000; + ;AN000; + Extrn CDSAlt:DWORD ;AN000; + Extrn DFLAddr:DWORD ;AN000; + Extrn DFLCount:BYTE ;AN000; +;;;aliasExtrn NLAddr:DWORD ;AN000; +;;;aliasExtrn NLSIZE:WORD ;AN000; + Extrn INT_2F_5:BYTE ;AN000; + Extrn NEXT_2F_5:DWORD ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn CD1:WORD ;AN000; + Extrn DF1:WORD ;AN000; + Extrn SFF1:WORD ;AN000; + Extrn THISIFS:DWORD ;AN000; + Extrn IFSPROC_FLAGS:WORD ;AN000; + Extrn IFSFUNC_FLAGS:WORD ;AN000; + Extrn UNC_FS_HDR:DWORD ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + Extrn IFS_ATTRS:WORD + Extrn RODS_LABEL:BYTE ;AN000; + Extrn IFSSEM:BYTE + ;AN000; + PUBLIC CODESIZE ;AN000; +CODESIZE DB 'RMG' ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 20H ;AN000; + PUBLIC TOTSIZE ;AN000; +TOTSIZE DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 30H ;AN000; + DB 20H ;AN000; + ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +IF DEBUG ;AN000; +Procedure NetPointers,NEAR ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + LDS SI,[DFLAddr] ;AN000; +;;;aliasLES DI,[NLAddr] ;AN000; + return ;AN000; +EndProc NetPointers ;AN000; + ;AN000; +Procedure NetPointers2,NEAR ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV CX,[DFLCount] ;AN000; +;;;aliasMOV DX,[NLSIZE] ;AN000; + return ;AN000; +EndProc NetPointers2 ;AN000; +ENDIF ;AN000; + ;AN000; +IF PATHGEN ;AN000; +Procedure GetIFSFCSinES,NEAR ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; + return ;AN000; +EndProc GetIFSFCSinES ;AN000; +ENDIF ;AN000; + ;AN000; +Procedure UnusedFunc,NEAR ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + fmt <>,<>,<"Unused IFSFUNC function issued\n"> ;AN000; + MOV AX,error_invalid_function ;AN000; + STC ;AN000; + return ;AN000; +EndProc UnusedFunc ;AN000; + ;AN000; +; the following multiplex functions are implemented: ;AN000; + ;AN000; +retn1 DD ? ;AN000; +DMY DW ? ;AN000; +CONT DD ? ;AN000; +FOO DW Leave2F ;AN000; + ;AN000; +INT2F PROC FAR ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:DOSGroup ;AN000; + CMP AH,multIFS ;AN000; + JZ IDispatch ;AN000; + JMP CONT ;AN000; +Leave2F: ;AN000; + RET ;AN000; +INT2F ENDP ;AN000; + ;AN000; +Procedure IDispatch,NEAR ;AN000; + POP WORD PTR retn1 ; remove long return ;AN000; + POP WORD PTR retn1+2 ;AN000; + POP DMY ; remove flags ;AN000; + XCHG AX,BX ; save bx/move index to index reg ;AN000; + SHL BL,1 ; convert byte to word index ;AN000; + XOR BH,BH ; convert to word index ;AN000; + POP DMY ; save fictitious AX ;AN000; + PUSH DMY ; restore spot on stack ;AN000; + PUSH WORD PTR retn1+2 ; restore long return ;AN000; + PUSH WORD PTR retn1 ;AN000; + PUSH FOO ; place near address of far return ;AN000; + PUSH CS:IFStable[BX] ; place destination routine ;AN000; + XCHG AX,BX ; restore BX ;AN000; + MOV AX,DMY ; restore AX ;AN000; + STI ; let Mani see Clock ticks ;AN000; +ShortReturn: ;AN000; + return ; go to routine (dispatch for Aaron) ;AN000; + ;AN000; +EDW MACRO name ;AN000; + extrn name:near ;AN000; + DW name ;AN000; +ENDM ;AN000; + ;AN000; +IFSTable LABEL WORD ;AN000; + DW IFSInstall ;AN000; + EDW IFS_RMDIR ; 1 IFS_RMDIR ;AN000; + EDW IFS_SEQ_RMDIR ; 2 IFS_SEQ_RMDIR ;AN000; + EDW IFS_MKDIR ; 3 IFS_MKDIR ;AN000; + EDW IFS_SEQ_MKDIR ; 4 IFS_SEQ_MKDIR ;AN000; + EDW IFS_CHDIR ; 5 IFS_CHDIR ;AN000; + EDW IFS_CLOSE ; 6 IFS_CLOSE ;AN000; + EDW IFS_COMMIT ; 7 IFS_COMMIT ;AN000; + EDW IFS_READ ; 8 IFS_READ ;AN000; + EDW IFS_WRITE ; 9 IFS_WRITE ;AN000; + EDW IFS_XLOCK ; 10 IFS_XLOCK ;AN000; + DW UnusedFunc ; 11 ;AN000; + EDW IFS_DISK_INFO ; 12 IFS_DISK_INFO ;AN000; + EDW IFS_SET_FILE_ATTRIBUTE ; 13 IFS_SET_FILE_ATTRIBUTE ;AN000; + EDW IFS_SEQ_SET_FILE_ATTRIBUTE ; 14 IFS_SEQ_SET_FILE_ATTRIBUTE ;AN000; + EDW IFS_GET_FILE_INFO ; 15 IFS_GET_FILE_INFO ;AN000; + EDW IFS_SEQ_GET_FILE_INFO ; 16 IFS_SEQ_GET_FILE_INFO ;AN000; + EDW IFS_RENAME ; 17 IFS_RENAME ;AN000; + EDW IFS_SEQ_RENAME ; 18 IFS_SEQ_RENAME ;AN000; + EDW IFS_DELETE ; 19 IFS_DELETE ;AN000; + EDW IFS_SEQ_DELETE ; 20 IFS_SEQ_DELETE ;AN000; + EDW IFS_OPEN ; 21 IFS_OPEN ;AN000; + EDW IFS_SEQ_OPEN ; 22 IFS_SEQ_OPEN ;AN000; + EDW IFS_CREATE ; 23 IFS_CREATE ;AN000; + EDW IFS_SEQ_CREATE ; 24 IFS_SEQ_CREATE ;AN000; + EDW IFS_SEQ_SEARCH_FIRST ; 25 IFS_SEQ_SEARCH_FIRST ;AN000; + EDW IFS_SEQ_SEARCH_NEXT ; 26 IFS_SEQ_SEARCH_NEXT ;AN000; + EDW IFS_SEARCH_FIRST ; 27 IFS_SEARCH_FIRST ;AN000; + EDW IFS_SEARCH_NEXT ; 28 IFS_SEARCH_NEXT ;AN000; + EDW IFS_ABORT ; 29 IFS_ABORT ;AN000; + EDW IFS_ASSOPER ; 30 IFS_ASSOPER ;AN000; + EDW Printer_GETSET_STRING ; 31 Printer_GETSET_STRING ;AN000; + EDW IFSFlushBuf ; 32 IFS_Flush_Buf ;AN000; + EDW IFS_LSEEK ; 33 IFS_LSEEK ;AN000; + EDW IFS_RESET_ENVIRONMENT ; 34 IFS_RESET_ENVIRONMENT ;AN000; + EDW IFS_DEVICE_CHECK ; 35 IFSDeviceCheck ;AN000; + EDW IFS_DEVICE_CLOSE ; 36 IFSDeviceClose ;AN000; + EDW IFS_DEVICE_OPER ; 37 IFSDeviceOper ;AN000; + EDW IFS_SPOOL_ECHO_CHECK ; 38 IFSSpoolEchoCheck ;AN000; + DW UnusedFunc ; 39 ;AN000; + DW UnusedFunc ; 40 ;AN000; + DW UnusedFunc ; 41 ;AN000; + EDW SERVER_DOSCALL_CLOSEFILES_FOR_UID ; 42 util ;AN000; + EDW DEVICE_IOCTL ; 43 dev ;AN001; + EDW IFS_UPDATE_CB ; 44 UPDATECB util ;AN000; + EDW IFS_FILE_XATTRIBUTES ; 45 hand ;AN000; + EDW IFS_XOPEN ; 46 XOPEN file ;AN000; + EDW IFS_DEPENDENT_IOCTL ; 47 util ;AN000; + ;AN000; + IF DEBUG ;AN000; + DW NetPointers ; 47 NetPointers ;AN000; + DW NetPointers2 ; 48 NetPointers2 ;AN000; + ENDIF ;AN000; + ;AN000; + IF PATHGEN ;AN000; + DW GetIFSFCSinES ; 49 (if debug) GetRedirCSinES ;AN000; + ; 47 (if NOT debug) GetRedirCSinES ;AN000; + ENDIF ;AN000; + ;AN000; +IFSInstall: ;AN000; + MOV AL,0FFh ;AN000; + MOV BX,IFS_ATTRS + return ;AN000; +EndProc IDispatch ;AN000; + ;AN000; +Procedure EcritNet,NEAR ;AN000; + ASSUME SS:NOTHING ;AN000; + PUSHF ;AN000; + CLI ;AN000; + PUSH AX ;AN000; + MOV AX,8000h+CritNet ;AN000; + INT int_ibm ;AN000; + POP AX ;AN000; +IF DEBUG ;AN000; + JNC NoCarry ;AN000; + fmt <>,<>,<"$p: ECritNet overflowed semaphore\n"> ;AN000; +NoCarry: ;AN000; +ENDIF ;AN000; + STI ;AN000; + POPF ;AN000; + return ;AN000; +EndProc EcritNet ;AN000; + ;AN000; +; ;AN000; +; Leave critical section for network. Note that the first instruction (PUSH ;AN000; +; AX) here is used as the patch byte to enable the DOS critical section ;AN000; +; routines... ;AN000; +; ;AN000; +; NOTE!!! On a 286, this instruction issues POPF!!! ;AN000; +; ;AN000; +Procedure LcritNet,NEAR ;AN000; + PUSH AX ;AN000; + PUSHF ;AN000; + CLI ;AN000; +IF DEBUG ;AN000; + JGE NoWrap ;AN000; + fmt <>,<>,<"$p: LCritNet decrementing semaphore through zero\n"> ;AN000; +NoWrap: ;AN000; +ENDIF ;AN000; + ;AN000; + MOV AX,8100h+critNet ;AN000; + INT int_ibm ;AN000; + STI ;AN000; + POPF ; NOTE that this restores entry ;AN000; + POP AX ;AN000; + return ;AN000; +EndProc LcritNet ;AN000; + ;AN000; + ;AN000; +Procedure EcritIFS,NEAR ;AN000; + ASSUME SS:NOTHING ;AN000; + PUSHF ;AN000; + CLI ;AN000; + PUSH AX ;AN000; + MOV AX,8000h+CritIFS ;AN000; + INT int_ibm ;AN000; + POP AX ;AN000; + STI ;AN000; + POPF ;AN000; + return ;AN000; +EndProc EcritIFS ;AN000; + ;AN000; +Procedure LcritIFS,NEAR ;AN000; + PUSH AX ;AN000; + PUSHF ;AN000; + CLI ;AN000; + MOV AX,8100h+critIFS ;AN000; + INT int_ibm ;AN000; + STI ;AN000; + POPF ; NOTE that this restores entry ;AN000; + POP AX ;AN000; + return ;AN000; +EndProc LcritIFS ;AN000; + ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:DOSGroup ;AN000; + ;AN000; +INTERR: ;AN000; +INTERRL:jmp INTERRL ; hang here - we're sick ;AN000; + ;AN000; + ;AN000; + PUBLIC TEMPBUF ;AN000; +TEMPBUF LABEL BYTE ;AN000; +; THE SPACE FROM HERE TO NETEND CONSTITUTES THE TEMP AREA OF IFSFUNC. ;AN000; +; WARNING DANGER!!!!!!!!! ;AN000; +; DO NOT reduce the size of this area without first checking ;AN000; +; all users of it. It is OK to make it BIGGER without checking. ;AN000; +; Current size: ?? ;AN000; + ;AN000; +Break ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; map: Resident: ;AN000; +; IF_40 - (contifsinit) 2nd half of ifsfinit procedure = tempbuf area ;AN000; +; allocate: DFL_LIST, altcds, sftfcb, ;AN000; +; set TOTALSIZE ;AN000; +; IFSFUNCINIT start ;AN000; +; I_700 - INIT: 2nd half of IFSFUNCINIT ;AN000; +; INT 23,24 stuff ;AN000; +; call IFSFINIT ;AN000; +; close std handles ;AN000; +; enable critical section ;AN000; +; terms & stays ;AN000; +; tempbuf ends ;AN000; +; Transient: ;AN000; +; IFSFINIT procedure ;AN000; +; Set interrupt vectors - 2F ;AN000; +; Call AUTO_ATTACH ;AN000; +; allocate stuff (write over code) ;AN000; +; jumps up to 2nd half ;AN000; +; IFSFUNCINIT init code ;AN000; +; version checks ;AN000; +; error msg processing ;AN000; +; free environment ;AN000; +; parsing ;AN000; +; move stack ;AN000; +; check size for everything ;AN000; +; ifsfunc code size calculation ;AN000; +; ifsfunc total size calculation ;AN000; +; jmps to I_700 ;AN000; +; AutoAttach ;AN000; +; CheckUNCpresence ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +; This Code must be protected from overwrite when the structures are ;AN000; +; initialized ;AN000; + ;AN000; + ;AN000; +IF_40: ; CONTIFSINIT ;AN000; +ASSUME DS:IFSSEG,ES:NOTHING,SS:NOTHING ;AN000; + ;AN000; +; ;AN000; +; Allocate and init DFL_LIST ;AN000; +; ;AN000; + MOV WORD PTR DFLAddr,DI ;AN000; + MOV WORD PTR DFLAddr+2,ES ;AN000; + MOV AL,DFLCount ;AN000; + XOR AH,AH ;AN000; + MOV BX,SIZE DFLL_LIST ;AN000; + MUL BX ;AN000; + MOV CX,AX ;AN000; + XOR AX,AX ;AN000; + REP STOSB ;AN000; + ;AN000; +;;;aliasMOV WORD PTR NLAddr,DI ;AN000; +;;; MOV WORD PTR NLAddr+2,ES ;AN000; +;;; MOV AX,NLSIZE ;AN000; +;;; STOSW ;AN000; +;;; XOR AX,AX ;AN000; +;;; STOSW ;AN000; +;;;aliasADD DI,NLSIZE-4 ;AN000; +; ;AN000; +; Allocate alt CDSs area ;AN000; +; ;AN000; + TEST IFSFUNC_FLAGS,UNC_INSTALLED ;AN000; + JZ IF_50 ;AN000; + MOV WORD PTR CDSAlt,DI ;AN000; + MOV WORD PTR CDSAlt+2,ES ;AN000; + PUSH DS ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; + MOV AL,CDSCount ; Alt = Alloc ((sizeof(CDS)+1)*CDSCount); ;AN000; + XOR AH,AH ;AN000; + INC AX ;AN000; + MOV BX,SIZE curdir_list ;AN000; + MUL BX ;AN000; + ADD DI,AX ;AN000; + JMP SHORT IF_55 ;AN000; +IF_50: ;AN000; + PUSH DS ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; +; ;AN000; +; Allocate new FCB cache if appropriate ;AN000; +; ;AN000; +IF_55: ;AN000; + CMP BYTE PTR CS:NEWFCBCACHE,0 ; Damn forward reference ;AN000; + JZ IF_80 ; JZ NO_FCB_CACHE ;AN000; +; ;AN000; +; We need to allocate (NewNumFCB * size of SF_entry) + size of sfTable. ;AN000; +; ;AN000; + CLI ; Diddling a DOS table, make sure ;AN000; +; ;AN000; +; Make dos point to new table ;AN000; +; ;AN000; + MOV WORD PTR SFTFCB,DI ;AN000; + MOV WORD PTR SFTFCB+2,ES ;AN000; +; ;AN000; +; Initialize table parts, next link and size ;AN000; +; ;AN000; + MOV WORD PTR ES:[DI.sfLink],-1 ;AN000; + MOV WORD PTR ES:[DI.sfLink+2],-1 ;AN000; + MOV CX,NewNumFCB ;AN000; + MOV ES:[DI.sfcount],CX ;AN000; +; ;AN000; +; Set up keepcount ;AN000; +; ;AN000; + MOV KeepCount,NewKeepVal ;AN000; +; ;AN000; +; Clean out the new FCB Cache ;AN000; +; ;AN000; + LEA DI,[DI].SFTable ; Point to the FCB SFTs ;AN000; +IF_60: ; CleanScan: ;AN000; + MOV ES:[DI.sf_ref_count],0 ;AN000; + MOV WORD PTR ES:[DI.sf_position],0 ;AN000; + MOV WORD PTR ES:[DI.sf_position+2],0 ;AN000; + ADD DI,SIZE sf_entry ;AN000; + LOOP IF_60 ;AN000; + STI ;AN000; +IF_80: ; NO_FCB_CACHE: ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + MOV [TOTALSIZE],DI ; Offset of 1st free byte ;AN000; + POP AX ;AN000; + POP BX ;AN000; + POP CX ;AN000; + POP DX ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP ES ;AN000; + POP DS ;AN000; + return ;AN000; + ;AN000; + ;AN000; + ;AN000; + ASSUME CS:IFSSEG,DS:IFSSEG,ES:NOTHING,SS:STACK ;AN000; + ;AN000; +.xlist ;AN000; +.xcref ;AN000; + msg_services ;AN007; + PUBLIC SYSGETMSG + msg_services +.cref ;AN000; +.list ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +Totalsize DW ? ;AN000; + ;AN000; +NEWFCBCACHE DB 0 ;AN000; + ;AN000; +INT_24: ; INT 24 handler used during INIT. ;AN000; + MOV AL,3 ; FAIL any INT 24s ;AN000; +INT_23: ; ^C handler used during INIT. ;AN000; + IRET ; ignores any ^C. ;AN000; + ;AN000; +I_700: ; Init ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; +; ;AN000; +; We are now going to set lots of INT vectors and other stuff. We need ;AN000; +; to make ourselves immune to INT 24 and ^C ;AN000; +; ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + MOV DX,OFFSET INT_23 ;AN000; + MOV AX,(Set_Interrupt_Vector SHL 8) + 23H ;AN000; + INT 21H ;AN000; + MOV DX,OFFSET INT_24 ;AN000; + MOV AX,(Set_Interrupt_Vector SHL 8) + 24H ;AN000; + INT 21H ;AN000; + invoke IFSFINIT ; Do general INIT ;AN000; + ;AN000; + XOR BX,BX ;AN000; + MOV CX,5 ; StdIN,StdOUT,StdERR,StdAUX,StdPRN ;AN000; +I_720: ; Close STD handles before ;AN000; + ; keep process ;AN000; + MOV AH,CLOSE ;AN000; + INT 21H ;AN000; + INC BX ;AN000; + LOOP I_720 ;AN000; + ;AN000; +; ;AN000; +; Enable the critical section code. This consists of replacing the RETs at ;AN000; +; the beginning of each critical section routine with a PUSH AX ;AN000; +; ;AN000; + PUSH CS ;AN000; + POP DS ; ds - ifsseg ;AN000; + ;AN000; + TEST IFSFUNC_FLAGS,UNC_INSTALLED ; 1st check if unc fs loaded ;AN000; + JZ I_800 ; only do this for unc ;AN000; + MOV AH,Get_In_Vars ; do crit patch ;AN000; + INT 21h ;AN000; + cld ;AN000; + ASSUME ES:DOSGroup ;AN000; + MOV AL,BYTE PTR LCritNet ;AN000; + MOV BX,OFFSET DOSGROUP:CritPatch ;AN000; + CLI ;AN000; +I_760: ; Scan ;AN000; + MOV DI,ES:[BX] ;AN000; + ADD BX,2 ;AN000; + OR DI,DI ;AN000; + JZ I_780 ;AN000; + stosb ;AN000; + JMP I_760 ;AN000; +I_780: ;AN000; + STI ;AN000; +I_800: ;AC012;moved + MOV CS:IFSSEM,0 ; initialize ifs semaphores ;AN012; +; ;AN000; +; Compute total size for residency. ;AN000; +; ;AN000; + MOV DX,TotalSize ; size of code and structs ;AN000; + ADD DX,100H+0Fh ; Add size of header ;AN000; + RCR DX,1 ;AN000; + MOV CL,3 ;AN000; + SHR DX,CL ;AN000; + MOV AX,(Keep_Process SHL 8) + 0 ;AN000; + INT 21h ;AN000; + MOV AX,(EXIT SHL 8) + 1 ;AN000; + INT 21h ;AN000; + ;AN000; + ;AN000; +; %%%% CODE/DATA BELOW IS OVERLAYED WHEN STRUCTURES ARE SET UP ;AN000; + ;AN000; +NETEND LABEL BYTE ;AN000; + ;AN000; + procedure IFSFINIT,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + ;AN000; +; Perform initialization at DOSINIT time ;AN000; + ;AN000; + PUSH DS ;AN000; + PUSH ES ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH DX ;AN000; + PUSH CX ;AN000; + PUSH BX ;AN000; + PUSH AX ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; +; SET INTERRUPT VECTORS ;AN000; + ;AN000; + MOV AL,2FH ;AN000; + PUSH AX ;AN000; + MOV AX,(multDOS SHL 8) OR 2 ;AN000; + INT 2FH ;AN000; + POP AX ; no know contents ;AN000; + ;AN000; + PUSH ES ;AN000; + PUSH BX ;AN000; + LES BX,DWORD PTR ES:[BX] ; setting int 2f mult 5 ;AN000; + MOV WORD PTR [NEXT_2F_5],BX ;AN000; + MOV WORD PTR [NEXT_2F_5+2],ES ;AN000; + POP BX ;AN000; + POP ES ;AN000; + ;AN000; + MOV DX,OFFSET INT_2F_5 ;AN000; + MOV ES:[BX],DX ;AN000; + MOV ES:[BX+2],DS ;AN000; + ;AN000; + MOV AX,(Get_Interrupt_Vector SHL 8) + 2Fh ;AN000; + INT 21h ;AN000; + MOV WORD PTR CONT,BX ;AN000; + MOV WORD PTR CONT+2,ES ;AN000; + MOV AX,(Set_Interrupt_Vector SHL 8) + 2Fh ;AN000; + MOV DX,OFFSET INT2F ; multIFS handler ;AN000; + INT 21h ;AN000; +; ;AN000; +; auto - attach ;AN000; +; ;AN000; + CALL AUTO_ATTACH ;AN000; +; ;AN000; +; call swap setup ;AN000; +; ;AN000; + PUSH DS ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; + invoke SERVER_IFSFUNC_DATA_AREA ;AN000; + POP DS ;AN000; + invoke SET_IFS_DOSCALL@ ;AN003; + ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; +; ;AN007; +; Prep error messages ;AN007; +; ;AN007; + LEA DI,Rods_label ;AN007; + SaveReg ;AN007; + RestoreReg ;AN007; + MOV AX,DOS_GET_EXT_PARSE_ADD ;AN007; + MOV DL,7 ; set msg addr ;AN007; + INT 2FH ;AN007; +; ;AN000; +; Now start clobbering code ;AN000; +; ;AN000; + MOV DI,OFFSET NETEND ; Start strucs here ;AN000; + TEST DI,1 ; Word aligned? ;AN000; + JZ IF_20 ; Yes, ok ;AN000; + INC DI ; Bump to word align ;AN000; +IF_20: ; NOADJ1 ;AN000; + JMP IF_40 ; jmp CONTIFSINIT ;AN000; + ;AN000; +EndProc IFSFINIT ;AN000; + ;AN000; +;************* ifsfuncinit transient portion ****************************** ;AN000; + AA_PARMS_BUF DB 6 DUP(0) ; temp storage used by auto-attach ;AN000; + S_SIZE1 DB 11 ; Sublist size(PTR next SUBLIST) ;AN000; + DB 0 ; Reserved ;AN000; + DD SUB_IFSFUNC ; Ptr to substituted string ;AN000; + DB 1 ; n of %n ;AN000; + DB Left_Align+Char_Field_ASCIIZ ; Data-type flags ;AN000; + DB 7 ; Maximum field width ;AN000; + DB 5 ; Minimum field width ;AN000; + DB " " ; Character for Pad field ;AN000; + S_SIZE2 DB 11 ; Sublist size(PTR next SUBLIST) ;AN000; + DB 0 ; Reserved ;AN000; + DD SUB_SHARE ; Ptr to substituted string ;AN000; + DB 1 ; n of %n ;AN000; + DB Left_Align+Char_Field_ASCIIZ ; Data-type flags ;AN000; + DB 7 ; Maximum field width ;AN000; + DB 5 ; Minimum field width ;AN000; + DB " " ; Character for Pad field ;AN000; + ;AN000; +SUB_IFSFUNC DB "IFSFUNC",0 ;AN000; +SUB_SHARE DB "SHARE",0 ;AN000; + ;AN000; +DEFAULT_DFLCount DB 4 ;AN000; +;;;alias DEFAULT_NLSize DW 172 ; 4 * 43 ;AN000; + ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING ;AN000; +.xlist ;AN000; +.xcref ;AN000; + INCLUDE IFSPARSE.INC ;AN000; + msg_services ;AN000; + msg_services ; parse/install msgs ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; !!!!!!! IFSFUNC starts here !!!!!!! (see END statement) ;AN000; +;****************************************************************************** ;AN000; + ;AN000; +IFSFUNCINIT: ;AN000; + ;AN000; + CALL SYSLOADMSG ;AN000; + JNC I_20 ;AN000; + SaveReg ;AN006; + RestoreReg ;AN006; + CALL SYSDISPMSG ;AN000; + ;AN000; +Badver_msg proc far ;AN000; + MOV AL,0FFh ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + MOV AH,EXIT ;AN000; + INT 21h ;AN000; + PUSH ES ;AN000; + XOR AX,AX ;AN000; + PUSH AX ;AN000; + RET ;AN000; +badver_msg ENDP ;AN000; + ;AN000; +Badmes proc far ;AN000; + ASSUME CS:IFSSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + MOV BX,STDERR ;AN000; + XOR DL,DL ;AN000; + CALL SYSDISPMSG ;AN000; + MOV AX,(EXIT SHL 8) + 0FFH ;AN000; + INT 21h ;AN000; +badmes ENDP ;AN000; + ;AN000; + ;AN000; +I_20: ; Version OK ;AN000; + MOV AX,(multIFS SHL 8)+0 ; Check if IFSFUNC already installed ;AN000; + INT 2Fh ;AN000; + CMP AL,0 ;AN000; + JE I_40 ;AN000; + MOV AX,COMMON_ERR_2 ; yes - already installed - error 2 ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + MOV SI,OFFSET S_SIZE1 ; prep for sysdispmsg call ;AN000; + MOV CX,1 ;AN000; + MOV DH,UTILITY_MSG_CLASS ;AN000; +I_30: ;AN005; + PUSH CS ;AN000; + POP DS ;AN000; + JMP BADMES ;AN000; + ; no error on install check, ;AN000; +I_40: ; free environment - no longer needed ;AN000; + MOV AX,DS:[PDB_ENVIRON] ;AN000; + OR AX,AX ;AN000; + JZ I_60 ;AN000; + PUSH ES ;AN000; + MOV ES,AX ;AN000; + MOV AH,DEALLOC ;AN000; + INT 21H ;AN000; + POP ES ;AN000; +I_60: ;AN000; +;************************************************************************************ ;AN000; +; Parse IFSFUNC parameter : ;AN000; +; NAMES = n ;;;alias[n | (n {m})] ;AN000; +;************************************************************************************ ;AN000; + ; Set default n and m ;AN000; + MOV AL,DEFAULT_DFLCount ;AN000; + MOV [DFLCount],AL ; 4 (n) ;AN000; +;;;aliasMOV AX,DEFAULT_NLSize ;AN000; +;;;aliasMOV NLSize,AX ; 4 * 43 (m) ;AN000; + ;AN000; + MOV SI,81h ; ds:si -> cmd parameter ;AN000; + XOR CX,CX ; no operands parsed yet ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; +ASSUME ES:IFSSEG ;AN000; + MOV DI,OFFSET IFSF_PARMS ; es:di -> parse control blocks ;AN000; + XOR DX,DX ; reserved ;AN000; + ;AN000; + CALL SYSPARSE ; call parser ;AN000; + ;AN000; + CMP AX,-1 ; End of cmd? ;AN000; + JNE I_70 ;AN000; + JMP I_160 ; if so continue w/init ;AN000; +I_70: ;AN000; + CMP AX,0 ; Error? ;AN000; + JNE I_140 ; yes - go display parse error ;AN000; + ;AN000; +;;;aliasCMP IFSF_RESULT,COMPLEX ; complex? ;AN000; +;;;aliasJE I_80 ;AN000; + CMP IFSF_TAG,"N" ; no - n only ;AN000; + MOV AX,PARSE_ERR_6 ;AN002; + JNE I_140 ;AN000; + ;AN000; + MOV AL,IFSF_NM ;AN000; + MOV [DFLCount],AL ;AN000; + ;AN000; + CALL SYSPARSE ;AN000; + CMP AX,-1 ;AN000; + JE I_160 ;AN000; + MOV AX,PARSE_ERR_1 ;AN000; +;;;aliasJMP I_140 ; go display parse error ;AN000; +;;; ;AN000; +;;;aliasI_80: ; process complex (n,m) ;AN000; +;;; XOR CX,CX ; prep for new parse call ;AN000; +;;; XOR DX,DX ;AN000; +;;; CALL SYSPARSE ;AN000; +;;; CMP AX,-1 ; End of cmd? ;AN000; +;;; JE I_160 ; if so continue w/init ;AN000; +;;; CMP AX,0 ; Error? ;AN000; +;;; JNE I_140 ; if so go display error ;AN000; +;;; CMP IFSF_TAG,"N" ; check if n or m parm ;AN000; +;;; JNE I_100 ;AN000; +;;; MOV AL,IFSF_NM ; n parm ;AN000; +;;; MOV DFLCount,AL ;AN000; +;;; CALL SYSPARSE ; go back for m ;AN000; +;;; CMP AX,-1 ; End of cmd? ;AN000; +;;; JE I_160 ; if so continue w/init ;AN000; +;;; CMP AX,0 ; Error? ;AN000; +;;; JNE I_140 ; if so go display error ;AN000; +;;; ;AN000; +;;;00: ;AN000; +;;; CMP IFSF_TAG,"M" ; check if m parm ;AN000; +;;; JE I_120 ;AN000; +;;; MOV AX,PARSE_ERR_7 ; not m - error ;AN002; +;;; JMP I_140 ;AN000; +;;;20: ;AN000; +;;; MOV AX,WORD PTR IFSF_NM ; m parm ;AN000; +;;; MOV NLSize,AX ;AN000; +;;; ;AN000; +;;; CALL SYSPARSE ; call parser again to check for ;AN000; +;;; CMP AX,-1 ; possible garbage ;AN000; +;;; JE I_160 ;AN000; +;;; MOV AX,PARSE_ERR_1 ;AN000; +;;;alias ;AN000; +I_140: ; display parse error ;AN000; + MOV DH,PARSE_ERR_CLASS ; then continue w/defaults ;AN000; + XOR CX,CX ;AN000; +;;; MOV BX,STDERR ;AD005; +;;; XOR DL,DL ;AD005; +;;; CALL SYSDISPMSG ;AD005; + JMP I_30 ;AN005; + ;AN000; +I_160: ;AN000; + ; doinit ;AN000; + MOV AX,DS ; Move the stack so it doesn't ;AN000; + ; get blasted by structure init ;AN000; + MOV SS,AX ; Set stack in the PSP overlaying ;AN000; + MOV SP,100H ; parms just processed ;AN000; +; ;AN000; +; We must now do some computation. We have to check if there is enough room ;AN000; +; for everything. We must do this here BEFORE we start overlaying this ;AN000; +; code ;AN000; +; ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + MOV DI,OFFSET NETEND ; We have this much code ;AN000; + TEST DI,1 ; Word aligned? ;AN000; + JZ I_180 ; Yes, OK. ;AN000; + INC DI ; Make word aligned ;AN000; +I_180: ; no adjust 5 label ;AN000; + ;AN000; +; This code is added to make it easy to determine the code size ;AN000; +; of IFSFUNC for debug purposes. It is overlayed, so does not use extra ;AN000; +; storage. ;AN000; + PUSH DI ; ;AN000; + PUSH SI ; ;AN000; + LEA SI,CODESIZE+3 ; ;AN000; +I_200: ; TENT ;AN000; + SUB DI,10000 ; ;AN000; + JC I_220 ; ;AN000; + INC BYTE PTR [SI] ; ;AN000; + JMP I_200 ; ;AN000; +I_220: ; NEG1 ;AN000; + ADD DI,10000 ; ;AN000; + INC SI ; ;AN000; +I_240: ; THOU ;AN000; + SUB DI,1000 ; ;AN000; + JC I_260 ; ;AN000; + INC BYTE PTR [SI] ; ;AN000; + JMP I_240 ; ;AN000; +I_260: ; NEG2 ;AN000; + ADD DI,1000 ; ;AN000; + INC SI ; ;AN000; +I_280: ; HUND ;AN000; + SUB DI,100 ; ;AN000; + JC I_300 ; ;AN000; + INC BYTE PTR [SI] ; ;AN000; + JMP I_280 ; ;AN000; +I_300: ; NEG3 ;AN000; + ADD DI,100 ; ;AN000; + INC SI ; ;AN000; +I_320: ; TENS ;AN000; + SUB DI,10 ; ;AN000; + JC I_340 ; ;AN000; + INC BYTE PTR [SI] ; ;AN000; + JMP I_320 ; ;AN000; +I_340: ; NEG4 ;AN000; + ADD DI,10 ; ;AN000; + INC SI ; ;AN000; +I_360: ; ONES ;AN000; + SUB DI,1 ; ;AN000; + JC I_380 ; ;AN000; + INC BYTE PTR [SI] ; ;AN000; + JMP I_360 ; ;AN000; +I_380: ; DONE ;AN000; + POP SI ; ;AN000; + POP DI ; ;AN000; +; ;AN000; +; Allocate the DFL ;AN000; +; ;AN000; + MOV AL,DFLCount ;AN000; + XOR AH,AH ;AN000; + MOV CX,SIZE DFLL_LIST ;AN000; + MUL CX ;AN000; + OR DX,DX ;AN000; + JZ I_402 ;AN000; + JMP I_640 ; out of memp ;AN000; +I_402: ;AN000; + ADD DI,AX ;AN000; + JNC I_403 ;AN000; + JMP I_640 ; out of memp ;AN000; +I_403: ;AN000; +;;;aliasADD DI,NLSIZE ;AN000; +;;;aliasJNC I_404 ;AN000; +;;;aliasJMP I_640 ; out of memp ;AN000; +I_404: ;AN000; + CALL CHECK_UNC_PRESENCE ; check if unc present, if not, ;AN000; + TEST IFSFUNC_FLAGS,UNC_INSTALLED ;AN000; + JZ I_415 ; no need to allocate altcds ;AN000; +; ;AN000; +; Allocate the TEMP CDS area ;AN000; +; ;AN000; + PUSH DS ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; + MOV CL,CDSCount ;AN000; + XOR CH,CH ;AN000; + INC CX ;AN000; + MOV AX,SIZE curdir_list ;AN000; + MUL CX ;AN000; + OR DX,DX ;AN000; + JZ I_410 ;AN000; + JMP I_640 ;AN000; +I_410: ;AN000; + ADD DI,AX ; Temp CDS area ;AN000; + JNC I_417 ;AN000; + JMP I_640 ;AN000; +I_415: ;AN000; +; ;AN000; +; Determine if need new FCB cache and Allocate it if appropriate ;AN000; +; ;AN000; + PUSH DS ; get addressability to DOSGROUP ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; +I_417: ;AN000; + CMP KeepCount,DefKeepVal ;AN000; + JNZ I_420 ;AN000; + LDS SI,SFTFCB ;AN000; +ASSUME DS:NOTHING ;AN000; + CMP [SI].sfCount,DefNumFCB ;AN000; + JNZ I_420 ;AN000; + INC NEWFCBCACHE ; Flag ourselves ;AN000; + ADD DI,((SIZE sf_entry) * NewNumFCB)+((SIZE sf)-2) ; New cache ;AN000; + JC I_640 ; out of memp ;AN000; +I_420: ; no fcb ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; +; This code is added to make it easy to determine the total size @A1A ;AN000; +; of IFSFUNC. It is overlayed, so does not use extra storage. @A1A ;AN000; + ; @A1A ;AN000; + PUSH DI ; @A1A ;AN000; + PUSH SI ; @A1A ;AN000; + LEA SI,TOTSIZE ; @A1A ;AN000; +I_440: ; TENT2 @A1A ;AN000; + SUB DI,10000 ; @A1A ;AN000; + JC I_460 ; @A1A ;AN000; + INC BYTE PTR [SI] ; @A1A ;AN000; + JMP I_440 ; @A1A ;AN000; +I_460: ; NEG5 @A1A ;AN000; + ADD DI,10000 ; @A1A ;AN000; + INC SI ; @A1A ;AN000; +I_480: ; THOU2 @A1A ;AN000; + SUB DI,1000 ; @A1A ;AN000; + JC I_500 ; @A1A ;AN000; + INC BYTE PTR [SI] ; @A1A ;AN000; + JMP I_480 ; @A1A ;AN000; +I_500: ; NEG6 @A1A ;AN000; + ADD DI,1000 ; @A1A ;AN000; + INC SI ; @A1A ;AN000; +I_520: ; HUND2 @A1A ;AN000; + SUB DI,100 ; @A1A ;AN000; + JC I_540 ; @A1A ;AN000; + INC BYTE PTR [SI] ; @A1A ;AN000; + JMP I_520 ; @A1A ;AN000; +I_540: ; NEG7 @A1A ;AN000; + ADD DI,100 ; @A1A ;AN000; + INC SI ; @A1A ;AN000; +I_560: ; TENS2 @A1A ;AN000; + SUB DI,10 ; @A1A ;AN000; + JC I_580 ; @A1A ;AN000; + INC BYTE PTR [SI] ; @A1A ;AN000; + JMP I_560 ; @A1A ;AN000; +I_580: ; NEG8 @A1A ;AN000; + ADD DI,10 ; @A1A ;AN000; + INC SI ; @A1A ;AN000; +I_600: ; ONES2 @A1A ;AN000; + SUB DI,1 ; @A1A ;AN000; + JC I_620 ; @A1A ;AN000; + INC BYTE PTR [SI] ; @A1A ;AN000; + JMP I_600 ; @A1A ;AN000; +I_620: ; DONE2 @A1A ;AN000; + POP SI ; @A1A ;AN000; + POP DI ; @A1A ;AN000; + ;AN000; + ;AN000; + JMP I_700 ;AN000; + ;AN000; +I_640: ; OUT_OF_MEMP ;AN000; + POP DS ;AN000; +I_660: ; OUT_OF_MEM ;AN000; + MOV AX,PARSE_ERR_10 ;AN000; + XOR CX,CX ;AN000; + JMP BADMES ;AN000; + ;AN000; +ASSUME DS:NOTHING ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; AUTO_ATTACH ;AN000; +; ;AN000; +; Called by: init ;AN000; +; ;AN000; +; Routines called: CALL_IFS ;AN000; +; CDS_TO_CD ;AN000; +; CD_TO_CDS ;AN000; +; FIND_IFS_DRIVER ;AN000; +; Inputs: ;AN000; +; None ;AN000; +; ;AN000; +; Function: ;AN000; +; Get addressability to CDS structure (SYSVARS - IBMDOS/BIO) ;AN000; +; FOR I = 1 to # CDS ;AN000; +; DO ;AN000; +; ³ Drive = I - 1 (0-A,1-B,...) ;AN000; +; ³ IF (curdir_inuse == 0 & curdir_devptr .NOT. 0) THEN ;AN000; +; ³ DO ;AN000; +; ³ ³ Get pointer to 1st IFS header ;AN000; +; ³ ³ WHILE pointer .NOT. 0FFFFH ;AN000; +; ³ ³ DO ;AN000; +; ³ ³ START ATTACH ;AN000; +; ³ ³ (IFSR_TYPE = 2 ;AN000; +; ³ ³ IFSR_PARMS@ -> IFS name, 0 parms) ;AN000; +; ³ ³ IF Attach successful THEN ;AN000; +; ³ ³ DO ;AN000; +; ³ ³ IF IFSUSESHARE set THEN ;AN000; +; ³ ³ Set share flag ;AN000; +; ³ ³ ENDIF ;AN000; +; ³ ³ LEAVE While ;AN000; +; ³ ³ ENDDO ;AN000; +; ³ ³ ELSE ;AN000; +; ³ ³ Get pointer to next IFS header ;AN000; +; ³ ³ ENDIF ;AN000; +; ³ ³ ENDDO ;AN000; +; ³ ³ ENDWHILE ;AN000; +; ³ ENDDO ;AN000; +; ³ ENDIF ;AN000; +; ENDDO ;AN000; +; IF Share flag set THEN ;AN000; +; DO ;AN000; +; IF SHARE .NOT. loaded THEN ;AN000; +; issue warning msg: "SHARE not loaded" using msg retriever ;AN000; +; END ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: Successful auto-attachments in effect ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure AUTO_ATTACH,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + TEST IFSFUNC_FLAGS,NO_IFS_DRIVERS ;AN000; + JZ AA_05 ;AN000; + JMP AA_1000 ;AN000; + ;AN000; +AA_05: ;AN000; + SaveReg ; preserve ds - psp,es di storage ;AN000; + ifsr_fcn_def ATTSTART ;AN000; + MOV CS:IFSPROC_FLAGS,THISIFS_SET+IsInit ; set this so that cds_to_cd doesn't ;AC010; + ; set thisifs ;AN000; + ;AN000; + MOV AH,Get_In_Vars ; Get ptr to ifs hdr chain ;AN000; + INT 21h ; es:bx -> sysinitvars ;AN000; + LES DI,ES:[BX.SYSI_IFS] ; es:di -> 1st ifs driver ;AN000; + ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ; get addressability to dosgroup ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; + ;AN000; + MOV CL,[CDSCount] ; prep cds loop ;AN000; + XOR CH,CH ;AN000; + MOV DX,SIZE CURDIR_LIST ;AN000; + LDS SI,[CDSAddr] ; ds:si -> CDS list ;AN000; +ASSUME DS:NOTHING ;AN000; + ;AN000; +AA_10: ; ** Loop here on cds entries ;AN000; + + TEST DS:[SI.CURDIR_FLAGS],CURDIR_INUSE ; check for ifs-able drive ;AN000; + JZ AA_13 ;AN000; + JMP AA_120 ; cds already inuse, try next cds ;AN000; +AA_13: ;AN000; + CMP WORD PTR DS:[SI.CURDIR_DEVPTR],0 ;AN000; + JNZ AA_16 ;AN000; + CMP WORD PTR DS:[SI.CURDIR_DEVPTR+2],0 ;AN000; + JNZ AA_16 ;AN000; + JMP AA_120 ; cds not real, try next cds ;AN000; +AA_16: ;AN000; + MOV AX,SI ; attempt ;AN000; + SaveReg ; cds seg, offset ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ; get dosgroup in ds to access cdsaddr ;AN000; + INT 2FH ;AN000; +ASSUME DS:DOSGROUP ;AN000; + RestoreReg ; cds offset ;AN000; + SUB AX,WORD PTR [CDSADDR] ; get drive # (0-based) in al ;AN000; + MOV BL,SIZE CurDir_list ;AN000; + DIV BL ;AN000; + RestoreReg ; cds segment ;AN000; + SaveReg ; drive # (0-based 0=A) ;AN000; + MOV BL,AL ;AN000; + INC BL ; change to 1-based (1=A) ;AN000; + MOV AX,CHECK_REMOVABLE ; 4408H (device ioctl) ;AN000; + INT 21H ;AN000; + OR AX,AX ; ax 0 - drive removable ;AN000; + RestoreReg ; drive # (0-based) ;AN000; + JNZ AA_19 ;AN000; + JMP AA_120 ; drive removable, don't auto-attach ;AN000; + ;AN000; +AA_19: ; cds ok, proceed with autoattach ;AN000; + CBW ; convert al to word (ax) ;AN000; + MOV BL,10 ;AN000; + DIV BL ; convert number (ex.14) to char ;AN000; + ADD AX,3030H ; (3134) (ah-remain,al-quot) ;AN000; + ;AN000; + SaveReg ; Save 1st ifs driver ;AN000; + MOV CS:WORD PTR [THISIFS],DI ; Send attach start request ;AN000; + MOV CS:WORD PTR [THISIFS+2],ES ; to all fs drivers. Stop when ;AN000; + ; one clicks. ;AN000; +AA_20: ;AN000; + SaveReg ; ifs ptr, cds count-size-ptr ;AN000; + ;AN000; + SaveReg ; get ES -> dosgroup (save char drv#) ;AN000; + MOV AX,(multDOS SHL 8) OR 3 ;AN000; + INT 2FH ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; +ASSUME DS:DOSGROUP,ES:DOSGROUP ;AN000; + ; do attach w/dummy cds so as not ;AN000; + MOV DI,OFFSET DOSGROUP:DummyCDS ; to ruin valid cds ;AN000; + RestoreReg ;AN000; +ASSUME DS:NOTHING ;AN000; + PUSH DI ;AN000; + MOV CX,SIZE curdir_list ;AN000; + REP MOVSB ;AN000; + PUSH ES ;AN000; + POP DS ;AN000; + POP SI ; DS:SI -> dummy CDS ;AN000; + MOV [SI.curdir_flags],curdir_isifs + curdir_inuse ;AN000; + MOV [SI.curdir_type],type_drive ;AN000; + MOV AX,WORD PTR CS:[THISIFS] ;AN000; + MOV WORD PTR [SI.CURDIR_IFS_HDR],AX ;AN000; + MOV AX,WORD PTR CS:[THISIFS+2] ;AN000; + MOV WORD PTR [SI.CURDIR_IFS_HDR+2],AX ;AN000; + RestoreReg ; char drive # ;AN000; + SaveReg ; dummy cds ptr ;AN000; + ;AN000; + invoke PREP_IFSR ; sets es:bx -> ifsr, 0s fields, ;AN000; + ; ds - ifsseg ;AN000; + MOV DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ; sets ifsr_device_cb@ ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTSTART ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSATTSTART ;AN000; + MOV ES:[BX.IFSR_TYPE],TYPE_DRIVE ;AN000; + ;AN000; + MOV SI,OFFSET AA_PARMS_BUF ; set up attach parameter buffer ;AN000; + MOV WORD PTR DS:[SI],1 ; in tempbuf = dw 1 ;AN000; + MOV WORD PTR DS:[SI+2],AX ; db 3134,0 ;AN000; + XOR AL,AL ;AN000; + MOV BYTE PTR DS:[SI+4],AL ; asciiz ;AN000; + MOV WORD PTR ES:[BX.IFSR_PARMS@],SI ;AN000; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DS ;AN000; + ;AN000; +AA_40: ; ** Loop here on ifs drivers ;AN000; + invoke CALL_IFS ; call ifs driver w/attach start req ;AN000; + ;AN000; + JC AA_60 ; jmp on no click ;AN000; + ; click: ;AN000; + RestoreReg ; restore cds ptr to es:di ;AN000; + invoke CD_TO_CDS ; update cds entry ;AN000; + SaveReg ; move dummy cds ptr back to ds:si ;AN000; + RestoreReg ;AN000; + MOV SI,DI ; ds:si -> dummy cds ;AN000; + RestoreReg ; es:di -> real cds ;AN000; + MOV CX,SIZE CURDIR_LIST ; copy dummy into real - ok to ;AN000; + SaveReg ;AN000; + OR DS:[SI.CURDIR_FLAGS],CURDIR_ISIFS ; set this cds as ifs ;AN009; + REP MOVSB ; clobber now ;AN000; + RestoreReg ; move real cds ptr back to ds:si ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + RestoreReg ; restore cds size, count, ;AN000; + ; ifs ptr ;AN000; + TEST CS:IFSPROC_FLAGS,ISSHARE ; check if share checked ;AN000; + JNZ AA_100 ; go process next cds ;AN000; + TEST ES:[DI.IFS_ATTRIBUTE],IFSUSESHARE ;AN000; + JZ AA_100 ; ifs driver needs share ;AN000; +;; D526 CallInstall SHAREInstall,multSHARE,0 ; check that share loaded ;AN000; + CallInstall SHAREInstall,multSHARE,40H ; check that share loaded ;AN013; + CMP AL,INSTALLED ; if not generate warning ;AN000; + JE AA_50 ;AN000; + SaveReg ;AN000; + MOV AX,COMMON_ERR_3 ; "SHARE not installed" ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + MOV SI,OFFSET S_SIZE2 ;AN000; + MOV CX,1 ;AN000; + MOV DH,UTILITY_MSG_CLASS ;AN000; + MOV BX,STDERR ;AN000; + XOR DL,DL ;AN000; + CALL SYSDISPMSG ;AN000; + RestoreReg ;AN000; + ;AN000; +AA_50: ;AN000; + OR CS:IFSPROC_FLAGS,ISSHARE ; set this so won't check share again ;AN000; + JMP AA_100 ;AN000; + ;AN000; +AA_60: ; ** Next driver ;AN000; + RestoreReg ; dummy cds ptr ;AN000; + RestoreReg ; restore: ifs and cds ptrs, ;AN000; + ; cds count and size ;AN000; + LES DI,ES:[DI.IFS_NEXT] ; check next fs driver ;AN000; + CMP DI,NULL_PTR ; if ptr null, end of ifs drivers ;AN000; + JNE AA_80 ;AN000; + PUSH AX ; dummy cds offset ;AN000; + MOV AX,ES ;AN000; + CMP AX,NULL_PTR ;AN000; + POP AX ; dummy cds offset ;AN000; + JE AA_100 ; go process next cds if no more ifs ;AN000; +AA_80: ;AN000; + MOV CS:WORD PTR [THISIFS],DI ; prep next ifs driver ;AN000; + MOV CS:WORD PTR [THISIFS+2],ES ;AN000; + SaveReg ; Save regs ;AN000; + SaveReg ; dummy cds ptr ;AN000; + SaveReg ; get esdi back to ifsrh ;AN008; + RestoreReg ; and ds-ifsseg ;AN008; + MOV BX,OFFSET IFSR ;AN008; + XOR AX,AX ;AN008; + MOV ES:[BX.IFSR_RETCODE],AX ; restore error fields ;AN008; + MOV ES:[BX.IFSR_RETCLASS],AL ;AN008; + JMP AA_40 ; go process next ifs driver ;AN000; + ;AN000; +AA_100: ;AN000; + RestoreReg ; restore 1st ifs driver ;AN000; +AA_120: ;AN000; + ADD SI,DX ; ** Next CDS ;AN000; + DEC CX ;AN000; + JZ AA_990 ;AC004; + JMP AA_10 ;AN000; + ;AN000; + ;AN000; +AA_990: ;AC004; + RestoreReg ; restore ds - psp,esdi - storage ;AN000; +AA_1000: ;AN004; + AND CS:IFSPROC_FLAGS,NOT IsInit ; reset isinit ;AN010; + return ;AN000; + ;AN000; +EndProc AUTO_ATTACH ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CHECK_UNC_PRESENCE ;AN000; +; ;AN000; +; Called by: init - general ;AN000; +; ;AN000; +; Routines called: SYSDISPMSG ;AN000; +; ;AN000; +; Inputs: ;AN000; +; None ;AN000; +; ;AN000; +; Function: ;AN000; +; Get pointer to 1st IFS header ;AN000; +; IF no file systems THEN ;AN000; +; Display warning ;AN000; +; ELSE DO ;AN000; +; BX=0 +; WHILE pointer .NOT. 0FFFFH ;AN000; +; DO ;AN000; +; OR BX,IFS_ATTRIBUTES +; IF file system driver has unc bit set THEN ;AN000; +; DO ;AN000; +; Set unc_installed flag in IFSFUNC_FLAGS ;AN000; +; Set UNC_FS_HDR = unc file system driver header ;AN000; +; Set unc_found ;AN000; +; ENDDO ;AN000; +; ENDDO ;AN000; +; ENDWHILE ;AN000; +; IF unc not found THEN ;AN000; +; Set UNC_FS_HDR = null ptr ;AN000; +; ENDIF ;AN000; +; IFS_ATTRS=BX +; ENDDO ;AN000; +; ENDIF ;AN000; +; ;AN000; +; Outputs: unc_installed flag set in ifsfunc_flags in unc present ;AN000; +; IFS_ATTRS set +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure CHECK_UNC_PRESENCE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; preserve ds - psp,es di storage ;AN000; + MOV AH,Get_In_Vars ; Get ptr to ifs hdr chain ;AN000; + INT 21h ; es:bx -> sysinitvars ;AN000; + LES DI,ES:[BX.SYSI_IFS] ; es:di -> 1st ifs driver ;AN000; + XOR BX,BX ;AN000; + CMP DI,NULL_PTR ; if 1st null, then no drivers ;AN000; + JNE CUP_20 ; must display no driver msg ;AN000; + MOV AX,ES ;AN000; + CMP AX,NULL_PTR ;AN000; + JNE CUP_20 ;AN000; + ;AN000; + MOV AX,UTIL_ERR_4 ; def 4 "No IFS drivers found",CR,LF ;AN000; + MOV BX,STDERR ;AN000; + XOR CX,CX ;AN000; + MOV DL,NO_INPUT ;AN000; + MOV DH,UTILITY_MSG_CLASS ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + CALL SYSDISPMSG ;AN000; + MOV CS:IFSFUNC_FLAGS,NO_IFS_DRIVERS ;AN000; + ;AN000; + JMP SHORT CUP_1000 ;AN000; + ;AN000; +CUP_20: ;AN000; + OR BX,ES:[DI.IFS_ATTRIBUTE] + TEST ES:[DI.IFS_ATTRIBUTE],IFSUNC ; now set UNC_FS_HDR ;AN000; + JNZ CUP_40 ;AN000; +CUP_30: + LES DI,ES:[DI.IFS_NEXT] ;AN000; + CMP DI,NULL_PTR ;AN000; + JNE CUP_20 ;AN000; + MOV AX,ES ;AN000; + CMP AX,NULL_PTR ;AN000; + JNE CUP_20 ;AN000; + TEST IFSFUNC_FLAGS,UNC_INSTALLED + JNZ CUP_1000 + MOV WORD PTR [UNC_FS_HDR],NULL_PTR ; no unc - set unc ptr null ;AN000; + MOV WORD PTR [UNC_FS_HDR+2],NULL_PTR ;AN000; + JMP SHORT CUP_1000 ;AN000; + ;AN000; +CUP_40: ; found unc - set unc ptr ;AN000; + MOV WORD PTR [UNC_FS_HDR],DI ; and unc flag ;AN000; + MOV WORD PTR [UNC_FS_HDR+2],ES ;AN000; + OR IFSFUNC_FLAGS,UNC_INSTALLED ;AN000; + JMP SHORT CUP_30 ;AN000; + ;AN000; + ;AN000; +CUP_1000: ;AN000; + RestoreReg ; restore ds - psp,esdi - storage ;AN000; + return ;AN000; + +include msgdcl.inc + ;AN000; +EndProc CHECK_UNC_PRESENCE ;AN000; + ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +STACK SEGMENT STACK ;AN000; +DB 278 + 128 DUP (?) ; 278 == IBM's ROM requirements ;AN000; +STACK ENDS ;AN000; + ;AN000; +END IFSFUNCinit ;AN000; +END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSPARSE.INC b/v4.0/src/CMD/IFSFUNC/IFSPARSE.INC new file mode 100644 index 0000000..d986ca9 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSPARSE.INC @@ -0,0 +1,92 @@ +;****************************************************************************** ;AN000; +; IFSFUNC Parse Symbol File ;AN000; +; ;AN000; +; Parsing: NAMES = n ;;;alias[n | (n {m})] ;AN000; +; ;AN000; +; Modification history: ;AN000; +; Created: May 30 1987 ;AN000; +; ;AN000; +; LOD - 35 ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; +IFSF_PARMS LABEL WORD ; IFSFUNC parms input block ;AN000; + DW IFSF_PARMSX ; offset of ifsfunc parms extension block ;AN000; + DB 0 ; No extra delimeters or eol chars ;AN000; + ;AN000; +IFSF_PARMSX LABEL BYTE ; IFSFUNC parm extension block ;AN000; + DB 0,0,0 ; 0 positionals, 0 switches ;AN000; + DB 1 ; 1 keyword (NAMES=) ;AN000; + DW IFSF_K1 ;AN000; + ;AN000; +IFSF_K1 LABEL WORD ; IFSFUNC 1 keyword ;AN000; + DW 8001h ; Numeric/optional(NAMES= ok) ;AN000; + DW 0 ; no function ;AN000; + DW IFSF_RESULT ; Result buffer ;AN000; + DW IFSF_K1_VAL ; value list ;AN000; + DB 1 ; 1 keyword ;AN000; + DB "NAMES=",0 ;AN000; + ;AN000; +IFSF_K1_VAL LABEL BYTE ; value definition ;AN000; + DB 1 ; # value defns: get one: n or (n,m) ;AN000; + DB 1 ; # ranges ;AN000; + DB "N" ; value to return if n in range ;AN000; + DD 0,255 ; range ;AN000; + ;AN000; + ;AN000; +;;;alias Complex control blocks ;AN000; +; ;AN000; +; IFSF_COMPLEX_PARMS LABEL WORD ;AN000; +; DW IFSF_COMPLEX_PARMSX ;AN000; +; DB 0 ; No extra delimeters or eol chars ;AN000; +; ;AN000; +; IFSF_COMPLEX_PARMSX LABEL BYTE ; ;AN000; +; DB 1,2 ; Min 1, Max 2 positionals ;AN000; +; DW IFSF_COMPLEX_POS1 ;AN000; +; DW IFSF_COMPLEX_POS2 ;AN000; +; DB 0,0 ; 0 switches, 0 keywords ;AN000; +; ;AN000; +; IFSF_COMPLEX_POS1 LABEL WORD ; ;AN000; +; DW 8001h ; N - optional ;AN000; +; DW 0 ; no function ;AN000; +; DW IFSF_RESULT ; Result buffer ;AN000; +; DW IFSF_POS_VAL ; value list ;AN000; +; DB 0 ; no switches/keywords ;AN000; +; ;AN000; +; IFSF_COMPLEX_POS2 LABEL WORD ; ;AN000; +; DW 8001H ; Numeric value, optional ;AN000; +; DW 0 ; no function ;AN000; +; DW IFSF_RESULT ; Result value buffer ;AN000; +; DW IFSF_POS_VAL ; value list ;AN000; +;;;alias DB 0 ; no switches/keywords ;AN000; +; ;AN000; +;FSF_POS_VAL LABEL BYTE ; value definition ;AN000; +; DB 2 ; N and M ;AN000; +; DB 2 ; 2 ranges ;AN000; +; DB "N" ; item tag for N ;AN000; +; DD 0,255 ; range of N ;AN000; +; DB "M" ; item tag for M ;AN000; +;;;aliasDD 0,8160 ; range of M ;AN000; + ;AN000; +IFSF_RESULT LABEL BYTE ;AN000; + DB ? ; type - 1=number, 4=complex ;AN000; +IFSF_TAG DB ? ; item tag returned: N,M or FF ;AN000; + DW ? ;AN000; +IFSF_NM DB ? ; actual n or m value ;AN000; + DB ? ;AN000; + DB ? ;AN000; + DB ? ;AN000; + ;AN000; + ;AN000; +; parser assemble switches ;AN000; +DateSW equ 0 ;AN000; +TimeSW equ 0 ;AN000; +FileSW equ 0 ;AN000; +CAPSW equ 0 ;AN000; +DrvSW equ 0 ;AN000; +QusSW equ 0 ;AN000; +SwSW equ 0 ;AN000; +Val3SW equ 0 ;AN000; + ;AN000; + ;AN000; + include PARSE.ASM ;together with PSDATA.INC ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSSESS.ASM b/v4.0/src/CMD/IFSFUNC/IFSSESS.ASM new file mode 100644 index 0000000..8eba357 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSSESS.ASM @@ -0,0 +1,2187 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifssess.asm 1.0 87/05/11 ;AN000; +TITLE IFSFUNC SESSION ROUTINES - IFS Attach Routines ;AN000; +NAME IFSSESS ;AN000; +;************************************************************************************ +; +; IFSSESS +; +; Session related IFS calls (Session = attachment) +; +; IFS_ASSOPER +; RETURN_ASSIGN_MODE +; SET_ASSIGN_MODE +; GET_IFSFUNC_ITEM +; ATTACH_START +; ATTACH_END +; IFS_RESET_ENVIRONMENT +; IFS_ABORT +; GET_IFS_DRIVER_NAME +; FIND_IFS_DRIVER +; AssignOn/AssignOff +; PrintOn/PrintOff +; GET_UNC_ITEM_INFO +; +; REVISION HISTORY: +; A000 Original version 4.00 May 1987 +; A001 DCR 158 - merge unc info in attach start/status requests 8/87 RGAZZIA +; A002 DCR 187 - ctrl req renumber, make attach type byte 8/87 RGAZZIA +; A003 DCR 188 - design correction of Get IFSFUNC Item 8/87 RGAZZIA +; A004 PTM 764 - Printer attach problems 8/87 RGAZZIA +; A005 DCR 213 - SFT Serial Number 9/87 RGazzia +; A006 PTM 849 - Printer open problems 9/87 RGazzia +; A007 P242 - IFSFUNC hangs on 2nd install. 8/87 rg +; A008 P1244- Net Print problems 8/87 rg +; A009 P1411- Net Use erroneous pause 10/87 rg +; A010 P2270- Filesys network drive problems 11/87 RG +; A011 P2312- Allow Net Use status to show FILESYSed network devices 11/87 RG +; Do this via user word: 0001 without password +; 8001 with password +; A012 P2307- Critical error problems 11/87 RG +; A013 P2379- Filesys status fails without network installed 11/87 RGazzia +; A014 P2952- dfl problem 1/88 RG +; A015 P3251- net trans problem (library.exe) 1/88 RG +; A016 P3334- new abort subfunc - reset environment 2/88 RMG +; A017 P3673- Filesys problems again. A010 not fixed right....3/14/88 RMG +; A018 Austin deviceless attach problems 3/29/88 RMG +; A019 P4188- names=0 problems 4/08/88 RMG +; A020 Austin garbage attach problem 4/11/88 RMG +; A021 P4140 dos ext err msgs enhancement 4/19/88 RMG +; A022 P4249 filesys problems related to gii bx ret on user stack 4/21/88 RMG +; A023 P4540 fAssign,fPrint out of swappable area 4/28/88 RMG +; A024 P4731 find ifs driver must check for none 5/4/88 RMG +; A025 P4839 ctrl ptrsc problems 5/13/88 RMG +; A026 P4789 message problems w/no ifs drivers loaded 5/18/88 RMG +; A027 P4791 Don't overwrite ax on error 5/19/88 RMG +; A028 Error code problems w/no ifs drivers 5/20/88 RMG +; A029 GII error path fixup 5/24/88 RMG +; A030 P5005 Print stream problems 6/1/88 RMG +; +; LOC - 871 +; LOD - 63 +; +;************************************************************************************ + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; ;AN000; +; NOTE: We cannot include DOSSEG here because the START seg is not declared ;AN000; +; as PARA aligned in DOSSEG. ;AN000; +; ;AN000; + ;AN000; +START SEGMENT PARA PUBLIC 'START' ;AN000; +START ENDS ;AN000; + ;AN000; +CONSTANTS SEGMENT WORD PUBLIC 'CONST' ;AN000; +CONSTANTS ENDS ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; +DATA ENDS ;AN000; + ;AN000; +TABLE SEGMENT BYTE PUBLIC 'TABLE' ;AN000; +TABLE ENDS ;AN000; + ;AN000; +CODE SEGMENT BYTE PUBLIC 'CODE' ;AN000; +CODE ENDS ;AN000; + ;AN000; +LAST SEGMENT PARA PUBLIC 'LAST' ;AN000; +LAST ENDS ;AN000; + ;AN000; +DOSGROUP GROUP START,CONSTANTS,DATA,TABLE,CODE,LAST ;AN000; + ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ;DOSGROUP Data ;AN000; + Extrn CurrentPDB:WORD ;AN000; + Extrn THISCDS:DWORD ;AN000; + Extrn CDSAddr:DWORD ;AN000; + Extrn CDSCount:BYTE ;AN000; + Extrn MYNAME:BYTE ;AN000; + Extrn DummyCDS:BYTE ;AN000; + Extrn sftFCB:DWORD ;AN000; + Extrn THISSFT:DWORD ;AN000; + Extrn SysInitTable:BYTE ;AN000; + Extrn EXIT_TYPE:BYTE ;AN000; + Extrn IFS_HEADER:DWORD ;AN000; +if debug ;AN000; + Extrn BugLev:WORD ;AN000; + Extrn BugTyp:WORD ;AN000; + include bugtyp.asm ;AN000; +endif ;AN000; +DATA ENDS ;AN000; + ;AN000; + ;AN000; +; define our own code segment ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data - external ;AN000; + Extrn TEMPBUF:BYTE ;AN000; + ;AN000; + ;IFS Data - public - *** IFSFUNC SWAPPABLE DATA AREA *** ;AN000; + ;AN000; +PUBLIC IFSF_SWAP_START ;AN000; +IFSF_SWAP_START LABEL BYTE ;AN000; + ;AN000; + PUBLIC THISIFS ;AN000; +THISIFS DD -1 ;AN000; + + PUBLIC THISDFL ;AN000; +THISDFL DD -1 ;AN000; + + PUBLIC IFSR ;AN000; +IFSR DB 72 DUP (0) ;AN000; + + PUBLIC SFF1 ;AN000; +SFF1 DB 62 DUP (0) ;AN000; + + PUBLIC CD1 ;AN000; +CD1 DW 84 DUP (0) ;AN000; + + PUBLIC DF1 ;AN000; +DF1 DW 18 DUP (0) ;AN000; + + PUBLIC IFSPROC_FLAGS ;AN000; +IFSPROC_FLAGS DW 0 ;AN000; + +; Number of net drive (0=A) for use on net I 24 ;AN000; + PUBLIC IFSDRV ;AN000; +IFSDRV DB -1 ;AN000; + + PUBLIC DEVICE_CB@_OFFSET ;AN000; +; This used to set offset of ifsr_device_cb@ in common routine cds_to_cd ;AN000; +; in ifsutil. If not used, offset always 1EH since that's what it is at ;AN000; +; ifsutil assembly time. This not good for control fcns (attstart,attstat). ;AN000; +DEVICE_CB@_OFFSET DW 0 ; offset in ifsrh of device cb@ ;AN000; + + PUBLIC SAVE_CB@ ;AN000; +; This used by SFT_TO_SFF and SFF_TO_SFT routines in IFSUTIL to save cds ptr. ;AN000; +SAVE_CB@ DD -1 ;AN000; + + PUBLIC IFSSEM ;AN021; +; This used as byte of semaphores. ;AN021; +IFSSEM DB 0 ;AN021; + +IFSF_SWAP_END LABEL BYTE ;AN000; +PUBLIC IFSF_SWAP_END ;AN000; + ;AN000; + ;IFS Data - public ;AN000; + ;AN000; + PUBLIC DFLAddr ;AN000; +DFLAddr DD -1 ;AN000; + + PUBLIC DFLCount ;AN000; +DFLCount DB 0 ;AN000; + +;;;aliasPUBLIC NLAddr ;AN000; +;;;aliasNLAddr DD -1 ;AN000; + +;;;aliasPUBLIC NLSIZE ;AN000; +;;;aliasNLSIZE DW 0 ;AN000; + + PUBLIC CDSAlt ;AN000; +CDSAlt DD -1 ;AN000; + + PUBLIC UNC_FS_HDR ;AN000; +UNC_FS_HDR DD -1 ;AN000; + + PUBLIC IFSFUNC_FLAGS ;AN000; +IFSFUNC_FLAGS DW 0 ;AN000; + + PUBLIC IFS_ATTRS ;AN000; +IFS_ATTRS DW 0 ; all ifs_attribute words from ifs ;AN000; + ; headers or'ed together (ifsinit) ;AN000; + PUBLIC DOSCALL@ ;AN000; +DOSCALL@ DD 0 ; IFS_DOSCALL@ set by ibmbio ;AN000; + + PUBLIC SFT_SERIAL_NUMBER ;AN005; +SFT_SERIAL_NUMBER DW 0 ; to get sfts unique for fcb reasons ;AN005; + + PUBLIC fAssign ;AC023; +fAssign DB -1 ;AC023; + + PUBLIC fPrint ;AC023; +fPrint DB -1 ;AC023; + + PUBLIC TRUNCATE_FLAG ;AC030;moved out of swap +TRUNCATE_FLAG DB 0 ;AC030; " " + + + ;IFS Data - local ;AN000; + ;AN000; +;SetBP DB 0 ; flag indicates whether to return ;AD003; + ; LSN on getuncitem call (GII) ;AN000; +;ERROR_STATUS DW 1 ; Status returned on error return ;AD029; +ERROR_STATUS DB "ERROR",0 ; from fs (GII) ;AC029; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +copyright db " IFSFUNC.EXE " ;AN000; +INCLUDE copyrigh.inc + +;************************************************************************************ ;AN000; +; ;AN000; +; IFS_ASSOPER ;AN000; +; ;AN000; +; Called by: IFSFUNC dispatcher ;AN000; +; ;AN000; +; Routines called: ;AN000; +; RETURN_ASSIGN_MODE ;AN000; +; SET_ASSIGN_MODE ;AN000; +; GET_IFSFUNC_ITEM ;AN000; +; ATTACH_START ;AN000; +; ATTACH_END ;AN000; +; ;AN000; +; Inputs: ;AN000; +; AL = 00 get / 01 set - redir assign mode (Return/Set Mode) ;AN000; +; AL = 02 get attach list entry (Get ifsfunc item) ;AN000; +; AL = 03 Define Macro (attach start) ;AN000; +; AL = 04 Cancel Attach (attach end) ;AN000; +; AL = 05 Revised get assign list entry (Getifsfuncitem2) ;AN000; +; AL = 06 Get IFSFUNC Item (Getifsfuncitem3) ;AN003; +; Function: ;AN000; +; IF AL=0 call RETURN_ASSIGN_MODE ;AN000; +; ELSE IF AL=1 call SET_ASSIGN_MODE ;AN000; +; ELSE IF AL=2 call GET_IFSFUNC_ITEM ;AN000; +; ELSE IF AL=3 call ATTACH_START ;AN000; +; ELSE IF AL=4 call ATTACH_END ;AN000; +; ;AN000; +; Outputs: ;AN000; +; see subroutines ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +AO_TABLE LABEL WORD ;AN000; + DW RETURN_ASSIGN_MODE ;AN000; + DW SET_ASSIGN_MODE ;AN000; + DW GET_IFSFUNC_ITEM ;AN000; + DW ATTACH_START ;AN000; + DW ATTACH_END ;AN000; + DW GET_IFSFUNC_ITEM2 ;AN000; + DW GET_IFSFUNC_ITEM3 ;AN003; + ;AN000; + Procedure IFS_ASSOPER,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + TEST CS:IFSFUNC_FLAGS,no_ifs_drivers + JZ AO_20 +AO_10: + MOV AX,error_not_supported + transfer ifs_980 +AO_20: + CMP AL,0 + JNE AO_40 + CMP AL,1 + JNE AO_40 + TEST CS:IFSFUNC_FLAGS,unc_installed + JZ AO_10 +AO_40: + MOV CS:IFSPROC_FLAGS,ZERO ;AN000; + PUSH BX ; save macro type ;AN000; + XOR AH,AH ;AN000; + SHL AL,1 ; AL x 2 ;AN000; + MOV BX,AX ;AN000; + JMP CS:AO_TABLE[BX] ;AN000; + ;AN000; +EndProc IFS_ASSOPER ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; RETURN_ASSIGN_MODE ;AN000; +; ;AN000; +; Called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: DOS: Get_User_Stack ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BL = macro type ;AN000; +; Function: ;AN000; +; If macro type = 3 (network printer) THEN ;AN000; +; BX = fPrint .AND. 1 ;AN000; +; Elseif macro type = 4 (network disk) THEN ;AN000; +; BX = fAssign .AND. 1 ;AN000; +; Else set error_invalid_function ;AN000; +; ;AN000; +; Output: ;AN000; +; IF AL==0 BX value on user stack ;AN000; +; ;AN000; +; Notes: This routine is used only for UNC file system. This is the ;AN000; +; only FS that supports pause. ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure RETURN_ASSIGN_MODE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + POP BX ; macro type ;AN000; + CMP BL,3 ; if (type == drive) ;AN000; + JZ GAM_20 ;AN000; + CMP BL,4 ;AN000; + JNZ GAM_60 ;AN000; + MOV BH,fAssign ; t = fAssign; ;AN000; + JMP Short GAM_40 ; else ;AN000; + ;AN000; +GAM_20: ; if (type == print) ;AN000; + MOV BH,fPrint ; t = fPrint; ;AN000; +GAM_40: ;AN000; + AND BH,1 ; return t&1; ;AN000; + CallInstall Get_User_Stack,multDOS,24 ;AN000; + MOV [SI].User_BX,BX ;AN000; + transfer ifs_990 ; go to general good ret in util ;AN000; + ;AN000; +GAM_60: ;AN000; + MOV AL,error_invalid_function ;AN000; + transfer ifs_980 ; go to general bad ret in util ;AN000; + ;AN000; + ;AN000; +EndProc RETURN_ASSIGN_MODE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SET_ASSIGN_MODE ;AN000; +; ;AN000; +; Called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BL = macro type ;AN000; +; BH = assign mode (0 = off - pause, 1 = on - no pause) ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Output: ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure SET_ASSIGN_MODE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + POP BX ; restore macro type (3 or 4) ;AN000; + ;AN000; + CMP BL,3 ; check if printer or drive ;AN000; + JNZ SAM_40 ; ;AN000; + OR BH,BH ; printer - check mode ;AN000; + JZ SAM_20 ; off - go pause ;AN000; + CMP BH,1 ;AN000; + JNZ SAM_80 ; jump on parm error ;AN000; + CALL PrintOn ; turn print on ;AN000; + transfer ifs_990 ; go to general good ret in util ;AN000; + ;AN000; +SAM_20: ; print off - pause ;AN000; + CALL PrintOff ;AN000; + transfer ifs_990 ; go to general good ret in util ;AN000; + ;AN000; +SAM_40: ; Drive ;AN000; + CMP BL,4 ;AN000; + JNZ SAM_80 ; jump on parm error ;AN000; + OR BH,BH ;AN000; + JZ SAM_60 ;AN000; + CMP BH,1 ;AN000; + JNZ SAM_80 ; jump on parm error ;AN000; + CALL AssignOn ; drive on ;AN000; + transfer ifs_990 ; go to general good ret in util ;AN000; + ;AN000; +SAM_60: ; drive off ;AN000; + invoke AssignOff ; turn drives off (pause) ;AN000; + transfer ifs_990 ; go to general good ret in util ;AN000; + ;AN000; + ;AN000; +SAM_80: ;AN000; + MOV AX,error_invalid_parameter ;AN000; + invoke SET_EXTERR_INFO ;AN000; + transfer ifs_980 ; go to general bad ret in util ;AN000; + ;AN000; + ;AN000; +EndProc SET_ASSIGN_MODE ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; GET_IFSFUNC_ITEM ;AN000; +; ;AN000; +; Called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: ;AN000; +; GET_IFS_DRIVER_NAME DOS: STRCPY ;AN000; +; CDS_TO_CD GET_USER_STACK ;AN000; +; DFL_TO_DF ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BL = redirection index ;AN000; +; DS:SI -> Device name buffer ;AN000; +; ES:DI -> Target buffer: old - net path string ;AN000; +; new - dw file system driver name +; dw # parms +; db parms +; Function: ;AN000; +; STRUCTURE = 1st CDS ;AN000; +; INDEX = 0 ;AN000; +; WHILE CDS structures ;AN000; +; DO ;AN000; +; IF curdir_isIFS TRUE THEN ;AN000; +; DO ;AN000; +; IF INDEX = BL THEN ;AN000; +; DO ;AN000; +; DS:SI = Letter version of Index (0=A:, 1=B:, ...) ;AN000; +; IF IFS .NOT. UNC THEN ;AN000; +; DO ;AN000; +; ES:[DI] = IFS name (retrieved from CURDIR_IFSR_HDR) ;AN000; +; Send ATTACH_STAT request to IFS for parms ;AN000; +; ES:DI+2 = IFS parms ;AN000; +; FOUND = true ;AN000; +; TYPE = 2 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Send ATTACH_STAT request to REDIR.SYS for parms ;AN000; +; Move parms into one buffer and point with ES:DI ;AN000; +; FOUND = true ;AN000; +; TYPE = 4 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; IF IFS UNC THEN ;AN000; +; DO ;AN000; +; INDEX=INDEX+1 ;AN000; +; IF INDEX = BL THEN ;AN000; +; DO ;AN000; +; DS:SI = Letter version of Index (0=A:, 1=B:, ;AN000; +; ES:DI = "REDIR" ;AN000; +; FOUND = true ;AN000; +; TYPE = 2 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Get next CDS structure ;AN000; +; ENDDO ;AN000; +; ENDWHILE ;AN000; +; IF FOUND = false THEN ;AN000; +; DO ;AN000; +; STRUCTURE = 1st DFL ;AN000; +; WHILE DFL structures ;AN000; +; DO ;AN000; +; IF INDEX = BL THEN ;AN000; +; DO ;AN000; +; DS:SI = name pointed to by DFLL_NAME_PTR ;AN000; +; IF IFS .NOT. UNC THEN ;AN000; +; DO ;AN000; +; ES:[DI] = IFS name (retrieved from DFLL_IFSR_HDR) ;AN000; +; Send ATTACH_STAT request to IFS for parms ;AN000; +; ES:DI+2 = IFS parms ;AN000; +; FOUND = true ;AN000; +; TYPE = 1 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Send ATTACH_STAT request to REDIR.SYS for parms ;AN000; +; Move parms into one buffer and point with ES:DI ;AN000; +; FOUND = true ;AN000; +; TYPE = 3 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; IF IFS UNC THEN ;AN000; +; DO ;AN000; +; INDEX=INDEX+1 ;AN000; +; IF INDEX = BL THEN ;AN000; +; DO ;AN000; +; ES:DI = "REDIR" ;AN000; +; FOUND = true ;AN000; +; TYPE = 3 ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Get next DFL structure ;AN000; +; ENDWHILE ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; IF FOUND = FALSE THEN ;AN000; +; DO ;AN000; +; Set carry ;AN000; +; AX = 18 ;AN000; +; ENDDO ;AN000; +; ELSE Clear carry ;AN000; +; ENDIF ;AN000; +; +; IFSRH for Attach Start: +; * IFSR_LENGTH DW 32 ; Request length +; * IFSR_FUNCTION DB 3 ; Attach Start +; + IFSR_RETCODE DW 0 +; + IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; + IFSR_TYPE DB ? ; BL (1,2,3,or 4) +; IFSR_RESV2 DB ? +; *+ IFSR_PARMS@ DD PARMS ; See below +; *+ IFSR_DEVICE_CB@ DD ? ; CD or DF (See below) +; + IFSR_USER_WORD DW ? +; + IFSR_MAX_XMITT_SIZE DW ? +; + IFSR_NET_NAME_ID DW ? +; + IFSR_LSN DW ? +; + IFSR_DEVICE_STATUS DB ? +; IFSR_RESV3 DB ? +; +; +; +; *+ PARMS LABEL WORD +; DW PARMCOUNT ; Number of parms. (only for new style) +; DB ASCIIZ,...; Parms +; +; ;AN000; +; Outputs: ;AN000; +; No Carry - BH = device status flag ;AN000; +; bit 0=0 is device valid ;AN000; +; 1 if device invalid ;AN000; +; BL = device type ;AN000; +; DS:SI = ASCIIZ local device name ;AN000; +; ES:DI = ASCIIZ network name ;AN000; +; For old style call: +; CX = user word ;AN000; +; DX = max xmitt size +; BP = Low 8 bits has LSN from NCB_LIST if input AL ^=0 +; AX = Net name ID +; +; Carry - AX = Error code ;AN000; +; 18 - end of list ;AN000; +; Regs: ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + USER_WORD DW 0 ; i give in - temp storage + ;AN000; + Procedure GET_IFSFUNC_ITEM ;AC003; +ASSUME DS:NOTHING,ES:NOTHING ;AC003; + ; get_ifsfunc_item and get_ifsfunc_item2 ;AC003; + MOV CS:IFSPROC_FLAGS,ZERO ; are old style - types 3,4 only ;AC003; + JMP SHORT GII_20 ;AC003; + ;AC003; + entry GET_IFSFUNC_ITEM2 ;AC003; + MOV CS:IFSPROC_FLAGS,SetBP ; set this to get lsn ;AC003; + JMP SHORT GII_20 ;AC003; + ;AC003; + entry GET_IFSFUNC_ITEM3 ; new style get ifsfunc item ;AC003; + MOV CS:IFSPROC_FLAGS,Filesys_Status ; gets types 1,2,3,4 ;AC003; + ;AC003; +;----------------------------------------------------------------------------------------;AC003; +; drive loop ;AC003; +;----------------------------------------------------------------------------------------;AC003; + ;AC003; +GII_20: ;AC003; + ifsr_fcn_def ATTSTAT ; define ifsr for attach status ;AC003; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN006; + ;AC003; + POP BX ; index ;AC003; + XOR AX,AX ; ax will be counter through CDSs ;AC003; + SaveReg ; save device/drive name buffer ;AC003; +GII_40: ;AC003; + CMP AL,SS:[CDSCount] ; if run out of CDSs, ;AC003; + JB GII_60 ; go to devices ;AC003; + XOR AL,AL ; reset for dfl count ;AC003; + JMP GII_400 ;AC003; +GII_60: ;AC003; + SaveReg ; save ax-cds count, bx-index ;AC003; + ;AC003; + LDS SI,[CDSAddr] ; Point ds:si to correct CDS entry ;AC003; + CMP [fAssign],ZERO ; if pause in effect, must use ;AC003; + JNZ GII_80 ; alternate cds list ;AC003; + LDS SI,[CDSAlt] ;AC003; + ;AC003; +GII_80: ;AC003; + MOV BL,SIZE CurDir_list ; size in convenient spot ;AC003; + MUL BL ; get net offset ;AC003; + ADD SI,AX ; convert to true pointer ;AC003; + RestoreReg ;AC003; + TEST [SI].curdir_flags,curdir_isnet ; make sure ifs drive ;AC003; + JNZ GII_100 ;AC003; + JMP GII_280 ; next drive ;AC003; +GII_100: ;AC003; + SUB BX,1 ; jae jumps if CF=0, CF=1 when ;AC003; + ; index hit ;AC003; + JB GII_120 ;AC003; + JMP GII_280 ; next drive ;AC003; +GII_120: ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_Status ; check old vs. new style ;AC003; + JNZ GII_140 ;AC003; + CMP [SI.CURDIR_TYPE],TYPE_NET_DRIVE ; old style: check for type 4 ;AC003; + JE GII_140 ;AC003; + JMP GII_280 ; not type 4, go get next one ;AC003; +GII_140: ;AC003; + RestoreReg ; get devname ptr into es:di, ;AC003; + SaveReg ; (push back for end ds:si setup) ;AC003; + SaveReg ; while preserving es:di - target ;AC003; + MOV ES,CX ;AC003; + MOV DI,DX ;AC003; + ADD AL,'A' ; storing d:0 in devname buffer ;AC003; + STOSB ;AC003; + MOV AX,(0 SHL 8) + ':' ;AC003; + STOSW ;AC003; + RestoreReg ; restore target ptr ;AC003; + ;AC003; + MOV BL,[SI.CURDIR_TYPE] ; set bx=type (1,2,3,4) ;AC003; + XOR BH,BH ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_status ; target different for new style ;AC003; + JNZ GII_150 ;AC003; + PUSH [SI.CURDIR_USER_WORD] ;AC003; + POP CS:[USER_WORD] ;AC003; + JMP GII_160 ;AC003; +GII_150: ;AC003; + PUSH DI ; ifs drive; save target offset ;AC003; + MOV DI,ES:[DI] ; es:di -> FS name buffer ;AC003; + OR IFSPROC_FLAGS,ISCDS ; get ifs driver name into target ;AC003; + CALL GET_IFS_DRIVER_NAME ;AC003; + ;AC003; + POP DI ; retrieve target offset from stack ;AC003; + PUSH DI ;AC003; + INC DI ; es:di -> parm buffer ;AC003; + INC DI ;AC003; + ;AC003; +GII_160: ;AC003; + SaveReg ; save target segment, type ;AC003; + ; go to IFS to fill in rest of tgt ;AC003; + invoke PREP_IFSR ; init ifsr ;AC003; + ;AC003; + MOV DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AC003; + invoke CDS_TO_CD ; CDS: sets [THISIFS] ;AC003; + ; ES:BX -> IFSRH ;AC003; + ; IFSR_DEVICE_CB@ ;AC003; + ; ds - IFSSEG ;AC003; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTSTAT ;AC003; + MOV ES:[BX.IFSR_FUNCTION],IFSATTSTAT ;AC003; + POP AX ; type (BX) ;AC003; + MOV ES:[BX.IFSR_TYPE],AL ;AC003; + POP DX ; target segment (ES) ;AC003; + ;AC003; + TEST IFSPROC_FLAGS,Filesys_status ;AC003; + JNZ GII_180 ;AC003; + PUSH CS ;AC003; + POP DS ;AC003; +ASSUME DS:IFSSEG ;AC003; + MOV SI,OFFSET TEMPBUF ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@],SI ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DS ;AC003; + PUSH DI ; push tgt offset here for later pop ;AC003; + JMP GII_200 ;AC003; +GII_180: ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@],DI ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DX ;AC003; +GII_200: ;AC003; + PUSH AX ; push type back (BX) ;AC003; + ;AC003; +;*********************************************************************************************** + invoke CALL_IFS ; call fs with attach status request ;AC003; +;*********************************************************************************************** + ;AC003; + JNC GII_220 ;AC003; + ; attach status error: ;AC003; + RestoreReg ; type,target offset ;AC003; + MOV ES,DX ;AC003; + SaveReg ; put "ERROR" in parms display ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_status ; don't add if net use ;AN029; + JZ GII_210 ;AN029; + ADD DI,2 ;AC003; + MOV AX,1 ;AC003; + STOSW ;AC003; +GII_210: ;AN029; + PUSH CS ;AC003; + POP DS ;AC003; +ASSUME DS:IFSSEG ;AC003; + MOV SI,OFFSET ERROR_STATUS ;AC003; + MOV CX,4 ;AC003; + REP MOVSW ;AC003; + RestoreReg ;AC003;;AC029; + transfer ifs_1000 ; go to general ret in util ;AC003; + ;AC003; +GII_220: ;AC003; + RestoreReg ; device type, target offset ;AC003; + TEST IFSPROC_FLAGS,Filesys_status ;AC003; + JZ GII_240 ;AC003; +;;;;;;;;RestoreReg ; IFS drive - devname ptr ;AC003;;AD022; +; MOV ES,DX ; target ;AC003;;AD022; +; MOV BX,AX ;AC003;;AD022; +;;;;;;;;transfer ifs_1000 ;AC003;;AD022; + JMP GII_630 ; want user bx set ;AN022; + ;AC003; +GII_240: ; NET drive: ;AC003; + JMP GII_640 ; go down to net device processing- ;AC003; + ; does the same thing ;AC003; +GII_280: ;AC003; + INC AX ; next drive ;AC003; + JMP GII_40 ;AC003; + ;AC003; +;----------------------------------------------------------------------------------------;AC003; +; device loop ;AC003; +;----------------------------------------------------------------------------------------;AC003; + ;AC003; +GII_400: ; Device loop ;AC003; + CMP AL,CS:[DFLCount] ; if run out of devices ;AC003; + JB GII_460 ;AC003; + JMP GII_800 ; go set no_more error ;AC003; +GII_460: ;AC003; + SaveReg ; save ax-dfl count, bx-index ;AC003; + LDS SI,CS:[DFLAddr] ; Point ds:si to correct DFL entry ;AC003; + MOV BL,SIZE DFLL_list ; size in convenient spot ;AC003; + MUL BL ; get net offset ;AC003; + ADD SI,AX ; convert to true pointer ;AC003; + RestoreReg ;AC003; + TEST [SI.DFLL_FLAGS],DFL_INUSE ; is dfl active??? ;AC003; + JNZ GII_480 ;AC003; + JMP GII_680 ;AC003; +GII_480: ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_Status ; check old vs. new style ;AC003; + JNZ GII_520 ;AC003; + CMP [SI.DFLL_TYPE],TYPE_NET_DEVICE ; old style: check for type 3 ;AC003; + JE GII_520 ;AC003; + JMP GII_680 ; not type 4, go get next one ;AC003; +GII_520: ;AC003; + SUB BX,1 ;AC003; + JB GII_540 ;AC003; + JMP GII_680 ; next device ;AC003; +GII_540: ;AC003; + MOV WORD PTR CS:[THISDFL],SI ; set thisdfl = dssi ;AN014; + PUSH DS ;AN014; + POP WORD PTR CS:[THISDFL+2] ;AN014; + RestoreReg ; get devname ptr into es:di, ;AC003; + SaveReg ; (push back for end ds:si setup) ;AC003; + SaveReg ; while preserving es:di - target ;AC003; + MOV ES,CX ;AC003; + MOV DI,DX ;AC003; + PUSH SI ; save DFL offset ;AC003; + ADD SI,DFLL_DEV_NAME ;AC003; + MOV CX,8 ;AC003; +GII_545: ; store device name in asciiz format ;AC003; + LODSB ;AC003; + CMP AL," " ;AC003; + JE GII_550 ;AC003; + STOSB ;AC003; + LOOP GII_545 ;AC003; +GII_550: ;AC003; + XOR AL,AL ;AC003; + STOSB ;AC003; + RestoreReg ; restore target ptr & DFL offset ;AC003; + ;AC003; + MOV BL,[SI.DFLL_TYPE] ;AC003; + XOR BH,BH ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_Status ;AC003; + JNZ GII_555 ;AC003; + PUSH [SI.DFLL_USER_WORD] ;AC003; + POP [USER_WORD] ;AC003; + JMP GII_560 ;AC003; +GII_555: ;AC003; + PUSH DI ; ifs device; save target offset ;AC003; + MOV DI,ES:[DI] ; es:di -> FS name buffer ;AC003; + invoke GET_IFS_DRIVER_NAME ;AC003; + ;AC003; + POP DI ; retrieve target offset from stack ;AC003; + PUSH DI ;AC003; + INC DI ; es:di -> parm buffer ;AC003; + INC DI ;AC003; + ;AC003; +GII_560: ;AC003; + SaveReg ; save target segment, type ;AC003; + ; now go to IFS to fill in rest of target;AC003; + invoke PREP_IFSR ; init ifsr ;AC003; + invoke DFL_TO_DF ; DFL: sets [THISIFS] ;AC003; + ; ES:BX -> IFSRH ;AC003; + ; IFSR_DEVICE_CB@ ;AC003; + ; ds - IFSSEG ;AC003; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTSTAT ;AC003; + MOV ES:[BX.IFSR_FUNCTION],IFSATTSTAT ;AC003; + POP AX ; type (BX) ;AC003; + MOV ES:[BX.IFSR_TYPE],AL ;AC003; + POP DX ; target segment (ES) ;AC003; + ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_Status ;AC003; + JNZ GII_580 ;AC003; + PUSH CS ;AC003; + POP DS ;AC003; +ASSUME DS:IFSSEG ;AC003; + MOV SI,OFFSET TEMPBUF ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@],SI ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DS ;AC003; + PUSH DI ; push tgt offset here for later pop ;AC003; + JMP GII_600 ;AC003; +GII_580: ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@],DI ;AC003; + MOV WORD PTR ES:[BX.IFSR_PARMS@+2],DX ;AC003; +GII_600: ;AC003; + PUSH AX ; push type back (BX) ;AC003; + ;AC003; +;*********************************************************************************************** + invoke CALL_IFS ; call fs with attach status request ;AC003; +;*********************************************************************************************** + ;AC003; + JNC GII_620 ;AC003; + RestoreReg ; type,target offset,devname ptr ;AC003; + MOV ES,DX ; target ;AC003; + SaveReg ; put "ERROR" in parms display ;AC003; + TEST CS:IFSPROC_FLAGS,Filesys_status ; don't add if net use ;AN029; + JZ GII_610 ;AN029; + ADD DI,2 ;AC003; + MOV AX,1 ;AC003; + STOSW ;AC003; +GII_610: ;AN029; + PUSH CS ;AC003; + POP DS ;AC003; +ASSUME DS:IFSSEG ;AC003; + MOV SI,OFFSET ERROR_STATUS ;AC003; + MOV CX,4 ;AC003; + REP MOVSW ;AC003; + RestoreReg ;AC003;;AC027; + transfer ifs_1000 ; go to general ret in util ;AC003; + ;AC003; +GII_620: ;AC003; + RestoreReg ; device type, target offset ;AC003; + TEST IFSPROC_FLAGS,Filesys_Status ;AC003; + JZ GII_640 ; IFS device: ;AC003; +GII_630: ;AN022; + CallInstall Get_User_Stack,MULTdos,24,, ;AN022; + MOV AH,ES:[BX.IFSR_DEVICE_STATUS] ;AN022; + MOV [SI].USER_BX,AX ;AN022; + RestoreReg ; target offset,devname ptr ;AC003; + MOV ES,DX ; target ;AC003; +;;;;;;;;MOV BX,AX ;AC003;;AD022; + transfer ifs_1000 ;AC003; + ;AC003; +GII_640: ; NET device: ;AC003; + CallInstall Get_User_Stack,multDOS,24,, ;AC003; + PUSH CS:[USER_WORD] ;AC003; + POP [SI].User_CX ; User Word ;AC003; + PUSH ES:[BX.IFSR_MAX_XMITT_SIZE] ;AC003; + POP [SI].User_DX ; Max Xmitt size ;AC003; + PUSH ES:[BX.IFSR_NET_NAME_ID] ;AC003/AC008/AC009 + PUSH ES:[BX.IFSR_NET_NAME_ID] ; leave this on stack for later pop into ax ;AC009; + POP [SI].User_AX ; Net name ID ;AC003/AC008; +;;;;;;;;PUSH AX ;AN008/AD009; + + MOV CH,ES:[BX.IFSR_DEVICE_STATUS] ;AC003; + MOV CL,AL ;AC003; + MOV [SI].User_BX,CX ; Bits and macro type ;AC003; + TEST CS:IFSPROC_FLAGS,SetBP ;AC003; + JZ GII_660 ;AC003; + PUSH ES:[BX.IFSR_LSN] ;AC003; + POP [SI].User_BP ; LSN ;AC003; +GII_660: ;AC003; + MOV SI,ES:WORD PTR [BX.IFSR_PARMS@] ;AC003; + MOV DS,ES:WORD PTR [BX.IFSR_PARMS@+2] ;AC003; + INC SI ; ds:si -> parms returned by redir ;AC003; + INC SI ;AC003; + MOV ES,DX ; es:di -> input target buffer ;AC003; + SaveReg ; save offset ;AC003; + CallInstall StrCpy,MultDOS,17 ;AC003; + RestoreReg ; tgt offset,netpath id,devname ptr ;AC003/AC008; + transfer ifs_990 ;AC003; + ;AC003; +GII_680: ;AC003; + INC AX ; next drive ;AC003; + JMP GII_400 ;AC003; + ;AC003; + ;AC003; +GII_800: ; end of CDSs & devices ;AC003; + ; now check deviceless attaches ;AC003; +;----------------------------------------------------------------------------------------;AC003; +; deviceless loop ;AC003; +;----------------------------------------------------------------------------------------;AC003; + ;AC003; + CALL GET_UNC_ITEM_INFO ;AC003; + JC GII_820 ;AC003; + RestoreReg ; set dev ptr null ;AC003; + MOV BYTE PTR DS:[SI],ZERO ;AC003; + transfer ifs_990 ;AC003; +GII_820: ;AC003; + MOV AX,error_no_more_files ;AC003; + RestoreReg ; restore regs ;AC003; + ;AC003; + return ;AC003; + ;AC003; +EndProc GET_IFSFUNC_ITEM ;AC003; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; ATTACH_START ;AN000; +; ;AN000; +; Called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: CALL_IFS DOS: GetCDSFromDrv ;AN000; +; CDS_TO_CD ;AN000; +; CD_TO_CDS ;AN000; +; CREATE_DFL_ENTRY ;AN000; +; DELETE_DFL_ENTRY ;AN000; +; DFL_MATCH ;AN000; +; DFL_TO_DF ;AN000; +; DF_TO_DFL ;AN000; +; CALL_IFS ;AN000; +; FIND_IFS_DRIVER ;AN000; +;;; alias PROCESS_ALIAS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; BL = Macro type ;AN000; +;;; alias = 0 alias ;AN000; +; = 1 device/file ;AN000; +; = 2 drive ;AN000; +; = 3 Char device -> network ;AN000; +; = 4 File device -> network ;AN000; +; DS:SI -> ASCIIZ source name ;AN000; +; ES:DI -> Target driver to attach to and parms. ;AN000; +; DW ASCIIZ - asciiz name of driver ;AN000; +; DW n - number of parms ;AN000; +; DW ASCIIZ,... parms ;AN000; +; ;AN000; +; CX is reserved (user word for REDIR) ;AN000; +; ;AN000; +; Function: ;AN000; +; IF BL > 0 THEN ;AN000; +; DO ;AN000; +; Check that IFS driver exists ;AN000; +; IF found, set IFS header to that found ;AN000; +; ELSE set error_file_system_not_found ;AN000; +; ENDDO ;AN000; +; IF (BL=2 .OR. BL=4) & no error THEN ;AN000; +; DO ;AN000; +; Find CDS for this drive ;AN000; +; IF none exists, then set error_invalid_parameter ;AN000; +; ELSE Call CDS_TO_CD ;AN000; +; END ;AN000; +; ELSE DO ;AN000; +; IF source name not in DFL THEN ;AN000; +; Call CREATE_DFL_ENTRY ;AN000; +; ELSE Set error_device_already_attached ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; IF no error THEN ;AN000; +; DO ;AN000; +; Prep IFSRH for Attach Start: ;AN000; +; * IFSR_LENGTH DW 34 ; Request length ;AN000; +; * IFSR_FUNCTION DB 2 ; Attach Start ;AN000; +; IFSR_RETCODE DW 0 ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_TYPE DB ? ; BL (0,1,2,3,or 4) ;AN000; +; IFSR_RESV2 DB ? ; +; * IFSR_PARMS@ DD PARMS ; See below ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; CD or DF (See below) ;AN000; +; * IFSR_USER_WORD DW ? ; for deviceless attach ;AN000; +; ;AN000; +; * PARMS LABEL WORD ;AN000; +; DW PARMCOUNT ; Number of parms. May be 0. ;AN000; +; DB ASCIIZ,...; Parms ;AN000; +; ENDDO ;AN000; +; IF no error THEN ;AN000; +; DO ;AN000; +; CALL routine, CALL_IFS, with pointer to IFS header ;AN000; +; IF IFSR_RETCODE = 0 THEN ;AN000; +; DO ;AN000; +; IF DFL flag set THEN ;AN000; +; DO ;AN000; +; Call DF_TO_DFL ;AN000; +; Set DFLL_PTR to IFS header ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Call CD_TO_CDS ;AN000; +; Set CDS_IFSR_PTR to IFS header ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; IF DFL flag set THEN ;AN000; +; Call DELETE_DFL_ENTRY ;AN000; +; Set carry ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ELSE Set carry ;AN000; +; ENDIF ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure ATTACH_START,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def ATTSTART ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + ;AN000; + POP BX ;AN000; + XOR BH,BH ; not interested in bh, but should ;AN000; + ; be 0 since later move type as word ;AN000; +AS_10: ;AN000; + CMP BL,TYPE_DRIVE ; check ifs vs. network ;AN000; + JLE AS_20 ;AN000; + CMP BL,TYPE_NET_DRIVE ;AN000; + JLE AS_30 ;AN000; + ;AN000; +AS_15: ;AN000; + MOV AX,error_invalid_function ; invalid fcn type ;AN000; + transfer ifs_980 ; go ret w/carry ;AN000; + ;AN000; +AS_20: ; IFS device/drive ;AN000; + SaveReg ; save target ptr for parms@ ;AN000; + MOV DI,ES:[DI] ; set ES:DI -> driver name ;AN000; + invoke FIND_IFS_DRIVER ; sets [THISIFS] ;AN000; + JC AS_25 ;AN000; + SaveReg ; save cx since next destroys ;AN000; + invoke SET_CATEGORY ; do this to determine unc or not ;AN000; + OR CL,CL ; cl=1 unc else ifs ;AN000; + RestoreReg ; restore before branch - zf preserved ;AN000; + JZ AS_50 ; jmp if not unc ;AN000; + ADD BL,2 ; change type from 1/2 to 3/4 ;AN000; + RestoreReg ; retrieve orig target ptr ;AN010; +;;;;;;;;OR CS:IFSPROC_FLAGS,Filesys_Network_Attach ;AN010;;AD017; + CMP WORD PTR ES:[DI+2],2 ; if # parms=2 then have password ;AN011; + JE AS_22 ;AN011; + MOV CX,0001H ; User word without password ;AN011; + JMP SHORT AS_23 ; go process as unc ;AN011;;AC017; +AS_22: ;AN011; + MOV CX,8001H ; User word with password ;AN011; +AS_23: ;AN017; + ADD DI,4 ; skip over ifs name offset & #parms ;AN017; + JMP SHORT AS_33 ; go process as unc ;AN000; + +AS_25: ; ifs driver not found ;AN000; + POP DI ; error, restore stack and return ;AN000; + POP ES ;AN000; + transfer ifs_1000 ;AN000; + ;AN000; +AS_30: ; NETWORK device/drive ;AN000; + TEST CS:IFSFUNC_FLAGS,UNC_INSTALLED ; check that unc installed ;AN000; + JZ AS_15 ;AN000; +AS_33: ; this label for unc already checked ;AN000; + OR IFSPROC_FLAGS,IsNetwork ; set network bit ;AN000; + CMP BL,TYPE_NET_DRIVE ; check pause status ;AN000; + JNE AS_35 ;AN000; + CMP CS:fAssign,-1 ;AN000; + JMP SHORT AS_37 ;AN000; +AS_35: ;AN000; + CMP CS:fPrint,-1 ;AN000; +AS_37: ;AN000; + JE AS_40 ; bad pause status ;AN000; + MOV AX,72 ; set error and ret w/carry ;AN000; +AS_38: ;AN020; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + invoke SET_EXTERR_INFO ;AN000; + transfer ifs_980 ;AN000; + ;AN000; +AS_40: ;AN000; + invoke SET_THISIFS_UNC ;AN000; + SaveReg ;AN004;;AC015; + invoke NET_TRANS ;AN000; + RestoreReg ;AN004;;AC015; + JNC SHORT AS_55 ;AC020; + MOV AX,error_path_not_found ; net trans failure = path not found ;AN020; + JMP AS_38 ;AN020; + ;AN000; +AS_50: ;AN000; + RestoreReg ; restore target parm ptr ;AN000; +AS_55: ;AN000; + OR CS:IFSPROC_FLAGS,THISIFS_SET ; do this so wont do in CDS_TO_CD ;AN000; + ; or DFL_TO_DF ;AN000; + CMP BL,TYPE_DEVICE ;AN000; + JNE AS_55_0 ;AN000; + JMP AS_200 ;AN000; +AS_55_0: ;AN000; + CMP BL,TYPE_NET_DEVICE ;AN000; + JNE AS_55_1 ;AN000; + JMP AS_200 ;AN000; +AS_55_1: ;AN000; + CMP BL,TYPE_NET_DRIVE ; deviceless attach check ;AN000; + JNE AS_56 ; jmp if no ;AN000; + CMP BYTE PTR [SI],0 ; DEVICELESS ATTACH ;AN000; + JNZ AS_56 ; Set dummy CDS and flag ;AN000; + Context DS ;AN000; + MOV SI,OFFSET DOSGROUP:DummyCDS ;AN000; + MOV WORD PTR [THISCDS+2],DS ;AN000; + MOV WORD PTR [THISCDS],SI ;AN000; + OR IFSPROC_FLAGS,ISDUMMYCDS ;AN000; + JMP SHORT AS_100 ;AN000; + ;AN000; +AS_56: ; DRIVE ATTACH ;AN000; + CMP WORD PTR [SI+1],ICOLON ; if 2nd char not ":" - error ;AN000; + JE AS_60 ; else - find CDS ;AN000; +AS_57: ;AN000; + MOV AX,error_invalid_drive ;AN000; + transfer ifs_980 ;AN000; + ;AN000; +AS_60: ;AN000; + LODSB ;AN000; + Context DS ; get addressability to DOSGROUP ;AN000; + OR AL,20H ;AN000; + SUB AL,"a" ; 0=A,1=B,... ;AN000; + CallInstall GetCDSFromDrv,multDOS,23,AX,AX ;AN000; +ASSUME DS:NOTHING ;AN000; + JC AS_57 ; no cds - error ;AN000; + TEST [SI.curdir_flags],curdir_inuse ; DS:SI -> CDS ;AN000; + JZ AS_100 ;AN000; + TEST [SI.curdir_flags],curdir_isnet + curdir_splice + curdir_local ;AN000; + JZ AS_100 ;AN000; + MOV AX,error_already_assigned ; error - CDS already assigned ;AN000; + transfer ifs_980 ; go return with carry ;AN000; + ;AN000; +AS_100: ;AN000; + SaveReg ; save real cds and target parm ptr ;AN000; + ; If all goes OK this will be the "REAL" CDS ;AN000; + Context ES ;AN000; + MOV DI,OFFSET DOSGROUP:DummyCDS ;AN000; + SaveReg ; dummy cds offset, input user word ;AC001; + MOV CX,SIZE curdir_list ;AN000; + REP MOVSB ;AN000; + RestoreReg ; input user word ;AN001; + PUSH ES ;AN000; + POP DS ;AN000; + POP SI ; DS:SI -> dummy CDS ;AN000; + MOV [SI.curdir_flags],curdir_isnet + curdir_inuse ;AN000; + ;AN000; + MOV AX,WORD PTR [THISIFS] ; set ifs ptr in cds ;AN000; + MOV DS:WORD PTR [SI.CURDIR_IFS_HDR],AX ;AN000; + MOV AX,WORD PTR [THISIFS+2] ;AN000; + MOV DS:WORD PTR [SI.CURDIR_IFS_HDR+2],AX ;AN000; + ;AN000; + MOV DS:[SI.CURDIR_TYPE],BL ; set CDS type ;AN000; + MOV DS:[SI.CURDIR_USER_WORD],CX ; set CDS user word ;AN001; + MOV AX,CX + ;AN000; + RestoreReg ; get target parm ptr off stack ;AN000; + SaveReg ; save type and dummy cds ptr ;AN000; + invoke PREP_IFSR ; clear ifsrh ;AN000; + invoke CDS_TO_CD ; CDS: sets ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + TEST IFSPROC_FLAGS,ISDUMMYCDS + JZ AS_120 + MOV ES:[BX.IFSR_USER_WORD],AX +AS_120: + POP AX ; restore type in AL ;AN000; + MOV ES:[BX.IFSR_TYPE],AL ;AC002; + SaveReg ; put target parm ptr back on stack ;AN000; + JMP SHORT AS_400 ; go prep IFSRH ;AN000; + ;AN000; +AS_200: ; DEVICE ATTACH: ;AN000; + invoke DFL_MATCH ; check if device already assigned ;AN000; + JC AS_220 ; cf-0 match, cf-set no match ;AN000; + MOV AX,error_already_assigned ;AN000; + transfer ifs_980 ; go return with carry ;AN000; + ;AN000; +AS_220: ;AN000; + SaveReg ; save target parm ptr & type ;AN000; + invoke CREATE_DFL_ENTRY ; DFL: sets ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + JNC AS_240 ;AN000; + RestoreReg ; restore stack ;AC019; + invoke CONSIST_SFT ;AN000; + transfer ifs_980 ; error ret ;AC019; +AS_240: ;AN000; + POP AX ; restore type in AL ;AN000;moved ;AM019; + MOV ES:[BX.IFSR_TYPE],AL ;AC002; + ;AN000; + ;AN000; +AS_400: ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTSTART ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSATTSTART ;AN000; + POP AX ; old target DI ;AN000; +;;;;;;;;TEST IFSPROC_FLAGS,Filesys_Network_Attach ;AN010;;AD017; +; JZ AS_405 ;AN010;;AD017; +; ADD AX,4 ; filesys-net skip name offset ;AN010;;AD017; +;;;;;;;;JMP SHORT AS_410 ; and # parms - just want net path;AN010;;AD017; +;AS_405: ;AN010;;AD017; + TEST IFSPROC_FLAGS,IsNetwork ;AN000; + JNZ AS_410 ;AN000; + INC AX ;AN000; + INC AX ;AN000; +AS_410: + MOV ES:WORD PTR [BX.IFSR_PARMS@],AX ;AN000; + POP AX ; old target ES ;AN000; + MOV ES:WORD PTR [BX.IFSR_PARMS@+2],AX ;AN000; + +;*********************************************************************************************** + invoke CALL_IFS ;AN000; +;*********************************************************************************************** + + JNC AS_440 ;AN000; + ;AN000; + ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; ifs error: ;AN000; + JZ AS_420 ;AN000; + RestoreReg ; pop dummy & real cds ;AN000; + transfer ifs_980 ;AN000; +AS_420: ;AN000; + SaveReg ; preserve error code ;AN027; + invoke DELETE_DFL_ENTRY ;AN000; + invoke CONSIST_SFT ;AN025; + RestoreReg ;AN027; + transfer ifs_980 ;AN000; + ;AN000; +AS_440: ; successful attach ;AN000; + TEST IFSPROC_FLAGS,ISCDS ;AN000; + JZ AS_460 ;AN000; + RestoreReg ; restore ES:DI -> dummy cds ;AN000; + invoke CD_TO_CDS ;AN000; + RestoreReg ; ds:si - real cds ;AN000; + invoke XCHGP ;AN000; + MOV CX,SIZE CURDIR_LIST ;AN000; + OR DS:[SI.CURDIR_FLAGS],CURDIR_ISIFS ; make sure this flag set ;AN000; + REP MOVSB ;AN000; + transfer ifs_990 ;AN000; + ;AN000; +AS_460: ;AN000; + invoke DF_TO_DFL ;AN000; + invoke CONSIST_SFT ;AN025; + transfer ifs_990 ;AN000; + ;AN000; + ;AN000; +EndProc ATTACH_START ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; ATTACH_END ;AN000; +; ;AN000; +; Called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: DFL_MATCH DOS: StrCpy ;AN000; +; DFL_TO_DF DriveFromText ;AN000; +; DF_TO_DFL GetThisDrv ;AN000; +; CDS_TO_CD InitCDS ;AN000; +; CD_TO_CDS ;AN000; +; SET_EXTERR_INFO ;AN000; +; CALL_IFS ;AN000; +; DELETE_DFL_ENTRY ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> ASCIZ source name ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 30 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; End Attach ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_DEVICE_CB@ DD ? ; CD or DF ;AN000; +; * IFSR_NAME@ DD ? ; for deviceless detach (unc) ;AN000; +; ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure ATTACH_END,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def ATTEND ;AN000; + ;AN000; + POP BX ;AN000; + ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + MOV CS:IFSPROC_FLAGS,0 ;AN000; + invoke PREP_IFSR ;AN000; + ;AN000; + PUSH DS ;AN000; + POP ES ;AN000; + MOV DI,SI ; ES:DI=DS:SI=source name ;AN000; + PUSH SI ; Save SI ;AN000; + CallInstall StrCpy,multDOS,17 ; "Beautify" input string ;AN000; + ; (converts to uppercase & ;AN000; + ; / to \) ;AN000; + POP SI ; Recover string pointer ;AN000; + CMP WORD PTR [SI],"\\" ; Special Case - ;AN000; + JZ AE_300 ; deviceless detach ;AN000; + CMP WORD PTR [SI+1],":" ; check for drive ;AN000; + JNZ AE_200 ; no, go to device check ;AN000; + CMP fAssign,-1 ; BREAK DRIVE ATTACH ;AN000; + JZ AE_20 ;AN000; +AE_10: ;AN000; + MOV AX,72 ; pause error ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + invoke SET_EXTERR_INFO ;AN000; + transfer ifs_980 ;AN000; +AE_20: ;AN000; + CallInstall DriveFromText,multDOS,26 ; AL = drive # (0-not drive ;AN000; + context DS ; -1=a,1=b,2=c,...) ;AN000; + CallInstall GetThisDrv,multDOS,25,AX,BX ; ES:DI->CDS ;AN000; + JNC AE_40 ;AN000; + MOV AX,error_invalid_drive ;AN000; + transfer ifs_1000 ;AN000; +AE_40: ;AN000; + LES DI,[THISCDS] ;AN000; + TEST ES:[DI.curdir_flags],curdir_isnet ;AN000; + JNZ AE_60 ;AN000; + MOV AX,error_invalid_drive ; not redirected ;AN000; + transfer ifs_980 ;AN000; +AE_60: ;AN000; + PUSH AX ; drive # ;AN000; + PUSH ES ;AN000; + POP DS ;AN000; + MOV SI,DI ; move cds ptr to ds:si ;AN000; + invoke CDS_TO_CD ;AN000; + OR IFSPROC_FLAGS,ISCDS ;AN000; + JMP SHORT AE_400 ;AN000; + ;AN000; +AE_200: ; BREAK DEVICE ATTACH ;AN000; + CMP fPrint,-1 ; check for pause error ;AN000; + JZ AE_210 ;AN000; + JMP AE_10 ;AN000; +AE_210: ;AN000; + CALL DFL_MATCH ;AN000; + JNC AE_220 ;AN000; + MOV AX,device_not_attached ;AN000; + transfer ifs_1000 ;AN000; +AE_220: ;AN000; + MOV SI,WORD PTR [THISDFL] ;AN000; + MOV DS,WORD PTR [THISDFL+2] ;AN000; + ;AN000; + TEST DS:[SI.DFLL_FLAGS],DFL_DEV_REAL ;AN000; +; ???????????? check with baf on what reverting to ... ;AN000; + ;AN000; + invoke DFL_TO_DF ; DFL: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_DEVICE_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + JMP SHORT AE_400 ;AN000; + ;AN000; +AE_300: ; deviceless detach ;AN000; + SaveReg ; restore es to ifsr & set seq flag ;AN018; + RestoreReg ;AN018; + OR CS:IFSPROC_FLAGS,IsSeq ;AN018; + CMP fAssign,-1 ;AN000; + JZ AE_320 ;AN000; + JMP AE_10 ; jump to pause error ;AN000; +AE_320: ;AN000; + SaveReg ; ifsr ptr ;AC004; + RestoreReg ; set esdi = dssi = net path ;AC004; +ASSUME ES:NOTHING ;AC004; + MOV DI,SI ;AC004; + invoke NET_TRANS ;AC004; + SaveReg ;AC004; + RestoreReg ; name string segment ;AC004; + MOV SI,DI ; name string offset ;AC004; + RestoreReg ; ifsr pointer ;AC004; +ASSUME ES:IFSSEG ;AC004; + MOV WORD PTR ES:[BX.IFSR_NAME@],DI ;AC004; + MOV WORD PTR ES:[BX.IFSR_NAME@+2],AX ;AC004; + SaveReg ;AC004; + RestoreReg ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; +AE_400: ; call ifs ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_ATTEND ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSATTEND ;AN000; + ;AN000; +;*********************************************************************************************** + invoke CALL_IFS ;AN000; +;*********************************************************************************************** + ;AN000; + JNC AE_410 ;AN000; + TEST IFSPROC_FLAGS,ISCDS ; att end error: ;AN000; + JZ AE_405 ;AN000; + ADD SP,2 ; clear ax (drive #) off stack ;AN000; +AE_405: ;AN000; + transfer ifs_980 ;AN000; +AE_410: ;AN000; + TEST CS:IFSPROC_FLAGS,ISCDS ;AN000; + JZ AE_420 ;AN000; + ;AN000; + POP AX ; drive ;AN000; + ADD AL,'A' ;AN000; + CallInstall InitCDS,multDOS,31,AX,AX ;AN000; + transfer ifs_990 ;AN000; +AE_420: ;AN000; + TEST CS:IFSPROC_FLAGS,IsSeq ;AN018; + JNZ AE_440 ;AN018; + CALL DELETE_DFL_ENTRY ;AN000; +AE_440: ;AN018; + transfer ifs_990 ;AN000; + ;AN000; + ;AN000; +EndProc ATTACH_END ;AN000; + ;AN000; + +BREAK ;AN016; + +;*********************************************************************************** +; +; IFS_RESET_ENVIRONMENT +; +; Called by: IFSFUNC Dispatcher +; +; Routines called: +; jumps into ifs_abort +; +; Inputs: +; [CurrentPDB] set to PID of process aborting +; +; Function: +; Get address of IFS driver chain. +; FOR I = 1 to last IFS driver +; Send request below to IFS driver +; +; IFSRH: +; * IFSR_LENGTH DW 42 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; IFSR_RETCODE DW ? +; IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 18 ; End of Process +; IFSR_ERROR_CLASS DB ? +; IFSR_ERROR_ACTION DB ? +; IFSR_ERROR_LOCUS DB ? +; IFSR_ALLOWED DB ? +; IFSR_I24_RETRY DB ? +; IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; IFSR_DEVICE_CB@ DD ? ; CD +; IFSR_OPEN_CB@ DD ? +; * IFSR_PID DW ? ; process ID +; * IFSR_SUBFUNC DB 2 ; 0=normal exit 1=abort exit +; ; 2=reset environment +; IFSR_RESV3 DB ? +; +; Call all IFSs with this info. +; Scan through SFTFCB +; IF (ref_count ^= 0 .AND. ^busy .AND. isifs .AND. SF_PID = currentPDB) THEN +; Call SF_IFS_HDR with close request +; ENDIF +; +; Outputs: None +; DS Preserved, All others destroyed +; +;************************************************************************************ + + procedure IFS_RESET_ENVIRONMENT,NEAR ;AN016; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN016; + + ifsr_fcn_def EXECAPI ;AN016; + ifsr_api_def EOP ;AN016; + + MOV CS:IFSPROC_FLAGS,IsResetEnvirn ;AN016; + Context DS ; make sure ds=ss=dosgroup ;AN016; + JMP IA_70 ;AN016; + +EndProc IFS_RESET_ENVIRONMENT ;AN016; + + +BREAK ;AN016; + ;AN016; +;************************************************************************************ +; +; IFS_ABORT +; +; Called by: IFSFUNC Dispatcher +; +; Routines called: +; CALL_IFS +; IFS_CLOSE +; +; Inputs: +; [CurrentPDB] set to PID of process aborting +; +; Function: +; Get address of IFS driver chain. +; FOR I = 1 to last IFS driver +; Send request below to IFS driver +; +; IFSRH: +; * IFSR_LENGTH DW 42 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; IFSR_RETCODE DW ? +; IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 16 DUP(0) +; * IFSR_APIFUNC DB 18 ; End of Process +; IFSR_ERROR_CLASS DB ? +; IFSR_ERROR_ACTION DB ? +; IFSR_ERROR_LOCUS DB ? +; IFSR_ALLOWED DB ? +; IFSR_I24_RETRY DB ? +; IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; IFSR_DEVICE_CB@ DD ? ; CD +; IFSR_OPEN_CB@ DD ? +; * IFSR_PID DW ? ; process ID +; * IFSR_SUBFUNC DB ? ; 0=normal exit 1=abort exit +; ; 2=reset environment +; IFSR_RESV3 DB ? +; +; Call all IFSs with this info. +; Scan through SFTFCB +; IF (ref_count ^= 0 .AND. ^busy .AND. isifs .AND. SF_PID = currentPDB) THEN +; Call SF_IFS_HDR with close request +; ENDIF +; +; Outputs: None +; DS Preserved, All others destroyed +; +;************************************************************************************ + + procedure IFS_ABORT,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def EOP ;AN000; + + MOV CS:IFSPROC_FLAGS,ZERO + ;AN000; +; Scan the FCB Cache and close any NET FCBs ;AN000; +; belonging to this process. The reason we must do this is that ;AN000; +; NET FCBs are well behaved and must be closed on EXIT. ;AN000; + ;AN000; + LES DI,[SFTFCB] ;AN000; + MOV CX,ES:[DI].sfCount ;AN000; + LEA DI,[DI].sfTable ;AN000; + JCXZ IA_70 ;AN000; +IA_20: ; Loop through sftfcb's ;AN000; + CMP ES:[DI].sf_ref_count,0 ;AN000; + JZ IA_60 ; Ignore Free ones ;AN000; + CMP ES:[DI].sf_ref_count,sf_busy ;AN000; + JZ IA_60 ; Ignore busy ones ;AN000; + TEST ES:[DI].sf_flags,sf_isnet ;AN000; + JZ IA_60 ; Ignore non NET ones ;AN000; + MOV AX,[CurrentPDB] ;AN000; + CMP AX,ES:[DI].sf_PID ;AN000; + JNZ IA_60 ; Ignore FCBs not for this proc ;AN000; + MOV WORD PTR [THISSFT],DI ;AN000; + MOV WORD PTR [THISSFT+2],ES ;AN000; + PUSH CX ;AN000; +IA_40: ; CLOSE ;AN000; + invoke IFS_CLOSE ; IGNORE ANY ERRORS ON THIS. ;AN000; + CMP ES:[DI].sf_ref_count,0 ; Make sure it gets closed ;AN000; + JNE IA_40 ; Loop until closed ;AN000; + POP CX ;AN000; +IA_60: ;AN000; + ADD DI,size sf_entry ;AN000; + LOOP IA_20 ;AN000; +; ;AN000; +; Now loop through all ifs drivers with end of process request ;AN000; +; ;AN000; +IA_70: ;AN000; + LDS SI,IFS_HEADER ;AN000; +ASSUME DS:NOTHING ;AN000; + JMP SHORT IA_100 ; go check if null ;AN007; + ;AN000; +IA_80: ;AN000; + MOV CS:WORD PTR [THISIFS],SI ; Send end of process request ;AN000; + MOV CS:WORD PTR [THISIFS+2],DS ; to all fs drivers. ;AN000; + invoke PREP_IFSR ; sets esbx -> ifsrh ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_EOP ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSEOP ;AN000; + MOV AX,[CurrentPDB] ;AN000; + MOV ES:[BX.IFSR_PID],AX ; ????? ;AN000; + MOV AL,[EXIT_TYPE] ;AN000; + MOV ES:[BX.IFSR_SUBFUNC],AL ;AN000; + TEST CS:IFSPROC_FLAGS,IsResetEnvirn ;AN016; + JZ IA_90 ;AN016; + MOV ES:[BX.IFSR_SUBFUNC],RESET_ENVIRONMENT ;AN016; +IA_90: ;AN016; + SaveReg ; dssi - ifs driver ;AC012; + RestoreReg ; ds - ifsseg ;AN000; + ;AN000; +;*********************************************************************************************** + invoke CALL_IFS ;AN000; +;*********************************************************************************************** + ;AN000; + RestoreReg ; dssi - ifs driver ;AC012; + LDS SI,[SI.IFS_NEXT] ; check next fs driver ;AN000; +IA_100: ;AN007; + CMP SI,NULL_PTR ; if ptr null, no more ;AN000; + JNE IA_80 ;AN000; + PUSH DS ;AN000; + POP AX ;AN000; + CMP AX,NULL_PTR ;AN000; + JNE IA_80 ;AN000; + ;AN000; + ;AN000; +IA_1000: ;AN000; + SaveReg ; dosgroup ;AN000; + RestoreReg ;AN000; + return ;????????? may need redir ioctl to ;AN000; + ; consist_refs ;AN000; + ;AN000; +EndProc IFS_ABORT ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; GET_IFS_DRIVER_NAME ;AN000; +; ;AN000; +; Called by: GET_IFSFUNC_ITEM ;AN000; +; ;AN000; +; Routines called: ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> CDS/DFL ;AN000; +; ES:DI = buffer to place name ;AN000; +; Function: ;AN000; +; Find FS name in IFS header pointed to by CDS or DFL ;AN000; +; Place name in buffer pointed to by ES:DI ;AN000; +; Output: ;AN000; +; buffer filled, hopefully with ifs name ;AN000; +; pointer not checked for valid ifs driver hdr ptr ;AN000; +; Regs: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure GET_IFS_DRIVER_NAME,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; preserve cds/dfl ptr, cx, buffer ;AN000; + ; offset ;AN000; + TEST CS:IFSPROC_FLAGS,ISCDS ; get ifs hdr ptr from ;AN000; + JZ GIDN_20 ;AN000; + LDS SI,[SI.CURDIR_IFS_HDR] ; cds ;AN000; + JMP GIDN_40 ;AN000; +GIDN_20: ;AN000; + LDS SI,[SI.DFLL_IFS_HDR] ; dfl ;AN000; +GIDN_40: ;AN000; + invoke MOVE_DRIVER_NAME ; move ifs driver name into buffer ;AN000; + ;AN000; + RestoreReg ; restore cds/dfl ptr, cx, buffer ;AN000; + ; offset ;AN000; + return ;AN000; + ;AN000; +EndProc GET_IFS_DRIVER_NAME ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ +; +; FIND_IFS_DRIVER +; +; Called by: ATTACH_START +; +; Routines called: CHECK_END_SPACE +; +; Inputs: +; ES:DI -> IFS driver name +; Function: +; Loop through IFS driver chain until name match. +; If match found - set [THISIFS] and clear carry +; Else set carry. +; Output: +; carry clear - match found,[THISIFS] set +; carry set - no match found +; +; Regs: all but ax preserved +; +;************************************************************************************ + ;AN000; + Procedure FIND_IFS_DRIVER ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save registers (except ax for error) ;AC026; + ;AN000; + TEST CS:IFSFUNC_FLAGS,NO_IFS_DRIVERS ; check for no drivers first ;AN024; + JZ FID_10 ;AN024; + JMP FID_30 ;AN024; +FID_10: ;AN024; + + SaveReg ; get addressability to dosgroup ;AN000; + RestoreReg ; to get ifs driver chain ;AN000; + LDS SI,IFS_HEADER ;AN000; +ASSUME DS:NOTHING ; ds:si -> 1st ifs driver ;AN000; + ;AN000; +FID_20: ;AN000; + SaveReg ; save ds,si,es,di ;AN000; + RestoreReg ; set es=cs ;AN000; +ASSUME ES:IFSSEG ;AN000; + MOV DI,OFFSET TEMPBUF ; move ifs driver name into tempbuf ;AN000; + SaveReg ; so that can be asciiz form before ;AN000; + invoke MOVE_DRIVER_NAME ; strcmp ;AN000; + RestoreReg ; dssi -> tempbuf (ifs driver asciiz ;AN000; + SaveReg ; name) ;AN000; + RestoreReg ; esdi -> ifs driver name (input) ;AN000; + CALL CHECK_END_SPACE ; make sure ^ has no blanks ;AN000; + + CallInstall StrCmp,multDOS,30 ; check for match (regs preserved) ;AN000; + RestoreReg ; (ifs driver) ;AN000; + JZ FID_40 ; if match, go set thisifs & return ;AN000; + LDS SI,[SI.IFS_NEXT] ; else check next fs driver ;AN000; + CMP SI,MINUS_ONE ; if ptr null, no more = error ;AN000; + JNE FID_20 ;AN000; + PUSH DS ;AN000; + POP AX ;AN000; + CMP AX,MINUS_ONE ;AN000; + JNE FID_20 ;AN000; +FID_30: ;AN024; + MOV AX,fs_driver_not_found ;AN000; + JMP SHORT FID_980 ;AN000; +FID_40: ;AN000; + MOV WORD PTR CS:[THISIFS],SI ; match. Set [THISIFS] to this ;AN000; + MOV WORD PTR CS:[THISIFS+2],DS ; driver ;AN000; + JMP FID_990 ;AN000; + ;AN000; + ;AN000; +FID_980: ; Return area ;AN000; + STC ;AN000; + JMP SHORT FID_1000 ;AN000; +FID_990: ;AN000; + CLC ;AN000; +FID_1000: ;AN000; + RestoreReg ; restore registers ;AC026; + return ;AN000; + ;AN000; +EndProc FIND_IFS_DRIVER ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; AssignOn/AssignOff ;AN000; +; ;AN000; +; Called by: SET_ASSIGN_MODE ;AN000; +; ;AN000; +; AssignOn and AssignOFF copied from Network Redirector code ;AN000; +; PrintOn and PrintOff IFSFUNC new code ;AN000; +; ;AN000; +; Inputs: ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Output: ;AN000; +; ;AN000; +; Regs: none preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure AssignOn,Near ;AN000; +ASSUME ES:NOTHING, DS:NOTHING ;AN000; + EnterCrit CritNet ;AN000; + CMP fAssign,-1 ; if (fAssign) ;AN000; + JZ CrLvA ; return; ;AN000; + MOV fAssign,-1 ; fAssign = TRUE; ;AN000; + LDS SI,CDSAlt ; s = CDSAlt; ;AN000; + LES DI,CDSAddr ; d = CDSAddr; ;AN000; + MOV AL,CDSCount ;AN000; + MOV DX,SIZE curdir_list ;AN000; +OnLoop: ;AN000; + TEST [SI].curdir_flags,curdir_isnet ;AN000; + JNZ RestCDS ; Restore this NET guy ;AN000; + ADD SI,DX ; Skip to next CDS ;AN000; + ADD DI,DX ;AN000; +NextCDS: ;AN000; + DEC AL ;AN000; + JNZ OnLoop ;AN000; +CrLvA: ;AN000; + LeaveCrit CritNet ;AN000; + return ;AN000; + ;AN000; +RestCDS: ;AN000; + MOV CX,DX ;AN000; + REP MOVSB ; strcpy (d, s); ;AN000; + JMP NextCDS ;AN000; +EndProc AssignOn ;AN000; + ;AN000; +Procedure AssignOff,Near ;AN000; + ASSUME ES:NOTHING, DS:NOTHING ;AN000; + EnterCrit CritNet ;AN000; + CMP fAssign,0 ; if (!fAssign) ;AN000; + JZ CrLvB ; return; ;AN000; + LES DI,CDSAlt ; d = CDSAlt; ;AN000; + LDS SI,CDSAddr ; s = CDSAddr; ;AN000; + MOV AL,CDSCount ;AN000; + CBW ; always less or = 26 ;AN000; + MOV CX,SIZE curdir_list ;AN000; + MUL CX ;AN000; + MOV CX,AX ;AN000; + REP MOVSB ; Save current CDS state ;AN000; + XOR AL,AL ;AN000; +OffLoop: ; for (i=0; p1=getcds(i); i++) ;AN000; + CallInstall GetCDSFromDrv,multDOS,23,AX,AX ; Set THISCDS for possible ;AN000; + ; call to InitCDS ;AN000; + JC OffDone ; ;AN000; + TEST [SI].curdir_flags,curdir_isnet ;AN000; + JZ OffInc ;AN000; + SaveReg ;AN000; + ADD AX,'A' ;AN000; + CallInstall InitCDS,multDOS,31,AX,AX ; initcds (p1); ;AN000; + RestoreReg ;AN000; +OffInc: INC AL ;AN000; + JMP OffLoop ;AN000; + ;AN000; +OffDone: ;AN000; + MOV fAssign,0 ; fAssign = FALSE; ;AN000; +CrLvB: ;AN000; + LeaveCrit CritNet ;AN000; + return ;AN000; +EndProc AssignOff ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; PrintOn/PrintOff ;AN000; +; ;AN000; +; Called by: SET_ASSIGN_MODE ;AN000; +; ;AN000; +; Routines called: CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; ;AN000; +; Function: ;AN000; +; Print on - loop through dfl entries resetting pause flag to zero ;AN000; +; Print off- loop through dfl entries, set pause flag if unc ;AN000; +; ;AN000; +; Prep IFSRH: ;AN000; +; * IFSR_LENGTH DW 48 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DB ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 17 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; IFSR_ALLOWED DB ? ;AN000; +; IFSR_I24_RETRY DB ? ;AN000; +; IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; IFSR_DEVICE_CB@ DD ? ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB 0 ; 0 generic ioctl ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; * IFSR_BUFFER@ DD ? ; al-2 es:di, else ds:dx ;AN000; +; * IFSR_BUFSIZE DW ? ; al-2 cx, else ??? ;AN000; +; * IFSR_CATEGORY DB 1 ; 1 for UNC ;AN000; +; * IFSR_CTLFUNC DB ? ; x - print on, y - print off ;AN000; +; ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to IFS header ;AN000; +; ;AN000; +; Outputs: none ;AN000; +; ;AN000; +; Regs: nothing preserved ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; +Procedure PrintOn,Near ;AN000; + ASSUME DS:NOTHING, ES:NOTHING ;AN000; + ;AN000; + EnterCrit CritNet ;AN000; + CMP fPrint,-1 ; if (fPrint) ;AN000; + JNE PON_20 ;AN000; + JMP POF_1000 ; return; ;AN000; +PON_20: ;AN000; + MOV fPrint,-1 ; fPrint = TRUE; ;AN000; + MOV CS:IFSPROC_FLAGS,PRINT_ON ;AN000; + JMP POF_20 ; finish in printoff routine ;AN000; + ;AN000; + ;AN000; +EndProc PrintOn ;AN000; + ;AN000; +Procedure PrintOff,NEAR ;AN000; + ASSUME DS:NOTHING, ES:NOTHING ;AN000; + ;AN000; + EnterCrit CritNet ;AN000; + CMP fPrint,0 ; quit if already off ;AN000; + JZ POF_1000 ; return ;AN000; + MOV fPrint,0 ; set off ;AN000; + MOV CS:IFSPROC_FLAGS,ZERO ; init processing flags ;AN000; + ;AN000; +POF_20: ; (welcome print on) ;AN000; + PUSH CS ; get addressability to IFSSEG ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG,ES:NOTHING ;AN000; + ;AN000; + MOV CL,[DFLCount] ; Prep loop through DFL list ;AN000; + XOR CH,CH ; For all unc devices, set pause ;AN000; + XOR DH,DH ; flag ;AN000; + MOV DL,SIZE DFLL_LIST ;AN000; + LDS SI,[DFLAddr] ;AN000; +POF_40: ; *** loop on setting pause flag ;AN000; + TEST IFSPROC_FLAGS,PRINT_ON ; on print on, just reset all ;AN000; + JNZ POF_50 ;AN000; + LES DI,DS:[SI.DFLL_IFS_HDR] ; only set pause on unc devices ;AN000; + OR DI,DI ; make sure this dfl taken ;AN000; + JNZ POF_45 ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + OR AX,AX ;AN000; + RestoreReg ;AN000; + JZ POF_60 ;AN000; +POF_45: ;AN000; + TEST ES:[DI.IFS_ATTRIBUTE],IFSUNC ;AN000; + JZ POF_60 ;AN000; + OR DS:[SI.DFLL_FLAGS],DFL_PAUSED ;AN000; + JMP SHORT POF_60 ;AN000; +POF_50: ;AN000; + AND DS:[SI.DFLL_FLAGS],NOT DFL_PAUSED ;AN000; +POF_60: ;AN000; + ADD SI,DX ; prep for next dfl ;AN000; + LOOP POF_40 ; go process next dfl ;AN000; + ; now go tell unc, device pause ;AN000; + ; is in effect ;AN000; + invoke PREP_IFSR ; init ifsr ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ; define ifsr for dep ioctl ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + ;AN000; + invoke SET_DEPIOCTL_IFSR ;AN000; + TEST IFSPROC_FLAGS,PRINT_ON ;AN000; + JZ POF_80 ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINT_ON ;AN000; + JMP SHORT POF_100 ;AN000; +POF_80: ;AN000; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_PRINT_OFF ;AN000; +POF_100: ;AN000; + MOV ES:[BX.IFSR_CATEGORY],1 ;AN000; + invoke SET_THISIFS_UNC ;AN000; + +;*********************************************************************************************** + invoke CALL_IFS ; call ifs driver w/request ;AN000; +;*********************************************************************************************** + + invoke CONSIST_SFT ;AN000; + ;AN000; +POF_1000: ;AN000; + LeaveCrit CritNet ;AN000; + return ;AN000; + ;AN000; +EndProc PrintOff ;AN000; + ;AN000; + ;AN000; +BREAK ;AC000; + +;****************************************************************************** +; +; GET_UNC_ITEM_INFO +; +; Called by: GET_IFSFUNC_ITEM +; +; Routines called: CALL_IFS +; +; Inputs: +; BL = redirection index +; ES:DI -> Target buffer: old - net path string ;AN00 +; new - dw file system driver name +; dw # parms +; db parms +; +; Function: +; +; Prep IFSRH: +; * IFSR_LENGTH DW 48 ; Request length +; * IFSR_FUNCTION DB 4 ; Execute API function +; IFSR_RETCODE DB ? +; IFSR_RETCLASS DB ? +; IFSR_RESV1 DB 17 DUP(0) +; * IFSR_APIFUNC DB 16 ; IFS dependent IOCTL +; IFSR_ERROR_CLASS DB ? +; IFSR_ERROR_ACTION DB ? +; IFSR_ERROR_LOCUS DB ? +; IFSR_ALLOWED DB ? +; IFSR_I24_RETRY DB ? +; IFSR_I24_RESP DB ? +; IFSR_RESV2 DB ? +; IFSR_DEVICE_CB@ DD ? +; IFSR_OPEN_CB@ DD ? +; * IFSR_FUNC DB 0 ; 0 generic ioctl +; IFSR_RESV2 DB 0 +; * IFSR_BUFFER@ DD ? ; unc item info buffer +; IFSR_BUFSIZE DW 10 +; * IFSR_CATEGORY DB 1 ; 1 for UNC +; * IFSR_CTLFUNC DB ? ; 4 - get unc item +; +; buffer: dw index (bx) +; dw user word +; dw max xmitt size +; dw net name ID +; dw lower 8 bits lsn from ncb_list +; db redir reserved bits +; db net path...(asciiz) +; +; +; CALL routine, CALL_IFS, with pointer to IFS header +; +; Outputs: user stack contains info +; cx - user word +; bx - bits and macro type +; dx - max xmitt size +; ax - net name id +; bp - lsn (if specified) +; +; Regs: nothing preserved +; +;****************************************************************************** + ;AC003; + Procedure GET_UNC_ITEM_INFO,NEAR ;AC003; + ;AC003; + TEST CS:IFSFUNC_FLAGS,UNC_INSTALLED ;AN013; + JNZ GUI_05 ;AN013; + transfer ifs_980 ;AN013; + +GUI_05: ;AN013; + SaveReg ; target ptr and index ;AC003; + ;AC003; + invoke PREP_IFSR ; init ifsr ;AC003; + SaveReg ; prep ds for call ifs call ;AC003; + RestoreReg ;AC003; +ASSUME DS:IFSSEG ;AC003; + ;AC003; + invoke SET_DEPIOCTL_IFSR ; prep IFSRH ;AC003; + invoke SET_THISIFS_UNC ; prep IFSRH ;AC003; + MOV ES:[BX.IFSR_CATEGORY],1 ;AC003; + MOV ES:[BX.IFSR_CTLFUNC],CTLFUNC_GET_UNC_ITEM ;AC003; + ;AC003; + MOV SI,OFFSET TEMPBUF ;AC003; + MOV WORD PTR ES:[BX.IFSR_BUFFER@],SI ;AC003; + MOV WORD PTR ES:[BX.IFSR_BUFFER@+2],DS ;AC003; + RestoreReg ; index ;AN003; + MOV WORD PTR DS:[SI],AX ;AN003; + +;*********************************************************************************************** + invoke CALL_IFS ; call redir w/get unc item request ;AC003; +;*********************************************************************************************** + + ;AC003; + JNC GUI_10 ;AC003; + RestoreReg ;AC003; + return ;AC003; +GUI_10: ;AC003; + MOV SI,WORD PTR ES:[BX.IFSR_BUFFER@] ;AC003; + MOV DS,WORD PTR ES:[BX.IFSR_BUFFER@+2] ;AC003; + SaveReg + ADD SI,2 ; space to user word (skip index) ;AN018; + LODSW ; user word ;AC003; + MOV CX,AX ;AC003; + LODSW ; max xmitt size ;AC003; + MOV DX,AX ;AC003; + LODSW ; net name id ;AC003; + PUSH AX ;AC003; + LODSW ; lsn ;AC003; + MOV BP,AX ;AC003; + LODSB ; redir bits ;AC003; + MOV BH,AL ;AC003; + MOV BL,4 ;AC003; + POP AX ; net name id ;AC003; + SaveReg ;AC003; + CallInstall Get_User_Stack,multDOS,24,, ;AC003; + MOV [SI].User_CX,CX ; User Word ;AC003; + MOV [SI].User_BX,BX ; Bits and macro type ;AC003; + MOV [SI].User_DX,DX ; Max Xmitt size ;AC003; + MOV [SI].User_AX,AX ; Net name ID ;AC003; + TEST CS:IFSPROC_FLAGS,SetBP ;AC003; + JZ GUI_15 ;AC003; + MOV [SI].User_BP,BP ; LSN ;AC003; +GUI_15: ;AN003; + RestoreReg + TEST IFSPROC_FLAGS,Filesys_status ;AC003; + JNZ GUI_20 ;AC003; + ADD SP,2 ; old si + RestoreReg ; buffer/target ptr (dssi - 18) ;AC003;;AC018; + SaveReg ;AC003;;AC008; + JMP SHORT GUI_40 ;AC003; + ;AC003; +GUI_20: ; new style ;AC003; + RestoreReg ; offset path + ADD SI,11 ;AC003; + RestoreReg ; target - dw fsname ;AC003; + ; dw # parms ;AC003; + ; db asciiz,... ;AC003; + SaveReg ;AC003; + MOV DI,ES:[DI] ;AC003; + invoke GET_UNC_FS_NAME ;AC003; + RestoreReg ;AC003; + SaveReg ;AC003; + INC DI ;AC003; + INC DI ;AC003; + MOV WORD PTR ES:[DI],1 ;AC003; + INC DI ;AC003; + INC DI ;AC003; + ;AC003; +GUI_40: ;AC003; + CallInstall StrCpy,MultDOS,17 ;AC003; + RestoreReg ;AC003; +;;;;;;;;TEST CS:IFSPROC_FLAGS,FILESYS_STATUS ;AN008;;AD018; +;;;;;;;;JZ GUI_1000 ;AN008;;AD018; + RestoreReg ;AN008; + +GUI_1000: + return ;AC003; + ;AC003; + ;AC003; +EndProc GET_UNC_ITEM_INFO ;AC003; + ;AN000; + +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CHECK_END_SPACE ;AN000; +; ;AN000; +; Called by: FIND_IFS_DRIVER ;AN000; +; ;AN000; +; Routines called: +; ;AN000; +; Inputs: ;AN000; +; ES:DI -> IFS driver name ;AN000; +; Function: ;AN000; +; Replace any blanks in asciiz ifs driver name with 0's. ;AN000; +; Output: ;AN000; +; none +; ;AN000; +; Regs: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure CHECK_END_SPACE ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save registers ;AN000; + RestoreReg ; set dssi -> asciiz ifs name ;AN000; + MOV SI,DI ;AN000; + CLD ; clear dir flag to count forward ;AN000; +CES_20: ; search LOOP ;AN000; + LODSB ; put char in al ;AN000; + OR AL,AL ; check for end of string ;AN000; + JZ CES_1000 ; if so go quit ;AN000; + CMP AL," " ; check for blank ;AN000; + JNE CES_20 ; cont loop if not ;AN000; + MOV BYTE PTR DS:[SI-1],0 ; replace blank with zero ;AN000; + ;AN000; + ;AN000; +CES_1000: ;AN000; + RestoreReg ; restore registers ;AN000; + return ;AN000; + ;AN000; +EndProc CHECK_END_SPACE ;AN000; + + ;AN000; + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/IFSUTIL.ASM b/v4.0/src/CMD/IFSFUNC/IFSUTIL.ASM new file mode 100644 index 0000000..7c9e303 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/IFSUTIL.ASM @@ -0,0 +1,2739 @@ + PAGE ,132 ;  ;AN000; +; SCCSID = @(#)ifsutil.asm 1.0 87/05/05 ;AN000; +TITLE IFSFUNC UTILITY ROUTINES - Routines for IFSFUNC ;AN000; +NAME IFSUTIL ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; Miscellaneous routines ;AN000; +; ;AN000; +; IFSFlushBuf ;AN000; +; IFS_UPDATE_CB (Part II) ;AN000; +; SERVER_DOSCALL_CLOSEFILES_FOR_UID ;AN000; +; SERVER_IFSFUNC_DATA_AREA ;AN000; +; DRIVE_FROM_CDS ;AN000; +; DRIVE_FROM_SFT ;AN000; +; PREP_IFSR ;AN000; +; CALL_IFS ;AN000; +; CREATE_DFL_ENTRY ;AN000; +;;;alias ENTER_NAMES_LIST ;AN000; +; DELETE_DFL_ENTRY ;AN000; +;;;alias EXIT_NAMES_LIST ;AN000; +; DFL_MATCH ;AN000; +; DFL_SINGLE_FILE_CHECK ;AN000; +;;;alias PROCESS_ALIAS ;AN000; +; CDS_TO_CD ;AN000; +; CD_TO_CDS ;AN000; +; DFL_TO_DF ;AN000; +; DF_TO_DFL ;AN000; +; SFT_TO_SFF ;AN000; +; SF_TO_SFT ;AN000; +; XCHGP ;AN000; +; CONSIST_SFT ;AN000; +; CONSIST_DFL ;AN000; +; PRN_CHECK ;AN000; +; IFSDrvFromCDS ;AN000; +; SET_THISIFS_UNC ;AN000; +; SET_CATEGORY ;AN000; +; SET_DEPIOCTL_IFSR ;AN000; +; GET_UNC_FS_NAME +; MOVE_DRIVER_NAME ;AN000; +; CONVERT_NAME_ASCIIZ ;AN000; +; CHECK_SEQ ;AN000; +; CHECK_REAL_DEVICE ;AN000; +; NET_TRANS ;AN000; +; STRIP_WFP_START +; CHECK_IFS_ATTRIBUTE +; CHECK_IFS_SUPPORT +; ;AN000; +; REVISION HISTORY: ;AN000; +; A000 Original version 4.00 May 1987 ;AN000; +; A001 P453 - Correct $NameTrans processing on connect part of string ;AN000; +; RGazzia Aug 25,1987 +; A002 D158 - merge redir info into attach stuff 8/87 RGazzia +; A003 P635 - read problem - sff-to-sft problem 8/87 RGazzia +; A004 P764 - printer attach problem 8/87 RGazzia +; A005 P845 - Disk reset infinitely calls 8/87 RGazzia +; A006 P868 - Lock problems 8/87 RGazzia +; A007 P849 - Printer open problems 8/87 RGazzia +; A008 P2307- Critical error problems 11/87 RGazzia +; A009 P2364- Chkdsk fails if afs loaded 11/87 RGazzia +; due to losing cx in flush buf loop +; A010 P2385- check for ifs support of multifile/device fcns 11/87 RGazzia +; A011 P2827- ifs driver error mapping 12/87 RGazzia +; A012 P3225- prn to lpt1 problems 1/88 RGazzia +; A013 P3251- Net trans buffer problems 1/88 RGazzia +; A014 P3692- detach of attached ptr problem 3/88 RGazzia +; A015 P3745- commit problem due to sft flags problem 3/88 RGazzia +; A016 P3810- new sff field - sft entry id 3/88 RGazzia +; A017 P3680- sft changes 3/88 RGazzia +; A018 P3883- Share violation problems 3/16/88 RMG +; A019 P3971- pause problems 3/24/88 RMG +; A020 P4055 Make sure THISDFL reset to null 3/30/88 RMG +; A021 P4172 share violation fail - wrong dos extended error 4/08/88 RMG +; A022 P4188 names=0 problems 4/08/88 RMG +; A023 P4227 Austin garbage attach problem 4/11/88 RMG +; A024 P4392 Yet another sft change 4/18/88 RMG +; A025 P4751 retry logic fix 5/05/88 RMG +; A026 P4802 NET821 retry hang/ fail hang 5/10/88 RMG +; A027 P4839 ctrl-prtsc problems (consist_sft) 5/13/88 RMG +; A028 P4863 criter/parms problem 5/14/88 RMG +; A029 P4968 I24 DI not set right 5/25/88 RMG +; A030 P5004 Cap of device name corrupted 6/01/88 RMG +; A031 P5006 ctrl prtsc problems - pause back to real 6/02/88 RMG +; consist_sft +; +; LOC - 696 +;************************************************************************************ ;AN000; + ;AN000; +.xlist ;AN000; +.xcref ;AN000; +INCLUDE IFSSYM.INC ;AN000; +INCLUDE IFSFSYM.INC ;AN000; +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +.cref ;AN000; +.list ;AN000; + ;AN000; +AsmVars ;AN000; + ;AN000; +; define the base code segment of the network support first ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; +IFSSEG ENDS ;AN000; + ;AN000; +; include the rest of the segment definitions for normal MSDOS ;AN000; + ;AN000; +include dosseg.asm ;AN000; + ;AN000; +DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; + ;DOSGROUP Data ;AN000; + Extrn sft_addr:DWORD ;AN000; + Extrn sftFCB:DWORD ;AN000; + Extrn WFP_START:WORD ;AN000; + Extrn THISCDS:DWORD ;AN000; + Extrn THISSFT:DWORD ;AN000; + Extrn CDSADDR:DWORD ;AN000; + Extrn CDSCOUNT:BYTE ;AN000; + Extrn CurrentPDB:WORD ;AN000; + Extrn RetryCount:WORD ;AN000; + Extrn SysInitTable:BYTE ;AN000; + Extrn CurrentPDB:WORD ;AN000; + Extrn IFS_HEADER:DWORD ;AN000; + Extrn NULDEV:DWORD ;AN000; + Extrn SWAP_AREA_TABLE:BYTE ;AN000; + Extrn EXTERR:WORD ;AN011; + Extrn EXTERR_ACTION:BYTE ;AN011; + Extrn EXTERR_CLASS:BYTE ;AN011; + Extrn EXTERR_LOCUS:BYTE ;AN011; + Extrn ALLOWED:BYTE ;AN011; + Extrn ErrMap24End:BYTE + Extrn ErrMap24:BYTE +if debug ;AN000; + Extrn BugLev:WORD ;AN000; + Extrn BugTyp:WORD ;AN000; + include bugtyp.asm ;AN000; +endif ;AN000; +DATA ENDS ;AN000; + ;AN000; +; define our own code segment ;AN000; + ;AN000; +IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; + ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; + ;AN000; + ;IFS Data ;AN000; + Extrn IFSPROC_FLAGS:WORD ;AN000; + Extrn IFSFUNC_FLAGS:WORD ;AN000; +;;;aliasExtrn NLAddr:DWORD ;AN000; + Extrn TEMPBUF:BYTE ;AN000; + Extrn DFLAddr:DWORD ;AN000; + Extrn DFLCount:BYTE ;AN000; + Extrn UNC_FS_HDR:DWORD ;AN000; + Extrn THISIFS:DWORD ;AN000; + Extrn THISDFL:DWORD ;AN000; + Extrn IFSR:WORD ;AN000; + Extrn CD1:WORD ;AN000; + Extrn DF1:WORD ;AN000; + Extrn SFF1:WORD ;AN000; + Extrn IFSDRV:BYTE ;AN000; + Extrn PHONEY_NAME:BYTE ;AN000; + Extrn DEVICE_CB@_OFFSET:WORD ;AN000; + Extrn SAVE_CB@:DWORD ;AN000; + Extrn IFSF_SWAP_START:BYTE ;AN000; + Extrn IFSF_SWAP_END:BYTE ;AN000; + ;AN000; + PUBLIC LPT1_NAME ;AN000; +LPT1_NAME DB "LPT1",0 ;AN000; +PRN_NAME DB "PRN",0 ;AN000; + ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN013; +; The following buffer was created 1/88 to temporarily hold canonicalized ;AN013; +; path name for $Nametrans call for Redir ;AN013; +; Some area of TEMPBUF should be used instead for optimized storage space but ;AN013; +; I didn't have time to research the best way to use it as time was short to ;AN013; +; fix ptm ;AN013; +; This buffer should later be taken out when time permits to do this right ;AN013; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN013; +NET_TRANS_BUFFER DB 128 DUP (0) ; temporary buffer used for $Nametrans ;AN013; + ; storage of canonicalized pathname ;AN013; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFSFlushBuf ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: CD_TO_CDS ;AN000; +; CDS_TO_CD ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Input: AL = 0 Flush all Net buffers. ;AN000; +; -1 " " " plus invalidate them. ;AN000; +; ;AN000; +; Function: ;AN000; +; FOR I = 1 to # CDSs ;AN000; +; DO ;AN000; +; IF CURDIR_ISIFS = true THEN ;AN000; +; DO ;AN000; +; Prepare IFSRH: ;AN000; +; * IFSR_LENGTH DW 40 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; + IFSR_RETCODE DW ? ;AN000; +; + IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 1 ; Drive Reset ;AN000; +; + IFSR_ERROR_CLASS DB ? ;AN000; +; + IFSR_ERROR_ACTION DB ? ;AN000; +; + IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; *+ IFSR_DEVICE_CB@ DD ? ; Call CDS_TO_CD to convert ;AN000; +; ; CDS to CD and set this as ;AN000; +; ; pointer to it. ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_FUNC DB ? ; 0 IF AL=0. 1 IF AL=-1. ;AN000; +; IFSR_RESV2 DB 0 ;AN000; +; ;AN000; +; CALL routine, CALL_IFS, with pointer to CURDIR_IFSR_HDR ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ;AN000; +; Output: None ;AN000; +; ;AN000; +; Notes: all destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure IFSFlushBuf,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DRIVERESET ;AN000; + ;AN000; + MOV CL,CDSCount ; CX = # CDS's ;AN000; + MOV DX,SIZE curdir_list ; DX = size CDS entry ;AN000; + LDS SI,[CDSAddr] ; Get addr 1st CDS ;AN000; + ;AN000; +IFB_20: ;AN000; + TEST DS:[SI.curdir_flags],curdir_isnet ;AN000; + JZ IFB_60 ;AN000; + ; Is IFS. Send drive reset request ;AN000; + invoke PREP_IFSR ; sets es:bx -> ifsr (zeroed out) ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_DRIVERESET ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSDRIVERESET ;AN000; + SaveReg ; save cds ptr ;AN000; + MOV CS:DEVICE_CB@_OFFSET,IFSR_DEVICE_CB@ ;AN000; + invoke CDS_TO_CD ;AN000; + MOV ES:[BX.IFSR_FUNC],AL ;AN000; + ;AN000; + SaveReg ; preserve loop count + invoke CALL_IFS ; Call IFS ;AN000; + RestoreReg ; retrieve loop count + JNC IFB_30 ;AN000; + RestoreReg ; restore cds ptr ;AN000; + JMP SHORT IFB_60 ;AN000; +IFB_30: ;AN000; + RestoreReg ; restore cds ptr into es:di ;AN000; + CALL CD_TO_CDS ; update CDS if retcode ok ;AN000; + PUSH ES ; get cds ptr into ds:si ;AN000; + POP DS ;AN000; + MOV SI,DI ;AN000; + ;AN000; +IFB_60: ;AN000; + ADD SI,DX ; Skip to next CDS ;AN000; + LOOP IFB_20 ;AN000; + JMP IFS_990 ;AN000; + ;AN000; +;*********************************************************************************** ;AN000; +; ifs common return area ;AN000; +;*********************************************************************************** ;AN000; + entry IFS_980 ;AN000; + STC ;AN000; + return ;AN000; + entry IFS_990 ;AN000; + CLC ;AN000; + entry IFS_1000 ;AN000; + return ;AN000; + ;AN000; + ;AN000; +EndProc IFSFlushBuf ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;****************************************************************************** ;AN000; +; ;AN000; +; IFS_UPDATE_CB ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher (Share) ;AN000; +; ;AN000; +; Routines called: ;AN000; +; SFT_TO_SFF ;AN000; +; SF_TO_SFT ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> SFT ;AN000; +; ;AN000; +; Function: ;AN000; +; Prep IFSRH: ;AN000; +; * IFS_LENGTH DW 28 ; Request length ;AN000; +; * IFS_FUNCTION DB 6 ; Control Block Update ;AN000; +; IFS_RETCODE DW ? ;AN000; +; IFS_RETCLASS DB ? ;AN000; +; IFS_RESV1 DB 16 DUP(0) ;AN000; +; * IFS_CB@ DD ? ; Control Block Address ;AN000; +; * IFS_TYPE DB ? ; Control Block Type ;AN000; +; IFSOPEN EQU 0 ; Open instnce (SFT) entry ;AN000; +; IFSCB EQU -1 ; See CB Type Field ;AN000; +; IFS_RESV2 DB 0 ;AN000; +; ;AN000; +; Call IFS specified in SFT ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Carry set on error. Error code in AX. ;AN000; +; ;AN000; +; Regs: ;AN000; +; ;AN000; +; Programming notes: ;AN000; +; ;AN000; +;****************************************************************************** ;AN000; + ;AN000; + procedure IFS_UPDATE_CB,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def UPDATECB ;AN000; + ; Reset ifsfunc processing flags ;AN000; + MOV CS:IFSPROC_FLAGS,ISCTLFCN+ISSFT ; Set this so SFT_TO_SFF sets ;AN000; + ; ifsr_cb@ instead of ifsr_open_cb@ ;AN000; + ; ISSFT set so sft_to_sff sets ;AN000; + ; thisifs ;AN000; + invoke PREP_IFSR ; sets es:bx -> ifsr (zeroed out) ;AN000; + Context DS ;AN000; + invoke SFT_TO_SFF ; SFT: sets [THISIFS] ;AN000; + ; ES:BX -> IFSRH ;AN000; + ; IFSR_CB@ ;AN000; + ; ds - IFSSEG ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_UPDATECB ; prep IFSRH ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSUPDATECB ;AN000; + MOV ES:[BX.IFSR_TYPE],IFSOPEN ;AN000; + ;AN000; + invoke CALL_IFS ;AN000; + JC ifs_1000 ; cf already set ;AN000; + invoke SFF_TO_SFT ;AN000; + JMP ifs_990 ;AN000; + ;AN000; +EndProc IFS_UPDATE_CB ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SERVER_DOSCALL_CLOSEFILES_FOR_UID ;AN000; +; ;AN000; +; Called by: IFSFUNC Dispatcher ;AN000; +; ;AN000; +; Routines called: ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [CurrentPDB] set to UID of user aborting ;AN000; +; Function: ;AN000; +; Get address of IFS driver chain. ;AN000; +; FOR I = 1 to last IFS driver ;AN000; +; Send request below to IFS driver ;AN000; +; ;AN000; +; IFSRH: ;AN000; +; * IFSR_LENGTH DW 40 ; Request length ;AN000; +; * IFSR_FUNCTION DB 4 ; Execute API function ;AN000; +; IFSR_RETCODE DW ? ;AN000; +; IFSR_RETCLASS DB ? ;AN000; +; IFSR_RESV1 DB 16 DUP(0) ;AN000; +; * IFSR_APIFUNC DB 19 ; End of Computer ID ;AN000; +; IFSR_ERROR_CLASS DB ? ;AN000; +; IFSR_ERROR_ACTION DB ? ;AN000; +; IFSR_ERROR_LOCUS DB ? ;AN000; +; + IFSR_ALLOWED DB ? ;AN000; +; + IFSR_I24_RETRY DB ? ;AN000; +; + IFSR_I24_RESP DB ? ;AN000; +; IFSR_RESV2 DB ? ;AN000; +; IFSR_DEVICE_CB@ DD ? ; CD ;AN000; +; IFSR_OPEN_CB@ DD ? ;AN000; +; * IFSR_UID DW ? ;AN000; +; ;AN000; +; Outputs: None ;AN000; +; ;AN000; +; Regs: All destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SERVER_DOSCALL_CLOSEFILES_FOR_UID,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def EOCID ;AN000; + ;AN000; + LDS SI,IFS_HEADER ; get 1st ifs driver ;AN000; +ASSUME DS:NOTHING ;AN000; + ;AN000; +SDC_20: ; ** Loop here on ifs drivers ;AN000; + MOV CS:WORD PTR [THISIFS],SI ; Send end of process request ;AN000; + MOV CS:WORD PTR [THISIFS+2],DS ; to all fs drivers. ;AN000; + ; Set thisifs for call_ifs ;AN000; + invoke PREP_IFSR ; sets es:bx -> ifsr (zeroed out) ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_EOCID ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSEOCID ;AN000; + MOV AX,[CurrentPDB] ;AN000; + MOV ES:[BX.IFSR_UID],AX ;AN000; + ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; +ASSUME DS:IFSSEG ; ds - ifsseg ;AN000; + ;AN000; + invoke CALL_IFS ;AN000; + ;AN000; + RestoreReg ; ds - fs driver ;AN000; + LDS SI,[SI.IFS_NEXT] ; Do next fs driver ;AN000; + CMP SI,NULL_PTR ; if ptr null, no more ;AN000; + JNE SDC_20 ;AN000; + PUSH DS ;AN000; + POP AX ;AN000; + CMP AX,NULL_PTR ;AN000; + JNE SDC_20 ;AN000; + ;AN000; + jmp ifs_1000 ; go return ;AN000; + ;AN000; + ;AN000; +EndProc SERVER_DOSCALL_CLOSEFILES_FOR_UID ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SERVER_IFSFUNC_DATA_AREA ;AN000; +; ;AN000; +; Called by: Dispatcher ;AN000; +; ;AN000; +; Routines called: None ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS - DOSGroup ;AN000; +; ;AN000; +; Function: ;AN000; +; Put IFSFUNC swappable data area info in ibmdos's swap_area_table +; ;AN000; +; Outputs: ;AN000; +; swap_area_table filled in: ;AN000; +; dw num areas - 3 ;AN000; +; dd ibmdos swap indos area address +; dw ibmdos swap indos area length +; dd ibmdos swap always area address +; dw ibmdos swap always area length +; dd ifsfunc swap indos area address +; dw ifsfunc swap indos area length +; ;AN000; +; Regs: All preserved +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SERVER_IFSFUNC_DATA_AREA,NEAR ;AN000; +ASSUME DS:DOSGROUP,ES:NOTHING ;AN000; + ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + MOV DI,OFFSET CS:IFSF_SWAP_START ;AN000; + MOV DX,OFFSET CS:IFSF_SWAP_END ;AN000; + SUB DX,DI ;AN000; + LEA SI,SWAP_AREA_TABLE ; get offset address of swap area table ;AN000; + + MOV WORD PTR DS:[SI],3 ; number of data areas increased from 2 to 3 ;AN000; + ADD SI,14 ; skip to ifsfunc area ;AN000; + MOV WORD PTR DS:[SI],DI ; fill in ifsfunc data area address ;AN000; + MOV WORD PTR DS:[SI+2],ES ;AN000; + MOV WORD PTR DS:[SI+4],DX ; fill in ifsfunc data area length ;AN000; + ;AN000; + RestoreReg ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc SERVER_IFSFUNC_DATA_AREA ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; + procedure DRIVE_FROM_CDS,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DRIVE_FROM_CDS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISCDS] Set ;AN000; +; DS - DOSGROUP ;AN000; +; Function: ;AN000; +; Compute drive letter from THISCDS ;AN000; +; Outputs: ;AN000; +; [IFSDRV] = Drive # (0=A) ;AN000; +; No registers Revised ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + PUSH BX ;AN000; + PUSH AX ;AN000; + MOV [IFSDRV],0FEH ; Default to ?, 0FEH + 'A' = '?' ;AN000; + MOV AX,WORD PTR [THISCDS] ;AN000; + CMP AX,-1 ;AN000; + JZ DFC_20 ;AN000; + CALL IFSDrvFromCDS ;AN000; +DFC_20: ;AN000; + POP AX ;AN000; + POP BX ;AN000; + jmp ifs_1000 ; go return ;AN000; + ;AN000; +EndProc DRIVE_FROM_CDS ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DRIVE_FROM_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISSFT] Set DS-Dosgroup ;AN000; +; Function: ;AN000; +; Compute drive letter from THISSFT ;AN000; +; Outputs: ;AN000; +; [IFSDRV] = Drive # (0=A) ;AN000; +; [IFSDRV] = -1 if printer ;AN000; +; PHONEY_NAME ;AN000; +; No registers Revised ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure DRIVE_FROM_SFT,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ;AC006; + LDS BX,[THISSFT] ;AN000; + TEST [BX.sf_flags],sf_net_spool ;AN000; + JNZ DFS_100 ;AN000; + MOV BL,BYTE PTR [BX.sf_flags] ;AN000; + AND BL,devid_file_mask_drive ;AN000; + CMP BL,0FEH AND devid_file_mask_drive ; UNC ???? ;AN000; + JNZ DFS_20 ; No ;AN000; + MOV BL,0FEH ; Restore lost bits if UNC ;AN000; +DFS_20: ;AN000; + MOV [IFSDRV],BL ;AN000; + RestoreReg ;AC006; + JMP ifs_1000 ; go return ;AN000; + ;AN000; +DFS_100: ;AN000; + SaveReg ;AN000; + MOV DI,OFFSET CS:[PHONEY_NAME] ; Set name for I24 handler ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; + MOV SI,BX ;AN000; + ADD SI,SF_NAME ;AN000; + MOV CX,8 ;AC007; + REP MOVSB ;AN000; + ;AN000; + RestoreReg ;AN000; + MOV BL,-1 ;AN000; + JMP DFS_20 ;AN000; + ;AN000; +EndProc DRIVE_FROM_SFT ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; PREP_IFSR ;AN000; +; ;AN000; +; Called by: all function routines ;AN000; +; ;AN000; +; Inputs: none ;AN000; +; ;AN000; +; Function: ;AN000; +; set all ifsrh fields to zero ;AN000; +; ;AN000; +; Outputs: ;AN000; +; ES:BX -> IFSRH ;AN000; +; ;AN000; +; Regs: all except ES,BX saved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure PREP_IFSR,NEAR ;AN000; + ;AN000; + SaveReg ; save regs ;AN000; + ;AN000; + SaveReg ; get ds,es -> ifsseg ;AN000; + RestoreReg ;AN000; +ASSUME DS:IFSSEG,ES:IFSSEG ;AN000; + ;AN000; + MOV DI,OFFSET IFSR ; es:di -> ifsrh ;AN000; + MOV BX,DI ; es:bx -> ifsrh ;AN000; + MOV CX,SIZE IFSRH /2 ;AN000; + XOR AX,AX ;AN000; + REP STOSW ; fill ifsr w/zeros ;AN000; + ;AN000; + RestoreReg ; restore regs ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc PREP_IFSR ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CALL_IFS ;AN000; +; ;AN000; +; Called by: all function routines ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISIFS] set ;AN000; +; ES:BX -> IFS request header ;AN000; +; DS - IFSSEG ;AN000; +; ;AN000; +; Function: ;AN000; +; Call file system function entry point ;AN000; +; ;AN000; +; Outputs: ;AN000; +; Outputs of call ;AN000; +; ;AN000; +; Regs: none preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CALL_IFS,NEAR ;AN000; + ;AN000; + CALL CHECK_IFS_SUPPORT ; 1st check if this request ok for ifs ;AN010; + PUSH WORD PTR [THISIFS] ; save thisifs offset ;AN000; + + CALL SET_CATEGORY ; do this to determine unc or ifs ;AN000; + OR CL,CL ; cl-1 for unc, 0 for ifs ;AN000; + JNZ CI_05 ;AN000; + invoke EcritIFS ; enter ifs critical section ;AN000; + JMP SHORT CI_10 ;AN000; +CI_05: ;AN000; + invoke EcritNET ; enter network critical section ;AN000; + +CI_10: + LDS SI,[THISIFS] ; set thisifs=fs driver fcn entry pt ;AN000; + MOV AX,DS:[SI.IFS_CALL@] ; offset=contents of ifs_call@ ;AN000; + ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + MOV WORD PTR [THISIFS],AX ;AN000; + PUSH CX ; save this for later unc vs. ifs check ;AN000; +;---------------------------------------------------------------------------- ;AN000; + CALL [THISIFS] ; call fs driver with request ;AN000; +;---------------------------------------------------------------------------- ;AN000; + POP CX ; unc or ifs result ;AN000; + POP WORD PTR [THISIFS] ; restore thisifs offset ;AN000; + + OR CL,CL ; again, determine whether to exit ifs ;AN000; + JNZ CI_15 ; or unc critical section ;AN000; + invoke LcritIFS ; leave ifs critical section ;AN000; + JMP SHORT CI_17 ;AN000; +CI_15: ;AN000; + invoke LcritNET ; leave network critical section ;AN000; + +CI_17: ;AN000; + MOV AL,ES:[BX.IFSR_RETCLASS] ; check for error (class) ;AN000; + CMP AL,IFSR_NO_ERROR ; (any err must have class set) ;AN000; + JNE CI_20 ;AN000; + JMP ifs_990 ; no error, go ret no carry ;AN000; + ;AN000; +;-----------------------------------------------; error processing ;AN000; +CI_20: ;AN000; + TEST IFSPROC_FLAGS,IsInit ; if in init code, skip error proc ;AN011; + JZ CI_22 ;AN011; + JMP ifs_980 ; init error- just go stc and quit ;AN011; +CI_22: ;AN011; + CMP AL,IFSR_INT21H_CRITER ; critical error? ;AN000; + JE CI_23 ;AN029; + JMP CI_30 ;AC029; +CI_23: ;AN029; + MOV AX,ES:[BX.IFSR_RETCODE] ; put retcode in al before condition ;AN000; + + + CMP AX,error_write_protect ;AN029; + JB NO_UNMAP ;AN029; + CMP AX,error_gen_failure ;AN029; + JA NO_UNMAP ;AN029; + SUB AX,error_write_protect ; BIAS old errors back down into 0-12 range ;AN029; +NO_UNMAP: ;AN029; + PUSH DS ;AN029; + Context DS ;AN029; +ASSUME DS:DOSGROUP ;AN029; + MOV DI,AX ;AN029; + MOV AX,OFFSET DOSGroup:ErrMap24End ;AN029; + SUB AX,OFFSET DOSGroup:ErrMap24 ;AN029; +; ;AN029; +; AX is the index of the first unavailable error. Do not translate if ;AN029; +; greater or equal to AX. ;AN029; +; ;AN029; + CMP DI,AX ;AN029; + MOV AX,DI ;AN029; + JAE NoTrans ;AN029; + MOV AL,ErrMap24[DI] ;AN029; + XOR AH,AH ;AN029; +NoTrans: ;AN029; + POP DS + invoke SET_EXTERR_INFO ; yes - set error info ;AN000; + +CI_25: ;AN011; + SaveReg ; temporarily save ifsr in tempbuf over ;AN008; + SaveReg ; next call ;AN008; + RestoreReg ; Set dssi -> ifsr (current esbx) ;AN008; + MOV SI,BX ;AN008; + MOV CX,36 ; half size of max ifsr ;AN008; + MOV DI,OFFSET TEMPBUF ; set esdi -> tempbuf ;AN008; + CLD ; next instr auto-increment ;AN008; + REP MOVSW ; copy the ifsr over (word move) ;AN008; + MOV AX,CS:IFSPROC_FLAGS ; preserve ifsproc_flags ;AN026; + STOSW ;AN026; + RestoreReg ; restore regs ;AN008; + + CMP DI,error_I24_gen_failure ;AN029; + JBE CI_26 ;AN029; + MOV DI,error_I24_gen_failure ;AN029; +CI_26: ;AN029; + SaveReg ; preserve dos ext err ;AN021; + invoke IFS_I24 ; do int 24h ;AN000; + + SaveReg ; restore original ifsr (over criter one);AN008; + SaveReg ; set dssi -> tempbuf ;AN008; + RestoreReg ; set esdi -> ifsr ;AN008; + MOV SI,OFFSET TEMPBUF ; ;AN008; + MOV DI,OFFSET IFSR ; ;AN008; + MOV CX,36 ; half size of max ifsr ;AN008; + CLD ; next instr auto-increment ;AN008; + REP MOVSW ; copy the ifsr over (word move) ;AN008; + LODSW ; restore ifsproc_flags ;AN026; + MOV CS:IFSPROC_FLAGS,AX ; ;AN026; + RestoreReg ; restore regs ;AN008; + + CMP AL,RETRY ; if retry, restart request ;AN000; + JE CI_27 ; else, go ret w/carry ;AC011; + RestoreReg ; retrieve dos ext err ;AN021;;AM025; + JMP ifs_980 ;AN000; +CI_27: ;AN011; + ADD SP,2 ; restore stack (dos ext error #) ;AN025; + JMP CI_80 ;AN011; + ;AN000; +CI_30: ; not critical error: ;AN000; + CMP AL,IFSR_BAD_FORMAT ; map ifsr bad format error to general ;AN011; + JNE CI_32 ; failure (12) critical error ;AN011; + MOV AL,12 + MOV SS:[EXTERR],31 ; set dos error variables for abort ;AN011; + MOV SS:[EXTERR_CLASS],4 ; (Internal) ;AN011; + MOV SS:[EXTERR_ACTION],4 ; (Abort) ;AN011; + MOV SS:[EXTERR_LOCUS],1 ; (Unknown) ;AN011; + MOV SS:[ALLOWED],08H ; allow only fail ;AN011; + MOV DI,AX ;AN029; + JMP CI_25 ; go back & treat as critical error ;AN011; +CI_32: ;AN011; + CMP AL,IFSR_DRIVER_ERROR ;AN011; + JNE CI_37 ;AC011; + MOV AX,ES:[BX.IFSR_RETCODE] ; *** driver error class *** ;AN011; + CMP AX,IFSR_NO_FCN_SUPPORT ;AN011; + JG CI_34 ;AN011; + MOV AX,50 ; request not supported by file system ;AN011; + JMP CI_100 ;AN011; +CI_34: ;AN011; + CMP AX,IFSR_ACCESS_DENIED ;AN011; + JNE CI_35 ;AN011; + MOV AX,65 ; access denied by file system ;AN011; + JMP CI_100 ;AN011; +CI_35: ;AN011; + CMP AX,IFSR_DEVICE_TYPE_MISMATCH ;AN011; + JNE CI_36 ;AN011; + MOV AX,66 ; file sytem device type incorrect ;AN011; + JMP CI_100 ;AN011; +CI_36: ;AN011; + MOV AX,59 ; fs experienced an unexpected error ;AN011; + JMP CI_100 ;AN011; + +CI_37: ;AN011; + CMP AL,IFSR_DEVICE_ERROR ; fs got device error ;AN011; + JNE CI_38 ;AN011; + MOV AX,ES:[BX.IFSR_RETCODE] ;AN011; + invoke DEVICE2EXTERR ; convert device - ext error ;AN011; + JMP CI_100 ; go set class/action/locus ;AN011; +CI_38: ;AN011; + MOV AX,ES:[BX.IFSR_RETCODE] ;AN011; + CMP AX,error_sharing_violation ;AN000; + JNZ CI_100 ;AN000; + ;AN000; + SaveReg ; save ifsseg ;AN018; + Context DS ; Share error ;AN000; + invoke PHONEY_DPB ; Set phoney NET DPB for INT 24 ;AN000; + CMP ES:[BX.IFSR_APIFUNC],IFSOPENFILE ; on open/create - share error,no int24 ;AN018; + JNE CI_39 ;AN018; + CallInstall SHARE_ERROR,MultDOS,11 ;AN018; + JMP SHORT CI_39_20 ;AN018; +CI_39: ;AN018; + CallInstall SHARE_VIOLATION,MultDOS,10 ;AN000; +CI_39_20: ;AN018; + RestoreReg ;AN018; + ;AN000; + JNC CI_40 ;AN000; + MOV AX,error_sharing_violation ; carry set - quit w/error ;AN000; + invoke SET_EXTERR_INFO ;AN000; + JMP ifs_980 ;AN000; + ;AN000; +CI_40: ; carry clear - retry ;AN000; + MOV AL,RETRY ;AN000; + +CI_80: ;AN000; + INC ES:[BX.IFSR_I24_COUNT] ; retry: inc retry count ;AN000; + MOV ES:[BX.IFSR_I24_RESP],AL ; store i24 response ;AN000; + MOV ES:[BX.IFSR_RETCODE],0 ; reset retcode and class ;AN008; + MOV ES:[BX.IFSR_RETCLASS],0 ;AN008; + MOV ES:[BX.IFSR_ERROR_CLASS],0 ; reset retcode and class ;AN025; + MOV ES:[BX.IFSR_ERROR_ACTION],0 ;AN025; + MOV ES:[BX.IFSR_ERROR_LOCUS],0 ; reset retcode and class ;AN025; + MOV ES:[BX.IFSR_ALLOWED],0 ;AN025; + SaveReg ; restore ds-ifsseg ;AN000; + RestoreReg ;AN000; +ASSUME DS:IFSSEG ;AN000; + JMP CALL_IFS ;AN000; + ;AN000; +CI_100: ; non-critical error ;AN000; + TEST CS:IFSPROC_FLAGS,IsMsgRet ; if msg ret call to int 2f-5 stack ;AN028; + JNZ CI_120 ; not dosgroup so can't call next ;AN028; + CALL SET_EXTERR_INFO ; set exterr info and ;AN000; +CI_120: ;AN028; + JMP ifs_980 ; go ret w/carry ;AN000; + ;AN000; + ;AN000; +EndProc CALL_IFS ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CREATE_DFL_ENTRY ;AN000; +; ;AN000; +; Routine called by: ATTACH_START ;AN000; +; PROCESS_ALIAS ;AN000; +; ;AN000; +; Routines called: DFL_TO_DF ;AN000; +; ENTER_NAMES_LIST ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISIFS] set ;AN000; +; BL = macro type ;AN000; +; CX = user word +; DS:SI -> ASCIIZ device name ;AN000; +; ES:DI -> Target driver to attach to and parms. ;AN000; +; DW ASCIIZ - FS name ;AN000; +; DW n - number of parms ;AN000; +; DB ASCIIZ,... parms ;AN000; +; ;AN000; +; Function: ;AN000; +; WHILE DFL entries ;AN000; +; IF entry not in use THEN ;AN000; +; DO ;AN000; +; Set in progress flag for this entry ;AN000; +; DFL_TYPE = BL ;AN000; +; DFL_DEV_NAME = name pointed to by DS:SI ;AN000; +; DFL_USER_WORD = CX +; IF alias, Call ENTER_NAMES_LIST ;AN000; +; DFL_IFS_HDR = [THISIFS] ;AN000; +; Set in use flag ;AN000; +; Reset in progress flag ;AN000; +; Set [THISDFL] ;AN000; +; Call DFL_TO_DF ;AN000; +; LEAVE WHILE ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; Get next DFL entry ;AN000; +; IF no entry THEN ;AN000; +; Set error_out_of_structures ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDWHILE ;AN000; +; ;AN000; +; Outputs: ;AN000; +; carry clear: ;AN000; +; DFL entry created. Names list addition if alias. ;AN000; +; [THISDFL] set ;AN000; +; DS:SI -> DFL ;AN000; +; If not alias: ;AN000; +; DF loaded ;AN000; +; ES:BX -> IFSRH ;AN000; +; IFSR_DEVICE_CB@ -> DF ;AN000; +; ;AN000; +; carry set on error, ax - error ;AN000; +; ;AN000; +; Regs: DS:SI -> DFL, all others destroyed ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CREATE_DFL_ENTRY,NEAR ;AN000; + ;AN000; + SaveReg ; save input DS:SI (devname) ;AN000; + MOV DX,CX ; save user word in dx ;AN002; + ;AN000; + LDS SI,CS:[DFLAddr] ; Set DS:SI -> 1st DFL entry ;AN000; + MOV CL,CS:DFLCount ; CX = # DFL entries ;AN000; + OR CL,CL ; check for available dfl structure ;AN022; + JZ CDE_30 + XOR CH,CH ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + CALL CONSIST_DFL ; reset all in_prog flags ;AN000; +CDE_20: ;AN000; + TEST [SI.DFLL_FLAGS],DFL_INUSE ; look for unused DFL ;AN000; + JZ CDE_40 ; entry ;AN000; + ADD SI,SIZE DFLL_LIST ;AN000; + LOOP CDE_20 ;AN000; +CDE_30: + MOV AX,error_out_of_structures ;AN000; + RestoreReg ; restore stack ;AN000; + JMP ifs_980 ; go return w/carry ;AN000; +CDE_40: ;AN000; + CALL INIT_DFL ; zero out dfl entry ;AN000; + OR [SI.DFLL_FLAGS],DFL_INPROG ; Found DFL entry - ;AN000; + ; Set in progress flag ;AN000; + MOV [SI.DFLL_TYPE],BL ; Store DFL_TYPE ;AN000; + MOV [SI.DFLL_USER_WORD],DX ; store user word ;AN002; + ;AN000; + RestoreReg ; get dev name ptr off stack ;AN000; + CALL XCHGP ; Set DS:SI -> devname ;AN000; + PUSH DI ; ES:DI -> DFL ;AN000; + ; save dfl start offset ;AN000; +CDE_60: ;AN000; + INC DI ; mov di to dfl_dev_name ;AN000; + INC DI ;AN000; + MOV CX,8 ; Devs max of 8 ch and ':', and a NUL ;AN000; +CDE_70: ; dssi->source, esdi->dfl_dev_name ;AN000; + LODSB ; just store 1st 8 padded to right ;AN000; + CallInstall UCase,multDOS,19,, ; w/blanks ;AC030; ax chg to bx + OR AL,AL ; 0 . : signal end ;AN000; + JZ CDE_73 ;AN000; + CMP AL,'.' ;AN000; + JZ CDE_73 ;AN000; + CMP AL,':' ;AN000; + JZ CDE_73 ;AN000; + STOSB ;AN000; + LOOP CDE_70 ;AN000; + JMP SHORT CDE_80 ;AN000; +CDE_73: ;AN000; + MOV AL," " ;AN000; +CDE_76: ;AN000; + STOSB ;AN000; + LOOP CDE_76 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;;;aliasCMP BL,TYPE_ALIAS ;AN000; +;;;;;;;;JNE CDE_80 ;AN000; +;;;;;;;;CALL ENTER_NAMES_LIST ; Store alias index ;AN000; +;;;;;;;;JNC CDE_120 ;AN000; +;;;;;;;;POP DI ; if error back out ;AN000; +;;;;;;;;AND [SI.DFLL_FLAGS],NOT DFL_INPROG ; go exit with carry ;AN000; +;;;aliasJMP ifs_980 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +CDE_80: ;AN000; + ADD DI,4 ; skip alias index and user wd ;AC004; +;;;; INC DI ;AD004; +CDE_100: ;AN000; + MOV AX,WORD PTR [THISIFS] ;AN000; + STOSW ; Set DFL_IFS_HDR to ;AN000; + MOV AX,WORD PTR [THISIFS+2] ; [THISIFS] ;AN000; + STOSW ;AN000; +CDE_120: ;AN000; + POP DI ; retrieve dfl start ;AN000; + MOV WORD PTR CS:[THISDFL],DI ; Set [thisdfl] ;AN000; + MOV WORD PTR CS:[THISDFL+2],ES ;AN000; + ;AN000; + PUSH ES ; Set DS:SI -> DFL ;AN000; + POP DS ;AN000; + MOV SI,DI ;AN000; + ;AN000; + CALL CHECK_REAL_DEVICE ; this will set dfl_dev_real ;AN000; + ;AN000; + OR [SI.DFLL_FLAGS],DFL_INUSE ;AN000; + AND [SI.DFLL_FLAGS],NOT DFL_INPROG ;AN000; + ;AN000; +;;;aliasCMP BL,TYPE_ALIAS ;AN000; +;;;aliasJNE CDE_140 ;AN000; +;;;aliasJMP ifs_990 ; go ret no carry ;AN000; +CDE_140: ;AN000; + invoke PREP_IFSR ; init req hdr ;AN000; + invoke DFL_TO_DF ;AN000; + JMP ifs_990 ;AN000; + ;AN000; +EndProc CREATE_DFL_ENTRY ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DELETE_DFL_ENTRY ;AN000; +; ;AN000; +; Routine called by: IFS_ASSOPER ;AN000; +; ;AN000; +; Routines called: ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISDFL] set ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Outputs: ;AN000; +; carry clear: ;AN000; +; DFL entry deleted. ;AN000; +; carry set on error, ax - error ;AN000; +; ;AN000; +; Regs: everything preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure DELETE_DFL_ENTRY,NEAR ;AN000; + ;AN000; + LDS SI,[THISDFL] ; simply reset in_use bit ;AN000; + AND DS:[SI.DFLL_FLAGS],NOT DFL_INUSE ;AN000; +;;;aliasCMP DS:[SI.DFLL_TYPE],TYPE_ALIAS ; if alias, must remove name ;AN000; +;;;aliasJE DDE_20 ; from names list, and reset ;AN000; + JMP ifs_1000 ;AN000; +;;;aliasDDE_20: ;AN000; +;;;aliasCALL EXIT_NAMES_LIST ; all alias indicies ;AN000; +;;;aliasJMP ifs_1000 ;AN000; + ;AN000; +EndProc DELETE_DFL_ENTRY ;AN000; + ;AN000; +;BREAK ;AN000; +;;;alias ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; ENTER_NAMES_LIST ;AN000; +; ;AN000; +; Routine called by: CREATE_DFL_ENTRY ;AN000; +; ;AN000; +; Routines called: DOS: DStrLen ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> DFL ;AN000; +; ES:DI -> Target driver to attach to and parms. ;AN000; +; DW ASCIIZ - FS name ;AN000; +; DW n - number of parms ;AN000; +; DB ASCIIZ,... parms ;AN000; +; Function: ;AN000; +; Place one and only parameter (alias) into names list. ;AN000; +; Outputs: ;AN000; +; carry clear: name added ;AN000; +; carry set: AX error ;AN000; +; ;AN000; +; Notes: all preserved except AX ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; procedure ENTER_NAMES_LIST ;AN000; +;SSUME DS:IFSSEG,ES:IFSSEG ;AN000; +; ;AN000; +; SaveReg ;AN000; +; PUSH ES ;AN000; +; POP DS ;AN000; +; MOV SI,DI ;AN000; +; ADD SI,4 ; ds:si -> alias name ;AN000; +; CallInstall DStrlen,multDOS,37 ; get size of alias name in cx ;AN000; +; LES DI,[NLAddr] ; get address of names list ;AN000; +; MOV DX,WORD PTR ES:[DI] ; DX=total size of names list ;AN000; +; INC DI ;AN000; +; INC DI ;AN000; +; MOV AX,WORD PTR ES:[DI] ; AX=used size of names list ;AN000; +; PUSH AX ; save used size for dfl_alias_index ;AN000; +; ADD AX,CX ; AX=hopefully new used size ;AN000; +; CMP DX,AX ; check that new string fits ;AN000; +; JAE ENL_20 ;AN000; +; MOV AX,error_out_of_structures ; error - doesn't fit ;AN000; +; JMP ENL_980 ; ret w/carry ;AN000; +;NL_20: ; ok - fits ;AN000; +; STOSW ; store new used size ;AN000; +; POP AX ; get index from stack ;AN000; +; PUSH AX ;AN000; +; INC DI ;AN000; +; INC DI ;AN000; +; ADD DI,AX ; Space to spot in list to put name ;AN000; +; REP MOVSB ;AN000; +; RestoreReg ; Set dfl alias index to byte offset ;AN000; +; POP AX ; (+4) of name in list ;AN000; +; MOV DS:WORD PTR [SI.DFL_ALIAS_INDEX],AX ;AN000; +; JMP ENL_990 ; go ret no carry ;AN000; +; ;AN000; +; ;AN000; +;NL_980: ; Return area ;AN000; +; STC ; error ;AN000; +; RestoreReg ;AN000; +; return ;AN000; +;NL_990: ;AN000; +; CLC ; no error ;AN000; +; RestoreReg ;AN000; +;NL_1000: ;AN000; +; return ;AN000; +; ;AN000; +; ;AN000; +;ndProc ENTER_NAMES_LIST ;AN000; +; ;AN000; +; ;AN000; +;REAK ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; EXIT_NAMES_LIST ;AN000; +; ;AN000; +; Routine called by: DELETE_DFL_ENTRY ;AN000; +; ;AN000; +; Routines called: DOS: StrLen ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> DFL ;AN000; +; ;AN000; +; Function: ;AN000; +; Remove alias name from Names List ;AN000; +; Outputs: ;AN000; +; name removed ;AN000; +; ;AN000; +; Notes: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; procedure EXIT_NAMES_LIST ;AN000; +;SSUME DS:IFSSEG,ES:IFSSEG ;AN000; +; ;AN000; +; MOV DX,DS:[SI.DFL_ALIAS_INDEX] ; DX=index ;AN000; +; LES DI,[NLAddr] ;AN000; +; MOV AX,ES:WORD PTR [DI+2] ; AX=used size ;AN000; +; SaveReg ;AN000; +; ADD DI,DX+4 ;AN000; +; CallInstall StrLen,multDOS,18 ; CX=size of alias name ;AN000; +; PUSH ES ;AN000; +; POP DS ;AN000; +; MOV SI,DI ;AN000; +; ADD SI,CX ;AN000; +; MOV BX,CX ;AN000; +; SUB AX,SI ; CX= #bytes to move = ;AN000; +; MOV CX,AX ; used size - index of next name ;AN000; +; REP MOVSB ; move names up ;AN000; +; ;AN000; +; RestoreReg ; adjust used size ;AN000; +; SUB AX,BX ;AN000; +; MOV ES:WORD PTR [DI+2],AX ;AN000; +; ;AN000; +; LDS SI,[DFLAddr] ; loop thru all dfl entries to ;AN000; +; MOV DI,SIZE DFL_LIST ; adjust alias indicies above ;AN000; +; MOV CL,[DFLCount] ; index removed ;AN000; +; XOR CH,CH ;AN000; +;XNL_20: ; ** Loop here on dfl entries ;AN000; +; TEST DS:[SI.DFLL_FLAGS],DFL_INUSE ;AN000; +; JZ EXNL_40 ;AN000; +; MOV AX,DS:[SI.DFL_ALIAS_INDEX] ; 0 if not alias ;AN000; +; CMP AX,DX ;AN000; +; JB EXNL_40 ;AN000; +; SUB AX,BX ; adjust by size of name deleted ;AN000; +; MOV DS:[SI.DFL_ALIAS_INDEX],AX ;AN000; +;XNL_40: ;AN000; +; ADD SI,DX ;AN000; +; LOOP EXNL_20 ;AN000; +; ;AN000; +; JMP ifs_1000 ; go return ;AN000; +; ;AN000; +; ;AN000; +;ndProc EXIT_NAMES_LIST ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DFL_SINGLE_FILE_CHECK ;AN000; +; ;AN000; +; Routine called by: IFS_FILE_ATTRIBUTES ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISDFL] ;AN000; +; [WFP_START] ;AN000; +; ;AN000; +; Function: ;AN000; +; IF [THISDFL] .NOT. NULL THEN ;AN000; +; DO ;AN000; +; Get IFS header from DFL_IFS_HDR ;AN000; +; IF IFSDEVICE true THEN ;AN000; +; DO ;AN000; +; Call DFL_TO_DF ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE Set error - device doesn't support single file fcn ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ELSE DO ;AN000; +; CALL DFL_MATCH ;AN000; +; IF match found THEN ;AN000; +; DO ;AN000; +; Get IFS header from DFL_IFS_HDR ;AN000; +; IF IFSDEVICE true THEN ;AN000; +; DO ;AN000; +; Call DFL_TO_DF ;AN000; +; Clear carry ;AN000; +; ENDDO ;AN000; +; ELSE Set error - device doesn't support single file fcn ;AN000; +; ENDDO ;AN000; +; ELSE Set error - device not IFS ;AN000; +; ENDIF ;AN000; +; ENDDO ;AN000; +; ENDIF ;AN000; +; ;AN000; +; ;AN000; +; Outputs: ;AN000; +; no carry: carry: error ;AN000; +; [THISIFS] set ;AN000; +; ES:BX -> IFSRH ;AN000; +; IFSR_DEVICE_CB@ ;AN000; +; ds - IFSSEG ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure DFL_SINGLE_FILE_CHECK ;AN000; +ASSUME DS:IFSSEG,ES:IFSSEG ;AN000; +;; assume thisdfl aready set up here ;AN000; +;; don't want to write another parse routine ;AN000; +;; CMP WORD PTR [THISDFL],MINUS_ONE ;AN000; +;; JNZ DSFC_20 ;AN000; +;; CALL DFL_MATCH ; check for dfl entry ;AN000; +;; JNC DSFC_20 ;AN000; +;; MOV AX,error_not_ifs_device ;AN000; +;; JMP ifs_1000 ;AN000; + ;AN000; +DSFC_20: ;AN000; + LES DI,CS:[THISDFL] ;AN000; + LES DI,ES:[DI.DFLL_IFS_HDR] ; check that ifs device supports ;AN000; + TEST ES:[DI.IFS_ATTRIBUTE],IFSDEVICE ; single file function ;AN000; + JNZ DSFC_60 ;AN000; + MOV AX,error_file_not_found ; no - set error & go return w/carry ;AN000; + JMP ifs_980 ;AN000; +DSFC_60: ;AN000; + invoke DFL_TO_DF ;AN000; + JMP ifs_990 ;AN000; + ;AN000; + ;AN000; +EndProc DFL_SINGLE_FILE_CHECK ;AN000; + ;AN000; +;BREAK ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; PROCESS_ALIAS ;AN000; +; ;AN000; +; Called by: ATTACH_START ;AN000; +; ;AN000; +; Routines called: DFL_MATCH ;AN000; +; CREATE_DFL_ENTRY ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> ASCIIZ source name ;AN000; +; ES:DI -> ALIAS name ;AN000; +; ;AN000; +; Function: ;AN000; +; ;AN000; +; Regs: ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; Procedure PROCESS_ALIAS,NEAR ;AN000; +;SSUME DS:NOTHING,ES:NOTHING ;AN000; +; ;AN000; +; CALL DFL_MATCH ;AN000; +; JC PA_20 ;AN000; +;;;??? match found, error or override??? ;AN000; +;A_20: ;AN000; +; CALL CREATE_DFL_ENTRY ;AN000; +; JMP ifs_1000 ;AN000; +; ;AN000; +; ;AN000; +;ndProc PROCESS_ALIAS ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DFL_MATCH ;AN000; +; ;AN000; +; Called by: ATTACH_START CONSIST_SFT ;AN000; +; IFS_DELETE ;AN000; +; ;AN000; +; Routines called: ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> Asciiz Device name ;AN000; +; ;AN000; +; Function: ;AN000; +; Search DFL for match on name ;AN000; +; If match found - set [THISDFL] and clear carry ;AN000; +; Else set carry ;AN000; +; ;AN000; +; Output: ;AN000; +; carry clear - match found, [THISDFL] set ;AN000; +; carry set - match not found ;AN000; +; ;AN000; +; Regs: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + Procedure DFL_MATCH ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save registers ;AN000; + ;AN000; + SaveReg ; store canonicalized version of ;AN000; + RestoreReg ; source asciiz dev name in ;AN000; + MOV DI,OFFSET TEMPBUF+10 ; tempbuf+10 ;AN000; + MOV CX,10 ; devs max of 8 ch and : and nul ;AN000; +DM_20: ;AN000; + LODSB ;AN000; + CallInstall UCase,multDOS,19,, ;AN000; + STOSB ;AN000; + OR AL,AL ;AN000; + JZ DM_60 ;AN000; + CMP AL,"." ;AN000; + JZ DM_40 ;AN000; + LOOP DM_20 ;AN000; +DM_40: ;AN000; + XOR AL,AL ;AN000; + MOV BYTE PTR ES:[DI-1],AL ;AN000; +DM_60: ;AN000; + CMP BYTE PTR ES:[DI-2],":" ;AN000; + JNZ DM_80 ;AN000; + MOV BYTE PTR ES:[DI-2],0 ;AN000; + ;AN000; +DM_80: ;AN000; + XOR AX,AX ; ax is counter through DFL entries ;AN000; + LDS SI,[DFLAddr] ; dssi -> dfl entry ;AN000; +DM_100: ; <<<<< matching loop >>>>> ;AN000; + CMP AL,CS:[DFLCount] ;AN000; + JAE DM_980 ;AN000; + TEST DS:[SI.DFLL_FLAGS],DFL_INUSE ;AN000; + JZ DM_160 ;AN000; + SaveReg ; dfl entry offset ;AN000; + ADD SI,DFL_DEV_NAME ;AN000; + MOV DI,OFFSET TEMPBUF ;AN000; + CALL CONVERT_NAME_ASCIIZ ; moves dev name into tempbuf ;AN000; + ; in asciiz form - di preserved ;AN000; + MOV SI,OFFSET TEMPBUF+10 ;AN000; + Call PRN_CHECK ; if si->prn - chg si->lpt1 ;AN012; + CallInstall StrCmp,multDOS,30,, ; check for match ;AN000; + RestoreReg ; dfl entry offset ;AN000; + JZ DM_990 ;AN000; +DM_160: ;AN000; + ADD SI,SIZE DFLL_LIST ;AN000; + INC AL ;AN000; + JMP SHORT DM_100 ; go up & try next entry ;AN000; + ;AN000; +DM_980: ;AN000; + SaveReg ; set thisdfl null on error ;AN020; + RestoreReg ;AN020; + MOV AX,NULL_PTR ;AN020; + MOV WORD PTR [THISDFL],AX ;AN020; + MOV WORD PTR [THISDFL+2],AX ;AN020; + RestoreReg ;AN020; + STC ;AN000; + JMP SHORT DM_1000 ;AN000; +DM_990: ;AN000; + TEST DS:[SI.DFLL_FLAGS],dfl_paused ; if printer paused, no match ;AN019; + JNZ DM_980 ;AN019; + + MOV CS:WORD PTR [THISDFL],SI ;AN000; + MOV CS:WORD PTR [THISDFL+2],DS ;AN000; + CLC ; es:di -> dfl on match ;AN000; +DM_1000: ;AN000; + RestoreReg ; restore regs ;AN000; + return ;AN000; + ;AN000; +EndProc DFL_MATCH ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SFT_TO_SFF ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISSFT] set ;AN000; +; DS - DOSGROUP ;AN000; +; Function: ;AN000; +; Load SFF from SFT ;AN000; +; ;AN000; +; SFF_TYPE = 0 ;AN000; +; SFF_TYPE+1 = 0 ;AN000; +; SFF_FLAGS = SF_FLAGS ;AN000; +; SFF_MODE = SF_MODE ;AN000; +; SFF_RESV1 = 0 ;AN000; +; SFF_ATTR = SF_ATTR ;AN000; +; SFF_UID = SF_UID ;AN000; +; SFF_PID = SF_PID ;AN000; +; SFF_SIZE = SF_SIZE ;AN000; +; SFF_POSITION = SF_POSITION ;AN000; +; SFF_TIME = SF_TIME ;AN000; +; SFF_DATE = SF_DATE ;AN000; +; SFF_NAME = SF_NAME ;AN000; +; SFF_EXT = SF_NAME+8 ;AN000; +; SFF_RESV2 = 0 ;AN000; +; SFF_SF_ID = math on sft address +; SFF_FSDA = SF_CLUSPOS ;AN000; +; SFF_FSDA + 2 = SF_DIRSEC ;AN000; +; SFF_FSDA + 4 = SF_DIRSEC+2 ;AN000; +; SFF_FSDA + 6 = SF_LSTCLUS ;AN000; +; Outputs: ;AN000; +; SF loaded ;AN000; +; ES:BX -> IFSRH ;AN000; +; IFSR_OPEN_CB@ set ;AN000; +; If SetDeviceCB set then IFSR_DEVICE_CB@ set ;AN000; +; DS - IFSSEG ;AN000; +; ;AN000; +; notes: all except ES,BX,DS preserved ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SFT_TO_SFF,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save regs ;AN000; + ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; +ASSUME ES:IFSSEG ;AN000; + MOV DI,OFFSET SFF1 ; DS:SI -> SFT ;AN000; + LDS SI,[THISSFT] ; ES:DI -> SFF ;AN000; + ;AN000; + SaveReg ; save SFF offset ;AN000; + MOV AH,CBTYPE_SFF ; sff_type ;AN000; + XOR AL,AL ;AN000; + STOSW ;AN000; + ;AN000; + MOV AX,WORD PTR [SI.SF_FLAGS] ; sff_flags ;AN000; + STOSW ;AN015; + MOV AX,WORD PTR [SI.SF_MODE] ; sff_mode ;AN000; +;;;;;;;;PUSH BX ;AD015; +;;;;;;;;AND BX,8000H ;AD015; +;;;;;;;;OR AX,BX ;AD015; + STOSW ;AN000; +;;;;;;;;POP AX ;AD015; +;;;;;;;;AND AX,0EFFFH ;AD015; +;;;;;;;;STOSW ;AD015; +;;;;;;;;MOV AX,WORD PTR [SI.SF_IOMODE] ; sff_iomode ;AD024; + XOR AX,AX ; just put zero in reserved area ;AN024; + STOSW ;AN000; + MOV AL,BYTE PTR [SI.SF_ATTR] ; sff_attr ;AN000; +;;;;;;;;MOV AH,BYTE PTR [SI.SF_ATTR_HI] ; sff_attr_hi - no longer exists ;AD024; + STOSW ;AN000; + MOV AX,WORD PTR [SI.SF_UID] ; sff_uid ;AN000; + STOSW ;AN000; + MOV AX,WORD PTR [SI.SF_PID] ; sff_pid ;AN000; + STOSW ;AN000; + SaveReg ;AN000; + ADD SI,SF_SIZE ;AN000; + MOV CX,4 ;AN000; + REP MOVSW ; sff_size & position ;AN000; + RestoreReg ;AN000; + MOV AX,WORD PTR [SI.SF_TIME] ; sff_time ;AN000; + STOSW ;AN000; + MOV AX,WORD PTR [SI.SF_DATE] ; sff_date ;AN000; + STOSW ;AN000; + ;AN000; + SaveReg ; sff_name/ext/cp ;AN000; + ADD SI,SF_NAME ;AN000; + MOV CX,11 ; (name - 11, cp - 2 bytes) cp out ;AC024; + REP MOVSB ;AN000; + XOR AX,AX ;AN024; + STOSW ; just put zero in reserved area ;AN024; + + RestoreReg ; sff_sf_id ;AN000; + SaveReg ; calculate based on sft address ;AN016 + RestoreReg ;AN016; + MOV CL,4 ;AN016; + SHL AX,CL ;AN016; + ADD SI,AX ;AN016; + RestoreReg ;AN016; + AND AX,0F000H ;AN016; + ADD AX,SI ;AN016; + STOSW ;AN016; + RestoreReg ;AN016; + ;AN000; + ADD DI,SIZE SFF_RESV ; sff_fsda 1st word ;AN000; + SaveReg ; save si for issft case ;AN015; + ADD SI,SF_CLUSPOS ;AN000; + MOV CX,3 ;AC017; + REP MOVSW ;AN000; +;;;;;;;;ADD SI,12 ;AN017;;AD024; +;;;;;;;;MOVSW ;AN017;;AD024; + RestoreReg ;AN015; + MOV AX,WORD PTR [SI.SF_LSTCLUS] ; manually put lstclus in fsda+6 ;AN024; + STOSW ;AN024; + ;AN000; + TEST CS:[IFSPROC_FLAGS],ISSFT ;AN000; + JZ SFT_20 ;AN000; + MOV AX,WORD PTR [SI.SF_IFS_HDR] ; Set [THISIFS] only if ;AN000; + MOV WORD PTR CS:[THISIFS],AX ; no yet set by cds_to_cd or ;AN000; + MOV AX,WORD PTR [SI.SF_IFS_HDR+2] ; dfl_to_df ;AN000; + MOV WORD PTR CS:[THISIFS+2],AX ;AN000; + ;AN000; +SFT_20: ;AN000; + RestoreReg ; restore ES:DI -> start of SFF ;AN000; + SaveReg ; set DS:DI -> SFF ;AN000; + RestoreReg ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + MOV BX,OFFSET IFSR ; set ES:BX -> IFSRH ;AN000; + ;AN000; + TEST CS:IFSPROC_FLAGS,ISCTLFCN ;AN000; + JNZ SFT_40 ; API fcn - ;AN000; + MOV WORD PTR ES:[BX.IFSR_OPEN_CB@],DI ; set IFSR_OPEN_CB@ ;AN000; + MOV WORD PTR ES:[BX.IFSR_OPEN_CB@+2],DS ;AN000; + JMP SFT_60 ;AN000; +SFT_40: ; Ctl fcn - ;AN000; + MOV WORD PTR ES:[BX.IFSR_CB@],DI ; set IFSR_CB@ ;AN000; + MOV WORD PTR ES:[BX.IFSR_CB@+2],DS ;AN000; + ;AN000; +SFT_60: ;AN000; + TEST IFSPROC_FLAGS,SetDeviceCB ; check whether to set ;AN000; + JZ SFT_1000 ; device cb or not ;AN000; + LDS SI,[THISSFT] ;AN000; + CMP WORD PTR DS:[SI.SF_DEVPTR],NULL_PTR ; null if seq ;AN000; + JE SFT_1000 ;AN000; + TEST DS:[SI.SF_FLAGS],DEVID_DEVICE ; cds or dfl? ;AM007; + LDS SI,DS:[SI.SF_DEVPTR] ; get device ptr (cds/dfl) ;AM007; + JNZ SFT_100 ; jmp if dfl ;AN000; + MOV WORD PTR CS:SAVE_CB@,SI ; CDS ;AN000; + MOV WORD PTR CS:SAVE_CB@+2,DS ;AN000; + TEST DS:[SI.CURDIR_FLAGS],CURDIR_ISIFS ;AN000; + JZ SFT_1000 ;AN000; + CALL CDS_TO_CD ;AN000; + JMP SHORT SFT_1000 ;AN000; + ;AN000; +SFT_100: ;AN000; + MOV WORD PTR CS:[THISDFL],SI ; DFL ;AN000; + MOV WORD PTR CS:[THISDFL+2],DS ; set this cause dfl-df ;AN000; + CALL DFL_TO_DF ; expects it ;AN000; + ;AN000; + ;AN000; +SFT_1000: ;AN000; + RestoreReg ; restore regs ;AN000; + SaveReg ;AN000; + RestoreReg ; set ds -ifsseg ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc SFT_TO_SFF ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SFF_TO_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISSFT] set ;AN000; +; Function: ;AN000; +; Update SFT with SFF ;AN000; +; SF_FLAGS = SFF_FLAGS ;AN000; +; SF_MODE = SFF_MODE ;AN000; +; SF_ATTR = SFF_ATTR ;AN000; +; SF_UID = SFF_UID ;AN000; +; SF_PID = SFF_PID ;AN000; +; SF_SIZE = SFF_SIZE ;AN000; +; SF_POSITION = SFF_POSITION ;AN000; +; SF_TIME = SFF_TIME ;AN000; +; SF_DATE = SFF_DATE ;AN000; +; SF_NAME = SFF_NAME ;AN000; +; SF_NAME+8 = SFF_EXT ;AN000; +; SF_CLUSPOS = SFF_FSDA ;AN000; +; SF_DIRSEC = SFF_FSDA + 2 ;AN000; +; SF_DIRSEC+2 = SFF_FSDA + 4 ;AN000; +; SF_LSTCLUS = SFF_FSDA + 6 ;AN000; +; ;AN000; +; Outputs: ;AN000; +; SFT loaded ;AN000; +; notes: all regs preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure SFF_TO_SFT,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save regs ;AC003; + ;AN000; + PUSH SS ;AN000; + POP DS ;AN000; +ASSUME DS:DOSGROUP ;AN000; + LES DI,[THISSFT] ; DS:SI -> SFF ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV SI,OFFSET SFF1 ; ES:DI -> SFT ;AN000; + INC SI ;AN000; + INC SI ;AN000; + ;AN000; + LODSW ; sff_flags ;AN000; +;;;;;;;;AND AX,0EFFFH ; (hi bit sft_flags - also mode ) ;AD015; + MOV WORD PTR ES:[DI.SF_FLAGS],AX ; sft_flags ;AC015; + LODSW ;AN000; +;;;;;;;;AND AX,0EFFFH ;AD015; + MOV WORD PTR ES:[DI.SF_MODE],AX ; sft_mode ;AC015; + LODSW ;AN000; +;;;;;;;;MOV WORD PTR ES:[DI.SF_IOMODE],AX ; sft_iomode ...no longer exists ;AD024; + LODSW ;AN000; + MOV BYTE PTR ES:[DI.SF_ATTR],AL ; sft_attr ;AN000; +;;;;;;;;MOV BYTE PTR ES:[DI.SF_ATTR_HI],AH ; no longer exists ;AD024; + LODSW ;AN000; + MOV WORD PTR ES:[DI.SF_UID],AX ; sft_uid ;AN000; + LODSW ;AN000; + MOV WORD PTR ES:[DI.SF_PID],AX ; sft_pid ;AN000; + SaveReg ;AN000; + ADD DI,SF_SIZE ;AN000; + MOV CX,4 ;AN000; + REP MOVSW ; sft_size & position ;AN000; + RestoreReg ;AN000; + LODSW ;AN000; + MOV WORD PTR ES:[DI.SF_TIME],AX ; sft_time ;AN000; + LODSW ;AN000; + MOV WORD PTR ES:[DI.SF_DATE],AX ; sft_date ;AN000; + ;AN000; + ;AN000; + PUSH DI ; sft_name/ext/cp ;AN000; + ADD DI,SF_NAME ;AN000; + MOV CX,11 ; (name - 11, cp - 2 bytes) ;AN000; + REP MOVSB ;AN000; + ;AN000; + ADD SI,SIZE SFF_RESV ; sft_fsda 1st word ;AN000; + ADD SI,4 ; for sff_sf_id ;AN016;;AC024; + POP DI ;AN000; + ;AN000; + SaveReg ;AN003; + ADD DI,SF_CLUSPOS ;AN000; + MOV CX,3 ;AC017; + REP MOVSW ;AN000; +;;;;;;;;ADD DI,12 ;AN017;;AD024; +;;;;;;;;MOVSW ;AN017;;AD024; + LODSW ;AN024; + RestoreReg ;AN003;;AM024; + MOV WORD PTR ES:[DI.SF_LSTCLUS],AX ;AN024; + ;AN000; + TEST IFSPROC_FLAGS,SetDeviceCB ; check whether to update ;AN000; + JZ SFF_1000 ; device cb or not ;AN000; + TEST IFSPROC_FLAGS,IsSeq ;AN000; + JNZ SFF_1000 ;AN000; + ;AN000; + TEST ES:[DI.SF_FLAGS],DEVID_DEVICE ; cds or dfl? ;AM007; + PUSHF ; save results of this test for later ;AN007; + LES DI,ES:[DI.SF_DEVPTR] ; get device ptr (cds/dfl) ;AN000; + CMP DI,NULL_PTR ;AN000; + JNE SFF_20 ;AN000; + POPF ;AN000; + JMP SFF_1000 ;AN000; + +SFF_20: ;AN000; + POPF ; retrieve cd/df test results ;AN000; + JNZ SFF_100 ; jmp if dfl ;AN000; + MOV DI,WORD PTR CS:SAVE_CB@ ; CDS ;AN000; + PUSH WORD PTR CS:SAVE_CB@+2 ;AN000; + POP ES ;AN000; + TEST ES:[DI.CURDIR_FLAGS],CURDIR_ISIFS + JZ SFF_1000 + CALL CD_TO_CDS ;AN000; + JMP SHORT SFF_1000 ;AN000; + ;AN000; +SFF_100: ;AN000; + MOV WORD PTR CS:[THISDFL],DI ; DFL ;AN000; + MOV WORD PTR CS:[THISDFL+2],ES ; set this cause DF_TO_DFL ;AN000; + CALL DF_TO_DFL ; expects it ;AN000; + ;AN000; +SFF_1000: ;AN000; + RestoreReg ; restore regs ;AC003; + ;AN000; + return ;AN000; + ;AN000; +EndProc SFF_TO_SFT ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CDS_TO_CD ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> CDS ;AN000; +; ;AN000; +; Function: ;AN000; +; Load CD from CDS ;AN000; +; CD_TYPE = 1 ;AN000; +; CD_TYPE+1 = 0 ;AN000; +; CD_END = CURDIR_END ;AN000; +; CD_TEXT = CURDIR_TEXT ;AN000; +; CD_FSDA = CURDIR_ID ;AN000; +; CD_FSDA+2 = CURDIR_ID+2 ;AN000; +; CD_FSDA+4 = CURDIR_USER_WORD ;AN000; +; CD_FSDA+6 = CURDIR_FSDA ;AN000; +; Outputs: ;AN000; +; CD loaded ;AN000; +; ES:BX -> IFSRH ;AN000; +; IFSR_DEVICE_CB@ -> CD ;AN000; +; [THISIFS] = CURDIR_IFS_HDR ;AN000; +; DS - IFSSEG ;AN000; +; ;AN000; +; Regs: all except DS,ES,BX saved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CDS_TO_CD,NEAR ;AN000; + ;AN000; + SaveReg ; save regs ;AN000; + ;AN000; + PUSH CS ;AN000; + POP ES ; DS:SI -> CDS ;AN000; +ASSUME ES:IFSSEG ; ES:DI -> CD ;AN000; + MOV DI,OFFSET CS:CD1 ;AN000; + ;AN000; + PUSH DI ; save cd offset ;AN000; + MOV AL,CBTYPE_CD ; cd_type ;AN000; + TEST CS:IFSPROC_FLAGS,ISDUMMYCDS ; check for dummy cd ;AN000; + JZ CCD_10 ;AN000; + MOV AL,CBTYPE_DUMMYCD ;AN000; +CCD_10: ;AN000; + XOR AH,AH ;AN000; + STOSW ; move di down thru cd during store ;AN000; + ;AN000; + MOV AX,WORD PTR [SI.CURDIR_END] ; cd_end ;AN000; + STOSW ;AN000; + ;AN000; + PUSH SI ; cd_text ;AN000; + MOV CX,DIRSTRLEN ;AN000; + REP MOVSB ;AN000; + POP SI ;AN000; + ;AN000; + MOV AX,WORD PTR [SI.CURDIR_ID] ; cd_fsda ;AN000; + ADD DI,SIZE CD_RESV ;AN000; + STOSW ;AN000; + MOV AX,WORD PTR [SI.CURDIR_ID+2] ;AN000; + STOSW ;AN000; + MOV AX,WORD PTR [SI.CURDIR_USER_WORD] ;AN000; + STOSW ;AN000; + MOV AX,WORD PTR [SI.CURDIR_FSDA] ;AN000; + STOSW ;AN000; + ;AN000; + TEST CS:IFSPROC_FLAGS,THISIFS_SET ;AN000; + JNZ CCD_20 ;AN000; + MOV AX,WORD PTR [SI.CURDIR_IFS_HDR] ; Set [THISIFS] ;AN000; + MOV WORD PTR CS:[THISIFS],AX ;AN000; + MOV AX,WORD PTR [SI.CURDIR_IFS_HDR+2] ;AN000; + MOV WORD PTR CS:[THISIFS+2],AX ;AN000; +CCD_20: ;AN000; + POP DI ; restore CD offset ;AN000; + PUSH CS ; get DS -> IFSSEG ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + ;AN000; + MOV BX,OFFSET IFSR ; ES:BX -> IFSRH ;AN000; + SaveReg ;AN000; + ADD BX,DEVICE_CB@_OFFSET ;AN000; + MOV WORD PTR ES:[BX],DI ; set IFSR_DEVICE_CB@ ;AN000; + ADD BX,2 ;AN000; + MOV WORD PTR ES:[BX],ES ;AN000; + RestoreReg ;AN000; + ;AN000; + RestoreReg ; restore regs ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc CDS_TO_CD ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CD_TO_CDS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; ES:DI -> CDS ;AN000; +; DS -> IFSSEG ;AN000; +; Function: ;AN000; +; Update CDS with CD ;AN000; +; CURDIR_TEXT = CD_TEXT ;AN000; +; CURDIR_ID = CD_FSDA ;AN000; +; CURDIR_ID+2 = CD_FSDA+2 ;AN000; +; CURDIR_USER_WORD = CD_FSDA+4 ;AN000; +; CURDIR_END = CD_END ;AN000; +; CURDIR_FSDA = CD_FSDA+6 ;AN000; +; Outputs: ;AN000; +; CDS updated ;AN000; +; ;AN000; +; notes: all regs preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CD_TO_CDS,NEAR ;AN000; +ASSUME DS:IFSSEG,ES:IFSSEG ;AN000; + ;AN000; + SaveReg ; save regs ;AC005; + ;AN000; + MOV SI,OFFSET CD1 ; ES:DI -> CDS ;AN000; + ; DS:SI -> CD ;AN000; + INC SI ;AN000; + INC SI ;AN000; + ;AN000; + LODSW ; curdir_end ;AN000; + MOV ES:[DI.CURDIR_END],AX ;AN000; + ;AN000; + PUSH DI ;AN000; + MOV CX,DIRSTRLEN ;AN000; + REP MOVSB ;AN000; + POP DI ;AN000; + ;AN000; + ADD SI,SIZE CD_RESV ; curdir_id ;AN000; + LODSW ;AN000; + MOV WORD PTR ES:[DI.CURDIR_ID],AX ;AN000; + LODSW ;AN000; + MOV WORD PTR ES:[DI.CURDIR_ID+2],AX ;AN000; + LODSW ; curdir_user_word ;AN000; + MOV WORD PTR ES:[DI.CURDIR_USER_WORD],AX ;AN000; + LODSW ; curdir_fsda ;AN000; + MOV WORD PTR ES:[DI.CURDIR_FSDA],AX ;AN000; + ;AN000; + RestoreReg ; restore regs ;AC005; + ;AN000; + return ;AN000; + ;AN000; +EndProc CD_TO_CDS ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DFL_TO_DF ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISDFL] ;AN000; +; Function: ;AN000; +; Load DF from DFL ;AN000; +; ;AN000; +; DF_TYPE = 2 ;AN000; +; DF_TYPE + 1 = 0 ;AN000; +; DF_DEV_NAME = DFL_DEV_NAME ;AN000; +; DF_FSDA = DFL_FSDA ;AN000; +; Outputs: ;AN000; +; DF loaded ;AN000; +; ES:BX -> IFSRH ;AN000; +; IFSR_DEVICE_CB@ -> DF ;AN000; +; [THISIFS] = DFL_IFS_HDR ;AN000; +; DS - IFSSEG ;AN000; +; ;AN000; +; notes: es,bx,ds Revised, others saved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure DFL_TO_DF,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save regs ;AN000; + ;AN000; + PUSH CS ;AN000; + POP ES ;AN000; +ASSUME ES:IFSSEG ;AN000; + MOV DI,OFFSET DF1 ; es:di -> df ;AN000; + ;AN000; + MOV BX,OFFSET IFSR ; set es:bx - ifsrh ;AN000; + PUSH BX ; fill in device cb@ ;AN000; + ADD BX,CS:DEVICE_CB@_OFFSET ;AN000; + MOV WORD PTR ES:[BX],DI ;AN000; + ADD BX,2 ;AN000; + MOV WORD PTR ES:[BX],ES ;AN000; + POP BX ;AN000; + ;AN000; + LDS SI,[THISDFL] ; ds:si -> dfl ;AN000; + ;AN000; + MOV AL,CBTYPE_DF ; df_type ;AN000; + XOR AH,AH ;AN000; + STOSW ;AN000; + ;AN000; + PUSH SI ; df_dev_name ;AN000; + ADD SI,DFL_DEV_NAME ;AN000; + MOV CX,8 ;AN000; + REP MOVSB ;AN000; + POP SI ;AN000; + PUSH SI ;AN000; + ADD SI,DFL_FSDA ; df_fsda ;AN000; + + TEST CS:IFSPROC_FLAGS,SetDeviceCB ; if this flag set, i24 already taken ;AN004; + JNZ DDF_20 ; care of, otherwise take care of it ;AN004; + SaveReg ; df, dfl dev name offsets ;AN004; + MOV DI,OFFSET CS:[PHONEY_NAME] ; set phoney name and ifsdrv ;AN004; + MOV CX,4 ;AN004; + REP MOVSW ;AN004; + MOV CS:[IFSDRV],-1 ;AN004; + RestoreReg ; dfl dev name, df offsets ;AN004; + +DDF_20: ;AN004; + MOV CX,SIZE DFL_FSDA ;AN000; + REP MOVSB ;AN000; + POP SI ;AN000; + ;AN000; + MOV AX,WORD PTR DS:[SI.DFLL_IFS_HDR] ; Set [THISIFS] ;AN000; + MOV WORD PTR [THISIFS],AX ;AN000; + MOV AX,WORD PTR DS:[SI.DFLL_IFS_HDR+2] ;AN000; + MOV WORD PTR [THISIFS+2],AX ;AN000; + ;AN000; + PUSH CS ; set ds - ifsseg ;AN000; + POP DS ;AN000; + ;AN000; + RestoreReg ; restore regs ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc DFL_TO_DF ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; DF_TO_DFL ;AN000; +; ;AN000; +; Inputs: ;AN000; +; [THISDFL] set ;AN000; +; Function: ;AN000; +; Update DFL with DF ;AN000; +; DFL_DEV_NAME = DF_DEV_NAME ;AN000; +; DFL_FSDA = DF_FSDA ;AN000; +; Outputs: ;AN000; +; DFL updated ;AN000; +; ;AN000; +; notes: all regs preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure DF_TO_DFL,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ; save regs ;AN000; + ;AN000; + LES DI,[THISDFL] ; esdi -> dfl ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV SI,OFFSET DF1 ; dssi -> df ;AN000; + ;AN000; + INC SI ; space si,di to dev_name ;AN000; + INC SI ;AN000; + PUSH DI ;AN000; + ADD DI,DFL_DEV_NAME ;AN000; + MOV CX,8 ;AN000; + REP MOVSB ; update dfl_dev_name for some reason ;AN000; + ;AN000; + POP DI ;AN000; + ADD DI,DFL_FSDA ;AN000; + MOV CX,SIZE DFL_FSDA ;AN000; + REP MOVSB ; update dfl_fsda ;AN000; + ;AN000; + RestoreReg ; restore regs ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc DF_TO_DFL ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CONSIST_SFT ;AN000; +; ;AN000; +; Inputs: ;AN000; +; None ;AN000; +; ;AN000; +; Function: ;AN000; +; Make sure all device SFTs are consistent with current IFSFUNC state ;AN000; +; ;AN000; +; Outputs: ;AN000; +; None ;AN000; +; ;AN000; +; Regs: DS,ES,SI,DI preserved others destroyed ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CONSIST_SFT,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + CMP CS:[DFLCount],0 ; if no dfl, forget it ;AN022; + JE CS_20 + SaveReg ;AN000; + CLI ; This scan of the SFT tables is ;AN000; + ; a critical section we must protect ;AN000; + ; with CLI and STI as CritNET must ;AN000; + ; be disjoint from all other critical ;AN000; + ; sections ;AN000; + LDS SI,[SFTFCB] ;AN000; +ASSUME DS:NOTHING ;AN000; + MOV CX,[SI].sfCount ;AN000; + LEA SI,[SI].sfTable ;AN000; + JCXZ DONE_LOOK_FCB ;AN000; + CALL LOOK_FIX ;AN000; +DONE_LOOK_FCB: ;AN000; + LDS SI,[SFT_Addr] ; get pointer to beginning of table ;AN000; +ScanLoop: ;AN000; + MOV CX,[SI].SFCount ;AN000; + PUSH DS ;AN000; + PUSH SI ;AN000; + LEA SI,[SI].sfTable ;AN000; + CALL LOOK_FIX ;AN000; + POP SI ;AN000; + POP DS ;AN000; + LDS SI,[SI].SFLink ; get next table segment ;AN000; + CMP SI,-1 ; end of tables? ;AN000; + JNZ ScanLoop ; no, try again ;AN000; + STI ;AN000; + RestoreReg ;AN000; +CS_20: + return ;AN000; + ;AN000; +LOOK_FIX: ;AN000; + CMP [SI].sf_ref_count,0 ;AN000; + JZ NEXT_SFT ; Ignore Free ones ;AN000; + TEST [SI].sf_flags,devid_device ;AN000; + JZ NEXT_SFT ; Only look at device SFTs ;AN000; + TEST [SI].sf_flags,sf_isnet +;AN000; + PUSH CX ; sft loop count ;AN000; + PUSH DS ; sft ptr ;AN000; + PUSH SI ;AN000; + PUSHF ; Save result of above TEST ;AN000; + ADD SI,sf_name ; put asciiz form of sf_name in tempbuf ;AN000; + PUSH CS ; to call dfl_match with ;AN000; + POP ES ;AN000; + MOV DI,OFFSET TEMPBUF ;AN000; + CALL CONVERT_NAME_ASCIIZ ;AN000; + PUSH CS ;AN000; + POP DS ;AN000; + MOV SI,DI ;AN000; + CALL DFL_MATCH ; is this sft attached? cf1-no,cf0-yes ;AN000; + JC NOT_R_DEV ;AN000; + PUSH CS ; IS ATTACHED - recover test for sf_isnet ;AN000; + CALL PIRET ;AN000; + JNZ NOT_REDIR ; jmp if marked attached - ok ;AN000; +; [THISDFL] dfl entry ;AN000; +; (TOS+2):(TOS) -> SFT ;AN000; +; (TOS+4) = CX loop count ;AN000; + ; Not marked attached, but should & will be ;AN000; + LES DI,[THISDFL] ;AN000; + POP SI ;AN000; + POP DS ; DS:SI -> SFT ;AN000; + MOV AX,WORD PTR [SI.sf_devptr+2] ; save original devptr ;AN031; + MOV WORD PTR ES:[DI.DFLL_DEVPTR+2],AX ;AN031; + MOV AX,WORD PTR [SI.sf_devptr] ;AN031; + MOV WORD PTR ES:[DI.DFLL_DEVPTR],AX ;AN031; + MOV WORD PTR [SI.sf_devptr+2],ES ;AC027; + MOV WORD PTR [SI.sf_devptr],DI ;AC027; + MOV AX,WORD PTR ES:[DI.DFL_FSDA] ; put dfl fsda into sft fsda ;AN027; + MOV WORD PTR [SI.sf_cluspos],AX ;AN027; + MOV AX,WORD PTR ES:[DI.DFL_FSDA+2] ;AN027; + MOV WORD PTR [SI.sf_dirsec],AX ;AN027; + MOV AX,WORD PTR ES:[DI.DFL_FSDA+4] ;AN027; + MOV WORD PTR [SI.sf_dirsec+2],AX ;AN027; + MOV AX,WORD PTR ES:[DI.DFL_FSDA+6] ;AN027; + MOV WORD PTR [SI.sf_lstclus],AX ;AN027; + OR [SI.sf_flags],sf_isnet + sf_net_spool ; Turn on bits ;AC027; + JMP SHORT CLEAN_CX ;AN000; + ;AN000; +PIRET: ;AN000; + IRET ;AN000; + ;AN000; +NOT_R_DEV: ;AN000; + PUSH CS ; NOT ATTACHED - recover test for sf_isnet ;AN000; + CALL PIRET ;AN000; + JNZ UNDO_BITS ; jmp if marked attached - problem ;AN000; +NOT_REDIR: ;AN000; + POP SI ;AN000; + POP DS ;AN000; +CLEAN_CX: ;AN000; + POP CX ;AN000; +NEXT_SFT: ;AN000; + ADD SI,size sf_entry ;AN000; + LOOP LOOK_FIX ;AN000; + return ;AN000; + ;AN000; +; [THISDFL] dfl entry ;AN000; +; (TOS+2):(TOS) -> SFT ;AN000; +; (TOS+4) = CX loop count ;AN000; +UNDO_BITS: ; device not attached, but marked so ;AN000; + POP SI ; unmark it, restore original devptr ;AN000; + POP DS ; DS:SI -> SFT ;AN000; + AND [SI.sf_flags],NOT (sf_isnet + sf_net_spool) ; Turn off bits ;AN000; + MOV ES,WORD PTR [SI.sf_devptr+2] ; set esdi -> dfl ;AN031; + MOV DI,WORD PTR [SI.sf_devptr] ;AN031; + MOV AX,WORD PTR ES:[DI.DFLL_DEVPTR+2] ; restore original devptr ;AN031; + MOV WORD PTR [SI.sf_devptr+2],AX ;AN031; + MOV AX,WORD PTR ES:[DI.DFLL_DEVPTR] ;AN031; + MOV WORD PTR [SI.sf_devptr],AX ;AN031; + JMP SHORT CLEAN_CX ;AN000; + ;AN000; +EndProc CONSIST_SFT ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; CONSIST_DFL ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI -> 1st DFL entry ;AN000; +; CX = DFLCount ;AN000; +; Function: ;AN000; +; Set all dfl_inprog flags to zero ;AN000; +; Outputs: ;AN000; +; dfl_inprog flags all zero ;AN000; +; ;AN000; +; notes: all regs preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure CONSIST_DFL,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ;AC023; + MOV DX,SIZE DFLL_LIST ;AN000; +CD_20: ; reset loop ;AN000; + AND BYTE PTR DS:[SI],NOT DFL_INPROG ;AN000; + ADD SI,DX ;AN000; + LOOP CD_20 ;AN000; + ;AN000; + RestoreReg ;AC023; + return ;AN000; + ;AN000; +EndProc CONSIST_DFL ;AN000; + + +BREAK + +;************************************************************************************ +; +; PRN_CHECK +; +; Inputs: +; DS -> IFSSEG +; SI -> asciiz canonicalized device name +; Function: +; IF DSSI-> "PRN",0 THEN +; Set SI -> LPT1_NAME +; ENDIF +; Outputs: +; SI possibly Revised +; +; notes: all but si preserved +; +;************************************************************************************ + + procedure PRN_CHECK,NEAR ;AN012; +ASSUME DS:IFSSEG,ES:NOTHING ;AN012; + + SaveReg ;AN012;;AC014; + RestoreReg ;AN012; + MOV DI,OFFSET PRN_NAME ;AN012; + SaveReg ;AN012; + CallInstall StrCmp,MultDOS,30 ;AN012; + RestoreReg ;AN012; + JNZ PC_20 ;AN012; + MOV SI,OFFSET LPT1_NAME ;AN012; +PC_20: ;AN012; + RestoreReg ;AN012;;AC014; + return ;AN012; + +EndProc PRN_CHECK ;AN012; + + +BREAK ;AN000; + ;AN000; +;************************************************************************************ +; +; CHECK_REAL_DEVICE +; +; Inputs: +; DS:SI -> DFL entry +; +; Function: +; Match device name to device driver chain names +; IF match found +; set dfl_dev_real +; IF device name = "prn" THEN +; set to "LPT1" +; Outputs: +; dfl_dev_real set +; device name changed to "LPT1" if "PRN" +; +; Regs: AX,CX destroyed. All others preserved. +; +;************************************************************************************ + ;AN000; + procedure CHECK_REAL_DEVICE,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; +ASSUME ES:IFSSEG ;AN000; + MOV DI,OFFSET TEMPBUF+10 ; esdi-> tempbuf+10 ;AN000; + ADD SI,DFL_DEV_NAME ; dssi -> dfl_dev_name ;AN000; + CALL CONVERT_NAME_ASCIIZ ; asciiz form of dfl_dev_name ;AN000; + ; at tempbuf+10 ;AN000; + ; Use this to match real devnames ;AN000; + ;AN000; + Context DS ; get addressability to dosgroup ;AN000; + ; to access device driver chain ;AN000; + LDS SI,NULDEV ; dssi -> real device driver chain ;AN000; +CRD_20: ; <<< matching loop on dev drvrs >>> ;AN000; + SaveReg ;AN000; + ADD SI,SDEVNAME ; dssi -> real dev name ;AN000; + MOV DI,OFFSET TEMPBUF ;AN000; + CALL CONVERT_NAME_ASCIIZ ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + MOV SI,DI ; dssi -> tempbuf (real) ;AN000; + ADD DI,10 ; esdi -> tempbuf+10 (dfl) ;AN000; + CallInstall StrCmp,MultDOS,30 ; compare (case insensitive) ;AN000; + RestoreReg ; device driver chain ;AN000; + JZ CRD_40 ;AN000; + LDS SI,DS:[SI.SDEVNEXT] ;AN000; + CMP SI,NULL_PTR ;AN000; + JNE CRD_20 ;AN000; +;;;;;;;;SaveReg ; only offset null ;AD022; +; RestoreReg ;AD022; +; CMP AX,NULL_PTR ;AD022; +;;;;;;;;JNE CRD_20 ;AD022; + RestoreReg ; dfl entry ;AN000; + JMP SHORT CRD_100 ; go check "prn" ;AN000; + ;AN000; +CRD_40: ; match found ;AN000; + RestoreReg ; dfl entry ;AN000; + OR DS:[SI.DFLL_FLAGS],DFL_DEV_REAL ;AN000; + ;AN000; +CRD_100: ;AN000; + SaveReg ; dfl entry ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV SI,OFFSET PRN_NAME ; ds:si -> "prn",0 ;AN000; + ; es:di -> tempbuf+10 (dfl) ;AN000; + CallInstall StrCmp,MultDOS,30 ; compare (case insensitive) ;AN000; + RestoreReg ; dfl entry ;AN000; + JNZ CRD_120 ;AN000; + ; prn match ;AN000; + CALL XCHGP ; after call: ds ifsseg ;AN000; + ; esdi->dfl entry ;AN000; +ASSUME DS:IFSSEG ;AN000; + MOV SI,OFFSET LPT1_NAME ;AN000; + SaveReg ; dfl entry offset ;AN000; + ADD DI,DFL_DEV_NAME ; make dfl_dev_name = "LPT1 " ;AN000; + MOV CX,4 ;AN000; + REP MOVSB ;AN000; + RestoreReg ; dfl entry offset ;AN000; + OR DS:[SI.DFLL_FLAGS],DFL_DEV_REAL ;AN022; + ;AN000; +CRD_120: ;AN000; + RestoreReg ; restore es,di ;AN000; + return ;AN000; + ;AN000; +EndProc CHECK_REAL_DEVICE ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; XCHGP ;AN000; +; ;AN000; +; Inputs: ;AN000; +; DS:SI & ES:DI ;AN000; +; Function: ;AN000; +; Swap ds:si with es:di ;AN000; +; Outputs: ;AN000; +; ds<=>es, si<=>di ;AN000; +; ;AN000; +; notes: all preserved ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure XCHGP,NEAR ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + XCHG SI,DI ;AN000; + return ;AN000; +EndProc XCHGP ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; IFSDrvFromCDS - convert an offset to a CDS into a 0-based drive number. ;AN000; +; Sets IFSDrv also. ;AN000; +; ;AN000; +; Inputs: AX contains offset from the beginning of CDSAddr ;AN000; +; Outputs: AL contains the 0-based drive number ;AN000; +; IFSDrv is set ;AN000; +; Registers Revised: AH, BL ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure IFSDrvFromCDS,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + SUB AX,WORD PTR [CDSADDR] ; AX is offset of THISCDS ;AN000; + MOV BL,SIZE CurDir_list ; size in convenient spot ;AN000; + DIV BL ; get drive number ;AN000; + MOV CS:[IFSDRV],AL ;AN000; + return ;AN000; +EndProc IFSDrvFromCDS ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SET_THISIFS_UNC ;AN000; +; ;AN000; +; Inputs: DS - IFSSEG, UNC_FS_HDR set ;AN000; +; Outputs: [THISIFS] = UNC_FS_HDR ;AN000; +; ;AN000; +; Registers Revised: none ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure SET_THISIFS_UNC,NEAR ;AN000; + MOV AX,CS:WORD PTR [UNC_FS_HDR] ;AN000; + MOV CS:WORD PTR [THISIFS],AX ;AN000; + MOV AX,CS:WORD PTR [UNC_FS_HDR+2] ;AN000; + MOV CS:WORD PTR [THISIFS+2],AX ;AN000; + return ;AN000; +EndProc SET_THISIFS_UNC ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ +; +; SET_CATEGORY +; +; Inputs: DS - IFSSEG, ES:BX -> IFSR, THISIFS set +; Outputs: CL set to 1 for unc fs, 0 otherwize +; +; Registers Revised: CX +; +;************************************************************************************ + ;AN000; +Procedure SET_CATEGORY,NEAR ;AN000; + SaveReg ; preserve used regs ;AN000; + XOR CH,CH ;AN000; + MOV CL,CATEGORY_FS ; set category: 0 - non-UNC ;AN000; + TEST IFSFUNC_FLAGS,UNC_INSTALLED ; check if unc fs installed ;AN000; + JZ SC_20 ; no unc - go set category to fs ;AN000; + MOV AX,WORD PTR [THISIFS] ; now must check if thisifs=unc ;AN000; + CMP AX,WORD PTR [UNC_FS_HDR] ;AN000; + JNE SC_20 ;AN000; + MOV AX,WORD PTR [THISIFS+2] ;AN000; + CMP AX,WORD PTR [UNC_FS_HDR+2] ;AN000; + JNE SC_20 ;AN000; + INC CL ; is unc - inc category to 1=unc ;AN000; +SC_20: ;AN000; + RestoreReg ;AN000; + return ;AN000; +EndProc SET_CATEGORY ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; SET_DEPIOCTL_IFSR ;AN000; +; ;AN000; +; Inputs: ES:BX -> IFSR +; Outputs: IFSR_LENGTH, IFSR_FUNCTION, IFSR_APIFUNC, IFSR_FUNC set ;AN000; +; ;AN000; +; Registers Revised: none ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure SET_DEPIOCTL_IFSR,NEAR ;AN000; + ifsr_fcn_def EXECAPI ;AN000; + ifsr_api_def DEPIOCTL ;AN000; + MOV ES:[BX.IFSR_LENGTH],LENGTH_DEPIOCTL ;AN000; + MOV ES:[BX.IFSR_FUNCTION],IFSEXECAPI ;AN000; + MOV ES:[BX.IFSR_APIFUNC],IFSDEPIOCTL ;AN000; + MOV ES:[BX.IFSR_FUNC],GEN_IOCTL_BY_DEVNUM ;AN000; + return ;AN000; +EndProc SET_DEPIOCTL_IFSR ;AN000; + ;AN000; + +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; GET_UNC_FS_NAME ;AN000; +; ;AN000; +; Inputs: +; ES:DI -> BUFFER ;AN000; +; ;AN000; +; Outputs: Buffer contains asciiz form of ifs driver name ;AN000; +; ;AN000; +; Registers Revised: none ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure GET_UNC_FS_NAME,NEAR ;AN000; + ;AN000; + SaveReg + LDS SI,CS:UNC_FS_HDR + CALL MOVE_DRIVER_NAME + RestoreReg ;AN000; + return ;AN000; +EndProc GET_UNC_FS_NAME ;AN000; + + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; MOVE_DRIVER_NAME ;AN000; +; ;AN000; +; Inputs: DS:SI -> IFS DRIVER ;AN000; +; ES:DI -> BUFFER ;AN000; +; ;AN000; +; Outputs: Buffer contains asciiz form of ifs driver name ;AN000; +; ;AN000; +; Registers Revised: SI,DI ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure MOVE_DRIVER_NAME,NEAR ;AN000; + ;AN000; + ADD SI,IFS_NAME ; space to name in ifs hdr ;AN000; + MOV CX,8 ;AN000; +MDN_20: ; move name into buffer ;AN000; + LODSB ; move till 1st space or 8 chars ;AN000; + CMP AL," " ; then add 0 ;AN000; + JE MDN_40 ;AN000; + STOSB ;AN000; + LOOP MDN_20 ;AN000; +MDN_40: ;AN000; + XOR AL,AL ;AN000; + STOSB ;AN000; + ;AN000; + return ;AN000; +EndProc MOVE_DRIVER_NAME ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + +;************************************************************************************ +; +; CONVERT_NAME_ASCIIZ +; +; Inputs: DS:SI -> NAME +; ES:DI -> BUFFER +; +; Outputs: Buffer contains asciiz form of name +; +; Regs: All but SI preserved +; +;************************************************************************************ + +Procedure CONVERT_NAME_ASCIIZ,NEAR ;AN000; + SaveReg ; esdi buffer offset ;AC014; + CLD ; store name in asciiz format ;AN000; + MOV CX,8 ; in esdi buffer ;AN000; +CNA_20: ;AN000; + LODSB ;AN000; + CMP AL," " ;AN000; + JE CNA_40 ;AN000; + STOSB ;AN000; + LOOP CNA_20 ;AN000; +CNA_40: ;AN000; + XOR AL,AL ;AN000; + STOSB ;AN000; + ;AN000; + RestoreReg ; esdi buffer offset ;AC014; + ;AN000; + return ;AN000; + ;AN000; +EndProc CONVERT_NAME_ASCIIZ ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ +; +; CHECK_SEQ +; +; Inputs: [THISCDS],[THISDFL] +; DS - dosgroup +; +; Function: Check whether function has device_cb@ associated with it. +; (Rule out deviceless attach function) +; +; Outputs: cf = 0 seq (deviceless) +; cf = 1 device +; +; Registers Revised: none +; +;************************************************************************************ + +Procedure CHECK_SEQ,NEAR ;AN000; +ASSUME DS:DOSGROUP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; SaveReg ; ;AD007; +; MOV SI,[WFP_START] ; ;AD007; +; LODSW ; ;AD007; +; CMP AX,"\\" ; ;AD007; +; JE CS_10 ; ;AD007; +; STC ; ;AD007; +; JMP SHORT CS_20 ; ;AD007; +;S_10: ; ;AD007; +; CLC ; ;AD007; +; ; ;AD007; +;S_20: ; ;AD007; +; RestoreReg ; ;AD007; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + SaveReg ; save used regs ;AN007; + LDS SI,[THISCDS] ; check for cds ;AN007; + CMP SI,NULL_PTR ;AN007; + JNE CS_10 ;AN007; + LDS SI,CS:[THISDFL] ; no cds, check dfl ;AN007; + CMP SI,NULL_PTR ;AN007; + JNE CS_10 ;AN007; + CLC ; no cds, no dfl - is deviceless - clear carry ;AN007; + JMP SHORT CS_1000 ;AN007; + ;AN007; +CS_10: ;AN007; + STC ; has device - set carry ;AN007; + ;AN007; +CS_1000: ;AN007; + RestoreReg ; restore used regs ;AN007; + return ;AN000; + ;AN000; +EndProc CHECK_SEQ ;AN000; + ;AN000; + ;AN000; +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; INIT_DFL ;AN000; +; ;AN000; +; Inputs: DS:SI -> dfl entry ;AN000; +; ;AN000; +; Outputs: dfl entry zeroed out ;AN000; +; ;AN000; +; Registers Revised: none ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure INIT_DFL,NEAR ;AN000; + SaveReg ;AN000; + RestoreReg ;AN000; + MOV DI,SI ;AN000; + MOV CX,SIZE DFLL_LIST / 2 ;AN000; + XOR AX,AX ;AN000; + CLD ;AN000; + REP STOSW ;AN000; + RestoreReg ;AN000; + ;AN000; + return ;AN000; + ;AN000; +EndProc INIT_DFL ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; NET_TRANS ;AN000; +; ;AN000; +; Inputs: ;AN000; +; ES:DI -> Double string session start string for blockredir ;AC001; +; or printerredir. ;AN000; +; ;AN000; +; Function: ;AN000; +; Perform NAMETRANS DOS function on the connect part of the string ;AN000; +; ;AN000; +; Outputs: ;AN000; +; ES:DI points to NAMETRANSed REDIR string ;AC001; +; password, or extra 0, appended at end of string ;AC001; +; ;AN000; +; Registers Revised: ;AN000; +; ES,DI Revised, others preserved ;AC001; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; + procedure NET_TRANS,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + SaveReg ;AC001; + ;AN000; + SaveReg ; set ds:si -> string ;AN001; + RestoreReg ; for nametrans input ;AN001; + MOV SI,DI ;AN001; + + PUSH CS ;AN000; + POP ES ;AN000; + MOV DI,OFFSET NET_TRANS_BUFFER ; name transed string will be placed ;AC013; + ; in temporary buffer + SaveReg ; $NAMETRANS zaps these ;AC013; + CallInstall $Nametrans,MultDOS,33 ;AN000; + RestoreReg ;AN000; + JNC NT_20 ;AN023; + RestoreReg ; nametrans error - set carry & exit ;AN023; + JMP SHORT NT_60 ;AN023; + + ; dssi -> input target string +NT_20: ; esdi -> nametrans version in nettranbuf;AC001;;AC013; + LODSB ; move password or zero ;AC001; + OR AL,AL ;AC001; + JNZ NT_20 ; skip to password (or zero) ;AC001; +;;;;;;;;MOV DI,OFFSET TEMPBUF ; no need for this; ;AC001;;AD013; +; SaveReg ; nametrans already does it; ;AC001;;AD013; +;NT_40: ; ;AC001;;AD013; +; MOV AL,BYTE PTR ES:[DI] ; ;AC001;;AD013; +; INC DI ; ;AC001;;AD013; +; OR AL,AL ; ;AC001;;AD013; +;;;;;;;;;JNZ NT_40 ; Skip first part; ;AD013; + CallInstall StrCpy,MultDOS,17 ; Copy password string ;AC001; + RestoreReg ;AC001; + CLC ;AN023; +NT_60: ;AN023; + RestoreReg ;AC001; + ;AN001; + return ;AN000; + ;AN000; +EndProc NET_TRANS ;AN000; + ;AN000; + +Break ;AN000; + ;AN000; +;************************************************************************************ ;AN000; +; ;AN000; +; STRIP_WFP_START ;AN000; +; +; Called by: IFS_SEARCH_FIRST +; ;AN000; +; Inputs: DS:SI -> WFP_START ;AN000; +; ;AN000; +; Outputs: none ;AN000; +; ;AN000; +; Registers Revised: none ;AN000; +; ;AN000; +;************************************************************************************ ;AN000; + ;AN000; +Procedure STRIP_WFP_START,NEAR ;AN000; + ;AN000; + CMP BYTE PTR DS:[SI+1],":" ;AN000; + JNE SW_1000 ;AN000; + ADD SI,2 ;AN000; + CMP BYTE PTR DS:[SI],"\" ;AN000; + JE SW_20 ;AN000; + CMP BYTE PTR DS:[SI],"/" ;AN000; + JNE SW_1000 ;AN000; +SW_20: ;AN000; + INC SI ;AN000; + ;AN000; +SW_1000: ;AN000; + return ;AN000; + ;AN000; +EndProc STRIP_WFP_START ;AN000; + + +Break + +;************************************************************************************ +; +; CHECK_IFS_ATTRIBUTE +; +; Called by: IFS_DEPENDENT_IOCTL +; +; Inputs: DX = ifs_attribute equate +; +; Outputs: ZF = attribute not supported +; NZ = attribute supported +; +; Registers Revised: none +; +;************************************************************************************ + ;AN000; +Procedure CHECK_IFS_ATTRIBUTE,NEAR ;AN000; + ;AN000; + SaveReg + + LES DI,[THISIFS] ; esdi -> ifs header + TEST ES:[DI.IFS_ATTRIBUTE],DX ; test attribute + + RestoreReg + ;AN000; + return ;AN000; + ;AN000; +EndProc CHECK_IFS_ATTRIBUTE ;AN000; + + +Break + +;************************************************************************************ +; +; CHECK_IFS_SUPPORT +; +; Called by: CALL_IFS +; +; Inputs: TBD +; +; Outputs: TBD +; +; +; Registers Revised: TBD +; +;************************************************************************************ + ;AN000; +Procedure CHECK_IFS_SUPPORT,NEAR ;AN000; + + return ;AN010; + +EndProc CHECK_IFS_SUPPORT ;AN010; + + ;AN000; +IFSSEG ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/IFSFUNC/MAKEFILE b/v4.0/src/CMD/IFSFUNC/MAKEFILE new file mode 100644 index 0000000..3925be3 --- /dev/null +++ b/v4.0/src/CMD/IFSFUNC/MAKEFILE @@ -0,0 +1,127 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h +here =..\cmd\ifsfunc +make =nmake -i + +# +####################### dependencies begin here. ######################### +# + +all: ifsfunc.exe + +msdos.cl1: $(dos)\msdos.skl \ + $(msg)\$(COUNTRY).msg \ + $(dos)\makefile + copy $(dos)\msdos.skl + nosrvbld msdos.skl $(msg)\$(COUNTRY).msg + +ifsfunc.ctl: ifsfunc.skl $(msg)\$(COUNTRY).msg makefile + +$(inc)\dossym.inc: $(inc)\versiona.inc $(inc)\dosmac.inc \ + $(inc)\bpb.inc $(inc)\buffer.inc $(inc)\sysvar.inc \ + $(inc)\vector.inc $(inc)\mult.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc $(inc)\cpmfcb.inc \ + $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \ + $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc \ + $(inc)\mi.inc $(inc)\filemode.inc $(inc)\error.inc \ + $(inc)\syscall.inc \ + makefile + echo " touch $(inc)\dossym.inc " + +ifssess.obj: ifssess.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + makefile + +ifsdir.obj: ifsdir.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + makefile + +ifsfile.obj: ifsfile.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + makefile $(inc)\doscntry.inc + +ifshand.obj: ifshand.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + makefile + +ifsdev.obj: ifsdev.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + makefile + +ifsutil.obj: ifsutil.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + $(inc)\bugtyp.asm \ + makefile + +ifserror.obj: ifserror.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + ifsfunc.ctl ifsfunc.cla ifsfunc.cl1 ifsfunc.cl2 \ + makefile + +ifsfdos.obj: ifsfdos.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + $(inc)\msdata.asm $(inc)\bugtyp.asm $(inc)\sysmsg.inc \ + $(inc)\psdata.inc $(inc)\msgserv.asm ifsparse.inc \ + $(inc)\parse.asm \ + makefile + +ifsinit.obj: ifsinit.asm $(inc)\ifssym.inc ifsfsym.inc \ + $(inc)\dossym.inc $(inc)\devsym.inc $(inc)\dosseg.asm \ + $(inc)\msdata.asm $(inc)\bugtyp.asm $(inc)\sysmsg.inc \ + $(inc)\psdata.inc $(inc)\msgserv.asm ifsparse.inc \ + $(inc)\parse.asm \ + ifsfunc.ctl ifsfunc.cla ifsfunc.cl1 ifsfunc.cl2 \ + makefile + +$(inc)\nibdos.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\const2.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\msdata.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\mstable.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\msdosme.obj: + cd $(inc) + $(make) + cd $(here) + +$(dos)\msdisp.obj: + cd $(dos) + $(make) + cd $(here) + +$(dos)\mscode.obj: + cd $(dos) + $(make) + cd $(here) + +ifsflink.obj: ifsflink.asm \ + $(inc)\dossym.inc \ + makefile + +ifsfunc.exe: ifssess.obj ifsdir.obj ifsfile.obj ifshand.obj \ + ifsdev.obj ifsutil.obj ifserror.obj ifsfdos.obj \ + ifsinit.obj \ + $(inc)\nibdos.obj $(inc)\const2.obj $(inc)\msdata.obj \ + $(inc)\mstable.obj $(dos)\msdisp.obj \ + $(dos)\mscode.obj $(inc)\msdosme.obj \ + ifsflink.obj makefile ifsfunc.lnk + link @ifsfunc.lnk + diff --git a/v4.0/src/CMD/JOIN/JOIN.C b/v4.0/src/CMD/JOIN/JOIN.C new file mode 100644 index 0000000..b0e13d8 --- /dev/null +++ b/v4.0/src/CMD/JOIN/JOIN.C @@ -0,0 +1,669 @@ +/*  */ +/**************************************************************************/ +/* */ +/* UTILITY NAME: Join */ +/* */ +/* SOURCE FILE NAME: Join.C */ +/* */ +/* STATUS: Join Utility, DOS Version 4.0 */ +/* */ +/* FUNCTIONAL DESCRIPTION: This utility allows the splicing of a */ +/* physical drive to a pathname on another physical drive such that */ +/* operations performed using the pathname as an argument take place */ +/* on the physical drive. */ +/* */ +/* SYNTAX: [d:][path]JOIN or */ +/* [d:][path]JOIN d: d:\directory or */ +/* [d:][path]JOIN d: /D */ +/* where: */ +/* [d:][path] to specify the drive and path that */ +/* contains the JOIN command file, if it is not */ +/* in the current directory of the default drive. */ +/* */ +/* d: to specify the drive to be connected to a */ +/* directory on another drive. */ +/* */ +/* d:\directory to specify the directory that */ +/* you will join a drive under. The directory */ +/* must be at the root and only one level deep. */ +/* */ +/* /D to disconnect a join. You must specify the */ +/* drive letter of the drive whose join you */ +/* want to delete. */ +/* */ +/* LINKS: */ +/* CDS.C - Functions to get/set DOS CDS structures */ +/* DPB.C - Functions to get DOS DPB structures */ +/* ERRTST.C - Drive and path validity testing functions */ +/* SYSVAR.C - Functions to get/set DOS System Variable structures */ +/* COMSUBS.LIB - DOS DBCS function calls */ +/* MAPPER.LIB - DOS function calls */ +/* SLIBC3.LIB - C library functions */ +/* _MSGRET.SAL - Assembler interface for common DOS message services */ +/* _PARSE.SAL - Assembler interface for common DOS parser */ +/* */ +/* ERROR HANDLING: Error message displayed and utility is terminated. */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* MODIFICATIONS: */ +/* */ +/* Converted to CMERGE 03/26/85 by GregT */ +/* */ +/* M000 May 23/85 Barrys */ +/* Disallow splicing similar drives. */ +/* */ +/* M001 May 24/85 Barrys */ +/* The original IBM version of JOIN allowed the delete splice switch */ +/* "/D" immediately after the drive specification. The argument parsing */ +/* code has been Revised to allow this combination. */ +/* */ +/* M002 June 5/85 Barrys */ +/* Changed low version check for specific 320. */ +/* */ +/* M003 July 15/85 Barrys */ +/* Checked for any possible switch characters in the other operands. */ +/* */ +/* M004 July 15/85 Barrys */ +/* Moved check for physical drive before check for NET and SHARED tests. */ +/* */ +/* 33D0016 July 16/86 RosemarieG */ +/* Put SHARED test on an equal basis with physical drive check. */ +/* Last fix (M004) erroneously allowed joining physical or local shared */ +/* drives. This is because it only performed the SHARED test if the */ +/* drive failed the physical test. */ +/* */ +/* May /87 SusanM */ +/* Deletion of source code dealing with parsing and displaying messages */ +/* and addition of SYSLOADMSG, SYSDISPMSG, SYSPARSE in order to conform */ +/* to DOS Version 4.0 specifications to utilize common DOS parser and */ +/* message service routines. */ +/* */ +/* AC000: Changed code for DOS Version 4.0 S.M 5/87 */ +/* */ +/* AN000: New code for DOS Version 4.0 S.M 5/87 */ +/* AN000;M = message services */ +/* AN000;P = parser service */ +/* */ +/* Ax001: Changed code req'd - PTM0003919 S.M 3/88 */ +/* Incorrect message response */ +/* */ +/* Ax002: Changed code req'd - PTM0004046 S.M 3/88 */ +/* Incomplete message response */ +/* */ +/**************************************************************************/ + +#include "cds.h" +#include "ctype.h" +#include "dos.h" +#include "joinpars.h" /* ;AN000;P Parser structures */ +#include "jointype.h" +#include "stdio.h" +#include "sysvar.h" + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PARSE EQUATES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +#define ASCII_DRIVE 'A'-1 /* ;AN000;P Convert to Ascii drive */ +#define CAPRESULT 0x0001 /* ;AN000;P Cap result by file table */ +#define DRVONLY_OPT 0x0101 /* ;AN000;P Drive only & optional */ +#define ERRORLEVEL1 1 /* ;AN000;P Parsing error occurred */ +#define FILESPEC_OPT 0x0201 /* ;AN000;P File spec & optional */ +#define MAXPOSITION 2 /* ;AN000;P Max positionals in cmdline */ +#define MINPOSITION 0 /* ;AN000;P Min positionals in cmdline */ +#define NOCAPPING 0x0000 /* ;AN000;P Do not cap result */ +#define SWITCH_OPT 0x0000 /* ;AN000;P Optional switch */ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MESSAGE EQUATES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +#define MSG_NOMEM 1 /* ;AN000;M Insufficient memory */ +#define MSG_PARMNUM 2 /* ;AN000;M Too many parameters */ +#define MSG_DIRNEMP 3 /* ;AN000;M Directory not empty */ +#define MSG_BADPARM 4 /* ;AN000;M Invalid parameter */ +#define MSG_NETERR 5 /* ;AN000;M Cannot %1 a network drive */ +#define MSG_INVSWTCH 6 /* ;AN000;M Invalid switch */ + +#define BLNK ' ' /* ;AN000;M For sublist.pad_char */ +#define CARRY 0x0001 /* ;AN000;M Check carry flag */ +#define D_SWITCH "/D" /* ;AN000;M Only 1 switch */ +#define EXT_ERR_CLASS 0x01 /* ;AN000;M DOS Extended error class */ +#define FALSE 0 +#define MAX 256 +#define MAXWIDTH 0 /* ;AN000;M 0 ensures no padding */ +#define MINWIDTH 1 /* ;AN000;M At least 1 char in parm */ +#define NO_HANDLE 0xffff /* ;AN000;M No handle specified */ +#define NO_INPUT 0x00 /* ;AN000;M No input characters */ +#define NO_REPLACE 0x00 /* ;AN000;M No replacable parameters */ +#define NULL 0 +#define PARSE_ERR_CLASS 0x02 /* ;AN000;M Parse error class */ +#define RESERVED 0 /* ;AN000;M Reserved byte field */ +#define STDERR 0x0002 /* ;AN000;M Standard error device handle */ +#define STDOUT 0x0001 /* ;AN000;M Std output device handle */ +#define STR_INPUT 16 /* ;AN000;M Byte def for sublist.flags */ +#define SUB_ID1 1 /* ;AN000;M Only 1 replaceable parameter */ +#define SUBCNT0 0 /* ;AN000;M 0 substitutions in message */ +#define SUBCNT1 1 /* ;AN000;M 1 substitution in message */ +#define SUBLIST_LENGTH 11 /* ;AN000;M Length of sublist structure */ +#define UTILITY_CLASS 0x0ff /* ;AN000;M Utility message class */ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MISCELLANEOUS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +extern char *strchr() ; /* M003 */ +extern char *strbscan() ; /* SM extern'd */ + +char cmdln_drive[64] = {0} ; /* ;AN002; Save user's input in */ +char cmdln_flspec[64] = {0} ; /* ;AN002; order to pass to error */ +char cmdln_invalid[64] = {0} ; /* ;AN002; */ +char cmdln_switch[64] = {0} ; /* ;AN002; message, if needed */ +char fix_es_reg[1] ; /* ;AN000;P Corrects es reg after type-"far" */ +char p_drive[3] = {0} ; /* ;AN000;P Recvs drive ltr from parser */ +char p_filespec[64] = {0} ; /* ;AN000;P Recvs filespec from parser */ +char replparm_JOIN[] = "JOIN" ; /* ;AN000;P Cannot JOIN a network drv */ + +unsigned char source[MAX] = {0} ; /* ;AN000;P buffer for string manipulation */ + +struct sysVarsType SysVars ; + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ PARSE STRUCTURES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +struct p_parms p_p ; /* ;AN000;P # of extras & pts to descrptn */ +struct p_parmsx p_px ; /* ;AN000;P min/max parms & pts to controls */ +struct p_control_blk p_con1 ; /* ;AN000;P 1st posit parm in cmd str */ +struct p_control_blk p_con2 ; /* ;AN000;P 2nd posit parm in cmd str */ +struct p_switch_blk p_swi1 ; /* ;AN000;P /D switch in cmd str */ +struct p_result_blk rslt1 ; /* ;AN000;P Result blk rtrnd from parser */ +struct p_fresult_blk rslt2 ; /* ;AN000;P Result blk rtrnd from parser */ +struct p_result_blk rslt3 ; /* ;AN000;P Result blk rtrnd from parser */ +struct noval novals = {0} ; /* ;AN000;P Value list not used */ + +union REGS inregs, outregs ; /* ;AN000;P Define register variables */ + +/**************************************************************************/ +/* */ +/* SUBROUTINE NAME: main (program entry point) */ +/* */ +/* SUBROUTINE FUNCTION: Preload message file */ +/* Get the command line parameters */ +/* Parse the command line by calling SYSPARSEC */ +/* Verify the correctness of the parameters */ +/* Check for splice deletion switch */ +/* Determine if directory not empty */ +/* Check source and destination drives not same */ +/* Determine if network or shared drive */ +/* Determine if currently spliced */ +/* Determine if existing dir or can't mkdir */ +/* Print messages by calling SYSDISPMSG */ +/* */ +/* EXTERNAL ROUTINES: SYSLOADMSG */ +/* SYSDISPMSG */ +/* SYSPARSE */ +/* */ +/* INTERNAL ROUTINES: DoList Parser_Prep */ +/* Load_Msg dispmsg_terminate */ +/* Display_Msg */ +/* */ +/**************************************************************************/ + +main(c, v) +int c ; +char *v[] ; +{ + struct findType findbuf ; + struct CDSType CDS ; + + char path [MAXPATHLEN],*p ; + char far * fptr ; /* ;AN000;P Pointer to parser's buffer */ + + int delflag = FALSE ; /* M001 delete splice flag */ + int dstdrv ; /* M000 dest. drive number */ + int fchar = 0 ; /* ;AN000;P Parser filespec chars */ + int i ; + int index ; /* ;AN000;P Used in creating cmdline string */ + int more_toparse = TRUE ; /* ;AN000;P While parsing cmdline */ + int pdrive_flg = FALSE ; /* ;AN000;P Is there a drive letter? */ + int pflspec_flg = FALSE ; /* ;AN000;P Is there a filespec? */ + +/************************ BEGIN ***********************************************/ + + load_msg() ; /* ;AN000;M Point to msgs & chks DOS ver */ + + for (index = 1; index <= c; index++) /* ;AN000;P Loop through end of cmd line */ + { /* ;AN000;P */ + strcat(source,v[index]) ; /* ;AN000;P Add the argument */ + strcat(source," ") ; /* ;AN000;P Separate with a space */ + } /* ;AN000;P */ + Parser_Prep(source) ; /* ;AN000;P Initialization for the parser */ + + while (more_toparse) /* ;AN000;P test the flag */ + { /* ;AN000;P */ + index = 0 ; /* ;AN002; Init array index */ + parse(&inregs,&outregs) ; /* ;AN000;P call the parser */ + if (outregs.x.ax == P_No_Error) /* ;AN000;P if no error */ + { /* ;AN000;P */ + if (outregs.x.dx == (unsigned short)&rslt1) /* ;AN000;P if result is drv ltr */ + { /* ;AN000;P */ + p_drive[0] = *(rslt1.p_result_buff) ; /* ;AN000;P save the drive letter */ + p_drive[0] += (char)ASCII_DRIVE ; /* ;AN000;P */ + p_drive[1] = COLON ; /* ;AN000;P */ + pdrive_flg = TRUE ; /* ;AN000;P and set the flag */ + for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */ + { /* ;AN002; parser just parsed */ + cmdln_drive[index] = *(char *)inregs.x.si ; /* ;AN002; */ + index++ ; /* ;AN002; */ + } /* ;AN002; */ + } /* ;AN000;P */ + else /* ;AN000;P */ + if (outregs.x.dx == (unsigned short)&rslt2) /* ;AN000;P if result is filespec */ + { /* ;AN000;P */ + for (fptr = rslt2.fp_result_buff; (char)*fptr != NULL; fptr++) /* ;AN000;P Point to parser's buffer */ + { /* ;AN000;P */ + p_filespec[fchar] = (char)*fptr ; /* ;AN000;P Copy char */ + fchar++ ; /* ;AN000;P */ + } /* ;AN000;P */ + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + pflspec_flg = TRUE ; /* ;AN000;P and set the flag */ + for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */ + { /* ;AN002; parser just parsed */ + cmdln_flspec[index] = *(char *)inregs.x.si ; /* ;AN002; */ + index++ ; /* ;AN002; */ + } /* ;AN002; */ + } /* ;AN000;P */ + else /* ;AN000;P */ + { /* ;AN000;P */ + for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */ + { /* ;AN002; parser just parsed */ + cmdln_switch[index] = *(char *)inregs.x.si ; /* ;AN002; */ + index++ ; /* ;AN002; */ + } /* ;AN002; */ + if (!delflag) /* ;AN000;P Check for dup switch */ + delflag = TRUE ; /* ;AN000;P it's /D switch */ + else /* ;AN000;P else it's a dup switch */ + dispmsg_terminate(MSG_INVSWTCH,cmdln_switch) ; /* ;AN000;P display msg & end */ + } /* ;AN000;P */ + } /* ;AN000;P */ + else /* ;AN000;P */ + if (outregs.x.ax != P_RC_EOL) /* ;AN000;P there must be an error */ + { /* ;AN000;P */ + for (inregs.x.si ; inregs.x.si < outregs.x.si ; inregs.x.si++) /* ;AN002; Copy whatever */ + { /* ;AN002; parser just parsed */ + cmdln_invalid[index] = *(char *)inregs.x.si ; /* ;AN002; */ + index++ ; /* ;AN002; */ + } /* ;AN002; */ + switch (outregs.x.ax) /* ;AN000;P See what error the */ + { /* ;AN000;P parser may have found */ + case P_Too_Many : dispmsg_terminate(MSG_PARMNUM,cmdln_invalid) ; /* ;AN002; Too many parameters */ + break ; /* ;AN000;P more_toparse = FALSE */ + case P_Not_In_SW : dispmsg_terminate(MSG_INVSWTCH,cmdln_invalid) ;/* ;AN002; Invalid switch */ + break ; /* ;AN000;P more_toparse = FALSE */ + case P_Op_Missing : /* ;AN000;P Required operand missing */ + case P_Not_In_Key : /* ;AN000;P Not in kywrd list provided */ + case P_Out_Of_Range : /* ;AN000;P Out of range specified */ + case P_Not_In_Val : /* ;AN000;P Not in val list provided */ + case P_Not_In_Str : /* ;AN000;P Not in strg list provided */ + case P_Syntax : dispmsg_terminate(MSG_BADPARM,cmdln_invalid) ; /* ;AN000;P incorrect syntax */ + break ; /* ;AN000;P more_toparse = FALSE */ + default : dispmsg_terminate(MSG_BADPARM,cmdln_invalid) ; /* ;AN000;P */ + break ; /* ;AN000;P more_toparse = FALSE */ + } /* ;AN000;P */ + } /* ;AN000;P */ + else /* ;AN000;P */ + more_toparse = FALSE ; /* ;AN000;P End of the cmdline */ + inregs.x.cx = outregs.x.cx ; /* ;AN000;P Move the count */ + inregs.x.si = outregs.x.si ; /* ;AN000;P Move the pointer */ + } /* ;AN000;P */ + + if (pdrive_flg && !(pflspec_flg || delflag)) /* ;AN000;P drive & no flspec or delete ? */ + dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AN000;P display error msg & exit utility */ + + if (pflspec_flg && !pdrive_flg) /* ;AN000;P filespec & no drive ? */ + dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AN000;P display error msg & exit utility */ + + if (delflag && !pdrive_flg) /* ;AN000;P delete & no drive ? */ + dispmsg_terminate(MSG_BADPARM,cmdln_switch) ; /* ;AN000;P display error msg & exit utility */ + + if (pdrive_flg && pflspec_flg && delflag) /* ;AN000;P drive, filespec & /D ? */ + dispmsg_terminate(MSG_PARMNUM,cmdln_switch) ; /* ;AN000;P display error msg & exit utility */ + + GetVars(&SysVars) ; /* Access to DOS data structures */ + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + + if (c == 1) + DoList() ; /* list splices */ + else + { + i = p_drive[0] - 'A' ; /* ;AC000;P Convert to drv # */ + if (!fGetCDS(i, &CDS)) + dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M display error msg & exit utility */ + + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + if (delflag == TRUE) /* Deassigning perhaps? */ + { + if (!TESTFLAG(CDS.flags, CDSSPLICE)) + dispmsg_terminate(MSG_BADPARM,cmdln_switch) ; /* ;AC000;M If NOT spliced */ + + if (fPathErr(CDS.text)) + dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M If prefix of curdir */ + + CDS.text[0] = i + 'A' ; + CDS.text[1] = ':' ; + CDS.text[2] = '\\' ; + CDS.text[3] = 0 ; + CDS.cbEnd = 2 ; + + if (i >= SysVars.cDrv) + CDS.flags = FALSE ; + else + CDS.flags = CDSINUSE ; + GetVars(&SysVars) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + SysVars.fSplice-- ; + PutVars(&SysVars) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + fPutCDS(i, &CDS) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + } + else + { + if (TESTFLAG(CDS.flags,CDSSPLICE)) + dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000; If now spliced */ + + rootpath(p_filespec,path) ; /* Get root path */ + + if (i == getdrv() || /* M004 Start */ /* Can't mov curdrv */ + !fPhysical(i) || /* ;AC000; */ + fShared(i)) /* 33D0016 RG */ + { /* Determine if it was a NET error */ + if (fNet(i) || fShared(i)) + dispmsg_terminate(MSG_NETERR) ; /* ;AC000;M display error msg & exit utility */ + dispmsg_terminate(MSG_BADPARM,cmdln_drive) ; /* ;AC000;M display error msg & exit utility */ + } + + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + if (fPathErr(path) || *strbscan(path+3, "/\\") != 0) /* or curdir prefix */ + dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000; */ + + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + if (fNet(path[0] - 'A') || fShared(path[0] - 'A')) + dispmsg_terminate(MSG_NETERR) ; /* ;AC000;M display error msg & exit utility */ + + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + dstdrv = *path - 'A' ; /* M000 Check src and dst drvs ar not same */ + if (i == dstdrv) /* M000 */ + dispmsg_terminate (MSG_BADPARM,cmdln_flspec) ; /* M000 */ /* ;AC000; */ + if (mkdir(path) == -1) /* If can't mkdir or if no dir or */ + { /* if note is file */ + if (ffirst(path, A_D, &findbuf) == -1 || + !TESTFLAG(findbuf.attr,A_D)) + dispmsg_terminate(MSG_BADPARM,cmdln_flspec) ; /* ;AC000;M display error msg & exit utility */ + + p = path + strlen(path) ; + strcat(p, "\\*.*") ; + + if (ffirst(path, 0, &findbuf) != -1) + dispmsg_terminate(MSG_DIRNEMP,cmdln_flspec) ; /* ;AC001;M If dir not empty */ + + *p = 0 ; + } + + strcpy(CDS.text, path) ; + CDS.flags = CDSINUSE | CDSSPLICE ; + fPutCDS(i, &CDS) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + GetVars(&SysVars) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + SysVars.fSplice++ ; + PutVars(&SysVars) ; + strcpy(fix_es_reg,NULL) ; /* ;AN000;P (Set es reg correct) */ + } + } + exit(0) ; +} +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +DoList() /* Print list of cur joins */ +{ + int i ; + struct CDSType CDS ; + + for (i=0 ; fGetCDS(i, &CDS) ; i++) + { + if (TESTFLAG(CDS.flags,CDSSPLICE)) + printf("%c: => %s\n", i+'A', CDS.text) ; + } + return ; +} +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/**************************************************************************/ +/* */ +/* SUBROUTINE NAME: load_msg */ +/* */ +/* SUBROUTINE FUNCTION: Load the set of SUBST Utility messages to */ +/* become available for display_msg call. */ +/* */ +/* ERROR EXIT: Utility will be terminated by sysloadmsg if */ +/* version check is incorrect. */ +/* */ +/* EXTERNAL REF: SYSLOADMSG */ +/* */ +/**************************************************************************/ + +load_msg() /* ;AN000;M */ +{ /* ;AN000;M */ + sysloadmsg(&inregs,&outregs) ; /* ;AN000;M Load utility messages */ + if (outregs.x.cflag & CARRY) /* ;AN000;M If problem loading msgs */ + { /* ;AN000;M */ + sysdispmsg(&outregs,&outregs) ; /* ;AN000;M then display the err msg */ + exit(ERRORLEVEL1) ; /* ;AN000;M and exit utility */ + } /* ;AN000;M */ + return ; /* ;AN000;M */ +} /* ;AN000;M */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/**************************************************************************/ +/* */ +/* SUBROUTINE NAME: display_msg */ +/* */ +/* SUBROUTINE FUNCTION: The correct message called by main is displayed */ +/* to standard out. */ +/* */ +/* INPUT: msg_num (message number to display) */ +/* outline (substitution parameter) */ +/* */ +/* OUTPUT: none */ +/* */ +/* ERROR EXIT: Display error message corresponding to number */ +/* returned in AX. */ +/* */ +/* EXTERNAL REF: SYSDISPMSG */ +/* */ +/**************************************************************************/ + +display_msg(msg_num,outline) /* ;AN000;M */ +int msg_num ; /* ;AN000;M Message number #define'd */ +char *outline ; /* ;AN000;M Substitution parameter */ +{ /* ;AN000;M */ + unsigned char function ; /* ;AN000;M Y/N response or press key? */ + unsigned int message, /* ;AN000;M Message number to display */ + msg_class, /* ;AN000;M Which class of messages? */ + sub_cnt, /* ;AN000;M Number of substitutions? */ + handle ; /* ;AN000;M Display where? */ + + struct sublist /* ;AN000;M */ + { /* ;AN000;M */ + unsigned char size ; /* ;AN000;M Points to next sublist */ + unsigned char reserved ; /* ;AN000;M Required for disp msg */ + unsigned far *value ; /* ;AN000;M Data pointer */ + unsigned char id ; /* ;AN000;M Id of substitution parm (%1) */ + unsigned char flags ; /* ;AN000;M Format of data - (a0sstttt) */ + unsigned char max_width ; /* ;AN000;M Maximum field width */ + unsigned char min_width ; /* ;AN000;M Minimum field width */ + unsigned char pad_char ; /* ;AN000;M char to pad field */ + } sublist ; /* ;AN000;M */ + + switch (msg_num) /* ;AN000;M Which msg to display? */ + { /* ;AN000;M */ + case MSG_NOMEM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 8 ; /* ;AN000;M Message number to display */ + msg_class = EXT_ERR_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT0 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + case MSG_PARMNUM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 1 ; /* ;AN000;M Message number to display */ + msg_class = PARSE_ERR_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + case MSG_DIRNEMP : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 2 ; /* ;AN000;M Message number to display */ + msg_class = UTILITY_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + case MSG_BADPARM : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 10 ; /* ;AN000;M Message number to display */ + msg_class = PARSE_ERR_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + case MSG_NETERR : function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 12 ; /* ;AN000;M Message number to display */ + msg_class = UTILITY_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + case MSG_INVSWTCH: function = NO_INPUT ; /* ;AN000;M Y/N response or press key? */ + message = 3 ; /* ;AN000;M Message number to display */ + msg_class = PARSE_ERR_CLASS ; /* ;AN000;M Which class of messages? */ + sub_cnt = SUBCNT1 ; /* ;AN000;M Number of substitutions? */ + handle = STDERR ; /* ;AN000;M Display where? */ + break ; /* ;AN000;M */ + default : exit(ERRORLEVEL1) ; /* ;AN000;M */ + break ; /* ;AN000;M */ + } /* ;AN000;M */ + + switch (msg_num) /* ;AN000;M */ + { /* ;AN000;M */ + case MSG_NOMEM : inregs.x.ax = message ; /* ;AN000;M Insufficient memory */ + inregs.x.bx = handle ; /* ;AN000;M STDERR */ + inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT0 */ + inregs.h.dl = function ; /* ;AN000;M NO_INPUT */ + inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */ + sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */ + break ; /* ;AN000;M */ + case MSG_INVSWTCH: /* ;AN000;M Invalid switch */ + case MSG_DIRNEMP : /* ;AN000;M Directory not empty */ + case MSG_PARMNUM : /* ;AN000;M Too many parameters */ + case MSG_BADPARM : sublist.value = (unsigned far *)outline ; /* ;AN000;M Invalid parameter */ + sublist.size = SUBLIST_LENGTH ; /* ;AN000;M */ + sublist.reserved = RESERVED ; /* ;AN000;M */ + sublist.id = 0 ; /* ;AN000;M */ + sublist.flags = STR_INPUT ; /* ;AN000;M */ + sublist.max_width = MAXWIDTH ; /* ;AN000;M */ + sublist.min_width = MINWIDTH ; /* ;AN000;M */ + sublist.pad_char = (unsigned char)BLNK ; /* ;AN000;M */ + inregs.x.ax = message ; /* ;AN000;M Cannot JOIN a network drive */ + inregs.x.bx = handle ; /* ;AN000;M STDERR */ + inregs.x.si = (unsigned int)&sublist ; /* ;AN000;M Point to the substitution buffer */ + inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT1 */ + inregs.h.dl = function ; /* ;AN000;M STR_INPUT */ + inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */ + sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */ + break ; /* ;AN000;M */ + case MSG_NETERR : sublist.value = (unsigned far *)replparm_JOIN ; /* ;AN000;M Cannot JOIN a network drive */ + sublist.size = SUBLIST_LENGTH ; /* ;AN000;M */ + sublist.reserved = RESERVED ; /* ;AN000;M */ + sublist.id = SUB_ID1 ; /* ;AN000;M */ + sublist.flags = STR_INPUT ; /* ;AN000;M */ + sublist.max_width = MAXWIDTH ; /* ;AN000;M */ + sublist.min_width = MINWIDTH ; /* ;AN000;M */ + sublist.pad_char = (unsigned char)BLNK ; /* ;AN000;M */ + inregs.x.ax = message ; /* ;AN000;M Cannot JOIN a network drive */ + inregs.x.bx = handle ; /* ;AN000;M STDERR */ + inregs.x.si = (unsigned int)&sublist ; /* ;AN000;M Point to the substitution buffer */ + inregs.x.cx = sub_cnt ; /* ;AN000;M SUBCNT1 */ + inregs.h.dl = function ; /* ;AN000;M STR_INPUT */ + inregs.h.dh = msg_class ; /* ;AN000;M Extended, Parse or Utility */ + sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call common msg service */ + break ; /* ;AN000;M */ + default : exit(ERRORLEVEL1) ; /* ;AN000;M */ + break ; /* ;AN000;M */ + } /* ;AN000;M */ + + if (outregs.x.cflag & CARRY) /* ;AN000;M Is the carry flag set? */ + { /* ;AN000;M Then setup regs for extd-err */ + inregs.x.bx = STDERR ; /* ;AN000;M */ + inregs.x.cx = SUBCNT0 ; /* ;AN000;M */ + inregs.h.dl = NO_INPUT ; /* ;AN000;M */ + inregs.h.dh = EXT_ERR_CLASS ; /* ;AN000;M */ + sysdispmsg(&inregs,&outregs) ; /* ;AN000;M Call to display ext_err msg */ + exit(ERRORLEVEL1) ; /* ;AN000;M */ + } /* ;AN000;M */ + return ; /* ;AN000;M */ +} /* ;AN000;M */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/**************************************************************************/ +/* */ +/* SUBROUTINE NAME: dispmsg_terminate */ +/* */ +/* SUBROUTINE FUNCTION: Display the message, then terminate the utility.*/ +/* */ +/* INPUT: msg_num (#define'd message to display) */ +/* outline (substitution parameter) */ +/* */ +/**************************************************************************/ + +dispmsg_terminate(msg_num,outline) /* ;AN000;P */ +int msg_num ; /* ;AN000;P Message number #define'd */ +char *outline ; /* ;AN001;P Substitution parameter */ +{ /* ;AN000;P */ + display_msg(msg_num,outline) ; /* ;AN000;P First, display the msg */ + exit(ERRORLEVEL1) ; /* ;AN000;P Then, terminate utility */ +} /* ;AN000;P */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ +/**************************************************************************/ +/* */ +/* SUBROUTINE NAME: Parser_Prep */ +/* */ +/* SUBROUTINE FUNCTION: Initialize all structures for the parser. */ +/* */ +/* INPUT: source (command line string) */ +/* */ +/* OUTPUT: none */ +/* */ +/* EXTERNAL REF: parse */ +/* */ +/**************************************************************************/ + +Parser_Prep(source) /* ;AN000;P */ +char *source ; /* ;AN000;P Commandline */ +{ /* ;AN000;P */ + p_p.p_parmsx_address = &p_px ; /* ;AN000;P Address of extended parm list */ + p_p.p_num_extra = 0 ; /* ;AN000;P No extra declarations */ + + p_px.p_minp = MINPOSITION ; /* ;AN000;P */ + p_px.p_maxp = MAXPOSITION ; /* ;AN000;P */ + p_px.p_control1 = &p_con1 ; /* ;AN000;P Point to 1st control blk */ + p_px.p_control2 = &p_con2 ; /* ;AN000;P Point to 2nd control blk */ + p_px.p_maxs = 1 ; /* ;AN000;P Specify # of switches */ + p_px.p_switch = &p_swi1 ; /* ;AN000;P Point to the switch blk */ + p_px.p_maxk = 0 ; /* ;AN000;P Specify # of keywords */ + + p_con1.p_match_flag = DRVONLY_OPT ; /* ;AN000;P Drive only & optional */ + p_con1.p_function_flag = NOCAPPING ; /* ;AN000;P Cap result by file table */ + p_con1.p_result_buf = (unsigned int)&rslt1 ; /* ;AN000;P Point to result blk */ + p_con1.p_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */ + p_con1.p_nid = 0 ; /* ;AN000;P Not a switch id */ + + p_con2.p_match_flag = FILESPEC_OPT ; /* ;AN000;P File spec & optional */ + p_con2.p_function_flag = CAPRESULT ; /* ;AN000;P Cap result by file table */ + p_con2.p_result_buf = (unsigned int)&rslt2 ; /* ;AN000;P Point to result blk */ + p_con2.p_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */ + p_con2.p_nid = 0 ; /* ;AN000;P Not a switch id */ + + p_swi1.sp_match_flag = SWITCH_OPT ; /* ;AN000;P Optional (switch) */ + p_swi1.sp_function_flag = NOCAPPING ; /* ;AN000;P Cap result by file table */ + p_swi1.sp_result_buf = (unsigned int)&rslt3 ; /* ;AN000;P Point to result blk */ + p_swi1.sp_value_list = (unsigned int)&novals ; /* ;AN000;P Point to no value list */ + p_swi1.sp_nid = 1 ; /* ;AN000;P One switch allowed */ + strcpy(p_swi1.sp_keyorsw,D_SWITCH) ; /* ;AN000;P Identify the switch */ + + inregs.x.cx = 0 ; /* ;AN000;P Operand ordinal */ + inregs.x.di = (unsigned int)&p_p ; /* ;AN000;P Address of parm list */ + inregs.x.si = (unsigned int)source ; /* ;AN000;P Make DS:SI point to source */ + return ; /* ;AN000; */ +} /* ;AN000;P */ diff --git a/v4.0/src/CMD/JOIN/JOIN.LNK b/v4.0/src/CMD/JOIN/JOIN.LNK new file mode 100644 index 0000000..fd0b443 --- /dev/null +++ b/v4.0/src/CMD/JOIN/JOIN.LNK @@ -0,0 +1,12 @@ +JOIN.OBJ+ +..\..\inc\ERRTST.OBJ+ +..\..\inc\SYSVAR.OBJ+ +..\..\inc\CDS.OBJ+ +..\..\inc\DPB.OBJ+ +_MSGRET.OBJ+ +_PARSE.OBJ +JOIN +NUL +..\..\inc\comsubs.lib+ +..\..\mapper\mapper.lib; + \ No newline at end of file diff --git a/v4.0/src/CMD/JOIN/JOIN.SKL b/v4.0/src/CMD/JOIN/JOIN.SKL new file mode 100644 index 0000000..dd6806f --- /dev/null +++ b/v4.0/src/CMD/JOIN/JOIN.SKL @@ -0,0 +1,22 @@ +;JOIN Utility +;Message Service Routine + +:util JOIN ;BEGIN UTIL ;AN000; + +:class 1 ;EXTENDED ERRORS ;AN000; +;------- --------------- +;:use EXTEND8 ;Insufficient memory + +:class 2 ;PARSE ERRORS ;AN000; +;------- ------------ +;:use PARSE1 ;Too many parameters +;:use PARSE3 ;Invalid switch +;:use PARSE10 ;Invalid parameter + +:class A ;COMMON & DEFINED MSGS ;AN000; +;------- ------------ +:use 1 COMMON1 ;Incorrect DOS version ;AN000; +:def 2 "Directory not empty",CR,LF ;AN000; +:use 12 COMMON12 ;Cannot %1 a network drive ;AN000; + +:end ;END UTIL ;AN000; diff --git a/v4.0/src/CMD/JOIN/JOINPARS.H b/v4.0/src/CMD/JOIN/JOINPARS.H new file mode 100644 index 0000000..8573a17 --- /dev/null +++ b/v4.0/src/CMD/JOIN/JOINPARS.H @@ -0,0 +1,156 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the parser from a C program. | +| ** customized for the JOIN and SUBST utilities ** | +| | +| Date: 5-21-87 | +| | +| | ++----------------------------------------------------------------------*/ + + +struct p_parms + { + struct p_parmsx *p_parmsx_address; /* address of p_parmsx */ + unsigned char p_num_extra; /* number of extra stuff */ + }; + +struct p_parmsx + { + unsigned char p_minp; /* Minimum positional number */ + unsigned char p_maxp; /* Maximum positional number */ + struct p_control_blk *p_control1; /* Address of the 1st CONTROL block */ + struct p_control_blk *p_control2; /* Address of the 2nd CONTROL block */ + unsigned char p_maxs; /* Maximun switches */ + struct p_switch_blk *p_switch; /* Address of the SWITCH block */ + unsigned char p_maxk; /* Maximum keywords */ + }; + + +struct p_control_blk + { + unsigned int p_match_flag; /* Controls type matched */ + unsigned int p_function_flag; /* Function should be taken */ + unsigned int p_result_buf; /* Result buffer address */ + unsigned int p_value_list; /* Value list address */ + unsigned char p_nid; /* # of keyword/SW synonyms */ + }; + +struct p_switch_blk + { + unsigned int sp_match_flag; /* Controls type matched */ + unsigned int sp_function_flag; /* Function should be taken */ + unsigned int sp_result_buf; /* Result buffer address */ + unsigned int sp_value_list; /* Value list address */ + unsigned char sp_nid; /* # of keyword/SW synonyms */ + unsigned char sp_keyorsw[3]; /* keyword or sw */ + }; + +/* Match_Flags */ + +#define P_Num_Val 0x8000 /* Numeric Value */ +#define P_SNum_Val 0x4000 /* Signed numeric value */ +#define P_Simple_S 0x2000 /* Simple string */ +#define P_Date_S 0x1000 /* Date string */ +#define P_Time_S 0x0800 /* Time string */ +#define P_Cmpx_S 0x0400 /* Complex string */ +#define P_File_Spc 0x0200 /* File Spec */ +#define P_Drv_Only 0x0100 /* Drive Only */ +#define P_Qu_String 0x0080 /* Quoted string */ +#define P_Ig_Colon 0x0010 /* Ignore colon at end in match */ +#define P_Repeat 0x0002 /* Repeat allowed */ +#define P_Optional 0x0001 /* Optional */ + +/*----------------------------------------------------------------------+ +| | +| Function flags | +| | ++----------------------------------------------------------------------*/ + +#define P_CAP_File 0x0001 /* CAP result by file table */ +#define P_CAP_Char 0x0002 /* CAP result by character table */ +#define P_Rm_Colon 0x0010 /* Remove ":" at the end */ + + + +#define P_nval_None 0 /* no value list ID */ +#define P_nval_Range 1 /* range list ID */ +#define P_nval_Value 2 /* value list ID */ +#define P_nval_String 3 /* string list ID */ +#define P_Len_Range 9 /* Length of a range choice(two DD plus one DB) */ +#define P_Len_Value 5 /* Length of a value choice(one DD plus one DB) */ +#define P_Len_String 3 /* Length of a string choice(one DW plus one DB) */ + + +/*----------------------------------------------------------------------+ +| | +| Result block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_result_blk + { + unsigned char P_Type; /* Type returned */ + unsigned char P_Item_Tag; /* Matched item tag */ + unsigned int P_SYNONYM_Ptr; /* pointer to Synonym list returned */ + unsigned int p_result_buff[2]; /* result value */ + }; + +struct p_fresult_blk + { + unsigned char fP_Type; /* Type returned */ + unsigned char fP_Item_Tag; /* Matched item tag */ + unsigned int fP_SYNONYM_Ptr; /* pointer to Synonym list returned */ + char far * fp_result_buff; /* result value */ + }; + +/*----------------------------------------------------------------------+ +| | +| type | +| | ++----------------------------------------------------------------------*/ + +#define P_EOL 0 /* End of line */ +#define P_Number 1 /* Number */ +#define P_List_Idx 2 /* List Index */ +#define P_String 3 /* String */ +#define P_Complex 4 /* Complex */ +#define P_File_Spec 5 /* File Spec */ +#define P_Drive 6 /* Drive */ +#define P_Date_F 7 /* Date */ +#define P_Time_F 8 /* Time */ +#define P_Quoted_String 9 /* Quoted String */ + +#define P_No_Tag 0x0FF /* No ITEM_TAG found */ + +/*----------------------------------------------------------------------+ +| | +| Value list structure | +| | ++----------------------------------------------------------------------*/ + +struct noval + { + unsigned char null; + }; + +/*----------------------------------------------------------------------+ +| | +| following return code will be returned in the AX register. | +| | ++----------------------------------------------------------------------*/ + +#define P_No_Error 0 /* No error */ +#define P_Too_Many 1 /* Too many operands */ +#define P_Op_Missing 2 /* Required operand missing */ +#define P_Not_In_SW 3 /* Not in switch list provided */ +#define P_Not_In_Key 4 /* Not in keyword list provided */ +#define P_Out_Of_Range 6 /* Out of range specified */ +#define P_Not_In_Val 7 /* Not in value list provided */ +#define P_Not_In_Str 8 /* Not in string list provided */ +#define P_Syntax 9 /* Syntax error */ +#define P_RC_EOL 0x0ffff /* End of command line */ + + diff --git a/v4.0/src/CMD/JOIN/MAKEFILE b/v4.0/src/CMD/JOIN/MAKEFILE new file mode 100644 index 0000000..c177f0f --- /dev/null +++ b/v4.0/src/CMD/JOIN/MAKEFILE @@ -0,0 +1,81 @@ +#************************* makefile for cmd\join ************************ + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h +map =..\..\mapper +here =..\cmd\join # This is the path from INC or MAP dir's to here. +make =nmake -i + +# +####################### dependencies begin here. ######################### +# + +all: join.exe + +$(inc)\errtst.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\sysvar.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\cds.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\dpb.obj: + cd $(inc) + $(make) + cd $(here) + +$(inc)\comsubs.lib: + cd $(inc) + $(make) + cd $(here) + +$(map)\mapper.lib: + cd $(map) + $(make) + cd $(here) + +join.ctl: join.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + +_msgret.obj: _msgret.asm \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc \ + join.ctl \ + join.cla \ + join.cl1 \ + join.cl2 \ + join.skl + +_parse.obj: _parse.asm \ + $(inc)\parse.asm \ + $(inc)\psdata.inc + +join.obj: join.c \ + makefile \ + joinpars.h \ + $(hinc)\cds.h \ + $(hinc)\jointype.h \ + $(hinc)\sysvar.h + +join.exe: join.obj \ + $(inc)\errtst.obj \ + $(inc)\sysvar.obj \ + $(inc)\cds.obj \ + $(inc)\dpb.obj \ + $(map)\mapper.lib \ + $(inc)\comsubs.lib \ + _msgret.obj \ + _parse.obj \ + join.lnk + link @join.lnk diff --git a/v4.0/src/CMD/JOIN/_MSGRET.ASM b/v4.0/src/CMD/JOIN/_MSGRET.ASM new file mode 100644 index 0000000..085cb8b --- /dev/null +++ b/v4.0/src/CMD/JOIN/_MSGRET.ASM @@ -0,0 +1,250 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 message retriever +; +; CALLING FORMAT: +; sysloadmsg(&inregs,&outregs); +; sysgetmsg(&inregs,&outregs); +; sysdispmsg(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION;AN000; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; + + .8087 ;AN000; +_TEXT SEGMENT BYTE PUBLIC 'CODE' ;AN000; +_TEXT ENDS ;AN000; +_DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; +_DATA ENDS ;AN000; +CONST SEGMENT WORD PUBLIC 'CONST' ;AN000; +CONST ENDS ;AN000; +_BSS SEGMENT WORD PUBLIC 'BSS' ;AN000; +_BSS ENDS ;AN000; +DGROUP GROUP CONST, _BSS, _DATA ;AN000; + ASSUME CS: _TEXT, DS: _TEXT, SS: DGROUP, ES: DGROUP ;AN000; + + + public _sysloadmsg ;AN000; + public _sysgetmsg ;AN000; + public _sysdispmsg ;AN000; + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + +_DATA segment ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; + MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; +.LIST ;AN000; +.CREF ;AN000; +_DATA ends ;AN000; + + +_TEXT segment ;AN000; + +;------------------------------------------------------------------- + +; = = = = = = = = = = = = + + ;DEFAULT=CHECK DOS VERSION ;AN000; + ;DEFAULT=NEARmsg ;AN000; + ;DEFAULT=INPUTmsg ;AN000; + ;DEFAULT=NUMmsg ;AN000; + ;DEFAULT=NO TIMEmsg ;AN000; + ;DEFAULT=NO DATEmsg ;AN000; +; MSG_SERVICES ;AN000; +; MSG_SERVICES ;MSG TEXT ;AN000; +.XLIST ;AN000; +.XCREF ;AN000; +; MSG_SERVICES ;DATA AREA FOR THE MESSAGE HANDLER ;AN000; + MSG_SERVICES ;AN000; + MSG_SERVICES ;MSG TEXT ;AN000; +.LIST ;AN000; +.CREF ;AN000; +;------------------------------------------------------------------- + +_sysloadmsg proc near ;AN000; + + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) ;AN000; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack;AN000; + + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; + + push bp ; save base pointer ;AN000; + +;------------------------------------------------------------------- + call sysloadmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; + + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; + + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; + + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; + +_sysloadmsg endp ;AN000; + + +_sysgetmsg proc near ;AN000; + + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) ;AN000; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack;AN000; + + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; + + push bp ; save base pointer ;AN000; + +;------------------------------------------------------------------- + call sysgetmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; + + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; + + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; + + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; + +_sysgetmsg endp ;AN000; + +_sysdispmsg proc near ;AN000; + + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) ;AN000; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack;AN000; + + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; + + push bp ; save base pointer ;AN000; + +;------------------------------------------------------------------- + call sysdispmsg ; call the message retriever ;AN000; +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; + + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; + + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; + + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; + +_sysdispmsg endp ;AN000; + +include msgdcl.inc + +_TEXT ends ; end code segment ;AN000; + end ;AN000; + + \ No newline at end of file diff --git a/v4.0/src/CMD/JOIN/_PARSE.ASM b/v4.0/src/CMD/JOIN/_PARSE.ASM new file mode 100644 index 0000000..8c72302 --- /dev/null +++ b/v4.0/src/CMD/JOIN/_PARSE.ASM @@ -0,0 +1,121 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 parser +; +; **(Customized for the JOIN utility) +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse ;AN000; + +;------------------------------------------------------------------- + +; set for JOIN +; ------------- + +FarSW equ 0 ; make sysparse be a NEAR proc ;AN000; +TimeSW equ 0 ; Check time format ;AN000; +FileSW equ 1 ; Check file specification ;AN000; +CAPSW equ 1 ; Perform CAPS if specified ;AN000; +CmpxSW equ 0 ; Check complex list ;AN000; +NumSW equ 0 ; Check numeric value ;AN000; +KeySW equ 0 ; Support keywords ;AN000; +SwSW equ 1 ; Support switches ;AN000; +Val1SW equ 0 ; Support value definition 1 ;AN000; +Val2SW equ 0 ; Support value definition 2 ;AN000; +Val3SW equ 0 ; Support value definition 3 ;AN000; +DrvSW equ 1 ; Support drive only format ;AN000; +QusSW equ 0 ; Support quoted string format ;AN000; +;------------------------------------------------------------------- + +DGROUP GROUP _DATA +PGROUP GROUP _TEXT + +_DATA segment byte public 'DATA' ;AN000; +BASESW = 1 ;SPECIFY, PSDATA POINTED TO BY "DS" +INCSW = 0 ;PSDATA.INC IS ALREADY INCLUDED + INCLUDE PSDATA.INC ;PARSER'S WORK SPACE +_DATA ends ;AN000; + +_TEXT segment byte public 'CODE' ;AN000; + + ASSUME CS: PGROUP ;AN000; + ASSUME DS: DGROUP ;AN000; + +;------------------------------------------------------------------- +include parse.asm ; include the parser ;AN000; +;------------------------------------------------------------------- + +_parse proc near ;AN000; + + push bp ; save user's base pointer ;AN000; + mov bp,sp ; set bp to current sp ;AN000; + push di ; save some registers ;AN000; + push si ;AN000; + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) ;AN000; + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di ;AN000; + push ax ; the di value from inregs is now on stack;AN000; + + mov ax,[di+00] ; get inregs.x.ax ;AN000; + mov bx,[di+02] ; get inregs.x.bx ;AN000; + mov cx,[di+04] ; get inregs.x.cx ;AN000; + mov dx,[di+06] ; get inregs.x.dx ;AN000; + mov si,[di+08] ; get inregs.x.si ;AN000; + pop di ; get inregs.x.di from stack ;AN000; + + push bp ; save base pointer ;AN000; + +;------------------------------------------------------------------- + call sysparse ; call the parser ;AN000; +;------------------------------------------------------------------- + + pop bp ; restore base pointer ;AN000; + push di ; the di value from call is now on stack;AN000; + mov di,[bp+6] ; fix di (arg 1) ;AN000; + + mov [di+00],ax ; load outregs.x.ax ;AN000; + mov [di+02],bx ; load outregs.x.bx ;AN000; + mov [di+04],cx ; load outregs.x.cx ;AN000; + mov [di+06],dx ; load outregs.x.dx ;AN000; + mov [di+08],si ; load outregs.x.si ;AN000; + + lahf ; get flags into ax ;AN000; + mov al,ah ; move into low byte ;AN000; + mov [di+0ch],ax ; load outregs.x.cflag ;AN000; + + pop ax ; get di from stack ;AN000; + mov [di+0ah],ax ; load outregs.x.di ;AN000; + +;------------------------------------------------------------------- + + pop si ; restore registers ;AN000; + pop di ;AN000; + mov sp,bp ; restore sp ;AN000; + pop bp ; restore user's bp ;AN000; + ret ;AN000; + +_parse endp ;AN000; + +_TEXT ends ; end code segment ;AN000; + end ;AN000; + + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/COMMSUBS.ASM b/v4.0/src/CMD/KEYB/COMMSUBS.ASM new file mode 100644 index 0000000..3810ed2 --- /dev/null +++ b/v4.0/src/CMD/KEYB/COMMSUBS.ASM @@ -0,0 +1,603 @@ + PAGE ,132 + TITLE DOS - KEYB Command - Transient Command Processing + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: COMMSUBS.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Common subroutines used by NLS support +;; +;; Documentation Reference: +;; ------------------------ +;; None +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; +;; FIND_HW_TYPE - Determine the keyboard and system unit types and +;; set the corresponding flags. +;; +;; Include Files Required: +;; ----------------------- +;; None +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE ????????.ASM: +;; ????????? - ???????????????????????????????????????????? +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + PUBLIC FIND_SYS_TYPE ;; + PUBLIC FIND_KEYB_TYPE ;; + PUBLIC HW_TYPE ;; + PUBLIC SECURE_FL ;; + + ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE KEYBCPSD.INC ;; + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBCMD.INC ;; + INCLUDE DSEG.INC ;; + INCLUDE POSTEQU.INC ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: FIND_SYS_TYPE +;; +;; Description: +;; Determine the type of system we are running on. +;; SYSTEM_FLAG (in active SHARED_DATA) are set to +;; indicate the system type. +;; This routine is only called the first time KEYB is being installed. +;; +;; +;; Input Registers: +;; DS - points to our data segment +;; +;; Output Registers: +;; NONE +;; +;; Logic: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +ROM SEGMENT AT 0F000H ;; + ORG 0FFFEH ;; +ROMID DB ? ;; + ;; SEGMENT F000. (F000:FFFE) + ;; +ROMPC1 EQU 0FFH ;; ID OF PC1 hardware +ROMXT EQU 0FEH ;; ID OF PC-XT/PORTABLE hardware +ROMJR EQU 0FDH ;; ID OF PCjr & Optional ROM +ROMAT EQU 0FCH ;; ID OF PCAT +ROMXT_ENHAN EQU 0FBH ;; ID OF ENHANCED PCXT +ROMPAL EQU 0FAH ;; ID FOR PALACE +ROMLAP EQU 0F9H ;; ID FOR PC LAP (P-14) +ROM_RU_386 EQU 0F8H ;; ID FOR ROUNDUP-386 + ;; +ROM ENDS ;; + ;; + ;; ******** CNS + ROMEXT SEGMENT AT 00000H ;; ADDRESS SHOULD NOT BE FIXED AT + ORG 0003BH ;;AT 09FC0H -- This is just a ;; + KEYBID1 DB ? ;;a dummy value of 000H INT 15H call + ;; will load dynamically depending + ;; upon system mem size- 9FC0 was only for 640K system + ;; *** UNTRUE SEGMENT 9FC0. (9FC0:003B) + ROMEXT ENDS ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;***CNS + + + + + + + + +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FIND_SYS_TYPE PROC NEAR ;; + ;; + MOV AX,ROM ;; Set segmant to look at ROM + MOV DS,AX ;; using the data segment + ASSUME DS:ROM ;; + ;; + MOV AL,ROMID ;; Get hardware ID + PUSH AX ;; save it + ;; + PUSH CS ;; Set data seg back to code + POP DS ;; + ASSUME DS:CODE ;; + ;; + MOV AH,92H ;; SET INVALID CALL FOR INT16 + INT 16H ;; CALL BIOS + CMP AH,80H ;; IS EXTENDED INTERFACE THERE? + JA CHECK_PC_NET ;; NO, SKIP FLAG + OR SD.SYSTEM_FLAG,EXT_16 ;; default is extended INT 16 support + ;; +CHECK_PC_NET: ;; + MOV AH,30H ;; GET DOS VERSION NUMBER + INT 21H ;; MAJOR # IN AL, MINOR # IN AH + CMP AX,0A03H ;; SENSITIVE TO 3.10 OR > + JB CHECK_SYSTEM ;; EARLIER VERSION OF DOS NOTHING + ;; WAS ESTABLISHED FOR THIS SITUATION + PUSH ES ;; Save ES just in case + MOV AX,3509H ;; GET INT VECTOR 9 CONTENTS + INT 21H ;; ES:BX WILL = CURRENT INT9 VECTOR + ;; WE WANT TO SEE IF WE ARE THE 1ST ONES LOADED + MOV CX,ES ;; INTO THE INT VECTOR 9. WITH DOS 3.1 WE CAN + POP ES ;; + CMP CX,0F000H ;; HANDSHAKE WITH THE PC NETWORK BUT NO ONE ELSE + JE CHECK_SYSTEM ;; INT VECTOR 9 POINTS TO ROM, OK + MOV AX,0B800H ;; ASK IF PC NETWORK IS INSTALLED + INT 2FH ;; + CMP AL,0 ;; NOT INSTALLED IF AL=0 + JE CHECK_SYSTEM ;; SOMEBODY ELSE HAS LINKED INTO THE INT VECTOR + ;; 9 & I'M GOING TO DROP RIGHT IN AS USUAL + OR SD.SYSTEM_FLAG,PC_NET ;; INDICATE PC NET IS RUNNING + ;; +CHECK_SYSTEM: ;; + POP AX ;; get code back + ;; Is the hardware a PCjr + CMP AL,ROMJR ;; + JNE TEST_PC_XT ;; IF not then check for next type + OR SD.SYSTEM_FLAG,PC_JR ;; system type + JMP FIND_SYS_END ;; Done + ;; +TEST_PC_XT: ;; + ;; Is the hardware a PC1 or XT ? + CMP AL,ROMXT ;; + JAE ITS_AN_XT ;; IF FE OR FF THEN ITS AN XT + CMP AL,ROMXT_ENHAN ;; IF FB IT IS ALSO AN XT + JNE TEST_PC_AT ;; IF not then check for next type +ITS_AN_XT: ;; + OR SD.SYSTEM_FLAG,PC_XT ;; system type + JMP FIND_SYS_END ;; + ;; +TEST_PC_AT: ;; + ;; Is the hardware an AT ? + CMP AL,ROMAT ;; + JNE TEST_P12 ;; IF not then check for next type + ;; + OR SD.SYSTEM_FLAG,PC_AT ;; system type + ;; + JMP FIND_SYS_END ;; + ;; +TEST_P12: ;; + CMP AL,ROMLAP ;; IS this a P12? + JNE TEST_PAL ;; IF not then check for next type + OR SD.SYSTEM_FLAG,PC_LAP ;; system type + JMP FIND_SYS_END ;; + ;; +TEST_PAL: ;; + CMP AL,ROMPAL ;; IS this a PALACE? + JNE TEST_RU_386 ;; IF not then check for next type + OR SD.SYSTEM_FLAG,PC_PAL ;; system type + JMP FIND_SYS_END ;; + ;; +TEST_RU_386: ;; + CMP AL,ROM_RU_386 ;; IS this a ROUNDUP with a 386? + JNE FIND_SYS_END ;; IF not then check for next type + OR SD.SYSTEM_FLAG,PC_386 ;; system type + MOV SD.TIMING_FACTOR,2 ;; Bump scale factor to account for 386 + ;; +FIND_SYS_END: ;; + ;; + RET ;; + ;; +FIND_SYS_TYPE ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: FIND_KEYB_TYPE +;; +;; Description: +;; Determine the type of keyboard we are running on. +;; KEYB_TYPE (in SHARED_DATA) is set to +;; indicate the keyboard type. +;; This routine is only called the first time KEYB is being installed. +;; +;; +;; Input Registers: +;; DS - points to our data segment +;; +;; Output Registers: +;; NONE +;; +;; Logic: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +HW_TYPE DW 0 ;; +;***CNS ;; + +SECURE_FL DB 0 +;RESERVED ADDRESS 013h BITS 1 & 2 + + PASS_MODE equ 00000001B ;AN000; + SERVER_MODE equ 00000010B ;AN000; + SECRET_ADD equ 13h ;AN000; + PORT_70 equ 70h ;AN000; + PORT_71 equ 71h ;AN000; + +;***CNS +G_KEYBOARD EQU 0AB41h ;;????? ;; Keyboard ID for FERRARI_G +P_KEYBOARD EQU 0AB54h ;;????? ;; Keyboard ID for FERRARI_P + ;; +P_KB_ID DB 08 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FIND_KEYB_TYPE PROC NEAR ;; + ;; + PUSH ES ;; + PUSH DS ;; + ;; + MOV AX,ROM ;; Set segmant to look at ROM + MOV DS,AX ;; using the data segment + ASSUME DS:ROM ;; + ;; + MOV AX,DATA ;; + MOV ES,AX ;; ES points to BIOS data + ;; + MOV AL,ROMID ;; Get hardware ID + ;; + PUSH CS ;; Set data seg back to code + POP DS ;; + ASSUME DS:CODE ;; + ;; + ;; + MOV HW_TYPE,G_KB ;; Default keyboard is G_KB + ;; + ;; Is the hardware a PCjr + CMP AL,ROMJR ;; + JNE TEST_PC_XT_2 ;; IF not then check for next type + MOV HW_TYPE,JR_KB ;; keyboard type + JMP FIND_KEYB_END ;; Done + ;; +TEST_PC_XT_2: ;; + ;; Is the hardware a PC1 or XT ? + CMP AL,ROMXT ;; + JAE ITS_AN_XT_2 ;; IF FE OR FF THEN ITS AN XT + CMP AL,ROMXT_ENHAN ;; IF FB IT IS ALSO AN XT + JNE TEST_PC_AT_2 ;; IF not then check for next type +ITS_AN_XT_2: ;; + TEST ES:KB_FLAG_3,KBX ;; IS THE ENHANCED KEYBOARD INSTALLED? + JZ ITS_AN_XT_3 ;; + JMP FIND_KEYB_END ;; Yes, exit + ;; +ITS_AN_XT_3: ;; + MOV HW_TYPE,XT_KB ;; NO, normal XT keyboard + JMP FIND_KEYB_END ;; + ;; +TEST_PC_AT_2: ;; + ;; Is the hardware an AT ? + CMP AL,ROMAT ;; + JNE TEST_P12_2 ;; IF not then check for next type + ;; + ;; CHECK FOR ENHANCED KEYBOARD... + OR ES:KB_FLAG_2,08H ;; FROM COMNBODY.ASM - DON'T KNOW WHY + ;; + ;; READ ID COMMAND TO TEST FOR A KBX + ;; + MOV ES:KB_FLAG_3,RD_ID ;; INDICATE THAT A READ ID IS BEING + ;; DONE + MOV AL,0F2H ;; SEND THE READ ID COMMAND + CALL SND_DATA_AT ;; + ;; + MOV CX,03F00H ;; LOAD COUNT FOR ABOUT 37MS +WT_ID: TEST ES:KB_FLAG_3,KBX ;; TEST FOR KBX SET + LOOPZ WT_ID ;; WAIT OTHERWISE + ;; BE SURE FLAGS GOT RESET +;***CNS + ;; SAVE ALL REGISTERS BEFORE ENTRY + ;; INTO CHECKING KEYBOARD SECURITY + PUSH AX ;AN000; ;SAVE THE CURRENT ENVIRONMENT + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH DS ;AN000; + PUSH ES ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + + + + CALL KEYB_SECURE ;SEE IF THE KEYBOARD SECURITY IS + ;ACTIVATED AT THIS POINT + + + POP DI ;AN000; + POP SI ;AN000; + POP ES ;AN000; + POP DS ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000;SAVE THE CURRENT ENVIRONMENT + + JNC ASSUME_AT ;AN000;SECURITY UNAVAILABLE OR AN AT KB + + + MOV SECURE_FL,1 ;AN000;SECURITY IS ACTIVE + JMP FIND_KEYB_END ;AN000;ASSUME IT IS A G_KB WITH + ;AN000;NUM LOCK OFF +ASSUME_AT: +;***CNS + AND ES:KB_FLAG_3,NOT RD_ID+LC_AB + ;; + TEST ES:KB_FLAG_3,KBX ;; WAS IT A KBX? + JNZ DONE_AT_2 ;; YES, WE ARE DONE + ;; + MOV HW_TYPE,AT_KB ;; NO, AT KBD +DONE_AT_2: ;; + JMP FIND_KEYB_END ;; + ;; +TEST_P12_2: ;; + CMP AL,ROMLAP ;; IS this a P12? + JNE TEST_XT_ENH_OR_NEWER ;; IF not then check for next type + MOV HW_TYPE,P12_KB ;; IF yes then set flag + ;; +TEST_XT_ENH_OR_NEWER: ;; + CMP AL,ROMXT_ENHAN ;; + JNA GET_KEYB_ID ;; ** assume all new systems will have ext + JMP FIND_KEYB_END ;; ** ROM or else test previous to this + ;; +GET_KEYB_ID: ;; +;***************************** CNS **************************************** +;* This area has been Revised to allow the extended ROM support added +;* flexibility for the PALACE or FLASHLIGHT with less than 640k; AN extended +;* BIOS DATA call is to be made returning the segment of the extended +;* BIOS area which should be in maximum memory - 1k area. +;*************************************************************************** + + MOV AH,0C1H ;; Make the extended bios data area + INT 15H ;; call to get the segment address for + JNC NEW_SYSTEM ;; accessing the keyboard byte area + JMP FIND_KEYB_END ;; JNC SOMEWHERE&REPORT + ;; otherwise EXTENDED BIOS DATA RETURNED + ;; in the ES + ;; save the starting seg address value + ;; needs to start at locale 0003BH +;**************************************************************************** +NEW_SYSTEM: +;**CNS + ;; Set segment to look at extended ROM + ;; using the data segment + PUSH ES ;; SEG value returned from INT15h -- C1 call + POP DS + ASSUME DS:ROMEXT ;; + ;; + MOV AX,DATA ;; + MOV ES,AX ;; BP points to BIOS data + + ;; + MOV AL,KEYBID1 ;; Get keyboard ID ********** CNS +;**CNS +;***************************************************************************** +;old MOV AX,ROMEXT ;; Set segment to look at extended ROM +;code MOV DS,AX ;; using the data segment +; ASSUME DS:ROMEXT ;; +; ;; +; MOV AX,DATA ;; +;old MOV ES,AX ;; ES points to BIOS data +;code ;; +; MOV AL,KEYBID1 ;; Get keyboard ID +;****************************************************************************** + PUSH CS ;; Set data seg back to code + POP DS ;; + ASSUME DS:CODE ;; + ;; + AND AL,0FH ;; Remove high nibble + CMP AL,P_KB_ID ;; IF keyboard is a FERRARI P THEN + JNE FIND_KEYB_END ;; + OR HW_TYPE,P_KB ;; Set the HW_TYPE flag + ;; +FIND_KEYB_END: ;; ELSE + MOV AX,HW_TYPE ;; Leave default alone + MOV SD.KEYB_TYPE,AX ;; + ;; + POP DS ;; + POP ES ;; + RET ;; + ;; +FIND_KEYB_TYPE ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: SND_DATA_AT +;; +;; Description: +;; THIS ROUTINE HANDLES TRANSMISSION OF PC/AT COMMAND AND DATA BYTES +;; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO +;; HANDLES ANY RETRIES IF REQUIRED +;; +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to the BIOS data segment +;; +;; Output Registers: +;; +;; Logic: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +SND_DATA_AT PROC NEAR + PUSH AX ; SAVE REGISTERS + PUSH BX ; * + PUSH CX + MOV BH,AL ; SAVE TRANSMITTED BY FOR RETRIES + MOV BL,3 ; LOAD RETRY COUNT +SD0: CLI ; DISABLE INTERRUPTS + AND ES:KB_FLAG_2,NOT (KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS + +;------- WAIT FOR COMMAND TO BE ACCEPTED + + SUB CX,CX +SD5: + IN AL,STATUS_PORT + TEST AL,INPT_BUF_FULL + LOOPNZ SD5 ; WAIT FOR COMMAND TO BE ACCEPTED +; + MOV AL,BH ; REESTABLISH BYTE TO TRANSMIT + OUT PORT_A,AL ; SEND BYTE + STI ; ENABLE INTERRUPTS + MOV CX,01A00H ; LOAD COUNT FOR 10mS+ +SD1: TEST ES:KB_FLAG_2,KB_FE+KB_FA ; SEE IF EITHER BIT SET + JNZ SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS +; + LOOP SD1 ; OTHERWISE WAIT +; +SD2: DEC BL ; DECREMENT RETRY COUNT + JNZ SD0 ; RETRY TRANSMISSION +; + OR ES:KB_FLAG_2,KB_ERR ; TURN ON TRANSMIT ERROR FLAG + JMP SHORT SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION +; +SD3: TEST ES:KB_FLAG_2,KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE + JZ SD2 ; IF NOT, GO RESEND +; + ;; If this was an acknowledge, determine*RPS + ;; if keyboard is FERRARI G or P *RPS + MOV CX,1000 ;; +IO_DELAY1: ;; + LOOP IO_DELAY1 ;; + JMP SHORT $+2 ;; Allow for recovery time + IN AL,PORT_A ;; READ IN THE CHARACTER *RPS + MOV CX,1000 ;; +IO_DELAY2: ;; + LOOP IO_DELAY2 ;; + JMP SHORT $+2 ;; Allow for recovery time + MOV BH,AL ;; *RPS + ;; + IN AL,PORT_A ;; READ IN THE CHARACTER *RPS + MOV BL,AL ;; *RPS + ;; *RPS + CMP BX,P_KEYBOARD ;; Set HW_TYPE appropriately *RPS + JNE SD4 ;; *RPS + OR HW_TYPE,P_KB ;; *RPS + ;; +SD4: POP CX ; RESTORE REGISTERS + POP BX + POP AX ; * + RET ; RETURN, GOOD TRANSMISSION +SND_DATA_AT ENDP + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;************************************************************************ +; KEYBOARD SECURITY LOGIC +; CHECK THE CMOS RAM @ ADDRESS HEX 013H +; CHECK TO SEE IF EITHER BITS 1 (PASSWORD) OR 2 (SERVER MODE) ARE SET ON +; IF EITHER BIT IS SET ON THE SYSTEM IS A MOD 50 on up +; REPORT MESSAGE KEYBOARD LOCKED UNABLE TO LOAD KEYBOARD TABLES +; OTHERWISE AN INVALID RESPONSE OR ZERO SHOULD BE RETURNED +; PROCEED AS WITH LOADING OF THE CORRECT TABLES + +; PROPOSED KEYBOARD SYNTAX + +; KEYB [lang],[cp],[[d:][path]KEYBOARD.SYS][/ID:id] + + + +;************************************************************************ + +KEYB_SECURE PROC NEAR + + + +;RESERVED ADDRESS 013h BITS 1 & 2 + +; PASS_MODE equ 00000001B ;AN000; +; SERVER_MODE equ 00000010B ;AN000; + + + +; SECRET_ADD equ 13h ;AN000; +; PORT_70 equ 70h ;AN000; +; PORT_71 equ 71h ;AN000; + +; PUSH AX ;AN000; ;SAVE THE CURRENT ENVIRONMENT +; PUSH BX ;AN000; +; PUSH CX ;AN000; +; PUSH DX ;AN000; +; PUSH CS ;AN000; +; PUSH DS ;AN000; +; PUSH ES ;AN000; +; PUSH SI ;AN000; +; PUSH DI ;AN000; + CLI ;AN000;;DISABLE THE INTERRUPT TO AVOID + ;AN000;;THE CMOS REGISTER BEFORE + ;AN000;;THE READ & WRITE IS DONE + + XOR AX,AX + MOV AL,SECRET_ADD + OUT PORT_70,AL ;AN000;;SEND THE ADDRESS CONTAINING THE + ;BITS FOR THE PASSWORD AND SERVER + ;MODE STATE TO PORT 70H + + + + + + IN AL,PORT_71 ;AN000;;READ THE DATA IN TO GET THE + ;RESULTS OF THE CHECK FOR THE + ;EXISTENCE OF SECURITY. + + MOV DX,AX + + TEST DL,PASS_MODE+SERVER_MODE ;AN000;;CHECK & SEE IF THE BITS ARE ON + JNZ KEYB_LOCKED ;AN000;;YES THEY ARE ON SO EXIT AND REPORT + CLC ;XOR AX,AX ;ASSUME THIS IS AN AT KEYBOARD + JMP SECURE_RET + +KEYB_LOCKED: + + STC ; MOV AX,1 ;AN000;SET THE SECURITY FLAG + ;ON; + ;PROCEED - EITHER SYSTEM IS AN + ;AT OR THE SYSTEM IS UNLOCKED +SECURE_RET: + + STI ;AN000;;ENABLE THE INTERRUPT + + +; POP DI ;AN000; +; POP SI ;AN000; +; POP ES ;AN000; +; POP DS ;AN000; +; POP CS ;AN000; +; POP DX ;AN000; +; POP CX ;AN000; +; POP BX ;AN000; +; POP AX ;AN000; ;SAVE THE CURRENT ENVIRONMENT + + + RET + + +KEYB_SECURE ENDP + + + + +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/COMMSUBS.INC b/v4.0/src/CMD/KEYB/COMMSUBS.INC new file mode 100644 index 0000000..96bea5d --- /dev/null +++ b/v4.0/src/CMD/KEYB/COMMSUBS.INC @@ -0,0 +1,30 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: CONVERT.INC +;; ---------- +;; +;; Root File Name: KEYBCMD.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; External declarations for procedures in file KEYBCMD.ASM. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN FIND_SYS_TYPE :NEAR ;; + EXTRN FIND_KEYB_TYPE :NEAR ;; + ;; + EXTRN HW_TYPE :WORD ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST diff --git a/v4.0/src/CMD/KEYB/KBMSG.INC b/v4.0/src/CMD/KEYB/KBMSG.INC new file mode 100644 index 0000000..f7beb54 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KBMSG.INC @@ -0,0 +1,21 @@ + ;; +ACT_KEYB DB 'Current keyboard code: ','$' ;; +ACT_KEYB_CP DB ' code page: ','$' ;; +ACT_CON_CP DB 'Current CON code page: ','$' ;; +INV_L DB 'Invalid keyboard code specified',10,13,'$' ;; +INV_I DB 'Invalid keyboard ID specified',10,13,'$' ;; +INV_CP DB 'Invalid code page specified',10,13,'$' ;; +INV_S DB 'Invalid syntax',10,13,'$' ;; +INV_FN DB 'Bad or missing Keyboard Definition File',10,13,'$' ;; +INV_KEYB_Q DB 'KEYB has not been installed',10,13,'$' ;; +INV_CON_Q DB 'Active code page not available from CON device',10,13,'$' ;; +NOT_DESIG DB 'Code page specified has not been prepared',10,13,'$' ;; +NOT_SUPP DB 'One or more CON code pages invalid for given keyboard code',10,13,'$' ;; +NOT_VALID1 DB 'Code page requested (','$' ;; +NOT_VALID2 DB ') is not valid for given keyboard code',10,13,'$' ;; +WARNING_1 DB 'Code page specified is inconsistent with the selected code page',10,13,'$' ;; +INV_COMBO DB 'ID code specified is inconsistent with the selected keyboard code',13,'$' ;; +MEMORY_OVERF DB 'Unable to create KEYB table in resident memory',10,13,'$' ;; +CR_LF DB 10,13,'$' ;; + ;; + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/KEYB.ASM b/v4.0/src/CMD/KEYB/KEYB.ASM new file mode 100644 index 0000000..fffce04 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYB.ASM @@ -0,0 +1,71 @@ + + PAGE ,132 + TITLE DOS - KEYB Command - Root Module + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (c) Copyright 1988 Microsoft +;; +;; File Name: KEYB.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Contains root module for KEYB command. This module is the +;; KEYB command entry point. KEYB is an external command included +;; with PC DOS 3.3 to provide keyboard support for 14 languages. +;; KEYB will jump immediately into the command processing in +;; file KEYBCMD. All resident code is included before KEYBCMD +;; in the linkage list. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 NLS Interface Specification - May ?? 1986 +;; PC DOS 3.3 Detailed Design Document - May ?? 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; +;; +;; Include Files Required: +;; ----------------------- +;; KEYBCMD.INC - External declarations for transient command +;; processing routines +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE KEYCMD.ASM: +;; KEYB_COMMAND - Main routine for transient command processing. +;; +;; Linkage Instructions: +;; -------------------- +;; Link in .COM format. Resident code/data is in files KEYB thru +;; KEYBCPSD. +;; +;; LINK KEYB+KEYBI9+KEYBI9C+KEYBI2F+KEYBI48+KEYBCPSD+KEYBMSG+ +;; COMMSUBS+KEYBTBBL+KEYBCMD; +;; EXE2BIN KEYB.EXE KEYB.COM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; +CODE SEGMENT PUBLIC 'CODE' BYTE ;; + ;; + INCLUDE KEYBCMD.INC ;; Bring in external declarations + ;; for transient command processing + ASSUME CS:CODE,DS:CODE ;; + ORG 100H ;; required for .COM + ;; + ;; +START: ;; + ;; + JMP KEYB_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +CODE ENDS + END START diff --git a/v4.0/src/CMD/KEYB/KEYB.LNK b/v4.0/src/CMD/KEYB/KEYB.LNK new file mode 100644 index 0000000..4ef13e5 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYB.LNK @@ -0,0 +1,3 @@ +Keyb+keybi9+KEYBI9C+keybi2f+keybi48+ +keybcpsd+commsubs+keybtbbl+parser+KEYBCMD; + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/KEYB.SKL b/v4.0/src/CMD/KEYB/KEYB.SKL new file mode 100644 index 0000000..7bb2b5c --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYB.SKL @@ -0,0 +1,37 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Message Skeleton file for KEYB.COM +; +; Author: WGR +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +:util KEYB ;AN000;ty name +:class 2 +:use PARSE1 ;AN000; +:use PARSE2 ;AN000; +:use PARSE3 ;AN000; +:use PARSE4 ;AN000; +:use PARSE6 ;AN000; +:use PARSE7 ;AN000; +:use PARSE10 ;AN003; +:class A +:use 1 COMMON1 ;AN000;rrect DOS version' +:def 2 "Current keyboard code: %1" ;AN000; +:def 3 "Current keyboard ID: %1" ;AN000; +:def 4 " code page: %1",CR,LF ;AN000; +:def 5 "Current CON code page: %1",CR,LF ;AN000; +:def 6 "Invalid keyboard code specified",CR,LF ;AN000; +:def 7 "Invalid keyboard ID specified",CR,LF ;AN000; +:def 8 "Invalid code page specified",CR,LF ;AN000; +:def 9 "Bad or missing Keyboard Definition File",CR,LF ;AN000; +:def 10 "KEYB has not been installed",CR,LF ;AN000; +:def 11 "Active code page not available from CON device",CR,LF ;AN000; +:def 12 "Code page specified has not been prepared",CR,LF ;AN000; +:def 13 "One or more CON code pages invalid for given keyboard code",CR,LF ;AN000; +:def 14 "Code page requested (%1) is not valid for given keyboard code",CR,LF ;AN000; +:def 15 "Code page specified is inconsistent with the selected code page",CR,LF ;AN000; +:def 16 "ID code specified is inconsistent with the selected keyboard code",CR,LF ;AN000; +:def 17 "Unable to create KEYB table in resident memory",CR,LF ;AN000; +:use 18 PARSE8 ; 'Parameter format not correct' ;AN000; +:end ;AN000; diff --git a/v4.0/src/CMD/KEYB/KEYBCMD.ASM b/v4.0/src/CMD/KEYB/KEYBCMD.ASM new file mode 100644 index 0000000..57033f3 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBCMD.ASM @@ -0,0 +1,2072 @@ + + PAGE ,132 + TITLE DOS - KEYB Command - Transient Command Processing + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBCMD.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Contains transient command processing modules for KEYB command. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May ?? 1986 +;; +;; Procedures contained in this file: +;; ---------------------------------- +;; KEYB_COMMAND: Main routine for command processing. +;; PARSE_PARAMETERS: Validate syntax of parameters included +;; on command line. +;; BUILD_PATH: Find KEYBOARD.SYS file and validate language and/or +;; code page. +;; INSTALL_INT_VECTORS: Install our INT 9, INT 2F, INT48 Drivers +;; REMOVE_INT_VECTORS: Remove our INT 9, INT 2F, INT48 Drivers +;; NUMLK_ON: Turn on the NUM LOCK LED +;; FIND_FIRST_CP: Determine first code page for given language in the +;; Keyboard Definition file. +;; +;; Include Files Required: +;; ----------------------- +;; KEYBMSG.INC +;; KEYBEQU.INC +;; KEYBSYS.INC +;; KEYBI9C.INC +;; KEYBI9.INC +;; KEYBI2F.INC +;; KEYBI48.INC +;; KEYBSHAR.INC +;; KEYBDCL.INC +;; KEYBTBBL.INC +;; COMMSUBS.INC +;; KEYBCPSD.INC +;; POSTEQU.INC +;; DSEG.INC +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE KEYBTBBL.ASM: +;; TABLE_BUILD - Create the shared area containing all keyboard tables. +;; STATE_BUILD - Build all states within the table area +;; FROM FILE KEYBMSG.ASM: +;; KEYB_MESSAGES - All messages +;; +;; Change History: +;; +;; Revised for DOS 4.00 - NickS +;; A000 - WilfR +;; AN002- DCR ???? -KEYBAORD SECURITY LOCK - CNS +;; +;; +;; an003 PTM 3906 - KEYB messages do not conform +;; to spec. Error message does +;; 3/24/88 not pass back the bogus command +;; line argument. - CNS +;; +;; +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + PUBLIC KEYB_COMMAND ;; + ;; +;*****************CNS******************** + PUBLIC ID_TAB_OFFSET ;AN000; +;*****************CNS******************** + PUBLIC CP_TAB_OFFSET ;; + PUBLIC STATE_LOGIC_OFFSET ;; + PUBLIC SYS_CODE_PAGE ;; + PUBLIC KEYBCMD_LANG_ENTRY_PTR ;; + PUBLIC DESIG_CP_BUFFER ;; + PUBLIC DESIG_CP_OFFSET ;; + PUBLIC KEYBSYS_FILE_HANDLE ;; + PUBLIC NUM_DESIG_CP ;; + PUBLIC TB_RETURN_CODE ;; + PUBLIC FILE_BUFFER ;; + PUBLIC FILE_BUFFER_SIZE + PUBLIC FB ;; +;*****************CNS******************** + PUBLIC ID_PTR_SIZE ;AN000; + PUBLIC LANG_PTR_SIZE ;AN000; + PUBLIC CP_PTR_SIZE ;AN000; + PUBLIC NUM_ID ;AN000; + PUBLIC NUM_LANG ;AN000; + PUBLIC NUM_CP ;AN000; + PUBLIC SHARED_AREA_PTR ;; +;*****************CNS******************** + PUBLIC SD_SOURCE_PTR ;; + PUBLIC TEMP_SHARED_DATA ;; + ;; + PUBLIC FOURTH_PARM ;AN000; ;AN000 + PUBLIC ONE_PARMID ;AN000; ;AN000 + PUBLIC FTH_PARMID ;AN000; ;AN000 + PUBLIC ID_FOUND ;AN000; ;AN000 + PUBLIC BAD_ID ;AN000; ;AN000 + PUBLIC ALPHA ;AN000; ;AN000 + EXTRN PARSE_PARAMETERS:NEAR ;AN000; ;AN000 +;***CNS + EXTRN SECURE_FL:BYTE ;an002; + EXTRN CUR_PTR:WORD ;an003; + EXTRN OLD_PTR:WORD ;an003; + EXTRN ERR_PART:WORD ;an003; +;***CNS +.xlist + INCLUDE STRUC.INC ;AN000;;; WGR structured macros ;AN000 + INCLUDE SYSMSG.INC ;AN000;;; WGR message retriever ;AN000 +.list + ;; +MSG_UTILNAME ;AN000;;; WGR identify to message retriever ;AN000 + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; +.xlist ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE KEYBSYS.INC ;; + INCLUDE KEYBI9.INC ;; + INCLUDE KEYBI9C.INC ;; + INCLUDE KEYBI2F.INC ;; + INCLUDE KEYBI48.INC ;; + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBDCL.INC ;; + INCLUDE KEYBTBBL.INC ;; + INCLUDE COMMSUBS.INC ;; + INCLUDE KEYBCPSD.INC ;; +.xlist + INCLUDE POSTEQU.INC ;; + INCLUDE DSEG.INC ;; + ;; +.list + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: KEYB_COMMAND +;; +;; Description: +;; Main routine for transient command processing. +;; +;; Input Registers: +;; DS - points to our data segment +;; +;; Output Registers: +;; Upon termination, if an error has occurred in which a keyboard table +;; was not loaded, the AL register will contain the a error flag. This +;; flag is defined as follows: +;; AL:= 1 - Invalid language, code page, or syntax +;; 2 - Bad or missing Keyboard Definition File +;; 3 - KEYB could not create a table in resident memory +;; 4 - An error condition was received when communicating +;; with the CON device +;; 5 - Code page requested has not been designated +;; 6 - The keyboard table for the requested code page cannot +;; be found in resident keyboard table. +;; +;; Logic: +;; IF KEYB has NOT been previously loaded THEN +;; Set SHARED_AREA_PTR to TEMP_SHARED_AREA +;; INSTALLED_KEYB := 0 +;; Get HW_TYPE (set local variable) +;; ELSE +;; Set SHARED_AREA_PTR to ES:SHARED_AREA +;; Get HW_TYPE (set local variable) +;; Set TABLE_OK := 0 +;; INSTALLED_KEYB := 1 +;; +;; IF CPS-CON has been loaded THEN +;; INSTALLED_CON := 1 +;; +;;*********************************** CNS ************************************* +;; Call PARSE_PARAMETERS := Edit ID or language, code page, +;; and path parameters,ID on command line +;;*********************************** CNS ************************************* +;; Check all return codes: +;; IF any parameters are invalid THEN +;; Display ERROR message +;; ELSE +;; IF no language parm specified +;; AND code page is not invalid +;; AND syntax is valid THEN +;; Process QUERY: +;; IF KEYB is installed THEN +;; Get and display active language from SHARED_DATA_AREA +;; Get invoked code page from SHARED_DATA_AREA +;; Convert to ASCII +;; Display ASCII representation of code page, CR/LF +;;*********************************** CNS ************************************* +;; IF ALTERNATE FLAG SET +;; Get and display active ID from SHARED_DATA_AREA +;; Convert to ASCII +;; Display ASCII representation of ID, CR/LF +;;*********************************** CNS ************************************* +;; IF CPS-CON is installed THEN +;; Get selected code page info from CON +;; Convert to ASCII +;; Display ASCII representation of code page, CR/LF +;; EXIT without staying resident +;; +;; ELSE +;; Call BUILD_PATH := Determine location of Keyboard definition file +;; Open the file +;; IF error in opening file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Save handle +;; Set address of buffer +;; READ header of Keyboard definition file +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Check signature for correct file +;; IF file signature is correct THEN +;; READ language table +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Use table to verify language parm +;; Set pointer values +;; IF code page was specified +;; READ language entry +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; READ Code page table +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Use table to verify code page parm +;; Set pointer values +;; IF CPS-CON is not installed THEN +;; Set number of code pages = 1 +;; IF CODE_PAGE_PARM was specified THEN +;; Copy CODE_PAGE_PARM into table of code pages to build +;; ELSE +;; Call FIND_FIRST_CP := Define the system code page (1st in Keyb Def file) +;; Copy SYSTEM_CP into table of code pages to build +;; ELSE +;; Issue INT 2F ; 0AD03H to get table of Designated code pages +;; Set number of designated code pages (HWCP + Desig CP) +;; Issue INT 2F ; 0AD02H to get invoked code page +;; IF CODE_PAGE_PARM was specified THEN +;; Check that CODE_PAGE_PARM is in the list of designated code pages +;; IF CODE_PAGE_PARM is in the list of designated code pages THEN +;; Copy specified CP into table of code pages to build +;; IF a CP has been selected AND is inconsistent with specified CP +;; Issue WARNING message +;; ELSE +;; Display ERROR message +;; ELSE +;; IF a code page has been invoked THEN +;; Copy invoked code page into table of code pages to build +;; ELSE +;; Call FIND_FIRST_CP := Define the system code page (1st in Keyb Def file) +;; Copy SYSTEM_CP into table of code pages to build +;; +;; IF KEYB has not been previously installed THEN +;; Call FIND_SYS_TYPE := Determine system type +;; IF system type is PCjr THEN +;; IF multilingual ROM is present THEN +;; Set language code +;; EXIT without staying resident +;; Call INSTALL_INT_9 := Install INT 9 handler +;; Call FIND_KEYB_TYPE := Determine the keyboard type +;; +;; Call TABLE_BUILD := Build the TEMP_SHARED_DATA_AREA +;; +;; IF return codes from TABLE_BUILD are INVALID THEN +;; IF KEYB_INSTALLED := 0 THEN +;; Call REMOVE_INT_9 +;; Display corresponding ERROR message +;; EXIT without staying resident +;; ELSE +;; IF any of the designated CPs were invalid in the build THEN +;; Issue WARNING message +;; Close the Keyboard definition file +;; IF KEYB had NOT already been installed THEN +;; IF keyboard is a Ferrari_G AND system is not an XT THEN +;; Call NUMLK_ON := Turn the NUM LOCK LED on +;; IF extended INT 16 support required THEN +;; Install extended INT 16 support +;; Call INSTALL_INT_9_NET := Let network know about INT 9 +;; Call INSTALL_INT_2F_48 := Install the INT 2F and INT 48 drivers +;; Activate language +;; Get resident end and copy TEMP_SHARED_DATA_AREA into SHARED_DATA_AREA +;; EXIT but stay resident +;; ELSE +;; IF this was not a query call AND exit code was valid THEN +;; Activate language +;; Get resident end and copy TEMP_SHARED_DATA_AREA into SHARED_DATA_AREA +;; EXIT without staying resident +;; END +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +INVALID_PARMS EQU 1 ;; EXIT return codes +BAD_KEYB_DEF_FILE EQU 2 ;; +MEMORY_OVERFLOW EQU 3 ;; +CONSOLE_ERROR EQU 4 ;; +CP_NOT_DESIGNATED EQU 5 ;; +KEYB_TABLE_NOT_LOAD EQU 6 ;; +BAD_DOS_VER EQU 7 ;AN000;;; WGR ;AN000 + ;; +EXIT_RET_CODE DB 0 ;; +;******************** CNS *********** ;AN000;;; +ID_VALID EQU 0 ;AN000;;; +ID_INVALID EQU 1 ;AN000;;; +NO_ID EQU 2 ;AN000;;; +LANGUAGE_VALID EQU 0 ;AN000;;; +LANGUAGE_INVALID EQU 1 ;AN000;;; Return Codes +NO_LANGUAGE EQU 2 ;AN000;;; from +NO_IDLANG EQU 3 ;AN000;;; +;******************** CNS *********** ;; +CODE_PAGE_VALID EQU 0 ;; EDIT_LANGUAGE_CODE +CODE_PAGE_INVALID EQU 1 ;; +NO_CODE_PAGE EQU 2 ;; +VALID_SYNTAX EQU 0 ;; +INVALID_SYNTAX EQU 1 ;;;;;;; + ;; +ACT_KEYB EQU 2 ;AC000;;; WGR ;AN000 +ACT_ID EQU 3 ;AC000;;; WGR ;AN000 +ACT_KEYB_CP EQU 4 ;AC000;;; WGR ;AN000 +ACT_CON_CP EQU 5 ;AC000;;; WGR ;AN000 +INV_L EQU 6 ;AC000;;; WGR message numbers... ;AN000 +INV_I EQU 7 ;AC000;;; WGR ;AN000 +INV_CP EQU 8 ;AC000;;; WGR ;AN000 +INV_S EQU 18 ;AC000;;; WGR ;AN000 +INV_FN EQU 9 ;AC000;;; WGR ;AN000 +INV_KEYB_Q EQU 10 ;AC000;;; WGR ;AN000 +INV_CON_Q EQU 11 ;AC000;;; WGR ;AN000 +NOT_DESIG EQU 12 ;AC000;;; WGR ;AN000 +NOT_SUPP EQU 13 ;AC000;;; WGR ;AN000 +NOT_VALID EQU 14 ;AC000;;; WGR ;AN000 +WARNING_1 EQU 15 ;AC000;;; WGR ;AN000 +INV_COMBO EQU 16 ;AC000;;; WGR ;AN000 +MEMORY_OVERF EQU 17 ;AC000;;; WGR ;AN000 +CR_LF DB 10,13,'$' ;; WGR ;AN000 + ;; +FOURTH_PARM DB 0 ;AN000;;; WGR switch was specified ;AN000 +ONE_PARMID DB 0 ;AN000;;; WGR id given as positional ;AN000 +FTH_PARMID DB 0 ;AN000;;; WGR id given as switch ;AN000 +ID_FOUND DB 0 ;AN000;;; WGR id was good (in k.d. file) ;AN000 +BAD_ID DB 0 ;AN000;;; WGR id was bad (from parse) ;AN000 +ALPHA DB 0 ;AN000;;; WGR first parm a language id ;AN000 + ;; +ID_DISPLAYED DB 0 ;AN000;;; WGR Indicating ID already displayed ;AN000 + ;; WGR ;AN000 +SUBLIST_NUMBER LABEL BYTE ;AN000;;; WGR sublist for numbers ;AN000 + DB 11 ;AN000;;; WGR size ;AN000 + DB 0 ;AN000;;; WGR ;AN000 +PTR_TO_NUMBER DW ? ;AN000;;; WGR offset ptr ;AN000 +SEG_OF_NUMBER DW ? ;AN000;;; WGR segment ;AN000 + DB 1 ;AN000;;; WGR ;AN000 + DB 10100001B ;AN000;;; WGR flag ;AN000 + DB 3 ;AN000;;; WGR max width ;AN000 + DB 1 ;AN000;;; WGR min width ;AN000 + DB " " ;AN000;;; WGR filler ;AN000 + ;AN000;;; WGR + ;AN000;;; WGR +SUBLIST_ASCIIZ LABEL BYTE ;AN000;;; WGR sublist for asciiz ;AN000 + DB 11 ;AN000;;; WGR size ;AN000 + DB 0 ;AN000;;; WGR ;AN000 +PTR_TO_ASCIIZ DW ? ;AN000;;; WGR offset ptr ;AN000 +SEG_OF_ASCIIZ DW ? ;AN000;;; WGR segment ;AN000 + DB 1 ;AN000;;; WGR ;AN000 + DB 00010000B ;AN000;;; WGR flag ;AN000 + DB 2 ;AN000;;; WGR max width ;AN000 + DB 2 ;AN000;;; WGR min width ;AN000 + DB " " ;AN000;;; WGR filler ;AN000 + ;AN000;;; WGR ;AN000 +NUMBER_HOLDER DW ? ;AN000;;; WGR used for message retriever ;AN000 +;***CNS +SUBLIST_COMLIN LABEL BYTE ;an003;;; WGR sublist for asciiz ;AN000 + DB 11 ;an003;;; WGR size ;AN000 + DB 0 ;an003;;; WGR ;AN000 +PTR_TO_COMLIN DW ? ;an003;;; WGR offset ptr ;AN000 +SEG_OF_COMLIN DW ? + DB 0 ;an003;;; WGR ;AN000 + DB LEFT_ALIGN+CHAR_FIELD_ASCIIZ ;AN000;;; WGR flag ;AN000 + + DB 0 ;an003;;; WGR max width ;AN000 + DB 1 ;an003;;; WGR min width ;AN000 + DB " " ;an003;;; WGR filler ;AN000 + + +STRING_HOLDER DB 64 DUP(0) +;***CNS ;; + ;; +FILE_BUFFER_SIZE EQU 50*6 +FILE_BUFFER DB FILE_BUFFER_SIZE DUP(0) ;AC000;;; Buffer for Keyboard Def file +FB EQU FILE_BUFFER ;AC000;m for 32 language entries) +DESIG_CP_BUFFER DW 28 DUP(?) ;; (Room for 25 code pages) +DESIG_CP_BUF_LEN DW $-DESIG_CP_BUFFER ;; Length of code page buffer +NUM_DESIG_CP DW 0 ;; +CP_TAB_OFFSET DD ? ;; +;****************** CNS ******************;AN000; +TOTAL_SIZE DW 0 ;AN000; +PASS_LANG DW 0 ;AN000; +ID_TAB_OFFSET DD ? ;AN000; +;****************** CNS ******************;; +STATE_LOGIC_OFFSET DD -1 ;; +KEYBSYS_FILE_HANDLE DW ? ;;;;;;;;;;; +TB_RETURN_CODE DW 1 ;; +DESIG_CP_OFFSET DW OFFSET DESIG_CP_BUFFER ;; +SYS_CODE_PAGE DW 0 ;; +DESIG_LIST DW 0 ;; +QUERY_CALL DB 0 ;; + ;; +KB_MASK EQU 02h ;; + ;; +SIGNATURE DB 0FFh,'KEYB ' ;; +SIGNATURE_LENGTH DW 8 ;; +;****************** CNS ***************************;AN000; +NUM_ID DW 0 ;AN000; +ERR4ID DB 0 ;AN000; +NUM_LANG DW 0 ;AN000; +NUM_CP DW 0 ;AN000; +ID_PTR_SIZE DW SIZE KEYBSYS_ID_PTRS ;AN000; +;****************** CNS ***************************** +LANG_PTR_SIZE DW SIZE KEYBSYS_LANG_PTRS ;; +CP_PTR_SIZE DW SIZE KEYBSYS_CP_PTRS ;; +KEYBCMD_LANG_ENTRY_PTR DD ? ;; + ;; +KEYB_INSTALLED DW 0 ;; +CON_INSTALLED DW 0 ;; +SHARED_AREA_PTR DD 0 ;; +GOOD_MATCH DW 0 ;; +;****************** CNS ***************************;; +LANGUAGE_ASCII DB '??',0 ;; WGR ;AC000 + ;; +CMD_PARM_LIST PARM_LIST <> ;; + ;; +JR_LANGUAGE_CODES DW 'FR','GR','IT','SP','UK' ;; + ;; +JR_NUM_CODES EQU 5 ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;---------- TABLES FOR EXTENDED KEYBOARD SUPPORT CTRL CASE --------- RWV 11-06-85 ;; + ;; +RPL_K8 LABEL BYTE ;-------- CHARACTERS --------- ;; + DB 27,-1,00,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 ;; + DB 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - ;; + DB -1,127,148,17,23,5 ; =, Bksp, Tab, Q, W, E ;; + DB 18,20,25,21,09,15 ; R, T, Y, U, I, O ;; + DB 16,27,29,10,-1,01 ; P, [, ], Enter, Ctrl, A ;; + DB 19,04,06,07,08,10 ; S, D, F, G, H, J ;; + DB 11,12,-1,-1,-1,-1 ; K, L, ;, ', `, LShift ;; + DB 28,26,24,03,22,02 ; \, Z, X, C, V, B ;; + DB 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift ;; + DB 150,-1,' ',-1 ; *, Alt, Space, CL ;; + ;--------- FUNCTIONS --------- ;; + DB 94,95,96,97,98,99 ; F1 - F6 ;; + DB 100,101,102,103,-1,-1 ; F7 - F10, NL, SL ;; + DB 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 ;; + DB 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins ;; + DB 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 ;; +L_CTRL_TAB EQU $-RPL_K8 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYB_COMMAND PROC NEAR ;; + ;; + CALL SYSLOADMSG ;AN000;load messages ;AN000 + JNC VERSION_OK ;AN000;if no carry then version ok ;AN000 + CALL SYSDISPMSG ;AN000;error..display version error ;AN000 + MOV AL,BAD_DOS_VER ;AN000;bad DOS version ;AN000 + MOV EXIT_RET_CODE,AL ;AN000; ;AN000 + JMP KEYB_EXIT_NOT_RESIDENT ;AN000;exit..non resident ;AN000 +VERSION_OK: ;; WGR ;AN000 + MOV SEG_OF_NUMBER,CS ;AN000;initialize.. ;AN000 + MOV SEG_OF_ASCIIZ,CS ;AN000; ..sublists ;AN000 + MOV BP,OFFSET CMD_PARM_LIST ;AN000;pointer for parm list + MOV WORD PTR SHARED_AREA_PTR,ES ;AN000; ES segment + ;; +KEYB_INSTALL_CHECK: ;; + MOV AX,0AD80H ;; KEYB install check + INT 2FH ;; + CMP AL,-1 ;; If flag is not 0FFh THEN + JE INSTALLED_KEYB ;; + MOV WORD PTR SHARED_AREA_PTR+2,OFFSET TSD ;; + JMP CON_INSTALL_CHECK ;; + ;;;;;;;;;; +INSTALLED_KEYB: ;; + MOV KEYB_INSTALLED,1 ;; Set KEYB_INSTALLED flag = YES + MOV WORD PTR SHARED_AREA_PTR,ES ;; Save segment of SHARED_DATA_AREA + MOV WORD PTR SHARED_AREA_PTR+2,DI ;; Save offset of SHARED_DATA_AREA + MOV AX,ES:[DI].KEYB_TYPE ;; + MOV HW_TYPE,AX ;; + MOV ES:[DI].TABLE_OK,0 ;; Do not allow processing + PUSH CS ;; while building table + POP ES ;; Reset ES until required + ;; +CON_INSTALL_CHECK: ;;;;;;; + MOV AX,0AD00H ;; CONSOLE install check + INT 2FH ;; + CMP AL,-1 ;; If flag is not 0FFh THEN + JE INSTALLED_CON ;; + JMP CALL_FIRST_STAGE ;; + ;; +INSTALLED_CON: ;; + MOV CON_INSTALLED,1 ;; Set CON_INSTALLED flag = YES + ;; +CALL_FIRST_STAGE: ;; + PUSH CS ;; + POP ES ;; + CALL PARSE_PARAMETERS ;; Validate parameter list + ;; +BEGIN_PARM_CHECK: ;; CHECK ALL RETURN CODES + MOV DL,[BP].RET_CODE_3 ;; + CMP DL,1 ;; Check for invalid syntax + JNE VALID1 ;; + JMP ERROR3 ;; + ;; +VALID1: ;; + MOV DL,[BP].RET_CODE_1 ;; Check for invalid language parm + CMP DL,1 ;; + JNE VALID2 ;; + JMP ERROR1 ;; + ;; +VALID2: ;; + MOV DL,[BP].RET_CODE_2 ;; Check for invalid code page parm + CMP DL,1 ;; + JNE VALID3 ;; + JMP ERROR2 ;; + ;; +VALID3: ;; + MOV DL,[BP].RET_CODE_1 ;; Check for query command + CMP DL,2 ;; + JE QUERY ;; +;******************************* CNS **;; + MOV DL,[BP].RET_CODE_1 ;AN000;k for query command + CMP DL,3 ;AN000;;; Get a status of the codepage + JE QUERY ;AN000;;; language, and possible ID code +;******************************* CNS **;; + JMP NOT_QUERY ;; + ;; IF QUERY is requested THEN +QUERY: ;; + MOV QUERY_CALL,DL ;; + MOV AX,KEYB_INSTALLED ;; If KEYB is installed THEN + CMP AX,0 ;; + JE QUERY_CONTINUE1 ;;;;;;;;;;;;;;;; + ;; + MOV DI,WORD PTR SHARED_AREA_PTR+2 ;; Get offset of + MOV ES,WORD PTR SHARED_AREA_PTR ;; shared area + MOV BX,WORD PTR ES:[DI].ACTIVE_LANGUAGE ;; Get active language + CMP BX,0 ;; WGR if no language.. ;AN000 + JE I_MESSAGE ;; WGR then id was specified ;AN000 + ;; + ;;;;;;;;;;;; +L_MESSAGE: ;; + MOV WORD PTR LANGUAGE_ASCII,BX ;AC000;;; Display Language + LEA SI,LANGUAGE_ASCII ;AN000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_ASCIIZ,SI ;AN000;;; WGR language code asciiz string ;AN000 + MOV AX,ACT_KEYB ;AC000;;; WGR display 'Current keyboard code' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_ASCIIZ ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + JMP KEYB_L_FINISHED ;; + ;;;;;;; +I_MESSAGE: ;; + MOV BX,WORD PTR ES:[DI].INVOKED_KBD_ID;AN000;;; WGR get id code. ;AN000 + MOV NUMBER_HOLDER,BX ;AN000;;; WGR transfer number to temp loc. ;AN000 + LEA SI,NUMBER_HOLDER ;AN000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_NUMBER,SI ;AN000;;; WGR code page word ;AN000 + MOV AX,ACT_ID ;AN000;;; WGR display 'Current ID: ' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_NUMBER ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + MOV ID_DISPLAYED,1 ;AN000;;; WGR ID was displayed. ;AN000 + JMP KEYB_L_FINISHED ;AN000;;; WGR ;AN000 + ;;;;;;;;;;; +QUERY_CONTINUE1: ;; + MOV AX,INV_KEYB_Q ;AC000;;; WGR ;AN000 + MOV BX,STDOUT ;AN000;;; WGR Else ;AN000 + XOR CX,CX ;AC000;;; WGR Display message that KEYB ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR has not been installed ;AN000 + XOR DL,DL ;AN000;;; WGR ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + JMP KEYB_CP_FINISHED ;AC000;;; + ;;;;;;;;;;; +KEYB_L_FINISHED: ;; + MOV BX,ES:[DI].INVOKED_CP_TABLE ;; Get invoked code page + ;; + MOV NUMBER_HOLDER,BX ;AN000;;; WGR transfer number to temp loc. ;AN000 + LEA SI,NUMBER_HOLDER ;AN000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_NUMBER,SI ;AN000;;; WGR code page word ;AN000 + MOV AX,ACT_KEYB_CP ;AC000;;; WGR display ' code page: ' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_NUMBER ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + CMP ID_DISPLAYED,1 ;AN000;;; WGR was id displayed? ;AN000 + JE KEYB_CP_FINISHED ;AN000;;; WGR yes..continue. ;AN000 + ;; + MOV BX,WORD PTR ES:[DI].INVOKED_KBD_ID;AN000;;; WGR get id code. ;AN000 + CMP BX,0 ;AN000;;; WGR no id given.. ;AN000 + JE KEYB_CP_FINISHED ;AN000;;; WGR ;AN000 + ;; + MOV NUMBER_HOLDER,BX ;AN000;;; WGR transfer number to temp loc. ;AN000 + LEA SI,NUMBER_HOLDER ;AN000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_NUMBER,SI ;AN000;;; WGR code page word ;AN000 + MOV AX,ACT_ID ;AC000;;; WGR display 'Current ID: ' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_NUMBER ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + MOV AH,09H ;AC000;;; WGR need a CR_LF here. ;AN000 + MOV DX,OFFSET CR_LF ;AC000;;; WGR ;AN000 + INT 21H ;; WGR ;AN000 + ;;;;;;;;;;; +KEYB_CP_FINISHED: ;; + MOV AX,CON_INSTALLED ;; If CON has been installed THEN + CMP AX,0 ;; + JNE GET_ACTIVE_CP ;; + JMP CON_NOT_INSTALLED ;; + ;; +GET_ACTIVE_CP: ;; + MOV AX,0AD02H ;; Get active code page + INT 2FH ;; information from the console + JNC DISPLAY_ACTIVE_CP ;; + JMP ERROR5 ;; + ;; +DISPLAY_ACTIVE_CP: ;; + MOV NUMBER_HOLDER,BX ;AC000;;; WGR transfer number to temp loc. ;AN000 + LEA SI,NUMBER_HOLDER ;AC000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_NUMBER,SI ;AC000;;; WGR code page word ;AN000 + MOV AX,ACT_CON_CP ;AN000;;; WGR display 'Current CON code page: ' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_NUMBER ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + ;; + JMP KEYB_EXIT_NOT_RESIDENT ;; Exit from Proc + ;; +CON_NOT_INSTALLED: ;; ELSE + MOV AX,INV_CON_Q ;AC000;WGR ;AN000 + MOV BX,STDOUT ;AN000;;; WGR Else ;AN000 + XOR CX,CX ;AN000;;; WGR Display message that CON does ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR not have active code page ;AN000 + XOR DL,DL ;AN000;;; WGR ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + JMP KEYB_EXIT_NOT_RESIDENT ;; Exit from Proc + ;; +NOT_QUERY: ;; IF not a query function requested + CALL BUILD_PATH ;; Determine location of KEYBOARD.SYS + ;; WGR ...and open file. ;AC000 + ;; + JNC VALID4 ;; If no error in opening file then + JMP ERROR4 ;; + ;; +VALID4: ;; + MOV KEYBSYS_FILE_HANDLE,AX ;; Save handle + MOV BP,OFFSET CMD_PARM_LIST ;; Set base pointer for structures + MOV BX,KEYBSYS_FILE_HANDLE ;; Retrieve the file handle + MOV DX,OFFSET FILE_BUFFER ;; Set address of buffer +;************************* CNS ********;; + cmp [BP].RET_CODE_4,ID_VALID ;AN000; ;; CNS is there an ID available + je ID_TYPED ;AN000; ;; if so go find out if it is + jmp GET_LANG ;AN000; ;; a 1st or 4th parm, if not must + ;AN000; ;; must be a language +ID_TYPED: ;AN000; + + call SCAN_ID ;AN000; ;; scan the table for the ID + cmp ID_FOUND,1 ;AN000; ;; if a legal ID check and see if + jne LOST_ID ;AN000; ;; it is a first or fourth parm + cmp FTH_PARMID,1 ;AN000; ;; if it is a fourth parm go + je GET_ID ;AN000; ;; check for language compatibility + jmp Language_found ;AN000; ;; otherwise it must be a first + ;; parm id value + +LOST_ID: ;AN000; ;; otherwise must be a bogus match + ;; between language and ID codes + ;; or the ID code does not exist + jmp ERR1ID ;AN000; ;; in the table +;************************* CNS ***********;; +GET_LANG: ;; Must be a language/or a 1st parm ID + ;;;;; + ;; + XOR DI,DI ;; Set number + LEA CX,[DI].KH_NUM_LANG+2 ;; bytes to read header + ;; + MOV AH,3FH ;; Read header of the Keyb Def file + INT 21H ;; + JNC VALID5 ;; If no error in opening file then + JMP ERROR4 ;; + ;;;; +VALID5: ;; + CLD ;; WGR all moves/scans forward ;AN000 + MOV CX,SIGNATURE_LENGTH ;; + MOV DI,OFFSET SIGNATURE ;; Verify matching + MOV SI,OFFSET FB.KH_SIGNATURE ;; signatures + REPE CMPSB ;; + JE LANGUAGE_SPECIFIED ;; + JMP ERROR4 ;;;; + ;; READ the language table +LANGUAGE_SPECIFIED: ;; + MOV AX,FB.KH_NUM_LANG ;; + MOV NUM_LANG,AX ;; Save the number of languages + MUL LANG_PTR_SIZE ;; Determine # of bytes to read + MOV DX,OFFSET FILE_BUFFER ;; Establish beginning of buffer + MOV CX,AX ;; + CMP CX,FILE_BUFFER_SIZE ;; Make sure buffer is not to small + JBE READ_LANG_TAB ;; + JMP ERROR4 ;; + ;; +READ_LANG_TAB: ;; + MOV AH,3FH ;; Read language table from + INT 21H ;; Keyb Def file + JNC READ_VALID ;; If no error in opening file then + JMP ERROR4 ;; Else display ERROR message + ;; +READ_VALID: ;; + MOV CX,NUM_LANG ;; Number of valid codes + MOV DI,OFFSET FILE_BUFFER ;; Point to correct word in table + ;; +SCAN_LANG_TABLE: ;; FOR language parm + MOV AX,[BP].LANGUAGe_PARM ;; Get parameter + CMP [DI].KP_LANG_CODE,AX ;; Valid Code ?? + JE LANGUAGE_FOUND ;; If not found AND more entries THEN + ADD DI,LANG_PTR_SIZE ;; Check next entry + DEC CX ;; Decrement count of entries + JNE SCAN_LANG_TABLE ;; Else + JMP ERROR1 ;; Display error message + ;;;;;;;;;;;;;; +;**************************** CNS ****;;;; +GET_ID: ;AN000;;; CNS - Must be an ID value + mov cx,1 ;AN000;;; initialize ctr value for # of ids + ;; +SEARCH_ID: ;AN000;;; minimum per country +;.WHILE ;AN000;;; There is atleast 1 ID for each country + cmp cx,0 ;AN000;;; Check for any more IDs left to check + jne FINDID ;AN000;;; Country has more than one ID check + jmp END_IDCHK ;AN000;;; Country & ID has been found or value + ;; is zero +FINDID: ;AN000; + + push di ;AN000;;; save the current language entry ptr + push cx ;AN000;;; save the minimum # of ids before + ;; reading the table data from the disk +;**************************** CNS *****************;; +LANGUAGE_FOUND: ;; + MOV CX,WORD PTR [DI].KP_ENTRY_PTR+2 ;; Get offset of lang entry + MOV DX,WORD PTR [DI].KP_ENTRY_PTR ;; in the Keyb Def file + MOV WORD PTR KEYBCMD_LANG_ENTRY_PTR,DX ;; Save + MOV WORD PTR KEYBCMD_LANG_ENTRY_PTR+2,CX ;; offset + MOV AH,42H ;; Move file pointer to + MOV AL,0 ;;;;;;; location of language + INT 21H ;; entry + JNC LSEEK_VALID ;; + JMP ERROR4 ;; + ;; +LSEEK_VALID: ;; + MOV DI,AX ;; + MOV CX,SIZE KEYBSYS_LANG_ENTRY-1 ;; Set number + ;; bytes to read header + MOV DX,OFFSET FILE_BUFFER ;;;;;;;;; + MOV AH,3FH ;; Read language entry in + INT 21H ;; Keyb Def file + JNC VALID6a ;; If no error in file then + JMP ERROR4 ;;;;;;;;;; +;**************************** CNS ********************************************** + + +valid6a: + cmp FOURTH_PARM,1 ;AN000;;; Is the ID a 4th Parm + jne VALID6 ;AN000;;; if not get out of routine, otherwise + pop cx ;AN000;;;restore # of ids for the country + ; .IF ;AN000;;;Check to see if this is the first + ;AN000;;;time checking the primary ID + cmp cx,1 ;AN000;;;if there is just one ID check to make + jne CHK4PARM ;AN000;;;sure both flags are not set + ;AN000;;; this should not be necessary w/ new parser + cmp FTH_PARMID,1 ;AN000;;; is the ID flag for switch set + jne CHK1N4 ;AN000;;; is the flag set only for the 4th + cmp FOURTH_PARM,1 ;AN000;;; if set only for the switch proceed + jne CHK1N4 ;AN000;;; if not must be a positional + mov cl,fb.kl_num_id ;AN000;;; get the number of IDs available from the table + mov FTH_PARMID,0 ;AN000;;; turn switch flag off so the table + ;AN000;;; counter will not be reset + + ;;ids available for the +CHK1N4: ;AN000; ;;country + cmp ONE_PARMID,1 ;AN000; ;; this was to be done if + jne CHK4PARM ;AN000; ;; two the positional + cmp FOURTH_PARM,0 ;AN000; ;; and switch was specified + jne CHK4PARM ;AN000; ;; this should never happen + pop di ;AN000; ;; if the parser is intact + jmp error3 ;AN000; ;; report error & exit + +CHK4PARM: ;AN000; ;; check on the first ID + ; .IF ;AN000; ;;switch specified + ; call IDLANG_CHK ;AN000; ;;check the lang-id combo + ; .ELSE ;AN000; + ; xor cx,cx ;AN000; ;;clear to exit loop + ; .ENDIF ;AN000; + ; + cmp FOURTH_PARM,1 ;AN000; ;; ID was a switch + jne ABORT_LOOP ;AN000; ;; otherwise get out of routine + call IDLANG_CHK ;AN000; ;; check the ID + jmp ADVANCE_PTR ;AN000; ;; advance to the next position + +ABORT_LOOP: ;AN000; + xor cx,cx ;AN000; ;; end loop + +ADVANCE_PTR: ;AN000; + pop di ;AN000; ;;restore entry value + + dec cx ;AN000; ;;# of ids left to check + cmp cx,0 ;AN000; ;; if at 0 don't advance to next + je NO_ADVANCE ;AN000; ;; table position + cmp GOOD_MATCH,1 ;AN000; ;; check to see if ID matched language + je NO_ADVANCE ;AN000; ;; if equal do not advance + add di,LANG_PTR_SIZE ;AN000; ;;step to the next entry + ;;in the table + +NO_ADVANCE: ;AN000; + + jmp SEARCH_ID ;AN000; ;;for the country + +;.ENDWHILE ;;end of ID check for country + +END_IDCHK: ;AN000; + + cmp FOURTH_PARM,1 ;AN000; ;; see if id was found + jne VALID6 ;AN000; + cmp GOOD_MATCH,0 ;AN000; ;; none found + jne VALID6 ;AN000; ;; report error + mov [bp].ret_code_4,1 ;AN000; ;; incompatible lang code + mov al,[bp].ret_code_4 ;AN000; ;; id combo + jmp err2id ;AN000; + + ;; otherwise found it + ;; continue to build tbl +;**************************** CNS ********************************************** + ;; +VALID6: ;; + MOV AX,WORD PTR FB.KL_LOGIC_PTR ;; Save the offset of the state + MOV WORD PTR STATE_LOGIC_OFFSET,AX ;; logic section + MOV AX,WORD PTR FB.KL_LOGIC_PTR+2 ;; Save the offset of the state + MOV WORD PTR STATE_LOGIC_OFFSET+2,AX ;; logic section + ;; + MOV DL,[BP].RET_CODE_2 ;;;;;;;;;; IF code page was specified + CMP DL,2 ;; + JNE CODE_PAGE_SPECIFIED ;; + JMP DONE ;; + ;; +CODE_PAGE_SPECIFIED: ;; Then +;************************** CNS *********************************************** + xor ah,ah ;AN000; + MOV Al,FB.KL_NUM_CP ;AN000;;; +;************************** CNS *********************************************** + MOV NUM_CP,AX ;; Save the number of code pages + MUL CP_PTR_SIZE ;; Determine # of bytes to read + MOV DX,OFFSET FILE_BUFFER ;; Establish beginning of buffer + MOV CX,AX ;; + CMP CX,FILE_BUFFER_SIZE ;; Make sure buffer is not to small + JBE VALID7 ;; + JMP ERROR4 ;; + ;; +VALID7: ;; + MOV AH,3FH ;; Read code page table from + INT 21H ;; Keyb Def file + JNC VALID8 ;; If no error in opening file then + JMP ERROR4 ;; + ;; +VALID8: ;; + MOV CX,NUM_CP ;; Number of valid codes + MOV DI,OFFSET FILE_BUFFER ;; Point to correct word in table + ;; +SCAN_CP_TABLE: ;; FOR code page parm + MOV AX,[BP].CODE_PAGE_PARM ;; Get parameter + CMP [DI].KC_CODE_PAGE,AX ;; Valid Code ?? + JE CODE_PAGE_FOUND ;; If not found AND more entries THEN + ADD DI,CP_PTR_SIZE ;; Check next entry + DEC CX ;; Decrement count of entries + JNE SCAN_CP_TABLE ;; Else + JMP ERROR2 ;; Display error message + ;;;;;;;;; +CODE_PAGE_FOUND: ;; + MOV AX,WORD PTR [DI].KC_ENTRY_PTR ;; + MOV WORD PTR CP_TAB_OFFSET,AX ;; + MOV AX,WORD PTR [DI].KC_ENTRY_PTR+2 ;; + MOV WORD PTR CP_TAB_OFFSET+2,AX ;; + ;;;;;; +DONE: ;; + MOV SI,OFFSET DESIG_CP_BUFFER ;; + ;; + MOV AX,CON_INSTALLED ;;;;; If CON is NOT installed THEN + CMP AX,0 ;; + JE SYSTEM_CP ;; + JMP GET_DESIG_CPS ;; + ;; +SYSTEM_CP: ;; + MOV CX,1 ;; + MOV NUM_DESIG_CP,CX ;; Set number of CPs = 1 + MOV [SI].NUM_DESIGNATES,CX ;; + ;; + MOV DL,[BP].RET_CODE_2 ;; Check if code page parm + CMP DL,0 ;; was specified + JNE SET_TO_SYSTEM_CP ;; + MOV DX,[BP].CODE_PAGE_PARM ;; + MOV [SI].DESIG_CP_ENTRY,DX ;; Load specified code page into + JMP READY_TO_BUILD_TABLE ;; designated code page list + ;; +SET_TO_SYSTEM_CP: ;; + CALL FIND_FIRST_CP ;; Call routine that sets the first + CMP AX,0 ;; table found in the Keyb Def file + JE SET_TO_SYSTEM_CP2 ;; to the system code page + JMP ERROR4 ;; + ;; +SET_TO_SYSTEM_CP2: ;; + MOV SYS_CODE_PAGE,BX ;; + MOV [BP].CODE_PAGE_PARM,BX ;; + MOV [SI].DESIG_CP_ENTRY,BX ;; Move sys CP into desig list + JMP READY_TO_BUILD_TABLE ;; + ;; +GET_DESIG_CPS: ;; ELSE + MOV AX,0AD03H ;; + PUSH CS ;; Make sure ES is set + POP ES ;; + LEA DI,DESIG_CP_BUFFER ;; + MOV CX,DESIG_CP_BUF_LEN ;; + INT 2FH ;; Get all designated code pages + JNC SET_DESIG_VARIABLES ;; from console + JMP ERROR5 ;; + ;; +SET_DESIG_VARIABLES: ;; + MOV CX,[SI].NUM_DESIGNATES ;; + ADD CX,[SI].NUM_HW_CPS ;; + MOV NUM_DESIG_CP,CX ;; Set number of Designated CPs + ;; +BUFFER_CREATED: ;; + MOV AX,0AD02H ;; + INT 2FH ;; Get invoked code page + ;; +SET_TO_CP_INVOKED: ;; + MOV DL,[BP].RET_CODE_2 ;; IF code page parm was specified + CMP DL,0 ;; + JNE SET_TO_INVOKED_CP ;; + MOV CX,NUM_DESIG_CP ;; + MOV DESIG_LIST,SI ;; + JMP TEST_IF_DESIGNATED ;; + ;; +SET_TO_INVOKED_CP: ;; + CMP AX,1 ;; IF a code page has been invoked + JNE SET_TO_INVOKED_CP3 ;; + CALL FIND_FIRST_CP ;; Call the routine that sets the + CMP AX,0 ;; first code page in the Keyb Def + JE SET_TO_INVOKED_CP2 ;; file to the system code page + JMP ERROR4 ;; + ;; +SET_TO_INVOKED_CP2: ;; + MOV [BP].CODE_PAGE_PARM,BX ;; + MOV SYS_CODE_PAGE,BX ;; + ;; + JMP TEST_IF_DESIGNATED ;; + ;; +SET_TO_INVOKED_CP3: ;; + MOV [BP].CODE_PAGE_PARM,BX ;; + ;; +TEST_IF_DESIGNATED: ;; + MOV DX,[BP].CODE_PAGE_PARM ;; + CMP [SI].DESIG_CP_ENTRY,DX ;; Is Code page specified in the list + JE CODE_PAGE_DESIGNATED ;; of designated code pages ? + ;; +NEXT_DESIG_CP: ;; + ADD SI,2 ;; Check next code page + DEC CX ;; If all designated code pages have + JNZ TEST_IF_DESIGNATED ;; been checked Then ERROR + JMP ERROR6 ;; + ;; +CODE_PAGE_DESIGNATED: ;; + CMP SYS_CODE_PAGE,0 ;; + JNE READY_TO_BUILD_TABLE ;; + CMP AX,1 ;; IF a code page has been invoked + JE READY_TO_BUILD_TABLE ;; + CMP [BP].CODE_PAGE_PARM,BX ;; IF Invoked CP <> Specified CP + JE READY_TO_BUILD_TABLE ;; Issue warning +;;*************************************************************************** + PUSH BX ;AN000;;; WGR ;AN000 + PUSH CX ;AN000;;; WGR ;AN000 + MOV AX,WARNING_1 ;AN000;;; WGR ;AN000 + MOV BX,STDOUT ;AN000;;; WGR ;AN000 + XOR CX,CX ;AN000;;; WGR ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR ;AN000 + XOR DL,DL ;AN000;;; WGR ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + POP CX ;AN000;;; WGR ;AN000 + POP BX ;AN000;;; WGR ;AN000 +;;*************************************************************************** + ;; +READY_TO_BUILD_TABLE: ;; + ;; + MOV AX,KEYB_INSTALLED ;; + CMP AX,0 ;; Else if KEYB has not been installed + JNE BUILD_THE_TABLE ;; + ;; + CALL FIND_SYS_TYPE ;; Determine system type for INT 9 use + ;; + TEST SD.SYSTEM_FLAG,PC_JR ;; IS THIS ROM MULTILINGUAL? (JR.) AAD + JZ CONTINUE_INSTALL ; NO, LOAD THE NEW INT9 CODE + ; SEE IF MULTILINGUAL OPTION IS PRESENT + MOV AH,5 ; ADDRESS THE MULTILINGUAL SUPPORT + MOV AL,80H ; REQUEST CURRENT LANGUAGE BE IDENTIFIED + INT 16H ; CALL KEYBOARD TO IDENTIFY ITSELF + +;IF THE MULTILINGUAL OPTION IS NOT PRESENT, THE ROM DOES NOT RECOGNIZE THE +;OPTION 5 AND JUST RETURNS THE REGS INTACT. +;RESPONSE IN AL INDICATES THE CURRENT LANGUAGE: + + CMP AL,80H ; DID I GET BACK JUST WHAT I SENT? + JE CONTINUE_INSTALL ; SINCE RESPONSE WAS THE SAME MUST NOT BE + ; MULTILINGUAL, RELOCATE RESIDENT KBD ROUTINE + +;I AM GOING TO IGNORE WHAT LANGUAGE IS CURRENTLY SET. I WILL SET THE +;MULTILINGUAL KEYBOARD TO BECOME MY LANGUAGE. + + MOV AX,[BP].LANGUAGE_PARM ;; + XCHG AH,AL ;; + MOV DI,OFFSET JR_LANGUAGE_CODES ;; + MOV CX,JR_NUM_CODES ;; + PUSH CS ;; + POP ES ;; + REPNE SCASW ;; + JNE CONTINUE_INSTALL ;; + ;; + MOV AH,5 ; ADDRESS THE MULTILINGUAL KEYBOARD + MOV AL,JR_NUM_CODES ; SELECT MY LANGUAGE + SUB AL,CL ;; + INT 16H ; SET THE KEYBOARD ACCORDINGLY + INT 20H ; JOB DONE, ROM IS MULTILINGUAL + ; NO NEED TO STAY RESIDENT + ;; +;------ LOAD IN SPECIAL INT 9 HANDLER AND SPECIAL TABLES (IF NEEDED) + +CONTINUE_INSTALL: ;; + CALL INSTALL_INT_9 ;; Install INT 9 + ;; + CALL FIND_KEYB_TYPE ;; Determine keyboard type table use + ;; +BUILD_THE_TABLE: ;; + CALL TABLE_BUILD ;; Build the TEMP_SHARED_DATA_AREA + ;; +CHECK_ERRORS: ;; + XOR CX,CX ;; Take appropriate action considering + MOV CX,TB_RETURN_CODE ;; return codes from TABLE_BUILD + CMP CX,0 ;; + JE CHECK_FOR_INV_CP ;; If return code is not 0 + ;; + MOV AX,KEYB_INSTALLED ;; + CMP AX,0 ;; If KEYB has not been installed + JNE CHECK_ERROR_CONTINUE ;; + CALL REMOVE_INT_9 ;; remove installed vector + ;; +CHECK_ERROR_CONTINUE: ;; + CMP CX,1 ;; If return code = 1 + JNE CHECK_ERROR2 ;; + JMP ERROR1 ;; display error message + ;; +CHECK_ERROR2: ;; + CMP CX,2 ;; If return code = 2 + JNE CHECK_ERROR3 ;; + JMP ERROR2 ;; + ;; +CHECK_ERROR3: ;; + CMP CX,3 ;; If return code = 3 + JNE CHECK_ERROR4 ;; + JMP ERROR3 ;; display error message + ;; +CHECK_ERROR4: ;; + CMP CX,4 ;; If return code = 4 + JNE CHECK_ERROR5A ;; + JMP ERROR4 ;; display error message + ;; +CHECK_ERROR5A: ;; + CMP CX,5 ;; If return code = 5 + JNE CHECK_ERROR6A ;; + JMP ERROR5A ;; display error message + ;; +CHECK_ERROR6A: ;; + JMP ERROR6A ;; If return code not 0,1,2,3,4 then + ;; display error message +CHECK_FOR_INV_CP: ;; + MOV CX,CPN_INVALID ;; Check if any CPs were not loaded + CMP CX,0 ;; + JE TERMINATE ;; If some were invalid, issue + ;; warning message +;;*************************************************************************** + PUSH BX ;AN000;;; WGR ;AN000 + PUSH CX ;AN000;;; WGR ;AN000 + MOV AX,NOT_SUPP ;AN000;;; WGR ;AN000 + MOV BX,STDOUT ;AN000;;; WGR WARNING ;AN000 + XOR CX,CX ;AN000;;; WGR MESSAGE ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR ;AN000 + XOR DL,DL ;AN000;;; WGR ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + POP CX ;AN000;;; WGR ;AN000 + POP BX ;AN000;;; WGR ;AN000 +;;*************************************************************************** + ;; +TERMINATE: ;; + MOV AH,3EH ;; Close the KEYBOARD.SYS file + MOV BX,KEYBSYS_FILE_HANDLE ;; if open + CMP BX,0 ;; + JE KEYB_EXIT ;; + INT 21H ;; + ;; + MOV AX,KEYB_INSTALLED ;; + CMP AX,0 ;; + JE KEYB_EXIT ;; + JMP KEYB_EXIT_NOT_RESIDENT ;; + ;; +KEYB_EXIT: ;; + TEST SD.KEYB_TYPE,G_KB ;; Q..FERRARI G?? + JZ NO_FERRARI_G ;; N..LEAVE NUMLK ALONE + TEST SD.SYSTEM_FLAG,PC_XT ;; Q..PC/XT? + JNZ NO_FERRARI_G ;; Y..LEAVE NUMLK ALONE + TEST SD.KEYB_TYPE,P_KB ;; Q..FERRARI P?? ***RPS + JNZ NO_FERRARI_G ;; Y..LEAVE NUMLK ALONE ***RPS +;***CNS + CMP SECURE_FL,1 ;AN002;; IF SECURITY FLAG SET + JNE NO_FERRARI_G ;AN002;; DON'T TURN ON NUM_LK + +;***CNS + CALL NUMLK_ON ;; N..TURN NUMLK ON + ;; +NO_FERRARI_G: ;; + TEST SD.SYSTEM_FLAG,EXT_16 ;; extended INT 16 support? + JZ SKIP_CTRL_COPY ;; + ;; Yes, load extened CTRL case table + MOV CX,L_CTRL_TAB ;; CX = LENGTH OF EXTENDED TABLE + MOV SI,OFFSET CS:RPL_K8 ;; POINT TO EXT. CTRL TABLES + MOV DI,OFFSET CS:K8 ;; POINT TO REGULAR CTRL TABLE + CLD ;; + REP MOVSB ;; OVERLAY WITH EXT. CTRL TABLE + ;; +SKIP_CTRL_COPY: ;; + CALL INSTALL_INT_9_NET ;; Let the network know about INT 9 + ;; (if the network is installed) + CALL INSTALL_INT_2F_48 ;; Install INT 2F and INT 48 (If PCjr) + ;; + MOV AX,0AD82H ;; Activate language + MOV BL,-1 ;; + INT 2FH ;; + ;; + MOV DX,ES:TSD.RESIDENT_END ;; Get resident end + MOV CL,4 ;; Convert into paragrahs + SHR DX,CL ;; + INC DX ;; + MOV AH,31H ;; Function call to terminate but stay + XOR AL,AL ;; resident + ;; + MOV DI,OFFSET SD_DEST_PTR ;; Initialize destination ptr + MOV SI,OFFSET SD_SOURCE_PTR ;; Initialize source ptr + XOR BP,BP ;; + LEA BX,[BP].ACTIVE_LANGUAGE ;; + ADD DI,BX ;; Adjust for portion not copied + ADD SI,BX ;; Adjust for portion not copied + ;; + MOV CX,SD_LENGTH ;; Set length of SHARED_DATA_AREA + SUB CX,BX ;; Adjust for portion not copied + ;; + JMP COPY_SD_AREA ;; Jump to proc that copies area in new + ;; part of memory +;***************************** CNS ********************************************* +ERR1ID: ;AN000; +;;*************************************************************************** + MOV AX,INV_I ;AN000;;; WGR invalid ID message ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,INVALID_PARMS ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERR2ID: +;;*************************************************************************** + MOV AX,INV_COMBO ;AN000;;; WGR invalid combination message ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,INVALID_PARMS ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +;***************************** CNS ********************************************* +ERROR1: +;;*************************************************************************** + MOV AX,INV_L ;AN000;;; WGR invalid language code ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,INVALID_PARMS ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR2: +;;*************************************************************************** + MOV AX,INV_CP ;AN000;;; WGR invalid code page message ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,INVALID_PARMS ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR3: +;;*************************************************************************** + MOV AX,INV_S ;AN000;;; WGR invalid syntax message ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 +;***CNS + + LEA DI,STRING_HOLDER ;AN003;Set PTR to look at the STRING + PUSH SI ;AN003;Save current SI index + PUSH AX + MOV AX,OLD_PTR ;AN003;Last locale of the end of a PARAM + SUB CUR_PTR,AX ;AN003;Get the length via the PSP + MOV SI,CUR_PTR + MOV CX,SI ;AN003;Save it in CX to move in the chars + POP AX ;AN003;Restore the PTR to the command line position + + MOV SI,OLD_PTR ;AN003;Last locale of the end of a PARAM + REP MOVSB ;AN003;Move in the chars until no more + + LEA DI,STRING_HOLDER ;AN003;Set PTR to look at the STRING + + + POP SI ;AN003;Restore the PTR to the command line position + + MOV CX,1 ;AN003;One replacement + MOV PTR_TO_COMLIN,DI ;AN003;;; WGR language code asciiz string ;AN000 + + + PUSH AX ;AN003; + MOV AX,DS ;AN003;;; WGR language code asciiz string ;AN000 + MOV SEG_OF_COMLIN,AX ;AN003; + POP AX ;AN003; + ;XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + + MOV AX,ERR_PART ;AN003; + LEA SI,SUBLIST_COMLIN ;AN003; +; MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR parse error message ;AN000 + MOV DH,PARSE_ERR_CLASS ;AN000;;; WGR parse error message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,INVALID_PARMS ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR4: +;;*************************************************************************** + MOV AX,INV_FN ;AN000;;; WGR bad or missing file message ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,BAD_KEYB_DEF_FILE ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR5: +;;*************************************************************************** + MOV AX,INV_CON_Q ;AC000;;; WGR CON code page not available. ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,CONSOLE_ERROR ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR5A: +;;*************************************************************************** + MOV AX,MEMORY_OVERF ;AC000;;; WGR not enough resident memory. ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,MEMORY_OVERFLOW ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR6: +;;*************************************************************************** + MOV AX,NOT_DESIG ;AC000;;; WGR code page not prepared. ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + XOR CX,CX ;AN000;;; WGR no substitutions ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR display message ;AN000 + MOV AL,CP_NOT_DESIGNATED ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + JMP KEYB_EXIT_NOT_RESIDENT ;; +ERROR6A: +;;*************************************************************************** + MOV NUMBER_HOLDER,BX ;AN000;;; WGR transfer number to temp loc. ;AN000 + LEA SI,NUMBER_HOLDER ;AN000;;; WGR sublist points to... ;AN000 + MOV PTR_TO_NUMBER,SI ;AN000;;; WGR code page word ;AN000 + MOV AX,NOT_VALID ;AN000;;; WGR display 'Code page requested....' ;AN000 + MOV BX,STDOUT ;AN000;;; WGR to standard out ;AN000 + MOV CX,1 ;AN000;;; WGR one replacement ;AN000 + MOV DH,UTILITY_MSG_CLASS ;AN000;;; WGR utility message ;AN000 + XOR DL,DL ;AN000;;; WGR no input ;AN000 + LEA SI,SUBLIST_NUMBER ;AN000;;; WGR ptr to sublist ;AN000 + CALL SYSDISPMSG ;AN000;;; WGR ;AN000 + MOV AL,KEYB_TABLE_NOT_LOAD ;AN000;;; | + MOV EXIT_RET_CODE,AL ;AN000;;; | +;;*************************************************************************** + ;; +KEYB_EXIT_NOT_RESIDENT: ;; + MOV AH,04CH ;; + MOV AL,QUERY_CALL ;; Check if this was a query call + CMP AL,0 ;; + JNE KEYB_EXIT3 ;; IF yes then EXIT + MOV AL,EXIT_RET_CODE ;; Check if return code was valid + CMP AL,0 ;; + JNE KEYB_EXIT3 ;; IF not then EXIT + ;; +COPY_INTO_SDA: ;; + MOV AX,0AD82H ;; Activate language + MOV BL,-1 ;; + INT 2FH ;; + ;; + MOV AH,04CH ;;;;;;;;;;; + MOV AL,EXIT_RET_CODE ;; + MOV DI,WORD PTR SHARED_AREA_PTR+2 ;; Initialize destination ptr + MOV ES,WORD PTR SHARED_AREA_PTR ;; + MOV DX,[BP].RESIDENT_END ;;;;;;;;;;; + MOV CL,4 ;; Calculate resident end in paragraphs + SHR DX,CL ;; + INC DX ;; + ;; + MOV SI,OFFSET SD_SOURCE_PTR ;; Initialize source ptr + XOR BP,BP ;; + LEA BX,[BP].ACTIVE_LANGUAGE ;; + ADD DI,BX ;; + ADD SI,BX ;; + MOV CX,SD_LENGTH ;; Set length of SHARED_DATA_AREA + SUB CX,BX ;; + ;; + JMP COPY_SD_AREA ;; Jump to proc that copies area in new + ;; +KEYB_EXIT3: ;;;;;;;;;;; + MOV AL,EXIT_RET_CODE ;; + MOV DI,WORD PTR SHARED_AREA_PTR+2 ;; Initialize destination ptr + MOV ES,WORD PTR SHARED_AREA_PTR ;; + MOV ES:[DI].TABLE_OK,1 ;; + INT 21H ;;;;;;;;;;; + ;; +KEYB_COMMAND ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: NUMLK_ON +;; +;; Description: +;; Turn Num Lock On. +;; +;; Input Registers: +;; N/A +;; +;; Output Registers: +;; N/A +;; +;; Logic: +;; Set Num Lock bit in BIOS KB_FLAG +;; Issue Int 16 to update lights +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +NUMLK_ON PROC ;; + ;; + PUSH ES ;; + PUSH AX ;; + ;; + MOV AX,DATA ;; + MOV ES,AX ;; + ;; + OR ES:KB_FLAG,NUM_STATE ;; Num Lock state active + MOV AH,1 ;; Issue keyboard query call to + INT 16H ;; have BIOS update the lights + ;; + POP AX ;; + POP ES ;; + RET ;; + ;; +NUMLK_ON ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: INSTALL_INT_9 +;; +;; Description: +;; Install our INT 9 driver. +;; +;; Input Registers: +;; DS - points to our data segment +;; BP - points to ES to find SHARED_DATA_AREA +;; +;; Output Registers: +;; DS - points to our data segment +;; AX, BX, DX, ES Trashed +;; +;; Logic: +;; Get existing vector +;; Install our vector +;; Return +;; +;; Notes: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +REPLACE_INT_SEGMENT1 DW ? ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +INSTALL_INT_9 PROC ;; + ;; + PUSH ES ;; + ;; + MOV AH,35H ;; Get int 9 vector + MOV AL,9 ;; + INT 21H ;; Vector in ES:BX + MOV REPLACE_INT_SEGMENT1,ES ;; + PUSH CS ;; + POP ES ;; + MOV WORD PTR ES:SD.OLD_INT_9,BX ;; Offset + MOV AX,REPLACE_INT_SEGMENT1 ;; + MOV WORD PTR ES:SD.OLD_INT_9+2,AX ;; Segment + MOV AH,25H ;; + MOV AL,9 ;; + MOV DX,OFFSET KEYB_INT_9 ;; Let DOS know about our handler + INT 21H ;; + ;; + POP ES ;; + RET ;; + ;; +INSTALL_INT_9 ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: INSTALL_INT_9_NET +;; +;; Description: +;; +;; +;; Input Registers: +;; DS - points to our data segment +;; BP - points to ES to find SHARED_DATA_AREA +;; +;; Output Registers: +;; DS - points to our data segment +;; AX, BX, DX, ES Trashed +;; +;; Logic: +;; IF network is installed THEN +;; Let it know about our INT 9 +;; Return +;; +;; Notes: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +INSTALL_INT_9_NET PROC ;; + ;; + PUSH ES ;; + ;; + TEST SD.SYSTEM_FLAG,PC_NET ;; TEST FOR PC_NETWORK + JNZ NET_HAND_SHAKE ;; JUMP IF NETWORK INSTALLED + JMP INSTALL_9_DONE_NET ;; SKIP THE PC NETWORK HANDSHAKE + ;; +NET_HAND_SHAKE: ;; + ;; ES:BX TO CONTAIN INT 9 ADDR + MOV BX,OFFSET KEYB_INT_9 ;; + MOV AX,0B808H ;; FUNCTION FOR PC NETWORK TO INSTALL + ;; THIS ADDRESS FOR THEIR JUMP TABLE + INT 02FH ;; TELL PC_NET TO USE MY ADDR TO CHAIN TO + ;; +INSTALL_9_DONE_NET: ;; + POP ES ;; + RET ;; + ;; +INSTALL_INT_9_NET ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: INSTALL_INT_2F_48 +;; +;; Description: +;; Install our INT 2F, INT 48 drivers. +;; +;; Input Registers: +;; DS - points to our data segment +;; BP - points to ES to find SHARED_DATA_AREA +;; +;; Output Registers: +;; DS - points to our data segment +;; AX, BX, DX, ES Trashed +;; +;; Logic: +;; Get existing vectors +;; Install our vectors +;; Return +;; +;; Notes: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +REPLACE_INT_SEGMENT2 DW ? ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +INSTALL_INT_2F_48 PROC ;; + ;; + MOV AH,35H ;; Get int 2f vector + MOV AL,2FH ;; + INT 21H ;; Vector in ES:BX + MOV REPLACE_INT_SEGMENT2,ES ;; + PUSH CS ;; + POP ES ;; + MOV WORD PTR ES:SD.OLD_INT_2F,BX ;; Offset + MOV AX,REPLACE_INT_SEGMENT2 ;; + MOV WORD PTR ES:SD.OLD_INT_2F+2,AX ;; Segment + MOV AH,25H ;; Set int 9 vector + MOV AL,2FH ;; + MOV DX,OFFSET KEYB_INT_2F ;; Vector in DS:DX + INT 21H ;; + ;; +ARE_WE_A_PCJR: ;; + ;; + MOV AX,SD.SYSTEM_FLAG ;; Test if we are a PCjr + CMP AX,PC_JR ;; + JNE INSTALL_DONE ;; IF yes then + MOV AH,35H ;; Get int 48 vector + MOV AL,48H ;; + INT 21H ;; Vector in ES:BX + MOV REPLACE_INT_SEGMENT2,ES ;; + PUSH CS ;; + POP ES ;; + MOV WORD PTR ES:SD.OLD_INT_48,BX ;; Offset + MOV AX,REPLACE_INT_SEGMENT2 ;; + MOV WORD PTR ES:SD.OLD_INT_48+2,AX ;; Segment + MOV AH,25H ;; Set int 48 vector + MOV AL,48H ;; + MOV DX,OFFSET KEYB_INT_48 ;; Vector in DS:DX + INT 21H ;; + ;; +INSTALL_DONE: ;; + + + RET ;; + ;; +INSTALL_INT_2F_48 ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: REMOVE_INT_9 +;; +;; Description: +;; Remove our INT 9 driver. +;; +;; Input Registers: +;; DS - points to our data segment +;; BP - points to ES to find SHARED_DATA_AREA +;; +;; Output Registers: +;; DS - points to our data segment +;; AX, BX, DX, ES Trashed +;; +;; Logic: +;; Get old vector +;; Install old vector +;; Return +;; +;; Notes: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +REMOVE_INT_9 PROC ;; + ;; + PUSH DS ;; + PUSH ES ;; + MOV ES,WORD PTR SHARED_AREA_PTR ;; + MOV AX,WORD PTR ES:SD.OLD_INT_9+2 ;; int 9 vector - segment + MOV DS,AX ;; + MOV DX,WORD PTR ES:SD.OLD_INT_9 ;; int 9 vector - offset + ;; + MOV AH,25H ;;;;;;;;; Set int 9 vector + MOV AL,9 ;; + INT 21H ;; + ;; +REMOVE_9_DONE: ;; + POP ES ;; + POP DS ;; + RET ;; + ;; +REMOVE_INT_9 ENDP ;; + ;; +;*********************** CNS **********;; +PURPOSE: ;; +INPUT: ;; +OUTPUT: ;; +;**************************************;; + ;AN000;;; + ;AN000;;; + ;AN000;;; + IDLANG_CHK PROC NEAR ;AN000;;; + ;AN000;;; + mov ax,fb.kl_id_code ;AN000;;;get the id code from the table + cmp ax,[bp].id_parm ;AN000;;;;;;;;;;;compare it to value taken + jne end_match ;AN000; ;from the switch-- if found + cmp ALPHA,0 ;AN000; ;a keyboard code was specified + je a_match ;AN000; ;no lang & a match + ;AN000; ; + mov ax,fb.kl_lang_code ;AN000; ;compare lang codes + cmp ax,[BP].LANGUAGE_PARM ;AN000; ;they are equal + je a_match ;AN000; ; + ;AN000; ; + jmp end_match ;AN000; ;if not found go check next + ;AN000; ;id for the same country + ;AN000; ; + a_match: ;AN000; ; + ; + mov good_match,1 ;AN000; ;report the ids match + ; + end_match: ;AN000; ; + ; + ret ;AN000; ; + ; + IDLANG_CHK ENDP ;AN000; ; +;*********************** CNS *******************; +;**********************************SCAN_ID***********************; +; New variables defined - NUM_ID,ADRSS_LANG,ID_PTR_SIZE,ID_FOUND ; +;****************************************************************; + ; + ; + SCAN_ID PROC NEAR ; + ; + xor di,di ;AN000;;clear di to set at the + ;AN000;;beginning of KEYBSYS STRUCTURE + ;;;;;;;;;; + ; + lea cx,[di].kh_num_ID+4 ;AN000;; set number of bytes to read header + ; + mov ah,3fh ;AN000;; + int 21h ;AN000;; + jnc VAL5ID ;AN000;; + jmp BAD_TAB ;AN000;;;bad table message + ; + VAL5ID: ;AN000; ; + ; + mov cx,SIGNATURE_LENGTH ;AN000; ; + mov di,offset SIGNATURE ;AN000; ; + mov si,offset FB.KH_SIGNATURE;AN000; ; + repe CMPSB ;AN000; ; + je ID_SPECIFIED ;AN000; ; + jmp BAD_TAB ;AN000; ; + ; + ; + ; + ID_SPECIFIED: ;AN000; ; + ; + mov ax,FB.KH_NUM_ID ;AN000; ;;;;;;;;;;;;;;; + mov NUM_ID,ax ;AN000; ;save # of IDs + mul ID_PTR_SIZE ;AN000; ;determine # of bytes to read + push ax ;AN000; ;save current # of bytes to read for + ;AN000; ;ID values only + mov ax,FB.KH_NUM_LANG ;AN000; ;add on lang data in table + mul LANG_PTR_SIZE ;AN000; ;data that comes before the ID data + mov cx,ax ;AN000; ;save that value for the size compare + mov PASS_LANG,cx ;AN000; ; + pop ax ;AN000; ;restore the info for # of ID bytes to read + add cx,ax ;AN000; ;add that value to get total in CX + mov TOTAL_SIZE,cx ;AN000; ;save the total size + cmp cx,FILE_BUFFER_SIZE ;AN000; ; + jbe READ_ID_TAB ;AN000; ; + jmp BAD_TAB ;AN000; ; + ; + ; + READ_ID_TAB: ;AN000; ; + ; + mov dx,offset FILE_BUFFER ;AN000; ; + mov ah,3fh ;;AN000;read language table from + int 21h ;;AN000;keyb defn file + jnc READ_IDVAL ;;AN000; + jmp BAD_TAB ;;AN000; + ; + READ_IDVAL: ;;AN000; + ;;AN000; + mov cx,NUM_ID ;;AN000; + mov di,offset FILE_BUFFER ;;AN000;;;;;;;;;; + add di,PASS_LANG ;AN000; ; + ; + SCAN_ID_TAB: ;AN000; ; + ; + mov ax,[bp].ID_PARM ;AN000; ; + cmp [di].KP_ID_CODE,ax ;AN000; ; + je ID_HERE ;AN000; ; + add di,ID_PTR_SIZE ;AN000; ; + dec cx ;AN000; ; + jne SCAN_ID_TAB ;AN000; ; + jmp FINALE ;AN000; ; + ; + BAD_TAB: ;AN000;; + ; + mov ERR4ID,1 ;AN000; ; + jmp FINALE ;AN000; ; + ; + ; + ; + ID_HERE: ;AN000; ; + ; + mov ID_FOUND,1 ;AN000;;reset ptr for ; + ;AN000;;current country ; + ; + + ; + FINALE: ;AN000; ; + ; + ret ;AN000; ; + ; + ; + SCAN_ID ENDP ;AN000; ; + ; +;*******************************SCAN_ID END******; +;; +;; Module: BUILD_PATH +;; +;; Description: +;; Build the complete filename of the Keyboard Definition File +;;*************************************WGR********************* +;; and open the file. +;;+++++++++++++++++++++++++++++++++++++WGR+++++++++++++++++++++ +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to our data segment +;; BP - offset of parmeter list +;; +;; Output Registers: +;;************************************WGR********************** +;; CARRY CLEAR +;; AX = HANDLE +;; CARRY SET (ERROR) +;; NONE +;;++++++++++++++++++++++++++++++++++++WGR++++++++++++++++++++++ +;; The complete filename will be available in FILE_NAME +;; +;; Logic: +;; +;; Determine whether path parameter was specified +;; IF length is zero THEN +;;****************************************WGR****************** +;; Try to open file in ACTIVE directory +;; IF failed THEN +;; Try to open file in ARGV(0) directory +;; IF failed THEN +;; Try to open file in ROOT directory (for DOS 3.3 compatibility) +;; ENDIF +;; ENDIF +;; ENDIF +;; ELSE +;; Copy path from PSP to FILE_NAME memory area +;; Try to open USER SPECIFIED file +;;++++++++++++++++++++++++++++++++++++++++WGR++++++++++++++++++ +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBOARD_SYS DB '\KEYBOARD.SYS',00 ;AN000;;; +KEYB_SYS_ACTIVE DB 'KEYBOARD.SYS',00 ;AN000;;; WGR ;AN000 +KEYB_SYS_LENG EQU 14 ;AN000;;; +KEYB_SYS_A_LENG EQU 13 ;AN000;;; WGR ;AN000 + ;; +FILE_NAME DB 128 DUP(0) ;AN000;;; + ;; +FILE_NOT_FOUND EQU 2 ;AN000;;; WGR ;AN000 +PATH_NOT_FOUND EQU 3 ;AN000;;; WGR ;AN000 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +BUILD_PATH PROC NEAR ;; + CLD ;AN000;;; WGR ;AN000 + MOV DI,OFFSET FILE_NAME ;; Get the offset of the filename + MOV CX,[BP].PATH_LENGTH ;; If path is specified then + CMP CX,0 ;; + JE APPEND_KEYB_SYS ;; + MOV SI,[BP].PATH_OFFSET ;; Get the offset of the path + ;; + REPE MOVSB ;AC000;;; Copy each char of the specified + MOV AX,3D00H ;AC000;;; WGR Open the KEYBOARD.SYS file ;AN000 + MOV DX,OFFSET FILE_NAME ;AC000;;; WGR ;AN000 + INT 21H ;AC000;;; WGR ;AN000 + RET ;; path into the filename location + ;; +APPEND_KEYB_SYS: ;;;;; + MOV SI,OFFSET KEYB_SYS_ACTIVE ;AC000;;; WGR copy name for active directory ;AN000 + MOV CX,KEYB_SYS_A_LENG ;AC000;;;;;; WGR to file name variable. ;AN000 + REPE MOVSB ;AC000;;; WGR ;AN000 + MOV AX,3D00H ;AC000;;; WGR try to open it. ;AN000 + MOV DX,OFFSET FILE_NAME ;AC000;;; WGR ;AN000 + INT 21H ;AC000;;; WGR ;AN000 + .IF C ;AC000;;; WGR error in opening...was it.. ;AN000 + .IF OR ;AN000;;; WGR path or.. ;AN000 + .IF ;AN000;;; WGR file not found?... ;AN000 + CALL COPY_ARGV0 ;AC000;;; WGR yes....try ARGV(0) directory. ;AN000 + MOV AX,3D00H ;AC000;;; WGR ;AN000 + MOV DX,OFFSET FILE_NAME ;AC000;;; WGR ;AN000 + INT 21H ;AC000;;; WGR ;AN000 + .IF C ;AC000;;; WGR error in opening....was it.. ;AN000 + .IF OR ;AC000;;; WGR path or.. ;AN000 + .IF ;AC000;;; WGR file not found? ;AN000 + MOV SI,OFFSET KEYBOARD_SYS ;AC000;;; WGR try ROOT directory. ;AN000 + MOV DI,OFFSET FILE_NAME ;AC000;;; WGR ;AN000 + MOV CX,KEYB_SYS_LENG ;AC000;;; WGR ;AN000 + REPE MOVSB ;AC000;;; WGR ;AN000 + MOV AX,3D00H ;AC000;;; WGR ;AN000 + MOV DX,OFFSET FILE_NAME ;AC000;;; WGR ;AN000 + INT 21H ;AC000;;; WGR ;AN000 + .ELSE ;AC000;;; WGR if failed then carry set.. ;AN000 + STC ;AC000;;; WGR some other error..set flag ;AN000 + .ENDIF ;AC000;;; WGR ;AN000 + .ENDIF ;AC000;;; WGR ;AN000 + .ELSE ;AN000;;; WGR ;AN000 + STC ;AN000;;; WGR some other error..set flag. ;AN000 + .ENDIF ;AN000;;; WGR ;AN000 + .ENDIF ;AN000;;; WGR ;AN000 + ;; + RET ;AN000;;; + ;; +BUILD_PATH ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WGR +;; WGR +;; Module Name: WGR +;; COPY_ARGV0 WGR +;; WGR +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WGR + ;; WGR + ;; WGR +COPY_ARGV0 PROC ;; WGR ;AN000 + ;; WGR ;AN000 + PUSH ES ;AN000;;; WGR ;AN000 + PUSH DI ;AN000;;; WGR ;AN000 + PUSH SI ;AN000;;; WGR ;AN000 + PUSH CX ;AN000;;; WGR ;AN000 + ;AN000;;; WGR ;AN000 + MOV DI,2CH ;AN000;;; WGR Locate environment string ;AN000 + MOV ES,[DI] ;AN000;;; WGR ;AN000 + XOR SI,SI ;AN000;;; WGR ;AN000 + .WHILE < NE 0> ;AN000;;; WGR find ARGV(0) string. ;AN000 + INC SI ;AN000;;; WGR ;AN000 + .ENDWHILE ;AN000;;; WGR ;AN000 + ADD SI,4 ;AN000;;; WGR ;AN000 + LEA DI,FILE_NAME ;AN000;;; WGR move string to work area ;AN000 + .REPEAT ;AN000;;; WGR ;AN000 + MOV AL,ES:[SI] ;AN000;;; WGR ;AN000 + MOV [DI],AL ;AN000;;; WGR ;AN000 + INC SI ;AN000;;; WGR ;AN000 + INC DI ;AN000;;; WGR ;AN000 + .UNTIL < EQ 0> ;AN000;;; WGR ;AN000 + .REPEAT ;AN000;;; WGR ;AN000 + DEC DI ;AN000;;; WGR ;AN000 + .UNTIL < EQ '\'> OR ;AN000;;; WGR ;AN000 + .UNTIL < EQ 0> ;AN000;;; WGR scan back to.. ;AN000 + INC DI ;AN000;;; WGR first character after "\" ;AN000 + PUSH CS ;AN000;;; WGR ;AN000 + POP ES ;AN000;;; WGR ;AN000 + LEA SI,KEYB_SYS_ACTIVE ;AN000;;; WGR copy in "KEYBOARD.SYS" ;AN000 + MOV CX,KEYB_SYS_A_LENG ;AN000;;; WGR ;AN000 + REPE MOVSB ;AN000;;; WGR ;AN000 + ;AN000;;; WGR ;AN000 + POP CX ;AN000;;; WGR ;AN000 + POP SI ;AN000;;; WGR ;AN000 + POP DI ;AN000;;; WGR ;AN000 + POP ES ;AN000;;; WGR ;AN000 + RET ;AN000;;; WGR ;AN000 + ;AN000;;; WGR ;AN000 +COPY_ARGV0 ENDP ;AN000;;; + ;AN000;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: FIND_FIRST_CP +;; +;; Description: +;; Check the keyboard definition file for the first code page +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to our data segment +;; BP - offset of parmeter list +;; +;; Output Registers: +;; NONE +;; +;; Logic: +;; Open the file +;; IF error in opening file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Save handle +;; Set address of buffer +;; READ header of Keyboard definition file +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Check signature for correct file +;; IF file signature is correct THEN +;; READ language table +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Use table to verify language parm +;; Set pointer values +;; IF code page was specified +;; READ language entry +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; READ first code page +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; RET +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FIND_FIRST_CP PROC NEAR ;; + ;; + PUSH CX ;; Save everything that + PUSH DX ;; that will be changed + PUSH SI ;; + PUSH DI ;; + ;; + MOV BX,KEYBSYS_FILE_HANDLE ;; Get handle + MOV DX,WORD PTR KEYBCMD_LANG_ENTRY_PTR ;; LSEEK file pointer + MOV CX,WORD PTR KEYBCMD_LANG_ENTRY_PTR+2 ;; to top of language entry + MOV AH,42H ;; + MOV AL,0 ;;;;;;;;;;;;;; If no problem with + INT 21H ;; Keyb Def file Then + JNC FIND_FIRST_BEGIN ;; + JMP FIND_FIRST_CP_ERROR4 ;; + ;;;;;;;;; +FIND_FIRST_BEGIN: ;; + MOV DI,AX ;; + MOV CX,SIZE KEYBSYS_LANG_ENTRY-1 ;; Set number + ;; bytes to read header + MOV DX,OFFSET FILE_BUFFER ;;;;;;;;; + MOV AH,3FH ;; Read language entry in + INT 21H ;; keyboard definition file + JNC FIND_FIRST_VALID4 ;; If no error in opening file then + JMP FIND_FIRST_CP_ERROR4 ;; + ;; +FIND_FIRST_VALID4: ;; +;************************** CNS *******;; + xor ah,ah ;AC000;;; + MOV Al,FB.KL_NUM_CP ;AC000;;; +;************************** CNS *******;; + MUL CP_PTR_SIZE ;; Determine # of bytes to read + MOV DX,OFFSET FILE_BUFFER ;; Establish beginning of buffer + MOV CX,AX ;; + CMP CX,FILE_BUFFER_SIZE ;; Make sure buffer is not to small + JBE FIND_FIRST_VALID5 ;; + JMP FIND_FIRST_CP_ERROR4 ;; + ;; +FIND_FIRST_VALID5: ;; + MOV AH,3FH ;; Read code page table from + INT 21H ;; keyboard definition file + JNC FIND_FIRST_VALID6 ;; If no error in opening file then + JMP FIND_FIRST_CP_ERROR4 ;; + ;; +FIND_FIRST_VALID6: ;; + MOV CX,NUM_CP ;; Number of valid codes + MOV DI,OFFSET FILE_BUFFER ;; Point to correct word in table + ;; + MOV BX,[DI].KC_CODE_PAGE ;; Get parameter + XOR AX,AX ;; + JMP FIND_FIRST_RETURN ;; + ;; +FIND_FIRST_CP_ERROR4: ;; + MOV AX,4 ;; + ;; +FIND_FIRST_RETURN: ;; + POP DI ;; + POP SI ;; + POP DX ;; + POP CX ;; + ;; + RET ;; + ;; +FIND_FIRST_CP ENDP ;; + ;;;;;;;;;;;;; +.xlist ;; +MSG_SERVICES ;AN000;;; WGR ;AN000 +MSG_SERVICES ;AN000;;; WGR ;AN000 +MSG_SERVICES ;AN000;;; WGR ;AN000 +MSG_SERVICES ;AN000;;; WGR ;AN000 +MSG_SERVICES ;AN000;;; WGR ;AN000 +.list ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Temp Shared Data Area +;; Contains data which is required by +;; both the resident and transient KEYB code. +;; All keyboard tables are stored in this area +;; Structures for this area are in file KEYBSHAR.INC +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; + db 'TEMP SHARED DATA' ;; +SD_SOURCE_PTR LABEL BYTE ;; +TEMP_SHARED_DATA SHARED_DATA_STR <> ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +CODE ENDS + +include msgdcl.inc + + END + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/KEYBCMD.INC b/v4.0/src/CMD/KEYB/KEYBCMD.INC new file mode 100644 index 0000000..ac40fe5 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBCMD.INC @@ -0,0 +1,53 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBCMD.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; External declarations for procedures in file KEYCMD.ASM. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN KEYB_COMMAND :NEAR ;; + ;; + EXTRN KEYBSYS_FILE_HANDLE:WORD ;; + EXTRN CP_TAB_OFFSET:DWORD ;; + EXTRN STATE_LOGIC_OFFSET:DWORD ;; + EXTRN SYS_CODE_PAGE:WORD ;; + EXTRN KEYBCMD_LANG_ENTRY_PTR:DWORD ;; + EXTRN DESIG_CP_BUFFER:WORD ;; + EXTRN DESIG_CP_OFFSET:WORD ;; + EXTRN NUM_DESIG_CP:WORD ;; + EXTRN TB_RETURN_CODE:WORD ;; + EXTRN FILE_BUFFER_SIZE:ABS + EXTRN FILE_BUFFER:WORD ;; +;****************CNS**************************** + EXTRN ID_PTR_SIZE:WORD ;; +;****************CNS**************************** + EXTRN LANG_PTR_SIZE:WORD ;; + EXTRN CP_PTR_SIZE:WORD ;; +;****************CNS**************************** + EXTRN NUM_ID:WORD ;; +;****************CNS**************************** + EXTRN NUM_LANG:WORD ;; + EXTRN NUM_CP:WORD ;; + EXTRN SHARED_AREA_PTR:DWORD ;; + EXTRN SD_SOURCE_PTR:BYTE ;; + EXTRN TEMP_SHARED_DATA:BYTE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST + + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/KEYBCPSD.ASM b/v4.0/src/CMD/KEYB/KEYBCPSD.ASM new file mode 100644 index 0000000..2cae9fe --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBCPSD.ASM @@ -0,0 +1,128 @@ + PAGE ,132 + TITLE DOS - KEYB Command - Copy Shared_Data_Area + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBCPSD.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Copies the SHARED_DATA_AREA into a part of memory that +;; can be left resident. All relative pointers must already +;; be recalculated to this new position. +;; THIS FILE MUST BE THE LAST OF THE RESIDENT FILES WHEN KEYB IS LINKED. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May ?? 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; +;; Include Files Required: +;; ----------------------- +;; INCLUDE KEYBSHAR.INC +;; INCLUDE KEYBCMD.INC +;; INCLUDE KEYBTBBL.INC +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE ????????.ASM: +;; procedure - description???????????????????????????????? +;; +;; Linkage Information: Refer to file KEYB.ASM +;; -------------------- +;; +;; Change History: +;; --------------- +;; PTMP3955 ;AN004;KEYB component to free environment and close handles 0 - 4 +;; 3/24/88 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + PUBLIC SD_DEST_PTR ;; + PUBLIC COPY_SD_AREA ;; + PUBLIC SHARED_DATA ;; + ;; + INCLUDE STRUC.INC + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBCMD.INC ;; + INCLUDE KEYBTBBL.INC ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: COPY_SD_AREA +;; +;; Description: +;; +;; Input Registers: +;; +;; Output Registers: +;; N/A +;; +;; Logic: +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SD EQU SHARED_DATA ;; +TSD EQU TEMP_SHARED_DATA ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +COPY_SD_AREA PROC NEAR ;; + ;; + REP MOVS ES:BYTE PTR [DI],DS:[SI] ;; Copy SHARED_DATA_AREA to + + push ax ;AN004;save existing values + push es ;AN004;; + xor ax,ax ;AN004;clear out ax + mov ax,cs:[2ch] ;AN004;check offset for address containin environ. + cmp ax,0 ;AN004; + je NO_FREEDOM ;AN004; + mov es,ax ;AN004; + mov ax,4900H ;AN004;make the free allocate mem func + int 21h ;AN004;; + + +NO_FREEDOM: + pop es ;AN004;restore existing values + pop ax ;AN004;; + + push ax ;AN004; + push bx ;AN004; + + ;AN004; ;Terminate and stay resident + mov bx,4 ;AN004; ;1st close file handles + .REPEAT ;AN004; ;STDIN,STDOUT,STDERR + mov ah,3eh ;AN004; ; + int 21h ;AN004; ; + dec bx ;AN004; ; + .UNTIL ;AN004; ; + + pop bx ;AN004; + pop ax ;AN004; + ;AN004; new part of memory + MOV BYTE PTR ES:SD.TABLE_OK,1 ;; Activate processing flag + INT 21H ;; Exit + ;; + ;; +COPY_SD_AREA ENDP ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + db 'SHARED DATA' ;; +SD_DEST_PTR LABEL BYTE ;; + ;; +SHARED_DATA SHARED_DATA_STR <> ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/KEYBCPSD.INC b/v4.0/src/CMD/KEYB/KEYBCPSD.INC new file mode 100644 index 0000000..bb4f036 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBCPSD.INC @@ -0,0 +1,29 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBCPSD.INC +;; ---------- +;; +;; Description: +;; ------------ +;; External declarations and equates for procedures in file +;; KEYBCPSD.ASM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN COPY_SD_AREA:NEAR ;; + ;; + EXTRN SD_DEST_PTR :BYTE ;; + EXTRN SHARED_DATA :BYTE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBDCL.INC b/v4.0/src/CMD/KEYB/KEYBDCL.INC new file mode 100644 index 0000000..43b40a4 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBDCL.INC @@ -0,0 +1,50 @@ + +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBDCL.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; Common declarations for structures in procedures for KEYB.COM +;; +;; Change History: +;; --------------- +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +PARM_LIST STRUC ;; +;*******************CNS****************** +;*******************CNS****************** + RET_CODE_1 DB 0 ;; \ + RET_CODE_2 DB 0 ;; | + RET_CODE_3 DB 0 ;; | +;*******************CNS****************** + RET_CODE_4 DB 0 ;; |;AN000; +;*******************CNS****************** + LANGUAGE_PARM DW ? ;; } PARAMETER + CODE_PAGE_PARM DW ? ;; | LIST + PATH_OFFSET DW ? ;; | + PATH_LENGTH DW 0 ;; / +;*******************CNS****************** + ID_PARM DW ? ;AN000; +;*******************CNS****************** +PARM_LIST ENDS ;; + ;; +DESIG_CP_STRUC STRUC ;; + NUM_DESIGNATES DW ? ;; + NUM_FONTS DW ? ;; + NUM_HW_CPS DW ? ;; + DESIG_CP_ENTRY DW ? ;; +DESIG_CP_STRUC ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBEQU.INC b/v4.0/src/CMD/KEYB/KEYBEQU.INC new file mode 100644 index 0000000..f12f7f3 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBEQU.INC @@ -0,0 +1,31 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBEQU.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; Include file containing equates used by all KEYB modules. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +YES EQU 1 ;; +NO EQU 0 ;; + ;; +INT_2F_SUB_FUNC EQU 0ADH ;; our subfunction code for int 2f +SD EQU SHARED_DATA ;; +TSD EQU TEMP_SHARED_DATA ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST diff --git a/v4.0/src/CMD/KEYB/KEYBI2F.ASM b/v4.0/src/CMD/KEYB/KEYBI2F.ASM new file mode 100644 index 0000000..30dce7e --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI2F.ASM @@ -0,0 +1,225 @@ + + PAGE ,132 + TITLE DOS - KEYB Command - Interrupt 2F Handler + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI2F.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Contains Interrupt 2F handler. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May ?? 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; KEYB_INT_2F - Interupt 2F handler +;; +;; Include Files Required: +;; ----------------------- +;; INCLUDE KEYBEQU.INC +;; INCLUDE KEYBSHAR.INC +;; INCLUDE KEYBMAC.INC +;; INCLUDE KEYBCMD.INC +;; INCLUDE KEYBCPSD.INC +;; INCLUDE KEYBI9C.INC +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE ????????.ASM: +;; procedure - description???????????????????????????????? +;; +;; Linkage Information: Refer to file KEYB.ASM +;; -------------------- +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBMAC.INC ;; + INCLUDE KEYBCMD.INC ;; + INCLUDE KEYBCPSD.INC ;; + INCLUDE KEYBI9C.INC ;; + ;; + PUBLIC KEYB_INT_2F ;; + ;; + EXTRN ERROR_BEEP:NEAR ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: KEYB_INT_2F +;; +;; Description: +;; +;; Input Registers: +;; AH = 0ADH +;; AL = 80,81,82 +;; +;; Output Registers: +;; N/A +;; +;; Logic: +;; IF AH = 0ADh THEN (this call is for us) +;; Set carry flag to 0 +;; IF AL = 80 THEN +;; Get major and minor +;; Get SEG:OFFSET of SHARED_DATA_AREA +;; +;; IF AL = 81 THEN +;; Get FIRST_XLAT_PTR +;; FOR each table +;; IF code page requested = code page value at pointer THEN +;; Set INVOKED_CODE_PAGE +;; Set ACTIVE_XLAT_PTR +;; EXIT +;; ELSE +;; Get NEXT_SECT_PTR +;; NEXT table +;; IF no corresponding code page found THEN +;; Set carry flag +;; +;; IF AL = 82 THEN +;; IF BL = 00 THEN +;; Set COUNTRY_FLAG = 00 +;; ELSE IF BL = 0FFH THEN +;; Set COUNTRY_FLAG = 0FFH +;; ELSE +;; Set carry flag +;; IRET or JMP to another INT 2FH handler (if installed) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +CP_QUERY EQU 80H ;; +CP_INVOKE EQU 81H ;; +CP_LANGUAGE EQU 82H ;; + ;; +VERSION_MAJOR EQU 01H ;; +VERSION_MINOR EQU 00H ;; + ;; +CARRY_FLAG EQU 01H ;; +RESTORE_BP DW ? ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYB_INT_2F PROC ;; + ;; + PUSH DS ;; + PUSH BX ;; + PUSH CX ;; + PUSH SI ;; + ;; + PUSH CS ;; + POP DS ;; Set DATA SEGMENT register + ;; + CMP AH,INT_2F_SUB_FUNC ;; Q..is this call for us? + JE CHECK_REQUEST_CODE ;; Y..check request code + JMP INT_2F_DONE ;; N..get out + ;; +CHECK_REQUEST_CODE: ;; Y..check request code + MOV RESTORE_BP,BP ;;;;;;;;;;; + MOV BP,SP ;; Clear CARRY flag + AND WORD PTR [BP]+12,NOT CARRY_FLAG ;; + MOV BP,RESTORE_BP ;; + ;;;;;;;;;;; + ;; +INT_2F_CP_QUERY: ;; + CMP AL,CP_QUERY ;; Q..query CP? + JNE INT_2F_CP_INVOKE ;; N..next + MOV AX,-1 ;; Y..process query + MOV BH,VERSION_MAJOR ;; + MOV BL,VERSION_MINOR ;; + MOV DI,OFFSET SD ;; + PUSH CS ;; + POP ES ;; + JMP INT_2F_DONE ;; + ;; +INT_2F_CP_INVOKE: ;; + CMP AL,CP_INVOKE ;; Q..invoke CP? + JNE INT_2F_CP_LANGUAGE ;; N..next + ;; + MOV SI,SD.FIRST_XLAT_PTR ;; Get FIRST_XLAT_PTR + ;; +INT_2F_NEXT_SECTION: ;; + CMP SI,-1 ;; + JE INT_2F_ERROR_FLAG ;; + MOV CX,[SI].XS_CP_ID ;; Read in the code page value + CMP CX,BX ;; Is this the table to make active? + JNE INT_2F_CP_INVOKE_CONT1 ;; + MOV SD.ACTIVE_XLAT_PTR,SI ;; IF Yes, Set the ACTIVE_XLAT_PTR + MOV SD.INVOKED_CP_TABLE,BX ;; record new code page + JMP INT_2F_DONE ;; + ;; +INT_2F_CP_INVOKE_CONT1: ;; Else + MOV DI,[SI].XS_NEXT_SECT_PTR ;; IF No, + MOV SI,DI ;; Get NEXT_SECT_PTR + JMP INT_2F_NEXT_SECTION ;; NEXT_SECTION + ;; +INT_2F_ERROR_FLAG: ;; + MOV AX,1 ;; + MOV RESTORE_BP,BP ;;;;;; + MOV BP,SP ;; + OR WORD PTR [BP]+12,CARRY_FLAG ;; Set carry flag + MOV BP,RESTORE_BP ;; + ;;;;;; + JMP INT_2F_DONE ;; + ;; +INT_2F_CP_LANGUAGE: ;; + CMP AL,CP_LANGUAGE ;; Q..Set default language?? + JNE INT_2F_DONE ;; N..next + ;; + CMP BL,0 ;; Y..Check if Language is to be US437 + JNE INT_2F_CONTINUE1 ;; IF yes THEN, + MOV COUNTRY_FLAG,BL ;; Set COUNTRY_FLAG to 0 + JMP INT_2F_DONE ;; + ;; +INT_2F_CONTINUE1: ;; ELSE + CMP BL,-1 ;; Check if language is to be national + JNE INT_2F_LANG_ERROR_FLAG ;; IF yes THEN, + MOV COUNTRY_FLAG,BL ;; Set COUNTRY_FLAG to -1 (0FFH) + JMP INT_2F_DONE ;; + ;; +INT_2F_LANG_ERROR_FLAG: ;; ELSE + MOV RESTORE_BP,BP ;;;;;; Set CARRY flag + MOV BP,SP ;; + OR WORD PTR [BP]+12,CARRY_FLAG ;; + MOV BP,RESTORE_BP ;; + ;;;;;; + JMP INT_2F_DONE ;; + ;; +INT_2F_DONE: ;; + POP SI ;; + POP CX ;; + POP BX ;;;;;;; + POP DS ;; + CMP WORD PTR CS:SD.OLD_INT_2F,0 ;; Q..are we the last in the chain? + JNE INT_2F_JMP ;; N..call next in chain + CMP WORD PTR CS:SD.OLD_INT_2F+2,0 ;; Q..are we the last in the chain? + JNE INT_2F_JMP ;; N..call next in chain + ;;;;;;; + IRET ;; Y..return to caller + ;; +INT_2F_JMP: ;; + ;; + JMP CS:SD.OLD_INT_2F ;; + ;; +KEYB_INT_2F ENDP ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/KEYBI2F.INC b/v4.0/src/CMD/KEYB/KEYBI2F.INC new file mode 100644 index 0000000..57067f4 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI2F.INC @@ -0,0 +1,26 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI2F.INC +;; ---------- +;; +;; Description: +;; ------------ +;; External declarations and equates for procedures in file +;; KEYBI2F.ASM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN KEYB_INT_2F:NEAR ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBI48.ASM b/v4.0/src/CMD/KEYB/KEYBI48.ASM new file mode 100644 index 0000000..05ed786 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI48.ASM @@ -0,0 +1,174 @@ + + + PAGE ,132 + TITLE DOS - KEYB Command - Interrupt 48H Handler + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI48.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Contains Interrupt 48H handler. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May ?? 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; +;; Include Files Required: +;; ----------------------- +;; INCLUDE KEYBEQU.INC +;; INCLUDE KEYBSHAR.INC +;; INCLUDE KEYBMAC.INC +;; INCLUDE KEYBCMD.INC +;; INCLUDE KEYBCPSD.INC +;; INCLUDE POSTEQU.inc +;; INCLUDE DSEG.inc +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE ????????.ASM: +;; procedure - description???????????????????????????????? +;; +;; Linkage Information: Refer to file KEYB.ASM +;; -------------------- +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBMAC.INC ;; + INCLUDE KEYBCMD.INC ;; + INCLUDE KEYBCPSD.INC ;; + INCLUDE POSTEQU.inc ;; + INCLUDE DSEG.inc ;; + ;; + PUBLIC KEYB_INT_48 ;; + ;; + EXTRN ERROR_BEEP:NEAR ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + ASSUME CS:CODE,DS:CODE,ES:DATA;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: KEYB_INT_48 +;; +;; Description: +;; +;; Input Registers: +;; AL := Scan Code +;; +;; Output Registers: +;; N/A +;; +;; Logic: +;; IF scan code is not a break code THEN +;; IF CNTL was not entered THEN +;; IF ALT+SHIFT was pressed THEN +;; Set JB_KB_FLAG in SHARED_DATA_AREA +;; Clear ALT and SHIFT states in KB_FLAG +;; IRET or JMP to a chained INT48 routine +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYB_INT_48 PROC ;; + ;; + STI ;; allow NON-KB interrupts + PUSH BX ;; + PUSH BP ;; + PUSH CX ;; + PUSH DX ;; + PUSH DI ;; + PUSH SI ;; + PUSH DS ;; + PUSH ES ;; + PUSH AX ;; + ;; + MOV SD.JR_KB_FLAG,0 ;; Clear the flag + ;; + CMP AL,80H ;; Test for break code + JA INT48_EXIT ;; IF not a break code THEN + ;; + PUSH DS ;; Save segment registers + PUSH ES ;; + ;; + PUSH CS ;; Set up addressing + POP DS ;; for DATA SEGMENT (=CODE SEGMENT) + MOV BX,DATA ;; Set up addressing + MOV ES,BX ;; for EXTRA SEGMENT (=BIOS RAM AREA) + ;; + MOV AH,KB_FLAG ;; Get the flag status + AND AH,0FH ;; Clear all shift states + ;; + TEST AH,CTL_SHIFT ;; Test if CNTL was entered? + JNE INT48_PASS ;;;;;;;;;;;;;;;; IF yes THEN + ;; pass to ROM INT48 + AND AH,ALT_SHIFT+RIGHT_SHIFT+LEFT_SHIFT ;; Test if both ALT and + CMP AH,ALT_SHIFT ;; SHIFT were pressed + JBE INT48_PASS ;; IF no THEN + ;; pass to ROM INT48 + MOV BH,KB_FLAG ;;;;;;;;;;;; IF yes then + MOV SD.JR_KB_FLAG,BH ;; Setup JR flag + AND SD.JR_KB_FLAG,ALT_SHIFT+RIGHT_SHIFT+LEFT_SHIFT ;; Pass flags + ;; (ALT and + ;;;;;;;;;;;;;;;;;;;;;;;;;; EITHER/BOTH SHIFT) + XOR KB_FLAG,AH ;; Clear the ALT state and SHIFT state + ;; Reset the KB_FLAG to permit + ;; third shifts to go through +INT48_PASS: ;; + POP ES ;; + POP DS ;; + ;;;;;;; +INT48_EXIT: ;; + CMP WORD PTR CS:SD.OLD_INT_48,0 ;; Q..are we the last in the chain? + JNE INT_48_JMP ;; N..call next in chain + CMP WORD PTR CS:SD.OLD_INT_48+2,0 ;; Q..are we the last in the chain? + JNE INT_48_JMP ;; N..call next in chain + ;;;;;;; + POP AX ;; restore regs + POP ES ;; + POP DS ;; + POP SI ;; + POP DI ;; + POP DX ;; + POP CX ;; + POP BP ;; + POP BX ;; + ;; + IRET ;; Y..return to caller + ;; +INT_48_JMP: ;; + ;; + POP AX ;; restore regs + POP ES ;; + POP DS ;; + POP SI ;; + POP DI ;; + POP DX ;; + POP CX ;; + POP BP ;; + POP BX ;; + ;; + JMP CS:SD.OLD_INT_48 ;; + ;; +KEYB_INT_48 ENDP ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/KEYBI48.INC b/v4.0/src/CMD/KEYB/KEYBI48.INC new file mode 100644 index 0000000..592223c --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI48.INC @@ -0,0 +1,27 @@ + +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI48.INC +;; ---------- +;; +;; Description: +;; ------------ +;; External declarations and equates for procedures in file +;; KEYBI48.ASM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN KEYB_INT_48:NEAR ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBI9.ASM b/v4.0/src/CMD/KEYB/KEYBI9.ASM new file mode 100644 index 0000000..d32b096 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI9.ASM @@ -0,0 +1,672 @@ + + PAGE ,132 + TITLE DOS KEYB Command - Interrupt 9 Non-US Support + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI9.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Converts scan codes to ASCII for non-US keyboards. +;; This orutine uses the tables loaded into the SHARED_DATA_AREA +;; from KEYBOARD.SYS by the KEYB_COMMAND module. +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; KEYB_STATE_PROCESSOR - Scan to ASCII translator. +;; +;; External Procedure References: +;; ------------------------------ +;; None. +;; +;; Linkage Information: Refer to file KEYB.ASM +;; -------------------- +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;**** + INCLUDE KEYBEQU.INC ;; + INCLUDE DSEG.inc ;; System data segments + INCLUDE POSTEQU.inc ;; System equates + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBI2F.INC ;; + INCLUDE KEYBI9C.INC ;; + INCLUDE KEYBCPSD.INC ;; + INCLUDE KEYBCMD.INC ;; + ;; + PUBLIC KEYB_STATE_PROCESSOR ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: KEYB_STATE_PROCESSOR +;; +;; Description: +;; Convert scan to ASCII using the tables loaded into the +;; SHARED_DATA_AREA. Conversion is directed by the STATE LOGIC +;; commands contained in the SHARED_DATA_AREA. This routine +;; interprets those commands. +;; +;; Input Registers: +;; N/A +;; +;; Output Registers: +;; N/A +;; +;; Logic: +;; Enable interrupts +;; Save registers +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +BREAK_CODE EQU 80H ;; + ;; +HOT_KEY_ACTIVE DB 0 ;; 1 if hot key is active + ;; + ;; + ;; These are copies of the BIOS FLAGS +FLAGS_TO_TEST LABEL BYTE ;; KB_FLAG, KB_FLAG_1,2,3 +KB_SHADOW_FLAGS DB NUM_BIOS_FLAGS DUP(0) ;; +EXT_KB_FLAG DB 0 ;; Extended KB Flag for shift states +NLS_FLAG_1 DB 0 ;; NLS Flags for dead key etc +NLS_FLAG_2 DB 0 ;; . + ;; +SAVED_NLS_FLAGS DB 0,0 ;; Saved copy of the NLS flags + ;; +OPTION_BYTE DB 0 ;; Set by OPTION command + ;; +KB_FLAG_PTRS DW OFFSET KB_FLAG ;; These are pointers to the BIOS flags + DW OFFSET KB_FLAG_1 ;; we must test + DW OFFSET KB_FLAG_2 ;; + DW OFFSET KB_FLAG_3 ;; + ;; +XLAT_TAB_PTR DW 0 ;; pointer to xlat tables for cur state + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +NEST_LEVEL DB 0 ;; +PROCESS_LEVEL DB 0 ;; +TAKE_ELSE DB 0 ;; +BUSY_FLAG DB 0 ;; Flag to prevent re-entry + ;; +CMD_JUMP_TABLE LABEL WORD ;; + DW OFFSET IFF_PROC ;; CODE 0 + DW OFFSET ANDF_PROC ;; 1 + DW OFFSET ELSEF_PROC ;; 2 + DW OFFSET ENDIFF_PROC ;; 3 + DW OFFSET XLATT_PROC ;; 4 + DW OFFSET OPTION_PROC ;; 5 + DW OFFSET SET_FLAG_PROC ;; 6 + DW OFFSET PUT_ERROR_PROC ;; 7 + DW OFFSET IFKBD_PROC ;; 8 + DW OFFSET GOTO_PROC ;; 9 + DW OFFSET BEEP_PROC ;; A + DW OFFSET RESET_NLS_PROC ;; B + DW OFFSET UNKNOWN_COMMAND ;; C + DW OFFSET UNKNOWN_COMMAND ;; D + DW OFFSET UNKNOWN_COMMAND ;; E + DW OFFSET UNKNOWN_COMMAND ;; F + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYB_STATE_PROCESSOR PROC NEAR ;; + ;; + TEST CS:SD.TABLE_OK,1 ;; + JNZ WE_HAVE_A_TABLE ;; + CLC ;; BACK TO US INT 9 + RET ;; + + EVEN + +WE_HAVE_A_TABLE: ;; + + PUSH DS ;; save DS + PUSH ES ;; save ES + PUSH AX ;; save scan code for caller + PUSH BX ;; save shift states for caller + + PUSH CS ;; + POP DS ;; DS = our seg + MOV BX,DATA ;; + MOV ES,BX ;; addressability to BIOS data + ;; + ;; + CMP COUNTRY_FLAG,0FFH ;; Q..country mode? + JE INIT_STATE_PROCESSING ;; Y..continue + JMP GOTO_BIOS ;; N..exit + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; -------STATE SECTION PROCESSING------- +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +INIT_STATE_PROCESSING: ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Set NLS shift flags EITHER_SHIFT, EITHER_ALT, EITHER_CTRL +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; Q..in shift state? + TEST ES:KB_FLAG,RIGHT_SHIFT+LEFT_SHIFT + JNZ IN_SHIFT_STATE ;; Y..go set bit + AND EXT_KB_FLAG,NOT EITHER_SHIFT ;; N..clear bit + JMP SHORT TEST_CTL ;; +IN_SHIFT_STATE: ;; + OR EXT_KB_FLAG,EITHER_SHIFT ;; +TEST_CTL: ;; + TEST ES:KB_FLAG,CTL_SHIFT ;; Q..in control state? + JNZ IN_CTL_STATE ;; Y..go set bit + TEST ES:KB_FLAG_3,R_CTL_SHIFT ;; Q..how bout the right ctl? + JNZ IN_CTL_STATE ;; Y..go set the bit + AND EXT_KB_FLAG,NOT EITHER_CTL ;; N..clear the bit + JMP SHORT TEST_ALT ;; +IN_CTL_STATE: ;; + OR EXT_KB_FLAG,EITHER_CTL ;; +TEST_ALT: ;; + TEST ES:KB_FLAG,ALT_SHIFT ;; Q..in alt state? + JNZ IN_ALT_STATE ;; Y..go set bit + TEST ES:KB_FLAG_3,R_ALT_SHIFT ;; Q..how bout the right alt? + JNZ IN_ALT_STATE ;; Y..go set the bit + AND EXT_KB_FLAG,NOT EITHER_ALT ;; N..clear the bit + JMP SHORT COPY_FLAGS ;; +IN_ALT_STATE: ;; + OR EXT_KB_FLAG,EITHER_ALT ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Copy BIOS KB flags from BIOS data seg into the +;; FLAGS_TO_TEST structure. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +COPY_FLAGS: ;; + MOV CX,NUM_BIOS_FLAGS ;; + MOV SI,0 ;; pointers to the BIOS flags + MOV DI,0 ;; create shadow copies +MOVE_NEXT_FLAG: ;; + MOV BX,KB_FLAG_PTRS[SI] ;; pointer to next flag + MOV AL,ES:[BX] ;; flag in AL + MOV KB_SHADOW_FLAGS[DI],AL ;; save it in the shadow table + INC DI ;; + INC SI ;; + INC SI ;; + LOOP MOVE_NEXT_FLAG ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Interpret State Logic Commands +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +PROCESS_STATES: ;; + MOV OPTION_BYTE,0 ;; clear options + MOV SI,SD.LOGIC_PTR ;; + LEA SI,[SI].SL_LOGIC_CMDS ;; +NEXT_COMMAND: ;; + MOV BL,[SI] ;; command byte in BL + SHR BL,1 ;; + SHR BL,1 ;; + SHR BL,1 ;; + SHR BL,1 ;; ISOLATE COMMAND CODE + SHL BL,1 ;; command code * 2 + JMP CMD_JUMP_TABLE[BX] ;; go process command +UNKNOWN_COMMAND: ;; + JMP FATAL_ERROR ;; bad news + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IFKBD_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE IFKBD_DONE ;; N..don't process + + MOV AX,[SI+1] ;; Keyboard Type Flag + ;; + TEST SD.KEYB_TYPE,AX ;; Q..are we the right system? + JNZ IFKBD_TEST_OK ;; Y.. +IFKBD_TEST_FAILED: ;; + MOV TAKE_ELSE,YES ;; test failed - take ELSE + JMP SHORT IFKBD_DONE ;; +IFKBD_TEST_OK: ;; + INC PROCESS_LEVEL ;; process commands within IF + MOV TAKE_ELSE,NO ;; +IFKBD_DONE: ;; + INC NEST_LEVEL ;; IFKBD increments nest level + INC SI ;; bump past IFKBD + INC SI ;; + INC SI ;; + JMP NEXT_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +PUT_ERROR_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE PUT_ERROR_DONE ;; N..don't process + MOV DI,SD.ACTIVE_XLAT_PTR ;; pointer to active Xlat Section + MOV AL,[SI+1] ;; state id in AL + CALL PUT_ERROR ;; check active section + JC PUT_ERROR_DONE ;; carry set if translation found + MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section + MOV AL,[SI+1] ;; state id for XLATT in AL + CALL PUT_ERROR ;; + ;; +PUT_ERROR_DONE: ;; + INC SI ;; + INC SI ;; + JMP NEXT_COMMAND ;; + ;; +PUT_ERROR PROC ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Search for a state whose ID matches the ID +;; on the PUT_ERROR command +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + CLC ;; + LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section +PE_NEXT_STATE: ;; + CMP [DI].XS_STATE_LEN,0 ;; Q..out of states? + JE PE_EXIT ;; Y..exit + CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state? + JE PE_STATE_MATCH ;; + ADD DI,[DI].XS_STATE_LEN ;; N..check next state + JMP SHORT PE_NEXT_STATE ;; + ;; +PE_STATE_MATCH: ;; + MOV AX,[DI].XS_ERROR_CHAR ;; get error char in AX + CALL BUFFER_FILL ;; + STC ;; indicate that we found the state +PE_EXIT: ;; + RET ;; + ;; +PUT_ERROR ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +GOTO_BIOS: ;; + CLC ;; clear carry flag indicating + POP BX ;; we should continue INT 9 + POP AX ;; processing + POP ES ;; + POP DS ;; + RET ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +IFF_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE IFF_DONE ;; N..don't process IFF + MOV BL,[SI] ;; command byte + AND BL,FLAG_ID_BITS ;; isolate flag id + XOR BH,BH ;; + MOV AL,FLAGS_TO_TEST[BX] ;; flag in AL + TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT test? + JNZ ITS_A_NOT ;; + TEST AL,[SI]+1 ;; Y..check for bit set + JNZ IFF_MATCH ;; + JZ IFF_NO_MATCH ;; +ITS_A_NOT: ;; + TEST AL,[SI]+1 ;; Y..check for bit clear + JZ IFF_MATCH ;; +IFF_NO_MATCH: ;; + MOV TAKE_ELSE,YES ;; flag test failed - take ELSE + JMP SHORT IFF_DONE ;; +IFF_MATCH: ;; + INC PROCESS_LEVEL ;; process commands within IF + MOV TAKE_ELSE,NO ;; + ;; +IFF_DONE: ;; + INC NEST_LEVEL ;; IFF increments nest level + INC SI ;; bump past IFF + INC SI ;; + JMP NEXT_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +ELSEF_PROC: ;; + MOV AL,PROCESS_LEVEL ;; + CMP AL,NEST_LEVEL ;; Q..nest level = process level? + JNE CHECK_TAKE_ELSEF ;; N..check for take_else + DEC PROCESS_LEVEL ;; Y..we just finished the "IF" block + JMP ELSEF_DONE ;; so we are finished with IFF/ELSEF +CHECK_TAKE_ELSEF: ;; + CMP TAKE_ELSE,YES ;; Q..are we scanning for ELSE? + JNE ELSEF_DONE ;; N..done + DEC NEST_LEVEL ;; ELSEF itself is back a level + CMP AL,NEST_LEVEL ;; Q..nest level = process level? + JNE NOT_THIS_ELSEF ;; N..this else is not the one + INC PROCESS_LEVEL ;; Y..process ELSEF block + MOV TAKE_ELSE,NO ;; reset +NOT_THIS_ELSEF: ;; + INC NEST_LEVEL ;; stuff within the ELSEF is up a level + ;; +ELSEF_DONE: ;; + INC SI ;; bump past ELSEF + JMP NEXT_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ENDIFF_PROC: ;; + MOV AL,PROCESS_LEVEL ;; + CMP AL,NEST_LEVEL ;; Q..nest level = process level? + JNE ENDIFF_DONE ;; N..don't adjust process level + DEC PROCESS_LEVEL ;; Y..we just finished the IF/ELSE +ENDIFF_DONE: ;; + DEC NEST_LEVEL ;; ENDIF decrements nest level + INC SI ;; bump past ENDIF + JMP NEXT_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Translations may be in the Common or Specific +;; Sections. Search the Specific section first +;; then the common section. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +XLATT_PROC: ;; + MOV AL,PROCESS_LEVEL ;; + CMP AL,NEST_LEVEL ;; Q..nest level = process level? + JNE XLATT_DONE ;; N..next command + MOV DI,SD.ACTIVE_XLAT_PTR ;; pointer to active Xlat Section + MOV AL,[SI+1] ;; state id for XLATT in AL + CALL TRANSLATE ;; check active section + JC XLATT_FOUND ;; carry set if translation found + MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section + MOV AL,[SI+1] ;; state id for XLATT in AL + CALL TRANSLATE ;; + JNC XLATT_DONE ;; +XLATT_FOUND: ;; + OR EXT_KB_FLAG,SCAN_MATCH ;; set flag indicating scan matched + TEST OPTION_BYTE,EXIT_IF_FOUND ;; Q..exit + JZ XLATT_DONE ;; + JMP EXIT ;; Y..BYE + ;; +XLATT_DONE: ;; + INC SI ;; + INC SI ;; + JMP NEXT_COMMAND ;; + ;; +TRANSLATE PROC ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Search for a state whose ID matches the ID +;; on the XLATT command +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + CLC ;; + LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section +TP_NEXT_STATE: ;; + CMP [DI].XS_STATE_LEN,0 ;; Q..out of states? + JE TP_EXIT ;; Y..exit + CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state? + JE TP_STATE_MATCH ;; + ADD DI,[DI].XS_STATE_LEN ;; N..check next state + JMP SHORT TP_NEXT_STATE ;; + ;; +TP_STATE_MATCH: ;; + AND EXT_KB_FLAG,NOT SCAN_MATCH ;; reset flag before search + PUSH SI ;; save pointer to next command + LEA SI,[DI].XS_FIRST_TAB ;; point to first xlat table + MOV XLAT_TAB_PTR,SI ;; start of XLAT tables + MOV AL,SCAN_CODE ;; restore incoming scan code + JMP SHORT NEXT_XLAT_TAB ;; +TP_DONE: ;; return here from XLAT + POP SI ;; +TP_EXIT: ;; + RET ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check xlate tables for matching scan code +;; The xlate table can be in one of two forms: +;; Type 1 = Table contains buffer entries only. +;; Scan code is used as an index into xlat table +;; Type 2 = Table contains pairs of SCAN/BUFFER_ENTRY. +;; Table must be searched for matching scan. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +NEXT_XLAT_TAB: ;; + MOV SI,XLAT_TAB_PTR ;; pointer to xlat tables + CMP [SI].XLAT_TAB_SIZE,0 ;; Q..any more xlat tables? + JNE PROCESS_XLAT_TAB ;; Y..check um + JMP TP_DONE ;; N..done +PROCESS_XLAT_TAB: ;; + MOV DL,[SI].XLAT_OPTIONS ;; save translate options IN DL + MOV BX,[SI].XLAT_TAB_SIZE ;; Y..calc pointer to next xlat tab + ADD BX,SI ;; + MOV XLAT_TAB_PTR,BX ;; pointer to next xlat tab + TEST DL,TYPE_2_TAB ;; Q..is this a type 2 table? + JZ TYPE_1_LOOKUP ;; N..go do table lookup +TYPE_2_SEARCH: ;; Y..search table + XOR CH,CH ;; + MOV CL,[SI].XLAT_NUM ;; number of xlat entries + MOV BX,DEFAULT_TAB_2_ENT_SZ ;; default entry size + TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..are buffer entries ASCII only? + JZ NEXT_TAB_2_ENTRY ;; N..continue + MOV BX,ASC_ONLY_TAB_2_ENT_SZ ;; Y..set size in BX +NEXT_TAB_2_ENTRY: ;; entry size is in BX + CMP CX,0 ;; Q..last entry? + JE NEXT_XLAT_TAB ;; y..go to next table + CMP AL,[SI].XLAT_SCAN ;; Q..scan match? + JE FOUND_TAB_2_ENTRY ;; Y..go create buffer entry + ADD SI,BX ;; point to next entry + LOOP NEXT_TAB_2_ENTRY ;; + JMP SHORT NEXT_XLAT_TAB ;; +FOUND_TAB_2_ENTRY: ;; Q..set scan code to 0? + MOV AH,AL ;; default scan code in AH + MOV AL,[SI].XLAT_2_BUF_ENTRY ;; ASCII code from table in AL + TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..are buffer entries ASCII only? + JNZ BUFFER_ENTRY_READY ;; Y..buffer entry is ready + MOV AH,[SI].XLAT_2_BUF_ENTRY+1 ;; N..scan code from table as well + JMP SHORT BUFFER_ENTRY_READY ;; go put entry in buffer + ;; +TYPE_1_LOOKUP: ;; + CMP AL,[SI].XLAT_SCAN_LO ;; Q..is scan in range of this table? + JB NEXT_XLAT_TAB ;; N..next table + CMP AL,[SI].XLAT_SCAN_HI ;; Q..is scan in range of this table? + JA NEXT_XLAT_TAB ;; N..next table + SUB AL,[SI].XLAT_SCAN_LO ;; convert scan code to xlat index + TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..ASCII only in xlat ? + JZ TWO_BYTE_LOOKUP ;; N..go do 2-byte lookup + LEA BX,[SI].XLAT_1_BUF_ENTRY ;; Y..do 1-byte lookup + XLAT [SI].XLAT_1_BUF_ENTRY ;; ASCII code in AL + MOV AH,SCAN_CODE ;; SCAN in AH + JMP SHORT BUFFER_ENTRY_READY ;; go put entry in buffer +TWO_BYTE_LOOKUP: ;; + MOV BL,2 ;; multiply scan index + MUL BL ;; by two + MOV BX,AX ;; real index in BX + MOV AX,WORD PTR [SI].XLAT_1_BUF_ENTRY[BX] ;; get 2-byte buffer entry + ;; AL=ASCII AH=SCAN +BUFFER_ENTRY_READY: ;; + TEST DL,ZERO_SCAN ;; Q..set scan part to zero? + JZ NO_ZERO_SCAN ;; N.. + XOR AH,AH ;; scan = 0 +NO_ZERO_SCAN: ;; + CALL BUFFER_FILL ;; go put entry in buffer + STC ;; indicate translation found + JMP TP_DONE ;; + ;; +TRANSLATE ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +OPTION_PROC: ;; + MOV AL,PROCESS_LEVEL ;; + CMP AL,NEST_LEVEL ;; Q..nest level = process level? + JNE DONE_OPTION ;; N..done + MOV AL,[SI]+1 ;; mask in AL + TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT? + JNZ AND_MASK ;; + OR OPTION_BYTE,AL ;; N..OR in the mask bits + JMP DONE_OPTION ;; +AND_MASK: ;; + NOT AL ;; + AND OPTION_BYTE,AL ;; Y..AND out the mask bits +DONE_OPTION: ;; + INC SI ;; + INC SI ;; + JMP NEXT_COMMAND ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +RESET_NLS_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE RN_DONE ;; N..don't process + MOV NLS_FLAG_1,0 ;; + MOV NLS_FLAG_2,0 ;; +RN_DONE: ;; + INC SI ;; + JMP NEXT_COMMAND ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BEEP_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE BP_DONE ;; N..don't process + MOV BEEP_PENDING,YES ;; set beep pending flag. the beep + ;; will be done just before iret +BP_DONE: ;; + INC SI ;; + JMP NEXT_COMMAND ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +GOTO_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE GOTO_DONE ;; N..don't process + MOV BL,[SI] ;; command byte in BL + AND BL,NOT COMMAND_BITS ;; remove command code + OR BL,BL ;; Q..goto label? + JZ GOTO_LABEL ;; Y..go jump + CMP BL,EXIT_INT_9_FLAG ;; Q..SPECIAL - Exit Int 9? + JNE NOT_EXIT_INT_9 ;; N.. + JMP EXIT ;; Y..bye bye +NOT_EXIT_INT_9: ;; + CMP BL,EXIT_STATE_LOGIC_FLAG ;; Q..SPECIAL - Exit State Logic? + JNE NOT_EXIT_S_L ;; N.. + JMP GOTO_BIOS ;; Y..goto bios +NOT_EXIT_S_L: ;; + JMP FATAL_ERROR ;; garbage in that command +GOTO_LABEL: ;; + ADD SI,[SI]+1 ;; bump by relative offset + MOV PROCESS_LEVEL,0 ;; reset process and nest level + MOV NEST_LEVEL,0 ;; +GOTO_DONE: ;; + ADD SI,3 ;; bump to next command + JMP NEXT_COMMAND ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +ANDF_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE ANDF_DONE ;; N..don't process ANDF + MOV BL,[SI] ;; command byte + AND BL,FLAG_ID_BITS ;; isolate flag id + XOR BH,BH ;; + MOV AL,FLAGS_TO_TEST[BX] ;; flag in AL + TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT test? + JNZ ANDF_NOT ;; + TEST AL,[SI]+1 ;; Y..check for bit set + JNZ ANDF_DONE ;; if set then remain in IFF + JZ ANDF_NO_MATCH ;; +ANDF_NOT: ;; + TEST AL,[SI]+1 ;; Y..check for bit clear + JZ ANDF_DONE ;; if clear then remain in IFF +ANDF_NO_MATCH: ;; + MOV TAKE_ELSE,YES ;; flag test failed - take ELSE + DEC PROCESS_LEVEL ;; IFF would have inc'd - so dec +ANDF_DONE: ;; + INC SI ;; bump past ANDF + INC SI ;; + JMP NEXT_COMMAND ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; SET_FLAG Command. +;; Flag Table must be in the Common Section +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SET_FLAG_PROC: ;; + MOV AL,NEST_LEVEL ;; + CMP AL,PROCESS_LEVEL ;; Q..nest level = process level? + JNE SF_DONE ;; N..don't process + ;; + MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section + MOV AL,[SI+1] ;; state id in AL + LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section +SF_NEXT_STATE: ;; + CMP [DI].XS_STATE_LEN,0 ;; Q..out of states? + JE SF_DONE ;; Y..exit + CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state? + JE SF_STATE_MATCH ;; + ADD DI,[DI].XS_STATE_LEN ;; N..check next state + JMP SHORT SF_NEXT_STATE ;; + ;; +SF_STATE_MATCH: ;; + AND EXT_KB_FLAG,NOT SCAN_MATCH ;; reset flag before search + PUSH SI ;; save pointer to next command + LEA SI,[DI].XS_FIRST_TAB ;; point to table + MOV AL,SCAN_CODE ;; restore incoming scan code + MOV CX,[SI] ;; number of entries + CMP CX,0 ;; Q..any entries? + JE SF_RESTORE ;; N..done + INC SI ;; Y..Bump to first entry + INC SI ;; +NEXT_SF_ENTRY: ;; + CMP AL,[SI] ;; Q..scan match? + JE FOUND_SF_ENTRY ;; Y..go set flag + ADD SI,3 ;; point to next entry + LOOP NEXT_SF_ENTRY ;; + JMP SHORT SF_RESTORE ;; no match found +FOUND_SF_ENTRY: ;; + MOV NLS_FLAG_1,0 ;; clear all NLS bits + MOV NLS_FLAG_2,0 ;; + MOV BL,[SI]+1 ;; flag id in BX + XOR BH,BH ;; + MOV AL,[SI]+2 ;; mask in AL + OR FLAGS_TO_TEST[BX],AL ;; set the bit + OR EXT_KB_FLAG,SCAN_MATCH ;; set flag indicating scan matched + TEST OPTION_BYTE,EXIT_IF_FOUND ;; Q..exit + JZ SF_RESTORE ;; + POP SI ;; + JMP EXIT ;; +SF_RESTORE: ;; + POP SI ;; +SF_DONE: ;; + INC SI ;; bump past command + INC SI ;; + JMP NEXT_COMMAND ;; + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Fatal Error routine. Come here when +;; we have a critical error such as an +;; invalid State Logic Command. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FATAL_ERROR: ;; + JMP SHORT EXIT ;; end the int 9 processing + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Exit point. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +EXIT: ;; + MOV BUSY_FLAG,NO ;; + STC ;; indicate we should end INT 9 + POP BX ;; processing + POP AX ;; + POP ES ;; + POP DS ;; + RET ;; + ;; +KEYB_STATE_PROCESSOR ENDP ;; + ;; + ;; + +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/KEYBI9.INC b/v4.0/src/CMD/KEYB/KEYBI9.INC new file mode 100644 index 0000000..0541cb9 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI9.INC @@ -0,0 +1,29 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Micrsoft +;; +;; File Name: KEYBI9.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; External declarations and equates for procedures in file +;; KEYBI9.ASM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN KEYB_STATE_PROCESSOR:NEAR + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBI9C.ASM b/v4.0/src/CMD/KEYB/KEYBI9C.ASM new file mode 100644 index 0000000..9cf8f5d --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI9C.ASM @@ -0,0 +1,1894 @@ + + PAGE ,132 + TITLE DOS KEYB Command - Interrupt 9 (US support) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI9C.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Interrupt 9 mainline. +;; This routine handles all US keyboard support for the following +;; system units: PCjr, PC, PCXT, PCAT, PALACE, ROUNDUP, PC Convertible +;; KEYB_STATE_PROCESSOR is called for non-US keyboard support. +;; +;; +;; Documentation Reference: +;; ------------------------ +;; PC DOS 3.3 Detailed Design Document - May 1986 +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; KEYB_INT_9 - Interrupt 9 +;; +;; External Procedure References: +;; ------------------------------ +;; FROM FILE KEYBI9.ASM: +;; KEYB_STATE_PROCESSOR - Non US keyboard support. +;; +;; Linkage Information: Refer to file KEYB.ASM +;; -------------------- +;; +;; Change History: +;; --------------- +;; ;AN001; - DCR 478 - KEYBOARD INT SPLICING NickS +;; ;AN002; - PTM 3090 ENABLING RIGHT CTL FOR RE-BOOTING +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE DSEG.inc ;; System data segments + INCLUDE POSTEQU.inc ;; System equates + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBI2F.INC ;; + INCLUDE KEYBI9.INC ;; + INCLUDE KEYBCPSD.INC ;; + INCLUDE KEYBCMD.INC ;; + ;; + PUBLIC KEYB_INT_9 ;; + PUBLIC K8 ;; CTRL case tables + PUBLIC BUFFER_FILL ;; + PUBLIC COUNTRY_FLAG ;; + PUBLIC BEEP_PENDING ;; + PUBLIC SCAN_CODE ;; + PUBLIC ERROR_BEEP ;; + PUBLIC TEMP_HEAD ;; + PUBLIC TEMP_TAIL ;; + PUBLIC BUSY_TFLAG ;; + PUBLIC MYBUFF ;; + PUBLIC ENABLE_FL ;; + PUBLIC NEW_BUFF_CTR ;; + + +ROM_SEG EQU 0F000H ;; BIOS ROM SEGMENT +PC1DATE_ID EQU 03138H ;; YEAR ROM WAS RELEASED IN ASCII +SYSROM_DATE EQU 0FFFBH ;; OFFSET OF ROM YEAR DIGIT + ;; +DIAGS SEGMENT AT 0FFFFH ;; + ORG 0 ;; +RESET LABEL FAR ;; +DIAGS ENDS ;; + ;; + ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ASSUME CS:CODE,DS:DATA ;; + ;; + +;CNS*** + END_OF_BUFF EQU 16 ;AN000;END OF TEMP BUFF VALUE + ACTIVE_ON EQU -1 ;AN000; + ACTIVE_OFF EQU 0 ;AN000; + TEMP_HEAD DW 0 ;AN000; + TEMP_TAIL DW 0 ;AN000; + BUSY_TFLAG DB ACTIVE_OFF ;AN000;FLAG TO CHECK BUFFER ACTIVITY + MYBUFF DB 16 DUP(0) ;AN000; + ENABLE_FL DB 0 ;NEW BUFFER TO BE USED + NEW_BUFF_CTR DB 0 ;ON THE FRONT END OF THE +;CNS*** + + +BEEP_PENDING DB 0 ;; +BUFFER_ENTRY_OK DB 0 ;; +SCAN_CODE DB 0 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; TABLE OF SHIFT KEYS AND MASK VALUES +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;------ KEY_TABLE ;; +K6 LABEL BYTE ;; + DB INS_KEY ;; INSERT KEY + DB CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY + DB LEFT_KEY,RIGHT_KEY ;; +K6L EQU $-K6 ;; + ;; +;------ MASK_TABLE ;; +K7 LABEL BYTE ;; + DB INS_SHIFT ;; INSERT MODE SHIFT + DB CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT + DB LEFT_SHIFT,RIGHT_SHIFT ;; + ;; +;---------- TABLES FOR ALT CASE -----;; +;------ ALT-INPUT-TABLE ;; +K30 LABEL BYTE ;; + DB 82,79,80,81,75 ;; + DB 76,77,71,72,73 ;; 10 NUMBERS ON KEYPAD +;------ SUPER-SHIFT-TABLE ;; + DB 16,17,18,19,20,21 ;; A-Z TYPEWRITER CHARS + DB 22,23,24,25,30,31 ;; + DB 32,33,34,35,36,37 ;; + DB 38 ;; + DB 44,45,46,47,48,49 ;; + DB 50 ;; +K30_LEN EQU $-K30-10 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; K8 is overlaid by K8_RPL (from module KEYB_COMMAND) +;; if extended INT 16 support is available +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +K8 LABEL BYTE ;;-------- CHARACTERS --------- + DB 27,-1,00,-1,-1,-1 ;; Esc, 1, 2, 3, 4, 5 + DB 30,-1,-1,-1,-1,31 ;; 6, 7, 8, 9, 0, - + DB -1,127,-1,17,23,5 ;; =, Bksp, Tab, Q, W, E + DB 18,20,25,21,09,15 ;; R, T, Y, U, I, O + DB 16,27,29,10,-1,01 ;; P, [, ], Enter, Ctrl, A + DB 19,04,06,07,08,10 ;; S, D, F, G, H, J + DB 11,12,-1,-1,-1,-1 ;; K, L, ;, ', `, LShift + DB 28,26,24,03,22,02 ;; \, Z, X, C, V, B + DB 14,13,-1,-1,-1,-1 ;; N, M, ,, ., /, RShift + DB '*',-1,' ',-1 ;; *, Alt, Space, CL + ;;--------- FUNCTIONS --------- + DB 94,95,96,97,98,99 ;; F1 - F6 + DB 100,101,102,103,-1,-1 ;; F7 - F10, NL, SL + DB 119,-1,132,-1,115,-1 ;; Home, Up, PgUp, -, Left, Pad5 + DB 116,-1,117,-1,118,-1 ;; Right, +, End, Down, PgDn, Ins + DB -1,-1,-1,-1,137,138 ;; Del, SysReq, Undef, WT, F11, F12 +PAGE ;; +;----- TABLES FOR LOWER CASE (USA) --;; + ;; +K10 LABEL BYTE ;; + DB 27,'12345' ;; + DB '67890-' ;; + DB '=',08,09,'qwe' ;; + DB 'rtyuio' ;; + DB 'p[]',0DH,-1,'a' ;; LETTERS, Return, Ctrl + DB 'sdfghj' ;; + DB "kl;'`",-1 ;; LETTERS, L Shift + DB '\zxcvb' ;; + DB 'nm,./' ;; + DB -1,'*',-1,' \' ;; R Shift, *, Alt, Sp, CL (REALLY WT KEY) + ;; +;------ LC TABLE SCAN ;; + DB 59,60,61,62,63 ;; BASE STATE OF F1 - F10 + DB 64,65,66,67,68 ;; + DB -1,-1 ;; NL, SL + ;; +;------ KEYPAD TABLE ;; +K15 LABEL BYTE ;; + DB 71,72,73,-1,75,-1 ;; BASE STATE OF KEYPAD KEYS + DB 77,-1,79,80,81,82 ;; + DB 83 ;; + DB -1,-1,'\',133,134 ;; SysRq, Undef, WT, F11, F12 + ;; +;------- TABLES FOR UPPER CASE (USA) ;; + ;; +K11 LABEL BYTE ;; + DB 27,'!@#$%' ;; + DB '^&*()_' ;; + DB '+',08,00,'QWE' ;; + DB 'RTYUIO' ;; + DB 'P{}',0DH,-1,'A' ;; LETTERS, Return, Ctrl + DB 'SDFGHJ' ;; + DB 'KL:"~',-1 ;; LETTERS, L Shift + DB '|ZXCVB' ;; + DB 'NM<>?' ;; + DB -1,'*',-1,' |' ;; R Shift, *, Alt, Sp, CL (REALLY WT KEY) + ;; +;------ UC TABLE SCAN ;; +K12 LABEL BYTE ;; + DB 84,85,86,87,88 ;; SHIFTED STATE OF F1 - F10 + DB 89,90,91,92,93 ;; + DB -1,-1 ;; NL, SL + ;; +;------ NUM STATE TABLE ;; +K14 LABEL BYTE ;; + DB '789-456+1230.' ;; NUMLOCK STATE OF KEYPAD KEYS + DB -1,-1,'|',135,136 ;; SysRq, Undef, WT, F11, F12 + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: KEYB_INT_9 +;; +;; Description: +;; Entry point for interrupt 9 processing. +;; +;; Input Registers: +;; None +;; +;; Output Registers: +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYB_INT_9 PROC NEAR ;; + JMP KB_INT_1 ; THIS JUMP AND ENSUING BYTE MUST BE HERE TO BE + COUNTRY_FLAG DB -1 ; COMPATIBLE WITH APL. APL WILL FORCE THIS + ; BYTE TO BE ZERO, ONLY BECAUSE IT'S 3 BYTES +KB_INT_1: ; AWAY FROM WHERE THE INT9 VECTOR POINTS + +; PUSH DS ;ICE +; push bx ;ICE +; push ax ;ICE +; mov bx,0140H ;ICE +; xor ax,ax ;ICE +; mov ds,ax ;ICE +; mov ax,word ptr ds:[bx] ;ICE +; mov word ptr ds:[bx],ax ;ICE +; POP ax ;ICE +; pop bx ;ICE +; pop ds ;ICE + + PUSH BP + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS + PUSH ES + STI ; ENABLE INTERRUPTS + CLD ; FORWARD DIRECTION + + MOV BX,DATA ; SET UP ADDRESSING + MOV DS,BX ;; DS POINTS AT THE + MOV CS:BEEP_PENDING,NO ;; ROM DATA AREA + MOV CS:BUFFER_ENTRY_OK,NO ;; INITIALIZE ALL FLAGS +;***CNS ;; FOR LOADING AND UNLOADING THE + CMP CS:BUSY_TFLAG,ACTIVE_ON + JE NO_INIT + + MOV DI,OFFSET CS:MYBUFF + MOV CS:TEMP_HEAD,DI + MOV CS:TEMP_TAIL,DI + MOV CS:ENABLE_FL,0 +; MOV CS:NEW_BUFF_CTR,0 ;;CLEAR OUT NEW BUFFER CTR +;***CNS + ;; BUFFER +NO_INIT: +;------- TEST SYSTEM TYPE ;CHECK TO SEE IF THE SYSTEM IS + ;NEW ****** + + + + TEST CS:SD.SYSTEM_FLAG,PC_AT+PC_386 ; IF THE SYSTEM WE'RE RUNNING ON IS A + JNZ KB_INT_00 ; PC3, THEN DO PC3 CODE + +;------ PC1, XT, HOME COMPUTER POST CODE + + TEST CS:SD.SYSTEM_FLAG,PC_JR ;; Q..PCjr? + JZ READ_CHAR_PORT ;; N..go read port + MOV BL,CS:SD.JR_KB_FLAG ;; Its a JR so incorporate flag bits + OR KB_FLAG,BL ;; from INT 48 preprocessor + MOV CS:SD.JR_KB_FLAG,0 ;; Clear JR KB_Flag + JMP UP1MORE;UP1 ;; Skip to key processing +EVEN ;; +READ_CHAR_PORT: ;; + IN AL,KB_DATA ;; READ IN THE CHARACTER + ;; FOR PC, XT, P12: RESET THE KEYBOARD + TEST CS:SD.SYSTEM_FLAG,PC_XT+PC_LAP + JZ SYSTEM_HOOK ;; + PUSH AX ; SAVE IT + IN AL,KB_CTL ; GET THE CONTROL PORT + MOV AH,AL ; SAVE VALUE + OR AL,80H ; RESET BIT FOR KEYBOARD + OUT KB_CTL,AL + XCHG AH,AL ; GET BACK ORIGINAL CONTROL + OUT KB_CTL,AL ; KB HAS BEEN RESET + POP AX ; GET SCAN CODE BACK RWV 11-06-85 + +;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INTERRUPT LEVEL 9H) + +SYSTEM_HOOK: ;; + MOV AH,04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION + STC ; SET CY= 1 (IN CASE OF IRET) + INT 15H ; CASSETTE CALL (AL)= KEY SCAN CODE + ; RETURNS CY= 1 FOR INVALID FUNCTION + STI ; MAKE SURE INT'S STAY ENABLED RWV 11-11-85 + JC UP1MORE ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) + JMP PREP_EXIT ; EXIT IF SYSTEM HANDLED SCAN CODE + ; EXIT HANDLES HARDWARE EOI AND ENABLE + +UP1MORE: + + + CALL DUMBJMP + JMP EXIT_CHK + + + +;------ PCAT POST CODE + +;------ WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED +KB_INT_00: + MOV AL,DIS_KBD ; DISABLE THE KEYBOARD COMMAND + CALL SHIP_IT ; EXECUTE DISABLE + CLI ; DISABLE INTERRUPTS +; SUB CX,CX ; SET MAXIMUM TIMEOUT +;KB_INT_01: +; IN AL,STATUS_PORT ; READ ADAPTER STATUS +; TEST AL,INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT +; LOOPNZ KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED + ;; + CALL WAIT_ON_STATUS_PORT ;; + +;----- READ CHARACTER FROM KEYBOARD INTERFACE + + + + IN AL,PORT_A ;;AN000;GET SCAN CODE VALUE FROM PORT 60H + +; PUSH DS ;ICE +; push bx ;ICE +; push ax ;ICE +; mov bx,0140H ;ICE +; xor ax,ax ;ICE +; mov ds,ax ;ICE +; mov ax,word ptr ds:[bx] ;ICE +; mov word ptr ds:[bx],ax ;ICE +; POP ax ;ICE +; pop bx ;ICE +; pop ds ;ICE + +;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INTERRUPT LEVEL 9H) + + MOV AH,04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION + STC ; SET CY= 1 (IN CASE OF IRET) + INT 15H ; CASSETTE CALL (AL)= KEY SCAN CODE + ; RETURNS CY= 1 FOR INVALID FUNCTION + JC LOAD_TBUFF ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) + JMP PREP_EXIT ; EXIT IF SYSTEM HANDLED SCAN CODE + ; EXIT HANDLES HARDWARE EOI AND ENABLE + + + +LOAD_TBUFF: + + CMP CS:NEW_BUFF_CTR,END_OF_BUFF+1 ;;AN000;CHECK TO SEE IF THE SECONDARY BUFFER IS FULL + JB LOAD_CHAR + +;***CNS + PUSH DI ;; + PUSH AX ;; + CALL CLEAR_BUFFER ;;CLEAR OUT NEW BUFFER + POP AX ;; + POP DI ;; + MOV CS:TEMP_HEAD,DI ;;AN000;RESET POINTER BACK TO THE BEGINNING + MOV CS:TEMP_TAIL,DI ;;AN000;RESET POINTER BACK TO THE BEGINNING + MOV CS:BUSY_TFLAG,ACTIVE_OFF ;;AN000; + MOV CS:NEW_BUFF_CTR,0 ;;CLEAR OUT NEW BUFFER CTR +;***CNS + +LOAD_CHAR: + + MOV DI,CS:TEMP_TAIL ;;AN003;MOVE PTR TO LATEST INSERT POSITION + MOV BYTE PTR CS:[DI],AL ;;AN000;LOAD CHARACTER INTO MY BUFFER + INC CS:NEW_BUFF_CTR ;;AN000; + INC DI ;;AN000;TAIL POINTER NEEDS TO BE ADVANCED + MOV CS:TEMP_TAIL,DI ;;AN000;ADD ONE TO TAIL POINTER + ;;AN000;GET ANOTHER CHAR. IF AVAILABLE + TEST CS:BUSY_TFLAG,ACTIVE_ON ;;AN000;CHECK TO SEE IF WE ARE IN A BUSY STATE + JZ KEEP_BUSY ;;AN000;IF YES ROUTINE TO UNLOAD TEMP BUFFER + CLI ; TURN OFF INTERRUPTS +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ; END OF INTERRUPT COMMAND + OUT 020H,AL ; SEND COMMAND TO INTERRUPT CONTROL PORT +;***CNS + JMP SHORT $+2 +;***CNS +; PUSH DS ;ICE +; push bx ;ICE +; push ax ;ICE +; mov bx,0140H ;ICE +; xor ax,ax ;ICE +; mov ds,ax ;ICE +; mov ax,word ptr ds:[bx] ;ICE +; mov word ptr ds:[bx],ax ;ICE +; POP ax ;ICE +; pop bx ;ICE +; pop ds ;ICE + ;;AN000;OTHERWISE FREE UP THE PROCESSOR + MOV CS:BUSY_TFLAG,ACTIVE_OFF ;;AN000; + JMP KEY_EXIT ; KEY_EXIT + +EXIT_CHK: + + CMP CS:ENABLE_FL,1 + JE ENABLE_CHK + + CMP CS:ENABLE_FL,2 + JE KEY_EXIT + + CMP CS:ENABLE_FL,-1 + JE CHK_BEEPER + + +PREP_EXIT: + + AND KB_FLAG_3,NOT LC_E0+LC_E1 ; RESET LAST CHAR H.C. FLAG RWV 7-23-85 + + +CHK_BEEPER: ; INTERRUPT-RETURN + + CMP CS:BEEP_PENDING,YES ;; Q..SHOULD WE BEEP? + JNE JR_EXIT ;; + MOV CS:BEEP_PENDING,NO ;; + CALL ERROR_BEEP ;; + +JR_EXIT: ;; + TEST CS:SD.SYSTEM_FLAG,PC_JR ;; + JNZ KEY_EXIT ;K27A ;; + CLI ; TURN OFF INTERRUPTS + MOV AL,EOI ; END OF INTERRUPT COMMAND + OUT 020H,AL ; SEND COMMAND TO INTERRUPT CONTROL PORT + +ENABLE_CHK: ; INTERRUPT-RETURN-NO-EOI + + MOV AL,ENA_KBD ; ENSURE KEYBOARD IS ENABLED (AT ONLY) + CALL SHIP_IT ; EXECUTE ENABLE + CMP CS:BUFFER_ENTRY_OK,YES ;; ENTRY IN BUFFER? + JNE GOOD_ENTRY ;K271 ;; NO, SKIP POST + MOV AX,09102H ; MOVE IN POST CODE & TYPE + INT 15H ; PERFORM OTHER FUNCTION + +GOOD_ENTRY: ;; + +KEY_EXIT: + + + CLI ; DISABLE INTERRUPTS + POP ES ; RESTORE REGISTERS + POP DS ; * + POP DI ; * + POP SI ; * + POP DX ; * + POP CX ; * + POP BX ; * + POP AX ; * + POP BP + IRET ; RETURN, INTERRUPTS BACK ON WITH FLAG CHANGE + ;;AND RETURN INT OFF OF THE STACK + + + +KEEP_BUSY: + + CALL CLEAR_BUFFER ;;UNLOAD THE TEMPORARY BUFFER + +TBUFF_EMPTY: + JMP EXIT_CHK + +; RET + +;(*EQUIVALENT TO PREP_EXIT*) +;; Procedure: CLEAR_BUFFER +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; +CLEAR_BUFFER: ;; + ;; + ;; + MOV DI,CS:TEMP_HEAD ;;AN000;RESET POINTER BACK TO THE BEGINNING + MOV CS:BUSY_TFLAG,ACTIVE_ON ;;AN000; + ;; +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ;;AN000; END OF INTERRUPT COMMAND + OUT 020H,AL ;;AN000; SEND COMMAND TO INTERRUPT CONTROL PORT +;***CNS + JMP SHORT $+2 +;***CNS + ;; + ;; + ;;AN000; INTERRUPT-RETURN-NO-EOI +GET_KB: ;;AN000;AN000; + XOR BX,BX ;;AN000; + CLI ;;AN000;DO NOT PROCESS UNTIL UNLOADED + ;;AN000; + MOV AL,BYTE PTR CS:[DI] ;;AN000;TEMPORARY BUFFER + STI ;;AN000;ENABLE SO I CAN KEEP PROCESSING + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH ES + PUSH SI + PUSH DI ;;AN000;SAVE THE POINTER + PUSH CS:TEMP_TAIL + CALL OLD_METHOD ;;AN000;LOAD USING EXISTING METHOD + POP CS:TEMP_TAIL + POP DI ;;AN000;RESTORE THE POINTER + POP SI + POP ES + POP DS + POP DX + POP CX + POP BX + POP AX + +CHK_BUFF_EMPTY: + + INC DI ;;AN000;INCREMENT POINTER + CMP DI,CS:TEMP_TAIL ;;AN000;IS THE BUFFER EMPTY YET? + JE EMPTY_BUFF ;;AN000;YES - MARK INACTIVE & RETURN + ;;AN000; + ;;AN000; + ;;AN000; + JMP GET_KB ;;AN000;NO - GET ANOTHER CHARACTER + + + +EMPTY_BUFF: + + CLI ;;AN000;OTHERWISE DISABLE INTERRUPTS + MOV CS:BUSY_TFLAG,ACTIVE_OFF ;;AN000;LET SYSTEM KNOW NOT BUSY ANYMORE + MOV CS:NEW_BUFF_CTR,0 ;;CLEAR OUT NEW BUFFER CTR + + + + RET ;;AN000; + + +OLD_METHOD: + + +KB_INT_02: ; (AL)= SCAN CODE + STI ; ENABLE INTERRUPTS AGAIN + CMP AL,KB_RESEND ; IS THE INPUT A RESEND + JE KB_INT_4 ; GO IF RESEND + +;------ CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD + + CMP AL,KB_ACK ; IS THE INPUT AN ACKNOWLEDGE + JNZ KB_INT_2 ; GO IF NOT + +;------ A COMMAND TO THE KEYBOARD WAS ISSUED + + CLI ; DISABLE INTERRUPTS + OR KB_FLAG_2,KB_FA ; INDICATE ACK RECEIVED + RET +; JMP PREP_EXIT ; RETURN IF NOT (ACK RETURNED FOR DATA) + +;------ RESEND THE LAST BYTE + +KB_INT_4: + CLI ; DISABLE INTERRUPTS + OR KB_FLAG_2,KB_FE ; INDICATE RESEND RECEIVED + RET +; JMP PREP_EXIT ; RETURN IF NOT (ACK RETURNED FOR DATA) + + +;------ UPDATE MODE INDICATORS IF CHANGE IN STATE + +KB_INT_2: + PUSH AX ; SAVE DATA IN + CALL MAKE_LED ; GO GET MODE INDICATOR DATA BYTE + MOV BL,KB_FLAG_2 ; GET PREVIOUS BITS + XOR BL,AL ; SEE IF ANY DIFFERENT + AND BL,07H ; ISOLATE INDICATOR BITS + JZ UP0 ; IF NO CHANGE BYPASS UPDATE + CALL SND_LED ; GO TURN ON MODE INDICATORS + +;------ PROCESSING COMES BACK TOGETHER HERE + +UP0: POP AX ; RESTORE DATA IN +PAGE +;--------------------------------------------------------------------- +; START OF KEY PROCESSING - +;--------------------------------------------------------------------- + +UP1: MOV AH,AL ; SAVE SCAN CODE IN AH ALSO + MOV CS:SCAN_CODE,AL ;; SAVE SCAN CODE + +;------ TEST FOR OVERRUN SCAN CODE FROM KEYBOARD + + CMP AL,0FFH ; IS THIS AN OVERRUN CHAR? + JNZ K16 ; NO, TEST FOR SHIFT KEY + MOV CS:BEEP_PENDING,YES ;; + TEST CS:SD.SYSTEM_FLAG,PC_JR ;; ON JR WE HAVE TO CLEAR SOME FLAGS + JZ OVERRUN ;; + AND KB_FLAG,0F0H ;; CLEAR SHIFTS + AND KB_FLAG_1,0FH ;; + AND KB_FLAG_2,1FH ;; CLEAR FUNCTION STATES +OVERRUN: ;; + RET +; JMP PREP_EXIT ; BUFFER_FULL_BEEP + +K16: PUSH CS + POP ES ; ESTABLISH ADDRESS OF TABLES + MOV BH,KB_FLAG_3 ; LOAD FLAGS FOR TESTING RWV 10-08-85 + +;------ TEST TO SEE IF A READ_ID IS IN PROGRESS + + TEST BH,RD_ID+LC_AB ; ARE WE DOING A READ ID? RWV 10-08-85 + JZ NOT_ID ; CONTINUE IF NOT + JNS TST_ID_2 ; IS THE RD_ID FLAG ON? + CMP AL,ID_1 ; IS THIS THE 1ST ID CHARACTER? + JNE RST_RD_ID + OR KB_FLAG_3,LC_AB ; INDICATE 1ST ID WAS OK +RST_RD_ID: + AND KB_FLAG_3,NOT RD_ID ; RESET THE READ ID FLAG + JMP SHORT ID_EX ; AND EXIT RWV 8-02-85 + +TST_ID_2: + AND KB_FLAG_3,NOT LC_AB ; RESET FLAG + CMP AL,ID_2A ; IS THIS THE 2ND ID CHARACTER? + JE KX_BIT ; JUMP IF SO + CMP AL,ID_2 ; IS THIS THE 2ND ID CHARACTER? + JNE ID_EX ; LEAVE IF NOT + +;------ A READ ID SAID THAT IT WAS ENHANCED KEYBOARD + + TEST BH,SET_NUM_LK ; SHOULD WE SET NUM LOCK? RWV 10-08-85 + JZ KX_BIT ; EXIT IF NOT + OR KB_FLAG,NUM_STATE ; FORCE NUM LOCK ON + CALL SND_LED ; GO SET THE NUM LOCK INDICATOR +KX_BIT: OR KB_FLAG_3,KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND +ID_EX: ;JMP PREP_EXIT ; EXIT + RET +PAGE +NOT_ID: + CMP AL,MC_E0 ; IS THIS THE GENERAL MARKER CODE? RWV 7-19-85 + JNE TEST_E1 ; RWV 7-19-85 + OR KB_FLAG_3,LC_E0+KBX ; SET FLAG BIT, SET KBX, AND RWV 7-19-85 + JMP SHORT EXIT ; THROW AWAY THIS CODE RWV 7-19-85 + +TEST_E1: + CMP AL,MC_E1 ; IS THIS THE PAUSE KEY? RWV 7-19-85 + JNE NOT_HC ; RWV 7-19-85 + OR KB_FLAG_3,LC_E1+KBX ; SET FLAG, PAUSE KEY MARKER CODE RWV 7-19-85 +EXIT: +;***CNS + MOV CS:ENABLE_FL,-1 + RET;JMP CHK_BEEPER ; THROW AWAY THIS CODE RWV 7-19-85 +;***CNS +NOT_HC: + AND AL,07FH ; TURN OFF THE BREAK BIT RWV 7-28-85 + TEST BH,LC_E0 ; LAST CODE THE E0 MARKER CODE? RWV 10-08-85 + JZ NOT_LC_E0 ; JUMP IF NOT RWV + + MOV CX,2 ; LENGTH OF SEARCH RWV + MOV DI,OFFSET K6+6 ; IS THIS A SHIFT KEY? RWV + REPNE SCASB ; CHECK IT RWV + JNE K16A ; NO, CONTINUE KEY PROCESSING RWV + JMP SHORT K16B ; YES, THROW AWAY & RESET FLAG RWV + +NOT_LC_E0: + TEST BH,LC_E1 ; LAST CODE THE E1 MARKER CODE? RWV 10-08-85 + JZ T_SYS_KEY ; JUMP IF NOT RWV + + MOV CX,4 ; LENGTH OF SEARCH RWV + MOV DI,OFFSET K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? RWV + REPNE SCASB ; CHECK IT RWV + JE EXIT ; THROW AWAY IF SO RWV + + CMP AL,NUM_KEY ; IS IT THE PAUSE KEY? RWV + JNE K16B ; NO, THROW AWAY & RESET FLAG RWV + TEST AH,80H ; YES, IS IT THE BREAK OF THE KEY? RWV + JNZ K16B ; YES, THROW THIS AWAY, TOO RWV + TEST KB_FLAG_1,HOLD_STATE ; NO, ARE WE PAUSED ALREADY? PED 6-25-86 + JNZ K16B ; YES, THROW AWAY PED 6-25-86 + JMP K39P ; NO, THIS IS THE REAL PAUSE STATE RWV +PAGE +;------ TEST FOR SYSTEM KEY + +T_SYS_KEY: + CMP AL,SYS_KEY ; IS IT THE SYSTEM KEY? + JNE K16A ; CONTINUE IF NOT + +;;;;;; TEST cs:SD.SYSTEM_FLAG,PC_AT+PC_386 ; LET ALL SYSTEMS ISSUE INT15 RWV 8-02-85 +;;;;;; JZ K16A ; IGNORE SYSTEM KEY IF NOT PC3 + + TEST AH,080H ; CHECK IF THIS A BREAK CODE + JNZ K16C ; DON'T TOUCH SYSTEM INDICATOR IF TRUE + + TEST KB_FLAG_1,SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN + JNZ K16B ; IF YES, DON'T PROCESS SYSTEM INDICATOR + + OR KB_FLAG_1,SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ; END OF INTERRUPT COMMAND + OUT 020H,AL ; SEND COMMAND TO INTERRUPT CONTROL PORT +;***CNS + JMP SHORT $+2 +;***CNS + ; INTERRUPT-RETURN-NO-EOI + ;; + MOV AL,ENA_KBD ; INSURE KEYBOARD IS ENABLED + CALL SHIP_IT ; EXECUTE ENABLE + + MOV AX,08500H ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY + STI ; MAKE SURE INTERRUPTS ENABLED + INT 15H ; USER INTERRUPT +;***CNS + MOV CS:ENABLE_FL,2 + RET;JMP KEY_EXIT ; END PROCESSING +;***CNS +K16B: ;JMP PREP_EXIT ; IGNORE SYSTEM KEY + RET +K16C: AND KB_FLAG_1,NOT SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ; END OF INTERRUPT COMMAND + OUT 020H,AL ; SEND COMMAND TO INTERRUPT CONTROL PORT +;***CNS + JMP SHORT $+2 +;***CNS + ; INTERRUPT-RETURN-NO-EOI + MOV AL,ENA_KBD ; ENSURE KEYBOARD IS ENABLED + CALL SHIP_IT ; EXECUTE ENABLE + + MOV AX,08501H ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY + STI ; MAKE SURE INTERRUPTS ENABLED + INT 15H ; USER INTERRUPT +;***CNS + MOV CS:ENABLE_FL,2 + RET;JMP KEY_EXIT ; IGNORE SYSTEM KEY +;***CNS +PAGE +;------ TEST FOR SHIFT KEYS +; +; HERE IS WHERE KBFLAGS ARE SET. WHAT HAPPENS IS, THE SYSTEM SEARCHES TABLE +; 'K6' FOR THE KEY. IF FOUND, IT GETS THE APPROPRIATE BIT FROM TABLE 'K7' +; AND SETS IT ON. (TABLES ARE ALL AT THE END OF THIS ROUTINE) FLAGS FOR THE +; SECOND ALT AND CTRL ARE SET IN KB_FLAG_3 AND HAVE THE SAME BIT POSITIONS AS +; THEIR ORIGINAL COUNTERPARTS IN KB_FLAG + +K16A: MOV BL,KB_FLAG ; PUT STATE FLAGS IN BL RWV 8-28-85 + MOV DI,OFFSET K6 ; SHIFT KEY TABLE + MOV CX,K6L ; LENGTH + REPNE SCASB ; LOOK THROUGH THE TABLE FOR A MATCH + MOV AL,AH ; RECOVER SCAN CODE + JE K17 ; JUMP IF MATCH FOUND + JMP K25 ; IF NO MATCH, THEN SHIFT NOT FOUND + +;------ SHIFT KEY FOUND + +K17: SUB DI,OFFSET K6+1 ; ADJUST PTR TO SCAN CODE MTCH + MOV AH,CS:K7[DI] ; GET MASK INTO AH + MOV CL,2 ; SET UP COUNT FOR FLAG SHIFTS RWV 9-11-85 + TEST AL,80H ; TEST FOR BREAK KEY + JZ K17C + JMP K23 ; JUMP IF BREAK RWV 8-14-85 + +;------ SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE + +K17C: CMP AH,SCROLL_SHIFT + JAE K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY + +;------ PLAIN SHIFT KEY, SET SHIFT ON + + CMP COUNTRY_FLAG,0FFh ; ARE WE IN FOREIGN LANG MODE? RWV 8-29-85 + JNE K17C1 ; NO, US MODE, JUMP RWV 8-29-85 + CMP AL,ALT_KEY ; IS THIS THE ALT KEY? RWV 8-29-85 + JNE K17C1 ; NO, NORMAL KEY RWV 8-29-85 + ;**CNS +;;AD000TEST KB_FLAG_3,LC_E0 ; IS IT THE ALT_GR KEY? RWV 8-29-85 +;;AD000JNZ K17C2 ; YES, DON'T SET KB_FLAG RWV 8-29-85 + + +K17C1: OR KB_FLAG,AH ; TURN ON SHIFT BIT RWV 8-28-85 +K17C2: TEST AH,CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? RWV 8-28-85 + JZ K17F ; NO, JUMP RWV 8-28-85 +K17D: TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS? RWV 10-08-85 + JZ K17E ; NO, JUMP RWV 7-22-85 + OR KB_FLAG_3,AH ; SET BITS FOR RIGHT CTRL, ALT RWV 7-22-85 + RET +; JMP PREP_EXIT ; INTERRUPT_RETURN RWV 7-22-85 +K17E: SHR AH,CL ; MOVE FLAG BITS TWO POSITIONS RWV 8-28-85 + OR KB_FLAG_1,AH ; SET BITS FOR LEFT CTRL, ALT RWV 7-22-85 + RET +; JMP PREP_EXIT ;; + ;; Q..typewriter caps locks +K17F: ;; + TEST CS:SD.SPECIAL_FEATURES,TYPEWRITER_CAPS_LK + JZ K17G ;; N..all done + CMP COUNTRY_FLAG,0FFh ; ARE WE IN LANG MODE? RWV 8-28-85 + JNE K17G ; NO, ALL DONE WITH SHIFT KEY RWV 8-28-85 + +;; If keyboard is P12 then we still need to release caps_lk ***RPS 10-3-86 + + TEST CS:SD.SYSTEM_FLAG,PC_LAP ;; IS THIS A P12 KEYBOARD? ***RPS 10-3-86 + JNZ REMOVE_CAPS_SHIFT ;; ***RPS 10-3-86 + + TEST BH,KBX ; THIS THE ENHANCED KEYBOARD? RWV 11-06-85 + JZ K17G ; NO, ALL DONE WITH SHIFT KEY RWV 8-13-85 +REMOVE_CAPS_SHIFT: ;; ***RPS 10-3-86 + AND KB_FLAG,NOT CAPS_SHIFT ; YES, TAKE KB OUT OF C_L STATE RWV 8-13-85 + TEST CS:SD.SYSTEM_FLAG,PC_AT+PC_386 ; IF THIS IS A PC1 OR XT, RWV 9-18-85 + JZ K17G ; THEN SKIP THE LEDs RWV 9-18-85 + CALL SND_LED ; AND UPDATE THE INDICATOR RWV 8-13-85 +K17G: RET;JMP PREP_EXIT + +;------ TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT + +K18: ; SHIFT-TOGGLE + TEST BL,CTL_SHIFT ; CHECK CTL SHIFT STATE RWV 7-30-85 + JZ K18A ; JUMP IF NOT CTL STATE + JMP K25 ; JUMP IF CTL STATE +K18A: CMP AL,INS_KEY ; CHECK FOR INSERT KEY + JNE K22 ; JUMP IF NOT INSERT KEY + TEST BL,ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT RWV 7-30-85 + JZ K18B ; JUMP IF NOT ALTERNATE SHIFT RWV 7-30-85 + JMP K25 ; JUMP IF ALTERNATE SHIFT +K18B: TEST BH,LC_E0 ; IS THIS THE NEW INSERT KEY? RWV 10-08-85 + JNZ K22 ; YES, THIS ONE'S NEVER A "0" RWV 7-23-85 +K19: TEST BL,NUM_STATE ; CHECK FOR BASE STATE RWV 7-30-85 + JNZ K21 ; JUMP IF NUM LOCK IS ON + TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE RWV 7-30-85 + JZ K22 ; JUMP IF BASE STATE +K20: MOV AH,AL ; PUT SCAN CODE BACK IN AH RWV 11-07-85 + JMP K25 ; NUMERAL "0", STNDRD. PROCESSING RWV 7-22-85 + +K21: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; MIGHT BE NUMERIC RWV 7-30-85 + JZ K20 ; IS NUMERIC, STD. PROC. RWV 7-23-85 + +K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT + TEST AH,KB_FLAG_1 ; IS KEY ALREADY DEPRESSED? + JZ K22A + RET;JMP PREP_EXIT ; JUMP IF KEY ALREADY DEPRESSED +K22A: OR KB_FLAG_1,AH ; INDICATE THAT THE KEY IS DEPRESSED + XOR KB_FLAG,AH ; TOGGLE THE SHIFT STATE + + TEST CS:SD.SPECIAL_FEATURES,TYPEWRITER_CAPS_LK + JZ K22C ;; N..all done + +;; If keyboard is P12 then we do not toggle ***RPS 10-3-86 + + TEST CS:SD.SYSTEM_FLAG,PC_LAP ;; IS THIS A P12 KEYBOARD? ***RPS 10-3-86 + JNZ LAP_SO_DONT_TOGGLE ;; ***RPS 10-3-86 + + TEST BH,KBX ; THIS THE ENHANCED KEYBOARD? RWV 11-06-85 + JZ K22C ; NO, ALL DONE WITH TOGGLE KEYS RWV 8-13-85 + +LAP_SO_DONT_TOGGLE: ;; ***RPS 10-3-86 + CMP CS:COUNTRY_FLAG,0FFh ; ARE WE IN FOREIGN LANG MODE? RWV 9-11-85 + JNE K22C ; NO, NO SPECIAL STUFF FOR U.S. RWV 9-11-85 + TEST AH,CAPS_SHIFT ; IS IT THE CAPS_LOCK KEY? RWV 8-13-85 + JZ K22C ; NO, NOTHING ELSE TO DO RWV 8-13-85 + OR KB_FLAG,AH ; YES, SET CAPS_LOCK (NOT TOGGLE) RWV 8-13-85 + +;------- TEST SYSTEM TYPE + +K22C: TEST CS:SD.SYSTEM_FLAG,PC_AT+PC_386 ; IF THE SYSTEM WE'RE RUNNING ON IS + JZ K22B ; A PC1 OR XT, THEN SKIP THE LEDs + +;------ TOGGLE LED IF CAPS, NUM, OR SCROLL KEY DEPRESSED + + TEST AH,CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? + JZ K22B ; GO IF NOT + PUSH AX ; SAVE SCAN CODE AND SHIFT MASK + CALL SND_LED ; GO TURN MODE INDICATORS ON + POP AX ; RESTORE SCAN CODE + +K22B: CMP AL,INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY +;**CNS + JE INS_CHK ; JUMP IF NOT INSERT KEY + RET;JMP PREP_EXIT + + +;**CNS +INS_CHK: + + MOV AH,AL ; SCAN CODE IN BOTH HALVES OF AX RWV 7-24-85 + JMP K28 ; FLAGS UPDATED, PROC. FOR BUFFER RWV 7-23-85 + +;------ BREAK SHIFT FOUND + +K23: ; BREAK-SHIFT-FOUND + CMP AH,SCROLL_SHIFT ; IS THIS A TOGGLE KEY? + NOT AH ; INVERT MASK + JAE K24 ; YES, HANDLE BREAK TOGGLE + AND KB_FLAG,AH ; TURN OFF SHIFT BIT + CMP AH,NOT CTL_SHIFT ; IS THIS ALT OR CTL? RWV 8-29-85 + JA K23D ; NO, ALL DONE RWV 8-29-85 + + + + TEST BH,LC_E0 ; 2ND ALT OR CTL? RWV 10-08-85 + JZ K23A ; NO, HANDLE NORMALLY RWV 7-22-85 + AND KB_FLAG_3,AH ; RESET BIT FOR RIGHT ALT OR CTL RWV 7-22-85 + JMP SHORT K23B ; CONTINUE RWV 7-22-85 +K23A: SAR AH,CL ; MOVE THE MASK BIT TWO POSITIONS RWV 8-28-85 + AND KB_FLAG_1,AH ; RESET BIT FOR LEFT ALT OR CTL RWV 8-28-85 +K23B: MOV AH,AL ; SAVE SCAN CODE RWV 8-28-85 + MOV AL,KB_FLAG_3 ; GET RIGHT ALT & CTRL FLAGS RWV 8-28-85 + CMP COUNTRY_FLAG,0FFH ; ARE WE IN LANGUAGE MODE? RWV 8-28-85 + JNE K23C ; NO, LEAVE RIGHT FLAGS AS IS RWV 8-28-85 +;**CNS + AND AL,NOT GRAPH_ON ; YES, FILTER OUT THE ALT_GR KEY RWV 8-28-85 +;**CNS +K23C: SHR AL,CL ; MOVE TO BITS 1 & 0 RWV 8-28-85 + OR AL,KB_FLAG_1 ; PUT IN LEFT ALT & CTL FLAGS RWV 8-28-85 + SHL AL,CL ; MOVE BACK TO BITS 3 & 2 RWV 8-28-85 + AND AL,ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE RWV 8-28-85 + OR KB_FLAG,AL ; PUT RESULT IN THE REAL FLAGS RWV 8-28-85 + MOV AL,AH ; RECOVER SAVED SCAN CODE RWV 8-28-85 + +K23D: CMP AL,ALT_KEY+80H ; IS THIS ALTERNATE SHIFT RELEASE + JE ALT_SHFT ; INTERRUPT_RETURN + RET;JMP PREP_EXIT + +;------ ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER + +ALT_SHFT: + + MOV AL,ALT_INPUT + MOV AH,0 ; SCAN CODE OF 0 + MOV ALT_INPUT,AH ; ZERO OUT THE FIELD + CMP AL,0 ; WAS THE INPUT = 0? + JNE GOOD_ALTCHAR ; INTERRUPT_RETURN + RET;JMP PREP_EXIT + +GOOD_ALTCHAR: + + CALL BUFFER_FILL_ANY_CHAR ;; Put in buffer, but use this + ;; entry point to avoid trashing + ;; an ASCII code of 255 + RET;JMP PREP_EXIT ; INTERRUPT_RETURN + +K24: ; BREAK-TOGGLE + AND KB_FLAG_1,AH ; INDICATE NO LONGER DEPRESSED + RET;JMP PREP_EXIT ; INTERRUPT_RETURN + +;------ TEST FOR HOLD STATE + ; AL, AH = SCAN CODE +K25: ; NO-SHIFT-FOUND + CMP AL,80H ; TEST FOR BREAK KEY + JB NO_BREAK ; NOTHING FOR BREAK CHARS FROM HERE ON + RET;JMP PREP_EXIT + +NO_BREAK: + + TEST KB_FLAG_1,HOLD_STATE ; ARE WE IN HOLD STATE + JZ K28 ; BRANCH AROUND TEST IF NOT + CMP AL,NUM_KEY + JNE HOLD_OFF ; CAN'T END HOLD ON NUM_LOCK + RET;JMP PREP_EXIT + +HOLD_OFF: + + AND KB_FLAG_1,NOT HOLD_STATE ; TURN OFF THE HOLD STATE BIT + +;------ EXIT POINT ;; + + RET;JMP PREP_EXIT + +PAGE +;------ NOT IN HOLD STATE + ; AL, AH = SCAN CODE (ALL MAKES) +K28: ; NO-HOLD-STATE + CMP AL,88 ; TEST FOR OUT-OF-RANGE SCAN CODES RWV 8-01-85 + JBE SCAN_INRANGE ; IGNORE IF OUT-OF-RANGE RWV 8-01-85 + RET;JMP PREP_EXIT + + +SCAN_INRANGE: + + TEST BL,ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT? RWV 7-30-85 + JZ K28A ; JUMP IF NOT ALTERNATE RWV 7-26-85 + + TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD? RWV 10-08-85 + JZ K29 ; NO, ALT STATE IS REAL RWV 7-24-85 + + TEST KB_FLAG_1,SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? RWV 7-24-85 + JZ K29 ; NO, ALT STATE IS REAL RWV 7-24-85 +;**CNS + + TEST AH,LC_E0 ; IS IT THE ALT_GR KEY? RWV 8-29-85 + JZ K28A ; YES, DON'T SET KB_FLAG RWV 8-29-85 + + TEST AL,R_ALT_SHIFT ; TURN ON SHIFT BIT RWV 8-28-85 + JNZ K29 ; TURN ON SHIFT BIT RWV 8-28-85 + +;**CNS + +K28A: JMP K38 ; YES, THIS IS PHONY ALT STATE RWV 7-24-85 + ; DUE TO PRESSING SYSREQ RWV 7-24-85 + +;------ TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) + +K29: ; TEST-RESET + TEST BL,CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? RWV 7-30-85 + JZ K31 ; NO_RESET + CMP AL,DEL_KEY ; SHIFT STATE IS THERE, TEST KEY + JNE K31A ; NO_RESET, TRANSLATE TABLE SWAP + +;------ CTL-ALT-DEL HAS BEEN FOUND, DO I/O CLEANUP + + MOV RESET_FLAG,1234H ; SET FLAG FOR RESET FUNCTION + AND WORD PTR KB_FLAG_3,KBX ; CLEAR ALL FLAG BITS EXCEPT KBX PED 6-25-86 + JMP RESET ; JUMP TO POWER ON DIAGNOSTICS + +;------ IN ALTERNATE SHIFT, RESET NOT FOUND + +K31: ; NO-RESET + CALL KEYB_STATE_PROCESSOR ;; + JNC K3105 ;; NO TRANSLATIONS FOUND - CONTINUE + RET;JMP PREP_EXIT ;; TRANSLATIONS FOUND - EXIT +K3105: ;; + ;; + CMP AL,57 ; TEST FOR SPACE KEY + JNE K311 ; NOT THERE + MOV AL,' ' ; SET SPACE CHAR + JMP K57 ; BUFFER_FILL +K311: + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS EXTENDED INT 16 LOADED? RWV 11-06-85 + JZ K32 ; NO, SKIP THIS EXTENDED STUFF RWV 11-06-85 + CMP AL,15 ; TEST FOR TAB KEY RWV 10-04-85 + JNE K312 ; NOT THERE RWV 10-04-85 + MOV AX,0A500h ; SET SPECIAL CODE FOR ALT-TAB RWV 10-04-85 + JMP K57 ; BUFFER_FILL RWV 10-04-85 +K312: + CMP AL,74 ; TEST FOR KEYPAD - RWV 10-04-85 + JE K312A ; GO PROCESS RWV 10-04-85 + CMP AL,78 ; TEST FOR KEYPAD + RWV 10-04-85 + JNE K32 ; SKIP TEST FOR LANG SWAP & CONT. RWV 11-06-85 +K312A: JMP K37B ; GO PROCESS RWV 10-04-85 + +;------ SET COUNTRY FLAG TO INDICATE WHICH TABLE WE'RE USING, FOREIGN OR DOMESTIC + +K31A: CMP AL,CS:SD.HOT_KEY_ON_SCAN ; TEST FOR HOT KEY TO US + JNE K31B ; + MOV CS:COUNTRY_FLAG,00 ; SET FLAG FOR DOMESTIC KEY'S + RET;JMP PREP_EXIT ; INTERRUPT RETURN + +K31B: CMP AL,CS:SD.HOT_KEY_OFF_SCAN ; TEST FOR HOT KEY TO FOREIGN + JNE K31C ; IF NOT TEST FOR FRONT ENGRAV + MOV CS:COUNTRY_FLAG,0FFH ; SET FLAGS FOR FOREIGN KEY'S + RET;JMP PREP_EXIT ; INTERRUPT RETURN + + +;------ ALT, CTRL DOWN ; NO HOT KEY + +K31C: CMP CS:COUNTRY_FLAG,0FFH + JNE K32 ; TRY ALT_KEY_PAD + CALL KEYB_STATE_PROCESSOR ;; + JNC K32 ;; NO TRANSLATIONS FOUND - CONTINUE + RET;JMP PREP_EXIT ;; TRANSLATIONS FOUND - EXIT + + +;------ LOOK FOR KEY PAD ENTRY + +K32: ; ALT-KEY-PAD + MOV DI,OFFSET K30 ; ALT-INPUT-TABLE + MOV CX,10 ; LOOK FOR ENTRY USING KEYPAD + REPNE SCASB ; LOOK FOR MATCH + JNE K33 ; NO_ALT_KEYPAD + TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS? RWV 10-08-85 + JZ K321 ; NO, PROCESS AS ALT-NUMPAD RWV 11-06-85 + JMP K37C ; YES, JUMP, NOT NUMPAD KEY RWV 7-24-85 +K321: SUB DI,OFFSET K30+1 ; DI NOW HAS ENTRY VALUE + MOV AL,ALT_INPUT ; GET THE CURRENT BYTE + MOV AH,10 ; MULTIPLY BY 10 + MUL AH + ADD AX,DI ; ADD IN THE LATEST ENTRY + MOV ALT_INPUT,AL ; STORE IT AWAY +K32A: RET;JMP PREP_EXIT ; THROW AWAY THAT KEYSTROKE + +;------ LOOK FOR SUPERSHIFT ENTRY + +K33: ; NO-ALT-KEYPAD + MOV ALT_INPUT,0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT + ; DI,ES ALREADY POINTING + MOV CX, K30_LEN ; NORMALLY 26, BUT 27 FOR FR, DUE RWV 8-06-85 + ; TO THE ";" KEY BEING "M" RWV 8-06-85 + REPNE SCASB ; LOOK FOR MATCH IN ALPHABET + JNE K34 ; NOT FOUND, FUNCTION KEY OR OTHER + JMP SHORT K37A ; PUT IT IN THE BUFFER RWV 8-06-85 + +;------ LOOK FOR TOP ROW OF ALTERNATE SHIFT + +K34: ; ALT-TOP-ROW + CMP AL,2 ; KEY WITH '1' ON IT + JB K37B ; MUST BE ESCAPE RWV 10-04-85 + CMP AL,13 ; IS IT IN THE REGION + JA K35 ; NO, ALT-SOMETHING ELSE + ADD AH,118 ; CONVERT PSEUDO SCAN CODE TO RANGE + JMP SHORT K37A ; GO FILL THE BUFFER RWV 8-06-85 + +;------ TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES + +K35: ; ALT-FUNCTION + CMP AL,F11_M ; IS IT F11? RWV 7-24-85 + JB K35A ; NO, BRANCH RWV 7-24-85 + CMP AL,F12_M ; IS IT F12? RWV 7-24-85 + JA K35A ; NO, BRANCH RWV 7-24-85 + ADD AH,52 ; CONVERT TO PSEUDO SCAN CODE RWV 7-24-85 + JMP SHORT K37A ; GO FILL THE BUFFER RWV 8-06-85 + +K35A: TEST BH,LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? RWV 10-08-85 + JZ K37 ; NO, JUMP RWV 10-04-85 + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 LOADED? RWV 11-06-85 + JZ K37 ; NO, DO COMPATIBLE OUTPUT RWV 11-06-85 + CMP AL,28 ; TEST FOR KEYPAD ENTER RWV 10-04-85 + JNE K35B ; NOT THERE RWV 10-04-85 + MOV AX,0A600h ; SPECIAL CODE RWV 10-04-85 + JMP K57 ; BUFFER FILL RWV 10-04-85 +K35B: CMP AL,83 ; TEST FOR DELETE KEY RWV 10-04-85 + JE K37C ; HANDLE WITH OTHER EDIT KEYS RWV 10-04-85 + CMP AL,53 ; TEST FOR KEYPAD / RWV 10-04-85 + JNE K32A ; NOT THERE, NO OTHER E0 SPECIALS RWV 10-04-85 + MOV AX,0A400h ; SPECIAL CODE RWV 10-04-85 + JMP K57 ; BUFFER FILL RWV 10-04-85 + +K37: CMP AL,59 ; TEST FOR FUNCTION KEYS (F1) RWV 10-04-85 + JB K37B ; NO FN, HANDLE W/OTHER EXTENDED RWV 10-04-85 + CMP AL,68 ; IN KEYPAD REGION? RWV 7-26-85 + ; OR NUMLOCK, SCROLLOCK? RWV 7-26-85 + JA K32A ; IF SO, IGNORE + ADD AH,45 ; CONVERT TO PSEUDO SCAN CODE RWV 8-06-85 + +K37A: MOV AL,0 ; ASCII CODE OF ZERO RWV 8-06-85 + JMP K57 ; PUT IT IN THE BUFFER RWV 8-06-85 + +K37B: + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 LOADED? RWV 11-06-85 + JNZ K37B1 ; YES, TRANSLATE AS EXTENDED RWV 11-06-85 + RET;JMP PREP_EXIT ; NO, INGORE THIS ONE RWV 11-06-85 +K37B1: MOV AL,0F0h ; USE SPECIAL ASCII CODE RWV 10-04-85 + JMP K57 ; PUT IT IN THE BUFFER RWV 10-04-85 + +K37C: + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 LOADED? RWV 11-06-85 + JZ K37A ; NO, DO COMPATIBLE OUTPUT RWV 11-06-85 + ADD AL,80 ; CONVERT SCAN CODE (EDIT KEYS) RWV 10-07-85 + MOV AH,AL ; (SCAN CODE NOT IN AH FOR INSERT) RWV 10-07-85 + JMP K37A ; PUT IT IN THE BUFFER RWV 10-07-85 +PAGE +;------ NOT IN ALTERNATE SHIFT + +K38: ; NOT-ALT-SHIFT + ; BL STILL HAS SHIFT FLAGS RWV 7-26-85 + TEST BL,CTL_SHIFT ; ARE WE IN CONTROL SHIFT? RWV 7-26-85 + JNZ K38A ; YES, START PROCESSING RWV 8-01-85 + JMP K44 ; NOT-CTL-SHIFT + +;------ CONTROL SHIFT, TEST SPECIAL CHARACTERS + +;------ TEST FOR BREAK + +K38A: CMP AL,SCROLL_KEY ; TEST FOR BREAK + JNE K39 ; JUMP, NO-BREAK + TEST CS:SD.SYSTEM_FLAG,PC_LAP ; IS THIS THE LAP COMPUTER? RWV 12-02-85 + JNZ K38B ; YES, THIS IS CTRL-BREAK RWV 12-02-85 + TEST BH,KBX ; NO, IS THIS THE ENHANCED KBD? RWV 10-08-85 + JZ K38B ; NO, BREAK IS VALID RWV 7-26-85 + TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0? RWV 10-08-85 + JZ K39 ; NO-BREAK, TEST FOR PAUSE RWV 7-26-85 + +K38B: MOV BX,BUFFER_HEAD ; RESET BUFFER TO EMPTY RWV 10-23-85 + MOV BUFFER_TAIL,BX ; + MOV BIOS_BREAK,80H ; TURN ON BIOS_BREAK BIT + +;-------- ENABLE KEYBOARD + + MOV AL,ENA_KBD ; ENABLE KEYBOARD + CALL SHIP_IT ; EXECUTE ENABLE + INT 1BH ; BREAK INTERRUPT VECTOR + SUB AX,AX ; PUT OUT DUMMY CHARACTER + JMP K57 ; BUFFER_FILL + +;-------- TEST FOR PAUSE + +K39: ; NO-BREAK + CMP AL,NUM_KEY ; LOOK FOR PAUSE KEY + JNE K41 ; NO-PAUSE + TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD? RWV 10-08-85 + JZ K39P ; NO, THIS IS A VALID PAUSE RWV 9-26-85 + TEST CS:SD.SYSTEM_FLAG,PC_LAP ; IS THIS THE LAP COMPUTER? RWV 9-26-85 + JZ K41 ; NO, IT'S NOT PAUSE THIS TIME RWV 9-26-85 +K39P: OR KB_FLAG_1,HOLD_STATE ; TURN ON THE HOLD FLAG + MOV BUSY_TFLAG,ACTIVE_OFF ;TURN THE BUSY FLAG OFF - THIS IS + ;A SPECIAL CASE FOR THE SPLICER + DEC CS:TEMP_TAIL ;DELETE THE PAUSE KEY FROM THE BUFFER + ;IN CASE A INTERRUPT COMES IN + ;SO IT IS NOT DONE REPEATEDLY +;-------- ENABLE KEYBOARD + + MOV AL,ENA_KBD ; ENABLE KEYBOARD + CALL SHIP_IT ; EXECUTE ENABLE +K39A: +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ; END OF INTERRUPT TO CONTROL PORT + OUT 020H,AL ; ALLOW FURTHER KEYSTROKE INTS +;***CNS + JMP SHORT $+2 +;***CNS + +;------ DURING PAUSE INTERVAL, TURN CRT BACK ON + + CMP CRT_MODE,7 ; IS THIS BLACK AND WHITE CARD + JE K40 ; YES, NOTHING TO DO + MOV DX,03D8H ; PORT FOR COLOR CARD + MOV AL,CRT_MODE_SET ; GET THE VALUE OF THE CURRENT MODE + OUT DX,AL ; SET THE CRT MODE, SO THAT CRT IS ON +K40: ; PAUSE-LOOP + +; PUSH DS ;ICE +; push bx ;ICE +; push ax ;ICE +; mov bx,0140H ;ICE +; xor ax,ax ;ICE +; mov ds,ax ;ICE +; mov ax,word ptr ds:[bx] ;ICE +; mov word ptr ds:[bx],ax ;ICE +; POP ax ;ICE +; pop bx ;ICE +; pop ds ;ICE + + TEST CS:SD.SYSTEM_FLAG,PC_LAP ; IS THIS THE LAP COMPUTER? RWV 9-26-85 + JZ K40A ; NO, SKIP THE BATTERY LIFE STUFF RWV 9-26-85 + MOV AX,4104H ; FUNCTION 41, AL=04=RETURN IF 0 RWV from AAD + MOV BX,HOLD_STATE*100H ; BH=HOLD_STATE, BL=0=NO TIME OUT RWV from AAD + PUSH DS ; MAKE ES:DI POINT TO KB_FLAG_1 RWV from AAD + POP ES ; RWV from AAD + MOV DI,OFFSET KB_FLAG_1 ; RWV from AAD + INT 15H ; SLEEP UNTIL OUT OF HOLD RWV from AAD +K40A: + + + TEST KB_FLAG_1,HOLD_STATE + JNZ K40 ; LOOP UNTIL FLAG TURNED OFF +;***CNS + MOV CS:ENABLE_FL,1 + RET;JMP ENABLE_CHK ; INTERRUPT_RETURN_NO_EOI +;***CNS +;------ TEST SPECIAL CASE KEY 55 + +K41: ; NO-PAUSE + CMP AL,55 ; TEST FOR */PRTSC KEY + JNE K42 ; NOT-KEY-55 + TEST CS:SD.SYSTEM_FLAG,PC_LAP ; IS THIS THE LAP COMPUTER? RWV 9-23-85 + JZ K41B ; NO, JUMP RWV 9-23-85 + TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0? RWV 10-24-85 + JZ K41A ; NO, THIS IS THE PRTSC KEY RWV 9-23-85 + JMP SHORT K42B ; YES, E0 MEANS THE "*" KEY RWV 9-23-85 + +K41B: TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD? RWV 10-08-85 + JZ K41A ; NO, CTL-PRTSC IS VALID RWV 8-01-85 + TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0? RWV 10-08-85 + JZ K42B ; NO, TRANSLATE TO A FUNCTION RWV 10-04-85 +K41A: MOV AX,114*256 ; START/STOP PRINTING SWITCH + JMP K57 ; BUFFER_FILL + +;------ SET UP TO TRANSLATE CONTROL SHIFT + +K42: + CALL KEYB_STATE_PROCESSOR ;; + JNC K421 ;; NO TRANSLATIONS FOUND - CONTINUE + RET;JMP PREP_EXIT ;; TRANSLATIONS FOUND - EXIT + +K421: ; NOT-KEY-55 + CMP AL,15 ; IS IT THE TAB KEY? RWV 10-04-85 + JE K42B ; YES, XLATE TO FUNCTION CODE RWV 10-04-85 + CMP AL,53 ; IS IT THE / KEY? RWV 10-04-85 + JNE K42A ; NO, NO MORE SPECIAL CASES RWV 10-04-85 + TEST BH,LC_E0 ; YES, IS IT FROM THE KEYPAD? RWV 10-08-85 + JZ K42A ; NO, JUST TRANSLATE RWV 10-04-85 + MOV AX,9500h ; YES, SPECIAL CODE FOR THIS ONE RWV 10-04-85 + JMP K57 ; BUFFER FILL RWV 10-04-85 + +K42A: MOV BX,OFFSET K8 ; SET UP TO TRANSLATE CTL + CMP AL,59 ; IS IT IN CHARACTER TABLE? + JAE K42B ; NO, CTL-TABLE-TRANSLATE-SCAN RWV 11-06-85 + JMP K56 ; GO TRANSLATE CHAR +K42B: MOV BX,OFFSET K8 ; SET UP TO TRANSLATE CTL RWV 10-07-85 + JMP K64 ; GO TRANSLATE_SCAN RWV 8-06-85 +PAGE +;------ NOT IN CONTROL SHIFT + +K44: + CALL KEYB_STATE_PROCESSOR ;; + JNC K4401 ;; NO TRANSLATIONS FOUND - CONTINUE + RET;JMP PREP_EXIT ;; TRANSLATIONS FOUND - EXIT +K4401: + CMP AL,55 ; PRINT SCREEN KEY? + JNE K45 ; NOT-PRINT-SCREEN + TEST CS:SD.SYSTEM_FLAG,PC_LAP ; IS THIS THE LAP COMPUTER? RWV 9-12-85 + JZ K441 ; NO, JUMP RWV 9-12-85 + TEST BH,LC_E0 ; YES, WAS LAST CODE THE MARKER? RWV 10-08-85 + JZ K44A ; NO, TEST THE SHIFT STATE RWV 9-12-85 + JMP K45C ; YES, XLATE TO "*" CHAR RWV 9-12-85 +K441: TEST BH,KBX ; IS THIS ENHANCED KEYBOARD? RWV 10-08-85 + JZ K44A ; NO, TEST FOR SHIFT STATE RWV 7-30-85 + TEST BH,LC_E0 ; YES, LAST CODE A MARKER? RWV 10-08-85 + JNZ K44B ; YES, IS PRINT SCREEN RWV 7-30-85 + JMP SHORT K45C ; NO, XLATE TO "*" CHARACTER RWV 7-31-85 +K44A: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;NOT 101 KBD, SHIFT KEY DOWN? RWV 7-30-85 + JZ K45C ; NO, XLATE TO "*" CHARACTER RWV 7-30-85 + +;------ ISSUE INTERRUPT TO PERFORM PRINT SCREEN FUNCTION +K44B: MOV AL,ENA_KBD ; INSURE KEYBOARD IS ENABLED + CALL SHIP_IT ; EXECUTE ENABLE +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ; END OF CURRENT INTERRUPT + OUT 020H,AL ; SO FURTHER THINGS CAN HAPPEN +;***CNS + JMP SHORT $+2 +;***CNS + PUSH BP ; SAVE POINTER + INT 5H ; ISSUE PRINT SCREEN INTERRUPT + POP BP ; RESTORE POINTER + AND KB_FLAG_3,NOT LC_E0+LC_E1 ;ZERO OUT THESE FLAGS RWV 8-13-85 +;***CNS + MOV CS:ENABLE_FL,1 + RET;JMP ENABLE_CHK ; GO BACK WITHOUT EOI OCCURRING +;***CNS + + +;------ HANDLE THE IN-CORE KEYS +K45: ; NOT-PRINT-SCREEN + CMP AL,58 ; TEST FOR IN-CORE AREA RWV 7-30-85 + JA K46 ; JUMP IF NOT RWV 8-13-85 + +K450: TEST BH,GRAPH_ON ; IS ALT GRAPHICS ON? AEV + JZ K456 ; GO ON IF NOT AEV + RET;JMP PREP_EXIT ;; YES, TRASH KEYSTROKE + +K456: CMP AL,53 ; IS THIS THE "/" KEY? RWV 8-01-85 + JNE K45A ; NO, JUMP RWV 8-01-85 + TEST BH,LC_E0 ; WAS LAST CODE THE MARKER? RWV 10-08-85 + JNZ K45C1 ; YES, TRANSLATE TO US CHARACTER RWV 8-01-85 + +K45A: + +K45A1: MOV CX,K30_LEN ; LENGTH OF SEARCH RWV 7-30-85 + MOV DI,OFFSET K30+10 ; POINT TO TABLE OF A-Z CHARS RWV 7-30-85 + REPNE SCASB ; IS THIS A LETTER KEY? RWV 7-30-85 + JNE K45B ; NO, SYMBOL KEY RWV 7-30-85 + +K45A2: TEST BL,CAPS_STATE ; ARE WE IN CAPS_LOCK? RWV 7-30-85 + JNZ K45D ; TEST FOR SURE RWV 7-30-85 +K45B: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? RWV 7-30-85 + JNZ K45E ; YES, UPPERCASE RWV 7-30-85 + ; NO, LOWERCASE RWV 7-30-85 +K45C: ;; +K45C1: MOV BX,OFFSET K10 ; XLATE TO LOWERCASE US LETTERS RWV 8-06-85 + JMP SHORT K45E2 +K45D: ; ALMOST-CAPS-STATE RWV 7-30-85 + TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? RWV 7-30-85 + JNZ K45C1 ; SHIFTED TEMP OUT OF CAPS STATE RWV 7-30-85 +K45E: +K45E1: MOV BX,OFFSET K11 ; XLATE TO UPPERCASE US LETTERS RWV 8-06-85 +K45E2: JMP SHORT K56 ; GO TRANSLATE RWV 8-06-85 + + +;------ TEST FOR KEYS F1 - F10 +K46: ; NOT IN-CORE AREA RWV 7-30-85 + CMP AL,68 ; TEST FOR F1 - F10 RWV 7-30-85 + JA K47 ; JUMP IF NOT RWV 7-30-85 + JMP SHORT K53A ; YES, GO DO FN KEY PROCESS RWV 7-30-85 + + +;------ HANDLE THE NUMERIC PAD KEYS + +K47: ; NOT F1 - F10 RWV 7-30-85 + CMP AL,83 ; TEST FOR NUMPAD KEYS RWV 7-30-85 + JA K52 ; JUMP IF NOT RWV 7-30-85 + +;------ KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION +K48: CMP AL,74 ; SPECIAL CASE FOR MINUS + JE K45E1 ; GO TRANSLATE (US & WT ARE SAME) RWV 8-06-85 + CMP AL,78 ; SPECIAL CASE FOR PLUS + JE K45E1 ; GO TRANSLATE (US & WT ARE SAME) RWV 8-06-85 + TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS? RWV 10-08-85 + JNZ K49 ; YES, TRANSLATE TO BASE STATE RWV 8-06-85 + + TEST BL,NUM_STATE ; ARE WE IN NUM_LOCK? RWV 7-30-85 + JNZ K50 ; TEST FOR SURE + TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? RWV 7-30-85 + JNZ K51 ; IF SHIFTED, REALLY NUM STATE + +;------ BASE CASE FOR KEYPAD +K49: CMP AL,76 ; SPECIAL CASE FOR BASE STATE 5 RWV 10-04-85 + JNE K49A ; CONTINUE IF NOT KEYPAD 5 RWV 10-04-85 + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 LOADED? RWV 11-06-85 + JNZ K491 ; YES, TRANSLATE AS EXTENDED RWV 11-06-85 + RET;JMP PREP_EXIT ; NO, INGORE RWV 11-06-85 + +K491: MOV AL,0F0h ; SPECIAL ASCII CODE RWV 10-04-85 + JMP K57 ; BUFFER FILL RWV 10-04-85 +K49A: MOV BX,OFFSET K10 ; BASE CASE TABLE RWV 7-30-85 + JMP SHORT K64 ; CONVERT TO PSEUDO SCAN + +;------ MIGHT BE NUM LOCK, TEST SHIFT STATUS +K50: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;ALMOST-NUM-STATE RWV 7-30-85 + JNZ K49 ; SHIFTED TEMP OUT OF NUM STATE +K51: ; REALLY_NUM_STATE RWV 8-06-85 + JMP SHORT K45E1 ; (US & WT ARE SAME) RWV 8-06-85 + +;------ TEST FOR THE NEW KEY ON WT KEYBOARDS + +K52: ; NOT A NUMPAD KEY RWV 7-30-85 + CMP AL,86 ; IS IT THE NEW WT KEY? RWV 7-30-85 + JNE K53 ; JUMP IF NOT RWV 7-30-85 + MOV AL,58 ; WE'RE GOING TO PULL A SNEAKY RWV 8-06-85 + JMP K45 ; TRICK HERE. WT TABLES ARE TOO SHORT TO + ; XLATE 86, SO WE'LL CHANGE IT TO CAPS_LOCK + ; AND PUT THE CHAR IN THE TABLES IN THE C_L + ; POSITION, SINCE C_L SCAN CODES NEVER GET + ; HERE ANYWAY. RWV 8-06-85 + +;------ MUST BE F11 OR F12 + +K53: TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 THERE? RWV 11-06-85 +;*** CNS + JZ K59 ; NO, INGORE F11 & F12 (NEAR RET) RWV 11-06-85 + ; F1 - F10 COME HERE, TOO RWV 7-30-85 +K53A: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;TEST SHIFT STATE RWV 7-30-85 + JZ K49 ; JUMP, LOWERCASE PSEUDO SC'S RWV 7-30-85 + + MOV BX,OFFSET K11 ; UPPER CASE PSEUDO SCAN CODES + JMP SHORT K64 ; TRANSLATE_SCAN +PAGE +;------ TRANSLATE THE CHARACTER + +K56: ; TRANSLATE-CHAR + DEC AL ; CONVERT ORIGIN + XLAT CS:K11 ; CONVERT THE SCAN CODE TO ASCII +K56C: TEST KB_FLAG_3,LC_E0 ; IS THIS A NEW KEY? RWV 10-08-85 + JZ K57 ; NO, GO FILL BUFFER RWV 10-04-85 + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 THERE? RWV 11-06-85 + JZ K57 ; NO, DO COMPATIBLE OUTPUT RWV 11-06-85 + MOV AH,MC_E0 ; YES, PUT SPECIAL MARKER IN AH RWV 10-04-85 + JMP SHORT K57 ; PUT IT INTO THE BUFFER + +;------ TRANSLATE SCAN FOR PSEUDO SCAN CODES + +K64: ; TRANSLATE-SCAN-ORGD + DEC AL ; CONVERT ORIGIN RWV 8-06-85 + XLAT CS:K8 ; CTL TABLE SCAN + MOV AH,AL ; PUT VALUE INTO AH + MOV AL,0 ; ZERO ASCII CODE + TEST KB_FLAG_3,LC_E0 ; IS THIS A NEW KEY? RWV 10-08-85 + JZ K57 ; NO, GO FILL BUFFER RWV 10-04-85 + TEST CS:SD.SYSTEM_FLAG,EXT_16 ; IS THE EXTENDED INT 16 THERE? RWV 11-06-85 + JZ K57 ; NO, DO COMPATIBLE OUTPUT RWV 11-06-85 + MOV AL,MC_E0 ; YES, PUT SPECIAL MARKER IN AL RWV 10-04-85 + +;------ PUT CHARACTER INTO BUFFER + +K57: ; BUFFER-FILL + CALL BUFFER_FILL ;; +K59: ;; + RET ;; return to unload the buffer +;OLDK59: +; JMP PREP_EXIT ;; THAT'S ALL FOLKS + + ;; + ;; +KEYB_INT_9 ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: BUFFER_FILL +;; +;; Description: +;; Generate keyboard buffer entry +;; +;; Input Registers: +;; AX - the buffer entry +;; DS - BIOS data segment +;; +;; Output Registers: +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +BUFFER_FILL PROC NEAR ;; + ;; + CMP AL,-1 ;; IS THIS AN IGNORE CHAR + JE K61B ;; YES, EXIT + CMP AH,-1 ;; LOOK FOR -1 PSEUDO SCAN + JE K61B ;; EXIT +;; +;; BUFFER_FILL_ANY_CHAR is an alternate entry point to this PROC. +;; Entry at this point will avoid trashing ASCII values of 255. +;; +BUFFER_FILL_ANY_CHAR LABEL NEAR ;; + ;; + PUSH SI ;; + PUSH BX ;; + PUSH DS ;; This routine may be called + PUSH AX ;; externally so make sure DS points + MOV AX,DATA ;; to BIOS data + MOV DS,AX ;; + POP AX ;; + ;; + CLC ;; + + MOV BX,BUFFER_TAIL ; GET THE END POINTER TO THE BUFFER + MOV SI,BX ; SAVE THE VALUE + INC BX ;; MOVE TO NEXT WORD IN LIST + INC BX ;; + ;; +;; VERIFY IF THE CURRENT ROM LEVEL IN THE SYSTEM IS FOR THE ORIGINAL PC1 + ;; + PUSH AX ;; SAVE AX,DS + PUSH DS ;; + MOV AX,ROM_SEG ;; SET DS TO POINT AT BIOS ROM SEGMENT + MOV DS,AX ;; TEST FOR PC1 ROM INSTALLED + CMP WORD PTR DS:SYSROM_DATE,PC1DATE_ID + POP DS ;; RESTORE DS,AX + POP AX ;; + JNE NOT_PC1 ;; IF IT'S A LATER ROM RELEASE, BRANCH + ;; + CMP BX,OFFSET KB_BUFFER_END ; AT END OF BUFFER? + JNE K5 ;; NO, CONTINUE + MOV BX,OFFSET KB_BUFFER ;; YES, RESET TO BUFFER BEGINNING + JMP K5 ;; +NOT_PC1: ;; + CMP BX,BUFFER_END ;; AT END OF BUFFER? + JNE K5 ;; NO, CONTINUE + MOV BX,BUFFER_START ;; YES, RESET TO BUFFER BEGINNING +K5: ;; + CMP BX,BUFFER_HEAD ;; HAS THE BUFFER WRAPPED AROUND + JE K62 ;; BUFFER_FULL_BEEP + MOV [SI],AX ;; STORE THE VALUE + MOV BUFFER_TAIL,BX ;; MOVE THE POINTER UP + MOV CS:BUFFER_ENTRY_OK,YES ;; INDICATE WE PUT SOMETHING IN BUFFER + JMP SHORT K61A +K62: + MOV CS:BEEP_PENDING,YES ;; INDICATE WE NEED A BEEP + TEST CS:SD.SYSTEM_FLAG,PC_JR ;; ON JR WE HAVE TO CLEAR SOME FLAGS + JZ K61A ;; + AND KB_FLAG,0F0H ;; CLEAR SHIFTS + AND KB_FLAG_1,0FH ;; + AND KB_FLAG_2,1FH ;; CLEAR FUNCTION STATES +K61A: ;; + POP DS ;; + POP BX ;; + POP SI ;; +K61B: ;; + RET ;; +BUFFER_FILL ENDP ;; +PAGE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: KB_NOISE +;; +;; Description: +;; General routine to generate beep tones +;; +;; Input Registers: +;; BX - length of tone +;; CX - tone frequency (larger CX = lower pitch) +;; +;; Output Registers: +;; AX,BX,CX trashed +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +BEEPING DB 0 ;; 1 if beep already in progress + ;; +KB_NOISE PROC ;; + CMP CS:BEEPING,0 ;; ARE WE BEEPING? + JE NOT_BEEPING_YET ;; + RET ;; YES - RETURN +NOT_BEEPING_YET: ;; + MOV CS:BEEPING,1 ;; beep in progress + ;; + STI ;; + ;; + IN AL,061H ;; Get control info + PUSH AX ;; +LOOP01: ;; + AND AL,0FCH ;; Turn off timer gate and speaker + OUT 061H,AL ;; output to control + PUSH CX ;; half cycle time for tone +LOOP02: ;; + LOOP LOOP02 ;; speaker off + OR AL,2 ;; turn on speaker + OUT 061H,AL ;; output to control + POP CX ;; + PUSH CX ;; +LOOP03: ;; + LOOP LOOP03 ;; another half cycle + DEC BX ;; time count + POP CX ;; another cycle + JNZ LOOP01 ;; + POP AX ;; + OUT 061H,AL ;; restore control + ;; + ;; + MOV CS:BEEPING,0 ;; indicate beep over + RET ;; +KB_NOISE ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: DUMBJMP +;; +;; Description: +;; Dummy JUMP used to allow smooth exit +;; for XT & older machines +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +DUMBJMP PROC ;; + JMP UP1 ;; ARE WE BEEPING? +DUMBJMP ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: ERROR_BEEP +;; +;; Description: +;; Call KB_NOISE to generate a beep. +;; +;; Input Registers: +;; None +;; +;; Output Registers: +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; +ERROR_BEEP PROC NEAR ;; + ;; + PUSH AX ;; SAVE REGS + PUSH BX ;; + PUSH CX ;; + ;; +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ;; ENABLE INTR. CTL. CHIP + OUT INTA00,AL ;; +;***CNS + JMP SHORT $+2 +;***CNS + ;; + TEST CS:SD.SYSTEM_FLAG,PC_JR + JZ EB_TEST_1 ;; The JR + MOV BX,80H ;; NUMBER OF CYCLES FOR 1/8 SECOND TONE + MOV CX,021H ;; FREQUENCY + JMP SHORT BEEP_IT ;; +EB_TEST_1: ;; + TEST CS:SD.SYSTEM_FLAG,PC_XT+PC_PAL+PC_LAP + JZ EB_TEST_2 ;; 8088/8886 MACHINE + MOV BX,80H ;; NUMBER OF CYCLES FOR 1/8 SECOND TONE + MOV CX,048H ;; FREQUENCY + JMP SHORT BEEP_IT ;; +EB_TEST_2: ;; + TEST CS:SD.SYSTEM_FLAG,PC_386 + JZ EB_TEST_3 ;; 386 MACHINE + MOV BX,80H ;; + MOV CX,19CH ;; FREQUENCY + JMP SHORT BEEP_IT ;; +EB_TEST_3: ;; + MOV BX,80H ;; DEFAULT TO 286 MACHINE + MOV CX,0CEH ;; FREQUENCY +BEEP_IT: ;; + CALL KB_NOISE ;; + ;; + POP CX ;; RESTORE REGS + POP BX ;; + POP AX ;; + RET ;; RETURN +ERROR_BEEP ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; SHIP_IT +;; +;; THIS ROUTINE HANDLES TRANSMISSION OF COMMAND AND DATA BYTES +;; TO THE KEYBOARD CONTROLLER. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SHIP_IT PROC NEAR ;; + ;; +;------- TEST SYSTEM TYPE ;; + ;; + TEST CS:SD.SYSTEM_FLAG,PC_AT+PC_386 ; IF THE SYSTEM WE'RE RUNNING ON IS A + JNZ SI1 ;; PCAT, EXECUTE THIS ROUTINE, + RET ;; ELSE RET + ;; + ;; +SI1: PUSH AX ;; SAVE DATA TO SEND + ;; +;;;-- WAIT FOR COMMAND TO BE ACCEPTED ;; + CLI ;; DISABLE INTERRUPTS + ;; + CALL WAIT_ON_STATUS_PORT ;; + ;; + POP AX ;; GET DATA TO SEND + OUT STATUS_PORT,AL ;; SEND TO KEYBOARD CONTROLLER + STI ;; ENABLE INTERRUPTS AGAIN + RET ;; RETURN TO CALLER +SHIP_IT ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Procedure: WAIT_ON_STATUS_PORT +;; +;; Description: +;; Waits for a keyboard command to be accepted +;; +;; Input Registers: +;; None +;; +;; Output Registers: +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +WAIT_ON_STATUS_PORT PROC NEAR ;; + ;; +;---- WAIT FOR COMMAND TO BE ACCEPTED ;; + ;; + MOV CX,CS:SD.TIMING_FACTOR ;; PROCESSOR SCALE FACTOR; PCAT = 1 +W01: ;; + PUSH CX ;; + SUB CX,CX ;; +W02: ;; + IN AL,STATUS_PORT ;; + TEST AL,INPT_BUF_FULL ;; + LOOPNZ W02 ;; WAIT FOR COMMAND TO BE ACCEPTED + POP CX ;; + LOOPNZ W01 ;; + ;; + RET ;; + ;; +WAIT_ON_STATUS_PORT ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; SND_DATA +;; +;; THIS ROUTINE HANDLES TRANSMISSION OF COMMAND AND DATA BYTES +;; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO +;; HANDLES ANY RETRIES IF REQUIRED +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SND_DATA PROC NEAR ;; + PUSH AX ;; SAVE REGISTERS + PUSH BX ;; * + PUSH CX ;; + MOV BH,AL ;; SAVE TRANSMITTED BY FOR RETRIES + MOV BL,3 ;; LOAD RETRY COUNT +SD0: CLI ;; DISABLE INTERRUPTS + AND KB_FLAG_2,NOT (KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS + ;; + CALL WAIT_ON_STATUS_PORT ;; + ;; + MOV AL,BH ;; REESTABLISH BYTE TO TRANSMIT + OUT PORT_A,AL ;; SEND BYTE + STI ;; ENABLE INTERRUPTS + MOV AX,01A00H ;; LOAD COUNT FOR 10mS+ + MUL CS:SD.TIMING_FACTOR ;; ACCOUNT FOR PROCESSOR SPEED + MOV CX,AX ;; +SD1: TEST KB_FLAG_2,KB_FE+KB_FA ;; SEE IF EITHER BIT SET + JNZ SD3 ;; IF SET, SOMETHING RECEIVED GO PROCESS + ;; + LOOP SD1 ;; OTHERWISE WAIT + ;; +SD2: DEC BL ;; DECREMENT RETRY COUNT + JNZ SD0 ;; RETRY TRANSMISSION + ;; + OR KB_FLAG_2,KB_ERR ;; TURN ON TRANSMIT ERROR FLAG + JMP SHORT SD4 ;; RETRIES EXHAUSTED FORGET TRANSMISSION + ;; +SD3: TEST KB_FLAG_2,KB_FA ;; SEE IF THIS IS AN ACKNOWLEDGE + JZ SD2 ;; IF NOT, GO RESEND + ;; +SD4: POP CX ;; RESTORE REGISTERS + POP BX ;; + POP AX ;; * + RET ;; RETURN, GOOD TRANSMISSION +SND_DATA ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; SND_LED +;; +;; THIS ROUTINE TURNS ON THE MODE INDICATORS. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SND_LED PROC NEAR ;; + CLI ;; TURN OFF INTERRUPTS + TEST KB_FLAG_2,KB_PR_LED ;; CHECK FOR MODE INDICATOR UPDATE + JNZ SL1 ;; DONT UPDATE AGAIN IF UPDATE UNDERWAY + ;; + OR KB_FLAG_2,KB_PR_LED ;; TURN ON UPDATE IN PROCESS +;***CNS + JMP SHORT $+2 +;***CNS + MOV AL,EOI ;; END OF INTERRUPT COMMAND + OUT 020H,AL ;; SEND COMMAND TO INTERRUPT CONTROL PORT +;***CNS + JMP SHORT $+2 +;***CNS + JMP SHORT SL0 ;; GO SEND MODE INDICATOR COMMAND + ;; +SND_LED1: ;; + CLI ;; TURN OFF INTERRUPTS + TEST KB_FLAG_2,KB_PR_LED ;; CHECK FOR MODE INDICATOR UPDATE + JNZ SL1 ;; DONT UPDATE AGAIN IF UPDATE UNDERWAY + ;; + OR KB_FLAG_2,KB_PR_LED ;; TURN ON UPDATE IN PROCESS +SL0: MOV AL,LED_CMD ;; LED CMD BYTE + CALL SND_DATA ;; SEND DATA TO KEYBOARD + CLI ;; + CALL MAKE_LED ;; GO FORM INDICATOR DATA BYTE + AND KB_FLAG_2,0F8H ;; CLEAR MODE INDICATOR BITS + OR KB_FLAG_2,AL ;; SAVE PRESENT INDICATORS STATES FOR NEXT TIME + TEST KB_FLAG_2,KB_ERR ;; TRANSMIT ERROR DETECTED + JNZ SL2 ;; IF YES, BYPASS SECOND BYTE TRANSMISSION + ;; + CALL SND_DATA ;; SEND DATA TO KEYBOARD + CLI ;; TURN OFF INTERRUPTS + TEST KB_FLAG_2,KB_ERR ;; TRANSMIT ERROR DETECTED + JZ SL3 ;; IF NOT, DONT SEND AN ENABLE COMMAND + ;; +SL2: MOV AL,KB_ENABLE ;; GET KEYBOARD CSA ENABLE COMMAND + CALL SND_DATA ;; SEND DATA TO KEYBOARD + CLI ;; TURN OFF INTERRUPTS +SL3: AND KB_FLAG_2,NOT(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR + ;; UPDATE AND TRANSMIT ERROR FLAG +SL1: STI ;; ENABLE INTERRUPTS + RET ;; RETURN TO CALLER +SND_LED ENDP ;; +PAGE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; MAKE_LED +;; +;; THIS ROUTINE FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF +;; THE MODE INDICATORS +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +MAKE_LED PROC NEAR ;; + PUSH CX ;; SAVE CX + MOV AL,KB_FLAG ;; GET CAPS & NUM LOCK INDICATORS + AND AL,CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS + MOV CL,4 ;; SHIFT COUNT + ROL AL,CL ;; SHIFT BITS OVER TO TURN ON INDICATORS + AND AL,07H ;; MAKE SURE ONLY MODE BITS ON + POP CX ;; + RET ;; RETURN TO CALLER +MAKE_LED ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;CNS*** + +CODE ENDS + END diff --git a/v4.0/src/CMD/KEYB/KEYBI9C.INC b/v4.0/src/CMD/KEYB/KEYBI9C.INC new file mode 100644 index 0000000..7848a1b --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBI9C.INC @@ -0,0 +1,41 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBI9C.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; External declarations and equates for procedures in file +;; KEYBI9C.ASM +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN KEYB_INT_9:NEAR ;; + EXTRN BUFFER_FILL:NEAR ;; + EXTRN ERROR_BEEP :NEAR ;; + EXTRN COUNTRY_FLAG:BYTE ;; + EXTRN BEEP_PENDING:BYTE ;; + EXTRN SCAN_CODE:BYTE ;; + EXTRN K8:BYTE ;; + EXTRN TEMP_HEAD:WORD ;; + EXTRN TEMP_TAIL:WORD ;; + EXTRN BUSY_TFLAG:BYTE ;; + EXTRN MYBUFF:BYTE ;; + EXTRN ENABLE_FL:BYTE ;; + EXTRN NEW_BUFF_CTR :BYTE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBMAC.INC b/v4.0/src/CMD/KEYB/KEYBMAC.INC new file mode 100644 index 0000000..5666666 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBMAC.INC @@ -0,0 +1,319 @@ +.XLIST +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - Keyboard Definition File +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBMAC.INC +;; ---------- +;; +;; Description: +;; ------------ +;; Include file containing macros for the Keyboard Definition File. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dead key flags +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +ACUTE EQU 80H ;; NLS_FLAG_1 +GRAVE EQU 40H ;; +DIARESIS EQU 20H ;; +CIRCUMFLEX EQU 10H ;; +CEDILLA EQU 08H ;; +TILDE EQU 04H ;; + ;; NLS_FLAG_2 : nothing defined yet + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; State IDs +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +DEAD_LOWER EQU 1 ;; dead keys on lower shift +DEAD_UPPER EQU 2 ;; +ALPHA_LOWER EQU 3 ;; +ALPHA_UPPER EQU 4 ;; +NON_ALPHA_LOWER EQU 5 ;; +NON_ALPHA_UPPER EQU 6 ;; +THIRD_SHIFT EQU 7 ;; +ACUTE_LOWER EQU 8 ;; +ACUTE_UPPER EQU 9 ;; +ACUTE_SPACE EQU 10 ;; +GRAVE_LOWER EQU 11 ;; +GRAVE_UPPER EQU 12 ;; +GRAVE_SPACE EQU 13 ;; +DIARESIS_LOWER EQU 14 ;; +DIARESIS_UPPER EQU 15 ;; +DIARESIS_SPACE EQU 16 ;; +CIRCUMFLEX_LOWER EQU 17 ;; +CIRCUMFLEX_UPPER EQU 18 ;; +CIRCUMFLEX_SPACE EQU 19 ;; +CEDILLA_LOWER EQU 20 ;; +CEDILLA_UPPER EQU 21 ;; +CEDILLA_SPACE EQU 22 ;; +CEDILLA_CEDILLA EQU 23 ;; +DEAD_THIRD EQU 24 ;; +ACUTE_ACUTE EQU 25 ;; +GRAVE_GRAVE EQU 26 ;; +DIARESIS_DIARESIS EQU 27 ;; +CIRCUMFLEX_CIRCUMFLEX EQU 28 ;; +FOURTH_SHIFT EQU 29 ;; +DEAD_FOURTH EQU 30 ;; +TILDE_LOWER EQU 31 ;; +TILDE_UPPER EQU 32 ;; +TILDE_SPACE EQU 33 ;; +ALT_CASE EQU 34 ;; +CTRL_CASE EQU 35 ;; +NUMERIC_PAD EQU 36 ;; +DIVIDE_SIGN EQU 37 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Logic Macros +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + +UNKNOWN = 255 + +FIND_FLAG MACRO FLAG_MASK + IFIDN , + FLAG_ID = EXT_KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = EXT_KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = EXT_KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = EXT_KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_3_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_3_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = NLS_FLAG_1_ID + ELSE + IFIDN , + FLAG_ID = KB_FLAG_3_ID + ELSE + FLAG_ID = UNKNOWN + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +FLAG MACRO FLAG_MASK + FIND_FLAG FLAG_MASK + IF (FLAG_ID EQ UNKNOWN) + IF2 + %OUT Unknown parameter FLAG_MASK on FLAG MACRO + ENDIF + ELSE + DB FLAG_ID + DB FLAG_MASK + ENDIF + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IFF MACRO FLAG_MASK,MASK_TYPE + MAC_OK = 1 + IFB + NOT_BIT = 00000000B + ELSE + IFIDN , + NOT_BIT = 00001000B + ELSE + MAC_OK = 0 + IF2 + %OUT Unknown parameter MASK_TYPE on IFF MACRO + ENDIF + ENDIF + ENDIF + IF MAC_OK + FIND_FLAG FLAG_MASK + IF (FLAG_ID EQ UNKNOWN) + IF2 + %OUT Unknown parameter FLAG_MASK on IFF MACRO + ENDIF + ELSE + DB IFF_COMMAND+NOT_BIT+FLAG_ID + DB FLAG_MASK + ENDIF + ENDIF + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +IFKBD MACRO SYS + DB IFKBD_COMMAND + DW SYS + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ANDF MACRO FLAG_MASK,MASK_TYPE + MAC_OK = 1 + IFB + NOT_BIT = 00000000B + ELSE + IFIDN , + NOT_BIT = 00001000B + ELSE + MAC_OK = 0 + IF2 + %OUT Unknown parameter MASK_TYPE on ANDF MACRO + ENDIF + ENDIF + ENDIF + IF MAC_OK + FIND_FLAG FLAG_MASK + IF (FLAG_ID EQ UNKNOWN) + IF2 + %OUT Unknown parameter FLAG_MASK on ANDF MACRO + ENDIF + ELSE + DB ANDF_COMMAND+NOT_BIT+FLAG_ID + DB FLAG_MASK + ENDIF + ENDIF + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ELSEF MACRO + DB ELSEF_COMMAND + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ENDIFF MACRO + DB ENDIFF_COMMAND + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +XLATT MACRO STATE + DB XLATT_COMMAND + DB STATE + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PUT_ERROR_CHAR MACRO STATE + DB PUT_ERROR_COMMAND + DB STATE + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +OPTION MACRO MASK,MASK_TYPE + MAC_OK = 1 + IFB + NOT_BIT = 00000000B + ELSE + IFIDN , + NOT_BIT = 00001000B + ELSE + MAC_OK = 0 + IF2 + %OUT Unknown parameter MASK_TYPE on OPTION MACRO + ENDIF + ENDIF + ENDIF + IF MAC_OK + DB OPTION_COMMAND+NOT_BIT + DB MASK + ENDIF + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SET_FLAG MACRO STATE + DB SET_FLAG_COMMAND + DB STATE + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +RESET_NLS MACRO + DB RESET_NLS_COMMAND + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BEEP MACRO + DB BEEP_COMMAND + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +GOTO MACRO GOTO_OFFSET + DB GOTO_COMMAND + DW GOTO_OFFSET-$-2 + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +EXIT_INT_9 MACRO + DB GOTO_COMMAND+EXIT_INT_9_FLAG + DW 0 + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +EXIT_STATE_LOGIC MACRO + DB GOTO_COMMAND+EXIT_STATE_LOGIC_FLAG + DW 0 + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CHECK_FOR_CORE_KEY MACRO + DB CHECK_CORE_COMMAND + ENDM + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST diff --git a/v4.0/src/CMD/KEYB/KEYBMSG.INC b/v4.0/src/CMD/KEYB/KEYBMSG.INC new file mode 100644 index 0000000..3bcb061 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBMSG.INC @@ -0,0 +1,44 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBMSG.INC +;; ---------- +;; +;; Root File Name: KEYBCMD.ASM (KEYB.ASM) +;; --------------- +;; +;; Description: +;; ------------ +;; External declarations for procedures in file KEYBCMD.ASM. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN ACT_KEYB_CP :BYTE ;; + EXTRN ACT_CON_CP :BYTE ;; + EXTRN ACT_KEYB :BYTE ;; + EXTRN INV_L :BYTE ;; + EXTRN INV_I :BYTE ;; + EXTRN INV_CP :BYTE ;; + EXTRN INV_S :BYTE ;; + EXTRN INV_FN :BYTE ;; + EXTRN INV_KEYB_Q :BYTE ;; + EXTRN INV_CON_Q :BYTE ;; + EXTRN NOT_DESIG :BYTE ;; + EXTRN NOT_SUPP :BYTE ;; + EXTRN NOT_VALID1 :BYTE ;; + EXTRN NOT_VALID2 :BYTE ;; + EXTRN WARNING_1 :BYTE ;; + EXTRN INV_COMBO :BYTE ;; + EXTRN CR_LF :BYTE ;; + EXTRN MEMORY_OVERF :BYTE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.LIST diff --git a/v4.0/src/CMD/KEYB/KEYBSHAR.INC b/v4.0/src/CMD/KEYB/KEYBSHAR.INC new file mode 100644 index 0000000..75bbc13 --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBSHAR.INC @@ -0,0 +1,307 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBSHAR.INC +;; ---------- +;; +;; Description: +;; ------------ +;; Include file containing structure definitions Shared Data Area +;; for the Shared Data Area. +;; The Shared Data Area contains data which is required by +;; both the resident and transient KEYB code. The Shared +;; Data Area is allocated in the KEYBI2F file and will be +;; resident following initial installation. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; SHARED_DATA_STR defines the initial fixed length portion of the +;; Shared Data Area. +;; Tables are loaded beginning at TABLE_AREA in the following order: +;; State Logic +;; Common Translate Section +;; Specific Translate Sections for +;; each code page +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; SPECIAL_FEATURES equates: +TYPEWRITER_CAPS_LK EQU 8000H ;; typewriter style caps lock +JR_HOT_KEY_1_2 EQU 4000H ;; on PCjr use 1/2 as the hot keys + ;; instead of F1/F2 + ;; + ;; Some useful scan codes: +F1_SCAN EQU 59 ;; F1 +F2_SCAN EQU 60 ;; F2 +ONE_SCAN EQU 2 ;; "1" +TWO_SCAN EQU 3 ;; "2" + ;; + ;; SYSTEM_FLAG equates: +EXT_16 EQU 8000H ;; extended int16 support is there +PC_AT EQU 4000H ;; code for pcat +PC_LAP EQU 2000H ;; code for pc lap computer (p-12) +PC_XT EQU 1000H ;; code for PC, PC/XT, PORTABLE +PC_JR EQU 0800H ;; code for PCjr +PC_PAL EQU 0400H ;; code for PALACE +PC_386 EQU 0200H ;; code for WRANGLER +PC_NET EQU 0100H ;; PC Net is installed + ;; + ;; HOT_KEY_FLAG EQUATES: +US_MODE EQU 0 ;; hot key is active => US +LANG_MODE EQU 0FFH ;; hot key is inactive + ;; + ;; ----------------------------------- +SHARED_DATA_STR STRUC ;; SHARED DATA AREA + ;; +OLD_INT_9 DD 0 ;; saved int 9 vector +OLD_INT_2F DD 0 ;; saved int 2F vector +OLD_INT_48 DD 0 ;; saved int 48 vector (if PCjr) +KEYB_TYPE DW 0 ;; type of keyboard +SYSTEM_FLAG DW 0 ;; system configuration flags +TABLE_OK DB 0 ;; flag to INT 9 that table is built +JR_KB_FLAG DB 0 ;; flag for special PCjr processing +TIMING_FACTOR DW 1 ;; Scale factor for INT 9 timing loops + ;; PC_AT = 1 + DB 2 DUP(0) ;; reserved + ;; + ;; Table copy begins here: +ACTIVE_LANGUAGE DB 'US' ;; language code +INVOKED_CP_TABLE DW 437 ;; ptr to table for invoked code page +INVOKED_KBD_ID DW 0 ;; WGR invoked keyboard id. ;AN000 +ACTIVE_XLAT_PTR DW -1 ;; ptr to active Specific Translate Sect +FIRST_XLAT_PTR DW -1 ;; ptr to first Specific Translate Sect +RESIDENT_END DW 0ffffh ;; offset of last byte in resident mem +LOGIC_PTR DW -1 ;; ptr to State Logic +COMMON_XLAT_PTR DW -1 ;; ptr to Common Translate Section +SPECIAL_FEATURES DW ? ;; special Features +TABLE_OVERFLOW DB 0 ;; overflow flag for table rebuild +HOT_KEY_ON_SCAN DB ? ;; scan codes to use with ALT+CTRL +HOT_KEY_OFF_SCAN DB ? ;; to turn hot key on and off + DB 4 DUP(0) ;; reserved +TABLE_AREA DB ? ;; tables loaded here: + ;; State Logic + ;; Common Translate Section + ;; Specific Translate Sections for + ;; each code page +SHARED_DATA_STR ENDS ;; + ;; + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; State Logic equates. +;; Contains equates for our NLS Flags and for the State Logic +;; commands. +;; State Logic command macros are defined in KEYBMAC.INC +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +STATE_LOGIC_STR STRUC ;; + ;; +SL_LOGIC_LEN DW ? ;; length of state logic +SL_SPECIAL_FEATURES DW ? ;; +SL_LOGIC_CMDS DB 0 ;; state logic commands begin here + ;; +STATE_LOGIC_STR ENDS ;; + ;; + ;; +NUM_BIOS_FLAGS EQU 4 ;; +NUM_NLS_FLAGS EQU 2 ;; '+1' below is the EXT_KB_FLAG +NUM_FLAGS EQU NUM_BIOS_FLAGS+NUM_NLS_FLAGS+1 + ;; + ;; +EITHER_SHIFT EQU 80H ;; EXT_KB_FLAG : our own shift state +EITHER_CTL EQU 40H ;; flags +EITHER_ALT EQU 20H ;; +SCAN_MATCH EQU 08H ;; set if scan code found in XLATT + ;; or SET_FLAG searches + ;; + ;; +KB_FLAG_ID EQU 0 ;; Flag ID's as coded in IFF and ANDF +KB_FLAG_1_ID EQU 1 ;; commands +KB_FLAG_2_ID EQU 2 ;; +KB_FLAG_3_ID EQU 3 ;; +EXT_KB_FLAG_ID EQU 4 ;; +NLS_FLAG_1_ID EQU 5 ;; +NLS_FLAG_2_ID EQU 6 ;; + ;; +COMMAND_BITS EQU 0F0H ;; Mask to isolate command code +SUB_CMD_BITS EQU 0FH ;; mask to isolate sub command code +NOT_TEST EQU 08H ;; NOT bit in IFF, ANDF +COMMAND_SHIFT EQU 4 ;; shift amount for command code +FLAG_ID_BITS EQU 07H ;; mask to isolate flag id in IFF, ANDF +NUM_COMMANDS EQU 0CH ;; number of commands + ;; +IFF_COMMAND EQU 00H ;; +ANDF_COMMAND EQU 10H ;; +ELSEF_COMMAND EQU 20H ;; +ENDIFF_COMMAND EQU 30H ;; +XLATT_COMMAND EQU 40H ;; +OPTION_COMMAND EQU 50H ;; +SET_FLAG_COMMAND EQU 60H ;; +PUT_ERROR_COMMAND EQU 70H ;; +IFKBD_COMMAND EQU 80H ;; +GOTO_COMMAND EQU 90H ;; +BEEP_COMMAND EQU 0A0H ;; +RESET_NLS_COMMAND EQU 0B0H ;; +CHECK_CORE_COMMAND EQU 0C0H ;; + ;; + ;; +EXIT_INT_9_FLAG EQU 01H ;; Special forms of GOTO. These +EXIT_STATE_LOGIC_FLAG EQU 02H ;; values are in the right nibble + ;; of the GOTO command. + ;; + ;; PROCESSING OPTIONS: +EXIT_IF_FOUND EQU 80H ;; exit INT 9 if a translation + ;; match is found + ;; +ANY_KB EQU 0FFFFH ;; +JR_KB EQU 8000H ;; Keyboard types +XT_KB EQU 4000H ;; +AT_KB EQU 2000H ;; +G_KB EQU 1000H ;; +P_KB EQU 0800H ;; +P12_KB EQU 0400H ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Translate Table Sections. Both the Specific and Common +;; Translate Sections are formatted as follows. +;; +;; The Specific Translate Sections are chained together using the +;; XS_NEXT_SECT_PTR field (-1 if last section). +;; Translate Sections contains multiple States. +;; A State contains the translate tables for a single +;; shift state (IE lower case, upper case ....) +;; Each State may contain multiple translate tables. +;; +;; The Translate Section layout is defined using several STRUCs. +;; These STRUCs are allocated in the Shared Data Area as follows: +;; +;; XLAT_SECT_STR ; header info for the section +;; STATE_STR ; header for state #1 +;; XLAT_STR ; first translate tab for state #1 +;; XLAT_TYPE_1_STR or XLAT_TYPE_2_STR +;; XLAT_STR ; second translate tab +;; XLAT_TYPE_1_STR or XLAT_TYPE_2_STR +;; ... +;; STATE_STR ; header for state #2 +;; XLAT_STR +;; XLAT_TYPE_1_STR or XLAT_TYPE_2_STR +;; ... +;; ... +;; +;; A State may contain a "Set_Flag" table instead of translate tables. +;; These tables are used to set the NLS flags instead of generating +;; ASCII codes (for example: to remember dead key states). +;; There can be only on Set_Flag table per state. +;; The Set_Flag table layout is defined in the SET_FLAG_STR STRUC. +;; +;; So some states will contain translate tables (to generate ASCII codes) +;; and some states will contain a Set_Flag table (to record dead key +;; status). +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +XLAT_SECT_STR STRUC ;; + ;; +XS_NEXT_SECT_PTR DW ? ;; Pointer to next Specific Translate + ;; Section +XS_CP_ID DW ? ;; code page id +XS_FIRST_STATE DB ? ;; + ;; +XLAT_SECT_STR ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; State structure. +;; The last State is a null State containing only the +;; XS_STATE_LEN field with a value of 0. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +STATE_STR STRUC ;; + ;; +XS_STATE_LEN DW ? ;; length of state section +XS_STATE_ID DB ? ;; State ID +XS_KBD_TYPE DW ? ;; Keyboard Type +XS_ERROR_CHAR DW ? ;; Buffer entry for error character +XS_FIRST_TAB DB ? ;; + ;; +STATE_STR ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Translate Table structures. +;; There may be many translate tables in a State. The last +;; table is a null table containing only the XLAT_TAB_SIZE field with +;; a value of 0. +;; The xlate table can be in one of two forms: +;; Type 1 = Table contains buffer entries only. +;; Scan code is used as an index into xlat table +;; Type 2 = Table contains pairs of SCAN/BUFFER_ENTRY. +;; Table must be searched for matching scan. +;; Type 1 is the default. Type 2 tables should be identified by setting +;; the TYPE_2_TAB bit in XLAT_OPTIONS. +;; Buffer entries default to 2-bytes per entry. +;; Optionally the table may contain ASCII codes only +;; (1-byte entries). This is specified by setting the ASCII_ONLY bit +;; in XLAT_OPTIONS. 2-byte buffer entries are coded ASCII,SCAN. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; Translate options: +ASCII_ONLY EQU 80H ;; Only ASCII codes listed - use + ;; incoming scan for buffer entry +TYPE_2_TAB EQU 40H ;; search xlat table for matching scan +ZERO_SCAN EQU 20H ;; set the scan half of the buffer + ;; entry to 0 + ;; +NULL_ASCII_CODE EQU -1 ;; + ;; +DEFAULT_TAB_2_ENT_SZ EQU 3 ;; +ASC_ONLY_TAB_2_ENT_SZ EQU 2 ;; + ;; + ;; +XLAT_STR STRUC ;; + ;; +XLAT_TAB_SIZE DW ? ;; Size in bytes of this table - + ;; includes this field, options etc. +XLAT_OPTIONS DB ? ;; xlat options + ;; XLAT TABLE IS HERE +XLAT_STR ENDS ;; + ;; +XLAT_TYPE_1_STR STRUC ;; use scan code as index into table + DB TYPE XLAT_STR DUP(?) ;; filler +XLAT_SCAN_LO DB ? ;; Scan code +XLAT_SCAN_HI DB ? ;; range +XLAT_1_BUF_ENTRY DB ? ;; The table itself +XLAT_TYPE_1_STR ENDS ;; + ;; +XLAT_TYPE_2_STR STRUC ;; search table for scan + DB TYPE XLAT_STR DUP(?) ;; filler +XLAT_NUM DB ? ;; number of scans +XLAT_SCAN DB ? ;; Scan code +XLAT_2_BUF_ENTRY DB ? ;; The table itself +XLAT_TYPE_2_STR ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Set_Flag Tables. +;; State Sections immediately following the LAST_ENTRYs. +;; Dead key definitions. If the scan matches then +;; set the bit in NLS_FLAGs indicated in DK_MASK +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SF_ENT_SZ EQU 3 ;; size of entry + ;; +SET_FLAG_STR STRUC ;; + ;; +SF_NUM DB 0 ;; Number of entries +SF_SCAN_CODE DB 0 ;; scan code +SF_FLAG_ID DB 0 ;; flag id +SF_FLAG_MASK DB 0 ;; flag mask + ;; +SET_FLAG_STR ENDS ;; + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST diff --git a/v4.0/src/CMD/KEYB/KEYBSYS.INC b/v4.0/src/CMD/KEYB/KEYBSYS.INC new file mode 100644 index 0000000..4b42fbe --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBSYS.INC @@ -0,0 +1,137 @@ +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBSYS.INC +;; ---------- +;; +;; Root File Name: KEYB.ASM +;; --------------- +;; +;; Description: +;; ------------ +;; Include file containing structure definitions and equates +;; for the KEYBOARD.SYS file. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; File header - contains pointers to keyboard tables for each language +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBSYS_HEADER STRUC ;; + ;; +KH_SIGNATURE DB 0FFh,'KEYB ' ;; signature +KH_RESV_1 DB 8 DUP(0) ;; reserved +KH_MAX_COM_SZ DW 0 ;AN000;**chg ;; maximum size of Common Xlat Sect +KH_MAX_SPEC_SZ DW 0 ;AN000;;**chg ;; max size of Specific Xlat Sect +KH_MAX_LOGIC_SZ DW 0 ;AN000;;**chg ;; max size of State Logic +KH_RESV_2 Dw 0 ;AN000;;**chg ;; reserved CNS +KH_NUM_ID Dw 0 ;AN000;;; ************* CNS +KH_NUM_LANG DW 0 ;; number of languages +KH_LANG_PTRS DB 0 ;; language pointers start here +;********************* CNS ********************** +;KH_NUM_ID DW 0 ;; number of languages +;KH_ID_PTRS DB 0 ;; id pointers start here +;********************* CNS ********************** +KEYBSYS_HEADER ENDS ;; +;******************CNS******************* +KEYBSYS_ID_PTRS STRUC + +KP_ID_CODE DW 0 ;AN000; +KP_LANG_PTR DD 0 ;AN000; + +KEYBSYS_ID_PTRS ENDS + ;; +;*****************CNS******************** +KEYBSYS_LANG_PTRS STRUC ;; + ;; Next two entries repeat: +KP_LANG_CODE DW 0 ;; language code +KP_ENTRY_PTR DD 0 ;; language entry pointer + ;; +KEYBSYS_LANG_PTRS ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Language Entry - pointed to by KH_ENTRY_PTR in KEYBSYS_HEADER +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBSYS_LANG_ENTRY STRUC ;; + ;; +KL_LANG_CODE DW 'XX' ;; language code +KL_ID_CODE DW 0 ;; reserved (ID CODE) +KL_LOGIC_PTR DD 0 ;AC000;;**chg ;; State Logic pointer +KL_NUM_ID DB 0 ;AN000;;CNS ;; number of valid IDs for this lang +KL_NUM_CP DB 0 ;; number of valid CPs for this lang +KL_CP_PTRS DB 0 ;; CP table pointers start here + ;; +KEYBSYS_LANG_ENTRY ENDS ;; + ;; +KEYBSYS_CP_PTRS STRUC ;; + ;; Next two entries repeat: +KC_CODE_PAGE DW 0 ;; code page +KC_ENTRY_PTR DD 0 ;; ptr to Specific Translate Section + ;; +KEYBSYS_CP_PTRS ENDS ;; + ;; + ;; +;; Everything from here down is new +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; State Logic - pointed to by KL_LOGIC_PTR in KEYBSYS_LANG_ENTRY +;; Common Translate Section follows immediately after the State Logic. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBSYS_STATE_LOGIC STRUC ;; + ;; +KT_LOGIC_LEN DW ? ;; length of state logic +KT_SPECIAL_FEATURES DW ? ;; Special Features (see KEYBSHAR.INC) +KT_LOGIC_CMDS DB 0 ;; state logic commands begin here + ;; +KEYBSYS_STATE_LOGIC ENDS ;; + ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Translate Section - Common and Specific Translate Sections +;; are both in this form. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBSYS_XLAT_SECT STRUC ;; + ;; +KX_SECTION_LEN DW ? ;; Length of this section +KX_CP_ID DW ? ;; code page id +KX_FIRST_STATE DB ? ;; + ;; +KEYBSYS_XLAT_SECT ENDS ;; + ;; + ;; +KEYBSYS_STATE STRUC ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Translate Sections contains multiple States. + ;; A State contains the translate tables for a single + ;; shift state (IE lower case, upper case ....) + ;; The last State is a null State containing only the + ;; KX_STATE_LEN field with a value of 0. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; +KX_STATE_LEN DW ? ;; length of state section +KX_STATE_ID DB ? ;; State ID +KX_KBD_TYPE DW ? ;; Keyboard Type +KX_ERROR_CHAR DW ? ;; Buffer entry for error character +KX_FIRST_XLAT DB ? ;; XLAT tables begin here + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Each State consists of multiple translate tables. + ;; The last translate table within a state is a null + ;; table containing only the + ;; KX_XLAT_LEN field with a value of 0. + ;; Refer to KEYBSHAR.INC for translate table format. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +KEYBSYS_STATE ENDS ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST + diff --git a/v4.0/src/CMD/KEYB/KEYBTBBL.ASM b/v4.0/src/CMD/KEYB/KEYBTBBL.ASM new file mode 100644 index 0000000..b28f08c --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBTBBL.ASM @@ -0,0 +1,855 @@ + + PAGE ,132 + TITLE DOS KEYB Command - Transient Command Processing + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBTBBL.ASM +;; ---------- +;; +;; Description: +;; ------------ +;; Build SHARED_DATA_AREA with parameters specified +;; in KEYBCMD.ASM +;; +;; Documentation Reference: +;; ------------------------ +;; None +;; +;; Procedures Contained in This File: +;; ---------------------------------- +;; TABLE_BUILD: Build the header sections of the SHARED_DATA_AREA +;; STATE_BUILD: Build the state sections in the table area +;; FIND_CP_TABLE: Given the language and code page parm, determine the +;; offset of the code page table in KEYBOARD.SYS +;; +;; Include Files Required: +;; ----------------------- +;; KEYBSHAR.INC +;; KEYBSYS.INC +;; KEYBDCL.INC +;; KEYBI2F.INC +;; +;; External Procedure References: +;; ------------------------------ +;; None +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + PUBLIC TABLE_BUILD ;; + PUBLIC FIND_CP_TABLE ;; + PUBLIC CPN_INVALID ;; + PUBLIC SD_LENGTH ;; + ;; +CODE SEGMENT PUBLIC 'CODE' ;; + ;; + INCLUDE KEYBEQU.INC ;; + INCLUDE KEYBSHAR.INC ;; + INCLUDE KEYBSYS.INC ;; + INCLUDE KEYBCMD.INC ;; + INCLUDE KEYBDCL.INC ;; + INCLUDE COMMSUBS.INC ;; + INCLUDE KEYBCPSD.INC ;; + ;; + ASSUME CS:CODE,DS:CODE ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: TABLE_BUILD +;; +;; Description: +;; Create the table area within the shared data structure. Each +;; table is made up of a descriptor plus the state sections. +;; Translate tables are found in the Keyboard definition file and are +;; copied into the shared data area by means of the STATE_BUILD +;; routine. +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to our data segment +;; BP - points at beginning of CMD_PARM_LIST +;; +;; SHARED_DATA_STR must be allocated in memory +;; +;; The following variables must also be passed from KEYB_COMMAND +;; KEYBSYS_FILE_HANDLE is set to file handle after opening file +;; CP_TAB_OFFSET is the offset of the CP table in the SHARED_DATA_AREA +;; STATE_LOGIC_OFFSET is the offset of the state section in the SHARED_DATA_AREA +;; SYS_CODE_PAGE is the binary representation of the system CP +;; KEYBCMD_LANG_ENTRY_PTR is a pointer to the lang entry in KEY DEF file +;; DESIG_CP_BUFFER is the buffer which holds a list of designated CPs +;; DESIG_CP_OFFSET:WORD is the offset of that list +;; NUM_DESIG_CP is the number of CPs designated +;; FILE_BUFFER is the buffer to read in the KEY DEF file +;**********CNS *************************************** +;; ID_PTR_SIZE is the size of the ID ptr structure +;**********CNS *************************************** +;; LANG_PTR_SIZE is the size of the lang ptr structure +;; CP_PTR_SIZE is the size of the CP ptr structure +;; NUM_CP is the number of CPs in the KEYB DEF file for that lang +;; SHARED_AREA_PTR segment and offset of the SHARED_DATA_AREA +;; +;; +;; Output Registers: +;; CX - RETURN_CODE := 0 - Table build successful +;; 1 - Table build unsuccessful - ERROR 1 +;; (Invalid language parm) +;; 2 - Table build unsuccessful - ERROR 2 +;; (Invalid Code Page parm) +;; 3 - Table build unsuccessful - ERROR 3 +;; (Machine type unavaliable) +;; 4 - Table build unsuccessful - ERROR 4 +;; (Bad or missing keyboard def file) +;; 5 - Table build unsuccessful - ERROR 5 +;; (Memory overflow occurred) +;; Logic: +;; Calculate Offset difference between TEMP and SHARED_DATA_AREAs +;; Get LANGUAGE_PARM and CODE_PAGE_PARM from parm list +;; Call FIND_CP_TABLE := Determine whether CP is valid for given language +;; IF CP is valid THEN +;; Store them in the SHARED_DATA_AREA +;; Prepare to read Keyboard definition file by LSEEKing to the top +;; READ the header +;; Store maximum table values for calculation of RES_END +;; Set DI to point at TABLE_AREA within SHARED_DATA_AREA +;; FOR the state logic section of the specified language: +;; IF STATE_LOGIC_PTR is not -1 THEN +;; LSEEK to state logic section in keyboard definition file +;; READ the state logic section into the TABLE_AREA +;; Set the hot keyb scan codes +;; Set the LOGIC_PTR in the header +;; FOR the common translate section: +;; IF Length parameter is not 0 THEN +;; Build state +;; Set the COMMON_XLAT_PTR in the header +;; FOR the specific translate sections: +;; Establish addressibility to list of designated code pages +;; FOR each code page +;; IF CP_ENTRY_PTR is not -1 THEN +;; Determine offset of CP table in Keyb Def file +;; IF CP table not avaliable THEN +;; Set CPN_INVALID flag +;; ELSE +;; LSEEK to CPn state section in keyboard definition file +;; IF this is the invoked code page THEN +;; Set ACTIVE_XLAT_PTR in SHARED_DATA_AREA +;; Update RESIDENT_END ptr +;; Build state +;; Update RESIDENT_END ptr +;; End +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FB EQU FILE_BUFFER ;; +KB_MASK EQU 02H ;; + ;; +FIRST_XLAT_TAB DW 0 ;; +NEXT_SECT_PTR DW -1 ;; + ;; +MAX_COM_SIZE DW ? ;; +MAX_SPEC_SIZE DW ? ;; +MAX_LOGIC_SIZE DW ? ;; + ;; +RESIDENT_END_ACC DW 0 ;; +SA_HEADER_SIZE DW SIZE SHARED_DATA_STR;; +PARM_LIST_OFFSET DW ? ;; +;********************CNS************************* +TB_ID_PARM DW 0 +;********************CNS************************* +TB_LANGUAGE_PARM DW 0 ;; +TB_CODE_PAGE_PARM DW 0 ;; + ;; +CPN_INVALID DW 0 ;; + ;; +KEYB_INSTALLED DW 0 ;; +SD_AREA_DIFFERENCE DW 0 ;; +SD_LENGTH DW 2000 ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +TABLE_BUILD PROC NEAR ;; + ;; + MOV AX,OFFSET SD_SOURCE_PTR ;; Setup the difference + SUB AX,OFFSET SD_DEST_PTR ;; value used to calculate + MOV SD_AREA_DIFFERENCE,AX ;; new ptr values for + ;; SHARED_DATA_AREA + MOV AX,[BP].ID_PARM ;; WGR Get id parameter ;AN000 + MOV TB_ID_PARM,AX ;; WGR ;AN000 + MOV AX,[BP].LANGUAGE_PARM ;; Get language parameter + MOV TB_LANGUAGE_PARM,AX ;; + MOV BX,[BP].CODE_PAGE_PARM ;; Get code page parameter + MOV TB_CODE_PAGE_PARM,BX ;; + ;; Make sure code page is + CALL FIND_CP_TABLE ;; valid for the language + CMP CX,0 ;; Test return codes + JE TB_CHECK_CONTINUE1 ;; IF code page is found + JMP TB_ERROR6 ;; for language THEN + ;; +TB_CHECK_CONTINUE1: ;;;;;;;; + MOV BP,OFFSET SD_SOURCE_PTR ;; Put language parm and ;AN000 + MOV AX,TB_ID_PARM ;; WGR id parm and.. ;AN000 + MOV ES:[BP].INVOKED_KBD_ID,AX ;; WGR + MOV BX,TB_CODE_PAGE_PARM ;; + MOV ES:[BP].INVOKED_CP_TABLE,BX ;;;;;; code page parm into the + MOV AX,TB_LANGUAGE_PARM ;; SHARED_DATA_AREA + MOV WORD PTR ES:[BP].ACTIVE_LANGUAGE,AX ;; + ;; + MOV BX,KEYBSYS_FILE_HANDLE ;;;;;;;;;;;;;;; Get handle + XOR DX,DX ;; LSEEK file pointer + XOR CX,CX ;; back to top of file + MOV AH,42H ;; + MOV AL,0 ;; If no problem with + INT 21H ;; Keyboard Def file THEN + JNC TB_START ;; + JMP TB_ERROR4 ;; + ;; +TB_START: ;; Else + XOR DI,DI ;; Set number + LEA CX,[DI].KH_MAX_LOGIC_SZ+2;; bytes to read header + MOV DX,OFFSET FILE_BUFFER ;; Move contents into file buffer + MOV AH,3FH ;; READ + PUSH CS ;; + POP DS ;; + INT 21H ;; File + JNC TB_CONTINUE1 ;; + JMP TB_ERROR4 ;; + ;; +TB_CONTINUE1: ;; + CMP CX,AX ;; + JE TB_ERROR_CHECK1 ;; + MOV CX,4 ;; + JMP TB_CPN_INVALID ;; + ;; +TB_ERROR_CHECK1: ;; + MOV CX,FB.KH_MAX_COM_SZ ;; Save values for RESIDENT_END + MOV MAX_COM_SIZE,CX ;; calculation + MOV CX,FB.KH_MAX_SPEC_SZ ;; + MOV MAX_SPEC_SIZE,CX ;; + MOV CX,FB.KH_MAX_LOGIC_SZ ;; + MOV MAX_LOGIC_SIZE,CX ;; + ;; + LEA DI,[BP].TABLE_AREA ;; Point at beginning of table area + ;; DI ---> TABLE_AREA +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ** FOR STATE LOGIC SECTION FOR LANG ** +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +TB_STATE_BEGIN: ;; + MOV BX,KEYBSYS_FILE_HANDLE ;; Get handle + MOV CX,WORD PTR STATE_LOGIC_OFFSET+2 ;; + MOV DX,WORD PTR STATE_LOGIC_OFFSET ;; Get LSEEK file pointer + ;; + CMP DX,-1 ;;;;;;;;;; If no language table then + JNE TB_STATE_CONTINUE1 ;; jump to code page begin + JMP TB_CP_BEGIN ;; + ;; +TB_STATE_CONTINUE1: ;; Else + MOV AH,42H ;; LSEEK to beginning of state logic sect + MOV AL,0 ;; If no problem with + INT 21H ;; Keyboard Def file THEN + JNC TB_STATE_CONTINUE2 ;; + JMP TB_ERROR4 ;; + ;;;;;;;;;; +TB_STATE_CONTINUE2: ;; + MOV DX,AX ;; + MOV WORD PTR SB_STATE_OFFSET+2,CX ;; Save the offset of the + MOV WORD PTR SB_STATE_OFFSET,DX ;; states in Keyb Def file + ;; + SUB DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + MOV ES:[BP].LOGIC_PTR,DI ;;;;;;;;;; Set because this is state + ADD DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;; + MOV CX,4 ;; Set number bytes to read length and + ;; special features + MOV DX,OFFSET FILE_BUFFER ;; Set the buffer address + MOV AH,3FH ;; Read from the Keyb Def file + INT 21H ;; + JNC TB_STATE_CONTINUE3 ;; + JMP TB_ERROR4 ;; + ;; +TB_STATE_CONTINUE3: ;; + CMP CX,AX ;; + JE TB_ERROR_CHECK2 ;; + MOV CX,4 ;; + JMP TB_CPN_INVALID ;; + ;;;;; +TB_ERROR_CHECK2: ;; + MOV AX,FB.KT_SPECIAL_FEATURES ;; Save the special features in the + MOV ES:[BP].SPECIAL_FEATURES,AX ;; SHARED_DATA_AREA + ;; + CMP HW_TYPE,JR_KB ;;;;;;;; + JNE USE_F1_F2 ;; + TEST AX,JR_HOT_KEY_1_2 ;; + JZ USE_F1_F2 ;; + MOV ES:[BP].HOT_KEY_ON_SCAN,ONE_SCAN ;; + MOV ES:[BP].HOT_KEY_OFF_SCAN,TWO_SCAN ;; + JMP HOT_KEY_SET ;; + ;; +USE_F1_F2: ;; + MOV ES:[BP].HOT_KEY_ON_SCAN,F1_SCAN ;; + MOV ES:[BP].HOT_KEY_OFF_SCAN,F2_SCAN ;; + ;; +HOT_KEY_SET: ;;;;;;;; + MOV CX,FB.KT_LOGIC_LEN ;; Set length of section to read + CMP CX,0 ;; + JNE TB_STATE_CONTINUE4 ;; + MOV CX,-1 ;;;;; + MOV ES:[BP].LOGIC_PTR,CX ;; + JMP SB_COMM_BEGIN ;; + ;; +TB_STATE_CONTINUE4: ;; + MOV ES:[DI],CX ;; Store length parameter in + ADD DI,2 ;; SHARED_DATA_AREA + MOV CX,FB.KT_SPECIAL_FEATURES;; Save the special features + MOV ES:[DI],CX ;; + ADD DI,2 ;; + MOV CX,FB.KT_LOGIC_LEN ;; Set length of section to read + SUB CX,4 ;; Adjust for what we have already read + MOV DX,DI ;; Set the address of SHARED_DATA_AREA + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; Read logic section from the + INT 21H ;; Keyb Def file + PUSH CS ;; + POP DS ;; + JNC TB_STATE_CONTINUE5 ;; + JMP TB_ERROR4 ;; + ;; +TB_STATE_CONTINUE5: ;; + CMP CX,AX ;; + JE TB_ERROR_CHECK3 ;; + MOV CX,4 ;; + JMP TB_CPN_INVALID ;; + ;; +TB_ERROR_CHECK3: ;; + ADD DI,CX ;; Set DI at new beginning of area + ;; TABLE_AREA + ;; STATE_LOGIC + MOV CX,RESIDENT_END_ACC ;; DI ---> + ADD CX,SA_HEADER_SIZE ;; + ADD CX,MAX_LOGIC_SIZE ;; + MOV RESIDENT_END_ACC,CX ;; Refresh resident end size + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ** FOR COMMON TRANSLATE SECTION FOR LANG ** +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +SB_COMM_BEGIN: ;; + MOV CX,SIZE KEYBSYS_XLAT_SECT-1 ;; Set number bytes to read header + MOV DX,DI ;; Set the SHARED_DATA_AREA address + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; Read from the Keyb Def file + INT 21H ;; + PUSH CS ;; + POP DS ;; + JNC TB_STATE_CONTINUE6 ;; + JMP TB_ERROR4 ;; + ;; +TB_STATE_CONTINUE6: ;; + MOV CX,ES:[DI].KX_SECTION_LEN;; Set length of section to read + CMP CX,0 ;; + JNE TB_STATE_CONTINUE7 ;; + JMP TB_CP_BEGIN ;; + ;;;;;;; +TB_STATE_CONTINUE7: ;; + MOV CX,WORD PTR SB_STATE_OFFSET ;; Save the offset of the + ADD CX,FB.KT_LOGIC_LEN ;; + MOV WORD PTR SB_STATE_OFFSET,CX ;; Save the offset of the + SUB DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + MOV ES:[BP].COMMON_XLAT_PTR,DI ;; + ADD DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;;;;;;; + CALL STATE_BUILD ;; + ;; DI set at new beginning of area + ;; TABLE_AREA + ;; STATE_LOGIC + ;; COMMON_XLAT_SECTION + MOV CX,RESIDENT_END_ACC ;; + ADD CX,MAX_COM_SIZE ;; + MOV RESIDENT_END_ACC,CX ;; Refresh resident end size + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; FOR ALL DESIGNATED OR INVOKED CODE PAGES +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +TB_CP_BEGIN: ;; Get the offset to + MOV CX,OFFSET DESIG_CP_BUFFER.DESIG_CP_ENTRY ;; the beginning of the + MOV DESIG_CP_OFFSET,CX ;; table of designated + ;;;;;; code pages +TB_CPN_BEGIN: ;; + MOV AX,WORD PTR ES:[BP].ACTIVE_LANGUAGE ;; Get the active language + MOV CX,NUM_DESIG_CP ;;;;;;;;;;;;;; Get the number of CPs + CMP CX,0 ;; IF we have done all requested CPs + JNE TB_CPN_VALID1 ;; + JMP TB_DONE ;; Then done + ;; +TB_CPN_VALID1: ;; + MOV SI,[DESIG_CP_OFFSET] ;; + MOV BX,[SI] ;; Get the CP + CMP BX,-1 ;; + JNE TB_CPN_CONTINUE1 ;; + JMP TB_CPN_REPEAT ;; + ;; +TB_CPN_CONTINUE1: ;; ELSE + PUSH DI ;; + CALL FIND_CP_TABLE ;; Find offset of code page table + POP DI ;; + ;; + CMP CX,0 ;; Test return codes + JE TB_CPN_VALID ;; IF code page is not found for language + MOV CPN_INVALID,CX ;; Set flag and go to next CP + JMP TB_CPN_REPEAT ;; Else + ;; +TB_CPN_VALID: ;;;;;; + MOV BX,KEYBSYS_FILE_HANDLE ;; Get handle + MOV CX,WORD PTR CP_TAB_OFFSET+2 ;; Get offset of the code page + MOV DX,WORD PTR CP_TAB_OFFSET ;; in the Keyb Def file + ;; + CMP DX,-1 ;;;;;; Test if code page is blank + JNE TB_CPN_CONTINUE2 ;; + JMP TB_CPN_REPEAT ;; If it is then go get next CP + ;; +TB_CPN_CONTINUE2: ;; + MOV AH,42H ;; LSEEK to table in Keyb Def file + MOV AL,0 ;; If no problem with + INT 21H ;; Keyb Def file Then + JNC TB_CPN_CONTINUE3 ;; + JMP TB_ERROR4 ;; + ;;;;;;;;;; +TB_CPN_CONTINUE3: ;; + MOV DX,AX ;; + MOV WORD PTR SB_STATE_OFFSET+2,CX ;; Save the offset of the + MOV WORD PTR SB_STATE_OFFSET,DX ;; states in Keyb Def file + ;; + MOV CX,TB_CODE_PAGE_PARM ;;;;; If this code page is the + MOV SI,[DESIG_CP_OFFSET] ;; invoked code page + CMP CX,[SI] ;; + JNE TB_CPN_CONTINUE4 ;; Then + ;; + SUB DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + MOV ES:[BP].ACTIVE_XLAT_PTR,DI ;; Set active xlat section + ADD DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;;;;;;; +TB_CPN_CONTINUE4: ;; + SUB DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + MOV ES:[BP].FIRST_XLAT_PTR,DI;; Set flag + ADD DI,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;; +TB_CPN_CONTINUE5: ;; + CALL STATE_BUILD ;; Build state + ;; TABLE_AREA + CMP CX,0 ;; COMMON_XLAT_SECTION + JE TB_CPN_REPEAT ;; SPECIFIC_XLAT_SECTION(S) + JMP TB_ERROR4 ;; DI ---> + ;; +TB_CPN_REPEAT: ;; + MOV CX,RESIDENT_END_ACC ;; + ADD CX,MAX_SPEC_SIZE ;; Refresh resident end size + MOV RESIDENT_END_ACC,CX ;; + ;; + MOV CX,DESIG_CP_OFFSET ;; + ADD CX,2 ;; Adjust offset to find next code page + MOV DESIG_CP_OFFSET,CX ;; + ;; + MOV CX,NUM_DESIG_CP ;; Adjust the number of code pages left + DEC CX ;; + MOV NUM_DESIG_CP,CX ;; + ;; + JMP TB_CPN_BEGIN ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +TB_DONE: ;; + MOV CX,RESIDENT_END_ACC ;; Set final calculated value + ADD CX,BP ;;;;;;;;;;; + SUB CX,SD_AREA_DIFFERENCE ;; Adjust for relocation + MOV ES,WORD PTR SHARED_AREA_PTR ;; Set segment + MOV BP,WORD PTR SHARED_AREA_PTR+2 ;; + CMP CX,ES:[BP].RESIDENT_END ;; + JNA TB_DONE_CONTINUE1 ;;;;;;;;;;; + JMP TB_ERROR5 ;; + ;; +TB_DONE_CONTINUE1: ;; + CMP ES:[BP].RESIDENT_END,-1 ;; + JNE DONT_REPLACE ;; + PUSH CS ;; + POP ES ;; + MOV BP,OFFSET SD_SOURCE_PTR ;; + MOV ES:[BP].RESIDENT_END,CX ;; Save resident end + JMP CONTINUE_2_END ;; + ;; +DONT_REPLACE: ;; + PUSH CS ;; + POP ES ;; + MOV BP,OFFSET SD_SOURCE_PTR ;; + ;; +CONTINUE_2_END: ;; + SUB CX,OFFSET SD_DEST_PTR ;; Calculate # of bytes to copy + MOV SD_LENGTH,CX ;; + ;; + XOR CX,CX ;; Set valid completion return code + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_CPN_INVALID: ;; + CMP CX,1 ;; Set error 1 return code + JNE TB_ERROR2 ;; + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_ERROR2: ;; + CMP CX,2 ;; Set error 2 return code + JNE TB_ERROR3 ;; + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_ERROR3: ;; + CMP CX,3 ;; Set error 3 return code + JNE TB_ERROR4 ;; + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_ERROR4: ;; + CMP CX,4 ;; Set error 4 return code + JNE TB_ERROR5 ;; + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_ERROR5: ;; + MOV CX,5 ;; Set error 5 return code + MOV TB_RETURN_CODE,CX ;; + RET ;; + ;; +TB_ERROR6: ;; + MOV BX,TB_CODE_PAGE_PARM ;; + MOV CX,6 ;; + MOV TB_RETURN_CODE,CX ;; Set error 6 return code + RET ;; + ;; +TABLE_BUILD ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: STATE_BUILD +;; +;; Description: +;; Create the state/xlat section within the specific translate section. +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to our data segment +;; SB_STATE_OFFSET - offset to the beginning of the info in Keyb Def SYS +;; DI - offset of the beginning of the area used to build states +;; +;; KEYBSYS_FILE_HANDLE - handle of the KEYBOARD.SYS file +;; +;; Output Registers: +;; DI - offset of the end of the area used by STATE_BUILD +;; +;; CX - Return Code := 0 - State build successful +;; 4 - State build unsuccessful +;; (Bad or missing Keyboard Def file) +;; +;; Logic: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +END_OF_AREA_PTR DW 0 ;; +SB_FIRST_STATE DW 0 ;; +SB_STATE_LENGTH DW 0 ;; +SB_STATE_OFFSET DD 0 ;; +STATE_LENGTH DW 0 ;; +RESTORE_BP DW ? ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +STATE_BUILD PROC NEAR ;; + ;; + MOV SI,DI ;; Get the tally pointer + MOV END_OF_AREA_PTR,DI ;; Save pointer + ;; + MOV RESTORE_BP,BP ;; Save the base pointer + ;;;;;;;;; + MOV BX,KEYBSYS_FILE_HANDLE ;; Get handle + MOV DX,WORD PTR SB_STATE_OFFSET ;; LSEEK file pointer + MOV CX,WORD PTR SB_STATE_OFFSET+2 ;; back to top of XLAT table + MOV AH,42H ;; + MOV AL,0 ;;;;;;;;; If no problem with + INT 21H ;; Keyboard Def file THEN + JNC SB_FIRST_HEADER ;; + JMP SB_ERROR4 ;; + ;; +SB_FIRST_HEADER: ;; + XOR BP,BP ;; + LEA CX,[BP].KX_FIRST_STATE ;; Set number of bytes to read header + MOV DX,DI ;; + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; read in the header + INT 21H ;; + PUSH CS ;; + POP DS ;; + JNC SB_HEAD_CONTINUE1 ;; + JMP SB_ERROR4 ;; + ;; +SB_HEAD_CONTINUE1: ;; + MOV DX,NEXT_SECT_PTR ;; + CMP DX,-1 ;; + JE SB_HEAD_CONTINUE2 ;; + SUB DX,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;;;;; +SB_HEAD_CONTINUE2: ;; + MOV ES:[DI].XS_NEXT_SECT_PTR,DX ;; + CMP DX,-1 ;; + JE SB_HEAD_CONTINUE3 ;;;;; + ADD DX,SD_AREA_DIFFERENCE ;; Adjust for relocation + ;; +SB_HEAD_CONTINUE3: ;; + ADD DI,CX ;; Update the DI pointer + ;; +SB_NEXT_STATE: ;; + XOR BP,BP ;; Set number + LEA CX,[BP].KX_STATE_ID ;; bytes to read state length + MOV DX,DI ;; Read the header into the + MOV BX,KEYBSYS_FILE_HANDLE ;; SHARED_DATA_AREA + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; + INT 21H ;; + ;; +SB_CONTINUE1: ;; + PUSH CS ;; Reset the data segment + POP DS ;; + MOV CX,ES:[DI].KX_STATE_LEN ;; If the length of the state section + MOV STATE_LENGTH,CX ;; + ADD DI,2 ;; is zero then done + CMP CX,0 ;; + JE SB_DONE ;; + XOR BP,BP ;; Set number + LEA CX,[BP].KX_FIRST_XLAT-2 ;; bytes to read state length + MOV DX,DI ;; Read the header into the + MOV BX,KEYBSYS_FILE_HANDLE ;; SHARED_DATA_AREA + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; + INT 21H ;; + ;; +SB_CONTINUE1A: ;; + PUSH CS ;; Reset the data segment + POP DS ;; + SUB DI,2 ;; + MOV AX,ES:[DI].XS_KBD_TYPE ;; Get the keyboard type def + TEST AX,HW_TYPE ;; Does it match our hardware? + JNZ SB_CONTINUE2 ;; + MOV DX,ES:[DI].XS_STATE_LEN ;; No, then + LEA CX,[BP].KX_FIRST_XLAT ;; + SUB DX,CX ;; + XOR CX,CX ;; + MOV AH,42H ;; LSEEK past this state + MOV AL,01H ;; + INT 21H ;; + JMP SB_NEXT_STATE ;; + ;; +SB_CONTINUE2: ;; Yes, then + MOV AX,SIZE STATE_STR-1 ;; + ADD DI,AX ;; Set PTR and end of header + ;; +SB_XLAT_TAB_BEGIN: ;; Begin getting xlat tables + MOV BX,KEYBSYS_FILE_HANDLE ;; + LEA DX,[BP].KX_FIRST_XLAT ;; Adjust for what we have already read + MOV CX,STATE_LENGTH ;; + SUB CX,DX ;; + MOV DX,DI ;; + PUSH ES ;; + POP DS ;; + MOV AH,3FH ;; Read in the xlat tables + INT 21H ;; + PUSH CS ;; + POP DS ;; + JNC SB_CONTINUE4 ;; + JMP SB_ERROR4 ;; + ;; +SB_CONTINUE4: ;; + CMP CX,AX ;; + JE SB_ERROR_CHECK1 ;; + JMP SB_ERROR4 ;; + ;; +SB_ERROR_CHECK1: ;; + ADD DI,CX ;; Update the end of area ptr + ;; + MOV SI,DI ;; + JMP SB_NEXT_STATE ;; + ;; +SB_DONE: ;; + MOV AX,-1 ;; + MOV SI,END_OF_AREA_PTR ;; + MOV NEXT_SECT_PTR,SI ;; + ;; + MOV BP,RESTORE_BP ;; + RET ;; + ;; +SB_ERROR1: ;; + MOV CX,1 ;; + RET ;; + ;; +SB_ERROR2: ;; + MOV CX,2 ;; + RET ;; + ;; +SB_ERROR3: ;; + MOV CX,3 ;; + RET ;; + ;; +SB_ERROR4: ;; + MOV CX,4 ;; + RET ;; + ;; + ;; +STATE_BUILD ENDP ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Module: FIND_CP_TABLE +;; +;; Description: +;; Determine the offset of the specified code page table in KEYBOARD.SYS +;; +;; Input Registers: +;; DS - points to our data segment +;; ES - points to our data segment +;; AX - ASCII representation of the language parm +;; BX - binary representation of the code page +;; +;; KEYBSYS_FILE_HANDLE - handle of the KEYBOARD.SYS file +;; +;; Output Registers: +;; CP_TAB_OFFSET - offset of the CP table in KEYBOARD.SYS +;; +;; CX - Return Code := 0 - State build successful +;; 2 - Invalid Code page for language +;; 4 - Bad or missing Keyboard Def file +;; Logic: +;; +;; READ language table +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Use table to verify language parm +;; Set pointer values +;; IF code page was specified +;; READ language entry +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; READ Code page table +;; IF error in reading file THEN +;; Display ERROR message and EXIT +;; ELSE +;; Use table to get the offset of the code page parm +;; RET +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FIND_CP_PARM DW ? ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Program Code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; +FIND_CP_TABLE PROC NEAR ;; + ;; + ;; + MOV FIND_CP_PARM,BX ;; Save Code page + ;;;;;;;;;;;;;; + MOV BX,KEYBSYS_FILE_HANDLE ;; Get handle + MOV DX,WORD PTR KEYBCMD_LANG_ENTRY_PTR ;; LSEEK file pointer + MOV CX,WORD PTR KEYBCMD_LANG_ENTRY_PTR+2 ;; to top of language entry + MOV AH,42H ;; + MOV AL,0 ;;;;;;;;;;;;;; If no problem with + INT 21H ;; Keyb Def file Then + JNC FIND_BEGIN ;; + JMP FIND_CP_ERROR4 ;; + ;;;;;;;;; +FIND_BEGIN: ;; + MOV DI,AX ;; + MOV CX,SIZE KEYBSYS_LANG_ENTRY-1 ;; Set number + ;; bytes to read header + MOV DX,OFFSET FILE_BUFFER ;;;;;;;;; + MOV AH,3FH ;; Read language entry in + INT 21H ;; KEYBOARD.SYS file + JNC FIND_VALID4 ;; If no error in opening file then + JMP FIND_CP_ERROR4 ;; + ;; +FIND_VALID4: ;; +;****************************** CNS ******************************************* + xor ah,ah + mov al,FB.KL_NUM_CP +;****************************** CNS ******************************************* + MOV NUM_CP,AX ;; Save the number of code pages + MUL CP_PTR_SIZE ;; Determine # of bytes to read + MOV DX,OFFSET FILE_BUFFER ;; Establish beginning of buffer + MOV CX,AX ;; + CMP CX,FILE_BUFFER_SIZE ;; Make sure buffer is not to small + JBE FIND_VALID5 ;; + JMP FIND_CP_ERROR4 ;; + ;; +FIND_VALID5: ;; + MOV AH,3FH ;; Read code page table from + INT 21H ;; KEYBOARD.SYS file + JNC FIND_VALID6 ;; If no error in opening file then + JMP FIND_CP_ERROR4 ;; + ;; +FIND_VALID6: ;; + MOV CX,NUM_CP ;; Number of valid codes + MOV DI,OFFSET FILE_BUFFER ;; Point to correct word in table + ;; +F_SCAN_CP_TABLE: ;; FOR code page parm + MOV AX,FIND_CP_PARM ;; Get parameter + CMP [DI].KC_CODE_PAGE,AX ;; Valid Code ?? + JE F_CODE_PAGE_FOUND ;; If not found AND more entries THEN + ADD DI,LANG_PTR_SIZE ;; Check next entry + DEC CX ;; Decrement count of entries + JNE F_SCAN_CP_TABLE ;; Else + JMP FIND_CP_ERROR2 ;; Display error message + ;;;;;;;;;; +F_CODE_PAGE_FOUND: ;; + MOV AX,WORD PTR [DI].KC_ENTRY_PTR ;; + MOV WORD PTR CP_TAB_OFFSET,AX ;; + MOV AX,WORD PTR [DI].KC_ENTRY_PTR+2 ;; + MOV WORD PTR CP_TAB_OFFSET+2,AX ;; + ;; + XOR CX,CX ;;;;;;;;;; + RET ;; + ;; +FIND_CP_ERROR1: ;; + MOV CX,1 ;; + RET ;; + ;; +FIND_CP_ERROR2: ;; + MOV CX,2 ;; + RET ;; + ;; +FIND_CP_ERROR3: ;; + MOV CX,3 ;; + RET ;; + ;; +FIND_CP_ERROR4: ;; + MOV CX,4 ;; + RET ;; + ;; +FIND_CP_TABLE ENDP ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CODE ENDS + END TABLE_BUILD + \ No newline at end of file diff --git a/v4.0/src/CMD/KEYB/KEYBTBBL.INC b/v4.0/src/CMD/KEYB/KEYBTBBL.INC new file mode 100644 index 0000000..c5ea73a --- /dev/null +++ b/v4.0/src/CMD/KEYB/KEYBTBBL.INC @@ -0,0 +1,33 @@ + +.XLIST + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DOS - NLS Support - KEYB Command +;; (C) Copyright 1988 Microsoft +;; +;; File Name: KEYBTBBL.INC +;; ---------- +;; +;; Description: +;; ------------ +;; Include file containing structure definitions Shared Data Area +;; for the Shared Data Area. +;; The Shared Data Area contains data which is required by +;; both the resident and transient KEYB code. The Shared +;; Data Area is allocated in the KEYBI2F file and will be +;; resident following initial installation. +;; +;; Change History: +;; --------------- +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + EXTRN TABLE_BUILD :NEAR ;; + EXTRN FIND_CP_TABLE :NEAR ;; + ;; + EXTRN CPN_INVALID :WORD ;; + EXTRN SD_LENGTH :WORD ;; + ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LIST diff --git a/v4.0/src/CMD/KEYB/MAKEFILE b/v4.0/src/CMD/KEYB/MAKEFILE new file mode 100644 index 0000000..509b679 --- /dev/null +++ b/v4.0/src/CMD/KEYB/MAKEFILE @@ -0,0 +1,72 @@ +#************************* Makefile for KEYB ************************* + +inc =..\..\inc +msg =..\..\messages +dos =..\..\dos +hinc =..\..\h + +# +###################### Dependencies begin here. ###################### +# + +all: keyb.com + +keyb.ctl: keyb.skl $(msg)\$(COUNTRY).msg + +keybcmd.obj: keybcmd.asm \ + $(inc)\struc.inc \ + $(inc)\sysmsg.inc \ + $(inc)\versiona.inc \ + keybequ.inc \ + keybsys.inc \ + keybi9.inc \ + keybi9c.inc \ + keybi2f.inc \ + keybi48.inc \ + keybshar.inc \ + keyb.ctl \ + keyb.cl1 \ + keyb.cl2 \ + keyb.cla \ + keybdcl.inc \ + keybtbbl.inc \ + commsubs.inc \ + keybcpsd.inc \ + $(inc)\postequ.inc \ + $(inc)\dseg.inc + +keybtbbl.obj: keybtbbl.asm + +commsubs.obj: commsubs.asm + +keybi2f.obj: keybi2f.asm + +keybi48.obj: keybi48.asm + +keyb.obj: keyb.asm + +keybcpsd.obj: keybcpsd.asm + +keybi9.obj: keybi9.asm + +keybi9c.obj: keybi9c.asm + +parser.obj: parser.asm \ + $(inc)\parse.asm \ + $(inc)\struc.inc \ + keybdcl.inc \ + makefile + +keyb.com: keyb.obj \ + parser.obj \ + keybcmd.obj \ + keybtbbl.obj \ + commsubs.obj \ + keybi2f.obj \ + keybi48.obj \ + keybcpsd.obj \ + keybi9.obj \ + keybi9c.obj + link @keyb.lnk + exe2bin keyb.exe keyb.com + del keyb.exe diff --git a/v4.0/src/CMD/KEYB/PARSER.ASM b/v4.0/src/CMD/KEYB/PARSER.ASM new file mode 100644 index 0000000..808f37a --- /dev/null +++ b/v4.0/src/CMD/KEYB/PARSER.ASM @@ -0,0 +1,517 @@ +PAGE ,132 +TITLE PARSE CODE AND CONTROL BLOCKS FOR KEYB.COM + +;****************** START OF SPECIFICATIONS ************************** +; +; MODULE NAME: PARSER.ASM +; +; DESCRIPTIVE NAME: PARSES THE COMMAND LINE PARAMETERS FOR KEYB.COM +; +; FUNCTION: THE COMMAND LINE IN THE PSP IS PARSED FOR PARAMETERS. +; +; ENTRY POINT: PARSE_PARAMETERS +; +; INPUT: BP POINTS TO PARAMETER LIST +; DS & ES POINT TO PSP +; +; AT EXIT: +; PARAMETER LIST FILLED IN AS REQUIRED. +; +; INTERNAL REFERENCES: +; +; ROUTINES: SYSPARSE - PARSING CODE +; +; DATA AREAS: PARMS - PARSE CONTROL BLOCK FOR SYSPARSE +; +; EXTERNAL REFERENCES: +; +; ROUTINES: N/A +; +; DATA AREAS: PARAMETER LIST BLOCK TO BE FILLED. +; +; NOTES: +; +; REVISION HISTORY: +; A000 - DOS Version 4.00 +; 3/24/88 AN003 - P3906 PARSER changes to return "bogus" parameter on the +; "Parameter value not allowed " message - CNS +; 5/12/88 AN004 - P4867 /ID:NON-Numeric hangs the sytem as a 1st positional +; +; COPYRIGHT: "The KEYB.COM Keyboard Driver" +; "Version 4.00 (C) Copyright 1988 Microsoft" +; "Licensed Material - Program Property of Microsoft" +; +; PROGRAM AUTHOR: WGR +; +;****************** END OF SPECIFICATIONS **************************** + +INCLUDE KEYBDCL.INC ;AN000 + +ID_VALID EQU 0 ;AN000; ;AN000 +ID_INVALID EQU 1 ;AN000; ;AN000 +NO_ID EQU 2 ;AN000; ;AN000 + +LANGUAGE_VALID EQU 0 ;AN000; ;AN000 +LANGUAGE_INVALID EQU 1 ;AN000; ;AN000 +NO_LANGUAGE EQU 2 ;AN000; ;AN000 + +NO_IDLANG EQU 3 ;AN000; ;AN000 + +CODE_PAGE_VALID EQU 0 ;AN000; ;AN000 +CODE_PAGE_INVALID EQU 1 ;AN000; ;AN000 +NO_CODE_PAGE EQU 2 ;AN000; ;AN000 +VALID_SYNTAX EQU 0 ;AN000; ;AN000 +INVALID_SYNTAX EQU 1 ;AN000; ;AN000 + +COMMAND_LINE_START EQU 81H ;AN000; ;AN000 +RC_EOL EQU -1 ;AN000; ;AN000 +RC_NO_ERROR EQU 0 ;AN000; ;AN000 +RC_OP_MISSING EQU 2 ;AN000; ;AN000 +RC_NOT_IN_SW EQU 3 ;AN000; ;AN000 +;***CNS P4867 1st CHECK for /ID:ALPHA +RC_SW_FIRST EQU 9 ;AN004; ;AN000 +;***CNS P4867 1st CHECK for /ID:ALPHA +ERROR_COND EQU -1 ;AN000; ;AN000 +NUMBER EQU 1 ;AN000; ;AN000 +STRING EQU 3 ;AN000; ;AN000 +FILE_SPEC EQU 5 ;AN000; ;AN000 +MAX_ID EQU 999 ;AN000; ;AN000 +LANG_LENGTH EQU 2 ;AN000; ;AN000 + +INVALID_SWITCH EQU 3 +TOO_MANY EQU 1 +INVALID_PARAM EQU 10 +VALUE_DISALLOW EQU 8 + +.XLIST +INCLUDE STRUC.INC ; Structured macros ;AN000 +.LIST + +PUBLIC PARSE_PARAMETERS ;AN003;; near procedure for parsing command line ;AN000 +PUBLIC CUR_PTR ;AN003;; near procedure for parsing command line ;AN000 +PUBLIC OLD_PTR ;AN003;; near procedure for parsing command line ;AN000 +PUBLIC ERR_PART;AN003;; near procedure for parsing command line ;AN000 +EXTRN BAD_ID:BYTE ;; WGR to match old code ;AN000; ;AN000 +EXTRN FOURTH_PARM:BYTE ;; WGR to match old code ;AN000; ;AN000 +EXTRN ONE_PARMID:BYTE ;; WGR to match old code ;AN000; ;AN000 +EXTRN FTH_PARMID:BYTE ;; WGR to match old code ;AN000; ;AN000 +EXTRN ALPHA:BYTE ;; WGR to match old code ;AN000; ;AN000 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Set assemble switches for parse code that is not required!! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +DateSW EQU 0 ;AN000; ;AN000 +TimeSW EQU 0 ;AN000; ;AN000 +CmpxSW EQU 0 ;AN000; ;AN000 +DrvSW EQU 0 ;AN000; ;AN000 +QusSW EQU 0 ;AN000; ;AN000 +KeySW EQU 0 ;AN000; ;AN000 +Val1SW EQU 0 ;AN000; ;AN000 +Val2SW EQU 0 ;AN000; ;AN000 +Val3SW EQU 0 ;AN000; ;AN000 + + +CODE SEGMENT PUBLIC 'CODE' BYTE ;AN000; ;AN000 + ASSUME CS:CODE,DS:CODE ;AN000; ;AN000 + +.XLIST +INCLUDE PARSE.ASM ; Parsing code ;AN000 +.LIST + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; PARM control blocks for KEYB +; Parsing command line as follows: +; +; KEYB [lang],[cp],[[d:][path]KEYBOARD.SYS][/ID:id] +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PARMS LABEL WORD ;AN000; ;AN000 + DW PARMSX ;AN000; ;AN000 + DB 0 ;AN000;; no extra delimeters or EOLs. ;AN000 + +PARMSX LABEL BYTE ;AN000; ;AN000 + DB 0,3 ;AN000;; min,max positional operands ;AN000 + DW LANG ;AN000;; pointer to control block ;AN000 + DW CP ;AN000;; pointer to control block ;AN000 + DW FILE_NAME ;AN000;; pointer to control block ;AN000 + DB 1 ;AN000;; 1 switch ;AN000 + DW ID_VALUE ;AN000;; pointer to control block ;AN000 + DB 0 ;AN000;; no keywords ;AN000 + +LANG LABEL WORD ;AN000; ;AN000 + DW 0A001H ;AN000;; sstring or numeric value (optional) ;AN000 + DW 0002H ;AN000;; cap result by char table (sstring) ;AN000 + DW RESULT_BUF ;AN000;; result ;AN000 + DW NOVALS ;AN000;; no value checking done ;AN000 + DB 0 ;AN000;; no keyword/switch synonyms ;AN000 + +CP LABEL WORD ;AN000; ;AN000 + DW 8001H ;AN000;; numeric ;AN000 + DW 0 ;AN000;; no functions ;AN000 + DW RESULT_BUF ;AN000;; result ;AN000 + DW NOVALS ;AN000;; no value checking done ;AN000 + DB 0 ;AN000;; no keyword/switch synonyms ;AN000 + +FILE_NAME LABEL WORD ;AN000; ;AN000 + DW 0201H ;AN000;; file spec ;AN000 + DW 0001H ;AN000;; cap by file table ;AN000 + DW RESULT_BUF ;AN000;; result ;AN000 + DW NOVALS ;AN000;; no value checking done ;AN000 + DB 0 ;AN000;; no keyword/switch synonyms ;AN000 + +ID_VALUE LABEL WORD ;AN000; ;AN000 + DW 8010H ;AN000;; numeric ;AN000 + DW 0 ;AN000;; no functions ;AN000 + DW RESULT_BUF ;AN000;; result ;AN000 + DW NOVALS ;AN000;; no value checking done ;AN000 + DB 1 ;AN000;; 1 switch synonym ;AN000 + DB "/ID",0 ;AN000;; ID switch ;AN000 + +NOVALS LABEL BYTE ;AN000; ;AN000 + DB 0 ;AN000;; no value checking done ;AN000 + +RESULT_BUF LABEL BYTE ;AN000; ;AN000 +RESULT_TYPE DB 0 ;AN000;; type returned (number, string, etc.) ;AN000 + DB ? ;AN000;; matched item tag (if applicable) ;AN000 +RESULT_SYN_PTR DW ? ;AN000;; synonym ptr (if applicable) ;AN000 +RESULT_VAL DD ? ;AN000;; value ;AN000 + +LOOP_COUNT DB 0 ;AN000;; keeps track of parameter position ;AN000 +;***CNS +CUR_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000 +OLD_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000 +ERR_PART DW 0 ;AN003;; keeps track of parameter position ;AN000 +;***CNS + ;AN000;; ..and reports an error condition ;AN000 +TEMP_FILE_NAME DB 128 DUP(0) ;AN000;; place for file name ;AN000 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; PROCEDURE_NAME: PARSE_PARAMETERS +; +; FUNCTION: +; THIS PROCEDURE PARSES THE COMMAND LINE PARAMETERS IN THE PSP FOR +; KEYB.COM. THE PARAMETER LIST BLOCK IS FILLED IN ACCORDINGLY. +; +; AT ENTRY: AS ABOVE. +; +; AT EXIT: +; AS ABOVE. +; +; AUTHOR: WGR +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PARSE_PARAMETERS PROC NEAR ;AN000 + XOR AX,AX ;AN000;; setup default parameters. ;AN000 + MOV [BP].RET_CODE_1,NO_IDLANG ;AN000;; ;AN000 + MOV [BP].RET_CODE_2,NO_CODE_PAGE ;AN000;; ;AN000 + MOV [BP].RET_CODE_3,VALID_SYNTAX ;AN000;; ;AN000 + MOV [BP].RET_CODE_4,NO_ID ;AN000;; ;AN000 + MOV [BP].PATH_LENGTH,AX ;AN000;; ;AN000 + LEA DI,PARMS ;AN000;; setup parse blocks ;AN000 + MOV SI,COMMAND_LINE_START ;AN000;; ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + +;***CNS + XOR CX,CX ;AN000;; ;AN000 + XOR DX,DX ;AN000;; ;AN000 + CALL SYSPARSE ;AN000;; ;AN000 + .WHILE near AND ;AN000;; while not end of line and.. ;AN000 + .WHILE near ;AN000;; parameters valid do. ;AN000 + .IF near OR ;AN000;; invalid switch? ;AN000 + .IF near ;AN000;; invalid switch? ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; set invalid syntax flag. ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set error flag to exit parse. ;AN000 +;***CNS + MOV ERR_PART,INVALID_SWITCH + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + +;***CNS + .ELSE ;AN000;; ;AN000 + .IF ;AN000;; was the switch found? ;AN000 + MOV AX,WORD PTR RESULT_VAL+2 ;AN000;; is it valid? ;AN000 + OR AX,AX ;AN000;; ;AN000 + .IF NZ OR ;AN000;; ;AN000 + MOV AX,WORD PTR RESULT_VAL ;AN000;; ;AN000 + .IF ;AN000;; ;AN000 + MOV [BP].RET_CODE_1,ID_INVALID ;AN000;; no...invalid id. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error. ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse ;AN000 + mov bad_id,1 ;AN000;; ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + +;***CNS + .ELSE ;AN000;; ;AN000 + MOV [BP].RET_CODE_4,ID_VALID ;AN000;; yes...set return code 4. ;AN000 + MOV [BP].ID_PARM,AX ;AN000;; ;AN000 + mov fourth_parm,1 ;AN000;; ;AN000 + mov fth_parmid,1 ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + .ELSE ;AN000;; ;AN000 + INC LOOP_COUNT ;AN000;; positional encountered... ;AN000 + .SELECT ;AN000;; ;AN000 + .WHEN ;AN000;; check for language ;AN000 + CALL PROCESS_1ST_PARM ;AN000;; ;AN000 + +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment +;***CNS + + + .WHEN ;AN000;; check for code page ;AN000 + CALL PROCESS_2ND_PARM ;AN000;; ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment +;***CNS + .WHEN ;AN000;; check for file name ;AN000 + CALL PROCESS_3RD_PARM ;AN000;; ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment +;***CNS + .OTHERWISE ;AN000;; ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; too many parms ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment +;***CNS + MOV ERR_PART,TOO_MANY + MOV LOOP_COUNT,ERROR_COND ;AN000;; set error flag to exit parse. ;AN000 + .ENDSELECT ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + MOV RESULT_TYPE,0 ;AN000;; reset result block. ;AN000 + CALL SYSPARSE ;AN000;; parse next parameter. ;AN000 + .ENDIF ;AN000;; ;AN000 + .ENDWHILE ;AN000;; ;AN000 + .IF <[BP].RET_CODE_4 EQ ID_VALID> AND ;AN000;; ensure that if the switch ;AN000 + .IF <[BP].RET_CODE_1 NE LANGUAGE_VALID> ;AN000;; was used..that a valid keyboard ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; code was used.. ;AN000 +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + MOV ERR_PART,VALUE_DISALLOW +;***CNS + .ENDIF ;AN000;; ;AN000 + RET ;AN000;; ;AN000 +PARSE_PARAMETERS ENDP ;AN000; ;AN000 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; PROCEDURE_NAME: PROCESS_1ST_PARM +; +; FUNCTION: +; THIS PROCEDURE PROCESSES THE FIRST POSITIONAL PARAMETER. THIS SHOULD +; BE THE LANGUAGE ID OR THE KEYBOARD ID. +; +; AT ENTRY: PARSE RESULT BLOCK CONTAINS VALUES IF AX HAS NO ERROR. +; +; AT EXIT: +; PARAMETER CONTROL BLOCK UPDATED FOR LANGUAGE ID. +; +; AUTHOR: WGR +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PROCESS_1ST_PARM PROC NEAR ;AN000 + .IF ;AN000;; error on parse? ;AN000 + MOV [BP].RET_CODE_1,LANGUAGE_INVALID ;AN000;; yes...set invalid language ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; and syntax error.. ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse. ;AN000 + MOV ERR_PART,AX ;AN003;; + .ELSE near ;AN000;; ;AN000 + + .IF ;AN000;; was this a number (id)? ;AN000 + MOV AX,WORD PTR RESULT_VAL+2 ;AN000;; yes...check to see if ;AN000 + OR AX,AX ;AN000;; within range. ;AN000 + .IF NZ OR ;AN000;; ;AN000 + MOV AX,WORD PTR RESULT_VAL ;AN000;; ;AN000 + .IF ;AN000;; ;AN000 + MOV [BP].RET_CODE_1,ID_INVALID ;AN000;; no...invalid id. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error. ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse ;AN000 + mov bad_id,1 ;AN000;; ;AN000 + .ELSE ;AN000;; ;AN000 + MOV [BP].RET_CODE_1,ID_VALID ;AN000;; valid id...set ;AN000 + MOV [BP].RET_CODE_4,ID_VALID ;AN000;; valid id...set ;AN000 + MOV [BP].ID_PARM,AX ;AN000;; and value moved into block ;AN000 + MOV LOOP_COUNT,4 ;AN000;; there should be no more parms ;AN000 + mov one_parmid,1 ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + .ELSEIF ;AN000;; must be a string then.. ;AN000 + PUSH SI ;AN000;; ;AN000 + PUSH DI ;AN000;; ;AN000 + PUSH CX ;AN000;; ;AN000 + PUSH DS ;AN000;; ;AN000 + LDS SI,RESULT_VAL ;AN000;; get ptr to string ;AN000 + MOV DI,BP ;AN000;; ;AN000 + ADD DI,LANGUAGE_PARM ;AN000;; point to block for copy. ;AN000 + MOV CX,LANG_LENGTH ;AN000;; maximum length = 2 ;AN000 + LODSB ;AN000;; load AL with 1st char.. ;AN000 + .WHILE AND ;AN000;; do twice....unless ;AN000 + .WHILE ;AN000;; there is only 1 character. ;AN000 + STOSB ;AN000;; store ;AN000 + DEC CX ;AN000;; dec count ;AN000 + LODSB ;AN000;; load ;AN000 + .ENDWHILE ;AN000;; ;AN000 + .IF OR ;AN000;; if there was less than 2 or.. ;AN000 + .IF ;AN000;; greater than 2 characters then.. ;AN000 + MOV [BP].RET_CODE_1,LANGUAGE_INVALID ;AN000;; invalid. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error ;AN000 + MOV ERR_PART,INVALID_PARAM + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse. ;AN000 + .ELSE ;AN000;; ;AN000 + MOV [BP].RET_CODE_1,LANGUAGE_VALID ;AN000;; valid language has been copied ;AN000 + MOV ALPHA,1 ;AN000;; language found ;AN000 + .ENDIF ;AN000;; ;AN000 + POP DS ;AN000;; ;AN000 + POP CX ;AN000;; ;AN000 + POP DI ;AN000;; ;AN000 + POP SI ;AN000;; ;AN000 + .ELSE ;AN000;; ommited parameter... ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; invalid since further parameters.;AN000 + .ENDIF ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + RET ;AN000;; ;AN000 +PROCESS_1ST_PARM ENDP ;AN000; ;AN000 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; PROCEDURE_NAME: PROCESS_2ND_PARM +; +; FUNCTION: +; THIS PROCEDURE PROCESSES THE 2ND POSITIONAL PARAMETER. THIS SHOULD +; BE THE CODE PAGE, IF REQUESTED. +; +; AT ENTRY: PARSE RESULT BLOCK CONTAINS VALUES IF AX HAS NO ERROR. +; +; AT EXIT: +; PARAMETER CONTROL BLOCK UPDATED FOR CODE PAGE. +; +; AUTHOR: WGR +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PROCESS_2ND_PARM PROC NEAR ;AN000 + .IF ;AN000;; if parse error.. ;AN000 + MOV [BP].RET_CODE_2,CODE_PAGE_INVALID ;AN000;; mark invalid.. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse ;AN000 + MOV ERR_PART,AX ;AN003;; + .ELSE ;AN000;; ;AN000 + .IF ;AN000;; was parameter specified? ;AN000 + MOV AX,WORD PTR RESULT_VAL+2 ;AN000;; yes..if code page not.. ;AN000 + OR AX,AX ;AN000;; ;AN000 + .IF NZ OR ;AN000;; ;AN000 + MOV AX,WORD PTR RESULT_VAL ;AN000;; valid..then ;AN000 + .IF ;AN000;; ;AN000 + MOV [BP].RET_CODE_2,CODE_PAGE_INVALID ;AN000;; mark invalid.. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse ;AN000 + .ELSE ;AN000;; ;AN000 + MOV [BP].RET_CODE_2,CODE_PAGE_VALID;AN000;; else...valid code page ;AN000 + MOV [BP].CODE_PAGE_PARM,AX ;AN000;; move into parm ;AN000 + .ENDIF ;AN000;; ;AN000 + .ELSE ;AN000;; ;AN000 + MOV [BP].RET_CODE_2,NO_CODE_PAGE ;AN000;; mark as not specified. ;AN000 + .ENDIF ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + RET ;AN000;; ;AN000 +PROCESS_2ND_PARM ENDP ;AN000; ;AN000 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; PROCEDURE_NAME: PROCESS_3RD_PARM +; +; FUNCTION: +; THIS PROCEDURE PROCESSES THE 3RD POSITIONAL PARAMETER. THIS SHOULD +; BE THE KEYBOARD DEFINITION FILE PATH, IF SPECIFIED. +; +; AT ENTRY: PARSE RESULT BLOCK CONTAINS VALUES IF AX HAS NO ERROR. +; +; AT EXIT: +; PARAMETER CONTROL BLOCK UPDATED FOR FILE NAME. +; +; AUTHOR: WGR +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PROCESS_3RD_PARM PROC NEAR ;AN000; ;AN000 + .IF ;AN000;; if parse error then.. ;AN000 + MOV [BP].RET_CODE_3,INVALID_SYNTAX ;AN000;; syntax error. ;AN000 + MOV LOOP_COUNT,ERROR_COND ;AN000;; set flag to exit parse ;AN000 + MOV ERR_PART,AX ;AN003;; + .ELSE ;AN000;; ;AN000 + .IF ;AN000;; ;AN000 + PUSH DS ;AN000;; ;AN000 + PUSH SI ;AN000;; ;AN000 + PUSH DI ;AN000;; ;AN000 + PUSH CX ;AN000;; ;AN000 + LDS SI,RESULT_VAL ;AN000;; load offset of file name ;AN000 + LEA DI,TEMP_FILE_NAME ;AN000;; ;AN000 + MOV [BP].PATH_OFFSET,DI ;AN000;; copy to parameter block ;AN000 + XOR CX,CX ;AN000;; ;AN000 + LODSB ;AN000;; count the length of the path. ;AN000 + .WHILE ;AN000;; ;AN000 + STOSB ;AN000;; ;AN000 + LODSB ;AN000;; ;AN000 + INC CX ;AN000;; ;AN000 + .ENDWHILE ;AN000;; ;AN000 + MOV [BP].PATH_LENGTH,CX ;AN000;; copy to parameter block ;AN000 + POP CX ;AN000;; ;AN000 + POP DI ;AN000;; ;AN000 + POP SI ;AN000;; ;AN000 + POP DS ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + .ENDIF ;AN000;; ;AN000 + RET ;AN000;; ;AN000 +PROCESS_3RD_PARM ENDP ;AN000; ;AN000 + ;AN000; +CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/LABEL/LABEL.ASM b/v4.0/src/CMD/LABEL/LABEL.ASM new file mode 100644 index 0000000..c29d5b7 --- /dev/null +++ b/v4.0/src/CMD/LABEL/LABEL.ASM @@ -0,0 +1,1351 @@ + PAGE 90,132 ;A2 + title LABEL.SAL - DOS LABEL COMMAND +;***************************************************************************** +;* * +;* MODULE NAME: LABEL * +;* * +;* DESCRIPTIVE NAME: LABEL a diskette or disk * +;* * +;* FUNCTION: Create, change or delete a volume label on a disk. * +;* * +;* ENTRY POINT: Start * +;* * +;* INPUT: (DOS command line parameters) * +;* [d:][path]LABEL [d:][volume label] * +;* where: * +;* [d:][path] before LABEL specifies the drive and path that contains * +;* the LABEL command file. * +;* * +;* [d:][volume label] specifies the volume label. Volume labels are * +;* used to identify a disk. They can be up to 11 characters and are in * +;* the same format as volume labels created by FORMAT/V. * +;* * +;* EXIT-NORMAL: ERRORLEVEL 0 - Normal completion * +;* * +;* EXIT-ERROR: ERRORLEVEL 1 - Any error * +;* * +;* EFFECTS: The volume label is set to the indicated string. The volume * +;* serial number, if present, is also displayed. * +;* * +;* INCLUDED FILES: None * +;* * +;* INTERNAL REFERENCES: * +;* * +;* Routines: * +;* CHARACTER_CHECK - See if char is valid for filename * +;* CHECK_DELETE - Get user Y/N if to delete old label * +;* CHECK_FOR_DRIVE_LETTER - Parse for drive in string * +;* CHECK_TRANSLATE_DRIVE - See if drive is SUBST or ASSIGN * +;* CHK_DBCS -See if specified byte is a DBCS lead byte * +;* CHK_DBCS_BLANK - Process DBCS blank char * +;* CREATE_NEW_LABEL - Output new vol label * +;* DATA AREAS - STACK, buffers, FCB'S, message sublists * +;* DELETE_OLD_LABEL - Delete original volume label * +;* DISPLAY_MSG - Send msg to system message handler * +;* DRIVE_SETUP - Verify drive, get default, setup drive ID * +;* ERROR_EXIT - Abnormal return to DOS * +;* FIND_FIRST_CHAR - Locate first non blank in input * +;* FIND_OLD_LABEL - Get the existing volume label * +;* GET_NEW_LABEL - Parse new vol label name into path * +;* GET_SERIAL_NUM - Get vol ser number from "GET_MEDIA_ID" * +;* GET_USER_INPUT - Read from user new vol label * +;* MAIN CODE - PSP, entry point * +;* MAIN_BEGIN - High level function control * +;* OUTPUT_OLD_LABEL - Display the original vol label * +;* PRELOAD_MESSAGES - Set up sys msgs, DOS version check * +;* PROCESS_STRING - Mov string to buf, check bad chars * +;* SETUP_CRLF - Carriage return, line feed * +;* SETUP_DELLABEL - "Delete current volume label (Y/N)?" * +;* SETUP_HASLABEL - "Volume in drive %1 is %2" * +;* SETUP_INVCHAR - "Invalid characters in volume label" * +;* SETUP_INVDRIVE - "Invalid drive specification" * +;* SETUP_NETDRIVE - "Cannot %1 a Network drive" * +;* SETUP_NEWLABEL - "Volume label (11 characters, ENTER for none)?" * +;* SETUP_NOLABEL - "Volume in drive %1 has no label" * +;* SETUP_NOROOM - "Cannot make directory entry" * +;* SETUP_SERIALNUM - "Volume Serial Number is %1-%2" * +;* SETUP_SUBSTASGN - "Cannot %1 a SUBSTed or ASSIGNed drive" * +;* SETUP_TOOMANY - "Too many files open" * +;* * +;* Data Areas: * +;* CONTROL BLOCKS - SUBLISTS for message parameters * +;* BUFFERS - For GET_MEDIA_ID, several FCB'S * +;* PSP - Contains the DOS command line parameters. * +;* STACK - Temporary save area * +;* * +;* EXTERNAL REFERENCES: * +;* * +;* Routines: * +;* SYSDISPMSG (NEAR) - Message display routine * +;* SYSLOADMSG (NEAR) - System message loader * +;* * +;* Data Areas: * +;* DTA - defined for the DOS FINDFIRST function. * +;* * +;* NOTES: LABEL should not be used with SUBSTed drives. The root directory * +;* of the actual drive will be the target of LABEL. LABEL should * +;* not be used with ASSIGNed drives or to label network drives. * * +;* * +;* This module should be processed with the SALUT pre-processor * +;* with the re-alignment not requested, as: * +;* * +;* SALUT LABEL,NUL * +;* * +;* To assemble these modules, the sequential or alphabetical * +;* ordering of segments may be used. * +;* * +;* Sample LINK command: * +;* * +;* LINK @LABEL.ARF * +;* * +;* Where the LABEL.ARF is defined as: * +;* * +;* LABEL+ * +;* LABELM * +;* * +;* These modules should be linked in this order. The load module is * +;* a COM file. It should be converted via EXE2BIN to a .COM file. * +;* * +;* REVISION HISTORY: * +;* * +;* AN000;D DBCS Support (New LOC) 06/87 S. Maes * +;* AN000;M Message service routine (New LOC) 06/87 S. Maes * +;* AC000;M Message service routine (Changed LOC) 06/87 S. Maes * +;* AN000;S Serial Number (New LOC) 06/87 S. Maes * +;* AC000;K SALUT 08/87 E. Kiser * +;* Ax001; DCR0524 - enable deletion of labelID 04/88 S. Maes * +;* Ax002; PTM4282 - parse complete line for invalids 04/88 S. Maes * +;* AN003; PTM4588 - scan entire line fails DBCS 05/88 S. Maes * +;* * +;* COPYRIGHT: The following notice is found in the OBJ code generated * +;* in the LABELM.SAL module. * +;* * +;* "Version 4.00 (C)Copyright 1988 Microsoft +;* "Licensed Material - Program Property of Microsoft" * +;* * +;***************************************************************************** + HEADER +IF1 + %OUT COMPONENT=LABEL, MODULE=LABEL.SAL +ENDIF +HEADER MACRO TEXT +.XLIST + SUBTTL &TEXT +.LIST + PAGE + ENDM +;***************************************************************************** +; Equate Area +;***************************************************************************** +; $SALUT (4,20,25,36) ;AN000;K +; DOS FUNCTION CALLS +FCB_SEARCH equ 11h +FCB_DELETE equ 13h +GET_DEFAULT equ 19h +SET_DTA equ 1Ah +CLOSE equ 3Eh +READ equ 3Fh +IOCTL equ 44h +LOC_OR_NET equ 9h ;AN000;K Local or network, subfunc of IOCTL +EXIT equ 4Ch +CREATE_FILE equ 5Bh +YN_CHECK equ 6523h ;AN001; 65=GetExtCtry 23=Y/NCheck +GET_MEDIA_ID equ 6900h ;AN000;S Int 21 for Serial Number +GET_DBCS_ENV equ 6300h ;AN000;D DBCS support +XNAMETRANS equ 60h ;AN000; + +; DBCS SPECIAL CHARACTER DEFINITIONS + +DBCSBLK_BYTEONE equ 81h ;AN000;D 1st byte of DBCS blank +DBCSBLK_BYTETWO equ 40h ;AN000;D 2nd byte of DBCS blank +SBCSBLANKS equ 2020h ;AN000;D 2 SBCS blanks + +; MISCELLANEOUS EQUATES + +ASCII_DRV equ "A"-1 ;AN000;D Convert to Ascii drive +BLANK equ " " +CHAR_ZERO equ "0" ;AN000;K Padding for serial number +COLON equ ":" +DEFAULT_DRIVE equ 0 +DOT_LOCATION equ 8 +DRIVE_INVALID equ 0FFh +END_OF_STRING equ 0 +MAX_CHARS equ 11 +MAX_INPUT equ 100h-81h ;Size of input buffer +NO equ 0 ;AN001; Compare for Y/N response +PERIOD equ "." +YES equ 1 ;AN001; Compare for Y/N response +ZERO equ 0 + +; ERROR LEVEL RETURN CODES + +ERRORLEVEL_0 equ 0 +ERRORLEVEL_1 equ 1 + +; ATTRIBUTE OF DIRECTORY ENTRY + +VOL_ATTRIBUTE equ 8 + +; ERROR CODES FROM DOS FUNCTIONS + +VOL_NOT_FOUND equ 0FFh +TOO_MANY_FILES equ 4 + +; ID IF MESSAGES DISPLAYED BY "LABEL" + +TOO_MANY_MSG equ 1 ;AN000;M Too many files open +NO_ROOM_MSG equ 2 ;AN000;M Cannot make directory entry +INV_CHAR_MSG equ 3 ;AN000;M Invalid characters in volume label +NEW_LABEL_MSG equ 4 ;AN000;M Vol label (11 chars, ENTER for none)? +INV_DRIVE_MSG equ 5 ;AN000;M Invalid drive specification +NETWORKDRIVEMSG equ 6 ;AN000;M Cannot %1 a Network drive +SUBSTASSIGNMSG equ 7 ;AN000;M Cannot %1 a SUBSTed or ASSIGNed drive +NO_LABEL_MSG equ 8 ;AN000;M Volume in drive %1 has no label +SERIAL_NUM_MSG equ 9 ;AN000;M Volume Serial Number is %1 +HAS_LABEL_MSG equ 10 ;AN000;M Volume in Drive %1 is %2 +DEL_LABEL_MSG equ 11 ;AN001;M Delete current volume label (Y/N)? +CRLF_MSG equ 12 ;AN001;M CR,LF + +; DEFINITIONS OF FIELDS WITHIN MSG SUBLISTS + +MAXWIDTH equ 0 ;AN000;M 0 will ensure no padding +MINWIDTH equ 1 ;AN000;M At least 1 char to insert in msg +STR_INPUT equ 16 ;AN000;M Byte definition for s?_flags +SUBLIST_LENGTH equ 11 ;AN000;M Length of sublist structure +RESERVED equ 0 ;AN000;M Reserved byte field +CR equ 0Dh ;Carriage Return +NO_INPUT equ 00h ;AN000;M No input characters +DOS_CON_INPUT equ 00C8h ;AN000;M No input characters +EXT_ERR_CLASS equ 01h ;AN000;M DOS Extended error class +UTILITY_MSG_CLASS equ 0FFh ;AN000;M Utility message class +STDIN equ 0000h ;File handle +STDOUT equ 0001h ;Standard Output device handle +STDERR equ 0002h ;Standard Error Output device handle +BIN_HEX_WORD equ 23h ;AN000;M a0100011 +RIGHT_ALIGN equ 80h ;AN000;M 10xxxxxx +CHAR_FIELD_CHAR equ 0 ;AN000;M a0000000 + HEADER
+CSEG segment public + + ASSUME cs:CSEG,ds:CSEG,es:CSEG,ss:CSEG + + EXTRN SYSDISPMSG:NEAR ;SYSTEM DISPLAY MESSAGE ROUTINE + EXTRN SYSLOADMSG:NEAR ;SYSTEM MESSAGE LOADER ROUTINE + + org 5Ch +FCB1 label byte + + org 80h +Num_Parms label byte + + org 81h +Parm_Area label byte + + org 100h +Start: ;DOS ENTRY POINT + jmp Main_Begin ;SKIP CONSTANTS + HEADER + EVEN +Stack_Area db 512 dup ("S") ;Added in DOS 3.20 to support hardware requiring +End_Stack_Area db 0 ;large stacks. DO NOT PUT DATA ABOVE THIS ! +New_Vol_Path db " :\" ;Path for new vol label +New_Vol_Name db " " ;Where first 8 chars go +New_Vol_Ext db ". ",0 ;Dot and extension +End_Parameters dw 0 ;End of input string + +Program_Flag db 0 ;Status Flag +USER_INPUT equ 01h ;User has input already +LABEL_FND equ 02h ;Volume label found +NO_DELETE equ 04h ;No need for label delete +GET_INPUT equ 08h ;Need user input +CHAR_BAD equ 10h ;Invalid character in string +FOUND_DBCS equ 20h ;AN000;K in process of handling DBCS chars + +Vol_FCB db 0FFh ;Extended FCB + db 0,0,0,0,0 + db VOL_ATTRIBUTE ;Attribute for vol label +FCB_Drive db 0 ;Drive number +Vol_Name db "???????????" ;Match any vol name found + db 25 dup (0) ;Rest of the opened FCB +Label_Name db "???????????",0 ;AN000; +FCB_Drive_Char db " " ;AN000;K printable version of FCB_Drive above + +TranSrc db "A:CON",0,0 ;AN000;A Device so we don't hit the drive +TranDst db 64 dup(' ') ;AN000;A +Label_Word db "LABEL",0 ;AN000;M Message substitution parm + +Del_FCB db 0FFh ;Extended FCB + db 0,0,0,0,0 + db VOL_ATTRIBUTE ;Attribute for vol label +Del_Drive db 0 ;Drive number +Del_Name db "???????????" ;Match any vol name found + +; MESSAGE SUBLIST STRUCTURES + +Sublist1 Label Dword ;AN000;M Substitution list +s1_nxtlst db SUBLIST_LENGTH ;AN000;M (11)Ptr to next sublist +s1_reserve db RESERVED ;AN000;M (0)Reserved +s1_offset dw ? ;AN000;M Time/date or data pointer +s1_segment dw ? ;AN000;M Time/date or data pointer +s1_id db 1 ;AN000;M N of %n +s1_flags db ? ;AN000;M Data-type flags (a0sstttt) +s1_maxwidth db ? ;AN000;M Maximum field width +s1_minwidth db ? ;AN000;M Minimum field width +s1_padchar db ? ;AN000;M Char to pad field + +Sublist2 Label Dword ;AN000;M Substitution list +s2_nxtlst db SUBLIST_LENGTH ;AN000;M (11)Ptr to next sublist +s2_reserve db RESERVED ;AN000;M (0)Reserved +s2_offset dw ? ;AN000;M Time/date or data pointer +s2_segment dw ? ;AN000;M Time/date or data pointer +s2_id db 2 ;AN000;M N of %n +s2_flags db ? ;AN000;M Data-type flags (a0sstttt) +s2_maxwidth db ? ;AN000;M Maximum field width +s2_minwidth db ? ;AN000;M Minimum field width +s2_padchar db ? ;AN000;M Char to pad field + +; GET_MEDIA_ID STRUCTURE + +SerNumBuf Label Byte ;AN000;S GET_MEDIA_ID buffer + dw 0 ;AN000;S Info level (set on input) +SerNum dd 0 ;AN000;S Serial # + db 11 DUP(' ') ;AN000;S Volume label + db 8 DUP(' ') ;AN000;S File system type + +; CHK_DBCS STRUCTURE +DBCSev_Off dw 0 ;AC000;D offset of DBCS EV +DBCSev_Seg dw 0 ;AC000;D segment of DBCS EV + + HEADER +; $SALUT (4,4,9,36) ;AN000;K +;***************************************************************************** +;* * +;* SUBROUTINE NAME: main_begin * +;* * +;* SUBROUTINE FUNCTION: Preload message file and check DOS version * +;* by calling SYSLOADMSG * +;* Get the command line parameters * +;* Parse command line * +;* Verify the correctness of the parameters * +;* Get label if exists * +;* Get serial number if exists * +;* Get new volume name * +;* Make new volume file * +;* Print messages by calling SYSDISPMSG * +;* * +;* EXTERNAL ROUTINES: SYSDISPMSG * +;* SYSLOADMSG * +;* * +;* INTERNAL ROUTINES: Character_Check Main_Begin * +;* Check_Delete Output_Old_Label * +;* Check_For_Drive_Letter Preload_Messages * +;* Check_Trans_Drive Process_String * +;* Chk_DBCS Setup_CRLF * +;* Chk_DBCS_Blank Setup_DelLabel * +;* Create_New_Label Setup_HasLabel * +;* Delete_Old_Label Setup_InvChar * +;* Display_Msg Setup_InvDrive * +;* Drive_Setup Setup_NetDrive * +;* Error_Exit Setup_NewLabel * +;* Find_First_Char Setup_NoLabel * +;* Find_Old_Label Setup_NoRoom * +;* Get_New_Label Setup_SerialNum * +;* Get_Serial_Num Setup_SubstAsgn * +;* Get_User_Input Setup_TooMany * +;* * +;***************************************************************************** + PUBLIC MAIN_BEGIN +Main_Begin Proc Near + mov sp,offset End_Stack_Area ;Move stack to user area(Added in DOS 3.20) + cld + call Preload_Messages ;AN000;M Check DOS version & load msgs + call Drive_Setup ;Get Drive letters + call Find_Old_Label ;Get label if exist + call Get_New_Label ;Get New Name + call Check_Delete ;AN001; See if delete needed or wanted + call Delete_Old_Label ;Del the old label if it exists + call Create_New_Label ;Make new Vol file + mov ax,(EXIT shl 8)+ERRORLEVEL_0 ;all done, pass back zero ret code + INT 21H +Main_Begin ENDP + + HEADER +;***************************************************************************** +; Verify specified drive, get default if needed, setup drive letters +;***************************************************************************** + + PUBLIC DRIVE_SETUP +Drive_Setup PROC NEAR + cmp al,DRIVE_INVALID ;Was specified drive ok ? +; $if e ;AN000;K No + JNE $$IF1 + mov ax,INV_DRIVE_MSG ;Nope, tell & quit + call Setup_InvDrive ;AN000;M + call Display_Msg ;AN000;M Set up msg & display + call Error_Exit +; $endif ;AN000;K +$$IF1: +; Get_Drive: + mov al,FCB1 ;Get specified drive + cmp al,DEFAULT_DRIVE ;Was drive given ? +; $if e ;AN000;K No + JNE $$IF3 + mov ah,GET_DEFAULT ;No, get default drive + INT 21H + inc al ;Get a: based on 1, not 0 +; $endif ;AN000;K +$$IF3: +; Drive_Letter: + mov FCB_Drive,al ;Put drive number in FCB + mov Del_Drive,al ;Put drive number in FCB + mov bl,al + mov al,FCB_Drive ;AN000;K get numeric value of drive letter + add al,ASCII_DRV ;AN000;M ("A"-1) + mov FCB_Drive_Char,al ;AN000;K make drive printable + mov ax,(IOCTL SHL 8)+LOC_OR_NET ;(4409h)determine drive type + INT 21H + test dx,1000h ;bit 12 on means network drive +; $if nz ;AN000;K + JZ $$IF5 + mov ax,NETWORKDRIVEMSG + call Setup_NetDrive ;AN000;M + call Display_Msg ;AN000;M First display the msg + call Error_Exit +; $endif ;AN000;K +$$IF5: + call Check_Trans_Drive ;AN000;A Is drv SUBSTed/ASSIGNed? +; $if nz ;AN000;K Yes + JZ $$IF7 + mov ax,SUBSTASSIGNMSG ;AN000;A Prepare SUBST/ASSIGN msg + call Setup_SubstAsgn ;AN000;M + call Display_Msg ;AN000;A Display the message + call Error_Exit ;AN000;A Then exit +; $endif ;AN000;K +$$IF7: + mov al,Del_Drive + add al,ASCII_DRV ;AN000;K ("A"-1) Convert to Ascii + mov New_Vol_Path,al ;Put drive letter in path + ret +Drive_Setup ENDP + + HEADER +;***************************************************************************** +; Routine name: Check_Translate_Drive +;***************************************************************************** +; Descr: Do a name translate call on the drive letter to see if it is +; assigned by SUBST or ASSIGN +; Input: Drive + + PUBLIC CHECK_TRANS_DRIVE +Check_Trans_Drive PROC NEAR ;AN000;A + mov bl,FCB_Drive_Char ;AN000;A Get drive + mov byte ptr [TranSrc],bl ;AN000;A Make string "x:\" + mov si,offset TranSrc ;AN000;A Point to translate string + mov di,offset TranDst ;AN000;A Point at output buffer + mov ah,XNAMETRANS ;AN000;A (60H) Get real path + INT 21H ;AN000;A + mov bl,byte ptr [TranSrc] ;AN000;A Get drive letter from path + cmp bl,byte ptr [TranDst] ;AN000;A Did drive letter change? + ret ;AN000;A +Check_Trans_Drive ENDP ;AN000;A + + HEADER +;***************************************************************************** +; Find old volume label +;***************************************************************************** +; Input: VOL_FCB set to find any vol label +; Output: VOL_FCB has label name if one found +; PROGRAM_FLAG = LABEL_FND if one is found +; LABEL_NAME gets found label name + + PUBLIC FIND_OLD_LABEL +Find_Old_Label PROC NEAR + mov dx,offset Vol_FCB ;Point at FCB to find vol + mov ah,SET_DTA ;(1AH) + INT 21H + mov dx,offset Vol_FCB ;Point at FCB to find vol + mov ah,FCB_SEARCH ;(11H) + INT 21H ;Find vol label + cmp al,VOL_NOT_FOUND ;Find one +; $if ne ;AN000;K Yes + JE $$IF9 + or Program_Flag,LABEL_FND ;Yes, set flag + mov si,offset Vol_Name ;Found name + mov di,offset Label_Name ;Where to put it + mov cx,MAX_CHARS ;How many characters + rep movsb ;Move the string +; $endif ;AN000;K +$$IF9: +; Find_Return: + ret +Find_Old_Label ENDP + + HEADER +;***************************************************************************** +; Parse new volume label name into path. +;***************************************************************************** +; Input: PARM_AREA has input string +; Output: NEW_VOL_NAME has ASCIIZ string for new label, or an END_OF_STRING +; if nothing entered + + PUBLIC GET_NEW_LABEL +Get_New_Label PROC NEAR +; $do ;AN000;K +$$DO11: + xor cx,cx ;Zero counter + mov si,offset Parm_Area ;Input buffer + mov di,offset New_Vol_Name ;Target Buffer + call Find_First_Char ;Get first not blank char + test Program_Flag,GET_INPUT ;Find input? + jnz Need_User_Input ;No, go get it + call Process_String ;Scan string, move it + test Program_Flag,CHAR_BAD ;Invalid characters? + jnz Need_User_Input ;Yes, get user to input + mov al,END_OF_STRING ;Mark end of ASCIIZ string + stosb + cmp New_Vol_Name,END_OF_STRING ;Any chars entered? +; $leave ne ;Yes, all done here + JNE $$EN11 + test Program_Flag,USER_INPUT ;See if command line parse +; $leave nz ;No, user had his chance + JNZ $$EN11 +Need_User_Input: + test Program_Flag,USER_INPUT ;Is this the first time here? +; $if z ;AN000;K Yes, label not already gone out + JNZ $$IF14 + call Output_Old_Label ;Yes, print current vol label +; $endif ;AN000;K +$$IF14: +Input_New_Label: + call Get_User_Input ;Get new string +; $enddo ;AN000;K Go parse it again + JMP SHORT $$DO11 +$$EN11: + ret +Get_New_Label ENDP + + HEADER +;***************************************************************************** +; Find the first non blank character in input string +;***************************************************************************** +; Input: SI = pointer to next character +; Output: PROGRAM_FLAG = GET_INPUT if user input needed +; AL = First not blank character +; Notes: GET_INPUT set if nothing follows drive letter + + PUBLIC FIND_FIRST_CHAR +Find_First_Char PROC NEAR +; $do ;AN000;K +$$DO17: + and Program_Flag,not GET_INPUT ;Clear flag + lodsb ;Get char + call Chk_DBCS ;AN000;D Check DBCS env +; $if c ;AN000;K + JNC $$IF18 + call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? +; $endif ;AN000;K +$$IF18: + cmp al,BLANK ;Is it a blank? +; $enddo ne ;AN000;K No, quit + JE $$DO17 + call Check_For_Drive_Letter ;Parse out drive letter + call Chk_DBCS ;AN000;D Check DBCS env +; $if c ;AN000;K + JNC $$IF21 + call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? + and Program_Flag,not FOUND_DBCS ;AN000;K forget this was a dbcs for now +; $endif ;AN000;K +$$IF21: + cmp al,BLANK ;Blank following drive letter? +; $if e ;AN000;K + JNE $$IF23 + or Program_Flag,GET_INPUT +; $endif ;AN000;K +$$IF23: + ret +Find_First_Char ENDP + + HEADER +;***************************************************************************** +; Check DBCS environment +;***************************************************************************** +; Function: Check if a specified byte is in ranges of the DBCS lead bytes +; Input: AL = Code to be examined +; Output: If CF is on then a lead byte of DBCS +; Register: FL is used for the output, others are unchanged. + + PUBLIC CHK_DBCS +Chk_DBCS PROC ;AC000;D + push ds ;AC000;D save regs, about to be clobbered + push si ;AC000;D + cmp DBCSev_Seg,ZERO ;AC000;D Already set ? +; $if e ;AN000;K if the vector not yet found + JNE $$IF25 + push ax ;AC000;D + mov ax,GET_DBCS_ENV ;AC000;D GET DBCS EV call + INT 21H ;AC000;D ds:si points to the dbcs vector + ASSUME ds:NOTHING ;AN000;K that function clobbered old DS + mov DBCSev_Off,si ;AC000;D remem where dbcs vector is so next + mov DBCSev_Seg,ds ;AC000;D time don't have to look for it + pop ax ;AC000;D +; $endif ;AN000;K +$$IF25: + mov si,DBCSev_Off ;AC000;D set DS:SI to point to + mov ds,DBCSev_Seg ;AC000;D the dbcs vector +; $search ;AN000;K +$$DO27: + cmp word ptr [si],ZERO ;AC000;D vec ends with nul terminator entry +; $leave e ;AN000;K if that was terminator entry, quit + JE $$EN27 + cmp al,[si] ;AC000;D look at LOW value of vector +; $exitif nb,and ;AN000;K if this byte in range of LOW + JB $$IF27 + cmp al,[si+1] ;AC000;D look at HIGH value of vector +; $exitif na ;AN000;K if this byte is still in range + JA $$IF27 + or Program_Flag,FOUND_DBCS ;AN000;K remember we found one of a pair + stc ;AC000;D set flag to say, found a DBCS char +; $orelse ;AN000;K since char not in this vector + JMP SHORT $$SR27 +$$IF27: + add si,2 ;AC000;D go look at next vec in dbcs table +; $endloop ;AN000;K go back and ck out new vector entry + JMP SHORT $$DO27 +$$EN27: + clc ;AC000;D set flag to say not a DBCS char +; $endsrch ;AN000;K +$$SR27: + pop si ;AC000;D restore the regs + pop ds ;AC000;D + ASSUME ds:CSEG ;AN000;K tell masm, DS back to normal + ret ;AC000;D +Chk_DBCS ENDP ;AC000;D + + HEADER +;***************************************************************************** +; Check DBCS char for a blank (8140) +;***************************************************************************** +; Function: Check if a specified byte is a DBCS blank +; Input: AL = Byte to be examined +; SI = Points to next byte +; Output: SI = UNchanged + + PUBLIC CHK_DBCS_BLANK +Chk_DBCS_Blank PROC NEAR ;AN000;D + cmp al,DBCSBLK_BYTEONE ;AN000;D Is the leading byte 81h? +; $if e,and ;AN000;K + JNE $$IF33 + cmp byte ptr [si],DBCSBLK_BYTETWO ;AN000;D Is the 2nd byte 40h? +; $if e ;AN000;K Yes, change to 2 SBCS blanks + JNE $$IF33 +; Convert_DBCS_Blank: ;AN000;D + mov word ptr es:[si]-1,SBCSBLANKS ;AN000;D Fill it up with blank-blank + mov al,BLANK ;AN000;K pretend this char is a blank +; $endif ;AN000;K +$$IF33: +; DBCS_Blank_Exit: ;AN000;D + ret ;AN000;D And leave +Chk_DBCS_Blank ENDP ;AN000;D + + HEADER +;***************************************************************************** +; Parse a drive letter out of the string [Check_For_Drive_Letter] +;***************************************************************************** +; Input: SI = pointer to next character +; CX = character count +; Output: SI = SI+1 if drive letter entered + + PUBLIC CHECK_FOR_DRIVE_LETTER +Check_For_Drive_Letter PROC NEAR + test Program_Flag,USER_INPUT ;Input not from command line? +; $if z ;AN000;K + JNZ $$IF35 + cmp cx,END_OF_STRING ;Anything parsed yet +; $if e ;AN000; + JNE $$IF36 + cmp al,CR ;First char a CR ? +; $if ne + JE $$IF37 + cmp byte ptr [si],COLON ;Drive letter entered? +; $if e ;AN000;K + JNE $$IF38 + inc si ;Yes, point past the colon + lodsb ;And get next character +; $endif ;AN000;K +$$IF38: +; $endif ;AN000;K +$$IF37: +; $endif ;AN000;K +$$IF36: +; $endif ;AN000;K +$$IF35: +Drive_Letter_Ret: + ret +Check_For_Drive_Letter ENDP + + HEADER +;***************************************************************************** +; Move the input string into buffer, checking for bad characters +;***************************************************************************** +; Input: SI = pointer to next character +; DI = pointer to buffer +; AL = current character in string +; Output: PROGRAM_FLAG = CHAR_BAD if invalid char in string (Flag set in +; called Character_Check routine) +; Notes: Insert a "." in string to seperate 8th and 9th characters so +; ASCIIZ string is the result. + + PUBLIC PROCESS_STRING +Process_String PROC NEAR + cmp al,CR ;is it an ENTER ? +; $if e + JNE $$IF43 + test Program_Flag,USER_INPUT ;has user been told to provide input? +; $if nz ;If user has been prompted for input + JZ $$IF44 + cmp cx,ZERO ;And he said - nothing +; $if e + JNE $$IF45 + jmp Process_String_Return ;AN001; ENTER is acceptable +; $endif +$$IF45: +; $endif +$$IF44: +; $else ;Since got other than just ENTER + JMP SHORT $$EN43 +$$IF43: + test Program_Flag,FOUND_DBCS ;AN000;K If prev char not 1st of DBCS pair + jz Do_More_Check ;AN000;K then go check it out + and Program_Flag,not FOUND_DBCS ;AN000; Reset flag, found its partner + cmp cx,11 ;AC003; Continue to check chars but don't + jge Scan_Continue ;AC003; store anything more + jmp short Got_Ok_Character ;AN000; Partner is ok +Do_More_Check: + call Chk_DBCS ;AN000;D Check DBCS env + jnc Check_Char ;AN000;D If carry, it's a DBCS char + cmp cx,10 ;AC003; If previous char was the 10th + jge Scan_Continue ;AC003; then there is no room for 11th DBCS + call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? + jmp Got_Ok_Character ;AN000;D +Check_Char: + call Character_Check ;Is it a valid char ? + test Program_Flag,CHAR_BAD + jnz Process_String_Return ;Flag was set, char was invalid + cmp cx,11 ;AN003; Continue to check chars but don't + jge Scan_Continue ;AN003; store anything more +Got_Ok_Character: + stosb ;Good char, store it +Scan_Continue: ;AN003; Skip storing chars since past limit + inc cx ;Inc character count + cmp cx,DOT_LOCATION ;Do we need "." for extension? + jne Get_Next_Char ;No + mov al,PERIOD ;Get a "." for extension + stosb ;And save it +Get_Next_Char: + lodsb ;Get next character + cmp cx,MAX_INPUT ;AN002; Have we reached end? + jne Process_String ;No, go diddle with it +; $endif +$$EN43: +Process_String_Return: + ret +Process_String ENDP + + HEADER +;***************************************************************************** +; See if a character is valid for filename [Character_Check] +;***************************************************************************** +; Input: AL = character to be checked +; Output: AL = character +; PROGRAM_FLAG = CHAR_BAD if invalid characters found + + PUBLIC CHARACTER_CHECK +Character_Check PROC NEAR + or Program_Flag,CHAR_BAD ;Assume bad character + cmp al,"*" + je Char_Check_Done + cmp al,"?" + je Char_Check_Done + cmp al,"[" + je Char_Check_Done + cmp al,"]" + je Char_Check_Done + cmp al,":" + je Char_Check_Done + cmp al,"<" + je Char_Check_Done + cmp al,"|" + je Char_Check_Done + cmp al,">" + je Char_Check_Done + cmp al,"+" + je Char_Check_Done + cmp al,"=" + je Char_Check_Done + cmp al,";" + je Char_Check_Done + cmp al,"," + je Char_Check_Done + cmp al,"/" + je Char_Check_Done + cmp al,"\" + je Char_Check_Done + cmp al,'.' + je Char_Check_Done + cmp al,'"' + je Char_Check_Done + cmp al," " + jb Char_Check_Done + and Program_Flag,not CHAR_BAD ;Char is ok +Char_Check_Done: + ret +Character_Check ENDP + + HEADER +;***************************************************************************** +; Print the old volume label +;***************************************************************************** +; Input: PROGRAM_FLAG = LABEL_FND if there is a label +; Output: None +; Notes: Print the volume label + + PUBLIC OUTPUT_OLD_LABEL +Output_Old_Label PROC NEAR + mov ax,HAS_LABEL_MSG ;Assume label + call Setup_HasLabel ;AN000;M + test Program_Flag,LABEL_FND ;Is there one? +; $if z ;AN000;K If no label found, then + JNZ $$IF50 + mov ax,NO_LABEL_MSG ;No, other message + call Setup_NoLabel ;AN000;M +; $endif ;AN000;K +$$IF50: + call Display_Msg ;AC000;M Set up msg and display + call Get_Serial_Num ;AN000;S Since LABEL_FND, ck for SN +; $if nc ;AN000;K SN must be known + JC $$IF52 + mov ax,SERIAL_NUM_MSG ;AN000;S Prepare for SN message + call Setup_SerialNum ;AN000;M + call Display_Msg ;AC000;M Set up msg and display +; $endif ;AN000;K +$$IF52: + ret +Output_Old_Label ENDP + + HEADER +;***************************************************************************** +; Get the volume serial number +;***************************************************************************** +; Input: FCB_Drive +; Output: SerNum if no carry +; Notes: Only DOS Version 4.0 and above will contain serial numbers + + PUBLIC GET_SERIAL_NUM +Get_Serial_Num PROC NEAR ;AN000;S + mov ax,GET_MEDIA_ID ;AN000;S + mov bh,0 ;AN000;S + mov bl,FCB_Drive ;AN000;S Which drive to check + lea dx,SerNumBuf ;AN000;S Pt to the buffer + INT 21H ;AN000;S Make the call + ret ;AN000;S +Get_Serial_Num ENDP ;AN000;S + + HEADER +;***************************************************************************** +; Input from user a new volume label string +;***************************************************************************** +; Input: PROGRAM_FLAG = CHAR_BAD if there were invalid characters in string +; Output: New string placed in PARM_AREA +; Notes: Print bad character message if needed and prompt and get user input + + PUBLIC GET_USER_INPUT +Get_User_Input PROC NEAR + test Program_Flag,CHAR_BAD ;Do we need bad char message +; $if nz ;AN000;K + JZ $$IF54 + mov ax,INV_CHAR_MSG ;Yes + call Setup_InvChar ;AN000;M + call Display_Msg ;AC000;M Set up msg and display + and Program_Flag,not CHAR_BAD ;Char is ok +; $endif ;AN000;K +$$IF54: + mov ax,NEW_LABEL_MSG ;Tell user to input new label + call Setup_NewLabel ;AN000;M + call Display_Msg ;AC000;M Set up msg and display + mov dx,offset Parm_Area ;Point where to put new name + mov cx,MAX_INPUT ;Number of characters to read + mov bx,STDIN ;Read from keyboard + mov ah,READ ;(3FH) + INT 21H + or Program_Flag,USER_INPUT ;Indicate user input has been received + ret +Get_User_Input ENDP + + HEADER +;***************************************************************************** +; Check to see if old label should be deleted +;***************************************************************************** +; Input: PROGRAM_FLAG = LABEL_FND if there is a label +; Output: PROGRAM_FLAG = NO_DELETE if label should not be deleted +; Notes: Get user Y/N if to delete previous label + + PUBLIC CHECK_DELETE +Check_Delete PROC NEAR + test Program_Flag,LABEL_FND ;AN001; Is there a vol label + jz Check_Delete_Return ;AN001; No, no need for prompt + cmp New_Vol_Name,END_OF_STRING ;AN001; Did user enter label + jne Check_Delete_Return ;AN001; Yes, no need for prompt +Delete_Prompt: ;AN001; + mov ax,DEL_LABEL_MSG ;AN001; Point at Y/N prompt + call Setup_DelLabel ;AN001;M Prepare message + call Display_Msg ;AN001;M Call to Sysdispmsg + mov dx,ax ;AN001; Char ret'd, prep for ck + mov ax,YN_CHECK ;AN001; GetExtCtry,Y/NCheck + INT 21H ;AN001; + cmp ax,YES ;AN001; Delete label ? + je Check_Delete_Return ;AN001; Yes + cmp ax,NO ;AN001; Delete label ? + je Delete_Label ;AN001; Yes + jne Delete_Prompt ;AN001; No, try again +Delete_Label: ;AN001; + or Program_Flag,NO_DELETE ;AN001; Yes, set flag +Check_Delete_Return: ;AN001; + mov ax,CRLF_MSG ;AN001; Point at CRLF message + call Setup_CRLF ;AN001;M Prepare message + call Display_Msg ;AN001;M Call to Sysdispmsg + ret ;AN001; +Check_Delete ENDP + + HEADER +;***************************************************************************** +; Delete old volume label +;***************************************************************************** +; Input: VOL_FCB has name of label if one found +; PROGRAM_FLAG = NO_DELETE if label doesn't need to be deleted +; Output: Vol label deleted if it exists and user say's it is okay +; Notes: Ask user if old label should be deleted. + + PUBLIC DELETE_OLD_LABEL +Delete_Old_Label PROC NEAR + test Program_Flag,NO_DELETE ;Need to delete label ? +; $if z ;AN000;K + JNZ $$IF56 + lea dx,Del_FCB ;Point at FCB to delete vol + mov ah,FCB_DELETE ;(13H) label and delete it + INT 21H ;Can't use handle cause Chmod won't find it +; $endif ;AN000;K +$$IF56: + ret +Delete_Old_Label ENDP + + HEADER +;***************************************************************************** +; Create new volume label file if user specified one +;***************************************************************************** + + PUBLIC CREATE_NEW_LABEL +Create_New_Label PROC NEAR + cmp New_Vol_Name,END_OF_STRING ;Did user enter a vol label +; $if ne ;AN000;K + JE $$IF58 + mov dx,offset New_Vol_Path ;Point at path for file + mov cx,VOL_ATTRIBUTE ;Set it as a volume label + mov ah,CREATE_FILE ;(5BH) Go make it + INT 21H +; $if nc ;AN000;K + JC $$IF59 + mov bx,ax ;shift file handle + mov ah,CLOSE ;And close the file + INT 21H +; $else ;AN000;K since there was creation error, + JMP SHORT $$EN59 +$$IF59: + cmp ax,TOO_MANY_FILES ;Is it +; $if ne ;AN000;K if not "too many files", then + JE $$IF61 + mov ax,NO_ROOM_MSG ;AN000;M + call Setup_NoRoom ;AN000;M + call Display_Msg ;AN000;M + test Program_Flag,LABEL_FND ;AN000;K was an old label found? +; $if ne ;AN000;K if there was an old one, + JE $$IF62 + ;need to restore the previous label + ;because the new one did not stick + mov si,offset Label_Name ;AN000;K where old name was kept + mov di,offset New_Vol_Name ;AN000;K where to put old name + mov cx,8 ;AN000;K count of filename up to "." + rep movsb ;AN000;K + inc di ;AN000;K skip the "." + mov cx,3 ;AN000;K length of extension + rep movsb ;AN000;K + mov dx,offset New_Vol_Path ;AN000;K drive\path\filename + mov cx,VOL_ATTRIBUTE ;AN000;K make it a label + mov ah,CREATE_FILE ;AN000;K make a label + INT 21H ;AN000;K at least, try to, anyway... +; $endif ;AN000;K old label? +$$IF62: +; $else ;AN000;K since is "too many files", then... + JMP SHORT $$EN61 +$$IF61: + mov ax,TOO_MANY_MSG ;AN000;M + call Setup_TooMany ;AN000;M + call Display_Msg ;AN000;M +; $endif ;AN000;K +$$EN61: + jmp Error_Exit ;Tell user bad news and quit +; $endif ;AN000;K +$$EN59: +; $endif ;AN000;K +$$IF58: + ret +Create_New_Label ENDP + + HEADER +;***************************************************************************** +; Preload utility messages +;***************************************************************************** +; Input: None +; Output: None +; Notes: Checks DOS version, if incorrect, or if error loading messages, will +; display error message and terminate + + PUBLIC PRELOAD_MESSAGES +Preload_Messages PROC NEAR ;AN000;M + push ax ;AN000;M + push bp ;AN000;M + mov bp,sp ;AN000;M + push di ;AN000;M + push si ;AN000;M + call SYSLOADMSG ;AN000;M Load msgs & chk DOS ver +; $if c ;AN000;K + JNC $$IF68 + call SYSDISPMSG ;AN000;M + pop si ;AN000;M + pop di ;AN000;M + mov sp,bp ;AN000;M + pop bp ;AN000;M + pop ax ;AN000;M + call Error_Exit ;AN000;M +; $endif ;AN000;K +$$IF68: + pop si ;AN000;M + pop di ;AN000;M + mov sp,bp ;AN000;M + pop bp ;AN000;M + pop ax ;AN000;M + ret ;AN000;M +Preload_Messages ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Display utility messages +;***************************************************************************** +; Input: dx contains the messsage to display +; Output: None +; Notes: The message called is displayed to stdout/stderr unless AX returns +; with error code (then setup for extended error to display) + + PUBLIC DISPLAY_MSG +Display_Msg PROC NEAR ;AN000;M + push bp ;AN000;M + mov bp,sp ;AN000;M + push di ;AN000;M + push si ;AN000;M + call SYSDISPMSG ;AN000;M Now display the message +; $if c ;AN000;K if there was a problem, then... + JNC $$IF70 + mov bx,STDERR ;AN000;M Error msg, so stderr + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class + call SYSDISPMSG ;AN000;M Now display the extended error + pop si ;AN000;M + pop di ;AN000;M + mov sp,bp ;AN000;M + pop bp ;AN000;M + call Error_Exit ;AN000;M Nothing we can do so leave +; $endif ;AN000;K +$$IF70: +; Done: ;AN000;M + pop si ;AN000;M + pop di ;AN000;M + mov sp,bp ;AN000;M + pop bp ;AN000;M + ret ;AN000;M Bye,bye +Display_Msg ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_TOOMANY +Setup_TooMany PROC NEAR ;AN000;M + mov ax,4 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class + ret ;AN000;M Now display the message +Setup_TooMany ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_NOROOM +Setup_NoRoom PROC NEAR ;AN000;M + mov ax,82 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class + ret ;AN000;M +Setup_NoRoom ENDP + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_INVCHAR +Setup_InvChar PROC NEAR ;AN000;M + mov ax,3 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_InvChar ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_NEWLABEL +Setup_NewLabel PROC NEAR ;AN000;M + mov ax,6 ;AN000;M Utility's message number + mov bx,STDOUT ;AN000;M Info msg, so stdout + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_NewLabel ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_INVDRIVE +Setup_InvDrive PROC NEAR ;AN000;M + mov s1_offset,offset FCB_Drive_Char ;AN000;M + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting + mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s1_padchar,BLANK ;AN000;M In case, pad with blanks + mov ax,15 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + lea si,sublist1 ;AN000;M Display invalid drive + mov cx,0 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class + ret ;AN000;M +Setup_InvDrive ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_NETDRIVE +Setup_NetDrive PROC NEAR ;AN000;M + mov s1_offset,offset Label_Word ;AN000;M Cannot LABEL a network... + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,STR_INPUT ;AN000;M Set up the parm formatting + mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s1_padchar,BLANK ;AN000;M In case, pad with blanks + mov ax,8 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + lea si,sublist1 ;AN000;M Display network drive msg + mov cx,1 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_NetDrive ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_SUBSTASGN +Setup_SubstAsgn PROC NEAR ;AN000;M + mov s1_offset,offset Label_Word ;AN000;M Cannot LABEL a SUBSTed... + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,STR_INPUT ;AN000;M Set up the parm formatting + mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s1_padchar,BLANK ;AN000;M In case, pad with blanks + mov ax,2 ;AN000;M Utility's message number + mov bx,STDERR ;AN000;M Error msg, so stderr + lea si,sublist1 ;AN000;M Display SUBST/ASSIGN drive ,dh + mov cx,1 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_SubstAsgn ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_NOLABEL +Setup_NoLabel PROC NEAR ;AN000;M + mov s1_offset,offset FCB_Drive_Char ;AN000;M + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting + mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s1_padchar,BLANK ;AN000;M In case, pad with blanks + mov ax,4 ;AN000;M Utility's message number + mov bx,STDOUT ;AN000;M Info msg, so stdout + lea si,sublist1 ;AN000;M Display drive + mov cx,1 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_NoLabel ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_SERIALNUM +Setup_SerialNum PROC NEAR ;AN000;M + mov s1_offset,offset SerNum+2 ;AN000;M + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,BIN_HEX_WORD+RIGHT_ALIGN ;AN000;M Set up the parm formatting + mov s1_maxwidth,DWORD ;AN000;M 0 ensures no padding + mov s1_minwidth,DWORD ;AN000;M At least 1 char to insert + mov s1_padchar,CHAR_ZERO ;AN000;M In case, pad with ZERO CHAR + mov s2_offset,offset SerNum ;AN000;M + mov s2_segment,ds ;AN000;M Setup segment + mov s2_flags,BIN_HEX_WORD+RIGHT_ALIGN ;AN000;M Set up the parm formatting + mov s2_maxwidth,DWORD ;AN000;M 0 ensures no padding + mov s2_minwidth,DWORD ;AN000;M At least 1 char to insert + mov s2_padchar,CHAR_ZERO ;AN000;M In case, pad with ZERO CHAR + mov ax,7 ;AN000;M Utility's message number + mov bx,STDOUT ;AN000;M Info msg, so stdout + lea si,sublist1 ;AN000;M Display serial number + mov cx,2 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_SerialNum ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_HASLABEL +Setup_HasLabel PROC NEAR ;AN000;M + mov s1_offset,offset FCB_Drive_Char ;AN000;M + mov s1_segment,ds ;AN000;M Setup segment + mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting + mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s1_padchar,BLANK ;AN000;M In case, pad with blanks + mov s2_offset,offset Label_Name ;AN000;M + mov s2_segment,ds ;AN000;M Setup segment + mov s2_flags,STR_INPUT ;AN000;M Set up the parm formatting + mov s2_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding + mov s2_minwidth,MINWIDTH ;AN000;M At least 1 char to insert + mov s2_padchar,BLANK ;AN000;M In case, pad with blanks + mov ax,5 ;AN000;M Utility's message number + mov bx,STDOUT ;AN000;M Info msg, so stdout + lea si,sublist1 ;AN000;M Display drive then label + mov cx,2 ;AN000;M Substitution count + mov dl,NO_INPUT ;AN000;M No input characters + mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class + ret ;AN000;M +Setup_HasLabel ENDP ;AN000;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_DELLABEL +Setup_DelLabel PROC NEAR ;AN001;M + mov ax,9 ;AN001;M Utility's message number + mov bx,STDOUT ;AN001;M Info msg, so stdout + mov cx,0 ;AN001;M Substitution count + mov dl,DOS_CON_INPUT ;AN001;M Input Y/N character + mov dh,UTILITY_MSG_CLASS ;AN001;M Utility message class + ret ;AN001;M +Setup_DelLabel ENDP ;AN001;M + + HEADER +;***************************************************************************** +; Setup for utility messages +;***************************************************************************** +; Input: None +; Output: None + + PUBLIC SETUP_CRLF +Setup_CRLF PROC NEAR ;AN001;M + mov ax,10 ;AN001;M Utility's message number + mov bx,STDOUT ;AN001;M Info msg, so stdout + mov cx,0 ;AN001;M Substitution count + mov dl,NO_INPUT ;AN001;M Input Y/N character + mov dh,UTILITY_MSG_CLASS ;AN001;M No input characters + ret ;AN001;M +Setup_CRLF ENDP ;AN001;M + + HEADER +;***************************************************************************** +; Error on exit +;***************************************************************************** + + PUBLIC ERROR_EXIT +Error_Exit PROC NEAR ;AC000;M + mov ax,(EXIT SHL 8)+ERRORLEVEL_1 ;AN000;K Terminate, with ret code + INT 21H +Error_Exit ENDP ;AN000;M + +End_Of_Program label byte + Public End_Of_Program + +CSEG ends + end Start + \ No newline at end of file diff --git a/v4.0/src/CMD/LABEL/LABEL.LNK b/v4.0/src/CMD/LABEL/LABEL.LNK new file mode 100644 index 0000000..62ebbb4 --- /dev/null +++ b/v4.0/src/CMD/LABEL/LABEL.LNK @@ -0,0 +1,4 @@ +LABEL+ +LABELM +label.EXE; + \ No newline at end of file diff --git a/v4.0/src/CMD/LABEL/LABELM.ASM b/v4.0/src/CMD/LABEL/LABELM.ASM new file mode 100644 index 0000000..abd48cc --- /dev/null +++ b/v4.0/src/CMD/LABEL/LABELM.ASM @@ -0,0 +1,92 @@ + PAGE ,132 ; + TITLE LABELM.SAL - MESSAGE HANDLER FOR LABEL UTILITY +;***************************************************************************** +;* * +;* MODULE NAME: LABELM.SAL * +;* * +;* DESCRIPTIVE NAME: Include the DOS system MESSAGE HANDLER in the SEGMENT * +;* configuration expected by the modules of LABEL. * +;* * +;* FUNCTION: The common code of the DOS SYSTEM MESSAGE HANDLER is * +;* made a part of the LABEL module by using INCLUDE to * +;* bring in the common portion, in SYSMSG.INC. This * +;* included code contains the routines to initialize for * +;* message services, to find where a particular message * +;* is, and to display a message. * +;* * +;* ENTRY POINT: SYSDISPMSG:near * +;* SYSLOADMSG:near * +;* * +;* INPUT: ax = message number * +;* bx = handle to display to * +;* cx = number of %parms, 0 if none * +;* dx = class in high byte, input function in low * +;* si = offset in es: of sublist, or 0 if none * +;* * +;* EXIT-NORMAL: CARRY is not set * +;* * +;* EXIT-ERROR: CARRY is set * +;* Call SYSDISPMSG * +;* * +;* INTERNAL REFERENCES: * +;* Routines: SYSDISPMSG (generated by MSG_SERVICES macro) * +;* SYSLOADMSG " " " " * +;* Data Areas: INCLUDE SYSMSG.INC (permit Sys Msg handler definition) * +;* * +;* EXTERNAL REFERENCES: * +;* Routines: None * +;* Data Areas: Control blocks pointed to by input registers * +;* * +;* NOTES: This module should be processed with the SALUT pre-processor * +;* with the re-alignment not requested, as: * +;* * +;* SALUT LABELM,NUL * +;* * +;* To assemble these modules, the sequential or alphabetical * +;* ordering of segments may be used. * +;* * +;* Sample LINK command: * +;* * +;* LINK @LABEL.ARF * +;* * +;* Where the LABEL.ARF is defined as: * +;* * +;* LABEL+ * +;* LABELM * +;* * +;* These modules should be linked in this order. The load module is * +;* a COM file. It should be converted via EXE2BIN to a .COM file. * +;* * +;* REVISION HISTORY: * +;* * +;* Prolog edited 04/88 S. Maes * +;* * +;***************************************************************************** +IF1 + %OUT COMPONENT=LABEL MODULE=LABELM.SAL + %OUT INCLUDING SYSMSG.INC +ENDIF + INCLUDE sysmsg.inc + MSG_UTILNAME + +CSEG segment public + assume cs:CSEG,ds:CSEG + assume es:CSEG,ss:CSEG + + PUBLIC SYSDISPMSG,SYSLOADMSG + + MSG_SERVICES + MSG_SERVICES ;AN000;M Support Utility msgs + ;DEFAULT=CHECK DOS VERSION + ;DEFAULT=NEARmsg + ;DEFAULT=INPUTmsg + ;DEFAULT=NO TIMEmsg + ;DEFAULT=NO DATEmsg + ;DEFAULT=NO GETmsg + MSG_SERVICES +CSEG ENDS ;AN000;M Access to svcs macro + + include msgdcl.inc + + END + \ No newline at end of file diff --git a/v4.0/src/CMD/LABEL/LABL.SKL b/v4.0/src/CMD/LABEL/LABL.SKL new file mode 100644 index 0000000..fa12e33 --- /dev/null +++ b/v4.0/src/CMD/LABEL/LABL.SKL @@ -0,0 +1,26 @@ +;LABEL Utility +;Message Service Routine + +:util LABL ;BEGIN UTIL ;AN000; + +:class 1 ;EXTENDED ERRORS ;AN000; +;------- --------------- +;:use EXTEND4 ;Too many files open +;:use EXTEND15 ;Invalid drive specification +;:use EXTEND82 ;Can not make directory entry + +:class A ;COMMON & DEFINED MSGS ;AN000; +;------- ------------ +:use 01 COMMON1 ;Incorrect DOS version +:use 02 COMMON14 ;Cannot %1 a SUBSTed or ASSIGNed drive +:use 03 COMMON21 ;Invalid characters in volume label +:use 04 COMMON33 ;Volume in drive %1 has no label +:use 05 COMMON34 ;Volume in drive %1 is %2 +:use 06 COMMON35 ;Vol label (11 chars, ENTER for none)? +:use 07 COMMON36 ;Volume Serial Number is %1-%2 +:use 08 COMMON12 ;Cannot %1 a network drive +:def 09 CR,LF,"Delete current volume label (Y/N)?" ;AN001; +:use 10 COMMON38 ;CR,LF ;AN001; + +:end ;END UTIL ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/LABEL/MAKEFILE b/v4.0/src/CMD/LABEL/MAKEFILE new file mode 100644 index 0000000..d710a23 --- /dev/null +++ b/v4.0/src/CMD/LABEL/MAKEFILE @@ -0,0 +1,34 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: label.com + +labl.ctl: labl.skl \ + makefile \ + $(msg)\$(COUNTRY).msg + +label.obj: label.asm \ + makefile + +labelm.obj: labelm.asm \ + labl.ctl \ + makefile \ + $(inc)\copyrigh.inc \ + $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm + +label.com: label.obj \ + labelm.obj \ + makefile \ + label.lnk + link @label.lnk + exe2bin label.exe label.com + del label.exe diff --git a/v4.0/src/CMD/MAKEFILE b/v4.0/src/CMD/MAKEFILE new file mode 100644 index 0000000..b253a5b --- /dev/null +++ b/v4.0/src/CMD/MAKEFILE @@ -0,0 +1,83 @@ +#************************** CMD Root level Makefile *********************** + +make =nmake + +all: + cd command + $(make) + cd ..\attrib + $(make) + cd ..\assign + $(make) + cd ..\chkdsk + $(make) + cd ..\debug + $(make) + cd ..\edlin + $(make) + cd ..\exe2bin + $(make) + cd ..\find + $(make) + cd ..\fc + $(make) + cd ..\format + $(make) + cd ..\join + $(make) + cd ..\more + $(make) + cd ..\print + $(make) + cd ..\recover + $(make) + cd ..\sort + $(make) + cd ..\subst + $(make) + cd ..\sys + $(make) + cd ..\share + $(make) + cd ..\nlsfunc + $(make) + cd ..\ifsfunc + $(make) + cd ..\mem + $(make) + cd ..\filesys + $(make) + cd ..\backup + $(make) + cd ..\comp + $(make) + cd ..\diskcomp + $(make) + cd ..\diskcopy + $(make) + cd ..\fdisk + $(make) + cd ..\label + $(make) + cd ..\mode + $(make) + cd ..\restore + $(make) + cd ..\tree + $(make) + cd ..\replace + $(make) + cd ..\xcopy + $(make) + cd ..\graftabl + $(make) + cd ..\fastopen + $(make) + cd ..\append + $(make) + cd ..\graphics + $(make) + cd ..\keyb + $(make) + cd .. + diff --git a/v4.0/src/CMD/MEM/MAKEFILE b/v4.0/src/CMD/MEM/MAKEFILE new file mode 100644 index 0000000..ec63a73 --- /dev/null +++ b/v4.0/src/CMD/MEM/MAKEFILE @@ -0,0 +1,37 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h +lib =..\..\lib + +# +####################### dependencies begin here. ######################### +# + +all: mem.exe + + +mem.ctl: mem.skl \ + $(msg)\$(COUNTRY).msg makefile + +_parse.obj: _parse.asm \ + makefile \ + $(inc)\parse.asm \ + $(inc)\psdata.inc + +_msgret.obj: _msgret.asm \ + makefile \ + mem.ctl \ + $(inc)\msgserv.asm \ + $(inc)\sysmsg.inc + +mem.obj: mem.c \ + msgdef.h \ + $(hinc)\copyrigh.h + +mem.exe: mem.obj _msgret.obj _parse.obj + link mem+_msgret+_parse,,,$(lib)\mem; + + diff --git a/v4.0/src/CMD/MEM/MEM.C b/v4.0/src/CMD/MEM/MEM.C new file mode 100644 index 0000000..624681e --- /dev/null +++ b/v4.0/src/CMD/MEM/MEM.C @@ -0,0 +1,1674 @@ + +/*----------------------------------------------------------------------+ +| | +| | +| Title: MEM | +| | +| Syntax: | +| | +| From the DOS command line: | +| | +| MEM | +| - Used to display DOS memory map summary. | +| | +| MEM /PROGRAM | +| - Used to display DOS memory map. | +| | +| MEM /DEBUG | +| - Used to display a detailed DOS memory map. | +| | +| AN001 - PTM P2914 -> This PTM relates to MEM's ability to report| +| the accurate total byte count for EM | +| memory. | +| | +| AN002 - PTM P3477 -> MEM was displaying erroneous base memory | +| information for "Total" and "Available" | +| memory. This was due to incorrect logic | +| for RAM carving. | +| | +| AN003 - PTM P3912 -> MEM messages do not conform to spec. | +| PTM P3989 | +| | +| Date: 1/28/88 | +| | +| AN004 - PTM P4510 -> MEM does not give correct DOS size. | +| | +| Date: 4/27/88 | +| | +| AN005 - PTM P4957 -> MEM does not give correct DOS size for | +| programs loaded into high memory. | +| | +| Date: 6/07/88 | +| | ++----------------------------------------------------------------------*/ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + +#include "ctype.h" /* ;an000; */ +#include "conio.h" /* need for kbhit prototype */ /* ;an000; */ +#include "stdio.h" /* ;an000; */ +#include "dos.h" /* ;an000; */ +#include "string.h" /* ;an000; */ +#include "stdlib.h" /* ;an000; */ +#include "msgdef.h" /* ;an000; */ +#include "parse.h" /* ;an000; */ + +/* #include "copyrigh.h" */ /* Only need one copyright statement an004 */ + /* It is included by the message ret an004 */ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ + + char *SingleDrive = "%c:" ; /* ;an000; */ + char *MultipleDrives = "%c: - %c:" ; /* ;an000; */ + char *UnOwned = "----------" ; /* ;an000; */ + char *Ibmbio = "IO " ; /* ;an000; */ + char *Ibmdos = "MSDOS " ; + /* ;an000; */ + struct sublistx /* ;an000; */ + { /* ;an000; */ + unsigned char size; /* sublist size */ /* ;an000; */ + unsigned char reserved; /* reserved for future growth */ /* ;an000; */ + unsigned far *value; /* pointer to replaceable parm */ /* ;an000; */ + unsigned char id; /* type of replaceable parm */ /* ;an000; */ + unsigned char flags; /* how parm is to be displayed */ /* ;an000; */ + unsigned char max_width; /* max width of replaceable field */ /* ;an000; */ + unsigned char min_width; /* min width of replaceable field */ /* ;an000; */ + unsigned char pad_char; /* pad character for replaceable field */ /* ;an000; */ + } sublist[4]; /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| define structure used by parser | ++----------------------------------------------------------------------*/ + +struct p_parms p_p; /* ;an000; */ + /* ;an000; */ +struct p_parmsx p_px; /* ;an000; */ + /* ;an000; */ +struct p_control_blk p_con1; /* ;an000; */ +struct p_control_blk p_con2; /* ;an000; */ + /* ;an000; */ +struct p_result_blk p_result1; /* ;an000; */ +struct p_result_blk p_result2; /* ;an000; */ + /* ;an000; */ +struct p_value_blk p_noval; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + struct DEVICEHEADER { /* ;an000; */ + struct DEVICEHEADER far *NextDeviceHeader; /* ;an000; */ + unsigned Attributes; /* ;an000; */ + unsigned Strategy; /* ;an000; */ + unsigned Interrupt; /* ;an000; */ + char Name[8]; /* ;an000; */ + }; /* ;an000; */ + /* ;an000; */ +#define DA_TYPE 0x8000; /* ;an000; */ +#define DA_IOCTL 0x4000; /* ;an000; */ + /* ;an000; */ +#define a(fp) ((char) fp) /* ;an000; */ + /* ;an000; */ +/* defines used in EMS support */ /* ;an000; */ + /* ;an000; */ +#define GET_VECT 0x35 /* EMS interrupt */ /* ;an000; */ +#define EMS 0x67 /* ;an000; */ + /* ;an000; */ +#define CASSETTE 0x15 /* interrupt to get extended memory */ /* ;an000; */ + /* ;an000; */ +#define DOSEMSVER 0x40 /* EMS version */ /* ;an000; */ + /* ;an000; */ +#define EMSGetStat 0x4000 /* get stat */ /* ;an000; */ +#define EMSGetVer 0x4600 /* get version */ /* ;an000; */ +#define EMSGetFreePgs 0x4200 /* get free pages */ /* ;an000; */ + /* ;an000; */ +#define GetExtended 0x8800 /* get extended memory size */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/* defines used by total memory determination */ /* ;an000; */ +#define GET_PSP (unsigned char ) 0x62 /* get PSP function call */ /* ;an000; */ + +#define MEMORY_DET 0x12 /* BIOS interrupt used to get total memory size */ /* ;an000; */ + /* ;an000; */ + struct SYSIVAR { /* ;an000; */ + char far *DpbChain; /* ;an000; */ + char far *SftChain; /* ;an000; */ + char far *Clock; /* ;an000; */ + char far *Con; /* ;an000; */ + unsigned MaxSectorSize; /* ;an000; */ + char far *BufferChain; /* ;an000; */ + char far *CdsList; /* ;an000; */ + char far *FcbChain; /* ;an000; */ + unsigned FcbKeepCount; /* ;an000; */ + unsigned char BlockDeviceCount; /* ;an000; */ + char CdsCount; /* ;an000; */ + struct DEVICEHEADER far *DeviceDriverChain; /* ;an000; */ + unsigned NullDeviceAttributes; /* ;an000; */ + unsigned NullDeviceStrategyEntryPoint; /* ;an000; */ + unsigned NullDeviceInterruptEntryPoint; /* ;an000; */ + char NullDeviceName[8]; /* ;an000; */ + char SpliceIndicator; /* ;an000; */ + unsigned DosParagraphs; /* ;an000; */ + char far *DosServiceRntryPoint; /* ;an000; */ + char far *IfsChain; /* ;an000; */ + unsigned BufferValues; /* ;an000; */ + unsigned LastDriveValue; /* ;an000; */ + char BootDrive; /* ;an000; */ + char MoveType; + unsigned ExtendedMemory; + }; /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + struct ARENA { /* ;an000; */ + char Signature; /* ;an000; */ + unsigned Owner; /* ;an000; */ + unsigned Paragraphs; /* ;an000; */ + char Dummy[3]; /* ;an000; */ + char OwnerName[8]; /* ;an000; */ + }; /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +#define FALSE (char)(1==0) /* ;an000; */ +#define TRUE !(FALSE) /* ;an000; */ +#define CR '\x0d' /* ;an000; */ +#define LF '\x0a' /* ;an000; */ +#define NUL (char) '\0' /* ;an000; */ +#define TAB '\x09' /* ;an000; */ +#define BLANK ' ' /* ;an000; */ + /* ;an000; */ +extern unsigned DOS_TopOfMemory; /* PSP Top of memory from 'C' init code */ /* ;an005; */ + +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + unsigned far *ArenaHeadPtr; /* ;an000; */ + struct SYSIVAR far *SysVarsPtr; /* ;an000; */ + /* ;an000; */ + char OwnerName[128]; /* ;an000; */ + char TypeText[128]; /* ;an000; */ + char cmd_line[128]; /* ;an000; */ + char far *cmdline; /* ;an000; */ + /* ;an000; */ + char UseArgvZero = TRUE; /* ;an000; */ + char EMSInstalledFlag = (char) 2; /* ;an000; */ + /* ;an000; */ + union REGS InRegs; /* ;an000; */ + union REGS OutRegs; /* ;an000; */ + struct SREGS SegRegs; /* ;an000; */ + /* ;an000; */ + int DataLevel; /* ;an000; */ + int i; /* ;an000; */ + /* ;an000; */ + int BlockDeviceNumber; /* ;an000; */ + unsigned Parse_Ptr; /* ;an003; dms; pointer to command */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void main(int, char *[]); /* ;an000; */ + /* ;an000; */ +int printf(); +int sprintf(); +int strcmp(const char *, const char *); +int sscanf(); /* ;an000; */ +void exit(int); /* ;an000; */ +int kbhit(); /* ;an000; */ +char *OwnerOf(struct ARENA far *); /* ;an000; */ +char *TypeOf(struct ARENA far *); /* ;an000; */ +unsigned long AddressOf(char far *); /* ;an000; */ + /* ;an000; */ +char EMSInstalled(void); /* ;an000; */ +void DisplayEMSSummary(void); /* ;an000; */ +void DisplayEMSDetail(void); /* ;an000; */ + /* ;an000; */ +void DisplayBaseSummary(void); /* ;an000; */ +void DisplayExtendedSummary(void); /* ;an000; */ +void DisplayExpandedSummary(void); /* ;an000; */ + /* ;an000; */ +void DisplayBaseDetail(void); /* ;an000; */ + /* ;an000; */ +void GetFromArgvZero(unsigned,unsigned far *); /* ;an000; */ + /* ;an000; */ +void DisplayDeviceDriver(struct DEVICEHEADER far *,int); /* ;an000; */ + /* ;an000; */ +void parse_init(void); /* ;an000; */ + /* ;an000; */ +void Parse_Message(int,int,unsigned char); /* ;an000; */ +void Sub0_Message(int,int,unsigned char); /* ;an000; */ +void Sub1_Message(int,int,unsigned char,unsigned long int *); /* ;an000; */ +void Sub2_Message(int,int,unsigned char,char *,int); /* ;an000; */ +void Sub3_Message(int,int,unsigned char, /* ;an000; */ + char *, /* ;an000; */ + unsigned long int *, /* ;an000; */ + int); /* ;an000; */ + /* ;an000; */ +void Sub4_Message(int,int,unsigned char, /* ;an000; */ + unsigned long int *, /* ;an000; */ + int, /* ;an000; */ + unsigned long int *, /* ;an000; */ + int); /* ;an000; */ + /* ;an000; */ +void Sub4a_Message(int,int,unsigned char, /* ;an000; */ + unsigned long int *, /* ;an000; */ + char *, /* ;an000; */ + unsigned long int *, /* ;an000; */ + char *); /* ;an000; */ + /* ;an000; */ +void EMSPrint(int,int,unsigned char, /* ;an000; */ + int *, /* ;an000; */ + char *, /* ;an000; */ + unsigned long int *); /* ;an000; */ + /* ;an000; */ +extern void sysloadmsg(union REGS *, union REGS *); /* ;an000; */ +extern void sysdispmsg(union REGS *, union REGS *); /* ;an000; */ +extern void sysgetmsg(union REGS *, struct SREGS *, union REGS *); /* ;an000; */ +extern void parse(union REGS *, union REGS *); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void main(argc,argv) /* ;an000; */ +int argc; /* ;an000; */ +char *argv[]; /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + sysloadmsg(&InRegs,&OutRegs); /* ;an000; */ + if ((OutRegs.x.cflag & CarryFlag) == CarryFlag) /* ;an000; */ + { /* ;an000; */ + sysdispmsg(&OutRegs,&OutRegs); /* ;an000; */ + exit(1); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + InRegs.h.ah = (unsigned char) 0x62; /* an000; dms; get the PSP */ /* ;an000; */ + intdosx(&InRegs, &InRegs, &SegRegs); /* an000; dms; invoke the INT 21 */ /* ;an000; */ + /* ;an000; */ + FP_OFF(cmdline) = 0x81; /* an000; dms; offset of command line */ /* ;an000; */ + FP_SEG(cmdline) = InRegs.x.bx; /* an000; dms; segment of command line */ /* ;an000; */ + /* ;an000; */ + i = 0; /* an000; dms; init index */ /* ;an000; */ + while ( *cmdline != (char) '\x0d' ) cmd_line[i++] = *cmdline++; /* an000; dms; while no CR */ /* ;an000; */ + cmd_line[i++] = (char) '\x0d'; /* an000; dms; CR terminate string */ /* ;an000; */ + cmd_line[i++] = (char) '\0'; /* an000; dms; null terminate string */ /* ;an000; */ + /* ;an000; */ + DataLevel = 0; /* ;an000; */ + /* ;an000; */ + parse_init(); /* an000; dms; init for parser */ /* ;an000; */ + InRegs.x.si = (unsigned)cmd_line; /* an000; dms; initialize to command ln.*/ /* ;an000; */ + InRegs.x.cx = (unsigned)0; /* an000; dms; ordinal of 0 */ /* ;an000; */ + InRegs.x.dx = (unsigned)0; /* an000; dms; init pointer */ /* ;an000; */ + InRegs.x.di = (unsigned)&p_p; /* an000; dms; point to ctrl blocks */ /* ;an000; */ + Parse_Ptr = (unsigned)cmd_line; /*;an003; dms; point to command */ + /* ;an000; */ + parse(&InRegs,&OutRegs); /* an000; dms; parse command line */ /* ;an000; */ + while (OutRegs.x.ax == p_no_error) /* an000; dms; good parse loop */ /* ;an000; */ + { /* ;an000; */ + if (p_result1.P_SYNONYM_Ptr == (unsigned int)p_con1.p_keyorsw) /* an000; dms; DEBUG switch */ /* ;an000; */ + DataLevel = 2; /* an000; dms; flag DEBUG switch */ /* ;an000; */ + if (p_result2.P_SYNONYM_Ptr == (unsigned int)p_con2.p_keyorsw) /* an000; dms; PROGRAM switch */ /* ;an000; */ + DataLevel = 1; /* an000; dms; flag PROGRAM switch */ /* ;an000; */ + Parse_Ptr = OutRegs.x.si; /* an003; dms; point to next parm */ + parse(&OutRegs,&OutRegs); /* an000; dms; parse the line */ /* ;an000; */ + if (OutRegs.x.ax == p_no_error) /* an000; dms; check for > 1 switch */ /* ;an000; */ + OutRegs.x.ax = p_too_many; /* an000; dms; flag too many */ /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (OutRegs.x.ax != p_rc_eol) /* an000; dms; parse error? */ /* ;an000; */ + { /* ;an000; */ + Parse_Message(OutRegs.x.ax,STDERR,Parse_Err_Class); /* an000; dms; display parse error */ /* ;an000; */ + exit(1); /* an000; dms; exit the program */ /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if (DataLevel > 0) /* ;an000; */ + { /* ;an000; */ + DisplayBaseDetail(); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + DisplayBaseSummary(); /* display low memory totals */ /* ;an000; */ + /* ;an000; */ + if (EMSInstalled() && (DataLevel > 1)) /* ;an000; */ + DisplayEMSDetail(); /* display EMS memory totals */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if (EMSInstalled()) /* ;an000; */ + DisplayEMSSummary(); /* display EMS memory totals */ /* ;an000; */ + /* ;an000; */ + DisplayExtendedSummary(); /* display extended memory summary */ /* ;an000; */ + /* ;an000; */ + return; /* end of MEM main routine */ /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayBaseDetail() /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + struct ARENA far *ThisArenaPtr; /* ;an000; */ + struct ARENA far *NextArenaPtr; /* ;an000; */ + struct ARENA far *ThisConfigArenaPtr; /* ;an000; */ + struct ARENA far *NextConfigArenaPtr; /* ;an000; */ + /* ;an000; */ + struct DEVICEHEADER far *ThisDeviceDriver; /* ;an000; */ + /* ;an000; */ + int SystemDataType; /* ;an000; */ + char SystemDataOwner[64]; /* ;an000; */ + /* ;an000; */ + int i; /* ;an000; */ + unsigned int long Out_Var1; /* ;an000; */ + unsigned int long Out_Var2; /* ;an000; */ + char Out_Str1[64]; /* ;an000; */ + char Out_Str2[64]; /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + if (DataLevel > 0) /* ;an000; */ + { /* ;an000; */ + Sub0_Message(Title1Msg,STDOUT,Utility_Msg_Class); /* ;an000; */ + Sub0_Message(Title2Msg,STDOUT,Utility_Msg_Class); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + InRegs.h.ah = (unsigned char) 0x30; /* ;an000; */ + intdos(&InRegs, &OutRegs); /* ;an000; */ + /* ;an000; */ + if ( (OutRegs.h.al != (unsigned char) 3) || (OutRegs.h.ah < (unsigned char) 40) ) /* ;an000; */ + UseArgvZero = TRUE; /* ;an000; */ + else UseArgvZero = FALSE; /* ;an000; */ + /* ;an000; */ + /* Display stuff below DOS */ /* ;an000; */ + /* ;an000; */ + Out_Var1 = 0l; /* ;an000; */ + Out_Var2 = 0x400l; /* ;an000; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + BlankMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + InterruptVectorMsg); /* ;an000; */ + /* ;an000; */ + Out_Var1 = 0x400l; /* ;an000; */ + Out_Var2 = 0x100l; /* ;an000; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + BlankMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + ROMCommunicationAreaMsg); /* ;an000; */ + /* ;an000; */ + Out_Var1 = 0x500l; /* ;an000; */ + Out_Var2 = 0x200l; /* ;an000; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + BlankMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + DOSCommunicationAreaMsg); /* ;an000; */ + /* ;an000; */ + /* Display the DOS data */ /* ;an000; */ + /* ;an000; */ + InRegs.h.ah = (unsigned char) 0x52; /* ;an000; */ + intdosx(&InRegs,&OutRegs,&SegRegs); /* ;an000; */ + /* ;an000; */ + FP_SEG(SysVarsPtr) = SegRegs.es; /* ;an000; */ + FP_OFF(SysVarsPtr) = OutRegs.x.bx; /* ;an000; */ + /* ;an000; */ + /* Display the BIO location and size */ /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + Out_Var1 = 0x700l; /* ;an000; */ + Out_Var2 = (long) (FP_SEG(SysVarsPtr) - 0x70)*16l; /* ;an000; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + IbmbioMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + SystemProgramMsg); /* ;an000; */ + /* ;an000; */ + /* Display the Base Device Driver Locations and Sizes */ /* ;an000; */ + /* ;an000; */ + BlockDeviceNumber = 0; /* ;an000; */ + /* ;an000; */ + for (ThisDeviceDriver = SysVarsPtr -> DeviceDriverChain; /* ;an000; */ + (FP_OFF(ThisDeviceDriver) != 0xFFFF); /* ;an000; */ + ThisDeviceDriver = ThisDeviceDriver -> NextDeviceHeader) /* ;an000; */ + { if ( FP_SEG(ThisDeviceDriver) < FP_SEG(SysVarsPtr) ) /* ;an000; */ + DisplayDeviceDriver(ThisDeviceDriver,SystemDeviceDriverMsg); /* ;an000; */ + kbhit(); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* Display the DOS location and size */ /* ;an000; */ + + FP_SEG(ArenaHeadPtr) = FP_SEG(SysVarsPtr); /* ;an004; */ + FP_OFF(ArenaHeadPtr) = FP_OFF(SysVarsPtr) - 2; /* ;an004; */ + /* ;an004; */ + FP_SEG(ThisArenaPtr) = *ArenaHeadPtr; /* ;an004; */ + FP_OFF(ThisArenaPtr) = 0; /* ;an004; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + Out_Var1 = (long) FP_SEG(SysVarsPtr) * 16l; /* ;an000; */ + Out_Var2 = (long) ((AddressOf((char far *)ThisArenaPtr)) - Out_Var1); /* ;ac004; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + IbmdosMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + SystemProgramMsg); /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + /* Display the memory data */ /* ;an000; */ + /* ;an000; */ + while (ThisArenaPtr -> Signature != (char) 'Z') /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + if (ThisArenaPtr -> Owner == 8) /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + Out_Var1 = AddressOf((char far *)ThisArenaPtr); /* ;an000; */ + Out_Var2 = (long) (ThisArenaPtr -> Paragraphs) * 16l; /* ;an000; */ + Sub4_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + IbmbioMsg, /* ;an000; */ + &Out_Var2, /* ;an000; */ + SystemDataMsg); /* ;an000; */ + /* ;an000; */ + FP_SEG(NextArenaPtr) = FP_SEG(ThisArenaPtr) + ThisArenaPtr -> Paragraphs + 1; /* ;an000; */ + FP_OFF(NextArenaPtr) = 0; /* ;an000; */ + /* ;an000; */ + FP_SEG(ThisConfigArenaPtr) = FP_SEG(ThisArenaPtr) + 1; /* ;an000; */ + FP_OFF(ThisConfigArenaPtr) = 0; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + while ( (FP_SEG(ThisConfigArenaPtr) > FP_SEG(ThisArenaPtr)) && /* ;an000; */ + (FP_SEG(ThisConfigArenaPtr) < FP_SEG(NextArenaPtr)) ) /* ;an000; */ + { /* ;an000; */ + strcpy(SystemDataOwner," "); /* ;an000; */ + switch(ThisConfigArenaPtr -> Signature) /* ;an000; */ + { /* ;an000; */ + case 'B': /* ;an000; */ + SystemDataType = ConfigBuffersMsg; /* ;an000; */ + break; /* ;an000; */ + case 'D': /* ;an000; */ + SystemDataType = ConfigDeviceMsg; /* ;an000; */ + strcpy(SystemDataOwner,OwnerOf(ThisConfigArenaPtr)); /* ;an000; */ + break; /* ;an000; */ + case 'F': /* ;an000; */ + SystemDataType = ConfigFilesMsg; /* ;an000; */ + break; /* ;an000; */ + case 'I': /* ;an000; */ + SystemDataType = ConfigIFSMsg; /* ;an000; */ + strcpy(SystemDataOwner,OwnerOf(ThisConfigArenaPtr)); /* ;an000; */ + break; /* ;an000; */ + case 'L': /* ;an000; */ + SystemDataType = ConfigLastDriveMsg; /* ;an000; */ + break; /* ;an000; */ + case 'S': /* ;an000; */ + SystemDataType = ConfigStacksMsg; /* ;an000; */ + break; /* ;an000; */ + case 'T': /* gga */ /* ;an000; */ + SystemDataType = ConfigInstallMsg; /* gga */ /* ;an000; */ + break; /* gga */ /* ;an000; */ + case 'X': /* ;an000; */ + SystemDataType = ConfigFcbsMsg; /* ;an000; */ + break; /* ;an000; */ + default: /* ;an000; */ + SystemDataType = BlankMsg; /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + Out_Var1 = ((long) ThisConfigArenaPtr -> Paragraphs) * 16l; /* ;an000; */ + Sub3_Message(DriverLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + SystemDataOwner, /* ;an000; */ + &Out_Var1, /* ;an000; */ + SystemDataType ); /* ;an000; */ + /* ;an000; */ + NextConfigArenaPtr = ThisConfigArenaPtr; /* ;an000; */ + FP_SEG(NextConfigArenaPtr) += NextConfigArenaPtr -> Paragraphs + 1; /* ;an000; */ + if (ThisConfigArenaPtr -> Signature == (char) 'D') /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + FP_SEG(ThisDeviceDriver) = FP_SEG(ThisConfigArenaPtr) + 1; /* ;an000; */ + FP_OFF(ThisDeviceDriver) = 0; /* ;an000; */ + while ( (a(ThisDeviceDriver) > a(ThisConfigArenaPtr)) && /* ;an000; */ + (a(ThisDeviceDriver) < a(NextConfigArenaPtr)) ) /* ;an000; */ + DisplayDeviceDriver(ThisDeviceDriver,InstalledDeviceDriverMsg); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + FP_SEG(ThisConfigArenaPtr) += ThisConfigArenaPtr -> Paragraphs + 1; /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + else { /* ;an000; */ + /* ;an000; */ + Out_Var1 = AddressOf((char far *)ThisArenaPtr); /* ;an000; */ + Out_Var2 = ((long) (ThisArenaPtr -> Paragraphs)) * 16l; /* ;an000; */ + strcpy(Out_Str1,OwnerOf(ThisArenaPtr)); /* ;an000; */ + strcpy(Out_Str2,TypeOf(ThisArenaPtr)); /* ;an000; */ + Sub4a_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + Out_Str1, /* ;an000; */ + &Out_Var2, /* ;an000; */ + Out_Str2); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + FP_SEG(ThisArenaPtr) += ThisArenaPtr -> Paragraphs + 1; /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + Out_Var1 = AddressOf((char far *)ThisArenaPtr); /* ;an000; */ + Out_Var2 = ((long) (ThisArenaPtr -> Paragraphs)) * 16l; /* ;an000; */ + strcpy(Out_Str1,OwnerOf(ThisArenaPtr)); /* ;an000; */ + strcpy(Out_Str2,TypeOf(ThisArenaPtr)); /* ;an000; */ + Sub4a_Message(MainLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &Out_Var1, /* ;an000; */ + Out_Str1, /* ;an000; */ + &Out_Var2, /* ;an000; */ + Out_Str2); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + return; /* end of MEM main routine */ /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayDeviceDriver(ThisDeviceDriver,DeviceDriverType) /* ;an000; */ +struct DEVICEHEADER far *ThisDeviceDriver; /* ;an000; */ +int DeviceDriverType; /* ;an000; */ +{ /* ;an000; */ + char LocalDeviceName[16]; /* ;an000; */ + int i; /* ;an000; */ + /* ;an000; */ + if (DataLevel < 2) return; /* ;an000; */ + /* ;an000; */ + if ( ((ThisDeviceDriver -> Attributes) & 0x8000 ) != 0 ) /* ;an000; */ + { for (i = 0; i < 8; i++) LocalDeviceName[i] = ThisDeviceDriver -> Name[i]; /* ;an000; */ + LocalDeviceName[8] = NUL; /* ;an000; */ + /* ;an000; */ + Sub2_Message(DeviceLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + LocalDeviceName, /* ;an000; */ + DeviceDriverType); /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + else { /* ;an000; */ + if ((int) ThisDeviceDriver -> Name[0] == 1) /* ;an000; */ + sprintf(&LocalDeviceName[0],SingleDrive,'A'+BlockDeviceNumber); /* ;an000; */ + else sprintf(&LocalDeviceName[0],MultipleDrives, /* ;an000; */ + 'A'+BlockDeviceNumber, /* ;an000; */ + 'A'+BlockDeviceNumber + ((int) ThisDeviceDriver -> Name[0]) - 1); /* ;an000; */ + /* ;an000; */ + Sub2_Message(DeviceLineMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + LocalDeviceName, /* ;an000; */ + DeviceDriverType); /* ;an000; */ + /* ;an000; */ + BlockDeviceNumber += (int) (ThisDeviceDriver -> Name[0]); /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayBaseSummary() /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + struct PSP_STRUC /* ;an000; */ + { /* ;an000; */ + unsigned int int_20; /* ;an000; */ + unsigned int top_of_memory; /* ;an000; */ + }; /* ;an000; */ + /* ;an000; */ + char far *CarvedPtr; /* ;an000; */ + /* ;an000; */ + unsigned long int total_mem; /* total memory in system */ /* ;an000; */ + unsigned long int avail_mem; /* avail memory in system */ /* ;an000; */ + unsigned long int free_mem; /* free memory */ /* ;an000; */ + struct PSP_STRUC far *PSPptr; /* ;an000; */ + /* ;an000; */ +/* skip a line */ /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ +/* get PSP info */ /* ;an000; */ + InRegs.h.ah = GET_PSP; /* get PSP function call */ /* ;an000; */ + intdos(&InRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_SEG(PSPptr) = OutRegs.x.bx; /* PSP segment */ /* ;an000; */ + FP_OFF(PSPptr) = 0; /* offset 0 */ /* ;an000; */ + +/* Get total memory in system */ /* ;an000; */ + int86(MEMORY_DET,&InRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ +/* Convert to bytes */ /* ;an000; */ + total_mem = (unsigned long int) OutRegs.x.ax * 1024l; /* ;an000; */ + avail_mem = total_mem; + InRegs.x.bx = 0; /* ;an000; */ + InRegs.x.ax = 0xc100; /* ;an000; */ + int86x(0x15, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + if (OutRegs.x.cflag == 0) /* ;an000; */ + { /* ;an000; */ + FP_SEG(CarvedPtr) = SegRegs.es; /* ;an000; */ + FP_OFF(CarvedPtr) = 0; /* ;an000; */ + total_mem = total_mem + ( (unsigned long int) (*CarvedPtr) * 1024l) ; /* ;an002; dms;adjust total for */ + } /* RAM carve value */ + /* ;an000; */ + Sub1_Message(TotalMemoryMsg,STDOUT,Utility_Msg_Class,&total_mem); /* ;an000; */ + /* ;an000; */ + Sub1_Message(AvailableMemoryMsg,STDOUT,Utility_Msg_Class,&avail_mem); /* ;an000; */ + /* ;an000; */ +/* Calculate the total memory used. PSP segment * 16. Subtract from total to get free_mem */ /* ;an000; */ + free_mem = (DOS_TopOfMemory * 16l) - (FP_SEG(PSPptr)*16l); /* ;an000;ac005; */ + /* ;an000; */ + Sub1_Message(FreeMemoryMsg,STDOUT,Utility_Msg_Class,&free_mem); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end of display_low_total */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayEMSDetail() /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ +#define EMSGetHandleName 0x5300 /* get handle name function */ /* ;an000; */ +#define EMSGetHandlePages 0x4c00 /* get handle name function */ /* ;an000; */ +#define EMSCODE_83 0x83 /* handle not found error */ /* ;an000; */ +#define EMSMaxHandles 256 /* max number handles */ /* ;an000; */ + /* ;an000; */ + int HandleIndex; /* used to step through handles */ /* ;an000; */ + char HandleName[9]; /* save area for handle name */ /* ;an000; */ + unsigned long int HandleMem; /* memory associated w/handle */ /* ;an000; */ + char TitlesPrinted = FALSE; /* flag for printing titles */ /* ;an000; */ + /* ;an000; */ + HandleName[0] = NUL; /* initialize the array */ /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + segread(&SegRegs); /* ;an000; */ + /* ;an000; */ + SegRegs.es = SegRegs.ds; /* ;an000; */ + /* ;an000; */ + for (HandleIndex = 0; HandleIndex < EMSMaxHandles; HandleIndex++) /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = EMSGetHandleName; /* get handle name */ /* ;an000; */ + InRegs.x.dx = HandleIndex; /* handle in question */ /* ;an000; */ + InRegs.x.di = (unsigned int) HandleName; /* point to handle name */ /* ;an000; */ + int86x(EMS, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + /* ;an000; */ + HandleName[8] = NUL; /* make sure terminated w/nul */ /* ;an000; */ + /* ;an000; */ + if (OutRegs.h.ah != EMSCODE_83) /* ;an000; */ + { /* ;an000; */ + InRegs.x.ax = EMSGetHandlePages; /* get pages assoc w/this handle */ /* ;an000; */ + InRegs.x.dx = HandleIndex; /* ;an000; */ + int86x(EMS, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + HandleMem = OutRegs.x.bx; /* ;an000; */ + HandleMem *= (long) (16l*1024l); /* ;an000; */ + /* ;an000; */ + if (!TitlesPrinted) /* ;an000; */ + { /* ;an000; */ + Sub0_Message(Title3Msg,STDOUT,Utility_Msg_Class); /* ;an000; */ + Sub0_Message(Title4Msg,STDOUT,Utility_Msg_Class); /* ;an000; */ + TitlesPrinted = TRUE; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (HandleName[0] == NUL) strcpy(HandleName," "); /* ;an000; */ + EMSPrint(HandleMsg, /* ;an000; */ + STDOUT, /* ;an000; */ + Utility_Msg_Class, /* ;an000; */ + &HandleIndex, /* ;an000; */ + HandleName, /* ;an000; */ + &HandleMem); /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + } /* end for (HandleIndex = 0; HandleIndex < EMSMaxHandles;HandleIndex++) */ /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end of DisplayEMSDetail */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayExtendedSummary() /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + unsigned long int EXTMemoryTot; /* ;an000; */ + /* ;an000; */ + InRegs.h.ah = (unsigned char) 0x52; /* Get SysVar Pointer ;an001; dms;*/ + intdosx(&InRegs,&OutRegs,&SegRegs); /* Invoke interrupt ;an001; dms;*/ + /* ;an000; */ + FP_SEG(SysVarsPtr) = SegRegs.es; /* put pointer in var ;an001; dms;*/ + FP_OFF(SysVarsPtr) = OutRegs.x.bx; /* ;an001; dms;*/ + if ((SysVarsPtr) -> ExtendedMemory != 0) /* extended memory? ;an001; dms;*/ + { /* yes ;an001; dms;*/ + EXTMemoryTot = (long) (SysVarsPtr) -> ExtendedMemory; /* get total EM size ;an001; dms;*/ + EXTMemoryTot *= (long) 1024l; /* at boot time ;an001; dms;*/ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* print blank line ;an001; dms;*/ + Sub1_Message(EXTMemoryMsg,STDOUT,Utility_Msg_Class,&EXTMemoryTot); /* print total EM mem ;an001; dms;*/ + /* ;an000; */ + OutRegs.x.cflag = 0; /* clear carry flag ;an001; dms;*/ + InRegs.x.ax = GetExtended; /* get extended mem ;an001; dms;*/ + /* available */ + int86(CASSETTE, &InRegs, &OutRegs); /* INT 15h call ;an001; dms;*/ + + EXTMemoryTot = (long) OutRegs.x.ax; /* returns 1K mem blocks;an001; dms;*/ + EXTMemoryTot *= (long) 1024l; /* convert to bytes ;an001; dms;*/ + + Sub1_Message(EXTMemAvlMsg,STDOUT,Utility_Msg_Class,&EXTMemoryTot); /* display available ;an001; dms;*/ + } + + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end of DisplayExtendedSummary */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void DisplayEMSSummary() /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + unsigned long int EMSFreeMemoryTot; /* ;an000; */ + unsigned long int EMSAvailMemoryTot; /* ;an000; */ + /* ;an000; */ + Sub0_Message(NewLineMsg,STDOUT,Utility_Msg_Class); /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = EMSGetFreePgs; /* get total number unallocated pages */ /* ;an000; */ + int86x(EMS, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + /* ;an000; */ + EMSFreeMemoryTot = OutRegs.x.bx; /* total unallocated pages in BX */ /* ;an000; */ + EMSFreeMemoryTot *= (long) (16l*1024l); /* ;an000; */ + /* ;an000; */ + EMSAvailMemoryTot = OutRegs.x.dx; /* total pages */ /* ;an000; */ + EMSAvailMemoryTot *= (long) (16l*1024l); /* ;an000; */ + /* ;an000; */ + Sub1_Message(EMSTotalMemoryMsg,STDOUT,Utility_Msg_Class,&EMSAvailMemoryTot); /* ;an000; */ + Sub1_Message(EMSFreeMemoryMsg,STDOUT,Utility_Msg_Class,&EMSFreeMemoryTot); /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end of DisplayEMSSummary */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +char EMSInstalled() /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + unsigned int EMSStatus; /* ;an000; */ + unsigned int EMSVersion; /* ;an000; */ + char ReturnFlag; /* ;an000; */ + /* ;an000; */ + if (EMSInstalledFlag == 2) /* ;an000; */ + { /* ;an000; */ + EMSInstalledFlag = FALSE; /* ;an000; */ + InRegs.h.ah = GET_VECT; /* get int 67 vector */ /* ;an000; */ + InRegs.h.al = EMS; /* ;an000; */ + intdosx(&InRegs,&OutRegs,&SegRegs); /* ;an000; */ + /* ;an000; */ + /* only want to try this if vector is non-zero */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if ((SegRegs.es != 0) && (OutRegs.x.bx != 0)) /* ;an000; */ + { /* ;an000; */ + InRegs.x.ax = EMSGetStat; /* get EMS status */ /* ;an000; */ + int86x(EMS, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + EMSStatus = OutRegs.h.ah; /* EMS status returned in AH */ /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = EMSGetVer; /* get EMS version */ /* ;an000; */ + int86x(EMS, &InRegs, &OutRegs, &SegRegs); /* ;an000; */ + EMSVersion = OutRegs.h.al; /* EMS version returned in AL */ /* ;an000; */ + /* ;an000; */ + if ((EMSStatus == 0) && (EMSVersion >= DOSEMSVER)) /* ;an000; */ + EMSInstalledFlag = TRUE; /* ;an000; */ + else /* ;an000; */ + EMSInstalledFlag = FALSE; /* ;an000; */ + /* ;an000; */ + } /* end ((SegRegs.es != 0) && (OutRegs.x.bx != 0)) */ /* ;an000; */ + /* ;an000; */ + } /* end if (EMSInstalledFlag == 2) */ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + return(EMSInstalledFlag); /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +char *OwnerOf(ArenaPtr) /* ;an000; */ +struct ARENA far *ArenaPtr; /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + char far *StringPtr; /* ;an000; */ + unsigned far *WordPtr; /* ;an000; */ + char *o; /* ;an000; */ + unsigned far *EnvironmentSegmentPtr; /* ;an000; */ + unsigned PspSegment; /* ;an000; */ + int i; /* ;an000; */ + /* ;an000; */ + o = &OwnerName[0]; /* ;an000; */ + *o = NUL; /* ;an000; */ + sprintf(o,UnOwned); /* ;an000; */ + /* ;an000; */ + PspSegment = ArenaPtr -> Owner; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if (PspSegment == 0) sprintf(o,Ibmdos); /* ;an000; */ + else if (PspSegment == 8) sprintf(o,Ibmbio); /* ;an000; */ + else { /* ;an000; */ + FP_SEG(ArenaPtr) = PspSegment-1; /* -1 'cause Arena is 16 bytes before PSP */ /* ;an000; */ + StringPtr = (char far *) &(ArenaPtr -> OwnerName[0]); /* ;an000; */ + for (i = 0; i < 8; i++) *o++ = *StringPtr++; /* ;an000; */ + *o = (char) '\0'; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + if (UseArgvZero) GetFromArgvZero(PspSegment,EnvironmentSegmentPtr); /* ;an000; */ + /* ;an000; */ + return(&OwnerName[0]); /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +void GetFromArgvZero(PspSegment,EnvironmentSegmentPtr) /* ;an000; */ +unsigned PspSegment; /* ;an000; */ +unsigned far *EnvironmentSegmentPtr; /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + char far *StringPtr; /* ;an000; */ + char *OutputPtr; /* ;an000; */ + unsigned far *WordPtr; /* ;an000; */ + /* ;an000; */ + OutputPtr = &OwnerName[0]; /* ;an000; */ + /* ;an000; */ + if (UseArgvZero) /* ;an000; */ + { /* ;an000; */ + if (PspSegment < FP_SEG(ArenaHeadPtr)) /* ;an000; */ + { /* ;an000; */ + if (*OutputPtr == NUL) sprintf(OutputPtr,Ibmdos); /* ;an000; */ + } /* ;an000; */ + else { /* ;an000; */ + FP_SEG(EnvironmentSegmentPtr) = PspSegment; /* ;an000; */ + FP_OFF(EnvironmentSegmentPtr) = 44; /* ;an000; */ + /* ;an000; */ +/* FP_SEG(StringPtr) = *EnvironmentSegmentPtr; */ /* ;an000; */ + FP_SEG(StringPtr) = FP_SEG(EnvironmentSegmentPtr); /* ;an000; */ + FP_OFF(StringPtr) = 0; /* ;an000; */ + /* ;an000; */ + while ( (*StringPtr != NUL) || (*(StringPtr+1) != NUL) ) StringPtr++; /* ;an000; */ + /* ;an000; */ + StringPtr += 2; /* ;an000; */ + WordPtr = (unsigned far *) StringPtr; /* ;an000; */ + /* ;an000; */ + if (*WordPtr == 1) /* ;an000; */ + { /* ;an000; */ + StringPtr += 2; /* ;an000; */ + while (*StringPtr != NUL) /* ;an000; */ + *OutputPtr++ = *StringPtr++; /* ;an000; */ + *OutputPtr++ = NUL; /* ;an000; */ + /* ;an000; */ + while ( OutputPtr > &OwnerName[0] ) /* ;an000; */ + { if (*OutputPtr == (char) '.') *OutputPtr = NUL; /* ;an000; */ + if ( (*OutputPtr == (char) '\\') || (*OutputPtr == (char) ':') ) /* ;an000; */ + { OutputPtr++; /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + OutputPtr--; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + strcpy(&OwnerName[0],OutputPtr); /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + +char *TypeOf(Header) /* ;an000; */ +struct ARENA far *Header; /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + char *t; /* ;an000; */ + unsigned PspSegment; /* ;an000; */ + unsigned far *EnvironmentSegmentPtr; /* ;an000; */ + unsigned int Message_Number; + char far *Message_Buf; + unsigned int i; + /* ;an000; */ + t = &TypeText[0]; /* ;an000; */ + *t = NUL; /* ;an000; */ + /* ;an000; */ + Message_Number = 0xff; /* ;an000; initialize number value */ + if (Header -> Owner == 8) Message_Number = StackMsg; /* ;an000; */ + if (Header -> Owner == 0) Message_Number = FreeMsg; /* ;an000; */ + /* ;an000; */ + PspSegment = Header -> Owner; /* ;an000; */ + if (PspSegment < FP_SEG(ArenaHeadPtr)) /* ;an000; */ + { /* ;an000; */ + if (Message_Number == 0xff) Message_Number = BlankMsg; + } /* ;an000; */ + else { /* ;an000; */ + FP_SEG(EnvironmentSegmentPtr) = PspSegment; /* ;an000; */ + FP_OFF(EnvironmentSegmentPtr) = 44; /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + if (PspSegment == FP_SEG(Header)+1) + Message_Number = ProgramMsg; + else if ( *EnvironmentSegmentPtr == FP_SEG(Header)+1 ) + Message_Number = EnvironMsg; + else + Message_Number = DataMsg; + + } + + InRegs.x.ax = Message_Number; /* ;an000; */ + InRegs.h.dh = Utility_Msg_Class; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + + FP_OFF(Message_Buf) = OutRegs.x.si; /* ;an000; */ + FP_SEG(Message_Buf) = SegRegs.ds; /* ;an000; */ + + i = 0; + while ( *Message_Buf != (char) '\x0' ) + TypeText[i++] = *Message_Buf++; + TypeText[i++] = '\x0'; + + /* ;an000; */ + return(t); /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ +unsigned long AddressOf(Pointer) /* ;an000; */ +char far *Pointer; /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + unsigned long SegmentAddress,OffsetAddress; /* ;an000; */ + /* ;an000; */ + SegmentAddress = (unsigned long) (FP_SEG(Pointer)) * 16l; /* ;an000; */ + OffsetAddress = (unsigned long) (FP_OFF(Pointer)); /* ;an000; */ + /* ;an000; */ + return( SegmentAddress + OffsetAddress); /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ +/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB0_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that do not require a */ /* ;an000; */ +/* a sublist. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub0_Message(Msg_Num,Handle,Message_Type) /* print messages with no subs */ /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ + { /* ;an000; */ + InRegs.x.ax = Msg_Num; /* put message number in AX */ /* ;an000; */ + InRegs.x.bx = Handle; /* put handle in BX */ /* ;an000; */ + InRegs.x.cx = No_Replace; /* no replaceable subparms */ /* ;an000; */ + InRegs.h.dl = No_Input; /* no keyboard input */ /* ;an000; */ + InRegs.h.dh = Message_Type; /* type of message to display */ /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* display the message */ /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB1_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that require 1 replaceable */ /* ;an000; */ +/* parm. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* Replace_Parm - pointer to parm to replace */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub1_Message(Msg_Num,Handle,Message_Type,Replace_Parm) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ +unsigned long int *Replace_Parm; /* pointer to message to print */ /* ;an000; */ + /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Parm; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Unsgn_Bin_DWord+Right_Align; /* ;an000; */ + sublist[1].max_width = 10; /* ;an000; */ + sublist[1].min_width = 10; /* ;an000; */ + sublist[1].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt1; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB2_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that require 2 replaceable */ /* ;an000; */ +/* parms. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* Replace_Parm1 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm2 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm3 - pointer to parm to replace */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub2_Message(Msg_Num,Handle,Message_Type, /* ;an000; */ + Replace_Parm1, /* ;an000; */ + Replace_Message1) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ +int Replace_Message1; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ +char *Replace_Parm1; /* pointer to message to print */ /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + switch(Msg_Num) /* ;an000; */ + { /* ;an000; */ + case DeviceLineMsg: /* ;an000; */ + /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Parm1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[1].max_width = 0x0008; /* ;an000; */ + sublist[1].min_width = 0x0008; /* ;an000; */ + sublist[1].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Replace_Message1; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_OFF(sublist[2].value) = OutRegs.x.si; /* ;an000; */ + FP_SEG(sublist[2].value) = SegRegs.ds; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Right_Align; /* ;an000; */ + sublist[2].max_width = 00; /* ;an000; */ + sublist[2].min_width = 10; /* ;an000; */ + sublist[2].pad_char = Blank; /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt2; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB3_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that require 3 replaceable */ /* ;an000; */ +/* parms. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* Replace_Parm1 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm2 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm3 - pointer to parm to replace */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub3_Message(Msg_Num,Handle,Message_Type, /* ;an000; */ + Replace_Parm1, /* ;an000; */ + Replace_Parm2, /* ;an000; */ + Replace_Message1) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ +char *Replace_Parm1; /* ;an000; */ +unsigned long int *Replace_Parm2; /* ;an000; */ +int Replace_Message1; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + switch(Msg_Num) /* ;an000; */ + { /* ;an000; */ + case DriverLineMsg: /* ;an000; */ + /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Parm1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[1].max_width = 0x0008; /* ;an000; */ + sublist[1].min_width = 0x0008; /* ;an000; */ + sublist[1].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[2].value = (unsigned far *)Replace_Parm2; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[2].max_width = 0x0006; /* ;an000; */ + sublist[2].min_width = 0x0006; /* ;an000; */ + sublist[2].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Replace_Message1; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_OFF(sublist[3].value) = OutRegs.x.si; /* ;an000; */ + FP_SEG(sublist[3].value) = SegRegs.ds; /* ;an000; */ + sublist[3].size = Sublist_Length; /* ;an000; */ + sublist[3].reserved = Reserved; /* ;an000; */ + sublist[3].id = 3; /* ;an000; */ + sublist[3].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[3].max_width = 00; /* ;an000; */ + sublist[3].min_width = 10; /* ;an000; */ + sublist[3].pad_char = Blank; /* ;an000; */ + break; /* ;an000; */ + /* ;an000; */ + case HandleMsg: /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Parm1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Unsgn_Bin_Byte+Right_Align; /* ;an000; */ + sublist[1].max_width = 0x0009; /* ;an000; */ + sublist[1].min_width = 0x0009; /* ;an000; */ + sublist[1].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[2].value = (unsigned far *)Replace_Parm2; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[2].max_width = 0x0008; /* ;an000; */ + sublist[2].min_width = 0x0008; /* ;an000; */ + sublist[2].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Replace_Message1; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_OFF(sublist[3].value) = OutRegs.x.si; /* ;an000; */ + FP_SEG(sublist[3].value) = SegRegs.ds; /* ;an000; */ + sublist[3].size = Sublist_Length; /* ;an000; */ + sublist[3].reserved = Reserved; /* ;an000; */ + sublist[3].id = 3; /* ;an000; */ + sublist[3].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[3].max_width = 00; /* ;an000; */ + sublist[3].min_width = 10; /* ;an000; */ + sublist[3].pad_char = Blank; /* ;an000; */ + break; /* ;an000; */ + /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt3; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB4_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that require 4 replaceable */ /* ;an000; */ +/* parms. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* Replace_Parm1 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm2 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm3 - pointer to parm to replace */ /* ;an000; */ +/* Dynamic_Parm - parm number to use as replaceable */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub4_Message(Msg_Num,Handle,Message_Type, /* ;an000; */ + Replace_Value1, /* ;an000; */ + Replace_Message1, /* ;an000; */ + Replace_Value2, /* ;an000; */ + Replace_Message2) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ +unsigned long int *Replace_Value1; /* ;an000; */ +int Replace_Message1; /* ;an000; */ +unsigned long int *Replace_Value2; /* ;an000; */ +int Replace_Message2; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + switch(Msg_Num) /* ;an000; */ + { /* ;an000; */ + case MainLineMsg: /* ;an000; */ + /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Value1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[1].max_width = 06; /* ;an000; */ + sublist[1].min_width = 06; /* ;an000; */ + sublist[1].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Replace_Message1; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_OFF(sublist[2].value) = OutRegs.x.si; /* ;an000; */ + FP_SEG(sublist[2].value) = SegRegs.ds; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[2].max_width = 0x0008; /* ;an000; */ + sublist[2].min_width = 0x0008; /* ;an000; */ + sublist[2].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[3].value = (unsigned far *)Replace_Value2; /* ;an000; */ + sublist[3].size = Sublist_Length; /* ;an000; */ + sublist[3].reserved = Reserved; /* ;an000; */ + sublist[3].id = 3; /* ;an000; */ + sublist[3].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[3].max_width = 06; /* ;an000; */ + sublist[3].min_width = 06; /* ;an000; */ + sublist[3].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Replace_Message2; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + sysgetmsg(&InRegs,&SegRegs,&OutRegs); /* ;an000; */ + /* ;an000; */ + FP_OFF(sublist[4].value) = OutRegs.x.si; /* ;an000; */ + FP_SEG(sublist[4].value) = SegRegs.ds; /* ;an000; */ + sublist[4].size = Sublist_Length; /* ;an000; */ + sublist[4].reserved = Reserved; /* ;an000; */ + sublist[4].id = 4; /* ;an000; */ + sublist[4].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[4].max_width = 0; /* ;an000; */ + sublist[4].min_width = 10; /* ;an000; */ + sublist[4].pad_char = Blank; /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt4; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* SUB4a_MESSAGE - This routine will print only those */ /* ;an000; */ +/* messages that require 4 replaceable */ /* ;an000; */ +/* parms. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Inputs : Msg_Num - number of applicable message */ /* ;an000; */ +/* Handle - display type */ /* ;an000; */ +/* Message_Type - type of message to display */ /* ;an000; */ +/* Replace_Parm1 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm2 - pointer to parm to replace */ /* ;an000; */ +/* Replace_Parm3 - pointer to parm to replace */ /* ;an000; */ +/* Dynamic_Parm - parm number to use as replaceable */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void Sub4a_Message(Msg_Num,Handle,Message_Type, /* ;an000; */ + Replace_Value1, /* ;an000; */ + Replace_Message1, /* ;an000; */ + Replace_Value2, /* ;an000; */ + Replace_Message2) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ +unsigned long int *Replace_Value1; /* ;an000; */ +char *Replace_Message1; /* ;an000; */ +unsigned long int *Replace_Value2; /* ;an000; */ +char *Replace_Message2; /* ;an000; */ + /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + switch(Msg_Num) /* ;an000; */ + { /* ;an000; */ + case MainLineMsg: /* ;an000; */ + /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Value1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[1].max_width = 06; /* ;an000; */ + sublist[1].min_width = 06; /* ;an000; */ + sublist[1].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + sublist[2].value = (unsigned far *)Replace_Message1; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[2].max_width = 0x0008; /* ;an000; */ + sublist[2].min_width = 0x0008; /* ;an000; */ + sublist[2].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[3].value = (unsigned far *)Replace_Value2; /* ;an000; */ + sublist[3].size = Sublist_Length; /* ;an000; */ + sublist[3].reserved = Reserved; /* ;an000; */ + sublist[3].id = 3; /* ;an000; */ + sublist[3].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[3].max_width = 06; /* ;an000; */ + sublist[3].min_width = 06; /* ;an000; */ + sublist[3].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + sublist[4].value = (unsigned far *)Replace_Message2; /* ;an000; */ + sublist[4].size = Sublist_Length; /* ;an000; */ + sublist[4].reserved = Reserved; /* ;an000; */ + sublist[4].id = 4; /* ;an000; */ + sublist[4].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[4].max_width = 0; /* ;an000; */ + sublist[4].min_width = 10; /* ;an000; */ + sublist[4].pad_char = Blank; /* ;an000; */ + break; /* ;an000; */ + } /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt4; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ + /* ;an000; */ +/************************************************************************/ /* ;an000; */ +/* EMSPrint - This routine will print the message */ /* ;an000; */ +/* necessary for EMS reporting. */ /* ;an000; */ +/* */ /* ;an000; */ +/* Outputs : message */ /* ;an000; */ +/* */ /* ;an000; */ +/************************************************************************/ /* ;an000; */ + /* ;an000; */ +void EMSPrint(Msg_Num,Handle,Message_Type, /* ;an000; */ + Replace_Value1, /* ;an000; */ + Replace_Message1, /* ;an000; */ + Replace_Value2) /* ;an000; */ + /* ;an000; */ +int Msg_Num; /* ;an000; */ +int Handle; /* ;an000; */ +unsigned char Message_Type; /* ;an000; */ +int *Replace_Value1; /* ;an000; */ +char *Replace_Message1; /* ;an000; */ +unsigned long int *Replace_Value2; /* ;an000; */ + /* extended, parse, or utility */ /* ;an000; */ +{ /* ;an000; */ + /* ;an000; */ + { /* ;an000; */ + sublist[1].value = (unsigned far *)Replace_Value1; /* ;an000; */ + sublist[1].size = Sublist_Length; /* ;an000; */ + sublist[1].reserved = Reserved; /* ;an000; */ + sublist[1].id = 1; /* ;an000; */ + sublist[1].flags = Unsgn_Bin_Word+Right_Align; /* ;an000; */ + sublist[1].max_width = 03; /* ;an000; */ + sublist[1].min_width = 03; /* ;an000; */ + sublist[1].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[2].value = (unsigned far *)Replace_Message1; /* ;an000; */ + sublist[2].size = Sublist_Length; /* ;an000; */ + sublist[2].reserved = Reserved; /* ;an000; */ + sublist[2].id = 2; /* ;an000; */ + sublist[2].flags = Char_Field_ASCIIZ+Left_Align; /* ;an000; */ + sublist[2].max_width = 0x0008; /* ;an000; */ + sublist[2].min_width = 0x0008; /* ;an000; */ + sublist[2].pad_char = Blank; /* ;an000; */ + /* ;an000; */ + sublist[3].value = (unsigned far *)Replace_Value2; /* ;an000; */ + sublist[3].size = Sublist_Length; /* ;an000; */ + sublist[3].reserved = Reserved; /* ;an000; */ + sublist[3].id = 3; /* ;an000; */ + sublist[3].flags = Bin_Hex_DWord+Right_Align; /* ;an000; */ + sublist[3].max_width = 06; /* ;an000; */ + sublist[3].min_width = 06; /* ;an000; */ + sublist[3].pad_char = 0x0030; /* ;an000; */ + /* ;an000; */ + InRegs.x.ax = Msg_Num; /* ;an000; */ + InRegs.x.bx = Handle; /* ;an000; */ + InRegs.x.cx = SubCnt3; /* ;an000; */ + InRegs.h.dl = No_Input; /* ;an000; */ + InRegs.h.dh = Message_Type; /* ;an000; */ + InRegs.x.si = (unsigned int)&sublist[1]; /* ;an000; */ + sysdispmsg(&InRegs,&OutRegs); /* ;an000; */ + } /* ;an000; */ + return; /* ;an000; */ +} /* ;an000; */ + /* ;an000; */ +/*----------------------------------------------------------------------+ +| | +| SUBROUTINE NAME: PARSE_INIT | +| | +| SUBROUTINE FUNCTION: | +| | +| This routine is called by the FILESYS MAIN routine to initialize| +| the parser data structures. | +| | +| INPUT: | +| none | +| | +| OUTPUT: | +| properly initialized parser control blocks | +| | ++----------------------------------------------------------------------*/ +void parse_init() /* ;an000; */ + { /* ;an000; */ + p_p.p_parmsx_address = &p_px; /* address of extended parm list */ /* ;an000; */ + p_p.p_num_extra = 0; /* ;an000; */ + /* ;an000; */ + p_px.p_minp = 0; /* ;an000; */ + p_px.p_maxp = 0; /* ;an000; */ + p_px.p_maxswitch = 2; /* ;an000; */ + p_px.p_control[0] = &p_con1; /* ;an000; */ + p_px.p_control[1] = &p_con2; /* ;an000; */ + p_px.p_keyword = 0; /* ;an000; */ + /* ;an000; */ + p_con1.p_match_flag = p_none; /* ;an000; */ + p_con1.p_function_flag = p_cap_file; /* ;an000; */ + p_con1.p_result_buf = (unsigned int)&p_result1; /* ;an000; */ + p_con1.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con1.p_nid = 1; /* ;an000; */ + strcpy(p_con1.p_keyorsw,"/DEBUG"+NUL); /* ;an000; */ + /* ;an000; */ + p_con2.p_match_flag = p_none; /* ;an000; */ + p_con2.p_function_flag = p_cap_file; /* ;an000; */ + p_con2.p_result_buf = (unsigned int)&p_result2; /* ;an000; */ + p_con2.p_value_list = (unsigned int)&p_noval; /* ;an000; */ + p_con2.p_nid = 1; /* ;an000; */ + strcpy(p_con2.p_keyorsw,"/PROGRAM"+NUL); /* ;an000; */ + /* ;an000; */ + p_noval.p_val_num = 0; /* ;an000; */ + /* ;an000; */ + p_result1.P_Type = 0; /* ;an000; */ + p_result1.P_Item_Tag = 0; /* ;an000; */ + p_result1.P_SYNONYM_Ptr = 0; /* ;an000; */ + p_result1.p_result_buff = 0; /* ;an000; */ + /* ;an000; */ + p_result2.P_Type = 0; /* ;an000; */ + p_result2.P_Item_Tag = 0; /* ;an000; */ + p_result2.P_SYNONYM_Ptr = 0; /* ;an000; */ + p_result2.p_result_buff = 0; /* ;an000; */ + /* ;an000; */ + return; /* ;an000; */ + /* ;an000; */ + } /* end parse_init */ /* ;an000; */ + + +/************************************************************************/ /* ;an000; */ +/* Parse_Message - This routine will print only those */ +/* messages that require 1 replaceable */ +/* parm. */ +/* */ +/* Inputs : Msg_Num - number of applicable message */ +/* Handle - display type */ +/* Message_Type - type of message to display */ +/* Replace_Parm - pointer to parm to replace */ +/* */ +/* Outputs : message */ +/* */ +/************************************************************************/ + +void Parse_Message(Msg_Num,Handle,Message_Type) /*;an003; dms; */ + /*;an003; dms; */ +int Msg_Num; /*;an003; dms; */ +int Handle; /*;an003; dms; */ +unsigned char Message_Type; /*;an003; dms; */ + /*;an003; dms; */ +{ /*;an003; dms; */ +char far *Cmd_Ptr; /*;an003; dms; */ + /*;an003; dms; */ + /*;an003; dms; */ + { /*;an003; dms; */ + segread(&SegRegs); /*;an003; dms; */ + FP_SEG(Cmd_Ptr) = SegRegs.ds; /*;an003; dms; */ + FP_OFF(Cmd_Ptr) = OutRegs.x.si; /*;an003; dms; */ + *Cmd_Ptr = '\0'; /*;an003; dms; */ + /*;an003; dms; */ + FP_SEG(sublist[1].value) = SegRegs.ds; /*;an003; dms; */ + FP_OFF(sublist[1].value) = Parse_Ptr; /*;an003; dms; */ + sublist[1].size = Sublist_Length; /*;an003; dms; */ + sublist[1].reserved = Reserved; /*;an003; dms; */ + sublist[1].id = 0; /*;an003; dms; */ + sublist[1].flags = Char_Field_ASCIIZ+Left_Align; /*;an003; dms; */ + sublist[1].max_width = 40; /*;an003; dms; */ + sublist[1].min_width = 01; /*;an003; dms; */ + sublist[1].pad_char = Blank; /*;an003; dms; */ + /*;an003; dms; */ + InRegs.x.ax = Msg_Num; /*;an003; dms; */ + InRegs.x.bx = Handle; /*;an003; dms; */ + InRegs.x.cx = SubCnt1; /*;an003; dms; */ + InRegs.h.dl = No_Input; /*;an003; dms; */ + InRegs.h.dh = Message_Type; /*;an003; dms; */ + InRegs.x.si = (unsigned int)&sublist[1]; /*;an003; dms; */ + sysdispmsg(&InRegs,&OutRegs); /*;an003; dms; */ + } /*;an003; dms; */ + return; /*;an003; dms; */ +} /*;an003; dms; */ + + diff --git a/v4.0/src/CMD/MEM/MEM.SKL b/v4.0/src/CMD/MEM/MEM.SKL new file mode 100644 index 0000000..af49786 --- /dev/null +++ b/v4.0/src/CMD/MEM/MEM.SKL @@ -0,0 +1,53 @@ + +:util MEM + +:class 1 + +:class A +:use COMMON1 ;Incorrect DOS version +:def 10 CR,LF +:def 11 " Address Name Size Type ",CR,LF +:def 12 " ÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄ ÄÄÄÄÄÄ",CR,LF +:def 13 " Handle EMS Name Size ",CR,LF +:def 14 " ÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄ ",CR,LF +:def 15 " %1 %2 %3 %4",CR,LF +:def 16 " %1 %2 %3 ",CR,LF +:def 17 " %1 %2 ",CR,LF ;fix in usa +:def 18 "%1 bytes total memory",CR,LF +:def 19 "%1 bytes available",CR,LF +:def 20 "%1 largest executable program size",CR,LF +:def 21 "%1 bytes total EMS memory",CR,LF +:def 22 "%1 bytes free EMS memory",CR,LF +:def 23 "%1 bytes total extended memory",CR,LF +:def 24 "Interrupt Vector",0 +:def 25 "ROM Communication Area",0 +:def 26 "DOS Communication Area",0 +:def 27 "IBMBIO",0 +:def 28 "IBMDOS",0 +:def 29 "System Data",0 +:def 30 "System Program",0 +:def 31 "System Device Driver",0 +:def 32 "Installed Device Driver",0 +:def 33 "%1:",0 +:def 34 "%1: - %2:",0 +:def 35 "BUFFERS=",0 +:def 36 "FILES=",0 +:def 37 "FCBS=",0 +:def 38 "STACKS=",0 +:def 39 "DEVICE=",0 +:def 40 "IFS=",0 +:def 45 "INSTALL=",0 + +:class B +:def 41 "LASTDRIVE=",0 +:def 42 "----------",0 +:def 43 " ",0 +:def 44 " %1 %2 %3",CR,LF +:def 46 "%1 bytes available extended memory",CR,LF +:def 47 "System Stacks",0 +:def 48 "-- Free --",0 +:def 49 "Program",0 +:def 50 "Environment",0 +:def 51 "Data",0 + +:end diff --git a/v4.0/src/CMD/MEM/MSGDEF.H b/v4.0/src/CMD/MEM/MSGDEF.H new file mode 100644 index 0000000..c9703a6 --- /dev/null +++ b/v4.0/src/CMD/MEM/MSGDEF.H @@ -0,0 +1,93 @@ +/************************************************************************/ +/* MSGDEF.H - This include file defines each message type */ +/* that can occur in MEM. These defines will */ +/* be used by MEM to build the proper message. */ +/* */ +/* Date : 10/29/87 */ +/************************************************************************/ + +#define NewLineMsg 10 +#define Title1Msg 11 +#define Title2Msg 12 +#define Title3Msg 13 +#define Title4Msg 14 +#define MainLineMsg 15 +#define DriverLineMsg 16 +#define DeviceLineMsg 17 +#define TotalMemoryMsg 18 +#define AvailableMemoryMsg 19 +#define FreeMemoryMsg 20 +#define EMSTotalMemoryMsg 21 +#define EMSFreeMemoryMsg 22 +#define EXTMemoryMsg 23 +#define InterruptVectorMsg 24 +#define ROMCommunicationAreaMsg 25 +#define DOSCommunicationAreaMsg 26 +#define IbmbioMsg 27 +#define IbmdosMsg 28 +#define SystemDataMsg 29 +#define SystemProgramMsg 30 +#define SystemDeviceDriverMsg 31 +#define InstalledDeviceDriverMsg 32 +#define SingleDriveMsg 33 +#define MultipleDrivesMsg 34 +#define ConfigBuffersMsg 35 +#define ConfigFilesMsg 36 +#define ConfigFcbsMsg 37 +#define ConfigStacksMsg 38 +#define ConfigDeviceMsg 39 +#define ConfigIFSMsg 40 +#define ConfigLastDriveMsg 41 +#define ConfigInstallMsg 45 /* gga */ +#define UnownedMsg 42 +#define BlankMsg 43 +#define HandleMsg 44 +#define EXTMemAvlMsg 46 /* ;an001; dms;*/ +#define StackMsg 47 +#define FreeMsg 48 +#define ProgramMsg 49 +#define EnvironMsg 50 +#define DataMsg 51 + + +#define ParseError1Msg 01 +#define ParseError10Msg 10 + +/************************************************************************/ +/* Message Retriever Standard Equates */ +/************************************************************************/ + +#define Ext_Err_Class 0x0001 +#define Parse_Err_Class 0x0002 +#define Utility_Msg_Class 0x00ff +#define No_Handle 0xffff +#define No_Replace 0x0000 +#define Sublist_Length 0x000b +#define Reserved 0x0000 +#define Left_Align 0x0000 +#define Right_Align 0x0080 +#define Char_Field_Char 0x0000 +#define Char_Field_ASCIIZ 0x0010 +#define Unsgn_Bin_Byte 0x0011 +#define Unsgn_Bin_Word 0x0021 +#define Unsgn_Bin_DWord 0x0031 +#define Sgn_Bin_Byte 0x0012 +#define Sgn_Bin_Word 0x0022 +#define Sgn_Bin_DWord 0x0032 +#define Bin_Hex_Byte 0x0013 +#define Bin_Hex_Word 0x0023 +#define Bin_Hex_DWord 0x0033 +#define No_Input 0x0000 +#define STDIN 0x0000 +#define STDOUT 0x0001 +#define STDERR 0x0002 +#define Blank 0x0020 + +#define SubCnt1 0x0001 +#define SubCnt2 0x0002 +#define SubCnt3 0x0003 +#define SubCnt4 0x0004 +#define SubCnt5 0x0005 + +#define CarryFlag 0x0001 + diff --git a/v4.0/src/CMD/MEM/PARSE.H b/v4.0/src/CMD/MEM/PARSE.H new file mode 100644 index 0000000..ec4f4eb --- /dev/null +++ b/v4.0/src/CMD/MEM/PARSE.H @@ -0,0 +1,144 @@ +/*  */ +/*----------------------------------------------------------------------+ +| | +| This file contains the structures and defines that are needed to use | +| the parser from a C program. | +| | +| | +| Date: 5-21-87 | +| | ++----------------------------------------------------------------------*/ + + +#define p_len_parms 4 /* length of p_parms */ +#define p_i_use_default 0 /* no extra stuff specified */ +#define p_i_have_delim 1 /* extra delimiter specified */ +#define p_i_have_eol 2 /* extra EOL specified */ + +struct p_parms + { + struct p_parmsx *p_parmsx_address; /* address of p_parmsx */ + unsigned char p_num_extra; /* number of extra stuff */ + unsigned char p_len_extra_delim; /* length of extra delimiter */ + char p_extra_delim[30]; /* extra delimiters */ + }; + +struct p_parmsx + { + unsigned char p_minp; /* Minimum positional number */ + unsigned char p_maxp; /* Maximum positional number */ + unsigned char p_maxswitch; /* Maximum switches */ + struct p_control_blk *p_control[2]; /* Address of the 1st CONTROL block */ + unsigned char p_keyword; /* Keyword count */ + }; + + +struct p_control_blk + { + unsigned int p_match_flag; /* Controls type matched */ + unsigned int p_function_flag; /* Function should be taken */ + unsigned int p_result_buf; /* Result buffer address */ + unsigned int p_value_list; /* Value list address */ + unsigned char p_nid; /* # of keyword/SW synonyms */ + char p_keyorsw[64]; /* keyword or sw */ + }; + +/* Match_Flags */ + +#define p_num_val 0x8000 /* Numeric Value */ +#define p_snum_val 0x4000 /* Signed numeric value */ +#define p_simple_s 0x2000 /* Simple string */ +#define p_date_s 0x1000 /* Date string */ +#define p_time_s 0x0800 /* Time string */ +#define p_cmpx_s 0x0400 /* Complex string */ +#define p_file_spc 0x0200 /* File Spec */ +#define p_drv_only 0x0100 /* Drive Only */ +#define p_qu_string 0x0080 /* Quoted string */ +#define p_ig_colon 0x0010 /* Ignore colon at end in match */ +#define p_repeat 0x0002 /* Repeat allowed */ +#define p_optional 0x0001 /* Optional */ +#define p_none 0x0000 + +/*----------------------------------------------------------------------+ +| | +| Function flags | +| | ++----------------------------------------------------------------------*/ + +#define p_cap_file 0x0001 /* CAP result by file table */ +#define p_cap_char 0x0002 /* CAP result by character table */ +#define p_rm_colon 0x0010 /* Remove ":" at the end */ + + + +#define p_nval_none 0 /* no value list ID */ +#define p_nval_range 1 /* range list ID */ +#define p_nval_value 2 /* value list ID */ +#define p_nval_string 3 /* string list ID */ +#define p_len_range 9 /* Length of a range choice(two DD plus one DB) */ +#define p_len_value 5 /* Length of a value choice(one DD plus one DB) */ +#define p_len_string 3 /* Length of a string choice(one DW plus one DB) */ + +/*----------------------------------------------------------------------+ +| | +| Value block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_value_blk + { + unsigned char p_val_num; + }; + + +/*----------------------------------------------------------------------+ +| | +| Result block structure | +| | ++----------------------------------------------------------------------*/ + +struct p_result_blk + { + unsigned char P_Type; /* Type returned */ + unsigned char P_Item_Tag; /* Matched item tag */ + unsigned int P_SYNONYM_Ptr; /* pointer to Synonym list returned */ + unsigned long int p_result_buff; /* result value */ + }; + +/*----------------------------------------------------------------------+ +| | +| type | +| | ++----------------------------------------------------------------------*/ + +#define p_eol 0 /* End of line */ +#define p_number 1 /* Number */ +#define p_list_idx 2 /* List Index */ +#define p_string 3 /* String */ +#define p_complex 4 /* Complex */ +#define p_file_spec 5 /* File Spec */ +#define p_drive 6 /* Drive */ +#define p_date_f 7 /* Date */ +#define p_time_f 8 /* Time */ +#define p_quoted_string 9 /* Quoted String */ + +#define p_no_tag 0x0FF /* No ITEM_TAG found */ + +/*----------------------------------------------------------------------+ +| | +| following return code will be returned in the AX register. | +| | ++----------------------------------------------------------------------*/ + +#define p_no_error 0 /* No error */ +#define p_too_many 1 /* Too many operands */ +#define p_op_missing 2 /* Required operand missing */ +#define p_not_in_sw 3 /* Not in switch list provided */ +#define p_not_in_key 4 /* Not in keyword list provided */ +#define p_out_of_range 6 /* Out of range specified */ +#define p_not_in_val 7 /* Not in value list provided */ +#define p_not_in_str 8 /* Not in string list provided */ +#define p_syntax 9 /* Syntax error */ +#define p_rc_eol 0x0ffff /* End of command line */ + + diff --git a/v4.0/src/CMD/MEM/_MSGRET.ASM b/v4.0/src/CMD/MEM/_MSGRET.ASM new file mode 100644 index 0000000..0b982f7 --- /dev/null +++ b/v4.0/src/CMD/MEM/_MSGRET.ASM @@ -0,0 +1,263 @@ +page 60,132 +name _msgret +title C to Message Retriever +;------------------------------------------------------------------- +; +; MODULE: _msgret +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 message retriever +; +; CALLING FORMAT: +; msgret(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + + INCLUDE SYSMSG.INC ;PERMIT SYSTEM MESSAGE HANDLER DEFINITION ;AN000; + + MSG_UTILNAME ;IDENTIFY THE COMPONENT ;AN000; + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + +DGROUP GROUP CONST, _BSS, _DATA + ASSUME CS: DGROUP, DS: DGROUP, SS: DGROUP, ES: NOTHING + + public data_sysloadmsg + public data_sysdispmsg + public data_sysgetmsg + +_DATA SEGMENT + + MSG_SERVICES + MSG_SERVICES + MSG_SERVICES + MSG_SERVICES ;AN000; + + +data_sysloadmsg proc far + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + + call sysloadmsg ; call the message retriever + +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6+4] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +data_sysloadmsg endp + + +data_sysdispmsg proc far + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + + call sysdispmsg + +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6+4] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +data_sysdispmsg endp + + +data_sysgetmsg proc far + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- + + call sysgetmsg ; call the message retriever + +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6+4] ; fix di (arg 1) + + push ax ; save ax + mov [di+00],es ; load segregs.es + mov [di+06],ds ; load outregs.ds + pop ax ; restore ax + + pop di ; restore di + push di ; save it + mov di,[bp+8+4] ; fix di (arg 2) + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + lahf ; get flags into ax + mov al,ah ; move into low byte + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +data_sysgetmsg endp + +include msgdcl.inc + +_DATA ends ; end code segment + +_TEXT SEGMENT + + assume cs:_TEXT + + public _sysdispmsg + public _sysloadmsg + public _sysgetmsg + +_sysdispmsg proc near + call data_sysdispmsg + ret +_sysdispmsg endp + +_sysloadmsg proc near + call data_sysloadmsg + ret +_sysloadmsg endp + +_sysgetmsg proc near + call data_sysgetmsg + ret +_sysgetmsg endp + +_TEXT ENDS + end + diff --git a/v4.0/src/CMD/MEM/_PARSE.ASM b/v4.0/src/CMD/MEM/_PARSE.ASM new file mode 100644 index 0000000..d1424b7 --- /dev/null +++ b/v4.0/src/CMD/MEM/_PARSE.ASM @@ -0,0 +1,165 @@ +page 60,132 +name _parse +title C to PARSER interface +;------------------------------------------------------------------- +; +; MODULE: _parse +; +; PURPOSE: Supplies an interface between C programs and +; the DOS 3.3 parser +; +; CALLING FORMAT: +; parse(&inregs,&outregs); +; +; DATE: 5-21-87 +; +;------------------------------------------------------------------- + +; extrn sysparse:far + + public _parse + +;------------------------------------------------------------------- +;FarSW equ 0 ; make sysparse be a NEAR proc +;TimeSW equ 0 ; Check time format +;FileSW equ 0 ; Check file specification +;CAPSW equ 0 ; Perform CAPS if specified +;CmpxSW equ 0 ; Check complex list +;NumSW equ 1 ; Check numeric value +;KeySW equ 0 ; Support keywords +;SwSW equ 1 ; Support switches +;Val1SW equ 1 ; Support value definition 1 +;Val2SW equ 1 ; Support value definition 2 +;Val3SW equ 0 ; Support value definition 3 +;DrvSW equ 0 ; Support drive only format +;QusSW equ 0 ; Support quoted string format +;------------------------------------------------------------------- + + + + +_TEXT SEGMENT BYTE PUBLIC 'CODE' +_TEXT ENDS +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +CONST SEGMENT WORD PUBLIC 'CONST' +CONST ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS + + +DGROUP GROUP CONST, _BSS, _DATA + + +_DATA segment word public 'DATA' + + assume cs:DGROUP + assume ss:dgroup + + public SysParse + +;------------------------------------------------------------------- +.xlist +include parse.asm ; include the parser +.list +;------------------------------------------------------------------- + + public CallParser +CallParser proc far + + push ds + PUSH ES + + push cs + pop ds + assume ds:DGROUP + + push cs + pop es + assume es:DGROUP + + nop + + call SysParse + + POP ES + pop ds + + ret + +CallParser endp + + + +_DATA ends + +_TEXT segment byte public 'CODE' + + ASSUME CS:_TEXT + ASSUME DS:DGROUP + ASSUME ES:NOTHING + ASSUME SS:DGROUP + +_parse proc near + + push bp ; save user's base pointer + mov bp,sp ; set bp to current sp + push di ; save some registers + push si + +; copy C inregs into proper registers + + mov di,[bp+4] ; fix di (arg 0) + +;------------------------------------------------------------------- + + mov ax,[di+0ah] ; load di + push ax ; the di value from inregs is now on stack + + mov ax,[di+00] ; get inregs.x.ax + mov bx,[di+02] ; get inregs.x.bx + mov cx,[di+04] ; get inregs.x.cx + mov dx,[di+06] ; get inregs.x.dx + mov si,[di+08] ; get inregs.x.si + pop di ; get inregs.x.di from stack + + push bp ; save base pointer + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + call CallParser ; call the parser + +;------------------------------------------------------------------- +;------------------------------------------------------------------- + + pop bp ; restore base pointer + push di ; the di value from call is now on stack + mov di,[bp+6] ; fix di (arg 1) + + mov [di+00],ax ; load outregs.x.ax + mov [di+02],bx ; load outregs.x.bx + mov [di+04],cx ; load outregs.x.cx + mov [di+06],dx ; load outregs.x.dx + mov [di+08],si ; load outregs.x.si + + xor ax,ax ; clear ax + lahf ; get flags into ax + mov [di+0ch],ax ; load outregs.x.cflag + + pop ax ; get di from stack + mov [di+0ah],ax ; load outregs.x.di + +;------------------------------------------------------------------- + + pop si ; restore registers + pop di + mov sp,bp ; restore sp + pop bp ; restore user's bp + ret + +_parse endp + +_TEXT ends ; end code segment + end + diff --git a/v4.0/src/CMD/MODE/COMMON.STC b/v4.0/src/CMD/MODE/COMMON.STC new file mode 100644 index 0000000..1212c55 --- /dev/null +++ b/v4.0/src/CMD/MODE/COMMON.STC @@ -0,0 +1,36 @@ +;common structures + +bogus EQU 88H ;totally invalid value + +codepage_parms STRUC + cp_device DW ? + des_pack_ptr DW ? + font_filespec DW ? + request_typ DW ? +codepage_parms ENDS + + +parm_list_entry STRUC ;used by parse_parameters and invoke + +parm_type DB bogus +item_tag DB 0FFH +value1 DW bogus ;used only for filespecs and code page numbers +value2 DW bogus ;used only for filespecs and code page numbers +keyword_switch_ptr DW 0 + +parm_list_entry ENDS + + +sublist_def STRUC ;used by initialize_sublists + + db ? ;Sublist Length, fixed + db ? ;Reserved, not used yet ;AN000; +sublist_off dw ? ;offset +sublist_seg dw ? ;segment part of pointer to piece of message + db ? ;ID, special end of message format ;AN000; + db ? ;flags + db ? + db ? + db ? + +sublist_def ENDS diff --git a/v4.0/src/CMD/MODE/DISPLAY.ASM b/v4.0/src/CMD/MODE/DISPLAY.ASM new file mode 100644 index 0000000..870110f --- /dev/null +++ b/v4.0/src/CMD/MODE/DISPLAY.ASM @@ -0,0 +1,181 @@ +;m +PRINTF_CODE SEGMENT PUBLIC + +ASSUME CS:PRINTF_CODE, DS:PRINTF_CODE, ES:PRINTF_CODE, SS:PRINTF_CODE + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +PUBLIC initialize_sublists + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +;***************************************************************************** +; External Declarations +;***************************************************************************** +; + +EXTRN first_sublist:BYTE +EXTRN number_of_sublists:ABS +EXTRN SysDispMsg:Near + + + + + + +; +;*************************************************************************** +; Message Structures +;*************************************************************************** +; + + +Message_Table struc ; ;AN000; + ; +Entry1 dw 0 ; ;AN000; +Entry2 dw 0 ; ;AN000; +Entry3 dw 0 ; ;AN000; +Entry4 dw 0 ; ;AN000; +Entry5 db 0 ; ;AN000; +Entry6 db 0 ; ;AN000; +Entry7 dw 0 ; ;AN000; + ; +Message_Table ends ; ;AN000; + +include common.stc ;contains the following structure + +;sublist_def STRUC + +; db ? ;Sublist Length, fixed +; db ? ;Reserved, not used yet ;AN000; +; dw ? ;offset +;sublist_seg dw ? ;segment part of pointer to piece of message +; db ? ;ID, special end of message format ;AN000; +; db ? ;flags +; db ? +; db ? +; db ? + +;sublist_def ENDS + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;³ +;³ INITIALIZE_SUBLISTS +;³ ------------------- +;³ A .COM file cannot have references to segments in it at EXE2BIN time so +;³ the segment part of pointers to pieces of messages in sublist blocks must +;³ be done at execution time. This routine does that for all sublists. +;³ +;³ +;³ INPUT: +;³ +;³ +;³ +;³ +;³ +;³ +;³ +;³ RETURN: +;³ +;³ +;³ MESSAGES: none +;³ +;³ +;³ +;³ REGISTER +;³ USAGE AND +;³ COMVENTIONS: +;³ +;³ +;³ +;³ ASSUMPTIONS: +;³ +;³ +;³ SIDE EFFECT: +;³ +;³ +;³ ùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùù +;³ +;³ BEGIN +;³ ³ +;³ END ³ +;³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +initialize_sublists PROC NEAR ;AN000; + +MOV CX,number_of_sublists ;AN000; +MOV SI,OFFSET first_sublist ;address first sublist ;AN000; +REPEAT: ;AN000; + MOV [SI].sublist_seg,DS ;set up the segment part of the pointer field in the sublist block ;AN000; + ADD SI,TYPE sublist_def ;point to next sublist block ;AN000; +LOOPNZ repeat ;AN000; + ;AN000; +RET + ;AN000; +initialize_sublists ENDP + +;***************************************************************************** +;PRINTF +;***************************************************************************** +; +;Description: Save all registers, set up registers required for SysDispMsg +; routine. This information is contained in a message description +; table pointed to by the DX register. Call SysDispMsg, then +; restore registers. This routine assumes that the only time an +; error will be returned is if an extended error message was +; requested, so it will ignore error returns +; +;Called Procedures: sysdispmsg +; +;Change History: Created 4/22/87 MT +; +;Input: ES:DX = pointer to message description +; +;Output: None +; +;Psuedocode +;---------- +; +; Save all registers +; Setup registers for SysDispMsg from Message Description Tables +; CALL SysDispMsg +; Restore registers +; ret +;***************************************************************************** + +Public PRINTF +PRINTF PROC NEAR ; ;AN000; + +; push ax + ;Save registers ;AN000; + push bx ; " " " " ;AN000; + push cx ; " " " " ;AN000; + push dx ; " " " " ;AN000; + push si ; " " " " ;AN000; + push di ; " " " " ;AN000; + mov di,dx ;Change pointer to table ;AN000; + mov ax,[di].Entry1 ;Message number ;AN000; + mov bx,[di].Entry2 ;Handle ;AN000; + mov si,[di].Entry3 ;Sublist ;AN000; + mov cx,[di].Entry4 ;Count ;AN000; + mov dh,[di].Entry5 ;Class ;AN000; + mov dl,[di].Entry6 ;Function ;AN000; + mov di,[di].Entry7 ;Input ;AN000; + call SysDispMsg ;Display the message ;AN000; + pop di ;Restore registers ;AN000; + pop si ; " " " " ;AN000; + pop dx ; " " " " ;AN000; + pop cx ; " " " " ;AN000; + pop bx ; " " " " ;AN000; +; pop ax ; " " " " ;AN000; + ret ;All done ;AN000; + +PRINTF ENDP ; ;AN000; + +PRINTF_CODE ENDS + + end diff --git a/v4.0/src/CMD/MODE/INVOKE.ASM b/v4.0/src/CMD/MODE/INVOKE.ASM new file mode 100644 index 0000000..2d836c3 --- /dev/null +++ b/v4.0/src/CMD/MODE/INVOKE.ASM @@ -0,0 +1,1549 @@ + ;AN000; +;m ;AN000; + PAGE ,132 ; ;AN000; + TITLE ANALYZE_AND_INVOKE - call appropriate routine based on request ;AN000; +.XLIST ;AN000; + INCLUDE STRUC.INC ;AN000; +.LIST ;AN000; +;.SALL ;AN000; + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +; AC000 - P2944: Was displaying the lines and column settings for CON even +; though couldn't get them when ANSI.SYS isn't loaded. Now +; check if ANSI loaded before trying to display the settings. + +; AC002 - P3331: ES was getting zeroed, which caused problems later in MODECP. + +; AC003 - P3541: The retry status routine was assuming different format than +; the retry type byte was in. I fixed the status checking +; routine. + +; AX004 - P3982: The screen was being cleared after the "Unable to shift +; screen ..." message. + +; AC005 - P4934: The multiplex number for ANSI.SYS was changed due to a +; 5/20/88 conflict with a Microsoft product that has already been +; shipped. + +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ M A C R O S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +GET_EXTENDED_ERROR MACRO ;AN000; + ;AN000; +MOV BX,0 ;level for 3.00 to 4.00 ;AN000; +MOV AH,59H ;function number for get extended error ;AN000; +INT 21H ;AN000; + ;AN000; +ENDM ;AN000; + ;AN000; + ;AN000; +BREAK MACRO X ;AN000; + JMP endcase_&X ;AN000; +ENDM ;AN000; + ;AN000; + ;AN000; + ;AN000; + ;AN000; +DISPLAY MACRO MESSAGE ;AN000; + MOV DX,OFFSET MESSAGE ;AN000; + CALL PRINTF ;AN000; +ENDM ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ M A C R O S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +INCLUDE modequat.inc ;AN000; + ;AN000; +ANSIINT2F EQU 1AH ;INT 2F multiplex number for ANSI.SYS ;AC005; +ASCII_0 EQU "0" ;change one based binary printer number into ASCII printer number ;AN000; +ASCII_1 EQU "1" ;AN000; +B EQU 2 ;retry setting ;AN000; +blink EQU 0000H ;value for flags field of IOCTL data block ;AN000; +busy_retry_active EQU 2 ;indicates bust retry is active ;AN000; +check_installed EQU 0 ;request installed state for INT2F (ANSI) ;AN000; +;COLUMNS EQU 00000010B ; ;AN000; +com1_retry_type_status EQU 0 ;request for retry status on com1 ;AN000; +com2_retry_type_status EQU 2 ;request for retry status on com2 ;AN000; +com3_retry_type_status EQU 4 ;request for retry status on com3 ;AN000; +com4_retry_type_status EQU 6 ;request for retry status on com4 ;AN000; +display_device EQU 3 ;type of device, used for calls to IOCTL 0C function ;AN000; +E EQU 1 ;retry setting ;AN000; +error_retry_active EQU 1 ;indicates error retry is active ;AN000; +false EQU 00H ;AN000; +font_not_loaded EQU 31 ;return from IOCTL 0C (via ext err) indicating DISPLAY.SYS don't have necessary font loaded +get_current_settings EQU 07FH ;request for IOCTL 0C call ;AN000; +installed EQU 0FFH ;return from get_installed_state function ;AN000; +intense EQU 0001H ;value for flags field of IOCTL data block ;AN000; +IOCTL0C EQU [SI] ;AN000; +;LINES EQU 00000001B ;flag for IOCTL0C_functions_requested ;AN000; +lowercase EQU 020H ;when ORed with char value it changes it to lowercase ;AN000; +LPT1 EQU 1 ;mask for input to display_device_reroute_status, see modeecho ;AN000; +LPT2 EQU 2 ;mask for input to display_device_reroute_status, see modeecho ;AN000; +LPT3 EQU 4 ;mask for input to display_device_reroute_status, see modeecho ;AN000; +lpt1_retry_type_status EQU 0 ;request for retry status on lpt1 ;AN000; +lpt2_retry_type_status EQU 1 ;request for retry status on lpt2 ;AN000; +lpt3_retry_type_status EQU 2 ;request for retry status on lpt3 ;AN000; +MODE_INT2F_MULTIPLEX_NUMBER EQU 0 ;AN000; +no_retry EQU 3 ;retry setting ;AN000; +no_retry_active EQU 0 ;indicates no retry active on device ;AN000; +not_supported_on_machine EQU 29 ;return from IOCTL 0C (via ext err) indicating hardware don't support the function ;AN000; +parm_list_BX EQU [BX] ;AN000; +prn_ports_attached EQU CL ;used in printer_reroute_case and check_prn_ports_attached +R EQU 3 ;retry setting for com ports ;AN000; +ready_retry_active EQU 3 ;indicates ready retry is active ;AN000; +redirected EQU 2 ;network puts a 2 in printer address word for printers redirected +rerouted_printer_mask EQU BL ;holds the mask to check ptsflag1 with, see modeecho.asm +returned_retry_type EQU AL ;holds the returned status value ;AN000; +set_display_characteristics EQU 05FH ;request for IOCTL 0C call ;AN000; +status EQU 0 ;request for modecp ;AN000; +StdOut equ 1 ;AN000; +text EQU 01 ;mode field of IOCTL 0C call indicating screen mode type (vs APA mode) ;AN000; +true EQU 0FFH ;AN000; +unspecified EQU 0FFH ;state of item_tags in parm_list if the positonal parm was not specified ;AN664; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ S T R U C T U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; + ;AN000; +des_strt_packet STRUC ;AN000; + des_strt_pkfl DW 0000 ;assume a filename specified ;AN000; + des_strt_pklen DW 02 ;start with size of 'des_strt_pknum' ;AN000; + des_strt_pknum DW 0 ;number of cp numbers in the packet ;AN000; + des_strt_pkcp1 DW -1 ;code page number for 1st slot ;AN000; + des_strt_pkcp2 DW -1 ;AN000; + des_strt_pkcp3 DW -1 ;AN000; + des_strt_pkcp4 DW -1 ;AN000; + des_strt_pkcp5 DW -1 ;AN000; + des_strt_pkcp6 DW -1 ;AN000; + des_strt_pkcp7 DW -1 ;AN000; + des_strt_pkcp8 DW -1 ;AN000; + des_strt_pkcp9 DW -1 ;AN000; + des_strt_pkcpA DW -1 ;AN000; + des_strt_pkcpB DW -1 ;AN000; + des_strt_pkcpC DW -1 ;code page number for 12th slot ;AN000; +des_strt_packet ENDS ;AN000; + ;AN000; +;The info_level is 0 on input, and contains a return code on exit. If carry set ;AN000; +;and 2 then the requested function is not supported on this machine. If carry ;AN000; +;set and 3 then DISPLAY.SYS does not have the appropriate RAM font loaded to ;AN000; +;support the requested function. ;AN000; + ;AN000; +IOCTL0C_def STRUC ;AN000; + ;AN000; +info_level DB 0 ;return code: 0 on input, 1 ?, 2 or 3 as returns ;AN000; + DB 0 ;reserved ;AN000; +data_length DW 14 ;length of the data block not including this field ;AN000; +flags DW 0 ;filled with intense or blink ;AN000; +mode DB text ;filled with text, may be returned as 2 which means APA ;AN000; + DB 0 ;reserved ;AN000; +colors DW 16 ;0 means monochrome ;AN000; + DW bogus ;width in pixels for APA modes ;AN000; + DW bogus ;length in pixels for APA modes ;AN000; +cols DW bogus ;nubmer of text columns ;AN000; +rows DW bogus ;number of text rows ;AN000; + ;AN000; +IOCTL0C_def ENDS ;AN000; + ;AN000; +INCLUDE COMMON.STC ;includes the following strucs ;AN000; + ;AN000; +;codepage_parms STRUC ;AN000; +; cp_device DW ? ;AN000; +; des_pack_ptr DW ? ;AN000; +; font_filespec DW ? ;AN000; +; request_typ DW ? ;AN000; +;codepage_parms ENDS ;AN000; + ;AN000; + ;AN000; +;parm_list_entry STRUC ;used by parse_parameters and invoke ;AN000; + ;AN000; +;parm_type DB bogus ;AN000; +;item_tag DB 0FFH ;AN000; +;value1 DW bogus ;used only for filespecs and code page numbers ;AN000; +;value2 DW bogus ;used only for filespecs and code page numbers ;AN000; +;keyword_switch_ptr DW 0 ;AN000; + ;AN000; +;parm_list_entry ENDS ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ S T R U C T U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; +ROM SEGMENT AT 0 ;AN000; + ORG 530H ;AN000; +resseg LABEL DWORD ;location of resident mode code vector ;AN000; +ROM ENDS ;AN000; + ;AN000; + ;AN000; + PAGE ;AN000; +PRINTF_CODE SEGMENT PUBLIC ;AN000; + ASSUME CS:PRINTF_CODE,DS:PRINTF_CODE,SS:PRINTF_CODE ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +PUBLIC analyze_and_invoke ;make available to "MAIN" ;AN000; +PUBLIC busy_retry_active ;used by modecom ;AN000; +PUBLIC cp_cb ;modepars needs to set the font file name ;AN000; +PUBLIC error_retry_active ;used by modecom ;AN000; +PUBLIC initialize_printer_port_case ;AN000; +PUBLIC no_retry_active ;used by modecom ;AN000; +PUBLIC parm_list_holder ;used by modeprin ;AN664; +PUBLIC ready_retry_active ;used by modecom ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +EXTRN ANSI_not_loaded:BYTE ;see modedefs.inc ;AN000; +EXTRN BAUD_equal:BYTE ;the string "BAUD=", see modepars ;AN000; +EXTRN BAUD_index:WORD ;see modecom.asm ;AN000; +EXTRN B_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN BW40:NEAR ;see modedefs.inc ;AN000; +EXTRN BW40_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN BW80:NEAR ;see modedefs.inc ;AN000; +EXTRN BW80_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN busy_status:ABS +EXTRN close:ABS ;EQU 3EH ;CLOSE A FILE HANDLE,see modecpeq.inc ;AN000; +EXTRN columns_ptr:WORD ;see modesubs.inc ;AN000; +EXTRN CO40:NEAR ;see modedefs.inc ;AN000; +EXTRN CO40_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN CO80:NEAR ;see modedefs.inc ;AN000; +EXTRN CO80_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN codepage_index_holder:WORD ;see MODEPARS.ASM ;AN000; +EXTRN codepage_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN columns_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN columns_equal_msg:BYTE ;see MODEdefS.inc ;AN000; +EXTRN columns_holder:BYTE ;holder for printer chars per line (binary) value, see modeprin ;AN000; +EXTRN COLS_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN columns_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN COM1_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN COM2_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN COM3_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN COM4_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN COMX:ABS ;one of two possible values for "device_type" +EXTRN CON_str:BYTE ;"CON"see MODEPARS.ASM ;AN000; +EXTRN CRLF:BYTE ;see MODEDEFS.ASM, used before "Invalid parameter - " for consistent spacing ;AN000; +EXTRN data_bits_index:WORD ;see modecom.asm ;AN000; +EXTRN DATA_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN DELAY_equal:BYTE ;see MODEPars.asm ;AN000; +EXTRN DEL_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN des_start_packet:WORD ;AX000; des_strt_packet <>, see modepars ;AN000; +EXTRN device:BYTE ;holder of com number for invoke and modeecho ;AN000; +EXTRN device_name:WORD ;AN000; +EXTRN device_type:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN dev_name_size:WORD ;see MODEPARS.ASM ;AN000; +EXTRN dev_open_mode:ABS ;read write access ;AN000; +EXTRN display_printer_reroute_status:NEAR ;see modeecho.asm +EXTRN eighty_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN eighty_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN error_status:ABS ;see MODEPRIN +EXTRN five_char_underline:BYTE ;see modedefs.inc ;AN000; +EXTRN four_char_underline:BYTE ;see modedefs.inc ;AN000; +EXTRN function_not_supported:BYTE ;see modedefs.inc ;AN000; +EXTRN err1:BYTE ;see modedefs.inc +EXTRN E_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN fourty_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN fourty_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN handle_40_or_80:NEAR ;see modescrn ;AN000; +EXTRN illegal_device_ptr:WORD ;see modesubs.inc +EXTRN keyword:ABS ;see MODEPARS ;AN000; +EXTRN invalid_number_of_parameters:WORD ;AN000; +;EXTRN invalid_parameter:WORD ;"Invalid parameter '????'",beep ;AN000; +EXTRN len_COMX_str:ABS ;see MODEPARS.ASM ;AN000; +EXTRN len_CON_str:ABS ;see MODEPARS.ASM ;AN000; +EXTRN len_LPTX_str:ABS ;see MODEPARS.ASM ;AN000; +EXTRN L_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN LINES_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN LINES_equal_msg:BYTE ;see MODEDEFS.INC ;AN000; +EXTRN lines_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN long_underline:BYTE ;see modedefs.inc ;AN000; +EXTRN lptno:BYTE ;holder of printer number for invoke and modeecho ;AN000; +EXTRN lpt1_retry_type:BYTE ;see RESCODE +EXTRN LPT1_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN LPT2_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN LPT3_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN notredpt:BYTE ;printer number in "LPTn not rerouted" +EXTRN max_request_type:ABS ;see MODEPARS.ASM ;AN000; +EXTRN modecom:NEAR ;AN000; +EXTRN modecp:NEAR ;AN000; +EXTRN modeecho:NEAR ;AN000; +EXTRN modeecno:NEAR ;AN000; +EXTRN modeprin:NEAR ;AN000; +EXTRN modify_resident_code:NEAR ;see modeprin ;AN000; +EXTRN MONO:NEAR ;see modedefs.inc ;AN000; +EXTRN MONO_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN no_retry_flag:ABS ;see MODEPRIN +EXTRN noerror:BYTE ;AN000; +EXTRN none_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN none_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN offending_parameter:BYTE ;see MODEMES ;AN000; +EXTRN OFF_item_tag:ABS ;see pares.asm ;AN000; +EXTRN off_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN onethirtytwo_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN ON_item_tag:ABS ;see pares.asm ;AN000; +EXTRN on_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN open:ABS ;open a device handle, see modecpeq.inc ;AN000; +EXTRN parity_equal:BYTE ;see modepars.asm ;AN000; +EXTRN parity_index:WORD ;see modecom ;AN000; +EXTRN parm2:BYTE ;see MODEPRIN.ASM ;AN000; +EXTRN parm3:BYTE ;see MODEPARS.ASM ;AN000; +;EXTRN parm_lst:BYTE ;parm_list_entry max_pos_parms DUP (<>), see MODEPARS.ASM ;AN000; +EXTRN parms_form:byte ;indicator of whether the parameters were entered as positionals or as keywords ;AN000; +EXTRN pbaud_ptr:WORD ;AN000;;pointer to the baud rate string in the initialization message for COM, see modesubs.inc +EXTRN pdata:BYTE ;see modesubs.inc ;AN000; +EXTRN pparity_ptr:WORD ;see modesubs.inc ;AN000; +EXTRN pparm:BYTE ;used by modecom and for message, see modesubs.inc ;AN000; +EXTRN prepare:ABS ;AN000; +EXTRN prepare_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN PRINTR:WORD ;PRINTER BASE (40:8), HOLDS PORT ADDRESSES OF PRINTER CARDS +EXTRN pstop_ptr:WORD ;see modesubs.inc ;AN000; +EXTRN PRINTF:NEAR ;AN000; +EXTRN rate_equal:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN ready_status:ABS ;see modeprin +EXTRN redpt:BYTE ;printer number (n) in message "LPTn rerouted to COMm" +EXTRN refresh:ABS ;AN000; +EXTRN retry_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN request_type:BYTE ;see "MODEPARS.ASM" ;AN000; +EXTRN retry_equal:BYTE ;see MODEDEFS.INC ;AN000; +EXTRN retry_equal_str:BYTE ;AN000; +EXTRN retry_index:WORD ;see MODECOM.ASM ;AN000; +EXTRN retry_type_ptr:WORD ;see MODESUBS.INC ;AN000; +EXTRN row_ptr:WORD ;see modesubs.inc ;AN000; +EXTRN row_type:WORD ;see modesubs.inc ;AN000; +EXTRN R_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN R_str:BYTE ;see MODEPARS.ASM ;AN000; +EXTRN Required_font_not_loaded:BYTE ;see modedefs.asm ;AN000; +EXTRN res_com_retry_type:ABS ;see RESCODE.SAL ;AN000; +;EXTRN res_lpt_retry_type:ABS ;see RESCODE.SAL ;AN000; +EXTRN select:ABS ;request type for 'modecp' ;AN000; +EXTRN select_item_tag:ABS ;see MODEPARS.ASM ;AN000; +EXTRN serial_base:WORD ;see modecom ;AN000; +EXTRN set_con_features:ABS ;AN000; +EXTRN set_retry_type:NEAR ;see modeprin ;AN000; +EXTRN shift_screen:NEAR ;see modescrn ;AN000; +EXTRN stat_dev_ptr:WORD ;see modedefs.inc ;AN000; +EXTRN status_for_device:BYTE ;"Status for device %1:" see modedefs.inc ;AN000; +EXTRN status_for_everything:ABS ;AN000; +EXTRN stop_bits_index:WORD ;see modecom.asm ;AN000; +EXTRN stop_equal:BYTE ;"STOP=", see modepars ;AN000; +EXTRN typamat:NEAR ;see "typamat.asm" ;AN000; + ;AN000; +;possible values of "request_type" ;AN000; + ;AN000; +EXTRN all_con_status:ABS ;AN000; +EXTRN codepage_prepare:ABS ;AN000; +EXTRN codepage_refresh:ABS ;AN000; +EXTRN codepage_select:ABS ;AN000; +EXTRN codepage_status:ABS ;AN000; +EXTRN codepage_prepared_status:ABS ;AN000; +EXTRN codepage_selected_status:ABS ;AN000; +EXTRN com_status:ABS ;AN000; +;EXTRN con_status:ABS ;AN000; +EXTRN initialize_com_port:ABS ;AN000; +EXTRN initialize_printer_port:ABS ;AN000; +EXTRN old_initialize_printer_port:ABS ;AN000; +EXTRN old_video_mode_set:ABS ;AN000; +EXTRN printer_reroute:ABS ;AN000; +EXTRN printer_status:ABS ;AN000; +EXTRN turn_off_reroute:ABS ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +ANSI_installed DB false ;boolean indicator of whether ANSI.SYS is installed ;AN000; +columns_specified DB false ;indicates if columns= was on the command line, see set_con_features_case;AN000; +code_page_numbers_encountered DB 0 ;AN000; +cp_cb codepage_parms <> ;codepage subroutine parameter block ;AN000; +com_ports_attached DB 0 ;number of com ports in the machine +current_packet_cp_number DW -2 ;adjustment for accessing current 'des_strt_pkcp?' in 'des_start_packet' ;AN000; +delay_holder DB 1 ;holder for binary form of delay requested ;AN000; +device_request DB ? ;holds device request value ;AN000; +max_pknum EQU ($ - OFFSET des_start_packet.des_strt_pkcp1)/2 ;most cp numbers can send at once ;AN000; +;IOCTL0C_functions_requested DB 0 ;for displaying messages, flag byte indicating IOCTL functions requested ;AN000; +need_typamat_call DB false ;boolean for saving up delay and rate settings ;AN000; +need_IOCTL0C DB false ;boolean for saving up parts of an IOCTL 0CH call ;AN000; +parm_list_holder DW bogus ;holder for address of parsed parameter list for when BX is needed elsewhere ;AN000; +parm_list_index_holder DW bogus ;holder for index of parsed parameter list for when DI is needed elsewhere ;AN000; +i DB 0 ;index for status loop ;AN000; +rate_holder DB 32 ;holder for binary form of rate value ;AN000; +row_value DB ? ;holder for binary form of row value during status display ;AN000; + ;AN000; +IOCTL0C_data_block IOCTL0C_def<> ;AN000; + +PUBLIC IOCTL0C_data_block + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; +check_ANSI_installed PROC NEAR ;See if ANSI.SYS is installed ;AC001; + + MOV AH,ANSIINT2F ;AC001; + MOV AL,check_installed ;AC001; + INT 2FH ;AC001; + .IF THEN ;AC001; + MOV ANSI_installed,true ;initialized to false, so no ELSE needed ;AC001; + .ENDIF + +check_ANSI_installed ENDP ;AC001; + +;------------------------------------------------------------------------------ + + + +setup_device_name PROC NEAR ;AN000; + ;AN000; +MOV DX,device_name ;DX=pointer to ASCIIZ device name ;AN000; +MOV cp_cb.cp_device,DX ;Set the pointer to the device name ASCIIZ in the parameter block for 'modecp'. ;AN000; + ;AN000; +RET ;AN000; + ;AN000; +setup_device_name ENDP ;AN000; + ;AN000; +;------------------------------------------------------------------------------- ;AN000; + ;AN000; + ;AN000; +do_IOCTL0C PROC NEAR ;AN000; +PUBLIC DO_IOCTL0C ;AN000; + MOV AH,open ;open device ;AN000; + MOV AL,dev_open_mode ;AL=open mode for devices, see modecpeq.inc ;AN000; + MOV DX,OFFSET CON_str ;know that CON is being opened, avoid using user input and having to remove colon ;AN000; + INT 21H ;AN000; + ;AN000; + MOV BX,AX ;BX=handle of CON ;AN000; + MOV AX,440CH ;AN000; + MOV CH,display_device ;type of device ;AN000; + MOV DX,OFFSET IOCTL0C_data_block ;AN000; + INT 21H ;the IOCTL data block is filled with the current settings ;AN000; + PUSHF ;save result of the IOCTL ;AN000; + ;AN000; + MOV AH,3EH ;assume that BX still has the handle ;AN000; + INT 21H ;close CON, open and close each time because if error may not be back to close ;AN000; + ;AN000; + POPF ;restore result of the IOCTL ;AN000; + ;AN000; + RET ;AN000; + ;AN000; +do_IOCTL0C ENDP ;AN000; + ;AN000; +;------------------------------------------------------------------------------- ;AN000; + ;AN000; +display_columns_status PROC NEAR ;AN000; + ;AN000; +MOV CL,get_current_settings ;AN000; +CALL do_IOCTL0C ;get current settings of CON ;AN000; +.IF THEN ;AN000; + .IF THEN ;AN000; + MOV columns_ptr,OFFSET eighty_str ;set up message block with pointer to "80" ;AN000; + .ELSE ;AN000; + MOV columns_ptr,OFFSET fourty_str ;AN000; + .ENDIF ;AN000; +.ELSE ;AN000; + MOV columns_ptr,OFFSET NONE_str ;AN000; +.ENDIF ;AN000; +display COLUMNS_equal_msg ;AN000; + ;AN000; +RET ;AN000; + ;AN000; +display_columns_status ENDP ;AN000; + ;AN000; +;------------------------------------------------------------------------------- ;AN000; + ;AN000; +display_lines_status PROC NEAR ;AN000; + ;AN000; +MOV CL,get_current_settings ;AN000; +CALL do_IOCTL0C ;get current settings of CON ;AN000; +.IF THEN ;AN000; + MOV AX,IOCTL0C_data_block.rows ;AN000; + MOV row_value,AL ;row_value=binary row value ;AN000; + MOV row_type,right_align+unsgn_bin_byte ;set up sublist so msg ret knows it is a binary byte ;AN000; + MOV row_ptr,OFFSET row_value ;set up LINES_equal sublist ;AN000; +.ELSE ;AN000; + MOV row_ptr,OFFSET NONE_str ;AN000; +.ENDIF ;AN000; +display LINES_equal_msg ;AN000; + ;AN000; +RET ;AN000; + ;AN000; +display_lines_status ENDP ;AN000; + +;------------------------------------------------------------------------------- + +old_video_mode_set_IOCTL PROC NEAR ;AN004; + +MOV CL,set_display_characteristics ;AN000; +CALL do_IOCTL0C ;AN000; +.IF C THEN ;AN000; + get_extended_error ;AN000; + .IF THEN ;AN000; + DISPLAY Function_not_supported ;AN000; + .ELSEIF THEN ;AN000; + DISPLAY Required_font_not_loaded ;AN000; + .ENDIF ;AN000; + MOV noerror,false ;AN000; +.ENDIF ;AN000;carry ;AN000; + +RET + ;AN004; +old_video_mode_set_IOCTL ENDP ;AN004; + + ;AN000; +;------------------------------------------------------------------------------- ;AN000; +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; +;³ +;³ CHECK_COM_PORTS_ATTACHED +;³ ------------------------ +;³ +;³ Return the number of com ports in the machine. +;³ +;³ INPUT: none +;³ +;³ +;³ RETURN: com_ports_attached - number of com ports +;³ +;³ +;³ MESSAGES: none +;³ +;³ REGISTER +;³ USAGE: SI - index of the FOR loop and displacement from serial_base +;³ ES - holds segment of ROM data area +;³ +;³ +;³ ASSUMPTIONS: The user has initialized com_ports_attached to zero. +;³ +;³ +;³ SIDE EFFECT: ES is lost +;³ SI is lost +;³ ;AN000; +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; + +check_com_ports_attached PROC NEAR + +MOV SI,0 +MOV ES,SI ;now ES:SERIAL_BASE addresses 40:0=0:400 + +.FOR SI = 0 TO 6 STEP 2 + + .IF < NE 0> THEN ;SEE IF THE COM PORT EXISTS + INC com_ports_attached + .ENDIF + +.NEXT SI + +RET + +check_com_ports_attached ENDP + + +;------------------------------------------------------------------------------- ;AN000; +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; +;³ +;³ CHECK_PRN_PORTS_ATTACHED +;³ ------------------------ +;³ +;³ Return the number of printer ports in the machine. The network will put a 2 +;³ in th address word if the printer is redirected, so for the printer to +;³ actually exist the address must be greater than 2 ("redirected"). Since +;³ can't have infinite retry on redirected printers only want to count ports +;³ with >2 for addresses. +;³ +;³ INPUT: none +;³ +;³ +;³ RETURN: prn_ports_attached - number of printer ports +;³ +;³ +;³ MESSAGES: none +;³ +;³ REGISTER +;³ USAGE: SI - index of the FOR loop and displacement from printr +;³ ES - holds segment of ROM data area (0 in this case) +;³ +;³ +;³ ASSUMPTIONS: All valid printer port addresses are >2. +;³ +;³ +;³ SIDE EFFECT: ES is lost +;³ SI is lost +;³ ;AN000; +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; + +check_prn_ports_attached PROC NEAR + + +MOV SI,0 +MOV ES,SI ;now ES:printr addresses 40:8=0:408 + +.FOR SI = 0 TO 4 STEP 2 ;for each of 3 printer port address holder words + + .IF < GT redirected> THEN ;SEE IF THE PORT EXISTS + INC prn_ports_attached + .ENDIF + +.NEXT SI + +RET + +check_prn_ports_attached ENDP + + +;------------------------------------------------------------------------------- ;AN000; +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; +;³ ;AN000; +;³ GET_DEVICE_RETRY_TYPE ;AN000; +;³ --------------------- ;AN000; +;³ ;AN000; +;³ Return the type of retry active for comX or lptX. ;AN000; +;³ ;AN000; +;³ INPUT: device_request - scalar indicating what status the user requested. ;AN000; +;³ use the following equates: ;AN000; +;³ ;AN000; +;³ com1_retry_type_status EQU 0 ;AN000; +;³ com2_retry_type_status EQU 2 ;AN000; +;³ com3_retry_type_status EQU 4 ;AN000; +;³ com4_retry_type_status EQU 6 ;AN000; +;³ lpt1_retry_type_status ;AN000; +;³ lpt2_retry_type_status ;AN000; +;³ lpt3_retry_type_status ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ RETURN: returned_retry_type - scalar indicating type of retry active for ;AN000; +;³ the requested device. compare with the following equates: ;AN000; +;³ ;AN000; +;³ no_retry_flag ;AN000; +;³ error_status ;AN000; +;³ busy_status ;AN000; +;³ ready_status ;AN000; +;³ ;AN000; +;³ retry_type_ptr - set to proper string ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ MESSAGES: none ;AN000; +;³ ;AN000; +;³ REGISTER ;AN000; +;³ USAGE: CL - For com ports it serves as bit shift count for the retry type byte. +;³ ;AN000; +;³ AL - On exit holds retry type scalar on exit (returned_retry_type) ;AN000; +;³ ;AN000; +;³ ES - holds segment of resident mode code ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ CONVENTIONS: The value in device_request is used as an index into the LPTX ;AN000; +;³ array of retry type flags, or as a bit shift count for the ;AN000; +;³ COM retry type byte. ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ASSUMPTIONS: The user has initialized device_request on entry with ;AN000; +;³ the equates provided. ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ SIDE EFFECT: none. ;AN000; +;³ ;AN000; +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; + ;AN000; +get_device_retry_type PROC NEAR ;AN665; + +PUBLIC get_device_retry_type + +PUSH BX ;AN665; +PUSH ES ;AN665; + +XOR BX,BX ;AN665; +MOV ES,BX ;set segment to zero ;AN665; + +.IF < NE 0000H> THEN ;IF code resident THEN ;AN665; + MOV ES,ES:WORD PTR resseg[2] ;ES=seg of resident code ;AN665; + .IF THEN + MOV CL,device_request ;CL has 0, 2, 4 or 6 for COM 1, 2, 3 or 4 respectively ;AC003; + MOV returned_retry_type,BYTE PTR ES:res_com_retry_type ;AL=the status byte for all 4 com ports ;AN665; + SHR returned_retry_type,CL ;AL=XXXXXX??, where ?? is the retry bits for port in question ;AC003; + AND returned_retry_type,00000011B ;AL=000000??, where ?? is the retry bits for port in question ;AC003; + .ELSE ;AN665; + MOV BL,device_request ;BX=index into retry bytes in resident code ;AN665; + MOV returned_retry_type,BYTE PTR ES:lpt1_retry_type[BX] ;AN665; + .ENDIF ;AN665; +.ELSE ;AN665; + MOV returned_retry_type,no_retry_flag ;AN665; +.ENDIF ;AN665; + +.IF OR ;COM form of busy flag ;AN665; +.IF THEN ;AN665; + MOV retry_type_ptr,OFFSET B_str ;AN665; +.ELSEIF OR ;COM form of error flag ;AN665; +.IF THEN ;AN665; + MOV retry_type_ptr,OFFSET E_str ;AN665; +.ELSEIF OR ;COM form of ready flag ;AN665; +.IF THEN ;AN665; + MOV retry_type_ptr,OFFSET R_str ;AN665; +.ELSE ;AN665; + MOV retry_type_ptr,OFFSET NONE_str ;not E, B or R. ;AN665; +.ENDIF ;AN665; + +POP ES ;AN665; +POP BX ;AN665; +RET ;AN665; + +get_device_retry_type ENDP ;AN665; + ;AN000; +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; +;³ ;AN000; +;³ ANALYZE_AND_INVOKE ;AN000; +;³ ------------------ ;AN000; +;³ ;AN000; +;³ The command line is boken down into pieces by "parse_parameters". Each piece ;AN000; +;³ is analyzed here, and the appropriate routine called to setup and/or execute ;AN000; +;³ the requested function. ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ INPUT: request_type - scalar indicating what operation the user requested. ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ RETURN: none ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ MESSAGES: none ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ REGISTER ;AN000; +;³ USAGE: DI - index into the list of parsed parms, the array parm_list. ;AN000; +;³ ;AN000; +;³ CX - temporary holder for memory to memory MOVs ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ CONVENTIONS: ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ASSUMPTIONS: All the input are valid. The parm_list entry past the last one ;AN000; +;³ has a parm_type of bogus. ;AN000; +;³ ;AN000; +;³ The lines and columns values are in binary for request_type= ;AN000; +;³ set_con_features ;AN000; +;³ ;AN000; +;³ The codepage numbers were put into des_start_packet. ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ ;AN000; +;³ SIDE EFFECT: ;AN000; +;³ ;AN000; +;³ ;AN000; +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;AN000; + ;AN000; +analyze_and_invoke PROC NEAR ;AX000; ;AN000; + ;AN000; + ;AN000; +;CASE request_type= ;AN000; + ;AN000; + MOV cp_cb.des_pack_ptr,OFFSET des_start_packet ;AX000;In case a codepage request ;AN000; + ;AN000; + MOV DI,0 ;initialize index into the list of parsed parameters ;AN000; + ;AN000; + ;calculate the displacement for the jump to the jump ;AN000; + MOV parm_list_holder,BX ;save parm_list_BX ;AN000; + XOR BX,BX ;AX000; ;AN000; + MOV BL,max_request_type ;AX000; ;AN000; + SUB BL,request_type ;AX000;see the list of equates for request_type ;AN000; + SHL BX,1 ;AX000;BX=word displacement into jump table ;AN000; + JMP jump_table1[BX] ;AX000;jump to appropriate jump ;AN000; + ;AN000; + jump_table1 LABEL WORD ;the order of the following entries is critical ;AN000; + ;AN000; + DW OFFSET all_con_status_case ;AN000; + DW OFFSET codepage_prepare_case ;AN000; + DW OFFSET codepage_refresh_case ;AN000; + DW OFFSET codepage_select_case ;AN000; + DW OFFSET codepage_status_case ;AN000; + DW OFFSET codepage_prepared_status_case ;AN000; + DW OFFSET codepage_selected_status_case ;AN000; + DW OFFSET com_status_case ;AN000; + DW OFFSET initialize_com_port_case ;AN000; + DW OFFSET initialize_printer_port_case ;AN000; + DW OFFSET old_initialize_printer_port_case ;AN000; + DW OFFSET old_video_mode_set_case ;AN000; + DW OFFSET printer_reroute_case ;AN000; + DW OFFSET printer_status_case ;AN000; + DW OFFSET set_con_features_case ;AN000; + DW OFFSET status_for_everything_case ;AN000; + DW OFFSET turn_off_reroute_case ;AN000; + ;AN000; + ;AN000; + all_con_status_case: ;know that all con status is requested ;AN000; + ;AN000; + ;AN000; + MOV stat_dev_ptr,OFFSET CON_str ;set up msg ser input ;AN000; + MOV dev_name_size,len_CON_str ;set up for msg service, see MODEPARS.ASM ;AN000; + display status_for_device ;AN000; + display long_underline ;Status for device CON: ;AN000; + display four_char_underline ;---------------------- ;AN000; + ;AN000; + CAll check_ANSI_installed ;see if ANSI.SYS is installed ;AC001; + .IF THEN ;IF can get info on settings THEN display them ELSE don't display them + CALL display_columns_status ;AN000; + CALL display_lines_status ;AN000; + .ENDIF ;AC001; + MOV cp_cb.request_typ,status ;set up variables for modecp ;AN000; + MOV cp_cb.cp_device,OFFSET CON_str ;AN000; + ;AN000; + CALL modecp ;display codepage status ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + codepage_prepare_case: ;AN000; + ;AN000; + MOV cp_cb.request_typ,prepare ;AN000; + CALL setup_device_name ;Set the pointer to the device name ASCIIZ in the parameter block for 'modecp'. ;AN000; + ;AN000; + call modecp ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + codepage_refresh_case: ;AN000; + ;AN000; + MOV cp_cb.request_typ,refresh ;AN000; + CALL setup_device_name ;Set the pointer to the device name ASCIIZ in the parameter block for 'modecp'. ;AN000; + ;AN000; + call modecp ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + ;AN000; + codepage_select_case: ;AN000; + ;AN000; + MOV cp_cb.request_typ,select ;AN000; + CALL setup_device_name ;Set the pointer to the device name ASCIIZ in the parameter block for 'modecp'. ;AN000; + MOV des_start_packet.des_strt_pknum,1 ;one cp number ;AN000; + MOV des_start_packet.des_strt_pklen,4 ;bytes for count (word) and one number (word) ;AN000; + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + MOV DI,codepage_index_holder ;DI=index in parm list of the entry for the codepage to be selected;AN000; + MOV AX,parm_list_BX[DI].value1 ;AX=codepage number in binary form ;AN000; + MOV des_start_packet.des_strt_pkcp1,AX ;setup parm block with the (single) cp number ;AN000; + ;AN000; + CALL modecp ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + codepage_status_case: ;AN000; + codepage_prepared_status_case: ;AN000; + codepage_selected_status_case: ;AN000; + ;AN000; + MOV cp_cb.request_typ,status ;AN000; + CALL setup_device_name ;Set the pointer to the device name ASCIIZ in the parameter block for 'modecp'. ;AN000; + ;AN000; + CALL modecp ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + com_status_case: ;AN000; + ;AN000; + ; INPUT: device_type = COMx + ; device = ASCII COM number + + + CALL check_com_ports_attached ;return number of com ports in com_ports_attached ;AN000; + ;AN000; + .IF > AND ;AN000; + .IF THEN ;COM1 exists + MOV BL,COM1 ;AN000; + MOV stat_dev_ptr,OFFSET COM1_str ;set up msg ser input ;AN000; + MOV device_request,com1_retry_type_status ;AN000; + .ELSEIF > AND ;AN000; + .IF THEN ;COM2 exists + MOV BL,COM2 ;AN000; + MOV stat_dev_ptr,OFFSET COM2_str ;set up msg ser input ;AN000; + MOV device_request,com2_retry_type_status ;AN000; + .ELSEIF > AND ;AN000; + .IF THEN ;COM3 exists + MOV BL,COM3 ;AN000; + MOV stat_dev_ptr,OFFSET COM3_str ;set up msg ser input ;AN000; + MOV device_request,com3_retry_type_status ;AN000; + .ELSEIF > AND ;AN000; + .IF THEN ;COM4 exists + MOV BL,COM4 ;AN000; + MOV stat_dev_ptr,OFFSET COM4_str ;set up msg ser input ;AN000; + MOV device_request,com4_retry_type_status ;AN000; + .ELSE ;device does not exist ;AN000; + MOV CX,device_name ;AN000; ;AN000; + MOV illegal_device_ptr,CX ;put pointer to com port string in message ;AN000; + DISPLAY err1 ;AN000;"Illegal device name - COMX" ;AN000; + MOV noerror,false ;set flag for displaying status to be skipped + .ENDIF ;AN000; + .IF THEN + MOV dev_name_size,len_COMX_str ;set up for msg service, see MODEPARS.ASM ;AN000; + display status_for_device ;"Status for device COM?:" ;AN000; + display long_underline ;"------------------" ;AN000; + display five_char_underline ;has CRLF on it "-----" ;AN000; + call get_device_retry_type ;AN000; + display retry_equal ;AN000; + .ENDIF + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; +; con_status_case: ;don't know which con status is requested ;AN000; + ;AN000; +; MOV request_type,all_con_status ;AC000;DCR76 ;AN000; +; CALL analyze_and_invoke ;AC000;DCR76 ;AN000; + ;AN000; +; MOV dev_name_size,len_CON_str ;set up for msg service, see MODEPARS.ASM ;AN000; +; MOV stat_dev_ptr,OFFSET CON_str ;set up msg ser input ;AN000; +; display status_for_device ;AN000; +; display long_underline ;Status for device CON: ;AN000; +; display four_char_underline ;---------------------- ;AN000; +; ;AN000; +; MOV DI,0 ;AN000; +; ;AN000; +; .WHILE DO ;the entry after the last has parm_type of bogus ;AN000; +; ;AN000; +; ;CASE parm_list_BX[DI].item_tag= ;AN000; +; ;AN000; +; ;CODEPAGE, ;AN000; +; ;PREPARE, ;AN000; +; ;SELECT: ;AN000; +; ;AN000; +; .IF OR ;AN000; +; .IF OR ;AN000; +; .IF THEN ;AN000; +; ;AN000; +; MOV cp_cb.request_typ,status ;AN000; +; MOV cp_cb.cp_device,OFFSET CON_str ;AN000; +; CALL modecp ;display codepage status ;AN000; +; ;AN000; +; BREAK 2 ;AN000; +; ;AN000; +; .ENDIF ;AN000; +; ;AN000; +; ;BLINK: ;AN000; +; ;AN000; +; .IF THEN ;AN000; +; ;AN000; +; CALL display_blink_status ;AN000; +; ;AN000; +; BREAK 2 ;AN000; +; ;AN000; +; .ENDIF ;AN000; +; ;AN000; +; ;AN000; +; ;COLUMNS: ;AN000; +; ;AN000; +; .IF THEN ;AN000; +; ;AN000; +; CALL display_COLUMNS_status ;AN000; +; ;AN000; +; BREAK 2 ;AN000; +; ;AN000; +; .ENDIF ;AN000; +; ;AN000; +; ;AN000; +; ;LINES: ;AN000; +; ;AN000; +; .IF THEN ;AN000; +; ;AN000; +; CALL display_lines_status ;AN000; +; ;AN000; +; BREAK 2 ;AN000; +; ;AN000; +; .ENDIF ;AN000; +; ;AN000; +; ENDCASE_2: ;AN000; +; ;AN000; +; ADD DI,TYPE parm_list_entry ;AN000; +; ;AN000; +; .ENDWHILE ;AN000; + ;AN000; +; BREAK 0 ;AN000; + ;AN000; + ;AN000; + ;AN000; + initialize_com_port_case: ;AN000; + ;AN000; + + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + + .IF THEN ;IF the parms were input as keywords THEN ;AN000; + ;AN000; + MOV DI,TYPE parm_list_entry ;skip COMN parm ;AN000; + ;AN000; + .WHILE DO NEAR ;the entry after the last has parm_type of bogus ;AN000; + ;AN000; + ;CASE parm_list_BX[DI].keyword_switch_ptr= ;AN000; + ;AN000; + ;BAUD_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV AX,parm_list_BX[DI].value1 ;AX= pointer to the baud rate string ;AN000; + MOV pbaud_ptr,AX ;set pointer to the baud rate string in the messge ;AN000; + MOV baud_index,DI ;set index into parm list for setcom ;AN000; + BREAK 3 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;PARITY_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV SI,parm_list_BX[DI].value1 ;AX= pointer to the parity string ;AN000; + MOV pparity_ptr,SI ;set pointer to the parity string in the messge ;AN000; + OR BYTE PTR [SI],lowercase ;convert to lowercase for compatibility with previous versions + MOV parity_index,DI ;set index into parm list for setcom ;AN000; + BREAK 3 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;DATA_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV BP,parm_list_BX[DI].value1 ;BP= pointer to the data bits string ;AN000; + MOV AL,[BP] ;AL= data bits character ;AN000; + MOV pdata,AL ;set the data bits string in the messge ;AN000; + MOV data_bits_index,DI ;set index into parm list for setcom ;AN000; + BREAK 3 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;STOP_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV AX,parm_list_BX[DI].value1 ;AX= pointer to the stop bit string ;AN000; + MOV pstop_ptr,AX ;set pointer to the parity string in the messge ;AN000; + MOV stop_bits_index,DI ;set index into parm list for setcom ;AN000; + BREAK 3 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;RETRY_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV retry_index,DI ;indicate to modecom which parm is retry ;AN000; +; BREAK 3 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ENDCASE_3: ;AN000; + ;AN000; + ADD DI,TYPE parm_list_entry ;AN000; + ;AN000; + ;AN000; + .ENDWHILE ;AN000; + ;AN000; + .ELSE ;the parms were entered as positionals (the old form) ;AN000; + ;AN000; + MOV baud_index,TYPE parm_list_entry ;AN000; + MOV DI,2 * (TYPE parm_list_entry) ;AN000; + .IF THEN ;AN000;IF stopbits requested THEN + MOV parity_index,DI ;AN000; + .ENDIF + MOV DI,3 * (TYPE parm_list_entry) ;AN000; + .IF THEN ;AN000;IF stopbits requested THEN + MOV data_bits_index,DI ;AN000; + .ENDIF + MOV DI,4 * (TYPE parm_list_entry) ;DI=stopbits index ;AN000; + .IF THEN ;AN000;IF stopbits requested THEN + MOV stop_bits_index,DI ;AN000; + .ENDIF + MOV DI,5 * (TYPE parm_list_entry) ;AN000;DI=index of retry parm + .IF THEN ;AN000;IF retry requested THEN + MOV retry_index,DI ;AN000;set up index for modecom + .ENDIF ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + CALL modecom ;AN000; + ;AN000; + BREAK 0 ;AN000; + + ;AN000; + ;AN000; + old_initialize_printer_port_case: ;Assume that parms not specified have an entry in parm_list that is in initial state;AN000; + + ;printer_no has ASCII form of printer number ;AN000; + ;need to put binary form of columns in columns_holder (80 or 132) ;AN000; + ;need to put "6" or "8" in parm2 ;AN000; + ;need to set retry_index ;AN000; + + +PUBLIC old_initialize_printer_port_case + + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + MOV DI,TYPE parm_list_entry ;skip LPTN parm, point at chars per line ;AN000; + + .IF THEN ;AN000; + MOV columns_holder,132 ;AN000; + .ELSEIF THEN ;AN000; + MOV columns_holder,80 ;AN000; + .ENDIF ;if not 80 or 132 modeprin assumes not specified, and makes no change;AN000; + ADD DI,TYPE parm_list_entry ;look at lines per inch ;AN000; + + .IF THEN ;IF chars per line specified THEN ;AN000; + MOV SI,parm_list_BX[DI].value1 ;SI=>"6" or "8" ;AN000; + MOV AL,BYTE PTR DS:[SI] ;AN000; + MOV parm2,AL ;parm2="6" or "8" ;AN000; + .ENDIF ;otherwise leave parm2=0FFH (unspecified) ;AN000; + + ADD DI,TYPE parm_list_entry ;look at retry request ;AN000; + .IF THEN ;AN000; + MOV retry_index,DI ;AN000;let modeprin know retry was requested and the index of it. + .ENDIF ;AN000; + + CALL modeecno ;AN000; + CALL modeprin ;AN000; + ;AN000; + BREAK 0 ;AN000; + + + + initialize_printer_port_case: ;printer_no has ASCII form of printer number ;AN000; + ;need to put binary form of columns in columns_holder (80 or 132) ;AN000; + ;need to put "6" or "8" in parm2 ;AN000; + ;need to set retry_index ;AN000; + ;AN000; + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + MOV DI,TYPE parm_list_entry ;skip LPTN parm ;AN000; + + .WHILE DO ;the entry after the last has parm_type of bogus ;AN000; + ;AN000; + ;CASE parm_list_BX[DI].keyword_switch_ptr= ;AN000; + ;AN000; + ;AN000; + ;LINES_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV SI,parm_list_BX[DI].value1 ;SI=>"6" or "8" ;AN000; + MOV AL,BYTE PTR DS:[SI] ;AN000; + MOV parm2,AL ;parm2="6" or "8" ;AN000; + BREAK 4 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;COLUMNS_equal: ;AN000; + ;AN000; + .IF > OR ;AN000; + .IF > THEN ;AN000; + ;AN000; + .IF THEN ;AN000; + MOV columns_holder,132 ;AN000; + .ELSE ;AN000; + MOV columns_holder,80 ;AN000; + .ENDIF ;AN000; + BREAK 4 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;RETRY_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + + MOV retry_index,DI ;AN664; + BREAK 4 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ENDCASE_4: ;AN000; + ;AN000; + ADD DI,TYPE parm_list_entry ;AN000; + ;AN000; + ;AN000; + .ENDWHILE ;AN000; + + CALL modeecno ;turn of rerouting ;AN000; + CALL modeprin ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + ;AN000; + ;AN000; + old_video_mode_set_case: ;AN000; + ;AN000; + PUBLIC old_video_mode_set_case ;AN000; + ;AN000; + ;AN000; + ;first see if ANSI.SYS is loaded ;AN000; + CALL check_ANSI_installed ;AC001; + .IF THEN ;AC001; + MOV CL,get_current_settings ;AN000; + PUSH BX ;save parm_list ;AN000; + CALL do_IOCTL0C ;get current settings of CON ;AN000; + POP BX ;restore parm_list ;AN000; + MOV IOCTL0C_data_block.mode,text ;AN000; + .ENDIF ;AN000;ANSI installed ;AN000; + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + PUSH DI ;save parm list index ;AN000; + .IF THEN + .IF THEN ;IF BW40 REQUESTED ;AN000; + CALL BW40 ;AN000; + .ELSEIF THEN ;IF BW80 REQUESTED ;AN000; + CALL BW80 ;AN000; + .ELSEIF THEN ;IF CO40 REQUESTED ;AN000; + CALL CO40 ;AN000; + .ELSEIF THEN ;IF CO80 REQUESTED ;AN000; + CALL CO80 ;AN000; + .ELSEIF THEN ;IF MONO REQUESTED ;AN000; + CALL MONO ;AN000; + .ELSE ;AN000; + .IF THEN ;AN000; +;AC004; MOV need_IOCTL0C,true ;use IOCTL if possible to retain lines setting ;AN000; + .IF > THEN ;AN000; + MOV IOCTL0C_data_block.cols,40 ;setup IOCTL input block with the columns requested ;AN000; + .ELSE + MOV IOCTL0C_data_block.cols,80 ;setup IOCTL input block with the columns requested ;AN000; + .ENDIF ;AN000; + CALL old_video_mode_set_IOCTL ;AN004;use IOCTL if possible to retain lines setting ;AN000; + .ELSE + .IF THEN ;IF 40 REQUESTED ;AN000; + MOV BL,40 ;set up for handle_40_or_80 ;AN000; + .ELSE ;AN000; + MOV BL,80 ;set up for handle_40_or_80 ;AN000; + .ENDIF ;AN000; + CALL HANDLE_40_OR_80 ;AN000; + .ENDIF + .ENDIF ;AN000; + .ENDIF + +dummy9: +PUBLIC dummy9 + ;AN000; + POP DI ;restore parm list index ;AN000; + + .IF AND ;process ,r ³ l,[T] ;AN000; + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + ADD DI,TYPE parm_list_entry ;process second parm, shift direction ;AN000; + .IF THEN ;AN000; + .IF OR ;AN000; + .IF THEN ;AN000; + MOV CL,parm_list_BX[DI].item_tag ;AN000; + MOV PARM2,CL ;set up for SHIFT_SCREEN ;AN000; + ADD DI,TYPE parm_list_entry ;look at third parm ;AN000; + MOV CL,parm_list_BX[DI].item_tag ;CL=T_item_tag or bogus ;AN000; + MOV PARM3,CL ;may be bogus, but shift_screen will handle it correctly ;AN000; + CALL SHIFT_SCREEN ;AN000; + .ELSE ;AN000;must be a rows value + .IF THEN ;AN000; +;AC004; MOV need_IOCTL0C,true ;use IOCTL if possible to retain lines setting ;AN000; + MOV DX,parm_list_BX[DI].value1 ;AN000; + MOV IOCTL0C_data_block.rows,DX ;the IOCTL input block has the columns requested ;AN000; + CALL old_video_mode_set_IOCTL ;AN004;use IOCTL if possible to retain lines setting ;AN000; + .ELSE ;AN000;ANSI not installed ;AN000; + DISPLAY ANSI_not_loaded ;AN000; + MOV noerror,false ;AN000; + .ENDIF ;AN000;ANSI installed ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + ;AN000; + BREAK 0 ;AN000; + + + ;AN000; +PUBLIC printer_reroute_case + ;AN000; + printer_reroute_case: + ;INPUT:lptno=zero based printer number OUTPUT:;AH=printer number mask: lpt1=1, lpt2=2, lpt3=4 ;AN000; + ;device=COM number in ASCII form ;SI=printer number value (one based) ;AN000; + ;AL=com number character ;AN000; + XOR CX,CX + MOV CL,lptno ;lptno always <= 255 + MOV SI,CX ;SI=zero based printer number (0, 1, or 2) ;AN000; + INC SI ;SI=one based printer number (1, 2, or 3) ;AN000; + MOV AH,1 ;AN000; + SAL AH,CL ;AH=2**SI,AH=printer number mask for MODEECHO ;AN000; + MOV DH,CL + ADD DH,ASCII_1 ;DH=ASCII printer number ;AN000; + MOV AL,device ;AL=ASCII form of com device number ;AN000; + MOV REDPT,DH ;PUT n OF LPTn IN REDIRECT MESSAGE + MOV NOTREDPT,DH ;AND INTO NOT REDIRECTED MSG + CALL modeecho ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + ;AN000; + printer_status_case: ;AN000; + +PUBLIC printer_status_case + + ; INPUT: device_type = LPTx + ; device = ASCII printer number + ; lptno = ASCII printer number + ; device_name = offset of printer string + ;AN000; + + MOV cp_cb.request_typ,status ;AN000; + MOV AX,device_name ;AN000; + MOV stat_dev_ptr,AX ;AC665;set up msg ser input ;AN000; + MOV dev_name_size,len_LPTX_str ;AN000;set up for msg service, see MODEPARS.ASM ;AN000; + MOV cp_cb.cp_device,AX ;AN665;set up for call to modecp ;AN000; + ;AN000; + .IF > THEN ;AN000; + MOV device_request,lpt1_retry_type_status ;AN000; + MOV rerouted_printer_mask,LPT1 + MOV redpt,"1" ;set up for reroute message + MOV notredpt,"1" ;set up for not rerouted message + .ELSEIF > THEN ;AN000; + MOV device_request,lpt2_retry_type_status ;AN000; + MOV rerouted_printer_mask,LPT2 + MOV redpt,"2" ;set up for reroute message + MOV notredpt,"2" ;set up for not rerouted message + .ELSEIF > THEN ;AN000; + MOV device_request,lpt3_retry_type_status ;AN000; + MOV rerouted_printer_mask,LPT3 + MOV redpt,"3" ;set up for reroute message + MOV notredpt,"3" ;set up for not rerouted message + .ENDIF ;AN000; + ;AN000; + PUSH ES ;save ES, used in MODECP ;AC002; +;AC002;PUSH AX ;AN000;save + ;AN000; + display status_for_device ;AN000; + display long_underline "Status for device LPTX?" ;AN000; + display five_char_underline ;has CRLF on it ----------------------- ;AN000; + call display_printer_reroute_status ;see modeecho.asm ;AN000; +;AC002;POP AX ;restore "device_request" ;AN000; + XOR CX,CX ;initialize prn_ports_attached ;AN000; + CALL check_prn_ports_attached ;return number of printer cards in prn_ports_attached ;AN000; + POP ES ;restore ES ;AC002; + ADD prn_ports_attached,ASCII_0 ;CX=ASCII form of last printer number ;AN000; + .IF THEN ;IF the printer exists THEN ;AN000; + call get_device_retry_type ;AN000; + display retry_equal ;AN000; + CALL modecp ;display codepage status ;AN000; + .ENDIF ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; +;m ;AN000; + set_con_features_case: ;the command line was nothing but con keywords ;AN000; + ;AN000; + ;first see if ANSI.SYS is loaded ;AN000; + CALL check_ANSI_installed ;AC001; + .IF THEN ;AC001; + MOV CL,get_current_settings ;AN000; + CALL do_IOCTL0C ;get current settings of CON ;AN000; + ;MOV SI,OFFSET IOCTL0C_data_block ;set up IOCTL0C, addressablitiy to the IOCTL data block ;AN000; + ;AN000; + MOV IOCTL0C_data_block.mode,text ;AN000; + ;AN000; + .ENDIF ;ANSI.SYS installed ;AN000; + ;AN000; + MOV BX,parm_list_holder ;restore parm_list_BX ;AN000; + ADD DI,TYPE parm_list_entry ;skip CON parm ;AN000; + .WHILE DO NEAR ;the entry after the last has parm_type of bogus ;AN000; + ;AN000; + ;CASE parm_list_BX[DI].keyword_switch_ptr= ;AN000; + ;AN000; + ;AN000; + ;LINES_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV DX,parm_list_BX[DI].value1 ;AN000; + MOV IOCTL0C_data_block.rows,DX ;the IOCTL input block has the columns requested ;AN000; + MOV need_IOCTL0C,true ;AN000; + BREAK 1 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;COLUMNS_equal: ;the value is binary ;AN000; + ;AN000; + .IF > OR ;AN000; + .IF > THEN ;AN000; + ;AN000; + .IF THEN ;AN000; + MOV need_IOCTL0C,true ;use IOCTL if possible to retain lines setting ;AN000; + MOV DX,parm_list_BX[DI].value1 ;AN000; + MOV IOCTL0C_data_block.cols,DX ;the IOCTL input block has the columns requested ;AN000; + .ELSE + .IF THEN ;IF 40 REQUESTED ;AN000; + MOV columns_specified,40 ;set up for handle_40_or_80 ;AN000; + .ELSE ;AN000; + MOV columns_specified,80 ;set up for handle_40_or_80 ;AN000; + .ENDIF ;AN000; + .ENDIF + BREAK 1 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;RATE_equal: ;AN000; + ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV AL,BYTE PTR parm_list_BX[DI].value1 ;save the rate requested in binary form, always <255 ;AN000; + MOV rate_holder,AL ;AN000; + MOV need_typamat_call,true ;AN000; + BREAK 1 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ;AN000; + ;DELAY_equal: ;AN000; + ;AN000; + .IF > OR ;AN000; + .IF > THEN ;AN000; + ;AN000; + MOV AL,BYTE PTR parm_list_BX[DI].value1 ;save delay requested (binary), always <255 ;AN000; + MOV delay_holder,AL ;AN000; + MOV need_typamat_call,true ;AN000; + BREAK 1 ;AN000; + ;AN000; + .ENDIF ;AN000; + ;AN000; + ENDCASE_1: ;AN000; + ;AN000; + ADD DI,TYPE parm_list_entry ;address next parm ;AN000; + ;AN000; + .ENDWHILE ;AN000; + ;AN000; +DUMMY3: ;AN000; +PUBLIC DUMMY3 ;AN000; + ;AN000; + .IF THEN ;AN000; + .IF THEN ;AN000; + MOV CL,set_display_characteristics ;AN000; + CALL do_IOCTL0C ;AN000; + .IF C THEN ;AN000; + get_extended_error ;AN000; + .IF THEN ;AN000; + DISPLAY Function_not_supported ;AN000; + .ELSEIF THEN ;AN000; + DISPLAY Required_font_not_loaded ;AN000; + .ENDIF ;AN000; + MOV noerror,false ;AN000; + .ENDIF ;AN000; + .ELSE ;AN000; + DISPLAY ANSI_not_loaded ;AN000; + MOV noerror,false ;AN000; + .ENDIF ;AN000; + .ELSEIF THEN ;AN000; + MOV BL,columns_specified ;set up for call to handle_40_or_80 ;AN000; + CALL HANDLE_40_OR_80 ;AN000; + .ENDIF ;AN000; + + .IF THEN ;AN000; + MOV BL,rate_holder ;AN000; + MOV BH,delay_holder ;AN000; + CALL typamat ;AN000; + .ENDIF ;AN000; + ;AN000; + BREAK 0 ;AN000; + ;AN000; + ;AN000; + status_for_everything_case: ;AN000; + ;AN000; + MOV request_type,printer_status ;status routine for printers ;AN000; + MOV device_name,OFFSET LPT1_str ;will display the reroute ;AN000; + CALL analyze_and_invoke ;status for the printer whether ;AN000; + MOV device_name,OFFSET LPT2_str ;it exists or not, so call for ;AN000; + CALL analyze_and_invoke ;all of them ;AN000; + MOV device_name,OFFSET LPT3_str ;AN000; + CALL analyze_and_invoke ;AN000; + ;AN000; + MOV request_type,all_con_status ;AN000; + CALL analyze_and_invoke ;AN000; + + CALL check_com_ports_attached ;return number of com ports in com_ports_attached ;AN000; + + MOV request_type,com_status ;AN000; + MOV CL,com_ports_attached ;AN000; + .FOR i = 1 TO CL ;AN000; + + .SELECT ;AN000; + + .WHEN ;AN000; + MOV device_name,OFFSET COM1_str ;AN000; ;AN000; + + .WHEN ;AN000; + MOV device_name,OFFSET COM2_str ;AN000; + + .WHEN ;AN000; + MOV device_name,OFFSET COM3_str ;AN000; + + .WHEN ;AN000; + MOV device_name,OFFSET COM4_str ;AN0;AN000; + + .ENDSELECT ;AN000; + + CALL analyze_and_invoke ;AN000; ;AN000; + .NEXT i ;AN000; + + BREAK 0 ;AN000; + + + + turn_off_reroute_case: ;user specified only LPTx[:] ;AN000; + ;INPUT:lptno=ASCII printer number + + + + CALL modeecno ;turn off rerouting ;AN000; + XOR CX,CX ;initialize prn_ports_attached + CALL check_prn_ports_attached ;return number of printer cards in prn_ports_attached + ADD prn_ports_attached,ASCII_0 ;CX=ASCII form of last printer number + .IF THEN ;IF the printer exists THEN + CALL set_retry_type ;turn off infinit retry ;AN000; + CALL modify_resident_code ;modify resident code to reflect retry turned off ;AN000; + .ENDIF + + BREAK 0 ;AN000; + + ;AN000; +ENDCASE_0: ;AN000; + ;AN000; +RET ;AN000; + ;AN000; +analyze_and_invoke ENDP ;AN000; + ;AN000; + ;AN000; +PRINTF_CODE ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/CMD/MODE/MAIN.ASM b/v4.0/src/CMD/MODE/MAIN.ASM new file mode 100644 index 0000000..73acd7f --- /dev/null +++ b/v4.0/src/CMD/MODE/MAIN.ASM @@ -0,0 +1,168 @@ +;m + PAGE ,132 ; + TITLE MODE COMMAND - MAIN PROCEDURE AND COMMAND PARSING +.XLIST + INCLUDE STRUC.INC +.LIST +;.SALL + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +; AC001 - P3976: Need to have all pieces of messages in MODE.SKL so have to +; implement the SYSGETMSG method of getting addressability to +; the pieces. This means that the code does a SYSGETMSG call +; which returns a pointer (DS:SI) to the message piece. The +; address is then put in the sublist block for the message +; being issued. + +; AN002 - P4011: Need to close all open handles before terminating and staying +; resident so don't eat into the total available handles for the +; system. +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +INCLUDE SYSMSG.INC + +MSG_UTILNAME + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +false EQU 00H +STDIN EQU 0 ;AN002;handle for standard input device +STDPRN EQU 4 ;AN002;handle for standard printer device +TERMINATE EQU 4CH ;INT 21 "TERMINATE RETURNING CODE" FUNCTION +terminate_and_stay_resident EQU 31H ;INT 21 "terminate and remain resident" +truu EQU 0FFH + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ S T R U C T U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ S T R U C T U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + + PAGE +PRINTF_CODE SEGMENT PUBLIC + ASSUME CS:PRINTF_CODE,DS:PRINTF_CODE,SS:PRINTF_CODE + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +PUBLIC main +PUBLIC SYSDISPMSG +PUBLIC SYSGETMSG + + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +EXTRN analyze_and_invoke:NEAR +EXTRN get_machine_type:NEAR ;get model and sub-model bytes +EXTRN initialize_sublists:NEAR ;see display.asm +EXTRN move_destination:ABS ;location of res code after it has been moved +EXTRN noerror:BYTE +EXTRN parse_parameters:NEAR +EXTRN PRINTF:NEAR +EXTRN rescode_length:ABS ;length in paragraphs of the resident code +EXTRN stay_resident:BYTE ;boolean indicating just loaded resident code see 'rescode' + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + + + DB "The MODE command " + DB "--------------------------------------------------------------" + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O C E D U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +close_handles PROC NEAR ;AN002;close all standard device handles + ;AN002; +MOV AH,3EH ;AN002; + ;AN002; +.FOR BX = STDIN TO STDPRN ;AN002; + INT 21H ;AN002; +.NEXT BX ;AN002; + ;AN002; +RET ;AN002; + ;AN002; +close_handles ENDP ;AN002; + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O C E D U R E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +; +;------------------------------------------------------------------------------- + +MSG_SERVICES ;define message service data area + +MSG_SERVICES ;AC001; +MSG_SERVICES ;class B is for messages > 30 +;;RPS MSG_SERVICES + + +main PROC NEAR + +CALL SYSLOADMSG ;load the message text +.IF NC THEN ;IF messages loaded successfully THEN + CALL get_machine_type + CALL initialize_sublists + CALL parse_parameters + .IF THEN ;no problems parsing so continue + CALL analyze_and_invoke ;semantically analyze the parms and invoke appropriate routine + .ENDIF + + MOV AH,TERMINATE ;assume won't stay resident + .IF THEN + MOV AL,1 ;had a problem somewhere + .ELSE + .IF THEN + CALL close_handles ;close all standard devices;AN002; + MOV DX,move_destination + MOV CL,4 ;4 right shifts = divide by 16 + SAR DX,CL ;DX=offset of start of resident code in paragraphs + ;SET END OF RESIDENT CODE FOR "terminate and remain resident" + ;TO first usable + ADD DX,rescode_length ;BYTE OF PROGRAM segment PREFIX + MOV AH,terminate_and_stay_resident + .ENDIF + MOV AL,0 ;all went well + .ENDIF +.ELSE ;ABORT + + CALL SYSDISPMSG ;display some "I'm crashing" message + +.ENDIF + + +INT 21H ;TERMINATE RETURNING ERRORLEVEL INDICATING success +RET + +include msgdcl.inc + +main ENDP + +PRINTF_CODE ENDS + END diff --git a/v4.0/src/CMD/MODE/MAKEFILE b/v4.0/src/CMD/MODE/MAKEFILE new file mode 100644 index 0000000..0e059d8 --- /dev/null +++ b/v4.0/src/CMD/MODE/MAKEFILE @@ -0,0 +1,130 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: mode.com + +mode.ctl: mode.skl \ + makefile \ + $(msg)\$(COUNTRY).msg + + +main.obj: main.asm \ + makefile \ + $(inc)\copyrigh.inc \ + $(inc)\versiona.inc \ + $(inc)\struc.inc \ + $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm \ + mode.ctl \ + mode.cl1 \ + mode.cl2 \ + mode.cla \ + mode.clb + +scrntab.obj: scrntab.asm \ + makefile + +modescrn.obj: modescrn.asm \ + makefile \ + $(inc)\struc.inc + +rescode.obj: rescode.asm \ + makefile \ + $(inc)\struc.inc + +modecom.obj: modecom.asm \ + makefile \ + $(inc)\struc.inc \ + modequat.inc \ + common.stc + +modeprin.obj: modeprin.asm \ + makefile \ + $(inc)\struc.inc + +modevid.obj: modevid.asm \ + makefile \ + $(inc)\struc.inc + +modeecho.obj: modeecho.asm \ + makefile \ + common.stc \ + $(inc)\struc.inc + +modeleng.obj: modeleng.asm \ + modequat.inc \ + makefile \ + $(inc)\struc.inc + +modemes.obj: modemes.asm \ + makefile \ + $(inc)\msgserv.asm \ + modesubs.inc \ + modedefs.inc \ + modequat.inc \ + common.stc + +display.obj: display.asm \ + makefile \ + common.stc + +typamat.obj: typamat.asm \ + makefile \ + $(inc)\struc.inc \ + modequat.inc + +invoke.obj: invoke.asm \ + makefile \ + $(inc)\struc.inc \ + modequat.inc \ + common.stc + +modepars.obj: modepars.asm \ + makefile \ + $(inc)\struc.inc \ + $(inc)\psdata.inc \ + modequat.inc \ + common.stc + + +parshell.obj: parshell.asm \ + makefile \ + $(inc)\parse.asm + + +modecp.obj: modecp.asm \ + makefile \ + modecpro.inc \ + modecpeq.inc \ + modecpms.inc \ + $(inc)\struc.inc + +mode.com: main.obj \ + makefile \ + scrntab.obj \ + modescrn.obj \ + rescode.obj \ + modecom.obj \ + modeprin.obj \ + modevid.obj \ + modeleng.obj \ + modeecho.obj \ + modecp.obj \ + display.obj \ + typamat.obj \ + invoke.obj \ + parshell.obj \ + modepars.obj \ + modemes.obj \ + mode.lnk + link @mode.lnk + exe2bin mode.exe mode.com + del mode.exe diff --git a/v4.0/src/CMD/MODE/MODE.LNK b/v4.0/src/CMD/MODE/MODE.LNK new file mode 100644 index 0000000..5f49459 --- /dev/null +++ b/v4.0/src/CMD/MODE/MODE.LNK @@ -0,0 +1,17 @@ +/MAP RESCODE+ +MODEECHO+ +MODELENG+ +MODEMES+ +MODESCRN+ +MAIN+ +MODEVID+ +MODEPRIN+ +MODECOM+ +SCRNTAB+ +MODECP+ +DISPLAY+ +TYPAMAT+ +INVOKE+ +PARSHELL+ +MODEPARS,MODE; + \ No newline at end of file diff --git a/v4.0/src/CMD/MODE/MODE.SKL b/v4.0/src/CMD/MODE/MODE.SKL new file mode 100644 index 0000000..b93dfc5 --- /dev/null +++ b/v4.0/src/CMD/MODE/MODE.SKL @@ -0,0 +1,193 @@ +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +; AN001 - P3976: Need to have all pieces of messages in MODE.SKL so have to +; implement the SYSGETMSG method of getting addressability to +; the pieces. This means that the code does a SYSGETMSG call +; which returns a pointer (DS:SI) to the message piece. The +; address is then put in the sublist block for the message +; being issued. + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +:util MODE ;AN000; + ;AN000; +:class 1 ;AN000; + ;AN000; +;:use extend3 ;AN000; +;:use extend15 ;AN000; + ;AN000; +:class 2 ;AN000; + ;AN000; +;:use parse1 ;AN000; +;:use parse3 ;Invalid switch +;:use parse7 ;AN000; +;:use parse8 ;AN000; + ;AN000; + ;AN000; +:class A ;Transient messages, all MODE's messages are transient ;AN000; + ;AN000; +:use 1 COMMON1 ;"Incorrect DOS Version" ;AN000; +:use 2 extend1 ;AN000; +:def 3 CR,LF,"Must specify COM1, COM2, COM3 or COM4",CR,LF ;AN000; +:def 4 CR,LF,"Resident portion of MODE loaded",CR,LF ;AN000; +:def 5 CR,LF,"Illegal device name",CR,LF ;AN000; +:def 6 CR,LF,"Printer error",CR,LF ;AN000; +:def 7 CR,LF,"LPT%1: set for 80",CR,LF ;AN000; +:def 8 CR,LF,"LPT%1: set for 132",CR,LF ;AN000; +:def 9 CR,LF,"Printer lines per inch set",CR,LF ;AN000; +:def 10 CR,LF,"Invalid baud rate specified",CR,LF ;AN000; +:def 11 CR,LF,"COM%1: %2,%3,%4,%5,%6",CR,LF ;AN000; +; DEVICE - 1, 2, 3 or 4 ;AN000; +; BAUD - 110, 150, 300, 600, 1200, 2400, 4800, 9600 etc. ;AN000; +; PARITY - n, o, e etc ;AN000; +; DATA - 5, 6, 7, or 8 ;AN000; +; STOP - 1, 1.5 or 2 ;AN000; +; P - old retry indication ;AN000; +:def 12 "0123456789" ;AN000; +:def 13 CR,LF,"Do you see the %1? (YES/NO)",CR,LF ;AN000; + ;"rightmost 9?" ;goes at the end of "Do you see the" ;AN000; + ;"leftmost 0?" ;goes at the end of "Do you see the" ;AN000; +; Fourteen used to be "Invalid parameters", now use message 54 for those cases. +:def 15 "LPT%1: rerouted to COM%2:",CR,LF ;AN000; +:def 16 "LPT%1: not rerouted",CR,LF ;AN000; +:def 17 CR,LF,"%1 retry on parallel printer time-out",CR,LF ;AN000; +; ONE OF THE FOLLOWING TWO WORDS IS INSERTED: ;AN000; + ;"No" ;goes before "retry on parallel printer time-out" ;AN000; + ;"Infinite" ;goes before "retry on parallel printer time-out" ;AN000; +:def 18 CR,LF," Unable to shift screen %1",CR,LF ;AN000; + ;"left" ;goes at the end of "Unable to shift screen" ;AN000; + ;"right" ;goes at the end of "Unable to shift screen" ;AN000; +; ;The offending_parameter is determined by parsing logic ;AN000; +:use 19 PARSE10 ;"Invalid parameter - %1",CR,LF ;AN000; +:def 20 CR,LF,"Invalid number of parameters",CR,LF ;AN000; +:def 21 CR,LF,"NET 042: Unable to do requested command",CR,LF ;AN000; +:def 22 CR,LF,"Infinite retry not supported on Network printer",cr,lf ;AN000; +:def 23 CR,LF,"Failure to access code page Font File",CR,LF ;AN000; + ;%1 FILLED IN WITH PTR TO DEVICE NAME ;AN000; +:def 24 CR,LF,"Failure to access device: %1",CR,LF ;AN000; +:def 25 CR,LF,"Device or code page missing from font file",CR,LF ;AN000; +:def 26 CR,LF,"Font file contents invalid",CR,LF ;AN000; +:def 27 CR,LF,"Previously prepared code page replaced",CR,LF ;AN000; +:def 28 CR,LF,"Active code page for device %1 is %2",CR,LF ;AN000; + ;%1 FILLED IN BY "QUERY" ROUTINE WITH PTR TO DEVICE NAME ;AN000; + ;%2 FILLED IN BY "QUERY" ROUTINE WITH CODEPAGE ID ;AN000; +:def 29 CR,LF,"Device %1 not prepared",CR,LF ;AN000; + ;FILLED IN BY "QUERY" ROUTINE WITH PTR TO DEVICE NAME ;AN000; + ;"hardware" ;used before "codepages:" ;AN000; + ;"prepared" ;AN000; + ;AN000; +:class B ;nothing special, just too many messages for one class ;AN000; + ;AN000; +:def 30 "%1 code pages:",CR,LF ;AN000; +:def 31 " code page %1",CR,LF ;FILLED IN BY "QUERY" ROUTINE WITH CODEPAGE ID ;AN000; +:def 32 CR,LF,"MODE %1 code page function completed",CR,LF ;AN000; + ;FILLED IN with one of: ;AN000; + ; "Status" ;AN000; + ; "Prepare" ;AN000; + ; "Select" ;AN000; + ; "Refresh" ;AN000; + ;AN000; +:def 33 CR,LF,"Current code page settings:",CR,LF ;table header ;AN000; + ;AN000; +:def 34 " %1 - %2 code page",CR,LF ;AN000; + ;%1 FILLED IN WITH CODEPAGE ID ;AN000; + ;%2 FILLED IN TO POINT TO "Selected" or "System". ;AN000; + ;AN000; +:def 35 " Code page not prepared",CR,LF ;AN000; +:def 36 "Code page operation not supported on this device",CR,LF ;AN000; + ;AN000; +:def 37 "No code page has been SELECTED",CR,LF ;AN000; + ;AN000; +:def 38 "Device error during %1",CR,LF ;AN000; + ;FILLED IN TO POINT TO: ;AN000; +; "Status" ;AN000; +; "Prepare" ;AN000; +; "Select" ;AN000; +; "Refresh" ;AN000; +; "write of font file to device" ;AN000; + ;AN000; +:def 39 "code page not prepared",CR,LF ;AN000; + ;AN000; +:def 40 CR,LF,"Current keyboard does not support this code page",CR,LF ;AN000; + ;AN000; +:def 41 CR,LF,"Error during read of font file",CR,LF ;AN000; + ;AN000; +:def 42 CR,LF,"Unable to perform REFRESH operation",CR,LF ;AN000; + ;AN000; +:use 43 COMMON38 ;used for formatting common messages for consistent spacing ;AN000; + ;AN000; +:def 44 CR,LF,"Status for device %1:",CR,LF ;header for status reports ;AN000; + ;AN000; +:def 45 "------------------" ;first part of underline under "Status for device %1:" ;AN000; + ;AN000; +:def 46 "----",CR,LF ;four_char_underline ;AN000; + ;AN000; +:def 47 "-----",CR,LF ;five_char_underline ;AN000; + ;AN000; +:def 48 "LINES=%1",CR,LF ;AN000; + ;AN000; +:def 49 "COLUMNS=%1",CR,LF ;AN000; + ;AN000; +:def 50 CR,LF,"RATE and DELAY must be specified together",CR,LF ;AN000; + ;AN000; +:def 51 "RATE=%1",CR,LF ;AN000; + ;AN000; +:def 52 "DELAY=%1",CR,LF ;AN000; + ;AN000; +:def 53 CR,LF,"Function not supported on this computer - %1",CR,LF ;AN000; + ;AN000; +:def 54 CR,LF,"Required font not loaded",CR,LF ;AN000; + ;AN000; +:def 55 CR,LF,"ANSI.SYS must be installed to perform requested function",CR,LF ;AN000; + ;AN000; +:def 56 CR,LF,"Baud rate required",CR,LF ;AN000; + ;AN000; +:def 57 "RETRY=%1",CR,LF ;AN000; + ;AN000; +:use 58 PARSE9 ;"Syntax error - ???????",CR,LF ;AN000; + + +;Following are the definitions of pieces of messages. + + ;AN000; +;SHIFT_MSG - CR,LF,"Do you see the %s? (",YES,"/",NO,")",CR,LF,EOM + +:def 59 "rightmost 9",0 ;AN001;RIGHTMOST DB +:def 60 "leftmost 0",0 ;AN001;LEFTMOST DB + +;RETPARTO - CR,LF,"%s retry on parallel printer time-out",CR,LF,EOM + +:def 61 "No",0 ;AN001;NORETRY DB +:def 62 "Infinite",0 ;AN001;INFINITE DB + +;CANT_SHIFT - CR,LF," Unable to shift screen %s",CR,LF,BEEP,EOM + +:def 63 "left",0 ;AN001;LEFT DB +:def 64 "right",0 ;AN001;RIGHT DB + +;CPMSG8 DB "%S code pages:",CR,LF,EOM + +:def 65 "Hardware",0 ;AN001;CPMSG8_HW DB +:def 66 "Prepared",0 ;AN001;CPMSG8_PR DB + +;CPMSG10 DB "MODE %S code page function completed",CR,LF,EOM +;CPMSG17 DB "Device error during %S",BEEP,CR,LF,EOM + +:def 67 "status",0 ;AN001;CPMSG17_QUERY CPMSG10_QUERY +:def 68 "prepare",0 ;AN001;CPMSG17_PREP CPMSG10_DES +:def 69 "select",0 ;AN001;CPMSG17_ACT CPMSG10_SELECT +:def 70 "refresh",0 ;AN001;CPMSG17_REFRESH CPMSG10_REFRESH + +;CPMSG17 DB "Device error during %S",BEEP,CR,LF,EOM + +:def 71 "write of font file to device",0 ;AN001;CPMSG17_WRIT + +;CPMSG13 DB " %D - %S code page",CR,LF,EOM + +:def 72 "selected",0 ;AN001;CPMSG13_ACT +:def 73 "system",0 ;AN001;CPMSG13_SYS + +:end ;AN000; diff --git a/v4.0/src/CMD/MODE/MODECOM.ASM b/v4.0/src/CMD/MODE/MODECOM.ASM new file mode 100644 index 0000000..7ab77f0 --- /dev/null +++ b/v4.0/src/CMD/MODE/MODECOM.ASM @@ -0,0 +1,592 @@ +PAGE ,132 ; ;AN000; +TITLE MODECOM.ASM - RS232 SUPPORT FOR THE MODE COMMAND ;AN000; + ;AN000; +.XLIST ;AN000; +INCLUDE STRUC.INC ;AN000; +.LIST ;AN000; + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +; AC000 - P2852: Loading resident code trashed CX which was used as a shift +; count. + +; AC001 - P3540: PS/2 only parms other than baud not being treated properly. + +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P R O L O G ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +DISPLAY MACRO MESSAGE ;AN000; + MOV DX,OFFSET MESSAGE ;AN000; + CALL PRINTF ;AN000; +ENDM ;AN000; + ;AN000; +;------------------------------------------------------------------------ ;AN000; + ;AN000; +ABORT MACRO ;AN000; + JMP ENDIF01 ;AN000; +ENDM ;AN000; + ;AN000; + ;AN000; +;------------------------------------------------------------------------ ;AN000; + ;AN000; +INCLUDE common.stc ;contains the following structure ;AN000; + ;AN000; + ;AN000; +;parm_list_entry STRUC ;used by parse_parameters and invoke ;AN000; +; ;AN000; +;parm_type DB bogus ;AN000; +;item_tag DB 0FFH ;AN000; +;value1 DW bogus ;used only for filespecs and code page numbers ;AN000; +;value2 DW bogus ;used only for filespecs and code page numbers ;AN000; +;keyword_switch_ptr DW 0 ;AN000; +; ;AN000; +;parm_list_entry ENDS ;AN000; + ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; + +INCLUDE modequat.inc ;AN000;include definition of false, machine types + + ;AN000; +AT_family EQU 0FCH ;model byte for 286 boxes ;AN000; +DEV1 EQU "1" ;CHAR IN "COM1:" ;AN000; +DEV2 EQU "2" ;CHAR IN "COM2:" ;AN000; +DEV3 EQU "3" ;CHAR IN "COM3:" ;AN000; +DEV4 EQU "4" ;CHAR IN "COM4:" ;AN000; +OFFTO EQU modeto ;OFFSET OF MODETO IN RESIDENT CODE FROM SEGMENT ;AN000; + ; STORED AT 530H BY MODELOAD ;AN000; +not_specified EQU 0 ;AN000; +parm_list EQU [BP] ;AN000; +;Roughrider EQU 05 ;sub model byte ;AN000; +SPACE EQU " " ;BLANK CHARACTER ;AN000; +;Trailboss EQU 04 ;sub model byte for 'Trailboss' ;AN000; +true EQU 0FFH ;AN000; +;Wrangler EQU 0F8H ;primary model byte ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E Q U A T E S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + + ; BEGINNING OF PROC MODETO) ;AN000; +ROM SEGMENT AT 0 ;AN000; + ORG 50H ;AN000; +VECT14H LABEL DWORD ;RS232 CALL, POINTS TO PROC MODETO WHEN ;AN000; + ; WHEN CODE IS RESIDENT ;AN000; + ORG 400H ;AN000; +SERIAL_BASE LABEL WORD ;SERIAL PORT ADDRESSES ;AN000; + ORG 530H ;AN000; +RESSEG LABEL DWORD ;VECTOR OF MODETO, WHEN RESIDENT ;AN000; +ROM ENDS ;AN000; +PAGE ;AN000; +PRINTF_CODE SEGMENT PUBLIC ;AN000; + ASSUME CS:PRINTF_CODE,DS:PRINTF_CODE ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +EXTRN B_item_tag:ABS ;see modepars ;AN000; +EXTRN baud_19200:BYTE ;AN000; +EXTRN busy_retry_active:ABS ;see invoke.asm ;AN000; +EXTRN E_item_tag:ABS ;see modepars ;AN000; +EXTRN eight_item_tag:ABS ;see modepars ;AN000; +EXTRN ERR1:WORD ;AN000; +EXTRN even_item_tag:ABS ;see modepars ;AN000; +EXTRN error_retry_active:ABS ;see invoke.asm ;AN000; +EXTRN five_item_tag:ABS ;see modepars ;AN000; +EXTRN fourtyeighthundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN fourtyeighthundred_str:BYTE ;AN000; +EXTRN illegal_device_ptr:WORD ;see modesubs.inc ;AN000; +EXTRN INITMSG:BYTE,DEVICE:BYTE,PPARITY:BYTE,PDATA:BYTE,PSTOP:BYTE,PPARM:BYTE ;AN000; +EXTRN keyword:ABS ;AN000; +EXTRN machine_type:BYTE ;see 'rescode' ;AN000; +EXTRN mark_item_tag:ABS ;see modepars ;AN000; +EXTRN MODELOAD:NEAR ;AN000; +EXTRN MODETO:WORD ;AN000; +EXTRN new_com_initialize:BYTE ;flag indicating that a PS/2 only parm was specified ;AC001; +EXTRN nineteentwohundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN nineteentwohundred_str:BYTE ;see modepars.asm ;AN000; +EXTRN ninetysixhundred_item_tag:ABS ;AC001; +EXTRN ninetysixhundred_str:BYTE ;AN000; +EXTRN no_retry_active:ABS ;see invoke.asm ;AN000; +EXTRN noerror:byte ;boolean indicating success of previous actions ;AN000; +EXTRN none_item_tag:ABS ;see modepars ;AN000; +EXTRN onefifty_str:BYTE ;AN000; +EXTRN oneten_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN oneten_str:BYTE ;AN000; +EXTRN onefifty_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN one_point_five_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN one_point_five_str:BYTE ;see modesubs.inc ;AN000; +EXTRN p_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN parm_lst:BYTE ;parm_list_entry max_pos_parms DUP (<>) ;AN000; +EXTRN parms_form:BYTE ;AN000; +EXTRN pstop_ptr:WORD ;see modedefs.inc ;AN000; +EXTRN odd_item_tag:ABS ;see modepars ;AN000; +EXTRN one_item_tag:ABS ;see modepars ;AN000; +EXTRN PBAUD_ptr:WORD ;see 'modemes' ;AN000; +EXTRN PRINTF:NEAR ;AN000; +EXTRN PARM1:BYTE,PARM2:BYTE,PARM3:BYTE,MODE:BYTE,FLAG:BYTE ;AN000; +;PARM1 DB 10 DUP(0) ;AN000; +;PARM2 DB 0 ;AN000; +;PARM3 DB 0 ;AN000; +;MODE DB 0 ;AN000; +;FLAG DB 0 ;AN000; +EXTRN R_item_tag:ABS ;AN000; +EXTRN RATEMSG:WORD ;CR,LF,"Invalid baud rate specified",BEEP,CR,LF,"$" ;AN000; +EXTRN ready_retry_active:ABS ;see invoke.asm ;AN000; +;EXTRN RES_MODEFLAG:ABS ;RETRY FLAG IN RESIDENT CODE, (OFFSET FROM ;AN000; +EXTRN res_com_retry_type:ABS ;retry type flag, displacement from address pointed to by 50:30 when code is resident, see rescode +EXTRN seven_item_tag:ABS ;see modepars ;AN000; +EXTRN sixhundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN sixhundred_str:BYTE ;AN000; +EXTRN six_item_tag:ABS ;see modepars ;AN000; +EXTRN space_item_tag:ABS ;see modepars ;AN000; +EXTRN submodel_byte:BYTE ;see 'rescode' ;AN000; +EXTRN threehundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN threehundred_str:BYTE ;AN000; +EXTRN twelvehundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN twelvehundred_str:BYTE ;AN000; +EXTRN twentyfourhundred_str:BYTE ;AN000; +EXTRN twentyfourhundred_item_tag:ABS ;see modepars.asm ;AN000; +EXTRN two_item_tag:ABS ;see modepars ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; +PUBLIC baud_index ;holder of the index in the parm list of the baud rate requested ;AN000; +PUBLIC data_bits_index ;set by invoke ;AN000; +PUBLIC MODECOM ;AN000; +PUBLIC parity_index ;set by invoke ;AN000; +PUBLIC SERIAL_BASE ;Make available to RESCODE and MAIN ;AN000; +PUBLIC retry_index ;make available to analyze_and_invoke ;AN000; +PUBLIC setcom ;get it listed in the link map ;AN000; +PUBLIC setto ;get it listed in link map for debugging ;AN000; +PUBLIC stop_bits_index ;set by invoke ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; + ;AN000; +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; +;º º ;AN000; + ;AN000; + ;AN000; +;THESE FOLLOWING BAUD RATES REPRESENT THE 1ST 2 CHAR ;AN000; +baud_index DW TYPE parm_list_entry ;holder of the index into the parm list of the baud rate ;AN000; +data_bits_index DW 0 ;holder of the index into the parm list of the data bits ;AN000; +parity_index DW 0 ;holder of the index into the parm list of the parity ;AN000; +stop_bits_index DW 0 ;holder of the index into the parm list of the stop bits ;AN000; +retry_index DW 0 ;AN000; + ;AN000; +;INITMSG DB CR,LF ;AN000; +; DB "COM" ;AN000; +;DEVICE DB " " ;AN000; +; DB ": " ;SEPARATOR BLANK ;AN000; +;PBAUD DB 4 DUP(" ") ;AN000; +; DB "," ;SEPARATOR ;AN000; +;PPARITY DB "e" ;DEFAULT IS EVEN PARITY ;AN000; +; DB "," ;SEPARATOR ;AN000; +;PDATA DB "7" ;DEFAULT IS 7 DATA BITS PER BYTE ;AN000; +; DB "," ;SEPARATOR ;AN000; +;PSTOP DB "1" ;DEFAULT FOR BAUD > 110, CHANGED TO 2 FOR 110 ;AN000; +; DB "," ;SEPARATOR ;AN000; +;PPARM DB " " ;AN000; +; DB CR,LF,"$" ;END OF 'INITMSG' ;AN000; + ;AN000; + ;AN000; +;º º ;AN000; +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; + ;AN000; + ;AN000; +SUBTTL SET UP FOR SERIAL RETRY ;AN000; +PAGE ;AN000; +; +; +;------------------------------------------------------------------------------- +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ ³ +;³ SETTO ³ +;³ ----- ³ +;³ ³ +;³ Set the resident retry flag to type of retry active for comx. ³ +;³ ³ +;³ INPUT: device - holds '1', '2', '3' or '4' (ascii) for x of lptx. ³ +;³ retry_index - holds index value for the parsed retry parameter. ³ +;³ resseg - holds offset of resident code in memory ³ +;³ res_com_retry_type - holds offset of com retry flag in resident ³ +;³ code. ³ +;³ ³ +;³ ³ +;³ RETURN: pparm - set to 'P', 'B', 'R', 'E', or '-' for type of retry active.³ +;³ flag in resident code set ³ +;³ ³ +;³ ³ +;³ MESSAGES: none. ³ +;³ ³ +;³ ³ +;³ REGISTER ³ +;³ USAGE: AL - new setting for resident flag. (see RESCODE.SAL for ³ +;³ format) ³ +;³ CL - shift bit count ³ +;³ ES - holds segment of resident code ³ +;³ BP - offset of parameter list ³ +;³ DI - offset of retry index within parameter list ³ +;³ DL - current resident flag setting ³ +;³ ³ +;³ ³ +;³ PSUEDO CODE: ³ +;³ ³ +;³ SAVE REGISTERS ³ +;³ SET UP SEGMENT REGISTER AND BIT MASKS ³ +;³ IF ³ +;³ SET UP PARAMETER LIST STRUCTURE ³ +;³ SET BIT MASK FOR TYPE OF RETRY AND SET pparm TO PROPER LETTER ³ +;³ IF ³ +;³ LOAD RESIDENT CODE ³ +;³ ENDIF ³ +;³ GET CURRENT com_lpt_retry_type ³ +;³ SET AND STORE NEW com_lpt_retry_type ³ +;³ ELSEIF ³ +;³ GET CURRENT com_lpt_retry_type ³ +;³ IF ³ +;³ SET FLAG TO ZERO, SET pparm TO PROPER LETTER ³ +;³ ELSE ³ +;³ SET pparm TO PROPER LETTER FOR CURRENT SETTING ³ +;³ ENDIF ³ +;³ ELSE ³ +;³ SET pparm TO '-' ³ +;³ ENDIF ³ +;³ RESTORE REGISTERS ³ +;³ RETURN ³ +;³ ³ +;³ ³ +;³ ³ +;³ SIDE EFFECT: Loads resident code if it is needed and has not been loaded. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; +SETTO PROC NEAR ;AN663; + ;AN663; + PUSH ES ;save registers ;AN663; + PUSH DI ;AN663; + PUSH AX ;AN663; + PUSH DX ;AN663; + ;AN663; + XOR AX,AX ;clear a reg ;AN663; + MOV ES,AX ;set to segment at 0 ;AN663; + MOV CL,device ;AN663; + AND CL,07H ;AN663; + DEC CL ;AN663; + SHL CL,1 ;AN663; + MOV DH,11111100B ;set bit mask to clear old flag setting ;AN663; + ROL DH,CL ;AN663; + ;AN663; + .IF THEN ;retry specified, set ;AN663; + ; byte in resident code ;AN663; + MOV DI,retry_index ; to proper setting. ;AN663; + ; if code is not loaded, ;AN663; + .SELECT ; loaded it. ;AN663; + .WHEN ;AN663; + MOV AL,busy_retry_active ;AN663; + MOV pparm,'p' ;AN663; + .WHEN ;AN663; + MOV AL,error_retry_active ;AN663; + MOV pparm,'e' ;AN663; + .WHEN ;AN663; + MOV AL,busy_retry_active ;AN663; + MOV pparm,'b' ;AN663; + .WHEN ;AN663; + MOV AL,ready_retry_active ;AN663; + MOV pparm,'r' ;AN663; + .ENDSELECT ;AN663; + ;AN663; + .IF < EQ 0000H> THEN ;AN663; + PUSH CX ;save shift count + CALL modeload ;load the resident code ;AN663; + POP CX ;restore shift count + .ENDIF ;AN663; + ;AN663; + MOV ES,ES:WORD PTR resseg[2] ;AN663; + MOV DL,BYTE PTR ES:res_com_retry_type ;AN663; + ;get the old setting ;AN663; + ROL AL,CL ;AN663; + AND DL,DH ;AN663; + OR DL,AL ;AN663; + MOV BYTE PTR ES:res_com_retry_type,DL ;store the new setting ;AN663; + ;AN663; + .ELSEIF < NE 0000H> THEN ;if code is loaded but no ;AN663; + ; retry is specified then ;AN663; + MOV ES,ES:WORD PTR resseg[2] ;AN663; + MOV DL,BYTE PTR ES:res_com_retry_type ;AN663; + ;AN663; + .IF ;if 'NONE' was specified ;AN663; + ; with positional parameter ;AN663; + AND DL,DH ; set bits to zero ;AN663; + MOV BYTE PTR ES:res_com_retry_type,DL ;AN663; + ;AN663; + .ELSE ;else update pparm with ;AN663; + ; current retry type ;AN663; + NOT DH ;AN663; + AND DL,DH ;AN663; + SHR DL,CL ;AN663; + ;AN663; + .SELECT ;set pparm to proper letter ;AN663; + .WHEN
;AN663; + MOV pparm,'-' ;AN663; + .WHEN
;AN663; + MOV pparm,'e' ;AN663; + .WHEN
;AN663; + MOV pparm,'b' ;AN663; + .WHEN
;AN663; + MOV pparm,'r' ;AN663; + .ENDSELECT ;AN663; + ;AN663; + .ENDIF ;AN663; + ;AN663; + .ELSE ;no retry, no code resident ;AN663; + ;AN663; + MOV pparm,'-' ;AN663; + ;AN663; + .ENDIF ;AN663; + ;AN663; + POP DX ;AN663; + POP AX ;restore registers ;AN663; + POP DI ;AN663; + POP ES ;AN663; + RET ;AN663; + ;AN663; +SETTO ENDP ;AN663; + + + +SUBTTL SET SERIAL PROTOCOL +PAGE + +;------------------------------------------------------------------------------ + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ ³ +;³ SETCOM ³ +;³ ------ ³ +;³ ³ +;³ ³ +;³ ³ +;³ INPUT: ³ +;³ ³ +;³ ³ +;³ ³ +;³ ³ +;³ ³ +;³ ³ +;³ RETURN: ³ +;³ ³ +;³ ³ +;³ ³ +;³ MESSAGES: none. ³ +;³ ³ +;³ ³ +;³ REGISTER ³ +;³ USAGE: ³ +;³ ³ +;³ ³ +;³ ASSUMPTIONS: All parms have been checked for validity as being possible and³ +;³ supported on the machine. ³ +;³ ³ +;³ ³ +;³ ³ +;³ SIDE EFFECT: ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +SETCOM PROC NEAR ;AN000; + ;AN000; + ;AN000; +MOV BP,OFFSET parm_lst ;address the parm list via parm_list which is [BP] ;AN000; +MOV DI,baud_index ;DI=index into parm list of the baud rate entry ;AN000; + +.SELECT ;prepare AL for old init and CL for new init ;AC001; + + .WHEN ;AC001; + MOV AL,0 ;AN000; + MOV CL,0 + MOV pbaud_ptr,OFFSET oneten_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,00100000B ;AN000; + MOV CL,1 + MOV pbaud_ptr,OFFSET onefifty_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,01000000B ;AN000; + MOV CL,2 + MOV pbaud_ptr,OFFSET threehundred_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,01100000B ;AN000; + MOV CL,3 + MOV pbaud_ptr,OFFSET sixhundred_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,10000000B ;AN000; + MOV CL,4 + MOV pbaud_ptr,OFFSET twelvehundred_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,10100000B ;AN000; + MOV CL,5 + MOV pbaud_ptr,OFFSET twentyfourhundred_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,11000000B ;AN000; + MOV CL,6 + MOV pbaud_ptr,OFFSET fourtyeighthundred_str ;AN000; + .WHEN THEN ;AN000; + MOV AL,11100000B ;AN000; + MOV CL,7 + MOV pbaud_ptr,OFFSET ninetysixhundred_str ;AN000; + .WHEN NEAR THEN ;handle 19200 case if 19, 19200, 19.2 or 19.2K specified + MOV CL,8 ;value for 19200 baud, no old equivalent ;AC001; + MOV pbaud_ptr,OFFSET nineteentwohundred_str ;AC001; + +.ENDSELECT ;AC001; +; AL IS: XXX00000 for the baud rate, CL has appropriate value for baud + +MOV DI,parity_index ;AN000; +.IF THEN ;AN000; + MOV PPARITY,"n" ;set up message for no PARITY ;AN000; + MOV BH,0 ;AL already set properly for old init ;AN000; +.ELSEIF THEN ;AN000; + MOV PPARITY,"o" ;set up message for odd PARITY ;AN000; + OR AL,08H ;PUT THE 000XX000 BITS TO AL PARM WHERE XX=01 FOR PARITY=ODD ;AN000 + MOV BH,1 ;new initialize ;AN000; +.ELSEIF THEN ;AN000; + MOV PPARITY,"s" ;set up message for space PARITY ;AN000; + MOV BH,4 ;SPACE not supported in old init ;AN000; +.ELSEIF THEN ;AN000; + MOV PPARITY,"m" ;set up message for mark PARITY ;AN000; + MOV BH,3 ;MARK parity not supported in old init ;AN000; +.ELSE ;not specified or asked for even ;AN000; + MOV PPARITY,"e" ;set up message for even PARITY, the default if not specified ;AN000; + OR AL,18H ;PUT THE 000XX000 BITS TO AL PARM WHERE XX=11 FOR PARITY=EVEN ;AN000 + MOV BH,2 ;even parity for new initialize ;AN000; +.ENDIF ;AN000; + +MOV DI,data_bits_index ;AN000; +.IF THEN ;AN000; + MOV pdata,"5" ;set up message for 5 bits ;AN000; + MOV CH,0 ;not old init for 5 data bits ;AN000; +.ELSEIF THEN ;AN000; + MOV pdata,"6" ;set up message for 6 bits ;AN000; + MOV CH,1 ;no old init for 6 data bits ;AN000; +.ELSEIF THEN ;AN000; + MOV pdata,"8" ;set up message for 8 bits ;AN000; + OR AL,03H ;IN THE 000000XX POSITION, SET XX=11 TO MEAN 8 DATA BITS ;AN000; + MOV CH,3 ;AN000; +.ELSE ;asked for 7 or skipped the parm and will get 7 as default ;AN000; + OR AL,02H ;IN THE 000000XX POSITION, SET XX=10 TO MEAN 7 DATA BITS ;AN000; + MOV CH,2 ;message already set up for 7 bits ;AN000; +.ENDIF ;AN000; + +;PUT THE NO. STOP BITS TO AL PARM IN THE 00000X00 POSITION and BL for new init ;AN000 +MOV DI,stop_bits_index ;AN000; +MOV BL,0 ;assume stop bits was 1, message already set up ;AN000; +.SELECT + ;AN000; + .WHEN ;AN000; + MOV pstop,"2" ;set up message for 2 stop bits ;AN000; + MOV BL,1 ;value for two or 1.5 ;AN000; + + .WHEN ;AN000; ;AN000; + MOV pstop_ptr,OFFSET one_point_five_str ;set up message for 1.5 stop bits ;AN000; + MOV BL,1 ;new init for 1.5 ;AN000; + + .WHEN ;if stop bits not specified ;AN000; + MOV DI,baud_index ;AC000; + .IF ;BAUD=110 SPECIFIED THEN SET DEFAULT STOP BITS TO TWO ;AC000; + OR AL,04H ;TURN ON BIT IN 00000X00 POSITION TO REQUEST 2 STOP BITS ;AN000; + MOV pstop,"2" ;set up message for 2 stop bits ;AN000; + .ENDIF ;FOR STOPBITS=1, LEAVE THAT BIT OFF, message already set by modecom ;AN000; + +; .OTHERWISE specified 1, everything set up + +.ENDSELECT ;IF not 1.5 or two, already set up for 1 ;AN000; + ;AN000; +.IF THEN ;AC001; + XOR AL,AL ;ask for no break ;AN000; + MOV AH,4 ;new set baud BIOS call ;AN001; +.ELSE ;old style com initialization ;AN000; ;AC001; + XOR AH,AH ;AH=0 requests initialization ;AC001; +.ENDIF ;AC001; + + ;AN000; +;SET DX PARM TO REQUEST WHICH COM DEVICE ;AN000; + XOR DX,DX ;AN000; + MOV DL,DEVICE ;device set by modepars in first_parm_case: ;AN000; + AND DL,07 ;convert to binary 1 thru 4 ;AN000; + DEC DL ;put in BIOS digestable 0 thru 3 ;AN000; +; AH ALREADY IS 0 or 4, WHICH REQUESTS ;AN000; +; INITIALIZATION OF THE RS232 ;AN000; +; ACCORDING TO PARMS IN AL and/or BX and CX. ;AN000; + .IF THEN ;AN000; + INT 14H ;INIT THE RS232 ;AN000; +; ;AN000; +; NOW THAT THE RS232 IS INITIALIZED, ;AN000; + CALL SETTO ;LOOK AT P PARM, MAYBE TIMEOUT TO BE RETRIED ;AN000; +; ;AN000; + DISPLAY INITMSG ;TELL USER RS232 IS INITIALIZED ;AN000; + .ENDIF ;AN000; + + RET ;AN000; +SETCOM ENDP ;AN000; + ;AN000; + ;AN000; +SUBTTL ;AN000; +PAGE ;AN000; + ;AN000; + ;AN000; + +MODECOM PROC NEAR + + + MOV AL,DEVICE ;AL= DEVICE ID OF "1", "2", "3" or "4" + AND AL,07 ;TRANSLATE TO BINARY + DEC AL ;PUT IN ZERO BASE + SAL AL,1 ;POSITION OF PORT ADDRESS WORD (2*AL) + XOR AH,AH ;CLEAR AH + MOV SI,AX + XOR AL,AL ;CLEAR AX + PUSH DS + MOV DS,AX + CMP WORD PTR DS:SERIAL_BASE[SI],0 ;SEE IF THE COM PORT EXISTS + POP DS + JNE THEN01A + MOV DI,0 ;the device name is always the first parm ;AN000; + MOV BP,OFFSET parm_lst ;address the parm list via parm_list which is [BP] ;AN000; + MOV CX,parm_list[DI].value1 ;AN000; + MOV illegal_device_ptr,CX + DISPLAY err1 ;AN000;"Illegal device name - COMX" + MOV noerror,false ;AN000; + ABORT +; +THEN01A: + +; DEFINE DEFAULTS: + MOV PSTOP,"1" ;ONE STOP BIT, OK FOR BAUD>110 + MOV PDATA,"7" ;7 DATA BITS + MOV PPARM,"-" ;NO SERIAL TIMEOUT RETRY +; + +;WE HAVE THE INFORMATION NEEDED TO INITIALIZE THE RS232 DEVICE +; + CALL SETCOM ;SET THE RS232 DEVICE +; +; : ELSE ,SINCE COUNT WAS NOT BIG ENUF +ENDIF01: ;jump to here if the port does not exist + RET ;RETURN TO MODE MAIN ROUTINE +MODECOM ENDP +PRINTF_CODE ENDS + END diff --git a/v4.0/src/CMD/MODE/MODECP.ASM b/v4.0/src/CMD/MODE/MODECP.ASM new file mode 100644 index 0000000..c3f1e38 --- /dev/null +++ b/v4.0/src/CMD/MODE/MODECP.ASM @@ -0,0 +1,1279 @@ +.XLIST +INCLUDE STRUC.INC +.LIST + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ M A C R O S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +set_submessage_ptr MACRO submessage,message ;PUT pointer to "subMESSAGE" into submessage pointer field of "message". + +MOV AX,submessage ;AX=message number ;AN001; +MOV DH,utility_msg_class ;DH=message class=utility class ;AN001; +CALL SYSGETMSG ;DS:SI=>message piece ;AN001; +MOV BP,OFFSET sublist_&message ;address the sublist control block ;AN001; +MOV [BP].sublist_off,SI ;the sublist now points to the desired message piece ;AN001; +ENDM ;AN001; + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ M A C R O S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + PAGE ,132 ; + TITLE MODECP.SAL - CODEPAGE SUPPORT + INCLUDE MODECPRO.INC ;MODULE PROLOGUE +;THE FOLLOWING "INCLUDE MODECPEQ.INC" CONTAINS THE FOLLOWING DEFINITIONS: +; MACROS: HEADER, DOSCALL +; DOS FUNCTION CALLS EQUATES +; MAJOR AND MINOR CODES FOR "GENERIC IOCTL" DOS FUNCTION CALL +; ERROR RETURN CODES FROM SEVERAL SUBFUNCTIONS OF THE GENERIC IOCTL +; OPEN MODE EQUATES +; DEFINITIONS OF STRUC: +; "FON" - THE HEADER OF THE CODEPAGE FONT FILE +; "CODEPAGE_PARMS" - INPUT PARM LIST FROM CALLER +; "PACKET" AND "DES_STRT_PACKET" - BUFFERS USED +; BY THE SEVERAL CODEPAGE DOS IOCTL CALLS + INCLUDE MODECPEQ.INC ;MACROS,DOS EQUATES,STRUCS,OTHER EQUATES +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER + INCLUDE MODECPMS.INC ;DESCRIPTIONS OF MESSAGES +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER +; $SALUT CP(4,16,22,38) ;(set preprocessor columns for indenting) +PRINTF_CODE SEGMENT WORD PUBLIC + ASSUME CS:PRINTF_CODE ;"MODE" IS A ".COM" FILE; + ASSUME DS:PRINTF_CODE ; AS SUCH, ALL FOUR SEG REGS + ASSUME ES:PRINTF_CODE ; POINT TO THE ONE COMMON + ASSUME SS:PRINTF_CODE ; SEGMENT, "PRINTF_CODE" + +MODECP00 EQU $ ;UNREFERENCED, LOCATES REL ZERO IN LINK MAP + PUBLIC MODECP00 + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +PUBLIC CLOSE ;EQU 3EH ;CLOSE A FILE HANDLE,make available to analyze_and_invoke, see modecpeq.inc +PUBLIC DES_STRT_FL_CART ;EQU 0001H, means CARTRIDGE prepare +PUBLIC DEV_OPEN_MODE ;make available to analyze_and_invoke, see modecpeq.inc +PUBLIC OPEN ;make available to analyze_and_invoke, see modecpeq.inc + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ P U B L I C S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + +EXTRN cp_cb:WORD ;AN000;codepage_parms <>, see invoke + + EXTRN NOERROR:BYTE ;ERRORLEVEL RETURN CODE FLAG BYTE + ; NORMAL VALUE IS "TRUE" (-1) + ; IF ERROR OCCURS, SET IT TO "FALSE" (0) + EXTRN PRINTF:NEAR ;SENDS MESSAGES TO STDOUT OR STDERR + +EXTRN SYSGETMSG:NEAR ;AN001;message services routine to get the address of a message. Used to get address of a submessage. +EXTRN Utility_Msg_Class:ABS ;AN001; +EXTRN sublist_cpmsg8:BYTE ;AN001; +EXTRN sublist_cpmsg10:BYTE ;AN001; +EXTRN sublist_cpmsg17:BYTE ;AN001; + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ E X T R N S ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + +INCLUDE common.stc ;AN001;includes the following structures + + +;bogus EQU 88H ;totally invalid value +; +;codepage_parms STRUC +; cp_device DW ? +; des_pack_ptr DW ? +; font_filespec DW ? +; request_typ DW ? +;codepage_parms ENDS +; +; +;parm_list_entry STRUC ;used by parse_parameters and invoke +; +;parm_type DB bogus +;item_tag DB 0FFH +;value1 DW bogus ;used only for filespecs and code page numbers +;value2 DW bogus ;used only for filespecs and code page numbers +;keyword_switch_ptr DW 0 +; +;parm_list_entry ENDS +; +; +;sublist_def STRUC ;used by initialize_sublists +; +; db ? ;Sublist Length, fixed +; db ? ;Reserved, not used yet ;AN000; +;sublist_off dw ? ;offset +;sublist_seg dw ? ;segment part of pointer to piece of message +; db ? ;ID, special end of message format ;AN000; +; db ? ;flags +; db ? +; db ? +; db ? +; +;sublist_def ENDS + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º + + + ;ALL MESSAGES ARE IN THE MODEMES.ASM MODULE +current_request DB bogus ;see 'do_refresh' and 'des_end' +dgroup group zseg,printf_code +zseg segment para public +; LOCAL WORKAREA +BUF DB 512 DUP(0) ;DEFAULT BUFFER AREA + public buf ;not referenced, just shows up on mapf buf +END_OF_BUF EQU $ +zseg ends + +RESPONSE_LIST LABEL WORD ;WHERE TO PUT THE RESULTS OF QUERY prepareS +RES_NUM_ENTRIES EQU 12 ;NUMBER ENTRIES IN EACH HARDWARE AND prepare LISTS +RES_LEN DW RES_END - RESPONSE_LIST - 2 ;BYTE SIZE OF RESPONSE AREA +RES_HWCP DW RES_NUM_ENTRIES ;NUMBER OF HARDWARE CODE PAGES IN FOLLOWING LIST + DW RES_NUM_ENTRIES DUP(-1) +RES_DSCP DW RES_NUM_ENTRIES ;NUMBER OF prepare CODE PAGES IN FOLLOWING LIST + DW RES_NUM_ENTRIES DUP(-1) +RES_END EQU $ ;END OF QUERY prepare RESPONSE LIST + + +OLDINT24 DD ? ;ORIGINAL CONTENTS OF INT 24H VECTOR +CRITERROR DW 0 ;ERROR REPORTED IN DI TO INT 24H HANDLER + +DEVICE_STATUS DW ? ;FLAGS SET BY IOCTL (GET DEVICE INFO) +DEV_HANDLE DW ? ;VALUE OF HANDLE RETURNED BY + ; OPEN TO DEVICE FOR IOCTL I/O +FILE_HANDLE DW ? ;VALUE OF HANDLE RETURNED BY + ; OPEN TO FILESPEC. +DEV_TYPE DW prepare_STRT ;CX=xxx_DEV_TYPE * 256 + "prepare_STRT" + ;THE HIGH BYTE IS JUST ZERO HERE, BUT + ; THAT WILL BE OR'ED IN LATER +PK PACKET <> ;SELECT, QUERY SELECTED, prepare END + +PUBLIC PK + +DBCS_headr DBCS_head <> + +PUBLIC DBCS_headr + +; THESE NEXT TWO WORDS MUST BE KEPT TOGETHER +; THEY ARE REFERENCED AS A DWORD +DBUF LABEL DWORD +BUF_OFF DW 0 ;OFFSET OF ALLOCATED BUFFER +BUF_SEG DW ? ;SEGID OF ALLOCATED BUFFER + +BUF_SIZ DW 0FFFH ;REMEMBER HOW MUCH BUF IS AVAILABLE + ; (IN PARAGRAPHS, NOT BYTES) +BUF_BYTES DW ? ;NUMBER OF BYTES ACTUALLY IN THE BUFFER +PREPED DW 0 ;COUNT OF CODEPAGES KNOWN TO DEVICE +MINOR_VERSION DB 0,0 ;MINOR VERSION OF DOS +STATUS_BREAK DB 0 ;SAVES THE CURRENT STATUS OF "BREAK" +DEV_TABLE LABEL BYTE ;TABLE OF SUPPORTED DEVICE NAMES +CN DB "CON",0 +LP DB "PRN",0 +L1 DB "LPT1",0 +L2 DB "LPT2",0 +L3 DB "LPT3",0 +C1 DB "COM1",0 +C2 DB "COM2",0 +C3 DB "COM3",0 +C4 DB "COM4",0 +G1 DB "*",0 +END_DEV_TABLE LABEL BYTE +DEV_TAB_PTRS DW CN,LP,L1,L2,L3,C1,C2,C3,C4,G1,END_DEV_TABLE +NUM_TABL_ENTRIES EQU (($-DEV_TAB_PTRS)-2)/2 ;NUMBER OF DEVICE POINTERS +;THE ENTRIES IN THE NEXT TABLE MUST BE KEPT IN THE SAME ORDER AS THE +; DEVICE NAMES IN THE ABOVE LIST. THERE MUST BE A ONE-TO-ONE CORRESPONDENCE +; BETWEEN THE DEVICE NAMES AND THIS TABLE OF DEVICE TYPES. +DEV_TYPES DB CON_DEV_TYPE ;CN + DB LPT_DEV_TYPE ;LP + DB LPT_DEV_TYPE ;L1 + DB LPT_DEV_TYPE ;L2 + DB LPT_DEV_TYPE ;L3 + DB COM_DEV_TYPE ;C1 + DB COM_DEV_TYPE ;C2 + DB COM_DEV_TYPE ;C3 + DB COM_DEV_TYPE ;C4 + DB GLOBAL_CP ;G1 + + +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ D A T A ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + + + +MODECP PROC NEAR ;SUBROUTINE ENTRY POINT + + + PUBLIC MODECP + ;REMEMBER WHAT THE CURRENT SETTING IS + ; OF "BREAK" + DOSCALL BREAK_CHECK,REQUEST_BREAK_STATE ;CURRENT STATE RETURNED IN DL + + MOV STATUS_BREAK,DL ;REMEMBER WHAT THE CURRENT BREAK STATUS IS + + MOV DL,BREAK_OFF ;AVOID UNWANTED CTRL-BREAK DURING OPERATION + DOSCALL BREAK_CHECK,SET_BREAK_STATE + +;DOSCALL DOS_VERSION ;DETERMINE VERSION OF DOS + ;OUTPUT: AL=MAJOR, AH=MINOR VERSION NUMBER +;MOV MINOR_VERSION,AH ; BX AND CX SET TO ZERO + +; REMEMBER ORIGINAL OWNER OF INT 24H +; THE CRITICAL ERROR HANDLER + CALL SAVE_VECTOR24 ;SET DWORD AT "OLDINT24" WITH ORIGINAL POINTERS + +; SET UP THE DEVICE TYPE +; FOR THE prepare START FUNCTION + MOV BX,CP_CB.cp_device ;SET A BASE REG TO POINT TO DEV NAME + CALL SET_DEV_TYPE ;INTERROGATE THE DEVICE NAME, + ; SET "DEV_TYPE" ACCORDINGLY +;CMP BYTE PTR DEV_TYPE+BYTE,GLOBAL_CP ;WAS THE DEVICE SPECIFIED AS "*"? +;$IF E +; CALL SET_GLOBAL_CODEPAGE +;$ELSE ;SINCE DEVICE WAS NOT "*" + + +; OPEN DEVICE + MOV DX,BX ;DS:DX=POINTER TO ASCIIZ DEVICE NAME + DOSCALL OPEN,DEV_OPEN_MODE ;OPEN DEVICE WITH READ/WRITE ACCESS + +; $IF NC ;IF OPEN OK, + JC $$IF1 + MOV DEV_HANDLE,AX ;REMEMBER HANDLE TO DEVICE + + MOV BX,AX ;PASS DEVICE HANDLE TO IOCTL + DOSCALL IOCTL,IOCTL_FUN_GET_INFO + + MOV DEVICE_STATUS,DX ;SAVE THE DEVICE STATUS +; $IF NC,AND ;IF OK + JC $$IF2 + TEST DX,ISDEVICE ;IS THIS A DEVICE OR FILE? +; $IF NZ ;IF IS A DEVICE + JZ $$IF2 + CALL FUNCTION_SELECT ;CHECK THE "request_typ", AND + ; CALL THE APPROPRIATE FUNCTION HANDLER +; $ELSE ;SINCE NOT A DEVICE, MUST BE A FILE + JMP SHORT $$EN2 +$$IF2: + MOV DX,OFFSET CPMSG15 ;PASS POINTER TO MSG PARM LIST + CALL SEND_MSG ;"DEVICE NOT SUPPORTED FOR CODEPAGE" + +; $ENDIF ;OK FROM IOCTL, AND DEVICE OR FILE? +$$EN2: + MOV BX,DEV_HANDLE + DOSCALL CLOSE ;FINISHED WITH DEVICE + +; $ELSE ;SINCE DEVICE OPEN NOT OK + JMP SHORT $$EN1 +$$IF1: + MOV AX,CP_CB.cp_device ;GET OFFSET TO ASCIIZ DEVICE NAME + MOV CPMSGLST2DEV,AX ; TO MSG PARM LIST + MOV DX,OFFSET CPMSG2 ;PASS POINTER TO MSG PARM LIST + CALL SEND_MSG ;"FAILURE TO OPEN DEVICE" + +; $ENDIF ;DEVICE OPEN OK? +$$EN1: +;$ENDIF ;DEVICE "*"? + MOV DL,STATUS_BREAK ;GET WHAT THE BREAK STATUS USED TO BE + DOSCALL BREAK_CHECK,SET_BREAK_STATE ;RETURN TO USER DEFINED BREAK CONDITION + + RET ;RETURN TO CALLER +MODECP ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +SET_DEV_TYPE PROC NEAR + + + +;INPUT: BX = OFFSET TO ASCIIZ OF DEVICE NAME + + MOV CX,NUM_TABL_ENTRIES ;SET LOOP COUNTER TO NUMBER OF DEVICE NAMES IN LIST + MOV SI,OFFSET DEV_TAB_PTRS ;SET INDEX TO FIRST ENTRY IN TABLE OF POINTERS + MOV DI,OFFSET DEV_TYPES ;SET INDEX TO FIRST ENTRY OF DEVICE TYPES +;$SEARCH ;LOOK THRU TABLE FOR MATCHING ENTRY +$$DO7: + PUSH DS ;AN002; + POP ES ;need ES and DS the same for the CMPSB ;AN002; + PUSH CX ;SAVE COUNTER OF DEVICE NAMES + PUSH SI ;SAVE POINTER TO TABLE OF POINTERS TO DEVICE NAMES + PUSH DI ;SAVE POINTER TO TABLE OF DEVICE TYPES + + MOV CX,[SI]+WORD ;GET OFFSET TO NEXT DEVICE NAME + SUB CX,[SI] ;SET COUNT TO SIZE OF THIS DEVICE NAME + MOV DI,[SI] ;POINT TO DEVICE NAME FROM ENTRY IN TABLE + MOV SI,BX ;POINT TO DEVICE NAME FROM COMMAND LINE + REP CMPSB ;IS THIS THE ONE? + + POP DI ;RESTORE POINTER TO DEVICE TYPE LIST + POP SI ;RESTORE POINTER TO TABLE OF DEVICE NAME POINTERS + POP CX ;RESTORE COUNTER OF DEVICES +;$EXITIF E + JNE $$IF7 + MOV AL,BYTE PTR[DI] ;GET TYPE OF THIS DEVICE +;$ORELSE + JMP SHORT $$SR7 +$$IF7: + ADD SI,WORD ;BUMP INDEX TO NEXT ENTRY IN TABLE + ADD DI,BYTE ;BUMP INDEX TO NEXT ENTRY IN TABLE +;$ENDLOOP LOOP + LOOP $$DO7 + MOV AL,UNK_DEV_TYPE ;DEVICE NAME IS NOT IN THE ABOVE LIST +;$ENDSRCH +$$SR7: + MOV BYTE PTR DEV_TYPE+BYTE,AL ;ADD DESCRIPTOR OF DEVICE TO DEV_TYPE WORD + +RET +SET_DEV_TYPE ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +;SET_GLOBAL_CODEPAGE PROC NEAR +; +;;DEVICE WAS SPECIFIED AS "*", INDICATING THE GLOBAL CODEPAGE IS THE DEVICE +; +; MOV AX,CP_CB.request_typ +; CMP AX,SELECT +; $IF E +; MOV BX,CP_CB.DES_PACK_PTR ;SET BASE REG TO POINT TO PACKET AREA +; MOV BX,[BX].DES_STRT_PKCP1 ;GET CODEPAGE ID FROM PACKET +; MOV AX,SET_GLOBAL_CP ;SET GLOBAL CODEPAGE +; DOSCALL +; +; $IF C ;IF ERROR TRYING TO SET GLOBAL CODEPAGE +; MOV CPMSGLST11FUN,OFFSET CPMSG11_SET ;PUT "SETTING" INTO MESSAGE +; MOV DX,OFFSET CPMSG11 ;PASS OFFSET TO MSG PARM LIST +; CALL SEND_MSG +; +; $ELSE +; MOV CPMSGLST10FUN,OFFSET CPMSG10_GLOBAL ;SET MSG TO SAY "GLOBAL" +; MOV DX,OFFSET CPMSG10 ;PASS OFFSET TO MSG PARM LIST +; CALL QUEUE ;"MODE GLOBAL CODEPAGE FUNCTION COMPLETED" +; +; $ENDIF ;ERROR IN SETTING GLOBAL CODEPAGE? +; $ELSE ;SINCE NOT "SELECT" ASSUME IT IS "STATUS" +; MOV AX,GET_GLOBAL_CP +; DOSCALL +; +; $IF C ;IF ERROR +; MOV CPMSGLST11FUN,OFFSET CPMSG11_GET ;PUT "GETTING" INTO MESSAGE +; MOV DX,OFFSET CPMSG11 ;PASS OFFSET TO MSG PARM LIST +; CALL SEND_MSG +; +; $ELSE ;SINCE NO ERROR +; PUSH DX ; DX=SYSTEM CODE PAGE +; PUSH BX ; BX=ACTIVE CODE PAGE +; MOV DX,OFFSET CPMSG12 ;PASS OFFSET TO MSG PARM LIST +; CALL QUEUE ;"CURRENT CODEPAGE SETTINGS:" +; +; MOV CPMSGLST13TYP,OFFSET CPMSG13_ACT ;PUT "ACTIVE" INTO MESSAGE +; POP CPMSGLST13CP ;PASS ACTIVE CODEPAGE ID TO MSG PARM LIST (PUSHED FROM BX) +; MOV DX,OFFSET CPMSG13 ;PASS OFFSET TO MSG PARM LIST +; CALL QUEUE ;" XXX - ACTIVE CODEPAGE" +; +; POP CPMSGLST13CP ;PASS SYSTEM CODE PAGE (PUSHED FROM DX) +; MOV CPMSGLST13TYP,OFFSET CPMSG13_SYS ;PUT "SYSTEM" INTO MESSAGE +; MOV DX,OFFSET CPMSG13 ;PASS OFFSET TO MSG PARM LIST +; CALL QUEUE ;" XXX - SYSTEM CODEPAGE" +; +; $ENDIF ;ERROR IN GETTING GLOBAL CODEPAGE STATUS? +; $ENDIF ;"SELECT" OR "STATUS"? +; +; RET +;SET_GLOBAL_CODEPAGE ENDP +; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + HEADER ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA,SS:our_STACK ;AN000; + ; +OLD_STACK_SEG DW ? ;AN000; +OLD_STACK_OFF DW ? ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Beginning of code +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +INSTALL PROC FAR ;AN000; + CLI ;AN000; + MOV AX,SS ;AN000; + MOV OLD_STACK_SEG,AX ;AN000; + MOV OLD_STACK_OFF,SP ;AN000; + mov ax,our_stack ;AN000; + mov ss,ax ;AN000; + mov sp,512*4 ;AN000; + STI ;AN000; + ; + MOV AX,DATA ;AN000; + MOV DS,AX ;AN000; + JMP INITIALIZATION ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; CODE TO LEAVE SELECT WITH!!!! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +EXIT_SELECT: ;AN000; + ; + FIND_FILE S_AUTO_REBOOT, 0 ;AN000;DT Make sure INSTALL disk in drive + .IF < c > ;AN000;DT + .REPEAT ;AN000;DT make sure diskette + CLEAR_SCREEN ;AN000;DT with COMMAND.COM in drive + DISPLAY_MESSAGE 19 ;AN000;DT Insert INSTALL diskette + GET_FUNCTION FK_ENT ;AN000;DT + FIND_FILE S_AUTO_REBOOT, 0 ;AN000;DT + .LEAVE < nc > ;AN000;DT + HANDLE_ERROR ERR_DOS_DISK, 2 ;AN000;DT + .UNTIL ;AN000;DT + CLEAR_SCREEN2 ;AN000;JW + .ENDIF ;AN000; + ; +EXIT_SELECT2: ;AN000; + ; + DEALLOCATE_MEMORY ;AN000;free up allocated segment + .IF < NC > ;AN000; + CALL RESTORE_INT_23 ;AN074;SEH restore ctrl-break before exiting + MOV AX,OLD_STACK_SEG ;AN000; + MOV SS,AX ;AN000; + MOV SP,OLD_STACK_OFF ;AN000; + CALL CURSORON ;AN000; + MOV AX,4C00H ;AN000; + INT 21H ;AN000; + .ELSE ;AN000; +ABORT_SELECT: ;AN000;exit without handling allocated memory + CALL RESTORE_INT_23 ;AN074;SEH restore ctrl-break before exiting + MOV AX,OLD_STACK_SEG ;AN000; + MOV SS,AX ;AN000; + MOV SP,OLD_STACK_OFF ;AN000; + CALL CURSORON ;AN000; + MOV AX,4C00H ;AN000; + INT 21H ;AN000; + .ENDIF ;AN000; +INSTALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Message Retriever code inserted at this point.... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Start of SELECT.EXE code +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +INITIALIZATION: ;AN000; + LOAD_MESSAGES ;AN000; + JMP CHECK_VERSION ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +SELECT ENDS ;AN000; + +include msgdcl.inc + + END INSTALL ;AN000; + diff --git a/v4.0/src/SELECT/SELECT1.ASM b/v4.0/src/SELECT/SELECT1.ASM new file mode 100644 index 0000000..3770fd7 --- /dev/null +++ b/v4.0/src/SELECT/SELECT1.ASM @@ -0,0 +1,447 @@ + + +PAGE 60,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT1 - DOS - SELECT.EXE ;AN000; +SUBTTL select1.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT1.ASM : Copyright 1988 Microsoft +; +; DATE: July 4/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; SELECT1.ASM +; SELECT2.ASM +; SELECT3.ASM +; SELECT4.ASM +; SELECT5.ASM +; SELECT6.ASM +; +; CHANGE HISTORY: +; +; ;AN001;JW - P2452 Check for user switching disk before asked to +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +_TEXT segment byte public 'CODE' ;AN000; + extrn gget_status:far ;AN000; +_TEXT ends ;AN000; +_DATA segment word public 'DATA' ;AN000; +_DATA ends ;AN000; +CONST segment word public 'CONST' ;AN000; +CONST ends ;AN000; +_BSS segment word public 'BSS' ;AN000; +_BSS ends ;AN000; + ; +DGROUP GROUP CONST,_BSS,_DATA ;AN000; + ; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; Segment for Data values +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; +.LIST ;AN000; + ; + EXTRN PM_BASECHAR:BYTE ;AN000; + EXTRN PM_BASEATTR:BYTE ;AN000; + EXTRN CRD_CCBVECOFF:WORD ;AN000; + EXTRN CRD_CCBVECSEG:WORD ;AN000; + ; + EXTRN ALLOCATE_MEMORY_CALL:FAR ;AN000; + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN000; + EXTRN VIDEO_CHECK:FAR ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; + EXTRN EXIT_SELECT2:NEAR ;AN000;JW + EXTRN ABORT_SELECT:NEAR ;AN000; + EXTRN HANDLE_F3:NEAR ;AN001;GHG + ; + PUBLIC CHECK_VERSION ;AN000; + PUBLIC INTRO_SCREEN ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + PUBLIC BCHAR ;AN000; + DB 'BCHAR=' ;AN000; +BCHAR DB ' ' ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_DOS:NEAR ;AN000; + EXTRN EXIT_DOS_CONT:NEAR ;AN000; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN WORKSPACE_SCREEN:NEAR ;AN000; + EXTRN DATE_TIME_SCREEN:NEAR ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Beginning of code +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CHECK_VERSION: ;AN000; + INIT_VAR N_HOUSE_CLEAN,E_CLEAN_NO ;AN000; no files to be erased on exit + ; + CHECK_DOS_VERSION ;AN000; check DOS version + ;;;check for DOS version 4.00 ; + .IF c ;AN000; if incorrect DOS version + DISPLAY_MESSAGE 1 ;AN000; + GOTO EXIT_DOS_CONT ;AN000; + .ENDIF ;AN000; EXIT + ; + CHECK_DEFAULT_DRIVE ;AN000; check if default drive is A: + ;;;check if default drive is A: ; + .IF c ;AN000; if default drive not A: + DISPLAY_MESSAGE 4 ;AN000; + GOTO EXIT_DOS_CONT ;AN000; + .ENDIF ;AN000; EXIT + ; + CHECK_DISKETTE N_DISKETTE_A,N_DISKETTE_B,N_DISKETTE_TOT,P_STR120_1 ;AN000; + ;;;get diskette media type and no of drives ; + ;;;N_DISKETTE_A & B - media type 360k,720k, etc ; + ;;;N_DISKETTE_TOT - number of drives ; + ; + CHECK_DISK E_DISK_1,N_DISK_1,N_DISK_1_S1,N_DISK_1_S2,DISK_1_TABLE ;AN000; + ;;;get partition status for 1st fixed disk ; + ;;;N_DISK_1 - disk status ; + ;;;N_DISK_1_S1 - detailed disk status word 1 ; + ;;;N_DISK_1_S2 - detailed disk status word 2 ; + ;;;DISK_1_TABLE - status of all partitions ; + ; + CHECK_DISK E_DISK_2,N_DISK_2,N_DISK_2_S1,N_DISK_2_S2,DISK_2_TABLE ;AN000; + ;;;get partition status for 2nd fixed disk ; + ;;;N_DISK_2 - disk status ; + ;;;N_DISK_2_S1 - detailed disk status byte 1 ; + ;;;N_DISK_2_S2 - detailed disk status byte 2 ; + ;;;DISK_2_TABLE - status of all partitions ; + ; + CHECK_VALID_MEDIA N_DISKETTE_A,N_DISKETTE_B,N_DISKETTE_TOT,N_DISK_1,N_DEST_DRIVE,I_DEST_DRIVE,N_DRIVE_OPTION ;AN000;JW + ;;;check if disk/diskette combination is valid ; + ;;;also determine default install drive ; + ;;;N_DEST_DRIVE - default/user drive choice ; + ;;;I_DEST_DRIVE - drive A: or B: or C: ; ;AN111;JW + ;;;N_DRIVE_OPTION - which drive options are avail ;AN111;JW + .IF c ;AN000; + DISPLAY_MESSAGE 5 ;AN000; + GOTO EXIT_DOS_CONT ;AN000; + .ENDIF ;AN000; + ; + GET_INSTALLED_MEM MEM_SIZE ;AN000; + ; + CHECK_MACHINE MACHINE_TYPE, PS2_FLAG ;AN000;JW + ; + SCAN_PARAMETERS N_SELECT_MODE ;AN000; + ;;;scan command line ; + ;;;N_SELECT_MODE - MENU or FDISK ; + .IF < N_SELECT_MODE EQ E_SELECT_INV > ;AN000;JW + DISPLAY_MESSAGE 6 ;AN000;JW + GOTO EXIT_SELECT2 ;AN000;JW + .ENDIF ;AN000;JW + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; If this is reboot after FDISK, load parameters in SELECT.TMP +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < N_SELECT_MODE eq E_SELECT_FDISK > and ;AN000;JW + .IF < N_DISKETTE_A ne E_DISKETTE_360 > ;AN000; + CALL SCAN_INFO_CALL ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + CHECK_DISPLAY ;AN000; determine display type + .IF < ACTIVE eq EGA > or ;AN000; + .IF < ALTERNATE eq EGA > or ;AN000; + .IF < ACTIVE eq LCD > or ;AN000; + .IF < ALTERNATE eq LCD > ;AN000; + INIT_VAR N_DISPLAY, E_CPSW_DISP ;AN000; + .ELSE ;AN000; + INIT_VAR N_DISPLAY, E_NOCPSW_DISP ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Read in SELECT.DAT data (all but the help) +; +; This will read in the panels, the scroll fields, +; the color index (COLOR or MONO), and (EVENTUALLY) +; the input fields. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + SET_DISPLAY_MODE ;AC084; SEH call moved before video information requested ;AN000; set display to 80 col and 25 lines + CALL PCGVIDO_CALL ;AN000;get video information + ALLOCATE_MEMORY ;AN000;allocate enough memory for SELECT.DAT + .IF < NC > ;AN000; + CALL INITIALIZE ;AN000;read all panels, color, scroll + .IF < NC > ;AN000;check if error condition occurred + INITIALIZE_BCHAR BCHAR ;AN000;Initialize the background character + JMP MEMORY_ALLOCATED ;AN000; + .ELSE ;AN000; + JMP EXIT_SELECT ;AN000;terminate SELECT without affecting memory + .ENDIF ;AN000; + .ELSE ;AN000; + DISPLAY_MESSAGE 20 ;AN067;SEH insufficient memory + JMP ABORT_SELECT ;AN000; + .ENDIF ;AN000; +MEMORY_ALLOCATED: ;AN000; + ;;; CALL CURSOROFF ;AN000;deactive cursor +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Commence the heart of the SELECT installation routine. +; At the initial portion of the code, a system hardware +; check out is performed. The peripherals are established, +; the display type is determined, and checks are made against +; disk media installed. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;; CALL CURSOROFF ;AN000; + ; + .IF < ACTIVE eq EGA > ;AN000; if active display = EGA + COPY_STRING S_STR120_1,M_STR120_1,S_PREP_EGA;AN000; set parameter for EGA.CPI + .ELSEIF < ACTIVE eq LCD > ;AN000; elseif active display = LCD + COPY_STRING S_STR120_1,M_STR120_1,S_PREP_LCD;AN000; set parameter for LCD.CPI + .ELSE ;AN000; else + INIT_VAR S_STR120_1, 0 ;AN000; set parameter = null + .ENDIF ;AN000; + ; + .IF < S_STR120_1 gt 0 > ;AN000; if parameter is not null + EXEC_PROGRAM S_MODE,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000;GHG exec MODE CON CP PREP((850)...) + EXEC_PROGRAM S_MODE,S_CP_SEL,PARM_BLOCK,EXEC_DIR ;AN000;GHG execute MODE CON CP SEL=850 + .ENDIF ;AN000; + ; + INIT_VAR F_PARTITION, E_PART_DEFAULT ;AN000; + INIT_VAR F_FORMAT, E_FORMAT_FAT ;AN000; + .IF < N_SELECT_MODE eq E_SELECT_FDISK > ;AN000; + INIT_VAR I_DEST_DRIVE, E_DEST_DRIVE_C ;AN000; + GOTO DATE_TIME_SCREEN ;AN000; + .ENDIF ;AN000; + ; + CHECK_EXPANDED_MEMORY N_XMA, N_MOD80 ;AN000; check if expanded memory is present + GET_NUMBER_PORTS N_PARALLEL, N_SERIAL ;AN000; get number of parallel/serial ports +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Initialize pre-defined country and keyboard information +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + GET_DOS_COUNTRY P_STR120_1, N_COUNTRY ;AN000; get current DOS country + GET_COUNTRY_INDEX N_COUNTRY, N_CTY_LIST,I_COUNTRY ;AN000; get index into country table + GET_COUNTRY_DEFAULTS N_CTY_LIST, I_COUNTRY ;AN000; get default data for specified country + .IF < N_DISPLAY eq E_CPSW_DISP > ;AN000; + .IF < N_CPSW eq E_CPSW_NOT_VAL > ;AN000; if cpsw not valid + INIT_VAR F_CPSW, E_CPSW_NA ;AN000; set cpsw = not available + .ELSEIF < N_CPSW eq E_CPSW_NOT_REC > ;AN000; else if cpsw not recommended + INIT_VAR F_CPSW, E_CPSW_NO ;AN000; set cpsw = no + .ELSE ;AN000; else + INIT_VAR F_CPSW, E_CPSW_YES ;AN000; set cpsw = yes + .ENDIF ;AN000; + .ELSE ;AN000; + INIT_VAR F_CPSW, E_CPSW_NA ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; If country is SWISS: +; then get keyboard from an input field +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + COMPARE_STRINGS S_KEYBOARD,S_SWISS ;AN000;GHG is default KB=SF? + .IF ;AN000;GHG + RETURN_STRING STR_SWISS_KEYB,S_KEYBOARD,M_KEYBOARD+2;AN000;GHG + .ENDIF ;AN000;GHG +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Establish the default keyboard indice based on the +; existing keyboard string. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + GET_KEYBOARD_INDEX S_KEYBOARD,N_KYBD_LIST,I_KEYBOARD,N_KYBD_ALT;AN000; get kybd info + .IF < N_KYBD_ALT eq E_KYBD_ALT_YES > near ;AN000; + GET_ALT_KYBD_TABLE S_KEYBOARD,ALT_TAB_PTR,ALT_KYB_ID ;AN000; get ptr to alt kybd + COPY_BYTE ALT_KYB_ID_PREV, ALT_KYB_ID ;AN000; set prev id = current id + INIT_VAR I_KYBD_ALT, 2 ;AN090; set index into alt kybd list = 2 + GET_ALT_KEYBOARD ALT_TAB_PTR,ALT_KYB_ID,I_KYBD_ALT,S_KYBD_ALT;AN000; get alt kybd id + .ELSE ;AN000; + INIT_VAR ALT_KYB_ID_PREV, 0 ;AN000; set prev alt kyb id = 0 + .ENDIF ;AN000; + ; + INIT_VAR N_KYB_LOAD, E_KYB_LOAD_UND ;AN000; set KEYB loaded status = undefined +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Initialize installation variables to default values +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < MEM_SIZE eq 256 > ;AN000;JW + INIT_VAR I_WORKSPACE, E_WORKSPACE_MIN ;AN000; set workspace option = minimum DOS JW + COPY_STRING S_FILES, M_FILES, D_FILES_2 ;AN000; set FILES = 20 + .ELSE ;AN000;JW + INIT_VAR I_WORKSPACE, E_WORKSPACE_BAL ;AN000; set workspace option = balance DOS + COPY_STRING S_FILES, M_FILES, D_FILES_1 ;AN000; set FILES = 20 + .ENDIF ;AN000;JW + INIT_VAR N_WORK_PREV, 0 ;AN000; set previous workspace option=undefined + COPY_STRING S_BREAK, M_BREAK, S_ON ;AN000; set BREAK = ON + COPY_STRING S_CPSW, M_CPSW, S_OFF ;AN000; set CPSW = OFF + COPY_STRING S_LASTDRIVE,M_LASTDRIVE,D_LASTDRIVE_1 ;AN000; set LASTDRIVE = E + INIT_VAR S_STACKS, 0 ;AN000; set STACKS = null (spaces) + COPY_STRING S_VERIFY, M_VERIFY, S_OFF ;AN000; set VERIFY = OFF + COPY_STRING S_PROMPT, M_PROMPT, D_PROMPT_1 ;AN000; set PROMPT = $P$G + COPY_STRING S_DOS_LOC,M_DOS_LOC,D_DOS_LOC_1 ;AN000; set DOS location = DOS + INIT_VAR S_INSTALL_PATH, 0 ;AN000; set install path = null + INIT_VAR F_SHELL,E_SHELL_NO ;AN000; set SHELL = no + .IF < MEM_SIZE eq 256 > ;AN000;DT + COPY_STRING S_SHELL, M_SHELL, D_SHELL_1 ;AN000; set SHELL parameter = /R + .ELSE ;AN000; + COPY_STRING S_SHELL, M_SHELL, D_SHELL_2 ;AN000; set SHELL parameter = /R + .ENDIF ;AN000;DT +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_VAR F_SHARE, E_SHARE_NO ;AN000; set SHARE = no + INIT_VAR S_SHARE, 0 ;AN000; set SHARE parameter = null +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Continue initialization ... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_VAR F_VDISK, E_VDISK_NO ;AN000; set VDISK = no + INIT_VAR S_VDISK, 0 ;AN000; set VDISK field = null (spaces) + .IF < N_XMA eq E_XMA_PRESENT > ;AN000; if expanded memory present + INIT_VAR F_XMA, E_XMA_NO ;AN000; set XMA = no (default) + INIT_VAR S_XMAEM, 0 ;AN000; set XMAEM field=null (spaces) + COPY_STRING S_XMA2EMS,M_XMA2EMS,D_XMA2EMS_1 ;AN000; & XMA2EMS field=FRAME=(D000,C800,CC00) + .ELSE ;AN000; else + INIT_VAR F_XMA, E_XMA_NA ;AN000; set XMA = no + .ENDIF ;AN000; + INIT_VAR F_REVIEW, E_REVIEW_ACCEPT ;AN000; set review option = accept selection + INIT_VAR I_CTY_KYBD, E_CTY_KB_PREDEF ;AN000; set country support=pre-defined support + ; + .IF < ACTIVE eq CGA > or ;AN000; if CGA adaptor + .IF < ALTERNATE eq CGA > ;AN000; + INIT_VAR F_GRAFTABL, E_GRAFTABL_YES ;AN000; set GRAFTABL = yes + .ELSE ;AN000; else + INIT_VAR F_GRAFTABL, E_GRAFTABL_NA ;AN000; set GRAFTABL = not available + .ENDIF ;AN000; + ; + INIT_VAR N_NUMPRINT, MIN_NUMPRINT ;AN000; set number of printers = 0 + INIT_VAR I_PRINTER, 1 ;AN000; set index into printer list = 1 + INIT_VAR I_PORT, 1 ;AN000; set port number = 1 + INIT_VAR I_REDIRECT, 1 ;AN000; set redirect port number = 1 + ; + CALL HOOK_INT_23 ;AN074; SEH don't allow ctrl-break + CALL CURSOROFF ;AN054; SEH moved from earlier in code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �WELCOME_SCREEN � +; � � +; �������������������������������������� +; +; The WELCOME screen is always presented. +; The screen does not have help, F3 function or input variables. +; Valid keys are ENTER and ESC. +; ESC key will return control to the DOS command line. +; If installing from 360KB diskettes, must prompt for INSTALL diskette +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +WELCOME_SCREEN: ;AN000; + ; + .IF < N_DISKETTE_A eq E_DISKETTE_360 > ;AN000; + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 ;AN000; Insert the INSTALL diskette + .ENDIF ;AN000; + ; +WELCOME_SCREEN2: ;AN000; + INIT_PQUEUE PAN_WELCOME ;AN000; initialize queue + PREPARE_PANEL SUB_CONT_OPTION ;AN000; prepare continue or cancel + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + DISPLAY_PANEL ;AN000; display WELCOME panel + ; + GET_FUNCTION FK_ENT_ESC_F3 ;AN000; get user entered function + .IF < N_USER_FUNC eq E_F3 > ;AN000;DT if user entered F3 key + GOTO EXIT_DOS ;AN000;DT + .ELSEIF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + FIND_FILE S_PRINT_FILE, E_FILE_ATTR ;AN001; check to make sure they did not switch + .IF < c > ;AN000;JW + INSERT_DISK SUB_REM_DOS_A, S_PRINT_FILE ;AN000;JW + .ENDIF ;AN000;JW + GOTO INTRO_SCREEN ;AN000; go to next screen + .ELSE ;AN000; else + CALL HANDLE_F3 ;AN001;GHG exit to DOS command line + .IF < C > ;AN001;GHG + GOTO EXIT_DOS ;AN001;GHG + .ELSE ;AN001;GHG + GOTO WELCOME_SCREEN2 ;AN001;GHG + .ENDIF ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �INTRO_SCREEN � +; � � +; �������������������������������������� +; +; The INTRODUCTION screen is always presented. +; The screen does not have help, F3 function or any variables. +; Valid keys are ENTER and ESC. +; ESC key will return control to the DOS command line. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +INTRO_SCREEN: ;AN000; + INIT_PQUEUE PAN_INTRO ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + DISPLAY_PANEL ;AN000; display INTRODUCTION panel + ; + GET_FUNCTION FK_ENT_ESC_F3 ;AN000; get user entered function + .IF < N_USER_FUNC eq E_F3 > ;AN027;SEH Added to prevent going to Welcome Screen + GOTO EXIT_DOS ;AN027;SEH when F3 hit + ; (ENTER or ESC) + .ELSEIF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + GOTO WORKSPACE_SCREEN ;AN000; go to next screen + .ELSE ;AN000; else + GOTO WELCOME_SCREEN2 ;AN001;GHG; exit to DOS command line + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ROUTINE TO SCAN SELECT.TMP FILE +; +; Broken down into a subroutine for code savings... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC SCAN_INFO_CALL ;AN000; +SCAN_INFO_CALL PROC NEAR ;AN000; + SCAN_INFO_FILE F_SHELL, N_FORMAT_MODE,N_DISK1_MODE,I_DESTINATION,S_INSTALL_PATH,S_SELECT_TMP,P_STR120_1,M_STR120_1 + ;;;F_SHELL - shell installation flag + ;;;N_FORMAT_MODE - partition & format option : + ;;; new(select),new(user),used(user) ; + ;;;N_DISK1_MODE - 1st disk status - new or used ; + ;;;I_DESTINATION - destination on c: disk option + ;;;S_INSTALL_PATH - DOS install path ; + ;;;S_SELECT_TMP - file for FDISK parameters ; + ; + .IF < N_SELECT_MODE eq E_SELECT_INV > ;AN000; if SELECT mode not MENU or FDISK + DISPLAY_MESSAGE 6 ;AN000; + GOTO EXIT_DOS_CONT ;AN000; + .ENDIF ;AN000; EXIT + ; + .IF < N_SELECT_MODE eq E_SELECT_FDISK > and ;AN000; if SELECT mode is FDISK + .IF < N_FORMAT_MODE eq E_SELECT_INV > or ;AN000; and format and disk status + .IF < N_DISK1_MODE eq E_SELECT_INV > ;AN000; not available from SELECT.TMP + DISPLAY_MESSAGE 6 ;AN000; + GOTO EXIT_DOS_CONT ;AN000; + .ENDIF ;AN000; EXIT + RET ;AN000; +SCAN_INFO_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT2.ASM b/v4.0/src/SELECT/SELECT2.ASM new file mode 100644 index 0000000..d6dc952 --- /dev/null +++ b/v4.0/src/SELECT/SELECT2.ASM @@ -0,0 +1,589 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT2.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT2.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the -A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; +; Module contains code for : +; - Program/Memory workspace screen +; - Predefined country/keyboard screen +; - Country screen +; - Keyboard screen +; - Alternate Keyboard screen +; - Load the specified keyboard +; - Install drive screen +; - DOS location screen +; +; CHANGE HISTORY: +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + EXTRN EXEC_ERR:BYTE ; +DATA ENDS ;AN000; + ; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; +.LIST ;AN000; + ; + PUBLIC WORKSPACE_SCREEN ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_DOS:NEAR ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN INTRO_SCREEN:NEAR ;AN000; + EXTRN DOS_LOC_SCREEN:NEAR ;AN000; + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN GET_OVERLAY:NEAR ;AN000;DT +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �WORKSPACE_SCREEN � +; � � +; �������������������������������������� +; +; The User Function and Memory Workspace Needs Screen is always presented. +; The screen allows the user to define the memory requirements for +; the install process. Default values for DOS commands will be assigned based +; on user input. +; Valid keys are ENTER, ESC, F1, cursor up/down and numeric 1 to 3. +; +; All values are re-initialized the second time round only if the new option +; is different from the previously selected option. +; +; �����������������������������������������������������������������Ŀ +; � � I_WORKSPACE=1 � I_WORKSPACE=2 � I_WORKSPACE=3 � +; �����������������������������������������������������������������Ĵ +; � P_BREAK � 'ON' � 'ON' � 'ON' � +; � P_BUFFERS � ' ' � '20' � '50,4' � +; � P_CPSW � 'OFF' � 'OFF' � 'OFF' � +; � F_CPSW � no � no � no � +; � P_FCBS � ' ' � ' ' � '20,8' � +; � P_FILES � '8' � '20' � '20' � +; � P_LASTDRIVE � 'E' � 'E' � 'E' � +; � P_STACKS � ' ' � ' ' � ' ' � +; � P_VERIFY � 'OFF' � 'OFF' � 'OFF' � +; � P_PROMPT � '$P$G' � '$P$G' � '$P$G' � +; � F_PROMPT � no � no � no � +; � P_PATH � ' ' � ' ' � ' ' � +; � F_PATH � no � no � no � +; � P_APPEND � ' ' � ' ' � ' ' � +; � F_APPEND � no � no � no � +; � P_ANSI � ' ' � ' ' � '/X' � +; � F_ANSI � no � yes � yes � +; � P_FASTOPEN � ' ' � 'C:=(50,25)' � 'C:=(100,200)'� +; � F_FASTOPEN � no � yes � yes � +; � F_GRAFTABL � no � no � no � +; � P_GRAPHICS � ' ' � ' ' � ' ' � +; � F_GRAPHICS � no � yes � yes � +; � P_SHARE � ' ' � ' ' � ' ' � +; � F_SHARE � no � no � no � +; � P_SHELL � '/R' � '/R' � '/R' � +; � F_SHELL � yes � yes � yes � +; � P_VDISK � ' ' � ' ' � ' ' � +; � F_VDISK � no � no � no � +; � P_XMAEM � ' ' � ' ' � ' ' � +; � DOS_LOC � 'DOS' � 'DOS' � 'DOS' � +; � F_XMA � yes � yes � yes � +; � P_XMA2EMS � 'FRAME=D000 P254=C800 P255=CC00' for all options� +; ������������������������������������������������������������������� +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +WORKSPACE_SCREEN: ;AN000; + INIT_PQUEUE PAN_WORKSPACE ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_DOS_SUPPORT,I_WORKSPACE ;AN000; + DISPLAY_PANEL ;AN000; display WORKSPACE panel + ; + GET_SCROLL SCR_DOS_SUPPORT,I_WORKSPACE,FK_SCROLL ;AN000; get user entered option + .IF < N_USER_FUNC eq E_F3 > ;AN027;SEH Added to prevent going to Intro Screen + GOTO EXIT_DOS ;AN027;SEH when F3 hit + .ELSEIF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + .THEN ;AN000; + PUSH_HEADING WORKSPACE_SCREEN ;AN000; save screen address on SELECT STACK + COMP_WORDS N_WORK_PREV, I_USER_INDEX ;AN000; compare previous and new options + .IF nz near ;AN000; if new option is different + .THEN ;AN000; + COPY_WORD I_WORKSPACE, I_USER_INDEX ;AN000; set current option = new option + COPY_WORD N_WORK_PREV, I_USER_INDEX ;AN000; set previous option = new option + ; + .SELECT ;AN000; + ; + .WHEN < I_WORKSPACE eq E_WORKSPACE_MIN > near ;AN000; option = minimize DOS functions + INIT_VAR_MINIMIZE ;AN000; initialize variables + ; + .WHEN < I_WORKSPACE eq E_WORKSPACE_BAL > near ;AN000; option = balance DOS functions + INIT_VAR_BALANCE ;AN000; initialize variables + ; + .OTHERWISE ;AN000; option = maximize DOS functions + INIT_VAR_MAXIMIZE ;AN000; initialize variables + ; + .ENDSELECT ;AN000; + ; + .ENDIF ;AN000; + GOTO CTY_KYBD_SCREEN ;AN000; goto the next screen (CTY-KYBD) + .ELSE ;AN000; + GOTO INTRO_SCREEN ;AN001;GHG; user entered ENTER or ESC, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �CTY_KYBD_SCREEN � +; � � +; �������������������������������������� +; +; The COUNTRY and KEYBOARD support screen is always presented. +; The screen allows the user to choose the pre-defined country and +; keyboard displayed or to select a country specific support. +; When the screen is presented for the first time, the pre-defined +; country is the country code in the CONFIG.SYS file obtained by a DOS call. +; The pre-defined keyboard is the +; default keyboard associated with the pre-defined country. If there is no +; valid keyboard association, "None" is displayed. Subsequent presentation of +; this screen will display the user selected support. +; Two keyboards are associated with the Swiss country code; French and +; German. The keyboard code to be used will be identified during translation +; and will be saved in the form of a panel. +; Valid keys are ENTER, ESC, F1, F3, cursor up/down, numeric 1 to 2. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CTY_KYBD_SCREEN: ;AN000; + COPY_WORD N_WORD_1, I_COUNTRY ;AN000; scroll list item = country index + .IF < N_CTY_LIST eq E_CTY_LIST_2 > ;AN000; if country list = 2 + .THEN ;AN000; + ADD_WORD N_WORD_1, CTY_A_ITEMS ;AN000; add items in list 1 + .ENDIF ;AN000; + ; + .IF < N_KYBD_ALT eq E_KYBD_ALT_NO > near ;AN000; if no alt kyb id + .THEN ;AN000; + COPY_WORD N_WORD_2, I_KEYBOARD ;AN000; scroll list item = keyboard index + .IF < N_KYBD_LIST eq E_KYBD_LIST_2 > ;AN000; if kybd list = 2 + .THEN ;AN000; + ADD_WORD N_WORD_2, KYBD_A_ITEMS ;AN000; add items in list 1 + .ENDIF ;AN000; + .ELSE ;AN000; else + ; + INIT_VAR N_WORD_2, KYBD_A_ITEMS ;AN000; scroll list item = items in list 1 + ADD_WORD N_WORD_2, KYBD_B_ITEMS ;AN000; + items in list 2 + ADD_WORD N_WORD_2, 1 ;AN000; + 1st item in French alt kybd + .IF < ALT_KYB_ID gt ALT_FRENCH > ;AN000; if alt kybd id > French + .THEN ;AN000; + ADD_WORD N_WORD_2, ALT_FR_ITEMS ;AN000; add items in French alt kybd to list + .ENDIF ;AN000;GHG + .IF < ALT_KYB_ID gt ALT_ITALIAN > ;AN000;GHG if alt kybd id > Italian + .THEN ;AN000; + ADD_WORD N_WORD_2, ALT_IT_ITEMS ;AN000; add items in Italian alt kybd to list + .ENDIF ;AN000; + ; + DEC N_WORD_2 ;AN090;GHG These two lines were moved inside the + ADD_WORD N_WORD_2, I_KYBD_ALT ;AN090;GHG ELSE clause. + ; + .ENDIF ;AN000; + ; + ; + INIT_PQUEUE PAN_CTY_KYB ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_ACC_CTY, N_WORD_1 ;AN000; display current country + INIT_SCROLL SCR_ACC_KYB, N_WORD_2 ;AN000; display current keyboard + INIT_SCROLL SCR_CTY_KYB, I_CTY_KYBD ;AN000; + DISPLAY_PANEL ;AN000; display screen + ; + GET_SCROLL SCR_CTY_KYB,I_CTY_KYBD,FK_SCROLL;AN000; get new option + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD I_CTY_KYBD, I_USER_INDEX ;AN000; save new option + PUSH_HEADING CTY_KYBD_SCREEN ;AN000; save screen address on SELECT STACK + GOTO COUNTRY_SCREEN ;AN000; goto the next screen (COUNTRY) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �COUNTRY_SCREEN � +; � � +; �������������������������������������� +; +; The COUNTRY CODE screen is presented if the user selected to define +; country specific support (CTY_KYBD_SCREEN). +; When this screen is presented for the first time, the current +; country obtained from DOS will be highlighted. Subsequent presentations +; of this screen will highlight the user selected country. +; Code Page to be used will be determined by the selected country code. +; Valid keys are ENTER, ESC, F1, F3, cursor up/down. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +COUNTRY_SCREEN: ;AN000; + .IF < I_CTY_KYBD eq E_CTY_KB_PREDEF > ;AN000; if accept pre-defined support + .THEN ;AN000; + GOTO LOAD_KEYBOARD ;AN000; goto load specified kybd id + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_COUNTRY ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_CTY_1, 0 ;AN000; init 1st scroll list + INIT_SCROLL SCR_CTY_2, 0 ;AN000; init 2nd scroll list + DISPLAY_PANEL ;AN000; display COUNTRY panel + ; + .IF < N_CTY_LIST eq E_CTY_LIST_1 > ;AN000; if country is in list 1 + .THEN ;AN000; + GET_SCROLL SCR_CTY_1,I_COUNTRY, FK_SCROLL ;AN000; highlight country in list 1 & get new choice + .ELSE ;AN000; else + GET_SCROLL SCR_CTY_2, I_COUNTRY, FK_SCROLL ;AN000; highlight country in list 2 & get new choice + .ENDIF ;AN000; + ; + .REPEAT ;AN000; repeat code block: CASS cannot do this automatically + .IF < N_USER_FUNC eq UPARROW > near ;AN000; if user entered cursor up + .THEN ;AN000; + .IF < N_CTY_LIST eq E_CTY_LIST_1 > near ;AN000; if country list = 1 + .THEN ;AN000; + INIT_VAR N_CTY_LIST, E_CTY_LIST_2 ;AN000; set country list = 2 + GET_SCROLL SCR_CTY_2,CTY_B_ITEMS,FK_SCROLL ;AN000; point to last item in list 2 + .ELSE near ;AN000; else + INIT_VAR N_CTY_LIST, E_CTY_LIST_1 ;AN000; set country list = 1 + GET_SCROLL SCR_CTY_1,CTY_A_ITEMS,FK_SCROLL ;AN000; point to last item in list 1 + .ENDIF ;AN000; + .ELSEIF < N_USER_FUNC EQ DNARROW > near ;AN000; else if user entered cursor down + .THEN ;AN000; + .IF < N_CTY_LIST eq E_CTY_LIST_1 > near ;AN000; if country list = 1 + .THEN ;AN000; + INIT_VAR N_CTY_LIST, E_CTY_LIST_2 ;AN000; set country list = 2 + GET_SCROLL SCR_CTY_2, 1, FK_SCROLL ;AN000; point to 1st item in list 2 + .ELSE near ;AN000; else + INIT_VAR N_CTY_LIST, E_CTY_LIST_1 ;AN000; set country list = 1 + GET_SCROLL SCR_CTY_1, 1, FK_SCROLL ;AN000; point to 1st item in list 1 + .ENDIF ;AN000; + .ELSE near ;AN000; else + .LEAVE ;AN000; break away from repeat loop + .ENDIF ;AN000; + .UNTIL ;AN000; end of repeat block + ; + .IF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD I_COUNTRY, I_USER_INDEX ;AN000; save new country + PUSH_HEADING COUNTRY_SCREEN ;AN000; save screen address on SELECT STACK + GET_COUNTRY_DEFAULTS N_CTY_LIST, I_COUNTRY ;AN000; get country default parameters + .IF < N_DISPLAY eq E_CPSW_DISP > ;AN000; + .THEN ;AN000; + .IF < N_CPSW eq E_CPSW_NOT_VAL > ;AN000; if cpsw not valid + .THEN ;AN000; + INIT_VAR F_CPSW, E_CPSW_NA ;AN000; set cpsw = not available + .ELSEIF < N_CPSW eq E_CPSW_NOT_REC > ;AN000; else if cpsw not recommended + .THEN ;AN000; + INIT_VAR F_CPSW, E_CPSW_NO ;AN000; set cpsw = no + .ELSE ;AN000; else + INIT_VAR F_CPSW, E_CPSW_YES ;AN000; set cpsw = yes + .ENDIF ;AN000; + .ELSE ;AN000; + INIT_VAR F_CPSW, E_CPSW_NA ;AN000; + .ENDIF ;AN000; + ; + ;;; get keyboard from input field if country = Swiss ; + COMPARE_STRINGS S_KEYBOARD,S_SWISS ;AN000;GHG is default KB=SF? + .IF ;AN000;GHG + .THEN ;AN000;GHG + RETURN_STRING STR_SWISS_KEYB,S_KEYBOARD,M_KEYBOARD+2;AN000;GHG + .ENDIF ;AN000;GHG + ; + GET_KEYBOARD_INDEX S_KEYBOARD,N_KYBD_LIST,I_KEYBOARD,N_KYBD_ALT ;AN000; get index into keyboard tables + GOTO KEYBOARD_SCREEN ;AN000; goto the next screen (KEYBOARD) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �KEYBOARD_SCREEN � +; � � +; �������������������������������������� +; The KEYBOARD CODE screen is presented if the user had selected to +; define country specific support and the country code selected has a valid +; keyboard code association. +; The keyboard code associated with the selected country code will be +; highlighted. +; For keyboards that have more than one valid keyboard code, a second +; level keyboard code screen will be presented to the user. +; Valid keys are ENTER, ESC, F1, F3, cursor up/down. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +KEYBOARD_SCREEN: ;AN000; + .IF < N_KYB_LOAD eq E_KYB_LOAD_ERR > ;AN000; if KEYB load status is error + .THEN ;AN000; + INIT_VAR N_KYB_LOAD, E_KYB_LOAD_UND ;AN000; set KEYB loaded status = undefined + POP_HEADING ;AN000; goto previous screen + .ENDIF ;AN000; + ; + .IF < N_KYBD_VAL eq E_KYBD_VAL_NO > ;AN000; if keyboard id not valid + .THEN ;AN000; + GOTO LOAD_KEYBOARD ;AN000; goto load specified kybd id + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_KEYBOARD ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_KYB_1, 0 ;AN000; init 1st scroll list + INIT_SCROLL SCR_KYB_2, 0 ;AN000; init 2nd scroll list + DISPLAY_PANEL ;AN000; display KEYBOARD panel + ; + .IF < N_KYBD_LIST eq E_KYBD_LIST_1 > ;AN000; if keyboard is in list 1 + .THEN ;AN000; + GET_SCROLL SCR_KYB_1,I_KEYBOARD, FK_SCROLL ;AN000; highlight kybd in list 1 & get new choice + .ELSE ;AN000; else + GET_SCROLL SCR_KYB_2,I_KEYBOARD, FK_SCROLL ;AN000; highlight kybd in list 2 & get new choice + .ENDIF ;AN000; + ; + .REPEAT ;AN000; repeat code block: CASS cannot do this automatically + .IF < N_USER_FUNC eq UPARROW > near ;AN000; if user entered cursor up + .THEN ;AN000; + .IF < N_KYBD_LIST eq E_KYBD_LIST_1 > near ;AN000; if kybd list = 1 + .THEN ;AN000; + INIT_VAR N_KYBD_LIST, E_KYBD_LIST_2 ;AN000; set kybd list = 2 + GET_SCROLL SCR_KYB_2,KYBD_B_ITEMS,FK_SCROLL;AN000; point to last item in list 2 + .ELSE near ;AN000; else + INIT_VAR N_KYBD_LIST, E_KYBD_LIST_1 ;AN000; set kybd list = 1 + GET_SCROLL SCR_KYB_1,KYBD_A_ITEMS,FK_SCROLL;AN000; point to last item in list 1 + .ENDIF ;AN000; + .ELSEIF < N_USER_FUNC EQ DNARROW > near ;AN000; else if user entered cursor down + .THEN ;AN000; + .IF < N_KYBD_LIST eq E_KYBD_LIST_1 > near ;AN000; if kybd list = 1 + .THEN ;AN000; + INIT_VAR N_KYBD_LIST, E_KYBD_LIST_2 ;AN000; set kybd list = 2 + GET_SCROLL SCR_KYB_2, 1, FK_SCROLL ;AN000; point to 1st item in list 2 + .ELSE near ;AN000; else + INIT_VAR N_KYBD_LIST, E_KYBD_LIST_1 ;AN000; set kybd list = 1 + GET_SCROLL SCR_KYB_1, 1, FK_SCROLL ;AN000; point to 1st item in list 1 + .ENDIF ;AN000; + .ELSE near ;AN000; else + .LEAVE ;AN000; break away from repeat loop + .ENDIF ;AN000; + .UNTIL ;AN000; end of repeat block + ; + .IF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD I_KEYBOARD, I_USER_INDEX ;AN000; save new kybd + PUSH_HEADING KEYBOARD_SCREEN ;AN000; save screen address on SELECT STACK + GET_KEYBOARD N_KYBD_LIST,I_KEYBOARD,S_KEYBOARD,N_KYBD_ALT ;AN000; get keyboard code + GOTO ALT_KYB_SCREEN ;AN000; goto next screen (ALT_KYBD) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ENTER or ESC, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �ALT_KYB_SCREEN � +; � � +; �������������������������������������� +; +; The ALTERNATE KEYBOARD CODE screen is presented if the selected keyboard +; has different keyboard layouts. +; The screen allows the user to enter the desired keyboard when the +; language supports different keyboard layouts. The following languages +; have different keyboard layouts: +; French +; Italian +; UK English +; Valid keys are ENTER, ESC, F1, F3, cursor up/down. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ALT_KYB_SCREEN: ;AN000; + .IF < N_KYB_LOAD eq E_KYB_LOAD_ERR > ;AN000; if KEYB load status is error + .THEN ;AN000; + POP_HEADING ;AN000; goto previous screen + .ENDIF ;AN000; + ; + .IF < N_KYBD_ALT eq E_KYBD_ALT_NO > ;AN000; if no alternate keyboard + .THEN ;AN000; + GOTO LOAD_KEYBOARD ;AN000; goto load specified kybd id + .ENDIF ;AN000; + ; + GET_ALT_KYBD_TABLE S_KEYBOARD, ALT_TAB_PTR, ALT_KYB_ID ;AN000; get alternate keyboard id + ; + .SELECT ;AN000; + ; + .WHEN < ALT_KYB_ID eq ALT_FRENCH > ;AN000; kybd id = French + INIT_VAR N_WORD_1, SCR_FR_KYB ;AN000; set scroll list id = French + ; + .WHEN < ALT_KYB_ID eq ALT_ITALIAN > ;AN000; kybd id = Italian + INIT_VAR N_WORD_1, SCR_IT_KYB ;AN000; set scroll list id = Italian + ; + .OTHERWISE ;AN000; kybd id = UK English + INIT_VAR N_WORD_1, SCR_UK_KYB ;AN000; set scroll list id = UK English + ; + .ENDSELECT ;AN000; + ; + COMP_BYTES ALT_KYB_ID, ALT_KYB_ID_PREV ;AN000; if current alt kyb id different + .IF nz ;AN000; + .THEN ;AN000; + INIT_VAR I_KYBD_ALT, 2 ;AN090; set index into list = 1 + COPY_BYTE ALT_KYB_ID_PREV, ALT_KYB_ID ;AN000; set prev id = current id + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_KYBD_ALT ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL N_WORD_1, 0 ;AN000; init scroll list + DISPLAY_PANEL ;AN000; display ALTERNATE keyboard panel + ; + GET_SCROLL N_WORD_1, I_KYBD_ALT, FK_SCROLL ;AN000; get new alt kyb id + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD I_KYBD_ALT, I_USER_INDEX ;AN000; save new alternate keyboard + PUSH_HEADING ALT_KYB_SCREEN ;AN000; push screen address on SELECT STACK + GET_ALT_KEYBOARD ALT_TAB_PTR,ALT_KYB_ID,I_KYBD_ALT,S_KYBD_ALT ;AN000;get alternate keyboard code + GOTO LOAD_KEYBOARD ;AN000; goto load specified kybd id + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; � � � � � � � � � � � � � � � � � � � +; � LOAD_KEYBOARD � +; +; � This will execute the keyboard � +; program to load the requested +; � keyboard routine. � +; � � � � � � � � � � � � � � � � � � � +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +LOAD_KEYBOARD: ;AN000; + .IF < N_KYBD_LIST eq E_KYBD_LIST_2 > and ;AN000; if kybd is none + .IF < I_KEYBOARD eq KYBD_B_ITEMS > ;AN000; + .THEN ;AN000; + INIT_VAR N_KYBD_VAL, E_KYBD_VAL_DEF ;AN000; set kybd id = default id + .ENDIF ;AN000; + ; + .IF < N_KYBD_VAL eq E_KYBD_VAL_YES > near ;AN000; if kybd id is valid + .THEN ;AN000; + .IF < N_KYBD_ALT eq E_KYBD_ALT_NO > ;AN000; if alt kybd not valid + .THEN ;AN000; + COPY_STRING S_STR120_1,M_STR120_1,S_KEYBOARD;AN000; set par = kybd id + .ELSE ;AN000; else + COPY_STRING S_STR120_1,M_STR120_1,S_KYBD_ALT;AN000; set par = alt kybd id + .ENDIF ;AN000; + INIT_VAR N_WORD_1, E_KYB_LOAD_SUC ;AN000; + .ELSE ;AN000; + COPY_STRING S_STR120_1,M_STR120_1,S_US ;AN000; + INIT_VAR N_WORD_1, E_KYB_LOAD_US ;AN000; + .ENDIF ;AN000; + ; + .IF < N_KYB_LOAD eq E_KYB_LOAD_US > and ;AN000; + .IF < N_WORD_1 eq E_KYB_LOAD_US > ;AN000; + .THEN ;AN000; + .ELSE near ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT this includes support for PC Convertible (SEH) + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + CALL HOOK_INT_24 ;AN000; + EXEC_PROGRAM S_KEYB,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; load specified kybd id + .IF < MEM_SIZE eq 256 > ;AN063;SEH + CALL GET_OVERLAY ;AN063;SEH + .ENDIF ;AN063;SEH + .IF < EXEC_ERR eq TRUE > ;AC063;SEH ;AN000; + .THEN ;AN000; + HANDLE_ERROR ERR_KEYB,E_RETURN ;AN000; + INIT_VAR N_KYB_LOAD, E_KYB_LOAD_ERR ;AN000; + POP_HEADING ;AN000; + .ENDIF ;AN000; + CALL RESTORE_INT_24 ;AN000; + COPY_WORD N_KYB_LOAD, N_WORD_1 ;AN000; + ; + .IF < MEM_SIZE eq 256 > and ;AC063;SEH ;AN000;DT + .IF < N_DISKETTE_A ne E_DISKETTE_720 > ;AN063;SEH + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 ;AN000;JW Insert the INSTALL diskette + .ENDIF ;AN000;DT + ; + .ENDIF ;AN000; + ; + .IF < N_KYBD_LIST eq E_KYBD_LIST_2 > and ;AN000; if kybd is US ENGLISH JW + .IF < I_KEYBOARD eq 8 > ;AN000; JW + .THEN ;AN000; JW + INIT_VAR N_KYBD_VAL, E_KYBD_VAL_YES ;AN000; set kybd id = US KEYBOARD JW + .ENDIF ;AN000; JW + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �DEST_DRIVE_SCREEN � +; � � +; �������������������������������������� +; +; The DESTINATION DRIVE screen is presented when there is an option for +; the destination drive. Possible options are: +; B or C +; A or C +; Valid keys are ENTER, ESC, F1, F3, cursor up/down, numeric 1 to 2. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DEST_DRIVE_SCREEN: ;AN000; + .IF < N_DEST_DRIVE eq E_DEST_SELECT > ;AN000; if default destination drive + .THEN ;AN000; + GOTO DOS_LOC_SCREEN ;AN000; goto next screen (DOS_LOC) + .ENDIF ;AN000; + ; + .IF < N_DRIVE_OPTION eq E_OPTION_B_C > ;AN111;JW + INIT_VAR N_WORD_1, SCR_DEST_B_C ;AN111;JW + .ELSE ;AN111;JW + INIT_VAR N_WORD_1, SCR_DEST_A_C ;AN111;JW + .ENDIF ;AN111;JW + ; + INIT_PQUEUE PAN_DEST_DRIVE ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL N_WORD_1, I_DEST_DRIVE ;AN000; init scroll list + DISPLAY_PANEL ;AN000; display DEST_DRIVE panel + ; + GET_SCROLL N_WORD_1,I_DEST_DRIVE,FK_SCROLL ;AN000; get new install destination + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + .IF < N_DRIVE_OPTION eq E_OPTION_A_C > and ;AN111;JW + .IF < I_USER_INDEX eq 2 > ;AN111;JW + INIT_VAR I_DEST_DRIVE, E_DEST_DRIVE_A ;AN111;JW + .ELSE ;AN111;JW + COPY_WORD I_DEST_DRIVE, I_USER_INDEX ;AN000; save new install destination drive + .ENDIF ;AN111;JW + PUSH_HEADING DEST_DRIVE_SCREEN ;AN000; save screen address on the SELECT STACK + GOTO DOS_LOC_SCREEN ;AN000; goto the next screen (DOS_LOC) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC OR F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT2A.ASM b/v4.0/src/SELECT/SELECT2A.ASM new file mode 100644 index 0000000..f253a3f --- /dev/null +++ b/v4.0/src/SELECT/SELECT2A.ASM @@ -0,0 +1,381 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT2A.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT2A.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the -A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; CHANGE HISTORY: +; +; mrw0 6/16/88 Added panel for shell selection... +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; Dummy data segment + EXTRN SEG_LOC:WORD ;AN000; + EXTRN NAMES_OFF:WORD ;AN000; + EXTRN N_PRN_NAMES:WORD ;AN000; + EXTRN MAX_NAME:WORD ;AN000; + EXTRN SIZE_NAMES:ABS ;AN000; +DATA ENDS ;AN000; + ; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; +.LIST ;AN000; + PUBLIC DOS_LOC_SCREEN ;AN000; + PUBLIC PRINTER_SCREEN ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN INSTALL_ERROR:NEAR ;AN000; + EXTRN EXIT_DOS:NEAR ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; + ; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN INTRO_SCREEN:NEAR ;AN000; + EXTRN choose_shell_screen:NEAR ;mrw0 ;AC020;SEH +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �DOS_LOC_SCREEN � +; � � +; �������������������������������������� +; +; The DOS LOCATION screen is presented only if DOS is to be installed +; on drive C:. +; The maximum length of the install path will be limited to 40 characters. +; This restriction is imposed so that when generating commands +; for the CONFIG.SYS and AUTOEXEC.BAT files, the command line length will not +; exceed 128 characters. +; When the screen is presented for the first time, the default install +; path displayed will be "DOS". On subsequent presentations, the user +; selected path will be displayed. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters A to Z. +;?????????????????????????????update????????????????????????????????? +; The Functional Specification dated 5 May 1987, states that the APPEND +; and PATH commands will be generated if the user selected to minimize workspace +; or maximize workspace but not if the user selected balance workspace. Since +; this assumption does not seem logical, the check has been revised to +; generate the commands if the install destination is drive C:. Also, the +; PC/DOS parameters screen does not check for the workspace definition. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DOS_LOC_SCREEN: ;AN000; + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AN111; if install destination is drive A: or B: JW + .THEN ;AN000; + INIT_VAR F_PROMPT, E_PROMPT_NO ;AN000; set prompt = no + INIT_VAR F_PATH, E_PATH_NO ;AN000; set path = no + INIT_VAR F_APPEND, E_APPEND_NO ;AN000; set append = no + GOTO PRINTER_SCREEN ;AN000; goto next screen (PRINTER) + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_DOS_LOC ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_DOS_LOC,S_DOS_LOC,M_DOS_LOC ;AN000; + .IF < N_DISK1_MODE ne E_DISK1_INSTALL > ;AN000; if this is not a new fixed disk JW + .THEN ;AN000; then JW + INIT_SCROLL SCR_COPY_DEST,I_DESTINATION ;AN000; initialize destination choice JW + INIT_SCROLL_COLOUR SCR_COPY_DEST,2 ;AN026; set field to not active color + .ENDIF ;AN000; endif JW + DISPLAY_PANEL ;AN000; display DOS_LOC panel + ; + COPY_STRING S_STR120_1,M_STR120_1,S_DOS_LOC ;AN000; + ; +GET_DOS_LOCATION: ;AN000; + GET_STRING STR_DOS_LOC,S_STR120_1,M_DOS_LOC,FK_TAB ;AN000;get new install path + ; + PROCESS_F3 ;AN000; if user entered F3, exit to DOS + PROCESS_ESC ;AN000; if user entered ESC, goto previous screen + ; + COPY_STRING S_STR120_1,M_STR120_1,S_USER_STRING ;AN000; + CHECK_PATH S_STR120_1,0, 0 ;AN000; + .IF nc near ;AN000; if path is valid + .THEN ;AN000; + COPY_STRING S_DOS_LOC,M_DOS_LOC,S_USER_STRING ;AN000; save new DOS install path + COPY_STRING S_STR120_2, M_STR120_2, S_INSTALL_PATH;AN000;save old install path + MERGE_STRING S_INSTALL_PATH,M_INSTALL_PATH,S_DEST_DRIVE,S_DOS_LOC ;AN000; add 'C:\' to install path + COMPARE_STRINGS S_INSTALL_PATH, S_STR120_2 ;AN000; compare old and new paths + .IF c ;AN000; if paths different + .THEN ;AN000; + INIT_VAR F_APPEND, E_APPEND_YES ;AN000; set APPEND = yes + COPY_STRING S_APPEND,M_APPEND,S_INSTALL_PATH;AN000; set new APPEND path + INIT_VAR F_PATH, E_PATH_YES ;AN000; set PATH = yes + COPY_STRING S_PATH, M_PATH, S_INSTALL_PATH ;AN000; set new DOS path + .ELSEIF < S_APPEND eq 0 > ;AN000; + .THEN ;AN000; + COPY_STRING S_APPEND,M_APPEND,S_INSTALL_PATH;AN000; + INIT_VAR F_APPEND, E_APPEND_YES ;AN000; + .ENDIF ;AN000; + .IF < I_WORKSPACE eq E_WORKSPACE_MIN > ;AN000; if workspace option = minimize + .THEN ;AN000; + INIT_VAR S_APPEND, 0 ;AN000; set APPEND= null + .ENDIF ;AN000; + INIT_VAR F_PROMPT, E_PROMPT_YES ;AN000; set PROMPT = yes + .ELSE ;AN000; else + HANDLE_ERROR ERR_BAD_PATH, E_RETURN ;AN000; pop error message + GOTO GET_DOS_LOCATION ;AN000; goto get DOS location again + .ENDIF ;AN000; + ; + .IF < N_DISK1_MODE ne E_DISK1_INSTALL > AND ;AN000; if this is not a new fixed disk JW + .IF < N_USER_FUNC eq E_TAB > ;AN000; if user tabbed to the scroll field JW + .THEN ;AN000; JW + GET_SCROLL SCR_COPY_DEST,I_DESTINATION,FK_TAB ;AN000; JW + PROCESS_F3 ;AN000; if user entered F3, exit to DOS JW + PROCESS_ESC ;AN000; JW + COPY_WORD I_DESTINATION, I_USER_INDEX ;AN000; save new install destination drive JW + .IF < N_USER_FUNC eq E_TAB > ;AN000; if user entered ESC JW + .THEN ;AN000; JW + SET_SCROLL SCR_COPY_DEST,I_DESTINATION ;AN026; Set to not active + GOTO GET_DOS_LOCATION ;AC051;SEH ;AN000 Go get dos location JW + .ENDIF ;AN000; JW + .ENDIF ;AN000; JW + PUSH_HEADING DOS_LOC_SCREEN ;AC051;SEH ;AN000; save screen address on SELECT STACK +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �PRINTER_SCREEN � +; � � +; �������������������������������������� +; +; The PRINTER SCREEN is always presented. +; The screen allows the user to indicate the number of printers attached. +; Valid keys are ENTER, ESC, F1, F3 and numeric 0 to 7. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PRINTER_SCREEN: ;AN000; + .IF < N_PARALLEL eq 0 > and ;AN000; if zero parallel and + .IF < N_SERIAL eq 0 > ;AN000; and zero serial printers + .THEN ;AN000; + INIT_VAR F_GRAPHICS, E_GRAPHICS_NO ;AN000; set GRAPHICS = no JW + GOTO choose_shell_screen ;mrw0 ;AC020;SEH goto next screen + .ENDIF ;AN000; + ; + ;;;display panel to get number of printers ; + INIT_PQUEUE PAN_PRINTER ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_NUMERIC NUM_PRINTER,N_NUMPRINT,MAX_NUMPRINT,S_STR120_1;AN000; + DISPLAY_PANEL ;AN000; + ; + ;;;get number of printers ; + GET_NUMERIC NUM_PRINTER,N_NUMPRINT,MIN_NUMPRINT,MAX_NUMPRINT,FK_TEXT,S_STR120_1;AN000; + ; + ;;;save number of printers and goto next screen ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD N_NUMPRINT, N_USER_NUMERIC ;AN000; save number of printers + PUSH_HEADING PRINTER_SCREEN ;AN000; save screen address on SELECT STACK + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �PRINTER_TYPE_SCREEN � +; � � +; �������������������������������������� +; +; Get type of printer +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PRINTER_TYPE_SCREEN: ;AN000; + .IF < N_NUMPRINT eq MIN_NUMPRINT > ;AN000; if zero printers specified + .THEN ;AN000; + INIT_VAR F_GRAPHICS, E_GRAPHICS_NO ;AN000; set GRAPHICS = no JW + GOTO choose_shell_screen ;mrw0 ;AC020; SEH goto next screen + .ENDIF ;AN000; + ; + GET_PRINTER_TITLES S_PRINT_FILE ;AN000; read printer titles from SELECT.PRT + .IF c ;AN000; if error reading file + .THEN ;AN000; + INIT_VAR N_NUMPRINT, MIN_NUMPRINT ;AN000; set no of printers = 0 + HANDLE_ERROR ERR_BAD_PFILE, E_RETURN ;AN000; popup error message + GOTO choose_shell_screen ;mrw0 ;AC020; SEH goto next screen + .ENDIF ;AN000; + ; + INIT_VAR N_COUNTER, 1 ;AN000; set printer no = 1 + .IF < I_WORKSPACE ne E_WORKSPACE_MIN > ;AN014; SEH if not minimum DOS workspace + .THEN ;AN014; + INIT_VAR F_GRAPHICS, E_GRAPHICS_YES ;AN000; set GRAPHICS = yes SEH + .ENDIF ;AN014; SEH + ; +GET_PRINTER_TYPE: ;AN000; repeat loop to get printer info + ; + .IF < N_COUNTER eq 0 > ;AN000; if printer no = zero + .THEN ;AN000; + RELEASE_PRINTER_INFO ;AN000; release memory + .IF c ;AN000; + .THEN ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + POP_HEADING ;AN000; goto previous screen + .ENDIF ;AN000; + ; + .SELECT ;AN000; get printer no sub panel + ; + .WHEN < N_COUNTER eq 1 > ;AN000; + INIT_VAR N_BYTE_1, '1' ;AC025; + ; + .WHEN < N_COUNTER eq 2 > ;AN000; + INIT_VAR N_BYTE_1, '2' ;AC025; + ; + .WHEN < N_COUNTER eq 3 > ;AN000; + INIT_VAR N_BYTE_1, '3' ;AC025; + ; + .WHEN < N_COUNTER eq 4 > ;AN000; + INIT_VAR N_BYTE_1, '4' ;AC025; + ; + .WHEN < N_COUNTER eq 5 > ;AN000; + INIT_VAR N_BYTE_1, '5' ;AC025; + ; + .WHEN < N_COUNTER eq 6 > ;AN000; + INIT_VAR N_BYTE_1, '6' ;AC025; + ; + .OTHERWISE ;AN000; + INIT_VAR N_BYTE_1, '7' ;AC025; + ; + .ENDSELECT ;AN000; + ; + GET_PRINTER_PARAMS N_COUNTER, 0, N_RETCODE ;AN000; based on printer # + ; + ;;;N_BYTE_1 = printer number ; + INIT_CHAR N_BYTE_1, E_DISK_ROW, E_DISK_COL, SUB_PRINTER_1 ;AN025; display the printer number + INIT_PQUEUE PAN_PRT_TYPE ;AN000; initialize queue + PREPARE_PANEL SUB_PRINTER_1 ;AC025; printer no + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL_W_LIST SCR_PRT_TYPE,SEG_LOC,NAMES_OFF,N_PRN_NAMES,SIZE_NAMES,MAX_NAME,I_PRINTER;AN000; + DISPLAY_PANEL ;AN000; + ; + GET_SCROLL SCR_PRT_TYPE,I_PRINTER,FK_SCROLL;AN000; get printer type + ; + PROCESS_F3 ;AN000; take action if F3 entered + ; + .IF < N_USER_FUNC eq E_ESCAPE > ;AN000; if user entered ESC + .THEN ;AN000; + DEC N_COUNTER ;AN000; dec printer number + GOTO GET_PRINTER_TYPE ;AN000; goto previous printer + .ENDIF ;AN000; + ; + COPY_WORD I_PRINTER, I_USER_INDEX ;AN000; save printer type + ; + GET_PRINTER_INFO I_PRINTER ;AN000; get printer info from SELECT.PRT + .IF c ;AN000; if error + .THEN ;AN000; + HANDLE_ERROR ERR_BAD_PPRO, E_RETURN ;AN000; popup error message + GOTO GET_PRINTER_TYPE ;AN000; goto get printer type + .ENDIF ;AN000; + ; + .IF < N_PRINTER_TYPE eq E_PARALLEL > and ;AN000; + .IF < N_PARALLEL eq 0 > ;AN000; + .THEN ;AN000; + HANDLE_ERROR ERR_PRT_NO_HDWR, E_RETURN ;AN000; + GOTO GET_PRINTER_TYPE ;AN000; + .ENDIF ;AN000; + ; + .IF < N_PRINTER_TYPE eq E_SERIAL > and ;AN000; + .IF < N_SERIAL eq 0 > ;AN000; + .THEN ;AN000; + HANDLE_ERROR ERR_PRT_NO_HDWR, E_RETURN ;AN000; + GOTO GET_PRINTER_TYPE ;AN000; + .ENDIF ;AN000; + ; + .SELECT ;AN000; + ; + .WHEN < N_PRINTER_TYPE eq E_PARALLEL > near ;AN000; if parallel printer + INIT_CHAR N_BYTE_1, E_DISK_ROW, E_DISK_COL, SUB_PRINTER_1 ;AN025; display the printer number + INIT_PQUEUE PAN_PARALLEL ;AN000; initialize queue + PREPARE_PANEL SUB_PRINTER_1 ;AC025; + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL_W_LIST SCR_ACC_PRT,SEG_LOC,NAMES_OFF,N_PRN_NAMES,SIZE_NAMES,MAX_NAME,I_PRINTER;AN000; + INIT_SCROLL_W_NUM SCR_PARALLEL,N_PARALLEL,I_PORT ;AN000; + DISPLAY_PANEL ;AN000; display panel + ; + GET_SCROLL SCR_PARALLEL, I_PORT, FK_SCROLL ;AN000; + COPY_WORD I_PORT, I_USER_INDEX ;AN000; + ; + .OTHERWISE near ;AN000; if serial printer + ; + INIT_CHAR N_BYTE_1, E_DISK_ROW, E_DISK_COL, SUB_PRINTER_1 ;AN025; display the printer number + INIT_PQUEUE PAN_SERIAL ;AN000; initialize queue + PREPARE_PANEL SUB_PRINTER_1 ;AN025; + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL_W_LIST SCR_ACC_PRT,SEG_LOC,NAMES_OFF,N_PRN_NAMES,SIZE_NAMES,MAX_NAME,I_PRINTER;AN000; + INIT_SCROLL_W_NUM SCR_SERIAL,N_SERIAL,I_PORT ;AN000; + INIT_SCROLL SCR_PRT_REDIR, I_REDIRECT ;AN000; + INIT_SCROLL_COLOUR SCR_PRT_REDIR, 2 ;AN000; + DISPLAY_PANEL ;AN000; + ; + .REPEAT ;AN000; + SET_SCROLL SCR_PRT_REDIR, I_REDIRECT ;AN000; + GET_SCROLL SCR_SERIAL, I_PORT, FK_TAB ;AN000; + COPY_WORD I_PORT, I_USER_INDEX ;AN000; + .IF < N_USER_FUNC eq E_TAB > near ;AN000; + .THEN ;AN000; + SET_SCROLL SCR_SERIAL, I_PORT ;AN000; + GET_SCROLL SCR_PRT_REDIR,I_REDIRECT,FK_TAB ;AN000; + COPY_WORD I_REDIRECT, I_USER_INDEX ;AN000; + .ENDIF ;AN000; + ; + .UNTIL < N_USER_FUNC eq E_ENTER > or near ;AN000; + .UNTIL < N_USER_FUNC eq E_ESCAPE > or near ;AN000; + .UNTIL < N_USER_FUNC eq E_F3 > ;AN000; + ; + .ENDSELECT ;AN000; + ; + PROCESS_F3 ;AN000; + ; + .IF < N_USER_FUNC eq E_ESCAPE > ;AN000; if user entered ESC + .THEN ;AN000; + GOTO GET_PRINTER_TYPE ;AN000; goto get printer type + .ENDIF ;AN000; + SAVE_PRINTER_PARAMS N_COUNTER ;AN000; save printer parameters + INC_VAR N_COUNTER ;AN000; inc printer number + COMP_WORDS N_COUNTER, N_NUMPRINT ;AN000; if printer no > no of printers + .IF nc and ;AN000; + .IF nz ;AN000; + .THEN ;AN000; + RELEASE_PRINTER_INFO ;AN000; release memory + .IF c ;AN000; if error + .THEN ;AN000; + GOTO INSTALL_ERROR ;AN000; ::::::: + .ENDIF ;AN000; + GOTO choose_shell_screen ;mrw0 ;AC020; SEH goto next screen + .ELSE ;AN000; + GOTO GET_PRINTER_TYPE ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT3.ASM b/v4.0/src/SELECT/SELECT3.ASM new file mode 100644 index 0000000..64c46c5 --- /dev/null +++ b/v4.0/src/SELECT/SELECT3.ASM @@ -0,0 +1,286 @@ + + +PAGE 60,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT3.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT3.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the -A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; +; The following screens are contained in this module: +; - External diskette parameters +; - Review selection choice +; - Review selections for fixed disk +; - Review selections for diskette +; +; +; ;AN001; GHG changes for 0 Parallel/Serial printer ports +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; Dummy DATA Seg + EXTRN SEG_LOC:WORD ;AN000; + EXTRN NAMES_OFF:WORD ;AN000; + EXTRN N_PRN_NAMES:WORD ;AN000; + EXTRN MAX_NAME:WORD ;AN000; + EXTRN SIZE_NAMES:ABS ;AN000; +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Continuation of code ... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_SELECT:NEAR ;AN000; + EXTRN INSTALL_ERROR:NEAR ;AN000; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN DOS_PARAMETERS_SCREEN:NEAR ;AN000; + EXTRN EXIT_DOS:NEAR ;AN000; + EXTRN FIRST_DISK_SCREEN:NEAR ;AN000; + PUBLIC choose_shell_screen ;AC020; SEH +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �choose_shell_screen � +; � � +; �������������������������������������� +; +; The CHOOSE SHELL SCREEN is always presented. +; This screen allows the user to decide whether or not the DOS +; shell will be installed. +; Valid keys are ENTER, ESC, F1, F3 and numeric 1 and 2. +;---- +; Note: This screen (and, hence, all shell support) can be eradicated +; by defining the symbol NOSHELL. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +choose_shell_screen: ;AN000; +IFNDEF NOSHELL + INIT_PQUEUE PAN_choose_shell ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_choose_shell, f_shell ;AN000; + DISPLAY_PANEL ;AN000; display CHOOSE SHELL SCREEN + ; + GET_SCROLL SCR_choose_shell, f_shell, FK_SCROLL ;AN000; get new shell option + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD f_shell, I_USER_INDEX ;AN000; save new shell option + PUSH_HEADING choose_shell_screen ;AN000; save address on SELECT STACK + GOTO REVIEW_SELECTION_SCREEN ;AN000; goto the next screen (REVIEW_SELECTION) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +ENDIF +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �REVIEW_SELECTION_SCREEN � +; � � +; �������������������������������������� +; +; The REVIEW SELECTION SCREEN is always presented. +; The screen asks the user if SELECT generated choices are to be presented. +; Valid keys are ENTER, ESC, F1, F3 and numeric 1 and 2. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +REVIEW_SELECTION_SCREEN: ;AN000; + INIT_PQUEUE PAN_REVIEW ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_REVIEW, F_REVIEW ;AN000; + DISPLAY_PANEL ;AN000; display REVIEW SELECTION SCREEN + ; + GET_SCROLL SCR_REVIEW, F_REVIEW, FK_SCROLL ;AN000; get new review option + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_WORD F_REVIEW, I_USER_INDEX ;AN000; save new review option + PUSH_HEADING REVIEW_SELECTION_SCREEN ;AN000; save address on SELECT STACK + GOTO REVIEW_DISK_SCREEN ;AN000; goto the next screen (REVIEW_FUNCTIONS) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �REVIEW_DISK_SCREEN � +; � � +; �������������������������������������� +; +; The REVIEW SELECT DOS FUNCTIONS SELECTION SCREEN is presented if +; the user selected to view/change the selections generated by +; SELECT ( F_REVIEW = 2 ) +; The screen asks the user to select functions required from the +; displayed list. Functions are Code Page Switching, Expanded Memory Support, +; ANSI.SYS support, FASTOPEN support, GRAFTABL support, GRAPHICS support, +; SHARE support, and VDISK support. +; There are two versions of this screen. The screen version displayed +; will depend on whether the install destination is drive B:/A: or drive C:. +; This screen version will be presented if install destination is drive C:. +; The screen lists the parameters for which selections have been made by +; SELECT. The user may accept these choices (yes/no) +; or change them by cursoring to the parameter and pressing the SPACE key. +; The SPACE key will toggle the choice for the selected parameter. +; The cursor key is used to move to the next item on the parameter list. +; If the cursor is on the last item in the parameter list, cursor down key +; will cause the cursor to wrap around to the first item of the parameter list. +; If the cursor is on the first item in the parameter list, cursor up key +; will cause the cursor to wrap around to the last item of the parameter list. +; When the SPACE key is depressed, the current parameter value is saved in +; a temporary location. The temporary parameter values are copied to actual +; values only when the ENTER key is depressed. +; Valid keys are ENTER, ESC, F1, F3, SPACE, cursor up and cursor down. +; If a parameter is not supported due to the hardware environment, the +; choice presented to the user will be NO but internally will be stored as N/A. +; a N/A choice would not be toggled by the user and a beep would be issued +; instead. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +REVIEW_DISK_SCREEN: ;AN000; + .IF < F_REVIEW eq E_REVIEW_ACCEPT > ;AN000; if accept SELECT generated commands + .THEN ;AN000; + GOTO FIRST_DISK_SCREEN ;AN000; skip related screens + .ENDIF ;AN000; + ; + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AC000; if install to drive B: or A: JW + .THEN ;AN000; + GOTO REVIEW_DISKETTE_SCREEN ;AN000; goto disket functions screen + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_FUNC_DISK ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_FUNC_DISK, 0 ;AN000; + INIT_SUPPORT SUPPORT_STATUS,E_CPSW_C, F_CPSW ;AN000; cpsw support + INIT_SUPPORT SUPPORT_STATUS, E_XMA_C, F_XMA ;AN000; expanded memory support + INIT_SUPPORT SUPPORT_STATUS,E_ANSI_C, F_ANSI ;AN000; ANSI.SYS support + INIT_SUPPORT SUPPORT_STATUS,E_FASTOPEN_C,F_FASTOPEN;AN000; FASTOPEN support + INIT_SUPPORT SUPPORT_STATUS,E_GRAFTABL_C,F_GRAFTABL;AN000; GRAFTABL support + INIT_SUPPORT SUPPORT_STATUS,E_GRAPHICS_C,F_GRAPHICS;AN000; GRAPHICS support + INIT_SUPPORT SUPPORT_STATUS,E_SHARE_C,F_SHARE;AN000; SHARE support + INIT_SUPPORT SUPPORT_STATUS,E_SHELL_C,F_SHELL;AN000; SHELL support + INIT_SUPPORT SUPPORT_STATUS,E_VDISK_C,F_VDISK;AN000; VDISK support + INIT_SCROLL_STATUS SCR_FUNC_DISK,SUPPORT_STATUS ;AN000; + DISPLAY_PANEL ;AN000; display functions list screen + ; + INIT_VAR I_USER_INDEX, 1 ;AN000; set counter = 1 + ; + .REPEAT ;AN000; repeat code block + ; + GET_SCROLL SCR_FUNC_DISK,I_USER_INDEX,FK_REVIEW ;AN000; get new value + ; + .IF < N_USER_FUNC eq E_SPACE > ;AN000; if user entered TAB + .THEN ;AN000; + TOGGLE_SUPPORT SUPPORT_STATUS, I_USER_INDEX ;AN000; toggle support of parameter + .ELSE ;AN000; else + .LEAVE ;AN000; break from repeat loop + .ENDIF ;AN000; + ; + .UNTIL ;AN000; end of repeat loop + ; + .IF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + .THEN ;AN000; get revised values for + RET_SUPPORT SUPPORT_STATUS,E_CPSW_C, F_CPSW ;AN000; cpsw support + RET_SUPPORT SUPPORT_STATUS, E_XMA_C, F_XMA ;AN000; expanded memory support + RET_SUPPORT SUPPORT_STATUS,E_ANSI_C, F_ANSI ;AN000; ANSI.SYS support + RET_SUPPORT SUPPORT_STATUS,E_FASTOPEN_C,F_FASTOPEN;AN000; FASTOPEN support + RET_SUPPORT SUPPORT_STATUS,E_GRAFTABL_C,F_GRAFTABL;AN000; GRAFTABL support + RET_SUPPORT SUPPORT_STATUS,E_GRAPHICS_C,F_GRAPHICS;AN000; GRAPHICS support + RET_SUPPORT SUPPORT_STATUS,E_SHARE_C,F_SHARE;AN000; SHARE support + RET_SUPPORT SUPPORT_STATUS,E_SHELL_C,F_SHELL;AN000; SHELL support + RET_SUPPORT SUPPORT_STATUS,E_VDISK_C,F_VDISK;AN000; VDISK support + PUSH_HEADING REVIEW_DISK_SCREEN ;AN000; save screen address on SELECT STACK + GOTO DOS_PARAMETERS_SCREEN ;AN000; goto the next screen (DOS_PARAMETERS) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESCAPE or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �REVIEW_DISKETTE_SCREEN � +; � � +; �������������������������������������� +; +; The REVIEW SELECT DOS FUNCTIONS SELECTION SCREEN is presented if +; the user selected to view/change the selections generated by +; SELECT ( F_REVIEW = 2 ) +; This screen version will be presented if install destination is drive A:/B: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +REVIEW_DISKETTE_SCREEN: ;AN000; + INIT_PQUEUE PAN_FUNC_DISKET ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_FUNC_DISKET, 0 ;AN000; + INIT_SUPPORT SUPPORT_STATUS,E_CPSW_B, F_CPSW ;AN000; cpsw support + INIT_SUPPORT SUPPORT_STATUS,E_ANSI_B, F_ANSI ;AN000; ANSI.SYS support + INIT_SUPPORT SUPPORT_STATUS,E_GRAFTABL_B,F_GRAFTABL;AN000; GRAFTABL support + INIT_SUPPORT SUPPORT_STATUS,E_GRAPHICS_B,F_GRAPHICS;AN000; GRAPHICS support + INIT_SUPPORT SUPPORT_STATUS,E_SHELL_B,F_SHELL;AN000; SHELL support + INIT_SUPPORT SUPPORT_STATUS,E_VDISK_B,F_VDISK;AN000; VDISK support + INIT_SCROLL_STATUS SCR_FUNC_DISKET, SUPPORT_STATUS ;AN000; + DISPLAY_PANEL ;AN000; display functions list screen + ; + INIT_VAR I_USER_INDEX, 1 ;AN000; set counter = 1 + ; + .REPEAT ;AN000; repeat code block + ; + GET_SCROLL SCR_FUNC_DISKET,I_USER_INDEX,FK_REVIEW;AN000; get new value + ; + .IF < N_USER_FUNC eq E_SPACE > ;AN000; if user entered TAB + .THEN ;AN000; + TOGGLE_SUPPORT SUPPORT_STATUS, I_USER_INDEX ;AN000; toggle support of parameter + .ELSE ;AN000; + .LEAVE ;AN000; else + .ENDIF ;AN000; break from loop + ; + .UNTIL ;AN000; end of repeat block + ; + .IF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + .THEN ;AN000; get revised values + RET_SUPPORT SUPPORT_STATUS,E_CPSW_B, F_CPSW ;AN000; cpsw support + RET_SUPPORT SUPPORT_STATUS,E_ANSI_B, F_ANSI ;AN000; ANSI.SYS support + RET_SUPPORT SUPPORT_STATUS,E_GRAFTABL_B,F_GRAFTABL;AN000; GRAFTABL support + RET_SUPPORT SUPPORT_STATUS,E_GRAPHICS_B,F_GRAPHICS;AN000; GRAPHICS support + RET_SUPPORT SUPPORT_STATUS,E_SHELL_B,F_SHELL;AN000; SHELL support + RET_SUPPORT SUPPORT_STATUS,E_VDISK_B,F_VDISK;AN000; VDISK support + PUSH_HEADING REVIEW_DISKETTE_SCREEN ;AN000; save screen address onto SELECT STACK + GOTO DOS_PARAMETERS_SCREEN ;AN000; goto the next screen (DOS_PARAMETERS) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or E3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT4.ASM b/v4.0/src/SELECT/SELECT4.ASM new file mode 100644 index 0000000..bd56ddd --- /dev/null +++ b/v4.0/src/SELECT/SELECT4.ASM @@ -0,0 +1,438 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT4.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT4.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; +; +; Module contains code for : +; - DOS parameters screen +; - SHELL parameters screen +; - FASTOPEN parameters screen +; - SHARE screen +; - GRAPHICS parameter screen +; - EXPANDED MEMORY parameters screen +; +; +; CHANGE HISTORY: +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; +HLP_OVER EQU 00010000B ;AN000; +ICB_OUT EQU 0000000100000000B ;AN000;display default and accept input + ; + PUBLIC DOS_PARAMETERS_SCREEN ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN FIRST_DISK_SCREEN:NEAR ;AN000; + EXTRN VDISK_SCREEN:NEAR ;AN000; + EXTRN EXIT_DOS:NEAR ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �DOS_PARAMETERS_SCREENS � +; � � +; �������������������������������������� +; +; The DOS PARAMETERS SCREEN is presented if the user selected to +; view/change the selections generated by SELECT ( F_REVIEW = 2 ). +; The screen gets various DOS parameters (PATH, APPEND, PROMPT). +; The TAB key is used to move to the next item on the parameter list. +; If the cursor is on the last item in the parameter list, TAB key +; will cause the cursor to wrap around to the first item of the parameter list. +; When the TAB key is depressed, the current parameter value is saved in +; a temporary location. The temporary parameter values are copied to actual +; values only when the ENTER key is depressed. +; Valid keys are ENTER, ESC, F1, F3, TAB and ASCII characters. +; Since the DOS parameters APPEND and PATH are only useful for hard +; disk based systems, an additional check of install to drive C: has been +; included. This check is not specified in the Functional Specification. +; PROMPT parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DOS_PARAMETERS_SCREEN: ;AN000; if user accepts choices + .IF < F_REVIEW eq E_REVIEW_ACCEPT > ;AN000; + .THEN ;AN000; + GOTO FIRST_DISK_SCREEN ;AN000; goto FIRST_DISK_SCREEN + .ENDIF ;AN000; + ; + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AC000; if install to drive B: or A: JW + .THEN ;AN000; + GOTO SHELL_SCREEN ;AN000; goto next screen + .ENDIF ;AN000; + ; + COPY_STRING S_STR120_1, M_STR120_1, S_PATH ;AN000; copy PATH to temp location + COPY_STRING S_STR40, M_STR40, S_APPEND_P ;AN000; copy APPEND parameters to temp location JW + COPY_STRING S_STR120_2, M_STR120_2,S_APPEND ;AN000; copy APPEND to temp location + COPY_STRING S_STR120_3, M_STR120_3,S_PROMPT ;AN000; copy PROMPT to temp location + ; + INIT_PQUEUE PAN_DOS_PARAM ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_DOS_PATH,S_STR120_1, M_PATH ;AN000; display current PATH value + INIT_STRING STR_DOS_APPEND_P,S_STR40,M_APPEND_P ;AN000; display current APPEND parameters value JW + INIT_STRING STR_DOS_APPEND,S_STR120_2,M_APPEND ;AN000; display current APPEND value + INIT_STRING STR_DOS_PROMPT,S_STR120_3,M_PROMPT ;AN000; display current PROMPT value + DISPLAY_PANEL ;AN000; display PC/DOS parameters panel + ; + INIT_VAR N_COUNTER, 1 ;AN000; set counter = 1 + ; +GET_PARAMETERS: ;AN000; + ; + .REPEAT ;AN000; repeat code block + ; + .SELECT ;AN000; + ; + .WHEN < N_COUNTER eq 1 > ;AN000; + GET_STRING STR_DOS_PATH,S_STR120_1,M_PATH,FK_TAB ;AN000; get user parameters for PATH + COPY_STRING S_STR120_1,M_STR120_1,S_USER_STRING ;AN000; save parameter in temp location + ; + .WHEN < N_COUNTER eq 2 > ;AN000; JW + GET_STRING STR_DOS_APPEND_P,S_STR40,M_APPEND_P,FK_TAB ;AN000; get user parameters for APPEND JW + COPY_STRING S_STR40,M_STR40,S_USER_STRING ;AN000; save parameter in temp location JW + ; + .WHEN < N_COUNTER eq 3 > ;AN000; + GET_STRING STR_DOS_APPEND,S_STR120_2,M_APPEND,FK_TAB ;AN000; get user path for APPEND + COPY_STRING S_STR120_2,M_STR120_2,S_USER_STRING ;AN000; save parameter in temp location + ; + .OTHERWISE ;AN000; + GET_STRING STR_DOS_PROMPT,S_STR120_3,M_PROMPT,FK_TAB ;AN000; get user parameters for PROMPT + COPY_STRING S_STR120_3,M_STR120_3,S_USER_STRING ;AN000; save parameter in temp location + ; + .ENDSELECT ;AN000; + ; + INC_VAR N_COUNTER ;AN000; inc counter + ; + .IF < N_COUNTER a 4 > ;AN000; if counter > 3 + .THEN ;AN000; + INIT_VAR N_COUNTER, 1 ;AN000; set counter = 1 + .ENDIF ;AN000; + ; + .UNTIL < N_USER_FUNC eq E_ENTER > or near ;AN000; break loop if ENTER entered + .UNTIL < N_USER_FUNC eq E_ESCAPE > or near ;AN000; or ESCAPE entered + .UNTIL < N_USER_FUNC eq E_F3 > near ;AN000; or F3 entered + ; + PROCESS_ESC ;AN000; + PROCESS_F3 ;AN000; + ; + CHECK_DOS_PATH S_STR120_1 ;AN000; check PATH path + .IF c ;AN000; + .THEN ;AN000; + HANDLE_ERROR ERR_BAD_PATH, E_RETURN ;AN000; + INIT_VAR N_COUNTER, 1 ;AN000; + GOTO GET_PARAMETERS ;AN000; + .ENDIF ;AN000; + ; + CHECK_DOS_PATH S_STR120_2 ;AN000; check APPEND path + .IF c ;AN000; + .THEN ;AN000; + HANDLE_ERROR ERR_BAD_PATH, E_RETURN ;AN000; + INIT_VAR N_COUNTER,2 ;AN000; + GOTO GET_PARAMETERS ;AN000; + .ENDIF ;AN000; + ; + COPY_STRING S_PATH, M_PATH, S_STR120_1 ;AN000; save PATH parameter + COPY_STRING S_APPEND_P, M_APPEND_P, S_STR40 ;AN000; save APPEND parameter JW + COPY_STRING S_APPEND, M_APPEND, S_STR120_2 ;AN000; save APPEND path + COPY_STRING S_PROMPT, M_PROMPT, S_STR120_3 ;AN000; save PROMPT parameter + PUSH_HEADING DOS_PARAMETERS_SCREEN ;AN000; save screen address on SELECT STACK + GOTO SHELL_SCREEN ;AN000; goto the next screen (SHELL) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �SHELL_SCREEN � +; � � +; �������������������������������������� +; +; The SHELL PARAMETERS SCREEN is presented if the user selected to +; install SHELL support and the user wants to view/change parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets the parameters for SHELL. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SHELL_SCREEN: ;AN000; + .IF < F_SHELL eq E_SHELL_NO > ;AN000; if SHELL support is not required + .THEN ;AN000; + GOTO FASTOPEN_SCREEN ;AN000; goto the next screen (KSAM) + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_SHELL ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_SHELL,S_SHELL,M_SHELL ;AN000; get SHELL parameters + DISPLAY_PANEL ;AN000; display SHELL panel + ; + GET_STRING STR_SHELL,S_SHELL,M_SHELL,FK_TEXT ;AN000; get SHELL parameters + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_STRING S_SHELL, M_SHELL, S_USER_STRING ;AN000; save new SHELL parameters + PUSH_HEADING SHELL_SCREEN ;AN000; save screen address on SELECT STACK + GOTO FASTOPEN_SCREEN ;AN000; goto the next screen (KSAM) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �FASTOPEN_SCREEN � +; � � +; �������������������������������������� +; +; The FASTOPEN PARAMETERS SCREEN is presented if the user selected to +; install FASTOPEN support and the user wants to view/change the parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets parameters for the FASTOPEN command. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +FASTOPEN_SCREEN: ;AN000; + .IF < F_FASTOPEN eq E_FASTOPEN_NO > or ;AN000; if FASTOPEN support not required + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AC000;JW + .THEN ;AN000; + GOTO SHARE_SCREEN ;AN000; goto next screen (SHARE) + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_FASTOPEN ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_FASTOPEN,S_FASTOPEN,M_FASTOPEN ;AN000; get new parameters for FASTOPEN + DISPLAY_PANEL ;AN000; display FASTOPEN panel + ; + GET_STRING STR_FASTOPEN,S_FASTOPEN,M_FASTOPEN,FK_TEXT ;AN000; get new parameters for FASTOPEN + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_STRING S_FASTOPEN,M_FASTOPEN,S_USER_STRING ;AN000;save new parameters for FASTOPEN + PUSH_HEADING FASTOPEN_SCREEN ;AN000; save screen address on SELECT STACK + GOTO SHARE_SCREEN ;AN000; goto the next screen (SHARE) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �SHARE_SCREEN � +; � � +; �������������������������������������� +; +; The SHARE PARAMETERS SCREEN is presented if the user selected to +; install SHARE support and the user wants to view/change parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets parameters for the SHARE command. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SHARE_SCREEN: ;AN000; + .IF < F_SHARE eq E_SHARE_NO > or ;AN000; if SHARE support not required + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AC000;JW + .THEN ;AN000; +;; INIT_VAR F_SHARE, E_SHARE_NO ;AN021; + GOTO GRAPHICS_SCREEN ;AN000; goto the next screen (GRAPHICS) + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_SHARE ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_SHARE,S_SHARE,M_SHARE ;AN000; get new parameters for SHARE + DISPLAY_PANEL ;AN000; display SHARE panel + ; + GET_STRING STR_SHARE,S_SHARE,M_SHARE,FK_TEXT ;AN000; get new parameters for SHARE + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_STRING S_SHARE, M_SHARE, S_USER_STRING ;AN000; save new parameters for SHARE + PUSH_HEADING SHARE_SCREEN ;AN000; save screen address on SELECT STACK + GOTO GRAPHICS_SCREEN ;AN000; goto the next screen (GRAPHICS) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �GRAPHICS_SCREEN � +; � � +; �������������������������������������� +; +; The GRAPHICS PARAMETERS SCREEN is presented if the user selected to +; install GRAPHICS support and the user wants to view/change parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets parameters for the GRAPHICS command. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +GRAPHICS_SCREEN: ;AN000; + .IF < F_GRAPHICS eq E_GRAPHICS_NO > ;AN000; if GRAPHICS support not required + .THEN ;AN000; + GOTO EXP_MEMORY_SCREEN ;AN000; goto the next screen (EXPANDED_MEM) + .ENDIF ;AN000; + ; + GET_PRINTER_PARAMS 0, 1, N_RETCODE ;AN000; + .IF < N_RETCODE eq 1 > ;AN000; + .THEN ;AN000; + COPY_STRING S_GRAPHICS,M_GRAPHICS,S_GRAPH_PARM ;AN000; + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_GRAPHICS ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_GRAPHICS,S_GRAPHICS,M_GRAPHICS ;AN000; get new parameters for GRAPHICS + DISPLAY_PANEL ;AN000; display GRAPHICS panel + ; + GET_STRING STR_GRAPHICS,S_GRAPHICS,M_GRAPHICS,FK_TEXT ;AN000; get new parameters for GRAPHICS + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_STRING S_GRAPHICS, M_GRAPHICS, S_USER_STRING ;AN000;save new parameters for GRAPHICS + PUSH_HEADING GRAPHICS_SCREEN ;AN000; save screen address on SELECT STACK + GOTO EXP_MEMORY_SCREEN ;AN000; goto next screen (EXPANDED_MEMORY) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �EXP_MEMORY_SCREEN � +; � � +; �������������������������������������� +; +; The EXPANDED MEMORY PARAMETERS SCREEN is presented if the user selected to +; install expanded memory support and the user wants to view/change parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets parameters for the XMAEM and XMA2EMS commands. +; The expanded memory commands are only supported if memory above 1000000H +; is available. +; The TAB key is used to move to the next item on the parameter list. +; If the cursor is on the last item in the parameter list, TAB key +; will cause the cursor to wrap around to the first item of the parameter list. +; When the TAB key is depressed, the current parameter value is saved in +; a temporary location. The temporary parameter values are copied to actual +; values only when the ENTER key is depressed. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +EXP_MEMORY_SCREEN: ;AN000; + .IF < F_XMA eq E_XMA_NO > or ;AN000; if XMA support not required + .IF < F_XMA eq E_XMA_NA > or ;AN000; or if XMA not available + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AC000; or if install to drive B: or A: JW + .THEN ;AN000; + GOTO VDISK_SCREEN ;AN000; goto the next screen (VDISK) + .ENDIF ;AN000; + ; + COPY_STRING S_STR120_1, M_STR120_1, S_XMAEM ;AN000; copy XMAEM to temp location + COPY_STRING S_STR120_2,M_STR120_2,S_XMA2EMS ;AN000; copy XMA2EMS to temp location + ; + .IF < N_MOD80 eq E_IS_MOD80 > ;AN000; JW + .THEN ;AN000; JW + INIT_PQUEUE PAN_EXP_MEMORY ;AN000; initialize queue + .ELSE ;AN000; JW + INIT_PQUEUE PAN_EXP_MEMORY2 ;AN000; initialize queue JW + .ENDIF ;AN000; JW + ; + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + ; + .IF < N_MOD80 eq E_IS_MOD80 > ;AN000; JW + .THEN ;AN000; JW + INIT_STRING STR_XMAEM,S_STR120_1,M_XMAEM ;AN000; display parameter for XMAEM + .ENDIF ;AN000; JW + ; + INIT_STRING STR_XMA2EMS,S_STR120_2,M_XMA2EMS ;AN000; display XMA2EMS parameters + DISPLAY_PANEL ;AN000; display EXPANDED_MEMORY panel + ; + ; + .IF < N_MOD80 eq E_IS_MOD80 > near ;AN000; JW + .THEN ;AN000; JW + INIT_VAR N_COUNTER,1 ;AN000; set counter = 1 + ; + .REPEAT ;AN000; repeat block of code + ; + .SELECT ;AN000; + ; + .WHEN < N_COUNTER eq 1 > near ;AN000; + GET_STRING STR_XMAEM,S_STR120_1,M_XMAEM,FK_TAB;AN000; get new parameter for XMAEM + COPY_STRING S_STR120_1,M_STR120_1,S_USER_STRING;AN000; save parameter in temp location + ; + .OTHERWISE ;AN000; + GET_STRING STR_XMA2EMS,S_STR120_2,M_XMA2EMS,FK_TAB ;AN000;get new parameter for XMA2EMS + COPY_STRING S_STR120_2,M_STR120_2,S_USER_STRING ;AN000; save parameter in temp location + ; + .ENDSELECT ;AN000; + ; + INC_VAR N_COUNTER ;AN000; + ; + .IF < N_COUNTER a 2 > ;AN000; + .THEN ;AN000; + INIT_VAR N_COUNTER,1 ;AN000; + .ENDIF ;AN000; + ; + .UNTIL < N_USER_FUNC eq E_ENTER > or near ;AN000; break loop if ENTER entered + .UNTIL < N_USER_FUNC eq E_ESCAPE > or near ;AN000; or ESCAPE entered + .UNTIL < N_USER_FUNC eq E_F3 > near ;AN000; or F3 entered + .ELSE ;AN000; JW + GET_STRING STR_XMA2EMS,S_STR120_2,M_XMA2EMS,FK_TEXT ;AN000;get new parameter for XMA2EMS JW + COPY_STRING S_STR120_2,M_STR120_2,S_USER_STRING ;AN000; save parameter in temp location JW + .ENDIF ;AN000; JW + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + .THEN ;AN000; + COPY_STRING S_XMAEM, M_XMAEM, S_STR120_1 ;AN000; save new XMAEM parameter + COPY_STRING S_XMA2EMS, M_XMA2EMS,S_STR120_2 ;AN000; save new XMA2EMS parameter + PUSH_HEADING EXP_MEMORY_SCREEN ;AN000; save screen address on SELECT STACK + GOTO VDISK_SCREEN ;AN000; goto next screen (VDISK) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT5.ASM b/v4.0/src/SELECT/SELECT5.ASM new file mode 100644 index 0000000..68920be --- /dev/null +++ b/v4.0/src/SELECT/SELECT5.ASM @@ -0,0 +1,576 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT5.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT5.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; Module contains code for : +; - VDISK screen +; - CONFIG.SYS screen +; - Fixed disk partition screen +; - Date/Time screen +; +; CHANGE HISTORY: +; +; ;AN002; for DCR225 by G.G. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + EXTRN SEL_FLG:BYTE ;AN000; + EXTRN EXEC_DEALLOC:BYTE ;AN000; + EXTRN EXEC_FDISK:BYTE ;AN000;DT + EXTRN EXEC_ERR:BYTE ;AN000;DT + EXTRN BCHAR:BYTE ;AN000;DT +DATA ENDS ;AN000; + ; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + EXTRN DEALLOCATE_HELP:FAR ;AN000;DT + EXTRN ALLOCATE_HELP:FAR ;AN000;DT + EXTRN DEALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN ALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN ALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN PM_BASECHAR:BYTE ;AN000; + EXTRN PM_BASEATTR:BYTE ;AN000; + EXTRN CRD_CCBVECOFF:WORD ;AN000; + EXTRN CRD_CCBVECSEG:WORD ;AN000; + ; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN CREATE_AUTOEXEC_BAT:NEAR ;AN000; + EXTRN CREATE_CONFIG_SYS:NEAR ;AN000; + EXTRN CREATE_SHELL_BAT:NEAR ;AN000;DT + EXTRN SCAN_INFO_CALL:NEAR ;AN000;DT + EXTRN DATE_TIME_SCREEN:NEAR ;AN000;DT + ; + PUBLIC FIRST_DISK_SCREEN ;AN000; + PUBLIC VDISK_SCREEN ;AN000; + EXTRN PROCESS_ESC_F3:near ;AN000; + EXTRN FORMAT_DISK_SCREEN:near ;AN000; + EXTRN EXIT_DOS:near ;AN000; + EXTRN INSTALL_ERROR:near ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �VDISK_SCREEN � +; � � +; �������������������������������������� +; +; The VDISK PARAMETERS SCREEN is presented if the user selected to +; install virtual disk support and the user wants to view/change parameters. +; Note.The view/change parameters condition is not specified in the May 5, 1987 +; Functional Specification. +; The screen gets parameters for the VDISK command. +; Valid keys are ENTER, ESC, F1, F3 and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +VDISK_SCREEN: ;AN000; + .IF < F_VDISK eq E_VDISK_NO > ;AN000; if VDISK support not required + GOTO CONFIG_SYS_SCREEN ;AN000; goto the next screen (CONFIG.SYS) + .ENDIF ;AN000; + ; + INIT_PQUEUE PAN_VDISK ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_VDISK,S_VDISK,M_VDISK ;AN000; get new parameters for VDISK + DISPLAY_PANEL ;AN000; display VDISK panel + ; + GET_STRING STR_VDISK,S_VDISK,M_VDISK,FK_TEXT ;AN000; get new parameters for VDISK + ; + .IF < N_USER_FUNC eq E_ENTER > ;AN000; if user entered ENTER key + COPY_STRING S_VDISK, M_VDISK, S_USER_STRING ;AN000; save new parameters for VDISK + PUSH_HEADING VDISK_SCREEN ;AN000; save screen address on SELECT STACK + GOTO CONFIG_SYS_SCREEN ;AN000; goto the next screen (CONFIG.SYS) + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �CONFIG_SYS_SCREEN � +; � � +; �������������������������������������� +; +; The CONFIG.SYS PARAMETERS SCREEN is presented if the user selected to +; view/change SELECT generated commands ( F_REVIEW = 2 ). +; The screen gets parameters for CONFIG.SYS commands ( BREAK, BUFFERS, +; FCBS, FILES, LASTDRIVE, STACKS, VERIFY ). +; The TAB key is used to move to the next item on the parameter list. +; If the cursor is on the last item in the parameter list, TAB key +; will cause the cursor to wrap around to the first item of the parameter list. +; When the TAB key is depressed, the current parameter value is saved in +; a temporary location. The temporary parameter values are copied to actual +; values only when the ENTER key is depressed. +; Valid keys are ENTER, ESC, F1, F3, TAB and ASCII characters. +; Note.User entered parameter values are not checked for validity. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CONFIG_SYS_SCREEN: ;AN000; + COPY_STRING ST_BREAK, MT_BREAK, S_BREAK ;AN000; copy BREAK par to temp location + COPY_STRING ST_BUFFERS,MT_BUFFERS,S_BUFFERS ;AN000; copy BUFFERS par to temp location + COPY_STRING ST_FCBS, MT_FCBS, S_FCBS ;AN000; copy FCBS par to temp location + COPY_STRING ST_FILES, MT_FILES, S_FILES ;AN000; copy FILES par to temp location + COPY_STRING ST_LASTDRIVE,MT_LASTDRIVE,S_LASTDRIVE ;AN000; copy LASTDRIVE par to temp location + COPY_STRING ST_STACKS, MT_STACKS, S_STACKS ;AN000; copy STACKS par to temp location + COPY_STRING ST_VERIFY, MT_VERIFY, S_VERIFY ;AN000; copy VERIFY par to temp location + ; + INIT_PQUEUE PAN_CONFIG_PARS ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_STRING STR_BREAK, ST_BREAK, MT_BREAK ;AN000; display BREAK parameters + INIT_STRING STR_BUFFERS,ST_BUFFERS,MT_BUFFERS ;AN000; display BUFFERS parameters + INIT_STRING STR_FCBS, ST_FCBS, MT_FCBS ;AN000; display FCBS parameters + INIT_STRING STR_FILES, ST_FILES, MT_FILES ;AN000; display FILES parameters + INIT_STRING STR_LASTDRIVE,ST_LASTDRIVE,MT_LASTDRIVE ;AN000; display LASTDRIVE parameters + INIT_STRING STR_STACKS,ST_STACKS, MT_STACKS ;AN000; display STACKS parameters + INIT_STRING STR_VERIFY,ST_VERIFY, MT_VERIFY ;AN000; display VERIFY parameters + DISPLAY_PANEL ;AN000; display CONFIG.SYS parameters panel + ; + INIT_VAR N_COUNTER, 1 ;AN000; + ; + .REPEAT ;AN000; repeat code block + ; + .SELECT ;AN000; + ; + .WHEN < N_COUNTER eq 1 > ;AN000; + GET_STRING STR_BREAK,ST_BREAK,MT_BREAK,FK_TAB ;AN000; get new parameter for BREAK + COPY_STRING ST_BREAK,MT_BREAK,S_USER_STRING ;AN000; save new BREAK parameter + ; + .WHEN < N_COUNTER eq 2 > ;AN000; + GET_STRING STR_BUFFERS,ST_BUFFERS,MT_BUFFERS,FK_TAB ;AN000; get new parameter for BUFFERS + COPY_STRING ST_BUFFERS,MT_BUFFERS,S_USER_STRING ;AN000; save new BUFFERS parameter + ; + .WHEN < N_COUNTER eq 3 > ;AC000;JW + GET_STRING STR_FCBS,ST_FCBS,MT_FCBS,FK_TAB ;AN000; get new parameter for FCBS + COPY_STRING ST_FCBS, MT_FCBS, S_USER_STRING ;AN000; save new FCBS parameter + ; + .WHEN < N_COUNTER eq 4 > ;AC000;JW; + GET_STRING STR_FILES,ST_FILES,MT_FILES,FK_TAB ;AN000; get new parameter for FILES + COPY_STRING ST_FILES,MT_FILES,S_USER_STRING ;AN000; save new FILES parameter + ; + .WHEN < N_COUNTER eq 5 > ;AC000;JW; + GET_STRING STR_LASTDRIVE,ST_LASTDRIVE,MT_LASTDRIVE, FK_TAB ;AN000; get new parameter for LASTDRIVE + COPY_STRING ST_LASTDRIVE,MT_LASTDRIVE,S_USER_STRING ;AN000;save new LASTDRIVE parameter + ; + .WHEN < N_COUNTER eq 6 > ;AC000;JW; + GET_STRING STR_STACKS,ST_STACKS,MT_STACKS,FK_TAB ;AN000;get new parameter for STACKS + COPY_STRING ST_STACKS,MT_STACKS,S_USER_STRING ;AN000; save new STACKS parameter + ; + .OTHERWISE ;AN000; + GET_STRING STR_VERIFY,ST_VERIFY,MT_VERIFY,FK_TAB ;AN000;get new parameter for VERIFY + COPY_STRING ST_VERIFY,MT_VERIFY,S_USER_STRING ;AN000; save new VERIFY parameter + ; + .ENDSELECT ;AN000; + ; + INC_VAR N_COUNTER ;AN000; inc counter + ; + .IF < N_COUNTER a 7 > ;AC000;JW; if counter > 8 + INIT_VAR N_COUNTER, 1 ;AN000; set counter = 1 + .ENDIF ;AN000; + ; + .UNTIL < N_USER_FUNC eq E_ENTER > or near ;AN000; break if loop if ENTER entered + .UNTIL < N_USER_FUNC eq E_ESCAPE > or near ;AN000; or ESCAPE entered + .UNTIL < N_USER_FUNC eq E_F3 > near ;AN000; or F3 entered + ; + .IF < N_USER_FUNC eq E_ENTER > near ;AN000; if user entered ENTER key + COPY_STRING S_BREAK, M_BREAK, ST_BREAK ;AN000; save BREAK parameter + COPY_STRING S_BUFFERS,M_BUFFERS, ST_BUFFERS ;AN000; save BUFFERS parameter + COPY_STRING S_FCBS, M_FCBS, ST_FCBS ;AN000; save FCBS parameter + COPY_STRING S_FILES, M_FILES, ST_FILES ;AN000; save FILES parameter + COPY_STRING S_LASTDRIVE,M_LASTDRIVE,ST_LASTDRIVE ;AN000;save LASTDRIVE parameter + COPY_STRING S_STACKS, M_STACKS, ST_STACKS ;AN000; save STACKS parameter + COPY_STRING S_VERIFY, M_VERIFY, ST_VERIFY ;AN000; save VERIFY parameter + PUSH_HEADING CONFIG_SYS_SCREEN ;AN000; save screen address on SELECT STACK + GOTO FIRST_DISK_SCREEN ;AN000; goto the first fixed disk screen + .ELSE ;AN000; + GOTO PROCESS_ESC_F3 ;AN000; user entered ESC or F3, take action + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �FIRST_DISK_SCREEN � +; � � +; �������������������������������������� +; +; The PARTITION FIXED DISK SCREEN is presented if the first fixed drive +; exists and is completely unused. +; When SELECT is invoked, the system configuration is checked and if fixed +; disks exist, the fixed disk status is obtained and variables are initialized. +; The screen allows the user to create partitions for the fixed drive. +; If the user chooses to let SELECT define partition sizes, the first fixed +; disk will be partitioned as follows: +; - A Primary DOS partition is created using the entire disk. +; SELECT will partition the second fixed disk if it exists as follows: +; - An Extended DOS partition is created using the entire disk space and a +; logical drive is created using the entire Extended DOS partition. +; Valid keys are ENTER, ESC, F1, F3, cursor up/down, 1/2. +; Note.After FDISK, the partitions have to formatted. Since the system is going +; to reboot, SELECT must know if the user had created his own partitions or not +; so that the partitions can be automatically formatted. The MENU parameter +; in the AUTOEXEC.BAT file is changed FDISK. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +FIRST_DISK_SCREEN: ;AN000; + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > or ;AC111;JW + .IF < N_DISK_1 eq E_DISK_INV > ;AN000; if first fixed disk not present + GOTO DATE_TIME_SCREEN ;AN000; goto DATE_TIME screen + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �MAKE_BACKUP_DISKETTE � +; � � +; � � +; �������������������������������������� +; +; WE NEED TO MAKE A DUPLICATE OF THE SELECT/SHELL DISKETTE +; FOR R/W PURPOSES! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MAKE_BACKUP_DISKETTE: ;AN000; + ; + .REPEAT ;AN000;JW + .REPEAT ;AN000; + ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL PAN_DISKCOPY ;AN000; + PREPARE_PANEL PAN_HBAR ;AN000; + PREPARE_CHILDREN ;AN000; + DISPLAY_PANEL ;AN000; + ; + GET_FUNCTION FK_ENT_ESC_F3 ;AN002;GHG get user entered function (ENTER or ESC ) + ; + .IF < N_USER_FUNC ne E_ENTER > ;AN002;GHG if user entered ENTER key + GOTO PROCESS_ESC_F3 ;AN002;GHG exit to DOS command line + .ENDIF ;AN002;GHG + ; + FIND_FILE S_AUTO_REBOOT, E_FILE_ATTR ;AN000;DT Look for AUTOEXEC.BAT (INSTALL diskette) + .LEAVE < nc > ;AN000;DT + HANDLE_ERROR ERR_DOS_DISK, E_RETURN ;AN000;DT + ; + .UNTIL ;AN000;DT + ; + .IF < MEM_SIZE ne 256 > near ;AN000;DT + CALL HOOK_INT_2F ;AN000;GHG + .ELSE ;AN000; + DEALLOCATE_MEMORY ;AN000; + CALL HOOK_INT_2F_256KB ;AN000; + .ENDIF ;AN000; + ; + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK ;AN000;JW + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR;AN000; control will not return + .IF < c > ;AN000; + MOV EXEC_ERR,TRUE ;AN000; + .ENDIF ;AN000; + CALL RESTORE_INT_2F ;AN000;GHG + ; + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near ;AN000;JW + ; + .IF < MEM_SIZE eq 256 > near ;AN000;DT + CLEAR_SCREEN ;AN000; + DISPLAY_MESSAGE 12 ;AN000;DT Insert SELECT diskette + .REPEAT ;AN000; + CALL GET_ENTER_KEY ;AN000; get user entered function + FIND_FILE S_DOS_SEL_360, E_FILE_ATTR ;AN000; + .LEAVE < nc > ;AN000; + DISPLAY_MESSAGE 11 ;AN000;DT Beep + .UNTIL ;AN000; + ALLOCATE_MEMORY ;AN000; + CALL INITIALIZE ;AN000;DT and read them in + INITIALIZE_BCHAR BCHAR ;AN000;Initialize the background character + INSERT_DISK SUB_INSTALL_COPY, S_DOS_COM_360 ;AN000;JW + .ENDIF ;AN000; + .IF < EXEC_ERR eq TRUE > ;AN000; + HANDLE_ERROR ERR_GENERAL, E_RETURN ;AN000; + GOTO MAKE_BACKUP_DISKETTE ;AN000; + .ENDIF ;AN000; + CALL CURSOROFF ;AN000; set cursor off + ; + OR SEL_FLG,INSTALLRW ;AN000; indicate INSTALL diskette is R/W +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; � Create the CONFIG.340, AUTOEXEC.340, and SHELL.BAT on the � +; � INSTALL COPY diskette in drive A: � +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + CREATE_CONFIG S_CONFIG_NEW, N_RETCODE ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + INIT_VAR N_HOUSE_CLEAN,E_CLEAN_YES ;AN000; set to perform cleanup on exit + ; + CREATE_AUTOEXEC S_AUTO_NEW,E_DEST_SHELL,N_RETCODE ;AN000; create autoexec with SHELL commands + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + CREATE_SHELL S_SHELL_NEW, N_RETCODE ;AN000;DT + .IF c ;AN000;DT + GOTO INSTALL_ERROR ;AN000;DT + .ENDIF ;AN000;DT + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ������������������������������������Ŀ +; �DISK_PARTITION_OPTION � +; � � +; � � +; �������������������������������������� +; +; If the first fixed disk is not new (existing partition) +; goto different screen. Else present screen with partition +; options. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < N_DISK_1 eq E_DISK_VAL_PART > ;AN000; if first disk has partitions + GOTO BOTH_DISK_SCREEN ;AN000; goto next screen (BOTH_DISK) + .ENDIF ;AN000; + ; +DISK_PARTITION_OPTION: ;AN000; + INIT_VAR N_DISK_NUM, '1' ;AN000;JW + INIT_CHAR N_DISK_NUM, E_DISK_ROW, E_DISK_COL, SUB_FIXED_1 ;AN000; display the disk number JW + ; + INIT_PQUEUE PAN_FIXED_FIRST ;AN000; initialize queue + PREPARE_PANEL SUB_FIXED_1 ;AN000; prepare fixed disk 1 message + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_FIXED_FIRST, F_PARTITION ;AN000; + DISPLAY_PANEL ;AN000; display first fixed disk partition screen + ; + GET_SCROLL SCR_FIXED_FIRST,F_PARTITION,FK_SCROLL ;AN000; get user selected option for creating partitions + ; + PROCESS_F3 ;AN000; + PROCESS_ESC ;AN000; + ; + COPY_WORD F_PARTITION, I_USER_INDEX ;AN000; + .IF < F_PARTITION eq E_PART_DEFAULT > ;AN000; + INIT_VAR N_FORMAT_MODE, E_FORMAT_SELECT ;AN000; + .ELSE ;AN000; + INIT_VAR N_FORMAT_MODE, E_FORMAT_NEW ;AN000; + .ENDIF ;AN000; + ; + SAVE_PARAMETERS S_SELECT_TMP, N_RETCODE ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + CHANGE_AUTOEXEC S_AUTO_REBOOT, S_AUTO_FDISK ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000; + .ENDIF ;AN000;DT + ; + .IF < F_PARTITION eq E_PART_USER > near ;AN000; if user selected to define his own partition sizes + ; + SAVE_PANEL_LIST ;AN000; save panel list for test team + INIT_VAR S_STR120_1, 0 ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_Q ;AN000;DT add /Q parameter (no insert disk at end) + CALL CURSORON ;AN000; set cursor to show + EXEC_PROGRAM S_FDISK,S_STR120_1,PARM_BLOCK,EXEC_NO_DIR ;AN000; control will not return + .IF c ;AN000; + GOTO FDISK_ERROR ;AN000; + .ENDIF ;AN000; + ; + GOTO FDISK_REBOOT ;AN000;DT + .ENDIF ;AN000; + ; + INIT_VAR N_WORD_1, 1 ;AN000; + SCAN_DISK_TABLE E_DISK_1, N_WORD_1, N_RETCODE ;AN000; + .IF < N_RETCODE eq 0 > and ;AN000; + .IF < N_NAME_PART eq E_FREE_MEM_DISK > ;AN000; + WORD_TO_CHAR N_SIZE_PART, S_STR120_2 ;AN000; + MERGE_STRING S_STR120_1,M_STR120_1,SC_1,SC_PRI ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_STR120_2;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_Q ;AN000;DT add /Q parameter (no insert disk at end) + EXEC_PROGRAM S_FDISK,S_STR120_1,PARM_BLOCK,EXEC_NO_DIR ;AN000; + .IF c ;AN000; + GOTO FDISK_ERROR ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + ; + .IF < N_DISK_2 eq E_DISK_NO_PART > near ;AN000; + INIT_VAR N_WORD_1, 1 ;AN000; + SCAN_DISK_TABLE E_DISK_2, N_WORD_1, N_RETCODE ;AN000; + .IF < N_RETCODE eq 0 > and near ;AN000; + .IF < N_NAME_PART eq E_FREE_MEM_DISK > near ;AN000; + WORD_TO_CHAR N_SIZE_PART, S_STR120_2 ;AN000; + MERGE_STRING S_STR120_1,M_STR120_1,SC_2,SC_EXT ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_STR120_2;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,SC_LOG ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_STR120_2;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_Q ;AN000;DT add /Q parameter (no insert disk at end) + EXEC_PROGRAM S_FDISK,S_STR120_1,PARM_BLOCK,EXEC_NO_DIR ;AN000; + .IF c ;AN000; + GOTO FDISK_ERROR ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + ; +FDISK_REBOOT: ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CLEAR_SCREEN ;AN000; + DISPLAY_MESSAGE 9 ;AN000; + .ELSE ;AN000; + CALL CURSOROFF ;AN000; set to hide cursor + INIT_PQUEUE PAN_REBOOT ;AN000; initialize queue + PREPARE_PANEL SUB_REBOOT_KEYS ;AN000; + DISPLAY_PANEL ;AN000; + SAVE_PANEL_LIST ;AN000; save panel list for test team + .ENDIF ;AN000; + ; + GET_FUNCTION FK_REBOOT ;AN000; Reboot + ; +FDISK_ERROR: ;AN000; + .IF < MEM_SIZE eq 256 > near ;AN000;DT + CLEAR_SCREEN ;AN000; + DISPLAY_MESSAGE 12 ;AN000;DT Insert SELECT diskette + ; + .REPEAT ;AN000; + GET_FUNCTION FK_ENT ;AN000; get user entered function + FIND_FILE S_DOS_SEL_360, E_FILE_ATTR ;AN000; + .LEAVE < nc > ;AN000; + DISPLAY_MESSAGE 11 ;AN000;DT Beep + .UNTIL ;AN000; + ; + ALLOCATE_MEMORY ;AN000; + CALL INITIALIZE ;AN000;DT and read them in + .ENDIF ;AN000; + .IF < SUB_ERROR eq 1 > ;AN023; If error is because no Primary DOS partition + CALL CURSOROFF ;AN023; set cursor off + GOTO DISK_PARTITION_OPTION ;AN023; return to partition options + .ENDIF ;AN023; + GOTO INSTALL_ERROR ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �BOTH_DISK_SCREEN � +; � � +; � � +; �������������������������������������� +; +; Ask user if they want to change the existing partition +; layout or leave it the same (for both disks if 2nd exists). +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +BOTH_DISK_SCREEN: ;AN000; +BOTH_DISK_PART_OPTION: ;AN000; + ; + .IF < N_DISK_1_S2 eq E_SPACE_EDOS > or ;AN000; + .IF < N_DISK_1_S2 eq E_SPACE_DISK > ;AN000; + INIT_VAR N_DISK_NUM, '1' ;AN000;JW + .ELSEIF < N_DISK_2_S2 eq E_SPACE_EDOS > or ;AN000; + .IF < N_DISK_2_S2 eq E_SPACE_DISK > ;AN000; + INIT_VAR N_DISK_NUM, '2' ;AN000;JW + .ELSE ;AN000; + GOTO DATE_TIME_SCREEN ;AN000; no more partitions to be created + .ENDIF ;AN000; + ; + INIT_CHAR N_DISK_NUM, E_DISK_ROW, E_DISK_COL, SUB_FIXED_1 ;AN000; display the disk number JW + INIT_PQUEUE PAN_FIXED_BOTH ;AN000; initialize queue + PREPARE_PANEL SUB_FIXED_1 ;AN000; prepare fixed disk message JW + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_SCROLL SCR_FIXED_BOTH, F_PARTITION ;AN000; + DISPLAY_PANEL ;AN000; display first fixed disk partition screen + ; + GET_SCROLL SCR_FIXED_BOTH,F_PARTITION,FK_SCROLL ;AN000; get user selected option for creating partitions + ; + PROCESS_ESC ;AN000; + PROCESS_F3 ;AN000; + ; + COPY_WORD F_PARTITION, I_USER_INDEX ;AN000; + CHANGE_AUTOEXEC S_AUTO_REBOOT, S_AUTO_FDISK ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + .IF < F_PARTITION eq E_PART_USER > near ;AN000; if user will define his own partition + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000; + .ENDIF ;AN000;DT + ; + INIT_VAR N_FORMAT_MODE, E_FORMAT_USED ;AN000; + SAVE_PARAMETERS S_SELECT_TMP, N_RETCODE ;AN000; + SAVE_PANEL_LIST ;AN000; save panel list for test team + INIT_VAR S_STR120_1, 0 ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_Q ;AN000;DT add /Q parameter (no insert disk at end) + CALL CURSORON ;AN000; set to show cursor + EXEC_PROGRAM S_FDISK,S_STR120_1,PARM_BLOCK,EXEC_NO_DIR ;AN000; control will not return + .IF c ;AN000; + .IF < SUB_ERROR eq 2 > ;AN034; SEH If user made no changes to partition + CALL CURSOROFF ;AN034; SEH Set cursor off + GOTO BOTH_DISK_SCREEN ;AN034; SEH Go to previous screen + .ELSE ;AN034; SEH + GOTO FDISK_ERROR ;AN000; + .ENDIF ;AN034; SEH + .ENDIF ;AN000; + ; + GOTO FDISK_REBOOT ;AN000;DT + .ELSE ;AN000; + GOTO DATE_TIME_SCREEN ;AN000; no more partitions to be created + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; GET KEY ROUTINE (256KB) +; +; Input: none +; +; Output: none +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PUBLIC GET_ENTER_KEY ;AN063;SEH +GET_ENTER_KEY PROC NEAR ;AN000;DT +GEKEY_AGN: ;AN000;DT + MOV AH,0 ;AN000;DT + INT 16H ;AN000;DT get keystroke + CMP AL,13 ;AN000;DT If ENTER the continue + JE GEKEY_EXIT ;AN000;DT + DISPLAY_MESSAGE 11 ;AN000;DT BEEP + JMP GEKEY_AGN ;AN000;DT + ; +GEKEY_EXIT: ;AN000;DT + RET ;AN000;DT +GET_ENTER_KEY ENDP ;AN000;DT + ; + ; +SELECT ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/SELECT/SELECT5A.ASM b/v4.0/src/SELECT/SELECT5A.ASM new file mode 100644 index 0000000..1a7d29e --- /dev/null +++ b/v4.0/src/SELECT/SELECT5A.ASM @@ -0,0 +1,186 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT5A.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT5A.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; Module contains code for : +; - Date/Time screen +; +; CHANGE HISTORY: +; +; ;AN002; for DCR225 +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + EXTRN SEL_FLG:BYTE ;AN000; +DATA ENDS ;AN000; + ; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN CREATE_AUTOEXEC_BAT:NEAR ;AN000; + EXTRN CREATE_CONFIG_SYS:NEAR ;AN000; + EXTRN CREATE_SHELL_BAT:NEAR ;AN000;DT + EXTRN SCAN_INFO_CALL:NEAR ;AN000;DT + ; + PUBLIC DATE_TIME_SCREEN ;AN000; + EXTRN PROCESS_ESC_F3:near ;AN000; + EXTRN FORMAT_DISK_SCREEN:near ;AN000; + EXTRN EXIT_DOS:near ;AN000; + EXTRN INSTALL_ERROR:near ;AN000; + EXTRN EXIT_SELECT:NEAR ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ������������������������������������Ŀ +; �DATE_TIME_SCREEN � +; � � +; �������������������������������������� +; +; The INSTALL DATE and TIME SCREEN is presented if the active date is 1/1/80. +; If the user is installing to drive C: , this is the first screen presented +; after the system is reboot due to the execution of FDISK. +; The user cannot go back to the previous screen or terminate the +; install process from this screen. +; If the user did not change the date or time presented on the screen, +; no action is taken. +; Valid keys are ENTER, F1, and numeric characters. +; If installing from 360KB diskettes, must prompt for INSTALL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATE_TIME_SCREEN: ;AN000; + ; + .IF < N_SELECT_MODE eq E_SELECT_FDISK > and ;AN000;DT + .IF < N_DISKETTE_A eq E_DISKETTE_360 > ;AN000;DT + CALL CURSOROFF ;AN082;SEH + INSERT_DISK SUB_INSTALL_COPY, S_SELECT_TMP ;AN000;JW + CALL SCAN_INFO_CALL ;AN000;DT + .ENDIF ;AN000;DT + ; + INIT_VAR STACK_INDEX, 0 ;AN000; clear SELECT STACK + ; + CHECK_WRITE_PROTECT DRIVE_A, N_RETCODE ;AC000;JW + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ELSE ;AN000; + OR SEL_FLG,INSTALLRW ;AN000; indicate INSTALL diskette is R/W + .ENDIF ;AN000; + ; + GET_DATE N_YEAR, N_MONTH, N_DAY ;AN000; get system date + .IF c ;AN000; if system date is 1/1/1980 + GOTO FORMAT_DISK_SCREEN ;AN000; goto next screen (FORMAT_DISK) + .ENDIF ;AN000; + ; + GET_TIME N_HOUR, N_MINUTE, N_SECOND ;AN000; get system time + ; + COPY_WORD N_WORD_1, N_YEAR ;AN000; copy year to temp var + COPY_WORD N_WORD_2, N_MONTH ;AN000; copy month to temp var + COPY_WORD N_WORD_3, N_DAY ;AN000; copy day to temp var + COPY_WORD N_WORD_4, N_HOUR ;AN000; copy hour to temp var + COPY_WORD N_WORD_5, N_MINUTE ;AN000; copy minute to temp var + COPY_WORD N_WORD_6, N_SECOND ;AN000; copy second to temp var + ; + INIT_PQUEUE PAN_DATE_TIME ;AN000; initialize queue + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + INIT_NUMERIC NUM_YEAR,N_WORD_1,MAX_YEAR,S_STR120_1 ;AN000; display current year + INIT_NUMERIC NUM_MONTH,N_WORD_2,MAX_MONTH,S_STR120_2 ;AN000; display current month + INIT_NUMERIC NUM_DAY,N_WORD_3,MAX_DAY,S_STR120_3 ;AN000; display current day + INIT_NUMERIC NUM_HOUR,N_WORD_4,MAX_HOUR,SC_LINE ;AN000; display current hour + INIT_NUMERIC NUM_MINUTE,N_WORD_5,MAX_MINUTE,S_MODE_PARM ;AN000; display current minute + INIT_NUMERIC NUM_SECOND,N_WORD_6,MAX_SECOND,S_CP_DRIVER ;AN000; display current second + CALL CURSORON ;AN082;SEH + DISPLAY_PANEL ;AN000; + ; + INIT_VAR N_COUNTER, 1 ;AN000; set counter = 1 + ; +DATE_TIME_LOOP: ;AN000; + ; + .REPEAT ;AN000; repeat code block + ; + .SELECT ;AN000; + ; + .WHEN < N_COUNTER eq 1 > ;AN000; counter = 1 + GET_NUMERIC NUM_YEAR,N_WORD_1,MIN_YEAR,MAX_YEAR,FK_DATE,S_STR120_1 ;AN000; get new year value + COPY_WORD N_WORD_1, N_USER_NUMERIC ;AN000; save new year value + ; + .WHEN < N_COUNTER eq 2 > ;AN000; counter = 2 + GET_NUMERIC NUM_MONTH,N_WORD_2,MIN_MONTH,MAX_MONTH,FK_DATE,S_STR120_2 ;AN000; get new month value + COPY_WORD N_WORD_2, N_USER_NUMERIC ;AN000; save new month value + ; + .WHEN < N_COUNTER eq 3 > ;AN000; counter = 3 + GET_NUMERIC NUM_DAY,N_WORD_3,MIN_DAY,MAX_DAY,FK_DATE,S_STR120_3 ;AN000; get new day value + COPY_WORD N_WORD_3, N_USER_NUMERIC ;AN000; save new day value + ; + .WHEN < N_COUNTER eq 4 > ;AN000; counter = 4 + GET_NUMERIC NUM_HOUR,N_WORD_4,MIN_HOUR,MAX_HOUR,FK_DATE,SC_LINE ;AN000; get new hour value + COPY_WORD N_WORD_4, N_USER_NUMERIC ;AN000; save new hour value + ; + .WHEN < N_COUNTER eq 5 > ;AN000; counter = 5 + GET_NUMERIC NUM_MINUTE,N_WORD_5,MIN_MINUTE,MAX_MINUTE,FK_DATE,S_MODE_PARM ;AN000; get new minute value + COPY_WORD N_WORD_5, N_USER_NUMERIC ;AN000; save new minute value + ; + .OTHERWISE ;AN000; counter = 6 + GET_NUMERIC NUM_SECOND,N_WORD_6,MIN_SECOND,MAX_SECOND,FK_DATE,S_CP_DRIVER ;AN000; get new second value + COPY_WORD N_WORD_6, N_USER_NUMERIC ;AN000; save new second value + ; + .ENDSELECT ;AN000; + ; + INC_VAR N_COUNTER ;AN000; inc counter + ; + .IF < N_COUNTER a 6 > ;AN000; if counter > 6 + INIT_VAR N_COUNTER, 1 ;AN000; set counter = 1 + .ENDIF ;AN000; + ; + .UNTIL < N_USER_FUNC eq E_ENTER > near ;AN000; break loop if user entered ENTER + ; + CHECK_DATE_CHANGE N_WORD_1,N_WORD_2,N_WORD_3,N_YEAR,N_MONTH,N_DAY ;AN000; check if new date is different + .IF c ;AN000; if new date different + SET_DATE N_WORD_1, N_WORD_2, N_WORD_3 ;AN000; set new system date + .IF c ;AN000; if new date invalid + INIT_VAR N_COUNTER, 3 ;AN000; set counter = 3 + GOTO DATE_TIME_LOOP ;AN000; goto get day again + .ENDIF ;AN000; + .ENDIF ;AN000; + ; + CHECK_TIME_CHANGE N_WORD_4,N_WORD_5,N_WORD_6,N_HOUR,N_MINUTE,N_SECOND ;AN000; check if new time is different + .IF c ;AN000; if new time is different + SET_TIME N_WORD_4, N_WORD_5, N_WORD_6 ;AN000; set new system time + .ENDIF ;AN000; + ; + GOTO FORMAT_DISK_SCREEN ;AN000; goto next screen (FORMAT_DISK) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT6.ASM b/v4.0/src/SELECT/SELECT6.ASM new file mode 100644 index 0000000..863aecc --- /dev/null +++ b/v4.0/src/SELECT/SELECT6.ASM @@ -0,0 +1,561 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT6.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT6.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; ;AN000; SELECT2.ASM +; ;AN000; SELECT3.ASM +; ;AN000; SELECT4.ASM +; ;AN000; SELECT5.ASM +; ;AN000; SELECT6.ASM +; +; +; Module contains code for : +; - Format the drives +; - Copy files +; +; CHANGE HISTORY: +; +; ;AN009; DT added support for creation of the DOSSHELL.BAT as a +; separately installed file. (D233) +; ;AN002; GHG for P1146 +; ;AN003; GHG for D234 +; ;AN004; GHG for P65 +; ;AN005; DT for single drive support +; ;AN006; JW for dos location choice (global or path only) +; ;AN007; JW for D239 - display drive letter to format +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + EXTRN SEL_FLG:BYTE ;AN000; + EXTRN EXEC_FDISK:BYTE ;AN000;DT + EXTRN EXEC_ERR:BYTE ;AN000;DT +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Define dummy segment to calculate end of program +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PARSER SEGMENT PARA PUBLIC 'PARSER' ;AN072; +PARSER ENDS ;AN072; + +SET_BLOCK equ 4AH ;AN072; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE MACROS7.INC ;AN009;DT + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + EXTRN DEALLOCATE_HELP:FAR ;AN000;DT + EXTRN DEALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN ALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN ALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN GET_OVERLAY:NEAR ;AN048;SEH + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_SELECT:near ;AN000; + EXTRN CREATE_CONFIG_SYS:NEAR ;AN000; + EXTRN CREATE_AUTOEXEC_BAT:NEAR ;AN000; + EXTRN CREATE_SHELL_BAT:NEAR ;AN009;DT + ; EXTRN DO_PREP_FOR_ONE:NEAR ;AN009;DT + ; EXTRN DO_HOOK15:NEAR ;AN009;DT + ; EXTRN DO_UNHOOK15:NEAR ;AN009;DT + ; + EXTRN EXIT_DOS:near ;AN004;GHG + EXTRN INSTALL_ERROR:near ;AN004;GHG + EXTRN EXIT_SELECT:NEAR ;AN004;GHG + EXTRN PROCESS_ESC_F3:near ;AN004;GHG + EXTRN DISKETTE_INSTALL:NEAR ;AN111;JW + EXTRN EXIT_DOS_CONT:NEAR ;AN004;GHG + EXTRN CONTINUE_360:NEAR ;AN004;GHG + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; CODE CONTINUES..... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC FORMAT_DISK_SCREEN ;AN000; +FORMAT_DISK_SCREEN: ;AN000; + ; + CALL DEALLOCATE_HELP ;AN072;Help no longer needed + POS_CURSOR ;AN085;SEH position cursor at top left corner so that future "% formatted" msg appears in correct spot + CALL CURSOROFF ;AN082;SEH + ; + .IF < I_DEST_DRIVE ne E_DEST_DRIVE_C > ;AN111;JW + GOTO DISKETTE_INSTALL ;AN111;JW + .ENDIF ;AN000; + ; +; N_WORD_1 : disk number ; +; N_WORD_2 : index into disk table ; +; N_WORD_3 : sub panel number for specified disk ; + ; + INIT_VAR N_WORD_1, 1 ;AN000; set disk no = 1 + .REPEAT ;AN000; repeat code block + INIT_VAR N_WORD_2, 1 ;AN000; set index into table = 1 + .IF < N_WORD_1 eq E_DISK_1 > ;AN000; if disk = 1 + INIT_VAR N_DISK_NUM, '1' ;AN007; sub panel = fixed disk 1 JW + .ELSE ;AN000; else + INIT_VAR N_DISK_NUM, '2' ;AN007; sub panel = fixed disk 2 JW + .ENDIF ;AN000; + ; + .REPEAT ;AN000; repeat code block + SCAN_DISK_TABLE N_WORD_1,N_WORD_2,N_RETCODE ;AN000; scan disk table + .LEAVE < N_RETCODE ne 0 > near ;AN000; break loop if no more entries + ; + .IF < N_NAME_PART eq E_PART_PRI_DOS > and ;AN000; if pri part & unformatted + .IF < N_STATUS_PART eq E_PART_UNFORMAT > ;AN000; + INIT_VAR N_TYPE_PART, E_PART_FAT ;AN000; set to format as FAT + .ELSEIF < N_NAME_PART eq E_PART_LOG_DRI > near and;AN000; if log drive & unformatted + .IF < N_STATUS_PART eq E_PART_UNFORMAT > near ;AN000; + .IF < N_FORMAT_MODE eq E_FORMAT_SELECT > ;AN000; if select to format partition + INIT_VAR N_TYPE_PART, E_PART_FAT ;AN000; set to format as FAT + .ELSE near ;AN000; else + INIT_CHAR N_DISK_NUM, E_DISK_ROW, E_DISK_COL,SUB_FIXED_1 ;AN007; display the disk number JW + INIT_CHAR P_DRIVE_PART, E_DRIVE_ROW, E_DRIVE_COL,SUB_LOG_DRIVE ;AN000; display the drive letter JW + INIT_PQUEUE PAN_FORMAT ;AN000; init format panel + PREPARE_PANEL PAN_HBAR ;AN000; prepare hor. bar panel + PREPARE_PANEL SUB_FIXED_1 ;AC007; prepare disk no panel JW + PREPARE_PANEL SUB_LOG_DRIVE ;AN000;JW + PREPARE_CHILDREN ;AN000; prepare children + INIT_VAR F_FORMAT, E_FORMAT_FAT ;AN000; set option=format as FAT + INIT_SCROLL SCR_FORMAT, F_FORMAT ;AN000; init scroll list + DISPLAY_PANEL ;AN000; display panel + GET_SCROLL SCR_FORMAT,F_FORMAT,FK_FORMAT ;AN000; get option + COPY_WORD F_FORMAT, I_USER_INDEX ;AN000; save option + .IF < F_FORMAT eq E_FORMAT_FAT > ;AN000; if option=format + INIT_VAR N_TYPE_PART, E_PART_FAT ;AN000; set to format as FAT + .ENDIF ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + UPDATE_DISK_TABLE N_WORD_1,N_WORD_2,N_RETCODE ;AN000; update disk table + INC_VAR N_WORD_2 ;AN000; inc index into table + .UNTIL ;AN000; end of repeat block + INC_VAR N_WORD_1 ;AN000; inc disk no + .UNTIL < N_WORD_1 gt 2> near ;AN000; end of repeat block +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Format the logical drives and primary partition +; N_WORD_1 : disk number +; N_WORD_2 : index into disk table +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_VAR N_WORD_1, 1 ;AN000; set disk no = 1 + .REPEAT ;AN000; repeat code block + INIT_VAR N_WORD_2, 1 ;AN000; set index into disk table = 1 + .REPEAT ;AN000; repeat code block + SCAN_DISK_TABLE N_WORD_1,N_WORD_2,N_RETCODE ;AN000; scan disk table + .LEAVE < N_RETCODE ne 0 > near ;AN000; break loop in index not valid + .IF < N_STATUS_PART eq E_PART_UNFORMAT > and near ;AN000; if partition not unformatted and + .IF < N_TYPE_PART eq E_PART_FAT > near ;AN000; format set to FAT + COPY_BYTE P_STR120_1, P_DRIVE_PART ;AN000; save drive letter in buffer + INIT_VAR S_STR120_1, 1 ;AN000; set length of string + APPEND_STRING S_STR120_1, M_STR120_1, S_COLON ;AN000; append colon to drive + .IF < N_NAME_PART eq E_PART_PRI_DOS > and ;AN111; if primary partition and JW + .IF < N_WORD_1 eq 1 > ;AN111; first drive JW + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_S ;AN000; append ' /s' to drive + INIT_VAR I_DESTINATION, E_ENTIRE_DISK ;AN033; SEH install to entire disk if formatting + .ENDIF ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_VOL_SEL ;AN000; append "/V:DOS340 /SELECT" + CLEAR_SCREEN ;AN000; pos cursor at top of screen + INIT_PQUEUE FORMAT_DISK ;AN000; initialize queue + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + EXEC_PROGRAM S_FORMAT,S_STR120_1,PARM_BLOCK,EXEC_NO_DIR ;AN000; format partition as FAT + .IF < c > ;AN000; + MOV EXEC_ERR,TRUE ;AN000; + .ENDIF ;AN000; + ; + .IF < MEM_SIZE eq 256 > near ;AN000;DT + CLEAR_SCREEN ;AN000; + DISPLAY_MESSAGE 12 ;AN000;DT Insert SELECT diskette + .REPEAT ;AN000; + GET_FUNCTION FK_ENT ;AN000; get user entered function + FIND_FILE S_DOS_SEL_360, E_FILE_ATTR;AN000; + .LEAVE < nc > ;AN000; + DISPLAY_MESSAGE 11 ;AN000;DT Beep + .UNTIL ;AN000; + ALLOCATE_MEMORY ;AN000;DT + CALL INITIALIZE ;AN000;DT and read them in + CALL DEALLOCATE_HELP ;AN072;Help no longer needed + ; + INSERT_DISK SUB_INSTALL_COPY, S_AUTO_NEW ;AN000;JW Insert INSTALL COPY diskette + ; + .ENDIF ;AN000; + ; + .IF < EXEC_ERR eq TRUE > ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + .ENDIF ;AN000; + INC_VAR N_WORD_2 ;AN000; + .UNTIL ;AN000; + INC_VAR N_WORD_1 ;AN000; + .UNTIL < N_WORD_1 gt 2> near ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + GET_TIME N_HOUR, N_MINUTE, N_SECOND ;AN000; get system time + GET_DATE N_YEAR, N_MONTH, N_DAY ;AN000; get system date +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Update date/time of CONFIG.340 +; AUTOEXEC.340 +; DOSSHELL.BAT in drive A: ; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + OPEN_FILE S_CONFIG_NEW, 2, N_HANDLE ;AN000; + SET_FILE_DATE_TIME N_HANDLE,N_HOUR,N_MINUTE,N_SECOND,N_YEAR,N_MONTH,N_DAY ;AN000; + CLOSE_FILE N_HANDLE ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + OPEN_FILE S_AUTO_NEW, 2, N_HANDLE ;AN000; + SET_FILE_DATE_TIME N_HANDLE,N_HOUR,N_MINUTE,N_SECOND,N_YEAR,N_MONTH,N_DAY ;AN000; + CLOSE_FILE N_HANDLE ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + OPEN_FILE S_SHELL_NEW, 2, N_HANDLE ;AN009;DT + SET_FILE_DATE_TIME N_HANDLE,N_HOUR,N_MINUTE,N_SECOND,N_YEAR,N_MONTH,N_DAY ;AN009;DT + CLOSE_FILE N_HANDLE ;AN009;DT + .IF < c > ;AN009;DT + GOTO INSTALL_ERROR ;AN009;DT + .ENDIF ;AN009;DT +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Make sure any previous AUTOEXEC.340 or CONFIG.340 +; are not READ-ONLY ! +; Copy CONFIG.340 & AUTOEXEC.340 from A: to root of C: +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + CHMOD_FILE S_AUTO_REN ;AN017; + CHMOD_FILE S_CONFIG_REN ;AN017; + COPY_FILES2 I_DEST_DRIVE,S_CONFIG_AUTO,E_FILES,S_DEST_DRIVE ;AC111;JW + .IF < c > ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; If the user selected to replace files throughout the fixed disk: +; 1) Copy COMMAND.COM to root of C: +; 2) Check if OS/2 is installed. If it is, rename CONFIG.SYS and +; AUTOEXEC.BAT (OS2'S) to CONFIG.OS2 and AUTOEXEC.OS2. Then +; rename CONFIG.400 and AUTOEXEC.400 to CONFIG.SYS and +; AUTOEXEC.BAT. +; 3) Try to locate C:\CONFIG.SYS & C:\AUTOEXEC.BAT (if OS/2 not installed) +; If either one is already present, then leave the names +; of the new files as CONFIG.400 and AUTOEXEC.400! +; Otherwise, the CONFIG.400 and AUTOEXEC.400 become the +; new user's SYS and BAT files. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < I_DESTINATION eq E_ENTIRE_DISK > near ;AN010;JW + ; + .IF < MEM_SIZE eq 256 > ;AN048;SEH memory must be freed up + DEALLOCATE_MEMORY ;AN048;SEH before reading COMMAND.COM + .ENDIF ;AN048;SEH + CHMOD_FILE S_COMMAND_COM ;AN017; + COPY_FILES2 I_DEST_DRIVE,COPY_SEL_SHEL,E_SEL_SHEL,S_DEST_DRIVE ;AC010;JW + .IF < c > ;AN000; + MOV EXEC_ERR,TRUE ;AN000; + .ENDIF ;AN000; + .IF < MEM_SIZE eq 256 > near ;AN000;DT + CALL GET_OVERLAY ;AC048;SEH replaced code with this proc call + INSERT_DISK SUB_INSTALL_COPY, S_DOS_COM_360 ;AN000;JW Insert INSTALL COPY diskette + CALL DEALLOCATE_HELP ;AN072;Help no longer needed + .ENDIF ;AN000;DT + .IF < EXEC_ERR eq TRUE > ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + INIT_VAR N_WORD_1,1 ;AN065;SEH set disk no. = 1 + INIT_VAR N_WORD_2,1 ;AN065;SEH set index into disk table = 1 + SCAN_DISK_TABLE N_WORD_1,N_WORD_2,N_RETCODE ;AN065;SEH get version number + .IF < N_RETCODE eq 0 > near and ;AN065;SEH + .IF < N_LEVEL2_PART ne '4' > near ;AN065;SEH is it OS/2? 1st byte of DOS version number = blank; for OS/2 it's 1 + RENAME_FILE S_CONFIG_C, S_OS2_CONFIG_C ;AN065;SEH rename OS/2's CONFIG.SYS to CONFIG.OS2 + RENAME_FILE S_AUTO_C, S_OS2_AUTO_C ;AN065;SEH rename OS/2's AUTOEXEC.BAT to AUTOEXEC.OS2 + RENAME_FILE S_CONFIG_REN, S_CONFIG_NEW_C ;AN065;SEH rename CONFIG.400 to CONFIG.SYS + .IF < c > ;AN065;SEH + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN065;SEH + .ENDIF ;AN065;SEH + RENAME_FILE S_AUTO_REN, S_AUTO_NEW_C ;AN065;SEH rename AUTOEXEC.400 to AUTOEXEC.BAT + .IF < c > near ;AN065;SEH + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN065;SEH + .ENDIF ;AN065;SEH + .ELSE near ;AN065;SEH + FIND_FILE S_CONFIG_C, E_FILE_ATTR ;AN000;GHG + .IF < c > ;AN000;GHG + FIND_FILE S_AUTO_C, E_FILE_ATTR ;AN000;GHG + .IF < c > ;AN000;GHG + RENAME_FILE S_CONFIG_REN, S_CONFIG_NEW_C;AN000;GHG new CONFIG ******* + .IF < c > ;AN000;GHG + HANDLE_ERROR ERR_COPY_DISK, E_RETURN;AN000;GHG + .ENDIF ;AN000;GHG + RENAME_FILE S_AUTO_REN, S_AUTO_NEW_C ;AN000;GHG new AUTOEXEC ******* + .IF < c > ;AN000;GHG + HANDLE_ERROR ERR_COPY_DISK, E_RETURN;AN000;GHG + .ENDIF ;AN000;GHG + .ENDIF ;AN000;GHG + .ENDIF ;AN000;GHG + .ENDIF ;AN065;SEH + .ENDIF ;AN010;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Create install path directory always ! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + MAKE_DIR_PATHS S_INSTALL_PATH ;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Make sure any previous DOSSHELL.BAT is not READ-ONLY ! +; Copy DOSSHELL.BAT from A: to subdirectory of C: +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < S_DOS_LOC eq 0 > ;AN058;SEH + MERGE_STRING S_STR120_1,M_STR120_1,S_DEST_DRIVE,S_SHELL_NEW ;AN058;SEH + .ELSE ;AN058;SEH + MERGE_STRING S_STR120_1,M_STR120_1,S_INSTALL_PATH,S_SLASH ;AN017; + APPEND_STRING S_STR120_1,M_STR120_1,S_SHELL_NEW ;AN017; + .ENDIF ;AN058;SEH + CHMOD_FILE S_STR120_1 ;AN017; + COPY_FILES2 I_DEST_DRIVE,S_SHELL2,SH_FILES,S_INSTALL_PATH ;AC111;JW + .IF c ;AN009; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN009; + .ENDIF ;AN009; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Erase: AUTOEXEC.340 CONFIG.340 +; DOSSHELL.BAT SELECT.TMP from drive A: +; +; Then perform cleanup of AUTOEXEC.BAT on INSTALL (source) +; diskette - ie. change to SELECT MENU!!! +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ERASE_FILE S_AUTO_NEW ;AN000; + ERASE_FILE S_CONFIG_NEW ;AN000; + ERASE_FILE S_SHELL_NEW ;AN000; + ERASE_FILE S_SELECT_TMP ;AN000; only present if reboot after FDISK + ; + CHANGE_AUTOEXEC S_AUTO_REBOOT, S_AUTO_MENU ;AN000; + .IF c ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; If 256KB machine, shrink SELECT memory below the parser +; and pcinput code. This frees about another 11KB. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + .IF < MEM_SIZE eq 256 > ;AN072; + ; + DEALLOCATE_MEMORY ;AN072; + MOV AH,62H ;AN072;Get the PSP segment + INT 21H ;AN072; + MOV AX,BX ;AN072;save the PSP segment of SELECT + MOV BX,PARSER ;AN072;get last address of code + MOV ES,AX ;AN072;set PSP segment in ES + SUB BX,AX ;AN072;calc # of paragraphs in the program + MOV AH,SET_BLOCK ;AN072;setblock function number + DOSCALL ;AN072;free used memory + + .IF < c > ;AN000; + CALL GET_OVERLAY ;AC048;SEH replaced code with this proc call + INSERT_DISK SUB_INSTALL_COPY, S_DOS_COM_360 ;AN000;JW Insert INSTALL COPY diskette + GOTO INSTALL_ERROR ;AN072;If error, exit + .ENDIF ;AN000; + + .ENDIF + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; If install is to entire disk, Exec SYS to the drive C: +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + .IF < I_DESTINATION eq E_ENTIRE_DISK > near ;AN010; + ; + ;;;copy system files from Startup diskette to drive C: + + EXEC_PROGRAM S_SYS_C,S_DRIVE_C,PARM_BLOCK,EXEC_DIR ;AN000; + .IF < c > ;AN000; + MOV EXEC_ERR,TRUE ;AN000; + .ENDIF ;AN000; + + .ENDIF ;AN010;JW + + .IF < MEM_SIZE eq 256 > near ;AN000;DT + CALL GET_OVERLAY ;AC048;SEH replaced code with this proc call + INSERT_DISK SUB_INSTALL_COPY, S_DOS_COM_360 ;AN000;JW Insert INSTALL COPY diskette + CALL DEALLOCATE_HELP ;AN072;DT + .ENDIF ;AN000;DT + .IF < EXEC_ERR eq TRUE > ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;; +; +; Display copying files from INSTALL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + .IF < N_DISKETTE_A eq E_DISKETTE_720 > near or ;AN000;GHG + .IF < N_DISKETTE_A eq E_DISKETTE_1440 > near ;AN000;GHG + ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL PAN_DSKCPY_CPY ;AN000; prepare copying + DISPLAY_PANEL ;AN000; from diskette 2 msg + ; + ;;;S_STR120_1 = "a:*.* c:\path /a parameter for REPLACE + MERGE_STRING S_STR120_1,M_STR120_1,S_A_STARS,S_INSTALL_PATH ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_A ;AN000; + ; +; .IF < I_DESTINATION eq E_ENTIRE_DISK > ;AN006;JW +; .THEN ;AN006; +; ;;;S_STR120_3 = "a:*.* c:\ /s parameter for REPLACE +; COPY_STRING S_STR120_3,M_STR120_3,S_REPLACE_PAR1 ;AN006;JW +; .ELSE ;AN006; + ;;;S_STR120_3 = "a:*.* c:\ /r parameter for REPLACE + MERGE_STRING S_STR120_3,M_STR120_3,S_A_STARS,S_INSTALL_PATH ;AN006;JW + APPEND_STRING S_STR120_3,M_STR120_3,S_SLASH_R ;AN000;JW +; .ENDIF ;AN006; + ; + ;;;change attributes of some files so they are not copied + CHANGE_ATTRIBUTE HIDE_SEL, E_HIDE_SEL ;AN000; + ; + ;;;replace files in drive C: with new files on INSTALL diskette + EXEC_PROGRAM S_REPLACE,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + RESTORE_ATTRIBUTE HIDE_SEL,E_HIDE_SEL ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A" ; + ;;;copy new files on SELECT diskette to install path ; + EXEC_PROGRAM S_REPLACE,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + RESTORE_ATTRIBUTE HIDE_SEL,E_HIDE_SEL ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;restore attributes of files ; + RESTORE_ATTRIBUTE HIDE_SEL,E_HIDE_SEL ;AN000; + ; + +;------------------------------------------------------------- +; copy files from 720k Operate diskette +;------------------------------------------------------------- +; NOTE: The REPLACE command is now issued from the hard disk +; (since it is not found on any other disk) + + COMPARE_STRINGS S_INSTALL_PATH, S_DEST_DRIVE ;AN000; compare to C:\ + .IF < nc > ;AN000; if the same + MERGE_STRING S_STR120_2,M_STR120_2,S_INSTALL_PATH,S_REPLACE ;AN000; + .ELSE ;AN000; + MERGE_STRING S_STR120_2,M_STR120_2,S_INSTALL_PATH,S_SLASH ;AN000; + APPEND_STRING S_STR120_2,M_STR120_2,S_REPLACE;AN000; + .ENDIF ;AN000; + + INSERT_DISK SUB_REM_SEL_A, S_DOS_UTIL1_DISK ;AN000;JW Insert Operating diskette + ; + ;;;display copying files from diskette 1 screen ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL PAN_DSKCPY_CPY ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + ;;;replace files in drive C: with new files on DOS diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy new files on DOS diskette to install path ; + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; +;------------------------------------------------------------- +; copy files from 720k Shell diskette +;------------------------------------------------------------- + + .IF < f_shell eq e_shell_yes > near + ; + INSERT_DISK SUB_INS_MSSHELL_A, S_DOS_SHEL_DISK ;AN000;JW Insert Operating diskette + ; + ;;;display copying files from diskette 1 screen ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL PAN_DSKCPY_CPY ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + ;;;replace files in drive C: with new files on DOS diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy new files on DOS diskette to install path ; + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + + .ENDIF ; IF shell supported + + + .ENDIF ;AN000;GHG +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;;;;720KB;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; End of 720KB support +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + GOTO CONTINUE_360 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELECT7.ASM b/v4.0/src/SELECT/SELECT7.ASM new file mode 100644 index 0000000..5882cd0 --- /dev/null +++ b/v4.0/src/SELECT/SELECT7.ASM @@ -0,0 +1,464 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT7.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT7.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; ;AN000; SELECT2.ASM +; ;AN000; SELECT3.ASM +; ;AN000; SELECT4.ASM +; ;AN000; SELECT5.ASM +; ;AN000; SELECT6.ASM +; +; +; Module contains code for : +; - Format the drives +; - Copy files +; +; CHANGE HISTORY: +; +; ;AN009; DT added support for creation of the DOSSHELL.BAT as a +; separately installed file. (D233) +; ;AN002; GHG for P1146 +; ;AN003; GHG for D234 +; ;AN004; GHG for P65 +; ;AN005; DT for single drive support +; ;AN006; JW for dos location choice (global or path only) +; ;AN007; JW fixed deletion of select.* when installation is to the root +; ;AN072; DT Overlay parser and pcinput if memory = 256KB +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE MACROS7.INC ;AN009;DT + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + EXTRN DEALLOCATE_HELP:FAR ;AN000;DT + EXTRN DEALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN ALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN000;DT + EXTRN ALLOCATE_MEMORY_CALL:FAR ;AN000;DT + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_SELECT:near ;AN000; + EXTRN CREATE_CONFIG_SYS:NEAR ;AN000; + EXTRN CREATE_AUTOEXEC_BAT:NEAR ;AN000; + EXTRN CREATE_SHELL_BAT:NEAR ;AN009;DT + ; + EXTRN EXIT_DOS:near ;AN004;GHG + EXTRN INSTALL_ERROR:near ;AN004;GHG + EXTRN EXIT_SELECT:NEAR ;AN004;GHG + EXTRN PROCESS_ESC_F3:near ;AN004;GHG + EXTRN EXIT_DOS_CONT:NEAR ;AN004;GHG + ; + PUBLIC CONTINUE_360 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; CODE CONTINUES..... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;INSTALL 360KB DISKETTE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files from INSTALL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +CONTINUE_360: ;AN000; + ;;; + ;;; + .IF < N_DISKETTE_A eq E_DISKETTE_360 > near ;AN000; + ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 2 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;S_STR120_1 = "a:*.* c:\path /a parameter for REPLACE + MERGE_STRING S_STR120_1,M_STR120_1,S_A_STARS,S_INSTALL_PATH ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_A ;AN000; + ; +; .IF < I_DESTINATION eq E_ENTIRE_DISK > ;AN006;JW +; .THEN ;AN006; +; ;;;S_STR120_3 = "a:*.* c:\ /s /r parameter for REPLACE +; COPY_STRING S_STR120_3,M_STR120_3,S_REPLACE_PAR1 ;AN006;JW +; .ELSE ;AN006; + ;;;S_STR120_3 = "a:*.* c:\ parameter for REPLACE + MERGE_STRING S_STR120_3,M_STR120_3,S_A_STARS,S_INSTALL_PATH ;AN006;JW + APPEND_STRING S_STR120_3,M_STR120_3,S_SLASH_R ;AN000;JW +; .ENDIF ;AN006; + ; + ;;;change attributes of some files so they are not copied + CHANGE_ATTRIBUTE HIDE_STARTUP, E_HIDE_STARTUP ;AN000; + ; + ;;;replace files in drive C: with new files on INSTALL diskette + EXEC_PROGRAM S_REPLACE,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + RESTORE_ATTRIBUTE HIDE_STARTUP,E_HIDE_STARTUP ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A" ; + ;;;copy NEW files on INSTALL diskette to install path ; + EXEC_PROGRAM S_REPLACE,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + RESTORE_ATTRIBUTE HIDE_STARTUP,E_HIDE_STARTUP ;AN000; + .ENDIF ;AN000; + ; + RESTORE_ATTRIBUTE HIDE_STARTUP,E_HIDE_STARTUP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Prompt the user to remove the INSTALL (source) diskette +; and insert the OPERATING 1 (source) diskette. +; +;;;;;;;;;;SHELL 360KB DISKETTE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + ; + ;;;insert OPERATING 1 diskette in drive A: ; + INSERT_DISK SUB_REM_SELECT_360, S_DOS_UTIL1_DISK ;AN000;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files +; +; NOTE: The REPLACE command is now issued from the hard disk +; (since it is not found on any other disk) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 2 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;S_STR120_1 = "a:*.* c:\path /a parameter for REPLACE + MERGE_STRING S_STR120_1,M_STR120_1,S_A_STARS,S_INSTALL_PATH ;AN000; + APPEND_STRING S_STR120_1,M_STR120_1,S_SLASH_A ;AN000; + ; + COMPARE_STRINGS S_INSTALL_PATH, S_DEST_DRIVE ;AN000; compare to C:\ + .IF < nc > ;AN000; if the same + MERGE_STRING S_STR120_2,M_STR120_2,S_INSTALL_PATH,S_REPLACE ;AN000; + .ELSE ;AN000; + MERGE_STRING S_STR120_2,M_STR120_2,S_INSTALL_PATH,S_SLASH ;AN000; + APPEND_STRING S_STR120_2,M_STR120_2,S_REPLACE;AN000; + .ENDIF ;AN000; + ; + ;;;replace files in drive C: with new files on OPERATING 1 diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A" ; + ;;;copy NEW files on OPERATING 1 diskette to install path + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; insert the OPERATING #2 diskette. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000;DT + ; + ;;; insert OPERATING #2 diskette in drive A: ; + INSERT_DISK SUB_INS_OPER2, S_DOS_UTIL2_DISK ;AN000;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files from OPERATING #2 +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;replace files in drive C: with new files on OPERATING 2 diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy NEW files on OPERATING 2 diskette to install path + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; insert the OPERATING #3 diskette. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000;DT + ; + ;;; insert OPERATING #3 diskette in drive A: ; + INSERT_DISK SUB_REM_UTIL1_360, S_DOS_UTIL3_DISK ;AN000;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files from OPERATING #3 +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;replace files in drive C: with new files on OPERATING 2 diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy NEW files on OPERATING 2 diskette to install path + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR ;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; insert the SELECT diskette. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ELSE ;AN000;DT + ;;; insert the SELECT diskette in drive A ; + INSERT_DISK SUB_REM_SHELL_360, S_DOS_SEL_360 ;AN000;JW + .ENDIF ;AN000;DT +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files from SELECT diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;replace files in drive C: with new files on SELECT diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy new files on SELECT diskette to install path ; + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; maybe insert the SHELL diskette. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + .IF < f_shell eq e_shell_yes > near + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000;DT + ; + INSERT_DISK SUB_INS_MSSHELL_A, S_DOS_SHEL_DISK ;AN000;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Display copying files from SHELL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying from diskette 1 message + DISPLAY_PANEL ;AN000; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + DEALLOCATE_MEMORY ;AN000;DT + .ENDIF ;AN000;DT + ; + ;;;replace files in drive C: with new files on SHELL diskette + EXEC_PROGRAM S_STR120_2,S_STR120_3,PARM_BLOCK,EXEC_DIR ;AN006;JW + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + ; + ;;;S_STR120_1 = "a:*.* C:\ /A " ; + ;;;copy NEW files on SHELL diskette to install path + EXEC_PROGRAM S_STR120_2,S_STR120_1,PARM_BLOCK,EXEC_DIR;AN000; copy new files + .IF c ;AN000; + .IF < MEM_SIZE eq 256 > ;AN000;DT + CALL GET_OVERLAY ;AN000;DT Get panels + .ENDIF ;AN000; + HANDLE_ERROR ERR_COPY_DISK, E_RETURN ;AN000; + .ENDIF ;AN000; + + .endif ; optional shell support + + + ;Delete select files from C: drive ; + COMPARE_STRINGS S_INSTALL_PATH, S_DEST_DRIVE ;AN007; compare to C:\ + .IF < nc > ;AN007; if installed to the root + MERGE_STRING S_STR120_1,M_STR120_1,S_C_DRIVE,S_SELDAT_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + MERGE_STRING S_STR120_1,M_STR120_1,S_C_DRIVE,S_SELEXE_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + .ELSE near ;AN007; else installed to a directory + MERGE_STRING S_STR120_1,M_STR120_1,S_INSTALL_PATH,S_SELDAT_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + MERGE_STRING S_STR120_1,M_STR120_1,S_INSTALL_PATH,S_SELEXE_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + MERGE_STRING S_STR120_1,M_STR120_1,S_INSTALL_PATH,S_AUTOEX_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + MERGE_STRING S_STR120_1,M_STR120_1,S_INSTALL_PATH,S_CONSYS_C ;AN000; + ERASE_FILE S_STR120_1 ;AN000;DT + .ENDIF ;AN007; + ; + .ENDIF ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;360KB;;;;360KB;;;;360KB;;;;360KB;;;;360KB;;;;360KB;;;;360KB;; +; +; End of 360KB support +; +; Installation completed. inform user to reboot +; +; Search for the installed CONFIG.340 , and +; we issue a different panel to describe the '.340' files. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + .IF < MEM_SIZE eq 256 > ;AN000;DT + ALLOCATE_MEMORY ;AN000;DT + CALL INITIALIZE ;AN000;DT and read them in + .ENDIF ;AN000;DT + ; + INIT_PQUEUE PAN_COMPLETE1 ;AN000; initialize queue + .IF < I_DESTINATION ne E_ENTIRE_DISK > ;AN010;JW + PREPARE_PANEL PAN_PARTIAL ;AN010;JW + .ELSE ;AN010;JW + FIND_FILE S_CONFIG_REN, E_FILE_ATTR ;AN003;GHG Look for '.340' files + .IF < c > ;AN003;GHG + PREPARE_PANEL SUB_COMP_VER ;AN003;GHG prepare DOS install message + .ELSE ;AN003;GHG + PREPARE_PANEL SUB_COMP_REP ;AN003;GHG prepare DOS Replace message + .ENDIF ;AN003;GHG + .ENDIF ;AN010; + ; + PREPARE_PANEL SUB_COMP_KYS_1 ;AN000; + DISPLAY_PANEL ;AN000; + SAVE_PANEL_LIST ;AN000; + ; + GET_FUNCTION FK_REBOOT ;AN000; User has to reboot +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PUBLIC GET_OVERLAY ;AN000; +GET_OVERLAY PROC NEAR ;AN000; + .IF < N_DISKETTE_A ne E_DISKETTE_720 > ;AN063;SEH + CLEAR_SCREEN ;AN000; + DISPLAY_MESSAGE 12 ;AN000;DT Insert SELECT diskette + .REPEAT ;AN000; + GET_FUNCTION FK_ENT ;AN000; get user entered function + FIND_FILE S_DOS_SEL_360, E_FILE_ATTR ;AN000; + .LEAVE < nc > ;AN000; + DISPLAY_MESSAGE 11 ;AN000;DT Beep + .UNTIL ;AN000; + .ENDIF ;AN063;SEH + ALLOCATE_MEMORY ;AN000;DT + CALL INITIALIZE ;AN000;DT and read them in + RET ;AN000; +GET_OVERLAY ENDP ;AN000; + ; +SELECT ENDS ;AN000; + END ;AN000; + \ No newline at end of file diff --git a/v4.0/src/SELECT/SELECT8.ASM b/v4.0/src/SELECT/SELECT8.ASM new file mode 100644 index 0000000..effac33 --- /dev/null +++ b/v4.0/src/SELECT/SELECT8.ASM @@ -0,0 +1,453 @@ + + +PAGE 55,132 ;AN000; +NAME SELECT ;AN000; +TITLE SELECT - DOS - SELECT.EXE ;AN000; +SUBTTL SELECT8.asm ;AN000; +.ALPHA ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT8.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; +; CHANGE HISTORY: +; +; ;AN000; DT added support for creation of the DOSSHELL.BAT as a +; separately installed file. (D233) +; ;AN002; GHG for P1146 +; ;AN003; GHG for D234 +; ;AN004; GHG for P65 +; ;AN005; DT for single drive support +; ;AN006; JW correct critical error problems during format/copy +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + EXTRN EXEC_ERR:BYTE ;AN063;SEH + EXTRN BCHAR:BYTE ;AN000;DT + EXTRN DSKCPY_ERR:BYTE ;AN000;DT + EXTRN DSKCPY_WHICH:BYTE ;AN000;DT + EXTRN DSKCPY_OPTION:BYTE ;AN000;DT + EXTRN DSKCPY_PAN1:WORD ;AN000;DT + EXTRN DSKCPY_PAN2:WORD ;AN000;DT + EXTRN DSKCPY_PAN3:WORD ;AN000;DT + EXTRN DSKCPY_SOURCE:WORD ;AN000;DT +DATA ENDS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE SELECT.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE ROUT_EXT.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN ALLOCATE_MEMORY_CALL:FAR ;AN063;SEH + EXTRN DEALLOCATE_MEMORY_CALL:FAR ;AN063;SEH + EXTRN ALLOCATE_BLOCK:FAR ;AN000;DT + EXTRN PM_BASECHAR:BYTE ;AN000; + EXTRN PM_BASEATTR:BYTE ;AN000; + EXTRN CRD_CCBVECOFF:WORD ;AN000; + EXTRN CRD_CCBVECSEG:WORD ;AN000; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000; + ASSUME CS:SELECT,DS:DATA ;AN000; + ; + INCLUDE CASEXTRN.INC ;AN000; + ; + EXTRN EXIT_SELECT:near ;AN000; + EXTRN CREATE_CONFIG_SYS:NEAR ;AN000; + EXTRN CREATE_AUTOEXEC_BAT:NEAR ;AN000; + EXTRN CREATE_SHELL_BAT:NEAR ;AN000;DT + EXTRN DEALLOCATE_HELP:FAR ;AN007;JW + ; + EXTRN INSTALL_TO_360_DRIVE:NEAR ;AN000;DT + EXTRN INSTALL_ERROR:NEAR ;AN000; + EXTRN EXIT_DOS:NEAR ;AN000; + EXTRN PROCESS_ESC_F3:NEAR ;AN000; + EXTRN EXIT_DOS_CONT:NEAR ;AN000; + EXTRN GET_ENTER_KEY:NEAR ;AN063;SEH + EXTRN GET_OVERLAY:NEAR ;AN063;SEH + extrn Free_Parser:near + PUBLIC DISKETTE_INSTALL ;AN111;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Install is to drive B: or drive A: +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DISKETTE_INSTALL: ;AC111;JW + ; + INIT_VAR F_PATH, E_PATH_NO ;AN000; + INIT_VAR F_APPEND, E_APPEND_NO ;AN000; + INIT_VAR F_PROMPT, E_PROMPT_NO ;AN000; + INIT_VAR F_XMA, E_XMA_NO ;AN000; + INIT_VAR F_FASTOPEN, E_FASTOPEN_NO ;AN000; + INIT_VAR F_SHARE, E_SHARE_NO ;AN000; + INIT_VAR S_INSTALL_PATH,0 ;AN000;set install path field = 0 + ; + .IF < N_DISKETTE_A eq E_DISKETTE_360 > ;AN111;JW + GOTO INSTALL_TO_360_DRIVE ;AN111;JW + .ENDIF ;AN111;JW + ; + .IF < N_DISKETTE_A eq E_DISKETTE_720 > ;AN111;JW + GOTO INSTALL_TO_720_DRIVE ;AN111;JW + .ENDIF ;AN111;JW + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; install is to 1.44M drives +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;;Introduction to 1440KB install ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL PAN_START1440 ;AN000; + PREPARE_PANEL PAN_HBAR ;AN000; + PREPARE_CHILDREN ;AN000; prepare child panels + DISPLAY_PANEL ;AN000; + ; + GET_FUNCTION FK_ENT ;AN000; + ; + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_B > near ;AN111;JW + ;;;insert startup diskette in drive B: ; + INIT_PQUEUE PAN_INST_PROMPT ;AN000; initialize queue + PREPARE_PANEL SUB_INS_START_B ;AN000; insert startup diskette in drive B: + PREPARE_PANEL PAN_HBAR ;AN000; prepare horizontal bar + PREPARE_CHILDREN ;AN000; prepare child panels + DISPLAY_PANEL ;AN000; display panel + ; + GET_FUNCTION FK_ENT ;AN000; + ; + ;;;formatting disk screen ; + INIT_PQUEUE FORMAT_DISKET ;AN000; initialize queue + DISPLAY_PANEL ;AN000; + ; + ;;;format startup diskette in drive B: ; + .REPEAT ;AN006;JW + EXEC_PROGRAM S_FORMAT,S_FORMAT_B,PARM_BLOCK,EXEC_NO_DIR;AN000; format startup disket & copy system files + .LEAVE nc ;AN006;JW + HANDLE_FORMAT_ERROR ;AN000;JW + .UNTIL ;AN006;JW + ; + ;;;create config and autoexec files on startup diskette ; + CREATE_CONFIG S_CONFIG_NEW_B, N_RETCODE ;AN000; create CONFIG.SYS file + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + CREATE_AUTOEXEC S_AUTO_NEW_B,E_DEST_SHELL,N_RETCODE;AN000; create AUTOEXEC.BAT file with SHELL pars + .IF < c > near ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + .ELSE near ;AN111; install is to 1.44 meg A: drive JW + ; + ;;;format startup diskette in drive A: ; + ;;;use format int2f call to display panels ; + INIT_VAR FORMAT_WHICH,STARTUP ;AN111;JW + .REPEAT ;AN006;JW + HOOK_2F_FORMAT ;AN111;JW + EXEC_PROGRAM S_FORMAT,S_FORMAT_A,PARM_BLOCK,EXEC_NO_DIR ;AN000; format startup disket & copy system files + .LEAVE nc ;AN006;JW + UNHOOK_2F ;AN111;JW + HANDLE_FORMAT_ERROR ;AN000;JW + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 ;AN000; + .UNTIL ;AN006;JW + UNHOOK_2F ;AN111;JW + ; + ;;;create config and autoexec files on startup diskette ; + CREATE_CONFIG S_CONSYS_C, N_RETCODE ;AN000; create CONFIG.SYS file + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + CREATE_AUTOEXEC S_AUTOEX_C,E_DEST_SHELL,N_RETCODE ;AN000; create AUTOEXEC.BAT file with SHELL pars + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + ;;; insert the INSTALL diskette in drive A: ; + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 ;AN000; + ; + .ENDIF ;AN000; + ; + ;;;copying files screen ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN111; prepare copying files message JW + DISPLAY_PANEL ;AN000; + ; + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_A > ;AN111;JW + INIT_VAR SOURCE_PANEL, SUB_REM_DOS_A ;AN000; + INIT_VAR DEST_PANEL, SUB_INS_STARTT_S360 ;AN000; + .ENDIF ;AN000; + ; + ;;;copy all files from INSTALL diskette to STARTUP diskette + COPY_FILES I_DEST_DRIVE,COPY_INST_1200_1440,E_INST_1200_1440;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + ; + ;;; insert OPERATING diskette in A: ; + INSERT_DISK SUB_REM_SEL_A, S_DOS_UTIL1_DISK ;AN000; + ; + ;;;copying files screen ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying files message + DISPLAY_PANEL ;AN000; + ; + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_A > ;AN111;JW + INIT_VAR SOURCE_PANEL, SUB_REM_SEL_A ;AN111;JW + INIT_VAR DEST_PANEL, SUB_INS_STARTT_S360 ;AN111;JW + .ENDIF ;AN000; + ; + ;;;copy all files from OPERATING diskette to STARTUP diskette; + COPY_FILES I_DEST_DRIVE,COPY_OPER_1200_1440,E_OPER_1200_1440;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + + .if < f_shell eq e_shell_yes > near ; install the shell? + + ;;; insert MS-SHELL diskette in A: ; + INSERT_DISK SUB_INS_MSSHELL_A, S_DOS_SHEL_DISK ;AN000; + ; + ;;;copying files screen ; + INIT_PQUEUE PAN_INSTALL_DOS ;AN000; initialize queue + PREPARE_PANEL SUB_COPYING ;AN000; prepare copying files message + DISPLAY_PANEL ;AN000; + ; + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_A > ;AN111;JW + INIT_VAR SOURCE_PANEL, SUB_INS_MSSHELL_A ;AN111;JW + INIT_VAR DEST_PANEL, SUB_INS_STARTT_S360 ;AN111;JW + .ENDIF ;AN000; + ; + ;;;copy all files from OPERATING diskette to STARTUP diskette; + COPY_FILES I_DEST_DRIVE,COPY_SHELL_1200_1440,E_SHELL_1200_1440;AN000; + .IF c ;AN000; + GOTO INSTALL_ERROR ;AN000; + .ENDIF ;AN000; + + .endif ; installing the shell + ; + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_B > ;AN111;JW + CREATE_SHELL S_SHELL_NEW_B, N_RETCODE ;AN000;DT + .IF c ;AN000;DT + GOTO INSTALL_ERROR ;AN000;DT + .ENDIF ;AN000;DT + .ELSE ;AN000; + CREATE_SHELL S_SHELL_NEW, N_RETCODE ;AN000;DT + .IF c ;AN000;DT + GOTO INSTALL_ERROR ;AN000;DT + .ENDIF ;AN000;DT + .ENDIF ;AN000; + ; + ;;;installation complete screen ; + INIT_PQUEUE PAN_COMPLETE2 ;AN000; initialize queue + PREPARE_PANEL SUB_COMP_KYS_1C ;AN000; + DISPLAY_PANEL ;AN000; + SAVE_PANEL_LIST ;AN000; + ; + GET_FUNCTION FK_REBOOT ;AN000; +;;;;;;;;control will not return here. user has to reboot;;;;;;;;; end of install to 1.44M drive +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Install to 720K drive +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +INSTALL_TO_720_DRIVE: + .IF < MEM_SIZE eq 256 > + DEALLOCATE_MEMORY + call Free_Parser + .IF < C > + GOTO INSTALL_ERROR + .ENDIF + CALL GET_OVERLAY + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + .ENDIF + + ;;;Introduction to 720KB install + INIT_PQUEUE PAN_INSTALL_DOS + PREPARE_PANEL PAN_START720 + PREPARE_PANEL PAN_HBAR + PREPARE_CHILDREN + DISPLAY_PANEL + + GET_FUNCTION FK_ENT + + CALL DEALLOCATE_HELP + + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_A > near + + ;;;diskcopy INSTALL diskette to STARTUP diskette + DISKCOPY_TO DSKCPY_TO_A_360,NO_SOURCE1,S_DOS_SEL_360 + DISKCOPY_PANELS SUB_REM_DOS_A,SUB_COPYING,SUB_INS_STARTT_S360 + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ; delete unneeded files + ERASE_FILE S_AUTOEX_C + ERASE_FILE S_CONSYS_C + ERASE_FILE S_SELEXE_C + ERASE_FILE S_SELHLP_C + ERASE_FILE S_SELPRT_C + ERASE_FILE S_SELDAT_C + ; make config.sys and autoexec.bat + create_config s_consys_c, n_retcode + .if c + goto install_error + .endif + create_autoexec s_autoex_c, e_dest_dos, n_retcode + .if c + goto install_error + .endif + + ;;; diskcopy OPERATE diskette to WORKING diskette + .REPEAT + DISKCOPY_TO DSKCPY_TO_A_360,SOURCE1,S_DOS_UTIL1_DISK + DISKCOPY_PANELS SUB_REM_SEL_A,SUB_COPYING,SUB_INS_WORKING_A + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .LEAVE < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 + .UNTIL + + ;;;perhaps diskcopy MS-SHELL to SHELL + .IF < f_shell eq e_shell_yes > near + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 + DISKCOPY_TO DSKCPY_TO_A_360,SOURCE1,S_DOS_SHEL_DISK + DISKCOPY_PANELS SUB_INS_MSSHELL_A,SUB_COPYING,SUB_INS_SHELL_S360 + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ; make config.sys and autoexec.bat + create_config s_consys_c, n_retcode + .if c + goto install_error + .endif + create_autoexec s_autoex_c, e_dest_shell, n_retcode + .if c + goto install_error + .endif + create_shell s_shell_new, n_retcode + .IF c near + goto install_error + .ENDIF + .ENDIF + + .ELSE near ; This is a two floppy system. Install from A to B. + + ;;;diskcopy INSTALL diskette to STARTUP diskette + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_SEL_360 + DISKCOPY_PANELS SUB_INS_START_B,SUB_COPYING,NOPANEL + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ; delete unneeded files + ERASE_FILE S_AUTO_NEW_B + ERASE_FILE S_CONFIG_NEW_B + ERASE_FILE S_SELEXE_NEW_B + ERASE_FILE S_SELHLP_NEW_B + ERASE_FILE S_SELPRT_NEW_B + ERASE_FILE S_SELDAT_NEW_B + ; make config.sys and autoexec.bat + create_config s_config_new_b, n_retcode + .if c + goto install_error + .endif + create_autoexec s_auto_new_b, e_dest_dos, n_retcode + .if c + goto install_error + .endif + + ;;; diskcopy OPERATE diskette to WORKING diskette + .REPEAT + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_UTIL1_DISK + DISKCOPY_PANELS SUB_INS_OP_WORK,SUB_COPYING,NOPANEL + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .LEAVE < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 + .UNTIL + + ;;;perhaps diskcopy MS-SHELL to SHELL + .IF < f_shell eq e_shell_yes > near + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_SEL_360 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_SHEL_DISK + DISKCOPY_PANELS SUB_INS_SHELL_DISKS,SUB_COPYING,NOPANEL + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ; make config.sys and autoexec.bat + create_config s_config_new_b, n_retcode + .if c + goto install_error + .endif + create_autoexec s_auto_new_b, e_dest_shell, n_retcode + .if c + goto install_error + .endif + create_shell s_shell_new_b, n_retcode + .if c + goto install_error + .endif + .ENDIF + .ENDIF ; end if two drive 720 installation + + + ;;;installation complete and change diskettes screen + INIT_PQUEUE PAN_COMPLETE2 + PREPARE_PANEL SUB_COMP_KYS_2 + DISPLAY_PANEL + SAVE_PANEL_LIST + GET_FUNCTION FK_REBOOT +;;;;;;;;control will not return here. user has to reboot +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS + END + \ No newline at end of file diff --git a/v4.0/src/SELECT/SELECT9.ASM b/v4.0/src/SELECT/SELECT9.ASM new file mode 100644 index 0000000..e294c6c --- /dev/null +++ b/v4.0/src/SELECT/SELECT9.ASM @@ -0,0 +1,518 @@ + + +PAGE 55,132 +NAME SELECT +TITLE SELECT - DOS - SELECT.EXE +SUBTTL SELECT9.asm +.ALPHA +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; SELECT9.ASM : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENTS: Assemble with MASM 3.0 (using the /A option) +; +; Panel flow is defined in the following files: +; +; � SELECT1.ASM +; � SELECT2.ASM +; � SELECT3.ASM +; � SELECT4.ASM +; � SELECT5.ASM +; � SELECT6.ASM +; +; +; Module contains code for : +; - Format the drives +; - Copy files +; +; CHANGE HISTORY: +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' + EXTRN DSKCPY_ERR:BYTE + EXTRN DSKCPY_WHICH:BYTE + EXTRN DSKCPY_OPTION:BYTE + EXTRN DSKCPY_PAN1:WORD + EXTRN DSKCPY_PAN2:WORD + EXTRN DSKCPY_PAN3:WORD + EXTRN DSKCPY_SOURCE:WORD +DATA ENDS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Define dummy segment to calculate end of program +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PARSER SEGMENT PARA PUBLIC 'PARSER' +PARSER ENDS + +SET_BLOCK equ 4AH +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.XLIST + INCLUDE PANEL.MAC + INCLUDE SELECT.INC + INCLUDE PAN-LIST.INC + INCLUDE CASTRUC.INC + INCLUDE STRUC.INC + INCLUDE MACROS.INC + INCLUDE MACROS7.INC + INCLUDE MACROS8.INC + INCLUDE EXT.INC + INCLUDE VARSTRUC.INC + INCLUDE ROUT_EXT.INC +.LIST +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' + ASSUME CS:SELECT,DS:DATA + + INCLUDE CASEXTRN.INC + + EXTRN EXIT_SELECT:near + EXTRN CREATE_CONFIG_SYS:NEAR + EXTRN CREATE_AUTOEXEC_BAT:NEAR + EXTRN CREATE_SHELL_BAT:NEAR + EXTRN DEALLOCATE_HELP:FAR + EXTRN DEALLOCATE_MEMORY_CALL:FAR + EXTRN ALLOCATE_BLOCK:FAR + EXTRN ALLOCATE_LVB:FAR + EXTRN GET_OVERLAY:NEAR + EXTRN ALLOCATE_MEMORY_CALL:FAR + + PUBLIC INSTALL_TO_360_DRIVE + PUBLIC INSTALL_ERROR + PUBLIC EXIT_DOS,PROCESS_ESC_F3 + PUBLIC EXIT_DOS_CONT + public Free_Parser + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +INSTALL_TO_360_DRIVE: + .IF < MEM_SIZE eq 256 > + DEALLOCATE_MEMORY + call Free_Parser + .IF < C > + GOTO INSTALL_ERROR + .ENDIF + CALL GET_OVERLAY + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + .ENDIF + + ;;;Introduction to 360KB install + INIT_PQUEUE PAN_INSTALL_DOS + PREPARE_PANEL PAN_START360 + PREPARE_PANEL PAN_HBAR + PREPARE_CHILDREN + DISPLAY_PANEL + + GET_FUNCTION FK_ENT + + CALL DEALLOCATE_HELP + + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_A > near + + ;;;diskcopy INSTALL diskette to WORKING1 + DISKCOPY_TO DSKCPY_TO_A_360,NO_SOURCE1,S_DOS_COM_360 + DISKCOPY_PANELS SUB_REM_DOS_A,SUB_COPYING,SUB_INS_WORK1_S360 + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF < c > + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ERASE_FILE S_AUTOEX_C + ERASE_FILE S_CONSYS_C + ERASE_FILE S_SELCOM_C + ERASE_FILE S_SELHLP_C + ERASE_FILE S_SELPRT_C + + ;;;diskcopy OPERATING1 diskette to WORKING2 + DISKCOPY_TO DSKCPY_TO_A_360,SOURCE1,S_DOS_UTIL1_DISK + DISKCOPY_PANELS SUB_REM_SELECT_360,SUB_COPYING,SUB_INS_WORK2_S360 + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .LEAVE < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + .UNTIL + + ;;;diskcopy OPERATING 2 diskette to WORKING3 + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_A_360,NO_SOURCE1,S_DOS_UTIL2_DISK + DISKCOPY_PANELS SUB_INS_OPER2,SUB_COPYING,SUB_INS_WORK3_A + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + + ;;;diskcopy OPERATING 3 diskette to STARTUP + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_A_360,SOURCE1,S_DOS_UTIL3_DISK + DISKCOPY_PANELS SUB_REM_UTIL1_360,SUB_COPYING,SUB_INS_STARTT_S360 + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + ERASE_FILE S_RECOVER_C + ERASE_FILE S_FASTOPEN_C + ;;;create config and autoexec files on startup diskette + CREATE_CONFIG S_CONSYS_C, N_RETCODE + .IF c + GOTO INSTALL_ERROR + .ENDIF + CREATE_AUTOEXEC S_AUTOEX_C,E_DEST_DOS,N_RETCODE + .IF c near + GOTO INSTALL_ERROR + .ENDIF + + .IF < ACTIVE eq EGA > or + .IF < ALTERNATE eq EGA > or + .IF < ACTIVE eq LCD > or + .IF < ALTERNATE eq LCD > near + .THEN + .IF < F_VDISK eq E_VDISK_NO > + ERASE_FILE S_VDISK_C + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_ANSI eq E_ANSI_NO > + ERASE_FILE S_ANSI_C + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_APPEND eq E_APPEND_NO > + ERASE_FILE S_APPEND_C + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_GRAFTABL eq E_GRAFTABL_NO > or + .IF < F_GRAFTABL eq E_GRAFTABL_NA > + ERASE_FILE S_GRAFTABL_C + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_GRAPHICS eq E_GRAPHICS_NO > + ERASE_FILE S_GRAPHICS_C + ERASE_FILE S_GRAPHPRO_C + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + ;;;Insert SELECT diskette in drive A: + INSERT_DISK SUB_REM_SHELL_360, S_DOS_SEL_360 + + ;;;copying files from INSTALL diskette screen + INIT_PQUEUE PAN_INSTALL_DOS + PREPARE_PANEL SUB_COPYING + DISPLAY_PANEL + + INIT_VAR SOURCE_PANEL, SUB_REM_SHELL_360 + INIT_VAR DEST_PANEL, SUB_INS_STARTT_S360 + + .IF < ACTIVE eq EGA > or + .IF < ALTERNATE eq EGA > near + .THEN + .IF < MEM_SIZE eq 256 > + DEALLOCATE_MEMORY + .ENDIF + COPY_FILES2 I_DEST_DRIVE,COPY_SEL_EGA,E_SEL_EGA,S_INSTALL_PATH + .IF c near + .IF < MEM_SIZE eq 256 > + ALLOCATE_MEMORY + CALL INITIALIZE + .ENDIF + HANDLE_ERROR ERR_COPY_DISK, E_RETURN + .ENDIF + .IF < MEM_SIZE eq 256 > near + ALLOCATE_MEMORY + CALL INITIALIZE + .ENDIF + .ELSE near + COPY_FILES2 I_DEST_DRIVE,COPY_SEL_LCD,E_SEL_LCD,S_INSTALL_PATH ;AC111; copy files to f-disk JW + .IF c near + HANDLE_ERROR ERR_COPY_DISK, E_RETURN + .ENDIF + .ENDIF + .ENDIF + + ;;;diskcopy MS-SHELL diskette to SHELL + .if near + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_A_360,SOURCE1,S_DOS_SHEL_DISK + DISKCOPY_PANELS SUB_INS_MSSHELL_A,SUB_COPYING,SUB_INS_SHELL_S360 + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DISKCOPY_PARM,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + CREATE_SHELL S_SHELL_NEW, N_RETCODE + .IF c near + GOTO INSTALL_ERROR + .ENDIF + .endif + + .ELSE near + + ;;;diskcopy INSTALL diskette to WORKING 1 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_COM_360 + DISKCOPY_PANELS SUB_INS_WORK1_360,SUB_COPYING,NOPANEL + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + ERASE_FILE S_AUTO_NEW_B + ERASE_FILE S_CONFIG_NEW_B + ERASE_FILE S_SELCOM_NEW_B + ERASE_FILE S_SELHLP_NEW_B + ERASE_FILE S_SELPRT_NEW_B + + ;;;diskcopy OPERATING 1 diskette to WORKING 2 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_UTIL1_DISK + DISKCOPY_PANELS SUB_INS_WORK2_360,SUB_COPYING,NOPANEL + .REPEAT + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .LEAVE < N_DSKCPY_ERR ne E_DSKCPY_RETRY > + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + .UNTIL + + ;;;diskcopy OPERATING 2 diskette to WORKING3 + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_UTIL2_DISK + DISKCOPY_PANELS SUB_INS_WORK3_360,SUB_COPYING,NOPANEL + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + + ;;;diskcopy OPERATING 3 diskette to STARTUP + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_UTIL3_DISK + DISKCOPY_PANELS SUB_INS_START_360,SUB_COPYING,NOPANEL + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + ERASE_FILE S_RECOVER_B + ERASE_FILE S_FASTOPEN_B + ;;;create config and autoexec files on startup diskette + CREATE_CONFIG S_CONFIG_NEW_B, N_RETCODE + .IF c + GOTO INSTALL_ERROR + .ENDIF + CREATE_AUTOEXEC S_AUTO_NEW_B,E_DEST_DOS,N_RETCODE + .IF c + GOTO INSTALL_ERROR + .ENDIF + .IF < ACTIVE eq EGA > or + .IF < ALTERNATE eq EGA > or + .IF < ACTIVE eq LCD > or + .IF < ALTERNATE eq LCD > near + .THEN + .IF < F_VDISK eq E_VDISK_NO > + ERASE_FILE S_VDISK_B + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_ANSI eq E_ANSI_NO > + ERASE_FILE S_ANSI_B + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_APPEND eq E_APPEND_NO > + ERASE_FILE S_APPEND_B + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_GRAFTABL eq E_GRAFTABL_NO > or + .IF < F_GRAFTABL eq E_GRAFTABL_NA > + ERASE_FILE S_GRAFTABL_B + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + .IF < F_GRAPHICS eq E_GRAPHICS_NO > + ERASE_FILE S_GRAPHICS_B + ERASE_FILE S_GRAPHPRO_B + .IF c + GOTO INSTALL_ERROR + .ENDIF + .ENDIF + ;;;Insert SELECT diskette in drive A: + INSERT_DISK SUB_INS_INSTALL_360, S_DOS_SEL_360 + ;;;copying files from INSTALL diskette screen + INIT_PQUEUE PAN_INSTALL_DOS + PREPARE_PANEL SUB_COPYING + DISPLAY_PANEL + .IF < ACTIVE eq EGA > or + .IF < ALTERNATE eq EGA > near + .IF < MEM_SIZE eq 256 > + DEALLOCATE_MEMORY + .ENDIF + COPY_FILES2 I_DEST_DRIVE,COPY_SEL_EGA,E_SEL_EGA,S_INSTALL_PATH ;AC111; copy files to f-disk JW + .IF c near + .IF < MEM_SIZE eq 256 > + ALLOCATE_MEMORY + CALL INITIALIZE + .ENDIF + HANDLE_ERROR ERR_COPY_DISK, E_RETURN + .ENDIF + .IF < MEM_SIZE eq 256 > + ALLOCATE_MEMORY + CALL INITIALIZE + .ENDIF + .ELSEIF < ACTIVE eq LCD > or + .IF < ALTERNATE eq LCD > + COPY_FILES2 I_DEST_DRIVE,COPY_SEL_LCD,E_SEL_LCD,S_INSTALL_PATH ;AC111; copy files to f-disk JW + .IF c near + HANDLE_ERROR ERR_COPY_DISK, E_RETURN + .ENDIF + .ENDIF + .ENDIF + + .if near + ;;;diskcopy MS-SHELL to SHELL + .REPEAT + INSERT_DISK SUB_REM_DOS_A, S_DOS_COM_360 + DISKCOPY_TO DSKCPY_TO_B,SOURCE1,S_DOS_SHEL_DISK + DISKCOPY_PANELS SUB_INS_SHELL_DISKS,SUB_COPYING,NOPANEL + INIT_VAR N_DSKCPY_ERR,E_DSKCPY_OK + CALL HOOK_INT_2F + EXEC_PROGRAM S_DISKCOPY,S_DSKCPY_TO_B,PARM_BLOCK,EXEC_NO_DIR + CALL RESTORE_INT_2F + .IF c + .THEN + GOTO INSTALL_ERROR + .ENDIF + .UNTIL < N_DSKCPY_ERR ne E_DSKCPY_RETRY > near + CREATE_SHELL S_SHELL_NEW_B, N_RETCODE + .IF c + GOTO INSTALL_ERROR + .ENDIF + .endif ; copy to shell + + .ENDIF + + ;;;installation complete and change diskettes screen + INIT_PQUEUE PAN_COMPLETE3 + PREPARE_PANEL SUB_COMP_KYS_3 + DISPLAY_PANEL + SAVE_PANEL_LIST + GET_FUNCTION FK_REBOOT + +;;;;;;;;control will not return here. user has to reboot;;;;;;;;; end of install to 1.2M or 1.44M drive +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Process the ESC/F3 keys. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PROCESS_ESC_F3: + .IF < N_USER_FUNC eq E_ESCAPE > + POP_HEADING + .ENDIF +EXIT_DOS: + CLEAR_SCREEN2 +EXIT_DOS_CONT: + .IF < I_DEST_DRIVE eq E_DEST_DRIVE_C > and + .IF < N_HOUSE_CLEAN eq E_CLEAN_YES > + ERASE_FILE S_AUTO_NEW + ERASE_FILE S_CONFIG_NEW + ERASE_FILE S_SHELL_NEW + ERASE_FILE S_SELECT_TMP + CHANGE_AUTOEXEC S_AUTO_REBOOT, S_AUTO_MENU + .ENDIF + + GOTO EXIT_SELECT + +INSTALL_ERROR: + + .IF < DSKCPY_ERR ne DSKCPY_EXIT > + HANDLE_ERROR ERR_EXIT, E_QUIT + .ENDIF + + GOTO EXIT_DOS + +Free_Parser: + MOV AH,62H + INT 21H + MOV AX,BX + MOV BX,PARSER + MOV ES,AX + SUB BX,AX + MOV AH,SET_BLOCK + DOSCALL + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS + END + \ No newline at end of file diff --git a/v4.0/src/SELECT/SELQUIT.ASM b/v4.0/src/SELECT/SELQUIT.ASM new file mode 100644 index 0000000..e92a619 --- /dev/null +++ b/v4.0/src/SELECT/SELQUIT.ASM @@ -0,0 +1,313 @@ + + +PAGE 55,132 ;AN000; +NAME SELQUIT ;AN000; +TITLE SELQUIT - Exit Panel support for SELECT.EXE;AN000; +SUBTTL selquit.asm ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; SELQUIT.ASM +; +; DATE: July 6/87 +; +; COMMENTS: +; +; This files must be compiled with MASM 3.0 (using /A option) +; +; Copyright 1988 Microsoft +; +; ;AN001; Added flag to indicate error processing was in effect. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.LFCOND ;AN000; +.XLIST ;AN000; + INCLUDE PANEL.MAC ;AN000; + INCLUDE PCEQUATE.INC ;AN000; + INCLUDE PAN-LIST.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE EXT.INC ;AN000; + INCLUDE STRUC.INC ;AN000; + INCLUDE MACROS.INC ;AN000; +.LIST ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Setup Environment +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN QM_ACTIVEPAN:WORD ;AN000; + ; + EXTRN GET_KEY:NEAR ;AN000; + EXTRN CURSOROFF:NEAR ;AN000; + EXTRN PCINPUT_CALL:NEAR ;AN000; + EXTRN PCDISPQ_CALL:NEAR ;AN000; + ; + EXTRN WR_DRETLEN:WORD ;AN000; + EXTRN WR_DRETOFF:WORD ;AN000; + EXTRN WR_DRETSEG:WORD ;AN000; + EXTRN GET_PCB:NEAR ;AN000; + EXTRN QM_OPT1:WORD ;AN000; + EXTRN QM_ID:WORD ;AN000; + EXTRN INC_KS:WORD ;AN000; + ; + EXTRN HANDLE_CHILDREN:NEAR ;AN000; + EXTRN ADJUST_UP:NEAR ;AN000; + EXTRN ADJUST_DOWN:NEAR ;AN000; + EXTRN INIT_PQUEUE_CALL:NEAR ;AN000; + EXTRN PREPARE_PANEL_CALL:NEAR ;AN000; + EXTRN DISPLAY_PANEL_CALL:NEAR ;AN000; + EXTRN GET_FUNCTION_CALL:NEAR ;AN000; + EXTRN QM_OPT2:WORD ;AN000; + EXTRN WR_REFIELDCNT:WORD ;AN000; + EXTRN ERROR_KEYS:BYTE ;AN000; + EXTRN ERROR_KEYS_LEN:ABS ;AN000; + EXTRN PCMBEEP_CALL:NEAR ;AN000; + EXTRN BIN_TO_CHAR_ROUTINE:FAR ;AN000; + ; +TRUE EQU 1 ;AN000; +FALSE EQU 0 ;AN000; + ; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; HANDLE_F3 +; +; +; CLC = return to SELECT +; STC = quit SELECT..... +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +F3_ACTIVE DB FALSE ;AN001;DT + ; + PUBLIC HANDLE_F3 ;AN000; +HANDLE_F3 PROC ;AN000; + PUSHH ;AN000; + PUSHH ;AN000; + PUSHH ;AN000; + ; + .IF < F3_ACTIVE eq FALSE > near ;AN000; + CALL CURSOROFF ;;AN000;;; + ; + MOV AX,QM_PUSHPQU ;AN000;save parent queue + OR AX,QM_PUSHCQU ;AN000;save child queue + MOV QM_OPT1,AX ;AN000; + CALL PCDISPQ_CALL ;AN000;update display queue + ; + MOV QM_OPT1,QM_CLSPAN ;AN000;clear parent panel queue + OR QM_OPT1,QM_CLSCHD ;AN000;clear parent panel queue + CALL PCDISPQ_CALL ;AN000;update display queue + MOV QM_ACTIVEPAN,PAN_CONFIRM;AN000;current active parent panel + MOV AX,PAN_CONFIRM ;AN000; + MOV QM_OPT1,QM_PUSHPAN ;AN000;push parent panels + CALL PREPARE_PANEL_CALL ;AN000;add panel to display queue + + MOV WR_REFIELDCNT,0 ;AN000;set for break = off + PREPARE_PANEL PAN_HBAR ;AN000; + PREPARE_CHILDREN ;AN000; + DISPLAY_PANEL ;AN000;push parent panels + ; + MOV CX,FK_ENT_F3_LEN ;AN000; + LEA DX,FK_ENT_F3 ;AN000; + MOV WR_DRETLEN,CX ;AN000;get return string length + MOV AX,DX ;AN000;get return string offset + MOV WR_DRETOFF,AX ;AN000; + MOV AX,DS ;AN000;get return string segment + MOV WR_DRETSEG,AX ;AN000; + CALL GET_KEY ;AN000; + MOV AX,INC_KS ;AN003;GHG + MOV N_USER_FUNC,AX ;AN003;GHG + ; + MOV AX,QM_POPPQU ;AN000; + OR AX,QM_POPCQU ;AN000; + MOV QM_OPT1,AX ;AN000; + CALL PCDISPQ_CALL ;AN000; + MOV AX,I_USER_INDEX ;AN000;get last current element + ; + .IF < N_USER_FUNC eq F3*256 > ;AN000; + .THEN ;AN000; + STC ;AN000; + MOV F3_ACTIVE,TRUE ;AN000;DT Indicate exit selected + .ELSE ;AN000; + POP WR_REFIELDCNT ;AN000; + PUSH WR_REFIELDCNT ;AN000; + DISPLAY_PANEL ;AN000; + CLC ;AN000; + .ENDIF ;AN000;;; + ; + .ELSE ;AN027;SEH Set carry flag to avoid + STC ;AN027;SEH endless loop in Get_Function_call + .ENDIF ;AN000; + ; + POPP ;AN000; + POPP ;AN000; + POPP ;AN000; + RET ;AN000; +HANDLE_F3 ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; BX,action +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ERROR_PANEL DW ? ;AN000; +ERROR_TYPE DW ? ;AN000; +ERROR_CODE DW ? ;AN000; +ERROR_STRING DB 5 DUP(0) ;AN000; + ; + PUBLIC ERROR_ACTIVE ;AN001;JW +ERROR_ACTIVE DB 0 ;AN001;JW + ; + PUBLIC HANDLE_ERROR_CALL ;AN000; +HANDLE_ERROR_CALL PROC FAR ;AN000; + PUSHH ;AN000; + PUSHH ;AN000; + PUSHH ;AN000; + ; + MOV ERROR_CODE,AX ;AN000; + MOV ERROR_PANEL,BX ;AN000; + MOV ERROR_TYPE,CX ;AN000; + MOV ERROR_ACTIVE,1 ;AN001;JW + ; + MOV BX,ERR_BORDER ;AN000;DT current active parent panel + CALL GET_PCB ;AN000;DT get the PCB for this + MOV ES:[DI].PCB_CHILDNUM,CX ;AN000;DT set the number of children + ; + CALL CURSOROFF ;AN000; + ; + MOV QM_OPT1,QM_PUSHPQU ;AN000;save parent queue + OR QM_OPT1,QM_PUSHCQU ;AN000;save child queue + CALL PCDISPQ_CALL ;AN000;update display queue + ; + .IF < F3_ACTIVE eq TRUE > ;AN000; + MOV QM_OPT1,QM_CLSPAN ;AN000;clear parent panel queue + OR QM_OPT1,QM_CLSCHD ;AN000;clear parent panel queue + CALL PCDISPQ_CALL ;AN000;update display queue + .ENDIF ;AN000; + + MOV QM_OPT1,QM_PUSHPAN ;AN000;push parent panels + OR QM_OPT2,QM_BREAKON ;AN000;break on + + MOV BX,ERR_BORDER ;AN000;current active parent panel + MOV QM_ID,BX ;AN000;current active parent panel + MOV QM_ACTIVEPAN,BX ;AN000;current active parent panel + MOV AX,BX ;AN000; + CALL PREPARE_PANEL_CALL ;AN000;add panel to display queue + ; + MOV QM_OPT2,0 ;AN000; + ; +;;;;;;;;MOV WR_REFIELDCNT,0 ;set for break = off + PREPARE_PANEL ERROR_PANEL ;AN000; + PREPARE_CHILDREN ;AN000; + DISPLAY_PANEL ;AN000;push parent panels + ; + CALL PCMBEEP_CALL ;AN000; + ; + MOV CX,ERROR_TYPE ;AN000; + INC CX ;AN000;JW + LEA DX,ERROR_KEYS ;AN000; + CALL GET_FUNCTION_CALL ;AN000; + MOV ERROR_ACTIVE,0 ;AN001;JW + ; + MOV QM_OPT1,QM_POPPQU ;AN000; + OR QM_OPT1,QM_POPCQU ;AN000; + CALL PCDISPQ_CALL ;AN000; + MOV AX,I_USER_INDEX ;AN000;get last current element + ; + .IF < N_USER_FUNC eq F3*256 > or ;AC000;DT F3 to exit SELECT + .IF < F3_ACTIVE eq TRUE > ;AN000;DT or already selected + .THEN ;AN000; + STC ;AN000; + .ELSE ;AN000; + POP WR_REFIELDCNT ;AN000; + PUSH WR_REFIELDCNT ;AN000; + DISPLAY_PANEL ;AN000; + CLC ;AN000; + .ENDIF ;AN000; + ; + POPP ;AN000; + POPP ;AN000; + POPP ;AN000; + RET ;AN000; +HANDLE_ERROR_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; BX,action +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC HANDLE_PANEL_CALL ;AN000; +HANDLE_PANEL_CALL PROC FAR ;AN000; + PUSH AX ;AN000; + PUSH AX ;AN000; + PUSH AX ;AN000; + MOV AX,PAN_INSTALL_DOS ;AN000; + CALL INIT_PQUEUE_CALL ;AN000; + POP AX ;AN000; + CALL PREPARE_PANEL_CALL ;AN000; + POP AX ;AN000; + .IF < AX ne PAN_DSKCPY_CPY > ;AN000; + MOV AX,PAN_HBAR ;AN000; + CALL PREPARE_PANEL_CALL ;AN000; + CALL HANDLE_CHILDREN ;AN000; + .ENDIF ;AN000; + CALL DISPLAY_PANEL_CALL ;AN000; + POP AX ;AN000; + RET ;AN000; +HANDLE_PANEL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; BX,action +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC HANDLE_PANEL_CALL2 ;AN000; +HANDLE_PANEL_CALL2 PROC FAR ;AN000; + PUSH AX ;AN000; + PUSH AX ;AN000; + MOV AX,BX ;AN000;DT + CALL INIT_PQUEUE_CALL ;AN000;DT + POP AX ;AN000; + CALL PREPARE_PANEL_CALL ;AN000; + POP AX ;AN000; + PUSH AX ;AN000;DT + .IF < AX ne SUB_COPYING > ;AN000; + MOV AX,PAN_HBAR ;AN000; + CALL PREPARE_PANEL_CALL ;AN000; + CALL HANDLE_CHILDREN ;AN000; + .ENDIF ;AN000; + CALL DISPLAY_PANEL_CALL ;AN000; + POP AX ;AN000; + RET ;AN000; +HANDLE_PANEL_CALL2 ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC HANDLE_PANEL_CALL3 ;AN111;JW +HANDLE_PANEL_CALL3 PROC FAR ;AN111;JW + CALL INIT_PQUEUE_CALL ;AN111;JW + CALL DISPLAY_PANEL_CALL ;AN111;JW + RET ;AN111;JW +HANDLE_PANEL_CALL3 ENDP ;AN111;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; BX,action +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC HANDLE_KEYSTROKE ;AN000; +HANDLE_KEYSTROKE PROC FAR ;AN000; + MOV CX,FK_ENT_LEN ;AN000; + LEA DX,FK_ENT ;AN000; + CALL GET_FUNCTION_CALL ;AN000; + RET ;AN000; +HANDLE_KEYSTROKE ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; End of program code +; +;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SELSERV.ASM b/v4.0/src/SELECT/SELSERV.ASM new file mode 100644 index 0000000..db547ba --- /dev/null +++ b/v4.0/src/SELECT/SELSERV.ASM @@ -0,0 +1,108 @@ + + +PAGE 55,132 ;AN000; +NAME SELSERV ;AN000; +TITLE SELSERV - SELECT Services ;AN000; +SUBTTL selserv.asm ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ADJUST_CURELE +; +; +; Entry: +; AX = index on entry +; +; Exit: +; AX = adjusted index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT ;AN000; + ; + EXTRN WR_SCBID:WORD ;AN000; + ; +SCROLL_ADJUST LABEL BYTE ;AN000; + DB 1 ;AN000;SCR_DOS_SUPPORT + DB 1 ;AN000;SCR_CTY_KYB + DB 0 ;AN000;SCR_CTY_1 + DB 0 ;AN000;SCR_CTY_2 + DB 0 ;AN000;SCR_KYB_1 + DB 0 ;AN000;SCR_KYB_2 + DB 1 ;AN000;SCR_FR_KYB + DB 1 ;AN000;SCR_IT_KYB + DB 1 ;AN000;SCR_UK_KYB + DB 1 ;AN000;SCR_DEST_DRIVE + DB 0 ;AN000;SCR_PRT_TYPE + DB 1 ;AN000;SCR_PARALLEL + DB 0 ;AN000;SCR_SERIAL + DB 0 ;AN000;SCR_PRT_REDIR + DB 1 ;AN000;SCR_REVIEW + DB 0 ;AN000;SCR_FUNC_DISK + DB 0 ;AN000;SCR_FUNC_DISKET + DB 1 ;AN000;SCR_FIXED_FIRST + DB 1 ;AN000;SCR_FIXED_BOTH + DB 1 ;AN000;SCR_FORMAT + DB 0 ;AC000;SCR_CONTEXT_HLP / SCR_INDEX_HLP JW + DB 0 ;AN000;SCR_TITLE_HLP + DB 0 ;AN000;SCR_ACC_CTY JW + DB 0 ;AN000;SCR_ACC_KYB JW + DB 0 ;AN000;SCR_ACC_PRT JW + DB 1 ;AC035;SCR_COPY_DEST SEH + DB 0 ;AN035;SCR_DEST_A_C; SEH + DB 1 ;mrw ;scr_choose_shell +SCROLL_ADJUST_LEN EQU ($-SCROLL_ADJUST);AN000; +ADJUST_ON EQU 1 ;AN000; +ADJUST_OFF EQU 0 ;AN000; + ; + PUBLIC ADJUST_UP,ADJUST_DOWN ;AN000; + ; +ADJUST_UP PROC ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + OR AX,AX ;AN000; + JZ AC_1 ;AN000; + ; + MOV CL,ADJUST_ON ;AN000; + CMP CS:[BX-1]+SCROLL_ADJUST,CL;AN000; + JNE AC_1 ;AN000; + ; + SHL AX,1 ;AN000; + DEC AX ;AN000; +AC_1: POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +ADJUST_UP ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; ADJUST_INDEX +; +; AX = index on entry +; +; AX = adjusted index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ADJUST_DOWN PROC ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + OR AX,AX ;AN000; + JZ AI_1 ;AN000; + ; + MOV CL,ADJUST_ON ;AN000; + CMP CS:[BX-1]+SCROLL_ADJUST,CL;AN000; + JNE AC_1 ;AN000; + ; + SHR AX,1 ;AN000; + INC AX ;AN000; +AI_1: POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +ADJUST_DOWN ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/v4.0/src/SELECT/SEL_FILE.INC b/v4.0/src/SELECT/SEL_FILE.INC new file mode 100644 index 0000000..b52b586 --- /dev/null +++ b/v4.0/src/SELECT/SEL_FILE.INC @@ -0,0 +1,578 @@ + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; +; SEL_FILE.INC : Copyright 1988 Microsoft +; +; DATE: August 8/87 +; +; COMMENT: Module contains variables used by SELECT. +; +; CHANGE HISTORY: +; +; ;AN002; Removal of SHELL.BAT from copying from SHELL (Source) +; diskette (D233)! +; +; ;AN004; 360KB support (D65) +; +; ;AN005;JW - P2145, Had to move chkdsk to shell due to growth of dos files +; +; ;AN006;JW - P2261, Removal of unused utilities on startup disk +; +; ;AN007;JW - D354, Removal of FASTOPEN and RECOVER from startup disk +; +; ;AN008;JW - P , SELECT.HLP was not being hidden before copy +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Files found on INSTALL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + PUBLIC COPY_SEL_EGA,E_SEL_EGA ;AN000; +COPY_SEL_EGA LABEL BYTE ;AN000; + DB 'EGA.CPI ' ;AN000; +E_SEL_EGA EQU ( $ - COPY_SEL_EGA ) / 12 ;AN000; + ; + PUBLIC COPY_SEL_LCD,E_SEL_LCD ;AN000; +COPY_SEL_LCD LABEL BYTE ;AN000; + DB 'LCD.CPI ' ;AN000; +E_SEL_LCD EQU ( $ - COPY_SEL_LCD ) / 12 ;AN000; + ; + PUBLIC COPY_SEL_SHEL,E_SEL_SHEL ;AN000; +COPY_SEL_SHEL LABEL BYTE ;AN000; + DB 'COMMAND.COM ' ;AN000; +E_SEL_SHEL EQU ( $ - COPY_SEL_SHEL) / 12 ;AN000; + ; + PUBLIC COPY_INST_1200_1440,E_INST_1200_1440 ;AN000; +COPY_INST_1200_1440 LABEL BYTE ;AN000; this will copy files for 1.44M diskettes + ; + DB 'ANSI.SYS ' ;AN000; + DB 'COMMAND.COM ' ;AN000; + DB 'COUNTRY.SYS ' ;AN000; + DB 'DISKCOPY.COM' ;AN001;GHG + DB 'DISPLAY.SYS ' ;AN000; + DB 'DRIVER.SYS ' ;AN000; + DB 'EGA.CPI ' + DB 'FORMAT.COM ' ;AN000; + DB 'GRAFTABL.COM' + DB 'GRAPHICS.COM' + DB 'GRAPHICS.PRO' + DB 'KEYB.COM ' ;AN000; + DB 'KEYBOARD.SYS' ;AN000; + DB 'LCD.CPI ' + DB 'MODE.COM ' ;AN000; + DB 'NLSFUNC.EXE ' + DB 'PRINT.COM ' + DB 'PRINTER.SYS ' ;AN000; + DB 'RAMDRIVE.SYS' ;AN000; + DB '4201.CPI ' ;AN000; + DB '5202.CPI ' ;AN000; + DB '4208.CPI ' ;AN000 + DB 'REPLACE.EXE ' + DB 'SHARE.EXE ' ;AC055 + DB 'SYS.COM ' ;AN000; + ; +E_INST_1200_1440 EQU ( $ - COPY_INST_1200_1440 ) / 12 ;AN000; end of list for 1.44M diskettes + ; + ; + PUBLIC HIDE_SEL,E_HIDE_SEL ;AN000; +HIDE_SEL DB 'AUTOEXEC.BAT',?,? ;AN000; + DB 'CONFIG.SYS ',?,? ;AN000; + DB 'SELECT.PRT ',?,? ;AN000; + DB 'SELECT.EXE ',?,? ;AN000; + DB 'SELECT.DAT ',?,? ;AN000; + DB 'SELECT.HLP ',?,? ;AN008;JW +E_HIDE_SEL EQU ($ - HIDE_SEL) / 14 ;AN000; + ; + PUBLIC HIDE_STARTUP,E_HIDE_STARTUP ;AN000; +HIDE_STARTUP DB 'AUTOEXEC.BAT',?,? ;AN000; + DB 'CONFIG.SYS ',?,? ;AN000; + DB 'SELECT.COM ',?,? ;AN000; + DB 'SELECT.HLP ',?,? ;AN000; + DB 'SELECT.PRT ',?,? ;AN000; +E_HIDE_STARTUP EQU ($ - HIDE_STARTUP) / 14 ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Files found on OPERATE diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + PUBLIC COPY_OPER_1200_1440,E_OPER_1200_1440 ;AN000; +COPY_OPER_1200_1440 LABEL BYTE ;AN000; this will copy files to 1.2M $ 1.44M diskettes + ; + DB 'APPEND.EXE ' ;AN000; + DB 'ASSIGN.COM ' ;AN000; + DB 'ATTRIB.EXE ' ;AN000; + DB 'BACKUP.COM ' + DB 'CHKDSK.COM ' + DB 'COMP.COM ' ;AN000; + DB 'DEBUG.COM ' ;AN000; + DB 'DISKCOMP.COM' ;AN000; + DB 'EDLIN.COM ' ;AN000; + DB 'EXE2BIN.EXE ' + DB 'FC.EXE ' + DB 'FILESYS.EXE ' + DB 'FIND.EXE ' ;AN000; + DB 'GWBASIC.EXE ' + DB 'IFSFUNC.EXE ' + DB 'JOIN.EXE ' ;AN000; + DB 'LABEL.COM ' ;AN000; + DB 'LINK.EXE ' + DB 'MEM.EXE ' ;AN000; + DB 'MODE.COM ' ;AN000; + DB 'MORE.COM ' ;AN000; + DB 'RECOVER.COM ' ;AN000; + DB 'RESTORE.COM ' + DB 'SORT.EXE ' ;AN000; + DB 'SUBST.EXE ' ;AN000; + DB 'TREE.COM ' ;AN000; + DB 'XCOPY.EXE ' +E_OPER_1200_1440 EQU ( $ - COPY_OPER_1200_1440 ) / 12 ;AN000; + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Files found on MS-SHELL diskette +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + PUBLIC COPY_SHELL_1200_1440,E_SHELL_1200_1440 ;AN000; +COPY_SHELL_1200_1440 LABEL BYTE ;AN000; this will copy files to 1.2M $ 1.44M diskettes + ; + DB 'SHELL.CLR ' ;AN000; + DB 'SHELL.HLP ' ;AN000; + DB 'SHELL.MEU ' ;AN000; + DB 'SHELLB.COM ' ;AN000; + DB 'SHELLC.EXE ' ;AN000; + DB 'DOSUTIL.MEU ' ;AN000;DT +E_SHELL_1200_1440 EQU ( $ - COPY_SHELL_1200_1440 ) / 12 ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Files which will be unique on ship/install diskettes +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC S_DOS_SHEL_DISK ;AN000; +S_DOS_SHEL_DISK DW M_DOS_SHEL_DISK ;AN000; +P_DOS_SHEL_DISK DB 'SHELLC.EXE ' ;AN000; +M_DOS_SHEL_DISK EQU $ - P_DOS_SHEL_DISK - 1 ;AN000; + ; + PUBLIC S_DOS_SEL_360 ;AN000;GHG +S_DOS_SEL_360 DW M_DOS_SEL_360 ;AN000;GHG +P_DOS_SEL_360 DB 'SELECT.EXE ' ;AN000;GHG +M_DOS_SEL_360 EQU $ - P_DOS_SEL_360 - 1 ;AN000;GHG + ;GHG + PUBLIC S_DOS_UTIL1_DISK ;AN000;GHG +S_DOS_UTIL1_DISK DW M_DOS_UTIL1_DISK ;AN000;GHG +P_DOS_UTIL1_DISK DB 'ATTRIB.EXE ' ;AN000;GHG +M_DOS_UTIL1_DISK EQU $ - P_DOS_UTIL1_DISK - 1 ;AN000;GHG + ;GHG + PUBLIC S_DOS_UTIL2_DISK ;AN000;GHG +S_DOS_UTIL2_DISK DW M_DOS_UTIL2_DISK ;AN000;GHG +P_DOS_UTIL2_DISK DB 'GWBASIC.EXE ' ;AN000;GHG +M_DOS_UTIL2_DISK EQU $ - P_DOS_UTIL2_DISK - 1 ;AN000;GHG + ;GHG + PUBLIC S_DOS_UTIL3_DISK ;AN000;GHG +S_DOS_UTIL3_DISK DW M_DOS_UTIL3_DISK ;AN000;GHG +P_DOS_UTIL3_DISK DB 'DRIVER.SYS ' ;AN000;GHG +M_DOS_UTIL3_DISK EQU $ - P_DOS_UTIL3_DISK - 1 ;AN000;GHG + + PUBLIC S_DOS_COM_360 ;AN000;GHG +S_DOS_COM_360 DW M_DOS_COM_360 ;AN000;GHG +P_DOS_COM_360 DB 'SELECT.COM ' ;AN000;GHG +M_DOS_COM_360 EQU $ - P_DOS_COM_360 - 1 ;AN000;GHG + ;GHG + PUBLIC E_FILE_ATTR ;AN000; +E_FILE_ATTR EQU 00H ;AN000; attribute not important +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC S_COMMAND_COM ;AN017; +S_COMMAND_COM DW M_COMMAND_COM ;AN017; +P_COMMAND_COM DB 'C:\COMMAND.COM ' ;AN017; +M_COMMAND_COM EQU $ - P_COMMAND_COM - 1 ;AN017; + ; + PUBLIC S_SELECT_TMP ;AN000; +S_SELECT_TMP DW M_SELECT_TMP ;AN000; +P_SELECT_TMP DB 'SELECT.TMP ' ;AN000; +M_SELECT_TMP EQU $ - P_SELECT_TMP - 1 ;AN000; space for ASCII-Z conversion + ; + PUBLIC S_PRINT_FILE,M_PRINT_FILE ;AN000; +S_PRINT_FILE DW M_PRINT_FILE ;AN000;GHG NAME OF THE SELECT PRINTER +P_PRINT_FILE DB 'SELECT.PRT ' ;AN000;GHG PROFILE. - space for ASCII-Z conversion +M_PRINT_FILE EQU $-P_PRINT_FILE-1 ;AN000;GHG + ; + PUBLIC S_AUTO_NEW, S_CONFIG_NEW ;AN000; +S_AUTO_NEW DW M_AUTO_NEW ;AN000; +P_AUTO_NEW DB 'AUTOEXEC.400 ' ;AN003;GHG Temporary +M_AUTO_NEW EQU $ - P_AUTO_NEW - 1 ;AN003;GHG AUTOEXEC.BAT + ; +S_CONFIG_NEW DW M_CONFIG_NEW ;AN000; +P_CONFIG_NEW DB 'CONFIG.400 ' ;AN003;GHG Temporary +M_CONFIG_NEW EQU $ - P_CONFIG_NEW - 1 ;AN003;GHG CONFIG + ; + PUBLIC S_OS2_CONFIG_C, S_OS2_AUTO_C ;AN065;SEH +S_OS2_CONFIG_C DW M_OS2_CONFIG_C ;AN065;SEH rename OS2's config.sys +P_OS2_CONFIG_C DB 'C:\CONFIG.OS2 ' ;AN065;SEH +M_OS2_CONFIG_C EQU $ - P_OS2_CONFIG_C - 1 ;AN065;SEH + ; +S_OS2_AUTO_C DW M_OS2_AUTO_C ;AN065;SEH rename OS2's autoexec.bat +P_OS2_AUTO_C DB 'C:\AUTOEXEC.OS2 ' ;AN065;SEH +M_OS2_AUTO_C EQU $ - P_OS2_AUTO_C - 1 ;AN065;SEH + ; + PUBLIC S_SHELL_NEW ;AN000;DT +S_SHELL_NEW DW M_SHELL_NEW ;AN000;DT +P_SHELL_NEW DB 'DOSSHELL.BAT ' ;AC019;SEH ;AN000;DT space for ASCII-Z conversion +M_SHELL_NEW EQU $ - P_SHELL_NEW - 1 ;AN000;DT + ; + PUBLIC S_SHELL_NEW_B ;AN000;DT +S_SHELL_NEW_B DW M_SHELL_NEW_B ;AN000;DT +P_SHELL_NEW_B DB 'B:\DOSSHELL.BAT ' ;AC019;SEH ;AN000;DT space for ASCII-Z conversion +M_SHELL_NEW_B EQU $ - P_SHELL_NEW_B - 1 ;AN000;DT + ; + PUBLIC S_AUTO_NEW_B, S_CONFIG_NEW_B ;AN000; +S_AUTO_NEW_B DW M_AUTO_NEW_B ;AN000; +P_AUTO_NEW_B DB 'B:\AUTOEXEC.BAT ' ;AN000; space for ASCII-Z conversion +M_AUTO_NEW_B EQU $ - P_AUTO_NEW_B - 1 ;AN000; + ; +S_CONFIG_NEW_B DW M_CONFIG_NEW_B ;AN000; +P_CONFIG_NEW_B DB 'B:\CONFIG.SYS ' ;AN000; space for ASCII-Z conversion +M_CONFIG_NEW_B EQU $ - P_CONFIG_NEW_B - 1 ;AN000; + ; + PUBLIC S_AUTO_REN, S_CONFIG_REN ;AN000; +S_AUTO_REN DW M_AUTO_REN ;AN000; +P_AUTO_REN DB 'C:\AUTOEXEC.400 ' ;AN003;GHG +M_AUTO_REN EQU $ - P_AUTO_REN - 1 ;AN000; + ; +S_CONFIG_REN DW M_CONFIG_REN ;AN000; +P_CONFIG_REN DB 'C:\CONFIG.400 ' ;AN003;GHG +M_CONFIG_REN EQU $ - P_CONFIG_REN - 1 ;AN000; + ; + PUBLIC S_AUTO_C, S_CONFIG_C ;AN000; +S_AUTO_C DW M_AUTO_C ;AN000; +P_AUTO_C DB 'C:\AUTOEXEC.BAT ' ;AN000; space for ASCII-Z conversion +M_AUTO_C EQU $ - P_AUTO_C - 1 ;AN000; + ; +S_CONFIG_C DW M_CONFIG_C ;AN000; +P_CONFIG_C DB 'C:\CONFIG.SYS ' ;AN000; space for ASCII-Z conversion +M_CONFIG_C EQU $ - P_CONFIG_C - 1 ;AN000; + ; + PUBLIC S_AUTO_NEW_C, S_CONFIG_NEW_C ;AN000; +S_AUTO_NEW_C DW M_AUTO_NEW_C ;AN000; +P_AUTO_NEW_C DB 'C:AUTOEXEC.BAT ' ;AN000; space for ASCII-Z conversion +M_AUTO_NEW_C EQU $ - P_AUTO_NEW_C - 1 ;AN000; + ; +S_CONFIG_NEW_C DW M_CONFIG_NEW_C ;AN000; +P_CONFIG_NEW_C DB 'C:CONFIG.SYS ' ;AN000; space for ASCII-Z conversion +M_CONFIG_NEW_C EQU $ - P_CONFIG_NEW_C - 1 ;AN000; + ; + PUBLIC S_AUTO_REBOOT ;AN000; +S_AUTO_REBOOT DW M_AUTO_REBOOT ;AN000; +P_AUTO_REBOOT DB 'AUTOEXEC.BAT ' ;AN000; +M_AUTO_REBOOT EQU $ - P_AUTO_REBOOT - 1 ;AN000; + ; + PUBLIC S_AUTO_MENU ;AN000; +S_AUTO_MENU DW M_AUTO_MENU ;AN000; +P_AUTO_MENU DB 'MENU' ;AN000; +M_AUTO_MENU EQU $ - P_AUTO_MENU ;AN000; + ; + PUBLIC S_AUTO_FDISK ;AN000; +S_AUTO_FDISK DW M_AUTO_FDISK ;AN000; +P_AUTO_FDISK DB 'FDISK' ;AN000; +M_AUTO_FDISK EQU $ - P_AUTO_FDISK ;AN000; + ; + PUBLIC S_CONFIG_AUTO, E_FILES ;AN000; +S_CONFIG_AUTO DB 'CONFIG.400 ' ;AN000; + DB 'AUTOEXEC.400' ;AN000; +E_FILES EQU ($ - S_CONFIG_AUTO) / 12 ;AN000; + ; + PUBLIC S_SHELL2, SH_FILES ;AN000; +S_SHELL2 DB 'DOSSHELL.BAT' ;AC019;SEH ;AN000; +SH_FILES EQU ($ - S_SHELL2) / 12 ;AN000; + ; + PUBLIC S_KEYB ;AN000; +S_KEYB DW M_KEYB ;AN000; +P_KEYB DB 'KEYB.COM ' ;AN000; KEYB command - space at end for ASCII-Z +M_KEYB EQU $ - P_KEYB - 1 ;AN000; + ; + PUBLIC S_FDISK ;AN000; +S_FDISK DW M_FDISK ;AN000; +P_FDISK DB 'FDISK.EXE ' ;AC042;SEH ;AN000; FDISK command - space at end for ASCII-Z +M_FDISK EQU $ - P_FDISK - 1 ;AN000; + ; + PUBLIC S_DISKCOPY ;AN000; +S_DISKCOPY DW M_DISKCOPY ;AN000; +P_DISKCOPY DB 'DISKCOPY.COM ' ;AN000; DISKCOPY command - space at end for ASCII-Z +M_DISKCOPY EQU $ - P_DISKCOPY - 1 ;AN000; + ; + PUBLIC S_DISKCOPY_PARM ;AN000; +S_DISKCOPY_PARM DW M_DISKCOPY_PARM ;AN000; +P_DISKCOPY_PARM DB ' A: A:' ;AN000; +M_DISKCOPY_PARM EQU $ - P_DISKCOPY_PARM ;AN000; + ; + PUBLIC SC_1, SC_2 ;AN000; +SC_1 DW MC_1 ;AN000; disk number 1 +PC_1 DB '1 ' ;AN000; +MC_1 EQU $ - PC_1 ;AN000; +SC_2 DW MC_2 ;AN000; disk number 2 +PC_2 DB '2 ' ;AN000; +MC_2 EQU $ - PC_2 ;AN000; + ; + PUBLIC SC_PRI,SC_EXT,SC_LOG ;AN000; +SC_PRI DW MC_PRI ;AN000; DOS parameter for FDSIK command +PC_PRI DB ' /PRI:' ;AN000; +MC_PRI EQU $ - PC_PRI ;AN000; +SC_EXT DW MC_EXT ;AN000; +PC_EXT DB ' /EXT:' ;AN000; +MC_EXT EQU $ - PC_EXT ;AN000; +SC_LOG DW MC_LOG ;AN000; +PC_LOG DB ' /LOG:' ;AN000; +MC_LOG EQU $ - PC_LOG ;AN000; + ; + PUBLIC S_FORMAT ;AN000; +S_FORMAT DW M_FORMAT ;AN000; +P_FORMAT DB 'FORMAT.COM ' ;AN000; FORMAT command - space at end for ASCII-Z +M_FORMAT EQU $ - P_FORMAT - 1 ;AN000; + ; + PUBLIC S_DRIVE_C ;AN000; +S_DRIVE_C DW M_DRIVE_C ;AN000; +P_DRIVE_C DB 'C:' ;AN000; +M_DRIVE_C EQU $ - P_DRIVE_C ;AN000; + ; + PUBLIC S_FORMAT_B ;AN000; +S_FORMAT_B DW M_FORMAT_B ;AN000; +P_FORMAT_B DB 'B: /S /V:DOS400 /SELECT ' ;AN000; +M_FORMAT_B EQU $ - P_FORMAT_B ;AN000; + ; + PUBLIC S_FORMAT_A ;AN111;JW +S_FORMAT_A DW M_FORMAT_A ;AN111;JW +P_FORMAT_A DB 'A: /S /V:DOS400 /SELECT ' ;AN111;JW +M_FORMAT_A EQU $ - P_FORMAT_A ;AN111;JW + ; + PUBLIC S_REPLACE ;AN000; +S_REPLACE DW M_REPLACE ;AN000; +P_REPLACE DB 'REPLACE.EXE ' ;AN000; space at end for ASCIII-Z string +M_REPLACE EQU $ - P_REPLACE - 1 ;AN000; + ; + PUBLIC S_REPLACE_PAR1 ;AN000; +S_REPLACE_PAR1 DW M_REPLACE_PAR1 ;AN000; +P_REPLACE_PAR1 DB 'A:*.* C:\ /S /R ' ;AC000;JW +M_REPLACE_PAR1 EQU $ - P_REPLACE_PAR1 ;AN000; + ; + PUBLIC S_SLASH_R ;AN000;JW +S_SLASH_R DW M_SLASH_R ;AN000;JW +P_SLASH_R DB ' /R' ;AN000;JW +M_SLASH_R EQU $ - P_SLASH_R ;AN000;JW + ; + PUBLIC S_A_STARS ;AN000; +S_A_STARS DW M_A_STARS ;AN000; +P_A_STARS DB 'A:*.* ' ;AN000; +M_A_STARS EQU $ - P_A_STARS ;AN000; + ; + PUBLIC S_SLASH_A ;AN000; +S_SLASH_A DW M_SLASH_A ;AN000; +P_SLASH_A DB ' /A' ;AN000; +M_SLASH_A EQU $ - P_SLASH_A ;AN000; + ; + PUBLIC S_SLASH_S ;AN000; +S_SLASH_S DW M_SLASH_S ;AN000; +P_SLASH_S DB ' /S' ;AN000; +M_SLASH_S EQU $ - P_SLASH_S ;AN000; + ; + PUBLIC S_SLASH_Q ;AN000; +S_SLASH_Q DW M_SLASH_Q ;AN000; +P_SLASH_Q DB ' /Q' ;AN000; +M_SLASH_Q EQU $ - P_SLASH_Q ;AN000; + ; + PUBLIC S_COLON ;AN000; +S_COLON DW M_COLON ;AN000; +P_COLON DB ':' ;AN000; +M_COLON EQU $ - P_COLON ;AN000; + ; + PUBLIC S_SYS_C ;AN000; +S_SYS_C DW M_SYS_C ;AN000; +P_SYS_C DB 'SYS.COM ' ;AN000; space dor ASCII-Z conversion +M_SYS_C EQU $ - P_SYS_C - 1 ;AN000; + ; + PUBLIC S_VOL_SEL ;AN000; +S_VOL_SEL DW M_VOL_SEL ;AN000; +P_VOL_SEL DB ' /V:DOS400 /SELECT ' ;AN000; +M_VOL_SEL EQU $ - P_VOL_SEL ;AN000; + ; + PUBLIC S_PREP_EGA ;AN000; +S_PREP_EGA DW M_PREP_EGA ;AN000; +P_PREP_EGA DB 'CON CP PREP=((850) EGA.CPI)' ;AN000; +M_PREP_EGA EQU $ - P_PREP_EGA ;AN000; + ; + PUBLIC S_PREP_LCD ;AN000; +S_PREP_LCD DW M_PREP_LCD ;AN000; +P_PREP_LCD DB 'CON CP PREP=((850) LCD.CPI)' ;AN000; +M_PREP_LCD EQU $ - P_PREP_LCD ;AN000; + ; + PUBLIC S_CP_SEL ;AN000; +S_CP_SEL DW M_CP_SEL ;AN000; +P_CP_SEL DB 'CON CP SEL=850' ;AN000; +M_CP_SEL EQU $ - P_CP_SEL ;AN000; + ; + PUBLIC S_MODE ;AN000; +S_MODE DW M_MODE ;AN000; +P_MODE DB 'MODE.COM ' ;AN000; Space at end of ASCII-Z conversion +M_MODE EQU $ - P_MODE-1 ;AN000; + ; + PUBLIC S_SLASH ;AN000;DT +S_SLASH DW M_SLASH ;AN000;DT +P_SLASH DB '\' ;AN000;DT +M_SLASH EQU $ - P_SLASH ;AN000;DT + ;AN000;DT + PUBLIC S_DSKCPY_TO_B ;AN000; +S_DSKCPY_TO_B DW M_DSKCPY_TO_B ;AN000; +P_DSKCPY_TO_B DB ' A: B:' ;AN000; +M_DSKCPY_TO_B EQU $ - P_DSKCPY_TO_B ;AN000; + ; + PUBLIC S_SELCOM_NEW_B ;AN004;DT +S_SELCOM_NEW_B DW M_SELCOM_NEW_B ;AN004;DT +P_SELCOM_NEW_B DB 'B:\SELECT.COM ' ;AN004;DT space for ASCII-Z conversion +M_SELCOM_NEW_B EQU $ - P_SELCOM_NEW_B - 1 ;AN004;DT + ;AN004;DT + PUBLIC S_SELHLP_NEW_B ;AN004;DT +S_SELHLP_NEW_B DW M_SELHLP_NEW_B ;AN004;DT +P_SELHLP_NEW_B DB 'B:\SELECT.HLP ' ;AN004;DT space for ASCII-Z conversion +M_SELHLP_NEW_B EQU $ - P_SELHLP_NEW_B - 1 ;AN004;DT + ;AN004;DT + PUBLIC S_SELPRT_NEW_B ;AN004;DT +S_SELPRT_NEW_B DW M_SELPRT_NEW_B ;AN004;DT +P_SELPRT_NEW_B DB 'B:\SELECT.PRT ' ;AN004;DT space for ASCII-Z conversion +M_SELPRT_NEW_B EQU $ - P_SELPRT_NEW_B - 1 ;AN004;DT + ; + PUBLIC S_SELEXE_NEW_B ;AN004;DT +S_SELEXE_NEW_B DW M_SELEXE_NEW_B ;AN004;DT +P_SELEXE_NEW_B DB 'B:\SELECT.EXE ' ;AN004;DT space for ASCII-Z conversion +M_SELEXE_NEW_B EQU $ - P_SELEXE_NEW_B - 1 ;AN004;DT + ; + PUBLIC S_SELDAT_NEW_B ;AN004;DT +S_SELDAT_NEW_B DW M_SELDAT_NEW_B ;AN004;DT +P_SELDAT_NEW_B DB 'B:\SELECT.DAT ' ;AN004;DT space for ASCII-Z conversion +M_SELDAT_NEW_B EQU $ - P_SELDAT_NEW_B - 1 ;AN004;DT + ; + PUBLIC S_SELDAT_C ;AN004;DT Used to erase from C: after 360KB install +S_SELDAT_C DW M_SELDAT_C ;AN004;DT +P_SELDAT_C DB '\SELECT.DAT ' ;AN004;DT space for ASCII-Z conversion +M_SELDAT_C EQU $ - P_SELDAT_C - 1 ;AN004;DT + ; + PUBLIC S_SELCOM_C ;AN004;DT +S_SELCOM_C DW M_SELCOM_C ;AN004;DT +P_SELCOM_C DB '\SELECT.COM ' ;AN004;DT space for ASCII-Z conversion +M_SELCOM_C EQU $ - P_SELCOM_C - 1 ;AN004;DT + ; + PUBLIC S_SELHLP_C ;AN004;DT +S_SELHLP_C DW M_SELHLP_C ;AN004;DT +P_SELHLP_C DB '\SELECT.HLP ' ;AN004;DT space for ASCII-Z conversion +M_SELHLP_C EQU $ - P_SELHLP_C - 1 ;AN004;DT + ; + PUBLIC S_SELPRT_C ;AN004;DT +S_SELPRT_C DW M_SELPRT_C ;AN004;DT +P_SELPRT_C DB '\SELECT.PRT ' ;AN004;DT space for ASCII-Z conversion +M_SELPRT_C EQU $ - P_SELPRT_C - 1 ;AN004;DT + ; + PUBLIC S_SELEXE_C ;AN004;DT +S_SELEXE_C DW M_SELEXE_C ;AN004;DT +P_SELEXE_C DB '\SELECT.EXE ' ;AN004;DT space for ASCII-Z conversion +M_SELEXE_C EQU $ - P_SELEXE_C - 1 ;AN004;DT + ; + PUBLIC S_AUTOEX_C ;AN004;DT +S_AUTOEX_C DW M_AUTOEX_C ;AN004;DT +P_AUTOEX_C DB '\AUTOEXEC.BAT ' ;AN004;DT space for ASCII-Z conversion +M_AUTOEX_C EQU $ - P_AUTOEX_C - 1 ;AN004;DT + ; + PUBLIC S_CONSYS_C ;AN004;DT +S_CONSYS_C DW M_CONSYS_C ;AN004;DT +P_CONSYS_C DB '\CONFIG.SYS ' ;AN004;DT space for ASCII-Z conversion +M_CONSYS_C EQU $ - P_CONSYS_C - 1 ;AN004;DT + ; + PUBLIC S_VDISK_B ;AN006;JW +S_VDISK_B DW M_VDISK_B ;AN006;JW +P_VDISK_B DB 'B:\RAMDRIVE.SYS ' ;AN006;JW space for ASCII-Z conversion +M_VDISK_B EQU $ - P_VDISK_B - 1 ;AN006;JW + ; + PUBLIC S_ANSI_B ;AN006;JW +S_ANSI_B DW M_ANSI_B ;AN006;JW +P_ANSI_B DB 'B:\ANSI.SYS ' ;AN006;JW space for ASCII-Z conversion +M_ANSI_B EQU $ - P_ANSI_B - 1 ;AN006;JW + ; + PUBLIC S_APPEND_B ;AN006;JW +S_APPEND_B DW M_APPEND_B ;AN006;JW +P_APPEND_B DB 'B:\APPEND.EXE ' ;AN006;JW space for ASCII-Z conversion +M_APPEND_B EQU $ - P_APPEND_B - 1 ;AN006;JW + ; + PUBLIC S_GRAFTABL_B ;AN006;JW +S_GRAFTABL_B DW M_GRAFTABL_B ;AN006;JW +P_GRAFTABL_B DB 'B:\GRAFTABL.COM ' ;AN006;JW space for ASCII-Z conversion +M_GRAFTABL_B EQU $ - P_GRAFTABL_B - 1 ;AN006;JW + ; + PUBLIC S_GRAPHICS_B ;AN006;JW +S_GRAPHICS_B DW M_GRAPHICS_B ;AN006;JW +P_GRAPHICS_B DB 'B:\GRAPHICS.COM ' ;AN006;JW space for ASCII-Z conversion +M_GRAPHICS_B EQU $ - P_GRAPHICS_B - 1 ;AN006;JW + ; + PUBLIC S_GRAPHPRO_B ;AN006;JW +S_GRAPHPRO_B DW M_GRAPHPRO_B ;AN006;JW +P_GRAPHPRO_B DB 'B:\GRAPHICS.PRO ' ;AN006;JW space for ASCII-Z conversion +M_GRAPHPRO_B EQU $ - P_GRAPHPRO_B - 1 ;AN006;JW + ; + PUBLIC S_RECOVER_B ;AN007;JW +S_RECOVER_B DW M_RECOVER_B ;AN007;JW +P_RECOVER_B DB 'B:\RECOVER.COM ' ;AN007;JW space for ASCII-Z conversion +M_RECOVER_B EQU $ - P_RECOVER_B - 1 ;AN007;JW + ; + PUBLIC S_FASTOPEN_B ;AN007;JW +S_FASTOPEN_B DW M_FASTOPEN_B ;AN007;JW +P_FASTOPEN_B DB 'B:\FASTOPEN.EXE ' ;AN007;JW space for ASCII-Z conversion +M_FASTOPEN_B EQU $ - P_FASTOPEN_B - 1 ;AN007;JW + ; + PUBLIC S_VDISK_C ;AN006;JW +S_VDISK_C DW M_VDISK_C ;AN006;JW +P_VDISK_C DB '\RAMDRIVE.SYS ' ;AN006;JW space for ASCII-Z conversion +M_VDISK_C EQU $ - P_VDISK_C - 1 ;AN006;JW + ; + PUBLIC S_ANSI_C ;AN006;JW +S_ANSI_C DW M_ANSI_C ;AN006;JW +P_ANSI_C DB '\ANSI.SYS ' ;AN006;JW space for ASCII-Z conversion +M_ANSI_C EQU $ - P_ANSI_C - 1 ;AN006;JW + ; + PUBLIC S_APPEND_C ;AN006;JW +S_APPEND_C DW M_APPEND_C ;AN006;JW +P_APPEND_C DB '\APPEND.EXE ' ;AN006;JW space for ASCII-Z conversion +M_APPEND_C EQU $ - P_APPEND_C - 1 ;AN006;JW + ; + PUBLIC S_GRAFTABL_C ;AN006;JW +S_GRAFTABL_C DW M_GRAFTABL_C ;AN006;JW +P_GRAFTABL_C DB '\GRAFTABL.COM ' ;AN006;JW space for ASCII-Z conversion +M_GRAFTABL_C EQU $ - P_GRAFTABL_C - 1 ;AN006;JW + ; + PUBLIC S_GRAPHICS_C ;AN006;JW +S_GRAPHICS_C DW M_GRAPHICS_C ;AN006;JW +P_GRAPHICS_C DB '\GRAPHICS.COM ' ;AN006;JW space for ASCII-Z conversion +M_GRAPHICS_C EQU $ - P_GRAPHICS_C - 1 ;AN006;JW + ; + PUBLIC S_GRAPHPRO_C ;AN006;JW +S_GRAPHPRO_C DW M_GRAPHPRO_C ;AN006;JW +P_GRAPHPRO_C DB '\GRAPHICS.PRO ' ;AN006;JW space for ASCII-Z conversion +M_GRAPHPRO_C EQU $ - P_GRAPHPRO_C - 1 ;AN006;JW + ; + PUBLIC S_RECOVER_C ;AN007;JW +S_RECOVER_C DW M_RECOVER_C ;AN007;JW +P_RECOVER_C DB '\RECOVER.COM ' ;AN007;JW space for ASCII-Z conversion +M_RECOVER_C EQU $ - P_RECOVER_C - 1 ;AN007;JW + ; + PUBLIC S_FASTOPEN_C ;AN007;JW +S_FASTOPEN_C DW M_FASTOPEN_C ;AN007;JW +P_FASTOPEN_C DB '\FASTOPEN.EXE ' ;AN007;JW space for ASCII-Z conversion +M_FASTOPEN_C EQU $ - P_FASTOPEN_C - 1 ;AN007;JW + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + \ No newline at end of file diff --git a/v4.0/src/SELECT/SERVICES.ASM b/v4.0/src/SELECT/SERVICES.ASM new file mode 100644 index 0000000..851c1bd --- /dev/null +++ b/v4.0/src/SELECT/SERVICES.ASM @@ -0,0 +1,899 @@ + + +PAGE 60,132 ;AN000; +NAME SERVICES ;AN000; +TITLE SERVICES - DOS - SELECT.EXE ;AN000; +SUBTTL services.asm ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; SERVICES.ASM: Copyright 1988 Microsoft +; +; +; CHANGE HISTORY: +; +; AN000 +; AN003 - DCR 225 +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN INC_KS:WORD ;AN000; + EXTRN IN_ICBID:WORD ;AN000; + EXTRN CRD_CCBVECOFF:WORD ;AN000; + EXTRN CRD_CCBVECSEG:WORD ;AN000; + EXTRN IN_CCBVECSEG:WORD ;AN000; + EXTRN IN_CCBVECOFF:WORD ;AN000; + EXTRN WR_HLPOPT:WORD ;AN000; + EXTRN WR_HLPROW:WORD ;AN000; + EXTRN WR_HCBCONT:WORD ;AN000; + EXTRN WR_SCBID:WORD ;AN000; + EXTRN WR_DRETLEN:WORD ;AN000; + EXTRN WR_DRETOFF:WORD ;AN000; + EXTRN WR_DRETSEG:WORD ;AN000; + EXTRN QM_ID:WORD ;AN000; + EXTRN QM_OPT1:WORD ;AN000; + EXTRN QM_ACTIVEPAN:WORD ;AN000; + EXTRN S_USER_STRING:WORD ;AN000; + EXTRN P_USER_STRING:BYTE ;AN000; + EXTRN I_USER_INDEX:WORD ;AN000; + EXTRN N_USER_FUNC:WORD ;AN000; + EXTRN WR_REFBUF:WORD ;AN000; + EXTRN WR_REFIELDCNT:WORD ;AN000; + EXTRN WR_REFID:WORD ;AN000; + EXTRN QM_OPT2:WORD ;AN000; + EXTRN WR_MAXREFID:ABS ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT SEGMENT PARA PUBLIC 'SELECT' ;AN000;segment for far routine + ASSUME CS:SELECT ;AN000; + ; + INCLUDE MACROS.INC ;AN000; + INCLUDE PCEQUATE.INC ;AN000; + INCLUDE CASTRUC.INC ;AN000; + INCLUDE CASVAR.INC ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; INIT_PQUEUE_CALL +; +; Entry: +; AX = panel id +; +; +; Exit: +; none +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN PCDISPQ_CALL:NEAR ;AN000; + ; + PUBLIC INIT_PQUEUE_CALL ;AN000; +INIT_PQUEUE_CALL PROC ;AN000; + MOV QM_OPT1,QM_CLSPAN ;AN000;clear parent panel queue + OR QM_OPT1,QM_CLSCHD ;AN000;clear parent panel queue + CALL PCDISPQ_CALL ;AN000;update display queue + MOV QM_ACTIVEPAN,AX ;AN000;current active parent panel + MOV QM_OPT1,QM_PUSHPAN ;AN000;push parent panels + OR QM_OPT2,QM_BREAKON ;AN000;break on + CALL PREPARE_PANEL_CALL ;AN000;add panel to display queue + MOV WR_REFBUF,AX ;AN000;update the field refresh buffer! + XOR AX,AX ;AN000; + MOV WR_REFIELDCNT,AX ;AN000; + MOV QM_OPT2,AX ;AN000;set options back off... + RET ;AN000; +INIT_PQUEUE_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX=panel +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + PUBLIC PREPARE_PANEL_CALL ;AN000; +PREPARE_PANEL_CALL PROC ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + MOV QM_ID,AX ;AN000;parent PCB number + MOV AX, 0ADC0H ;AN000; SELECT PANEL INTERFACE + INT 2FH ;AN000; + CALL PCDISPQ_CALL ;AN000;update display queue + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PREPARE_PANEL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX=input +; BX=index +; CX=f_keys&_LEN +; DX=offset f_keys +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + EXTRN GET_SCB:NEAR ;AN000; + EXTRN ADJUST_UP:NEAR ;AN000; + EXTRN ADJUST_DOWN:NEAR ;AN000; + EXTRN GET_SCROLL_CALL:NEAR ;AN000; + EXTRN HANDLE_F3:NEAR ;AN000; + ; + PUBLIC EXEC_SCROLL_CALL ;AN000; +EXEC_SCROLL_CALL PROC ;AN000; + PUSH ES ;AN000; + MOV WR_SCBID,AX ;AN000;get current scrolling field ID + ; + MOV WR_DRETLEN,CX ;AN000;get dynamic return string length + MOV WR_DRETOFF,DX ;AN000; + MOV CX,DS ;AN000;*********;get dynamic return string segment + MOV WR_DRETSEG,CX ;AN000; + ; + PUSH BX ;AN000; + MOV BX,WR_SCBID ;AN000; + CALL GET_SCB ;AN000; + POP BX ;AN000; + ; + MOV AX,BX ;AN000;initialize at list top + PUSH BX ;AN000; + MOV BX,WR_SCBID ;AN000; + CALL ADJUST_UP ;AN000; + POP BX ;AN000; + ; +ESC_0: PUSH ES:[DI]+SCB_OPT1 ;AN000; + PUSH ES:[DI]+SCB_OPT2 ;AN000; + PUSH ES:[DI]+SCB_OPT3 ;AN000; + PUSH ES:[DI]+SCB_NUMLINE ;AN000; + ; + CALL GET_SCROLL_CALL ;AN000;display and process scroll field + ; + POP ES:[DI]+SCB_NUMLINE ;AN000;GHG CAS BUG............. + POP ES:[DI]+SCB_OPT3 ;AN000; + POP ES:[DI]+SCB_OPT2 ;AN000; + POP ES:[DI]+SCB_OPT1 ;AN000; + MOV AX,ES:[DI]+SCB_CURELE ;AN000; + ; + CMP ES:[DI]+SCB_KS,F3*256 ;AN000;get last keystroke + JNE ESC_1 ;AN000; + ; + CALL HANDLE_F3 ;AN000; + JNC ESC_0 ;AN000; + ; +ESC_1: PUSH BX ;AN000; + MOV BX,WR_SCBID ;AN000; + CALL ADJUST_DOWN ;AN000; + POP BX ;AN000; + MOV I_USER_INDEX,AX ;AN000; + ; + MOV AX,ES:[DI]+SCB_KS ;AN000;get last keystroke + MOV N_USER_FUNC,AX ;AN000; + POP ES ;AN000; + RET ;AN000; +EXEC_SCROLL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX=input +; BX=index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN PCSLCTP_CALL:NEAR ;AN000; + EXTRN GET_PCB:NEAR ;AN000; + ; + PUBLIC INIT_SCROLL_CALL ;AN000; +INIT_SCROLL_CALL PROC ;AN000; + PUSH ES ;AN000; + MOV WR_SCBID,AX ;AN000;get current scrolling field ID + ; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + CALL GET_SCB ;AN000; + POP BX ;AN000; + ; + MOV AX,BX ;AN000; + OR AX,AX ;AN000; + JNZ ISC_0 ;AN000; + OR ES:[DI]+SCB_OPT2,SCB_ROTN ;AN000; + ; +ISC_0: PUSH BX ;AN000; + MOV BX,WR_SCBID ;AN000; + CALL ADJUST_UP ;AN000; + POP BX ;AN000; + MOV ES:[DI]+SCB_TOPELE,1 ;AN000;intialize parameters + MOV ES:[DI]+SCB_CURELE,AX ;AN000; + MOV BX,QM_ACTIVEPAN ;AN000;get the active panel number + CALL GET_PCB ;AN000;ES:DI address of panel PCB + ; + PUSH ES:[DI]+PCB_UROW ;AN000; ;get active panel row + PUSH ES:[DI]+PCB_UCOL ;AN000; ;get active panel column + PUSH ES:[DI]+PCB_CCBID ;AN000;get active panel color index + ; + MOV BX,WR_SCBID ;AN000;get PCSLCTP field + CALL GET_SCB ;AN000;ES:DI points to SCB + ; + POP ES:[DI]+SCB_CCBID ;AN000;get the panel's current color ind + POP ES:[DI]+SCB_RELCOL ;AN000;set the panel's relative column + POP ES:[DI]+SCB_RELROW ;AN000;set the panel's relative row + ; + MOV AX,SCROLLOBJID ;AN000; scroll_object type + MOV BX,WR_SCBID ;AN000; scroll_id + CALL ADD_REFRESH ;AN000; + POP ES ;AN000; + RET ;AN000; +INIT_SCROLL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX=input +; BX=index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC INIT_SCROLL_W_LIST_CALL ;AN000; +INIT_SCROLL_W_LIST_CALL PROC ;AN000; + PUSH ES ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + ; + MOV WR_SCBID,AX ;AN000;get current scrolling field ID + MOV BX,AX ;AN000; + CALL GET_SCB ;AN000; + ; + POP ES:[DI]+SCB_OAPOFF ;AN000; + POP ES:[DI]+SCB_OAPSEG ;AN000; + POP ES:[DI]+SCB_OASLEN ;AN000; + POP ES:[DI]+SCB_NUMELE ;AN000; + POP ES:[DI]+SCB_WIDTH ;AN000; + ; + PUSH ES:[DI]+SCB_OAPSEG ;AN000; + POP ES:[DI]+SCB_OASSEG ;AN000; + POP ES ;AN000; + RET ;AN000; +INIT_SCROLL_W_LIST_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX=input +; CX=num_ele +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC INIT_SCROLL_W_NUM_CALL ;AN000; +INIT_SCROLL_W_NUM_CALL PROC ;AN000; + PUSH ES ;AN000; + PUSH AX ;AN000;save current scroll field ID + MOV BX,AX ;AN000; + MOV AX,CX ;AN000;initialize at list top + CALL ADJUST_UP ;AN000; + ; + POP BX ;AN000;restore scroll field ID + PUSH AX ;AN000; + CALL GET_SCB ;AN000; + POP ES:[DI]+SCB_NUMELE ;AN000; + POP ES ;AN000; + RET ;AN000; +INIT_SCROLL_W_NUM_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX=input +; BX=index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC SET_SCROLL_COLOUR ;AN000; +SET_SCROLL_COLOUR PROC ;AN000; + PUSH ES ;AN000; + CALL GET_SCB ;AN000;ES:DI points to SCB + MOV ES:[DI]+SCB_CCBID,AX ;AN000;set the panel's current color ind + POP ES ;AN000; + RET ;AN000; +SET_SCROLL_COLOUR ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX=input +; BX=index +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + PUBLIC SET_SCROLL_CALL ;AN000; +SET_SCROLL_CALL PROC ;AN000; + PUSH ES ;AN000; + MOV WR_SCBID,AX ;AN000;get current scrolling field ID + ; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + CALL GET_SCB ;AN000; + POP BX ;AN000; + ; + PUSH ES:[DI]+SCB_OPT1 ;AN000; + PUSH ES:[DI]+SCB_OPT2 ;AN000; + ; + OR ES:[DI]+SCB_OPT1,SCB_RD ;AN000; + MOV AX,BX ;AN000; + OR AX,AX ;AN000; + JNZ SSC_0 ;AN000; + OR ES:[DI]+SCB_OPT2,SCB_ROTN ;AN000; + ; +SSC_0: PUSH BX ;AN000; + MOV BX,WR_SCBID ;AN000; + CALL ADJUST_UP ;AN000; + POP BX ;AN000; + MOV ES:[DI]+SCB_TOPELE,1 ;AN000;intialize parameters + MOV ES:[DI]+SCB_CURELE,AX ;AN000; + MOV BX,QM_ACTIVEPAN ;AN000;get the active panel number + CALL GET_PCB ;AN000;ES:DI address of panel PCB + ; + PUSH ES:[DI]+PCB_UROW ;AN000; ;get active panel row + PUSH ES:[DI]+PCB_UCOL ;AN000; ;get active panel column + PUSH ES:[DI]+PCB_CCBID ;AN000;get active panel color index + ; + MOV BX,WR_SCBID ;AN000;get PCSLCTP field + CALL GET_SCB ;AN000;ES:DI points to SCB + ; + POP ES:[DI]+SCB_CCBID ;AN000;get the panel's current color ind + POP ES:[DI]+SCB_RELCOL ;AN000;set the panel's relative column + POP ES:[DI]+SCB_RELROW ;AN000;set the panel's relative row + INC ES:[DI]+SCB_CCBID ;AN000;INCREMENT COLOUR INDEX TO MAKE IT DIFFERENT ************** + ; + AND ES:[DI]+SCB_OPT1,NOT SCB_UKS;AN000; + CALL PCSLCTP_CALL ;AN000;display scroll field + ; + POP ES:[DI]+SCB_OPT2 ;AN000; + POP ES:[DI]+SCB_OPT1 ;AN000; + POP ES ;AN000; + RET ;AN000; +SET_SCROLL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN PCPANEL_CALL:NEAR ;AN000; + ; + PUBLIC DISPLAY_PANEL_CALL ;AN000; +DISPLAY_PANEL_CALL PROC ;AN000; + MOV BX,0 ;AN000; + MOV AX,0ADC0H ;AN000; + INT 2FH ;AN000; + XOR AX,AX ;AN000;turn break option OFF + CMP WR_REFIELDCNT,0 ;AN000; + JE DP_10 ;AN000; + INC AX ;AN000;turn break option ON +DP_10: CALL PCPANEL_CALL ;AN000;display panel + RET ;AN000; +DISPLAY_PANEL_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN GET_KEY:NEAR ;AN000; + ; + PUBLIC GET_FUNCTION_CALL ;AN000; +GET_FUNCTION_CALL PROC ;AN000; + MOV WR_DRETLEN,CX ;AN000;get return string length + MOV AX,DX ;AN000;get return string offset + MOV WR_DRETOFF,AX ;AN000; + MOV AX,DS ;AN000;get return string segment + MOV WR_DRETSEG,AX ;AN000; +GFC_0: CALL GET_KEY ;AN000; + ; + MOV AX,INC_KS ;AN003;GHG + MOV N_USER_FUNC,AX ;AN003;GHG + ;GHG ;AN003; + CMP AX,F3*256 ;AN003;GHG + JNE GFC_1 ;AN003;GHG + ;GHG ;AN003; + CALL HANDLE_F3 ;AN003;GHG + JNC GFC_0 ;AN003;GHG + MOV N_USER_FUNC,F3*256 ;AN003;GHG set last keystroke to exit! + ; +GFC_1: RET ;AN000; +GET_FUNCTION_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; BX,string +; CX,fkeys&_LEN +; DX,fkeys +; SI,field_length +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN CURSOROFF:NEAR ;AN000; + EXTRN GET_ICB:NEAR ;AN000; + EXTRN GET_INPUT_CALL:NEAR ;AN000; + ; + PUBLIC GET_STRING_CALL ;AN000; +GET_STRING_CALL PROC ;AN000; + PUSH ES ;AN000; + CALL CLEAR_USER_STRING ;AN000; + ; + MOV IN_ICBID,AX ;AN000; process input field x + ; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + CALL GET_ICB ;AN000; + POP BX ;AN000; + ; + MOV WR_DRETLEN,CX ;AN000; SET RETURN KEYS + MOV WR_DRETOFF,DX ;AN000; + MOV AX,DS ;AN000; + MOV WR_DRETSEG,AX ;AN000; + ; + MOV ES:[DI]+ICB_WIDTH,SI ;AN000;GHG + MOV AX,SI ;AN000;GHG + ADD AX,ES:[DI]+ICB_COL ;AN000;GHG + CMP AX,75 ;AN000;GHG + JB GSC_10 ;AN000;GHG + MOV AX,70 ;AN000;GHG + SUB AX,ES:[DI]+ICB_COL ;AN000;GHG + MOV ES:[DI]+ICB_WIDTH,AX ;AN000;GHG +GSC_10: ;AN000; + MOV ES:[DI]+ICB_FIELDLEN,SI ;AN000; size specified by si + MOV AX,[BX] ;AN000; + MOV ES:[DI]+ICB_DEFLEN,AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_CURCHAR,AX ;AN000; + MOV AX,BX ;AN000; + INC AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_DEFOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_DEFSEG,AX ;AN000; + ; + LEA AX,P_USER_STRING ;AN000; + MOV ES:[DI]+ICB_FIELDOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_FIELDSEG,AX ;AN000; + ; + PUSH CRD_CCBVECOFF ;AN000; + PUSH CRD_CCBVECSEG ;AN000; + POP IN_CCBVECSEG ;AN000; + POP IN_CCBVECOFF ;AN000; + ; +GSC_0: CALL GET_INPUT_CALL ;AN000; + MOV AX,ES:[DI]+ICB_KEYRET ;AN000; + MOV N_USER_FUNC,AX ;AN000; + ; + CMP AX,F3*256 ;AN000;get last keystroke + JNE GSC_1 ;AN000; + ; + CALL HANDLE_F3 ;AN000; + JNC GSC_0 ;AN000; + MOV N_USER_FUNC,F3*256 ;AN000;set last keystroke to exit! + ; +GSC_1:;;AN000;MOV AX,ES:[DI]+ICB_ENDBYTE ; + ; + MOV ax,ES:[DI]+ICB_FIELDLEN ;AN000; size specified by si + MOV S_USER_STRING,AX ;AN000; + call unpad_user_string ;AN000; + ; + CALL CURSOROFF ;AN000; + POP ES ;AN000; + RET ;AN000; +GET_STRING_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX,input +; BX,string +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC INIT_STRING_CALL ;AN000; +INIT_STRING_CALL PROC ;AN000; + PUSH ES ;AN000; + CALL CLEAR_USER_STRING ;AN000; + ; + MOV IN_ICBID,AX ;AN000; process input field x + ; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + CALL GET_ICB ;AN000; + POP BX ;AN000; + ; + MOV ES:[DI]+ICB_WIDTH,SI ;AN000;GHG + MOV AX,SI ;AN000;GHG + ADD AX,ES:[DI]+ICB_COL ;AN000;GHG + CMP AX,75 ;AN000;GHG + JB ISC_10 ;AN000;GHG + MOV AX,70 ;AN000;GHG + SUB AX,ES:[DI]+ICB_COL ;AN000;GHG + MOV ES:[DI]+ICB_WIDTH,AX ;AN000;GHG + ; +ISC_10: MOV ES:[DI]+ICB_FIELDLEN,SI ;AN000; size specified by si + MOV AX,[BX] ;AN000; SETUP TO DISPLAY DEFAULT STRING + MOV ES:[DI]+ICB_DEFLEN,AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_CURCHAR,AX ;AN000; + MOV AX,BX ;AN000; + INC AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_DEFOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_DEFSEG,AX ;AN000; + ; + LEA AX,P_USER_STRING ;AN000; SETUP RETURN STRING ADDRESS + MOV ES:[DI]+ICB_FIELDOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_FIELDSEG,AX ;AN000; + ; + PUSH CRD_CCBVECOFF ;AN000; + PUSH CRD_CCBVECSEG ;AN000; + POP IN_CCBVECSEG ;AN000; + POP IN_CCBVECOFF ;AN000; + ; + MOV AX,INPUTOBJID ;AN000; input_object type + MOV BX,IN_ICBID ;AN000; scroll_id + CALL ADD_REFRESH ;AN000; + POP ES ;AN000; + RET ;AN000; +INIT_STRING_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX,input +; BX,string +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ENTER_KEY DB 13 ;AN000; +ENTER_KEY_LEN EQU ($-ENTER_KEY) ;AN000; + ; + PUBLIC SET_STRING_CALL ;AN000; +SET_STRING_CALL PROC ;AN000; + PUSH ES ;AN000; + CALL CLEAR_USER_STRING ;AN000; + ; + MOV IN_ICBID,AX ;AN000; process input field x + ; + PUSH BX ;AN000; + MOV BX,AX ;AN000; + CALL GET_ICB ;AN000; + POP BX ;AN000; + ; + MOV ES:[DI]+ICB_WIDTH,SI ;AN000;GHG + MOV AX,SI ;AN000;GHG + ADD AX,ES:[DI]+ICB_COL ;AN000;GHG + CMP AX,75 ;AN000;GHG + JB SSC_10 ;AN000;GHG + MOV AX,70 ;AN000;GHG + SUB AX,ES:[DI]+ICB_COL ;AN000;GHG + MOV ES:[DI]+ICB_WIDTH,AX ;AN000;GHG + ; +SSC_10: MOV ES:[DI]+ICB_FIELDLEN,SI ;AN000; size specified by si + MOV AX,[BX] ;AN000; SETUP TO DISPLAY DEFAULT STRING + MOV ES:[DI]+ICB_DEFLEN,AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_CURCHAR,AX ;AN000; + MOV AX,BX ;AN000; + INC AX ;AN000; + INC AX ;AN000; + MOV ES:[DI]+ICB_DEFOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_DEFSEG,AX ;AN000; + ; + LEA AX,P_USER_STRING ;AN000; SETUP RETURN STRING ADDRESS + MOV ES:[DI]+ICB_FIELDOFF,AX ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+ICB_FIELDSEG,AX ;AN000; + ; + MOV WR_DRETLEN,ENTER_KEY_LEN;AN000; SET AUTO RETURN KEYS + LEA AX,ENTER_KEY ;AN000; + MOV WR_DRETOFF,AX ;AN000; + MOV AX,CS ;AN000; + MOV WR_DRETSEG,AX ;AN000; + ; + PUSH CRD_CCBVECOFF ;AN000; + PUSH CRD_CCBVECSEG ;AN000; + POP IN_CCBVECSEG ;AN000; + POP IN_CCBVECOFF ;AN000; + ; + PUSH ES:[DI]+ICB_OPT2 ;AN000; + OR ES:[DI]+ICB_OPT2,ICB_UFK;AN000; + MOV ES:[DI]+ICB_KEYRET,ENTER;AN000; + ; + CALL GET_INPUT_CALL ;AN000; + ; + POP ES:[DI]+ICB_OPT2 ;AN000; + ; + CALL CURSOROFF ;AN000; + POP ES ;AN000; + RET ;AN000; +SET_STRING_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; AX,input +; SI,status_id +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC INIT_SCROLL_STATUS_CALL ;AN000; +INIT_SCROLL_STATUS_cALL PROC ;AN000; + PUSH ES ;AN000; + MOV BX,AX ;AN000; + CALL GET_SCB ;AN000; + ; + MOV ES:[DI]+SCB_SELOFF,SI ;AN000; + MOV AX,DS ;AN000; + MOV ES:[DI]+SCB_SELSEG,AX ;AN000; + POP ES ;AN000; + RET ;AN000; +INIT_SCROLL_STATUS_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; BX,index +; DX,table +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + EXTRN PCMBEEP_CALL:NEAR ;AN000; + ; + PUBLIC TOGGLE_SUPPORT_CALL ;AN000; +TOGGLE_SUPPORT_CALL PROC ;AN000; + PUSH SI ;AN000; + DEC BX ;AN000; + SHL BX,1 ;AN000; + MOV SI,DX ;AN000; + MOV AX,[SI+BX] ;AN000; + CMP AX,SCB_ACTIVEON ;AN000; + JNE TS_1 ;AN000; + MOV AX,SCB_SELECTON ;AN000; + MOV [SI+BX],AX ;AN000; + JMP TS_4 ;AN000; + ; +TS_1: CMP AX,SCB_SELECTON ;AN000; + JNE TS_3 ;AN000; + MOV AX,SCB_ACTIVEON ;AN000; + MOV [SI+BX],AX ;AN000; + JMP TS_4 ;AN000; + ; +TS_3: CALL PCMBEEP_CALL ;AN000; +TS_4: POP SI ;AN000; + RET ;AN000; +TOGGLE_SUPPORT_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC UNPAD_USER_STRING ;AN000; +UNPAD_USER_STRING PROC ;AN000; + PUSH SI ;AN000; + PUSH CX ;AN000; + LEA SI,P_USER_STRING ;AN000; + MOV CX,S_USER_STRING ;AN000; + ADD SI,CX ;AN000; + DEC SI ;AN000; + MOV AL,20H ;AN000; + ; +UUS_1: CMP [SI],AL ;AN000; + JA UUS_3 ;AN000; + DEC SI ;AN000; + LOOP UUS_1 ;AN000; + ; +UUS_3: MOV S_USER_STRING,CX ;AN000; + POP CX ;AN000; + POP SI ;AN000; + RET ;AN000; +UNPAD_USER_STRING ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC CLEAR_USER_STRING ;AN000; +CLEAR_USER_STRING PROC ;AN000; + PUSH SI ;AN000; + PUSH CX ;AN000; + PUSH AX ;AN000; + LEA SI,P_USER_STRING ;AN000; + MOV CX,110 ;AN000; + MOV AL,20H ;AN000; + ; +CUS_1: MOV [SI],AL ;AN000; + INC SI ;AN000; + LOOP CUS_1 ;AN000; + ; + POP AX ;AN000; + POP CX ;AN000; + POP SI ;AN000; + RET ;AN000; +CLEAR_USER_STRING ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; BX,minimum +; CX,maximum +; AX=input +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC CHECK_MIN_MAX ;AN000; +CHECK_MIN_MAX PROC ;AN000; + CMP AX,BX ;AN000; + JB CMM_3 ;AN000; + CMP AX,CX ;AN000; + JA CMM_3 ;AN000; + CLC ;AN000; + JMP CMM_5 ;AN000; +CMM_3: CALL PCMBEEP_CALL ;AN000; + STC ;AN000; +CMM_5: RET ;AN000; +CHECK_MIN_MAX ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; MOV AX,value +; LEA BX,P_USER_STRING +; CALL CONVERT_ASCII +; MOV S_USER_STRING,AX +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +TEN DW 10 ;AN000; + ; + PUBLIC CONVERT_ASCII ;AN000; +CONVERT_ASCII PROC ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + XOR CX,CX ;AN000; + ; + OR AX,AX ;AN000;test if input value is 0 + JNE CA_1 ;AN000; + ; + MOV CX,1 ;AN000; + MOV AX,1 ;AN000; + MOV DX,'0' ;AN000;if input=0, then put '0' on stack + PUSH DX ;AN000; + JMP CA_6 ;AN000; + ; +CA_1: OR AX,AX ;AN000; + JE CA_5 ;AN000; + ; + XOR DX,DX ;AN000; + DIV TEN ;AN000; + ADD DX,'0' ;AN000; + PUSH DX ;AN000; + INC CX ;AN000; + JMP CA_1 ;AN000; + ; +CA_5: MOV AX,CX ;AN000; + OR AX,AX ;AN000; + JZ CA_8 ;AN000; + ; +CA_6: POP [BX] ;AN000; + INC BX ;AN000; + LOOP CA_6 ;AN000; + ; +CA_8: POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +CONVERT_ASCII ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; LEA BX,P_USER_STRING +; MOV CX,S_USER_STRING +; CALL CONVERT_NUMERIC +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC CONVERT_NUMERIC ;AN000; +CONVERT_NUMERIC PROC ;AN000; + PUSH SI ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + XOR DX,DX ;AN000; + XOR AX,AX ;AN000; + ; + OR CX,CX ;AN000; + JZ CN_8 ;AN000; + ; +CN_3: MUL TEN ;AN000; + PUSH CX ;AN000; + MOV CL,[BX] ;AN000; + CMP CL,'0' ;AN000; + JB CN_4 ;AN000; + CMP CL,'9' ;AN000; + JA CN_4 ;AN000; + JMP CN_5 ;AN000; +CN_4: MOV CL,'0' ;AN000; +CN_5: SUB CL,'0' ;AN000; + XOR CH,CH ;AN000; + ADD AX,CX ;AN000; + POP CX ;AN000; + INC BX ;AN000; + LOOP CN_3 ;AN000; + ; +CN_8: POP DX ;AN000; + POP CX ;AN000; + POP SI ;AN000; + RET ;AN000; +CONVERT_NUMERIC ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX = OBJECT ID +; BX = FIELD ID +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC ADD_REFRESH ;AN000; +ADD_REFRESH PROC ;AN000; + PUSH SI ;AN000; + LEA SI,WR_REFID ;AN000; + ADD SI,WR_REFIELDCNT ;AN000; + ADD SI,WR_REFIELDCNT ;AN000; + ADD SI,WR_REFIELDCNT ;AN000; + ADD SI,WR_REFIELDCNT ;AN000; + MOV [SI],AX ;AN000; + MOV [SI+2],BX ;AN000; + CMP WR_REFIELDCNT,WR_MAXREFID;AN000; + JAE AD_10 ;AN000; + INC WR_REFIELDCNT ;AN000; +AD_10: POP SI ;AN000; + RET ;AN000; +ADD_REFRESH ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,input +; DX,maximum DESTINATION buffer size +; SI,field_length +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + PUBLIC RETURN_STRING_CALL ;AN000; +RETURN_STRING_CALL PROC ;AN000; + PUSHH ;AN000; + ; + MOV BX,AX ;AN000; + CALL GET_ICB ;AN000; + ; + PUSH ES:[DI]+ICB_DEFSEG ;AN000; + MOV CX,ES:[DI]+ICB_DEFLEN ;AN000; + CMP DX,CX ;AN000;check if DEFAULT string > buffer + JAE RS_10 ;AN000; + MOV CX,DX ;AN000;only copy as much as possible +RS_10: MOV DI,ES:[DI]+ICB_DEFOFF ;AN000; + POP ES ;AN000; + ; + PUSH DS ;AN000; + PUSH SI ;AN000; + PUSH ES ;AN000; + PUSH DI ;AN000; + POP SI ;AN000; + POP DS ;AN000; + POP DI ;AN000; + POP ES ;AN000; + CLD ;AN000; + REP MOVSB ;AN000; + ; + POPP ;AN000; + RET ;AN000; +RETURN_STRING_CALL ENDP ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; AX,row +; BX,panid +; CX,col +; DL,character +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +PUBLIC INIT_CHAR_CALL ;AN000;JW +INIT_CHAR_CALL PROC ;AN000;JW +; ;AN000;JW + PUSH DX ;AN000;JW + CALL GET_PCB ;AN000;JW + MUL ES:[DI]+PCB_WIDTH ;AN000;JW + ADD AX,CX ;AN000;JW + MOV SI,ES:[DI]+PCB_EXPANDOFF ;AN000;JW + ADD SI,AX ;AN000;JW + PUSH ES:[DI]+PCB_EXPANDSEG ;AN000;JW + POP ES ;AN000;JW + POP DX ;AN000;JW + MOV ES: BYTE PTR [SI],DL ;AN000;JW +; ;AN000;JW + RET ;AN000;JW +INIT_CHAR_CALL ENDP ;AN000;JW +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SELECT ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/SSTUB.ASM b/v4.0/src/SELECT/SSTUB.ASM new file mode 100644 index 0000000..b62fdbc --- /dev/null +++ b/v4.0/src/SELECT/SSTUB.ASM @@ -0,0 +1,209 @@ + + +TITLE SELECT Stub ;AN000; +SUBTTL SELSTUB.ASM ;AN000; + +PAGE 60,132 ;AN000; + + INCLUDE SYSMSG.INC ;AN000; + MSG_UTILNAME ;AN000; + ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000; + INCLUDE VARSTRUC.INC ;AN000; + INCLUDE SEL_FILE.INC ;AN000; + ; + PUBLIC E_ENTER,E_TAB,E_ESCAPE ;AN000; + ; +ESCAPE EQU 27 ;AN000; +ENTER EQU 13 ;AN000; +TAB EQU 9 ;AN000; +F1 EQU 59 ;AN000; +F3 EQU 61 ;AN000; +SPACE EQU 32 ;AN000; + ; + PUBLIC DRIVE_A,DRIVE_B ;AN000;JW +DRIVE_A EQU 0 ;AN000;JW +DRIVE_B EQU 1 ;AN000;JW + ; +MSG_SERVICES ;AN000; + ; + PUBLIC SUPPORT_STATUS ;AN000; +SUPPORT_STATUS DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + DW ? ;AN000; + ; + PUBLIC I_USER_INDEX ;AN000; +I_USER_INDEX DW ? ;AN000; Index value for scroll list + ; + PUBLIC N_USER_NUMERIC,MIN_INPUT_VAL,MAX_INPUT_VAL;AN000; +N_USER_NUMERIC DW ? ;AN000; Input value for numeric fields +MIN_INPUT_VAL DW ? ;AN000; Minimum value of input +MAX_INPUT_VAL DW ? ;AN000; Maximum value of input + ; + PUBLIC S_USER_STRING,P_USER_STRING,M_USER_STRING;AN000; +S_USER_STRING DW M_USER_STRING ;AN000; Length of string +P_USER_STRING DB 120 DUP(?) ;AN000; Actual string +M_USER_STRING EQU $ - P_USER_STRING ;AN000; + ; + PUBLIC N_VALID_KEYS ;AN000; +N_VALID_KEYS DW ? ;AN000; Valid keys for current input + ; + PUBLIC N_USER_FUNC, E_ENTER, E_ESCAPE, E_TAB, E_F3, E_SPACE ;AN000; +N_USER_FUNC DW ? ;AN000; Function type entered by user +E_ENTER = ENTER ;AN000; Enter key +E_ESCAPE = ESCAPE ;AN000; Escape key +E_TAB = TAB ;AN000; Tab key +E_F3 = F3*256 ;AN000; Function key 3 (F3,0) +E_SPACE = SPACE ;AN000; ; + ; + PUBLIC FK_ENT_F3, FK_ENT_F3_LEN ;AN000; +FK_ENT_F3 DB ENTER,0,F3 ;AN000; Enter, F3 +FK_ENT_F3_LEN EQU ($-FK_ENT_F3) ;AN000; + ; + PUBLIC FK_ENT_ESC, FK_ENT_ESC_LEN ;AN000; +FK_ENT_ESC DB ENTER,ESCAPE ;AN000; Enter, Esc +FK_ENT_ESC_LEN EQU ($-FK_ENT_ESC) ;AN000; + ; + PUBLIC FK_ENT_ESC_F3, FK_ENT_ESC_F3_LEN ;AN000; +FK_ENT_ESC_F3 DB ENTER,ESCAPE,0,F3 ;AN000; Enter, Esc +FK_ENT_ESC_F3_LEN EQU ($-FK_ENT_ESC_F3) ;AN000; + ; + PUBLIC FK_ENT, FK_ENT_LEN ;AN000; +FK_ENT DB ENTER ;AN000; Enter +FK_ENT_LEN EQU ($-FK_ENT) ;AN000; + ; + PUBLIC FK_TEXT, FK_TEXT_LEN ;AN000; +FK_TEXT DB ENTER,ESCAPE,0,F1,0,F3 ;AN000; Enter, ESC, F1, F3 +FK_TEXT_LEN EQU ($-FK_TEXT) ;AN000; + ; + PUBLIC FK_SCROLL, FK_SCROLL_LEN ;AN000; +FK_SCROLL DB ENTER,ESCAPE,0,F1,0,F3 ;AN000; Enter,ESC, F1, F3 +FK_SCROLL_LEN EQU ($-FK_SCROLL) ;AN000; + ; + PUBLIC FK_TAB, FK_TAB_LEN ;AN000; +FK_TAB DB TAB,ENTER,ESCAPE,0,F1,0,F3 ;AN000;Enter, ESC, F1, F3, Tab +FK_TAB_LEN EQU ($-FK_TAB) ;AN000; + ; + PUBLIC FK_REVIEW, FK_REVIEW_LEN ;AN000; +FK_REVIEW DB ENTER,SPACE,ESCAPE,0,F1,0,F3 ;AN000;Enter,ESC,F1,F3,SPACE +FK_REVIEW_LEN EQU ($-FK_REVIEW) ;AN000; + ; + PUBLIC FK_DATE, FK_DATE_LEN ;AN000; +FK_DATE DB TAB,ENTER,0,F1 ;AN000; Enter, ESC, F1, Tab +FK_DATE_LEN EQU ($-FK_DATE) ;AN000; + ; + PUBLIC FK_FORMAT, FK_FORMAT_LEN ;AN000; +FK_FORMAT DB ENTER,0,F1 ;AN000; +FK_FORMAT_LEN EQU ($-FK_FORMAT) ;AN000; + ; + PUBLIC FK_REBOOT, FK_REBOOT_LEN ;AN000; +FK_REBOOT DB ? ;AN000; only CTRL+ALT+DEL keys valid +FK_REBOOT_LEN EQU 0 ;AN000; + ; + PUBLIC ERROR_KEYS,ERROR_KEYS_LEN,E_QUIT,E_RETURN ;AN000; +ERROR_KEYS DB 0,F3,ENTER ;AN000; +ERROR_KEYS_LEN EQU $-ERROR_KEYS ;AN000; +E_QUIT EQU 1 ;AN000; +E_RETURN EQU 2 ;AN000; + ; + PUBLIC E_YES, E_NO, E_NA ;AN000; +E_YES EQU 1 ;AN000; +E_NO EQU 2 ;AN000; +E_NA EQU 6 ;AN000; + ; + PUBLIC N_SELECT_MODE, E_SELECT_MENU, E_SELECT_FDISK, E_SELECT_INV ;AN000; +N_SELECT_MODE DW ? ;AN000; SELECT command line mode +E_SELECT_MENU EQU 0 ;AN000; MENU mode +E_SELECT_FDISK EQU 1 ;AN000; FDISK mode +E_SELECT_INV EQU 0FFH ;AN000; Invalid parameter + ; + PUBLIC N_FORMAT_MODE,E_FORMAT_SELECT,E_FORMAT_NEW,E_FORMAT_USED ;AN000; +N_FORMAT_MODE DW ? ;AN000; FORMAT mode specified on command line +E_FORMAT_SELECT EQU 1 ;AN000; new disk - select to format all partitions +E_FORMAT_NEW EQU 2 ;AN000; new disk - user to format all partitions +E_FORMAT_USED EQU 3 ;AN000; used disk - user to format all partitions + ; + PUBLIC S_SPACE ;AN000; +S_SPACE DW M_SPACE ;AN000; +P_SPACE DB ' ' ;AN000; +M_SPACE EQU $ - P_SPACE ;AN000; + ; + PUBLIC S_OFF ;AN000; +S_OFF DW M_OFF ;AN000; OFF parameter +P_OFF DB 'OFF' ;AN000; +M_OFF EQU $ - P_OFF ;AN000; + ; + PUBLIC S_ON ;AN000; +S_ON DW M_ON ;AN000; ON parameter +P_ON DB 'ON' ;AN000; +M_ON EQU $ - P_ON ;AN000; + ; + PUBLIC I_WORKSPACE,N_WORK_PREV,E_WORKSPACE_BAL,E_WORKSPACE_MIN,E_WORKSPACE_MAX ;AN000; +I_WORKSPACE DW ? ;AN000; user workspace option +N_WORK_PREV DW ? ;AN000; previous workspace option +E_WORKSPACE_MIN EQU 1 ;AN000; minimize DOS functions +E_WORKSPACE_BAL EQU 2 ;AN000; balance DOS function +E_WORKSPACE_MAX EQU 3 ;AN000; maximize DOS functions + ; + PUBLIC S_ANSI,M_ANSI,F_ANSI,E_ANSI_YES,D_ANSI_1,E_ANSI_B,E_ANSI_C,E_ANSI_NO ;AN000; +S_ANSI DW M_ANSI ;AN000; ANSI command +P_ANSI DB 2 DUP(?) ;AN000; +M_ANSI EQU $ - P_ANSI ;AN000; +D_ANSI_1 DW 2 ;AN000; + DB '/X' ;AN000; +F_ANSI DW ? ;AN000; ANSI support required indicator +E_ANSI_NO = E_NO ;AN000; ANSI support not required +E_ANSI_YES = E_YES ;AN000; include ANSI.SYS command +E_ANSI_B EQU 2 ;AN000; +E_ANSI_C EQU 3 ;AN000; + ; + PUBLIC S_APPEND, F_APPEND, E_APPEND_YES, E_APPEND_NO, M_APPEND ;AN000; + PUBLIC S_APPEND_P, M_APPEND_P ;AN000;JW +S_APPEND DW M_APPEND ;AN000; APPEND command +P_APPEND DB 120 DUP(?) ;AN000; +M_APPEND EQU $ - P_APPEND ;AN000; +S_APPEND_P DW 2 ;AN000; APPEND command paramters JW +P_APPEND_P DB '/E' ;AN000; Default parameter JW + DB 38 DUP(' ') ;AN000; JW +M_APPEND_P EQU $ - P_APPEND_P ;AN000; JW +F_APPEND DW ? ;AN000; APPEND support indicator +E_APPEND_NO = E_NO ;AN000; APPEND support not required +E_APPEND_YES = E_YES ;AN000; include APPEND command + ; + PUBLIC S_BREAK, M_BREAK, ST_BREAK, MT_BREAK ;AN000; +S_BREAK DW M_BREAK ;AN000; BREAK command +P_BREAK DB 3 DUP(?) ;AN000; +M_BREAK EQU $ - P_BREAK ;AN000; +ST_BREAK DW MT_BREAK ;AN000; temp location for BREAK command +PT_BREAK DB M_BREAK DUP(?) ;AN000; +MT_BREAK EQU $ - PT_BREAK ;AN000; + ; + PUBLIC S_BUFFERS,M_BUFFERS,D_BUFFERS_1,D_BUFFERS_2,ST_BUFFERS,MT_BUFFERS ;AN000; +S_BUFFERS DW M_BUFFERS ;AN000; BUFFERS command +P_BUFFERS DB 7 DUP(?) ;AN000; +M_BUFFERS EQU $ - P_BUFFERS ;AN000; +D_BUFFERS_1 DW 2 ;AN000; + DB '20' ;AN000; +D_BUFFERS_2 DW 4 ;AN000; + DB '25,8' ;AC041;SEH for optimal performance +ST_BUFFERS DW MT_BUFFERS ;AN000; temp location for BUFFERS parameters +PT_BUFFERS DB M_BUFFERS DUP(?) ;AN000; +MT_BUFFERS EQU $ - PT_BUFFERS ;AN000; + ; + PUBLIC S_CPSW, M_CPSW, F_CPSW, E_CPSW_YES, E_CPSW_NO, E_CPSW_NA ;AN000; + PUBLIC E_CPSW_B, E_CPSW_C, ST_CPSW, MT_CPSW ;AN000; + PUBLIC N_CPSW, E_CPSW_NOT_VAL, E_CPSW_NOT_REC, E_CPSW_VALID ;AN000; +S_CPSW DW M_CPSW ;AN000; CPSW command +P_CPSW DB 3 DUP(?) ;AN000; +M_CPSW EQU $ - P_CPSW ;AN000; +F_CPSW DW ? ;AN000; CPSW support indicator +E_CPSW_NO = E_NO ;AN000; CPSW support not required +E_CPSW_YES = E_YES ;AN000; include CPSW command +E_CPSW_NA = E_NA ;AN000; CPSW not available +E_CPSW_B EQU 1 ;AN000; +E_CPSW_C EQU 1 ;AN000; +ST_CPSW DW MT_CPSW ;AN000; temp location for CPSW command +PT_CPSW DB M_CPSW DUP(?) ;AN000; +MT_CPSW EQU $ - PT_CPSW ;AN000; +N_CPSW DW ? ;AN000; code page switching indicator for country +E_CPSW_NOT_VAL EQU 0 ;AN000; code page switching not allowed +E_CPSW_NOT_REC EQU 1 ;AN000; code page switching not recommended +E_CPSW_VALID EQU 2 ;AN000; code page switching recommended + ; + PUBLIC S_FASTOPEN, M_FASTOPEN, F_FASTOPEN, E_FASTOPEN_YES ;AN000; + PUBLIC E_FASTOPEN_NO, D_FASTOPEN_1, D_FASTOPEN_2, E_FASTOPEN_C ;AN000; +S_FASTOPEN DW M_FASTOPEN ;AN000; FASTOPEN command +P_FASTOPEN DB 60 DUP(?) ;AN000; +M_FASTOPEN EQU $ - P_FASTOPEN ;AN000; +D_FASTOPEN_1 DW 10 ;AN000; + DB 'C:=(50,25)' ;AN000; +D_FASTOPEN_2 DW 12 ;AN000; + DB 'C:=(150,150)' ;AC078; SEH changed from 200,200 to 150,150 due to expanded mem problems ;AC041; SEH for optimal performance +F_FASTOPEN DW ? ;AN000; FASTOPEN support indicator +E_FASTOPEN_NO = E_NO ;AN000; FASTOPEN support not required +E_FASTOPEN_YES = E_YES ;AN000; include FASTOPEN command +E_FASTOPEN_C EQU 4 ;AN000; + ; + PUBLIC S_FCBS, M_FCBS, D_FCBS_1, ST_FCBS, MT_FCBS ;AN000; +S_FCBS DW M_FCBS ;AN000; FCBS command +P_FCBS DB 7 DUP(?) ;AN000; +M_FCBS EQU $ - P_FCBS ;AN000; +D_FCBS_1 DW 4 ;AN000; + DB '20,8' ;AN000; +ST_FCBS DW MT_FCBS ;AN000; temp location for FCBS command +PT_FCBS DB M_FCBS DUP(?) ;AN000; +MT_FCBS EQU $ - PT_FCBS ;AN000; + ; + PUBLIC S_FILES, M_FILES, D_FILES_1, D_FILES_2, ST_FILES, MT_FILES ;AN000; +S_FILES DW M_FILES ;AN000; FILES command +P_FILES DB 3 DUP(?) ;AN000; +M_FILES EQU $ - P_FILES ;AN000; +D_FILES_1 DW 2 ;AN000; + DB '20' ;AN000; +D_FILES_2 DW 1 ;AN000; + DB '8' ;AN000; +ST_FILES DW MT_FILES ;AN000; temp location for FILES command +PT_FILES DB M_FILES DUP(?) ;AN000; +MT_FILES EQU $ - PT_FILES ;AN000; + ; + PUBLIC S_GRAPHICS, M_GRAPHICS, F_GRAPHICS, E_GRAPHICS_YES ;AN000; + PUBLIC E_GRAPHICS_NO, E_GRAPHICS_B, E_GRAPHICS_C ;AN000; +S_GRAPHICS DW M_GRAPHICS ;AN000; GRAPHICS command +P_GRAPHICS DB 80 DUP(?) ;AN000; +M_GRAPHICS EQU $ - P_GRAPHICS ;AN000; +F_GRAPHICS DW ? ;AN000; GRAPHICS support indicator +E_GRAPHICS_NO = E_NO ;AN000; GRAPHICS support not required +E_GRAPHICS_YES = E_YES ;AN000; include GRAPHICS command +E_GRAPHICS_B EQU 4 ;AN000; +E_GRAPHICS_C EQU 6 ;AN000; + ; + PUBLIC F_GRAFTABL, E_GRAFTABL_YES, E_GRAFTABL_NO, E_GRAFTABL_NA ;AN000; + PUBLIC E_GRAFTABL_B, E_GRAFTABL_C ;AN000; +F_GRAFTABL DW ? ;AN000; GRAFTABL support indicator +E_GRAFTABL_NO = E_NO ;AN000; GRAFTABL support not required +E_GRAFTABL_YES = E_YES ;AN000; include GRAFTABL command +E_GRAFTABL_NA = E_NA ;AN000; GRAFTABL not available +E_GRAFTABL_B EQU 3 ;AN000; +E_GRAFTABL_C EQU 5 ;AN000; + ; + PUBLIC S_LASTDRIVE,M_LASTDRIVE,D_LASTDRIVE_1,ST_LASTDRIVE,MT_LASTDRIVE ;AN000; +S_LASTDRIVE DW M_LASTDRIVE ;AN000; LASTDRIVE command +P_LASTDRIVE DB 1 DUP(?) ;AN000; +M_LASTDRIVE EQU $ - P_LASTDRIVE ;AN000; +D_LASTDRIVE_1 DW 1 ;AN000; + DB 'E' ;AN000; +ST_LASTDRIVE DW MT_LASTDRIVE ;AN000; temp location for LASTDRIVE command +PT_LASTDRIVE DB M_LASTDRIVE DUP(?) ;AN000; +MT_LASTDRIVE EQU $ - PT_LASTDRIVE ;AN000; + ; + PUBLIC S_PATH, M_PATH, F_PATH, E_PATH_YES, E_PATH_NO ;AN000; +S_PATH DW M_PATH ;AN000; PATH command +P_PATH DB 120 DUP(?) ;AN000; +M_PATH EQU $ - P_PATH ;AN000; +F_PATH DW ? ;AN000; PATH support indicator +E_PATH_NO = E_NO ;AN000; PATH support not required +E_PATH_YES = E_YES ;AN000; include PATH command + ; + PUBLIC S_PROMPT,M_PROMPT,F_PROMPT,E_PROMPT_YES,E_PROMPT_NO,D_PROMPT_1 ;AN000; +S_PROMPT DW M_PROMPT ;AN000; PROMPT command +P_PROMPT DB 120 DUP(?) ;AN000; +M_PROMPT EQU $ - P_PROMPT ;AN000; +D_PROMPT_1 DW 4 ;AN000; + DB '$P$G' ;AN000; +F_PROMPT DW ? ;AN000; PROMPT command indicator +E_PROMPT_NO = E_NO ;AN000; PROMPT command not to be included +E_PROMPT_YES = E_YES ;AN000; include PROMPT command + ; + PUBLIC S_SHARE,M_SHARE,F_SHARE,E_SHARE_YES,E_SHARE_NO,E_SHARE_C ;AN000; +S_SHARE DW M_SHARE ;AN000; SHARE command +P_SHARE DB 15 DUP(?) ;AN000; +M_SHARE EQU $ - P_SHARE ;AN000; +F_SHARE DW ? ;AN000; SHARE support indicator +E_SHARE_NO = E_NO ;AN000; SHARE support not required +E_SHARE_YES = E_YES ;AN000; include SHARE command +E_SHARE_C EQU 7 ;AN000; + ; + PUBLIC S_SHELL, M_SHELL, F_SHELL, E_SHELL_YES, E_SHELL_NO ;AN000; + PUBLIC D_SHELL_1, D_SHELL_2, E_SHELL_B, E_SHELL_C ;AC018;SEH ;AC000;JW +S_SHELL DW M_SHELL ;AN000; SHELL command +P_SHELL DB 115 DUP(?) ;AN000; +M_SHELL EQU $ - P_SHELL ;AN000; +D_SHELL_1 DW M_SHELL_1 ;AN000; +P_SHELL_1 DB '/TRAN/MAINT/MENU/EXIT/SND/PROMPT' ;AC077;SEH ;AC000;JW +M_SHELL_1 EQU $ - P_SHELL_1 ;AN000; +D_SHELL_2 DW M_SHELL_2 ;AN000; +P_SHELL_2 DB '/TRAN/COLOR/DOS/MENU/MUL' ;AC071;SEH ;AC016;SEH ;AC000;JW + DB '/SND/MEU:SHELL.MEU/CLR:SHELL.CLR/PROMPT/MAINT/EXIT/SWAP/DATE' ;AC012;SEH ;AC000;JW +M_SHELL_2 EQU $ - P_SHELL_2 ;AN000; +F_SHELL DW ? ;AN000; SHELL support indicator +E_SHELL_NO = E_NO ;AN000; SHELL support not required +E_SHELL_YES = E_YES ;AN000; include SHELL command +E_SHELL_B = 5 +E_SHELL_C = 8 + ; + PUBLIC MACHINE_TYPE, PS2_FLAG, MOD25_OR_MOD30 ;AN000;JW +MACHINE_TYPE DB ? ;AN000;JW +PS2_FLAG DB ? ;AN000;JW +MOD25_OR_MOD30 EQU 0FAH ;AN000;JW + ; + PUBLIC S_STACKS,M_STACKS,ST_STACKS,MT_STACKS ;AN000; +S_STACKS DW M_STACKS ;AN000; STACKS command +P_STACKS DB 6 DUP(?) ;AN000; +M_STACKS EQU $ - P_STACKS ;AN000; +ST_STACKS DW MT_STACKS ;AN000; temp location for STACKS command +PT_STACKS DB M_STACKS DUP(?) ;AN000; +MT_STACKS EQU $ - PT_STACKS ;AN000; + ; + PUBLIC S_VDISK,M_VDISK,F_VDISK,E_VDISK_YES,E_VDISK_NO,E_VDISK_B,E_VDISK_C ;AN000; +S_VDISK DW M_VDISK ;AN000; VDISK command +P_VDISK DB 20 DUP(?) ;AN000; +M_VDISK EQU $ - P_VDISK ;AN000; +F_VDISK DW ? ;AN000; VDISK support indicator +E_VDISK_NO = E_NO ;AN000; VDISK support not required +E_VDISK_YES = E_YES ;AN000; include VDISK command +E_VDISK_B EQU 6 ;AN000; +E_VDISK_C EQU 9 ;AN000; + ; + PUBLIC S_VERIFY, M_VERIFY, ST_VERIFY, MT_VERIFY ;AN000; +S_VERIFY DW M_VERIFY ;AN000; VERIFY command +P_VERIFY DB 3 DUP(?) ;AN000; +M_VERIFY EQU $ - P_VERIFY ;AN000; +ST_VERIFY DW MT_VERIFY ;AN000; temp location for VERIFY command +PT_VERIFY DB M_VERIFY DUP(?) ;AN000; +MT_VERIFY EQU $ - PT_VERIFY ;AN000; + ; + PUBLIC S_XMAEM, M_XMAEM ;AN000; +S_XMAEM DW M_XMAEM ;AN000; XMAEM command +P_XMAEM DB 40 DUP(?) ;AN000; +M_XMAEM EQU $ - P_XMAEM ;AN000; + ; + PUBLIC S_XMA2EMS, M_XMA2EMS, D_XMA2EMS_1, F_XMA, E_XMA_NO, E_XMA_NA ;AN000; + PUBLIC E_XMA_YES, E_XMA_C, N_XMA, E_XMA_ABSENT, E_XMA_PRESENT ;AN000; +S_XMA2EMS DW M_XMA2EMS ;AN000; XMA2EMS command +P_XMA2EMS DB 40 DUP(?) ;AN000; +M_XMA2EMS EQU $ - P_XMA2EMS ;AN000; +D_XMA2EMS_1 DW 30 ;AN000; + DB 'FRAME=D000 P254=C000 P255=C400' ;AC044;SEH ;AC040;SEH ;AN000;JW +F_XMA DW ? ;AN000; Expanded Memory support indicator +E_XMA_NO = E_NO ;AN000; Expanded Memory support not required +E_XMA_YES = E_YES ;AN000; include XMAEM, XMA2EMS commands +E_XMA_NA = E_NA ;AN000; Expanded memory not available +E_XMA_C EQU 2 ;AN000; +N_XMA DW ? ;AN000; Expanded memory presence indicator +E_XMA_ABSENT EQU 0 ;AN000; expanded memory not present +E_XMA_PRESENT EQU 1 ;AN000; expanded memory is present + ; + PUBLIC N_MOD80, E_IS_MOD80, E_NOT_MOD80 ;AN000;JW +N_MOD80 DW ? ;AN000; Model 80 indicator +E_NOT_MOD80 EQU 0 ;AN000; is not a model 80 +E_IS_MOD80 EQU 1 ;AN000; is a model 80 + ; + PUBLIC I_DEST_DRIVE, E_DEST_DRIVE_A, E_DEST_DRIVE_B, E_DEST_DRIVE_C ;AN111;JW +I_DEST_DRIVE DW ? ;AN000; Install destination drive - set by CHECK_VALID_MEDIA +E_DEST_DRIVE_C EQU 1 ;AN000; drive C: +E_DEST_DRIVE_B EQU 2 ;AN000; drive B: +E_DEST_DRIVE_A EQU 3 ;AN111; drive A: + ; + PUBLIC N_DRIVE_OPTION, E_OPTION_B_C, E_OPTION_A_C ;AN111;JW +N_DRIVE_OPTION DW ? ;AN111; Which options to choose from JW +E_OPTION_B_C EQU 1 ;AN111; install to B or C JW +E_OPTION_A_C EQU 2 ;AN111; install to A or C JW + ; + PUBLIC N_DEST_DRIVE, E_DEST_SELECT, E_DEST_USER ;AN000; +N_DEST_DRIVE DB ? ;AN000; destination drive determined by user or SELECT +E_DEST_SELECT EQU 0 ;AN000; SELECT will determine default drive +E_DEST_USER EQU 1 ;AN000; user will select destination drive + ; + PUBLIC N_DISKETTE_TOT, N_ZERO_DISKETTE, N_DISKETTE_A, N_DISKETTE_B ;AN000; + PUBLIC E_DISKETTE_INV, E_DISKETTE_360, E_DISKETTE_720, E_DISKETTE_1200, E_DISKETTE_1440 ;AN000; +N_DISKETTE_TOT DB ? ;AN000; number of diskette drives +N_ZERO_DISKETTE EQU 0 ;AN000; +N_DISKETTE_A DB ? ;AN000; drive A: diskette status +N_DISKETTE_B DB ? ;AN000; drive B: diskette status +E_DISKETTE_INV EQU 0FFH ;AN000; diskette not present +E_DISKETTE_360 EQU 0 ;AN000; diskette media is 360K (5.25 inch) +E_DISKETTE_1200 EQU 1 ;AN000; diskette media is 1.2M (5.25 inch) +E_DISKETTE_720 EQU 2 ;AN000; diskette media is 720K (3.5 inch) +E_DISKETTE_1440 EQU 7 ;AN000; diskette media is 1.44M (3.5 inch) + ; + PUBLIC S_DEST_DRIVE,M_DEST_DRIVE,S_DRIVE_A ;AN000; +S_DEST_DRIVE DW M_DEST_DRIVE ;AN000; Destination drive to install DOS +P_DEST_DRIVE DB 'C:\' ;AN000; +M_DEST_DRIVE EQU $ - P_DEST_DRIVE ;AN000; +S_DRIVE_A DW M_DRIVE_A ;AN000; +P_DRIVE_A DB 'A:\' ;AN000; +M_DRIVE_A EQU $ - P_DRIVE_A ;AN000; + ; + PUBLIC S_C_DRIVE,S_A_DRIVE,S_B_DRIVE ;AC039;SEH;AN000;JW +S_C_DRIVE DW M_C_DRIVE ;AN000; Destination drive w/o backslash JW +P_C_DRIVE DB 'C:' ;AN000; +M_C_DRIVE EQU $ - P_C_DRIVE ;AN000; +S_A_DRIVE DW M_A_DRIVE ;AN039;SEH Destination drive w/o backslash +P_A_DRIVE DB 'A:' ;AN039;SEH +M_A_DRIVE EQU $ - P_A_DRIVE ;AN039;SEH +S_B_DRIVE DW M_B_DRIVE ;AN039;SEH Destination drive w/o backslash +P_B_DRIVE DB 'B:' ;AN039;SEH +M_B_DRIVE EQU $ - P_B_DRIVE ;AN039;SEH + ; + PUBLIC S_DOS_LOC, M_DOS_LOC, D_DOS_LOC_1 ;AN000; +S_DOS_LOC DW M_DOS_LOC ;AN000; user defined DOS location path for drive C: +P_DOS_LOC DB 37 DUP(?) ;AN000; +M_DOS_LOC EQU $ - P_DOS_LOC ;AN000; +D_DOS_LOC_1 DW 3 ;AN000; + DB 'DOS' ;AN000; + ; + PUBLIC S_INSTALL_PATH, M_INSTALL_PATH ;AN000; +S_INSTALL_PATH DW M_INSTALL_PATH ;AN000; install path including drive +P_INSTALL_PATH DB 40 DUP( ) ;AN000; +M_INSTALL_PATH EQU $ - P_INSTALL_PATH ;AN000; + ; + PUBLIC I_CTY_KYBD, E_CTY_KB_PREDEF, E_CTY_KB_USER ;AN000; +I_CTY_KYBD DW ? ;AN000; index for country and keyboard screen +E_CTY_KB_PREDEF EQU 1 ;AN000; Use predefined country/keyboard +E_CTY_KB_USER EQU 2 ;AN000; user specified country/keyboard to be used + ; + PUBLIC N_CTY_LIST, E_CTY_LIST_1, E_CTY_LIST_2 ;AN000; +N_CTY_LIST DW ? ;AN000; Country code scroll list identifier +E_CTY_LIST_1 EQU 1 ;AN000; code 001 - 046 +E_CTY_LIST_2 EQU 2 ;AN000; code 047 - 972 + ; + PUBLIC I_COUNTRY, N_COUNTRY ;AN000; +I_COUNTRY DW ? ;AN000; Index into country code list +N_COUNTRY DW ? ;AN000; Country Code + ; + PUBLIC N_KYBD_LIST, E_KYBD_LIST_1, E_KYBD_LIST_2 ;AN000; +N_KYBD_LIST DW ? ;AN000; Keyboard code scroll list identifier +E_KYBD_LIST_1 EQU 1 ;AN000; code BE - NO +E_KYBD_LIST_2 EQU 2 ;AN000; code PO - none + ; + PUBLIC I_KEYBOARD ;AN000; +I_KEYBOARD DW ? ;AN000; Index into keyboard code list + ; + PUBLIC S_KEYBOARD,N_KYBD_VAL,E_KYBD_VAL_YES,E_KYBD_VAL_NO ;AN000; + PUBLIC M_KEYBOARD,E_KYBD_VAL_DEF ;AN000; +S_KEYBOARD DW M_KEYBOARD ;AN000; +P_KEYBOARD DB 2 DUP(?) ;AN000; Keyboard code +M_KEYBOARD EQU $ - P_KEYBOARD ;AN000; +N_KYBD_VAL DB ? ;AN000; Keyboard code valid indicator +E_KYBD_VAL_NO EQU 0 ;AN000; Keyboard code is not valid +E_KYBD_VAL_YES EQU 1 ;AN000; Keyboard code is valid +E_KYBD_VAL_DEF EQU 2 ;AN000; Default keyboard (US) is to be used + ; This state is defined so that keyboard screen + ; will be displayed with "None" option + ; + PUBLIC N_DESIGNATES, N_CP_PRI, N_CP_SEC, N_CTY_RES ;AN000; +N_DESIGNATES DW ? ;AN000; number of designates +N_CP_PRI DW ? ;AN000; Primary code page +N_CP_SEC DW ? ;AN000; Secondary code page +N_CTY_RES DB ? ;AN000; reserved byte from country table + ; + PUBLIC I_KYBD_ALT, S_KYBD_ALT, M_KYBD_ALT, N_KYBD_ALT ;AN000; + PUBLIC E_KYBD_ALT_NO, E_KYBD_ALT_YES ;AN000; +I_KYBD_ALT DW ? ;AN000; Index into alternate keyboard code list +S_KYBD_ALT DW M_KYBD_ALT ;AN000; +P_KYBD_ALT DB 2 DUP(?) ;AN000; Keyboard code +M_KYBD_ALT EQU $ - P_KYBD_ALT ;AN000; +N_KYBD_ALT DB ? ;AN000; Alternate keyboards present indicator +E_KYBD_ALT_NO EQU 0 ;AN000; no alternate keyboards +E_KYBD_ALT_YES EQU 1 ;AN000; are alternate keyboards are present + ; + PUBLIC N_KYB_LOAD,E_KYB_LOAD_SUC,E_KYB_LOAD_ERR,E_KYB_LOAD_US,E_KYB_LOAD_UND ;AN000; +N_KYB_LOAD DW ? ;AN000; KEYB load status +E_KYB_LOAD_SUC EQU 1 ;AN000; no error from KEYB +E_KYB_LOAD_ERR EQU 2 ;AN000; error from KEYB +E_KYB_LOAD_US EQU 3 ;AN000; US keyboard loaded +E_KYB_LOAD_UND EQU 4 ;AN000; undefined keyboard loaded + ; +; Country code association with Keyboard code & Code Page + PUBLIC CTY_TAB_A,CTY_TAB_A_1,CTY_A_ITEMS ;AN000; +CTY_TAB_A DB CTY_A_ITEMS ;AN000; no of entries in table +CTY_TAB_A_1 CTY_DEF < 001,E_KYBD_VAL_DEF,' ',437,850,1,E_CPSW_NOT_REC,0> ;AN000; (01) United States + CTY_DEF < 002,E_KYBD_VAL_YES,'CF',863,850,2,E_CPSW_VALID ,0> ;AN000; (02) Canada (French) + CTY_DEF < 003,E_KYBD_VAL_YES,'LA',850,437,1,E_CPSW_VALID ,0> ;AC070;SEH ;AN000; (03) Latin America + CTY_DEF < 031,E_KYBD_VAL_YES,'NL',437,850,1,E_CPSW_VALID ,0> ;AN000; (04) Netherlands + CTY_DEF < 032,E_KYBD_VAL_YES,'BE',850,437,1,E_CPSW_VALID ,0> ;AN000; (05) Belgium + CTY_DEF < 033,E_KYBD_VAL_YES,'FR',437,850,1,E_CPSW_VALID ,1> ;AN000; (06) France + CTY_DEF < 034,E_KYBD_VAL_YES,'SP',850,437,1,E_CPSW_VALID ,0> ;AN000; (07) Spain + CTY_DEF < 039,E_KYBD_VAL_YES,'IT',437,850,1,E_CPSW_VALID ,2> ;AN000; (08) Italy + CTY_DEF < 041,E_KYBD_VAL_YES,'SF',850,437,1,E_CPSW_VALID ,0> ;AN000; (09) Switzerland + CTY_DEF < 044,E_KYBD_VAL_YES,'UK',437,850,1,E_CPSW_VALID ,3> ;AN000; (10) United Kingdom + CTY_DEF < 045,E_KYBD_VAL_YES,'DK',850,865,2,E_CPSW_VALID ,0> ;AN000; (11) Denmark + CTY_DEF < 046,E_KYBD_VAL_YES,'SV',437,850,1,E_CPSW_VALID ,0> ;AN000; (12) Sweden +CTY_A_ITEMS EQU ($ - CTY_TAB_A_1) / TYPE CTY_DEF ;AN000; no of items + ; + PUBLIC CTY_TAB_B,CTY_TAB_B_1,CTY_B_ITEMS ;AN000; +CTY_TAB_B DB CTY_B_ITEMS ;AN000; no of entries in table +CTY_TAB_B_1 CTY_DEF < 047,E_KYBD_VAL_YES,'NO',850,865,2,E_CPSW_VALID ,0 > ;AN000; (01) Norway + CTY_DEF < 049,E_KYBD_VAL_YES,'GR',437,850,1,E_CPSW_VALID ,0 > ;AN000; (02) Germany + CTY_DEF < 061,E_KYBD_VAL_YES,'US',437,850,1,E_CPSW_VALID ,0 > ;AN000; (03) Australia + CTY_DEF < 081,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (04) Japan + CTY_DEF < 082,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (05) Korea + CTY_DEF < 086,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (06) Republic of China + CTY_DEF < 088,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (07) Taiwan + CTY_DEF < 351,E_KYBD_VAL_YES,'PO',850,860,2,E_CPSW_VALID ,0 > ;AN000; (08) Portugal + CTY_DEF < 358,E_KYBD_VAL_YES,'SU',850,437,1,E_CPSW_VALID ,0 > ;AN000; (09) Finland + CTY_DEF < 785,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (10) Arabic Speaking + CTY_DEF < 972,E_KYBD_VAL_NO ,' ',000,000,0,E_CPSW_NOT_VAL,0 > ;AN000; (11) Hebrew Speaking +CTY_B_ITEMS EQU ($ - CTY_TAB_B_1) / TYPE CTY_DEF ;AN000; no of items + ; +; Keyboard Codes supported + PUBLIC KYBD_TAB_A,KYBD_TAB_A_1,KYBD_A_ITEMS ;AN000; +KYBD_TAB_A DB KYBD_A_ITEMS ;AN000; no of entries in table +KYBD_TAB_A_1 KYB_DEF < 'BE', E_KYBD_ALT_NO > ;AN000; (01) Flemish + KYB_DEF < 'CF', E_KYBD_ALT_NO > ;AN000; (02) Canadian French + KYB_DEF < 'DK', E_KYBD_ALT_NO > ;AN000; (03) Danish + KYB_DEF < 'FR', E_KYBD_ALT_YES> ;AN000; (04) French + KYB_DEF < 'GR', E_KYBD_ALT_NO > ;AN000; (05) German + KYB_DEF < 'IT', E_KYBD_ALT_YES> ;AN000; (06) Italian + KYB_DEF < 'LA', E_KYBD_ALT_NO > ;AN000; (07) Latin American (Spanish) + KYB_DEF < 'NL', E_KYBD_ALT_NO > ;AN000; (08) Dutch + KYB_DEF < 'NO', E_KYBD_ALT_NO > ;AN000; (09) Norwegian +KYBD_A_ITEMS EQU ($ - KYBD_TAB_A_1) / TYPE KYB_DEF ;AN000; no of items in table + ; + PUBLIC KYBD_TAB_B,KYBD_TAB_B_1,KYBD_B_ITEMS ;AN000; +KYBD_TAB_B DB KYBD_B_ITEMS ;AN000; no of entries in table +KYBD_TAB_B_1 KYB_DEF < 'PO', E_KYBD_ALT_NO > ;AN000; (01) Portuguese + KYB_DEF < 'SF', E_KYBD_ALT_NO > ;AN000; (02) Swiss (French) + KYB_DEF < 'SG', E_KYBD_ALT_NO > ;AN000; (03) Swiss (German) + KYB_DEF < 'SP', E_KYBD_ALT_NO > ;AN000; (04) Spanish + KYB_DEF < 'SU', E_KYBD_ALT_NO > ;AN000; (05) Finnish + KYB_DEF < 'SV', E_KYBD_ALT_NO > ;AN000; (06) Swedish + KYB_DEF < 'UK', E_KYBD_ALT_YES> ;AN000; (07) UK English + KYB_DEF < 'US', E_KYBD_ALT_NO > ;AN000; (08) US English + KYB_DEF < ' ', E_KYBD_ALT_NO > ;AN000; (09) none of the above +KYBD_B_ITEMS EQU ($ - KYBD_TAB_B_1) / TYPE KYB_DEF ;AN000; no of items in table + ; + PUBLIC ALT_TAB_PTR ;AN000; +ALT_TAB_PTR DW ? ;AN000; pointer keyboard table + ; + PUBLIC ALT_KYB_ID, ALT_FRENCH, ALT_ITALIAN, ALT_UK, ALT_KYB_ID_PREV ;AN000; +ALT_KYB_ID DB ? ;AN000; keyboard code identifier +ALT_KYB_ID_PREV DB ? ;AN000; previous keyboard code identifier +ALT_FRENCH EQU 1 ;AN000; French keyboard +ALT_ITALIAN EQU 2 ;AN000; Italian keyboard +ALT_UK EQU 3 ;AN000; UK English keyboard + ; + PUBLIC ALT_KYB_TABLE, ALT_KYB_TAB_1, ALT_KYB_ITEMS ;AN000; +ALT_KYB_TABLE DB ALT_KYB_ITEMS ;AN000; no of items in table +ALT_KYB_TAB_1 ALT_KYB_DEF < 'FR', ALT_KYBD_FR, ALT_FRENCH > ;AN000; French keyboard + ALT_KYB_DEF < 'IT', ALT_KYBD_IT, ALT_ITALIAN > ;AN000; Italian keyboard + ALT_KYB_DEF < 'UK', ALT_KYBD_UK, ALT_UK > ;AN000; UK English +ALT_KYB_ITEMS EQU ($ - ALT_KYB_TAB_1) / TYPE ALT_KYB_DEF ;AN000; no of items + ; + PUBLIC ALT_KYBD_FR, ALT_KYBD_FR_1, ALT_FR_ITEMS ;AN000; +ALT_KYBD_FR DB ALT_FR_ITEMS ;AN000; Alternate French Keyboard-no of entries in table +ALT_KYBD_FR_1 FR_STRUC <'120'> ;AN000; + FR_STRUC <'189'> ;AC000;JW +ALT_FR_ITEMS EQU ($ - ALT_KYBD_FR_1) / TYPE FR_STRUC ;AN000; + ; + PUBLIC ALT_KYBD_IT, ALT_KYBD_IT_1, ALT_IT_ITEMS ;AN000; +ALT_KYBD_IT DB ALT_IT_ITEMS ;AN000; Alternate Italian keyboard-no of entries in table +ALT_KYBD_IT_1 IT_STRUC <'142'> ;AC090;JW Switched with '141 + IT_STRUC <'141'> ;AC090;JW +ALT_IT_ITEMS EQU ($ - ALT_KYBD_IT_1) / TYPE IT_STRUC ;AN000; + ; + PUBLIC ALT_KYBD_UK, ALT_KYBD_UK_1, ALT_UK_ITEMS ;AN000; +ALT_KYBD_UK DB ALT_UK_ITEMS ;AN000; no of entries in table +ALT_KYBD_UK_1 UK_STRUC <'168'> ;AN000; + UK_STRUC <'166'> ;AC000;JW +ALT_UK_ITEMS EQU ($ - ALT_KYBD_UK_1) / TYPE UK_STRUC ;AN000; + ; + PUBLIC ALT_ID_DEF ;AN000; +ALT_ID_DEF DB 0 ;AN000;DT + ; + PUBLIC S_US ;AN000; +S_US DW M_US ;AN000; +P_US DB 'US' ;AN000; +M_US EQU $ - P_US ;AN000; + ; + PUBLIC S_SWISS ;AN000; +S_SWISS DW M_SWISS ;AN000; +P_SWISS DB 'SF' ;AN000; +M_SWISS EQU $ - P_SWISS ;AN000; + ; + PUBLIC PRINTER_TABLES ;AN000; +PRINTER_TABLES EQU $ ;AN000; + PRINTER_DEF < > ;AN000; LPT1 + PRINTER_DEF < > ;AN000; LPT2 + PRINTER_DEF < > ;AN000; LPT3 + PRINTER_DEF < > ;AN000; COM1 + PRINTER_DEF < > ;AN000; COM2 + PRINTER_DEF < > ;AN000; COM3 + PRINTER_DEF < > ;AN000; COM4 + ; + PUBLIC N_NUMPRINT, MIN_NUMPRINT, MAX_NUMPRINT ;AN000; +N_NUMPRINT DW ? ;AN000; No. of printers to install +MIN_NUMPRINT EQU 0 ;AN000; +MAX_NUMPRINT EQU 7 ;AN000; + ; + PUBLIC N_SERIAL, N_PARALLEL ;AN000; +N_PARALLEL DW ? ;AN000; +N_SERIAL DW ? ;AN000; + ; + PUBLIC I_PORT, I_REDIRECT, I_PRINTER ;AN000; +I_PORT DW ? ;AN000; port number +I_REDIRECT DW ? ;AN000; serial port redirection +I_PRINTER DW ? ;AN000; index into printer list + ; + PUBLIC N_PRINTER_TYPE, E_SERIAL, E_PARALLEL ;AN000; +N_PRINTER_TYPE DB ? ;AN000; printer type +E_SERIAL EQU 53H ;AN000; Serial 'S' +E_PARALLEL EQU 50H ;AN000; Parallel 'P' + ; + PUBLIC S_MODE_PARM, M_MODE_PARM ;AN000; +S_MODE_PARM DW M_MODE_PARM ;AN000; +P_MODE_PARM DB 40 DUP(?) ;AN000; +M_MODE_PARM EQU $ - P_MODE_PARM ;AN000; + ; + PUBLIC S_CP_DRIVER, M_CP_DRIVER ;AN000; +S_CP_DRIVER DW M_CP_DRIVER ;AN000; +P_CP_DRIVER DB 22 DUP(?) ;AN000; +M_CP_DRIVER EQU $ - P_CP_DRIVER ;AN000; + ; + PUBLIC S_CP_PREPARE, M_CP_PREPARE ;AN000; +S_CP_PREPARE DW M_CP_PREPARE ;AN000; +P_CP_PREPARE DB 12 DUP(?) ;AN000; +M_CP_PREPARE EQU $ - P_CP_PREPARE ;AN000; + ; + PUBLIC S_GRAPH_PARM, M_GRAPH_PARM ;AN000; +S_GRAPH_PARM DW M_GRAPH_PARM ;AN000; +P_GRAPH_PARM DB 20 DUP(?) ;AN000; +M_GRAPH_PARM EQU $ - P_GRAPH_PARM ;AN000; + ; + PUBLIC F_REVIEW, E_REVIEW_ACCEPT, E_REVIEW_VIEW ;AN000; +F_REVIEW DW ? ;AN000; Review selection screen index +E_REVIEW_ACCEPT EQU 1 ;AN000; user will accept selections made by SELECT +E_REVIEW_VIEW EQU 2 ;AN000; user wants to view/change selections made by SELECT + ; + PUBLIC N_DISPLAY, E_CPSW_DISP, E_NOCPSW_DISP ;AN000; +N_DISPLAY DB ? ;AN000; display type indicator +E_CPSW_DISP EQU 0 ;AN000; display type will support CPSW +E_NOCPSW_DISP EQU 1 ;AN000; display type will not support CPSW + ; + PUBLIC N_YEAR, MIN_YEAR, MAX_YEAR ;AN000; +N_YEAR DW ? ;AN000; calender year +MIN_YEAR EQU 1980 ;AN000; +MAX_YEAR EQU 2079 ;AN000; + ; + PUBLIC N_MONTH, MIN_MONTH, MAX_MONTH ;AN000; +N_MONTH DW ? ;AN000; calender month +MIN_MONTH EQU 1 ;AN000; +MAX_MONTH EQU 12 ;AN000; + ; + PUBLIC N_DAY, MIN_DAY, MAX_DAY ;AN000; +N_DAY DW ? ;AN000; calender day +MIN_DAY EQU 1 ;AN000; +MAX_DAY EQU 31 ;AN000; + ; + PUBLIC N_HOUR, MIN_HOUR, MAX_HOUR ;AN000; +N_HOUR DW ? ;AN000; hour +MIN_HOUR EQU 0 ;AN000; +MAX_HOUR EQU 23 ;AN000; + ; + PUBLIC N_MINUTE, MIN_MINUTE, MAX_MINUTE ;AN000; +N_MINUTE DW ? ;AN000; minute +MIN_MINUTE EQU 0 ;AN000; +MAX_MINUTE EQU 59 ;AN000; + ; + PUBLIC N_SECOND, MIN_SECOND, MAX_SECOND ;AN000; +N_SECOND DW ? ;AN000; second +MIN_SECOND EQU 0 ;AN000; +MAX_SECOND EQU 59 ;AN000; + ; + PUBLIC PARM_BLOCK, CMD_BUFF ;AN000; +PARM_BLOCK LABEL WORD ;AN000; parameter block for EXEC_PROGRAM + DW 0 ;AN000; use parent environment + DW OFFSET CMD_BUFF ;AN000; pointer to commnad line + DW ? ;AN000; segment for command line + DW 5CH ;AN000; default FCB + DW ? ;AN000; segment for FCB + DW 6CH ;AN000; default FCB + DW ? ;AN000; segment for FCB +PARM_BLOCK_END EQU $ ;AN000; + ; +CMD_BUFF LABEL BYTE ;AN000; command line passed to EXEC_PROGRAM + DB ? ;AN000; length of command line - excluding carrier return + DB 80 DUP(?) ;AN000; +CMD_BUFF_END EQU $ ;AN000; + ; + PUBLIC S_STR40, P_STR40, M_STR40 ;AN000;JW +S_STR40 DW M_STR40 ;AN000; Temporary variable for string field +P_STR40 DB 40 DUP(?) ;AN000;JW +M_STR40 EQU $ - P_STR40 ;AN000;JW + ; + PUBLIC S_STR120_1, P_STR120_1, M_STR120_1 ;AN000; +S_STR120_1 DW M_STR120_1 ;AN000; Temporary variable for string field +P_STR120_1 DB 120 DUP(?) ;AN000; +M_STR120_1 EQU $ - P_STR120_1 ;AN000; + ; + PUBLIC S_STR120_2, M_STR120_2 ;AN000; +S_STR120_2 DW M_STR120_2 ;AN000; Temporary variable for string field +P_STR120_2 DB 120 DUP(?) ;AN000; +M_STR120_2 EQU $ - P_STR120_2 ;AN000; + ; + PUBLIC S_STR120_3, M_STR120_3 ;AN000; +S_STR120_3 DW M_STR120_3 ;AN000; Temporary variable for string field +P_STR120_3 DB 120 DUP(?) ;AN000; +M_STR120_3 EQU $ - P_STR120_3 ;AN000; + ; + PUBLIC S_STR120_4, M_STR120_4 ;AN039;SEH +S_STR120_4 DW M_STR120_4 ;AN039;SEH Temporary variable for string field +P_STR120_4 DB 120 DUP(?) ;AN039;SEH +M_STR120_4 EQU $ - P_STR120_4 ;AN039;SEH + ; + PUBLIC SC_LINE, MC_LINE ;AN000; +SC_LINE DW MC_LINE ;AN000; Temporary variable for string field +PC_LINE DB 130 DUP(?) ;AN000; +MC_LINE EQU $ - PC_LINE - 2 ;AN000; + ; + PUBLIC N_HANDLE ;AN000; +N_HANDLE DW ? ;AN000; save location for file handle + ; + PUBLIC N_WRITE_HANDLE, N_WRITE_ERR_CODE ;AN000; +N_WRITE_HANDLE DW ? ;AN000; File handle for prepared file +N_WRITE_ERR_CODE DW ? ;AN000; error code for prepared file + ; + PUBLIC N_RETCODE, N_COUNTER ;AN000; +N_RETCODE DW ? ;AN000; Return code if execution not a success +N_COUNTER DW ? ;AN000; Loop counter + ; + PUBLIC N_WORD_1, N_WORD_2, N_WORD_3, N_WORD_4, N_WORD_5, N_WORD_6,N_BYTE_1 ;AN000; +N_WORD_1 DW ? ;AN000; temp variable +N_WORD_2 DW ? ;AN000; temp variable +N_WORD_3 DW ? ;AN000; temp variable +N_WORD_4 DW ? ;AN000; temp variable +N_WORD_5 DW ? ;AN000; temp variable +N_WORD_6 DW ? ;AN000; temp variable +N_BYTE_1 DB ? ;AN025; temp variable + ; + PUBLIC SAVE_AREA ;AN000; +SAVE_AREA DB 4 DUP(?) ;AN000; save area for stack pointer before EXEC program + ; + PUBLIC N_HOUSE_CLEAN,E_CLEAN_YES,E_CLEAN_NO ;AN000; +N_HOUSE_CLEAN DB ? ;AN000; +E_CLEAN_YES EQU 1 ;AN000; erase temp files +E_CLEAN_NO EQU 0 ;AN000; no temp files to erase + ; + PUBLIC N_DSKCPY_ERR,E_DSKCPY_RETRY,E_DSKCPY_OK ;AN000;JW +N_DSKCPY_ERR DB 0 ;AN000;JW +E_DSKCPY_RETRY EQU 1 ;AN000; retry diskcopy +E_DSKCPY_OK EQU 0 ;AN000; diskcopy successful + ; + PUBLIC E_CR, E_LF ;AN000; +E_CR EQU 0DH ;AN000; +E_LF EQU 0AH ;AN000; + ; +; EQUATES FOR FIELD TYPES DEFINED IN DISK STATUS STRUCTURE +; EQUATES FOR N_PART_NAME ; Partition name + PUBLIC E_PART_PRI_DOS, E_PART_EXT_DOS, E_PART_LOG_DRI ;AN000; + PUBLIC E_FREE_MEM_EDOS, E_FREE_MEM_DISK, E_PART_OTHER ;AN000; +E_PART_PRI_DOS EQU 1 ;AN000; Primary DOS partition +E_PART_EXT_DOS EQU 2 ;AN000; Extended DOS partition +E_PART_LOG_DRI EQU 3 ;AN000; Logical Drive +E_FREE_MEM_EDOS EQU 4 ;AN000; Free space in Extended DOS partition +E_FREE_MEM_DISK EQU 5 ;AN000; Free disk space - undefined partition +E_PART_OTHER EQU 6 ;AN000; other partition types i.e not DOS or EDOS + +; EQUATES FOR N_PART_STATUS ; Partition status + PUBLIC E_PART_UNFORMAT, E_PART_FORMAT ;AN000; +E_PART_UNFORMAT EQU 0 ;AN000; partition is unformatted +E_PART_FORMAT EQU 1 ;AN000; partition is formatted + ; +; EQUATES FOR N_PART_TYPE ; Partition type + PUBLIC E_PART_FAT, E_PART_KSAM, E_PART_UNDEF, E_PART_IGNORE ;AN000; +E_PART_FAT EQU 1 ;AN000; FAT +E_PART_KSAM EQU 2 ;AN000; KSAM +E_PART_UNDEF EQU 3 ;AN000; not assigned +E_PART_IGNORE EQU 4 ;AN000; other partition types i.e not FAT or KSAM + ; + PUBLIC N_DISK_1, E_DISK_1, N_DISK_2, E_DISK_2 ;AN000; + PUBLIC E_DISK_INV, E_DISK_NO_PART, E_DISK_VAL_PART ;AN000; +N_DISK_1 DW ? ;AN000; first fixed disk status +N_DISK_2 DW ? ;AN000; second fixed disk status +E_DISK_1 EQU 1 ;AN000; +E_DISK_2 EQU 2 ;AN000; +E_DISK_INV EQU 0 ;AN000; fixed disk not present +E_DISK_NO_PART EQU 1 ;AN000; fixed disk present : no DOS or EDOS partitions +E_DISK_VAL_PART EQU 2 ;AN000; fixed disk present : DOS or EDOS partitions exist + ; + PUBLIC N_DISK_1_S1,N_DISK_2_S1,E_DISK_PRI,E_DISK_EXT_DOS ;AN000; + PUBLIC E_DISK_LOG_DRI,E_DISK_EDOS_MEM,E_DISK_FREE_MEM ;AN000; +N_DISK_1_S1 DW ? ;AN000; detailed status of first fixed drive +N_DISK_2_S1 DW ? ;AN000; detailed status or second fixed drive +E_DISK_PRI EQU 01H ;AN000; Primary DOS partition exists +E_DISK_EXT_DOS EQU 02H ;AN000; Extended DOS partitions exists +E_DISK_LOG_DRI EQU 04H ;AN000; Logical drives exist in Extended Dos partitions +E_DISK_EDOS_MEM EQU 08H ;AN000; Free space exists in Extended DOS partition +E_DISK_FREE_MEM EQU 10H ;AN000; Free disk space exists + ; + PUBLIC N_DISK_1_S2, N_DISK_2_S2,E_SPACE_NONE,E_SPACE_EDOS,E_SPACE_DISK ;AN000; +N_DISK_1_S2 DW 0 ;AN000; +N_DISK_2_S2 DW 0 ;AN000; +E_SPACE_NONE EQU 0 ;AN000; no free space in EDOS and DISK +E_SPACE_EDOS EQU 1 ;AN000; free space in EDOS +E_SPACE_DISK EQU 2 ;AN000; no EDOS but free space in disk + ; + PUBLIC F_PARTITION, E_PART_DEFAULT, E_PART_USER ;AN000; +F_PARTITION DW 1 ;AN000; partition size division option +E_PART_DEFAULT EQU 1 ;AN000; default partition sizes are to be used +E_PART_USER EQU 2 ;AN000; user will define partition sizes + ; + PUBLIC I_DESTINATION, E_ENTIRE_DISK, E_PATH_ONLY ;AN000;JW +I_DESTINATION DW 1 ;AN000; destination on c: disk option JW +E_ENTIRE_DISK EQU 1 ;AN000; replace files across entire disk JW +E_PATH_ONLY EQU 2 ;AN000; replace files in dos path only JW + ; + PUBLIC F_FORMAT, E_FORMAT_FAT, E_FORMAT_NO ;AN000; +F_FORMAT DW ? ;AN000; +E_FORMAT_FAT EQU 1 ;AN000; format partition with FAT +E_FORMAT_NO EQU 2 ;AN000; do not format partition + ; + PUBLIC N_DISK1_MODE, E_DISK1_INSTALL, E_DISK1_REPLACE ;AN000; +N_DISK1_MODE DW ? ;AN000; install mode for fixed disk +E_DISK1_INSTALL EQU 1 ;AN000; install DOS-no partitions +E_DISK1_REPLACE EQU 2 ;AN000; replace DOS-partitions exist + ; + PUBLIC DISK_1_TABLE,DISK_1_VAL_ITEM,DISK_1_START,M_DISK_1_ITEMS ;AN000; +DISK_1_TABLE DB M_DISK_1_ITEMS ;AN000; maximum no of items in table +DISK_1_VAL_ITEM DB 0 ;AN000; number of valid entries in table +DISK_1_START DB (100*TYPE DISK_STATUS) DUP (0) ;AN000; +M_DISK_1_ITEMS EQU ($ - DISK_1_START) / TYPE DISK_STATUS ;AN000; + ; + PUBLIC DISK_2_TABLE,DISK_2_VAL_ITEM,DISK_2_START,M_DISK_2_ITEMS ;AN000; +DISK_2_TABLE DB M_DISK_2_ITEMS ;AN000; maximum no of items in table +DISK_2_VAL_ITEM DB 0 ;AN000; number of valid entries in table +DISK_2_START DB (100*TYPE DISK_STATUS) DUP (0) ;AN000; +M_DISK_2_ITEMS EQU ($ - DISK_2_START) / TYPE DISK_STATUS ;AN000; + ; + PUBLIC N_NAME_PART,N_SIZE_PART,N_STATUS_PART,P_DRIVE_PART,N_TYPE_PART,N_LEVEL1_PART,N_LEVEL2_PART,N_LEVEL3_PART,N_LEVEL4_PART ;AC065;SEH add check for version number ;AN000; +N_NAME_PART DB 0 ;AN000; partition name +N_SIZE_PART DW 0 ;AN000; partition size +N_STATUS_PART DB 0 ;AN000; partition status +N_TYPE_PART DB 0 ;AN000; partition type +P_DRIVE_PART DB ' ' ;AN000; drive letter assigned +N_LEVEL1_PART DB 0 ;AN065; SEH version number (1st part) for DOS 4.00 1st part = blank +N_LEVEL2_PART DB 0 ;AN065; SEH version number (2nd part) for DOS 4.00 2nd part = 4 +N_LEVEL3_PART DB 0 ;AN065; SEH version number (3rd part) for DOS 4.00 3rd part = . +N_LEVEL4_PART DB 0 ;AN065; SEH version number (4th part) for DOS 4.00 4th part = 0 + ; + PUBLIC N_DISK_NUM,E_DISK_ROW,E_DISK_COL,E_DRIVE_ROW,E_DRIVE_COL ;AN000; +N_DISK_NUM DB ? ;AN000; holder for ascii disk number +E_DISK_ROW EQU 0 ;AN000; row for fixed disk number (0 based) +E_DISK_COL EQU 19 ;AN000; column for fixed disk number +E_DRIVE_ROW EQU 0 ;AN000; row for logical drive letter (0 based) +E_DRIVE_COL EQU 19 ;AN000; column for logical drive letter + ; + PUBLIC STACK_INDEX, SELECT_STACK, STACK_SIZE ;AN000; +STACK_INDEX DB 00H ;AN000; no. of entries in stack +SELECT_STACK DW 50 DUP(?) ;AN000; stack entries +STACK_SIZE EQU $ - SELECT_STACK ;AN000; size of SELECT stack + ; + PUBLIC N_DEST,E_DEST_DOS,E_DEST_SHELL ;AN000; +N_DEST DB ? ;AN000; +E_DEST_DOS EQU 1 ;AN000; +E_DEST_SHELL EQU 2 ;AN000; + ; +; Variables which return information if a critical error occurs. +; INT_24_ERROR returns the error code from the critical error routine +; INT_24_FLAG is set if a critical error occurs. It is not enough +; to check if INT_24_ERROR is non-zero, since a value of zero is a critical error. +PUBLIC INT_24_ERROR, INT_24_FLAG ;AN000; +INT_24_ERROR DW 0 ;AN000; +INT_24_FLAG DB 0 ;AN000; + ; +; Area to save the old interrupt 23h vector for restoration when the program is done. +PUBLIC OLD_INT_23 ;AN074;SEH ctrl-break +OLD_INT_23 DD 0 ;AN074;SEH +; Area to save the old interrupt 24h vector for restoration when the program is done. +PUBLIC OLD_INT_24 ;AN000; +OLD_INT_24 DD 0 ;AN000; +; Area to save the old interrupt 2Fh vector for restoration when the program is done. +PUBLIC OLD_INT_2F ;AN000; +OLD_INT_2F DD 0 ;AN000; + ; +PUBLIC MEM_SIZE ;AN000; +MEM_SIZE DW 0 ;AN000;DT installed memory in machine + ; + PUBLIC FORMAT_WHICH, STARTUP, SHELL ;AN000; +FORMAT_WHICH DB ? ;AN111; indicator for which disk (720) to format JW +STARTUP EQU 0 ;AN111; format startup +SHELL EQU 1 ;AN111; format shell + ; + PUBLIC DISK_PANEL, SEARCH_FILE ;AN000;JW +DISK_PANEL DW ? ;AN000;JW Holds panel number for INSERT_DISK +SEARCH_FILE DW ? ;AN000;JW Holds offset of file to search for + + PUBLIC SUB_ERROR ;AN000;JW Holds error code of sub process +SUB_ERROR DB ? ;AN000;JW + +include msgdcl.inc + ; +DATA ENDS ;AN000; + END ;AN000; diff --git a/v4.0/src/SELECT/VARSTRUC.INC b/v4.0/src/SELECT/VARSTRUC.INC new file mode 100644 index 0000000..302fdb9 --- /dev/null +++ b/v4.0/src/SELECT/VARSTRUC.INC @@ -0,0 +1,65 @@ +CTY_DEF STRUC ;AN000; +COUNTRY_CODE DW 0 ;AN000; Country Code +KEYBOARD_VALID DB 0 ;AN000; =0 Keyboard code is not valid + ; =1 Keyboard code is valid +KEYBOARD_CODE DB ' ' ;AN000; Keyboard Code +PRI_CODEPAGE DW 0 ;AN000; Primary Code Page +SEC_CODEPAGE DW 0 ;AN000; Secondary Code Page +NUM_DESIGNATES DW 0 ;AN000; number of designates +CPSW_STAT DW 0 ;AN000; code page switching recommendation for country +RESERVED_1 DW 0 ;AN000; reserved byte +CTY_DEF ENDS ;AN000; + +KYB_DEF STRUC ;AN000; +KEYB_CODE DB ' ' ;AN000; Keyboard code +KEYB_ALT_VALID DB 0 ;AN000; =0 No alternate Keyboard code + ; =1 Alternate Keyboard code present +KYB_DEF ENDS ;AN000; + +ALT_KYB_DEF STRUC ;AN000; +ALT_KYB DB ' ' ;AN000; keyboard codes which have alternate keyboards +ALT_KYB_PTR DW 0 ;AN000; pointer to list of alternate keyboards +ALT_KYB_IDENT DB 0 ;AN000; keyboard code identifier +ALT_KYB_DEF ENDS ;AN000; + +FR_STRUC STRUC ;AN000; Alternate French Keyboard +FR_KYB DB ' ' ;AN000; +FR_STRUC ENDS ;AN000; + +IT_STRUC STRUC ;AN000; Alternate Italian Keyboard +IT_KYB DB ' ' ;AN000; +IT_STRUC ENDS ;AN000; + +UK_STRUC STRUC ;AN000; Alternate UK English Keyboard +UK_KYB DB ' ' ;AN000; +UK_STRUC ENDS ;AN000; + +DISK_STATUS STRUC ;AN000; +N_PART_NAME DB 0 ;AN000; Partition name +N_PART_SIZE DW 0 ;AN000; size of above partition in MBytes +N_PART_STATUS DB 0 ;AN000; Partition status +P_PART_DRIVE DB ? ;AN000; drive letter assigned to the partition (ASCII) +N_PART_TYPE DB 0 ;AN000; +N_PART_LEVEL1 DB 0 ;AN065; SEH version number (1st part) for DOS 4.00 1st part = blank +N_PART_LEVEL2 DB 0 ;AN065; SEH version number (2nd part) for DOS 4.00 2nd part = 4 +N_PART_LEVEL3 DB 0 ;AN065; SEH version number (3rd part) for DOS 4.00 3rd part = . +N_PART_LEVEL4 DB 0 ;AN065; SEH version number (4th part) for DOS 4.00 4th part = 0 +DISK_STATUS ENDS ;AN000; + +PRINTER_DEF STRUC ;AN000; +PRINTER_INDEX DW 0 ;AN000; index into SELECT.PRT +PRINTER_TYPE DB 0 ;AN000; printer type serial/parallel +PRINTER_DATA_VALID DB 0 ;AN000; +MODE_PARMS DW 0 ;AN000; + DB 40 DUP(?) ;AC000;JW +CODE_DRIVER DW 0 ;AN000; + DB 22 DUP(?) ;AN000; +CODE_PREPARE DW 0 ;AN000; + DB 12 DUP(?) ;AN000; +GRAPHICS_PARMS DW 0 ;AN000; + DB 20 DUP(?) ;AN000; +PORT_NUMBER DW 0 ;AN000; +REDIRECTION_PORT DW 0 ;AN000; +PRINTER_TAB_NUM DW 0 ;AN000; indicates 1st, 2nd, 3rd, etc. printer selected +PRINTER_DEF ENDS ;AN000; + diff --git a/v4.0/src/SELECT/XCOPY.EQU b/v4.0/src/SELECT/XCOPY.EQU new file mode 100644 index 0000000..d3f932d --- /dev/null +++ b/v4.0/src/SELECT/XCOPY.EQU @@ -0,0 +1,144 @@ +; +; +;REVISION HISTORY +; +; A005 DCR0201 10/9/87 Incorperate new format for EXTENDED +; ATTRIBUTES. +; +; +;Equates used for flags +; +;*** MY_FLAG **** + find_first_flag equ 01h ;AN000;set MY_FLAG by "OR" + findfile_flag equ 02h ;AN000; + no_more_file equ 04h ;AN000; + single_copy_flag equ 08h ;AN000;single copy instead of multi copy + visit_parent_flag equ 10h ;AN000;visit parent node + found_flag equ 20h ;AN000;found flag - for find subdir + missing_link_flag equ 40h ;AN000; + is_source_flag equ 80h ;AN000;if set, dealing with source + reset_find_first equ 0FEh ;AN000;reset by AND + reset_findfile equ 0FDh ;AN000; + reset_no_more equ 0FBh ;AN000; + reset_visit_parent equ 0EFh ;AN000; + reset_found equ 0DFh ;AN000; + reset_missing_link equ 0BFh ;AN000; + reset_is_source equ 07Fh ;AN000; + +;*** FILE_FLAG *** + cont_flag equ 01h ;AN000; + eof_flag equ 02h ;AN000; + big_file_flag equ 04h ;AN000; + file_bigger_flag equ 08h ;AN000; + created_flag equ 10h ;AN000; + reset_cont equ 0FEh ;AN000; + reset_eof equ 0FDh ;AN000; + reset_big_file equ 0FBh ;AN000; + reset_file_bigger equ 0F7h ;AN000; + reset_created equ 0EFh ;AN000; + reset_readfile equ 0F0h ;AN000;reset FILE_FLAG for read a file + +;*** COPY_STATUS *** + open_error_flag equ 01h ;AN000; + read_error_flag equ 02h ;AN000; + create_error_flag equ 04h ;AN000; + write_error_flag equ 08h ;AN000; + mkdir_error_flag equ 10h ;AN000; + chdir_error_flag equ 20h ;AN000; + maybe_itself_flag equ 40h ;AN000;source, target starting drv, directory is same. + disk_full_flag equ 80h ;AN000; + reset_open_error equ 0FEh ;AN000; + reset_read_error equ 0FDh ;AN000; + reset_create_error equ 0FBh ;AN000; + reset_write_error equ 0F7h ;AN000; + reset_close_error equ 0EFh ;AN000; + reset_chdir_error equ 0DFh ;AN000; + + +;*** ACTION_FLAG *** + + reading_flag equ 01h ;AN000;display "Reading source files..." + reset_reading equ 0FEh ;AN000;do not display. + +;*** SYS_FLAG *** + + one_disk_copy_flag equ 01h ;AN000; + default_drv_set_flag equ 02h ;AN000;default drive has been changed by this program + default_s_dir_flag equ 04h ;AN000;source current directory saved. + default_t_dir_flag equ 08h ;AN000;target current directory saved. + removalble_drv_flag equ 10h ;AN000; + sharing_source_flag equ 20h ;AN000;source shared + sharing_target_flag equ 40h ;AN000; + turn_verify_off_flag equ 80h ;AN000;turn the verify off when exit to dos. + reset_default_s_dir equ 0FBh ;AN000;reset default_s_dir_flag + +;*** OPTION_FLAG *** + + slash_a equ 01h ;AN000;soft archieve ? + slash_d equ 02h ;AN000;date? + slash_e equ 04h ;AN000;create empty dir? + slash_m equ 08h ;AN000;hard archieve ? (turn off source archieve bit) + slash_p equ 10h ;AN000;prompt? + slash_s equ 20h ;AN000;walk the tree? + slash_v equ 40h ;AN000;verify on? + slash_w equ 80h ;AN000;show "Press any key to begin copying" msg) + reset_slash_a equ 0FEh ;AN000;turn off soft archieve + reset_slash_m equ 0F7h ;AN000;turn off hard archieve + +;*** PARM_FLAG *** + + first_parm_flag equ 01h ;AN000;first parm entered in input parm + second_parm_flag equ 02h ;AN000;second parm entered. + end_of_parm_flag equ 04h ;AN000;end of parm reached + copy_onto_itself_flag equ 08h ;AN000;copy onto itself flag + cyclic_flag equ 10h ;AN000;cyclic copy flag + inv_time_flag equ 20h ;AN000;invalid time + inv_date_flag equ 40h ;AN000;invalid date + init_error_flag equ 80h ;AN000;critical initialization error. Should abort. + +;*** PARM1_FLAG *** + + inv_s_path_flag equ 01h ;AN000;invalid source path (path not found) + inv_t_path_flag equ 02h ;AN000;invalid target path + s_file_flag equ 04h ;AN000;source filename entered + t_file_flag equ 08h ;AN000;target filename entered + +;general equates + +COLON EQU ":" ;AN000;FOLLOWS DRV LTR IN FULL FILESPEC +NUL EQU 0 ;AN000;DELIMITER FOR ASCIIZ STRINGS +SPACE EQU " " ;AN000;TEST FOR DBCS IN 'F D ' MESSAGE +PARAGRAPH EQU 4 ;AN005;TO CONVERT TO/FROM BYTES/PARA. +PARA_BOUND EQU 15 ;AN005;BYTES TO ADD FOR PARA. CALCULAT +FIXD_HD_SIZ EQU 2 ;AN005;PARA COUNT MINIMUM FOR FILE HDR +SYSPRM_EX_MANY EQU 1 ;AN000;TOO MANY OPERANDS ERR FROM PARSE +SYSPRM_MISSING_OP EQU 2 ;AN000;MISSING OPERANDS ERR FROM PARSE +SYSPRM_DUP_SW EQU 3 ;AN004;INVALID SWITCH R-CODE FROM PARSE +F_APPEND EQU 8000H ;AN000; /X status bit in Append +NOT_X_APPEND EQU 0 ;AN000; /X NOT ACTIVE +ACT_APPEND EQU 0 ;AN000;ACTIVE STATUS OF APPEND +D_V_APPEND EQU 0FFH ;AN000;DOS VERSION OF APPEND +PSPFCB1_DRV EQU 5Ch ;AN000; +PSPFCB2_DRV EQU 6Ch ;AN000; +PSPDTA_PARMLEN EQU 80h ;AN000; +PSPDTA_PARRSTR EQU 81h ;AN000; +BASE_OF_ALPHA_DRV EQU 64 ;AN000;1 => A, 2 => B for drive letter +BASE_UPPER_CASE EQU 11011111B ;AN000;"AND"ed will make it to upper case chr +ALPHA_A EQU 'A' ;AN000; +;ALPHA_D EQU 'D' ;moved to XCPYINT.MSG file for translation. +ALPHA_E EQU 'E' ;AN000; +;ALPHA_F EQU 'F' ;moved to XCPYINT.MSG file for translation. +ALPHA_M EQU 'M' ;AN000; +ALPHA_S EQU 'S' ;AN000; +ALPHA_P EQU 'P' ;AN000; +ALPHA_T EQU 'T' ;AN000; +ALPHA_V EQU 'V' ;AN000; +ALPHA_W EQU 'W' ;AN000; +ALPHA_Z EQU 'Z' ;AN000; +A_dot EQU '.' ;AN000; +path_delim equ '\' ;AN000; +drv_delim equ ':' ;AN000; +;********************************************************************** +;DOS_LEVEL EQU 0314h ;VERSION 3.20 +;*************************END OF XCOPY.EQU **************************** + \ No newline at end of file diff --git a/v4.0/src/SELECT/XMAINMSG.EQU b/v4.0/src/SELECT/XMAINMSG.EQU new file mode 100644 index 0000000..b16913b --- /dev/null +++ b/v4.0/src/SELECT/XMAINMSG.EQU @@ -0,0 +1,44 @@ +;***************************************************************************** +; Message equates +;***************************************************************************** +CR equ 13 ;AN000; +LF equ 10 ;AN000; +BELL equ 7 ;AN000; +END_OF_MESSAGE equ 0 ;AN000; +ALPHA_D equ 'D' ;AN000; +ALPHA_F equ 'F' ;AN000; +PARM_SUBST_ONE EQU 01H ;AN000;MSG PARAMETER SUBSTITUTION = 1 +MSG_SER_CLASS EQU 00H ;AN000;MESSAGE SERVICE CLASS (RESERVED) +EXT_ERR_CLASS EQU 01H ;AN000;DOS EXTENDED ERROR CLASS +PARSE_ERR_CLASS EQU 02H ;AN000;PARSE ERROR CLASS +UTILITY_MSG_CLASS EQU 0FFH ;AN000;UTILITY MESSAGE CLASS +NO_INPUT EQU 00H ;AN000;NO INPUT CHARACTERS +DOS_KEYB_INP EQU 01H ;AN000;KEYBOARD INPUT EXPECTED +;****************************************************************************** +; XCOPY (MAIN) messages +;***************************************************************************** +; ERROR MESSAGES DEFINITION +; +MSG_ACCESS_DENIED EQU 13 ;AN000; +MSG_TOO_MANY_OPEN EQU 14 ;AN000; +MSG_GENERAL_FAIL EQU 15 ;AN000; +MSG_SHARING_VIOL EQU 16 ;AN000; +MSG_LOCK_VIOL EQU 17 ;AN000; +MSG_PATH_NOT EQU 18 ;AN000; +MSG_DISK_FULL EQU 19 ;AN000; +MSG_COPY_ITSELF EQU 20 ;AN000; +MSG_UNABLE_CREATE EQU 10 ;AN000; +MSG_RES_T_NAME EQU 22 ;AN000; +MSG_FILE_NOT_ERR EQU 23 ;AN000; +MSG_FILE_CREATE_ERR EQU 24 ;AN000; +MSG_READING_SOURCE EQU 25 ;AN000; +MSG_CR_LF_STR EQU 26 ;AN000; +MSG_FILES_COPIED EQU 27 ;AN000; +MSG_FILE_NOT_FOUND EQU 28 ;AN000; +S_PATH_FILE0 EQU 30 ;AN000; +S_PATH_FILE1 EQU 31 ;AN000; +DISPLAY_S_PATH EQU 32 ;AN000; +P_S_PATH_FILE0 EQU 33 ;AN000; +P_S_PATH_FILE1 EQU 34 ;AN000; +;******************** END OF XCPYMAIN.MSG ************************************** + \ No newline at end of file diff --git a/v4.0/src/SETENV.BAT b/v4.0/src/SETENV.BAT new file mode 100644 index 0000000..0a67782 --- /dev/null +++ b/v4.0/src/SETENV.BAT @@ -0,0 +1,12 @@ +@echo off +echo setting up system to build the MS-DOS 4.01 SOURCE BAK... +set CL= +set LINK= +set MASM= +set COUNTRY=usa-ms +set BAKROOT=d: +rem BAKROOT points to the home drive/directory of the sources. +set LIB=%BAKROOT%\src\tools\lib +set INIT=%BAKROOT%\src\tools +set INCLUDE=%BAKROOT%\src\tools\inc +set PATH=%BAKROOT%\src\tools diff --git a/v4.0/src/TOOLS/ASC2HLP.EXE b/v4.0/src/TOOLS/ASC2HLP.EXE new file mode 100644 index 0000000..a5487ff Binary files /dev/null and b/v4.0/src/TOOLS/ASC2HLP.EXE differ diff --git a/v4.0/src/TOOLS/ATTRIB.EXE b/v4.0/src/TOOLS/ATTRIB.EXE new file mode 100644 index 0000000..5afd271 Binary files /dev/null and b/v4.0/src/TOOLS/ATTRIB.EXE differ diff --git a/v4.0/src/TOOLS/BLD/INC/ASSERT.H b/v4.0/src/TOOLS/BLD/INC/ASSERT.H new file mode 100644 index 0000000..3a9809f --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/ASSERT.H @@ -0,0 +1,35 @@ +/*** +*assert.h - define the assert macro +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines the assert(exp) macro. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef _ASSERT_DEFINED + +#ifndef NDEBUG + +static char _assertstring[] = "Assertion failed: %s, file %s, line %d\n"; + +#define assert(exp) { \ + if (!(exp)) { \ + fprintf(stderr, _assertstring, #exp, __FILE__, __LINE__); \ + fflush(stderr); \ + abort(); \ + } \ + } + +#else + +#define assert(exp) + +#endif /* NDEBUG */ + +#define _ASSERT_DEFINED + +#endif /* _ASSERT_DEFINED */ diff --git a/v4.0/src/TOOLS/BLD/INC/BIOS.H b/v4.0/src/TOOLS/BLD/INC/BIOS.H new file mode 100644 index 0000000..0844857 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/BIOS.H @@ -0,0 +1,181 @@ +/*** +*bios.h - declarations for bios interface functions and supporting definitions +* +* Copyright (c) 1987-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file declares the constants, structures, and functions +* used for accessing and using various BIOS interfaces. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +/* manifest constants for BIOS serial communications (RS-232) support */ + +/* serial port services */ + +#define _COM_INIT 0 /* init serial port */ +#define _COM_SEND 1 /* send character */ +#define _COM_RECEIVE 2 /* receive character */ +#define _COM_STATUS 3 /* get serial port status */ + +/* serial port initializers. One and only one constant from each of the + * following four groups - character size, stop bit, parity, and baud rate - + * must be specified in the initialization byte. + */ + +/* character size initializers */ + +#define _COM_CHR7 2 /* 7 bits characters */ +#define _COM_CHR8 3 /* 8 bits characters */ + +/* stop bit values - on or off */ + +#define _COM_STOP1 0 /* 1 stop bit */ +#define _COM_STOP2 4 /* 2 stop bits */ + +/* parity initializers */ + +#define _COM_NOPARITY 0 /* no parity */ +#define _COM_ODDPARITY 8 /* odd parity */ +#define _COM_EVENPARITY 24 /* even parity */ + +/* baud rate initializers */ + +#define _COM_110 0 /* 110 baud */ +#define _COM_150 32 /* 150 baud */ +#define _COM_300 64 /* 300 baud */ +#define _COM_600 96 /* 600 baud */ +#define _COM_1200 128 /* 1200 baud */ +#define _COM_2400 160 /* 2400 baud */ +#define _COM_4800 192 /* 4800 baud */ +#define _COM_9600 224 /* 9600 baud */ + + +/* manifest constants for BIOS disk support */ + +/* disk services */ + +#define _DISK_RESET 0 /* reset disk controller */ +#define _DISK_STATUS 1 /* get disk status */ +#define _DISK_READ 2 /* read disk sectors */ +#define _DISK_WRITE 3 /* write disk sectors */ +#define _DISK_VERIFY 4 /* verify disk sectors */ +#define _DISK_FORMAT 5 /* format disk track */ + +/* struct used to send/receive information to/from the BIOS disk services */ + +#ifndef NO_EXT_KEYS /* extensions must be enabled */ + +#ifndef _DISKINFO_T_DEFINED + +struct diskinfo_t { + unsigned drive; + unsigned head; + unsigned track; + unsigned sector; + unsigned nsectors; + void far *buffer; + }; + +#define _DISKINFO_T_DEFINED + +#endif + +#endif /* NO_EXT_KEYS */ + + +/* manifest constants for BIOS keyboard support */ + +/* keyboard services */ + +#define _KEYBRD_READ 0 /* read next character from keyboard */ +#define _KEYBRD_READY 1 /* check for keystroke */ +#define _KEYBRD_SHIFTSTATUS 2 /* get current shift key status */ + + +/* manifest constants for BIOS printer support */ + +/* printer services */ + +#define _PRINTER_WRITE 0 /* write character to printer */ +#define _PRINTER_INIT 1 /* intialize printer */ +#define _PRINTER_STATUS 2 /* get printer status */ + + +/* manifest constants for BIOS time of day support */ + +/* time of day services */ + +#define _TIME_GETCLOCK 0 /* get current clock count */ +#define _TIME_SETCLOCK 1 /* set current clock count */ + + +#ifndef _REGS_DEFINED + +/* word registers */ + +struct WORDREGS { + unsigned int ax; + unsigned int bx; + unsigned int cx; + unsigned int dx; + unsigned int si; + unsigned int di; + unsigned int cflag; + }; + +/* byte registers */ + +struct BYTEREGS { + unsigned char al, ah; + unsigned char bl, bh; + unsigned char cl, ch; + unsigned char dl, dh; + }; + +/* general purpose registers union - + * overlays the corresponding word and byte registers. + */ + +union REGS { + struct WORDREGS x; + struct BYTEREGS h; + }; + +/* segment registers */ + +struct SREGS { + unsigned int es; + unsigned int cs; + unsigned int ss; + unsigned int ds; + }; + +#define _REGS_DEFINED + +#endif /* _REGS_DEFINED */ + + +/* function prototypes */ + +unsigned _CDECL _bios_equiplist(void); +unsigned _CDECL _bios_keybrd(unsigned); +unsigned _CDECL _bios_memsize(void); +unsigned _CDECL _bios_printer(unsigned, unsigned, unsigned); +unsigned _CDECL _bios_serialcom(unsigned, unsigned, unsigned); +unsigned _CDECL _bios_timeofday(unsigned, long *); +int _CDECL int86(int, union REGS *, union REGS *); +int _CDECL int86x(int, union REGS *, union REGS *, struct SREGS *); + +#ifndef NO_EXT_KEYS /* extensions must be enabled */ + +unsigned _CDECL _bios_disk(unsigned, struct diskinfo_t *); + +#endif /* NO_EXT_KEYS */ diff --git a/v4.0/src/TOOLS/BLD/INC/CONIO.H b/v4.0/src/TOOLS/BLD/INC/CONIO.H new file mode 100644 index 0000000..7941e2e --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/CONIO.H @@ -0,0 +1,34 @@ +/*** +*conio.h - console and port I/O declarations +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This include file contains the function declarations for +* the MS C V2.03 compatible console and port I/O routines. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +/* function prototypes */ + +char * _CDECL cgets(char *); +int _CDECL cprintf(char *, ...); +int _CDECL cputs(char *); +int _CDECL cscanf(char *, ...); +int _CDECL getch(void); +int _CDECL getche(void); +int _CDECL inp(unsigned int); +unsigned _CDECL inpw(unsigned int); +int _CDECL kbhit(void); +int _CDECL outp(unsigned int, int); +unsigned _CDECL outpw(unsigned int, unsigned int); +int _CDECL putch(int); +int _CDECL ungetch(int); + diff --git a/v4.0/src/TOOLS/BLD/INC/CTYPE.H b/v4.0/src/TOOLS/BLD/INC/CTYPE.H new file mode 100644 index 0000000..c65d021 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/CTYPE.H @@ -0,0 +1,66 @@ +/*** +*ctype.h - character conversion macros and ctype macros +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines macros for character classification/conversion. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + +/* + * This declaration allows the user access to the ctype look-up + * array _ctype defined in ctype.obj by simply including ctype.h + */ + +extern unsigned char _NEAR _CDECL _ctype[]; + +/* set bit masks for the possible character types */ + +#define _UPPER 0x1 /* upper case letter */ +#define _LOWER 0x2 /* lower case letter */ +#define _DIGIT 0x4 /* digit[0-9] */ +#define _SPACE 0x8 /* tab, carriage return, newline, */ + /* vertical tab or form feed */ +#define _PUNCT 0x10 /* punctuation character */ +#define _CONTROL 0x20 /* control character */ +#define _BLANK 0x40 /* space char */ +#define _HEX 0x80 /* hexadecimal digit */ + +/* the character classification macro definitions */ + +#define isalpha(c) ( (_ctype+1)[c] & (_UPPER|_LOWER) ) +#define isupper(c) ( (_ctype+1)[c] & _UPPER ) +#define islower(c) ( (_ctype+1)[c] & _LOWER ) +#define isdigit(c) ( (_ctype+1)[c] & _DIGIT ) +#define isxdigit(c) ( (_ctype+1)[c] & _HEX ) +#define isspace(c) ( (_ctype+1)[c] & _SPACE ) +#define ispunct(c) ( (_ctype+1)[c] & _PUNCT ) +#define isalnum(c) ( (_ctype+1)[c] & (_UPPER|_LOWER|_DIGIT) ) +#define isprint(c) ( (_ctype+1)[c] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT) ) +#define isgraph(c) ( (_ctype+1)[c] & (_PUNCT|_UPPER|_LOWER|_DIGIT) ) +#define iscntrl(c) ( (_ctype+1)[c] & _CONTROL ) + +#define toupper(c) ( (islower(c)) ? _toupper(c) : (c) ) +#define tolower(c) ( (isupper(c)) ? _tolower(c) : (c) ) + +#define _tolower(c) ( (c)-'A'+'a' ) +#define _toupper(c) ( (c)-'a'+'A' ) + +#define isascii(c) ( (unsigned)(c) < 0x80 ) +#define toascii(c) ( (c) & 0x7f ) + +/* MS C version 2.0 extended ctype macros */ + +#define iscsymf(c) (isalpha(c) || ((c) == '_')) +#define iscsym(c) (isalnum(c) || ((c) == '_')) diff --git a/v4.0/src/TOOLS/BLD/INC/DIRECT.H b/v4.0/src/TOOLS/BLD/INC/DIRECT.H new file mode 100644 index 0000000..2e2ebde --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/DIRECT.H @@ -0,0 +1,24 @@ +/*** +*direct.h - function declarations for directory handling/creation +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This include file contains the function declarations for the library +* functions related to directory handling and creation. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +/* function prototypes */ + +int _CDECL chdir(char *); +char * _CDECL getcwd(char *, int); +int _CDECL mkdir(char *); +int _CDECL rmdir(char *); diff --git a/v4.0/src/TOOLS/BLD/INC/DOS.H b/v4.0/src/TOOLS/BLD/INC/DOS.H new file mode 100644 index 0000000..5539156 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/DOS.H @@ -0,0 +1,220 @@ +/*** +*dos.h - definitions for MS-DOS interface routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines the structs and unions used for the direct DOS interface +* routines; includes macros to access the segment and offset +* values of far pointers, so that they may be used by the routines; and +* provides function prototypes for direct DOS interface functions. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +#ifndef _REGS_DEFINED + +/* word registers */ + +struct WORDREGS { + unsigned int ax; + unsigned int bx; + unsigned int cx; + unsigned int dx; + unsigned int si; + unsigned int di; + unsigned int cflag; + }; + + +/* byte registers */ + +struct BYTEREGS { + unsigned char al, ah; + unsigned char bl, bh; + unsigned char cl, ch; + unsigned char dl, dh; + }; + + +/* general purpose registers union - + * overlays the corresponding word and byte registers. + */ + +union REGS { + struct WORDREGS x; + struct BYTEREGS h; + }; + + +/* segment registers */ + +struct SREGS { + unsigned int es; + unsigned int cs; + unsigned int ss; + unsigned int ds; + }; + +#define _REGS_DEFINED + +#endif + + +/* dosexterror structure */ + +#ifndef _DOSERROR_DEFINED + +struct DOSERROR { + int exterror; + char class; + char action; + char locus; + }; + +#define _DOSERROR_DEFINED + +#endif + + +/* _dos_findfirst structure */ + +#ifndef _FIND_T_DEFINED + +struct find_t { + char reserved[21]; + char attrib; + unsigned wr_time; + unsigned wr_date; + long size; + char name[13]; + }; + +#define _FIND_T_DEFINED + +#endif + + +/* _dos_getdate/_dossetdate and _dos_gettime/_dos_settime structures */ + +#ifndef _DATETIME_T_DEFINED + +struct dosdate_t { + unsigned char day; /* 1-31 */ + unsigned char month; /* 1-12 */ + unsigned int year; /* 1980-2099 */ + unsigned char dayofweek; /* 0-6, 0=Sunday */ + }; + +struct dostime_t { + unsigned char hour; /* 0-23 */ + unsigned char minute; /* 0-59 */ + unsigned char second; /* 0-59 */ + unsigned char hsecond; /* 0-99 */ + }; + +#define _DATETIME_T_DEFINED + +#endif + + +/* _dos_getdiskfree structure */ + +#ifndef _DISKFREE_T_DEFINED + +struct diskfree_t { + unsigned total_clusters; + unsigned avail_clusters; + unsigned sectors_per_cluster; + unsigned bytes_per_sector; + }; + +#define _DISKFREE_T_DEFINED + +#endif + + +/* manifest constants for _hardresume result parameter */ + +#define _HARDERR_IGNORE 0 /* Ignore the error */ +#define _HARDERR_RETRY 1 /* Retry the operation */ +#define _HARDERR_ABORT 2 /* Abort program issuing Interrupt 23h */ +#define _HARDERR_FAIL 3 /* Fail the system call in progress */ + /* _HARDERR_FAIL is not supported on DOS 2.x */ + +/* File attribute constants */ + +#define _A_NORMAL 0x00 /* Normal file - No read/write restrictions */ +#define _A_RDONLY 0x01 /* Read only file */ +#define _A_HIDDEN 0x02 /* Hidden file */ +#define _A_SYSTEM 0x04 /* System file */ +#define _A_VOLID 0x08 /* Volume ID file */ +#define _A_SUBDIR 0x10 /* Subdirectory */ +#define _A_ARCH 0x20 /* Archive file */ + +/* macros to break MS C "far" pointers into their segment and offset + * components + */ + +#define FP_SEG(fp) (*((unsigned *)&(fp) + 1)) +#define FP_OFF(fp) (*((unsigned *)&(fp))) + + +/* external variable declarations */ + +extern unsigned int _NEAR _CDECL _osversion; + + +/* function prototypes */ + +int _CDECL bdos(int, unsigned int, unsigned int); +void _CDECL _disable(void); +unsigned _CDECL _dos_allocmem(unsigned, unsigned *); +unsigned _CDECL _dos_close(int); +unsigned _CDECL _dos_creat(char *, unsigned, int *); +unsigned _CDECL _dos_creatnew(char *, unsigned, int *); +unsigned _CDECL _dos_findfirst(char *, unsigned, struct find_t *); +unsigned _CDECL _dos_findnext(struct find_t *); +unsigned _CDECL _dos_freemem(unsigned); +void _CDECL _dos_getdate(struct dosdate_t *); +void _CDECL _dos_getdrive(unsigned *); +unsigned _CDECL _dos_getdiskfree(unsigned, struct diskfree_t *); +unsigned _CDECL _dos_getfileattr(char *, unsigned *); +unsigned _CDECL _dos_getftime(int, unsigned *, unsigned *); +void _CDECL _dos_gettime(struct dostime_t *); +void _CDECL _dos_keep(unsigned, unsigned); +unsigned _CDECL _dos_open(char *, unsigned, int *); +unsigned _CDECL _dos_setblock(unsigned, unsigned, unsigned *); +unsigned _CDECL _dos_setdate(struct dosdate_t *); +void _CDECL _dos_setdrive(unsigned, unsigned *); +unsigned _CDECL _dos_setfileattr(char *, unsigned); +unsigned _CDECL _dos_setftime(int, unsigned, unsigned); +unsigned _CDECL _dos_settime(struct dostime_t *); +int _CDECL dosexterr(struct DOSERROR *); +void _CDECL _enable(void); +void _CDECL _hardresume(int); +void _CDECL _hardretn(int); +int _CDECL intdos(union REGS *, union REGS *); +int _CDECL intdosx(union REGS *, union REGS *, struct SREGS *); +int _CDECL int86(int, union REGS *, union REGS *); +int _CDECL int86x(int, union REGS *, union REGS *, struct SREGS *); +void _CDECL segread(struct SREGS *); + + +#ifndef NO_EXT_KEYS /* extensions enabled */ +void _CDECL _chain_intr(void (_CDECL interrupt far *)()); +void (_CDECL interrupt far * _CDECL _dos_getvect(unsigned))(); +unsigned _CDECL _dos_read(int, void far *, unsigned, unsigned *); +void _CDECL _dos_setvect(unsigned, void (_CDECL interrupt far *)()); +unsigned _CDECL _dos_write(int, void far *, unsigned, unsigned *); +void _CDECL _harderr(void (far *)()); +#endif /* NO_EXT_KEYS */ diff --git a/v4.0/src/TOOLS/BLD/INC/ERRNO.H b/v4.0/src/TOOLS/BLD/INC/ERRNO.H new file mode 100644 index 0000000..0925338 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/ERRNO.H @@ -0,0 +1,50 @@ +/*** +*errno.h - system wide error numbers (set by system calls) +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the system-wide error numbers (set by +* system calls). Conforms to the XENIX standard. Extended +* for compatibility with Uniforum standard. +* [System V] +* +*******************************************************************************/ + +#define EZERO 0 +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EUCLEAN 35 +#define EDEADLOCK 36 diff --git a/v4.0/src/TOOLS/BLD/INC/FCNTL.H b/v4.0/src/TOOLS/BLD/INC/FCNTL.H new file mode 100644 index 0000000..08ad549 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/FCNTL.H @@ -0,0 +1,35 @@ +/*** +*fcntl.h - file control options used by open() +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines constants for the file control options used +* by the open() function. +* [System V] +* +*******************************************************************************/ + +#define O_RDONLY 0x0000 /* open for reading only */ +#define O_WRONLY 0x0001 /* open for writing only */ +#define O_RDWR 0x0002 /* open for reading and writing */ +#define O_APPEND 0x0008 /* writes done at eof */ + +#define O_CREAT 0x0100 /* create and open file */ +#define O_TRUNC 0x0200 /* open and truncate */ +#define O_EXCL 0x0400 /* open only if file doesn't already exist */ + +/* O_TEXT files have sequences translated to on read()'s, +** and sequences translated to on write()'s +*/ + +#define O_TEXT 0x4000 /* file mode is text (translated) */ +#define O_BINARY 0x8000 /* file mode is binary (untranslated) */ + +/* macro to translate the C 2.0 name used to force binary mode for files */ + +#define O_RAW O_BINARY + +/* Open handle inherit bit */ + +#define O_NOINHERIT 0x0080 /* child process doesn't inherit file */ diff --git a/v4.0/src/TOOLS/BLD/INC/FLOAT.H b/v4.0/src/TOOLS/BLD/INC/FLOAT.H new file mode 100644 index 0000000..2d73f85 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/FLOAT.H @@ -0,0 +1,137 @@ +/*** +*float.h - constants for floating point values +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains defines for a number of implementation dependent +* values which are commonly used by sophisticated numerical (floating +* point) programs. +* [ANSI] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +#define DBL_DIG 15 /* # of decimal digits of precision */ +#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */ +#define DBL_MANT_DIG 53 /* # of bits in mantissa */ +#define DBL_MAX 1.7976931348623158e+308 /* max value */ +#define DBL_MAX_10_EXP 308 /* max decimal exponent */ +#define DBL_MAX_EXP 1024 /* max binary exponent */ +#define DBL_MIN 2.2250738585072014e-308 /* min positive value */ +#define DBL_MIN_10_EXP -307 /* min decimal exponent +#define DBL_MIN_EXP -1021 /* min binary exponent */ +#define DBL_RADIX 2 /* exponent radix */ +#define DBL_ROUNDS 0 /* addition rounding: chops */ + +#define FLT_DIG 6 /* # of decimal digits of precision */ +#define FLT_EPSILON 1.192092896e-07 /* smallest such that 1.0+FLT_EPSILON != 1.0 */ +#define FLT_GUARD 0 +#define FLT_MANT_DIG 24 /* # of bits in mantissa */ +#define FLT_MAX 3.402823466e+38 /* max value */ +#define FLT_MAX_10_EXP 38 /* max decimal exponent */ +#define FLT_MAX_EXP 128 /* max binary exponent */ +#define FLT_MIN 1.175494351e-38 /* min positive value */ +#define FLT_MIN_10_EXP -37 /* min decimal exponent */ +#define FLT_MIN_EXP -125 /* min binary exponent */ +#define FLT_NORMALIZE 0 +#define FLT_RADIX 2 /* exponent radix */ +#define FLT_ROUNDS 0 /* addition rounding: chops */ + +#define LDBL_DIG DBL_DIG /* # of decimal digits of precision */ +#define LDBL_EPSILON DBL_EPSILON /* smallest such that 1.0+LDBL_EPSILON != 1.0 */ +#define LDBL_MANT_DIG DBL_MANT_DIG /* # of bits in mantissa */ +#define LDBL_MAX DBL_MAX /* max value */ +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP /* max decimal exponent */ +#define LDBL_MAX_EXP DBL_MAX_EXP /* max binary exponent */ +#define LDBL_MIN DBL_MIN /* min positive value */ +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP /* min deimal exponent +#define LDBL_MIN_EXP DBL_MIN_EXP /* min binary exponent */ +#define LDBL_RADIX DBL_RADIX /* exponent radix */ +#define LDBL_ROUNDS DBL_ROUNDS /* addition rounding: chops */ + + +/* + * 8087/80287 math control information + */ + + +/* User Control Word Mask and bit definitions. + * These definitions match the 8087/80287 + */ + +#define MCW_EM 0x003f /* interrupt Exception Masks */ +#define EM_INVALID 0x0001 /* invalid */ +#define EM_DENORMAL 0x0002 /* denormal */ +#define EM_ZERODIVIDE 0x0004 /* zero divide */ +#define EM_OVERFLOW 0x0008 /* overflow */ +#define EM_UNDERFLOW 0x0010 /* underflow */ +#define EM_INEXACT 0x0020 /* inexact (precision) */ + +#define MCW_IC 0x1000 /* Infinity Control */ +#define IC_AFFINE 0x1000 /* affine */ +#define IC_PROJECTIVE 0x0000 /* projective */ + +#define MCW_RC 0x0c00 /* Rounding Control */ +#define RC_CHOP 0x0c00 /* chop */ +#define RC_UP 0x0800 /* up */ +#define RC_DOWN 0x0400 /* down */ +#define RC_NEAR 0x0000 /* near */ + +#define MCW_PC 0x0300 /* Precision Control */ +#define PC_24 0x0000 /* 24 bits */ +#define PC_53 0x0200 /* 53 bits */ +#define PC_64 0x0300 /* 64 bits */ + + +/* initial Control Word value */ + +#define CW_DEFAULT ( IC_AFFINE + RC_NEAR + PC_64 + EM_DENORMAL + EM_UNDERFLOW + EM_INEXACT ) + + +/* user Status Word bit definitions */ + +#define SW_INVALID 0x0001 /* invalid */ +#define SW_DENORMAL 0x0002 /* denormal */ +#define SW_ZERODIVIDE 0x0004 /* zero divide */ +#define SW_OVERFLOW 0x0008 /* overflow */ +#define SW_UNDERFLOW 0x0010 /* underflow */ +#define SW_INEXACT 0x0020 /* inexact (precision) */ + + +/* invalid subconditions (SW_INVALID also set) */ + +#define SW_UNEMULATED 0x0040 /* unemulated instruction */ +#define SW_SQRTNEG 0x0080 /* square root of a neg number */ +#define SW_STACKOVERFLOW 0x0200 /* FP stack overflow */ +#define SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */ + + +/* Floating point error signals and return codes */ + +#define FPE_INVALID 0x81 +#define FPE_DENORMAL 0x82 +#define FPE_ZERODIVIDE 0x83 +#define FPE_OVERFLOW 0x84 +#define FPE_UNDERFLOW 0x85 +#define FPE_INEXACT 0x86 + +#define FPE_UNEMULATED 0x87 +#define FPE_SQRTNEG 0x88 +#define FPE_STACKOVERFLOW 0x8a +#define FPE_STACKUNDERFLOW 0x8b + +#define FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */ + +/* function prototypes */ + +unsigned int _CDECL _clear87(void); +unsigned int _CDECL _control87(unsigned int,unsigned int); +void _CDECL _fpreset(void); +unsigned int _CDECL _status87(void); diff --git a/v4.0/src/TOOLS/BLD/INC/GRAPH.H b/v4.0/src/TOOLS/BLD/INC/GRAPH.H new file mode 100644 index 0000000..7b69c51 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/GRAPH.H @@ -0,0 +1,216 @@ +/*** +*graph.h - declare constants and functions for graphics library +* +* Copyright (c) 1987-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file declares the graphics library functions and +* the manifest constants that are used with them. +* +*******************************************************************************/ + +/* user-visible declarations for Quick-C Graphics Library */ + +#ifndef _GRAPH_T_DEFINED + +/* structure for _getvideoconfig() as visible to user */ +struct videoconfig { + short numxpixels; /* number of pixels on X axis */ + short numypixels; /* number of pixels on Y axis */ + short numtextcols; /* number of text columns available */ + short numtextrows; /* number of text rows available */ + short numcolors; /* number of actual colors */ + short bitsperpixel; /* number of bits per pixel */ + short numvideopages; /* number of available video pages */ + short mode; /* current video mode */ + short adapter; /* active display adapter */ + short monitor; /* active display monitor */ + short memory; /* adapter video memory in K bytes */ +}; + +/* return value of _setlogorg(), etc. */ +struct xycoord { + short xcoord; + short ycoord; +}; + +/* structure for text position */ +struct rccoord { + short row; + short col; +}; + +#define _GRAPH_T_DEFINED + +#endif + + +/* SETUP AND CONFIGURATION */ + +short far cdecl _setvideomode(short); + +/* arguments to _setvideomode() */ +#define _DEFAULTMODE -1 /* restore screen to original mode */ +#define _TEXTBW40 0 /* 40 x 25 text, 16 grey */ +#define _TEXTC40 1 /* 40 x 25 text, 16/8 color */ +#define _TEXTBW80 2 /* 80 x 25 text, 16 grey */ +#define _TEXTC80 3 /* 80 x 25 text, 16/8 color */ +#define _MRES4COLOR 4 /* 320 x 200, 4 color */ +#define _MRESNOCOLOR 5 /* 320 x 200, 4 grey */ +#define _HRESBW 6 /* 640 x 200, BW */ +#define _TEXTMONO 7 /* 80 x 25 text, BW */ +#define _HERCMONO 8 /* 720 x 348, BW for HGC */ +#define _MRES16COLOR 13 /* 320 x 200, 16 color */ +#define _HRES16COLOR 14 /* 640 x 200, 16 color */ +#define _ERESNOCOLOR 15 /* 640 x 350, BW */ +#define _ERESCOLOR 16 /* 640 x 350, 4 or 16 color */ +#define _VRES2COLOR 17 /* 640 x 480, BW */ +#define _VRES16COLOR 18 /* 640 x 480, 16 color */ +#define _MRES256COLOR 19 /* 320 x 200, 256 color */ + +short far cdecl _setactivepage(short); +short far cdecl _setvisualpage(short); + +/* videoconfig adapter values */ +/* these manifest constants can be used to determine the type of monitor in */ +/* use, using either simple comparisons or the bitwise-AND operator (&) */ +#define _MDPA 0x0001 /* Monochrome Display Adapter (MDPA) */ +#define _CGA 0x0002 /* Color Graphics Adapter (CGA) */ +#define _EGA 0x0004 /* Enhanced Graphics Adapter (EGA) */ +#define _VGA 0x0008 /* Video Graphics Array (VGA) */ +#define _MCGA 0x0010 /* MultiColor Graphics Array (MCGA) */ +#define _HGC 0x0020 /* Hercules Graphics Card (HGC) */ + +/* videoconfig monitor values */ +/* these manifest constants can be used to determine the type of the active */ +/* adapter, using either simple comparisons or the bitwise-AND operator (&) */ +#define _MONO 0x0001 /* Monochrome */ +#define _COLOR 0x0002 /* Color (or Enhanced emulating color) */ +#define _ENHCOLOR 0x0004 /* Enhanced Color */ +#define _ANALOG 0x0018 /* Analog */ + +struct videoconfig far * far cdecl _getvideoconfig(struct videoconfig far *); + + +/* COORDINATE SYSTEMS */ + +struct xycoord far cdecl _setlogorg(short, short); +struct xycoord far cdecl _getlogcoord(short, short); +struct xycoord far cdecl _getphyscoord(short, short); + +void far cdecl _setcliprgn(short, short, short, short); +void far cdecl _setviewport(short, short, short, short); + + +/* OUTPUT ROUTINES */ + +/* control parameters for Rectangle, Ellipse and Pie */ +#define _GBORDER 2 /* draw outline only */ +#define _GFILLINTERIOR 3 /* fill using current fill mask */ + +#define _GCLEARSCREEN 0 +#define _GVIEWPORT 1 +#define _GWINDOW 2 + +void far cdecl _clearscreen(short); + +struct xycoord far cdecl _moveto(short, short); +struct xycoord far cdecl _getcurrentposition(void); + +short far cdecl _lineto(short, short); +short far cdecl _rectangle(short, short, short, short, short); +short far cdecl _ellipse(short, short, short, short, short); +short far cdecl _arc(short, short, short, short, short, short, short, short); +short far cdecl _pie(short, short, short, short, short, short, short, short, short); + +short far cdecl _setpixel(short, short); +short far cdecl _getpixel(short, short); +short far cdecl _floodfill(short, short, short); + + +/* PEN COLOR, LINE STYLE, FILL PATTERN */ + +short far cdecl _setcolor(short); +short far cdecl _getcolor(void); + +void far cdecl _setlinestyle(unsigned short); +unsigned short far cdecl _getlinestyle(void); + +void far cdecl _setfillmask(unsigned char far *); +unsigned char far * far cdecl _getfillmask(unsigned char far *); + +/* COLOR SELECTION */ + +long far cdecl _setbkcolor(long); +long far cdecl _getbkcolor(void); + +long far cdecl _remappalette(short, long); +short far cdecl _remapallpalette(long far *); +short far cdecl _selectpalette(short); + + +/* TEXT */ +#define _GCURSOROFF 0 +#define _GCURSORON 1 + +#define _GWRAPOFF 0 +#define _GWRAPON 1 + +void far cdecl _settextwindow(short, short, short, short); +void far cdecl _outtext(char far *); +short far cdecl _wrapon(short); +short far cdecl _displaycursor(short); + +struct rccoord far cdecl _settextposition(short, short); +struct rccoord far cdecl _gettextposition(void); + +short far cdecl _settextcolor(short); +short far cdecl _gettextcolor(void); + + +/* SCREEN IMAGES */ + +void far cdecl _getimage(short, short, short, short, char far *); +void far cdecl _putimage(short, short, char far *, short); +long far cdecl _imagesize(short, short, short, short); + +/* "action verbs" for _putimage() */ +#define _GPSET 3 +#define _GPRESET 2 +#define _GAND 1 +#define _GOR 0 +#define _GXOR 4 + +/* universal color values: */ +#define _BLACK 0x000000L +#define _BLUE 0x2a0000L +#define _GREEN 0x002a00L +#define _CYAN 0x2a2a00L +#define _RED 0x00002aL +#define _MAGENTA 0x2a002aL +#define _BROWN 0x00152aL +#define _WHITE 0x2a2a2aL +#define _GRAY 0x151515L +#define _LIGHTBLUE 0x3F1515L +#define _LIGHTGREEN 0x153f15L +#define _LIGHTCYAN 0x3f3f15L +#define _LIGHTRED 0x15153fL +#define _LIGHTMAGENTA 0x3f153fL +#define _LIGHTYELLOW 0x153f3fL +#define _BRIGHTWHITE 0x3f3f3fL + +/* mono mode F color values: */ +#define _MODEFOFF 0L +#define _MODEFOFFTOON 1L +#define _MODEFOFFTOHI 2L +#define _MODEFONTOOFF 3L +#define _MODEFON 4L +#define _MODEFONTOHI 5L +#define _MODEFHITOOFF 6L +#define _MODEFHITOON 7L +#define _MODEFHI 8L + +/* mono mode 7 color values: */ +#define _MODE7OFF 0L +#define _MODE7ON 1L +#define _MODE7HI 2L diff --git a/v4.0/src/TOOLS/BLD/INC/IO.H b/v4.0/src/TOOLS/BLD/INC/IO.H new file mode 100644 index 0000000..7261295 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/IO.H @@ -0,0 +1,43 @@ +/*** +*io.h - declarations for low-level file handling and I/O functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains the function declarations for the low-level +* file handling and I/O functions. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +/* function prototypes */ + +int _CDECL access(char *, int); +int _CDECL chmod(char *, int); +int _CDECL chsize(int, long); +int _CDECL close(int); +int _CDECL creat(char *, int); +int _CDECL dup(int); +int _CDECL dup2(int, int); +int _CDECL eof(int); +long _CDECL filelength(int); +int _CDECL isatty(int); +int _CDECL locking(int, int, long); +long _CDECL lseek(int, long, int); +char * _CDECL mktemp(char *); +int _CDECL open(char *, int, ...); +int _CDECL read(int, char *, unsigned int); +int _CDECL remove(const char *); +int _CDECL rename(const char *, const char *); +int _CDECL setmode(int, int); +int _CDECL sopen(char *, int, int, ...); +long _CDECL tell(int); +int _CDECL umask(int); +int _CDECL unlink(const char *); +int _CDECL write(int, char *, unsigned int); diff --git a/v4.0/src/TOOLS/BLD/INC/LIMITS.H b/v4.0/src/TOOLS/BLD/INC/LIMITS.H new file mode 100644 index 0000000..21e907f --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/LIMITS.H @@ -0,0 +1,32 @@ +/*** +*limits.h - implementation dependent values +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains defines for a number of implementation dependent values +* which are commonly used in C programs. +* [ANSI] +* +*******************************************************************************/ + +#ifndef _CHAR_UNSIGNED +#define CHAR_MAX 127 /* maximum char value */ +#define CHAR_MIN -127 /* mimimum char value */ +#else +#define CHAR_MAX 255 +#define CHAR_MIN 0 +#endif +#define SCHAR_MAX 127 /* maximum signed char value */ +#define SCHAR_MIN -127 /* minimum signed char value */ +#define UCHAR_MAX 255 /* maximum unsigned char value */ +#define CHAR_BIT 8 /* number of bits in a char */ +#define USHRT_MAX 0xffff /* maximum unsigned short value */ +#define SHRT_MAX 32767 /* maximum (signed) short value */ +#define SHRT_MIN -32767 /* minimum (signed) short value */ +#define UINT_MAX 0xffff /* maximum unsigned int value */ +#define ULONG_MAX 0xffffffff /* maximum unsigned long value */ +#define INT_MAX 32767 /* maximum (signed) int value */ +#define INT_MIN -32767 /* minimum (signed) int value */ +#define LONG_MAX 2147483647 /* maximum (signed) long value */ +#define LONG_MIN -2147483647 /* minimum (signed) long value */ diff --git a/v4.0/src/TOOLS/BLD/INC/MALLOC.H b/v4.0/src/TOOLS/BLD/INC/MALLOC.H new file mode 100644 index 0000000..e2aa979 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/MALLOC.H @@ -0,0 +1,124 @@ +/*** +*malloc.h - declarations and definitions for memory allocation functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Contains the function declarations for memory allocation functions; +* also defines manifest constants and types used by the heap routines. +* [System V] +* +*******************************************************************************/ + + +#define _HEAPEMPTY -1 +#define _HEAPOK -2 +#define _HEAPBADBEGIN -3 +#define _HEAPBADNODE -4 +#define _HEAPEND -5 +#define _HEAPBADPTR -6 +#define _FREEENTRY 0 +#define _USEDENTRY 1 + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#if (!defined(NO_EXT_KEYS)) + +#ifndef _HEAPINFO_DEFINED +typedef struct _heapinfo { + int far * _pentry; + size_t _size; + int _useflag; + } _HEAPINFO; +#define _HEAPINFO_DEFINED +#endif + +#else /* NO_EXT_KEYS */ +#if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) + +#ifndef _HEAPINFO_DEFINED + +typedef struct _heapinfo { + int * _pentry; + size_t _size; + int _useflag; + } _HEAPINFO; + +#define _HEAPINFO_DEFINED +#endif + +#endif /* M_I86CM || M_I86LM || M_I86HM */ + +#endif /* NO_EXT_KEYS */ + + +#if (defined(M_I86SM) || defined(M_I86MM)) +#define _heapchk _nheapchk +#define _heapset _nheapset +#define _heapwalk _nheapwalk +#endif +#if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) +#define _heapchk _fheapchk +#define _heapset _fheapset +#define _heapwalk _fheapwalk +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* external variable declarations */ +extern unsigned int _NEAR _CDECL _amblksiz; + +/* function prototypes */ + +void * _CDECL alloca(size_t); +void * _CDECL calloc(size_t, size_t); +void * _CDECL _expand(void *, size_t); +int _CDECL _fheapchk(void); +int _CDECL _fheapset(unsigned int); +unsigned int _CDECL _freect(size_t); +void _CDECL free(void *); +void * _CDECL malloc(size_t); +size_t _CDECL _memavl(void); +size_t _CDECL _memmax(void); +size_t _CDECL _msize(void *); +int _CDECL _nheapchk(void); +int _CDECL _nheapset(unsigned int); +void * _CDECL realloc(void *, size_t); +void * _CDECL sbrk(int); +size_t _CDECL stackavail(void); + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + +void cdecl _ffree(void far *); +void far * cdecl _fmalloc(size_t); +size_t cdecl _fmsize(void far *); +#ifndef _QC +void huge * cdecl halloc(long, size_t); +void cdecl hfree(void huge *); +#endif +void cdecl _nfree(void near *); +void near * cdecl _nmalloc(size_t); +size_t cdecl _nmsize(void near *); +int cdecl _nheapwalk(struct _heapinfo *); +int cdecl _fheapwalk(struct _heapinfo *); + +#else +#if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) + +int _nheapwalk(struct _heapinfo *); +int _fheapwalk(struct _heapinfo *); + +#endif /* M_I86CM || M_I86LM || M_I86HM */ + +#endif /* NO_EXT_KEYS */ diff --git a/v4.0/src/TOOLS/BLD/INC/MATH.H b/v4.0/src/TOOLS/BLD/INC/MATH.H new file mode 100644 index 0000000..9c0e701 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/MATH.H @@ -0,0 +1,112 @@ +/*** +*math.h - definitions and declarations for math library +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains constant definitions and external subroutine +* declarations for the math subroutine library. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + + +/* definition of exception struct - this struct is passed to the matherr + * routine when a floating point exception is detected + */ + +#ifndef _EXCEPTION_DEFINED +struct exception { + int type; /* exception type - see below */ + char *name; /* name of function where error occured */ + double arg1; /* first argument to function */ + double arg2; /* second argument (if any) to function */ + double retval; /* value to be returned by function */ + } ; +#define _EXCEPTION_DEFINED +#endif + + +/* definition of a complex struct to be used by those who use cabs and + * want type checking on their argument + */ + +#ifndef _COMPLEX_DEFINED +struct complex { + double x,y; /* real and imaginary parts */ + } ; +#define _COMPLEX_DEFINED +#endif + + +/* Constant definitions for the exception type passed in the exception struct + */ + +#define DOMAIN 1 /* argument domain error */ +#define SING 2 /* argument singularity */ +#define OVERFLOW 3 /* overflow range error */ +#define UNDERFLOW 4 /* underflow range error */ +#define TLOSS 5 /* total loss of precision */ +#define PLOSS 6 /* partial loss of precision */ + +#define EDOM 33 +#define ERANGE 34 + + +/* definitions of HUGE and HUGE_VAL - respectively the XENIX and ANSI names + * for a value returned in case of error by a number of the floating point + * math routines + */ + +extern double HUGE; +#define HUGE_VAL HUGE + + + +/* function prototypes */ + +int _CDECL abs(int); +double _CDECL acos(double); +double _CDECL asin(double); +double _CDECL atan(double); +double _CDECL atan2(double, double); +double _CDECL atof(const char *); +double _CDECL cabs(struct complex); +double _CDECL ceil(double); +double _CDECL cos(double); +double _CDECL cosh(double); +int _CDECL dieeetomsbin(double *, double *); +int _CDECL dmsbintoieee(double *, double *); +double _CDECL exp(double); +double _CDECL fabs(double); +int _CDECL fieeetomsbin(float *, float *); +double _CDECL floor(double); +double _CDECL fmod(double, double); +int _CDECL fmsbintoieee(float *, float *); +double _CDECL frexp(double, int *); +double _CDECL hypot(double, double); +double _CDECL j0(double); +double _CDECL j1(double); +double _CDECL jn(int, double); +long _CDECL labs(long); +double _CDECL ldexp(double, int); +double _CDECL log(double); +double _CDECL log10(double); +int _CDECL matherr(struct exception *); +double _CDECL modf(double, double *); +double _CDECL pow(double, double); +double _CDECL sin(double); +double _CDECL sinh(double); +double _CDECL sqrt(double); +double _CDECL tan(double); +double _CDECL tanh(double); +double _CDECL y0(double); +double _CDECL y1(double); +double _CDECL yn(int, double); diff --git a/v4.0/src/TOOLS/BLD/INC/MEMORY.H b/v4.0/src/TOOLS/BLD/INC/MEMORY.H new file mode 100644 index 0000000..519b71d --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/MEMORY.H @@ -0,0 +1,34 @@ +/*** +*memory.h - declarations for buffer (memory) manipulation routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This include file contains the function declarations for the +* buffer (memory) manipulation routines. +* [System V] +* +*******************************************************************************/ + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + + +/* function prototypes */ + +void * _CDECL memccpy(void *, void *, int, unsigned int); +void * _CDECL memchr(const void *, int, size_t); +int _CDECL memcmp(const void *, const void *, size_t); +void * _CDECL memcpy(void *, const void *, size_t); +int _CDECL memicmp(void *, void *, unsigned int); +void * _CDECL memset(void *, int, size_t); +void _CDECL movedata(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); diff --git a/v4.0/src/TOOLS/BLD/INC/PROCESS.H b/v4.0/src/TOOLS/BLD/INC/PROCESS.H new file mode 100644 index 0000000..f0c85f3 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/PROCESS.H @@ -0,0 +1,65 @@ +/*** +*process.h - definition and declarations for process control functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the modeflag values for spawnxx calls. Only +* P_WAIT and P_OVERLAY are currently implemented on DOS 2 & 3. +* P_NOWAIT is also enabled on DOS 4. Also contains the function +* argument declarations for all process control related routines. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* modeflag values for spawnxx routines */ + +extern int _NEAR _CDECL _p_overlay; + +#define P_WAIT 0 +#define P_NOWAIT 1 +#define P_OVERLAY _p_overlay +#define OLD_P_OVERLAY 2 +#define P_NOWAITO 3 + + +/* Action Codes used with Cwait() */ + +#define WAIT_CHILD 0 +#define WAIT_GRANDCHILD 1 + + +/* function prototypes */ + +void _CDECL abort(void); +int _CDECL cwait(int *, int, int); +int _CDECL execl(char *, char *, ...); +int _CDECL execle(char *, char *, ...); +int _CDECL execlp(char *, char *, ...); +int _CDECL execlpe(char *, char *, ...); +int _CDECL execv(char *, char * *); +int _CDECL execve(char *, char * *, char * *); +int _CDECL execvp(char *, char * *); +int _CDECL execvpe(char *, char * *, char * *); +void _CDECL exit(int); +void _CDECL _exit(int); +int _CDECL getpid(void); +int _CDECL spawnl(int, char *, char *, ...); +int _CDECL spawnle(int, char *, char *, ...); +int _CDECL spawnlp(int, char *, char *, ...); +int _CDECL spawnlpe(int, char *, char *, ...); +int _CDECL spawnv(int, char *, char * *); +int _CDECL spawnve(int, char *, char * *, char * *); +int _CDECL spawnvp(int, char *, char * *); +int _CDECL spawnvpe(int, char *, char * *, char * *); +int _CDECL system(const char *); +int _CDECL wait(int *); diff --git a/v4.0/src/TOOLS/BLD/INC/SEARCH.H b/v4.0/src/TOOLS/BLD/INC/SEARCH.H new file mode 100644 index 0000000..88ea976 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SEARCH.H @@ -0,0 +1,31 @@ +/*** +*search.h - declarations for searcing/sorting routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains the declarations for the sorting and +* searching routines. +* [System V] +* +*******************************************************************************/ + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + + +/* function prototypes */ + +char * _CDECL lsearch(char *, char *, unsigned int *, unsigned int, int (_CDECL *)(void *, void *)); +char * _CDECL lfind(char *, char *, unsigned int *, unsigned int, int (_CDECL *)(void *, void *)); +void * _CDECL bsearch(const void *, const void *, size_t, size_t, int (_CDECL *)(const void *, const void *)); +void _CDECL qsort(void *, size_t, size_t, int (_CDECL *)(const void *, const void *)); diff --git a/v4.0/src/TOOLS/BLD/INC/SETJMP.H b/v4.0/src/TOOLS/BLD/INC/SETJMP.H new file mode 100644 index 0000000..6f74793 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SETJMP.H @@ -0,0 +1,35 @@ +/*** +*setjmp.h - definitions/declarations for setjmp/longjmp routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the machine-dependent buffer used by +* setjmp/longjmp to save and restore the program state, and +* declarations for those routines. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + + +/* define the buffer type for holding the state information */ + +#define _JBLEN 9 /* bp, di, si, sp, ret addr, ds */ + +#ifndef _JMP_BUF_DEFINED +typedef int jmp_buf[_JBLEN]; +#define _JMP_BUF_DEFINED +#endif + + +/* function prototypes */ + +int _CDECL setjmp(jmp_buf); +void _CDECL longjmp(jmp_buf, int); diff --git a/v4.0/src/TOOLS/BLD/INC/SHARE.H b/v4.0/src/TOOLS/BLD/INC/SHARE.H new file mode 100644 index 0000000..2a34f71 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SHARE.H @@ -0,0 +1,15 @@ +/*** +*share.h - defines file sharing modes for sopen +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the file sharing modes for sopen(). +* +*******************************************************************************/ + +#define SH_COMPAT 0x00 /* compatibility mode */ +#define SH_DENYRW 0x10 /* deny read/write mode */ +#define SH_DENYWR 0x20 /* deny write mode */ +#define SH_DENYRD 0x30 /* deny read mode */ +#define SH_DENYNO 0x40 /* deny none mode */ diff --git a/v4.0/src/TOOLS/BLD/INC/SIGNAL.H b/v4.0/src/TOOLS/BLD/INC/SIGNAL.H new file mode 100644 index 0000000..18b8f10 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SIGNAL.H @@ -0,0 +1,59 @@ +/*** +*signal.h - defines signal values and routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the signal values and declares the signal functions. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + +#ifndef _SIG_ATOMIC_T_DEFINED +typedef int sig_atomic_t; +#define _SIG_ATOMIC_T_DEFINED +#endif + + +#define NSIG 23 /* maximum signal number + 1 */ + +/* signal types */ +/* SIGINT, SIGFPE, SIGILL, SIGSEGV, and SIGABRT are recognized on DOS 3.x */ + +#define SIGINT 2 /* interrupt - corresponds to DOS 3.x int 23H */ +#define SIGILL 4 /* illegal instruction - invalid function image */ +#define SIGFPE 8 /* floating point exception */ +#define SIGSEGV 11 /* segment violation */ +#define SIGTERM 15 /* Software termination signal from kill */ +#define SIGUSR1 16 /* User defined signal 1 */ +#define SIGUSR2 17 /* User defined signal 2 */ +#define SIGUSR3 20 /* User defined signal 3 */ +#define SIGBREAK 21 /* Ctrl-Break sequence */ +#define SIGABRT 22 /* abnormal termination triggered by abort call */ + + +/* signal action codes */ +/* SIG_DFL and SIG_IGN are recognized on DOS 3.x */ + +#define SIG_DFL (void (*)())0 /* default signal action */ +#define SIG_IGN (void (*)())1 /* ignore */ +#define SIG_SGE (void (*)())3 /* signal gets error */ +#define SIG_ACK (void (*)())4 /* error if handler not setup */ + + +/* signal error value (returned by signal call on error) */ + +#define SIG_ERR (void (*)())-1 /* signal error value */ + + +/* function prototypes */ + +void (_CDECL * _CDECL signal(int, void (_CDECL *)()))(); +int _CDECL raise(int); diff --git a/v4.0/src/TOOLS/BLD/INC/STDARG.H b/v4.0/src/TOOLS/BLD/INC/STDARG.H new file mode 100644 index 0000000..d261cfa --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/STDARG.H @@ -0,0 +1,20 @@ +/*** +*stdarg.h - defines ANSI-style macros for variable argument functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines ANSI-style macros for accessing arguments +* of functions which take a variable number of arguments. +* [ANSI] +* +*******************************************************************************/ + +#ifndef _VA_LIST_DEFINED +typedef char *va_list; +#define _VA_LIST_DEFINED +#endif + +#define va_start(ap,v) ap = (va_list)&v + sizeof(v) +#define va_arg(ap,t) ((t *)(ap += sizeof(t)))[-1] +#define va_end(ap) ap = NULL diff --git a/v4.0/src/TOOLS/BLD/INC/STDDEF.H b/v4.0/src/TOOLS/BLD/INC/STDDEF.H new file mode 100644 index 0000000..b9637b0 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/STDDEF.H @@ -0,0 +1,48 @@ +/*** +*stddef.h - definitions/declarations for common constants, types, variables +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains definitions and declarations for some commonly +* used constants, types, and variables. +* [ANSI] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* define NULL pointer value */ + +#if (defined(M_I86SM) || defined(M_I86MM)) +#define NULL 0 +#elif (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) +#define NULL 0L +#endif + + +/* declare reference to errno */ + +extern int _NEAR _CDECL errno; + + +/* define the implementation dependent size types */ + +#ifndef _PTRDIFF_T_DEFINED +typedef int ptrdiff_t; +#define _PTRDIFF_T_DEFINED +#endif + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + diff --git a/v4.0/src/TOOLS/BLD/INC/STDIO.H b/v4.0/src/TOOLS/BLD/INC/STDIO.H new file mode 100644 index 0000000..0c7f7b3 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/STDIO.H @@ -0,0 +1,165 @@ +/*** +*stdio.h - definitions/declarations for standard I/O routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the structures, values, macros, and functions +* used by the level 2 I/O ("standard I/O") routines. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#ifndef _VA_LIST_DEFINED +typedef char *va_list; +#define _VA_LIST_DEFINED +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* buffered I/O macros */ + +#define BUFSIZ 512 +#define _NFILE 20 +#define EOF (-1) + +#ifndef _FILE_DEFINED +#define FILE struct _iobuf +#define _FILE_DEFINED +#endif + +/* P_tmpnam: Directory where temporary files may be created. + * L_tmpnam size = size of P_tmpdir + * + 1 (in case P_tmpdir does not end in "\\") + * + 6 (for the temp number string) + * + 1 (for the null terminator) + */ + +#define P_tmpdir "\\" +#define L_tmpnam sizeof(P_tmpdir)+8 + +#define SEEK_CUR 1 +#define SEEK_END 2 +#define SEEK_SET 0 + +#define SYS_OPEN 20 +#define TMP_MAX 32767 + + +/* define NULL pointer value */ + +#if (defined(M_I86SM) || defined(M_I86MM)) +#define NULL 0 +#elif (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) +#define NULL 0L +#endif + + +/* define file control block */ + +#ifndef _IOB_DEFINED +extern FILE { + char *_ptr; + int _cnt; + char *_base; + char _flag; + char _file; + } _NEAR _CDECL _iob[]; +#define _IOB_DEFINED +#endif + +#define fpos_t long /* file position variable */ + +#define stdin (&_iob[0]) +#define stdout (&_iob[1]) +#define stderr (&_iob[2]) +#define stdaux (&_iob[3]) +#define stdprn (&_iob[4]) + +#define _IOREAD 0x01 +#define _IOWRT 0x02 + +#define _IOFBF 0x0 +#define _IOLBF 0x40 +#define _IONBF 0x04 + +#define _IOMYBUF 0x08 +#define _IOEOF 0x10 +#define _IOERR 0x20 +#define _IOSTRG 0x40 +#define _IORW 0x80 + +#define getc(f) (--(f)->_cnt >= 0 ? 0xff & *(f)->_ptr++ : _filbuf(f)) +#define putc(c,f) (--(f)->_cnt >= 0 ? 0xff & (*(f)->_ptr++ = (char)(c)) \ + : _flsbuf((c),(f))) +#define getchar() getc(stdin) +#define putchar(c) putc((c),stdout) + +#define feof(f) ((f)->_flag & _IOEOF) +#define ferror(f) ((f)->_flag & _IOERR) +#define fileno(f) ((f)->_file) + + +/* function prototypes */ + +int _CDECL _filbuf(FILE *); +int _CDECL _flsbuf(int, FILE *); +void _CDECL clearerr(FILE *); +int _CDECL fclose(FILE *); +int _CDECL fcloseall(void); +FILE * _CDECL fdopen(int, char *); +int _CDECL fflush(FILE *); +int _CDECL fgetc(FILE *); +int _CDECL fgetchar(void); +int _CDECL fgetpos(FILE *, fpos_t *); +char * _CDECL fgets(char *, int, FILE *); +int _CDECL flushall(void); +FILE * _CDECL fopen(const char *, const char *); +int _CDECL fprintf(FILE *, const char *, ...); +int _CDECL fputc(int, FILE *); +int _CDECL fputchar(int); +int _CDECL fputs(const char *, FILE *); +size_t _CDECL fread(void *, size_t, size_t, FILE *); +FILE * _CDECL freopen(const char *, const char *, FILE *); +int _CDECL fscanf(FILE *, const char *, ...); +int _CDECL fsetpos(FILE *, const fpos_t *); +int _CDECL fseek(FILE *, long, int); +long _CDECL ftell(FILE *); +size_t _CDECL fwrite(const void *, size_t, size_t, FILE *); +char * _CDECL gets(char *); +int _CDECL getw(FILE *); +void _CDECL perror(const char *); +int _CDECL printf(const char *, ...); +int _CDECL puts(const char *); +int _CDECL putw(int, FILE *); +int _CDECL remove(const char *); +int _CDECL rename(const char *, const char *); +void _CDECL rewind(FILE *); +int _CDECL rmtmp(void); +int _CDECL scanf(const char *, ...); +void _CDECL setbuf(FILE *, char *); +int _CDECL setvbuf(FILE *, char *, int, size_t); +int _CDECL sprintf(char *, const char *, ...); +int _CDECL sscanf(const char *, const char *, ...); +char * _CDECL tempnam(char *, char *); +FILE * _CDECL tmpfile(void); +char * _CDECL tmpnam(char *); +int _CDECL ungetc(int, FILE *); +int _CDECL unlink(const char *); +int _CDECL vfprintf(FILE *, const char *, va_list); +int _CDECL vprintf(const char *, va_list); +int _CDECL vsprintf(char *, const char *, va_list); + diff --git a/v4.0/src/TOOLS/BLD/INC/STDLIB.H b/v4.0/src/TOOLS/BLD/INC/STDLIB.H new file mode 100644 index 0000000..5fb67d7 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/STDLIB.H @@ -0,0 +1,151 @@ +/*** +*stdlib.h - declarations/definitions for commonly used library functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This include file contains the function declarations for +* commonly used library functions which either don't fit somewhere +* else, or, like toupper/tolower, can't be declared in the normal +* place (ctype.h in the case of toupper/tolower) for other reasons. +* [ANSI] +* +*******************************************************************************/ + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* definition of the return type for the onexit() function */ + +#ifndef _ONEXIT_T_DEFINED +typedef int (_CDECL * _CDECL onexit_t)(); +#define _ONEXIT_T_DEFINED +#endif + + +/* Data structure definitions for div and ldiv runtimes. */ + +#ifndef _DIV_T_DEFINED + +typedef struct { + int quot; + int rem; +} div_t; + +typedef struct { + long quot; + long rem; +} ldiv_t; + +#define _DIV_T_DEFINED +#endif + +/* Maximum value that can be returned by the rand function. */ + +#define RAND_MAX 0x7fff + + +/* min and max macros */ + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + + +/* sizes for buffers used by the _makepath() and _splitpath() functions. + * note that the sizes include space for 0-terminator + */ + +#define _MAX_PATH 144 /* max. length of full pathname */ +#define _MAX_DRIVE 3 /* max. length of drive component */ +#define _MAX_DIR 130 /* max. length of path component */ +#define _MAX_FNAME 9 /* max. length of file name component */ +#define _MAX_EXT 5 /* max. length of extension component */ + +/* external variable declarations */ + +extern int _NEAR _CDECL errno; /* XENIX style error number */ +extern int _NEAR _CDECL _doserrno; /* MS-DOS system error value */ +extern char * _NEAR _CDECL sys_errlist[]; /* perror error message table */ +extern int _NEAR _CDECL sys_nerr; /* # of entries in sys_errlist table */ + +extern char ** _NEAR _CDECL environ; /* pointer to environment table */ + +extern unsigned int _NEAR _CDECL _psp; /* Program Segment Prefix */ + +extern int _NEAR _CDECL _fmode; /* default file translation mode */ + +/* DOS major/minor version numbers */ + +extern unsigned char _NEAR _CDECL _osmajor; +extern unsigned char _NEAR _CDECL _osminor; + +#define DOS_MODE 0 /* Real Address Mode */ +#define OS2_MODE 1 /* Protected Address Mode */ + +extern unsigned char _NEAR _CDECL _osmode; + + +/* function prototypes */ + +double _CDECL atof(const char *); +double _CDECL strtod(const char *, char * *); +ldiv_t _CDECL ldiv(long, long); + +void _CDECL abort(void); +int _CDECL abs(int); +int _CDECL atexit(void (_CDECL *)(void)); +int _CDECL atoi(const char *); +long _CDECL atol(const char *); +void * _CDECL bsearch(const void *, const void *, size_t, size_t, int (_CDECL *)(const void *, const void *)); +void * _CDECL calloc(size_t, size_t); +div_t _CDECL div(int, int); +char * _CDECL ecvt(double, int, int *, int *); +void _CDECL exit(int); +void _CDECL _exit(int); +char * _CDECL fcvt(double, int, int *, int *); +void _CDECL free(void *); +char * _CDECL gcvt(double, int, char *); +char * _CDECL getenv(const char *); +char * _CDECL itoa(int, char *, int); +long _CDECL labs(long); +unsigned long _CDECL _lrotl(unsigned long, int); +unsigned long _CDECL _lrotr(unsigned long, int); +char * _CDECL ltoa(long, char *, int); +void _CDECL _makepath(char *, char *, char *, char *, char *); +void * _CDECL malloc(size_t); +onexit_t _CDECL onexit(onexit_t); +void _CDECL perror(const char *); +int _CDECL putenv(char *); +void _CDECL qsort(void *, size_t, size_t, int (_CDECL *)(const void *, const void *)); +unsigned int _CDECL _rotl(unsigned int, int); +unsigned int _CDECL _rotr(unsigned int, int); +int _CDECL rand(void); +void * _CDECL realloc(void *, size_t); +void _CDECL _searchenv(char *, char *, char *); +void _CDECL _splitpath(char *, char *, char *, char *, char *); +void _CDECL srand(unsigned int); +long _CDECL strtol(const char *, char * *, int); +unsigned long _CDECL strtoul(const char *, char * *, int); +void _CDECL swab(char *, char *, int); +int _CDECL system(const char *); +char * _CDECL ultoa(unsigned long, char *, int); + +#ifndef tolower /* tolower has been undefined - use function */ +int _CDECL tolower(int); +#endif /* tolower */ + +#ifndef toupper /* toupper has been undefined - use function */ +int _CDECL toupper(int); +#endif /* toupper */ diff --git a/v4.0/src/TOOLS/BLD/INC/STRING.H b/v4.0/src/TOOLS/BLD/INC/STRING.H new file mode 100644 index 0000000..8340688 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/STRING.H @@ -0,0 +1,61 @@ +/*** +*string.h - declarations for string manipulation functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file contains the function declarations for the string +* manipulation functions. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl +#else /* extensions not enabled */ + #define _CDECL +#endif /* NO_EXT_KEYS */ + + +/* function prototypes */ + +void * _CDECL memccpy(void *, void *, int, unsigned int); +void * _CDECL memchr(const void *, int, size_t); +int _CDECL memcmp(const void *, const void *, size_t); +int _CDECL memicmp(void *, void *, unsigned int); +void * _CDECL memcpy(void *, const void *, size_t); +void * _CDECL memmove(void *, const void *, size_t); +void * _CDECL memset(void *, int, size_t); +void _CDECL movedata(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); + +char * _CDECL strcat(char *, const char *); +char * _CDECL strchr(const char *, int); +int _CDECL strcmp(const char *, const char *); +int _CDECL strcmpi(const char *, const char *); +int _CDECL stricmp(const char *, const char *); +char * _CDECL strcpy(char *, const char *); +size_t _CDECL strcspn(const char *, const char *); +char * _CDECL strdup(const char *); +char * _CDECL _strerror(char *); +char * _CDECL strerror(int); +size_t _CDECL strlen(const char *); +char * _CDECL strlwr(char *); +char * _CDECL strncat(char *, const char *, size_t); +int _CDECL strncmp(const char *, const char *, size_t); +int _CDECL strnicmp(const char *, const char *, size_t); +char * _CDECL strncpy(char *, const char *, size_t); +char * _CDECL strnset(char *, int, size_t); +char * _CDECL strpbrk(const char *, const char *); +char * _CDECL strrchr(const char *, int); +char * _CDECL strrev(char *); +char * _CDECL strset(char *, int); +size_t _CDECL strspn(const char *, const char *); +char * _CDECL strstr(const char *, const char *); +char * _CDECL strtok(char *, const char *); +char * _CDECL strupr(char *); diff --git a/v4.0/src/TOOLS/BLD/INC/SYS/LOCKING.H b/v4.0/src/TOOLS/BLD/INC/SYS/LOCKING.H new file mode 100644 index 0000000..fb76160 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SYS/LOCKING.H @@ -0,0 +1,16 @@ +/*** +*sys\locking.h - flags for locking() function +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the flags for the locking() function. +* [System V] +* +*******************************************************************************/ + +#define LK_UNLCK 0 /* unlock the file region */ +#define LK_LOCK 1 /* lock the file region */ +#define LK_NBLCK 2 /* non-blocking lock */ +#define LK_RLCK 3 /* lock for writing */ +#define LK_NBRLCK 4 /* non-blocking lock for writing */ diff --git a/v4.0/src/TOOLS/BLD/INC/SYS/STAT.H b/v4.0/src/TOOLS/BLD/INC/SYS/STAT.H new file mode 100644 index 0000000..4259208 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SYS/STAT.H @@ -0,0 +1,56 @@ +/*** +*sys\stat.h - defines structure used by stat() and fstat() +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the structure used by the stat() and fstat() +* routines. +* [System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define CDECL cdecl +#else /* extensions not enabled */ + #define CDECL +#endif /* NO_EXT_KEYS */ + +#ifndef _TIME_T_DEFINED +typedef long time_t; +#define _TIME_T_DEFINED +#endif + +/* define structure for returning status information */ + +#ifndef _STAT_DEFINED +struct stat { + dev_t st_dev; + ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; + }; +#define _STAT_DEFINED +#endif + +#define S_IFMT 0170000 /* file type mask */ +#define S_IFDIR 0040000 /* directory */ +#define S_IFCHR 0020000 /* character special */ +#define S_IFREG 0100000 /* regular */ +#define S_IREAD 0000400 /* read permission, owner */ +#define S_IWRITE 0000200 /* write permission, owner */ +#define S_IEXEC 0000100 /* execute/search permission, owner */ + + +/* function prototypes */ + +int CDECL fstat(int, struct stat *); +int CDECL stat(char *, struct stat *); diff --git a/v4.0/src/TOOLS/BLD/INC/SYS/TIMEB.H b/v4.0/src/TOOLS/BLD/INC/SYS/TIMEB.H new file mode 100644 index 0000000..46bf4ac --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SYS/TIMEB.H @@ -0,0 +1,39 @@ +/*** +*sys\timeb.h - definition/declarations for ftime() +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file define the ftime() function and the types it uses. +* [System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define CDECL cdecl +#else /* extensions not enabled */ + #define CDECL +#endif /* NO_EXT_KEYS */ + +#ifndef _TIME_T_DEFINED +typedef long time_t; +#define _TIME_T_DEFINED +#endif + +/* structure returned by ftime system call */ + +#ifndef _TIMEB_DEFINED +struct timeb { + time_t time; + unsigned short millitm; + short timezone; + short dstflag; + }; +#define _TIMEB_DEFINED +#endif + + +/* function prototypes */ + +void CDECL ftime(struct timeb *); diff --git a/v4.0/src/TOOLS/BLD/INC/SYS/TYPES.H b/v4.0/src/TOOLS/BLD/INC/SYS/TYPES.H new file mode 100644 index 0000000..84fc6b6 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SYS/TYPES.H @@ -0,0 +1,31 @@ +/*** +*sys\types.h - types returned by system level calls for file and time info +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines types used in defining values returned by system +* level calls for file status and time information. +* [System V] +* +*******************************************************************************/ + +#ifndef _INO_T_DEFINED +typedef unsigned short ino_t; /* i-node number (not used on DOS) */ +#define _INO_T_DEFINED +#endif + +#ifndef _TIME_T_DEFINED +typedef long time_t; +#define _TIME_T_DEFINED +#endif + +#ifndef _DEV_T_DEFINED +typedef short dev_t; /* device code */ +#define _DEV_T_DEFINED +#endif + +#ifndef _OFF_T_DEFINED +typedef long off_t; /* file offset value */ +#define _OFF_T_DEFINED +#endif diff --git a/v4.0/src/TOOLS/BLD/INC/SYS/UTIME.H b/v4.0/src/TOOLS/BLD/INC/SYS/UTIME.H new file mode 100644 index 0000000..868756c --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/SYS/UTIME.H @@ -0,0 +1,40 @@ +/*** +*sys\utime.h - definitions/declarations for utime() +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines the structure used by the utime routine to set +* new file access and modification times. NOTE - MS-DOS +* does not recognize access time, so this field will +* always be ignored and the modification time field will be +* used to set the new time. +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define CDECL cdecl +#else /* extensions not enabled */ + #define CDECL +#endif /* NO_EXT_KEYS */ + +#ifndef _TIME_T_DEFINED +typedef long time_t; +#define _TIME_T_DEFINED +#endif + +/* define struct used by utime() function */ + +#ifndef _UTIMBUF_DEFINED +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ + }; +#define _UTIMBUF_DEFINED +#endif + + +/* function prototypes */ + +int CDECL utime(char *, struct utimbuf *); diff --git a/v4.0/src/TOOLS/BLD/INC/TIME.H b/v4.0/src/TOOLS/BLD/INC/TIME.H new file mode 100644 index 0000000..d9a1681 --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/TIME.H @@ -0,0 +1,75 @@ +/*** +*time.h - definitions/declarations for time routines +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file has declarations of time routines and defines +* the structure returned by the localtime and gmtime routines and +* used by asctime. +* [ANSI/System V] +* +*******************************************************************************/ + + +#ifndef NO_EXT_KEYS /* extensions enabled */ + #define _CDECL cdecl + #define _NEAR near +#else /* extensions not enabled */ + #define _CDECL + #define _NEAR +#endif /* NO_EXT_KEYS */ + + +/* define the implementation defined time type */ + +#ifndef _TIME_T_DEFINED +typedef long time_t; /* time value */ +#define _TIME_T_DEFINED /* avoid multiple def's of time_t */ +#endif + +#ifndef _CLOCK_T_DEFINED +typedef long clock_t; +#define _CLOCK_T_DEFINED +#endif + +#ifndef _TM_DEFINED +struct tm { + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday - [0,6] */ + int tm_yday; /* days since January 1 - [0,365] */ + int tm_isdst; /* daylight savings time flag */ + }; +#define _TM_DEFINED +#endif + +#define CLK_TCK 1000 + + +/* extern declarations for the global variables used by the ctime family of + * routines. + */ + +extern int _NEAR _CDECL daylight; /* non-zero if daylight savings time is used */ +extern long _NEAR _CDECL timezone; /* difference in seconds between GMT and local time */ +extern char * _NEAR _CDECL tzname[2]; /* standard/daylight savings time zone names */ + + +/* function prototypes */ + +char * _CDECL asctime(const struct tm *); +char * _CDECL ctime(const time_t *); +clock_t _CDECL clock(void); +double _CDECL difftime(time_t, time_t); +struct tm * _CDECL gmtime(const time_t *); +struct tm * _CDECL localtime(const time_t *); +time_t _CDECL mktime(struct tm *); +char * _CDECL _strdate(char *); +char * _CDECL _strtime(char *); +time_t _CDECL time(time_t *); +void _CDECL tzset(void); diff --git a/v4.0/src/TOOLS/BLD/INC/VARARGS.H b/v4.0/src/TOOLS/BLD/INC/VARARGS.H new file mode 100644 index 0000000..e96d04e --- /dev/null +++ b/v4.0/src/TOOLS/BLD/INC/VARARGS.H @@ -0,0 +1,21 @@ +/*** +*varargs.h - XENIX style macros for variable argument functions +* +* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This file defines XENIX style macros for accessing arguments of a +* function which takes a variable number of arguments. +* [System V] +* +*******************************************************************************/ + +#ifndef _VA_LIST_DEFINED +typedef char *va_list; +#define _VA_LIST_DEFINED +#endif + +#define va_dcl va_list va_alist; +#define va_start(ap) ap = (va_list)&va_alist +#define va_arg(ap,t) ((t *)(ap += sizeof(t)))[-1] +#define va_end(ap) ap = NULL diff --git a/v4.0/src/TOOLS/BLD/LIB/BINMODE.OBJ b/v4.0/src/TOOLS/BLD/LIB/BINMODE.OBJ new file mode 100644 index 0000000..a443384 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/BINMODE.OBJ differ diff --git a/v4.0/src/TOOLS/BLD/LIB/CLIBCE.LIB b/v4.0/src/TOOLS/BLD/LIB/CLIBCE.LIB new file mode 100644 index 0000000..a1433ab Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/CLIBCE.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/CLIBCR.LIB b/v4.0/src/TOOLS/BLD/LIB/CLIBCR.LIB new file mode 100644 index 0000000..e8e33da Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/CLIBCR.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/CLIBFP.LIB b/v4.0/src/TOOLS/BLD/LIB/CLIBFP.LIB new file mode 100644 index 0000000..fe17da2 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/CLIBFP.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/CVARSTCK.OBJ b/v4.0/src/TOOLS/BLD/LIB/CVARSTCK.OBJ new file mode 100644 index 0000000..5129408 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/CVARSTCK.OBJ differ diff --git a/v4.0/src/TOOLS/BLD/LIB/EM.LIB b/v4.0/src/TOOLS/BLD/LIB/EM.LIB new file mode 100644 index 0000000..0d6279e Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/EM.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/GRAPHICS.LIB b/v4.0/src/TOOLS/BLD/LIB/GRAPHICS.LIB new file mode 100644 index 0000000..4b7e0e7 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/GRAPHICS.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/LIBH.LIB b/v4.0/src/TOOLS/BLD/LIB/LIBH.LIB new file mode 100644 index 0000000..f7d3e50 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/LIBH.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/LLIBCE.LIB b/v4.0/src/TOOLS/BLD/LIB/LLIBCE.LIB new file mode 100644 index 0000000..0c581d1 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/LLIBCE.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/LLIBCR.LIB b/v4.0/src/TOOLS/BLD/LIB/LLIBCR.LIB new file mode 100644 index 0000000..1815c2b Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/LLIBCR.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/LLIBFP.LIB b/v4.0/src/TOOLS/BLD/LIB/LLIBFP.LIB new file mode 100644 index 0000000..804dcdc Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/LLIBFP.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/LVARSTCK.OBJ b/v4.0/src/TOOLS/BLD/LIB/LVARSTCK.OBJ new file mode 100644 index 0000000..365bbb6 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/LVARSTCK.OBJ differ diff --git a/v4.0/src/TOOLS/BLD/LIB/MLIBCE.LIB b/v4.0/src/TOOLS/BLD/LIB/MLIBCE.LIB new file mode 100644 index 0000000..3e35f4a Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/MLIBCE.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/MLIBCR.LIB b/v4.0/src/TOOLS/BLD/LIB/MLIBCR.LIB new file mode 100644 index 0000000..ae2c1c2 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/MLIBCR.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/MLIBFP.LIB b/v4.0/src/TOOLS/BLD/LIB/MLIBFP.LIB new file mode 100644 index 0000000..9a74029 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/MLIBFP.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/MVARSTCK.OBJ b/v4.0/src/TOOLS/BLD/LIB/MVARSTCK.OBJ new file mode 100644 index 0000000..2f2504c Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/MVARSTCK.OBJ differ diff --git a/v4.0/src/TOOLS/BLD/LIB/SETARGV.OBJ b/v4.0/src/TOOLS/BLD/LIB/SETARGV.OBJ new file mode 100644 index 0000000..7578cac Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/SETARGV.OBJ differ diff --git a/v4.0/src/TOOLS/BLD/LIB/SLIBCE.LIB b/v4.0/src/TOOLS/BLD/LIB/SLIBCE.LIB new file mode 100644 index 0000000..cbc6138 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/SLIBCE.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/SLIBCR.LIB b/v4.0/src/TOOLS/BLD/LIB/SLIBCR.LIB new file mode 100644 index 0000000..27017a1 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/SLIBCR.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/SLIBFP.LIB b/v4.0/src/TOOLS/BLD/LIB/SLIBFP.LIB new file mode 100644 index 0000000..362f4e9 Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/SLIBFP.LIB differ diff --git a/v4.0/src/TOOLS/BLD/LIB/SVARSTCK.OBJ b/v4.0/src/TOOLS/BLD/LIB/SVARSTCK.OBJ new file mode 100644 index 0000000..f88e7ae Binary files /dev/null and b/v4.0/src/TOOLS/BLD/LIB/SVARSTCK.OBJ differ diff --git a/v4.0/src/TOOLS/BUILDIDX.EXE b/v4.0/src/TOOLS/BUILDIDX.EXE new file mode 100644 index 0000000..9254c11 Binary files /dev/null and b/v4.0/src/TOOLS/BUILDIDX.EXE differ diff --git a/v4.0/src/TOOLS/BUILDMSG.EXE b/v4.0/src/TOOLS/BUILDMSG.EXE new file mode 100644 index 0000000..3565467 Binary files /dev/null and b/v4.0/src/TOOLS/BUILDMSG.EXE differ diff --git a/v4.0/src/TOOLS/C1.ERR b/v4.0/src/TOOLS/C1.ERR new file mode 100644 index 0000000..d26c849 --- /dev/null +++ b/v4.0/src/TOOLS/C1.ERR @@ -0,0 +1,334 @@ +/* SCCSWHAT( "@(#)c1.err 2.29 88/02/25 18:18:00 " ) */ + /* fatals */ + +1001 "Internal Compiler Error\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Technical Support" +1002 "out of heap space" +1003 "error count exceeds %d; stopping compilation" +1004 "unexpected EOF" +1005 "string too big for buffer" +1006 "write error on compiler intermediate file" +1007 "unrecognized flag '%s' in '%s'" +1008 "no input file specified" +1009 "compiler limit : macros too deeply nested" +1010 "compiler limit : macro expansion too big" +1012 "bad parenthesis nesting - missing '%c'" +1013 "cannot open source file '%s'" +1014 "too many include files" +1015 "cannot open include file '%s'" +1016 "#if[n]def expected an identifier" +1017 "invalid integer constant expression" +1018 "unexpected '#elif'" +1019 "unexpected '#else'" +1020 "unexpected '#endif'" +1021 "bad preprocessor command '%s'" +1022 "expected '#endif'" +1023 "no int size specified" +1024 "no ptr size specified" +1025 "no function size specified" +1026 "parser stack overflow, please simplify your program" +1027 "DGROUP data allocation exceeds 64K" /* QC, c23 */ +1028 "%s segment allocation exceeds 64K" /* QC */ +1031 "compiler limit : function calls too deeply nested" /* QC, c23 */ +1032 "cannot open object listing file '%s'" /* QC, c23 */ +1035 "expression too complex, please simplify" /* QC, c23 */ +1037 "cannot open object file '%s'" /* QC, c23 */ +1041 "cannot open compiler intermediate file - no more files" +1042 "cannot open compiler intermediate file - no such file or directory" +1043 "cannot open compiler intermediate file" +1044 "out of disk space for compiler intermediate file" +1045 "floating point overflow" +1047 "too many %s flags, '%s'" +1048 "unknown option '%c' in '%s'" +1049 "invalid numerical argument '%s'" +1052 "too many #if/#ifdef's" +1053 "compiler limit : struct/union nesting" +1054 "compiler limit : initializers too deeply nested" +1055 "compiler limit : out of keys" +1056 "compiler limit : out of macro expansion space" +1057 "unexpected EOF in macro expansion (missing ')'?)" +1059 "out of near heap space" +1060 "out of far heap space" +1061 "compiler limit : blocks too deeply nested" /* QC */ +1062 "error writing to preprocessor output file" +1063 "compiler limit : compiler stack overflow" /* QC */ +1064 "compiler limit : identifier overflowed internal buffer" +1065 "compiler limit : declarator too complex" +1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Technical Support" + + /* errors */ + +2001 "newline in constant" +2002 "out of macro actual parameter space" +2003 "expected 'defined id'" +2004 "expected 'defined(id)'" +2005 "#line expected a line number, found '%s'" +2006 "#include expected a file name, found '%s'" +2007 "#define syntax" +2008 "'%c' : unexpected in macro definition" +2009 "reuse of macro formal '%s'" +2010 "'%c' : unexpected in formal list" +2011 "'%s' : definition too big" +2012 "missing name following '<'" +2013 "missing '>'" +2014 "preprocessor command must start as first non-whitespace" +2015 "too many chars in constant" +2016 "no closing single quote" +2017 "illegal escape sequence" +2018 "unknown character '0x%x'" +2019 "expected preprocessor command, found '%c'" +2020 "bad octal number '%c'" +2021 "expected exponent value, not '%c'" +2022 "'%ld' : too big for char" +2023 "divide by 0" +2024 "mod by 0" +2025 "'%s' : enum/struct/union type redefinition" +2026 "'%s' : member of enum redefinition" +2028 "struct/union member needs to be inside a struct/union" +2029 "'%Fs' : bit-fields only allowed in structs" +2030 "'%Fs' : struct/union member redefinition" +2031 "'%Fs' : function cannot be struct/union member" +2032 "'%Fs' : base type with near/far/huge not allowed" +2033 "'%Fs' : bit-field cannot have indirection" +2034 "'%Fs' : bit-field type too small for number of bits" +2035 "enum/struct/union '%Fs' : unknown size" +2036 "left of '%s%s' must have a struct/union type" +2037 "left of '%s' specifies undefined struct/union '%Fs'" +2038 "'%s' : not struct/union member" +2039 "'->' requires struct/union pointer" +2040 "'.' requires struct/union name" +2042 "signed/unsigned keywords mutually exclusive" +2043 "illegal break" +2044 "illegal continue" +2045 "'%s' : label redefined" +2046 "illegal case" +2047 "illegal default" +2048 "more than one default" +2050 "non-integral switch expression" +2051 "case expression not constant" +2052 "case expression not integral" +2053 "case value %d already used" +2054 "expected '(' to follow '%Fs'" +2055 "expected formal parameter list, not a type list" +2056 "illegal expression" +2057 "expected constant expression" +2058 "constant expression is not integral" +2059 "syntax error : '%s'" +2060 "syntax error : EOF" +2061 "syntax error : identifier '%s'" +2062 "type '%s' unexpected" +2063 "'%s' : not a function" +2064 "term does not evaluate to a function" +2065 "'%s' : undefined" +2066 "cast to function returning . . . is illegal" +2067 "cast to array type is illegal" +2068 "illegal cast" +2069 "cast of 'void' term to non-void" +2070 "illegal sizeof operand" +2071 "'%Fs' : bad storage class" +2072 "'%Fs' : initialization of a function" +2073 "'%Fs' : cannot initialize array in function" +2074 "'%Fs' : cannot initialize struct/union in function" +2075 "'%Fs' : array initialization needs curly braces" +2076 "'%Fs' : struct/union initialization needs curly braces" +2077 "non-integral field initializer '%Fs'" +2078 "too many initializers" +2079 "'%Fs' uses undefined struct/union '%Fs'" +2082 "redefinition of formal parameter '%Fs'" +2083 "array '%Fs' already has a size" +2084 "function '%Fs' already has a body" +2085 "'%Fs' : not in formal parameter list" +2086 "'%Fs' : redefinition" +2087 "'%Fs' : missing subscript" +2088 "use of undefined enum/struct/union '%s'" +2089 "typedef specifies a near/far function" +2090 "function returns array" +2091 "function returns function" +2092 "array element type cannot be function" +2093 "cannot initialize a static or struct with address of automatic vars" +2094 "label '%Fs' was undefined" +2095 "'%Fs' : actual has type void : parameter %d" +2096 "struct/union comparison illegal" +2097 "illegal initialization" +2098 "non-address expression" +2099 "non-constant offset" +2100 "illegal indirection" +2101 "'&' on constant" +2102 "'&' requires lvalue" +2103 "'&' on register variable" +2104 "'&' on bit-field ignored" +2105 "'%s' needs lvalue" +2106 "'%s' : left operand must be lvalue" +2107 "illegal index, indirection not allowed" +2108 "non-integral index" +2109 "subscript on non-array" +2110 "'+' : 2 pointers" +2111 "pointer + non-integral value" +2112 "illegal pointer subtraction" +2113 "'-' : right operand pointer" +2114 "'%s' : pointer on left; needs integral right" +2115 "'%s' : incompatible types" +2116 "'%s' : bad %s operand" +2117 "'%s' : illegal for struct/union" +2118 "negative subscript" +2119 "'typedefs' both define indirection" +2120 "'void' illegal with all types" +2121 "typedef specifies different enum" +2122 "typedef specifies different struct" +2123 "typedef specifies different union" +2125 "%Fs : allocation exceeds 64K" /* QC, c23 */ +2126 "%Fs : auto allocation exceeds %s" /* QC, c23 */ +2127 "parameter allocation exceeds 32K" /* QC, c23 */ +2130 "#line expected a string containing the file name, found '%s'" +2131 "attributes specify more than one near/far/huge" +2132 "syntax error : unexpected identifier" +2133 "array '%Fs' : unknown size" +2134 "'%Fs' : struct/union too large" +2135 "missing ')' in macro expansion" +2137 "empty character constant" +2138 "unmatched close comment '*/'" +2139 "type following '%s' is illegal" +2140 "argument type cannot be function returning . . ." +2141 "value out of range for enum constant" +2142 "ellipsis requires three periods" +2143 "syntax error : missing '%s' before '%s'" +2144 "syntax error : missing '%s' before type '%Fs'" +2145 "syntax error : missing '%s' before identifier" +2146 "syntax error : missing '%s' before identifier '%s'" +2147 "unknown size" +2148 "array too large" +2149 "'%Fs' : named bit-field cannot have 0 width" +2150 "'%Fs' : bit-field must have type int, signed int, or unsigned int" +2151 "more than one cdecl/fortran/pascal attribute specified" +2152 "'%s' : pointers to functions with different attributes" +2153 "hex constants must have at least 1 hex digit" +2154 "'%s' : does not refer to a segment" +2155 "'%s' : already in a segment" +2156 "pragma must be at outer level" +2157 "'%s' : must be declared before use in pragma list" +2158 "'%s' : is a function" +2159 "more than one storage class specified" +2160 "## cannot occur at the beginning of a macro definition" +2161 "## cannot occur at the end of a macro definition" +2162 "expected macro formal parameter" +2163 "'%s' : not available as an intrinsic" +2164 "'%s' : intrinsic was not declared" +2165 "'%s' : cannot modify pointers to data" +2166 "lval specifies 'const' object" +2167 "'%Fs' : too many actual parameters for intrinsic" +2168 "'%Fs' : too few actual parameters for intrinsic" +2169 "'%Fs' : is an intrinsic, it cannot be defined" +2170 "'%s' : intrinsic not declared as a function" +2171 "'%s' : bad operand" +2172 "'%Fs' : actual is not a pointer : parameter %d" +2173 "'%Fs' : actual is not a pointer : parameter %d, parameter list %d" +2174 "'%Fs' : actual has type void : parameter %d, parameter list %d" +2175 "'%Fs' : unresolved external" /* QC */ +2176 "static far data not supported" /* QC */ +2177 "constant too big" +2178 "'%s' : storage class for same_seg variables must be 'extern'" +2179 "'%Fs' : was used in same_seg, but storage class is no longer 'extern'" +2180 "controlling expression has type 'void'" +2181 "pragma requires command line option '%s'" /* QC */ +2182 "'%Fs' : 'void' on variable" +2183 "'%Fs' : 'interrupt' function must be 'far'" +2184 "'%Fs' : '%s' function cannot be 'pascal/fortran'" +2186 "'%Fs' : 'saveregs/interrupt' modifiers mutually exclusive" +2187 "cast of near function pointer to far function pointer" +2188 "#error : %s" +2190 "'%s' : is a text segment" +2191 "'%s' : is a data segment" +2192 "'%s' : function has already been defined" +2000 "UNKNOWN ERROR\n\t\tContact Microsoft Technical Support" + + /* warnings */ + +4001 "macro '%s' requires parameters" +4002 "too many actual parameters for macro '%s'" +4003 "not enough actual parameters for macro '%s'" +4004 "missing close parenthesis after 'defined'" +4005 "'%s' : redefinition" +4006 "#undef expected an identifier" +4009 "string too big, trailing chars truncated" +4011 "identifier truncated to '%s'" +4012 "float constant in a cross compilation" +4013 "constant too big" +4014 "'%Fs' : bit-field type must be unsigned" +4015 "'%Fs' : bit-field type must be integral" +4016 "'%s' : no function return type, using 'int' as default" +4017 "cast of int expression to far pointer" +4020 "'%Fs' : too many actual parameters" +4021 "'%Fs' : too few actual parameters" +4022 "'%Fs' : pointer mismatch : parameter %d" +4024 "'%Fs' : different types : parameter %d" +4025 "function declaration specified variable argument list" +4026 "function was declared with formal argument list" +4027 "function was declared without formal argument list" +4028 "parameter %d declaration different" +4029 "declared parameter list different from definition" +4030 "first parameter list is longer than the second" +4031 "second parameter list is longer than the first" +4032 "unnamed struct/union as parameter" +4033 "function must return a value" +4034 "sizeof returns 0" +4035 "'%Fs' : no return value" +4036 "unexpected formal parameter list" +4037 "'%Fs' : formal parameters ignored" +4038 "'%Fs' : formal parameter has bad storage class" +4039 "'%Fs' : function used as an argument" +4040 "near/far/huge on '%Fs' ignored" +4041 "formal parameter '%s' is redefined" +4042 "'%Fs' : has bad storage class" +4044 "huge on '%Fs' ignored, must be an array" +4045 "'%s' : array bounds overflow" +4046 "'&' on function/array, ignored" +4047 "'%s' : different levels of indirection" +4048 "array's declared subscripts different" +4049 "'%s' : indirection to different types" +4051 "data conversion" +4052 "different enum types" +4053 "at least one void operand" +4060 "conversion of long address to short address" /* QC, c23 */ +4061 "long/short mismatch in argument : conversion supplied" /* QC, c23 */ +4062 "near/far mismatch in argument : conversion supplied" /* QC, c23 */ +4067 "unexpected characters following '%s' directive - newline expected" +4068 "unknown pragma" +4071 "'%Fs' : no function prototype given" +4074 "non standard extension used - '%s'" +4075 "size of switch expression or case constant too large - converted to int" +4076 "'%s' : may be used on integral types only" +4077 "unknown check_stack option" +4079 "unexpected token '%s'" +4080 "expected 'identifier' for segment name, found '%s'" +4081 "expected a comma, found '%s'" +4082 "expected an identifier, found '%s'" +4083 "expected '(', found '%s'" +4084 "expected a pragma keyword, found '%s'" +4085 "expected [on | off]" +4086 "expected [1 | 2 | 4]" +4087 "'%Fs' : declared with 'void' parameter list" +4088 "'%Fs' : pointer mismatch : parameter %d, parameter list %d" +4089 "'%Fs' : different types : parameter %d, parameter list %d" +4090 "different 'const' attributes" +4091 "no symbols were declared" +4092 "untagged enum/struct/union declared no symbols" +4093 "unescaped newline in character constant in non-active code" +4094 "unexpected newline" +4095 "expected ')', found '%s'" +4096 "huge treated as far" /* QC */ +4098 "void function returning a value" +4099 "expected ')', (too many arguments?)" +4100 "'%Fs' : unreferenced formal parameter" +4101 "'%Fs' : unreferenced local variable" +4102 "'%Fs' : unreferenced label" +4103 "'%Fs' : function definition used as prototype" +4104 "'%s' : near data in same_seg pragma, ignored" +4105 "'%Fs' : code modifiers only on function or pointer to function" +4106 "pragma requires integer between 1 and 127" +4107 "pragma requires integer between 15 and 255" +4108 "pragma requires integer between 79 and 132" +4109 "unexpected identifier '%s'" +4110 "unexpected token 'int constant'" +4111 "unexpected token 'string'" +4112 "macro name '%s' is reserved, %s ignored" +4113 "function parameter lists differed" +4000 "UNKNOWN WARNING\n\t\tContact Microsoft Technical Support" diff --git a/v4.0/src/TOOLS/C1.EXE b/v4.0/src/TOOLS/C1.EXE new file mode 100644 index 0000000..a60e821 Binary files /dev/null and b/v4.0/src/TOOLS/C1.EXE differ diff --git a/v4.0/src/TOOLS/C1L.EXE b/v4.0/src/TOOLS/C1L.EXE new file mode 100644 index 0000000..e90c0aa Binary files /dev/null and b/v4.0/src/TOOLS/C1L.EXE differ diff --git a/v4.0/src/TOOLS/C2.EXE b/v4.0/src/TOOLS/C2.EXE new file mode 100644 index 0000000..438ce70 Binary files /dev/null and b/v4.0/src/TOOLS/C2.EXE differ diff --git a/v4.0/src/TOOLS/C23.ERR b/v4.0/src/TOOLS/C23.ERR new file mode 100644 index 0000000..966407d --- /dev/null +++ b/v4.0/src/TOOLS/C23.ERR @@ -0,0 +1,73 @@ + /* fatals */ + +1001 "Internal Compiler Error\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Technical Support" +1002 "out of heap space" +1003 "error count exceeds %d; stopping compilation" +1004 "unexpected EOF" +1005 "string too big for buffer" +1006 "write error on compiler intermediate file" +1007 "unrecognized flag '%s' in '%s'" +1027 "DGROUP data allocation exceeds 64K" +1028 "infinite recursion in cnstrpush" +1029 "there are > 512 bytes of arguments" +1030 "there are > 512 bytes of local variables" +1031 "limit exceeded for nesting function calls" +1032 "cannot open object listing file '%s'" +1033 "cannot open assembly language output file '%s'" +1034 "cannot open source file '%s'" +1035 "expression too complex, please simplify" +1036 "cannot open source listing file '%s'" +1037 "cannot open object file '%s'" +1038 "unexpected end of file in Pass 3" +1039 "unrecoverable heap overflow in Pass 3" +1040 "unexpected EOF in source file '%s'" +1041 "cannot open compiler intermediate file - no more files" +1042 "cannot open compiler intermediate file - no such file or directory" +1043 "cannot open compiler intermediate file" +1044 "out of disk space for compiler intermediate file" +1045 "floating-point overflow" +1046 "bad %s flag, would overwrite '%s' with '%s'" +1047 "too many %s flags, '%s'" +1048 "unknown option '%c' in '%s'" +1049 "invalid numerical argument '%s'" +1050 "%s : code segment too large" +1051 "program too complex" +1058 "floating point expression too complex - would overflow NDP stack" +1064 "too many text segments" +1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Technical Support" + + /* errors */ + +2023 "divide by 0" +2024 "mod by 0" +2125 "%s : allocation exceeds 64K" +2126 "%s : automatic allocation exceeds %s" +2127 "parameter allocation exceeds 32K" +2128 "%s : huge array cannot be aligned to segment boundary" +2129 "static function '%s' not found" +2189 "constant item, -Gm, and data_seg pragma are incompatible" +2000 "UNKNOWN ERROR\n\t\tContact Microsoft Technical Support" + + /* warnings */ + +4054 "insufficient memory may affect optimization" +4055 "constant moved out of CONST even though -Gm specified" +4056 "overflow in constant arithmetic" +4057 "overflow in constant multiplication" +4058 "address of frame variable taken, DS != SS" +4059 "segment lost in conversion" +4060 "conversion of long address to short address" +4061 "long/short mismatch in argument : conversion supplied" +4062 "near/far mismatch in argument : conversion supplied" +4063 "%s : function too large for post-optimizer" +4064 "procedure too large, skipping %s optimization and continuing" +4065 "recoverable heap overflow in post-optimizer - some optimizations may be missed" +4066 "local symbol table overflow - some local symbols may be missing in listings" +4069 "conversion of near pointer to long integer" +4070 "function called as procedure" +4072 "Insufficient memory to process debugging information" +4073 "scoping too deep, deepest scoping merged when debugging" +4078 "loss of debugging information caused by optimization" +4185 "near call to %s in different segment" +4186 "string too long. Truncated to %d characters" +4000 "UNKNOWN WARNING\n\t\tContact Microsoft Technical Support" diff --git a/v4.0/src/TOOLS/C3.EXE b/v4.0/src/TOOLS/C3.EXE new file mode 100644 index 0000000..072ccaa Binary files /dev/null and b/v4.0/src/TOOLS/C3.EXE differ diff --git a/v4.0/src/TOOLS/CL.ERR b/v4.0/src/TOOLS/CL.ERR new file mode 100644 index 0000000..bd4c9e1 --- /dev/null +++ b/v4.0/src/TOOLS/CL.ERR @@ -0,0 +1,52 @@ + /* fatal messages */ + +1001 "could not execute '%s'" +1002 "too many open files, cannot redirect '%s'" +1000 "UNKNOWN COMMAND LINE FATAL ERROR\n\t\tContact Microsoft Technical Support" + + /* error messages */ + +2001 "too many symbols predefined with -D" +2002 "a previously defined model specification has been overridden" +2003 "missing source file name" +2007 "bad %s flag, would overwrite '%s' with '%s'" +2008 "too many %s flags, '%s'" +2009 "unknown option '%c' in '%s'" +2010 "unknown floating point option" +2011 "only one floating point model allowed" +2012 "too many linker flags on command line" +2013 "incomplete model specification" +/* 2014 "-ND not allowed with -Ad" */ +2015 "assembly files are not handled" +2016 "-Gw and -ND %s are incompatible" +2017 "-Gw and -Au flags are incompatible" +2018 "cannot open linker cmd file" +2019 "cannot overwrite the source file, '%s'" +2020 "-Gc option requires extended keywords to be enabled (-Ze)" +2021 "invalid numerical argument '%s'" +2022 "cannot open help file, '%s'" +2023 "invalid model specification - small model only" +2024 "-Gm and -ND %s are incompatible" +2025 "missing argument" +2000 "UNKNOWN COMMAND LINE ERROR\n\t\tContact Microsoft Technical Support" + + /* warning messages */ + +4001 "listing has precedence over assembly output" +4002 "ignoring unknown flag '%s'" +4003 "80186/286 selected over 8086 for code generation" +4004 "optimizing for time over space" +4005 "could not execute '%s';\nPlease enter new file name (full path) or Ctrl-C to quit: " +4006 "only one of -P/-E/-EP allowed, -P selected" +4007 "-C ignored (must also specify -P or -E or -EP)" +4008 "non-standard model -- defaulting to large model libraries" +4009 "threshold only for far/huge data, ignored" +4010 "-Gp not implemented, ignored" +4011 "preprocessing overrides source listing" +4012 "function declarations override source listing" +4013 "combined listing has precedence over object listing" +4014 "invalid value %d for '%s'. Default %d is used" +4015 "different default models - defaulting to %s model" +4017 "conflicting stack checking options - stack checking disabled" +4019 "string too long. Truncated to %d characters" +4000 "UNKNOWN COMMAND LINE WARNING\n\t\tContact Microsoft Technical Support" diff --git a/v4.0/src/TOOLS/CL.EXE b/v4.0/src/TOOLS/CL.EXE new file mode 100644 index 0000000..bfa8f4a Binary files /dev/null and b/v4.0/src/TOOLS/CL.EXE differ diff --git a/v4.0/src/TOOLS/CL.HLP b/v4.0/src/TOOLS/CL.HLP new file mode 100644 index 0000000..f8e5da0 --- /dev/null +++ b/v4.0/src/TOOLS/CL.HLP @@ -0,0 +1,79 @@ +C COMPILER OPTIONS +-MEMORY MODEL- +/AS small model (default) +/AC compact model +/AM medium model +/AL large model +/AH huge model +-OPTIMIZATION- +/O enable optimization (same as /Ot) +/Oa ignore aliasing +/Od disable optimizations +/Oi enable intrinsic functions +/Ol enable loop optimizations +/On disable "unsafe" optimizations +/Op enable precision optimizations +/Or disable in_line return +/Os optimize for space +/Ot optimize for speed (default) +/Ox max. optimization (/Oailt /Gs) +-CODE GENERATION- +/G0 8086 instructions (default) +/G1 186 instructions +/G2 286 instructions +/Gm put strings in constant segment +/Gc Pascal style function calls +/Gs no stack checking +/Gt[number] data size threshold +-OUTPUT FILES- +/Fa[assembly listing file] +/Fb[bound executable file] +/Fc[mixed source/object listing file] +/Fe +/Fl[object listing file] +/Fm[map file] +/Fo +/Fs[source listing file] +-PREPROCESSOR- +/C don't strip comments +/D[=text] define macro +/E preprocess to stdout +/EP same as /E but no #line +/I add #include path +/P preprocess to file +/U remove predefined macro +/u remove all predefined macros +/X ignore "standard places" +-LANGUAGE- +/Za disable extensions +/Zd line number information +/Ze enable extensions (default) +/Zg generate declarations +/Zi symbolic debugging information +/Zl remove default library info +/Zp[n] pack structs on n-byte boundary +/Zs syntax check only +-FLOATING POINT- +/FPa calls with altmath +/FPc calls with emulator +/FPc87 calls with 8087 library +/FPi inline with emulator (default) +/FPi87 inline with 8087 +-SOURCE LISTING- +/Sl set line width +/Sp set page length +/St set title string +/Ss set subtitle string +-MISCELLANEOUS- +/c compile only, no link +/H external name length +/J default char type is unsigned +/Tc compile file without .c +/V set version string +/W warning level +-LINKING- +/F stack size (hex. bytes) +/Lc link compatibility mode executable +/Lr link compatibility mode executable +/Lp link protect mode executable +/link [linker_options_and_libraries] diff --git a/v4.0/src/TOOLS/COMPRESS.COM b/v4.0/src/TOOLS/COMPRESS.COM new file mode 100644 index 0000000..df8b0d1 Binary files /dev/null and b/v4.0/src/TOOLS/COMPRESS.COM differ diff --git a/v4.0/src/TOOLS/CONVERT.EXE b/v4.0/src/TOOLS/CONVERT.EXE new file mode 100644 index 0000000..0511410 Binary files /dev/null and b/v4.0/src/TOOLS/CONVERT.EXE differ diff --git a/v4.0/src/TOOLS/DBOF.EXE b/v4.0/src/TOOLS/DBOF.EXE new file mode 100644 index 0000000..1d46e71 Binary files /dev/null and b/v4.0/src/TOOLS/DBOF.EXE differ diff --git a/v4.0/src/TOOLS/EXE2BIN.EXE b/v4.0/src/TOOLS/EXE2BIN.EXE new file mode 100644 index 0000000..8f42567 Binary files /dev/null and b/v4.0/src/TOOLS/EXE2BIN.EXE differ diff --git a/v4.0/src/TOOLS/EXEC.EXE b/v4.0/src/TOOLS/EXEC.EXE new file mode 100644 index 0000000..93176b7 Binary files /dev/null and b/v4.0/src/TOOLS/EXEC.EXE differ diff --git a/v4.0/src/TOOLS/EXEFIX.EXE b/v4.0/src/TOOLS/EXEFIX.EXE new file mode 100644 index 0000000..30728e6 Binary files /dev/null and b/v4.0/src/TOOLS/EXEFIX.EXE differ diff --git a/v4.0/src/TOOLS/EXEMOD.EXE b/v4.0/src/TOOLS/EXEMOD.EXE new file mode 100644 index 0000000..a8bef05 Binary files /dev/null and b/v4.0/src/TOOLS/EXEMOD.EXE differ diff --git a/v4.0/src/TOOLS/EXEPACK.EXE b/v4.0/src/TOOLS/EXEPACK.EXE new file mode 100644 index 0000000..79af609 Binary files /dev/null and b/v4.0/src/TOOLS/EXEPACK.EXE differ diff --git a/v4.0/src/TOOLS/LIB.EXE b/v4.0/src/TOOLS/LIB.EXE new file mode 100644 index 0000000..fef21fb Binary files /dev/null and b/v4.0/src/TOOLS/LIB.EXE differ diff --git a/v4.0/src/TOOLS/LINK.EXE b/v4.0/src/TOOLS/LINK.EXE new file mode 100644 index 0000000..a5b1be6 Binary files /dev/null and b/v4.0/src/TOOLS/LINK.EXE differ diff --git a/v4.0/src/TOOLS/MASM.EXE b/v4.0/src/TOOLS/MASM.EXE new file mode 100644 index 0000000..eacbb63 Binary files /dev/null and b/v4.0/src/TOOLS/MASM.EXE differ diff --git a/v4.0/src/TOOLS/MENUBLD.EXE b/v4.0/src/TOOLS/MENUBLD.EXE new file mode 100644 index 0000000..1acabed Binary files /dev/null and b/v4.0/src/TOOLS/MENUBLD.EXE differ diff --git a/v4.0/src/TOOLS/NMAKE.EXE b/v4.0/src/TOOLS/NMAKE.EXE new file mode 100644 index 0000000..3376989 Binary files /dev/null and b/v4.0/src/TOOLS/NMAKE.EXE differ diff --git a/v4.0/src/TOOLS/NOSRVBLD.EXE b/v4.0/src/TOOLS/NOSRVBLD.EXE new file mode 100644 index 0000000..0258d2c Binary files /dev/null and b/v4.0/src/TOOLS/NOSRVBLD.EXE differ diff --git a/v4.0/src/TOOLS/TOOLS.INI b/v4.0/src/TOOLS/TOOLS.INI new file mode 100644 index 0000000..3c6a267 --- /dev/null +++ b/v4.0/src/TOOLS/TOOLS.INI @@ -0,0 +1,73 @@ + +[nmake] + +############################################################################# +# # +# These are the built in rules and path definitions used by the new MS Make # +# Utility (NMAKE). The following variables are set externaly (ie set in the # +# individual makefiles. # +# # +# extasw = The 'extra assembly switch' variable is optionaly used in the # +# makefile to specify special MASM command line switches. # +# # +# extcsw = The 'extra C switch' variable is optionaly used in the makefile # +# to specify special C compiler command line switches. # +# # +# inc = The include file search path from the utility being built to the # +# INC directory. Used if needed. # +# # +# dos = The include file search path from the utility being built to the # +# DOS directory. Used if needed. # +# # +# hinc = The include file search path from the utility being built to the # +# H directory. Used if needed for C source compilation. # +# # +############################################################################# + +########## Definitionms for the Assembler ########## + +asm =masm +aflags =-Mx -t $(extasw) +ainc =-I. -I$(inc) -I$(dos) + +########## Definitions for C compiler ########## + +cc =cl +cflags =-AS -Os -Zp $(extcsw) +cinc =-I. -I$(hinc) + +########## Definitions for linker ########## + +link =link + +########## Built-in rules ########## + +.SUFFIXES: +.SUFFIXES: .c .obj .lst .exe .com .cod .inc .skl .cl1 .ctl .asm .idx .msg + +.asm.obj: + $(asm) $(aflags) $(ainc) $*.asm,$*.obj; + +.asm.lst: + $(asm) -l $(aflags) $(ainc) $*.asm; + +.c.obj: + $(cc) -c $(cflags) $(cinc) -Fo$*.obj $*.c + +.c.lst: + $(cc) -c $(cflags) $(cinc) -fc$*.cod -fo$*.obj $*.c + +.exe.com: + reloc $*.exe $*.com + +.skl.cl1: + nosrvbld $*.skl $(msg)\$(COUNTRY).msg + +.skl.ctl: + buildmsg $(msg)\$(COUNTRY) $*.skl + +.msg.idx: + attrib -R $*.msg + buildidx $*.msg + attrib +R $*.msg +