diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/softpc.new/bios | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/mvdm/softpc.new/bios')
27 files changed, 20460 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/bios/biosbop.inc b/private/mvdm/softpc.new/bios/biosbop.inc new file mode 100644 index 000000000..57ca401c1 --- /dev/null +++ b/private/mvdm/softpc.new/bios/biosbop.inc @@ -0,0 +1,10 @@ + +bop MACRO callid + db 0c4h,0c4h,callid + endm + +BIOS_PRINTER_IO equ 17h +PRNIO_EXECUTE equ -1 +PRNIO_FLUSH equ 0 +PRNIO_OPEN equ 1 +PRNIO_CLOSE equ 2 diff --git a/private/mvdm/softpc.new/bios/biosseg.inc b/private/mvdm/softpc.new/bios/biosseg.inc new file mode 100644 index 000000000..9e2a54536 --- /dev/null +++ b/private/mvdm/softpc.new/bios/biosseg.inc @@ -0,0 +1,39 @@ +; BIOSSEG.INC +; +; This file defines the segment structure of the BIOS. +; It should be included at the beginning of each source file. +; All further segment declarations in the file can then be done by just +; by specifying the segment name, with no attribute, class, or align type. + + +datagrp group Bios_Data,Bios_Data_Init + + +Bios_Data segment word public 'Bios_Data' +Bios_Data ends + +Bios_Data_Init segment word public 'Bios_Data_Init' +Bios_Data_Init ends + +Filler segment para public 'Filler' +Filler ends + +Bios_Code segment word public 'Bios_Code' +Bios_Code ends + +Filler2 segment para public 'Filler2' +Filler2 ends + +sysinitgrp group sysinitseg, SpcKbdSeg, SpcMseSeg, SpcEmmSeg + +SysInitSeg segment word public 'system_init' +SysInitSeg ends + +SpcKbdSeg segment para public 'SoftpcKeyboard' +SpcKbdSeg ends + +SpcMseSeg segment para public 'SoftpcMouse' +SpcMseSeg ends + +SpcEmmSeg segment para public 'SoftpcEmm' +SpcEmmSeg ends diff --git a/private/mvdm/softpc.new/bios/biostruc.inc b/private/mvdm/softpc.new/bios/biostruc.inc new file mode 100644 index 000000000..5afb16ac9 --- /dev/null +++ b/private/mvdm/softpc.new/bios/biostruc.inc @@ -0,0 +1,101 @@ +; 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/private/mvdm/softpc.new/bios/devmark.inc b/private/mvdm/softpc.new/bios/devmark.inc new file mode 100644 index 000000000..4b55e6ad8 --- /dev/null +++ b/private/mvdm/softpc.new/bios/devmark.inc @@ -0,0 +1,24 @@ +;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_spc equ 'Q' ;used for spckbd,spcmse + +setbrkdone equ 00000001b +for_devmark equ 00000010b +not_for_devmark equ 11111101b diff --git a/private/mvdm/softpc.new/bios/dosmsg.cmd b/private/mvdm/softpc.new/bios/dosmsg.cmd new file mode 100644 index 000000000..daa8f6150 --- /dev/null +++ b/private/mvdm/softpc.new/bios/dosmsg.cmd @@ -0,0 +1,6 @@ +cd ..\messages +chmode -r %2 +..\tools\buildidx %2 +chmode +r %2 +cd ..\bios +..\tools\nosrvbld %1 ..\messages\%2 diff --git a/private/mvdm/softpc.new/bios/makefile b/private/mvdm/softpc.new/bios/makefile new file mode 100644 index 000000000..b2e879795 --- /dev/null +++ b/private/mvdm/softpc.new/bios/makefile @@ -0,0 +1,102 @@ +#************************** makefile for NTIO.SYS *************************** + +include ..\..\make.inc + +tpath =..\..\tools +lpath =..\..\..\..\tools.os2 + +dest =ntio.sys + +# +####################### dependencies begin here. ######################### +# + + +all: $(dest) + binplace $(dest) + binplace ntio.sym + +inc.lst: inc.asm + +clean: + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist msbio.cl? del msbio.cl? + if exist ntio.sys del ntio.sys + +msbio.cl1: msbio.skl \ + $(msg)\$(COUNTRY).msg + +msbio1.obj msbio1.lst: msbio1.asm $(inc)\msbdata.inc \ + $(inc)\devsym.inc msequ.inc $(cinc)\vint.inc + +mschar.obj mschar.lst: mschar.asm biosbop.inc $(inc)\devsym.inc \ + $(inc)\ioctl.inc msequ.inc msgroup.inc $(cinc)\vint.inc + + +msend.obj msend.lst: msend.asm + +msinit.obj msinit.lst: msinit.asm $(inc)\VERSIONA.inc \ + $(inc)\dbcs.sw $(inc)\dirent.inc $(inc)\dosmac.inc $(inc)\dosmac.inc \ + $(inc)\dossym.inc $(inc)\error.inc $(inc)\version.inc biostruc.inc \ + msequ.inc msgroup.inc $(cinc)\dossvc.inc $(cinc)\vint.inc + +msint13.obj msint13.lst: msint13.asm biostruc.inc $(cinc)\vint.inc \ + msequ.inc msgroup.inc + + +sysconf.obj sysconf.lst: sysconf.asm $(inc)\doscntry.inc \ + $(inc)\parse.asm $(inc)\psdata.inc $(inc)\smifssym.inc \ + $(inc)\syscall.inc $(inc)\sysvar.inc $(inc)\version.inc devmark.inc \ + $(inc)\devsym.inc $(cinc)\dossvc.inc $(cinc)\cmdsvc.inc + +sysimes.obj sysimes.lst: sysimes.asm + +spckbd.obj spckbd.lst: spckbd.asm $(cinc)\vint.inc + +spcmse.obj spcmse.lst: spcmse.asm $(cinc)\vint.inc + +spcemm.obj spcemm.lst: spcemm.asm $(cinc)\vint.inc + +sysinit1.obj sysinit1.lst: sysinit1.asm $(inc)\VERSIONA.inc \ + $(inc)\arena.inc $(inc)\buffer.inc $(inc)\cputype.inc \ + $(cinc)\curdir.inc $(inc)\dbcs.sw $(inc)\dirent.inc $(inc)\dosmac.inc \ + $(inc)\dossym.inc $(inc)\error.inc $(inc)\exe.inc \ + $(inc)\pdb.inc $(inc)\sf.inc $(inc)\smifssym.inc $(inc)\syscall.inc \ + $(inc)\sysvar.inc $(inc)\version.inc biostruc.inc $(cinc)\vint.inc \ + devmark.inc $(inc)\devsym.inc $(inc)\ioctl.inc $(cinc)\dossvc.inc \ + $(cinc)\cmdsvc.inc + +sysinit2.obj sysinit2.lst: sysinit2.asm $(inc)\copyrigh.inc \ + $(inc)\doscntry.inc $(inc)\syscall.inc $(inc)\version.inc \ + devmark.inc $(inc)\devsym.inc $(inc)\ioctl.inc + +$(dest): msbio.cl1 msbio1.obj mschar.obj msint13.obj msinit.obj \ + sysinit1.obj spckbd.obj spcmse.obj spcemm.obj sysconf.obj \ + sysinit2.obj sysimes.obj msend.obj msbio.lnk +!IFDEF NTVDM_BASED_BUILD + link16 $(link_opts) @msbio.lnk +!ELSE + $(lpath)\link $(link_opts) @msbio.lnk +!ENDIF + mapsym ntio +!IFDEF NTVDM_BASED_BUILD + reloc ntio.exe $(dest) 70 +!ELSE + $(tpath)\reloc ntio.exe $(dest) 70 +!ENDIF + del ntio.exe + +# sudeepb 04-Mar-1991 : NT Message file handling for DOSEm. +# +# Many of the above .asm files needed for NTIO.SYS include "message class" +# files (i.e. msbio.cl3 etc.). These files have the message strings extracted +# from msbio.skl and internationalized using ..\messages\<COUNTRY>.msg file. +# The utilities needed for getting these *.cl? files from *.skl and *.msg +# files are all real mode, hence their building rules are not included in +# this makefile. Use dosmsg.bat command from 3xbox to build these *.cl? files. +# syntax for dosmsg.bat is "dosmsg <file>.skl <country>.msg". For example +# building *.cl> files for bios for usa version, the command will be +# "dosmsg msbio.skl usa-ms.msg" diff --git a/private/mvdm/softpc.new/bios/msbio.cl3 b/private/mvdm/softpc.new/bios/msbio.cl3 new file mode 100644 index 000000000..09b8ae4e5 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.cl3 @@ -0,0 +1,62 @@ +; msbio.cl3 + + +;_______________________ + +BADOPM DB 13,10,"Unrecognized command in CONFIG.SYS" + +;_______________________ + +CRLFM DB 13,10,"$" + +;_______________________ + +BadParm DB 13,10,"Bad command or parameters - $" + +;_______________________ + +BADSIZ_PRE DB 13,10,"Sector size too large in file $" + +;_______________________ + +BADLD_PRE DB 13,10,"Bad or missing $" + +;_______________________ + +BADCOM DB "Command Interpreter",0 + +;_______________________ + +BADCOUNTRY DB 13,10,"Invalid country code or code page",13,10,"$" + +;_______________________ + +BADCOUNTRYCOM DB 13,10,"Error in COUNTRY command",13,10,"$" + +;_______________________ + +INSUFMEMORY DB 13,10, "Insufficient memory for COUNTRY.SYS file",13,10,"$" + +;_______________________ + +BADMEM DB 13,10,"Configuration too large for memory",13,10,"$" + +;_______________________ + +BADBLOCK DB 13,10,"Too many block devices",13,10,"$" + +;_______________________ + +BADSTACK DB 13,10,"Invalid STACK parameters",13,10,"$" + +;_______________________ + +BADORDER DB 13,10,"Incorrect order in CONFIG.SYS line ","$" + +;_______________________ + +ERRORCMD DB "Error in CONFIG.SYS line ","$" + +;_______________________ + +toomanydrivesmsg DB "WARNING! Logical drives past Z: exist and will be ignored",13,10,"$" diff --git a/private/mvdm/softpc.new/bios/msbio.cl4 b/private/mvdm/softpc.new/bios/msbio.cl4 new file mode 100644 index 000000000..546f30ae9 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.cl4 @@ -0,0 +1,6 @@ +; msbio.cl4 + + +;_______________________ + +Mem_alloc_err DB 13,10,"Memory allocation error ","$" diff --git a/private/mvdm/softpc.new/bios/msbio.cl5 b/private/mvdm/softpc.new/bios/msbio.cl5 new file mode 100644 index 000000000..ca3ebdece --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.cl5 @@ -0,0 +1,7 @@ +; msbio.cl5 + + +;_______________________ + +FATAL_MSG DB 0DH,0AH,7,0DH,0AH, "Internal stack overflow",0DH,0AH + DB "System halted",0DH,0AH,"$" diff --git a/private/mvdm/softpc.new/bios/msbio.cl6 b/private/mvdm/softpc.new/bios/msbio.cl6 new file mode 100644 index 000000000..401af43a9 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.cl6 @@ -0,0 +1,10 @@ +; msbio.cl6 + + +;_______________________ + +DOSLOMSG DB "HMA not available : Loading DOS low",13,10,"$" + +;_______________________ + +FEMSG DB "Fatal Error:Cannot allocate Memory for DOS", 13, 10, "$" diff --git a/private/mvdm/softpc.new/bios/msbio.lnk b/private/mvdm/softpc.new/bios/msbio.lnk new file mode 100644 index 000000000..425da9c1b --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.lnk @@ -0,0 +1,3 @@ +msbio1+mschar+msint13+spckbd+spcmse+spcemm+ +msinit+sysinit1+sysconf+sysinit2+sysimes+ +msend,ntio.exe,ntio.map; diff --git a/private/mvdm/softpc.new/bios/msbio.skl b/private/mvdm/softpc.new/bios/msbio.skl new file mode 100644 index 000000000..3636eba2d --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio.skl @@ -0,0 +1,95 @@ +;============================================================================== +;REVISION HISTORY: +;============================================================================== + +;================== +:class 3 +;================== + +; displayed when there is a bad command in CONFIG.SYS. '$' TERMINATED, note +; that this message includes crlfm! + +:def 03 BADOPM DB 13,10,"Unrecognized command in CONFIG.SYS" +:def 04 CRLFM DB 13,10,'$' +:def 22 BadParm db 13,10,"Bad command or parameters - $" + +;displayed when installed device specifies too large a sector size.'$' terminated. +; FORM: <BADSIZ_PRE>device name<BADSIZ_POST> +:def 05 BADSIZ_PRE DB 13,10,"Sector size too large in file $" + +;displayed when installed device cannot be found. '$' terminated. +; FORM: <BADLD_PRE>device name<BADLD_POST> +:def 06 BADLD_PRE DB 13,10,"Bad or missing $" + +;displayed when command interpreter is not found. NUL terminated. +; FORM: <BADLD_PRE><BADCOM><BADLD_POST> +:def 07 BADCOM DB "Command Interpreter",0 + +;displayed when country code, code page combination was not found in country.sys file. '$' terminated. +; FORM: <BADCOUNTRY> +:def 08 BADCOUNTRY DB 13,10,"Invalid country code or code page",13,10,"$" + +;displayed when code page id is missing or wrong syntax. +; FORM: <BADCOUNTRYCOM> +:def 09 BADCOUNTRYCOM DB 13,10,"Error in COUNTRY command",13,10,"$" + +;displayed when the memory left is not sufficient to handle COUTRY.SYS file +; FORM: <INSUFMEMORY> +:def 10 INSUFMEMORY DB 13,10, "Insufficient memory for COUNTRY.SYS file",13,10,"$" + +; displayed 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,"$" + +; displayed 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,"$" + +; displayed when the attempt is made to install a stack with invalid +; combinations of # of stacks, stack size. +:def 13 BADSTACK DB 13,10,"Invalid STACK parameters",13,10,"$" + +; - displayed when encountering a command that is not "install=" after +; we had a "Install=" command. +; 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 ","$" + +; - displayed 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 ","$" + +; displayed when more than 24 fixed disk partitions are found ; M029 +:def 24 toomanydrivesmsg db "WARNING! Drives past Z: exist and will be ignored" ; M029 + +;================== +:class 4 +;================== +;MSBIO SYSINIT +;Message for SYSINIT_BASE program. +:def 16 Mem_alloc_err db 13,10,"Memory allocation error","$" + + +;================== +:class 5 +;================== + +; PUBLIC FATAL_MSG +:def 17 FATAL_MSG DB 0DH,0AH,7,0DH,0AH + DB "Internal stack overflow",0DH,0AH + DB "System halted",0DH,0AH,"$" +; +;================== +:class 6 +;================== + +; - displayed when DOS loads due to non-availability of HMA. +; +:def 18 DOSLOMSG DB "HMA not available : Loading DOS low", 13, 10, "$" +:def 23 FEMSG DB "Fatal Error:Cannot allocate Memory for DOS", 13, 10, "$" + + +;:END + + diff --git a/private/mvdm/softpc.new/bios/msbio1.asm b/private/mvdm/softpc.new/bios/msbio1.asm new file mode 100644 index 000000000..e115bd0d0 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msbio1.asm @@ -0,0 +1,955 @@ + page ,160 + title msbio1.asm - Bios_Data definition and device driver entry/exit + +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +; +;---------------------------------------------------------------------------- +; + include version.inc ; set build flags + include biosseg.inc ; define BIOS segments + + include devsym.inc + include msequ.inc + include vint.inc + + +; Assembly conditional for stack switching +; +STACKSW equ 1 + +Bios_Data segment + + assume cs:Bios_Data + public BData_start +BData_start: + + + assume ds:nothing,es:nothing + + public hdrv_pat +hdrv_pat label word ; patched by msinit + assume cs:Bios_Data + + extrn init:near ; this is in msinit + + jmp init ; go to initialization code + + +; define some stuff that is also used by msdos.sys from an include file + +In_Bios = 0ffffh ; define flag for msbdata.inc + include msbdata.inc + + + public inHMA,xms +inHMA db 0 ; flag indicates we're running from HMA +xms dd 0 ; entry point to xms if above is true + + align 4 + + public ntvdmstate +ntvdmstate dd 0 +IF 2 +.errnz ntvdmstate-BData_start-FIXED_NTVDMSTATE_OFFSET +ENDIF + + + 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 + public zeroseg +zeroseg dw 0 ; easy way to load segment registers with zero + + public auxnum +auxnum dw 0 ;which aux device was requested + + + public res_dev_list + +res_dev_list label byte + p_attr = chardev+outtilbusy+dev320+IOQUERY+DEVOPCL +; ** p_attr = chardev+outtilbusy+dev320 + + sysdev <auxdev2,8013h,strategy,con_entry,'CON '> +auxdev2 sysdev <prndev2,8000h,strategy,aux0_entry,'AUX '> +prndev2 sysdev <timdev,p_attr,strategy,prn0_entry,'PRN '> +timdev sysdev <com1dev,8008h,strategy,tim_entry,'CLOCK$ '> +com1dev sysdev <lpt1dev,8000h,strategy,aux0_entry,'COM1 '> +lpt1dev sysdev <lpt2dev,p_attr,strategy,prn1_entry,"LPT1 "> +lpt2dev sysdev <lpt3dev,p_attr,strategy,prn2_entry,"LPT2 "> +lpt3dev sysdev <com2dev,p_attr,strategy,prn3_entry,"LPT3 "> +com2dev sysdev <com3dev,8000h,strategy,aux1_entry,"COM2 "> +com3dev sysdev <com4dev,8000h,strategy,aux2_entry,"COM3 "> +com4dev dw -1,Bios_Data,8000h,strategy,aux3_entry + db "COM4 " + + + public RomVectors +RomVectors label byte + public Old10, Old15, Old19, Old1B + db 10h ; M028 +Old10 dd (?) ; M028 + db 15h +Old15 dd (?) + db 19h +Old19 dd (?) + db 1bh +Old1B dd (?) +EndRomVectors equ $ + public NUMROMVECTORS +NUMROMVECTORS equ ((EndRomVectors - RomVectors)/5) + + public spc_mse_int10 +spc_mse_int10 dd (?) + + public int29Perf +int29Perf dd (?) + + + public keyrd_func + public keysts_func + +; moved altah to inc\msbdata.inc so it could go in instance table in DOS + +keyrd_func db 0 ; default is conventional keyboard read +keysts_func db 1 ; default is conventional keyboard status check. + + public printdev +printdev db 0 ; index into above array + + public multrk_flag +multrk_flag dw 0 + +; 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. + + public wait_count +wait_count dw 4 dup (50h) ; array of retry counts for printer + + public int19sem +int19sem db 0 ; indicate that all int 19 + ; initialization is complete + +; we assume the following remain contiguous and their order doesn't change +i19_lst: + irp aa,<02,08,09,0a,0b,0c,0d,0e,70,72,73,74,76,77> + public int19old&aa + db aa&h ; store the number as a byte +int19old&aa dd -1 ;orignal hardware int. vectors for int 19h. + endm + +num_i19 = ((offset $) - (offset i19_lst))/5 + + +;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 + +; +; 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 ; january + dw 31 ; february + dw 59 + dw 90 + dw 120 + dw 151 + dw 181 + dw 212 + dw 243 + dw 273 + dw 304 + dw 334 ; december +daycnt2 dw 0000 ; temp for count of days since 1-1-80 +feb29 db 0 ; february 29 in a leap year flag + + +;************************************************************************ +;* * +;* entry points into Bios_Code routines. The segment values * +;* are plugged in by seg_reinit. * +;* * +;************************************************************************ + + public cdev +cdev dd chardev_entry +bcode_i2f dd i2f_handler +end_BC_entries: + +;************************************************************************ +;* * +;* cbreak - break key handling - simply set altah=3 and iret * +;* * +;************************************************************************ + + public cbreak +cbreak proc near + assume ds:nothing,es:nothing + + mov altah,3 ;indicate break key set + + public intret ; general purpose iret in the Bios_Data seg +intret: + FIRET +cbreak endp + +;************************************************************************ +;* * +;* strategy - store es:bx (device driver request packet) * +;* away at [ptrsav] for next driver function call * +;* * +;************************************************************************ + + public strategy +strategy proc far + assume ds:nothing,es:nothing + + mov word ptr cs:[ptrsav],bx + mov word ptr cs:[ptrsav+2],es + ret +strategy endp + +;************************************************************************ +;* * +;* device driver entry points. these are the initial * +;* 'interrupt' hooks out of the device driver chain. * +;* in the case of our resident drivers, they'll just * +;* stick a fake return address on the stack which * +;* points to dispatch tables and possibly some unit * +;* numbers, and then call through a common entry point * +;* which can take care of a20 switching * +;* * +;************************************************************************ + +con_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry ; call into code segment handler + dw con_table + +con_entry endp + +;-------------------------------------------------------------------- + +prn0_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw prn_table + db 0,0 ; device numbers + +prn0_entry endp + +;-------------------------------------------------------------------- + +prn1_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw prn_table + db 0,1 + +prn1_entry endp + +;-------------------------------------------------------------------- + +prn2_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw prn_table + db 1,2 + +prn2_entry endp + +;-------------------------------------------------------------------- + +prn3_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw prn_table + db 2,3 + +prn3_entry endp + +;-------------------------------------------------------------------- + +aux0_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw aux_table + db 0 + +aux0_entry endp + +;-------------------------------------------------------------------- + +aux1_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw aux_table + db 1 + +aux1_entry endp + +;-------------------------------------------------------------------- + +aux2_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw aux_table + db 2 + +aux2_entry endp + +;-------------------------------------------------------------------- + +aux3_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw aux_table + db 3 + +aux3_entry endp + +;-------------------------------------------------------------------- + +tim_entry proc near + assume ds:nothing,es:nothing + + call cdev_entry + dw tim_table + +tim_entry endp + +;-------------------------------------------------------------------- + +;************************************************************************ +;* * +;* Ensure A20 is enabled before jumping into code in HMA. * +;* This code assumes that if Segment of Device request packet is * +;* DOS DATA segment then the Device request came from DOS & that * +;* A20 is already on. * +;* * +;************************************************************************ + +cdev_entry proc near + assume ds:nothing,es:nothing +; +; M064 - BEGIN +; + cmp inHMA, 0 + je ce_enter_codeseg; optimized for DOS in HMA + + push ax + mov ax, DosDataSg + cmp word ptr [ptrsav+2], ax + pop ax + jne not_from_dos ; jump is coded this way to fall thru + ; in 99.99% of the cases +ce_enter_codeseg: + jmp cdev +not_from_dos: + call EnsureA20On +; +; M064 - END +; + jmp short ce_enter_codeseg +cdev_entry endp + +;************************************************************************ +;* * +;* outchr - this is our int 29h handler. it writes the * +;* character in al on the display using int 10h ttywrite * +;* * +;************************************************************************ + + public outchr +outchr proc far + assume ds:nothing,es:nothing + + push ax + push si + push di + push bp + push bx + mov ah,0eh ; set command to write a character + mov bx,7 ; set foreground color + int 10h ; call rom-bios + pop bx + pop bp + pop di + pop si + pop ax + jmp intret +outchr endp + +; M001 - BEGIN + +;************************************************************************ +;* * +;* EnsureA20On - ensure that a20 is enabled if we're running * +;* in the HMA before interrupt entry points into Bios_Code * +;* * +;************************************************************************ + +HiMem label dword + dw 90h + dw 0ffffh + +LoMem label dword + dw 80h + dw 0h + +EnsureA20On proc near + assume ds:nothing,es:nothing + call IsA20Off + jz ea_enable + ret + +EnableA20 proc near ; M041 +ea_enable: + push ax + push bx + mov ah,5 ; localenablea20 + call xms + pop bx + pop ax +bie_done: + ret +EnableA20 endp ; M041 + +EnsureA20On endp +; +; M001 - END + +; M041 : BEGIN +; +;---------------------------------------------------------------------------- +; +; procedure : IsA20Off +; +;---------------------------------------------------------------------------- +; +IsA20Off proc near + push ds + push es + push cx + push si + push di + lds si, HiMem + les di, LoMem + mov cx, 8 + rep cmpsw + pop di + pop si + pop cx + pop es + pop ds + ret +IsA20Off endp + +; +;---------------------------------------------------------------------------- +; +; procedure : DisableA20 +; +;---------------------------------------------------------------------------- +; +DisableA20 proc near + push ax + push bx + mov ah,6 ; localdisable a20 + call xms + pop bx + pop ax + ret +DisableA20 endp + +; M041 : END + +;************************************************************************ +;* * +;* int19 - bootstrap interrupt -- we must restore a bunch of the * +;* interrupt vectors before resuming the original int19 code * +;* * +;************************************************************************ + + + public int19 +int19 proc far + assume ds:nothing,es:nothing + + push cs + pop ds + assume ds:Bios_Data + + mov es,zeroseg + + mov cx, NUMROMVECTORS ; no. of rom vectors to be restored + mov si, offset RomVectors ; point to list of saved vectors +next_int: + lodsb ; get int number + cbw ; assume < 128 + shl ax, 1 + shl ax, 1 ; int * 4 + mov di, ax + lodsw + stosw + lodsw + stosw ; install the saved vector + loop next_int + + cmp byte ptr int19sem,0 ; don't do the others unless we + jz doint19 ; set our initialization complete flag + +; stacks code has changed these hardware interrupt vectors +; stkinit in sysinit1 will initialize int19holdxx values. + + mov si,offset i19_lst + mov cx,num_i19 + +i19_restore_loop: + lodsb ; get interrupt number + cbw ; assume < 128 + mov di,ax ; save interrupt number + lodsw ; get original vector offset + mov bx,ax ; save it + lodsw ; get original vector segment + cmp bx,-1 ; check for 0ffffh (unlikely segment) + jz i19_restor_1 ;opt no need to check selector too + cmp ax,-1 ;opt 0ffffh is unlikely offset + jz i19_restor_1 + + add di,di + add di,di + xchg ax,bx + stosw + xchg ax,bx + stosw ; put the vector back + +i19_restor_1: + loop i19_restore_loop + +doint19: + int 19h +int19 endp +; +; M036 - BEGIN +; +; +;---------------------------------------------------------------------------- +; +; procedure : int15 +; +; Int15 handler for recognizing ctrl-alt-del seq. +; +;---------------------------------------------------------------------------- +; +DELKEY equ 53h + public Int15 +Int15 proc far + assume ds:nothing + cmp ax, (4fh shl 8) + DELKEY ; del keystroke ? + je @f + jmp dword ptr Old15 +@@: + stc + jmp dword ptr Old15 +Int15 endp +; +; +;************************************************************************ +;* * +;* the int2f handler chains up to Bios_Code through here. * +;* it returns through one of the three functions that follow. * +;* notice that we'll assume we're being entered from DOS, so * +;* that we're guaranteed to be A20 enabled if needed * +;* * +;************************************************************************ + +int_2f proc far + assume ds:nothing,es:nothing + jmp bcode_i2f +int_2f endp + + + +;************************************************************************ +;* * +;* re_init - called back by sysinit after a bunch of stuff * +;* is done. presently does nothing. affects no * +;* registers! * +;* * +;************************************************************************ + + public re_init +re_init proc far + assume ds:nothing,es:nothing + ret +re_init endp + + +;SR; WIN386 support +; WIN386 instance data structure +; +; +; Here is a Win386 startup info structure which we set up and to which +; we return a pointer when Win386 initializes. +; + +public Win386_SI, SI_Version, SI_Next + +Win386_SI label byte ; Startup Info for Win386 +SI_Version db 3, 0 ; for Win386 3.0 +SI_Next dd ? ; pointer to next info structure + dd 0 ; a field we don't need + dd 0 ; another field we don't need +SI_Instance dw Instance_Table, Bios_Data ; far pointer to instance table + +; +; This table gives Win386 the instance data in the BIOS and ROM-BIOS data +; areas. Note that the address and size of the hardware stacks must +; be calculated and inserted at boot time. +; +Instance_Table label dword + dw 00H, 50H ; print screen status... + dw 02 ; ...2 bytes + dw 0Eh, 50H ; ROM Basic data... + dw 14H ; ...14H bytes + dw ALTAH, Bios_Data ; a con device buffer... + dw 01 ; ... 1 byte +IF STACKSW +public NextStack +NextStack label dword + +; NOTE: If stacks are disabled by STACKS=0,0, the following +; instance items WILL NOT be filled in by SYSINIT. +; That's just fine as long as these are the last items +; in the instance list since the first item is initialized +; to 0000 at load time. + + dw 0, 0 ; pointer to next stack to be used... + dw 02 ; ...2 bytes +; The next item in the instance table must be filled in at sysinit time +public IT_StackLoc, IT_StackSize +IT_StackLoc dd ? ; location of hardware stacks +IT_StackSize dw ? ; size of hardware stacks +ENDIF + dd 0 ; terminate the instance table + +;SR; +; Flag to indicate whether Win386 is running or not +; +public IsWin386 +IsWin386 db 0 + +; +;This routine was originally in BIOS_CODE but this causes a lot of problems +;when we call it including checking of A20. The code being only about +;30 bytes, we might as well put it in BIOS_DATA +; +PUBLIC V86_Crit_SetFocus + +V86_Crit_SetFocus PROC FAR + + push di + push es + push bx + push ax + + xor di,di + mov es,di + mov bx,0015h ;Device ID of DOSMGR device + mov ax,1684h ;Get API entry point + int 2fh + mov ax,es + or ax,di + jz Skip +; +;Here, es:di is address of API routine. Set up stack frame to simulate a call +; + push cs ;push return segment + mov ax,OFFSET Skip + push ax ;push return offset + push es + push di ;API far call address + mov ax,1 ;SetFocus function number + retf ;do the call +Skip: + pop ax + pop bx + pop es + pop di + ret +V86_Crit_SetFocus ENDP + + + +; +;End WIN386 support +; + + public FreeHMAPtr + public MoveDOSIntoHMA +FreeHMAPtr dw -1 +MoveDOSIntoHMA dd sysinitseg:FTryToMovDOSHi + + +;SR; +; A communication block has been setup between the DOS and the BIOS. All +;the data starting from SysinitPresent will be part of the data block. +;Right now, this is the only data being communicated. It can be expanded +;later to add more stuff +; + public SysinitPresent + public DemInfoFlag +SysinitPresent db 0 +DemInfoFlag db 0 + + +; this will be the end of the BIOS data if no hard disks are in system + + public endBIOSData +endBIOSData label byte + +Bios_Data ends + +; +; okay. so much for Bios_Data. Now let's put our device driver +; entry stuff up into Bios_Code. + +Bios_Code segment + assume cs:Bios_Code + +; ORG a bit past zero to leave room for running in HMA... + + org 30h + public BCode_start +BCode_start: + +; device driver entry point tables + + extrn con_table:near + extrn tim_table:near + extrn prn_table:near + extrn aux_table:near + + extrn i2f_handler:far + + public Bios_Data_Word +Bios_Data_Word dw Bios_Data + +;************************************************************************ +;* * +;* seg_reinit is called with ax = our new code segment value, * +;* trashes di, cx, es * +;* * +;* cas -- should be made disposable! * +;* * +;************************************************************************ + + public seg_reinit +seg_reinit proc far + assume ds:nothing,es:nothing + + mov es,Bios_Data_Word + assume es:Bios_Data + mov di,2+offset cdev + mov cx,((offset end_BC_entries) - (offset cdev))/4 + +seg_reinit_1: + stosw ; modify Bios_Code entry points + inc di + inc di + loop seg_reinit_1 + ret +seg_reinit endp + +;************************************************************************ +;* * +;* chardev_entry - main device driver dispatch routine * +;* called with a dummy parameter block on the stack * +;* dw dispatch_table, dw prn/aux numbers (optional) * +;* * +;* will eventually take care of doing the transitions in * +;* out of Bios_Code * +;* * +;************************************************************************ + +chardev_entry proc far + assume ds:nothing,es:nothing + + push si + push ax + push cx + push dx + push di + push bp + push ds + push es + push bx + mov bp,sp ; point to stack frame + mov si,18[bp] ; get return address (dispatch table) + mov ds,Bios_Data_Word ; load ds: -> Bios_Data + assume ds:Bios_Data + mov ax,word ptr 2[si] ; get the device number if present + mov byte ptr [auxnum],al + mov byte ptr [printdev],ah + mov si,word ptr [si] ; point to the device dispatch table + + les bx,[ptrsav] ;get pointer to i/o packet + + mov al,byte ptr es:[bx].unit ;al = unit code + mov ah,byte ptr es:[bx].media ;ah = media descrip + mov cx,word ptr es:[bx].count ;cx = count + mov dx,word ptr es:[bx].start ;dx = start sector + + xchg di,ax + mov al,byte ptr es:[bx].cmd + cmp al,cs:[si] + jae command_error + + cbw ; note that al <= 15 means ok + shl ax,1 + + add si,ax + xchg ax,di + + les di,dword ptr es:[bx].trans + + cld ; ***** always clear direction + call cs:word ptr [si+1] ;go do command + assume ds:nothing + + jc already_got_ah_status ; if function returned status, don't + mov ah,1 ; load with normal completion + +already_got_ah_status: + mov ds,Bios_Data_Word ; cas///// note: shouldn't be needed! + assume ds:Bios_Data + lds bx,[ptrsav] + assume ds:nothing + 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 + add sp,2 ; get rid of fake return address + +chardev_entry endp ; fall through into bc_retf + + public bc_retf +bc_retf proc far + assume ds:nothing,es:nothing + + ret + +bc_retf endp + + +command_error: + call bc_cmderr + jmp short already_got_ah_status + +; +;---------------------------------------------------------------------------- +; The following piece of hack is for supporting CP/M compatibility +; Basically at offset 5 we have a far call into 0:c0. But this does not call +; 0:c0 directly instead it call f01d:fef0, because it needs to support 'lhld 6' +; The following hack has to reside at ffff:d0 (= f01d:fef0) if BIOS is loaded +; high. +;---------------------------------------------------------------------------- + + +; BUGBUG sudeepb 21-May-1991 ; We can save these 30 bytes by moving +; off_d0 to right place. + + db 1fh dup (?) ; pad to bring offset to 0d0h + +if2 + if ( offset off_d0 - 0d0h ) + %out CP/M compatibilty broken!!! + %out Please re-pos hack to ffff:d0 + endif +endif + + public off_d0 +off_d0 db 5 dup (?) ; 5 bytes from 0:c0 will be copied onto here + ; which is the CP/M call 5 entry point + .errnz (offset off_d0 - 0d0h) + + +;---------------------------------------------------------- +; +; exit - all routines return through this path +; + + public bc_cmderr +bc_cmderr: + mov al,3 ;unknown command error + +; now zero the count field by subtracting its current value, +; which is still in cx, from itself. + + +; subtract the number of i/o's NOT YET COMPLETED from total +; in order to return the number actually complete + + + public bc_err_cnt +bc_err_cnt: + assume ds:Bios_Data + les bx,[ptrsav] + assume es:nothing + sub es:word ptr [bx].count,cx;# of successful i/o's + mov ah,81h ;mark error return + stc ; indicate abnormal end + ret + +Bios_Code ends + + +; the last real segment is sysinitseg + +sysinitseg segment + assume cs:sysinitseg + extrn FTryToMovDOSHi:far + public SI_start +SI_start: +sysinitseg ends + + end diff --git a/private/mvdm/softpc.new/bios/mschar.asm b/private/mvdm/softpc.new/bios/mschar.asm new file mode 100644 index 000000000..069273832 --- /dev/null +++ b/private/mvdm/softpc.new/bios/mschar.asm @@ -0,0 +1,1078 @@ + page ,160 + title mschar - character and clock devices +; +;---------------------------------------------------------------------------- +; +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +; +;---------------------------------------------------------------------------- +; + + .xlist + + include version.inc ; set build flags + include biosseg.inc ; establish bios segment structure + + include msequ.inc + include devsym.inc + include ioctl.inc + include vint.inc + +break macro + endm + + include biosbop.inc + + include error.inc + .list + + include msgroup.inc ; define Bios_Data segment + + + extrn ptrsav:dword + + extrn altah:byte + extrn keyrd_func:byte + extrn keysts_func:byte + + extrn auxnum:word + extrn auxbuf:byte + + extrn wait_count:word + extrn printdev:byte + extrn Old10:dword + extrn spc_mse_int10:dword + extrn int29Perf:dword + + +; close Bios_Data and open Bios_Code segment + + tocode + + extrn bc_cmderr:near + extrn bc_err_cnt:near + +MODE_CTRLBRK equ 0ffh ; M013 + +;************************************************************************ +;* * +;* device driver dispatch tables * +;* * +;* each table starts with a byte which lists the number of * +;* legal functions, followed by that number of words. Each * +;* word represents an offset of a routine in Bios_Code which * +;* handles the function. The functions are terminated with * +;* a near return. If carry is reset, a 'done' code is returned * +;* to the caller. If carry is set, the ah/al registers are * +;* returned as abnormal completion status. Notice that ds * +;* is assumed to point to the Bios_Data segment throughout. * +;* * +;************************************************************************ + + public con_table +con_table: + db (((offset con_table_end) - (offset con_table) - 1)/2) + dw bc_exvec ; 00 init + dw bc_exvec ; 01 + dw bc_exvec ; 02 + dw bc_cmderr ; 03 + dw con_read ; 04 + dw con_rdnd ; 05 + dw bc_exvec ; 06 + dw con_flush ; 07 + dw con_writ ; 08 + dw con_writ ; 09 + dw bc_exvec ; 0a +con_table_end: + + public prn_table +prn_table label byte + db (((offset prn_table_end) - (offset prn_table) -1)/2) + dw bc_exvec ; 00 init + dw bc_exvec ; 01 + dw bc_exvec ; 02 + dw bc_cmderr ; 03 + dw prn_input ; 04 indicate zero chars read + dw z_bus_exit ; 05 read non-destructive + dw bc_exvec ; 06 + dw bc_exvec ; 07 + dw prn_writ ; 08 + dw prn_writ ; 09 + dw prn_stat ; 0a + dw bc_exvec ; 0b + dw bc_exvec ; 0c + dw prn_open ; 0d + dw prn_close ; 0e + dw bc_exvec ; 0f + dw prn_tilbusy ; 10 + dw bc_exvec ; 11 + dw bc_exvec ; 12 + dw prn_genioctl ; 13 + dw bc_exvec ; 14 + dw bc_exvec ; 15 + dw bc_exvec ; 16 + dw bc_exvec ; 17 + dw bc_exvec ; 18 + dw prn_ioctl_query ; 19 +prn_table_end: + + + + public aux_table +aux_table label byte + db (((offset aux_table_end) - (offset aux_table) -1)/2) + + dw bc_exvec ; 00 - init + dw bc_exvec ; 01 + dw bc_exvec ; 02 + dw bc_cmderr ; 03 + dw aux_read ; 04 - read + dw aux_rdnd ; 05 - read non-destructive + dw bc_exvec ; 06 + dw aux_flsh ; 07 + dw aux_writ ; 08 + dw aux_writ ; 09 + dw aux_wrst ; 0a +aux_table_end: + + + public tim_table +tim_table label byte + db (((offset tim_table_end) - (offset tim_table) -1)/2) + dw bc_exvec ; 00 + dw bc_exvec ; 01 + dw bc_exvec ; 02 + dw bc_cmderr ; 03 + dw bc_cmderr ; 04 + dw z_bus_exit ; 05 + dw bc_exvec ; 06 + dw bc_exvec ; 07 + dw bc_cmderr ; 08 + dw bc_cmderr ; 09 +tim_table_end: + +;************************************************************************ +;* * +;* con_read - read cx bytes from keyboard into buffer at es:di * +;* * +;************************************************************************ + +con_read proc near + assume ds:Bios_Data,es:nothing + + jcxz con_exit + +con_loop: + call chrin ;get char in al + stosb ;store char at es:di + loop con_loop + +con_exit: + clc + ret +con_read endp + +;************************************************************************ +;* * +;* chrin - input single char from keyboard into al * +;* * +;* we are going to issue extended keyboard function, if * +;* supported. the returning value of the extended keystroke * +;* of the extended keyboard function uses 0e0h in al * +;* instead of 00 as in the conventional keyboard function. * +;* this creates a conflict when the user entered real * +;* greek alpha charater (= 0e0h) to distinguish the extended * +;* keystroke 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 + assume ds:Bios_Data,es:nothing + + mov ah,keyrd_func ; set by msinit. 0 or 10h + xor al,al + xchg al,altah ;get character & zero altah + + or al,al + jnz keyret + + int 16h ; do rom bios keyrd function + +alt10: + or ax,ax ;check for non-key after break + jz chrin + + cmp ax,7200h ;check for ctrl-prtsc + jnz alt_ext_chk + + mov al,16 + jmp short keyret + +alt_ext_chk: + +;************************************************************** +; if operation was extended function (i.e. keyrd_func != 0) then +; if character read was 0e0h then +; if extended byte was zero (i.e. ah == 0) then +; goto keyret +; else +; set al to zero +; goto alt_save +; endif +; endif +; endif + + cmp byte ptr keyrd_func,0 + jz not_ext + cmp al,0e0h + jnz not_ext + + or ah,ah + jz keyret +ifdef DBCS +ifdef KOREA ; Keyl 1990/11/5 + cmp ah, 0f0h ; If hangeul code range then + jb EngCodeRange1 ; do not modify any value. + cmp ah, 0f2h + jbe not_ext +EngCodeRange1: +endif ; KOREA +endif ; DBCS + xor al,al + jmp short alt_save + +not_ext: + + or al,al ;special case? + jnz keyret + +alt_save: + mov altah,ah ;store special key +keyret: + ret +chrin endp + +;************************************************************************ +;* * +;* con_rdnd - 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. * +;* * +;************************************************************************ + +con_rdnd proc near + assume ds:Bios_Data,es:nothing + + mov al,[altah] + or al,al + jnz rdexit + + mov ah,keysts_func ; keyboard i/o interrupt - get + int 16h ; keystroke status (keysts_func) + jnz gotchr + +; +; pc-convertible checking is not needed on NTVDM +; if no key in buff return immediatly with busy status +;04-Aug-1992 Jonle +; +; cmp fhavek09,0 +; jz z_bus_exit ; return with busy status if not k09 +; +; les bx,[ptrsav] +; assume es:nothing +; test es:[bx].status,0400h ; system wait enabled? +; jz z_bus_exit ; return with busy status if not +; +; need to wait for ibm response to request for code +; on how to use the system wait call. +; +; mov ax,4100h ; wait on an external event +; xor bl,bl ; M055; wait for any event +; int 15h ; call rom for system wait + +z_bus_exit: + stc + mov ah,3 ; indicate busy status + ret + +gotchr: + or ax,ax + jnz notbrk ;check for null after break + + mov ah,keyrd_func ; issue keyboard read function + int 16h + jmp con_rdnd ;and get a real status + +notbrk: + cmp ax,7200h ;check for ctrl-prtsc + jnz rd_ext_chk + + mov al,'P' and 1fh ; return control p + jmp short rdexit + +rd_ext_chk: + cmp keyrd_func,0 ; extended keyboard function? + jz rdexit ; no. normal exit. + + cmp al,0e0h ; extended key value or greek alpha? + jne rdexit + +ifdef DBCS +ifdef KOREA + cmp ah, 0f0h ; If hangeul code range then + jb EngCodeRange ; do not modify any value. + cmp ah, 0f2h + jbe rdexit ; Keyl 90/11/5 +EngCodeRange: +endif ; KOREA +endif ; DBCS + + cmp ah,0 ; scan code exist? + jz rdexit ; yes. greek alpha char. + mov al,0 ; no. extended key stroke. + ; change it for compatibility + +rdexit: + les bx,[ptrsav] + assume es:nothing + mov es:[bx].media,al ; *** return keyboard character here + +bc_exvec: + clc ; indicate normal termination + ret + +con_rdnd endp + +;************************************************************************ +;* * +;* con_write - console write routine * +;* * +;* entry: es:di -> buffer * +;* cx = count * +;* * +;************************************************************************ + +con_writ proc near + assume ds:Bios_Data,es:nothing + + jcxz bc_exvec + + push es + + mov bx,word ptr [int29Perf] + mov dx,word ptr [int29Perf+2] ;DX:BX is original INT 29h vector + sub ax,ax + mov es,ax + cmp BX,es:[29h*4+0] + jne con_lp1 ; if not the same do single int10s + cmp DX,es:[29h*4+2] + jne con_lp1 ; if not the same do single int10s + mov bx,word ptr [spc_mse_int10] + mov dx,word ptr [spc_mse_int10+2] ;DX:BX is original INT 10h vector + cmp BX,es:[10h*4+0] + jne con_lp1 ; if not the same do single int10s + cmp DX,es:[10h*4+2] + jne con_lp1 ; if not the same do single int10s + + pop es + + ; Sudeepb 21-Jul-1992: We know that no one has hooked in10 so we + ; can optimize it by calling a private in1t10h which takes a full + ; string, displays it with the same attribute as present on the + ; screen and moves the cursor to the end. + + mov ax,46h ; sounds like a good flag value + push ax ; make an iret frame + push cs + mov ax, offset ret_adr + push ax + push dx ; dx:bx is pointing to softpc int10 handler + push bx ; make the retf frame + mov ax,13FFh ; AH = WRITESTRING, AL = subfunction + retf +ret_adr: + jmp short cc_ret + +con_lp1: + pop es + +con_lp: + mov al,es:[di] ;get char + inc di + int chrout ;output char + loop con_lp ;repeat until all through + +cc_ret: + clc + ret +con_writ endp + +;************************************************************************ +;* * +;* con_flush - flush out keyboard queue * +;* * +;************************************************************************ + + public con_flush ; called from msbio2.asm for floppy swapping +con_flush proc near + assume ds:Bios_Data,es:nothing + + + mov [altah],0 ;clear out holding buffer + +; while (charavail()) charread(); + +flloop: + mov ah,1 ; command code for check status + int 16h ; call rom-bios keyboard routine + jz cc_ret ; return carry clear if none + + xor ah,ah ; if zf is nof set, get character + int 16h ; call rom-bios to get character + jmp flloop + +con_flush endp + +;************************************************************************ +;* * +;* some equates for rom bios printer i/o * +;* * +;************************************************************************ + +; ibm rom status bits (i don't trust them, neither should you) +; warning!!! the ibm rom does not return just one bit. it returns a +; whole slew of bits, only one of which is correct. + + +notbusystatus = 10000000b ; not busy +nopaperstatus = 00100000b ; no more paper +prnselected = 00010000b ; printer selected +ioerrstatus = 00001000b ; some kinda error +timeoutstatus = 00000001b ; time out. + +noprinter = 00110000b ; no printer attached + +;************************************************************************ +;* * +;* prn_input - return with no error but zero chars read * +;* * +;* enter with cx = number of characters requested * +;* * +;************************************************************************ + +prn_input proc near + assume ds:Bios_Data,es:nothing + + call bc_err_cnt ; reset count to zero (sub reqpkt.count,cx) + clc ; but return with carry reset for no error + ret + +prn_input endp + +;************************************************************************ +;* * +;* prn_writ - write cx bytes from es:di to printer device * +;* * +;* auxnum has printer number * +;* * +;************************************************************************ + +prn_writ proc near + assume ds:Bios_Data,es:nothing + + jcxz prn_done ;no chars to output + +prn_loop: + mov bx,2 ;retry count + +prn_out: + call prnstat ; get status + jnz TestPrnError ; error + + mov al,es:[di] ; get character to print + xor ah,ah + call prnop ; print to printer + jz prn_con ; no error - continue + + cmp ah, MODE_CTRLBRK ; M013 + jne @f ; M013 + mov al, error_I24_gen_failure ; M013 + mov altah, 0 ; M013 + jmp short pmessg ; M013 +@@: + test ah,timeoutstatus + jz prn_con ; not time out - continue + +TestPrnError: + dec bx ;retry until count is exhausted. + jnz prn_out + +pmessg: + jmp bc_err_cnt ; return with error + +; next character + +prn_con: + inc di ;point to next char and continue + loop prn_loop + +prn_done: + clc + ret +prn_writ endp + +;************************************************************************ +;* * +;* prn_stat - device driver entry to return printer status * +;* * +;************************************************************************ + +prn_stat proc near + + call prnstat ;device in dx + jnz pmessg ; other errors were found + test ah,notbusystatus + jnz prn_done ;no error. exit + jmp z_bus_exit ; return busy status +prn_stat endp + +;************************************************************************ +;* * +;* prnstat - utilty function to call ROM BIOS to check * +;* printer status. Return meaningful error code * +;* * +;************************************************************************ + +prnstat proc near + assume ds:Bios_Data,es:nothing + + mov ah, 2 ; set command for get status +prnstat endp ; fall into prnop + +;************************************************************************ +;* * +;* prnop - call ROM BIOS printer function in ah * +;* return zero true if no error * +;* return zero false if error, al = error code * +;* * +;************************************************************************ + +prnop proc near + assume ds:Bios_Data,es:nothing + + mov dx,[auxnum] ; get printer number + int 17h ; call rom-bios printer routine + + ; This check was added to see if this is a case of no + ; printer being installed. This tests checks to be sure + ; the error is noprinter (30h) + + push ax ; M044 + and ah, noprinter ; M044 + cmp AH,noprinter ; Chk for no printer + pop ax ; M044 + + jne NextTest + and AH,NOT nopaperstatus + or AH,ioerrstatus + +; 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. + +NextTest: + test ah,(ioerrstatus+nopaperstatus) ; 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,error_I24_out_of_paper + ; first, assume out of paper + test ah,nopaperstatus ; out of paper set? + jnz ret1 ; yes, error is set + inc al ; return al=10 (i/o error) +ret1: + ret ; return with error + +checknotready: + mov al,2 ; assume not-ready + test ah,timeoutstatus ; is time-out set? + ret ; if nz then error, else ok +prnop endp + +;************************************************************************ +;* * +;* prn_open - send bop to disable auto-close, and wait for * +;* a DOS close * +;* * +;* inputs: * +;* outputs: BOP has been issued * +;* * +;************************************************************************ + +prn_open proc near + push si + push dx + push ds + mov dx,40h + mov ds,dx + test word ptr ds:[FIXED_NTVDMSTATE_REL40], EXEC_BIT_MASK + pop ds + jnz po_nobop + xor dh, dh + mov dl, [printdev] + or dl, dl + jz @f + dec dl +@@: + mov si,PRNIO_OPEN + bop %BIOS_PRINTER_IO +po_nobop: + pop dx + pop si + ret +prn_open endp + +;************************************************************************ +;* * +;* prn_close - send bop to close actual printer, and re-enable * +;* autoclose * +;* * +;* inputs: * +;* outputs: BOP has been issued * +;* * +;************************************************************************ + +prn_close proc near + push si + push dx + push ds + mov dx,40h + mov ds,dx + test word ptr ds:[FIXED_NTVDMSTATE_REL40], EXEC_BIT_MASK + pop ds + jnz pc_nobop + xor dh, dh + mov dl, [printdev] + or dl, dl + jz @f + dec dl +@@: + mov si,PRNIO_CLOSE + bop %BIOS_PRINTER_IO +pc_nobop: + pop dx + pop si + ret +prn_close endp + +;************************************************************************ +;* * +;* prn_tilbusy - output until busy. Used by print spooler. * +;* this entry point should never block waiting for * +;* device to come ready. * +;* * +;* inputs: cx = count, es:di -> buffer * +;* outputs: set the number of bytes transferred in the * +;* device driver request packet * +;* * +;************************************************************************ + +prn_tilbusy proc near + + mov si,di ; everything is set for lodsb + +prn_tilbloop: + push cx + + push bx + xor bh,bh + mov bl,[printdev] + shl bx,1 + mov cx,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 + + lods es:byte ptr [si] + xor ah,ah + call prnop + jnz prn_berr ; error + + loop prn_tilbloop ; go for more + + clc ; normal no-error return + ret ; from device driver + +prn_bperr: + pop cx ; restore transfer count from stack + +prn_berr: + jmp bc_err_cnt +prn_tilbusy endp + +;************************************************************************ +;* * +;* prn_genioctl - get/set printer retry count * +;* * +;************************************************************************ + +prn_genioctl proc near + assume ds:Bios_Data,es:nothing + + les di,[ptrsav] + cmp es:[di].majorfunction,ioc_pc + jz prnfunc_ok + +prnfuncerr: + jmp bc_cmderr + +prnfunc_ok: + mov al,es:[di].minorfunction + les di,es:[di].genericioctl_packet + xor bh,bh + 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 + clc + ret +prn_genioctl endp + +;************************************************************************ +;* * +;* prn_ioctl_query * +;* * +;* Added for 5.00 * +;************************************************************************ + +prn_ioctl_query PROC NEAR + assume ds:Bios_Data,es:nothing + + les di,[ptrsav] + cmp es:[di].majorfunction,ioc_pc + jne prn_query_err + + mov al,es:[di].minorfunction + cmp al,get_retry_count + je IOCtlSupported + cmp al,set_retry_count + jne prn_query_err + +IOCtlSupported: + clc + ret + +prn_query_err: + stc + jmp BC_CmdErr + +prn_ioctl_query ENDP + +;************************************************************************ +;* * +;* aux port driver code -- "aux" == "com1" * +;* * +;* the device driver entry/dispatch code sets up auxnum to * +;* give the com port number to use (0=com1, 1=com2, 2=com3...) * +;* * +;************************************************************************ + +; 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, 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_timeout equ 80h ;timeout + +; these flags reported in al: + +flag_cts equ 10h ;clear to send +flag_dsr equ 20h ;data set ready +flag_rec_sig equ 80h ;receive line signal detect + +;************************************************************************ +;* * +;* aux_read - read cx bytes from [auxnum] aux port to buffer * +;* at es:di * +;* * +;************************************************************************ + +aux_read proc near + assume ds:Bios_Data,es:nothing + + jcxz exvec2 ; if no characters, get out + + call getbx ; put address of auxbuf in bx + xor al,al ; clear al 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 first auxin call + +aux1: + call auxin ; get character from port +; ^^^^^ won't return if error +aux2: + stosb ; store character + loop aux1 ; if more characters, go around again + +exvec2: + clc ; all done, successful exit + ret + +aux_read endp + +;************************************************************************ +;* * +;* auxin - call rom bios to read character from aux port * +;* if error occurs, map the error and return one * +;* level up to device driver exit code, setting * +;* the number of bytes transferred appropriately * +;* * +;************************************************************************ + +; +; M026 - BEGIN +; +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 + jnz arbad ; skip if any error bits set + ret ; normal completion, ah=stat, al=char + +; error getting character + +arbad: + pop ax ; remove return address (near call) + xor al,al + or al,flag_rec_sig or flag_dsr or flag_cts + jmp bc_err_cnt + +auxin endp + +IFDEF COMMENTEDOUT +auxin proc near + push cx + mov cx, 20 ; number of retries on time out errors +@@: + 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_timeout + jz no_timeout + loop @b +no_timeout: + pop cx + test ah, flag_timeout or flag_frame or flag_parity or flag_overrun + jnz arbad ; skip if any error bits set + ret ; normal completion, ah=stat, al=char + +; error getting character + +arbad: + pop ax ; remove return address (near call) + xor al,al + or al,flag_rec_sig or flag_dsr or flag_cts + jmp bc_err_cnt + +auxin endp +ENDIF + +; +; M026 - END +; +;************************************************************************ +;* * +;* aux_rdnd - non-destructive aux port read * +;* * +;************************************************************************ + +aux_rdnd proc near + assume ds:Bios_Data,es:nothing + + 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 + mov [bx],al ; save character in buffer + +auxrdx: + jmp rdexit ; return al in [packet.media] + +auxbus: + jmp z_bus_exit ; return busy status +aux_rdnd endp + +;************************************************************************ +;* * +;* aux_wrst - return aux port write status * +;* * +;************************************************************************ + +aux_wrst proc near + assume ds:Bios_Data,es:nothing + + call auxstat ; get status of aux in ax + 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 + jz auxbus ; then device is busy (not ready) + clc + ret +aux_wrst endp + +;************************************************************************ +;* * +;* auxstat - call rom bios to determine aux port status * +;* * +;* exit: ax = status * +;* dx = [auxnum] * +;* * +;************************************************************************ + +auxstat proc near + mov ah,auxfunc_status +auxstat endp ; fall into auxop + +;************************************************************************ +;* * +;* auxop - perform rom-biox aux port interrupt * +;* * +;* entry: ah = int 14h function number * +;* exit: ax = results * +;* dx = [auxnum] * +;* * +;************************************************************************ + +auxop proc near + ;ah=function code + ;0=init, 1=send, 2=receive, 3=status + mov dx,[auxnum] ; get port number + int 14h ; call rom-bios for status + ret +auxop endp + +;************************************************************************ +;* * +;* aux_flsh - flush aux input buffer - set contents of * +;* auxbuf [auxnum] to zero * +;* * +;* cas - shouldn't this code call the rom bios input function * +;* repeatedly until it isn't ready? to flush out any * +;* pending serial input queue if there's a tsr like MODE * +;* which is providing interrupt-buffering of aux port? * +;* * +;************************************************************************ + +aux_flsh proc near + call getbx ; get bx to point to auxbuf + mov byte ptr [bx],0 ; zero out buffer + clc ; all done, successful return + ret +aux_flsh endp + +;************************************************************************ +;* * +;* aux_writ - write to aux device * +;* * +;************************************************************************ + +aux_writ proc near + assume ds:Bios_Data ; 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 + mov ah,auxfunc_send ;value=1, indicates a write + call auxop ;send character over aux port + + test ah,flag_timeout ;check for error + jz awok ; then no error + mov al,10 ; else indicate write fault + jmp bc_err_cnt ; call error routines + + ; if cx is non-zero, still more +awok: + loop aux_loop ; more characrter to print + clc ; all done, successful return + ret +aux_writ endp + +;************************************************************************ +;* * +;* getbx - return bx -> single byte input buffer for * +;* selected aux port ([auxnum]) * +;* * +;************************************************************************ + +getbx proc near + assume ds:Bios_Data,es:nothing + + mov bx,[auxnum] + add bx,offset auxbuf + ret +getbx endp + +Bios_Code ends + end diff --git a/private/mvdm/softpc.new/bios/msend.asm b/private/mvdm/softpc.new/bios/msend.asm new file mode 100644 index 000000000..305cedbe9 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msend.asm @@ -0,0 +1,52 @@ + page ,160 +; +;---------------------------------------------------------------------------- +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +; +;---------------------------------------------------------------------------- + +; Define end labels for each segment in +; IO.SYS. Make the segments paragraph aligned +; to save the trouble of rounding up at run-time. +; +; also defines a special segment called dos_load_seg which is +; used to figure out where to load MSDOS (after sysinit) + +Bios_Data segment para public 'Bios_Data' + assume cs:Bios_Data + public BData_end +BData_end: +Bios_Data ends + +Bios_Code segment para public 'Bios_Code' + assume cs:Bios_Code + public BCode_end +BCode_end: +Bios_Code ends + +sysinitseg segment para public 'system_init' + assume cs:sysinitseg +sysinitseg ends + +SpcKbdSeg segment para public 'SoftpcKeyboard' + assume cs:SpcKbdSeg +SpcKbdSeg ends + +SpcMseSeg segment para public 'SoftpcMouse' + assume cs:SpcMseSeg +SpcMseSeg ends + +SpcEmmSeg segment para public 'SoftpcEmm' + assume cs:SpcEmmSeg + public SI_end +SI_end: +SpcEmmSeg ends + + +dos_load_seg segment para public 'dos_load_seg' +dos_load_seg ends + + end + diff --git a/private/mvdm/softpc.new/bios/msequ.inc b/private/mvdm/softpc.new/bios/msequ.inc new file mode 100644 index 000000000..bf743846d --- /dev/null +++ b/private/mvdm/softpc.new/bios/msequ.inc @@ -0,0 +1,56 @@ + +ftoobig equ 80h +fbig equ 40h +romstatus equ 1 +romread equ 2 +romwrite equ 3 +romverify equ 4 +romformat equ 5 + + +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 ;address of head settle time +normsettle= 15 ;normal head settle +speedsettle= 0 ;speed up settle time +initspot= 534h ;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 +start_l = 26 ; extended start sector (low) +start_h = 28 ; extended start sector (high) + + +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 + + + diff --git a/private/mvdm/softpc.new/bios/msgroup.inc b/private/mvdm/softpc.new/bios/msgroup.inc new file mode 100644 index 000000000..605fe1314 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msgroup.inc @@ -0,0 +1,18 @@ + +tocode macro +Bios_Data ends +Bios_Code segment + assume cs:Bios_Code + endm + +todata macro +Bios_Code ends +Bios_Data segment + assume cs:Bios_Data + endm + +;align the segment on word boundary to allow for even alignment of data + +Bios_Data segment + assume cs:Bios_Data + diff --git a/private/mvdm/softpc.new/bios/msinit.asm b/private/mvdm/softpc.new/bios/msinit.asm new file mode 100644 index 000000000..d4c7b4f42 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msinit.asm @@ -0,0 +1,288 @@ + page ,160 + title msinit for BIOS +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- +; + +EXTENDEDKEY equ 1 ; use extended keyboard functions + + include version.inc ; set build flags + include biosseg.inc ; establish bios segment structure + + include msequ.inc + include dossym.inc + include dosmac.inc + include biostruc.inc + include dossvc.inc + include vint.inc + +; the following segment follows sysinit. It is used to define +; the location to load MSDOS.SYS into. + +dos_load_seg segment para public 'dos_load_seg' +dos_load_seg ends + + extrn RomVectors:dword + extrn NUMROMVECTORS:abs + extrn res_dev_list:word + extrn keyrd_func:byte ; for mscon. defined in msdata. + extrn keysts_func:byte ; for mscon. defined in msdata. + extrn endBIOSData:byte + + extrn dosdatasg:word + + extrn Int15:far ; M036 + extrn int19:far + extrn intret:near + extrn cbreak:near + extrn outchr:near + extrn outchr:near + +sysinitseg segment + assume cs:sysinitseg + extrn current_dos_location:word + extrn device_list:dword + extrn memory_size:word + extrn sysinit:far +sysinitseg ends + +Bios_Data_Init segment + assume cs:datagrp + +;********************************************************* +; 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. +; +;******************************************************** + + + +;=========================================================================== +; +; 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. +; ax = first data sector (high) +; di = sectors/fat for the boot media. +; + public init +init proc near + assume ds:nothing,es:nothing + + FCLI + xor ax,ax + mov ds,ax + +; Save a pack of interrupt vectors... + + push cs + pop es ; cannot use cs override for stos + + mov cx, NUMROMVECTORS ; no. of rom vectors to be saved + mov si, offset RomVectors ; point to list of int vectors +next_int: + lods byte ptr cs:[si] ; get int number + cbw ; assume < 128 + shl ax, 1 + shl ax, 1 ; int no * 4 + mov di, ax + xchg si, di + lodsw + stosw + lodsw + stosw ; save the vector + xchg si, di + loop next_int + +; set up int 15 for new action ; M036 + + mov word ptr ds:[15h*4],offset Int15 ; M036 + mov ds:[15h*4+2],cs ; M036 + + + +; set up int 19 for new action + + mov word ptr ds:[19h*4],offset int19 + mov ds:[19h*4+2],cs + +; + xor dx,dx + mov ss,dx + mov sp,700h ;local stack + FSTI + assume ss:nothing + + ; NTVDM we do not intialize the com,prn ports here + ; to stay seamless with the host OS + ; 15-Sep-1992 Jonle + ; + ; mov al,3 ; init com4 + ; call aux_init + ; mov al,2 ; init com3 + ; call aux_init + ; mov al,1 ; init com2 + ; call aux_init + ; xor al,al ; init com1 + ; call aux_init + ; + ; mov al,2 ; init lpt3 + ; call print_init + ; mov al,1 ; init lpt2 + ; call print_init + ; xor al,al ; init lpt1 + ; call print_init + + 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 + + mov ds:word ptr chrout*4,offset outchr + mov ds:word ptr chrout*4+2,ax + + 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 + + + mov dx,sysinitseg + mov ds,dx + + assume ds:sysinitseg + +; set pointer to resident device driver chain + + mov word ptr device_list,offset res_dev_list + mov word ptr device_list+2,cs + + + mov current_dos_location,dos_load_seg ; will load MSDOS here + + +ifdef EXTENDEDKEY + +; we will check if the system has ibm extended keyboard by +; looking at a byte at 40:96. if bit 4 is set, then extended key board +; is installed, and we are going to set keyrd_func to 10h, keysts_func to 11h +; for the extended keyboard function. use cx as the temporary register. + + 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 ext. keyboard functions +org_key: + +endif + + push cs + pop ds + push cs + pop es + + assume ds:datagrp, es:datagrp + + mov di, offset endBIOSData ; BIOS data segment end address + shr di,1 + shr di,1 + shr di,1 + shr di,1 ; Converted to segmnet + inc di ; para align + + add di,datagrp ; Add segment of BIOS data + mov [dosdatasg],di ; di = to be dos data segment + + mov di,dos_load_seg + + SVC SVC_DEMLOADDOS ; di is segment to load DOS + ; If it fails it never comes back + + jmp sysinit + +init endp + + +;-------------------------------------------------------------------- + +; al = device number + +print_init proc near + assume ds:nothing,es:nothing + + cbw + mov dx,ax ; get printer port number into dx + mov ah,1 ;initalize printer port + int 17h ;call rom-bios routine + ret + +print_init endp + +;-------------------------------------------------------------------- + +aux_init proc near + assume ds:nothing,es:nothing + + cbw + mov dx,ax + mov al,rsinit ;2400,n,1,8 (msequ.inc) + mov ah,0 ;initalize aux port + int 14h ;call rom-bios routine + ret + +aux_init endp + +Bios_Data_Init ends + end + diff --git a/private/mvdm/softpc.new/bios/msint13.asm b/private/mvdm/softpc.new/bios/msint13.asm new file mode 100644 index 000000000..a95c05d92 --- /dev/null +++ b/private/mvdm/softpc.new/bios/msint13.asm @@ -0,0 +1,214 @@ + page ,160 + title MS-DOS BIOS int 2f handler +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- + +; THIS FILE SHOULD BE NAMED INT2f.ASM RATHER THAN INT13.ASM AS I HAVE RIPPED +; THE INT 13 SUPPORT. TO REDUCE CONFUSION WHEN PICKING FIXES FROM DOS 5.1 +; THE NAME IS RETAINED AS IT IS. + + include version.inc ; set build flags + include biosseg.inc ; establish bios segment structure + + include msequ.inc + include biostruc.inc + + include msgroup.inc ; establish Bios_Data segment + include vint.inc + +multMULT equ 4ah +multMULTGETHMAPTR equ 1 +multMULTALLOCHMA equ 2 + + +Win386_RelTS equ 80h +NT_WAIT_BOP equ 5Ah + +bop MACRO callid + db 0c4h,0c4h,callid +endm + +;SR; +; Include file for WIN386 support +; + include win386.inc + + + extrn SysinitPresent:byte + extrn FreeHMAPtr:word + extrn MoveDOSIntoHMA:dword + +;SR; +;New variables for Win386 support +; + extrn IsWin386:byte + extrn Win386_SI:byte + extrn SI_Next:dword + + +; close data, open Bios_code segment + + tocode + + extrn Bios_Data_Word:word + +; Int 2f functions to support communication of external block device +; drivers with msdisk are not supported. It also does'nt support +; function 13h which replaces the int 13 vector. +; + + public i2f_handler +i2f_handler proc far + assume ds:nothing,es:nothing + + cmp ah,13h + jz i2f_iret + cmp ah,8 + jz i2f_iret + +; +;Check for WIN386 startup and return the BIOS instance data +; + cmp ah,MULTWIN386 + jz win386call + + cmp ah, multMULT + jne i2f_iret + jmp handle_multmult + +i2f_iret: + FIRET + + +;WIN386 startup stuff is done here. If starting up we set our WIN386 present +;flag and return instance data. If exiting, we reset the WIN386 present flag +;NOTE: We assume that the BIOS int 2fh is at the bottom of the chain. + +win386call: + push ds + mov ds,cs:Bios_Data_Word + assume ds:Bios_Data + + cmp al, Win386_Init ; is it win386 initializing? + je Win386Init + cmp al, Win386_Exit ; is it win386 exiting? + je Win386Exit + cmp al, Win386_RelTS ; is it app release timeslice call? + jne win_iret ; if not, continue int2f chain + + push ax ; It's the idling case - call MS BOP A + xor ax,ax ; with AX = 0 + bop NT_WAIT_BOP + pop ax + xor al, al + jmp short win_iret + +Win386Exit: + test dx, 1 ; is it win386 or win286 dos extender? + jnz win_iret ; if not win386, then continue + and [IsWin386], 0 ; indicate that win386 is not present + jmp short win_iret + +Win386Init: + test dx, 1 ; is it win386 or win286 dos extender? + jnz win_iret ; if not win386, then continue + + or [IsWin386], 1 ; Indicate WIN386 present + mov word ptr [SI_Next], bx ; Hook our structure into chain + mov word ptr [SI_Next + 2], es + mov bx, offset Win386_SI ; point ES:BX to Win386_SI + push ds + pop es + +win_iret: + pop ds + assume ds:nothing + jmp i2f_iret ;return back up the chain + +handle_multmult: + cmp al, multMULTGETHMAPTR + jne try_2 + + push ds + call HMAPtr ; get offset of free HMA + mov bx, 0ffffh + mov es, bx ; seg of HMA + mov bx, di + not bx + or bx, bx + jz @f + inc bx +@@: + pop ds + jmp i2f_iret +try_2: + cmp al, multMULTALLOCHMA + jne try_3 + + push ds + mov di, 0ffffh ; assume not enough space + mov es, di + call HMAPtr ; get offset of free HMA + assume ds:Bios_Data + cmp di, 0ffffh + je InsuffHMA + neg di ; free space in HMA + cmp bx, di + jbe @f + mov di, 0ffffh + jmp short InsuffHMA +@@: + mov di, FreeHMAPtr + add bx, 15 + and bx, 0fff0h + add FreeHMAPtr, bx ; update the free pointer + jnz InsuffHMA + mov FreeHMAPtr, 0ffffh ; no more HMA if we have wrapped +InsuffHMA: + pop ds + assume ds:nothing + jmp i2f_iret +try_3: + jmp i2f_iret +i2f_handler endp + +; +;-------------------------------------------------------------------------- +; +; procedure : HMAPtr +; +; Gets the offset of the free HMA area ( with respect to +; seg ffff ) +; If DOS has not moved high, tries to move DOS high. +; In the course of doing this, it will allocate all the HMA +; and set the FreeHMAPtr to past the end of the BIOS and +; DOS code. The call to MoveDOSIntoHMA (which is a pointer) +; enters the routine in sysinit1 called FTryToMoveDOSHi. +; +; RETURNS : offset of free HMA in DI +; BIOS_DATA, seg in DS +; +;-------------------------------------------------------------------------- +; +HMAPtr proc near + mov ds, Bios_Data_Word + assume ds:Bios_Data + mov di, FreeHMAPtr + cmp di, 0ffffh + jne @f + cmp SysinitPresent, 0 + je @f + call MoveDOSIntoHMA + mov di, FreeHMAPtr +@@: + ret +HMAPtr endp + + +Bios_Code ends + end diff --git a/private/mvdm/softpc.new/bios/ntio.sym b/private/mvdm/softpc.new/bios/ntio.sym Binary files differnew file mode 100644 index 000000000..62d9798dd --- /dev/null +++ b/private/mvdm/softpc.new/bios/ntio.sym diff --git a/private/mvdm/softpc.new/bios/spcemm.asm b/private/mvdm/softpc.new/bios/spcemm.asm new file mode 100644 index 000000000..02440d144 --- /dev/null +++ b/private/mvdm/softpc.new/bios/spcemm.asm @@ -0,0 +1,167 @@ +; +; spcemm.asm, +; +; 10-Dec-1992 Jonle , adapted from em_drvr.asm from Insignia solutions +; +; This code serves as a stub device driver for emm memory manager. +; Its sole purpose is for apps to be able to identify that an emm driver is +; loaded and that LIM services are available. This code is linked into the +; device driver chain contains a strategy, interrupt and device header +; +; The driver should only be loaded if emm memory is available +; from NTVDM. +; + +BOP MACRO callid + db 0c4h, 0c4h, callid +endm + + +; +; Request Header, for initialization +; +REQHEAD STRUC +ReqLen DB ? ; Length in bytes of request block +ReqUnit DB ? ; Block Device unit number +ReqFunc DB ? ; Type of request +ReqStat DW ? ; Status Word +REQHEAD ENDS + +; +; Segment definitions for ntio.sys, +; +include biosseg.inc +include vint.inc + +SpcEmmSeg segment + + assume cs:SpcEmmSeg,ds:nothing,es:nothing + +; +; SpcEmmBeg - SpcEmmEnd +; +; Marks the resident code, anything outside of these markers +; is discarded after intialization +; 11-Dec-1992 Jonle +; + + public SpcEmmBeg + +SpcEmmBeg label byte + + +; +; character device Header +; must be first in the .sys file +; + dd -1 ;pointer to next device driver + dw 8000H ;attribute (plain character device) + dw offset STRATEGY ;pointer to device "strategy" routine + dw offset Interrupt ;pointer to device "interrupt" routine + db 'EMMXXXX0' ;8 byte name DO NOT CHANGE THE NAME + +; +; Request Header address, saved here by strategy routine +; +pReqHdr dd ? + + +; +; Device "strategy" entry point, save request header address +; +Strategy proc far + mov word ptr cs:pReqHdr, bx + mov word ptr cs:pReqHdr+2, es + ret +Strategy endp + + +; EmmIsr - int 67h isr +; +EmmIsr: ; LIM Isr + bop 67h +emmiret: + FIRET + +; ret trap for em function 'alter page map & call' +EmmRet: + bop 68h + jmp emmiret + + + +;---------------------------------------------------------------------- +; Device "interrupt" entry point +;---------------------------------------------------------------------- +Interrupt PROC FAR + + push es + push di + + les di, cs:pReqHdr ; check for valid commands + cmp es:[di.ReqFunc], 0ah + je validcmd + cmp es:[di.ReqFunc], 0 + je validcmd + + mov ax, 8003h ; we don't handle anything else + jmp short irptexit + +validcmd: + xor ax,ax + +irptexit: + or ax, 0100h ;tell em we finished + mov es:[di.ReqStat],AX ;store status in request header + + pop di + pop es + ret + +Interrupt ENDP + + public SpcEmmEnd +SpcEmmEnd label byte + + public InitSpcEmm +; +; InitSpcEmm Initializes Spc 32 bit memory manager +; returns ax=0 for success +; +; Inputs: ds is expected seg for drv code, cs is temporary sysinitseg +; Outputs: ax zero for success +; +InitSpcEmm proc near + + ; BOP 66 - initialize LIM memory + ; pass the address of bop 68 to the em manager + ; in ds:dx and to return the number of em pages in BX + ; + ; NOTE: All EMM options come from pif file + ; There are NO command line options + xor bx, bx + mov dx, offset EmmRet + bop 66h + cmp bx, 0ffffh ;ffff means incorrect config (eg no 64K gap) + je fail + cmp bx, 0 ;check expanded memory is available + je fail + + ; set up IVT for INT 67h + FCLI + xor ax, ax + mov es, ax + mov bx, offset EmmIsr + mov word ptr es:[67h*4], bx + mov word ptr es:[(67h*4)+2], ds + FSTI + + ret +fail: + mov ax, 0ffffh + ret + +InitSpcEmm endp + +SpcEmmSeg ends + end diff --git a/private/mvdm/softpc.new/bios/spckbd.asm b/private/mvdm/softpc.new/bios/spckbd.asm new file mode 100644 index 000000000..ba4d82c7b --- /dev/null +++ b/private/mvdm/softpc.new/bios/spckbd.asm @@ -0,0 +1,2141 @@ +;****************************************************************************** +; +; Copyright (c) 1992 Insignia Solutions Ltd. +; +; Program: +; +; Purpose: +; +; Version: +; +; Author: Dave Bartlett +; Modifications: +; 1) Tim June 92. Changes to get DEC PC working. Take over +; IVT entries 6h (illegal instruction), 11h (equipment +; check), 16h (keyboard BIOS), 17h (printer), +; 42h (default video). +; 2) Tim June 92. Changed version to 1.11 +; 3) Tim June 92. Avoid accesses to host ROM as far as +; possible. Take over lots of IVT entries and continue to +; point them at this driver. +; 4) Tim July 92. Version num 1.12, put pseudo ROM stuff back in. +; 5) Tim July 92. v 1.13, use SoftPC video BIOS when windowed. +; +; 6) 12-Sep-1992 Jonle, Merged with ntio.sys +; cleanup usage of assumes espcially with ES +; optimized loading of IVT +; other general cleanup +; +; This obj module is intially loaded in a temporary memory location +; along with ntio.sys. Ntio.sys will copy the resident code (marked by +; SpcKbdBeg, SpcKbdEnd) into the permanent memory location which resides +; just below the normal device drivers loaded by config.sys. +; +; The nonresident intialization code is run with CS= temp seg +; and DS= final seg. +; +;****************************************************************************** + + +.286 + +include vint.inc + +;================================================================ +; Macros and includes +;================================================================ + +bop MACRO callid + db 0c4h,0c4h,callid +endm + + +BIOS_CPU_QUIT equ 0FEh +BIOS_KB_INT equ 9 +BIOS_INT15 equ 15h +BIOS_PRINTER_IO equ 17h +UNEXP_BOP equ 2 +RTC_WAIT_FLAG equ 0a0h ; offset of rtc_wait_flag in bios data seg +VERSIONID equ 0BEEFh + +FULLSCREEN equ 1 +MAX_VIDEO_FUNC equ 1Ch +GET_FONT_FUNC equ 11h + +VID_MODECHANGE equ 0 +MOUSE_LIGHT_PEN equ 4 +MIN_MOUSE_FUNC equ 0F0H +MAX_MOUSE_FUNC equ 0F7H +XTRA_MOUSE_FUNC equ 0FAH +MS_VIDEO_STRING equ 13FFH + +MOUSE_VID_BOP equ 0BEh +EGA_VIDEO_BOP equ 42h + +PRT_NOTBUSY equ 80h +PRT_NUM_PORTS equ 3 +PRT_STATE_READY equ 0 +PRT_IRQ equ 10h +PRT_LPT_BUSY equ 1 + +TIMER_LOW equ 6ch +TIMER_HIGH equ 6eh +TIMER_OVFL equ 70h +MOTOR_STATUS equ 3fh +MOTOR_COUNT equ 40h + +; Keyboard buf ptrs +BUFFER_HEAD equ 1ah +BUFFER_TAIL equ 1ch +BUFFER_START equ 80h +BUFFER_END equ 82h + +; kb_flag and LED bits +KB_FLAG equ 17h +CAPS_STATE equ 40h +NUM_STATE equ 20h +SCROLL_STATE equ 10h + +KB_FLAG_1 equ 18h + +KB_FLAG_2 equ 97h +KB_LEDS equ 07h ; Keyboard LED state bits +KB_PR_LED equ 40h ; Mode indicator update + + +KB_FLAG_3 equ 96h +LC_E1 equ 01h +LC_E0 equ 02h + + + + +;..............................................keyboard constants + +; bits in kb_flag + RIGHT_SHIFT = 1 + LEFT_SHIFT = 2 + CTL_SHIFT = 4 + ALT_SHIFT = 8 + + +; bit in kb_flag_1 + HOLD_STATE = 8 + SCROLL_SHIFT = 10h + NUM_SHIFT = 20h + CAPS_SHIFT = 40h + INS_SHIFT = 80h + SYS_SHIFT = 04h + + +; IBM scan codes + CTL_KEY = 29 + LEFT_SHIFTKEY = 42 + RIGHT_SHIFTKEY = 54 + ALT_KEY = 56 + CAPS_KEY = 58 + NUM_KEY = 69 + SCROLL_KEY = 70 + INS_KEY = 82 + + + +; +; Segment definitions for ntio.sys, +; +include biosseg.inc + + +SpcKbdSeg segment + + assume cs:SpcKbdSeg,ds:nothing,es:nothing + +; +; SpcKbdBeg - SpcKbdEnd +; +; Marks the resident code, anything outside of these markers +; is discarded after intialization +; 13-Sep-1992 Jonle +; + public SpcKbdBeg + +SpcKbdBeg label byte + +; +; Reduced data table for Video 7 modes 0 and 2. +; This table is extracted from our video7 ROM. Only text modes are +; required, mode 0 and 1 are identical as are modes 2 and 3. +; +ega_parm_setup: + +;--40x25-- + DB 40,24,16 ; width,height,character height + DW 00800H ; Page size in bytes + + DB 008H, 003H, 000H, 002H ; Sequencer Parameters + + DB 067H ;Misc Reg + +; CRTC Parameters + DB 02dH, 027H, 028H, 090H, 02bH + DB 0a0H, 0bfH, 01fH, 000H, 04fH + DB 00dH, 00eH, 000H, 000H, 000H + DB 000H, 09cH, 0aeH, 08fH, 014H + DB 01fH, 096H, 0b9H, 0a3H, 0ffH + +; Attribute parameters + DB 000H, 001H, 002H, 003H, 004H + DB 005H, 014H, 007H, 038H, 039H + DB 03aH, 03bH, 03cH, 03dH, 03eH + DB 03fH, 00cH, 000H, 00fH, 008H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 010H, 00eH, 000H, 0ffH + +;--80x25-- + DB 80,24,16 ; width,height,character height + DW 01000H ; Page size in bytes + + DB 000H, 003H, 000H, 002H ; Sequencer Parameters + + DB 067H ;Misc Reg + +; CRTC Parameters + DB 05fH, 04fH, 050H, 082H, 055H + DB 081H, 0bfH, 01fH, 000H, 04fH + DB 00dH, 00eH, 000H, 000H, 000H + DB 000H, 09cH, 08eH, 08fH, 028H + DB 01fH, 096H, 0b9H, 0a3H, 0ffH + +; Attribute parameters + DB 000H, 001H, 002H, 003H, 004H + DB 005H, 014H, 007H, 038H, 039H + DB 03aH, 03bH, 03cH, 03dH, 03eH + DB 03fH, 00cH, 000H, 00fH, 008H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 010H, 00eH, 000H, 0ffH + +;--80x25 mono-- + DB 80,24,16 ; width,height,character height + DW 01000H ; Page size in bytes + + DB 000H, 003H, 000H, 003H ; Sequencer Parameters + + DB 0a6H ;Misc Reg + +; CRTC Parameters + DB 05fH, 04fH, 050H, 082H, 055H + DB 081H, 0bfH, 01fH, 000H, 04dH + DB 00bH, 00cH, 000H, 000H, 000H + DB 000H, 083H, 0a5H, 05dH, 028H + DB 00dH, 063H, 0baH, 0a3H, 0ffH + +; Attribute parameters + DB 000H, 008H, 008H, 008H, 008H + DB 008H, 008H, 008H, 010H, 018H + DB 018H, 018H, 018H, 018H, 018H + DB 018H, 00eH, 000H, 00fH, 008H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 010H, 00aH, 000H, 0ffH + +; Mode b (font load) + + DB 5eh,32H,8 ; width,height,character height + DW 09700H ; Page size in bytes + + DB 001H, 00fH, 000H, 006H ; Sequencer Parameters + + DB 0e7H ;Misc Reg + +; CRTC Parameters + DB 06dH, 05dH, 05eH, 090H, 061H + DB 08fH, 0bfH, 01fH, 000H, 040H + DB 000H, 000H, 000H, 000H, 000H + DB 000H, 0a2H, 08eH, 099H, 02fH + DB 000H, 0a1H, 0b9H, 0e3H, 0ffH + +; Attribute parameters + DB 000H, 001H, 002H, 003H, 004H + DB 005H, 014H, 007H, 038H, 039H + DB 03aH, 03bH, 03cH, 03dH, 03eH + DB 03fH, 001H, 000H, 00fH, 000H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 000H, 005H, 00fH, 0ffH + + +;--350 scanline 40x25 + DB 40,24,14 ; width,height,character height + DW 00800H ; Page size in bytes + + DB 009H, 003H, 000H, 002H ; Sequencer Parameters + + DB 0a3H ;Misc Reg + +; CRTC Parameters + DB 02dH, 027H, 028H, 090H, 02bH + DB 0a0H, 0bfH, 01fH, 000H, 04dH + DB 00bH, 00cH, 000H, 000H, 000H + DB 000H, 083H, 0a5H, 05dH, 014H + DB 01fH, 063H, 0baH, 0a3H, 0ffH + +; Attribute parameters + DB 000H, 001H, 002H, 003H, 004H + DB 005H, 014H, 007H, 038H, 039H + DB 03aH, 03bH, 03cH, 03dH, 03eH + DB 03fH, 008H, 000H, 00fH, 000H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 010H, 00eH, 000H, 0ffH + +;--350 scanline 80x25 + DB 80,24,14 ; width,height,character height + DW 01000H ; Page size in bytes + + DB 001H, 003H, 000H, 002H ; Sequencer Parameters + + DB 0a3H ;Misc Reg + +; CRTC Parameters + DB 05fH, 04fH, 050H, 082H, 055H + DB 081H, 0bfH, 01fH, 000H, 04dH + DB 00bH, 00cH, 000H, 000H, 000H + DB 000H, 083H, 0a5H, 05dH, 028H + DB 01fH, 063H, 0baH, 0a3H, 0ffH + +; Attribute parameters + DB 000H, 001H, 002H, 003H, 004H + DB 005H, 014H, 007H, 038H, 039H + DB 03aH, 03bH, 03cH, 03dH, 03eH + DB 03fH, 008H, 000H, 00fH, 000H + +; Graph parameters + DB 000H, 000H, 000H, 000H, 000H + DB 010H, 00eH, 000H, 0ffH + +; +; End of baby mode table. +; +; Table of VGA bios 'capability' info for func 1b to point at. +vga_1b_table db 07fh, 060h, 00fh, 000h, 000h, 000h, 000h, 007h + db 002h, 008h, 0ffh, 00eh, 000h, 000h, 03fh, 000h + +; Configuration table for INT 15 Func C0 to point at. +conf_table dw 008h +;; db 000h, 0fch, 002h, 000h, 070h, 000h, 000h, 000h, 000h + db 000h, 0fch, 002h, 074h, 070h, 000h, 000h, 000h, 000h + + +PRT_BUF_SIZE equ 255 + +;================================================================ +; Printer status table +;================================================================ +prt_status db PRT_NUM_PORTS dup (?) +prt_state db PRT_NUM_PORTS dup (?) +prt_control db PRT_NUM_PORTS dup (?) +prt_lpt_stat db PRT_NUM_PORTS dup (?) +cur_buf_size dw PRT_BUF_SIZE +prt_data_buf db PRT_BUF_SIZE dup (?) ; buffer in the 16bit side for perf. +cur_lpt db 0ffh ; buffer is not being used +cur_count dw ? +cur_busy db 0 ; initially not busy + +;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Keyboard tables +;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +shift_keys: ;K6 + DB INS_KEY,CAPS_KEY,NUM_KEY,SCROLL_KEY + DB ALT_KEY,CTL_KEY,LEFT_SHIFTKEY,RIGHT_SHIFTKEY + +shift_masks: ;K7 + DB INS_SHIFT,CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT + DB ALT_SHIFT,CTL_SHIFT,LEFT_SHIFT,RIGHT_SHIFT + +ctl_n_table: ;K8 + DB 27, -1, 0, -1, -1, -1, 30, -1 + DB -1, -1, -1, 31, -1, 127, 148, 17 + DB 23, 5, 18, 20, 25, 21, 9, 15 + DB 16, 27, 29, 10, -1, 1, 19, 4 + DB 6, 7, 8, 10, 11, 12, -1, -1 + DB -1, -1, 28, 26, 24, 3, 22, 2 + DB 14, 13, -1, -1, -1, -1, 150, -1 + DB ' ', -1 + +ctl_f_table: ;K9 + DB 94, 95, 96, 97, 98, 99, 100, 101 + DB 102, 103, -1, -1, 119, 141, 132, 142 + DB 115, 143, 116, 144, 117, 145, 118, 146 + DB 147, -1, -1, -1, 137, 138 + +lowercase: + DB 27, '1', '2', '3', '4', '5', '6', '7', '8', '9' ;K10 + DB '0', '-', '=', 8, 9, 'q', 'w', 'e', 'r', 't' + DB 'y', 'u', 'i', 'o', 'p', '[', ']', 13, -1, 'a' + DB 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39 + DB 96, -1, 92, 'z', 'x', 'c', 'v', 'b', 'n', 'm' + DB ',', '.', '/', -1, '*', -1, ' ', -1 + +lc_tbl_scan: + DB 59, 60, 61, 62, 63, 64, 65, 66, 67, 68 + DB -1, -1 + +base_case: + DB 71, 72, 73, -1, 75, -1, 77, -1, 79, 80 + DB 81, 82, 83, -1, -1, 92, 133, 134 ;K15 + +uppercase: ;K11 + DB 27, '!', '@', '#', '$', '%', '^', '&', '*', '(' + DB ')', '_', '+', 8, 0, 'Q', 'W', 'E', 'R', 'T' + DB 'Y', 'U', 'I', 'O', 'P', '{', '}', 13, -1, 'A' + DB 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"' + DB 126, -1, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M' + DB '<', '>', '?', -1, 0, -1, ' ', -1; + +ucase_scan: + DB 84, 85, 86, 87, 88, 89, 90, 91, 92, 93 + DB -1, -1 + +numb_state: + DB '7', '8', '9', '-', '4', '5', '6', '+', '1', '2' ;K14 + DB '3', '0', '.' , -1, -1, 124, 135, 136 + +alt_table: + DB 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 ;K30 + DB 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 + DB 30, 31, 32, 33, 34, 35, 36, 37, 38, 44 + DB 45, 46, 47, 48, 49, 50 + +;================================================================ +; Keyboard break caller +;================================================================ + +keyboard_break_caller: + int 1bh ;keyboard break + bop %BIOS_CPU_QUIT + +;================================================================ +; Print screen caller +;================================================================ + +print_screen_caller: + int 5h ;print screen + bop %BIOS_CPU_QUIT + +;================================================================ +; Int 15 caller +;================================================================ +; Tim modified int 15 caller. Copied from BIOS2. It gives CPU +; a chance to take other interrupts. Suspect the extra jumps are +; now harmless with IRET hooking. +;int15h_caller: + ;int 15h + ;bop %BIOS_CPU_QUIT +int15h_caller: + int 15h ; Cassette I/O. + jmp k1 +k1: jmp k2 +k2: jmp k3 +k3: BOP %BIOS_CPU_QUIT + +;================================================================ +; Unexpected interrupt handler +;================================================================ + +unexp_int: + bop %UNEXP_BOP + jmp iret_com + +;================================================================ +;Int 13 caller +;================================================================ +int13h_caller: + int 13h + bop %BIOS_CPU_QUIT + + +;================================================================ +; New interrupt 9h handler +;================================================================ + +int09h_vector: + push ax + xor ax, ax + bop %BIOS_KB_INT + pop ax + jmp iret_com + + ; CarbonCopy traces int 9 in order to gain control + ; over where the kbd data is coming from (the physical kbd + ; or the serial link) The kbd_inb instruction must be visible + ; in the 16 bit code via int 1 tracing, for CarbonCopy to work. + ; Softpc assumes the exact location of the first nop + ; relative to the bop just above. + nop + nop + in al, 60h ; keyba_io_buffers + nop + nop + BOP %BIOS_CPU_QUIT + + + + + +;================================================================= +; IRET hooks bop table +;================================================================= + + +IRET_HOOK = 5dh ;IRET hook BOP + +iret_bop_table: + bop %IRET_HOOK + db 0 +iret_end_first_entry: + bop %IRET_HOOK + db 1 + bop %IRET_HOOK + db 2 + bop %IRET_HOOK + db 3 + bop %IRET_HOOK + db 4 + bop %IRET_HOOK + db 5 + bop %IRET_HOOK + db 6 + bop %IRET_HOOK + db 7 + bop %IRET_HOOK + db 8 + bop %IRET_HOOK + db 9 + bop %IRET_HOOK + db 10 + bop %IRET_HOOK + db 11 + bop %IRET_HOOK + db 12 + bop %IRET_HOOK + db 13 + bop %IRET_HOOK + db 14 + bop %IRET_HOOK + db 15 + +;================================================================ +; New interrupt 13h handler +;================================================================ + +int13h_vector: + cmp dl,80h ; 0 - 7f are floppy commands + jb int40h_vector + + cmp ah,2 ; we fail the direct access commands + jb diskcmd ; read/write/seek/verify/format + cmp ah,5 ; but let others go through (disk tables etc) + jbe faildisk + cmp ah,0ah + jb diskcmd + cmp ah,0ch + ja diskcmd +faildisk: + push ax + mov ax,1 ; direct access error panel + bop 59h + pop ax ; preserve AL for safety sake + mov ah, 80h ; error - timeout + stc + retf 2 + +diskcmd: + bop 13h + retf 2 + +;================================================================ +; New interrupt 40h handler +;================================================================ + +int40h_vector: +; cmp ah,2 ; we fail the direct access commands +; jb flopcmd ; read/write/seek/verify/format +; cmp ah,5 ; but let others go through (disk tables etc) +; jbe failflop +; cmp ah,0ah +; jb flopcmd +; cmp ah,0ch +; ja flopcmd +failflop: +; push ax +; mov ax,0 ; direct access error panel +; bop 59h +; pop ax +; mov ah, 80h ; error - timeout +; stc +; retf 2 + +flopcmd: + bop 40h + retf 2 + +;; waiting for diskette interrupt +wait_int: + push ds + push ax + push cx + mov ax, 40h + mov ds, ax + mov cx, 10h +wait_int_loop: + mov al, [3Eh] + test al, 80h + loopz wait_int_loop + pop cx + pop ax + pop ds + bop %BIOS_CPU_QUIT + +;; floppy parameters table +floppy_table label byte + + DB 01 ;; 360KB in 360KB + DW OFFSET md_tbl1 + DB 82H ;; 360KB in 1,2MB + DW OFFSET md_tbl2 + DB 02 ;; 1.2MB in 1.2MB + DW OFFSET md_tbl3 + DB 03 ;; 720KB in 720KB + DW OFFSET md_tbl4 + DB 84H ;; 720KB in 1.44MB + DW OFFSET md_tbl5 + DB 04 ;; 1.44MB in 1.44MB + DW OFFSET md_tbl6 + DB 85h ;; 720KB in 2.88MB + DW OFFSET md_tbl7 + DB 85h ;; 1.44MB in 2.88MB + DW OFFSET md_tbl8 + DB 5 ;; 2.88MB in 2.88MB + DW OFFSET md_tbl9 + + +md_tbl1: + ; MEDIA = 40 track low data rate; DRIVE = 40 track low data rate + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 9 ; sectors/track + DB 02Ah ; gap length + DB 0FFh ; data length + DB 050h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 39 ; maximum track number + DB 80H ; transfer rate + +md_tbl2: + ; MEDIA = 40 track low data rate; DRIVE = 80 track high data rate + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 9 ; sectors/track + DB 02Ah ; gap length + DB 0FFh ; data length + DB 050h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 39 ; maximum track number + DB 40H ; transfer rate + +md_tbl3: + ; MEDIA = 80 track high data rate; DRIVE = 80 track high data rate + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 15 ; sectors/track + DB 01Bh ; gap length + DB 0FFh ; data length + DB 054h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 79 ; maximum track number + DB 0 ; transfer rate + +md_tbl4: + ; MEDIA = 80 track low data rate; DRIVE = 80 track low data rate + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 9 ; sectors/track + DB 02Ah ; gap length + DB 0FFh ; data length + DB 050h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start ime + DB 79 ; maximum track number + DB 80H ; transfer rate + +md_tbl5: + ; MEDIA = 80 track low data rate; DRIVE = 80 track high data rate + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 9 ; sectors/track + DB 02Ah ; gap length + DB 0FFh ; data length + DB 050h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 79 ; maximum track number + DB 80H ; transfer rate + +md_tbl6: + ; MEDIA = 80 track high data rate; DRIVE = 80 track high data rate + DB 0AFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 18 ; sectors/track + DB 01Bh ; gap length + DB 0FFh ; data length + DB 06Ch ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 79 ; maximum track number + DB 0 ; transfer rate + +md_tbl7: + ;MEDIA = 80 tracks, 9 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track + + DB 0E1h ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 9 ; sectors/track + DB 02Ah ; gap length + DB 0FFh ; data length + DB 050h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start ime + DB 79 ; maximum track number + DB 80H ; transfer rate +md_tbl8: + ;MEDIA = 80 tracks, 18 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track + + DB 0D1h ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 18 ; sectors/track + DB 01Bh ; gap length + DB 0FFh ; data length + DB 065h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 79 ; maximum track number + DB 0 ; transfer rate + +md_tbl9: + ;MEDIA = 80 tracks, 36 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track + + DB 0A1h ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 36 ; sectors/track + DB 038h ; gap length + DB 0FFh ; data length + DB 053h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time + DB 79 ; maximum track number + DB 0C0h ; transfer rate + + + +floppy_table_len equ $ - floppy_table + +bios_floppy_table label byte + DB 0DFh ; 1st specify byte + DB 2 ; 2nd specify byte + DB 25H ; motor off wait time + DB 2 ; ie 2 bytes/sector + DB 18 ; sectors/track + DB 01Bh ; gap length + DB 0FFh ; data length + DB 054h ; gap length for format + DB 0F6h ; fill byte for format + DB 15 ; head settle time/ms + DB 8 ; ie 1s motor start time +bios_floppy_table_len equ $ - bios_floppy_table + +;=============================================================== +; New interrupt 15h handler +;================================================================ +; Tim, modified this to be like a "normal" SoftPC ROM. +; Copied from BIOS2, but rtc_wait_flag is now referenced via ES not +; DS. +; +; 17-Sep-1992 Jonle , ES ref to rtc_wait was change from assume ES +; to seg overides to prevent accidents in assuming. +; + +;int15h_vector: + ;bop %BIOS_INT15 + ;iret +;;;;;;;;;STF hide this int15h_vector: +int15h_vector: + call DOSTI + cmp ah, 88h + je lbl1 + cmp ah, 91h + je lbl1 + cmp ah, 86h + je lbl2 + BOP 15h + RETF 2 +lbl1: BOP 15h + jmp iret_com +lbl2: BOP 15h + jc lbl5 + push cx + push dx + push es ; Tim, save ES not DS. + mov ax, 40 ; point es to biosdata + mov es, ax + xchg dx, cx +lbl3: + test byte ptr es:[RTC_WAIT_FLAG], 080h ; check for end of wait + loopz lbl3 ; dec timeout delay + jnz lbl4 ; exit if wait ended + sub dx, 1 ; dec error timeout counter + jnc lbl3 ; loop till counters timeout +lbl4: + mov byte ptr es:[RTC_WAIT_FLAG], 0 ; set function inactive + pop es ; Kipper, restore ES not DS. + pop dx + pop cx + clc +lbl5: + RETF 2 + +;================================================================= +; Regular SoftPC int 17 handler (especially important for DEC PCs) +;================================================================= + +int17h_vector: +; +; Do a get status purely in 16-bit code but only if the printer is ready and +;we don't have interrupts turned on. Otherwise we must do a BOP and let 32-bit +;code handle it. +; + push si + push dx + push ax + mov ax, dx ; dx = adapter no., ensure it is no + xor dx, dx ; greater than PRT_NUM_PORTS. + mov si, PRT_NUM_PORTS + div si + mov si, dx + pop ax + cmp ah, 2 + je do_prt_status + or ah,ah + je do_write + jmp do_print_bop + +do_prt_status: + cmp byte ptr cs:[si + prt_state], PRT_STATE_READY + jne do_print_bop + test byte ptr cs:[si + prt_control], PRT_IRQ + je get_status + jmp short do_print_bop + +do_write: + cmp byte ptr cs:[cur_lpt],0ffh + jne check_lpti + mov byte ptr cs:[cur_lpt],dl + mov word ptr cs:[cur_count],0 + mov byte ptr cs:[cur_busy],0ffh + jmp short do_print_bop +check_lpti: + cmp byte ptr cs:[cur_lpt],dl + je buf_ok + push si + xor si,si + bop %BIOS_PRINTER_IO + pop si + mov word ptr cs:[cur_count],0 + mov byte ptr cs:[cur_lpt],dl + jmp short do_print_bop +buf_ok: + mov dx,word ptr cs:[cur_count] + mov si,dx + mov byte ptr cs:[si + prt_data_buf],al + inc word ptr cs:[cur_count] + cmp word ptr cs:[cur_count],PRT_BUF_SIZE + jne no_flushing + xor si,si ; sub-function 0 for this bop + bop %BIOS_PRINTER_IO + test ah,08h + jz flush_ok + dec word ptr cs:[cur_count] + jmp short int17h_end +flush_ok: + mov word ptr cs:[cur_count],0 +no_flushing: + mov ah,90h + jmp short int17h_end + +do_print_bop: + mov si,0ffffh ; sub-function 1 + bop %BIOS_PRINTER_IO + jmp int17h_end + +get_status: + test byte ptr cs:[si + prt_lpt_stat], PRT_LPT_BUSY + jne noset + or byte ptr cs:[si + prt_status], PRT_NOTBUSY +noset: + mov ah, cs:[si + prt_status] + and ah, 0f8h + xor ah, 48h +int17h_end: + pop dx + pop si +iret_com: + FIRET + + +;================================================================= +; Pseudo-ROM vectuz, copied from BIOS2.ASM +;================================================================= + +dummy_vector: ; Copied from BIOS2.ASM + jmp iret_com +illegal_bop_vector: + bop 72h + jmp iret_com +intD11_vector: + bop 72h + jmp iret_com + +int05h_vector: ; Print Screen func. copied from BIOS2.ASM + call DOSTI + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + ;::::::::::::::::::::::::::::::::: Setup DS to point to BIOS data area + MOV AX,40H + MOV DS,AX + ;::::::::::::::::::::::::::::::: Print screen already in progress ???? + CMP BYTE PTR DS:[100H],1 + JE end_print + ;::::::::::::::::::::::::::::::::::::::::::::::: Set print screen busy + MOV BYTE PTR DS:[100h],1 + ;:::::::::::::::::::::::::::::::::::::::::::::::::::: Get video status + MOV AH,15 + INT 10H + MOV CH,AH ;No of columns + ;:::::::::::::::::::::::::::::::::: Setup no. of columns/rows to print + BOP 80H ;(BIOS_PS_PRIVATE_1) + MOV CL,AL ;No of rows + ;::::::::::::::::::::::::::::::::::: Print line feed / carriage return + CALL print_crlf + ;:::::::::::::::::::::::::::::::::::::::::: Get current cursor postion + PUSH CX + MOV AH,3 + INT 10H + POP CX + ;::::::::::::::::::::::::::::::::::::::::::::::::: Save cursor postion + PUSH DX ;save current cursor postion + XOR DH,DH ;current row being processed +start_print_col: + XOR DL,DL ;current column being processed + ;::::::::::::::::::::::::::::::::::::::::::::::: Start printing screen +start_print_row: + ;:::::::::::::::::::::::::::::::::::::::::::::::::: Set cursor postion + PUSH DX ;save current row,column + MOV AH,2 + INT 10H + ;::::::::::::::::::::::::::::::::::: Read character at current postion + MOV AH,8 + INT 10H + ;::::::::::::::::::::::::::::::::::::::::::::::::::::: Print character + OR al,al + JNZ print_char + MOV AL,20H +print_char: + XOR DX,DX + XOR AH,AH + INT 17H + ;:::::::::::::::::::::::::::::::::::::::::::: Check for printer errors + POP DX ;Restore current row,column + AND AH,25H + JZ cont2 + MOV BYTE PTR DS:[100H],0FFH + JMP short exit_print + ;::::::::::::::::::::::::::::::::::::::::::: Move to mext print column +cont2: + INC DL ;Inc current column + CMP DL,CH ;Current col compared to no. of cols + JB start_print_row + ;:::::::::::::::::::::::::::::::::::::::::: End of column, print CR/LF + CALL print_crlf + ;:::::::::::::::::::::::::::::::::::::::::::::::::: More rows to print + INC DH ;Inc current row + CMP DH,CL ;Current row compared to no. of rows + JBE start_print_col + MOV BYTE PTR DS:[0100H],0 + ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Exit print +exit_print: + ;:::::::::::::::::::::::::::::::::::::; Restore orginal cursor postion + POP DX + MOV AH,2 + INT 10H + ;:::::::::::::::::::::::::::::::::::::::::::::::::::: Tidy up and exit +end_print: + POP DS + POP DX + POP CX + POP BX + POP AX + jmp iret_com + + ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Print CR/LF +print_crlf: + PUSH DX + XOR DX,DX + MOV AX,0DH + INT 17H + XOR DX,DX + MOV AX,0AH + INT 17H + POP DX + RET +; End of int05_vector (print screen). + +int06h_vector: + bop 06h + jmp iret_com + +; IVT 7 is set to unexpected interrupt. + + +int08h_vector: +; The usual int8 handler modified for optimum performance. +; - stays in 16 bit code (no BOP) +; - keeps interrupts off when not needed +; - calls int 1c directly +; + call DOCLI ; make sure interrupts stay off until iret + + push es + push ds ; save some registers + push ax + push dx + + mov ax, 40h ; set ds to bios data area + mov ds, ax + xor ax, ax + mov es, ax ; set es to IVT seg for i1c callout + + inc word ptr ds:[TIMER_LOW] ; inc time counters + jnz i8v1 + inc word ptr ds:[TIMER_HIGH] +i8v1: + cmp word ptr ds:[TIMER_HIGH], 018h ; check for 24 hours, wrap point + jnz i8v2 + cmp word ptr ds:[TIMER_LOW], 0b0h + jnz i8v2 + + + mov word ptr ds:[TIMER_HIGH], ax ; 24 hour wrap, set OVFL bit + mov word ptr ds:[TIMER_LOW], ax + mov byte ptr ds:[TIMER_OVFL], 1 + or al, 8 ; set Overflow bit for fake flags + + ;--- ; skip floppy motor stuff + + +i8v2: ; handle the floppy motor stuff + push ax + dec byte ptr ds:[MOTOR_COUNT] + jnz i8v3 + and byte ptr ds:[MOTOR_STATUS], 0f0h + mov al, 0ch + mov dx, 03f2h ; costly outb happens 1/256 timer tics... + out dx, al + +i8v3: + pop ax + ; call int1c user routine directly + lahf ; get lobyte of flags for fake flags + xchg ah,al + push ax ; put fake flags on the stack + call dword ptr es:[1ch*4] ; do it! + call DOCLI ; make sure interrupts stay off until iret + + mov al, 20h ; send eoi + out 20h, al + + pop dx ;restore the stack + pop ax + pop ds + pop es + + jmp iret_com + + + +int0e_vector: + bop 0eh + jmp iret_com + +DOCLI: + FCLI + ret + +DOSTI: + FSTI + ret + +; +; Tim August 92. Video BIOS grabber. +; Call SPC BIOS when in windowed mode and the host BIOS when in full-screen. +; Controled by value of 'use_host_int10'. +; Try to limit bops by validating calling values. Mouse has to get first shot +; and then video bios. +; + +use_host_int10 db 01h ; native/softpc bios flag +changing_mode db 01h ; delay handshake if in bios mode change + +PUBLIC int10h_vector + +int10h_vector: + cmp use_host_int10, FULLSCREEN + je nativebios + + cmp ah,VID_MODECHANGE ; mode change?? + je modechange + cmp ah,MAX_VIDEO_FUNC ; range check + ja mousecheck ; not a vid func but mouse has higher + cmp ah,MOUSE_LIGHT_PEN ; light pen special case + je mousebios +spcbios: + bop EGA_VIDEO_BOP ; regular windowed Int 10 + jmp viddone + +mousecheck: + cmp ah,MIN_MOUSE_FUNC ; range check mouse fn f0-f7 + fa. + jb badvid + cmp ah,MAX_MOUSE_FUNC + jbe mousebios + cmp ah,XTRA_MOUSE_FUNC + jne badvid + +mousebios: ; call softpc mouse video entrypoint + bop MOUSE_VID_BOP + jmp viddone + +modechange: ; windowed modechange. Mouse gets a look + mov changing_mode,1 ; then softpc video bios. If gfx mode then + bop MOUSE_VID_BOP ; will go fullscreen + ;;;nop + ;;;nop ; nops aid debugging + ;;;bop EGA_VIDEO_BOP ; will go fullscreen here + nop + nop + push ax ; save video mode which may have top bit set + and ax,7fh + cmp al,3 + jbe endmode ; if graphics mode, repeat modechange to setup + cmp al,7 ; video card, else fall through + je endmode + pop ax + jmp nativebios +endmode: + pop ax + mov changing_mode,0 ; Clear 'mode changing' flag. + +viddone: + jmp iret_com + +badvid: ; unrecognised video func + stc + jmp viddone + +nativebios: + mov changing_mode,0 ; Clear 'mode changing' flag. + cmp ax,MS_VIDEO_STRING ; ensure not MS special video string fn + je ms_wrt_string + + cmp ah,MIN_MOUSE_FUNC ; could be a mouse call + jb chk_mse_vid + cmp ah,MAX_MOUSE_FUNC ; range check mouse fn f0-f7 + fa. + jbe mousebios + cmp ah,XTRA_MOUSE_FUNC + je mousebios + jmp jmp_native ; probably bad func but... + +chk_mse_vid: + cmp ah,MOUSE_LIGHT_PEN ; mouse handles light pen + je mousebios + cmp ah,VID_MODECHANGE + jne chk_font_change + bop MOUSE_VID_BOP ; mouse wants first sniff at mode changes + jmp jmp_native ; then fall through +chk_font_change: + cmp ah,GET_FONT_FUNC + jne jmp_native + bop MOUSE_VID_BOP ; select mouse buffer for new no. of lines + ; then fall through + +jmp_native: + db 0EAh ; far jump +host_int10 dd ? ; to native int 10 vector + +ms_wrt_string: + push si + push di + push bp +go_loop1: + mov dx,46h ; looks a good value for flags + push dx ; make an iret frame + push cs + mov bx, offset go_cont + push bx + mov bx,7 ; set foreground color + mov ah,0eh ; set command to write a character + mov al,es:[di] ; get char + inc di + jmp jmp_native ; make far jmp to int 10 vector + +go_cont: + loop go_loop1 ;repeat until all through + pop bp + pop di + pop si + mov ax,1 ; return success + jmp viddone +; +; int 42 - 'old' video bios entry point. Use same windowed/fullscreen +; redirection as Int 10 above. +; +int42h_vector: + cmp use_host_int10, FULLSCREEN + jz maybe_host_42_bios + + bop 10h ; old video bop + jmp iret_com + + ; If it's the special BIOS print string function, don't call the + ; host video BIOS cos it won't know what we are talking about. + ; It's only in our video BIOS. +maybe_host_42_bios: + cmp AH, 013h + jnz gogo_host_42_bios + cmp AL, 0ffh + jz ms_wrt_string ; reuse path from Int 10 + +gogo_host_42_bios: + db 0EAh ; far jump +host_int42 dd ? ; to native int 42 vector + +int10h_caller: + int 10h ; Re-entrant video entry point. + bop 0feh + +int11h_vector: ; Equipment check. + bop 11h + jmp iret_com +int12h_vector: ; Get memory size, copied from BIOS2.ASM + bop 12h + jmp iret_com + +; IVT 13 is floppy io, grabbed above to fake error status. + +int14h_vector: ; RS-232 serial comms, copied from BIOS2 + bop 14h + jmp iret_com + +; Int 15 cassette io, is done above. + + + +; Idle indicators- All word sized, and dword aligned +; Int 16 keyboard vector + + align 4 + public Icounter,CharsPerTick,MinTicks + +Icounter dw 0 + dw 0 +CharsPerTick dw 0 + dw 0 +MinTicks dw 50 + dw 0 + +int16h_vector: + push ds + push bx + mov bx, 40h ; bios data adressable + mov ds, bx + cmp ah, 10h + call DOCLI ; make sure interrupts are off + jb i16vStdFns + jmp i16vExtFns + + + ; The dispatch code must preserve the jz,dec,dec pattern + ; to return the same ah value as is returned by the + ; standard bios (0 for supported unless otherwise documented + ; and nonzero for unsupported). This is because some apps look + ; at the ret value of ah even tho it is a side effect of the + ; original dispatch code in the rom bios. + +i16vStdFns: + or ah, ah + jz i16v00h ; read key, wait + dec ah + jz i16v01h ; read key no wait + dec ah + jz i16v02h ; get shift state + dec ah + jz i16viret ; we don't support ah=3, set kbd rate + dec ah + jz i16viret ; undefined function + dec ah + jz i16v05h ; push char into kbd buffer + ; the rest are undefined\unsupported + + ; normal iret exit +i16viret: + pop bx + pop ds + jmp iret_com + + + ; return shift state in al +i16v02h: + mov al, ds:[KB_FLAG] + jmp i16viret + + +i16v05h: + push si + mov bx, word ptr ds:[BUFFER_TAIL] + mov si, bx + call IncrBuffPtr + cmp bx, word ptr ds:[BUFFER_HEAD] + je i16v05h1 + mov word ptr ds:[si], cx + mov word ptr ds:[BUFFER_TAIL], bx + mov al, 0 + pop si + jmp i16viret + +i16v05h1: + mov al, 1 + pop si + jmp i16viret + + + ; read a character, wait if none available +i16v00h: + mov bx, word ptr ds:[BUFFER_HEAD] + cmp bx, word ptr ds:[BUFFER_TAIL] + jne i16v00h1 + call DOSTI + mov ax, 09002h + int 15h ; wait device + +i16v00h0: + call DOCLI + mov bx, word ptr ds:[BUFFER_HEAD] + cmp bx, word ptr ds:[BUFFER_TAIL] + +i16v00h1: + call UpdateLed + jne i16v00h2 + call IdlePoll + jmp i16v00h0 + +i16v00h2: ; translate..... + mov ax, [bx] + call IncrBuffPtr + mov word ptr ds:[BUFFER_HEAD], bx + call TranslateStd + jc i16v00h0 + call IdleInit + jmp i16viret + + + ; read a character, nowait if none available +i16v01h: + mov bx, word ptr ds:[BUFFER_HEAD] ;;maybe should turn IF on ?? + cmp bx, word ptr ds:[BUFFER_TAIL] + mov ax, [bx] + call UpdateLed + je i16vretf1 + + call IdleInit + call TranslateStd + call DOSTI + jnc i16vretf5 ; got a key, all done! + call IncrBuffPtr ; throw away key + mov word ptr ds:[BUFFER_HEAD], bx + jmp i16v01h ; go for the next one + + + ; ExtKbd read a character, nowait if none available +i16v11h: + mov bx, word ptr ds:[BUFFER_HEAD] ;;maybe should turn IF on ?? + cmp bx, word ptr ds:[BUFFER_TAIL] + mov ax, [bx] + call UpdateLed + je i16vretf1 ; common retf stuff for nowait + + call IdleInit + call TranslateExt + call DOSTI + jmp i16vretf5 + + + ; retf2 exit preserving flags +i16vretf1: + call DOSTI + push ax + lahf + push ax + + mov ax, cs:Icounter + cmp ax, cs:MinTicks + jb i16vretf2 + + mov ah, 1 ; polling kbd, idle now + BOP 16h + jmp i16vretf4 + +i16vretf2: + inc cs:CharsPerTick + + +i16vretf4: + pop ax + sahf + pop ax + +i16vretf5: + pop bx + pop ds + retf 2 + + + +i16vExtFns: + sub ah, 10h + jz i16v10h ; extended read key, wait + dec ah + jz i16v11h ; extended read key, nowait + dec ah + jz i16v12h ; extended shift status + jmp i16viret ; undefined + + + ; return extended shift state +i16v12h: + mov al, ds:[KB_FLAG_1] + mov ah, al + and al, SYS_SHIFT + push cx + mov cl, 5 + shl al, cl + pop cx + and ah, NOT (SYS_SHIFT+HOLD_STATE+INS_SHIFT) + or al, ah + mov ah, ds:[KB_FLAG_3] + and ah, NOT (LC_E1+LC_E0) + or ah, al + mov al, ds:[KB_FLAG] + jmp i16viret + + + ; ExtKbd read a character, wait if none available +i16v10h: + mov bx, word ptr ds:[BUFFER_HEAD] + cmp bx, word ptr ds:[BUFFER_TAIL] + jne i16v10h1 + call DOSTI + mov ax, 09002h + int 15h ; wait device + +i16v10h0: + call DOCLI + mov bx, word ptr ds:[BUFFER_HEAD] + cmp bx, word ptr ds:[BUFFER_TAIL] + +i16v10h1: + call UpdateLed + jne i16v10h2 + call IdlePoll + jmp i16v10h0 + +i16v10h2: ; translate..... + mov ax, [bx] + call IncrBuffPtr + mov word ptr ds:[BUFFER_HEAD], bx + call TranslateExt + call IdleInit + jmp i16viret + + + +; IdlePoll - Spins waiting for a key, doing idle callouts as needed +; flags trashed, all registers preserved +; interrupts are left on upon exit +; +IdlePoll proc near + push ax + + call DOSTI + mov ah, 2 ; Idle_waitio + BOP 16h +IPoll1: + mov bx, word ptr ds:[BUFFER_HEAD] + cmp bx, word ptr ds:[BUFFER_TAIL] ; interrupts are off only + jne IPoll3 ; safe to peek for change + + mov ax, cs:Icounter + cmp ax, cs:MinTicks + jae IPoll2 + inc cs:CharsPerTick + jmp IPoll1 +IPoll2: + mov ah, 1 ; idle now + BOP 16h +IPoll3: + pop ax + ret +IdlePoll endp + + + + +; IdleInit - reinits the idle indicators, dups functionality +; of IDLE_init() +; +IdleInit proc near + + mov cs:Icounter, 0 + mov cs:CharsPerTick, 0 + + ret +IdleInit endp + + +; TranslateExt - Retrieves and translates next scan code +; pair for extended kbd +; +; input: ax - raw scan code pair +; output: ax - translated scan code pair +; +; all other flags,registers preserved + +TranslateExt proc near + + push bx + push ax + lahf + mov bx, ax + pop ax + push bx + + cmp al, 0f0h + jne TExt1 + or ah, ah + jz TExt1 + xor al, al +TExt1: + mov bx, ax + pop ax + sahf + mov ax, bx + pop bx + ret + +TranslateExt endp + + +; TranslateStd - Retrieves and translates next scan code +; pair for standard kbd +; +; input: ax - raw scan code pair +; output: ax - translated scan code pair +; returns carry for throw away +; all other flags,registers preserved + +TranslateStd proc near + + push bx + push ax + lahf + mov bx, ax + pop ax + push bx + + cmp ah, 0e0h + jne TStd1 + + ; keypad enter or '/' + mov ah, 1ch ; assume enter key + cmp al, 0dh + je TStdNoCarry + cmp al, 0ah + je TStdNoCarry + mov ah, 35h ; oops it was key pad! + jmp TStdNoCarry + +TStd1: + cmp ah, 84h + ja TStdCarry ; extended key ? + + cmp al, 0f0h ; fill in key ? + jne TStd2 + or ah, ah ; ah = 0 is special + jz TStdNoCarry + jmp TStdCarry + +TStd2: + cmp al, 0e0h ; convert to compatible output + jne TStdNoCarry + or ah, ah + jz TStdNoCarry + xor al, al + +TStdNoCarry: + mov bx, ax + pop ax + sahf + mov ax, bx + pop bx + clc + ret + +TStdCarry: + mov bx, ax + pop ax + sahf + mov ax, bx + pop bx + stc + ret +TranslateStd endp + + + +; IncrBuffPtr - increments the buffer pointer +; +; input: ds:bx - curr buf ptr +; output: ds:bx - new buf ptr +; does not update the bios buf ptr + +IncrBuffPtr proc near + inc bx + inc bx + cmp bx, word ptr ds:[BUFFER_END] + jne ibpExit + mov bx, word ptr ds:[BUFFER_START] +ibpExit: + ret +IncrBuffPtr endp + + + +; UpdateLed - forms the data byte for the mode indicators +; updates the led bits (MAKE_LED,SEND_LED) +; +; input: none +; output: led bits updated +; +; Caveats: all low flags,registers preserved +; MUST be called with interrupts off +; does not update the kbd hardware (send_led) +; +UpdateLed proc near + + push bx + push cx + push ax + lahf + push ax + + ; make_led + mov al, byte ptr ds:[KB_FLAG] ; get led bits + and al, CAPS_STATE+NUM_STATE+SCROLL_STATE + mov cl, 4 + rol al, cl ; shift for kb_flag_2 + and al, KB_LEDS ; only led mode bits + + mov bl, byte ptr ds:[KB_FLAG_2] + xor bl, al ; see of different + and bl, KB_LEDS ; only led mode bits + jz UledExit + + + test byte ptr ds:[KB_FLAG_2], KB_PR_LED ;if update under way + jnz ULedExit ; skip update + or byte ptr ds:[KB_FLAG_2], KB_PR_LED ;else upd in progress + + mov ah, 3 ; inform softpc to set lights + BOP 16h + + and byte ptr ds:[KB_FLAG_2], NOT KB_LEDS ;clear led bits + or byte ptr ds:[KB_FLAG_2], al ;stick in new led bits + and byte ptr ds:[KB_FLAG_2], NOT KB_PR_LED ;clear upd bit + +ULedExit: + pop ax + sahf + pop ax + pop cx + pop bx + + ret +UpdateLed endp + + + + +; IVT 17 is printer IO, done above. + +int18h_vector: ; ROM BASIC, copied from BIOS2.ASM + bop 18h + jmp iret_com +int19h_vector: ; reboot vector, we terminate vdm! + bop 19h + jmp iret_com + + +IdleTicLo dw 0 +IdleTicHi dw 0 +IdleTicNum db 0 + +int1Ah_vector: ; Time of day. + call DOSTI + cmp ah, 2 + jl i1aTic1 + + bop 1ah + jmp iret_com + +i1aTic1: + push ds ; bios data adressable + push bx + push ax + mov ax, 40h + mov ds, ax + pop ax + call DOCLI + + or ah, ah ; fn 0 or fn 1 ? + jnz i1aTic5 + +i1aTic2: + mov al, byte ptr ds:[TIMER_OVFL] ; GetTickCount + mov cx, word ptr ds:[TIMER_HIGH] + mov dx, word ptr ds:[TIMER_LOW] + + + ; If time stamp is within 1 tic of curr tic count + ; do idle polling managment + + cmp cs:IdleTicHi, cx ; check TIMER_HIGH + jnz i1aTic8 + + mov bx, cs:IdleTicLo ; check TIMER_LOW + cmp bx, dx + jz i1aTic3 + inc bx + cmp bx, dx + jnz i1aTic8 + + +i1aTic3: + inc cs:IdleTicNum ; Yes, inc poll count + cmp cs:IdleTicNum, 16 ; Is poll count too hi ? + jb i1aTic9 + + call DOSTI + xor ax,ax ; Yes, do idle BOP + dec cs:IdleTicLo ; make sure only bop once + BOP 5ah + call DOCLI + jmp short i1aTic2 + +i1aTic5: + mov word ptr ds:[TIMER_LOW], dx ; SetTickCount + mov word ptr ds:[TIMER_HIGH], cx + +i1aTic8: + mov cs:IdleTicNum, 0 ; reset idle indicators + +i1aTic9: + mov cs:IdleTicLo, dx ; store time stamp + mov cs:IdleTicHi, cx + mov byte ptr ds:[TIMER_OVFL], 0 ; common TicCount exit + pop bx + pop ds + jmp iret_com + + +; IVT 1B is keyboard break, set to dummy. + + +int1Eh_vector: + bop 1eh + jmp iret_com + +int70h_vector: ; Real time clock, copied from BIOS1.ASM + bop 70h ; rtc_bios.c:rtc_int() + jmp iret_com + +int4Ah_caller: + call DOSTI ; Called from base\bios\rtc_bios.c:rtc_int() + int 4ah ; User installed alarm. + jmp r1 +r1: jmp r2 +r2: jmp r3 +r3: + call DOCLI + bop 0feh + +int71h_vector: ; redirect, copied from BIOS1.ASM + bop 71h + int 0Ah + jmp iret_com +int75h_vector: ; NPX 287. + bop 75h + int 02h + jmp iret_com +;================================================================= +; End of pseudo-ROM vectuz. +;================================================================= + + +;================================================================ +; Wait for interrupts +;================================================================ + +cpu_nop_code: + call DOSTI + jmp short nxt1 +nxt1: jmp short nxt2 +nxt2: jmp short nxt3 +nxt3: bop %BIOS_CPU_QUIT + + public SpcKbdEnd +SpcKbdEnd label byte + + align 4 ;; makes MIPS happy + +; offset table for redirected functions +kio_table dw 29 dup(?) + + public InstSpcKbd + +; +; InstSpcKbd - Installs the softpc custom interrupt hooks +; +; Inputs: ds == Resident location of SysInitSeg +; Outputs: None +; +InstSpcKbd proc near + + pusha + call DOCLI + + ; The following vectors are used for both x86\mips + ; The dos interrupts Int 25\Int26 are handled by the dos kerenl + xor ax, ax + mov es, ax + mov word ptr es:[08h*4], offset int08h_vector + mov word ptr es:[(08h*4)+2], ds + mov word ptr es:[09h*4], offset int09h_vector + mov word ptr es:[(09h*4)+2], ds + mov word ptr es:[13h*4], offset int13h_vector + mov word ptr es:[(13h*4)+2], ds + mov word ptr es:[16h*4], offset int16h_vector + mov word ptr es:[(16h*4)+2], ds + mov word ptr es:[40h*4], offset int40h_vector + mov word ptr es:[(40h*4)+2], ds + mov word ptr es:[19h*4], offset int19h_vector + mov word ptr es:[(19h*4)+2], ds + mov word ptr es:[1ah*4], offset int1Ah_vector + mov word ptr es:[(1ah*4)+2], ds + + + + ; BOP 5F - send interesting addresses to softpc C BIOS + ; CS seg of kio_table + ; DS seg of resident keyboard code + ; DI offset of bop table + ; CX size of bop table entry + ; SI offset of kio_table + mov si,offset sysinitgrp:kio_table + push ds + push cs + pop ds + mov word ptr [si], offset shift_keys ;K6 + mov word ptr [si+2], offset shift_masks ;K7 + mov word ptr [si+4], offset ctl_n_table ;K8 + mov word ptr [si+6], offset ctl_f_table ;K9 + mov word ptr [si+8], offset lowercase ;K10 + mov word ptr [si+10], offset uppercase ;K11 + mov word ptr [si+12], offset alt_table ;K30 + mov word ptr [si+14], offset dummy_vector + mov word ptr [si+16], offset print_screen_caller + mov word ptr [si+18], offset int15h_caller + mov word ptr [si+20], offset cpu_nop_code + mov word ptr [si+22], offset int15h_vector + mov word ptr [si+24], offset Icounter + mov word ptr [si+26], offset int4Ah_caller + mov word ptr [si+28], offset keyboard_break_caller + mov word ptr [si+30], offset int10h_caller + mov word ptr [si+32], offset int10h_vector + mov word ptr [si+34], offset use_host_int10 + mov word ptr [si+36], offset ega_parm_setup + mov word ptr [si+38], offset changing_mode + mov word ptr [si+40], offset prt_status + mov word ptr [si+42], offset wait_int + mov word ptr [si+44], offset floppy_table + mov word ptr [si+46], offset vga_1b_table + mov word ptr [si+48], offset conf_table + mov word ptr [si+50], offset int08h_vector + mov word ptr [si+52], offset int13h_vector + mov word ptr [si+54], offset int13h_caller +; The last entry is reserved for assertion checking + mov word ptr [si+56], VERSIONID + pop ds + + ; mov si, offset kio_table + mov di, offset iret_bop_table + mov cx, offset iret_end_first_entry - offset iret_bop_table + mov ax, VERSIONID + bop 5fh + jc isk_int9 + jmp isk_Exit +isk_int9: + + ; save old video int + xor ax, ax + mov es, ax + mov bx, es:[40h] + mov si, offset host_int10 + mov word ptr ds:[si], bx + mov bx, es:[42h] + mov word ptr ds:[si+2], bx + + ; save old secondary video int (42h) + mov bx, es:[108h] + mov si, offset host_int42 + mov word ptr ds:[si], bx + mov bx, es:[10ah] + mov word ptr ds:[si+2], bx + + +;----------------------------------------------------------- +; +; Crazy vector grabber +; +; Works OK on DEC PC when grab INT's 6, 11, 16, 17, 42. +; Now try and avoid all accesses to host ROM. +; +; At this point we assume ES=0 +;----------------------------------------------------------- + + ; Grab some prominent vectors for pseudo-ROM routines. + ; start at Int 0h and work our way up as needed + cld + + mov di, 20 + mov ax, offset int05h_vector ; INT 05h + stosw ; Print screen + mov ax, ds + stosw + mov ax, offset int06h_vector ; INT 06h + stosw ; Illegal instruction. + mov ax, ds + stosw + mov ax, offset unexp_int ; INT 07h + stosw + mov ax, ds + stosw + + ; int 8h Timer hardware vector already done for both x86\mips + ; int 9h kbd hardware vector already done for both x86\mips + add di, 8 + + mov ax, offset unexp_int ; INT 0ah + stosw + mov ax, ds + stosw + mov ax, offset unexp_int ; INT 0bh + stosw + mov ax, ds + stosw + mov ax, offset unexp_int ; INT 0ch + stosw + mov ax, ds + stosw + mov ax, offset unexp_int ; INT 0dh + stosw + mov ax, ds + stosw + mov ax, offset int0e_vector ; INT 0eh + stosw ; Floppy hardware int. + mov ax, ds + stosw + mov ax, offset unexp_int ; INT 0fh + stosw + mov ax, ds + stosw + mov ax, offset int10h_vector ; INT 10h + stosw + mov ax, ds + stosw + mov ax, offset int11h_vector ; INT 11h + stosw ; Equipment check. + mov ax, ds + stosw + mov ax, offset int12h_vector ; INT 12h + stosw ; Get memory size. + mov ax, ds + stosw + + ; int 13h already done (see above) for both mips\x86 + + mov di, 14h*4 ; Communications. + mov ax, offset int14h_vector + stosw + mov ax, ds + stosw + mov ax, offset int15h_vector ; INT 15h + stosw + mov ax, ds + stosw + + ; int 16h kbd hardware vector already done for both x86\mips + add di, 4 + + mov ax, offset int17h_vector ; INT 17h + stosw + mov ax, ds + stosw + mov ax, offset int18h_vector ; INT 18h + stosw ; ROM BASIC. + mov ax, ds + stosw + + ; int 19h (reboot vector) already done for both x86\mips + + ; int 1ah, time of day, already done for both x86\mips + + mov di, 1Bh*4 + mov ax, offset dummy_vector ; INT 1Bh + stosw ; Keyboard break. + mov ax, ds + stosw + mov ax, offset dummy_vector ; INT 1Ch + stosw ; Timer tick. + mov ax, ds + stosw + + mov di, 1Eh*4 ; Floppy parameters. + mov ax, offset bios_floppy_table + stosw + mov ax, ds + stosw + + ; int 40h already done (see above) for both mips\x86 + + mov di, 41h*4 + mov ax, offset unexp_int ; INT 41h + stosw ; Hard disk parameters. + mov ax, ds + stosw + mov ax, offset int42h_vector ; INT 42h + stosw ; Default video. + mov ax, ds + stosw + + mov di, 70h*4 ; Real time clock init. + mov ax, offset int70h_vector + stosw + mov ax, ds + stosw + mov ax, offset int71h_vector ; INT 71h Redirect. + stosw + mov ax, ds + stosw + mov ax, offset intD11_vector ; INT 72h D11 int + stosw + mov ax, ds + stosw + mov ax, offset intD11_vector ; INT 73h D11 int + stosw + mov ax, ds + stosw + mov ax, offset intD11_vector ; INT 74h D11 int + stosw + mov ax, ds + stosw + mov ax, offset int75h_vector ; INT 75h 287 int + stosw + mov ax, ds + stosw + mov ax, offset intD11_vector ; INT 76h D11 int + stosw + mov ax, ds + stosw + mov ax, offset intD11_vector ; INT 77h D11 int + stosw + mov ax, ds + stosw + + +isk_Exit: + call DOSTI + popa + ret + +InstSpcKbd endp + +SpcKbdSeg ends + end diff --git a/private/mvdm/softpc.new/bios/spcmse.asm b/private/mvdm/softpc.new/bios/spcmse.asm new file mode 100644 index 000000000..bfdea5c8b --- /dev/null +++ b/private/mvdm/softpc.new/bios/spcmse.asm @@ -0,0 +1,5412 @@ +; Program: Installable Device Driver for Mouse. +; +; Purpose: to provide compatability with the +; Microsoft MOUSE.SYS device driver. +; the code here installs the driver and +; hooks the IVT in exactly the same +; way as the current Insignia MOUSE.COM. +; +; Version: 1.00 Date: 28th October 1992. +; +; Author: Andrew Watson +; +; Revisions: +; +; 23-June-1994 Williamh, made mode 4/5 and 12 work. +; +; 12-Sep-1992 Jonle, Merged with ntio.sys +; optimized loading of IVT +; +; 5-March-1993 Andyw, Moved fullscreen text pointer code +; from 32bit land to 16bit driver for +; for speed purposes. +; +; This obj module is intially loaded in a temporary memory location +; along with ntio.sys. Ntio.sys will copy the resident code (marked by +; SpcMseBeg, SpcMseEnd) into the permanent memory location which resides +; just below the normal device drivers loaded by config.sys. +; +; The nonresident intialization code is run with CS= temp seg +; and DS= final seg. +; +; +;**************************************************************** + +.286 + include vint.inc + +;================================================================ +; Defined constants used in the driver. +;================================================================ + + + VERSIONID equ 0BEEFh + MAXCMD equ 16 + UNKNOWN equ 8003h + DONE equ 0100h + MOUSEVER equ 0003h + INT1_BOP equ 0BAh + INT2_BOP equ 0BBh + IO_LANG_BOP equ 0BCh + IO_INTR_BOP equ 0BDh + VIDEO_IO_BOP equ 0BEh + UNSIMULATE_BOP equ 0FEh + VIDEO equ 010h + UNEXP_BOP equ 2 + FORCE_YODA equ 05bh + ANDYS_BOP equ 060h + STACKSIZE equ 200h-1 + + TRUE equ 0 + FALSE equ 1 + STORED equ 0 + NOTSTORED equ 1 + ON equ 0 + OFF equ 1 + + MAJOR_RELEASE_NUMBER equ 6 + MINOR_RELEASE_NUMBER equ 26 + + + +;MACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROS + +bop MACRO callid + db 0c4h,0c4h,callid +endm + + + +;============================================================================= +; Macro to reassign the stack segment register to point at the driver code +; segment and the stack pointer to point to the most significant word in an +; array reserved as the driver stack. +;============================================================================= + + +;; !!!! interrupt must be disabled before calling this function !!!!!! + +make_stack MACRO + LOCAL reent ;; a local symbol to this macro +;; call DOCLI ;; turn off interrupts during this + ;; macro's execution even if the CPU + ;; does this for you when modifying SS + inc cs:reentrant ;; has the interrupt been nested? + jnz reent ;; not reentrant if == zero + + ;; The driver code is not reentrant, so start the stack at the beginning + + mov cs:top_of_stack,ss ;; save the entry SS + mov cs:top_of_stack-2,sp ;; save SP on the stack + push cs ;; the current code/data segment + pop ss ;; point SS at CS + + ;; point SP at the next free stack location. + + mov sp,offset top_of_stack-2 ;; The current stack pointer position + +reent: ;; REENTRANT > 0 therefore reentrancy exists + ;; The driver has gone reentrant due to a nested interrupt, so just + ;; leave the stack alone because it is the same under reentrancy. + +;; call DOSTI ;; reenable interrupts + + ENDM + +;============================================================================= +; Macro to return the stack pointer and segment back to what it was when +; the driver was called. +;============================================================================= + +kill_stack MACRO + LOCAL reent1 +;; cli + cmp cs:reentrant,0 ;; is the code currently reentrant? + jg reent1 ;; yes it is + mov sp,cs:top_of_stack-2 ;; pop SP + mov ss,cs:top_of_stack ;; pop SS +reent1: + dec cs:reentrant ;; reduce the level of reentrancy +;; call DOSTI + ENDM + +;MACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROSMACROS + +; +; Segment definitions for ntio.sys, +; +include biosseg.inc + + + + +SpcMseSeg segment + assume cs:SpcMseSeg, ds:nothing, es:nothing + +; +; SpcMseBeg - SpcMseEnd +; +; Marks the resident code, anything outside of these markers +; is discarded after intialization +; 15-Sep-1992 Jonle +; + + public SpcMseBeg + +SpcMseBeg label byte + + ; CAUTION: for crazy apps mouse recognition + ; + ; The offset for int33h_vector must not be Zero for Borlands QuattroPro + ; The segment must not be in ROM area for pctools + ; to keep the int33h_vector from having an offset of ZERO + ; I have moved the data above it + ; 25-Sep-1992 Jonle + + +; describe the default screen and cursor masks +; remember that x86 machines are little-endian + + ;;; include pointer.inc + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;;; We'll Get this back to an include file soon but I'm including it like + ;;;; this for 'diplomatic' reasons. (ie I want to check this in without + ;;;; also doing an 'addfile' at this stage)!!! - Simon. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This data will be accessed, on occasion, word by word, so +; be tidy and align to a word boundary + +align 2 + +; Describe the default mouse pointer image. This is used if the +; user decides to switch on the pointer without specifying an image. + +default_cursor dw 0011111111111111b + dw 0001111111111111b + dw 0000111111111111b + dw 0000011111111111b + dw 0000001111111111b + dw 0000000111111111b + dw 0000000011111111b + dw 0000000001111111b + dw 0000000000111111b + dw 0000000000011111b + dw 0000000111111111b + dw 0001000011111111b + dw 0011000011111111b + dw 1111100001111111b + dw 1111100001111111b + dw 1111110001111111b + dw 0000000000000000b + dw 0100000000000000b + dw 0110000000000000b + dw 0111000000000000b + dw 0111100000000000b + dw 0111110000000000b + dw 0111111000000000b + dw 0111111100000000b + dw 0111111110000000b + dw 0111110000000000b + dw 0110110000000000b + dw 0100011000000000b + dw 0000011000000000b + dw 0000001100000000b + dw 0000001100000000b + dw 0000000000000000b + + ; Set up the memory where the working cursor is situated. It is + ; initialised to the default cursor image + +;****************** ALIGNED FOR PIXEL ZERO ******************************* + + ; screen mask + +even +current_cursor db 00111111b,11111111b,11111111b + db 00011111b,11111111b,11111111b + db 00001111b,11111111b,11111111b + db 00000111b,11111111b,11111111b + db 00000011b,11111111b,11111111b + db 00000001b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000000b,01111111b,11111111b + db 00000000b,00111111b,11111111b + db 00000000b,00011111b,11111111b + db 00000001b,11111111b,11111111b + db 00010000b,11111111b,11111111b + db 00110000b,11111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111100b,01111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 01000000b,00000000b,00000000b + db 01100000b,00000000b,00000000b + db 01110000b,00000000b,00000000b + db 01111000b,00000000b,00000000b + db 01111100b,00000000b,00000000b + db 01111110b,00000000b,00000000b + db 01111111b,00000000b,00000000b + db 01111111b,10000000b,00000000b + db 01111111b,11000000b,00000000b + db 01101100b,00000000b,00000000b + db 01000110b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL ONE ******************************* + + ; screen mask + +AlignData1: + db 10011111b,11111111b,11111111b + db 10001111b,11111111b,11111111b + db 10000111b,11111111b,11111111b + db 10000011b,11111111b,11111111b + db 10000001b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,01111111b,11111111b + db 10000000b,00111111b,11111111b + db 10000000b,00011111b,11111111b + db 10000000b,00001111b,11111111b + db 10000000b,11111111b,11111111b + db 10001000b,01111111b,11111111b + db 10011000b,01111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111110b,00111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00100000b,00000000b,00000000b + db 00110000b,00000000b,00000000b + db 00111000b,00000000b,00000000b + db 00111100b,00000000b,00000000b + db 00111110b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00111111b,10000000b,00000000b + db 00111111b,11000000b,00000000b + db 00111111b,11100000b,00000000b + db 00110110b,00000000b,00000000b + db 00100011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL TWO ******************************* + + ; screen mask + +AlignData2: + db 11001111b,11111111b,11111111b + db 11000111b,11111111b,11111111b + db 11000011b,11111111b,11111111b + db 11000001b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,01111111b,11111111b + db 11000000b,00111111b,11111111b + db 11000000b,00011111b,11111111b + db 11000000b,00001111b,11111111b + db 11000000b,00000111b,11111111b + db 11000000b,01111111b,11111111b + db 11000100b,00111111b,11111111b + db 11001100b,00111111b,11111111b + db 11111110b,00011111b,11111111b + db 11111110b,00011111b,11111111b + db 11111111b,00011111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00010000b,00000000b,00000000b + db 00011000b,00000000b,00000000b + db 00011100b,00000000b,00000000b + db 00011110b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,10000000b,00000000b + db 00011111b,11000000b,00000000b + db 00011111b,11100000b,00000000b + db 00011111b,11110000b,00000000b + db 00011011b,00000000b,00000000b + db 00010001b,10000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL THREE ******************************* + + ; screen mask + +AlignData3: + db 11100111b,11111111b,11111111b + db 11100011b,11111111b,11111111b + db 11100001b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,01111111b,11111111b + db 11100000b,00111111b,11111111b + db 11100000b,00011111b,11111111b + db 11100000b,00001111b,11111111b + db 11100000b,00000111b,11111111b + db 11100000b,00000011b,11111111b + db 11100000b,00111111b,11111111b + db 11100010b,00011111b,11111111b + db 11100110b,00011111b,11111111b + db 11111111b,00001111b,11111111b + db 11111111b,00001111b,11111111b + db 11111111b,10001111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00001000b,00000000b,00000000b + db 00001100b,00000000b,00000000b + db 00001110b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,10000000b,00000000b + db 00001111b,11000000b,00000000b + db 00001111b,11100000b,00000000b + db 00001111b,11110000b,00000000b + db 00001111b,11111000b,00000000b + db 00001101b,10000000b,00000000b + db 00001000b,11000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FOUR ******************************* + + ; screen mask + +AlignData4: + db 11110011b,11111111b,11111111b + db 11110001b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,01111111b,11111111b + db 11110000b,00111111b,11111111b + db 11110000b,00011111b,11111111b + db 11110000b,00001111b,11111111b + db 11110000b,00000111b,11111111b + db 11110000b,00000011b,11111111b + db 11110000b,00000001b,11111111b + db 11110000b,00011111b,11111111b + db 11110001b,00001111b,11111111b + db 11110011b,00001111b,11111111b + db 11111111b,10000111b,11111111b + db 11111111b,10000111b,11111111b + db 11111111b,11000111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000100b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,10000000b,00000000b + db 00000111b,11000000b,00000000b + db 00000111b,11100000b,00000000b + db 00000111b,11110000b,00000000b + db 00000111b,11111000b,00000000b + db 00000111b,11111100b,00000000b + db 00000110b,11000000b,00000000b + db 00000100b,01100000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FIVE ******************************* + + ; screen mask +AlignData5: + + db 11111001b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111000b,00111111b,11111111b + db 11111000b,00011111b,11111111b + db 11111000b,00001111b,11111111b + db 11111000b,00000111b,11111111b + db 11111000b,00000011b,11111111b + db 11111000b,00000001b,11111111b + db 11111000b,00000000b,11111111b + db 11111000b,00001111b,11111111b + db 11111000b,10000111b,11111111b + db 11111001b,10000111b,11111111b + db 11111111b,11000011b,11111111b + db 11111111b,11000011b,11111111b + db 11111111b,11100011b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000010b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,10000000b,00000000b + db 00000011b,11000000b,00000000b + db 00000011b,11100000b,00000000b + db 00000011b,11110000b,00000000b + db 00000011b,11111000b,00000000b + db 00000011b,11111100b,00000000b + db 00000011b,11111110b,00000000b + db 00000011b,01100000b,00000000b + db 00000010b,00110000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SIX ******************************* + + ; screen mask + +AlignData6: + db 11111100b,11111111b,11111111b + db 11111100b,01111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111100b,00011111b,11111111b + db 11111100b,00001111b,11111111b + db 11111100b,00000111b,11111111b + db 11111100b,00000011b,11111111b + db 11111100b,00000001b,11111111b + db 11111100b,00000000b,11111111b + db 11111100b,00000000b,01111111b + db 11111100b,00000111b,11111111b + db 11111100b,01000011b,11111111b + db 11111100b,11000011b,11111111b + db 11111111b,11100001b,11111111b + db 11111111b,11100001b,11111111b + db 11111111b,11110001b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000001b,11000000b,00000000b + db 00000001b,11100000b,00000000b + db 00000001b,11110000b,00000000b + db 00000001b,11111000b,00000000b + db 00000001b,11111100b,00000000b + db 00000001b,11111110b,00000000b + db 00000001b,11111111b,00000000b + db 00000001b,10110000b,00000000b + db 00000001b,00011000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SEVEN ******************************* + + ; screen mask +AlignData7: + + db 11111110b,01111111b,11111111b + db 11111110b,00111111b,11111111b + db 11111110b,00011111b,11111111b + db 11111110b,00001111b,11111111b + db 11111110b,00000111b,11111111b + db 11111110b,00000011b,11111111b + db 11111110b,00000001b,11111111b + db 11111110b,00000000b,11111111b + db 11111110b,00000000b,01111111b + db 11111110b,00000000b,00111111b + db 11111110b,00000011b,11111111b + db 11111110b,00100001b,11111111b + db 11111110b,01100001b,11111111b + db 11111111b,11110000b,11111111b + db 11111111b,11110000b,11111111b + db 11111111b,11111000b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000000b,10000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,11100000b,00000000b + db 00000000b,11110000b,00000000b + db 00000000b,11111000b,00000000b + db 00000000b,11111100b,00000000b + db 00000000b,11111110b,00000000b + db 00000000b,11111111b,00000000b + db 00000000b,11111111b,10000000b + db 00000000b,11011000b,00000000b + db 00000000b,10001100b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00000110b,00000000b + db 00000000b,00000110b,00000000b + db 00000000b,00000000b,00000000b + + +; Data area reserved for the clipped cursor images. When the pointer +; reaches byte 78 in the current raster, the image needs to be clipped +; to prevent it from being wrapped to the left hand edge of the screen. +; The image below stops that from happening by loading the image with +; a 1's partial AND mask and a 0's partial XOR mask. +; Note that byte 79 also needs a clipped image set. + +even +clip_cursor78 db 00111111b,11111111b,11111111b + db 00011111b,11111111b,11111111b + db 00001111b,11111111b,11111111b + db 00000111b,11111111b,11111111b + db 00000011b,11111111b,11111111b + db 00000001b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000000b,01111111b,11111111b + db 00000000b,00111111b,11111111b + db 00000000b,00011111b,11111111b + db 00000001b,11111111b,11111111b + db 00010000b,11111111b,11111111b + db 00110000b,11111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111100b,01111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 01000000b,00000000b,00000000b + db 01100000b,00000000b,00000000b + db 01110000b,00000000b,00000000b + db 01111000b,00000000b,00000000b + db 01111100b,00000000b,00000000b + db 01111110b,00000000b,00000000b + db 01111111b,00000000b,00000000b + db 01111111b,10000000b,00000000b + db 01111111b,11000000b,00000000b + db 01101100b,00000000b,00000000b + db 01000110b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL ONE ******************************* + + ; screen mask + +AlignClip178: + db 10011111b,11111111b,11111111b + db 10001111b,11111111b,11111111b + db 10000111b,11111111b,11111111b + db 10000011b,11111111b,11111111b + db 10000001b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,01111111b,11111111b + db 10000000b,00111111b,11111111b + db 10000000b,00011111b,11111111b + db 10000000b,00001111b,11111111b + db 10000000b,11111111b,11111111b + db 10001000b,01111111b,11111111b + db 10011000b,01111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111110b,00111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00100000b,00000000b,00000000b + db 00110000b,00000000b,00000000b + db 00111000b,00000000b,00000000b + db 00111100b,00000000b,00000000b + db 00111110b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00111111b,10000000b,00000000b + db 00111111b,11000000b,00000000b + db 00111111b,11100000b,00000000b + db 00110110b,00000000b,00000000b + db 00100011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL TWO ******************************* + + ; screen mask + +AlignClip278: + db 11001111b,11111111b,11111111b + db 11000111b,11111111b,11111111b + db 11000011b,11111111b,11111111b + db 11000001b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,01111111b,11111111b + db 11000000b,00111111b,11111111b + db 11000000b,00011111b,11111111b + db 11000000b,00001111b,11111111b + db 11000000b,00000111b,11111111b + db 11000000b,01111111b,11111111b + db 11000100b,00111111b,11111111b + db 11001100b,00111111b,11111111b + db 11111110b,00011111b,11111111b + db 11111110b,00011111b,11111111b + db 11111111b,00011111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00010000b,00000000b,00000000b + db 00011000b,00000000b,00000000b + db 00011100b,00000000b,00000000b + db 00011110b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,10000000b,00000000b + db 00011111b,11000000b,00000000b + db 00011111b,11100000b,00000000b + db 00011111b,11110000b,00000000b + db 00011011b,00000000b,00000000b + db 00010001b,10000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL THREE ******************************* + + ; screen mask + +AlignClip378: + db 11100111b,11111111b,11111111b + db 11100011b,11111111b,11111111b + db 11100001b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,01111111b,11111111b + db 11100000b,00111111b,11111111b + db 11100000b,00011111b,11111111b + db 11100000b,00001111b,11111111b + db 11100000b,00000111b,11111111b + db 11100000b,00000011b,11111111b + db 11100000b,00111111b,11111111b + db 11100010b,00011111b,11111111b + db 11100110b,00011111b,11111111b + db 11111111b,00001111b,11111111b + db 11111111b,00001111b,11111111b + db 11111111b,10001111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00001000b,00000000b,00000000b + db 00001100b,00000000b,00000000b + db 00001110b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,10000000b,00000000b + db 00001111b,11000000b,00000000b + db 00001111b,11100000b,00000000b + db 00001111b,11110000b,00000000b + db 00001111b,11111000b,00000000b + db 00001101b,10000000b,00000000b + db 00001000b,11000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FOUR ******************************* + + ; screen mask + +AlignClip478: + db 11110011b,11111111b,11111111b + db 11110001b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,01111111b,11111111b + db 11110000b,00111111b,11111111b + db 11110000b,00011111b,11111111b + db 11110000b,00001111b,11111111b + db 11110000b,00000111b,11111111b + db 11110000b,00000011b,11111111b + db 11110000b,00000001b,11111111b + db 11110000b,00011111b,11111111b + db 11110001b,00001111b,11111111b + db 11110011b,00001111b,11111111b + db 11111111b,10000111b,11111111b + db 11111111b,10000111b,11111111b + db 11111111b,11000111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000100b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,10000000b,00000000b + db 00000111b,11000000b,00000000b + db 00000111b,11100000b,00000000b + db 00000111b,11110000b,00000000b + db 00000111b,11111000b,00000000b + db 00000111b,11111100b,00000000b + db 00000110b,11000000b,00000000b + db 00000100b,01100000b,00000000b + db 00000000b,01100000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FIVE ******************************* + + ; screen mask +AlignClip578: + + db 11111001b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111000b,00111111b,11111111b + db 11111000b,00011111b,11111111b + db 11111000b,00001111b,11111111b + db 11111000b,00000111b,11111111b + db 11111000b,00000011b,11111111b + db 11111000b,00000001b,11111111b + db 11111000b,00000000b,11111111b + db 11111000b,00001111b,11111111b + db 11111000b,10000111b,11111111b + db 11111001b,10000111b,11111111b + db 11111111b,11000011b,11111111b + db 11111111b,11000011b,11111111b + db 11111111b,11100011b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000010b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,10000000b,00000000b + db 00000011b,11000000b,00000000b + db 00000011b,11100000b,00000000b + db 00000011b,11110000b,00000000b + db 00000011b,11111000b,00000000b + db 00000011b,11111100b,00000000b + db 00000011b,11111110b,00000000b + db 00000011b,01100000b,00000000b + db 00000010b,00110000b,00000000b + db 00000000b,00110000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SIX ******************************* + + ; screen mask + +AlignClip678: + db 11111100b,11111111b,11111111b + db 11111100b,01111111b,11111111b + db 11111100b,00111111b,11111111b + db 11111100b,00011111b,11111111b + db 11111100b,00001111b,11111111b + db 11111100b,00000111b,11111111b + db 11111100b,00000011b,11111111b + db 11111100b,00000001b,11111111b + db 11111100b,00000000b,11111111b + db 11111100b,00000000b,11111111b + db 11111100b,00000111b,11111111b + db 11111100b,01000011b,11111111b + db 11111100b,11000011b,11111111b + db 11111111b,11100001b,11111111b + db 11111111b,11100001b,11111111b + db 11111111b,11110001b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,10000000b,00000000b + db 00000001b,11000000b,00000000b + db 00000001b,11100000b,00000000b + db 00000001b,11110000b,00000000b + db 00000001b,11111000b,00000000b + db 00000001b,11111100b,00000000b + db 00000001b,11111110b,00000000b + db 00000001b,11111111b,00000000b + db 00000001b,10110000b,00000000b + db 00000001b,00011000b,00000000b + db 00000000b,00011000b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SEVEN ******************************* + + ; screen mask +AlignClip778: + + db 11111110b,01111111b,11111111b + db 11111110b,00111111b,11111111b + db 11111110b,00011111b,11111111b + db 11111110b,00001111b,11111111b + db 11111110b,00000111b,11111111b + db 11111110b,00000011b,11111111b + db 11111110b,00000001b,11111111b + db 11111110b,00000000b,11111111b + db 11111110b,00000000b,11111111b + db 11111110b,00000000b,11111111b + db 11111110b,00000011b,11111111b + db 11111110b,00100001b,11111111b + db 11111110b,01100001b,11111111b + db 11111111b,11110000b,11111111b + db 11111111b,11110000b,11111111b + db 11111111b,11111000b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000000b,10000000b,00000000b + db 00000000b,11000000b,00000000b + db 00000000b,11100000b,00000000b + db 00000000b,11110000b,00000000b + db 00000000b,11111000b,00000000b + db 00000000b,11111100b,00000000b + db 00000000b,11111110b,00000000b + db 00000000b,11111111b,00000000b + db 00000000b,11111111b,00000000b + db 00000000b,11011000b,00000000b + db 00000000b,10001100b,00000000b + db 00000000b,00001100b,00000000b + db 00000000b,00000110b,00000000b + db 00000000b,00000110b,00000000b + db 00000000b,00000000b,00000000b + + +clip_cursor79 db 00111111b,11111111b,11111111b + db 00011111b,11111111b,11111111b + db 00001111b,11111111b,11111111b + db 00000111b,11111111b,11111111b + db 00000011b,11111111b,11111111b + db 00000001b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000000b,11111111b,11111111b + db 00000001b,11111111b,11111111b + db 00010000b,11111111b,11111111b + db 00110000b,11111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111000b,01111111b,11111111b + db 11111100b,01111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 01000000b,00000000b,00000000b + db 01100000b,00000000b,00000000b + db 01110000b,00000000b,00000000b + db 01111000b,00000000b,00000000b + db 01111100b,00000000b,00000000b + db 01111110b,00000000b,00000000b + db 01111111b,00000000b,00000000b + db 01111111b,00000000b,00000000b + db 01111111b,00000000b,00000000b + db 01101100b,00000000b,00000000b + db 01000110b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL ONE ******************************* + + ; screen mask + +AlignClip179: + db 10011111b,11111111b,11111111b + db 10001111b,11111111b,11111111b + db 10000111b,11111111b,11111111b + db 10000011b,11111111b,11111111b + db 10000001b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10000000b,11111111b,11111111b + db 10001000b,11111111b,11111111b + db 10011000b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111110b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00100000b,00000000b,00000000b + db 00110000b,00000000b,00000000b + db 00111000b,00000000b,00000000b + db 00111100b,00000000b,00000000b + db 00111110b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00111111b,00000000b,00000000b + db 00110110b,00000000b,00000000b + db 00100011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL TWO ******************************* + + ; screen mask + +AlignClip279: + db 11001111b,11111111b,11111111b + db 11000111b,11111111b,11111111b + db 11000011b,11111111b,11111111b + db 11000001b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000000b,11111111b,11111111b + db 11000100b,11111111b,11111111b + db 11001100b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00010000b,00000000b,00000000b + db 00011000b,00000000b,00000000b + db 00011100b,00000000b,00000000b + db 00011110b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011111b,00000000b,00000000b + db 00011011b,00000000b,00000000b + db 00010001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL THREE ******************************* + + ; screen mask + +AlignClip379: + db 11100111b,11111111b,11111111b + db 11100011b,11111111b,11111111b + db 11100001b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100000b,11111111b,11111111b + db 11100010b,11111111b,11111111b + db 11100110b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00001000b,00000000b,00000000b + db 00001100b,00000000b,00000000b + db 00001110b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001111b,00000000b,00000000b + db 00001101b,00000000b,00000000b + db 00001000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FOUR ******************************* + + ; screen mask + +AlignClip479: + db 11110011b,11111111b,11111111b + db 11110001b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110000b,11111111b,11111111b + db 11110001b,11111111b,11111111b + db 11110011b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000100b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000111b,00000000b,00000000b + db 00000110b,00000000b,00000000b + db 00000100b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL FIVE ******************************* + + ; screen mask +AlignClip579: + + db 11111001b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111000b,11111111b,11111111b + db 11111001b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000010b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000011b,00000000b,00000000b + db 00000010b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SIX ******************************* + + ; screen mask + +AlignClip679: + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111100b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000001b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + + +;****************** ALIGNED FOR PIXEL SEVEN ******************************* + + ; screen mask +AlignClip779: + + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111110b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + db 11111111b,11111111b,11111111b + + ; cursor mask + + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + db 00000000b,00000000b,00000000b + +CursorOffsetLUT dw current_cursor + dw AlignData1 + dw AlignData2 + dw AlignData3 + dw AlignData4 + dw AlignData5 + dw AlignData6 + dw AlignData7 +ClipOffsetLUT78 dw clip_cursor78 + dw AlignClip178 + dw AlignClip278 + dw AlignClip378 + dw AlignClip478 + dw AlignClip578 + dw AlignClip678 + dw AlignClip778 +ClipOffsetLUT79 dw clip_cursor79 + dw AlignClip179 + dw AlignClip279 + dw AlignClip379 + dw AlignClip479 + dw AlignClip579 + dw AlignClip679 + dw AlignClip779 + +; pointer to the current look up table set for the pointer image. +; The LUTs are swapped when the pointer enters bytes 78 and 79 +; along a scanline to prevent the pointer wrapping around the screen. + +PointerLUT label word + dw offset CursorOffsetLUT + ;;;;;;;;;;;;;;;;;;;;;;; + ;;;; End of what should be an include for pointer.inc + ;;;;;;;;;;;;;;;;;;;;;;; + + even + clrgend dw 06e41h,07964h,05720h,07461h,06f73h,0f36eh + hiresylut dw 350,350,480,480 + +;============================================================================ +; Surprisingly, a look up table multiply is much faster than +; the shift - add instruction sequence for multiplying by 80. +; So it would be silly not to use it eh? Times by 80 is needed +; to convert a raster location (1 raster = 80 bytes) in pixel +; y coordinates into a video buffer byte index +; Note: Multiply by 80 is also used for text mode calculations +; now! Andy on the 9/3/93 +;============================================================================ + even + + mult80lut label word + + mulsum=0 + REPT 480 ; number of VGA scanlines for mode 12h + dw mulsum + mulsum=mulsum+80 + ENDM + +;============================================================================ +; A table to do a multiply by 320. This is used for converting number of +; rasters into video buffer offsets for mode 13h (256 VGA colour mode). +;============================================================================ + even + + mult320lut label word + + mulsum=0 + REPT 200 ; number of VGA scanlines for mode 13h + dw mulsum + mulsum=mulsum+320 + ENDM + even + +;============================================================================ +; Look up table for use with modes 10h and 12h. This table provides the means +; for the selection of a clipped or unclipped pointer image depending on the +; current x position of the pointer. +;============================================================================ + + ChooseImageLUT label word + + REPT 624 + dw offset CursorOffsetLUT + ENDM + + REPT 8 + dw offset ClipOffsetLUT78 + ENDM + + REPT 8 + dw offset ClipOffsetLUT79 + ENDM + +;============================================================================ +; Buffer arranged for 4 plane EGA video modes. The screen where +; the pointer is going to be drawn is scanned plane by plane and +; saved as bitplane separations. +;============================================================================ + + even ; make sure that this data is word aligned + + behindcursor dw 24 dup(?) ; Plane 0 + dw 24 dup(?) ; Plane 1 + dw 24 dup(?) ; Plane 2 + dw 24 dup(?) ; Plane 3 + + +;============================================================================ +; a table of the video buffer segment for the supported +; BIOS text and graphics modes. +;============================================================================ + + even ; make sure that this data is word aligned + + videomodetable dw 0b800h,0b800h ; modes 0,1 + dw 0b800h,0b800h ; modes 2,3 + dw 0b800h,0b800h ; modes 4,5 + dw 0b800h,0b000h ; modes 6,7 + dw 0ffffh,0ffffh ; n/a + dw 0ffffh,0ffffh ; n/a + dw 0ffffh,0a000h ; n/a,mode 0dh + dw 0a000h,0a000h ; modes 0eh,0fh + dw 0a000h,0a000h ; modes 10h,11h + dw 0a000h,0a000h ; modes 12h,13h + videobufferseg dw ? + + even ; make sure that this data is word aligned + + hotspot dw 2 dup(0) + + VRAMlasttextcelloff label word ; last text offset in VRAM + VRAMlastbyteoff dw ? ; Last offset in VRAM + VRAMlastbitoff dw ? ; LSB: Where pointer is in byte + ; MSB: ODD/EVEN of the pointer + ; first scan line + LastXCounters dw ? ; last X looping counter + LastYCounters dw ? ; last Y looping counter + ; ODD in LSB and EVEN in MSB + lasttextimage dw ? ; text cell from last time + + background dw NOTSTORED ; STORED if data in buffer + current_position_x dw ? + current_position_y dw ? + vidbytealigned dw ? + lastmaskrotate dw ? + lastvidmode db 0ffh ; the video mode during the last int. + internalCF db 0ffh ; the mouse driver keeps a flag called + ; the internal cursor flag. If the flag + ; = 0, then int 33h f1 will display the + ; pointer, -1 = default value. + + ; 32 bit code writes to this area on a hardware interrupt and + ; when an app does an int 33h function 3, it reads the data + ; directly from here. + ; Data format is: word 0 -> button status + ; word 1 -> x virtual coordinate + ; word 2 -> y virtual coordinate + + function3data dw 3 dup(?) + + conditional_off db 0 ;!= 0 if conditional off is on + ; +;============================================================================= +; Data to determine the address of where the latches should be saved in the +; video buffer for the current video mode. +; latchcache contains the value looked up by saveVGAregisters and used by +; restoreVGAregisters. +;============================================================================= + + + latchcache dw ? ; location of latch cache in VRAM +even +latchhomeLUT label word + dw ? ; mode 0 + dw ? ; mode 1 + dw ? ; mode 2 + dw ? ; mode 3 + dw ? ; mode 4 + dw ? ; mode 5 + dw ? ; mode 6 + dw ? ; mode 7 + dw ? ; mode 8 + dw ? ; mode 9 + dw ? ; mode a + dw ? ; mode b + dw ? ; mode c + dw ? ; mode d + dw 80*200+78 ; mode e + dw 80*350+78 ; mode f + dw 80*350+78 ; mode 10 + dw 80*480+78 ; mode 11 + dw 80*480+78 ; mode 12 + +;============================================================================= +; CGA video mode 4 is a 2 bit per pixel graphics mode. The pointer images +; received from the application (or the default images for that matter) are +; described by a one bit per pixel map. This look up table provides the means +; of conversion from one to two bits per pixel. +;============================================================================= +even +LUT1to2bit label word + dw 00000h,00003h,0000Ch,0000Fh,00030h,00033h,0003Ch,0003Fh + dw 000C0h,000C3h,000CCh,000CFh,000F0h,000F3h,000FCh,000FFh + dw 00300h,00303h,0030Ch,0030Fh,00330h,00333h,0033Ch,0033Fh + dw 003C0h,003C3h,003CCh,003CFh,003F0h,003F3h,003FCh,003FFh + dw 00C00h,00C03h,00C0Ch,00C0Fh,00C30h,00C33h,00C3Ch,00C3Fh + dw 00CC0h,00CC3h,00CCCh,00CCFh,00CF0h,00CF3h,00CFCh,00CFFh + dw 00F00h,00F03h,00F0Ch,00F0Fh,00F30h,00F33h,00F3Ch,00F3Fh + dw 00FC0h,00FC3h,00FCCh,00FCFh,00FF0h,00FF3h,00FFCh,00FFFh + + dw 03000h,03003h,0300Ch,0300Fh,03030h,03033h,0303Ch,0303Fh + dw 030C0h,030C3h,030CCh,030CFh,030F0h,030F3h,030FCh,030FFh + dw 03300h,03303h,0330Ch,0330Fh,03330h,03333h,0333Ch,0333Fh + dw 033C0h,033C3h,033CCh,033CFh,033F0h,033F3h,033FCh,033FFh + dw 03C00h,03C03h,03C0Ch,03C0Fh,03C30h,03C33h,03C3Ch,03C3Fh + dw 03CC0h,03CC3h,03CCCh,03CCFh,03CF0h,03CF3h,03CFCh,03CFFh + dw 03F00h,03F03h,03F0Ch,03F0Fh,03F30h,03F33h,03F3Ch,03F3Fh + dw 03FC0h,03FC3h,03FCCh,03FCFh,03FF0h,03FF3h,03FFCh,03FFFh + + dw 0C000h,0C003h,0C00Ch,0C00Fh,0C030h,0C033h,0C03Ch,0C03Fh + dw 0C0C0h,0C0C3h,0C0CCh,0C0CFh,0C0F0h,0C0F3h,0C0FCh,0C0FFh + dw 0C300h,0C303h,0C30Ch,0C30Fh,0C330h,0C333h,0C33Ch,0C33Fh + dw 0C3C0h,0C3C3h,0C3CCh,0C3CFh,0C3F0h,0C3F3h,0C3FCh,0C3FFh + dw 0CC00h,0CC03h,0CC0Ch,0CC0Fh,0CC30h,0CC33h,0CC3Ch,0CC3Fh + dw 0CCC0h,0CCC3h,0CCCCh,0CCCFh,0CCF0h,0CCF3h,0CCFCh,0CCFFh + dw 0CF00h,0CF03h,0CF0Ch,0CF0Fh,0CF30h,0CF33h,0CF3Ch,0CF3Fh + dw 0CFC0h,0CFC3h,0CFCCh,0CFCFh,0CFF0h,0CFF3h,0CFFCh,0CFFFh + + dw 0F000h,0F003h,0F00Ch,0F00Fh,0F030h,0F033h,0F03Ch,0F03Fh + dw 0F0C0h,0F0C3h,0F0CCh,0F0CFh,0F0F0h,0F0F3h,0F0FCh,0F0FFh + dw 0F300h,0F303h,0F30Ch,0F30Fh,0F330h,0F333h,0F33Ch,0F33Fh + dw 0F3C0h,0F3C3h,0F3CCh,0F3CFh,0F3F0h,0F3F3h,0F3FCh,0F3FFh + dw 0FC00h,0FC03h,0FC0Ch,0FC0Fh,0FC30h,0FC33h,0FC3Ch,0FC3Fh + dw 0FCC0h,0FCC3h,0FCCCh,0FCCFh,0FCF0h,0FCF3h,0FCFCh,0FCFFh + dw 0FF00h,0FF03h,0FF0Ch,0FF0Fh,0FF30h,0FF33h,0FF3Ch,0FF3Fh + dw 0FFC0h,0FFC3h,0FFCCh,0FFCFh,0FFF0h,0FFF3h,0FFFCh,0FFFFh + +;============================================================================ +; Table for selection of the correct pointer image for the current location +; in the video buffer, when using video BIOS mode 4. +;============================================================================ + +mode4pointerLUT label word + REPT 76 ; for the first 76 bytes of scanline, use these + dw current_cursor + dw AlignData1 + dw AlignData2 + dw AlignData3 + ENDM + dw clip_cursor78 + dw AlignClip178 + dw AlignClip278 + dw AlignClip378 + dw AlignClip478 + dw AlignClip578 + dw AlignClip678 + dw AlignClip778 + dw clip_cursor79 + dw AlignClip179 + dw AlignClip279 + dw AlignClip379 + dw AlignClip479 + dw AlignClip579 + dw AlignClip679 + dw AlignClip779 + +;============================================================================ +; Look up table to adjust CX on clipping in mode 4. This allows the mode4 +; pointer drawing algorithm to use the modes 10h/12h clipped pointer data +; without having to modify it. The problem is that mode 10/12 expects the +; data to be 4 bits per pixel and aligned to a word, whereas mode 4 is 2 bits +; per pixel and aligns to a byte. +;============================================================================ + +mode4clipCXadjustLUT label word + adjtemp=0 ; data for pixel x-coordinates 0 -> 307 + REPT 77 + dw 4 dup(adjtemp) + adjtemp=adjtemp+1 + ENDM + dw 4 dup(76) ; data for pixels 308 -> 311 + dw 8 dup(78) ; data for pixels 312 -> 319 + + +;============================================================================ +; The CGA buffer is split at 2000h. Therefore if the pointer starts writing +; below scanline 199 on the video display, the odd scanline video buffer +; will become corrupted. In these cases, the pointer should be clipped to +; display scanline 199. The look up table below maps loop counters to a +; display scanline for this purpose. +; +; table arrangement (odd scanline data, even scanline data) +; +;============================================================================ + +mode4clipDXLUT label word + + db 200-15 dup(8,8) ; scanlines 0 -> 184 + db 8,7 ; scanline 185 + db 7,7 ; scanline 186 + db 7,6 ; scanline 187 + db 6,6 ; scanline 188 + db 6,5 ; scanline 189 + db 5,5 ; scanline 190 + db 5,4 ; scanline 191 + db 4,4 ; scanline 192 + db 4,3 ; scanline 193 + db 3,3 ; scanline 194 + db 3,2 ; scanline 195 + db 2,2 ; scanline 196 + db 2,1 ; scanline 197 + db 1,1 ; scanline 198 + db 1,0 ; scanline 199 + +mode4SelectedPointer label word + dw ? + +;========================================================================== +; Some space into which the Medium resolution graphics pointer background +; gets stored. Note that the 256 colour mode buffer encroaches on that of +; mode 4. +;========================================================================== + +bkgrnd256 label byte ; 256 colour buffer = 24*16 @ 1 byte/pix + db 384-64 dup(?) ; share the CGA buffer(=64 bytes) + +CGAbackgrnd label byte + + db 24/4*16 dup(?) ; 24 pixels/row @ 4 pixels/byte for 16 + ; rows. + +;=========================================================================== +; Jump table to redirect the code flow according to the current video mode. +; Used in the 32 bit entry point procedure. +; Pointer drawing routines. +;=========================================================================== +even +drawpointerJMPT label word + dw offset not_supported ; mode 0 + dw offset not_supported ; mode 1 +IFDEF SIXTEENBIT + dw offset drawTextPointer ; mode 2 + dw offset drawTextPointer ; mode 3 +ELSE + dw offset not_supported ; mode 2 + dw offset not_supported ; mode 3 +ENDIF + dw offset drawMediumResPointer ; mode 4 + dw offset drawMediumResPointer ; mode 5 + dw offset not_supported ; mode 6 +IFDEF SIXTEENBIT + dw offset drawTextPointer ; mode 7 +ELSE + dw offset not_supported ; mode 7 +ENDIF + dw offset not_supported ; mode 8 + dw offset not_supported ; mode 9 + dw offset not_supported ; mode a + dw offset not_supported ; mode b + dw offset not_supported ; mode c + dw offset not_supported ; mode d + dw offset not_supported ; mode e + dw offset drawHiResPointer ; mode f + dw offset drawHiResPointer ; mode 10 + dw offset drawHiResPointer ; mode 11 + dw offset drawHiResPointer ; mode 12 + dw offset drawC256pointer ; mode 13 + +;=========================================================================== +; Jump table to redirect the code flow according to the current video mode. +; Used in the 32 bit entry point procedure. +; INT 33h Function 1 support modules. +;=========================================================================== +even +int33function1JMPT label word + dw offset not_supported ; mode 0 + dw offset not_supported ; mode 1 +IFDEF SIXTEENBIT + dw offset TextInt33Function1 ; mode 2 + dw offset TextInt33Function1 ; mode 3 +ELSE + dw offset not_supported ; mode 2 + dw offset not_supported ; mode 3 +ENDIF + dw offset MediumResInt33Function1 ; mode 4 + dw offset MediumResInt33Function1 ; mode 5 + dw offset not_supported ; mode 6 +IFDEF SIXTEENBIT + dw offset TextInt33Function1 ; mode 7 +ELSE + dw offset not_supported ; mode 7 +ENDIF + dw offset not_supported ; mode 8 + dw offset not_supported ; mode 9 + dw offset not_supported ; mode a + dw offset not_supported ; mode b + dw offset not_supported ; mode c + dw offset not_supported ; mode d + dw offset not_supported ; mode e + dw offset HiResInt33Function1 ; mode f + dw offset HiResInt33Function1 ; mode 10 + dw offset HiResInt33Function1 ; mode 11 + dw offset HiResInt33Function1 ; mode 12 + dw offset C256Int33Function1 ; mode 13 + +;=========================================================================== +; Jump table to redirect the code flow according to the current video mode. +; Used in the 32 bit entry point procedure. +; INT 33h Function 2 support modules. +;=========================================================================== +even +int33function2JMPT label word + dw offset not_supported ; mode 0 + dw offset not_supported ; mode 1 +IFDEF SIXTEENBIT + dw offset TextInt33Function2 ; mode 2 + dw offset TextInt33Function2 ; mode 3 +ELSE + dw offset not_supported ; mode 2 + dw offset not_supported ; mode 3 +ENDIF + dw offset MediumResInt33Function2 ; mode 4 + dw offset MediumResInt33Function2 ; mode 5 + dw offset not_supported ; mode 6 +IFDEF SIXTEENBIT + dw offset TextInt33Function2 ; mode 7 +ELSE + dw offset not_supported ; mode 7 +ENDIF + dw offset not_supported ; mode 8 + dw offset not_supported ; mode 9 + dw offset not_supported ; mode a + dw offset not_supported ; mode b + dw offset not_supported ; mode c + dw offset not_supported ; mode d + dw offset not_supported ; mode e + dw offset HiResInt33Function2 ; mode f + dw offset HiResInt33Function2 ; mode 10 + dw offset HiResInt33Function2 ; mode 11 + dw offset HiResInt33Function2 ; mode 12 + dw offset C256Int33Function2 ; mode 13 + + + +;========================================================================== +; Some storage space for the critical VGA registers. +;========================================================================== + +;Sequencer Registers + +seqregs label byte + db 4 dup(?) ; N.B. sequencer reset reg doesn't + ; get saved. + +; Graphics Controller Registers + +GCregs label byte + db 9 dup(?) + +;========================================================================== +; The mouse driver's very own stack. To prevent unnecessary tears, +; particulary from the application running in DOS land, a stack is +; maintained by the driver. This prevents the driver routines from +; blowing a very full stack elsewhere. +; N.B. on leaving the driver, the stack should be empty! +;========================================================================== + +even +mouse_stack dw STACKSIZE dup(?) +top_of_stack label word + dw ? ; this is where the stack starts + +;=========================================================================== +; The memory variable below is incremented on entry to the 16 bit code +; and on exit, decremented. If an interrupt occurs during the execution of +; this 16 bit code, the flag is incremented again, and thus greater than zero +; so it is known that the code has been reentered and the stack must be +; maintained accordingly. +;=========================================================================== + +reentrant dw -1 + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; END OF DATA +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + +;================================================================ +; code to redirect the flow of control from the segment:offset for +; the mouse interrupt (33h) as indicated in the IVT (the IVT entry +; has been set to point to here) to the Insignia mouse driver code. +;================================================================ +int33h_vector: + + jmp short skip + +; High level language entry point. + +lvector db 0EAh ; far jump opcode +loffset dw ? ; destination offset +lseg dw ? ; destination segment + +; The pointer set to our interrupt 33h handler + +skip: + +; +; Let's just jump to the C mouse_io_interrupt code for +; RISC and bypass the ROM like 4.0 does. +; + + bop 0BDh + iret + + + +db 0EAh ; far jump opcode +moff dw ? ; will be filled in by the driver code from the IVT +mseg dw ? ; as before + +DOCLI: + FCLI + ret + +DOSTI: + FSTI + ret + +DOIRET: + FIRET + + +;================================================================ +; Functions moved out of ROM - real ROMS mapped in +;================================================================ + +unexp_int: + bop UNEXP_BOP + jmp DOIRET + +mouse_io: + ; + ; INT 33h entry point + ; + + jmp mio_hack + nop +mouse_io_lang: ; entry point for HLL + pushf ; check ASAP if redundant show/hide cursor + push di ; save di, + mov di, [di+14] ; get first parameter (mouse function), + ; then duplicate mio_hack below. + ; this has to be done to preserve + ; compatibility between both ways to + ; call the mouse. + jz lbop ; F0 + cmp di,2 + jg lbop ; >F2 + je miol_2 +miol_1: + mov conditional_off, 0 ; disable conditonal off + cmp [internalCF],0 ; is the flag already zero? + je miol_12_quit ; if so, do nothing + inc [internalCF] ; increment it + jz lbop +miol_12_quit: + pop di + popf + jmp DOIRET + +miol_2: + dec [internalCF] ; decrement the pointer internal flag + cmp [internalCF], 0ffh; currently displayed? + jne miol_12_quit +lbop: + pop ax + popf + bop IO_LANG_BOP + retf 8 + +mio_hack: ; int 33h handler + pushf ; save up the flags + cmp ax,1 ; mouse show cursor. + je mio_1 + cmp ax,2 ; mouse hide cursor. + je mio_2 + cmp ax,3 ; get button status and mouse position. + je mio_3 + cmp ax,9 ; set graphics cursor + je mio_9 + cmp ax,10 ; set text cursor - not supported + je mio_quit ; return straight back to app. + + jmp short hack1bop ; none of the above, so goto 32 bit land + +mio_1: + mov conditional_off, 0 ; disable conditional off + cmp [internalCF],0 ; is the flag already zero? + je mio_quit ; if so, do nothing + inc [internalCF] ; increment it + jz hack1bop ; just turned zero, so turn pointer on + ; via the 32 bit code. +mio_quit: + popf + jmp DOIRET + +mio_2: + dec [internalCF] ; decrement the pointer internal flag + cmp [internalCF], 0ffh; currently displayed? + jne mio_quit ; Already turned off, so quit + +hack1bop: + popf + bop IO_INTR_BOP ; BOP to the 32 bit part of the handler + jmp DOIRET ; return back after the BOP to caller +mio_9: + call int33function9 ; change the shape of the graphics pointer + popf ; restore the flag state + jmp DOIRET ; back to the caller +mio_3: + mov bx,[function3data] ; return button status + mov cx,[function3data+2] ; return x coordinate + mov dx,[function3data+4] ; return x coordinate + popf ; return back to the application + jmp DOIRET ; via an iret. + + +IFDEF MOUSE_VIDEO_BIOS + +mouse_video_io: + + pushf + or ah,ah + jne mvio1 + jmp do_bop +mvio1: + cmp ax,6f05h + jne mvio2 + jmp do_bop +mvio2: + cmp ah,4 + jne mvio3 + jmp do_bop +mvio3: + +;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + + ; Microsoft EGA.LIB function support + ; input: AH = the function required + + cmp ah,0f0h ; is function F0 or greater? + jge mvio4 ; YES, so check to see if less than or == F7 + jmp go_rom ; NO, so do rom stuff +mvio4: + cmp ah,0f7h ; is it greater than F7 + jg mvio5 ; YES, so test for == FA + jmp ega_lib ; NO, but in range F0 to F7, so do EGALIB emm +mvio5: + cmp ah,0fah + jne mvio6 + jmp egaFA +mvio6: + jmp go_rom + + ; to get here, must want to do mouse video functions 0f0h to 0f7h or + ; function 0fah. + + jmp ega_lib + + ; data area for EGA.LIB function support + ; Notice that the sequencer register buffer only has space + ; for four entrys even though it actually has five addressable + ; registers. The Sequencer RESET status is not stored, so the buffer + ; is arranged thus: + ; buffer offset 0 1 2 3 + ; register index 1 2 3 4 + ; + + even + + ega_current_crtc db 25 dup(?) ; driver's copy of CRTC regs + ega_current_seq db 4 dup(?) ; driver's copy of Seq regs + ega_current_graph db 9 dup(?) ; driver's copy of GC regs + ega_current_attr db 20 dup(?) ; driver's copy of AC regs + ega_current_misc db ? ; driver's copy of misc reg + dirty_crtc db 25 dup(?) + dirty_seq db 4 dup(?) + dirty_graph db 9 dup(?) + dirty_attr db 20 dup(?) + ega_default_crtc db 25 dup(?) ; default EGA register values + ega_default_seq db 4 dup(?) ; as set by the application + ega_default_graph db 9 dup(?) ; through a call to F7 + ega_default_attr db 20 dup(?) + ega_default_misc db ? + + relnum label word + + release_major db MAJOR_RELEASE_NUMBER + release_minor db MINOR_RELEASE_NUMBER + + even + + egalibjmp label word ; crafty jump table to replace a base + ; switch + dw egaF0 ; 0F0h - read one EGA register + dw egaF1 ; 0F1h - write one EGA register + dw egaF2 ; 0F2h - read register range + dw egaF3 ; 0F3h - write register range + dw egaF4 ; 0F4h - read register set + dw egaF5 ; 0F5h - write register set + dw egaF6 ; 0F6h - revert to default regs + dw egaF7 ; 0F7h - define deflt reg table + dw noint ; 0F8h is not a valid function + dw noint ; 0F9h is not a valid function + dw egaFA ; 0FAh - interrogate driver +ega_lib: + + xor al,al + sub ax,0f0h ; create a jump table index + shl ax,1 ; remember that a word pointer is reqd + mov si,ax + jmp [egalibjmp+si] ; get the relavent jump address + +egaF0: ;--- Read an EGA register ---------------------------------------------- + + pusha + and bx,0ffh ; just want the lower byte (BL) +F00: + cmp dx,0 + jne F08 + mov bl,byte ptr [ega_current_crtc+bx] + popa + jmp noint +F08: + cmp dx,8 + jne F010 + dec bx ; note that RESET is not stored + mov bl,byte ptr [ega_current_seq+bx] + popa + jmp noint +F010: + cmp dx,010h + jne F018 + mov bl,byte ptr [ega_current_graph+bx] + popa + jmp noint +F018: + cmp dx,018h + jne F020 + mov bl,byte ptr [ega_current_attr+bx] + popa + jmp noint +F020: + cmp dx,020h + jne F028 + mov bl,byte ptr [ega_current_misc] + +F028: ; do nothing for this case +F0quit: + popa + jmp noint + +egaF1: ;--- Write an EGA register -------------------------------------------- + +F10: + pusha + cmp dx,0 + jne F18 + mov dx,03d4h ; write to the CRTC index register + mov ax,bx ; values to write to ports 3d4/3d5 + out dx,ax ; do the write + mov di,bx ; save the written values to memory + and di,0ffh ; get just the lower 8 bits + mov byte ptr [ega_current_crtc+di],bh + mov byte ptr [dirty_crtc+di],1 + popa + jmp noint +F18: + cmp dx,8 + jne F110 + mov dx,03c4h ; write to the Sequencer index register + mov ax,bx ; values to write to ports 3c4/3c5 + out dx,ax ; do the write + cmp bl,0 ; Cannot index reset because it its + jle F18bra1 ; not stored. range = 1->4 + and bx,0ffh ; just want BL + dec bx ; actually, one less than that + mov byte ptr [ega_current_seq+bx],ah + mov byte ptr [dirty_seq+bx],1 +F18bra1: + popa + jmp noint +F110: + cmp dx,010h + jne F118 + mov dx,03ceh ; write to the Graphics controller + mov ax,bx ; values to write to ports 3ce/3cf + out dx,ax ; do the write + mov di,bx ; save the written values to memory + and di,0ffh ; get just the lower 8 bits + mov byte ptr [ega_current_graph+di],bh + mov byte ptr [dirty_graph+di],1 + popa + jmp noint +F118: + cmp dx,018h + jne F120 + mov dx,03dah ; clear attribute controller index + in al,dx ; the read clears this register + mov ax,bx ; need to write BX to the ports + mov dx,03c0h ; Attribute Controller index register + out dx,ax ; do the write + inc dx + mov al,020h ; EGA palette enable + out dx,al ; enable the palette + mov di,bx ; save the written values to memory + and di,0ffh ; get just the lower 8 bits + mov byte ptr [ega_current_graph+di],bh + mov byte ptr [dirty_graph+di],1 + popa + jmp noint +F120: + cmp dx,020h + jne F128 + mov dx,03c2h ; EGA miscellaneous register + mov al,bl + out dx,al ; write to the register + mov [ega_current_misc],bl + popa + jmp noint +F128: + cmp dx,028h + jne F128 + mov dx,03dah ; EGA feature register + mov al,bl + out dx,al +F1quit: + popa + jmp noint + +egaF2: ;--- Read a register range --------------------------------------------- + + pusha + cmp dx,0 + jne F28 +F20: + lea si,ega_current_crtc ; get the address of this buffer + mov dx,cx ; save this value + xchg ch,cl ; create an index with CH + and cx,0ffh ; only need CH (now CL) + add si,cx ; SOURCE adjust the address + xor dh,dh ; only want the old CL value + mov cx,dx ; restore CX + mov di,bx ; DESTINATION got from the application + rep movsb ; copy to the app's register block + popa + jmp noint +F28: + cmp dx,8 + jne F210 + lea si,ega_current_seq ; get the address of this buffer + mov dx,cx ; save this value + xchg ch,cl ; create an index with CH + and cx,0ffh ; only need CH (now CL) + dec cx ; RESET is not stored, so index-1 + add si,cx ; SOURCE adjust the address + xor dh,dh ; only want the old CL value + mov cx,dx ; restore CX + mov di,bx ; DESTINATION got from the application + rep movsb ; copy to the app's register block + popa + jmp noint +F210: + cmp dx,010h + jne F218 + lea si,ega_current_graph ; get the address of this buffer + mov dx,cx ; save this value + xchg ch,cl ; create an index with CH + and cx,0ffh ; only need CH (now CL) + add si,cx ; SOURCE adjust the address + xor dh,dh ; only want the old CL value + mov cx,dx ; restore CX + mov di,bx ; DESTINATION got from the application + rep movsb ; copy to the app's register block + popa + jmp noint +F218: + cmp dx,018h + jne F2quit + lea si,ega_current_attr ; get the address of this buffer + mov dx,cx ; save this value + xchg ch,cl ; create an index with CH + and cx,0ffh ; only need CH (now CL) + add si,cx ; SOURCE adjust the address + xor dh,dh ; only want the old CL value + mov cx,dx ; restore CX + mov di,bx ; DESTINATION got from the application + rep movsb ; copy the application's register block +F2quit: + popa + jmp noint + +egaF3: ;--- Write a register range to the EGA adapter ------------------------ + + pusha + push ds + push es +F31: + cmp dx,0 + jne F38 + lea di,ega_current_crtc ; write the application data here + mov al,ch ; adjust the write position as required + cbw + add di,ax ; DESTINATION specified address + mov si,bx ; SOURCE from the application + lea bx,dirty_crtc ; need to write some data into here + add bx,ax ; well, at this offset anyway + mov ax,es ; The application is the source + mov ds,ax ; so point to its segment + mov dx,03d4h ; CRTC index register + mov ah,ch ; CRTC register to start at + xor ch,ch ; CX is now the loop counter + assume ds:nothing +F31cp: + mov byte ptr cs:[bx],1 ; fill in the dirty_crtc array + inc bx + movsb ; get the value from the app to write + ; and write to the internal buffer + out dx,ax ; write to the EGA adapter + loop F31cp + jmp F3quit +F38: + cmp dx,8 + jne F310 + lea di,ega_current_seq ; write the application data here + mov al,ch ; adjust the write position as required + cbw + add di,ax ; DESTINATION specified address + dec di ; RESET is not stored, so index-1 + mov si,bx ; SOURCE from the application + lea bx,dirty_seq ; need to write some data into here + add bx,ax ; well, at this offset anyway + inc bx + mov ax,es ; The application is the source + mov ds,ax ; so point to its segment + mov dx,03c4h ; Sequencer index register + mov ah,ch ; Sequencer register to start at + inc ah + xor ch,ch ; CX is now the loop counter + assume ds:nothing +F38cp: + mov byte ptr cs:[bx],1 ; fill in the dirty_seq array + inc bx + movsb ; get the value from the app to write + ; and write to the internal buffer + out dx,ax ; write to the EGA adapter + loop F38cp + assume ds:SpcMseSeg + jmp F3quit +F310: + cmp dx,010h + jne F318 + lea di,ega_current_graph ; write the application data here + mov al,ch ; adjust the write position as required + cbw + add di,ax ; DESTINATION specified address + mov si,bx ; SOURCE from the application + lea bx,dirty_graph ; need to write some data into here + add bx,ax ; well, at this offset anyway + mov ax,es ; The application is the source + mov ds,ax ; so point to its segment + mov dx,03ceh ; Graphics Controller index register + mov ah,ch ; GC register to start at + xor ch,ch ; CX is now the loop counter + assume ds:nothing +F310cp: + mov byte ptr cs:[bx],1 ; fill in the dirty_graph array + inc bx + movsb ; get the value from the app to write + ; and write to the internal buffer + out dx,ax ; write to the EGA adapter + loop F310cp + assume ds:SpcMseSeg + jmp short F3quit +F318: + cmp dx,018h + jne F3quit + mov dx,03dah ; clear attribute controller index + in al,dx ; the read clears this register + lea di,ega_current_attr ; write the application data here + mov al,ch ; adjust the write position as required + cbw + add di,ax ; DESTINATION specified address + mov si,bx ; SOURCE from the application + lea bx,dirty_attr ; need to write some data into here + add bx,ax ; well, at this offset anyway + mov ax,es ; The application is the source + mov ds,ax ; so point to its segment + mov dx,03c0h ; Attribute Controller index register + mov ah,ch ; AC register to start at + xor ch,ch ; CX is now the loop counter + assume ds:nothing +F318cp: + mov byte ptr cs:[bx],1 ; fill in the dirty_attr array + inc bx + movsb ; get the value from the app to write + ; and write to the internal buffer + out dx,ax ; write to the EGA adapter + loop F318cp + assume ds:SpcMseSeg +F3quit: + pop es + pop ds + popa + jmp noint + +egaF4: ;--- Read EGA register set ------------------------------------------- + ; + ; note that the incoming/outgoing data is structured thus: + ; + ; from application --> db Port number + ; --> db must be zero + ; --> db pointer value + ; to application <-- db data read from register + + pusha +F4lp: + mov al,byte ptr es:[bx] ; get the type of the next EGA register + mov dl,byte ptr es:[bx+2] ; load up the offset required + xor dh,dh ; convert DL to a word (DX) + add bx,3 ; point to where the data should + ; be written for the application +F40: + cmp al,0 + jne F48 + lea di,ega_current_crtc ; point to the internal CRTC reg. buffer + add di,dx ; index into the buffer + mov al,byte ptr [di] ; get the register value from the driver + mov byte ptr es:[bx],al ; store the register value + jmp short F4lp2 ; do the next loop iteration +F48: + cmp al,8 + jne F410 + lea di,ega_current_seq ; point to the internal Sequencer buffer + add di,dx ; index into the buffer + dec di ; RESET is not stored, so index off 1 + mov al,byte ptr [di] ; get the register value from the driver + mov byte ptr es:[bx],al ; store the register value + jmp short F4lp2 ; do the next loop iteration +F410: + cmp al,010h + jne F418 + lea di,ega_current_graph ; point to the internal GC reg. buffer + add di,dx ; index into the buffer + mov al,byte ptr [di] ; get the register value from the driver + mov byte ptr es:[bx],al ; store the register value + jmp short F4lp2 ; do the next loop iteration +F418: + cmp al,018h + jne F420 + lea di,ega_current_attr ; point to the interal AC reg. buffer + add di,dx ; index into the buffer + mov al,byte ptr [di] ; get the register value from the driver + mov byte ptr es:[bx],al ; store the register value + jmp short F4lp2 ; do the next loop iteration +F420: + cmp al,020h + jne F4lp2 + mov al,[ega_current_misc] ; load contents of miscellaneous reg + mov byte ptr[di],al ; store the register value + + ; the C code actually loads BL here but I don't know why! +F4lp2: + inc bx ; point to the next 'record' + loop F4lp + popa + jmp noint + +egaF5: ;--- Write EGA register set ------------------------------------------- + ; + ; note that the incoming data is structured thus: + ; + ; from application --> db Port number + ; --> db must be zero + ; --> db pointer value + ; --> db data read from register + + pusha +F5lp: + mov al,byte ptr es:[bx] ; get the type of the next EGA register + mov dl,byte ptr es:[bx+2] ; load up the offset required + xor dh,dh ; turn from 8 bit to a word quantity + mov si,dx ; need this when accessing buffers + add bx,3 ; point to where the data should + ; be written for the application + mov ah,byte ptr es:[bx] ; load data to send to the port + inc bx ; point to the next 'record' +F50: + cmp al,0 + jne F58 + mov al,dl ; also the port offset to access + mov dx,03d4h ; index register for CRTC + out dx,ax ; write to the specified port + mov byte ptr [ega_current_crtc+si],ah + mov byte ptr [dirty_crtc+si],1 + jmp short F5lp2 +F58: + cmp al,8 + jne F510 + mov al,dl ; also the port offset to access + mov dx,03c4h ; index register for Sequencer + out dx,ax ; write to the specified port + dec si ; RESET is not stored, so index off 1 + mov byte ptr [ega_current_seq+si],ah + mov byte ptr [dirty_seq+si],1 + jmp short F5lp2 +F510: + cmp al,010h + jne F518 + mov al,dl ; also the port offset to access + mov dx,03ceh ; index register for GC + out dx,ax ; write to the specified port + mov byte ptr [ega_current_graph+si],ah + mov byte ptr [dirty_graph+si],1 + jmp short F5lp2 +F518: + cmp al,018h + jne F520 + mov dx,03dah ; clear attribute controller index + in al,dx ; the read clears this register + lea di,ega_current_attr ; write the application data here + mov al,dl ; also the port offset to access + mov dx,03c0h ; index register for AC + out dx,ax ; write to the specified port + mov al,020h ; EGA palette enable + out dx,al ; reenable the video + mov byte ptr [ega_current_attr+si],ah + mov byte ptr [dirty_attr+si],1 + jmp short F5lp2 +F520: + cmp al,020h + jne F528 + mov byte ptr [ega_current_misc],ah + mov dx,03c2h ; Miscellaneous output register + xchg ah,al + out dx,al ; write one byte + jmp short F5lp2 +F528: + xchg ah,al + mov dx,03dah ; EGA feature register + out dx,al +F5lp2: + dec cx + cmp cx,0 + jz F5quit + jmp F5lp +F5quit: + popa + jmp noint + +egaF6: ;--- Restore the EGA default register values -------------------------- + pusha + push es + + ; copy the default EGA register sets to the driver's internal cache + + mov ax,ds + mov es,ax + + mov cx,25 + lea di,ega_current_crtc + lea si,ega_default_crtc + rep movsb + mov cx,4 + lea di,ega_current_seq + lea si,ega_default_seq + rep movsb + mov cx,9 + lea di,ega_current_graph + lea si,ega_default_graph + rep movsb + mov cx,20 + lea di,ega_current_attr + lea si,ega_default_attr + rep movsb + mov al,[ega_default_misc] + mov [ega_current_misc],al + + ; Set up the Sequencer defaults + + mov dx,03c4h ; Sequencer index register + mov ax,0100h ; Synchronous reset + out dx,ax ; do the work + + xor bx,bx ; do the four non reset registers + inc al ; point to the next Sequencer register +F6lp1: + cmp [dirty_seq+bx],1 ; has the dirty bit been set? + jne F6ne1 + mov ah,[ega_default_seq+bx] ; default value to send to the register + out dx,ax ; do the work +F6ne1: + inc bx ; point to the next buffer location + inc al ; point to the next Sequencer register + cmp bx,3 ; copy elements 0->3 to ports + jl F6lp1 + mov ax,0300h ; Clear synchronous reset + out dx,ax ; do the work + + ; Set up the default Miscellaneous Output Register value. + + mov dx,03c2h ; Miscellaneous o/p register address + mov al,[ega_default_misc] ; the default value + out dx,al ; write to the EGA/VGA + + ; Set up the Cathode Ray Tube Controller in the default fashion + + mov dx,03d4h ; Index to the CRTC + xor bx,bx ; clear an index register +F6lp2: + cmp [dirty_crtc+bx],1 ; has the dirty bit been set? + jne F6ne2 + mov ax,bx ; index for the CRTC index register + mov ah,[ega_default_crtc+bx] ; default value for the selected reg. + out dx,ax +F6ne2: + inc bx ; point to the next location + cmp bx,25 ; 25 registers to copy + jl F6lp2 + + ; Set up the Attribute Controller default values + ; Remember that this is a funny beast which uses a flip-flop + ; off just one address/data port + + mov dx,03dah ; CRT status register + in al,dx ; set the AC flip-flop + mov dx,03c0h ; Attibute controller address/data regs + xor bx,bx ; clear an index register +F6lp3: + cmp [dirty_attr+bx],1 ; has the dirty bit been set? + jne F6ne3 + mov ax,bx ; index for the CRTC index register + mov ah,[ega_default_attr+bx] ; default value for the selected reg. + out dx,al ; index the register, then flip the flop + xchg al,ah ; get the default data for this register + out dx,al ; write the data out +F6ne3: + inc bx ; point to the next location + cmp bx,20 ; 20 registers to copy + + ; Set the Graphics Controller default values + + mov dx,03ceh ; Index to the GC + xor bx,bx ; clear an index register +F6lp4: + cmp [dirty_graph+bx],1 ; has the dirty bit been set? + jne F6ne4 + mov ax,bx ; index for the GC index register + mov ah,[ega_default_graph+bx] ; default value for the selected reg. + out dx,ax +F6ne4: + inc bx ; point to the next location + cmp bx,9 ; 9 registers to copy + jl F6lp2 + + ; Reenable the video + + mov dx,03c0h ; index register for AC + mov al,020h ; EGA palette enable + out dx,al ; reenable the video + + ; Clean out the dirty register arrays + + xor al,al ; put a nice zero in all the dirty + ; registers + mov cx,25+4+9+20 ; do the CRTC, SEQ, GC and AC in + mov di,offset dirty_crtc ; one go + rep stosb + + pop es + popa + jmp noint + +egaF7: ;---Define default register table ------------------------------------- + pusha + push es + push ds + + ; Load a new set of default registers for a particular EGA/VGA component + + + mov si,bx ; SOURCE of the incoming data from the app + mov ax,es ; save the SOURCE segment register + mov bx,ds ; save the DESTINATION offset + mov ds,ax ; DS is now the SOURCE segment in the app + mov es,bx ; ES is now the DESTINATION segment in the dvr + + assume ds:nothing, es:SpcMseSeg + +F70: ; Set the default CRTC registers + + cmp dx,0 + jne F78 + mov cx,25 ; copy 25 register entries + mov di,offset ega_default_crtc + rep movsb ; do the copy + jmp short F7dirty + +F78: ; Set the default Sequencer registers + + cmp dx,8 + jne F710 + mov cx,4 ; copy 4 register entries + mov di,offset ega_default_seq + rep movsb ; do the copy + jmp short F7dirty + +F710: ; Set the default Graphic Controller registers + + cmp dx,10 + jne F718 + mov cx,9 ; copy 9 register entries + mov di,offset ega_default_graph + rep movsb ; do the copy + jmp short F7dirty + +F718: ; Set the default Attribute Controller registers + + cmp dx,18 + jne F720 + mov cx,20 ; copy 20 register entries + mov di,offset ega_default_attr + rep movsb ; do the copy + jmp short F7dirty + +F720: ; Set the default Miscellaneous Output register + + cmp dx,20 + jne F7quit + mov word ptr cs:[ega_default_misc],si + +F7dirty: + + ; Set all the dirty register arrays + + mov al,1 ; put a nice one in all the dirty + ; registers + mov cx,25+4+9+20 ; dirty all the registers in one go + mov di,offset dirty_crtc + rep stosb + +F7quit: + pop ds ; need to restore the segment registers + pop es + + assume ds:SpcMseSeg, es:nothing + + popa + + jmp noint + +egaFA: ;--- Interrogate driver ----------------------------------------------- + ; The real Microsoft mouse driver gets this wrong (release 7.03) + + push ax + mov ax,cs + mov es,ax + mov bx,offset relnum ; return the address of the mouse + ; driver version number + pop ax + jmp noint + +;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + +ENDIF ; MOUSE_VIDEO_BIOS + +do_bop: + + bop VIDEO_IO_BOP ;BOP BE + nop + nop + jnc noint +go_rom: + popf + db 0EAh ; this is a far jump +old_vid_int dd ? ; far pointer to the old int 10h vector + jmp DOIRET +noint: + popf + jmp DOIRET + +mouse_int1: + bop INT1_BOP + jmp DOIRET + +mouse_version: + dw 04242h + dw 0000h + +mouse_copyright: + db "Windows NT MS-DOS subsystem Mouse Driver" + +video_io: + int VIDEO + bop UNSIMULATE_BOP + +mouse_int2: + bop INT2_BOP + jmp DOIRET + +mouseINB: + in al,dx + bop 0feh + +mouseOUTB: + out dx,al + bop 0feh + +mouseOUTW: + out dx,ax + bop 0feh + + +;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +;16 BIT ENTRY POINT 16 BIT ENTRY POINT 16 BIT ENTRY POINT 16 BIT ENTRY POINT +; +;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +;======================================================================== +; Procedure that provides the driver interface to 32 bit land. This is +; the entry point to the Intel 16 bit driver from the mouse interrupt +; handler in the host mouse code. +; +; This procedure determines the current video mode from the BIOS data +; area, and depending on this branches to the correct display routines +; for this mode. +; +; N.B. This function MUST NOT modify CX and DX because the next level +; of functions in the driver heirarchy requires the values passed in +; them from 32 bit land. +;======================================================================== + + assume ds:SpcMseSeg + +entry_point_from_32bit proc near + make_stack ; use the driver's own stack + push ds + push ax + push bx + + mov ax,cs + mov ds,ax + + call getBIOSvideomode; read the BIOS data area + xor bx,bx ; clear the jump table index + shl al,1 ; create a table index for word sized entries + mov bl,al ; move into a base register + call [drawpointerJMPT+bx] ; jump to the correct routine + + pop bx + pop ax + pop ds + kill_stack ; return to the previous stack + + bop 0FEh ; return to the 32 bit side + +entry_point_from_32bit endp + + +;======================================================================== +; Procedure to set the cursor draw flag to DO DRAW. This is called from +; SoftPC code via a host_simulate(). This routine is called when the +; application does an INT 33h, function 1. +; +; In accordance with the Microsoft Programmer's Reference, the internal +; cursor flag (internalCF) has a default value of -1. If intenalCF = 0 +; then the cursor is drawn. If the flag is already 0, then this function +; does nothing. +; +; Note: with calls to int 33h AX = 2, it is legal to +; make internalCF less than -1. +;======================================================================== + +int33function1 proc near + + make_stack ; use the driver's own stack + push ax + push bx + push ds + + mov ax,cs + mov ds,ax +;; do not allow mouse int comes in while we are updating the cursor. +;; call DOCLI + + ; check to see if the pointer should be drawn + +; cmp [internalCF],0 ; is the flag already zero? +; jz fn1quit ; if so, do nothing + + ; pointer is not ON, so increment the flag to try to turn it ON + +; inc [internalCF] ; increment the pointer internal flag +; cmp [internalCF],0 ; if 0, then the pointer can be drawn +; jl fn1quit ; it is < 0, so don't draw the pointer. + + ; The internal cursor flag hits zero for the first time, so + ; draw the pointer. + + call getBIOSvideomode; read the BIOS data area + xor bx,bx ; clear the jump table index + shl al,1 ; create a table index for word sized entries + mov bl,al ; move into a base register + call [Int33function1JMPT+bx] ; do the correct function 1 handler +fn1quit: +;; call DOSTI + pop ds + pop bx + pop ax + kill_stack ; return to the previous stack + bop 0FEh ; back to jolly old 32 bit land + +int33function1 endp + + + +;======================================================================== +; Procedure to set the cursor draw flag to DONT DRAW. This is called from +; SoftPC code via a host_simulate(). This routine is called when the +; application does an INT 33h, function 2 +; +; Note: with calls to int 33h AX = 2, it is legal to +; make internalCF less than -1. +;======================================================================== + +int33function2 proc near + + make_stack ; use the driver's own stack + push ax + push bx + push ds + + mov ax,cs + mov ds,ax +;; do not allow mouse int comes in while we are updating the cursor. +;; call DOCLI + +; dec [internalCF] ; decrement the pointer internal flag + + ; if the internal cursor flag is less than -1, then do not try + ; do remove the pointer from the screen because this has already + ; been done. + +; cmp [internalCF],0ffh +; jl fn2quit ; do nothing if < -1 + + ; Internal flag hits -1, so remove the pointer from the screen. + + call getBIOSvideomode; read the BIOS data area + xor bx,bx ; clear the jump table index + shl al,1 ; create a table index for word sized entries + mov bl,al ; move into a base register + call [Int33function2JMPT+bx] ; do the correct function 1 handler +fn2quit: +;; call DOSTI + pop ds + pop bx + pop ax + kill_stack ; return to the previous stack + + bop 0feh + +int33function2 endp + +;======================================================================== +; Procedure to return straight back to cloud 32. This is needed if an +; unsupported video mode is found in the BIOS data area. +;======================================================================== + +not_supported proc near + ret ; cant't BOP 0feh here or the stack will die + ; (out of balance with CS:IP stored from call) +not_supported endp + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; END 16 BIT ENTRY END 16 BIT ENTRY END 16 BIT ENTRY END 16 BIT ENTRY +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +;======================================================================== +; Procedure to draw a cursor on the fullscreen X86 graphics display for +; high resolution graphics modes. +; This procedure saves the area about to be written over, blts the +; pointer image onto the screen and restores the background from whence +; cursor has just come. +; +; Input: CX = x-coordinate +; DX = y-coordinate +; Output: None +;======================================================================== + + +drawHiResPointer proc near + + ; save the video card's read/write context + +;; call DOCLI + pusha + push ds + mov ax,cs ; make sure that DS points to the + mov ds,ax ; right segment + + + call saveVGAregisters + call check_for_mode_change + + + mov bx,cx ; get X coordinate into a base register + shl bx,1 ; calculate a word index + mov ax,[ChooseImageLUT+bx] ; select the right image LUT + mov [PointerLUT],ax ; store the LUT address + + xor ax,ax ; assume carry clear after the next call + call determineboundary + jnc detcont ; pointer in buonds if carry clear + not ax ; carry was set, so set AX non zero + +detcont: + + ; Coordinates are now transformed from Cartesian to physical VRAM + ; memory byte and bit offsets. + + mov di,dx ; store DX for later + + ; internalCF = the current pointer status + ; background = indicates if a background has been stored or not + ; + ; if(internalCF == Zero && background == STORED) + ; The normal cursor ON condition + + cmp [internalCF],0 + jnz end_the_if ; request to turn pointer on + cmp [background],STORED + jne end_the_if + + mov si,cx + mov di,dx + mov dx,[VRAMlastbyteoff] + mov cx,[VRAMlastbitoff] + call restore_background + + cmp ax,0 ; should the pointer be drawn? + jnz end_the_if ; if the pointer has gone off the edge of + ; the screen, then quit + + mov [VRAMlastbyteoff],di ; save the current position + mov [VRAMlastbitoff],si + mov cx,si + mov dx,di + call save_background + mov cx,si + mov dx,di + call drawEGApointer + +end_the_if: + + call restoreVGAregisters + + pop ds + popa +;; call DOSTI + ret + +drawHiResPointer endp + +;======================================================================== +; Procedure to draw a cursor on the fullscreen X86 graphics display.for +; medium resolution graphics modes. +; This procedure saves the area about to be written over, blts the +; pointer image onto the screen and restores the background from whence +; cursor has just come. +; +; Input: CX = x-coordinate +; DX = y-coordinate +; Output: None +;======================================================================== + +drawMediumResPointer proc near + + pusha +;; call DOCLI + + shr cx,1 ; map from 640 virtual to 320 real + + ; CX,DX = x,y cartesian coordinates here. + + call check_for_mode_change + + ; internalCF = the current pointer status + ; background = indicates if a background has been stored or not + ; + ; if(internalCF == Zero && background == STORED) + ; The normal cursor ON condition + + + cmp [internalCF],0 + jnz cant_draw_ptr ; request to turn pointer on + cmp [background],STORED + jne cant_draw_ptr + mov si, cx ; save new cursor position + mov di, dx + mov dx,[VRAMlastbyteoff] ; + mov cx,[VRAMlastbitoff] + mov bp,[LastYCounters] ; Y looping counter + call restorebkgrndmode4 + mov cx, si ; restore new cursor position + mov dx, di + call detboundmode4 ; calculate new byte offset + jc cant_draw_ptr ; don't draw new cursor of out of scrn + + mov [VRAMlastbyteoff], dx ; byte offset + mov [VRAMlastbitoff], cx ; MSB = 0FFh if start with ODD line + ; LSB = bit offset + mov [LastYCounters], bp ; MSB: even counter, LSB for odd + call savebkgrndmode4 + call drawmode4pointer + +cant_draw_ptr: + +;; call DOSTI + popa + ret + +drawMediumResPointer endp + +;======================================================================== +; Procedure to draw a cursor on the fullscreen X86 graphics display for +; medium resolution, 256 colour graphics mode. (video bios mode 13h). +; This procedure saves the area about to be written over, blts the +; pointer image onto the screen and restores the background from whence +; cursor has just come. +; +; Input: CX = x-coordinate +; DX = y-coordinate +; Output: None +;======================================================================== + +drawC256Pointer proc near + pusha +;; call DOCLI + shr cx,1 ; map from 640 virtual to 320 real x + + ; CX,DX = x,y cartesian coordinates here. + + call check_for_mode_change + + ; internalCF = the current pointer status + ; background = indicates if a background has been stored or not + ; + ; if(internalCF == Zero && background == STORED) + ; The normal cursor ON condition + + + cmp [internalCF],0 + jnz cant_draw_256ptr ; request to turn pointer on + cmp [background],STORED + jne cant_draw_256ptr + + mov si,cx + mov di,dx + mov dx,[VRAMlastbyteoff] + mov cx,[LastXCounters] + mov bp,[LastYCounters] + call restorebkgrndmode13 + mov cx, si + mov dx, di + call detboundmode13 + jc cant_draw_256ptr + + mov [VRAMlastbyteoff],dx ; save the current position + mov [LastXCounters],cx + mov [LastYCounters], bp + call savebkgrndmode13 + call draw256pointer + +cant_draw_256ptr: +;; call DOSTI + popa + ret +drawC256Pointer endp + +;======================================================================== +; Procedure to draw a pointer on the fullscreen X86 text display for +; BIOS modes 3 and 7. +; This procedure saves the area about to be written over, XORs the +; pointer image onto the screen and restores the background from whence +; cursor has just come. +; +; Input: CX = x-coordinate +; DX = y-coordinate +; Output: None +;======================================================================== + +IFDEF SIXTEENBIT + +drawTextPointer proc near + pusha + push es + + ; CX,DX = x,y virtual pixel coordinates here. + ; 0 <= x < 640 + ; 0 <= y < 200 for 25 line mode + ; 0 <= y < 344 for 43 line mode + ; 0 <= y < 400 for 50 line mode + ; The virtual character size is always 8x8 virtual pixels. + + call check_for_mode_change + + ; internalCF = the current pointer status + ; background = indicates if a background has been stored or not + ; + ; if(internalCF == Zero && background == STORED) + ; The normal cursor ON condition + + cmp [internalCF],0 + jnz cant_draw_text_ptr ; request to turn pointer on + cmp [background],STORED + jne cant_draw_text_ptr + + + ; Calculate the current cell location as an offset + ; into the text buffer segment starting at B800:0 + ; Note: The following kinky shifts allow for the fact that the text + ; video buffer consists of word elements of the form char:attr. + ; So, if a row = 80 characters wide on the screen, it is 160 + ; bytes wide in VRAM. + + mov bx,dx ; create a word table index + shr bx,3 ; virtual char height = 8, but 160 bytes + ; per text row, so save some shifts. + shl bx,1 ; make a word table index + mov di,[mult80lut+bx] ; multiply by 80 words per text row. + shl di,1 + shr cx,3 ; divide the x virtual pixel coordinate + ; by 8 = virtual char width and mult + ; by 2 to get word offset in text row. + shl cx,1 + add di,cx ; full VRAM location now in DI + + ; Restore the text cell previously overwritten. + + mov si,[VRAMlasttextcelloff]; address of last modified text cell + mov [VRAMlasttextcelloff],di; store the current cell location + + mov ax,0b800h ; the text buffer segment + mov es,ax ; ES now points there + + ; The text pointer uses the same magic as the graphics code + ; to place a pointer on the screen. + + mov bx,07700h ; the magic cursor mask for pointer + mov cx,077ffh ; the magic screen mask for pointer + + assume es:nothing + + mov ax,[lasttextimage] ; restore the background + mov es:[si],ax ; from last time + mov ax,es:[di] ; load the cell to be modifyed + mov [lasttextimage],ax ; save this cell for next time + and ax,cx ; apply the screen mask + xor ax,bx ; apply the cursor mask + mov es:[di],ax ; and write back + + assume es:SpcMseSeg + +cant_draw_text_ptr: + + pop es + popa + ret +drawTextPointer endp + +ENDIF ;; SIXTEENBIT + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; Interrupt 33h support functions. +; These functions are called via a jump table from the 16 bit entry +; point code. +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +;======================================================================== +; Procedure to set the cursor draw flag to DO DRAW. This is called from +; SoftPC code via a host_simulate(). This routine is called when the +; application does an INT 33h, function 1 +;======================================================================== + +int33function0 proc near + + make_stack ; use the driver's own stack + push ds + push es + pusha + + ; sort out the segments + + mov ax,cs + mov ds,ax + mov ax,cs + mov es,ax +;; do not allow mouse int comes in while we are updating the cursor. +;; call DOCLI + ; set the internal pointer flag to its default value. + + mov [internalCF],0ffh + + ; set the default hotspot location = (0,0) + + xor ax,ax + mov [hotspot],ax + mov [hotspot+2],ax + + ; copy the default pointer to the working pointer buffer + + lea si,default_cursor + lea di,current_cursor + call copy_pointer_to_current + + ; clear the pointer enabled flag, turn the pointer off by restoring + ; the background. + + mov [background],NOTSTORED ; there is no stored background now + +;; call DOSTI + popa + pop es + pop ds + kill_stack ; restore the previous stack + bop 0FEh + +int33function0 endp + + + +;======================================================================== +; Procedure to accept a cursor bit image from the current application +; at ES:DX. This is stored as the current pointer image for use by +; the driver. +;======================================================================== + +assume es:nothing + +int33function9 proc near + call DOCLI + make_stack ; use the driver's own stack + push ds + push es + pusha + + + mov ax,cs ; point at the driver data segment + mov ds,ax +;; do not allow mouse int comes in while we are updating the cursor. +;; call DOCLI + ; Read in the hotspot cartesian coordinate values for the + ; new pointer image. If the hotspot values are out of range + ; i.e. >127 | < -128, then reset to the boundary value + ; Now using kinky non modRM short forms by clever use of AX + + mov ax,127 ; load accumulator with 127 + mov bp,ax ; store this constant in a register + cmp ax,bx ; compare X value of hotspot with 127 + jg test_low_x ; if 127 > BX, BX is within upper limit + xchg ax,bx ; BX > 127, so set to 127 + jmp short check_y_hotspot ; now test the Y values + +test_low_x: + + not ax ; change accumulator from 127 to -128 + cmp ax,bx ; compare X value of hotspot with -128 + jl check_y_hotspot ; if -128 < BX, BX is within lower lim. + xchg ax,bx ; BX < -128, so set it to -128 + +check_y_hotspot: + + mov ax,bp ; reload AX with 127 + cmp ax,cx ; compare Y value of hotspot with 127 + jg test_low_y ; if 127 > CX, Cx is within upper limit + xchg ax,cx ; CX > 127, so set CX to 127 + jmp short done_hotspot_check; both hotspot coords tested, so save + +test_low_y: + + not ax ; change accumulator from 127 to -128 + cmp ax,cx ; compare Y value of hotspot with -128 + jl done_hotspot_check ; if -128 < CX, CX is within lower lim. + xchg ax,cx ; CX < -128, so set it to -128 + +done_hotspot_check: + + mov [hotspot],bx ; save the hotspot x,y + mov [hotspot+2],cx ; y component of the hotspot + + ; DESTINATION: the driver current pointer buffer + ; Note: the SOURCE is already being pointed at by DX + + lea di,current_cursor ; this is the bit that must change + mov si,dx + + ; copy in the new application pointer + + mov ax,es + mov ds,ax ; DS now points to where ES points + mov ax,cs + mov ax,es ; ES points to our data area now + call copy_pointer_to_current ; Copy the pointer image appropriately + + popa + pop es + pop ds + kill_stack ; restore the previous stack + call DOSTI + ret ; this code is called from within this + ; 16 bit driver, so don't BOP +int33function9 endp + +;============================================================================ +; Procedure to display the pointer image in HIRES graphics modes +;============================================================================ + +HiResInt33Function1 proc near + + pusha + call check_for_mode_change + call saveVGAregisters + mov cx,[current_position_x] ; get the last known cursor position + mov dx,[current_position_y] ; from the OS via the event loop + call determineboundary ; convert to VRAM coordinates + jc end_function1 ; if the pointer has gone off the edge + ; of the screen, then quit + mov [VRAMlastbyteoff],dx ; save the restore background location + mov [VRAMlastbitoff],cx + mov si,cx + mov di,dx + call save_background + mov cx,si + mov dx,di + call drawEGApointer + mov [background],STORED +end_function1: + call restoreVGAregisters + popa + ret ; return to driver surface manager code + +HiResInt33Function1 endp + +;============================================================================ +; Procedure to display the pointer image in MEDIUMRES graphics modes +; Note that this function does a conversion from virtual pixel coordinates +; to real screen coordinates as required if the stored values in the +; current_position memory locations are greater than 320 for X or 200 +; for Y. +;============================================================================ + +MediumResInt33Function1 proc near + + pusha + call check_for_mode_change + mov cx,[current_position_x] ; get the last known cursor position + mov dx,[current_position_y] ; from the OS via the event loop + shr cx,1 ; virtual coor -> screen coor + call detboundmode4 ; convert to VRAM coordinates + jc MediumResFunction1_exit + + mov [VRAMlastbyteoff],dx ; save the restore background location + mov [VRAMlastbitoff],cx + mov [LastYCounters], bp + call savebkgrndmode4 + call drawmode4pointer + mov [background],STORED + +MediumResFunction1_exit: + popa + ret + +MediumResInt33Function1 endp + +;============================================================================ +; Procedure to display the pointer image in VGA 256 colour graphics modes +;============================================================================ + +C256Int33Function1 proc near + pusha + call check_for_mode_change + call modifyentry255 ; make sure that DAC entry 255 is white + mov cx,[current_position_x] ; get the last known cursor position + mov dx,[current_position_y] + shr cx, 1 ; virtual coor -> screen coord + call detboundmode13 ; convert to VRAM coordinates + jc C256Function1_exit + + mov [VRAMlastbyteoff],dx ; save the restore background location + mov [LastXCounters],cx ; X loop counter + mov [LastYCounters], bp ; Y loop counter + call savebkgrndmode13 + call draw256pointer + mov [background],STORED + +C256Function1_exit: + popa + ret ; return to driver surface manager code + +C256Int33Function1 endp + +;============================================================================ +; Procedure to show the TEXT pointer +;============================================================================ +IFDEF SIXTEENBIT + +TextInt33Function1 proc near + + pusha + push es + + mov [background],STORED + call check_for_mode_change + + mov cx,[current_position_x] ; get the last known cursor position + mov bx,[current_position_y] ; from the OS via the event loop + + shr bx,3 ; virtual char height = 8, but 160 bytes + ; per text row. + shl bx,1 ; make a word table index + mov di,[mult80lut+bx] ; multiply by 80 words per text row. + shl di,1 ; remember 160 bytes NOT 80 in a row + shr cx,3 ; divide the x virtual pixel coordinate + ; by 8 = virtual char width and mult + ; by 2 to get word offset in text row. + shl cx,1 + add di,cx ; full VRAM location now in DI + + mov [VRAMlasttextcelloff],di; store the current cell location + + mov ax,0b800h ; the text buffer segment + mov es,ax ; DS now points there + + mov bx,07700h ; the magic cursor mask for pointer + mov cx,077ffh ; the magic screen mask for pointer + + assume es:nothing + + mov ax,es:[di] ; load the cell to be modifyed + mov [lasttextimage],ax ; save this cell for next time + and ax,cx ; apply the screen mask + xor ax,bx ; apply the cursor mask + mov es:[di],ax ; and write back + + assume es:SpcMseSeg + + pop es + popa + ret ; return to driver surface manager code + +TextInt33Function1 endp + +ENDIF ;; SIXTEENBIT +;============================================================================ +; Procedure to remove the pointer image in HIRES graphics modes +;============================================================================ + +HiResInt33Function2 proc near + + push cx + push dx + + call saveVGAregisters + call check_for_mode_change + + cmp [background],STORED ; is there some stored background? + jne no_background_stored ; no, so don't restore it + mov dx,[VRAMlastbyteoff] + mov cx,[VRAMlastbitoff] + call restore_background ; restored the background at correct + mov [background],NOTSTORED ; place. Set buffer cleared Flag + +no_background_stored: + + call restoreVGAregisters + + pop dx + pop cx + ret + +HiResInt33Function2 endp + +;============================================================================ +; Procedure to remove the pointer image in MEDIUMRES graphics modes +;============================================================================ + +MediumResInt33Function2 proc near + push cx + push dx + push bp + call check_for_mode_change + + cmp [background],STORED ; is there some stored background? + jne nobkgrndstored ; no, so don't restore it + mov dx,[VRAMlastbyteoff] + cmp dx,80*100 ; mustn't be greater than buffer size + jl vidoffok ; it's OK, so do nothing + mov dx,80*10-1 ; modify DX to fit in the buffer +vidoffok: + mov cx,[VRAMlastbitoff] ; CL = bit offset + ; CH = odd/even flag + and cl,3 ; cannot be greater than bit 3( 2bits/p) + mov bp, [LastYCounters] + call restorebkgrndmode4 ; restored the background at correct + mov [background],NOTSTORED ; place. Set buffer cleared Flag + +nobkgrndstored: + pop bp + pop dx + pop cx + ret +MediumResInt33Function2 endp + +;============================================================================ +; Procedure to remove the pointer image in MEDIUMRES graphics modes +;============================================================================ + +C256Int33Function2 proc near + push cx + push dx + push bp + call check_for_mode_change + + cmp [background],STORED ; is there some stored background? + jne nobkgrndstored256 ; no, so don't restore it + mov dx,[VRAMlastbyteoff] + mov cx,[LastXCounters] + mov bp,[LastYCounters] + call restorebkgrndmode13 ; restored the background at correct + mov [background],NOTSTORED ; place. Set buffer cleared Flag +nobkgrndstored256: + + pop bp + pop dx + pop cx + ret + +C256Int33Function2 endp + +;============================================================================ +; Procedure to remove the pointer image in TEXT modes +;============================================================================ + +IFDEF SIXTEENBIT + +TextInt33Function2 proc near + + push ax + push si + push es + + call check_for_mode_change + + cmp [background],STORED ; is there some stored background? + jne no_text_background_stored ; no, so don't restore it + + mov [background],NOTSTORED ; place. Set buffer cleared Flag + + ; Restore the text cell previously overwritten. + + mov si,[VRAMlasttextcelloff]; address of last modified text cell + + mov ax,0b800h ; the text buffer segment + mov es,ax ; DS now points there + + assume es:nothing + + mov ax,[lasttextimage] ; restore the background + mov es:[si],ax ; from last time + +no_text_background_stored: + + assume es:SpcMseSeg + + pop es + pop si + pop ax + ret + +TextInt33Function2 endp + +ENDIF ;; SIXTEENBIT + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; End of Interrupt 33h support functions. +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; Mouse driver general support functions +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +;======================================================================== +; Procedure to determine if the application has changed video modes since +; the last mouse interrupt. If it has, then the image that is saved in the +; background restore buffer is invalid and should not be drawn. +;======================================================================== + +check_for_mode_change proc near + + push ax + + call getBIOSvideomode; peek at the BIOS data area for video mode + cmp al,[lastvidmode]; compare with the last mode value + ; from the preceding interrupt + jnz mode_change ; a mode change has occurred + pop ax ; no mode change, so quit + ret +mode_change: + mov [background],NOTSTORED + mov byte ptr [lastvidmode],al ; store the new mode + pop ax + + ret +check_for_mode_change endp + +;======================================================================== +; Procedure to read the BIOS data area and get the current video mode +; Output: AL = BIOS video mode +; Modifies: memory variable -> currentvidmode, puts the video found in +; the BIOS data area in this memory location. +;======================================================================== + +getBIOSvideomode proc near + + push es + push bx + mov ax,40h ; BIOS data area segment + mov es,ax + + mov al,es:[49h] ; get the BIOS video mode data + + mov bl,al ; copy the video mode value + xor bh,bh + shl bx,1 ; create a word table index + mov bx,[latchhomeLUT+bx] ; get the latch hiding place for this + ; video mode + mov [latchcache],bx ; save in memory for use in save and restore + ; vga registers. + + pop bx + pop es ; restore the 'normal' data segment + ret + +getBIOSvideomode endp + +;========================================================================= +; Function to modify the 256th palette entry for 256 colour mode. The +; driver requires white to be set in this DAC register triple. +;========================================================================= +modifyentry255 proc near + push ax + push dx + mov dx,03c8h + mov al,0ffh + out dx,al + inc dx + out dx,al + out dx,al + out dx,al + pop dx + pop ax + ret +modifyentry255 endp + + +;======================================================================== +; Procedure to copy the required pointer image to the snapshot +; buffers. Each buffer holds a different instance of the mouse +; pointer for each possible alignment of the pointer image in +; a VRAM byte. +; +; INPUT DS:SI = pointer to the source image +; +;======================================================================== + +assume ds:nothing + +copy_pointer_to_current proc near + + push ds + push es + pusha + + + ; Set up the destination for the copy + + mov ax,cs ; point ES to this segment + mov es,ax + lea di,current_cursor ; this is the bit that must change + mov bx,di ; save this address for a while + mov bp,si ; save the application source address + + ; Fill the AND buffer with 1s and then fill the XOR buffer with + ; 0s for the byte aligned pointer condition. This is done so that + ; the last byte in the 3byte scanline sequence is set to the correct + ; value to prevent image loss from the screen. + + cld ; move low mem -> high mem + mov ax,24 ; avoid doing a modRM load of immediate + mov cx,ax ; 24 words to fill. + mov dx,ax ; store this for a while + xor ax,ax ; clear AX (AX = 0) + not ax ; AX = 0ffffh -> fill AND mask with it. + rep stosw ; fill the screen mask (AND mask) + mov cx,dx ; do the next 24 words (XOR mask) + not ax ; AX = 0h -> fill XOR mask with it + rep stosw ; Fill the cursor mask + + ; Now fill the prepared 48 word buffer with the user defined + ; AND and XOR masks + ; Note that the image passed in from the application is little-endian. + ; To write to the VGA planes byte by byte, the image has to be reversed + ; to big-endian for the purpose of quick drawing since the VGA can only + ; read and write one byte from/to its latches. + + mov di,bx ; point to the top of the buffer again + mov si,bp ; point to the new pointer image + + mov cx,32 +norept1: + lodsw ; read in the required image word + xchg al,ah ; convert little endian to big endian + stosw ; write into local buffer + inc di ; remember local buffer in 3 bytes wide + dec cx + jnz norept1 + + ; Now, the aligned mask must be rotated, then copied into each of + ; the seven unaligned image buffers. + + mov ax,cs + mov ds,ax ; return to the default data segment + + mov bp,1000000000000000b ; a mask for the MSBit + + lea di,AlignData1 ; point to the buffer for 1 bit offset + mov si,bx ; source = byte aligned pointer image + + push bx + mov bx,32*7 +norept2: + lodsw ; load the word from 3 byte sequence + xchg al,ah ; put into little-endian format + mov cl,byte ptr [si] ; load the remaining byte + shr ax,1 ; LSB now stored in CF + rcr cl,1 ; CF into MSB, lsb into CF + jnc $+4 ; CF=0 -> don't need to do anything + or ax,bp ; OR in the carried bit from CF + xchg al,ah ; return to bitstream format + stosw ; write the rotated data + mov byte ptr[di],cl + inc si ; point to the next source scanline + inc di ; point to the next dest scanline + + dec bx + jnz norept2 + pop bx + + ; Just to do a little bit more work, the rotated buffers created + ; above must be copied to the instances for byte 78 and byte 79 + ; of the scanline. These images are then cunningly clipped in the + ; process to the edge of the screen! + + mov si,bx ; BX points to the top of current buffer + ; Note DI points to clip_cursor78 now + + ; may as well use the nice string functions now that I don't + ; have to XCHG bytes. (how space and cycle efficient + + xor al,al ; constant for putting in masks + + ; there are 8 instances for bits 0 to 7 + + mov bx,8 +norept3: + + ; Do the AND mask modifications for byte 78 + + not al ; AL = 11111111b + REPT 16 ; 16 scanlines + movsw ; copy contents of AND word + stosb ; Nice clear AND mask = 11111111b + inc si ; point to the first image byte in + ; the next scanline + ENDM + + ; Do the XOR mask modifications for byte 78 + + not al ; AL = 00000000b + REPT 16 ; 16 scanlines + movsw ; copy contents of XOR word + stosb ; Nice clear XOR mask = 00000000b + inc si ; point to the first image byte in + ; the next scanline + ENDM + + dec bx + jnz norept3 + + ; prepare the BYTE 79 instances + ; SI and DI should be in the right place + + xor ax,ax ; constant for putting in masks + mov bx,2 ; constant for addressing source + + ; there are 8 instances for bits 0 to 7 + + mov cx,8 +norept4: + + ; Do the AND mask modifications for byte 79 + + not ax ; AX = 0ffffh + REPT 16 ; 16 scanlines + movsb ; copy contents of AND byte + stosw ; Nice clear AND mask (=0ffffh) + add si,bx ; point to the first image byte in + ; the next scanline + ENDM + + ; Do the XOR mask modifications for byte 79 + + not ax ; AX = 0h + REPT 16 ; 16 scanlines + movsb ; copy contents of XOR byte + stosw ; Nice clear XOR mask + add si,bx ; point to the first image byte in + ; the next scanline + ENDM + + dec cx + jz norept4quit + jmp norept4 +norept4quit: + + popa + pop es + pop ds + + ret +copy_pointer_to_current endp + +;======================================================================== +; Procedure to determine the segment of the video buffer for +; the current display mode. +;======================================================================== + +assume ds:SpcMseSeg + +getvideobuffer proc near + + push ax + push si + + ; determine the current video mode from the BIOS and save it. + ; Use this value to determine the video buffer segment address. + + mov ah,0fh ; use the bios to get the video mode + int 10h + cbw ; create a table index + shl ax,1 ; word sized table entries + mov si,ax + mov ax,[videomodetable+si] ; use video mode to index the table + mov [videobufferseg],ax + + + pop si + pop ax + ret + +getvideobuffer endp + +IFDEF DEBUGMOUSE + +;========================================================================= +; Code to provide 32 bit side with a dump of the VGA registers on request. +;========================================================================= + +VGAregs db 9+5+25 dup(?) ; enough room for sequencer, GC and CTRC + +dumpVGAregs proc near + + call DOCLI + pusha + push ds + + + mov ax,cs + mov ds,ax + + assume ds:SpcMseSeg + + ; Save the Graphics Controller registers + + xor bx,bx ; Index into the G.C. register saving array + mov dx,03ceh ; Graphics Controller index register + xor ax,ax + + mov cx,9 ; save 9 G.C. registers +norept5: + mov al,ah + out dx,al ; Select it + inc dx ; Address the register + in al,dx ; Get the register contents + mov [VGAregs+bx],al ; Save the register + inc bx ; index to next array entry + inc ah + dec dx ; Sequencer index register + dec cx + jnz norept5 + + ; Save the Sequencer registers + + mov dx,03c4h ; Sequencer index register + xor ax,ax + + mov cx,5 ; save 5 sequencer registers +norept6: + mov al,ah + out dx,al ; Select it + inc dx ; Address the register + in al,dx ; Get the register contents + mov [VGAregs+bx],al ; Save the register + inc bx ; index to next array entry + inc ah + dec dx ; Sequencer index register + dec cx + jnz norept6 + + ; Save the CRTC registers + + mov dx,03d4h ; CRTC index register + xor ax,ax + + mov cx,25 ; save 25 sequencer registers +norept7: + mov al,ah + out dx,al ; Select it + inc dx ; Address the register + in al,dx ; Get the register contents + mov [VGAregs+bx],al ; Save the register + inc bx ; index to next array entry + inc ah + dec dx ; CRTC index register + dec cx + jnz norept7 + + pop ds + popa + call DOSTI + bop 0feh ; return to 32 bit land + +dumpVGAregs endp + +ENDIF ; DEBUGMOUSE + + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; End of Mouse driver general support functions +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +;======================================================================== +; Procedure to draw an EGA pointer image on the graphics screen at a +; specified bit location. +; +; Input: CX = pointer offset in the current VRAM byte. +; DX = offset in the video buffer to pointer +; Output: None +; Modifies: AX,BX,CX,DX,BP,SI,DI +;======================================================================== + + assume ds:SpcMseSeg +.286 +even + +drawEGApointer proc near + + push es + push ds + + mov ax,cs + mov ds,ax + + cld ; index from low memory to high for LODSB + + ; point to the video buffer + + mov ax,0a000h + mov es,ax + mov bp,dx ; save the byte offset in VRAM for the XOR code + + ; Select the Graphics Controller + + mov dx,03ceh + + ;************ AND MASK OPERATION ************************** + + ; use the bit position to select the relavent pointer image + + shl cx,1 ; need a word offset into LUT + mov di,cx ; need an index register + mov bx,[PointerLUT] + mov si,[bx+di] ; Point to the screen (AND) mask + mov di,bp ; point to the byte offset in VRAM + mov ax,0803h ; Index the data rotate register and select AND + out dx,ax ; do it + mov ax,80-2 ; Avoid modRM loading of CX + mov cx,ax ; A constant handily kept in a register + + ; The pointer contains 16 words of information + push bx + mov bx,16 +norept8: + + lodsw ; Load 2 bytes from the AND mask into AL and AH + xchg al,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + inc di ; point to the next byte in VRAM + + xchg ah,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + inc di ; point to the next byte in VRAM + + lodsb ; Load a byte from the AND mask into AL + xchg al,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + add di,cx ; point to the next byte in VRAM on the next scan + ; line to write to. CX contains 80-2 + + dec bx + jnz norept8 + pop bx + + ;************ XOR MASK OPERATION ************************** + + ; Note: SI points to current_cursor+48 now, automatically + ; i.e. at the start of the XOR mask. + + mov di,bp ; point to the byte offset in VRAM + mov ax,1803h ; Index the DATA ROTATE REGISTER and + ; Select the XOR function to XOR CPU data in + out dx,ax ; Do the deed + + push bx + mov bx,16 +norept9: + + lodsw ; Load 2 bytes from the AND mask into AL and AH + xchg al,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + inc di ; point to the next byte in VRAM + + xchg ah,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + inc di ; point to the next byte in VRAM + + lodsb ; Load a byte from the XOR mask into AL + xchg al,es:[di] ; Latch the 8 pixels for updating. + ; and write them back out with new data + add di,cx ; point to the next byte in VRAM on the next scan + ; line to write to. CX contains 80-2 + dec bx + jnz norept9 + pop bx + + pop ds + pop es + ret + +drawEGApointer endp + +;======================================================================== +; Procedure to determine what the byte and bit offset is, in the current +; VGA buffer for the top left hand corner of the pointer bitmap. +; The X,Y value is modified for hotspot in this routine. A flag is set, +; also, to relay whether or not the cursor bitmap is byte aligned or not. +; +; INPUT: CX,DX = pointer x,y coordinates +; OUT : DX = byte offset to top left hand pointer pixel +; CX = bit offset in the byte +; CF = set if it is not possible to draw the pointer on the +; screen because of the hotspot adjustment. (Usually a +; negative hotspot value will cause clipping and wrapping +; problems at the right and bottom screen boundaries. +;======================================================================== + +determineboundary proc near + + push ax + push bx + push es + + + ; do the adjustment in x,y for pointer hotspot + ; Also test for top or left screen boundary problems + ; and zero the coordinate if it goes negative. + + + sub cx,[hotspot] ; adjust the x cartesian coord for hotspot + jns dont_zero_x ; if x goes negative, assume zero + xor cx,cx +dont_zero_x: + sub dx,[hotspot+2] ; adjust the y cartesian coord for the hotspot + jns dont_zero_y ; if y goes negative, assume zero + xor dx,dx +dont_zero_y: + + ; Now check the right and bottom bounds to prevent the pointer + ; image wrapping if the hotspot adjustment forces either of + ; the coordinates to exceed the screen bounds. + ; First, for all video modes that this function handles, the + ; X bound is always x < 640 ... check this first. + + cmp cx,640 + jl didntexceedX + stc ; Oh oh - failed, so set carry flag. + jmp short quitdet ; bye bye. + +didntexceedX: + + ; Now check out the y value by finding the maximum extent from + ; a lut based on the current BIOS video mode. + + mov ax,40h ; B.D.A. segment + mov es,ax ; and ES points to it. + mov al,byte ptr es:[49h] + sub al,0fh ; table is normalized. mode f is in entry + ; zero. + xor ah,ah ; create a look up table index + shl ax,1 ; for a table with word sized elements. + xchg bx,ax ; use a suitable register as index + + cmp dx,[hiresylut+bx] ; get the extent and compare y coord. + jl didntexceedY + stc ; Oh oh - failed, so set carry flag. + jmp short quitdet ; bye bye. + +didntexceedY: + + ; determine the byte offset from the start of the video buffer + ; for the modified coordinates. First calculate how many bytes + ; there are for the number of scanlines -1 to where the pointer + ; is. + + mov ax,dx ; copy Y position into AX + shl ax,1 ; create a word table index + xchg ax,bx ; copy table index into a base register + mov dx,[mult80lut+bx] ; do a fast LUT multiply by 80 + + ; determine the byte position of the pixel in question + + mov ax,cx ; save the x-coordinate displacement + and ax,7 ; do a modulus 8 to find the pixel position + ; in the byte. The bit number is in DX. + + ; add the whole number of bytes in the current row to the number + ; of complete-row bytes + + shr cx,3 ; divide pixels by 8 to get bytes + add dx,cx ; DX hold the complete byte offset. + xchg ax,cx ; CX = bit offset in the byte. + + ; the pointer has not exceeded the screen buonds, so clear + ; the carry flag to signify this. + + clc + + ; Wind up the routine and return with the carry flag: + ; SET if cursor exceeded screen bounds. + ; CLEAR otherwise. +quitdet: + + pop es + pop bx + pop ax + ret + +determineboundary endp + +;======================================================================== +; Procedure to buffer up the data over which the cursor will next be +; drawn. This data will be used to replace the cursor at a later point +; when the cursor position has changed and for generating a cursor image +; To prevent having separate routines for aligned and unaligned pointer +; saves, this routine saves a pixel block 24 x 16 deep in all cases. The +; start offset is a byte location into VRAM in which the pointer TLHC lives. +; +; Input: DX = VRAM byte +; Modifies: AX,BX,DI,CX,DX,ES +; +;======================================================================== + +assume ds:SpcMseSeg + +even + +save_background proc near + + push ds + push es + pusha + + mov ax,cs ; point DS briefly at the driver data + mov ds,ax + mov es,ax ; point ES to the driver segment + + lea di,behindcursor ; DESTINATION: a nice, safe place in the + ; driver segment + mov ax,0a000h ; point DS at VRAM + mov ds,ax + + assume ds:nothing + + mov bp,dx ; save DX=VRAM byte offset for later use + mov dx,03ceh ; VGA GC index register + mov al,4 ; select the read map select reg + out dx,al ; Index in the map select register + inc dx ; DX holds port address to map select register + xor al,al ; plane 0 will be selected first + + cld ; make sure to address forward in memory + mov ah,3 ; number of bytes to copy per pointer scanline + xor cx,cx ; counter for the REP MOVSB + mov bx,80-3 ; another handy constant: move to next scanline + ; byte. + + REPT 4 ; read the 4 EGA planes individually + + mov si,bp ; SOURCE: somewhere in VRAM + out dx,al ; do the plane selection + inc al ; select the next plane to latch + + ; note that only one byte at a time may be read from the latches + + ; do 16 scanlines for each plane + push dx + mov dx,16 +@@: + mov cl,ah ; CX now contains 3 + rep movsb ; copy 3 bytes from VRAM to data segment + add si,bx ; move down to the first byte in next scanline + dec dx + jnz @B ; norept10 + pop dx + + ENDM + + popa + pop es + pop ds + + ret + +save_background endp + +;======================================================================== +; Procedure to restore the area of the screen that was behind the cursor +; before it had moved. +; +; Note. Currently (2/12/92) this is the only routine that modifies the +; VGA sequencer. Therefore, the code from save and restore vga registers +; that maintain the sequencer registers has been moved to here for +; centralisation purposes. +; +; Input: DX = VRAM byte +; Output: None +; Modifies: AX,BX,CX,DX,DI,SI +;======================================================================== +assume ds:SpcMseSeg + +even + +restore_background proc near + push ds + push es + pusha + +;; call DOCLI ; turn off interrupts + mov ax,cs + mov ds,ax ; point at the driver data segment + mov ax,0a000h ; videobufferseg + mov es,ax ; point ES at VRAM segment + mov bp,dx ; save the pointer for later + mov si,offset behindcursor ; SOURCE: point at the stored planes + + ; set up the Graphic Controller for the restore. + + mov dx,03ceh ; VGA GC index register + mov ax,0003h ; Select copy into latches function + out dx,ax ; i.e. data rotate -> replace + mov ax,0ff08h ; bitmask register reset + out dx,ax + + ; do the 4 plane restore. + + mov cx,80-2 ; point to the first byte in image on next line + cld ; write forward in memory + mov bx,0102h ; BH = initial plane mask value + ; plane 0 is selected with a 1 + ; BL = map mask register offset + mov dx,03c4h ; index register for sequencer + + mov al,bl ; point to the map mask register in sequencer + out dx,al ; index the register into 03c5h + inc dx ; point to the data register + in al,dx ; read the data register value in + dec dx ; restore DX to 03c4h + mov [seqregs],al ; save the map mask register value + + REPT 4 ; 4 planes to restore + + mov di,bp ; DESTINATION: pointer into VRAM + mov ax,bx ; select the plane to mask and map mask register + out dx,ax ; do the mask + shl bh,1 ; point to the mask for the next iteration + + push dx + mov dx,16 +@@: + + lodsw ; load the old background data (ONE WORD) + xchg al,es:[di] ; latch the VRAM data and swap with the + inc di ; point to next byte to replace + xchg ah,es:[di] ; latch the VRAM data and swap with the + inc di ; point to next byte to replace + lodsb ; load the old background data (ONE BYTE) + xchg al,es:[di] ; latch the VRAM data and swap with the + add di,cx ; point to the first byte in image on next line + + dec dx + jnz @B ; norept11 + pop dx + + ENDM + + mov ah,[seqregs] ; the old map mask value + mov al,bl ; need to restore the map mask register + out dx,ax ; do the restore +;; call DOSTI ; reenable interrupts. + popa + pop es + pop ds + ret +restore_background endp + + +;========================================================================== +; Procedure to save the register state of the VGA card on receiving a +; mouse pointer update interrupt. This procedure also sets up the following +; VGA registers to nice values for the driver. +; +; mode register <write mode 0, read mode 0> +; data rotate register <do not rotate, no logical ops> +; enable set/reset register <disable set/reset> +; +;========================================================================== + +even +assume ds:SpcMseSeg + +saveVGAregisters proc near + + push dx + push di + push es + + ; Save the Graphics Controller registers that the + ; Driver uses + + xor bx,bx ; Index into the G.C. register saving array + mov dx,03ceh ; Graphics Controller index register + xor al,al + + push cx + mov cx,9 ; save 9 G.C. registers +norept12: + out dx,al ; Select it + inc dx ; Address the register + in al,dx ; Get the register contents + mov [GCregs+bx],al ; Save the register + inc bx ; index to next array entry + mov al,bl + dec dx ; G.C. index register + dec cx + jnz norept12 + pop cx + + ; save the latches to location in a bit of video buffer + ; off the screen. + + mov ax,0a000h ; point to the video buffer + mov es,ax + + assume es:nothing + + mov ax,0105h ; select write mode 1 to squirt latches out + out dx,ax ; do the selection + mov di,[latchcache] ; 1 byte over the last location + mov es:[di],al ; write the latches out to the planes + + ; disable the enable set/reset register + + mov ax,01h ; select enable set/reset register and clear it + out dx,ax + + ; clear the data rotate register (no logical operations). + + inc ax + inc ax ; select data rotate register and clear it + out dx,ax ; AX = 3 therefore points to the DRR + + ; set write mode 0 for the graphics display + ; conveniently, this also sets read mode to 0 which is needed too! + + inc ax + inc ax ; select write mode 0 + out dx,ax ; AX = 5, i.e. the mode register + + ; color don't care. don't care for all planes + inc ax ;register 7, color don't care + inc ax + out dx, ax + ; bit mask register. enable all planes + ; + inc ax ;register 8, bit mask + not ah + out dx, ax + pop es + pop di + pop dx + ret + +saveVGAregisters endp + +;========================================================================== +; Procedure to restore the register state of the VGA card after dealing +; with mouse pointer update interrupt. +;========================================================================== + +restoreVGAregisters proc near + + assume ds:SpcMseSeg + + push es + push di + push bx + + ; restore the latches that where saved in the video planes + + mov ax,0a000h ; point to the video buffer + mov es,ax + + assume es:nothing + + mov di,[latchcache] ; the byte just off the end of the buffer + mov al,es:[di] ; read in the latches + + ; Restore the Graphics Controller registers that the + ; Driver uses + + xor ax,ax ; create an index + xor bx,bx ; Index into the G.C. register saving array + mov dx,03ceh ; Graphics Controller index register + +norept13: + mov ah,[GCregs+bx] ; restore the register + out dx,ax ; Select it + inc al ; index for the next register + inc bx ; index to next array entry + cmp al,9 + jne norept13 + + pop bx + pop di + pop es + ret + +restoreVGAregisters endp + +;======================================================================= +; Procedure to draw a BIOS Mode 4 graphics pointer to the display. +; Input: DX = byte offset +; CL = bit offset in the byte +; CH = 0FFh if ODD, 0 if EVEN +; BP = Y loop counter, ODD in LSB, EVEN in MSB +;======================================================================= +drawmode4pointer proc near + + pusha + push es + cld + + xchg dx, bp ; + mov di, bp ; bp = di = byte offset, dx = y counters + mov ax,0b800h ; point a segment register to + mov es,ax ; the CGA video buffer. + or ch, ch ; + je drawonevenscanline ; + jmp drawonoddscanline ; otherwise do an ODD job + +; ANDEVEN ANDEVEN ANDEVEN ANDEVEN ANDEVEN ANDEVEN ANDEVEN ANDEVEN ANDEVEN + +drawonevenscanline: + + mov si,[mode4SelectedPointer] + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for even scanlines + + xor cx, cx + mov cl, dh ; number of even scanlines to draw + push dx +evensl1: + mov dx,3 +norept14: + lodsb ; load 8 pixels from pointer bitmap + xor bh,bh ; want a zero extended 16 bit value + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah ; little-endianise + mov bx,es:[di] ; get the current displayed 8 pixels + and ax,bx ; AND the AND mask in + stosw ; write to the video buffer + dec dx + jnz norept14 + + add si,3 + add di,80-6 + loop evensl1 + pop dx + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for odd scanlines + + mov si,[mode4SelectedPointer] + add si,3 + mov di,bp + add di,02000h ; offset into video buffer + ; the video buffer + mov cl,dl ; number of odd scanlines to draw + push dx +oddsl1: + mov dx,3 +norept15: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + and ax,bx ; AND the AND mask in + stosw ; write to the video buffer + dec dx + jnz norept15 + + add si,3 + add di,80-6 + loop oddsl1 + pop dx + +; XOREVEN XOREVEN XOREVEN XOREVEN XOREVEN XOREVEN XOREVEN XOREVEN XOREVEN + + + mov si,[mode4SelectedPointer] + add si,48 + + mov di,bp ; offset into video buffer + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for even scanlines + + mov cl,dh ; number of even scanlines to draw + push dx +evensl2: + mov dx,3 +norept16: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + xor ax,bx ; XOR the XOR mask in + stosw ; write to the video buffer + dec dx + jnz norept16 + + add si,3 + add di,80-6 + loop evensl2 + pop dx + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for odd scanlines + + mov si,[mode4SelectedPointer] + add si,48+3 + mov di,bp + add di,02000h ; offset into video buffer + ; the video buffer + mov cl,dl ; number of odd scanlines to draw +oddsl2: + mov dx,3 +norept17: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + xor ax,bx ; XOR the XOR mask in + stosw ; write to the video buffer + dec dx + jnz norept17 + + add si,3 + add di,80-6 + loop oddsl2 + pop es + popa + ret + + +; ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD ANDODD +; +; This part of the code draws the pointer on an odd numbered scanline +; of the video display. Since the video buffer is split, 0000 to 1fff +; containing even scanlines and 2000 to 3fff containing odd, the data +; must be manipulated in a subtly different fashion than that of the +; even display scanline code. +; The even scanline code display arrangement falls through naturally, +; with an even scanline drawing thus: +; buffer 0: scanline 0 +; buffer 1: scanline 0 +; buffer 0: scanline 1 +; buffer 1: scanline 1 +; buffer 0: scanline 2 +; buffer 1: scanline 2 etc. +; whereas in the odd case: +; buffer 1: scanline 0 +; buffer 0: scanline 0 +; buffer 1: scanline 1 +; buffer 0: scanline 1 +; buffer 1: scanline 2 +; buffer 0: scanline 2 etc. +; and this requires that the odd image scanlines must be placed +; one scanline lower in the even buffer than the even image scanlines +; do in the odd buffer + +drawonoddscanline: + + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for odd scanlines + + mov si,[mode4SelectedPointer] + add di,02000h ; offset into video buffer + ; the video buffer + + xor cx,cx + mov cl,dl ; number of odd scanlines to draw + push dx +oddsl3: + mov dx,3 +norept18: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + and ax,bx ; AND the AND mask in + stosw ; write to the video buffer + dec dx + jnz norept18 + + add si,3 + add di,80-6 + loop oddsl3 + pop dx + + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for even scanlines + + and dh,dh + jz dontdothis1 ; can't do the loop 0 times + + mov si,[mode4SelectedPointer] + add si,3 + mov di,bp + add di,6 ; This is required to align the + ; even and odd scanlines together + mov cl,dh ; number of even scanlines to draw + push dx +evensl3: + add di,80-6 ; remember even BELOW odd + mov dx,3 +norept19: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + and ax,bx ; AND the AND mask in + stosw ; write to the video buffer + dec dx + jnz norept19 + add si,3 + loop evensl3 + pop dx + +dontdothis1: + +; XORODD XORODD XORODD XORODD XORODD XORODD XORODD XORODD XORODD XORODD XORODD + + + mov si,[mode4SelectedPointer] + add si,48 + mov di,bp ; offset into video buffer + add di,02000h ; offset into video buffer + ; the video buffer + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for odd scanlines + + mov cl,dl ; number of odd scanlines to draw + push dx +oddsl4: + mov dx,3 +norept20: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + xor ax,bx ; XOR the XOR mask in + stosw ; write to the video buffer + dec dx + jnz norept20 + add si,3 + add di,80-6 + loop oddsl4 + pop dx + + ; Load a word of the pointer image, convert it to two bits per + ; pixel and write to the screen for even scanlines + + and dh,dh ; can't do a loop 0 times + jz dontdothis2 + + mov si,[mode4SelectedPointer] + add si,48+3 + mov di,bp + add di,6 + + mov cl,dh ; number of even scanlines to draw + +evensl4: + add di,80-6 + mov dx,3 +norept21: + lodsb ; load 8 pixels from bitmap + xor bh,bh + mov bl,al ; copy into a base register + shl bx,1 ; create a word address + mov ax,[LUT1to2bit+bx] ; get the byte to word conversion + xchg al,ah + mov bx,es:[di] ; get the current displayed 8 pixels + xor ax,bx ; XOR the XOR mask in + stosw ; write to the video buffer + dec dx + jnz norept21 + + add si,3 + loop evensl4 + +dontdothis2: + +; XORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXORXOR + + pop es + popa + ret +drawmode4pointer endp + +;======================================================================== +; Procedure to determine what the byte and bit offset is, in the current +; VGA buffer for the top left hand corner of the pointer bitmap. +; The X,Y value is modified for hotspot in this routine. +; Y looping counter(ODD and EVEN) are also returned +; The CGA buffer is interleaved, and runs from B800:0000 to B800:1999 for +; odd scanlines and from B800:2000 for even scanlines. +; +; INPUT: CX,DX = pointer x,y coordinates +; OUT : +; carry set if either X or Y is out of screen +; DX = byte offset to top left hand pointer pixel of the pointer +; CL = bit offset in the byte +; CH = 0FFh if ODD, 0 if EVEN +; BP = Y loop counter(ODD in LSB and EVEN in MSB) +;======================================================================== + +detboundmode4 proc near + + push ax + push bx + push ds + + mov ax,cs + mov ds,ax + + assume ds:SpcMseSeg + + + ; do the adjustment in x,y for pointer hotspot + ; modify the raw X,Y values for hotspot + + sub cx,[hotspot] ; adjust the x cartesian coord for hotspot + jns dont_zero_xmode4; if x goes negative, assume zero + xor cx,cx + +dont_zero_xmode4: + + sub dx,[hotspot+2] ; adjust the y cartesian coord for the hotspot + jns dont_zero_ymode4; if y goes negative, assume zero + xor dx,dx + +dont_zero_ymode4: + + cmp cx, 320 ; + jae detboundmode4_exit ; CY is cleared + cmp dx, 200 + jae detboundmode4_exit ; CY is cleared + ; determine the byte offset from the start of the video buffer + ; for the modified coordinates. First calculate how many bytes + ; there are for the number of scanlines -1 to where the pointer + ; is. Also if the pointer starts on a odd scanline, set CF, else + ; clear CF. + + mov ax,dx ; copy Y position into AX + mov bp,dx ; copy Y position into BP for use later + + ; CGA video buffer is split in two. Therefore, screen scanline 0 maps + ; to video buffer scanline 0 and screen scanline 1 maps to video + ; buffer+2000h, scanline 0 + + and ax,0fffeh ; do the mapping 0->0, 1->0, 2->1, 3->1 etc. + ; and create a word table index + mov bx, ax ; copy table index into a base register + ; 2bits/pixel -> 4 pixels/byte + ; sine x total is 320, we have 80bytes + ; so a shl bx, 1 will be wrong. + mov dx,[mult80lut+bx] ; do a fast LUT multiply by 80 + + ; determine the byte position of the pixel in question + + mov ax,cx ; save the x-coordinate displacement + and ax,3 ; do a modulus 4 to find the pixel position + ; in the byte. The byte number will be in DX. + + ; add the whole number of bytes in the current row to the number + ; of complete-row bytes. Note that mode 4 is 2bits per pixel, so + ; there are four pixels represented by one byte. + + mov bx,cx ; Save in a base reg. to create a table index + shl bx,1 ; Create a table index for word sized entries + add dx,[mode4clipCXadjustLUT+bx]; DX hold the complete byte offset. + mov cx, ax ; CX = bit offset in the byte. + + mov ax, [mode4pointerLUT + bx] ; select appropriate pointer + mov [mode4SelectedPointer], ax + + ; Odd or Even scanline? note BP contains y cartesian coordinate + + mov bx, bp ; y coordinate + shr bp, 1 ; shift right to determine if odd or even + ; CF if odd, or 0 if even. + sbb ch, ch ; CH = 0FFh if ODD, 0 if EVEN + shl bx, 1 + mov bp, [mode4clipDXLUT + bx] ;the Y counters + stc ; we are fine, set the CY so we will return + ; CY cleared. +detboundmode4_exit: + cmc ; revese the CY + pop ds + pop bx + pop ax + ret + +detboundmode4 endp + + + +;============================================================================= +; Procedure to save the area of CGA video buffer into which the pointer will +; be drawn. The memory buffer in which this data is stored is arranged odd +; scanlines first, then even. So, the first 48 bytes are the odd scanline +; data. +; +; Input: DX = byte offset +; CL = bit offset in the byte +; CH = 0FFh if ODD, 0 if EVEN +; BP = Y loop counter, ODD in LSB, EVEN in MSB +; +;============================================================================= + +savebkgrndmode4 proc near + + pusha + push es + push ds + + ; set up the segment registers as required + + mov ax,ds + mov es,ax + mov ax,0b800h + mov ds,ax + assume ds:nothing, es:SpcMseSeg + mov si,dx ; start the save. + or ch, ch + je svbkeven ; check the returned carry flag + + ; the image's first scanline is odd + + mov di,offset CGAbackgrnd ; where the background will be saved + mov bx,bp ; set the loop counter up + xor bh,bh ; don't want unwanted mess in MSB + add si,2000h ; odd part of buffer starts at 2000h +svodd1: + mov cx,3 ; copy six bytes + rep movsw ; do the image scanline save + add si,80-6 ; point to the next scanline + dec bx ; decrement the loop counter + jnz svodd1 ; do more scanlines if necessary + + ; save some even scanlines if need be. + + mov si,dx ; offset into CGA buffer + add si, 80 + mov bx,bp ; set up the loop counter + xchg bl,bh ; get the even part of loop counter + xor bh,bh ; trash the top end trash + and bx,bx ; check for a zero loop + jz misseven ; can't have a loop which execs 0 times + mov di,offset CGAbackgrnd+48; where the background will be saved +sveven1: + mov cx,3 ; copy six bytes = 24 pixels + rep movsw ; do the scanline save + add si,80-6 ; point to the next scanline + dec bx ; decrement the loop counter + jnz sveven1 ; do more scanlines if necessary + +misseven: ; jump to here if there are no even scanlines to draw + + jmp short endsavemode4 + +svbkeven: ; the image's first scanline is even + + mov di,offset CGAbackgrnd+48; where the background will be saved + + mov bx,bp ; get the loop counter + xchg bl,bh ; rearrage to get the even part + xor bh,bh ; clear out the trash +sveven2: + mov cx,3 ; copy six bytes + rep movsw ; do the copy + add si,80-6 ; point to the next scanline + dec bx ; decrement the loop counter + jnz sveven2 ; do more scanlines if necessary + + mov si,dx ; offset into CGA buffer + add si,2000h ; odd part of the video buffer + mov di,offset CGAbackgrnd ; where to save the odd scanlines + mov bx,bp ; get the loop counter + xor bh,bh ; clear out the unwanted trash +svodd2: + mov cx,3 ; copy six bytes + rep movsw ; do the copy + add si,80-6 ; point to the next scanline + dec bx ; decrement the loop counter + jnz svodd2 ; do more scanlines if necessary + +endsavemode4: + assume ds:SpcMseSeg, es:nothing + + pop ds + pop es + popa + ret +savebkgrndmode4 endp + +;============================================================================= +; Procedure to restore the area of CGA video buffer into which the pointer +; was drawn. The memory buffer in which this data is stored is arranged +; odd scanlines first, then even. So, the first 48 bytes are the odd scanline +; data. +; +; Input: +; DX = byte offset to top left hand pointer pixel of the pointer +; CL = bit offset in the byte +; CH = 0FFh if ODD, 0 if EVEN +; BP = Y loop counter(ODD in LSB and EVEN in MSB) +; +;============================================================================= + +restorebkgrndmode4 proc near + + pusha + push es + + ; set up the segment registers as required + + mov ax,0b800h + mov es,ax + mov di,dx ; restore background + or ch, ch + je rsbkeven ; check the returned carry flag + + ; the image's first scanline is odd. The CGA buffer is translated + ; so that a scanline (row N) from the even part of the buffer appears + ; on the screen at raster I. The scanline at position N from the + ; odd part of the video buffer maps to screen position I+1. If the + ; 1st. scanline is odd, then this is drawn at raster A and the + ; following algorithm draws the 1st. even row at raster A+1 to + ; compensate for the video buffer arrangement. + + mov si,offset CGAbackgrnd ; where the background is be saved + add di,2000h ; do the odd buffer + + mov bx,bp ; set the loop counter up + xor bh,bh ; clear out the MSB trash +rsodd1: + mov cx,3 ; copy six bytes + rep movsw ; do the restore + add di,80-6 ; point to the next odd scanline + dec bx ; decrement the loop counter + jnz rsodd1 ; restore more even scanlines if needed + + mov bx,bp ; let the loop counter + xchg bl,bh ; get the even part + xor bh,bh ; clear out the MSB trash + and bx,bx ; test for zero even scanlines + jz misseven1rs ; can't have a zero execute loop + mov di,dx ; offset into CGA buffer + add di,80 ; get the odd/even scanlines instep + mov si,offset CGAbackgrnd+48; where the background is be saved +rseven1: + mov cx,3 ; restore six bytes + rep movsw ; do the restore + add di,80-6 ; point to the next even scanline + dec bx ; decrement the loop counter + jnz rseven1 ; restore more even scanlines if needed + +misseven1rs: ; jump to here if there are no even scanlines to be restored. + + jmp short endrestoremode4 + +rsbkeven: ; the image's first scanline is even + + mov si,offset CGAbackgrnd+48; where the background will be saved + + mov bx,bp ; get the loop counter + xchg bl,bh ; get the even part of the loop counter + xor bh,bh ; scrap the MSB trash +rseven2: + mov cx,3 ; restore six bytes + rep movsw ; do the restore + add di,80-6 ; point to the next even scanline + dec bx ; decrement the loop counter + jnz rseven2 ; do more even scanlines if needed + + mov di,dx ; offset into CGA buffer + add di,2000h ; do the odd buffer + mov si,offset CGAbackgrnd ; where to save the odd scanlines + + mov bx,bp ; set the loop counter up + xor bh,bh ; scrap the MSB trash +rsodd2: + mov cx,3 ; restore six bytes + rep movsw ; do the restore + add di,80-6 ; point to the next odd scanline + dec bx ; decrement the loop counter + jnz rsodd2 ; restore more odd scanlines if needed + +endrestoremode4: + assume ds:SpcMseSeg, es:nothing + + pop es + popa + ret +restorebkgrndmode4 endp + +;============================================================================ +; Procedure to draw the pointer image into the video buffer for mode 13h +; VGA graphics. +; +; Input: +; DX = byte offset +; BP = Y loop counter +; CX = X loop counter +; +;============================================================================ + +draw256pointer proc near + pusha + push es + push ds + + mov ax,0a000h ; point to the 256 colour mode video buffer + mov es,ax + mov ax,cs + mov ds,ax + + assume ds:SpcMseSeg, es:nothing + + cld ; write forward through the buffer + ; DX = TLHC pixel offset in the video buffer. + mov di,dx ; point DI at the video buffer location of fun + mov si, offset current_cursor ; we only use this cursor shape + ; because every pixel is on byte + ; boundary. The X counter would + ; take care of X clipping +y_256: + push cx + lodsw ;and mask + mov dx, [si + 48 - 2] ;xor mask + inc si ;we don't need the third byte + xchg al, ah ; byte sequence + xchg dh, dl ; +x_256: + shl ax, 1 ;AND mask bit + sbb bl, bl ; bl = 0FFf if CY, 0 if not CY + and bl, es:[di] ;and the target and save the result + shl dx, 1 ;XOR mask bit + sbb bh, bh ; + xor bl, bh ;xor with the save result + mov es:[di], bl ;update the target + inc di ;next pixel + loop x_256 ;until this scan line is done + pop cx ;recovery X loop counter + add di, 320 ;target address to next scan line + sub di, cx + dec bp ;Y counter + jne y_256 + + pop ds + pop es + popa + ret +draw256pointer endp + +;============================================================================= +; Procedure to save the area of 256 colour mode video buffer into which the +; pointer will be drawn. The memory buffer in which this data is stored is +; arranged odd scanlines first, then even. So, the first 48 bytes are the odd +; scanline data. +; +; Input: +; DX = byte offset +; BP = Y loop counter +; CX = X loop counter +; +;============================================================================= + +savebkgrndmode13 proc near + pusha + push es + push ds + + mov di,offset bkgrnd256 ; point to the area in which backgound + ; data will be saved + mov si,dx ; SOURCE: the video buffer at x,y + + mov ax,0a000h + mov ds,ax + mov ax,cs + mov es,ax + mov bx, cx ;x counter + mov dx, 320 + sub dx, bx + assume ds:nothing, es:SpcMseSeg + cld +save_256_loop: + mov cx, bx + shr cx, 1 + rep movsw + adc cl, 0 + rep movsb + add si, dx ; next scan line offset + dec bp ; until Y counter is done + jne save_256_loop + + pop ds + pop es + + assume es:nothing, ds:SpcMseSeg + + popa + ret +savebkgrndmode13 endp + +;============================================================================= +; Procedure to replace an existing pointer image in the 256 colour video +; buffer with the data that was there previous to the pointer draw operation. +; The data is stored in an internal (to the driver) buffer. +; +; Input: +; DX = byte offset +; BP = Y loop counter +; CX = X loop counter +; +;============================================================================= + +restorebkgrndmode13 proc near + pusha + push es + + mov di,dx ; DESTINATION: in the VRAM + mov ax,0a000h ; point a segment register at video buffer + mov es,ax + + assume es:nothing + mov bx, cx + mov si,offset bkgrnd256 ; where the data is saved + mov dx, 320 + sub dx, bx + + cld ; write forward in memory +restore_256_loop: + mov cx, bx + shr cx, 1 + rep movsw + adc cl, 0 + rep movsb + add di, dx + dec bp + jne restore_256_loop + + pop es + popa + ret +restorebkgrndmode13 endp + +;======================================================================== +; Procedure to determine what the byte offset is, in the current +; VGA buffer for the top left hand corner of the pointer bitmap. +; The X,Y value is modified for hotspot in this routine. X and Y looping +; counters are also returned. +; +; INPUT: CX,DX = pointer x,y coordinates +; OUT : +; carry set if either X or Y is out of screen +; DX = byte offset to top left hand pointer pixel of the pointer +; CX = X counter +; BP = Y counter +;======================================================================== + +detboundmode13 proc near + + push ax + push bx + push ds + + mov ax,cs + mov ds,ax + + assume ds:SpcMseSeg + + + ; do the adjustment in x,y for pointer hotspot + ; modify the raw X,Y values for hotspot + + sub cx,[hotspot] ; adjust the x cartesian coord for hotspot + jns dont_zero_xmode13; if x goes negative, assume zero + xor cx,cx + +dont_zero_xmode13: + + sub dx,[hotspot+2] ; adjust the y cartesian coord for the hotspot + jns dont_zero_ymode13; if y goes negative, assume zero + xor dx,dx + +dont_zero_ymode13: + cmp cx, 320 + jae detboundmode13_exit ; CY is cleared + cmp dx, 200 ; + jae detboundmode13_exit ; CY is cleared + + ; CX and DX are now validated for the following section: buffer + ; offset determination. Note, unlike other video modes, mode 13 + ; provides a direct mapping of the video display to video buffer. + ; in other words; 1 byte represents 1 pixel. From this, it is not + ; necessary to provide byte alignment data. + + mov bx,dx ; save in a base register + shl bx,1 ; create a word table index + mov dx,[mult320LUT+bx] ; do the multiply by 320 + ; add in the offset along the current raster. + + add dx,cx ; cx contains the byte offset from + mov ax,[mode4clipDXLUT + bx]; get Y loop counter from table + add al, ah ; the table has ODD/EVEN counters + cbw + mov bp, ax ; the final Y counter + ; column 0. + mov ax, 320 ; calculate X loop counter + sub ax, cx + cmp ax, 16 ; + jl set_new_x_counter + mov ax, 16 +set_new_x_counter: + mov cx, ax ; X counter + stc ; everything is fine, set CY + ; so we will return CY cleared +detboundmode13_exit: + cmc ; complement the CY + pop ds + pop bx + pop ax + ret + +detboundmode13 endp + + + public SpcMseEnd +SpcMseEnd label byte + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; Installation Code From Here Downwards +; +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +; segment:offset table for redirected mouse functions for real rom version. + +mio_table dw 38 dup(?) + + + + assume cs:SpcMseSeg,ds:nothing,es:nothing + + public InstSpcMse +; +; InstSpcMse - Installs the softpc mouse driver code +; +; Inputs: ds == Resident location of SpcMseSeg +; Outputs: None +; +InstSpcMse proc near + + ;;;;;;;;;;;;;;;;do ret to use old mouse driver;;; ret + + pusha + + ; save old int 10 vector + xor ax,ax + mov es,ax + mov ax,es:[40h] + mov si,offset old_vid_int + mov word ptr ds:[si],ax + mov ax,es:[42h] + mov word ptr ds:[si+2],ax + + mov bx,ds + mov si,offset sysinitgrp:mio_table + push ds + push cs + pop ds + + mov word ptr ds:[si], offset mouse_io + mov word ptr ds:[si+2],bx + +IFDEF MOUSE_VIDEO_BIOS + + mov word ptr ds:[si+4],offset mouse_video_io + mov word ptr ds:[si+6],bx + +ENDIF ; MOUSE_VIDEO_BIOS + + mov word ptr ds:[si+8],offset mouse_int1 + mov word ptr ds:[si+10],bx + mov word ptr ds:[si+12], offset mouse_version + mov word ptr ds:[si+14],bx + mov word ptr ds:[si+16],offset mouse_copyright + mov word ptr ds:[si+18],bx + mov word ptr ds:[si+20],offset video_io + mov word ptr ds:[si+22],bx + mov word ptr ds:[si+24],offset mouse_int2 + mov word ptr ds:[si+26],bx + mov word ptr ds:[si+28],offset entry_point_from_32bit + mov word ptr ds:[si+30],bx + mov word ptr ds:[si+32],offset int33function0 + mov word ptr ds:[si+34],bx + mov word ptr ds:[si+36],offset int33function1 + mov word ptr ds:[si+38],bx + mov word ptr ds:[si+40],offset int33function2 + mov word ptr ds:[si+42],bx + mov word ptr ds:[si+44],offset int33function9 + mov word ptr ds:[si+46],bx + mov word ptr ds:[si+48],offset current_position_x + mov word ptr ds:[si+50],bx + mov word ptr ds:[si+52],offset current_position_y + mov word ptr ds:[si+54],bx + mov word ptr ds:[si+56],offset mouseINB + mov word ptr ds:[si+58],bx + mov word ptr ds:[si+60],offset mouseOUTB + mov word ptr ds:[si+62],bx + mov word ptr ds:[si+64],offset mouseOUTW + mov word ptr ds:[si+66],bx + mov word ptr ds:[si+68],offset VRAMlasttextcelloff + mov word ptr ds:[si+70],bx + mov word ptr ds:[si+72],offset internalCF + mov word ptr ds:[si+74],bx + mov word ptr ds:[si+76],offset function3data + mov word ptr ds:[si+78],bx + mov word ptr ds:[si+80],offset conditional_off + mov word ptr ds:[si+82],bx + pop ds + mov bx, offset sysinitgrp:mio_table + bop 0C8h ; Host mouse installer BOP + +; get the freshly written int 33h vector from IVT +; write the vector segment:offset data to the jump patch + + xor ax,ax + mov es,ax + mov ax,es:[33h*4] + mov bx,es:[(33h*4)+2] + mov si,offset moff + mov word ptr ds:[si],ax + mov word ptr ds:[si+2],bx + add ax,2 ; HLL entry point + mov si,offset loffset + mov word ptr ds:[si],ax + mov word ptr ds:[si+2],bx + +; write the new value to the IVT + call DOCLI + mov bx, offset int33h_vector + mov word ptr es:[33h*4], bx + mov bx, ds + mov word ptr es:[(33h*4)+2], bx + call DOSTI + + popa + ret +InstSpcMse endp + +SpcMseSeg ends + end diff --git a/private/mvdm/softpc.new/bios/sysconf.asm b/private/mvdm/softpc.new/bios/sysconf.asm new file mode 100644 index 000000000..6a5209942 --- /dev/null +++ b/private/mvdm/softpc.new/bios/sysconf.asm @@ -0,0 +1,3972 @@ +page ,160 + title bios system initialization +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- + + include version.inc ; set version build flags + include biosseg.inc ; establish bios segment structure + +lf equ 10 +cr equ 13 +tab equ 9 + +have_install_cmd equ 00000001b ; config.sys has install= commands +has_installed equ 00000010b ; sysinit_base installed. + +default_filenum = 8 + + break macro ; dummy empty macro + endm + + include sysvar.inc + include pdb.inc ; M020 + include syscall.inc + include doscntry.inc + include devsym.inc + include devmark.inc + + include umb.inc + include dossym.inc + include dossvc.inc + include cmdsvc.inc + include softpc.inc + +stacksw equ true ;include switchable hardware stacks + + if ibmjapver +noexec equ true + else +noexec equ false + endif + + + + +; 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. + +Bios_Data segment + extrn multrk_flag:word + extrn keyrd_func:byte + extrn keysts_func:byte +Bios_Data ends + +; end of multi-track definition. + +sysinitseg segment + +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 badstack:byte,badcountrycom:byte + extrn 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 memory_size:word + extrn buffers:word + extrn files:byte,num_cds:byte + extrn dosinfo: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 + extrn install_flag:word + extrn badorder:byte + extrn errorcmd:byte + extrn linecount:word + extrn showcount:byte + extrn buffer_linenum:word + extrn h_buffers:word + extrn badparm:byte + extrn configmsgflag:word + extrn org_count:word + extrn multi_pass_id:byte + + 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 + extrn setdevmark:near + + extrn print:near,organize:near,newline:near + extrn parseline:near + extrn badload:near,calldev:near,prnerr:near + + extrn runhigh:byte + extrn IsXMSLoaded:near + + extrn TryToMovDOSHi:near + +ifdef DBCS + extrn testkanj:near +endif + + extrn bEchoConfig:byte ; NTVDM flag off\on echo of cfg processing + + 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 + +DOS_FLAG_OFFSET equ 86h + + extrn stack_count:word + extrn stack_size:word + extrn stack_addr:dword + + endif + + public doconf + public getchr + public multi_pass + public AllocUMB + public AllocUMBLow ; NTVDM + public multdeviceflag +multdeviceflag db 0 + public devmark_addr +devmark_addr dw ? ;segment address for devmark. + public setdevmarkflag +setdevmarkflag db 0 ;flag used for devmark + +ems_stub_installed db 0 + +IFDEF DONT_LOAD_OS2_DD ; M045 + +Os2ChkBuf DD 0 ; Tmp read buffer + +ENDIF ; M045 + +badparm_ptr label dword +badparm_off dw 0 +badparm_seg dw 0 + +;****************************************************************************** +;take care of config.sys file. +;system parser data and code. +;****************************************************************************** + +;******************************************************************* +; parser options set for msbio 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 + + + include parse.asm ;together with psdata.inc + +;control block definitions for parser. +;--------------------------------------------------- +; buffer = [n | n,m] {/e} + +p_parms struc + dw ? + db 1 ; an extra delimiter list + db 1 ; length is 1 + db ';' ; delimiter +p_parms ends + +p_pos struc + dw ? ; numeric value?? + dw ? ; function + dw ? ; result value buffer + +; note: by defining result_val before this structure, we could remove +; the "result_val" from every structure invocation + + dw ? ; value list + db 0 ; no switches/keywords +p_pos ends + +p_range struc + db 1 ; range definition + db 1 ; 1 definition of range + db 1 ; item tag for this range + dd ? ; numeric min + dd ? ; numeric max +p_range ends + +buf_parms p_parms <buf_parmsx> +buf_parmsx dw 201h,buf_pos1,buf_pos2 ; min 1, max 2 positionals + db 1 ; one switch + dw sw_x_ctrl + db 0 ; no keywords + +buf_pos1 p_pos <8000h,0,result_val,buf_range_1> ; numeric +buf_range_1 p_range <,,,1,99> ; M050 +buf_pos2 p_pos <8001h,0,result_val,buf_range_2> ; optional num. +buf_range_2 p_range <,,,0,8> + +sw_x_ctrl p_pos <0,0,result_val,noval,1> ; followed by one switch +switch_x db '/X',0 ; M016 + +p_buffers dw 0 ; local variables +p_h_buffers dw 0 +p_buffer_slash_x db 0 + +;common definitions ------------ +noval db 0 + +result_val label byte + db ? ; type returned + db ? ; item tag returned + dw ? ; es:offset of the switch defined +rv_byte label byte +rv_dword dd ? ; value if number,or seg:offset to string. +;------------------------------- + +; break = [ on | off ] + +brk_parms p_parms <brk_parmsx> + +brk_parmsx dw 101h,brk_pos ; min,max = 1 positional + db 0 ; no switches + db 0 ; no keywords + +brk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string + +on_off_string label byte + db 3 ; signals that there is a string choice + db 0 ; no range definition + db 0 ; no numeric values choice + db 2 ; 2 strings for choice + db 1 ; the 1st string tag + dw on_string + db 2 ; the 2nd string tag + dw off_string + +on_string db "ON",0 +off_string db "OFF",0 + +p_ctrl_break db 0 ; local variable + +;-------------------------------- + +; country = n {m {path}} +; or +; country = n,,path + +cntry_parms p_parms <cntry_parmsx> + +cntry_parmsx dw 301h,cntry_pos1,cntry_pos2,cntry_pos3 ; min 1, max 3 pos. + db 0 ; no switches + db 0 ; no keywords + +cntry_pos1 p_pos <8000h,0,result_val,cc_range> ; numeric value +cc_range p_range <,,,1,999> +cntry_pos2 p_pos <8001h,0,result_val,cc_range> ; optional num. +cntry_pos3 p_pos <201h,0,result_val,noval> ; optional filespec + +p_cntry_code dw 0 ; local variable +p_code_page dw 0 ; local variable + +;-------------------------------- + +; files = n + +files_parms p_parms <files_parmsx> + +files_parmsx dw 101h,files_pos ; min,max 1 positional + db 0 ; no switches + db 0 ; no keywords + +files_pos p_pos <8000h,0,result_val,files_range,0> ; numeric value +files_range p_range <,,,8,255> + +p_files db 0 ; local variable + +;------------------------------- + +; fcbs = n,m + +fcbs_parms p_parms <fcbs_parmsx> + +fcbs_parmsx dw 201h,fcbs_pos_1,fcbs_pos_2 ; min,max = 2 positional + db 0 ; no switches + db 0 ; no keywords + +fcbs_pos_1 p_pos <8000h,0,result_val,fcbs_range> ; numeric value +fcbs_range p_range <,,,1,255> +fcbs_pos_2 p_pos <8000h,0,result_val,fcbs_keep_range> ; numeric value +fcbs_keep_range p_range <,,,0,255> + +p_fcbs db 0 ; local variable +p_keep db 0 ; local variable + +;------------------------------- +; lastdrive = x + +ldrv_parms p_parms <ldrv_parmsx> + +ldrv_parmsx dw 101h,ldrv_pos ; min,max = 1 positional + db 0 ; no switches + db 0 ; no keywords + +ldrv_pos p_pos <110h,10h,result_val,noval> ; drive only, ignore colon + ; remove colon at end +p_ldrv db 0 ; local variable + +;------------------------------- + +; stacks = n,m + +stks_parms p_parms <stks_parmsx> + +stks_parmsx dw 202h,stks_pos_1,stks_pos_2 ; min,max = 2 positionals + db 0 ; no switches + db 0 ; no keywords + +stks_pos_1 p_pos <8000h,0,result_val,stks_range> ; numeric value +stks_range p_range <,,,0,64> +stks_pos_2 p_pos <8000h,0,result_val,stk_size_range> ; numeric value +stk_size_range p_range <,,,0,512> + +p_stack_count dw 0 ; local variable +p_stack_size dw 0 ; local variable + +;------------------------------- + +; multitrack = [ on | off ] + +mtrk_parms p_parms <mtrk_parmsx> + +mtrk_parmsx dw 101h,mtrk_pos ; min,max = 1 positional + db 0 ; no switches + db 0 ; no keywords + +mtrk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string + +p_mtrk db 0 ; local variable + +;------------------------------- +; switches=/k + +swit_parms p_parms <swit_parmsx> + +swit_parmsx dw 0 ; no positionals + db 3 ; 2 switches for now. M059 M063 + dw swit_k_ctrl ; /k control + dw swit_t_ctrl ; /t control M059 + dw swit_w_ctrl ; /w control M063 + db 0 ; no keywords + +swit_k_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows +swit_k db '/K',0 +swit_t_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M059 +swit_t db '/T',0 ; M059 +swit_w_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M063 +swit_w db '/W',0 ; M063 + +p_swit_k db 0 ; local variable +p_swit_t db 0 ; local variable M059 +p_swit_w db 0 ; local variable M063 + +;------------------------------- + +; DOS = [ high | low ] + +dos_parms p_parms <dos_parmsx> + +dos_parmsx db 1 ; min parameters + db 2 ; max parameters + dw dos_pos ; + dw dos_pos ; + db 0 ; no switches + db 0 ; no keywords + +dos_pos p_pos <2000h,0,result_val,dos_strings> ; simple string + p_pos <2000h,0,result_val,dos_strings> ; simple string + +dos_strings label byte + db 3 ; signals that there is a string choice + db 0 ; no range definition + db 0 ; no numeric values choice + db 4 ; 4 strings for choice + db 1 ; the 1st string tag + dw hi_string + db 2 ; the 2nd string tag + dw lo_string + db 3 + dw umb_string + db 4 + dw noumb_string + +hi_string db "HIGH",0 +lo_string db "LOW",0 +umb_string db "UMB",0 +noumb_string db "NOUMB",0 + +p_dos_hi db 0 ; local variable + ; BUGBUG : I dont know whether PARSER uses + ; this variable or not + + + +;****************************************************************************** + + public DevEntry + +DevSize dw ? ; size of the device driver being loaded(paras) +DevLoadAddr dw ? ; Mem addr where the device driver is 2 b loaded +DevLoadEnd dw ? ; MaxAddr to which device can be loaded +DevEntry dd ? ; Entry point to the device driver +DevBrkAddr dd ? ; Break address of the device driver +; +DevUMB db 0 ; byte indicating whether to load DDs in UMBs +DevUMBAddr dw 0 ; cuurent UMB used fro loading devices (paras) +DevUMBSize dw 0 ; Size of the current UMB being used (paras) +DevUMBFree dw 0 ; Start of free are in the current UMB (paras) +; +DevXMSAddr dd ? +; +DevExecAddr dw ? ; Device load address parameter to Exec call +DevExecReloc dw ? ; Device load relocation factor +; +DeviceHi db 0 ; Flag indicating whther the current device + ; is being loaded into UMB +DevSizeOption dw ? ; SIZE= option +; +Int12Lied db 0 ; did we trap int 12 ? +OldInt12Mem dw ? ; value in 40:13h (int 12 ram) +ThreeComName db 'PROTMAN$' ; 3Com Device name +; +FirstUMBLinked db 0 +DevDOSData dw ? ; segment of DOS Data +DevCmdLine dd ? ; Current Command line +DevSavedDelim db ? ; The delimiter which was replaced with null + ; to use the file name in the command line +; +;---------------------------------------------------------------------------- +; +; procedure : doconf +; +; Config file is parsed intitially with this routine. For the +; Subsequent passes 'multi_pass' entry is used . +; +;---------------------------------------------------------------------------- +; +doconf proc near + 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 + jnc noprob ; brif opened okay + mov multi_pass_id,11 ; set it to unreasonable number + ret +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,[confbot] ;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. + + push ax + push di + push cx + 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 + mov al,lf + stosb + sub di,dx ; difference moved + mov count,di ; new count + + pop cx + pop di + pop ax + + 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: + ret +; +;---------------------------------------------------------------------------- +; +; entry : multi_pass +; +; called to execute device=,install= commands +; +;---------------------------------------------------------------------------- +; + +multi_pass: + push cs + pop ds + + cmp multi_pass_id,10 + jae endconv ; do nothing. just return. + + push confbot + pop es ; es -> confbot + + mov si,org_count + mov count,si ; set count + xor si,si + mov chrptr,si ; reset chrptr,linecount + mov linecount,si + call getchr + jmp short conflp + +getcom: + call organize ;organize the file + call getchr + +conflp: jc endconv + +;*** call reset_dos_version ; still need to reset version even ibmdos handles this through +;*** ; function 4bh call,since ibmdos does not know when load/overlay call finishes. + + inc linecount ; increase linecount. + mov multdeviceflag,0 ; reset multdeviceflag. + mov setdevmarkflag,0 ; reset setdevmarkflag. + cmp al,lf ; linefeed? + je blank_line ; then ignore this line. + + mov ah,al + call getchr + jnc tryi + + cmp multi_pass_id,2 + jae endconv ;do not show badop again for multi_pass. + jmp badop + +coff: push cs + pop ds + call newline + jmp conflp + +blank_line: + call getchr + jmp conflp + +coff_p: + push cs + pop ds + + +;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 ; the initial pass for DOS=HI + je multi_try_doshi + + cmp multi_pass_id,2 ; the second pass was for ifs= + je coff ; now it is NOPs + ; This pass can be made use of if + ; we want do some config.sys process + ; after device drivers are loaded + ; and before install= commands + ; are processed + + cmp multi_pass_id,3 ; the third pass for install= ? + je multi_try_i + cmp ah, 'H' + je coff + cmp ah, 'E' + je coff + cmp ah,'I' ; install= command? + jne tryb ; the first pass is for normal operation. + or install_flag,have_install_cmd ; set the flag + jmp coff ; and handles the next command + +multi_try_i: + cmp ah,'I' ; install= command? + jne multi_pass_filter ; no. ignore this. + call do_install_exec ;install it. + jmp coff ;to handle next install= command. + +multi_pass_filter: + cmp ah,'Y' ; comment? + je multi_pass_adjust + cmp ah,'Z' ; bad command? + je multi_pass_adjust + cmp ah,'0' ; rem? + jne coff ; ignore the rest of the commands. + +multi_pass_adjust: ; these commands need to + dec chrptr ; adjust chrptr,count + inc count ; for newline proc. + +multi_pass_coff: + jmp coff ; to handle next install= commands. + + + +;---------------------------------------------------------------------------- +; DOS=HIGH/LOW command +; +; EchoConfig command turns on con echo for config processing +; NTVDM 14-Aug-1992 Jonle +;---------------------------------------------------------------------------- +; +multi_try_doshi: + cmp ah, 'H' + je it_is_h + cmp ah, 'E' + jne multi_pass_filter + + mov cs:bEchoConfig, ah ; init console + CMDSVC SVC_CMDINITCONSOLE + jmp coff + + +it_is_h: ; M003 - removed initing DevUMB + ; & runhigh + mov di,offset dos_parms + xor cx,cx + mov dx,cx +h_do_parse: + call sysinit_parse + jnc h_parse_ok ; parse error +h_badparm: + call badparm_p ; show message and end the serach loop. + jmp short h_end + +h_parse_ok: + cmp ax,$p_rc_eol ; end of line? + jz h_end ; then end the $endloop + call ProcDOS + jmp short h_do_parse +h_end: + jmp coff + + +;------------------------------------------------------------------------------ +; 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' + jnz tryc + + ; NTVDM - buffers command is ignored + ; 15-Aug-1992 Jonle + jmp coff + +if 0 + mov p_buffer_slash_x,0 + mov di,offset buf_parms + xor cx,cx + mov dx,cx + +do7: + call sysinit_parse + jnc if7 ; parse error, + call badparm_p ; and show messages and end the search loop. + jmp short sr7 + +if7: + cmp ax,$p_rc_eol ; end of line? + jz en7 ; then jmp to $endloop for semantic check + cmp result_val.$p_synonym_ptr,offset switch_x + jnz if11 + +; mov p_buffer_slash_x,1 ; set the flag M016 + jmp short en11 + +if11: + mov ax,word ptr result_val.$p_picked_val + cmp cx,1 + jnz if13 + + mov p_buffers,ax + jmp short en11 + +if13: + mov p_h_buffers,ax +en11: + jmp do7 + +en7: + cmp p_buffers,99 + jbe if18 +; cmp p_buffer_slash_x,0 ; M016 +; jnz if18 + + call badparm_p + mov p_h_buffers,0 + jmp short sr7 + +if18: + mov ax,p_buffers ; we don't have any problem. + mov buffers,ax ; now,let's set it really. + + mov ax,p_h_buffers + mov h_buffers,ax + +; mov al,p_buffer_slash_x ; M016 +; mov buffer_slash_x,al + + mov ax,linecount + mov buffer_linenum,ax ; save the line number for the future use. + +sr7: + jmp coff +endif + + +;------------------------------------------------------------------------------ +; 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' + jnz trym + mov di,offset brk_parms + xor cx,cx + mov dx,cx +do22: + call sysinit_parse + jnc if22 ; parse error + call badparm_p ; show message and end the serach loop. + jmp short sr22 + +if22: + cmp ax,$p_rc_eol ; end of line? + jz en22 ; then end the $endloop + cmp result_val.$p_item_tag,1 + jnz if26 + + mov p_ctrl_break,1 ; turn it on + jmp short en26 + +if26: + mov p_ctrl_break,0 ; turn it off +en26: + jmp short do22 ; we actually set the ctrl break + +en22: + mov ah,set_ctrl_c_trapping ; if we don't have any parse error. + mov al,1 + mov dl,p_ctrl_break + int 21h +sr22: + 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: + cmp ah,'M' + jnz tryu + + mov di,offset mtrk_parms + xor cx,cx + mov dx,cx +do31: + call sysinit_parse + jnc if31 ; parse error + call badparm_p ; show message and end the serach loop. + jmp short sr31 +if31: + cmp ax,$p_rc_eol ; end of line? + jz en31 ; then end the $endloop + + cmp result_val.$p_item_tag,1 + jnz if35 + + mov p_mtrk,1 ; turn it on temporarily. + jmp short en35 + +if35: + mov p_mtrk,0 ; turn it off temporarily. +en35: + jmp short do31 ; we actually set the multrk_flag here + +en31: + push ds + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + + cmp p_mtrk,0 + jnz if39 + + mov multrk_flag,multrk_off2 ; 0001h + jmp short en39 + +if39: + mov multrk_flag,multrk_on ; 8000h +en39: + pop ds + assume ds:sysinitseg +sr31: + jmp coff + + +; +;----------------------------------------------------------------------------- +; devicehigh command +;----------------------------------------------------------------------------- +; + assume ds:nothing +tryu: + cmp ah, 'U' + jne tryd + mov badparm_off, si ; stash it there in case of an error + mov badparm_seg, es + call ParseSize ; process the size= option + jnc @f + call badparm_p + jmp coff +@@: + push si + push es +@@: + mov al, es:[si] + cmp al, cr + je @f + cmp al, lf + je @f + call delim + jz @f + inc si + jmp @b +@@: + mov DevSavedDelim, al ; Save the delimiter before replacing + ; it with null + mov byte ptr es:[si], 0 + pop es + pop si + + mov DeviceHi, 0 + cmp DevUMB, 0 ; do we support UMBs + je LoadDevice ; no, we don't + mov DeviceHi, 1 + jmp short LoadDevice +; +;------------------------------------------------------------------------------ +; device command +;------------------------------------------------------------------------------ + + assume ds:nothing +tryd: + cmp ah,'D' + jz gotd + jmp tryq +gotd: + mov DeviceHi, 0 ; not to be loaded in UMB ;M007 + mov DevSizeOption, 0 + mov DevSavedDelim, ' ' ; In case of DEVICE= the null has to + ; be replaced with a ' ' + +LoadDevice: + mov bx,cs ;device= or devicehigh= command. + mov ds,bx + + mov word ptr [bpb_addr],si ; pass the command line to the dvice + mov word ptr [bpb_addr+2],es + + mov word ptr DevCmdLine, si ; save it for ourself + mov word ptr DevCmdLine+2, es + + call round + + call SizeDevice + jc BadFile + + call InitDevLoad + + mov ax, DevLoadAddr + add ax, DevSize + jc NoMem + cmp DevLoadEnd, ax + jae LoadDev + +NoMem: + jmp mem_err + +BadFile: + cmp byte ptr es:[si], cr + jne @f + jmp badop +@@: + call badload + jmp coff + +LoadDev: + 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 + + call ExecDev ; load device driver using exec call + + endif + +badldreset: + push ds + pop es ;es:si back to config.sys + push cs + pop ds ;ds back to sysinit + jc BadFile +goodld: + push es + push si ; ??? + + call RemoveNull + + push es + push si + + push cs + pop es + + +;NTVDM: block device drivers are not supported. +; Putup user warning popup for unsupported device driver +; 29-Sep-1992 Jonle +; + push ds + push si + lds si, DevEntry ; peek the header attribute + test word ptr ds:[si.sdevatt],devtyp ; IS block device driver? + pop si + pop ds + jnz got_device_com_cont ; no! + + pop si ;clear the stack + pop es + + mov ax, NOSUPPORT_DRIVER + BOP BOP_NOSUPPORT + jmp short erase_dev_do + +got_device_com_cont: + + call LieInt12Mem + call UpdatePDB ; update the PSP:2 value M020 + + cmp cs:multdeviceflag, 0 ; Pass limit only for the 1st device + ; driver in the file ; M027 + jne skip_pass_limit ; ; M027 + + mov word ptr break_addr, 0 ; pass the limit to the DD + mov bx, DevLoadEnd + mov word ptr break_addr+2, bx +skip_pass_limit: ; M027 + mov bx,sdevstrat + call calldev ; calldev (sdevstrat); + mov bx,sdevint + call calldev ; calldev (sdevint); + + call TrueInt12Mem + + mov ax, word ptr break_addr ; move break addr from the req packet + mov word ptr DevBrkAddr, ax + mov ax, word ptr break_addr+2 + mov word ptr DevBrkAddr+2, ax + + assume ds:nothing + + cmp DevUMB, 0 + jz @f + call AllocUMB +@@: + +; +;------ If we are waiting to be moved into hma lets try it now !!! +; + cmp runhigh, 0ffh + jne @f + + call TryToMovDOSHi ; move DOS into HMA if reqd +@@: + + pop si + pop ds + mov byte ptr [si],0 ; *p = 0; + + push cs + pop ds + + jmp short was_device_com + + +erase_dev_do: ; modified to show message "error in config.sys..." + pop si + pop es + + push cs + pop ds + +; test [setdevmarkflag],setbrkdone ;if already set_break is done, +; jnz skip1_resetmemhi ; then do not +; dec [memhi] ;adjust memhi by a paragrah of devmark. + +skip1_resetmemhi: + cmp configmsgflag,0 + je no_error_line_msg + + call error_line ; no "error in config.sys" msg for device driver. dcr d493 + mov configmsgflag,0 ;set the default value again. + +no_error_line_msg: + jmp coff +; +;---------------------------------------------------------------------------- +; +was_device_com: + mov ax,word ptr [DevBrkAddr+2] + cmp ax,DevLoadEnd + jbe breakok + + pop si + pop es + jmp BadFile + +breakok: + lds si,DevEntry ;ds:si points to header + les di,cs:[dosinfo] ;es:di point to dos info + mov ax,ds:[si.sdevatt] ;ax Dev attributes +; +;------ lets deal with character devices, +; NTVDM: removed check for block drivers, jonle +; +ischardev: + or cs:[setdevmarkflag],for_devmark + call DevSetBreak ; go ahead and alloc mem for device + jc erase_dev_do ;device driver's init routine failed. + + test ax,iscin ;is it a console in? + jz tryclk + + mov word ptr es:[di.sysi_con],si + mov word ptr es:[di.sysi_con+2],ds + +tryclk: test ax,isclock ;is it a clock device? + jz linkit + + mov word ptr es:[di+sysi_clock],si + mov word ptr es:[di+sysi_clock+2],ds + +linkit: + + mov cx,word ptr es:[di.sysi_dev] ;dx:cx = head of list + mov dx,word ptr es:[di.sysi_dev+2] + + 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:[DevEntry],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 ; possibly multiple device driver. + call DevBreak ; M009 + jmp goodld ; otherwise pretend we loaded it in + +coffj3: mov cs:multdeviceflag,0 ; reset the flag + call DevBreak + jmp coff + +bad_bpb_size_sector: + pop si + pop es + mov dx,offset badsiz_pre + mov bx,offset crlfm + call prnerr + +; test [setdevmarkflag],setbrkdone ;if already set_break is done, +; jnz skip2_resetmemhi ; then do not +; dec [memhi] ;adjust memhi by a paragrah of devmark. + +skip2_resetmemhi: + jmp coff + + +;------------------------------------------------------------------------------ +; country command +; 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: + + mov cntry_drv,0 ; reset the drive,path to default value. + mov p_code_page,0 + mov di,offset cntry_parms + xor cx,cx + mov dx,cx +do52: + call sysinit_parse + jnc if52 ; parse error,check error code and + + call cntry_error ; show message and end the search loop. + mov p_cntry_code,-1 ; signals that parse error. + jmp short sr52 + +if52: + cmp ax,$p_rc_eol ; end of line? + jz sr52 ; then end the search loop + + cmp result_val.$p_type,$p_number ; numeric? + jnz if56 + + mov ax,word ptr result_val.$p_picked_val + cmp cx,1 + jnz if57 + + mov p_cntry_code,ax + jmp short en57 + +if57: + mov p_code_page,ax +en57: + jmp short en56 ; path entered + +if56: + push ds + push es + push si + push di + + push cs + pop es + + lds si,rv_dword ; move the path to known place. + mov di,offset cntry_drv + call move_asciiz + + pop di + pop si + pop es + pop ds + +en56: + jmp do52 + +sr52: + cmp p_cntry_code,-1 ; had a parse error? + jne tryq_open + jmp coff + +tryqbad: ;"invalid country code or code page" + stc + mov dx,offset badcountry + jmp tryqchkerr + +tryq_open: + cmp cntry_drv,0 + je tryq_def + mov dx,offset cntry_drv + jmp short tryq_openit + +tryq_def: + mov dx,offset cntry_root +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 + mov dx,cs:p_code_page ; now,ax=country id,bx=filehandle + mov cx,cs:[memhi] + add cx,384 ; need 6k buffer to handle country.sys + ; M023 + 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 + pop es + cmp cs:cntry_drv,0 ;is the default file used? + je tryqdefbad + + mov si,offset cntry_drv + jmp short tryqbadload + +tryqdefbad: ;default file has been used. + 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 + + call print ;else show error message + call error_line + +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 + jnz if64 + mov dx,offset badcountry ;"invalid country code or code page" + jmp short en64 + +if64: + mov dx,offset badcountrycom ;"error in contry command" +en64: + call 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 + + mov di,offset files_parms + xor cx,cx + mov dx,cx + +do67: + call sysinit_parse + jnc if67 ; parse error + call badparm_p ; and show messages and end the search loop. + jmp short sr67 + +if67: + cmp ax,$p_rc_eol ; end of line? + jz en67 ; then end the $endloop + mov al,byte ptr result_val.$p_picked_val + mov p_files,al ; save it temporarily + jmp short do67 + +en67: + mov al,p_files + SVC SVC_DEMWOWFILES ; For WOW VDM Set the file= to max. + mov files,al ; no error. really set the value now. + +sr67: + 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 + jmp coff + +;NTVDM Ignore the lastdrive command. Dos will figure this from the host OS. +; 17-Aug-1992 Jonle +if 0 + + mov di,offset ldrv_parms + xor cx,cx + mov dx,cx + +do73: + call sysinit_parse + jnc if73 ; parse error + call badparm_p ; and show messages and end the search loop. + jmp short sr73 + +if73: + cmp ax,$p_rc_eol ; end of line? + jz en73 ; then end the $endloop + mov al,rv_byte ; pick up the drive number + mov p_ldrv,al ; save it temporarily + jmp do73 + +en73: + mov al,p_ldrv + mov num_cds,al ; no error. really set the value now. +sr73: + jmp coff +endif + + +;-------------------------------------------------------------------------- +; setting drive parameters +;-------------------------------------------------------------------------- + +tryp: + cmp ah,'P' + jnz tryk + jmp coff + +; sudeepb 04-Mar-1991 : Ignoring DRIVEPARM command +; call parseline +; jc trypbad +; +; call setparms +; call 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 + +do_tryk: + mov di,offset stks_parms + xor cx,cx + mov dx,cx + +do79: + call sysinit_parse + jnc if79 ; parse error + + mov dx,offset badstack ; "invalid stack parameter" + call print ; and show messages and end the search loop. + call error_line + jmp sr79 + +if79: + cmp ax,$p_rc_eol ; end of line? + jz en79 ; then end the $endloop + + mov ax,word ptr result_val.$p_picked_val + cmp cx,1 + jnz if83 + + mov p_stack_count,ax + jmp short en83 + +if83: + mov p_stack_size,ax +en83: + jmp do79 + +en79: + cmp p_stack_count,0 + jz if87 + + cmp p_stack_count,mincount + jb ll88 + cmp p_stack_size,minsize + jnb if88 + +ll88: + mov p_stack_count,-1 ; invalid +if88: + jmp short en87 + +if87: + cmp p_stack_size,0 + jz en87 + mov p_stack_count,-1 ; invalid +en87: + cmp p_stack_count,-1 ; invalid? + jnz if94 + + mov stack_count,defaultcount ;reset to default value. + mov stack_size,defaultsize + mov word ptr stack_addr,0 + + mov dx,offset badstack + call print + call error_line + jmp short sr79 + +if94: + mov ax,p_stack_count + mov stack_count,ax + mov ax,p_stack_size + mov stack_size,ax + mov word ptr stack_addr,-1 ; stacks= been accepted. +sr79: + jmp coff + + endif + +;------------------------------------------------------------------------ +; 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 +; push di +; mov di,offset commnd +; SVC SVC_SETSHELLNAME +; pop di + + 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 + + mov di,offset fcbs_parms + xor cx,cx + mov dx,cx + +do98: + call sysinit_parse + jnc if98 ; parse error + call badparm_p ; and show messages and end the search loop. + jmp short sr98 + +if98: + cmp ax,$p_rc_eol ; end of line? + jz en98 ; then end the $endloop + + mov al,byte ptr result_val.$p_picked_val + cmp cx,1 ; the first positional? + jnz if102 + mov p_fcbs,al + jmp short en102 + +if102: + mov p_keep,al +en102: + jmp do98 + +en98: + mov al,p_fcbs ; M017 + mov fcbs,al ; M017 + mov keep,0 ; M017 +sr98: + jmp coff + +;------------------------------------------------------------------------- +; comment= do nothing. just decrese chrptr,and increase count for correct +; line number +;------------------------------------------------------------------------- + +tryy: + cmp ah,'Y' + jne try0 + +donothing: + dec chrptr + inc count + jmp coff + +;------------------------------------------------------------------------ +; rem command +;------------------------------------------------------------------------ + +try0: ;do nothing with this line. + cmp ah,'0' + je donothing + +;----------------------------------------------------------------------- +; 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' ;switches= command entered? + je do_try1 + jmp tryt +do_try1: + mov di,offset swit_parms + xor cx,cx + mov dx,cx + +do110: + call sysinit_parse + jnc if110 ; parse error + call badparm_p ; and show messages and end the search loop. + jmp short sr110 + +if110: + cmp ax,$p_rc_eol ; end of line? + jz en110 ; then jmp to $endloop for semantic check + + cmp result_val.$p_synonym_ptr,offset swit_k + jnz if115 ; ;M059 + mov p_swit_k,1 ; set the flag + jmp do110 +if115: ;M059 + cmp result_val.$p_synonym_ptr, offset swit_t ;M059 + jne if116 ;M059 M063 + mov p_swit_t, 1 ;M059 + jmp do110 ;M059 +if116: + cmp result_val.$p_synonym_ptr, offset swit_w ;M063 + jne do110 ;M063 + mov p_swit_w, 1 ;M063 + jmp do110 ;M063 +en110: + cmp p_swit_k,1 ;if /k entered, + + push ds + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + jnz if117 + mov keyrd_func,0 ;use the conventional keyboard functions + mov keysts_func,1 +if117: +; mov al, p_swit_t ;M059 +; mov t_switch, al ;M059 + + cmp p_swit_w, 0 ;M063 + je skip_dos_flag ;M063 + push es + push bx + mov ah, GET_IN_VARS ;M063 + int 21h ;M063 + or byte ptr es:[DOS_FLAG_OFFSET], SUPPRESS_WINA20 ;M063 + pop bx + pop es +skip_dos_flag: ;M063 + pop ds + assume ds:sysinitseg + +sr110: + jmp coff + +;------------------------------------------------------------------------ +; NTCMDPROMPT command. This command forces SCS functionality to use +; cmd.exe prompt rather than command.com's prompt on shelling out +; and on finding a TSR. +;------------------------------------------------------------------------ +tryt: + cmp ah,'T' + je tryt_5 + jmp short tryo + +tryt_5: + push si + push bp + xor ax,ax + mov bp,ax + mov si,ax + mov al,4 + mov ah,setdpb + int 21h + pop bp + pop si + jmp coff + +;------------------------------------------------------------------------ +; DOSONLY command. This command forces only DOS binaries to run from +; command.com prompt. non_dos binaries will putup the stub message +; of unable to run it under DOS. +;------------------------------------------------------------------------ +tryo: + cmp ah,'O' + je tryo_5 + jmp short tryz + +tryo_5: + push si + push bp + xor ax,ax + mov bp,ax + mov si,ax + mov al,6 + mov ah,setdpb + int 21h + pop bp + pop si + jmp coff + +;------------------------------------------------------------------------ +; bogus command +;------------------------------------------------------------------------ + +tryz: + cmp ah,0ffh + je tryff + + dec chrptr + inc count + jmp short badop + +;------------------------------------------------------------------------ +; null command +;------------------------------------------------------------------------ + +tryff: ;skip this command. + jmp donothing + +doconf endp + +;------------------------------------------------------------------------------ + +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 ;save the pointer to the parm + mov cs:badparm_off,si ; we are about to parse for badparm msg. + mov dx,0 + call sysparse + cmp ax,$p_no_error ;no error + +;**cas note: when zero true after cmp, carry clear + + jz ll4 + cmp ax,$p_rc_eol ;or the end of line? + jnz if4 + +ll4: + clc + jmp short en4 + +if4: + stc +en4: + pop ds + pop es + ret +sysinit_parse endp + +; +;---------------------------------------------------------------------------- +; +; procedure : badop_p +; +; same thing as badop,but will make sure to set ds register back +; to sysinitseg and return back to the caller. +; +;---------------------------------------------------------------------------- +; +badop_p proc near + + + push cs + pop ds ;set ds to configsys seg. + mov dx,offset badopm + call print + call error_line + ret + +badop_p endp +; +;---------------------------------------------------------------------------- +; +; label : badop +; +;---------------------------------------------------------------------------- +; +badop: mov dx,offset badopm ;want to print command error "unrecognized command..." + call print + call error_line ;show "error in config.sys ..." . + jmp coff + + +; +;---------------------------------------------------------------------------- +; +; procedure : badparm_p +; +; show "bad command or parameters - xxxxxx" +; in badparm_seg,badparm_off -> xxxxx +; +;---------------------------------------------------------------------------- +; +badparm_p proc near + + + push ds + push dx + push si + + push cs + pop ds + + mov dx,offset badparm + call print ;"bad command or parameters - " + lds si,badparm_ptr + +; print "xxxx" until cr. + +do1: + mov dl,byte ptr [si] ; get next character + cmp dl,cr ; is a carriage return? + jz en1 ; exit loop if so + + mov ah,std_con_output ; function 2 + int 21h ; display character + inc si ; next character + jmp do1 +en1: + push cs + pop ds + + mov dx,offset crlfm + call print + call error_line + + pop si + pop dx + pop ds +badparmp_ret: + ret +badparm_p endp + +; +;---------------------------------------------------------------------------- +; +; procedure : getchr +; +;---------------------------------------------------------------------------- +; +getchr proc near + push cx + mov cx,count + jcxz nochar + + mov si,chrptr + mov al,es:[si] + dec count + inc chrptr + clc +get_ret: + pop cx + ret + +nochar: stc + jmp short get_ret +getchr endp + +; +;---------------------------------------------------------------------------- +; +; procedure : incorrect_order +; +; show "incorrect order in config.sys ..." message. +; +;---------------------------------------------------------------------------- +; + +incorrect_order proc near + + mov dx,offset badorder + call print + call showlinenum + ret + +incorrect_order endp + +; +;---------------------------------------------------------------------------- +; +; procedure : error_line +; +; show "error in config.sys ..." message. +; +;---------------------------------------------------------------------------- +; + public error_line +error_line proc near + + + push cs + pop ds + mov dx,offset errorcmd + call print + call showlinenum + ret + +error_line endp + +; +;---------------------------------------------------------------------------- +; +; procedure : showlinenum +; +; 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. +; +;---------------------------------------------------------------------------- +; +showlinenum proc near + + + push es + push ds + push di + + push cs + pop es ; es=cs + + push cs + pop ds + + mov di,offset showcount+4 ; di -> the least significant decimal field. + mov cx,10 ; decimal devide factor + mov ax,cs:linecount + +sln_loop: + cmp ax,10 ; < 10? + jb sln_last + + xor dx,dx + div cx + or dl,30h ; add "0" (= 30h) to make it an ascii. + mov [di],dl + dec di + jmp sln_loop + +sln_last: + or al,30h + mov [di],al + mov dx,di + call print ; show it. + pop di + pop ds + pop es + ret +showlinenum endp + +comment ^ +set_devmark proc near +;*************************************************************************** +; 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 + push si + push es + push di + + mov di,cs:[memhi] + mov ds,di + assume ds:nothing + mov [devmark_addr],di ; save the devmark address for the future. + mov ds:[devmark_id],devmark_device ; 'd' + inc di + mov ds:[devmark_seg],di + xor al,al + push si + pop di ; now es:si = es:di = [path]filename,0 + mov cx,128 ; maximum 128 char + repnz scasb ; find 0 + dec di ; now es:di-> 0 +sdvmk_backward: ; find the pointer to the start of the filename. + mov al,byte ptr es:[di] ; we do this by check es:di backward until + cmp al,'\' ; di = si or di -> '\' or di -> ':'. + je sdvmk_gotfile + cmp al,':' + je sdvmk_gotfile + cmp di,si + je sdvmk_fileptr + dec di + jmp sdvmk_backward +sdvmk_gotfile: + inc di +sdvmk_fileptr: ; now es:di -> start of file name + push di ; cas - holy sh*t!!! CODE! + pop si ; save di to si. + + push ds ; switch es,ds + push es + pop ds + pop es ; now,ds:si -> start of filename + + mov di,devmark_filename + push di + mov al,' ' + mov cx,8 + rep stosb ; clean up memory. + pop di + mov cx,8 ; max 8 char. only +sdvmk_loop: + lodsb + cmp al,'.' + je sdvmk_done + cmp al,0 + je sdvmk_done + stosb + loop sdvmk_loop + +sdvmk_done: + pop di + pop es + pop si + pop ds + ret +set_devmark endp +^ +; ========================================================================= +;reset_dos_version proc near +; +;;function: issue ax=122fh,dx=0,int 2fh to restore the dos version. +; +; push ax +; push dx +; mov ax,122fh +; mov dx,0 +; int 2fh +; pop dx +; pop ax +; ret +;reset_dos_version endp +; +; +; ========================================================================= + +IFDEF DONT_LOAD_OS2_DD ; M045 + +EXE_SIG EQU 5a4dh ; .EXE file signature +OS2_SIG EQU 454eh ; OS2 .EXE file signature + +SIGNATURE_LEN EQU 2 ; Lenght of .EXE signature in bytes +SIZE_DWORD EQU 4 + +SEG_SIG_OFFSET EQU 18h ; Offset of segmented .EXE signature +SEG_EXE_SIG EQU 40h ; Signature of a segmented .EXE file +SEG_HEADER_PTR EQU 3ch ; Offsets of ptr to segmented header + +; ========================================================================= +; CheckForOS2 PROC +; +; Examines an open file to see if it is really an OS2 executable file. +; +; REGISTERS: AX - Open file handle +; RETURNS: Carry - Carry set if file is an OS2 executable or error. +; DESTROYS: NOTHING +; NOTE: The file ptr is assumed to be set to start of file +; on entry and is not reset to begining of the file +; on exit. +; +; Strategy: If word value at 00h == 454eh file is OS2 +; else if word value at 00h == 5a4dh and +; (word value at 18h == 40h and the dword ptr at 3ch +; points to word value of 454eh) file is OS2. +; +; ========================================================================= + +CheckForOS2 PROC NEAR + + push AX + push BX + push CX + push DX + push DS + push BP + + push CS ; BUGBUG + pop DS ; NOT ROM DOS COMPATIBLE + + mov BX,AX ; Put open file handle in BX + mov BP,offset DS:Os2ChkBuf ; Save buff offset for latter + + ; First we need to read in the first 2 bytes of the file + ; to see if it's an OS2 .EXE file and if not see if + ; it is a DOS .EXE file. + + mov AX,(read shl 8) ; AH = DOS read function + mov CX,SIGNATURE_LEN ; CX = size of word value + mov DX,BP ; DS:DX --> tmp buffer + int 21h + jc OS2ChkExit ; Return carry on error + + dec AX ; Check number of byte read + dec AX + jnz NotOs2 ; Must be at end of file + + mov AX, WORD PTR DS:Os2ChkBuf + cmp AX, OS2_SIG ; Check for 454eh + je IsOS2 ; Return is OS2 if match + cmp AX, EXE_SIG ; Now see if it's a DOS .EXE + jne NotOS2 ; If no match can't be OS2 + + ; Here we know the file has a valid DOS .EXE signature so + ; now we need to see if it's a segmented .EXE file by looking + ; for the segmented .EXE signature at file offset 18h + + mov AX,(lseek shl 8) ; AX = Seek from begining + xor CX,CX + mov DX,SEG_SIG_OFFSET ; CX:DX = offset of segmented + int 21h ; Seek to offset 18h + jc OS2ChkExit ; Return carry on error + + mov AX,read shl 8 ; AX = Read file + mov CX,SIGNATURE_LEN ; CX = size of word value + mov DX,BP ; Restore buffer offset + int 21h ; DS:DX -> buffer + jc OS2ChkExit ; Return carry on error + + dec AX ; Check number of byte read + dec AX + jnz NotOs2 ; Must be at end of file + + cmp WORD PTR DS:Os2ChkBuf,SEG_EXE_SIG ; Chk for segmented .EXE file + jne NotOS2 ; Can't be OS2 if no match + + ; Here we know we have a segmented .EXE file so we have + ; to get the offset of the start of the segmented header + ; from offset 3ch in the file. + + mov AX,(lseek shl 8) ; AX = Seek from begining + xor CX,CX + mov DX,SEG_HEADER_PTR ; CX:DX = offset of head ptr + int 21h ; Seek to offset 3ch + jc OS2ChkExit ; Return carry on error + + mov AX,(read shl 8) ; AX = Read file + mov CX,SIZE_DWORD ; CX = size of dword (4 bytes) + mov DX,BP ; Restore buffer offset + int 21h ; Read in 4 byte offset + jc OS2ChkExit ; Return carry on error + + cmp AX,SIZE_DWORD ; Check number of byte read + jne NotOs2 ; Must be at end of file + + ; At this point OS2ChkBuf has a 4 byte offset into the file + ; to the start of a segmented .EXE header so we need to read + ; the 2 bytes at this location to see if they are 454eh + + mov DX,WORD PTR DS:Os2ChkBuf + mov CX,WORD PTR DS:Os2ChkBuf[2] ; CX:DX = offset of new header + mov AX,(lseek shl 8) ; AX = Seek from begining + int 21h ; Seek to offset 3ch + jc OS2ChkExit ; Return carry on error + + mov AX,(read shl 8) ; AX = Read file + mov CX,SIGNATURE_LEN ; CX = size of word (2 bytes) + mov DX,BP ; DS:DX --> Os2ChkBuf + int 21h ; Read in 4 byte offset + jc OS2ChkExit ; Return carry on error + + dec AX ; Check number of byte read + dec AX + jnz NotOs2 ; Must be at end of file + + ; We have the segmented .EXE header in OS2ChkBuf so all + ; we have left to do is see if it's a .EXE signature. + + cmp WORD PTR DS:OS2ChkBuf,OS2_SIG ; Check for 454eh + jne NotOs2 ; Not OS2 if it doesn't match + +IsOs2: + stc ; Signal error or OS2 .EXE + jmp SHORT OS2ChkExit +NotOs2: + clc ; Signal no err and not OS2 + +OS2ChkExit: + pop BP + pop DS + pop DX + pop CX + pop BX + pop AX + ret + +CheckForOS2 ENDP + +ENDIF ; M045 + +; +;---------------------------------------------------------------------------- +; +; procedure : ProcDOS +; +; Process the result of DOS= parsing +; +; result_val.$p_item_tag = 1 for DOS=HIGH +; = 2 for DOS=LOW +; = 3 for DOS=UMB +; = 4 for DOS=NOUMB +;---------------------------------------------------------------------------- +; +ProcDOS proc near + assume ds:nothing, es:nothing + xor ah, ah + mov al, result_val.$p_item_tag + dec ax + jz pd_hi + dec ax + jz pd_lo + dec ax + jz pd_umb + mov DevUMB, 0 + ret +pd_umb: + mov DevUMB, 0ffh + ret +pd_lo: + mov runhigh, 0 + ret +pd_hi: + mov runhigh, 0ffh + ret +ProcDOS endp + +; +;---------------------------------------------------------------------------- +; +; procedure : LieInt12Mem +; +; Input : DevEntry points to Device Start address (offset == 0) +; alloclim set to the limit of low memory. +; +; Output : none +; +; Changes the ROM BIOS variable which stores the total low memory +; If a 3com device driver (any character device with name 'PROTMAN$') +; is being loaded alloclim is converted into Ks and stored in 40:13h +; Else if a device driver being loaded into UMB the DevLoadEnd is +; converted into Ks and stored in 40:13h +; +;---------------------------------------------------------------------------- +; +LieInt12Mem proc near + + assume ds:nothing, es:nothing + + mov ax, alloclim ; lie INT 12 as alloclim + ; assuming that it is 3Com + call IsIt3Com? ; Is it 3Com driver? + je lim_set ; yes, lie to him differently + cmp DeviceHi, 0 ; Is the DD being loaded in UMB + je limx ; no, don't lie + mov ax, DevLoadEnd ; lie INT 12 as end of UMB +lim_set: + call SetInt12Mem +limx: + ret +LieInt12Mem endp + +; +;---------------------------------------------------------------------------- +; +; procedure : SetInt12Mem +; +; Input : AX = Memory size to be set (in paras) +; Output : none +; +; Sets the variable 40:13 to the memory size passed in AX +; It saves the old value in 40:13 in OldInt12Mem, +; It also sets a flag Int12Lied to 0ffh, which is checked before +; restoring the value of 40:13 +; +;---------------------------------------------------------------------------- +; +SetInt12Mem proc near + + assume ds:nothing, es:nothing + + push ds + mov bx, 40h + mov ds, bx ; ROM BIOS Data Segment + mov bx, word ptr ds:[13h] ; INT 12 memory variable + mov OldInt12Mem, bx ; save it + mov cl, 6 + shr ax, cl ; convert paras into Ks + mov word ptr ds:[13h], ax ; Lie + mov Int12Lied, 0ffh ; mark that we are lying + pop ds + ret +SetInt12Mem endp + +; +;---------------------------------------------------------------------------- +; +; procedure : TrueInt12Mem +; +; Input : Int12Lied = 0 if we are not lying currently +; = 0ffh if we are lying +; OldInt12Mem = Saved value of 40:13h +; +; Output : none +; +; Resets the INT 12 Memory variable if we were lying about int 12 +; and resets the flag which indicates that we were lying +; +;---------------------------------------------------------------------------- +; +TrueInt12Mem proc near + + assume ds:nothing, es:nothing + + cmp Int12Lied, 0 ; were we lying so far? + mov Int12Lied, 0 ; reset it anyway + je timx ; no, we weren't + push ds + mov ax, 40h + mov ds, ax + mov ax, OldInt12Mem + mov word ptr ds:[13h], ax ; restore INT 12 memory + pop ds +timx: + ret +TrueInt12Mem endp + +; +;---------------------------------------------------------------------------- +; +; procedure : IsIt3Com? +; +; Input : DevEntry = Seg:0 of device driver +; Output : Zero flag set if device name is 'PROTMAN$' +; else Zero flag is reset +; +;---------------------------------------------------------------------------- +; +IsIt3Com? proc near + assume ds:nothing, es:nothing, ss:nothing + push ds + push es + push si + lds si, DevEntry ; ptr to device header + add si, sdevname ; ptr device name + push cs + pop es + mov di, offset ThreeComName + mov cx, 8 ; name length + rep cmpsb + pop si + pop es + pop ds + ret +IsIt3Com? endp + +;M020 : BEGIN +; +;---------------------------------------------------------------------------- +;---------------------------------------------------------------------------- +; +UpdatePDB proc near + assume ds:nothing + push ds + mov ah, 62h + int 21h + mov ds, bx + mov bx, alloclim + mov ds:[PDB_Block_Len], bx + pop ds + ret +UpdatePDB endp +; +; M020 : END +; +;---------------------------------------------------------------------------- +; +; procedure : InitDevLoad +; +; Input : DeviceHi = 0 indicates load DD in low memory +; = 1 indicates load in UMB +; DevSize = Size of the device driver file in paras +; +; Output : none +; +; Initializes DevLoadAddr, DevLoadEnd & DevEntry. +; Also sets up a header for the Device driver entry for mem utility +; +;---------------------------------------------------------------------------- +; +InitDevLoad proc near + + assume ds:nothing, es:nothing + + cmp DeviceHi, 0 ; Are we loading in UMB + je InitForLo ; no, init for lo mem + call SpaceInUMB? ; Do we have space left in the + ; current UMB ? + jnc InitForHi ; yes, we have + call ShrinkUMB ; shrink the current UMB in use + call GetUMBForDev ; else try to allocate new UMB + jc InitForLo ; we didn't succeed, so load + ; in low memory +InitForHi: + mov ax, DevUMBFree ; get Para addr of free mem + mov dx, DevUMBAddr ; UMB start addr + add dx, DevUMBSize ; DX = UMB End addr + jmp short idl1 + +InitForLo: + mov DeviceHi, 0 ; in case we failed to load + ; into UMB indicate that we + ; are loading low + mov ax, memhi ; AX = start of Low memory + mov dx, alloclim ; DX = End of Low memory +idl1: + call DevSetMark ; setup a sub-arena for DD + mov DevLoadAddr, ax ; init the Device load address + mov DevLoadEnd, dx ; init the limit of the block + mov word ptr DevEntry, 0 ; init Entry point to DD + mov word ptr DevEntry+2, ax + ret +InitDevLoad endp + + +;------------------------------------------------------------------ +; NTVDM 08-Dec-1992 Jonle +; +; AllocUMBLow- Allocates a chunk from memory from UMB area +; or from low memory area in case UMB memory +; is unavailable. +; +; The arena is marked as +; +; Input: es:di addr of arena name to copy +; cx size to allocate +; +; Output: es:di points to memory allocated +; +;------------------------------------------------------------------ +AllocUMBLow proc near + + assume ds:nothing, es:nothing + + mov ax, cx ; convert size to paras + add ax, 18 ; extra for dummy dev header for mem.exe + call pararound + mov DevSize, ax + + mov word ptr [bpb_addr], di ; fake cmd line for dev name + mov word ptr [bpb_addr+2], es + + mov al, DevUMB ; we want UMB + mov DeviceHi, al + + call InitDevLoad + + mov ax, word ptr DevEntry+2 ; mark arena for mem.exe + dec ax + mov es, ax + mov byte ptr es:[devmark_id], devmark_spc + + inc ax ; mark final size + add ax, DevSize + mov word ptr DevBrkAddr+2,ax + mov word ptr DevBrkAddr, 0 + call DevBreak + + mov di, word ptr DevEntry ; es:di -> deventry + mov ax, word ptr DevEntry+2 + mov es, ax + +AllocUMBLow endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : SpaceInUMB? +; +; Input : DevUMBAddr, DevUMBSize, DevUMBFree & DevSize +; Output : Carry set if no space in UMB +; Carry clear if Space is available for the device in +; current UMB +; +;---------------------------------------------------------------------------- +; +SpaceInUMB? proc near + + assume ds:nothing, es:nothing + + mov ax, DevUMBSize + add ax, DevUMBAddr ; End of UMB + sub ax, DevUMBFree ; - Free = Remaining space + or ax, ax ; Nospace ? + jnz @f + stc + ret +@@: + dec ax ; space for sub-arena + cmp ax, DevSize ; do we have space ? + ret +SpaceInUMB? endp + +; +;---------------------------------------------------------------------------- +; +; procedure : GetUMBForDev +; +; Input : DevSize +; Output : Carry set if couldn't allocate a UMB to fit the +; the device. +; If success carry clear +; +; Allocates the biggest UMB for loading devices and updates +; DevUMBSize, DevUMBAddr & DevUMBFree if it succeeded in allocating +; UMB. +; +; This routine relies on the fact that all of the low memory +; is allocated, and any DOS alloc calls should return memory +; from the UMB pool. +; +;---------------------------------------------------------------------------- +; +GetUMBForDev proc near + + assume ds:nothing, es:nothing + +if 0 +;; + mov bx, 0ffffh + mov ax, 4800h + int 21h + + or bx, bx + jz gufd_err + + dec bx + cmp DevSize, bx + ja gufd_err + inc bx + mov ax, 4800h + int 21h + jc gufd_err + + push ds + dec ax + mov ds, ax + mov word ptr ds:[arena_owner], 8 + mov word ptr ds:[arena_name], 'DS' + inc ax + pop ds + + mov DevUMBSize, bx ; update the UMB Variables + mov DevUMBAddr, ax + mov DevUMBFree, ax + clc ; mark no error + ret +gufd_err: + xor ax, ax + mov DevUMBSize, ax ; erase the previous values + mov DevUMBAddr, ax + mov DevUMBFree, ax + stc + ret +else +;; we changed the allocation strategy to best-fit for NT. This is because +;; we want to reserve bigger blocks for loadhigh command. In most case, +;; device drivers are smaller than TSR(ran from loadhigh). This change give +;; us a better chance to load the big tsr like DOSX.EXE to UMB and +;; give applications more free conventional memory. +;; The following implementation seems slow because every time we need an +;; UMB, we go through the chain. This is done because each request has +;; different size - We can grab all UMBs from the very beginning and put +;; them in a list, but we have to maintain the list. -williamh + push cx + push dx + push es + xor cx, cx ;; allocated count = 0 + mov dx, DevSize + inc dx ;; minimum size in paras + ;; bios needs its sub-arena +search_for_best_block: + mov bx, 0ffffh ;; get largest block size + mov ah, 48h ;; so far + int 21h + cmp bx, dx ;; will this satisfy ours? + jb allocate_the_block ;; no, break + mov ah, 48h ;; allocate this block + int 21h + jc allocate_the_block ;; failed, use the previous one + inc cx ;; we have one more allocated + push bx ;; save the size + push ax ;; save the address + jmp short search_for_best_block + +allocate_the_block: +;; the block saved on the top of the stack is the best fit one +;; grab it if there is one + jcxz gufd_err ;; no block found, error + pop ax ;; get the address + pop DevUMBSize ;; and size + mov DevUMBAddr, ax + mov DevUMBFree, ax + dec ax + push ds + mov ds, ax + mov word ptr ds:[arena_owner], 8 + mov word ptr ds:[arena_name], 'DS' + pop ds + dec cx +;; now free those unnecessary blocks + jcxz allocate_done +free_allocated_blocks: + pop es ;; get the address + add sp, 2 ;; discard the size + mov ah, 49h ;; free it + int 21h + loop free_allocated_blocks +allocate_done: + clc ; mark no error + jmp short GetUMBForDevExit +gufd_err: + xor ax, ax + mov DevUMBSize, ax ; erase the previous values + mov DevUMBAddr, ax + mov DevUMBFree, ax + stc +GetUMBForDevExit: + pop es + pop dx + pop cx + ret +endif + +GetUMBForDev endp + +; +;---------------------------------------------------------------------------- +; +; procedure : DevSetMark +; +; Input : AX - Free segment were device is going to be loaded +; Output : AX - Segment at which device can be loaded (AX=AX+1) +; +; Creates a sub-arena for the device driver +; puts 'D' marker in the sub-arena +; Put the owner of the sub-arena as (AX+1) +; Copies the file name into sub-arena name field +; +; Size field of the sub-arena will be set only at succesful +; completion of Device load. +; +;---------------------------------------------------------------------------- +; +DevSetMark proc near + + assume ds:nothing, es:nothing + + push es + push di + push ds + push si + mov es, ax + mov byte ptr es:[devmark_id], devmark_device ; 'D' + inc ax + mov word ptr es:[devmark_seg], ax +; +;-------------- Copy file name +; + push ax ; save load addr + lds si, bpb_addr ; command line is still there +;M004 - BEGIN + mov di, si + cld +dsm_again: + lodsb + cmp al, ':' + jne isit_slash + mov di, si + jmp dsm_again +isit_slash: + cmp al, '\' + jne isit_null + mov di, si + jmp dsm_again +isit_null: + +ifdef DBCS + call testkanj + jz @f ; if this is not lead byte + lodsb ; get tail byte +@@: +endif + + or al, al + jnz dsm_again + mov si, di +;M004 - END + mov di, devmark_filename + mov cx, 8 ; maximum 8 characters +dsm_next_char: + lodsb + or al, al + jz blankout + cmp al, '.' + jz blankout + stosb + loop dsm_next_char +blankout: + jcxz dsm_exit + mov al, ' ' + rep stosb ; blank out the rest +dsm_exit: + pop ax ; restore load addr + pop si + pop ds + pop di + pop es + ret +DevSetMark endp + +; +;---------------------------------------------------------------------------- +; +; procedure : SizeDevice +; +; Input : ES:SI - points to device file to be sized +; +; Output : Carry set if file cannot be opened or if it is an OS2EXE file +; +; Calculates the size of the device file in paras and stores it +; in DevSize +; +;---------------------------------------------------------------------------- +; +SizeDevice proc near + + assume ds:nothing, es:nothing + + push es + pop ds + mov dx, si ; ds:dx -> file name + mov ax, 3d00h ; open + int 21h + jc sd_err ; open failed + +IFDEF DONT_LOAD_OS2_DD ; M045 + call CheckForOS2 ; is it a OS2 EXE file ? + jc sd_close ; yeah, we dont load them +ENDIF ; M045 + + mov bx, ax ; BX - file handle + mov ax, 4202h ; seek + xor cx, cx + mov dx, cx ; to end of file + int 21h + jc sd_close ; did seek fail (impossible) + add ax, 15 ; para convert + adc dx, 0 + test dx, 0fff0h ; size > 0ffff paras ? + jz @f ; no + mov DevSize, 0ffffh ; invalid device size + ; assuming that we fail later + jmp short sd_close +@@: + mov cl, 4 ; conver it to paras + shr ax, cl + mov cl, 12 + shl dx, cl + or ax, dx ; + cmp ax, DevSizeOption + ja @f + mov ax, DevSizeOption +@@: + mov DevSize, ax ; save file size + clc +sd_close: + pushf ; let close not spoil our + ; carry flag + mov ax, 3e00h ; close + int 21h ; we are not checking for err + popf +sd_err: + ret +SizeDevice endp + +; +;---------------------------------------------------------------------------- +; +; procedure : ExecDev +; +; Input : ds:dx -> device to be executed +; DevLoadAddr - contains where device has to be loaded +; +; Output : Carry if error +; Carry clear if no error +; +; Loads a device driver using the 4b03h function call +; +;---------------------------------------------------------------------------- +; +ExecDev proc near + + assume ds:nothing, es:nothing + + mov bx, DevLoadAddr + mov DevExecAddr, bx ; Load the parameter block + ; block for exec with + ; Load address + mov DevExecReloc, bx + mov bx,cs + mov es,bx + mov bx,offset DevExecAddr ;es:bx points to parameters + mov al,3 + mov ah,exec + int 21h ;load in the device driver + ret +ExecDev endp + +; +;---------------------------------------------------------------------------- +; +; procedure : RemoveNull +; +; Input : ES:SI points to a null terminated string +; +; Output : none +; +; Replaces the null at the end of a string with blank +; +;---------------------------------------------------------------------------- +; + +RemoveNull proc near + + assume ds:nothing, es:nothing + +rn_next: + mov bl, es:[si] + or bl, bl ; null ? + jz rn_gotnull + inc si ; advance the pointer + jmp rn_next +rn_gotnull: + mov bl, DevSavedDelim + mov byte ptr es:[si], bl ; replace null with blank + ret +RemoveNull endp + +; +;---------------------------------------------------------------------------- +; +; procedure : RoundBreakAddr +; +; Input : DevBrkAddr +; Output : DevBrkAddr +; +; Rounds DevBrkAddr to a para address so that it is of the form xxxx:0 +; +;---------------------------------------------------------------------------- +; +RoundBreakAddr proc near + + assume ds:nothing, es:nothing + + mov ax, word ptr DevBrkAddr + call pararound + add word ptr DevBrkAddr+2, ax + mov word ptr DevBrkAddr, 0 + mov ax, DevLoadEnd + cmp word ptr DevBrkAddr+2, ax + jbe rba_ok + jmp mem_err +rba_ok: + ret +RoundBreakAddr endp + +; +;---------------------------------------------------------------------------- +; +; procedure : DevSetBreak +; +; Input : DevBrkAddr +; Output : Carry set if Device returned Init failed +; Else carry clear +; +;---------------------------------------------------------------------------- +; +DevSetBreak proc near + + assume ds:nothing, es:nothing + + push ax + + mov ax,word ptr [DevBrkAddr+2] ;remove the init code + cmp multdeviceflag, 0 + jne set_break_continue ;do not check it. + cmp ax, DevLoadAddr + jne set_break_continue ;if not same, then o.k. + + cmp word ptr [DevBrkAddr],0 + je break_failed ;[DevBrkAddr+2]=[memhi] & [DevBrkAddr]=0 + +set_break_continue: + call RoundBreakAddr + pop ax + clc + ret +break_failed: + pop ax + stc + ret +DevSetBreak endp + +; +;---------------------------------------------------------------------------- +; +; procedure : DevBreak +; +; Input : DevLoadAddr & DevBrkAddr +; Output : none +; +; Marks a succesful install of a device driver +; Sets device size field in sub-arena & +; Updates Free ptr in UMB or adjusts memhi +; +;---------------------------------------------------------------------------- +; +DevBreak proc near + + assume ds:nothing, es:nothing + + push ds + mov ax, DevLoadAddr + mov bx, word ptr [DevBrkAddr+2] + dec ax ; seg of sub-arena + mov ds, ax + inc ax ; Back to Device segment + sub ax, bx + neg ax ; size of device in paras + mov ds:[devmark_size], ax ; store it in sub-arena + cmp DeviceHi, 0 + je db_lo + mov DevUMBFree, bx ; update Free ptr in UMB + jmp short db_exit +db_lo: + mov memhi, bx + mov memlo, 0 +db_exit: + pop ds + ret +DevBreak endp +; +;---------------------------------------------------------------------------- +; +; procedure : ParseSize +; +; Parses the command line for SIZE= command +; +; ES:SI = command line to parsed +; +; returns ptr to command line after SIZE= option in ES:SI +; updates the DevSizeOption variable with value supplied +; in SIZE=option +; Returns carry if the SIZE option was invalid +; +;---------------------------------------------------------------------------- +; +ParseSize proc near + + assume ds:nothing, es:nothing + + mov DevSizeOption, 0 ; init the value + mov word ptr DevCmdLine, si + mov word ptr DevCmdLine+2, es + call SkipDelim + cmp word ptr es:[si], 'IS' + jne ps_no_size + cmp word ptr es:[si+2], 'EZ' + jne ps_no_size + mov al, es:[si+4] + call delim + jne ps_no_size + add si, 5 + call GetHexNum + jc ps_err + mov DevSizeOption, ax + call SkipDelim +ps_no_size: + clc + ret +ps_err: + stc + ret +ParseSize endp +; +;---------------------------------------------------------------------------- +; +; procedure : SkipDelim +; +; Skips delimiters in the string pointed to by ES:SI +; Returns ptr to first non-delimiter character in ES:SI +; +;---------------------------------------------------------------------------- +; +SkipDelim proc near + + assume ds:nothing, es:nothing + +sd_next_char: + mov al, es:[si] + call delim + jnz sd_ret + inc si + jmp sd_next_char +sd_ret: + ret +SkipDelim endp +; +;---------------------------------------------------------------------------- +; +; procedure : GetHexNum +; +; Converts an ascii string terminated by a delimiter into binary. +; Assumes that the ES:SI points to a Hexadecimal string +; +; Returns in AX the number number of paras equivalent to the +; hex number of bytes specified by the hexadecimal string. +; +; Returns carry in case it encountered a non-hex character or +; if it encountered crlf +; +;---------------------------------------------------------------------------- +; +GetHexNum proc near + + assume ds:nothing, es:nothing + + xor ax, ax + xor dx, dx +ghn_next: + mov bl, es:[si] + cmp bl, cr + je ghn_err + cmp bl, lf + je ghn_err + push ax + mov al, bl + call Delim + pop ax + jz ghn_into_paras + call GetNibble + jc ghn_err + mov cx, 4 +ghn_shift1: + shl ax, 1 + rcl dx, 1 + loop ghn_shift1 + or al, bl + inc si + jmp ghn_next +ghn_into_paras: + add ax, 15 + adc dx, 0 + test dx, 0fff0h + jnz ghn_err + mov cx, 4 +ghn_shift2: + clc + rcr dx, 1 + rcr ax, 1 + loop ghn_shift2 + clc + ret +ghn_err: + stc + ret +GetHexNum endp +; +;---------------------------------------------------------------------------- +; +; procedure : GetNibble +; +; Convert one nibble (hex digit) in BL into binary +; +; Retruns binary value in BL +; +; Returns carry if BL contains non-hex digit +; +;---------------------------------------------------------------------------- +; +GetNibble proc near + cmp bl, '0' + jb gnib_err + cmp bl, '9' + ja is_it_hex + sub bl, '0' ; clc + ret +is_it_hex: + cmp bl, 'A' + jb gnib_err + cmp bl, 'F' + ja gnib_err + sub bl, 'A'- 10 ; clc + ret +gnib_err: + stc + ret +GetNibble endp +; +; +;============================================================================ +;============================================================================ +; +;---------------------------------------------------------------------------- +; +; procedure : AllocUMB +; +; Allocate all UMBs and link it to DOS arena chain +; +;---------------------------------------------------------------------------- +; +AllocUMB proc near + call InitAllocUMB ; link in the first UMB + jc au_exit ; quit on error +au_next: + call umb_allocate ; allocate + jc au_coalesce + call umb_insert ; & insert till no UMBs + jmp short au_next +au_coalesce: + call umb_coalesce ; coalesce all UMBs +au_exit: + ret +AllocUMB endp +; +;---------------------------------------------------------------------------- +; +; procedure : InitAllocUMB +; +;---------------------------------------------------------------------------- +; +InitAllocUMB proc near + call IsXMSLoaded + jnz iau_err ; quit on no XMS driver + mov ah, 52h + int 21h ; get DOS DATA seg + mov DevDOSData, es ; & save it for later + mov ax, 4310h + int 2fh + mov word ptr DevXMSAddr, bx ; get XMS driver address + mov word ptr DevXMSAddr+2, es + cmp FirstUMBLinked, 0 ; have we already linked a UMB? + jne @f ; quit if we already did it + call LinkFirstUMB ; else link the first UMB + jc iau_err + mov FirstUMBLinked, 0ffh ; mark that 1st UMB linked +@@: + clc + ret +iau_err: + stc + ret +InitAllocUMB endp + +;------------------------------------------------------------------------- +; +; Procedure Name : umb_allocate +; +; Inputs : DS = data +; +; Outputs : if UMB available +; Allocates the largest available UMB and +; BX = segment of allocated block +; DX = size of allocated block +; NC +; else +; CY +; +; Uses : BX, DX +; +;------------------------------------------------------------------------- + +umb_allocate proc near + + push ax + mov ah, XMM_REQUEST_UMB + mov dx, 0ffffh ; try to allocate largest + ; possible + call dword ptr DevXMSAddr + ; dx now contains the size of + ; the largest UMB + or dx, dx + jz ua_err + + mov ah, XMM_REQUEST_UMB + call dword ptr DevXMSAddr + + cmp ax, 1 ; Q: was the reqst successful + jne ua_err ; N: error + + clc + +ua_done: + pop ax + ret + +ua_err: + stc + jmp short ua_done + +umb_allocate endp + + + +;--------------------------------------------------------------------------- +; +; Procedure Name : umb_insert +; +; Inputs : DOSDATA:UMB_HEAD = start of umb chain +; : BX = seg address of UMB to be linked in +; : DX = size of UMB to be linked in paras +; ; DS = data +; +; Outputs : links the UMB into the arena chain +; +; Uses : AX, CX, ES, DX, BX +; +;--------------------------------------------------------------------------- + + +umb_insert proc near + + push ds + + mov ds, [DevDOSData] + mov ds, ds:[UMB_ARENA] ; es = UMB_HEAD + mov ax, ds + mov es, ax + +ui_next: + cmp ax, bx ; Q: is current block above + ; new block + ja ui_insert ; Y: insert it + ; Q: is current block the + ; last + cmp es:[arena_signature], arena_signature_end + jz ui_append ; Y: append new block to chain + ; N: get next block + + mov ds, ax ; M005 + call get_next ; ax = es = next block + jmp short ui_next + +ui_insert: + + mov cx, ds ; ds = previous arena + inc cx ; top of previous block + + sub cx, bx + neg cx ; cx = size of used block + mov ds:[arena_signature], arena_signature_normal + mov ds:[arena_owner], 8 ; mark as system owned + mov ds:[arena_size], cx + mov word ptr ds:[arena_name], 'CS' + +; prepare the arena at start of new block + + mov es, bx + mov es:[arena_signature], arena_signature_normal + mov es:[arena_owner], arena_owner_system + ; mark as free + sub dx, 2 ; make room for arena at + ; start & end of new block + mov es:[arena_size], dx + +; prepare arena at end of new block + + add bx, dx + inc bx + mov es, bx ; es=arena at top of new block + inc bx ; bx=top of new block + + ; ax contains arena just above + ; this block + sub ax, bx ; ax = size of used block + + mov es:[arena_signature], arena_signature_normal + mov es:[arena_owner], 8 ; mark as system owned + mov es:[arena_size], ax + mov word ptr es:[arena_name], 'CS' + + jmp short ui_done + +ui_append: + + ; es = arena of last block + + add ax, es:[arena_size] ; ax=top of last block-1 para + sub es:[arena_size], 1 ; reflect the space we are + ; going to rsrv on top of this + ; block for the next arena. + mov es:[arena_signature], arena_signature_normal + + mov cx, ax ; cx=top of prev block-1 + inc ax + sub ax, bx ; ax=top of prev block - + ; seg. address of new block + + neg ax + + mov es, cx ; ds = arena of unused block + + + mov es:[arena_signature], arena_signature_normal + mov es:[arena_owner], 8 ; mark as system owned + mov es:[arena_size], ax + mov word ptr es:[arena_name], 'CS' + +; prepare the arena at start of new block + + mov es, bx + mov es:[arena_signature], arena_signature_end + mov es:[arena_owner], arena_owner_system + ; mark as free + dec dx ; make room for arena + mov es:[arena_size], dx + +ui_done: + pop ds + ret + +umb_insert endp + + +; +;---------------------------------------------------------------------------- +; +;** umb_coalesce - Combine free blocks ahead with current block +; +; Coalesce adds the block following the argument to the argument block, +; iff it's free. Coalesce is usually used to join free blocks, but +; some callers (such as $setblock) use it to join a free block to it's +; preceeding allocated block. +; +; EXIT 'C' clear if OK +; (ds) unchanged, this block updated +; (ax) = address of next block, IFF not at end +; 'C' set if arena trashed +; USES cx, di, ds, es +; +;---------------------------------------------------------------------------- +; + +umb_coalesce proc near + + + + xor di, di + + mov es, [DevDOSData] + mov es, es:[UMB_ARENA] ; es = UMB_HEAD + +uc_nextfree: + mov ax, es + mov ds, ax + cmp es:[arena_owner], di ; Q: is current arena free + jz uc_again ; Y: try to coalesce with next block + ; N: get next arena + call get_next ; es, ax = next arena + jc uc_done + jmp short uc_nextfree +uc_again: + call get_next ; ES, AX <- next block + jc uc_done +uc_check: + cmp es:[arena_owner],di ; Q: is arena free + jnz uc_nextfree ; N: get next free arena + ; Y: coalesce + mov cx,es:[arena_size] ; cx <- next block size + inc cx ; cx <- cx + 1 (for header size) + add ds:[arena_size],cx ; current size <- current size + cx + mov cl,es:[di] ; move up signature + mov ds:[di],cl + jmp short uc_again ; try again +uc_done: + ret + +umb_coalesce endp + +; +;---------------------------------------------------------------------------- +; +;** get_next - Find Next item in Arena +; +; ENTRY dS - pointer to block head +; EXIT AX,ES - pointers to next head +; 'C' set iff arena damaged +; +;---------------------------------------------------------------------------- +; + +get_next proc near + + cmp byte ptr ds:[0], arena_signature_end + je gn_err + + mov ax,ds ; ax=current block + add ax,ds:[arena_size] ; ax=ax + current block length + inc ax ; remember that header! + mov es, ax + clc + ret +gn_err: + stc + ret + +get_next endp + +; +;---------------------------------------------------------------------------- +; +; procedure : LinkFirstUMB +; +;---------------------------------------------------------------------------- +; +LinkFirstUMB proc near + + call umb_allocate + jc lfu_err + +; bx = segment of allocated UMB +; dx = size of UMB + + int 12h ; ax = size of memory + mov cl, 6 + shl ax, cl ; ax = size in paragraphs + + mov cx, ax ; cx = size in paras + sub ax, bx ; ax = - size of unused block + + neg ax + + sub cx, 1 ; cx = first umb_arena + mov es, cx ; es = first umb_arena + + mov es:[arena_signature], arena_signature_normal + mov es:[arena_owner], 8 ; mark as system owned + + mov es:[arena_size], ax + mov word ptr es:[arena_name], 'CS' + + +; put in the arena for the first UMB + + mov es, bx ; es has first free umb seg + mov es:[arena_signature], arena_signature_end + mov es:[arena_owner], arena_owner_system + ; mark as free + dec dx ; make room for arena + mov es:[arena_size], dx + + + mov es, [DevDOSData] + mov di, UMB_ARENA + mov es:[di], cx ; initialize umb_head in DOS + ; data segment with the arena + ; just below Top of Mem + +; we must now scan the arena chain and update the size of the last +; arena + + mov di, DOS_ARENA + mov es, word ptr es:[di] ; es = start arena + xor di, di + + +scan_next: + cmp byte ptr es:[di], arena_signature_end + jz got_last + + mov ax, es + add ax, es:[arena_size] + inc ax + mov es, ax + jmp short scan_next + +got_last: +;; -williamh- we reserved the last paragraph for UMB_HEAD already. +;; refer to sysinit1.asm!goinit +;; The following instruction was commentted out for this reason. +;; sub es:[arena_size], 1 +;; + mov es:[arena_signature], arena_signature_normal + clc + ret + +lfu_err: + stc + ret +LinkFirstUMB endp + +; +;---------------------------------------------------------------------------- +; +; procedure : ShrinkUMB +; +; Shrinks the current UMB in use, so that the unused portions +; of the UMB is given back to the DOS free mem pool +; +;---------------------------------------------------------------------------- +; + public ShrinkUMB + +ShrinkUMB proc near + cmp DevUMBAddr, 0 + je su_exit + push es + push bx + mov bx, DevUMBFree + sub bx, DevUMBAddr + mov es, DevUMBAddr + mov ax, 4a00h + int 21h + mov ax, es + dec ax + mov es, ax + mov word ptr es:[arena_owner], 8 + pop bx + pop es +su_exit: + ret +ShrinkUMB endp + +;M002 - BEGIN +; +;---------------------------------------------------------------------------- +; +; procedure : UnlinkUMB +; +; Unlinks the UMBs from the DOS arena chain +; +;---------------------------------------------------------------------------- +; + public UnlinkUMB + +UnlinkUMB proc near + push ds + push es + cmp FirstUMBLinked, 0 + je ulu_x ; nothing to unlink + mov es, DevDOSData ; get DOS data seg + mov ds, es:[DOS_ARENA] + mov di, es:[UMB_ARENA] +ulu_next: + call get_next + jc ulu_x + cmp di, ax ; is the next one UMB ? + je ulu_found + mov ds, ax + jmp ulu_next +ulu_found: + mov ds:[arena_signature], 'Z' +ulu_x: + pop es + pop ds + ret +UnlinkUMB endp + +;M002 - END + +; ========================================================================= +; +sysinitseg ends + end diff --git a/private/mvdm/softpc.new/bios/sysimes.asm b/private/mvdm/softpc.new/bios/sysimes.asm new file mode 100644 index 000000000..ee958e288 --- /dev/null +++ b/private/mvdm/softpc.new/bios/sysimes.asm @@ -0,0 +1,26 @@ + page ,160 + ; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- + + include version.inc ; set build flags + include biosseg.inc ; establish bios segment structure + +sysinitseg segment + + public badopm,crlfm,badsiz_pre,badld_pre,badcom,badcountry + public badmem,badblock,badstack + public insufmemory,badcountrycom + public badorder,errorcmd + public badparm + public toomanydrivesmsg ;M029 + + include msbio.cl3 + +sysinitseg ends + end + diff --git a/private/mvdm/softpc.new/bios/sysinit1.asm b/private/mvdm/softpc.new/bios/sysinit1.asm new file mode 100644 index 000000000..e45d95e34 --- /dev/null +++ b/private/mvdm/softpc.new/bios/sysinit1.asm @@ -0,0 +1,4007 @@ + page ,160 + title bios system initialization +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- + +break macro ; dummy empty macro + endm + include version.inc + include biosseg.inc + include sysvar.inc + include curdir.inc + include pdb.inc + include exe.inc + include sf.inc + include arena.inc + include syscall.inc + include devsym.inc + include ioctl.inc + include biostruc.inc + include dossym.inc + include dosmac.inc + include mult.inc + include dossvc.inc + include dbgsvc.inc + include cmdsvc.inc + include xmssvc.inc + include vint.inc + +Bios_Code segment + extrn BCode_start:near + extrn BCode_end:near + extrn seg_reinit:far + +Bios_Code ends + + include devmark.inc + include cputype.inc + + +true equ 0ffffh +false equ 0 +cr equ 13 +lf equ 10 +tab equ 9 + +;multMULT equ 4ah +multMULTGETHMAPTR equ 1 +multMULTALLOCHMA equ 2 + + +stacksw equ true ;include switchable hardware stacks +mycds_size equ 71 ; size of curdir_list. if it is not + ;the same, then will generate compile error. + +if DEBUG ; BUGBUG - Jeez, remove this! + dossize equ 0b200h +else + dossize equ 0a000h +endif + + if ibmjapver +noexec equ true + else +noexec equ false + endif + +; if mycds_size <> curdirlen,then force a compilatiaon error. + + if mycds_size ne curdirlen + %out !!! sysinit1 compilation failed. different cds size !!! + .errne mycds_size eq curdirlen + endif + + if not ibmjapver + extrn re_init:far + endif + + ifdef TAIWAN + extrn cdosinit:near + endif + +;--------------------------------------- + +Bios_Data segment + +;equates for main stack and stack initialization program + + if stacksw + + extrn NextStack:dword ; Win386 Instance table stuff + extrn IT_StackLoc:dword ; we have to plug in so that our + extrn IT_StackSize:word ; stacks can be instanced + +entrysize equ 8 + +mincount equ 8 +defaultcount equ 9 +maxcount equ 64 + +minsize equ 32 +defaultsize equ 128 +maxsize equ 512 + +allocbyte equ 0 +intlevel equ 1 +savedsp equ 2 +savedss equ 4 +newsp equ 6 + +free equ 0 +allocated equ 1 +overflowed equ 2 +clobbered equ 3 + + + + + + +; external variables in ibmbio for int19h handling rouitne. + + extrn int19sem:byte + + irp aa,<02,08,09,0a,0b,0c,0d,0e,70,72,73,74,76,77> + extrn int19old&aa:dword + endm + endif + + +;--------------------------------------- +; 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. + + extrn multrk_flag:word +; +;SR; Win386 present flag +; + extrn IsWin386:BYTE +; +;SR; Added for SetFocus routine for WIN386 support +; + extrn V86_Crit_SetFocus:far + + extrn xms:dword ; entry point for xms driver + extrn inHMA:byte ; flag meaning we're running high + + extrn FreeHMAPtr:word + extrn MoveDOSIntoHMA:dword + extrn SysinitPresent:byte + extrn DemInfoFlag:byte + extrn spc_mse_int10:dword + extrn int29Perf:dword + + extrn outchr:near +Bios_Data ends + +; NTVDM 16-Sep-1992 Jonle +; Softpc Kbd, mouse, emm drivers +SpcKbdSeg segment + extrn InstSpcKbd:near + extrn SpcKbdBeg:byte + extrn SpcKbdEnd:byte + extrn int10h_vector:near +SpcKbdSeg ends + +SpcMseSeg segment + extrn InstSpcMse:near + extrn SpcMseBeg:byte + extrn SpcMseEnd:byte +SpcMseSeg ends + +SpcEmmSeg segment + extrn InitSpcEmm:near + extrn SpcEmmBeg:byte + extrn SpcEmmEnd:byte + extrn SI_end:byte +SpcEmmSeg ends + + + + +sysinitseg segment + assume cs:sysinitseg, ds:nothing,es:nothing,ss:nothing + + extrn badcom:byte + extrn condev:byte + extrn auxdev:byte + extrn prndev:byte + extrn commnd:byte + extrn devmark_addr:word + extrn setdevmarkflag:byte + extrn pathstring:byte + + extrn print:near + extrn int24:near + extrn mem_err:near + extrn doconf:near + extrn multi_pass:near + + extrn badload:near + extrn error_line:near + + extrn ShrinkUMB:near + extrn UnlinkUMB:near ;M002 + extrn AllocUMB:near + extrn toomanydrivesmsg:byte ; M029 + + + ;NTVDM + extrn MseDev:byte ; internal mouse driver name + extrn AllocUMBLow:near ; mem alloc for new internal drivers + extrn bEchoConfig:byte + extrn config:byte + + public current_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 + + if stacksw ; internal stack information + public stack_count + public stack_size + public stack_addr + endif + + public dosinfo + public fcbs + public keep + public confbot + public alloclim + public zero + public sepchr + public count + public chrptr + public org_count + public bufptr + public memlo + public prmblk + public memhi + public ldoff + public area + public packet + public unitcount + public break_addr + public bpb_addr + public 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 h_buffers + public configmsgflag + public do_install_exec + public multi_pass_id + public temp_bcode_seg + public seg_reinit_ptr + + public toomanydrivesflag ; M029 + +sysinit$: + if stacksw +.sall + +; 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 this 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. double checks that a nested interrupt didn't get the same stack. +; 5. intercepts ints 70, 72-77 for pc-ats and other future products + + 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 + + +; these are the individual interrupt handlers + + assume ds:nothing,es:nothing,ss:nothing + +public int02 +public old02 + old02 dd 0 +int02 proc far + +;; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle +;; +;; ********************************************************************* +;; +;; 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 ax +; push es +; mov ax,0f000h +; mov es,ax +; cmp byte ptr es:[0fffeh],mdl_convert ;check if convertible +; pop es +; jne normal02 +; +; in al,62h +; test al,80h +; jz normal02 +; +;special02: +; pop ax +; jmp dword ptr old02 +; +;normal02: +; pop ax +; + + call do_int_stacks + dw old02 + +int02 endp + +public int08 +public old08 +old08 dd 0 +int08 proc far + call do_int_stacks + dw old08 +int08 endp + +public int09 +public old09 +old09 dd 0 +int09 proc far + +; keyboard interrupt must have a three byte jump, a nop and a zero byte +; as its first instruction for compatibility reasons + + ifidn <09>,<09> + jmp short keyboard_lbl + nop + db 0 +keyboard_lbl label near + endif + + call do_int_stacks + dw old09 +int09 endp + +public int70 +public old70 +old70 dd 0 +int70 proc far + call do_int_stacks + dw old70 +int70 endp + + irp a,<0a,0b,0c,0d,0e,72,73,74,76,77> +public int&a +public old&a +public firstflag&a +int&a proc far + jmp short entry_int&a&_stk +old&a dd 0 ;forward pointer + dw 424bh ;compatible signature for int. sharing +firstflag&a db 0 ;the firstly hooked. + jmp short intret_&a ;reset routine. we don't care this. + db 7 dup (0) ;reserved for future. +entry_int&a&_stk: + call do_int_stacks + dw old&a +intret_&a: + jmp DOIRET +int&a endp + endm + + +DOCLI: + FCLI + ret +DOSTI: + FSTI + ret +DOIRET: + FIRET + + +;******************************************************************** +;common routines + +; do interrupt stack switching. the fake return address holds +; a pointer to the far-pointer of the actual interrupt +; service routine + +do_int_stacks: + push ax + push bp + push es + mov es, cs:[stacks+2] ; get segment of stacks + + mov bp,nextentry ; get most likely candidate + mov al,allocated + xchg es:byte ptr allocbyte[bp],al ; grab the entry + cmp al,free ; still avail? + jne notfree02 + + sub nextentry,entrysize ; set for next interrupt + +found02: + mov es:word ptr savedsp[bp],sp ; save sp value + mov es:word ptr savedss[bp],ss ; save ss also + + mov ax,bp ; temp save of table offset + + + mov bp,es:word ptr newsp[bp] ; get new sp value + cmp es:[bp],ax ; check for offset into table + jne foundbad02 + + push bp + mov bp,sp + mov ax,8[bp] ; get offset of interrupt vector + pop bp + + push es ; ss:sp = new stack + pop ss + mov sp,bp + + mov bp,ax ; get pointer to interrupt vector + mov bp,cs:[bp] + pushf ; go execute the real interrupt handler + call cs:dword ptr [bp] ; call the old interrupt vector + + mov bp,sp ; retrieve the table offset for us + mov bp,es:[bp] ; but leave it on the stack + mov ss,es:word ptr savedss[bp] ; get old stack back + mov sp,es:word ptr savedsp[bp] + + + mov es:byte ptr allocbyte[bp],free ; free the entry + mov nextentry,bp ; setup to use next time + +newerror02: + pop es + pop bp ; saved on entry + pop ax ; saved on entry + add sp,2 ; lose the fake return address + +intret_02: + jmp DOIRET ; done with this interrupt + +notfree02: + cmp al,allocated ; error flag + je findnext02 ; no, continue + xchg es:byte ptr allocbyte[bp],al ; yes, restore error value + +findnext02: + call longpath + jmp found02 + +foundbad02: + cmp bp,firstentry + jc findnext02 + mov bp,ax ; flag this entry + mov es:byte ptr allocbyte[bp],clobbered + jmp findnext02 ; keep looking +longpath: + mov bp,lastentry ; start with last entry in table + +lploopp: + cmp es:byte ptr allocbyte[bp],free ; is entry free? + jne inuse ; no, try next one + + mov al,allocated + xchg es:byte ptr allocbyte[bp],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 es:byte ptr allocbyte[bp],al ; yes, put back the error state + +inuse: + cmp bp,firstentry + je fatal + sub bp,entrysize + jmp lploopp + +found: + ret + +fatal proc near + +; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle +; +; push ds +; mov ax, 0f000h ;look at the model byte +; mov ds, ax +; cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? +; pop ds +; jne skip_nmis +; +; mov al,07h ; disable pc convertible nmis +; out 72h,al +; +;skip_nmis: + + call DOCLI ; 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 + +;SR; +; We set all foci to this VM to issue the stack failure message +; + push ax + push ds + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + + test ds:[IsWin386],1 + pop ds + pop ax + assume ds:nothing + jz fatal_loop ;win386 not present, continue + + call V86_Crit_SetFocus ;set focus to this VM +; +;SR; We do not bother about the returned status of this call. +; + +fatal_loop: + lodsb + cmp al,'$' + je fatal_done + + mov bl,7 + mov ah,14 + int 010h ; whoops, this enables ints + jmp fatal_loop + +fatal_done: + jmp fatal_done +fatal endp + + include msbio.cl5 ;fatal stack error message +.xall + public endstackcode +endstackcode label byte + endif + +sysinit: + jmp goinit +; +;---------------------------------------------------------------------------- +; +DDHighInfo struc + ddhigh_CSegPtr dd ? ; pointer to code segment to be relocated + ddhigh_CSegLen dw ? ; length of code segment to be relocated + ddhigh_CallBak dd ? ; pointer to the call back routine +DDHighInfo ends + + public runhigh +runhigh db 0h + + +dosinfo dd 0 ; address of the DOS Sysini Variables + +dos_temp_location label dword +dosinit dw 0 +current_dos_location dw 0 + +device_list dd 0 + +sysi_country dd 0 ; pointer to country table in dos + +dos_segreinit dw 0,0 ; room for dword + +lo_doscod_size dw 0 ; dos code size when in low mem +hi_doscod_size dw 0 ; dos code size when in HMA + +def_php dw 0 + + +; M022-- +; pointer for calling into Bios_Code for re-initializing segment values. +; call with ax = new segment for Bios_Code. Notice that we'll +; call it in its temporary home, cuz seg_reinit won't get moved to +; the new home. + +seg_reinit_ptr label dword + + dw offset Bios_Code:seg_reinit +temp_bcode_seg dw Bios_Code + + +;variables for stack initialization program. + + if stacksw +stack_count dw defaultcount +stack_size dw defaultsize +stack_addr dd 0 + endif + +; various default values + +memory_size dw 1 +RPLMemTop dw 0 +default_drive db 0 ;initialized by ibminit. +buffers dw -1 ; initialized during buffer allocation +h_buffers dw 0 ; # of the heuristic buffers. initially 0. +singlebuffersize dw ? ; maximum sector size + buffer header + +files db 8 ; enough files for pipe +fcbs db 4 ; performance for recycling +keep db 0 ; keep original set +num_cds db 1 ; minimum needed is 1, so that initialization does'nt have a problem +confbot dw ? +alloclim dw ? +DirStrng db "A:\",0 ; string for the root directory of a drive +command_line db 2,0,"P" ;default command.com args + db 125 dup (0) +zero db 0 +sepchr db 0 +linecount dw 0 ; line count in config.sys +showcount db ' ',cr,lf,'$' ; used to convert linecount to ascii. +buffer_linenum dw 0 ; line count for "buffers=" command if entered. + + +buf_prev_off dw 0 + + if not noexec +comexe exec0 <0,command_line,default_drive,zero> + endif + +;------------------------------------------------------------------ +; variables for install= command. + +multi_pass_id db 0 ; parameter passed to multi_pass + ; indicating the pass number + ; 0 - do scan for DOS=HIGH/LOW + ; 1 - load device drivers + ; 2 - was to load IFS + ; now it is unused + ; 3 - do install= + ; >3 - nop +install_flag dw 0 + +have_install_cmd equ 00000001b ; config.sys has install= commands +has_installed equ 00000010b ; sysinit_base installed. + +config_size dw 0 ; size of config.sys file. set by sysconf.asm +sysinit_base_ptr dd 0 ; pointer to sysinit_base +sysinit_ptr dd 0 ; returning addr. from sysinit_base +checksum dw 0 ; used by sum_up + +ldexec_fcb db 20 dup (' ') ;big enough +ldexec_line db 0 ;# of parm characters +ldexec_start db ' ' +ldexec_parm db 80 dup (0) + +instexe exec0 <0,ldexec_line,ldexec_fcb,ldexec_fcb> + +;------------------------------------------------------------------ +;variables for comment= + +com_level db 0 ;level of " " in command line +cmmt db 0 ;length of comment string token +cmmt1 db 0 ;token +cmmt2 db 0 ;token +cmd_indicator db ? +donotshownum db 0 + +;------------------------------------------------------------------ +count dw 0 +org_count dw 0 +chrptr dw 0 +cntryfilehandle dw 0 +old_area dw 0 +impossible_owner_size dw 0 ; paragraph +;------------------------------------------------------------------ + +bucketptr label dword +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 ; 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 ; used to control "error in config.sys line #" message + +toomanydrivesflag db 0 ;>24 fixed disk partitions flag ; M029 + +BCodeSeg dw Bios_Code + + + + +;SR; +; This is the communication block between the DOS and the BIOS. It starts at +;the SysinitPresent flag. Any other data that needs to be communicated +;to the DOS should be added after SysinitPresent. The pointer to this block +;is passed to DOS as part of the DOSINIT call. +; + +BiosComBlock dd Bios_Data:SysinitPresent + +tempstack db 80h dup (?) + +goinit: + +ifdef JAPAN + mov ah,50h ; set crt mode + mov al,0 + mov bx,81 ; for JAPAN + int 10h + mov ah,50h ; set keyboard mode + mov al,0 + mov bx,81 ; for JAPAN + int 16h +endif + cld + +;; Before we installed spckbd.asm (we hook a lot of vectors there), +;; we shouldn't invoke any interrupt calls directly to bios(they will +;; go directly to ROM bios). Since we do know what exactly those ROM +;; bios(s) do, a safer manner is to issue bop to our 32 bits side. +;; int 12h ; Get Memory in 1k + BOP 12h + mov cl,6 + shl ax,cl ;convert to 16-byte blocks(segment no.) + mov cx,ax + dec cx ; one para for an arena at end of mem + ; in case of UMBs + mov memory_size,cx + + push cs + pop ds + xor si,si + mov di,si + mov ax, offset sysinitgrp:SI_end ; need this much room for sysinit + call off_to_para + sub cx,ax + +; we need to leave room for the DOS and for the BIOS +; code above sysinit in memory +; + sub cx,dossize/16 ; leave this much room for DOS + + mov ax,offset BCode_end + call off_to_para ; leave this much room for BIOS code + sub cx,ax + + mov es,cx ; offset where sysinit will be located + mov cx,offset sysinitgrp:SI_end + shr cx,1 ;divide by 2 to get words + rep movsw ;relocate sysinit + + push es ; push relocated segment + mov ax,offset sysin + push ax ; push relocated entry point + + retf ; far jump to relocated sysinit + + +; move the dos to its proper location + +sysin: + assume ds:nothing,es:nothing,ss:nothing + + mov ax, Bios_Data ; point DS to BIOS data + mov ds, ax + + assume ds:Bios_Data + + mov word ptr MoveDOSIntoHMA+2, cs ; set seg of routine to move DOS + mov SysinitPresent, 1 ; flag that MoveDOSIntoHMA can be called + + SVC SVC_ISDEBUG + mov DemInfoFlag, al + + test al,ISDBG_DEBUGGEE + je @f + SAVEREG <bx,dx,es> + mov bx, cs ; current base of BIOS + xor cx, cx + mov dx, current_dos_location; get offset of end of code + sub dx, bios_data ; add in length of data segment + REPT 4 + shl dx, 1 + rcl cx, 1 + endm + + mov ax, SYMOP_LOAD SHL 8 + ID_NTIO + SVC SVC_DEMSYSTEMSYMBOLOP + + mov bx, 1 ; bugbug: Hardcoded segment number + mov ax, ds ; low segment location + mov es, ax ; relocated segment + + mov ax, SYMOP_MOVE SHL 8 + ID_NTIO + SVC SVC_DEMSYSTEMSYMBOLOP + + RESTOREREG <es,dx,bx> +@@: + +; first move the MSDOS.SYS image up to a harmless place +; on top of our new sysinitseg + + mov ax,offset sysinitgrp:SI_end ; how big is sysinitseg? + call off_to_para + mov cx,cs ; pick a buffer for msdos above us + add ax,cx + mov es,ax + xor si,si + mov di,si + + mov ds,[current_dos_location] ; where it is (set by msinit) + + assume ds:nothing + + mov cx,dossize/2 + rep movsw + mov [current_dos_location],es + +; The DOS code is ORGed at a non-zero value to allow it to be located in +; HIMEM. Thus, the DOS segment location must be adjusted accordingly. + + mov ax,ds:word ptr 3 ; get offset of dos + mov [dosinit],ax ; that's the entry point offset + call off_to_para ; subtract this much from segment + sub [current_dos_location],ax + + +; BIOS code is moved to the top of memory +; until it is determined whether it will be running in HIMEM or not. + + +; now put Bios_Code up on top of that. Assume Bios_Code + dossize < 64k + + mov ax,es + add ax,dossize/16 ; get paragraph of end of dos + mov es,ax + xchg ax,temp_bcode_seg ; swap with original home of Bios_Code + mov ds,ax ; point to loaded image of Bios_Code + + assume ds:nothing + + mov si,offset BCode_start + mov di,si + mov cx,offset BCode_end + sub cx,si + shr cx,1 + rep movsw ; move Bios_Code into place + + mov ax,es ; tell it what segment it's in + call [seg_reinit_ptr] ; far call to seg_reinit in Bios_Code (M022) + + +; now call dosinit while it's in its temporary home + + les di,cs:[BiosComBlock] ; ptr to BIOS communication block + lds si,cs:[device_list] ; set for call to dosinit + + assume ds:nothing, es:nothing + + mov dx,cs:[memory_size] ; set for call to dosinit + + call DOCLI + mov ax,cs + mov ss,ax + align 2 ; assembler wouldn't let me do an "and 0fffeh" +locstack label byte ; on the mov sp,offset locstack + mov sp,offset locstack ; set stack + + call DOSTI + + +; This call to DOSINIT will relocate the DOS data from its present location +; at the top of memory, to its final location in low memory just above the +; BIOS data. It will then build important DOS data structures in low +; memory following the DOS data. It returns (among many other things) the +; new starting address of free memory. + + call [dos_temp_location] ; call dosinit + ;es:di -> sysinitvars_ext + + mov [def_php],ds ; save pointer to PSP + mov [hi_doscod_size],ax ; size of doscode (including exepatch) + mov [lo_doscod_size],cx ; (not including exepatch) + mov [dos_segreinit],dx ; save offset of segreinit + + mov ax,word ptr es:[di.sysi_initvars] + 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 + + mov es,[current_dos_location] ; give dos its temporary loc. + mov [dos_segreinit+2],es +; + les di,dosinfo ;es:di -> dosinfo + + clc ;get the extended memory size + +; execute the get extended memory size subfunction in the bios int 15h +; if the function reports an error do nothing else store the extended +; memory size reported at the appropriate location in the dosinfo buffer +; currently pointed to by es:di. use the offsets specified in the +; definition of the sysinitvars struct in inc\sysvar.inc + + mov ah,88h +;; IBM ps/2 90 int 15(ah = 88h) read a coms byte(0B6h) which we don't support. +;; it returns 0 on this query. +;; we issue a bop to 32bits to get the real extended memeory size +;; int 15h ;check extended memory size + BOP 15h +;; jc no_ext_memory + mov es:[di].sysi_ext_mem,ax ;save extended memory size +;; or ax, ax +no_ext_memory: + mov ax,es:[di.sysi_maxsec] ; get the sector size + add ax,bufinsiz ; size of buffer header + mov [singlebuffersize],ax ; total size for a buffer + + SVC SVC_DEMGETBOOTDRIVE + mov [default_drive],al + mov es:[di.sysi_boot_drive],al ; set sysi_boot_drive + +; determine if 386 system... +if 1 + 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 +endif + + mov es:[di.sysi_dwmove],1 +not_386_system: + mov al,es:[di.sysi_numio] + mov drivenumber,al ; save start of installable block drvs + + mov ax,cs + sub ax,11h ; room for PSP we will copy shortly + mov cx,[singlebuffersize] ; temporary single buffer area + shr cx,1 + shr cx,1 ; divide size by 16... + shr cx,1 + shr cx,1 ; ...to get paragraphs... + inc cx ; ... and round up + +; cas note: this unorthodox paragraph rounding scheme wastes a byte if +; [singlebuffersize] ever happens to be zero mod 16. Could this +; ever happen? Only if the buffer overhead was zero mod 16, since +; it is probably safe to assume that the sector size always will be. +; +; mohans also found a bug in CONFIG.SYS processing where it replaces +; EOF's with cr,lf's, without checking for collision with [confbot]. +; perhaps the extra byte this code guarantees is what has kept that +; other code from ever causing a problem??? + + sub ax,cx + mov [confbot],ax ; temp "unsafe" location +; push es ; preserve pointer to DOSINFO data +; push di + +; setup and initialize the temporary buffer + +; les di,es:[di.sysi_buf] ;get the buffer chain entry pointer +; mov word ptr es:[di.Dirty_Buff_Count],0 +; mov word ptr es:[di.Buff_Queue],0 +; mov word ptr es:[di.Buff_Queue+2],ax +; mov es,ax +; xor ax,ax +; mov di,ax ;es:di -> single buffer + +; mov es:[di.buf_next],ax ;points to itself +; mov es:[di.buf_prev],ax ;points to itself + +; mov word ptr es:[di.buf_id],00ffh ;free buffer,clear flag +; mov word ptr es:[di.buf_sector],0 +; mov word ptr es:[di.buf_sector+2],0 + +; pop di ; restore pointer to DOSINFO data +; pop es + + push cs + pop ds + + assume ds:sysinitseg + + call tempcds ; set up cdss so re_init and sysinit + ; can make disk system calls + assume ds:nothing ; tempcds trashes ds + + mov ds,[def_php] ; retreive pointer to PSP returned by DOSINIT + + if not ibmjapver + call re_init ; re-call the bios + endif + + call DOSTI ; 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 ; preserve DS returned by DOSINIT + push cs + pop ds ; point DS to sysinitseg + + assume ds:sysinitseg + + ; set up temp. critical error handler + mov dx,offset int24 ;set up int 24 handler + mov ax,(set_interrupt_vector shl 8) or 24h + int 21h + + cmp byte ptr [TooManyDrivesFlag],0 ;Q: >24 partitions? M029 + je no_err ; N: continue M029 + mov dx,offset TooManyDrivesMsg ; Y: print error message M029 + call print ; M029 +no_err: ; M029 + + pop ds ; start of free memory + + 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 + +nodrvset: + +; +; Process the CONFIG.SYS file +; + +ProcessConfig: + +; +; NTVDM store temp file name for config.sys, 23-Nov-1992 Jonle +; + push ds + push cs + pop ds + assume ds:sysinitseg + mov dx,offset config ; ds:dx points file description + CMDSVC SVC_GETCONFIGSYS + pop ds + assume ds:nothing + + +ifndef TAIWAN + + call doconf ;do pre-scan for dos=high/low + +else ; taiwan + + call chkoemlocaldrv + mov cs:oemdriverinst,ax + call cdosinit + push es + push bx + + pop bx + pop es + call maketempvector ;make dummy int service routine + + call doconf ;do pre-scan for dos=high/low + + call chklocalexist ;check if local dev drv exist + ;if not found,system halt + call recovercsiint ;recover csi interrupt vector +endif ; taiwan + + + +; Now, we decide what to do with the DOS code. +; It will either be relocated to low memory, above the DOS data structures, +; or else it will be located in HiMem, in which case a stub with the DOS +; code entry points will be located in low memory. Dos_segreinit is used +; to tell the DOS data where the code has been placed, and to install the +; low memory stub if necessary. If the DOS is going to go into HiMem, we +; must first initialize it in its present location and load the installable +; device drivers. Then, if a HiMem driver has been located, we can actually +; relocate the DOS code into HiMem. +; + +; M025 begin + + cmp runhigh, 0 ; Did user choose to run low ? + je dont_install_stub ; yes, don't install dos low mem stub +; +;------ user chose to load high +; + + + mov es,[current_dos_location] ; give dos its temporary loc. + + xor ax,ax ; ax = 00 ---> install stub + call cs:dword ptr [dos_segreinit] ; call dos segreinit + jmp short do_multi_pass + +; +;------ User chose to load dos low +; +dont_install_stub: + + xor bx, bx ; M012 + ; don't use int 21 call to alloc mem + + call MovDOSLo ; move it ! + + + mov ax, 1 ; dont install stub + mov es, current_dos_location; set_dos_final_position set it up + call dword ptr dos_segreinit ; inform dos about new seg + + +do_multi_pass: + + call AllocFreeMem ; allocate all the free mem + ; & update [memhi] & [area] + ; start of free memory. + +; M025 end + + + +; NTVDM +; Copy softpc keyboard driver resident code to start of free mem +; Install Softpc IVT hooks + mov al,devmark_spc + call setdevmark + mov es, cs:[devmark_addr] + mov word ptr es:[arena_name], 'BK' + mov word ptr es:[arena_name+2], 'D' + + cld + mov ax,[memhi] + push ds + mov cx,Bios_Data + mov ds,cx + assume ds:Bios_Data + mov word ptr spc_mse_int10,offset int10h_vector + mov word ptr spc_mse_int10+2,ax + mov word ptr int29Perf,offset outchr ; sudeepb 03-Nov-1992 + mov word ptr int29Perf+2,ds ; added for int10 performance + pop ds + assume ds:nothing + + mov es,ax ;es dest seg. for SpcKbd + push es + push cs + pop ds ;ds src seg for SpcKbd + mov si,offset sysinitgrp:SpcKbdBeg + mov cx,offset sysinitgrp:SpcKbdEnd + sub cx,si + xor di,di + mov [memlo],cx + or [setdevmarkflag],for_devmark + call round + rep movsb + pop ds + call sysinitgrp:InstSpcKbd + + ; save value of int09 for int 09 hardware stack disable + xor ax,ax + mov ds,ax + mov si, 09h*4 + lodsw + mov word ptr cs:old09, ax + lodsw + mov word ptr cs:old09+2, ax + + ; save value of int08 for int 08 hardware stack disable + mov si, 08h*4 + lodsw + mov word ptr cs:old08, ax + lodsw + mov word ptr cs:old08+2, ax + + +; NTVDM +; Attempt to init emm memory manager. if we have emm +; then load internal emm stub device driver. +; + ; check if emm memory is available + mov ax, [memhi] + inc ax ;1 para for arena header + mov ds, ax ;expected seg for emm drv + call sysinitgrp:InitSpcEmm + cmp ax, 0 + jne NoEmmServices + + ; fill in the arena name + mov al, devmark_device + call setdevmark + mov es, cs:[devmark_addr] + mov word ptr es:[arena_name], 'ME' + mov word ptr es:[arena_name+2], 'M' + + ; copy in emm stub driver code + cld + mov ax,[memhi] + mov es,ax + push es ;save for diddling devheader + push cs + pop ds + mov si,offset sysinitgrp:SpcEmmBeg + mov cx,offset sysinitgrp:SpcEmmEnd + sub cx,si + xor di,di + mov [memlo],cx + or [setdevmarkflag],for_devmark + call round + rep movsb + + ; link in emm stub driver + ; so apps can find emm driver + pop ds + xor si, si ;ds:si = device header + les di, cs:[dosinfo] ;es:di = to dos info + mov cx,word ptr es:[di.sysi_dev] ;dx:cx = head of list + mov dx,word ptr es:[di.sysi_dev+2] + mov word ptr es:[di.sysi_dev],si ;set head of list in dos + mov word ptr es:[di.sysi_dev+2],ds + mov word ptr ds:[si], cx ;link in the driver + mov word ptr ds:[si+2], dx + +NoEmmServices: + + +; Now, process config.sys some more. +; Load the device drivers and install programs + inc cs:multi_pass_id ; multi_pass_id = 1 + call multi_pass ; load device drivers + + +; NTVDM +; Install Softpc Mouse driver in UMB if can else in LOW memory +; This must be done after himem.sys is loaded for umb support +; + mov cx, offset sysinitgrp:SpcMseEnd + sub cx, offset sysinitgrp:SpcMseBeg ; cx, size of SpceMse + mov di, offset MseDev + push cs + pop es ; es:di, dest + push cx ; preserve cx + call AllocUMBLow + pop cx + push es ; save to pass to InstSpcMse + + mov si, offset sysinitgrp:SpcMseBeg + push cs + pop ds ; ds:si, Source of SpcMse code + rep movsb + + pop ds + call sysinitgrp:InstSpcMse + + + + call ShrinkUMB + call UnlinkUMB ; unlink all UMBs ;M002 + inc cs:multi_pass_id ; multi_pass_id = 2 + call multi_pass ; was load ifs (now does nothing) + call endfile ; setup fcbs, files, buffers etc + +; +;Reset SysinitPresent flag here. This is needed for the special fix for lying +;to device drivers. This has been moved up to this point to avoid problems +;with overlays called from installed programs +; + mov ax,Bios_Data + mov es,ax ; point ES to bios data + + assume es:Bios_Data + + mov es:SysinitPresent,0 ; clear SysinitPresent flag + + test install_flag,have_install_cmd ; are there install commands? + jz dolast ; no, no need for further processing + inc cs:multi_pass_id ; mult_pass_id = 3 + call multi_pass ; execute install= commands +dolast: + assume es:nothing + +; [area] has the segment address for the allocated memory of sysinit, confbot. +; free the confbot area used for config.sys and sysinit itself. + + +; Now if DOS is supposed to run high, we actually move it into high memory +; (if HiMem manager is available). +; +; There is also this little hack for CPM style DOS calls that needs to +; be done when A20 is set... + + cmp runhigh, 0ffh ; are we still waiting to be moved? + jne @f ; no, our job is over + call LoadDOSHiOrLo +@@: + + cmp runhigh, 0 ; are we running low + je @f ; yes, no CPM hack needed + call CPMHack ; make ffff:d0 same as 0:c0 +@@: + + +; We are now done with CONFIG.SYS processing + +ConfigDone: +;; let NTVDM knows that we have done config.sys processing + xor al, al ;config.sys done + BOP BOP_NOTIFICATION ; + call AllocUMB ; allocate remaining UMBs if there are any + mov cs:[donotshownum],1 ; done with config.sys. do not show line number message. + mov es,[area] + + assume es:nothing + + mov ah,49h ; free allocated memory for command.com + int 21h + + test cs:[install_flag],has_installed ; sysinit_base installed? + jz skip_free_sysinitbase ; 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 + push bx + mov es,cs:[old_area] + mov bx,cs:[impossible_owner_size] + mov ah,setblock + int 21h + mov ax,es + dec ax + mov es,ax ;point to arena + mov es:[arena_owner],8 ;set impossible owner + mov word ptr es:[arena_name], 'DS' ; System Data + pop bx + pop es + +skip_free_sysinitbase: + +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 ; noexec + + push cs + pop ds ; point DS to sysinitseg + + 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 dfil ;read in command + jc comerr + mov ds,bp + mov dx,80h + mov ah,set_dma ;set disk tranfer address + int 21h + call DOCLI + mov ss,bp + mov sp,dx + call DOSTI + 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 + retf ;crank up command! + +else ; not noexec + +; 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] ; get location of end of memory + mov ax,cs ; get location of beginning of sysinit + sub bx,ax ; bx is size of sysinit in para + add bx,11h ; add the sysinit php + sub bp,bx ; sub sysinit size from amount of free memory + jc memerrjx ; if there isn't even this much memory, give up + + 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 + call off_to_para + 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 command fit in available mem? + 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 ; point es to sysinitseg + pop es + 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 + extrn badfil:near + call badfil + public stall +stall: SVC SVC_DEMEXITVDM ; Will Kill The VDM + +; +;---------------------------------------------------------------------------- +; procedure : AllocFreeMem +; +; Allocate Max memory from DOS to find out where to load DOS. +; DOS is at temporary location when this call is being made +; +; Inputs : None +; Outputs: The biggest chunk of memory is allocated (all mem at init time) +; [area] & [memhi] set to the para value of the start of the +; free memory. +; +; Uses : AX, BX +; +;---------------------------------------------------------------------------- +; +AllocFreeMem proc near + + assume es:nothing, ds:nothing + 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 + ret + ; start of free memory +AllocFreeMem endp + +; start M000 + include msbio.cl6 +; end M000 + +; +;---------------------------------------------------------------------------- +; +; procedure : LoadDOSHiOrLo +; +; Tries to move DOS into HMA. If it fails then loads +; DOS into Low memory. +; +;---------------------------------------------------------------------------- +; + +LoadDOSHiOrLo proc near + call TryToMovDOSHi ; Try moving it into HMA (M024) + jc LdngLo ; If that don't work... + ret +LdngLo: + push cs + pop ds + mov ah, 9 + mov dx, offset DOSLOMSG ; inform user that we are + int 21h ; loading low + + ; actually move the dos, and reinitialize it. + + mov bx, 1 ; M012 + ; use int 21 alloc for mem + call MovDOSLo + mov es,[current_dos_location] ; give dos its temporary loc. + xor ax,ax ; ax = 00 ---> install stub + call cs:dword ptr [dos_segreinit] ; call dos segreinit + + mov runhigh, 0 ; mark that we are running lo + ret +LoadDOSHiOrLo endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : TryToMovDOSHi +; +; This tries to move DOS into HMA. +; Returns CY if it failed. +; If it succeeds returns with carry cleared. +; +; +;---------------------------------------------------------------------------- +; + + public TryToMovDOSHi + +TryToMovDOSHi proc near + call MovDOSHi + jc ttldhx + + + mov es,[current_dos_location] ; give dos its temporary loc. + + xor ax,ax ; ax = 00 ---> install stub + call cs:dword ptr [dos_segreinit] ; call dos segreinit + + mov runhigh, 1 + clc +ttldhx: + ret +TryToMovDOSHi endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : MovDOSHi +; +; Tries to allocate HMA and Move DOS/BIOS code into HMA +; +; Returns : CY if it failed +; +;---------------------------------------------------------------------------- +; + +MovDOSHi proc near + call AllocHMA + jc mdhx ; did we get HMA? + mov ax, 0ffffh ; yes, HMA seg = 0ffffh + mov es, ax + + ; actually move the BIOS and DOS + + call MovBIOS ; First move BIOS into HMA + + ; ES:DI points to free HMA after BIOS + + mov cx, hi_doscod_size ; pass the code size of DOS + ; when it is in HMA + call MovDOS ; and move it + + ; ES:DI points to free HMA after DOS + + call SaveFreeHMAPtr ; Save the Free HMA ptr + clc +mdhx: + ret +MovDOSHi endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : MovDOSLo +; +; Allocates memory from DOS and moves BIOS/DOS code into it +; +;---------------------------------------------------------------------------- +; + + +MovDOSLo proc near + call AllocMemForDOS ; incestuosly!!! + mov es, ax ; pass the segment to MovBIOS + call MovBIOS +; +;------ ES:DI points memory immediately after BIOS +; + mov cx, lo_doscod_size ; DOS code size when loaded + ; low + call MovDOS + ret +MovDOSLo endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : MovBIOS +; +; Moves BIOS code into requested segment +; +; In : ES - segment to which BIOS is to be moved +; ( it moves always into offset BCode_Start) +; +; Out : ES:DI - pointer to memory immediately after BIOS +; +;---------------------------------------------------------------------------- +; + + +MovBIOS proc near + mov ds, temp_bcode_seg ; current BIOS code seg + mov si, offset BCode_Start + mov di, si + mov cx, offset BCode_End + sub cx, si ; size of BIOS + shr cx, 1 ; Both the labels are para + ; aligned + rep movsw + push es + push di ; save end of BIOS + mov ax, es + mov BCodeSeg, ax ; save it for later use + call [seg_reinit_ptr] ; far call to seg_reinit (M022) + pop di + pop es ; get back end of BIOS + ret +MovBIOS endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : MovDOS +; +; Moves DOS code into requested area +; +; In : ES:DI - pointer to memory where DOS is to be moved +; CX - size of DOS code to be moved +; +; Out : ES:DI - pointer to memory immediately after DOS +; +;---------------------------------------------------------------------------- +; + + +MovDOS proc near + push es + push di + lds si, dos_temp_location ; current location of DOS + rep movsb + pop bx ; get back offset into which + ; DOS was moved + mov ax, dosinit ; get the offset at which DOS + ; wants to run + sub ax, bx + call off_to_para + pop bx ; get the segment at which + ; we moved DOS into + sub bx, ax ; Adjust segment + mov current_dos_location, bx ; and save it + ret +MovDOS endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : AllocMemForDOS +; +; Allocate memory for DOS/BIOS code from DOS !!! +; +; Out : AX - seg of allocated memoryblock +; +;---------------------------------------------------------------------------- +; + + +AllocMemForDOS proc near + mov ax, offset BCode_end + sub ax, offset BCode_start ; BIOS code size + add ax, lo_doscod_size ; + DOS code size + add ax, 15 + call off_to_para ; convert to para + or bx, bx ; M012 + ; can we use int 21 for alloc + mov bx, ax + jz update_arena ; M012 + mov ah, 48h ; request DOS + int 21h + jc FatalErr ; IF ERR WE ARE HOSED + sub ax, 3 ; Take care ORG 30h of + ; BIOS code + mov es, ax + mov word ptr es:[20h+arena_owner], 08h ; mark it as system + mov word ptr es:[20h+arena_name], 'CS' ; code area + ret + +; +; M012 : BEGIN +; +update_arena: + push ds + push di + push cx + push dx + lds di, dosinfo ; get ptr to DOS var + dec di + dec di ; Arena head is immediately + ; before sysvar + mov es, ds:[di] ; es = arena head + mov cx, es:[arena_size] ; cx = total low mem size + cmp cx, bx ; is it sufficient ? + jb FatalErr ; no, fatal error + mov dl, es:[arena_signature] + mov ax, es + add ax, bx ; ax = new arena head + mov ds:[di], ax ; store it in DOS data area + mov ds, ax + mov byte ptr ds:[arena_signature], dl ; type of arena + mov word ptr ds:[arena_owner], 0 ; free + sub cx, bx ; size of the new block + mov word ptr ds:[arena_size], cx ; store it in the arena + mov ax, es ; return seg to the caller + sub ax, 3 ; Take care ORG 30h of + ; BIOS code + pop dx + pop cx + pop di + pop ds + ret +; +; M012 : END +; +FatalErr: + push cs + pop ds + mov dx, offset FEMsg + mov ah, 9h + int 21h + cli + hlt +AllocMemForDOS endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : AllocHMA +; +; grab_the_hma tries to enable a20 and make sure there is memory +; up there. If it gets any sort of error, it will return with +; carry set so that we can resort to running low. +; +; It also returns ES: -> 0ffffh if it returns success +; +;---------------------------------------------------------------------------- +; + +AllocHMA proc near + assume ds:nothing,es:nothing +; +; cas note: The pre-286 check is no longer needed here since the +; presence of XMS is sufficient. However, this code hasn't +; been deleted because it can be recycled for skipping the +; extra pass of CONFIG.SYS and assuming we're running low +; in the case of a pre-286. + +; +;; see if we're running on a pre-286. If not, force low. +; +; xor ax,ax +; pushf ; save flags (like int) +; push ax +; popf +; pushf +; pop ax +; popf ; restore original flags (like int) +; and ax,0f000h +; cmp ax,0f000h ; 8088/8086? +; jz grab_hma_error +; + push ds + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + + call IsXMSLoaded + jnz grabhma_error + + mov ax,4310h + int 2fh ; get the vector into es:bx + mov word ptr xms,bx + mov word ptr xms+2,es + + mov ah,1 ; request HMA + mov dx,0ffffh + call xms + dec ax + jz @f ; error if not able to allocate HMA + +; +;------ Himem may be lying because it has allocated mem for int 15 +; + mov ah, 88h + int 15h + cmp ax, 64 ; less than 64 K of hma ? + jb grabhma_error + +@@: mov ah,5 ; localenableA20 + call xms + dec ax + jnz grabhma_error ; error if couldn't enable A20 + + mov ax,0ffffh + mov es,ax + mov es:word ptr 10h,1234h ; see if we can really read/write there + cmp es:word ptr 10h,1234h + jnz grabhma_error ; don't try to load there if XMS lied + + clc + pop ds + ret + +grabhma_error: + stc + pop ds + assume ds:nothing + ret + +AllocHMA endp + +; +;---------------------------------------------------------------------------- +; +; procedure : IsXMSLoaded +; +; Checks whether a XMS driver is loaded +; +; Returns : Z flag set if XMS driver loaded +; Z flag reset if no XMS drivers are present +; +;---------------------------------------------------------------------------- +; + public IsXMSLoaded + +IsXMSLoaded proc near + mov ax,4300h + int 2fh + cmp al,80h ; XMS installed? + ret +IsXMSLoaded endp + +; +; +;---------------------------------------------------------------------------- +; procedure : FTryToMovDOSHi +; +; Called from HMA suballoc calls +; +;---------------------------------------------------------------------------- +; +; + + public FTryToMovDOSHi +FTryToMovDOSHi proc far + + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + cmp runhigh, 0ffh + jne @f + + call TryToMovDOSHi +@@: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + + ret +FTryToMovDOSHi endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : SaveFreeHMAPtr +; +; Save the Free HMA pointer in BIOS variable for later use. +; (INT 2f ax==4a01 call returns pointer to free HMA) +; Normalizes the pointer to ffff:xxxx format and stores only +; the offset. +; +; Inputs : ES:DI - pointer to free HMA +; Output : FreeHMAPtr in BIOS data segment updated +; +;---------------------------------------------------------------------------- +; +SaveFreeHMAPtr proc near + mov bx, es + mov ax, 0ffffh ; HMA segment + sub ax, bx + add di, 15 ; para round + and di, 0fff0h + mov cl, 4 + shl ax, cl + sub di, ax + push ds + mov ax, Bios_Data + mov ds, ax + assume ds:Bios_Data + mov FreeHMAPtr, di + mov inHMA, 0ffh + pop ds + assume ds:nothing + ret +SaveFreeHMAPtr endp +; +; +;---------------------------------------------------------------------------- +; +; procedure : CPMHack +; +; Copies the code from 0:c0 into ffff:0d0h +; for CPM comatibilty +; +;---------------------------------------------------------------------------- +; +CPMHack proc near + push ds + mov cx, 0ffffH + mov es, cx ; ES = FFFF + xor cx, cx + mov ds, cx ; DS = 0 + mov si, 0c0h + mov di, 0d0h + mov cx, 5 + cld + rep movsb ; move 5 bytes from 0:C0 to FFFF:D0 + pop ds + ret +CPMHack endp + +; +;---------------------------------------------------------------------------- +; +; procedure : off_to_para +; +;---------------------------------------------------------------------------- +; + +off_to_para proc near + shr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + ret +off_to_para endp + + +;** TempCDS - Create (Temporary?) CDS +; +; ENTRY ?? BUGBUG +; (DS) = SysInitSeg +; EXIT ?? BUGBUG +; USES ?? BUGBUG + + public tempcds +Procedure TempCDS + + assume ds:sysinitseg + les di,dosinfo + mov cl,byte ptr es:[di.sysi_numio] + xor ch,ch ; (cx) = # of block devices + mov es:[di.sysi_ncds],cl ; one CDS per device + mov al,cl + mov ah,size curdir_list + mul ah ; (ax) = byte size for those CDSs + call pararound ; (ax) = paragraph size for CDSs + mov si,[confbot] +; BUGBUG - we don't update confbot - won't someone else use it? + 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 ; set address of CDS list + assume ds:nothing + mov es,ax + xor di,di ; (es:di) = address of 1st CDS + + + +;* Initialize our temporary CDSs. +; +; (cx) = count of CDSs left to process +; (si) = 0 based drive being processed +; (es:di) = address of next CDS + +fooset: + xor dx,dx ; indicator to stop removable checks +foogo: + mov ax,word ptr DirStrng + .errnz CURDIR_TEXT ; setup the root as the curdir + stosw + mov ax,word ptr DirStrng+2 + stosw + xor ax,ax + push cx + .errnz CURDIR_FLAGS - CURDIR_TEXT - size CURDIR_TEXT + mov cx,curdir_flags - 4 + rep stosb ; zero out rest of CURDIR_TEXTs + +; Here es:di points to CURDIR_FLAGS + + or dx,dx ; have we found one fixed drive? + jnz fixed_drv2 ; NZ -> yes dont do IOCTL check + + cmp byte ptr DirStrng, 'B' + jbe not_fixed ; 'A' and 'B' are always removable + + mov bl,byte ptr DirStrng + sub bl,'A' + inc bl ; C is 3 + mov ax,4408h + int 21h ; Is drive removable + jc fixed_drv ; Could'nt find means NET hence fixed + or ax,ax + jnz fixed_drv + +not_fixed: + mov ax,CURDIR_LOCAL OR CURDIR_INUSE + jmp short fill_in + + +fixed_drv: + inc dx +fixed_drv2: + mov ax,CURDIR_LOCAL OR CURDIR_INUSE OR CURDIR_NT_FIX + +fill_in: + + FOLLOWS CURDIR_FLAGS,CURDIR_TEXT,2 + stosw ; Save Flags + + mov ax,2 + FOLLOWS CURDIR_END,CURDIR_FLAGS,2 + stosw ; Save CURDIR_END + + inc byte ptr DirStrng + pop cx + loop foogo + mov byte ptr DirStrng,"A" + ret + +EndProc TempCDS + + +;** EndFile - Build DOS structures +; +; This procedure is called after the config.sys has been processed and +; installable device drivers have been loaded (but before "install=" +; programs are loaded) to create the dos structures such as SFTs, buffers, +; FCBs, CDSs, etc. It also loads the sysinit_base module in low memory +; to allow for the safe EXECing of "install=" programs. All memory +; above these structures is deallocated back to DOS. +; +; ENTRY ?? BUGBUG +; EXIT ?? BUGBUG +; USES ?? BUGBUG + + +;------------------------------------------------------------------------------ +; 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. + +; if this procedure has been called to take care of install= command, +; then we have to save es,si registers. + + push ds + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + + cmp multrk_flag,multrk_off1 ;=0,multrack= command entered? + jne multrk_flag_done + or multrk_flag,multrk_on ; default will be on. +multrk_flag_done: + + pop ds + assume ds:nothing + + mov ax,[confbot] + mov [alloclim],ax + + push cs + pop ds + extrn round:near + call round + mov al,[files] + sub al,5 + jbe dofcbs + + push ax + mov al,devmark_files + call setdevmark ; set devmark for sfts (files) + pop ax + 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 + call 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 + call round + mov al,devmark_fcbs ;='x' + call setdevmark + 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 + call 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 cdss +;------------------------------------------------------------------------------ +buf1: + call round + + push ax + mov ax,devmark_cds ;='l' + call setdevmark + pop ax + + les di,dosinfo + mov cl,byte ptr es:[di.sysi_numio] + +;NTVDM Ignore the lastdrive command. There exists only one cds for all +; network drives and dos has already set sysi_numio to be +; num real drives + 1 for all network drives 17-Aug-1992 Jonle +; +; 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 + call round ; check for mem error before initializing + 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 + +doinstallstack: + mov ax,[stack_count] ; stack_count = 0? + or ax,ax ;then,stack size must be 0 too. + jz skipstack ;don't install stack. + +; dynamic relocation of stack code. + + call round ;[memhi] = seg. for stack code + ;[memlo] = 0 + +; set devmark block into memory for mem command +; devmark_id = 's' for stack + + mov al,devmark_stk ;='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 + + push ds ; stick the location of the NextStack entry + mov ax,Bios_Data ; into the Win386 Instance Data tables + mov ds,ax + assume ds:Bios_Data + mov word ptr NextStack,offset nextentry + mov word ptr NextStack+2,es + + mov ax,[memlo] + mov word ptr [stack_addr],ax ;set for stack area initialization + mov word ptr IT_StackLoc,ax ; pass it as Instance Data, too + mov ax,[memhi] ;this will be used by stack_init routine. + mov word ptr [stack_addr+2],ax + mov word ptr IT_StackLoc+2,ax + +; space for internal stack area = stack_count(entrysize + stack_size) + + mov ax,entrysize + add ax,[stack_size] + mul [stack_count] + + mov IT_StackSize,ax ; pass through to Instance Tables + + pop ds ; no more need to access Instance Table + assume ds:nothing + + call pararound ; convert size to pargraphs + add [memhi],ax + or [setdevmarkflag],for_devmark ;to set the devmark_size for stack by round routine. + call 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 +;; go directly to the handle table; donot close any invalid handles + push si + mov ah, Get_Current_PDB ; + int 21h + les si, es:[pdb_jfn_pointer] + mov bx, 2 +rcclloop: + cmp byte ptr es:[bx][si], 0FFh ;skip invalid handle + je skip_the_handle + mov ah,close ; need output so we can print message + int 21h ; in case we can't get new one open. +skip_the_handle: + inc bx + loop rcclloop + pop si + + 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 + call 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 + extrn open_dev:near + call open_dev + + mov dx,offset prndev + mov al,1 ;write only + call open_dev + +;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, msbio 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 +; +; +; Sudeepb 31-Dec-1991 Commented out for NT +if 0 + push ax + push bx + push dx + push es + + mov al,0ffh ;reset h/w by writing to port + mov dx,2f2h ;get starting address + 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 + +;sb secondary global rearm + + mov ax,0f000h ;get machine type + mov es,ax + cmp byte ptr es:[0fffeh],0fch ;q:is it a at type machine + je startrearm ; *if at no need to check + + mov ah,0c0h ;get system configuration + int 15h ; * + jc finishrearm ; *jmp if old rom + +; test feature byte for secondary interrupt controller + + test es:[bx.bios_sd_featurebyte1],scndintcontroller + je finishrearm ;jmp if it is there + +startrearm: + mov al,0ffh ;write any pattern to port + mov dx,6f2h ;get starting address + out dx,al ;out 06f2h,0ffh + inc dx ;bump address + out dx,al ;out 06f3h,0ffh + inc dx ;bump address + out dx,al ;out 06f4h,0ffh + inc dx ;bump address + inc dx ;bump address + out dx,al ;out 06f6h,0ffh + inc dx ;bump address + out dx,al ;out 06f7h,0ffh + +finishrearm: + pop es + pop dx + pop bx + pop ax +endif + +; global rearm end ******************* + +;------------------------------------------------------------------------------ +; allocate sysinit_base for install= command +;------------------------------------------------------------------------------ +; sysinit_base allocation. +; check if endfile has been called to handle install= command. + +set_sysinit_base: + +;-------------------------------------------------------------------------- +;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 ; set devmark for mem command + mov ax,[memhi] + sub ax,[area] + mov [impossible_owner_size],ax ;remember the size in case. + mov al,devmark_inst + call setdevmark + pop ax + + mov di,[memhi] + mov es,di + assume es:nothing + mov word ptr [sysinit_base_ptr+2],di ; save this entry for the next use. + xor di,di + mov word ptr [sysinit_base_ptr],di ; es:di -> destination. + mov si,offset sysinit_base ;ds:si -> source code to be relocated. + mov cx,(offset end_sysinit_base) - (offset sysinit_base) + add [memlo],cx + or cs:[setdevmarkflag],for_devmark + call round ; check mem error. also,readjust memhi for the next use. + rep movsb ; reallocate it. + + mov word ptr [sysinit_ptr],offset sysinitptr ; returing address from + mov word ptr [sysinit_ptr+2],cs ; sysinit_base back to sysinit. + or [install_flag],has_installed ; 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. +;------------------------------------------------------------------------------ + + call round + mov bx,[memhi] + mov ax,[area] + mov [old_area],ax ; 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 + mov word ptr es:[arena_name], 'DS' ; System Data + pop es + + mov bx,0ffffh + mov ah,alloc + int 21h + mov ah,alloc + int 21h ; allocate the rest of the memory + + mov [memhi],ax ; start of the allocated memory + mov [memlo],0 ; 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 + mov bx,[confbot] + sub bx,ax ; confbot - memhi + dec bx ; make a room for the memory block id. + dec bx ; make sure!!!. + mov ah,setblock + int 21h ; this will free (confbot to top of memory) + mov bx,0ffffh + mov ah,alloc + int 21h + mov ah,alloc + int 21h ; allocate (confbot to top of memory) + mov [area],ax ; save allocated memory segment. + ; need this to free this area for command.com. + mov es,[memhi] + mov ah,49h ; free allocated memory. + int 21h ; free (memhi to confbot(=area)) + +endfile_ret: + ret + +; End of "EndFile" DOS structure configuration. + + +;------------------------------------------------------------------------- +; Do_Install_Exec +; +; This procedure is used to EXEC a program being loaded via the +; "install=" mechanism in config.sys. It does this by setting up +; the parameters, and then jumping to sysinit_base, which has been +; setup in low memory. When complete, sysinit_base will jump back +; up to this procedure (if sysinit remains uncorrupted by the installed +; program). + +do_install_exec proc near ; now,handles install= command. + + push si ; 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. + +; es:si -> command line in config.sys. points to the first non blank +;character after =. + + push es + push ds + pop es + pop ds ; es->sysinitseg,ds->confbot seg + assume ds:nothing + mov dx,si ; ds:dx->file name,0 in config.sys image. + + xor cx,cx + cld + mov cs:ldexec_start,' ' ; clear out the parm area + mov di,offset ldexec_parm +installfilename: ; skip the file name + lodsb ; al = ds:si; si++ + cmp al,0 + je got_installparm + jmp installfilename +got_installparm: ; copy the parameters to ldexec_parm + lodsb + mov es:[di],al + cmp al,lf ; line feed? + je done_installparm + inc cl ; # of char. in the parm. + inc di + jmp got_installparm +done_installparm: + mov byte ptr cs:[ldexec_line],cl ; length of the parm. + cmp cl,0 ;if no parm,then + jne install_seg_set ; let the parm area + mov byte ptr cs:[ldexec_start],cr ; starts with cr. +install_seg_set: + mov word ptr cs:0,0 ; make a null environment segment + mov ax,cs ; by overlap jmp instruction of sysinitseg. + +;hkn; the environment pointer is made 0. so the current environment ptr. +;hkn; will be the same as pdb_environ which after dosinit is 0. + + mov cs:[instexe.exec0_environ],0 ; set the environment seg. + + + mov word ptr cs:[instexe.exec0_com_line+2],ax ; set the seg. + mov word ptr cs:[instexe.exec0_5c_fcb+2],ax + mov word ptr cs:[instexe.exec0_6c_fcb+2],ax + call sum_up + mov es:checksum,ax ; save the value of the sum + xor ax,ax + mov ah,exec ; load/exec + mov bx,offset instexe ; es:bx -> parm block. + push es ; save es,ds for load/exec + push ds ; these registers will be restored in sysinit_base. + jmp cs:dword ptr sysinit_base_ptr ; jmp to sysinit_base to execute + ; load/exec function and check sum. + +;j.k. this is the returning address from sysinit_base. + +sysinitptr: ; returning far address from sysinit_base + pop si ; restore si for config.sys file. + push es + push ds + pop es + pop ds ; now ds - sysinitseg,es - confbot + jnc exec_exit_code + + + push si ; error in loading the file for install=. + call badload ; es:si-> path,filename,0. + pop si + jmp short install_exit_ret + +exec_exit_code: + mov ah,4dh + int 21h + cmp ah,3 ;only accept "stay resident" prog. + je install_exit_ret + call error_line ;inform the user + + stc + +install_exit_ret: + ret + +do_install_exec endp + + + +;** ParaRound - Round Up length to paragraph multiple +; +; ParaRound rounds a byte count up to a multiple of 16, then divides +; by 16 yielding a "length in paragraphs" value. +; +; ENTRY (ax) = byte length +; EXIT (ax) = rounded up length in paragraphs +; USES ax, flags + +Procedure ParaRound + + add ax,15 + rcr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + ret + +EndProc ParaRound + + +;------------------------------------------------------------------------------ +; sysinit_base module. +; +; This module is relocated by the routine EndFile to a location in low +; memory. It is then called by SYSINIT to perform the EXEC of programs +; that are being loaded by the "install=" command. After the EXEC call +; completes, this module performs a checksum on the SYSINIT code (at the +; top of memory) to be sure that the EXECed program did not damage it. +; If it did, then this module will print an error message and stop the +; system. Otherwise, it returns control to SYSINIT. +; +; +;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. +; SI_end (byte) - offset vaule of end of sysinit module label +; bigsize (word) - # of word from confbot to SI_end. +; chksum (word) - sum of every byte from confbot to SI_end 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: + mov word ptr cs:sysinit_base_ss,ss ; save stack + mov word ptr cs:sysinit_base_sp,sp + int 21h ; load/exec dos call. + mov ss,word ptr cs:sysinit_base_ss ; restore stack + mov sp,word ptr cs:sysinit_base_sp + pop ds ; restore confbot seg + pop es ; restore sysinitseg + jc sysinit_base_end ; 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 ; otherwise,check if it is good. + cmp es:checksum,ax + je sysinit_base_end + +; memory broken. show "memory allocation error" message and stall. + + mov ah,9 + push cs + pop ds + mov dx,offset mem_alloc_err_msgx - sysinit_base + int 21h + jmp $ ; hang here!!!! + +sysinit_base_end: jmp es:sysinit_ptr ;return back to sysinit module + +sum_up: + +;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 + mov ax,es:confbot + mov ds,ax + xor si,si + xor ax,ax + mov cx,es:config_size ; if config_size has been broken,then this + ;whole test better fail. + shr cx,1 ; make it a word count + jz sum_sys_code ; when config.sys file not exist. +sum1: + add ax,ds:word ptr [si] + inc si + inc si + loop sum1 +;now,sum up sysinit module. +sum_sys_code: + mov si,offset locstack ; starting after the stack. + ; this does not cover the possible stack code!!! + mov cx,offset sysinitgrp:SI_end ; SI_end is the label at the end of sysinit + sub cx,si ; from after_checksum to SI_end + shr cx,1 +sum2: + add ax,es:word ptr [si] + inc si + inc si + loop sum2 + pop ds + ret + +sysinit_base_ss equ $-sysinit_base + dw ? +sysinit_base_sp equ $-sysinit_base + dw ? +mem_alloc_err_msgx: + + include msbio.cl4 ; memory allocation error message + +end_sysinit_base label byte + +;------------------------------------------------------------------------------ +; ibmstack initialization routine. + if stacksw +.sall +; +; to follow the standard interrupt sharing scheme, msstack.asm +; has been modified. this initialization routine also has to +; be modified because for the interrupt level 7 and 15, firstflag +; should be set to signal that this interrupt handler is the +; first handler hooked to this interrupt vector. +; we determine this by looking at the instruction pointed by +; this vector. if it is iret, then this handler should be the +; first one. in our case, only the interrupt vector 77h is the +; interrupt level 15. (we don't hook interrupt level 7.) +; +; the followings are mainly due to m.r.t; ptm fix of p886 12/3/86 +; some design changes are needed to the above interrupt sharing +; method. the above sharing scheme assumes that 1). interrupt +; sharing is never done on levels that have bios support. 2). "phantom" +; interrupts would only be generated on levels 7 and 15. +; these assumptions are not true any more. we have to use the firstflag +; for every level of interrupt. we will set the firstflag on the following +; conditions: +; +; a. if the cs portion of the vector is 0000, then "first" +; b. else if cs:ip points to valid shared header, then not "first" +; c. else if cs:ip points to an iret, then "first" +; d. else if cs:ip points to dummy, then "first" +; +; where dummy is - the cs portion must be f000, and the ip portion must +; be equal to the value at f000:ff01. this location is the initial value +; from vector_table for interrupt 7, one of the preserved addresses in all +; the bioses for all of the machines. +; +; system design group requests bios to handle the phantom interrupts. +; +; the "phantom" interrupt is an illegal interrupt such as an interrupt +; produced by the bogus adapter card even without interrupt request is +; set. more specifically, 1). the 8259 has a feature when running in +; edge triggered mode to latch a pulse and present the interrupt when +; the processor indicates interrupt acknowledge (inta). the interrupt +; pulse was exist at the time of inta to get a "phantom" interrupt. +; 2). or, this is caused by adapter cards placing a glitch on the +; interrupt line. +; +; to handle those "phantom" interrupts, the main stack code will check +; the own firstflag, and if it is not "first" (which means the forward +; pointer points to the legal shared interrupt handler), then pass the +; control. if it is the first, then the following action should be +; taken. we don't have to implement skack logic in this case. +; +; to implement this logic, we rather choose a simple method. +; if ont of the above "firstflag" conditions is met, we are not +; going to hook this interrupt vector. the reason is if the original +; vector points to "iret" and do nothing, we don't need +; to implement the stack logic for it. this will simplify implementation +; while maintaining compatibility with the old version of dos. +; this implies that in the main stack code, there might be a stack code +; that will never be used, a dead code. +; +;in - cs, ds -> sysinitseg, es -> relocated stack code & data. + + page + assume ds:sysinitseg +stackinit proc near + + push ax + push ds + push es + push bx + push cx + push dx + push di + push si + push bp + +;currently es -> stack code area + + mov ax, cs:[stack_count] ;defined in cs + mov es:[stackcount], ax ;defined in stack code area + mov ax, [stack_size] ;in cs + mov es:[stacksize], ax + mov ax, word ptr cs:[stack_addr] ; offset + mov word ptr es:[stacks], ax + mov ax, word ptr cs:[stack_addr+word] ; segment + mov word ptr es:[stacks+word], ax + +; initialize the data fields with the parameters + +; "firstentry" will always be at stacks + + mov bp, word ptr es:stacks ; get offset of stack + mov es:firstentry,bp + +; the stacks will always immediately follow the table entries + + mov ax,entrysize + mov cx,es:stackcount + mul cx + add ax,bp + mov es:stackat,ax + mov bx,ax + sub bx,2 + +; zero the entire stack area to start with + + mov di,es:stackat + mov ax,es:stacksize + mul cx + mov cx,ax + xor ax,ax + push es + pop ds ;ds = relocated stack code seg. + assume ds:nothing + +;now, ds -> stack code area + + mov es, word ptr ds:[stacks+2] ; get segment of stack area. + cld + rep stosb + + mov cx, ds:stackcount + +; loop for "count" times, building a table entry +; cs = sysinitseg, ds = relocated stack code seg , es = segment of stack space +; cx = number of entries +; es:bp => base of stacks - 2 +; es:bx => first table entry + +buildloop: + mov es:byte ptr allocbyte[bp],free + mov es:byte ptr intlevel[bp],al ;ax = 0 + mov es:word ptr savedsp[bp],ax + mov es:word ptr savedss[bp],ax + add bx,ds:stacksize + mov es:word ptr newsp[bp],bx + mov es:[bx],bp + add bp,entrysize + + loop buildloop + + sub bp,entrysize + mov ds:lastentry,bp + mov ds:nextentry,bp + +; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle +; push ds +; mov ax, 0f000h ;look at the model byte +; mov ds, ax +; cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? +; pop ds +; jne skip_disablenmis +; +; mov al,07h ; disable convertible nmis +; out 72h,al +; +;skip_disablenmis: + + xor ax,ax + mov es,ax ;es - segid of vector table at 0 + assume es:nothing ;ds - relocated stack code segment + + call DOCLI + + irp aa,<02,70> + + mov si,aa&h*4 ;pass where vector is to be adjusted + mov di, offset int19old&aa ;we have to set old&aa for int19 handler too. + mov bx,offset old&aa ;pass where to save original owner pointer + mov dx,offset int&aa ;pass where new handler is + call new_init_loop ;adjust the vector to new handler, + ; saving pointer to original owner + endm + + + ; NTVDM int 08, 09, special handling 24-Jan-1993 Jonle + ; + ; These Ints are usually done in the macro above with int 02,70 + ; However, we don't need stack swapping as long as no device + ; driver has hooked it. These ints are also left alone so that + ; softpc will know if they have been hooked by an app. + + mov si, 09h*4 + mov ax, word ptr es:[si+0] + cmp word ptr old09, ax + jne do_I9StkSwap + mov ax, word ptr es:[si+2] + cmp word ptr old09+2, ax + je skip_I9StkSwap +do_I9StkSwap: + mov di, offset int19old09 + mov bx,offset old09 + mov dx,offset int09 + call new_init_loop +skip_I9StkSwap: + + mov si, 08h*4 + mov ax, word ptr es:[si+0] + cmp word ptr old08, ax + jne do_I8StkSwap + mov ax, word ptr es:[si+2] + cmp word ptr old08+2, ax + je skip_I8StkSwap +do_I8StkSwap: + mov di, offset int19old08 + mov bx,offset old08 + mov dx,offset int08 + call new_init_loop +skip_I8StkSwap: + + + irp aa,<0a,0b,0c,0d,0e,72,73,74,76,77> ;shared interrupts + + mov si,aa&h*4 ;pass where vector is to be adjusted + push ds ;save relocated stack code segment + lds bx, es:[si] ;ds:bx -> original interrupt handler + push ds + pop dx ;dx = segment value + + 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. + pop ds + mov di, offset int19old&aa ;we have to set old&aa for int19 handler too. + mov bx, offset old&aa ;pass where to save original owner pointer + mov dx, offset int&aa ;pass where new handler is + call new_init_loop ;adjust the vector to new handler, saving + ;pointer to original owner. + jmp short int&aa&_end +int&aa&_first: ;the first. don't have to hook stack code. + pop ds +int&aa&_end: + + endm + +; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle +; push ds +; mov ax, 0f000h ;loook at the model byte +; mov ds, ax +; cmp ds:byte ptr [0fffeh], mdl_convert ;pc convertible? +; pop ds +; jne skip_enablenmis +; +; mov al,27h ; enable convertible nmis +; out 72h,al +; +; skip_enablenmis: + + call DOSTI + mov ax,Bios_Data + mov ds,ax + assume ds:Bios_Data + + + mov [int19sem],1 ; indicate that int 19 + ; initialization is complete + + pop bp ; restore all + pop si + pop di + pop dx + pop cx + pop bx + + pop es + pop ds + assume ds:sysinitseg + + pop ax + ret +stackinit endp + +new_init_loop proc near + +;input: si=ofset into vector table of the particular int vector being adjusted +; bx=ds:offset of oldxx, where will be saved the pointer to original owner +; dx=ds:offset of intxx, the new interrupt handler +; di=offset value of int19old&aa variable in bios. +; es=zero, segid of vector table +; ds=relocated stack code segment + + mov ax,es:[si+0] ;remember offset in vector + mov word ptr ds:[bx],ax ; to original owner in ds + mov ax,es:[si+2] ;remember segid in vector + mov word ptr ds:[bx]+2,ax ; to original owner in ds + + push ds + mov ax,Bios_Data + mov ds,ax ;set int19oldxx value in bios for + mov ax,es:[si+0] ;int 19 handler + mov word ptr ds:[di],ax + mov ax,es:[si+2] + mov word ptr ds:[di]+2,ax + pop ds + + mov word ptr es:[si+0],dx ;set vector to point to new int handler + mov es:[si+2],ds + ret +new_init_loop endp + + +.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 + push cx + + mov cx,cs:[memhi] + mov cs:[devmark_addr],cx + mov es,cx + mov es:[devmark_id],al + inc cx + mov es:[devmark_seg],cx + + pop cx + pop es + inc cs:[memhi] + ret +setdevmark endp + + + ifdef TAIWAN + +;--------------------- +; entry : none +; exit : ax = 0 --> oem local driver not found +; = 1 --> oem local driver found +; destore : ds,es,bx,cx,dx,si,di +; description : +; search config.sys to find oem local driver. +; oem local driver should in \csi\driver\ directory . +; if (found oem local driver in config.sys) +; ax=1; +; else +; ax=0; +; return; +; ps. please see state diagram for state description. +;--------------------- + +chkoemlocaldrv proc near + push es + push ds + push bx + push cx + push dx + push di + push si + call chkconfig + pop si + pop di + pop dx + pop cx + pop bx + pop ds + pop es + ret +chkoemlocaldrv endp + +config_sys db "C:\CONFIG.SYS",0 +sizeofconfig dw 0 +filehandle dw 0 +workingmemptr dw 0 +deviceid db "DEVICE" +csidrvid db "CSI\DRIVER\" +localdrvname dw 0 +chkconfig proc near + call preprocess + jnc initstate + jmp notfoundret + +; +; processing config.sys +; +; state 0 +; ds:si --> current line ( end of line is oah or 0dh ) + +initstate: + mov si,dx +state_0: + push cs + pop es + mov di,offset deviceid + mov cx,3 + repz cmpsw + jz state_1 + mov ax,0ffffh + jmp state_10 +state_1: + lodsb + cmp al,' ' + jz state_1 + cmp al,'=' + jz state_2 +state_10a: + jmp state_10 +state_2: + lodsb + cmp al,' ' + jz state_2 + cmp al,'\' + jz state_5 + cmp al,'A' + jb state_10a + cmp al,'z' + ja state_10a +state_3: + dec si + mov cs:[localdrvname],si + inc si +state_4: + lodsb + cmp al,':' + jz state_6 + jmp state_10 +state_5: + dec si + mov cs:[localdrvname],si + inc si + jmp state_7 +state_6: + lodsb + cmp al,'\' + jz state_7 + cmp al,'c' + jne state_10a + inc si +state_7: + mov di,offset csidrvid + mov cx,11 + repz cmpsb + jnz state_10a +state_8: + lodsb + cmp al,'1' + jb state_10 + cmp al,'z' + ja state_10 +state_9: +tryopenlocaldrv: + mov dx,cs:[localdrvname] + mov si,dx +chknextbyte: + lodsb + cmp al,0h + jz openfile + cmp al,' ' + jne chknextbyte + dec si + mov byte ptr ds:[si],0 +openfile: + mov ax,3d00h ; open config.sys + stc + int 21h + jc notfoundret + mov bx,ax ; bx = file handle + mov ah,3eh + int 21h ; close local driver + jc notfoundret + jmp foundret + +state_10: + cmp al,1ah ; look current char. == eof ? + jz notfoundret + lodsb + cmp al,0 + jz newlinestate + cmp al,1ah + jz notfoundret + jmp state_10 +newlinestate: + lodsb + cmp al,1ah + jz notfoundret + cmp al,0 + jz newlinestate + dec si + jmp state_0 +notfoundret: + mov ax,0 + jmp freemem +foundret: + mov ax,1 +freemem: + push ax + call freememory + pop ax + ret + +chkconfig endp + +preprocess proc near + push cs + pop ds + mov dx,offset config_sys + mov ax,3d00h ; open config.sys + stc + int 21h + jc errorfile + +; get size of config.sys + + mov bx,ax ; bx = file handle + mov cs:[filehandle],bx + xor cx,cx + xor dx,dx + mov ax,4202h ; move file ptr + int 21h + mov cs:[sizeofconfig],ax ; ax == size of config.sys + xor dx,dx ; ignore more than 64k of config + mov ax,4200h ; mov file ptr to beginning of file + int 21h + +; allocate for config.sys + + mov ax,cs:[sizeofconfig] + add ax,15 ; change to para + rcr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + add ax,20h + mov bx,ax ; size of memory in para + mov ah,48h + int 21h + jc memerr + ; ax --> free memory + mov cs:[workingmemptr],ax + +; read config.sys + + mov bx,cs:[filehandle] ; file handle + mov cx,cs:[sizeofconfig] ; byte count of reading + xor dx,dx + mov ds,ax ; ds:dx --> buffer + mov ah,3fh + int 21h + jc errorfile + +; translate to upper case + + call transtoupper + clc + ret +errorfile: +memerr: + stc + ret +preprocess endp + +; entry : ds:dx --> buffer +; exit : none +; description : translate all letter in buffer to upper type +; ps ,don't change ds:dx + +transtoupper proc near + cld + mov cx,cs:[sizeofconfig] + mov si,dx +transnext: + lodsb + cmp al,'A' + jb chklfcr + cmp al,'z' + ja chkcounter + sub al,'a'-'A' + mov ds:[si-1],al + jmp chkcounter +chklfcr: + cmp al,0dh + jz setzero + cmp al,0ah + jz setzero + jmp chkcounter +setzero: + mov al,0 + mov ds:[si-1],al +chkcounter: + loop transnext + ret +transtoupper endp + +;entry : none ( free memory block ptr in [workingmem] ) +;exit : none + +freememory proc near + mov ax,cs:[workingmemptr] + mov es,ax + mov ah,49h + int 21h + ret +freememory endp + + +; name : maketempvector +; entry : es:bx --> +; dd original int 9 vector ( offfset ,segment ) +; dd original int 10h vector ( offfset ,segment ) +; dd original int 16h vector ( offfset ,segment ) +; +; exit : none +; description : 1. save local driver table in static area +; 2. make temp. vector for int9 ,10h ,16h +; +oemdriverinst dw 0 +orgvectblptr dd 0 + + db 0eah +dummyint9 dd 0 + db 0eah +dummyint10h dd 0 + db 0eah +dummyint16h dd 0 + +csiint9 dd 0 +csiint10h dd 0 +csiint16h dd 0 + +maketempvector proc near + push ds + push ax + push di + push si + push cx + +; save table ptr + + mov word ptr cs:[orgvectblptr],bx + mov word ptr cs:[orgvectblptr+2],es + cmp cs:oemdriverinst,0 + jnz ignoreint9 + +; make temp. vector for int 9 , + + mov bx,9 ; int # + push cs + pop es + mov di,offset csiint9 ; es:di --> store area for csi vector + push cs + pop ds + mov si,offset dummyint9 ; ds:si --> dummy int service + call dummyvector + +ignoreint9: + +; make temp. vector for int 10h + + mov bx,10h ; int # + push cs + pop es + mov di,offset csiint10h ; es:di --> store area for csi vector + push cs + pop ds + mov si,offset dummyint10h ; ds:si --> dummy int service + call dummyvector + +; make temp. vector for int 16h + + mov bx,16h ; int # + push cs + pop es + mov di,offset csiint16h ; es:di --> store area for csi vector + push cs + pop ds + mov si,offset dummyint16h ; ds:si --> dummy int service + call dummyvector + pop cx + pop si + pop di + pop ax + pop ds + ret + + +maketempvector endp + +;name : dummyvector +; entey : ds:si --> dummy int sevice routine +; es:di --> point to csi vector store area +; bx == int number +; exit : none +; description : +; setting dummy vector of int 9 ,10h,16h +; for recover csi vector +; /* phase 1*/ +; [ds:si]=[0:bx*4] +; [ds:si+2]=[0:bx*4+2] +; /* phase 2*/ +; [es:di]=[0:bx*4] +; [es:di+2]=[0:bx*4+2] +; /* phase 2*/ +; [0:bx*4]=si-1; +; [0:bx*4+2]=ds; + +dummyvector proc near + shl bx,1 ; bx <- bx*4 + shl bx,1 ; ie ,get offset of vector + +; phase 1 +; es --> 0 +; es:bx --> cpu int vector table + + xor ax,ax + push es + mov es,ax + mov ax,es:[bx] ; get offset ds-->0 + mov ds:[si],ax ; store offset + mov ax,es:[bx+2] ; get offset ds-->0 + mov ds:[si+2],ax ; store segment + pop es + +; phase 2 +; ds --> 0 +; ds:bx --> cpu int vector table + + xor ax,ax + push ds + mov ds,ax + mov ax,ds:[bx] ; get offset + mov es:[di],ax ; store offset + mov ax,ds:[bx+2] ; get offset + mov es:[di+2],ax ; store segment + pop ds + +; phase 3 +; es --> 0 +; es:bx --> cpu int vector table + + xor ax,ax + push es + mov es,ax + dec si + mov es:[bx],si + mov ax,ds + mov es:[bx+2],ax + pop es + ret +dummyvector endp + +; name : recovercsiint +; entry : none +; exit :none +; description : +; recover int 9 ,10h,16h ,for csi vector + +recovercsiint proc near + push es + push ds + push ax + push bx + push cx + push dx + push si + push di + +;recover int 9 + + cmp cs:oemdriverinst,0 + jnz ignoreint9recover + + push cs + pop ds + mov si,offset dummyint9 + push cs + pop es + + mov di,offset csiint9 + mov bx,9 + mov ax,0 + call recoverint +ignoreint9recover: + +; recover int 10h + + push cs + pop ds + mov si,offset dummyint10h + push cs + pop es + mov di,offset csiint10h + mov bx,10h + mov ax,0+4 + call recoverint + +;recover int 16h + + push cs + pop ds + mov si,offset dummyint16h + push cs + pop es + mov di,offset csiint16h + mov bx,16h + mov ax,0+4+4 + call recoverint + pop di + pop si + pop dx + pop cx + pop bx + pop ax + pop ds + pop es + ret +recovercsiint endp + +; name : recoverint +; entey : ds:si --> dummy int sevice routine +; es:di --> point to csi vector store area +; bx == int number +; ax == 0 ; int 9 +; 4 ; int 10h +; 4+4 ; int 16h +; exit : none +; description : +; 1. if( [0:bx*4] == si-1 .and. [es:bx*4+2] == ds ) +; { +; [0:bx*4] = [es:di]; +; [0:bx*4+2] = [es:di+2]; +; } +; else +; { +; /* phase 1 */ +; [ds:si] = [(*orgvectblptr)+ax] +; [ds:si+2]= [(*orgvectblptr)+ax+2]; +; /* phase 2 */ +; [orgvectblptr+ax) ]=[0:bx*4] ; +; [orgvectblptr+ax+2 ]=[0:bx*4+2] ; +; /* phase 3 */ +; [0:bx*4] = [es:di]; +; [0:bx*4+2] = [es:di+2]; +; +; +; } + +; + +recoverint proc near +;chek vector change ? +; es --> 0 + + push es + mov cx,ax + xor ax,ax + mov es,ax + shl bx,1 + shl bx,1 ; es:bx --> cpu int vector + mov ax,si + dec ax + cmp es:[bx],ax ; offset same ? + jne vectorbechanged + + mov ax,ds + cmp es:[bx+2],ax ; segmnet same ? + jne vectorbechanged + pop es + +; vector not be changed +; ds --> 0 + + xor ax,ax + mov ds,ax ; ds:bx --> cpu int vector + mov ax,es:[di] + mov ds:[bx],ax + mov ax,es:[di+2] + mov ds:[bx+2],ax + ret + +vectorbechanged: + +;phase 1 +; di:es --> addres of local driver + + pop es + push di + push es + mov di,word ptr cs:[orgvectblptr] + mov es,word ptr cs:[orgvectblptr+2] + add di,cx + mov ax,es:[di] + mov ds:[si],ax + mov ax,es:[di+2] + mov ds:[si+2],ax + +;phase2 +; di:es --> addres of local driver +; ds --> 0 + + push ds + xor ax,ax + mov ds,ax + mov ax,ds:[bx] ; ds:bx --> cpu int vector + mov es:[di],ax + mov ax,ds:[bx+2] + mov es:[di+2],ax + pop ds + pop es + pop di + +;phase3 +; ds --> 0 + + xor ax,ax + push ds + mov ds,ax + mov cx,es:[di] + mov ds:[bx],cx ; ds:bx --> cpu int vector + mov cx,es:[di+2] + mov ds:[bx+2],cx + pop ds + ret + +recoverint endp + +;name : chklocalexist +;entry : none +;exit :none +; descriptin : check local driver exist ? +; if not exist system halt ! +; otherwise null return + +chklocalexist proc near + push ax + push cx + push dx + mov ah,0dbh + mov al,80h ; module_extsysutil + mov cx,01 ; syscmd_extquerysysmode + int 16h + test ax,8000h ; bit 15 on + jnz csisystemerror ; no,system halt + ; yes ,dx == country id + push dx ; save current id + mov dx,58h + mov ah,0dbh + mov al,80h ; module_extsysutil + mov cx,02 ; syscmd_extsetsysmode + int 16h + test ax,8000h ; bit 15 on + jnz localdrvnotfound ; no ,local driver error + + pop cx + cmp cx,dx ; current id == previous id ? + jnz localdrvnotfound ; no ,local driver error + + pop dx + pop cx + pop ax + ret + +localdrvnotfound: +csisystemerror: + push cs + pop ds + mov dx,offset bootfailmsg + mov ah,9 + int 21h + cli + hlt + ret + +chklocalexist endp + endif + +sysinitseg ends + end diff --git a/private/mvdm/softpc.new/bios/sysinit2.asm b/private/mvdm/softpc.new/bios/sysinit2.asm new file mode 100644 index 000000000..3439dd2ed --- /dev/null +++ b/private/mvdm/softpc.new/bios/sysinit2.asm @@ -0,0 +1,1609 @@ + page ,160 +title bios system initialization + +; +;---------------------------------------------------------------------------- +; +; Modification history +; +; 26-Feb-1991 sudeepb Ported for NT DOSEm +;---------------------------------------------------------------------------- + + + include version.inc ; set version build flags + include biosseg.inc ; establish bios segment structure + +lf equ 10 +cr equ 13 +tab equ 9 + +; the following depends on the positions of the various letters in switchlist + +switchnum equ 11111000b ; which switches require number + + include syscall.inc + include doscntry.inc + include devsym.inc + include ioctl.inc + include devmark.inc ; needed + + +stacksw equ true ;include switchable hardware stacks + + if ibmjapver +noexec equ true + else +noexec equ false + endif + + +sysinitseg segment public + +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 dosinfo: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 + extrn setdevmarkflag:byte + extrn org_count:word + + extrn pararound:near + extrn getchr:near + extrn stall:near + extrn error_line:near + + extrn DevEntry:dword + + insert_blank db 0 ; M051: indicates that blank has been + ; M051: inserted + + public int24,open_dev,organize,mem_err,newline,calldev,badload + public prndev,auxdev,config,commnd,condev,getnum,badfil,prnerr + public round,delim,print + public parseline, + public setdoscountryinfo,set_country_path,move_asciiz + public cntry_drv,cntry_root,cntry_path + public delim + public pathstring + + public MseDev ; NTVDM internal mouse driver + + + +; +;---------------------------------------------------------------------------- +; +; procedure : parseline +; +; entry point is parseline. al contains the first character in command line. +; +;---------------------------------------------------------------------------- +; + +parseline proc near + ; 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: + call getchr + jc done_line + jmp nextswtch + +swterr: + jmp short 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 + +parseline endp + +; +;---------------------------------------------------------------------------- +; +; procedure : check_switch +; +; 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 proc near + + call 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 + + call getchr + jc err_swtch + + cmp al,':' + jnz err_swtch + + call 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 + +check_switch endp + +; +;---------------------------------------------------------------------------- +; +; procedure : process_num +; +; 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 proc near + 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 + +; 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 + +process_num endp + +; +;---------------------------------------------------------------------------- +; +; procedure : organize +; +;---------------------------------------------------------------------------- +; + assume ds:nothing, es:nothing +organize proc near + + 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 + jz end_commd_line ; found a comment string and skipped. + call get2 ; not a comment string. then get a char. + cmp al, lf + je end_commd_line ; starts with a blank line. + cmp al, ' ' + jbe org1 ; skip leading control characters + jmp short findit + +end_commd_line: + stosb ; store line feed char in buffer for the linecount. + mov com_level, 0 ; reset the command level. + jmp org1 + +nochar1: + stc + ret + +findit: + 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 ;the next char might be cr,lf + je gotcom0 ; such as in "rem",cr,lf case. + cmp byte ptr es:[di], lf + je gotcom0 + push ax + mov al, byte ptr es:[di] ;now the next char. should be a delim. + call delim + pop ax + jnz findcom +gotcom0: + pop di + pop si + pop cx + jmp short gotcom + +nocom: + pop di + pop si + pop cx + mov al,'Z' + stosb ; save indicator char. +skip_line: + call get2 + cmp al, lf ; skip this bad command line + jne skip_line + jmp end_commd_line ; handle next command line + +gotcom: stosb ;save indicator char in buffer + mov cmd_indicator, al ; save it for the future use. + +org2: call get2 ;skip the commad name until delimiter + cmp al, lf + je org21 + cmp al, cr + je org21 + + call delim + jnz org2 + jmp short org3 + +org21: ;if cr or lf then + dec si ; undo si, cx register + inc cx ; and continue + +org3: + cmp cmd_indicator, 'Y' ; comment= command? + je get_cmt_token + cmp cmd_indicator, 'I' ; install= command? + je org_file + cmp cmd_indicator, 'D' ; device= command? + je org_file + cmp cmd_indicator, 'S' ; shell= is a special one!!! + je org_file + cmp cmd_indicator, '1' ; switches= command? + je org_switch + + jmp org4 + +org_switch: + call skip_comment + jz end_commd_line_brdg + + call get2 + call org_delim + jz org_switch + + stosb + jmp org5 + +org_file: ; get the filename and put 0 at end, + call skip_comment + jz org_put_zero + + call get2 ; not a comment + call delim + jz org_file ; skip the possible delimeters + + stosb ; copy the first non delim char found in buffer + +org_copy_file: + call skip_comment ; comment char in the filename? + jz org_put_zero ; then stop copying filename at that point + + call get2 + cmp al, '/' ; a switch char? (device=filename/xxx) + je end_file_slash ; this will be the special case. + + stosb ; save the char. in buffer + call delim + jz end_copy_file + + cmp al, ' ' + ja org_copy_file ; keep copying + jmp short end_copy_file ; otherwise, assume end of the filename. + +get_cmt_token: ; get the token. just max. 2 char. + call get2 + cmp al, ' ' ; skip white spaces or "=" char. + je get_cmt_token ; (we are allowing the other special + cmp al, tab ; charaters can used for comment id. + je get_cmt_token ; character.) + cmp al, '=' ; = is special in this case. + je get_cmt_token + cmp al, cr + je get_cmt_end ; cannot accept the carridge return + cmp al, lf + je get_cmt_end + + mov cmmt1, al ; store it + mov cmmt, 1 ; 1 char. so far. + call get2 + cmp al, ' ' + je get_cmt_end + cmp al, tab + je get_cmt_end + cmp al, cr + je get_cmt_end + cmp al, lf + je end_commd_line_brdg + + mov cmmt2, al + inc cmmt + +get_cmt_end: + call get2 + cmp al, lf + jne get_cmt_end ; skip it. + +end_commd_line_brdg: jmp end_commd_line ; else jmp to end_commd_line + +org_put_zero: ; make the filename in front of + mov byte ptr es:[di], 0 ; the comment string to be an asciiz. + inc di + jmp end_commd_line ; (maybe null if device=/*) + +end_file_slash: ; al = "/" option char. + mov byte ptr es:[di],0 ; make a filename an asciiz + inc di ; and + stosb ; store "/" after that. + jmp short org5 ; continue with the rest of the line + +end_copy_file: + mov byte ptr es:[di-1], 0 ; make it an asciiz and handle the next char. + cmp al, lf + je end_commd_line_brdg + jmp short org5 + +org4: ; org4 skips all delimiters after the command name except for '/' + call skip_comment + jz end_commd_line_brdg + + call get2 + call org_delim ; skip delimiters except '/' (mrw 4/88) + jz org4 + jmp short org51 + +org5: ; rest of the line + call skip_comment ; comment? + jz end_commd_line_brdg + call get2 ; not a comment. + +org51: + stosb ; copy the character + cmp al, '"' ; a quote ? + je at_quote + cmp al, ' ' + ja org5 + ; M051 - Start + + cmp cmd_indicator, 'U' ; Q: is this devicehigh + jne not_dh ; N: + cmp al, lf ; Q: is this line feed + je org_dhlf ; Y: stuff a blank before the lf + cmp al, cr ; Q: is this a cr + jne org5 ; N: + mov byte ptr es:[di-1], ' ' ; overwrite cr with blank + stosb ; put cr after blank + inc [insert_blank] ; indicate that blank has been + ; inserted + jmp org5 +not_dh: ; M051 - End + + cmp al, lf ; line feed? + je org1_brdg ; handles the next command line. + jmp org5 ; handles next char in this line. + +org_dhlf: ; M051 - Start + cmp [insert_blank], 1 ; Q:has a blank already been inserted + je org1_brdg ; Y: + mov byte ptr es:[di-1], ' ' ; overwrite lf with blank + stosb ; put lf after blank + ; M051 - End + +org1_brdg: + mov [insert_blank], 0 ; M051: clear blank indicator for + ; M051: devicehigh + jmp org1 + +at_quote: + cmp com_level, 0 + je up_level + mov com_level, 0 ; reset it. + jmp org5 + +up_level: + inc com_level ; set it. + jmp org5 + +organize endp + +; +;---------------------------------------------------------------------------- +; +; procedure : get2 +; +;---------------------------------------------------------------------------- +; +get2 proc near + jcxz noget + mov al,es:[si] + inc si + dec cx +od_ret: + ret +noget: + pop cx + mov count,di + mov org_count, di + xor si,si + mov chrptr,si +ng_ret: + ret +get2 endp + + +; +;---------------------------------------------------------------------------- +; +; procedure : skip_comment +; +;skip the commented string until lf, if current es:si-> a comment string. +;in) es:si-> sting +; cx -> length. +;out) zero flag not set if not found a comment string. +; zero flag set if found a comment string and skipped it. al will contain +; the line feed charater at this moment when return. +; ax register destroyed. +; if found, si, cx register adjusted accordingly. +; +;---------------------------------------------------------------------------- +; +skip_comment proc near + + jcxz noget ; get out of the organize routine. + cmp com_level, 0 ; only check it if parameter level is 0. + jne no_commt ; (not inside quotations) + + cmp cmmt, 1 + jb no_commt + + mov al, es:[si] + cmp cmmt1, al + jne no_commt + + cmp cmmt, 2 + jne skip_cmmt + + mov al, es:[si+1] + cmp cmmt2, al + jne no_commt + +skip_cmmt: + jcxz noget ; get out of organize routine. + mov al, es:[si] + inc si + dec cx + cmp al, lf ; line feed? + jne skip_cmmt + +no_commt: + ret + +skip_comment endp + +; +;---------------------------------------------------------------------------- +; +; procedure : delim +; +;---------------------------------------------------------------------------- +; +delim proc near + cmp al,'/' ; ibm will assume "/" as an delimeter. + jz delim_ret + + cmp al, 0 ; special case for sysinit!!! + jz delim_ret + +org_delim: ; used by organize routine except for getting + cmp al,' ' ;the filename. + jz delim_ret + cmp al,9 + jz delim_ret + cmp al,'=' + jz delim_ret + cmp al,',' + jz delim_ret + cmp al,';' +delim_ret: + ret +delim endp + +; +;---------------------------------------------------------------------------- +; +; procedure : newline +; +; newline returns with first character of next line +; +;---------------------------------------------------------------------------- +; + +newline proc near + + call getchr ;skip non-control characters + jc nl_ret + cmp al,lf ;look for line feed + jnz newline + call getchr +nl_ret: + ret + +newline endp + +; +;---------------------------------------------------------------------------- +; +; procedure : mapcase +; +;---------------------------------------------------------------------------- +; +mapcase proc near + push cx + push si + push ds + + push es + pop ds + + xor si,si + +convloop: + lodsb + + ifdef DBCS + call testkanj + jz normconv ; if this is not lead byte + + mov ah,al + lodsb ; get tail byte + cmp ax,DB_SPACE + jnz @f ; if this is not dbcs space + mov word ptr [si-2],' ' ; set 2 single space +@@: + + dec cx + jcxz convdone ;just ignore 1/2 kanji error + jmp short noconv + +;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 + ret + + ifdef DBCS + + public testkanj +testkanj: + push si + push ds + + push ax + mov ax,6300h ; get dos dbcs vector + int 21h + pop ax + +bdbcs_do: + + cmp ds:word ptr [si],0 ; end of lead byte info? + jz bdbcs_notfound ; jump if so + cmp al,ds:[si] ; less than first byte character? + jb bdbcs_next ; jump if not + cmp al,ds:[si+1] ; grater than first byte character? + ja bdbcs_next + +bdbcs_found: + + push ax + xor ax,ax + inc ax ; reset zero flag + pop ax + +bdbcs_exit: + + pop ds + pop si + ret + +bdbcs_notfound: + + push ax + xor ax,ax ; set zero flag + pop ax + jmp short bdbcs_exit + +bdbcs_next: + + add si,2 ; points next lead byte table + jmp short bdbcs_do + + endif ; DBCS + +mapcase endp + +; +;---------------------------------------------------------------------------- +; +; procedure : round +; +; round the values in memlo and memhi to paragraph boundary. +; perform bounds check. +; +;---------------------------------------------------------------------------- +; + +round proc near + + push ax + mov ax,[memlo] + + call 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 + jz skip_set_devmarksize + push es + push si + mov si, cs:[devmark_addr] + mov es, si + sub ax, si + dec ax + mov es:[devmark_size], ax ; paragraph + and cs:[setdevmarkflag], not_for_devmark + pop si + pop es +skip_set_devmarksize: + pop ax + clc ;clear carry + ret + +mem_err: + mov dx,offset badmem + push cs + pop ds + call print + jmp stall + +round endp + +; +;---------------------------------------------------------------------------- +; +; procedure : calldev +; +;---------------------------------------------------------------------------- +; +calldev proc near + + mov ds,word ptr cs:[DevEntry+2] + add bx,word ptr cs:[DevEntry] ;do a little relocation + mov ax,ds:[bx] + + push word ptr cs:[DevEntry] + mov word ptr cs:[DevEntry],ax + mov bx,offset packet + call [DevEntry] + pop word ptr cs:[DevEntry] + ret + +calldev endp + +; +;---------------------------------------------------------------------------- +; +; procedure : todigit +; +;---------------------------------------------------------------------------- +; +todigit proc near + sub al,'0' + jb notdig + cmp al,9 + ja notdig + clc + ret +notdig: + stc + ret +todigit endp + +; +;---------------------------------------------------------------------------- +; +; procedure : getnum +; +; 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 proc near + + push bx + 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 + + call getchr ;get next digit + jc b1 ; no more characters + cmp al, ' ' ; space? + jz b15 ; then end of digits + cmp al, ',' ; ',' is a seperator!!! + jz b15 ; then end of digits. + cmp al, tab ; tab + jz b15 + cmp al,sepchr ; allow 0 or special separators + jz b15 + cmp al,'/' ; see if another switch follows + nop ; cas - remnant of old bad code + nop + 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 + ret +badnum: + mov sepchr,0 + xor ax,ax ; set zero flag, and ax = 0 + pop bx + stc ; and carry set + ret + +getnum endp + +;***************************************************************** + +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 438 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,6144 ;read 6144 bytes. + call readincontrolbuffer ;read info + jc setdosdata_fail + + mov cx, word ptr ds:[si] ;get the # of country, codepage combination entries + cmp cx, 438 ;cannot handle more than 438 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,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] ;get offset of data again. + mov cx,word ptr ds:[si+6] + mov ax,4200h + stc + int 21h ;move pointer back again + jc setdosdata_fail + + push si + mov si,(512+8) ;get length of the data from the file + mov cx,word ptr ds:[si] + pop si + mov dx,512 ;start of data buffer + add cx,10 ;signature + a word for the length itself + mov ah,3fh ;read the data from the file. + stc + int 21h + jc setdosdata_fail + + cmp ax, cx + jne setdosdata_fail + + 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 + + if bugfix + call setdbcs_before_copy + endif + + cmp al, setcountryinfo ;is the data for setcountryinfo table? + jne setdoscntry_mov ;no, don't worry + + push word ptr es:[di+ccmono_ptr-cccountryinfolen] ;cannot destroy ccmono_ptr address. save them. + push word ptr es:[di+ccmono_ptr-cccountryinfolen+2] ;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] ;restore + pop word ptr es:[di+ccmono_ptr-cccountryinfolen] + +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 + dec cx + cmp cx,0 + je setdoscntry_ok + jmp setdoscntry_data + +setdoscntry_ok: + ret +setdoscountryinfo endp + + if bugfix +setdbcs_before_copy proc near + + cmp al,setdbcs ; dbcs vector set? + jnz @f ; jump if not + cmp word ptr es:[di], 0 ; zero byte data block? + jz @f ; jump if so + + push di + push ax + push cx + mov cx,es:[di] ; load block length + add di,2 ; points actual data + xor al,al ; fill bytes + rep stosb ; clear data block + pop cx + pop ax + pop di +@@: + ret +setdbcs_before_copy endp + endif + +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,"/" ;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 <badld_pre> <string> <badld_post> + +badfil: + push cs + pop es + + mov si,dx +badload: + mov dx,offset badld_pre ;want to print config error + mov bx, offset crlfm + +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 ; suppress line number when handling command.com + je prnexit + call error_line +prnexit: + ret + +print: + cmp cs:bEchoConfig, 0 ; NTVDM skip print call, Jonle + je prnexit + + mov ah,std_con_string_output + int 21h + + ret + + 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 + ret + 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 +of_ret: + ret + +open_dev3: + mov bx,ax ; handle from open to bx + xor ax,ax ; get device info + mov ah,ioctl + int 21h + test dl,10000000b + jnz of_ret + + mov ah,close + int 21h + jmp open_dev1 + +open_file: + mov ah,open + stc + int 21h + ret + +; test int24. return back to dos with the fake user response of "fail" + +int24: + mov al, 3 ; fail the system call + iret ; return back to dos. + +include copyrigh.inc ; copyright statement + +nuldev db "NUL",0 +condev db "CON",0 +auxdev db "AUX",0 +prndev db "PRN",0 +MseDev db "MOUSE",0 ; NTVDM for internal spc mouse + + + + +; NTVDM we use a temp file for config.sys 23-Nov-1992 Jonle +; config db "C:\CONFIG.SYS",0 +config db 64 dup (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) + +comtab label byte + +; cmd len command cmd code +; ------- ------- -------- +; + db 7, "BUFFERS", 'B' + db 5, "BREAK", 'C' + db 6, "DEVICE", 'D' + db 10, "DEVICEHIGH", 'U' + db 5, "FILES", 'F' + db 4, "FCBS", 'X' + db 9, "LASTDRIVE", 'L' + db 10, "MULTITRACK", 'M' + db 8, "DRIVPARM", 'P' +if stacksw + db 6, "STACKS", 'K' +endif + db 7, "COUNTRY", 'Q' + db 5, "SHELL", 'S' + db 7, "INSTALL", 'I' + db 7, "COMMENT", 'Y' + db 3, "REM", '0' + db 8, "SWITCHES", '1' + db 3, "DOS", 'H' + db 10, "ECHOCONFIG", 'E' ; NTVDM 14-Aug-1992 Jonle + db 11, "NTCMDPROMPT", 'T' ; NTVDM 06-May-1993 sudeepb + db 7, "DOSONLY", 'O' ; NTVDM 06-May-1993 sudeepb + db 0 + +hlim dw 2 +slim dw 9 + +public bEchoConfig ; NTVDM - 14-Aug-1992 Jonle +bEchoConfig db 0 + +public drive +drive db ? + +public switches +switches dw 0 + + +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 + +sysinitseg ends + end + |