TITLE 'rxdos - Copyright, 1990 1997 Api Software' PAGE 59, 132 .LALL ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Real Time Dos ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; This material was created as a published version of a DOS ; ; equivalent product. This program logically functions in ; ; the same way as MSDOS functions and it is internal data ; ; structure compliant with MSDOS 6.0 ; ; ; ; This product is distributed AS IS and contains no warranty ; ; whatsoever, including warranty of merchantability or ; ; fitness for a particular purpose. ; ; ; ; ; ; (c) Copyright 1990, 1997. Api Software and Mike Podanoffsky ; ; All Rights Reserved Worldwide. ; ; ; ; This product is protected under copyright laws and may not ; ; be reproduced in whole or in part, in any form or media, ; ; included but not limited to source listing, facsimile, data ; ; transmission, cd-rom, or floppy disk without the expressed ; ; written consent of the author. ; ; ; ; License for distribution for commercial use or resale ; ; required from: ; ; ; ; Api Software ; ; 12 South Walker Street ; ; Lowell, MA 01851 ; ; ; ; internet: mikep@world.std.com ; ; ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; Compile with MASM 5.1 ; ;...............................................................; ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Comments ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; DOS file system is divided into the following layers: ; ; ; ; ; ; Named File System ; ; ; ; Uses the handle or FCB for file requests based on file ; ; name and file position. A file pointer navigates thru ; ; file. ; ; ; ; Redirector ; ; ; ; Passes file requests to a file redirector layer that ; ; handles any proprietary file system requests, special ; ; or networked file calls. ; ; ; ; FAT File System ; ; ; ; Maps file requests to clusters using the cluster chain ; ; in the FAT (File Access Table). ; ; ; ; Device Driver ; ; ; ; Performs the actual disk (int 13) i/o. ; ; ; ;...............................................................; include rxdosmac.asm include rxdosdef.asm public RxDOS_start public DaysInMonthTable public AccumDaysPerMonthTable public sizeInvFnChars public sizeShiftTable public _bitShiftTable public _CallDOS public _mul32 public _div32 public _Interrupt_20 public _Interrupt_21 public _Interrupt_23 public _Interrupt_24 public _Interrupt_25 public _Interrupt_26 public _Interrupt_27 public _Interrupt_28 public _Interrupt_2a public _Interrupt_2f public _IRet public _invalidFnCharacters public _RetCallersStackFrame public stdDeviceAssignTable public _DebugInterruptTrap public _TerminateProcess public _RxDOS_CurrentSeg public _RxDOS_SharedBuffer public _RxDOS_UserCodePage public _RxDOS_SystemCodePage public _RxDOS_CurrCountryInfo public _RxDOS_AllocStrategy public _RxDOS_bCtrlBreakCheck public _RxDOS_bLastDrive public _RxDOS_bNumJoinDev public _RxDOS_BootDrive public _RxDOS_bSwitchChar public _RxDOS_BufferList public _RxDOS_Buffers public _RxDOS_CommandShell public _RxDOS_CurrentDrive public _RxDOS_CurrentInstance public _RxDOS_CurrentPSP public _RxDOS_data public _RxDOS_DOSProgramName public _RxDOS_DOSVersion public _RxDOS_ExtendedMem public _RxDOS_INDOSFlag public _RxDOS_StackLongJump public _RxDOS_MaxMemory public _RxDOS_nProtFCBs public _RxDOS_NULLDev public _RxDOS_pCDS public _RxDOS_pCLOCKdriver public _RxDOS_pCONdriver public _RxDOS_pDPB public _RxDOS_pDTA public _RxDOS_pFCBs public _RxDOS_pFT public _RxDOS_bNumBlockDev public _RxDOS_pStartMemBlock public _RxDOS_ShareRetry public _RxDOS_ShareDelay public _RxDOS_Verify public _RxDOS_wMaxBlock public _RxDOS_wSpecialNames public RxDOS_USA_DefaultUpperCaseFunction public _RxDOS_AbortInProgress public RxDOS_StackTop public RxDOS_StackTemp public RxDOS_StackProtect public _RxDOS_CurrentStackTop public _RxDOS_TabPosition public SDAInt24_SPSave public SDAFirstName public SDASecondName public SDApCurrentCDS public SDAExtendedSwapArea public pexterrInvalidFunction public pexterrFileNotFound public pexterrPathNotFound public pexterrIllegalName public pexterrNoHandlesAvailable public pexterrAccessDenied public pexterrInvalidHandle public pexterrArenaTrashed public pexterrNotEnoughMemory public pexterrInvalidBlock public pexterrInvalidAccess public pexterrInvalidDrive public pexterrCurrentDirectory public pexterrNoMoreFiles public pexterrFileExists ; defined in rxdosccb extrn CCBChanged : near extrn linkBegCCB : near extrn locateCCBPHeader : near extrn readBuffer : near extrn unlinkCCB : near extrn updateAllChangedCCBBuffers : near extrn updateDriveBuffers : near ; defined in rxdosdev extrn DefineDPB : near extrn getDPB : near extrn getSysDate : near extrn setSysDate : near extrn getExpandedDateTime : near extrn getExpandedDate : near extrn DevRead : near extrn DevWrite : near extrn readConsoleIn : near extrn writeConsoleOut : near extrn initReqBlock : near extrn CharDevRequest : near extrn devCharRead : near extrn devCharReadLine : near ; defined in rxdosexe extrn loadProgram : near extrn copyCurrentPSP : near ; defined in rxdosfat extrn AllocateInitCluster : near extrn AmountFreeSpace : near extrn ReleaseClusterChain : near extrn _FATReadRandom : near ; defined in rxdosfcb extrn initFCBfromSFT : near extrn buildFindFromFCB : near extrn buildDTAfcbFind : near ; defined in rxdosfil extrn blankinitDirName : near extrn initdiskAccess : near extrn compareDirEntries : near extrn computeLogSectorNumber : near extrn ExpandFileName : near extrn LocateFile : near extrn LocateFreeDirSlot : near extrn LocateFileByAttribute : near extrn GetActualDrive : near extrn getCurrDirCluster : near extrn getDevice : near extrn getDrive : near extrn getWhereInDir : near ; defined in rxdosifs extrn Interrupt2F : far ; defined in rxdosini extrn RxDOS_initialize : near extrn LogTraceInt21Calls : near ; defined in rxdosmem extrn _initializeMemoryBlock : near extrn _collectMemoryBlocks : near extrn _releaseOwnerMemoryBlocks : near extrn _allocateUpperMB : near extrn _allocateConvMB : near extrn _modifyMemBlock : near ; defined in rxdossft extrn createSFTEntry : near extrn FindAvailableSFTHandle : near extrn findmatchingFCBSFT : near extrn FindSFTbyHandle : near extrn MapAppToSFTHandle : near extrn MapSFTtoAppHandle : near extrn releaseSFT : near extrn VerifyAvailableHandle : near extrn TestIfMoveHandleTable : near extrn _SFTReadLine : near extrn _SFTReadFile : near extrn _SFTWriteFile : near extrn _SFTOpenFile : near extrn _SFTCreateFile : near extrn _SFTCloseFile : near extrn _SFTCloseAllFiles : near extrn _SFTCommitFile : near ; defined in rxdosstr extrn CopyString : near extrn CopyBlock : near extrn convFCBNametoASCIZ : near extrn convFilenametoFCBString : near extrn getSysDateinDirFormat : near extrn upperCase : near extrn lowerCase : near extrn __ascii_stosb : near extrn getMonthDayYear : near extrn getDaysSince1980 : near extrn StringLength : near extrn condStringLength : near extrn getSystemDateValue : near ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; DOS Data ; ;...............................................................; RxDOS SEGMENT PARA PUBLIC 'CODE' assume cs:RxDOS, ds:RxDOS, es:RxDOS, ss:RxDOS org 0000h RxDOS_start: jmp RxDOS_initialize db 0 _RxDOS_SDALayoutStyle db DOS5_SDASTYLE ; DOS 4.0 + Style _RxDOS_data db 21 dup (0) ; uninitialized _RxDOS_ShareRetry dw 0 ; sharing retry count _RxDOS_ShareDelay dw 0 ; sharing retry delay _RxDOS_pDTA dd 0 ; ptr to current disk buffer (* violates m/tasking) _RxDOS_UnreadCON dw 0 ; ptr to unread CON input _RxDOS_pStartMemBlock dw 0 ; seg ptr to start of memory allocation _RxDOS_pDPB dd 0 ; ptr to Drive Parameter Block (DPB) _RxDOS_pFT dd 0 ; ptr to File Tables (FT) _RxDOS_pCLOCKdriver dd 0 ; ptr to CLOCK$ device driver _RxDOS_pCONdriver dd 0 ; ptr to CON device driver _RxDOS_wMaxBlock dw sizeSector ; maximum bytes per block for any/all devices _RxDOS_BufferList dd 0 ; pointer set for buffer list _RxDOS_pCDS dd 0 ; ptr to array of current directory structures _RxDOS_pFCBs dd 0 ; ptr to System FCB table _RxDOS_nProtFCBs dw 0 ; number of protected fcbs (no longer supported) _RxDOS_bNumBlockDev db 0 ; number of block devices _RxDOS_bLastDrive db 0 ; lastdrive from config.sys ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; NULL Device Driver ; ;...............................................................; _RxDOS_NULLDev dd -1 ; link to other device dw ( DEV_CHAR + DEV_NULL + DEV_FASTCHARIO ) dw null_strategy dw null_interrupt db 'NUL ' ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Installable File System Parameters ; ;...............................................................; _RxDOS_bNumJoinDev db 0 ; number of JOIN'ed drives _RxDOS_wSpecialNames dw 0 ; pointer to list of special names _RxDOS_pSETVERList dd 0 ; pointer to SETVER program list _RxDOS_wDOSHIGHOffset dw 0 ; DOS High offset A20 fix dw 0 ; DOS High PSP _RxDOS_Buffers dw 0 ; BUFFERS x _RxDOS_BuffersY dw 0 ; BUFFERS y (lookahead buffers) _RxDOS_BootDrive db 0 ; Boot Drive (A: = 1, ...) _RxDOS_MachineType db 0 ; 1 if 80386+, else 0 _RxDOS_ExtendedMem dw 0 ; extended memory size in K ; the remainder of these arguments are not compatible with MS-DOS _RxDOS_Verify dw 0 ; NonZero if Verify. _RxDOS_AllocStrategy dw 0 ; Allocation strategy. _RxDOS_bSwitchChar db '/' ; Switch Char. _RxDOS_MaxMemory dw 0 ; max memory _RxDOS_NumFileHandles dw sizePSPHandleTable ; default _RxDOS_Remainder dw 0000 ; div32 remainder. _RxDOS_pExtErrorCode dw 0 ; Error code. _RxDOS_ExtErrorFlag dw 0 ; flag if infor set _RxDOS_ExtErrorInfo db size ERROR dup(0) ; extended error info _RxDOS_AbortInProgress dw 0 ; if NZ, skip critical error ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Current PSP ; ;...............................................................; even _RxDOS_CurrentInstance dw 0 ; base address of current stack _RxDOS_CurrentStackTop dw RxDOS_StackTop ; Reserved Stack Top ... _RxDOS_CurrentStackBot dw RxDOS_StackTop ; ... and Bottom. _RxDOS_StackLongJump dw 0 ; long jump ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; UMB Control Status Word ; ;...............................................................; _RxDOS_UMBEnabled dw 0 ; set by init _RxDOS_UMBAllowed dw 0 ; selectable by user ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Tab Expansion ; ;...............................................................; _RxDOS_TabPosition dw 0 ; tab position ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Country, Code Page, and Double Byte Character Set Info ; ;...............................................................; even _RxDOS_UserCodePage dw DEFAULT_CODEPAGE _RxDOS_SystemCodePage dw DEFAULT_CODEPAGE ; system code page _RxDOS_DBCS_Table dw 0 ; DBCS (NULL ) _RxDOS_UserCountryCode dw DEFAULT_COUNTRYCODE ; user set country _RxDOS_SysCountryCode dw DEFAULT_COUNTRYCODE ; system country code _RxDOS_SegCountryTables dw 0000 ; if non-zero, country info table _RxDOS_CurrCountryInfo dw DATE_USA db '$', 0, 0, 0, 0 ; currency symbol (asciz) 5 bytes dw ',' ; thousands separator 2 bytes dw '.' ; decimal separator 2 bytes dw '-' ; date separator 2 bytes dw ':' ; time separator 2 bytes db 0 ; currency format (before or after) db 2 ; places after decimal point db TIME_12HOUR ; 12-hour or 24-hour format dd RxDOS_USA_DefaultUpperCaseFunction dw ',' ; data-list ... db 10 dup(?) ; reserved ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Command Shell ; ;...............................................................; even _RxDOS_CommandShell db 128 dup(?) _RxDOS_SharedBuffer db 128 dup (?) ; shared buffer. ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Swappable Data Area ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Variables whose names begin with _RxDOS are used and will ; ; contain valid data. The remainder of the arguments are ; ; placeholders for compatibility reasons and are not used. ; ;...............................................................; SDABeginArea equ $ _RxDOS_CritErrorFlag db 0 _RxDOS_INDOSFlag db 0 ; INDOS flag. _RxDOS_CritErrorDrive db 0 ; drive where crit error occurred _RxDOS_LocusLasterror db 0 _RxDOS_ExtErrorcode dw 0 _RxDOS_SuggestedAction db 0 _RxDOS_ClassOfError db 0 SDApLastError dd 0 ; pointer for last error SDACurrentDTA dd 0 ; current disk transfer address _RxDOS_CurrentPSP dw 0 ; current PSP SDASaveSP dw 0 ; SP across int 23h _RxDOS_ChildReturnCode dw 0 ; Child return code. _RxDOS_CurrentDrive db 0 ; current drive ( a=0, ... ) SDAExtendedBreakFlag db 0 ; extended break flag SDAEndArea equ $ ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Extended Swappable Data Area ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _RxDOS_FunctionCall dw 0 ; AX on call _RxDOS_PSPShare dw 0 _RxDOS_MachineIDShare dw 0 SDAFirstUsableAlloc dw 0 SDABestUsableAlloc dw 0 SDALastUsableAlloc dw 0 SDAMemSizeinParas dw 0 dw 0 SDAInt24_RetFailStatus db 0 SDAInt24_AllowedActions db 0 ; Abort, Retry, Fail bits db 0 _RxDOS_bCtrlBreakCheck dw 0 ; Ctrl Break Flag. db 0 SDADayOfMonth db 0 SDAMonth db 0 SDAYear dw 0 ; year since 1980 SDADaysSince dw 0 ; since 1-1-1980 SDADayOfWeek db 0 ; 0 = Sunday SDASFTValidPointer db 0 SDAInt28_Safe db 0 SDAInt24_Fail db 0 SDADeviceDriverRequest db 26 dup(0) SDADeviceEntryPoint dd 0 SDADeviceRequest01 db 22 dup(0) SDADeviceRequest02 db 22 dup(0) SDAPSPCopyType dw 0 ; not used by RxDOS _RxDOS_UserSerialNumber db 0, 0, 0 ; User Identification _RxDOS_DOSOEMVersion db 94, 0, 0 ; OEM Version. SDAClockTransfer db 6 dup(0) ; not used by RxDOS SDATransferWord dw 0 ; not used SDAFirstName db sizeEXPANDNAME dup(0) SDASecondName db sizeEXPANDNAME dup(0) SDAFindBlock db 21 dup(0) SDADirEntry db 32 dup(0) SDACDSCopy db 81 dup(0) ; not used by RxDOS SDAFCBName db 12 dup(0) ; not used by RxDOS SDAFCBRename db 12 dup(0) ; not used by RxDOS db 8 dup(0) ; not used by RxDOS SDAExtendedAttrib db 0 ; not used by RxDOS SDAFCBType db 0 ; not used by RxDOS SDADirSearchAttrib db 0 ; not used by RxDOS SDAFileOpenMode db 0 ; not used by RxDOS dw 0, 0, 0 ; not used by RxDOS SDAReadWriteFlag db 0 ; not used by RxDOS SDADriveType db 0 ; not used by RxDOS dw 0 ; not used by RxDOS SDALineEditInsert db 0 ; not used by RxDOS SDAFileLocated dw 0 ; not used by RxDOS SDATypeProcessTerm dw 0 ; not used by RxDOS SDADeleteCode db DIRENTRY_DELETED ; not used by RxDOS SDADPBPointer dd 0 ; not used by RxDOS SDAUserStackFrame dd 0 ; not used by RxDOS SDAInt24_SPSave dd 0 ; not used by RxDOS dw 4 dup(0) ; not used by RxDOS SDAMediaID dw 0 ; not used by RxDOS SDApCurrentDPB dd 0 ; not used by RxDOS SDApCurrentSFT dd 0 ; not used by RxDOS SDApCurrentCDS dd 0 ; not used by RxDOS SDApCurrentFCB dd 0 ; not used by RxDOS SDASFTHandle dw 0, 0 ; not used by RxDOS SDApJobHandleTable dd 0, 0 ; not used by RxDOS SDAPathNameLast dw 0 ; not used by RxDOS ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Stacks ; ;...............................................................; even RxDOS_StackProtect dw 5E5Eh dw 1024 dup(?) RxDOS_StackTemp dw 2048 dup(?) RxDOS_StackTop dw 5E5Eh SDAExtendedSwapArea equ $ ; ** ROMABLE BEYOND THIS ADDRESS ** ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Real Time Dos Product Identification ; ;...............................................................; _RxDOS_DOSROMStatusFlag db ROM_IDENTIFICATION ; ROM Version Status _RxDOS_DOSVersion db 6, 20 ; Dos Version (6.20) _RxDOS_DOSProgramName db 'RxDOS6.0' ; Product Name. _RxDOS_ContrlC_Message db '^C', ControlM, ControlJ, 0 ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Device Assign Table ; ;...............................................................; stdDeviceAssignTable: StdRedirec < 'AUX ', -1, sftIsDevice > StdRedirec < 'CON ', -1, sftIsDevice + sftIsstdout + sftIsstdin > StdRedirec < 'PRN ', -1, sftIsDevice > dw -1 ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Code Segment Data ; ;...............................................................; ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Days In Month Table ; ;...............................................................; DaysInMonthTable: db 31 ; Jan db 28 ; Feb db 31 ; Mar db 30 ; Apr db 31 ; May db 30 ; Jun db 31 ; Jul db 31 ; Aug db 30 ; Sep db 31 ; Oct db 30 ; Nov db 31 ; Dec ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Accumulated Days Per Month Table ; ;...............................................................; AccumDaysPerMonthTable: dw 0 ; Jan dw 31 ; Feb dw 59 ; Mar dw 90 ; Apr dw 120 ; May dw 151 ; Jun dw 181 ; Jul dw 212 ; Aug dw 243 ; Sep dw 273 ; Oct dw 304 ; Nov dw 334 ; Dec ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Bit Shift Table ; ;...............................................................; _bitShiftTable: db 1 ; 0 db 2 ; 1 db 4 ; 2 db 8 ; 3 db 16 ; 4 db 32 ; 5 db 64 ; 6 db 128 ; 7 sizeShiftTable equ ($ - _bitShiftTable) ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Invalid Characters in Filename ; ;...............................................................; _invalidFnCharacters: db '[]<>|",;=+:', 0 sizeInvFnChars equ ($ - _invalidFnCharacters) ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Extended Error Tables ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; macro requires error code, locus, sug-action, class. ; ; ; ;...............................................................; pexterrInvalidFunction EXTERRORCODE pexterrFileNotFound EXTERRORCODE pexterrPathNotFound EXTERRORCODE pexterrIllegalName EXTERRORCODE pexterrNoHandlesAvailable EXTERRORCODE pexterrAccessDenied EXTERRORCODE pexterrInvalidHandle EXTERRORCODE pexterrArenaTrashed EXTERRORCODE pexterrNotEnoughMemory EXTERRORCODE pexterrInvalidBlock EXTERRORCODE pexterrInvalidAccess EXTERRORCODE pexterrInvalidDrive EXTERRORCODE pexterrCurrentDirectory EXTERRORCODE pexterrNoMoreFiles EXTERRORCODE pexterrFileExists EXTERRORCODE ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Real Time Dos ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ; ; Items marked by (*) are Undocumented DOS Functions. ; ;...............................................................; _RxDOS_functions: dw _TerminateProcess_00 ; 00 - Program terminate dw _KeyboardInput ; 01 - Keyboard input dw _DisplayOutput ; 02 - Display output dw _AuxInput ; 03 - Aux input dw _AuxOutput ; 04 - Aux output dw _PrinterOutput ; 05 - Printer output dw _DirectConsole ; 06 - Direct console dw _DirectConsoleInputNoEcho ; 07 - Direct console input noecho dw _ConsoleInputNoEcho ; 08 - Console input noecho dw _DisplayString ; 09 - Display string dw _BufferedKeyboardInput ; 0A - Buffered keyboard input dw _CheckKeyboardInput ; 0B - Check keyboard input dw _ClearBufferedKeyboardInput ; 0C - Clear buffered keyboard input dw _DiskReset ; 0D - Disk reset dw _SelectDisk ; 0E - Select disk dw _OpenFileFCB ; 0F - Open file FCB dw _CloseFileFCB ; 10 - Close file FCB dw _SearchFirstFileFCB ; 11 - Search first file FCB dw _SearchNextFileFCB ; 12 - Search next file FCB dw _DeleteFileFCB ; 13 - Delete file FCB dw _SeqReadFileFCB ; 14 - Seq read file FCB dw _SeqWriteFileFCB ; 15 - Seq write file FCB dw _CreateFileFCB ; 16 - Create file FCB dw _RenameFileFCB ; 17 - Rename file FCB dw _UnusedReturnInst ; 18 - Unused dw _CurrentDisk ; 19 - Current disk dw _SetDiskTransferAddress ; 1A - Set disk transfer address dw _GetDefaultDriveData ; 1B - Get default drive data dw _GetDriveData ; 1C - Get drive data dw _UnusedReturnInst ; 1D - Unused dw _UnusedReturnInst ; 1E - Unused dw _GetDefaultDriveParameterBlock ; 1F - Get default drive parameter block dw _UnusedReturnInst ; 20 - Unused dw _ReadFileFCB ; 21 - Read file FCB dw _WriteFileFCB ; 22 - Write file FCB dw _FileSizeFCB ; 23 - File size FCB dw _SetRelativeRecordFCB ; 24 - Set relative record FCB dw _SetInterruptVector ; 25 - Set interrupt vector dw _CreateNewProgramSeg ; 26 - Create new program seg dw _RandomBlockReadFCB ; 27 - Random block read FCB dw _RandomBlockWriteFCB ; 28 - Random block write FCB dw _ParseFilenameFCB ; 29 - Parse filename FCB dw _GetDate ; 2A - Get date dw _SetDate ; 2B - Set date dw _GetTime ; 2C - Get time dw _SetTime ; 2D - Set time dw _SetVerifySwitch ; 2E - Set verify switch dw _GetDiskTransferAddress ; 2F - Get disk transfer address dw _GetDOSVersion ; 30 - Get DOS version dw _TerminateStayResident ; 31 - Terminate stay resident dw _GetDriveParameterBlock ; 32 - Get drive parameter block dw _CtrlBreakCheck ; 33 - Ctrl break check dw _GetInDOSFlagAddress ; 34 - Get INDOS flag address dw _GetInterruptVector ; 35 - Get interrupt vector dw _GetFreeDiskSpace ; 36 - Get free disk space dw _GetSetSwitchChar ; 37 - Get/set switch char dw _CountryDependentInfo ; 38 - Country dependent info dw _CreateSubdirectory ; 39 - Create subdirectory dw _RemoveSubdirectory ; 3A - Remove subdirectory dw _ChangeSubdirectory ; 3B - Change subdirectory dw _CreateFile ; 3C - Create file dw _OpenFile ; 3D - Open file dw _CloseFile ; 3E - Close file dw _ReadFile ; 3F - Read file dw _WriteFile ; 40 - Write file dw _DeleteFile ; 41 - Delete file dw _MoveFilePointer ; 42 - Move file pointer dw _ChangeFileMode ; 43 - Change file mode dw _IoControl ; 44 - Io Control dw _DuplicateFileHandle ; 45 - Duplicate file handle dw _ForceFileHandle ; 46 - Force file handle dw _GetCurrentDirectory ; 47 - Get current directory dw _AllocateMemory ; 48 - Allocate memory dw _FreeAllocatedMemory ; 49 - Free allocated memory dw _ModifyAllocatedMemory ; 4A - Modify allocated memory dw _ExecuteProgram ; 4B - ExecuteProgram dw _TerminateProcess ; 4C - Terminate process dw _GetReturnCode ; 4D - Get return code dw _FindFirstFile ; 4E - Find first file dw _FindNextFile ; 4F - Find next file dw _SetPSPAddress ; 50 - Set PSP Address dw _GetPSPAddress ; 51 - Get PSP Address dw _GetDosDataTablePtr ; 52*- (Get DOS Data Table) dw _TranslateBIOSParameterBlock ; 53*- (Translate BIOS Parameter Block ) dw _GetVerify ; 54 - Get verify dw _DuplicatePSP ; 55*- (Duplicate PSP block) dw _RenameFile ; 56 - Rename file dw _SetFileDateTime ; 57 - Set file date time dw _GetAllocationStrategy ; 58 - Get allocation strategy dw _GetExtendedError ; 59 - Get extended error dw _CreateUniqueFile ; 5A - Create unique file dw _CreateNewFile ; 5B - Create new file dw _LockFileAccess ; 5C - Lock file access dw _ServerShareAndSwap ; 5D*- (Server, Share And Swap) dw _GetMachineName ; 5E - Get machine name dw _GetRedirectionList ; 5F - Get redirection list dw _GetActualFileName ; 60*- (Get Actual FileName ) dw _Unused ; 61 - Unused dw _GetPSPAddress ; 62 - Get PSP Address dw _GetDBCSString ; 63*- (Get DBCS String) dw _Unused ; 64 - Unused dw _ExtCountryDependentFunctions ; 65 - Extended Country Dependent Functions dw _GlobalCodePage ; 66 - Get/Set Global Code Page dw _SetHandlesCount ; 67 - Set Handles Count dw _CommitFile ; 68 - Commit File dw _GetDiskSerialNumber ; 69*- (Get disk serial number) dw _CommitFile ; 6A*- (Commit File (same as 68)) dw _Unused ; 6B - Unused dw _ExtendedOpenCreate ; 6C - Extended Open/ Create dw _Unused ; 6D - DOS in ROM Functions dw _Unused ; 6E - DOS in ROM Functions dw _Unused ; 6F - DOS in ROM Functions dw _Unused ; 70 - Unused or unknown dw _Unused ; 71 - Chicago long filenames dw _Unused ; 72 - Chicago long filenames _RxDOS_functionsLast: dw _Unused ; *- items: Undocumented DOS Functions _RxDOS_maxFunctionCode = (_RxDOS_functionsLast - _RxDOS_functions)/2 ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Critical Section Patch Area ; ;...............................................................; _RxDOS_CritSectPatches dw 5 dup (0) ; added later ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 21 ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ah contains function request ; ;...............................................................; _Interrupt_21 proc far push es push ds push bp push di push si push dx push cx push bx push ax mov bp, sp add bp, sizeStackFrame and word ptr [ _Flags ][ bp ], 0fffeh ; clear carry bit. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; switch to internal stack ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cli setES ss ; caller's stack mov bx, bp ; caller's stack to es: bx mov ds, word ptr cs:[ _RxDOS_CurrentSeg ] ; current segment. mov ss, word ptr cs:[ _RxDOS_CurrentSeg ] ; current segment. mov sp, word ptr ss:[ _RxDOS_CurrentStackTop ] ; point to current stack. push bx ; caller's stack reference push es ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; current stack parameters ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Entry ; set [ bp ] def _FctAddress push word ptr [ _RxDOS_CurrentStackTop ] sub word ptr [ _RxDOS_CurrentStackTop ], 384 ; reserve stack push word ptr [ _RxDOS_CurrentInstance ] ; base address of current stack mov word ptr [ _RxDOS_CurrentInstance ], bp ; base address of current stack push word ptr [ _RxDOS_INDOSFlag ] inc word ptr [ _RxDOS_INDOSFlag ] ; INDOS push word ptr [ _RxDOS_StackLongJump ] ; long jump ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; save PSP values ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov dx, word ptr [ _RxDOS_CurrentPSP ] or dx, dx ; was PSP zero ? jz _Interrupt_21_12 ; if no valid PSP --> mov ds, dx ; see if PSP was ever set mov word ptr ds:[ pspUserStack. _segment ], es mov word ptr ds:[ pspUserStack. _pointer ], bx ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; determine function address ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Interrupt_21_12: sti cld currSegment ds ; point to current segment mov word ptr [ _RxDOS_FunctionCall ], ax ; AX on call cmp ah, _RxDOS_maxFunctionCode ; max function code ? jnc _Interrupt_21_48 ; if out of range --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; [ds] from user call is passed in [es] ; [dx] from user call is passed in [di] ; [ds] is changed to current segment ; [ss] == [ds] is assumed ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xor bh, bh mov bl, ah ; offset into functions table add bx, bx mov bx, word ptr [ _RxDOS_functions ][ bx ] ; mov word ptr [ _FctAddress ][ bp ], bx ; save dispatch address RetCallersStackFrame ds, bx mov es, word ptr [ _DataSegment][ bx ] ; ds on call mov di, word ptr [ _DX ][ bx ] ; set di from DX mov bx, word ptr [ _BX ][ bx ] ; restore bx mov dx, di ; and also passed in DI clc currSegment ds ; point to current segment mov word ptr [ _RxDOS_StackLongJump ], sp ; save stack long jump IFDEF RxDOS_TRACEBUILD call LogTraceInt21Calls ; trace build ENDIF call word ptr [ _FctAddress ][ bp ] ; go do function jnc _Interrupt_21_48 _Interrupt_21_22: RetCallersStackFrame es, bx or word ptr es:[ _Flags ][ bx ], 1 ; set carry bit mov si, ax ; error pointer in AX cmp ax, -1 ; error an FCB error ? mov ah, byte ptr es:[ _AX. _AH ][ bx ] ; retain ah in case fcb error jz _Interrupt_21_32 ; yes --> mov word ptr ss:[ _RxDOS_pExtErrorCode ], si ; save ptr to error code mov ax, word ptr cs:[ ExtErrorCodeValue ][ si ] ; get actual error value _Interrupt_21_32: mov word ptr es:[ _AX ][ bx ], ax ; get actual error code. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return registers ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Interrupt_21_48: cli pop word ptr ss:[ _RxDOS_StackLongJump ] ; long jump pop word ptr ss:[ _RxDOS_INDOSFlag ] ; restore INDOS pop word ptr ss:[ _RxDOS_CurrentInstance ] ; _Instance pop word ptr ss:[ _RxDOS_CurrentStackTop ] pop bx ; fct address pop bx ; caller's stack pointer sub bx, sizeStackFrame ; adjusted stack pointer pop ss ; caller's stack reference mov sp, bx pop ax ; restore registers pop bx pop cx pop dx pop si pop di pop bp pop ds pop es iret _Interrupt_21 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Call DOS Interface ; ;...............................................................; _CallDOS proc far mov ah, cl ; old compatability Int21 ret ; far return _CallDOS endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 20 ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Terminate Program ; ;...............................................................; _Interrupt_20 proc far Int21 TerminateProcess, 00 iret ; no return expected _Interrupt_20 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Where Data Segment Relocated ; ;...............................................................; _RxDOS_CurrentSeg dw 0000 ; Current Segment. ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; System Wide Functions ; ;...............................................................; ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; NULL Device Driver ; ;...............................................................; null_interrupt proc far mov word ptr es:[ rwrStatus ][ bx ], ( OP_DONE ) null_strategy: ret null_interrupt endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 23 - Control Break Exit Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; This is a default Int 23 handler. ; ; ; ; Returns CY to cancel current application. ; ; ; ;...............................................................; _Interrupt_23 proc far stc ret 2 ; returns to appl (iret w/o status) _Interrupt_23 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 24 - Critical Error Handler ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; This is a default Int 24 handler. ; ; ; ; Usage: ; ; bp:si driver's header ; ; di error code ; ; al drive code ; ; ah allowed responses ; ; 08h CRITERROR_IGNOREALLOWED ; ; 10h CRITERROR_RETRYALLOWED ; ; 20h CRITERROR_FAILALLOWED ; ; ; ; Return: ; ; al contains one of these values ; ; 00h CRITERROR_IGNORE ; ; 01h CRITERROR_RETRY ; ; 02h CRITERROR_TERMINATE ; ; 03h CRITERROR_FAIL ; ;...............................................................; _Interrupt_24 proc far push ds push es push cs pop ds push ax xchg ax, di mov ah, 0 xchg di, ax ; upper bits zero add di, di mov di, word ptr [ CriticalErrorMessages ][ di ] call _CritErrorDisplayNewLine pop ax push ax cmp al, -1 ; valid unit ? jz _Interrupt_24_08 ; no drive --> mov di, offset perr_OnDrive call _CritErrorDisplayMessage pop ax push ax add al, 'A' int 29h mov al, ':' int 29h _Interrupt_24_08: pop ax ; abort, retry, fail, ... push ax ; mov di, offset CritError_AbortRetryIgnoreFail test ah, CRITERROR_FAILALLOWED jnz _Interrupt_24_12 mov di, offset CritError_AbortRetryIgnore _Interrupt_24_12: call _CritErrorDisplayNewLine xor ax, ax int 16h push ax int 29h pop cx ; character pop ax ; allowed to ah push ax or cl, 20h ; lower case cmp cl, "f" ; Fail ? jnz _Interrupt_24_22 ; if not fail --> mov dx, CRITERROR_FAIL test ah, CRITERROR_FAILALLOWED ; fail allowed ? jnz _Interrupt_24_36 ; exit with fail --> _Interrupt_24_22: cmp cl, "r" ; Retry ? jnz _Interrupt_24_26 ; if not retry --> mov dx, CRITERROR_RETRY test ah, CRITERROR_RETRYALLOWED ; retry allowed ? jnz _Interrupt_24_36 ; exit with retry --> _Interrupt_24_26: cmp cl, "i" ; Ignore ? jnz _Interrupt_24_30 ; if not ignore --> mov dx, CRITERROR_IGNORE test ah, CRITERROR_IGNOREALLOWED ; ignore allowed ? jnz _Interrupt_24_36 ; exit with ignore --> _Interrupt_24_30: cmp cl, "a" ; Abort ? jnz _Interrupt_24_08 ; if not abort --> mov dx, CRITERROR_TERMINATE ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Interrupt_24_36: mov ax, dx ; return value in ax pop dx ; throw away allowed pop es pop ds clc ; no exit flag ret 2 ; returns to appl (iret w/o status) _Interrupt_24 endp ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Display New Line ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CritErrorDisplayNewLine: push di mov al, ControlM int 29h mov al, ControlJ int 29h pop di ; jmp short _CritErrorDisplayMessage ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Display Message ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CritErrorDisplayMessage: mov al, byte ptr [ di ] or al, al jz _CritErrorDisp_08 int 29h inc di jmp _CritErrorDisplayMessage _CritErrorDisp_08: ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Abort, Retry, Ignore ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CritError_AbortRetryIgnoreFail: db "Abort, Retry, Ignore, Fail ?", 0 CritError_AbortRetryIgnore: db "Abort, Retry, Ignore ?", 0 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Critical Error Messages ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CriticalErrorMessages: dw perr_devErrWriteProtectViol dw perr_devErrUnknownUnit dw perr_devErrDeviceNotReady dw perr_devErrUnknownCommand dw perr_devErrCRCerr dw perr_devErrBadDriveReq dw perr_devErrSeekError dw perr_devErrUnknownMedia dw perr_devErrSectorNotFound dw perr_devErrPrinterOutPaper dw perr_devErrWriteFault dw perr_devErrReadFault dw perr_devErrGeneralFailure dw perr_devErrSharingViolation dw perr_devErrLockViolation dw perr_devErrInvalidDiskChange perr_devErrWriteProtectViol: db "Error Write Protect", 0 perr_devErrUnknownUnit: db "Error Unknown Unit", 0 perr_devErrDeviceNotReady: db "Error Device Not Ready", 0 perr_devErrUnknownCommand: db "Error Unknown Command", 0 perr_devErrCRCerr: db "Error CRC Error", 0 perr_devErrBadDriveReq: db "Error Bad Drive Request", 0 perr_devErrSeekError: db "Error Seek Error", 0 perr_devErrUnknownMedia: db "Error Unknown Media", 0 perr_devErrSectorNotFound: db "Error Sector Not Found", 0 perr_devErrPrinterOutPaper: db "Error Printer Out Paper", 0 perr_devErrWriteFault: db "Error Write Fault", 0 perr_devErrReadFault: db "Error Read Fault", 0 perr_devErrGeneralFailure: db "Error General Failure", 0 perr_devErrSharingViolation: db "Error Sharing Violation", 0 perr_devErrLockViolation: db "Error Lock Violation", 0 perr_devErrInvalidDiskChange: db "Error Invalid Disk Change", 0 perr_OnDrive: db " On Drive ", 0 ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 25 - Read From Disk ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Like MSDOS, the Int 25 and 26 definitions do not allow for ; ; 32 bit sector addressing. These functions support only disk ; ; drives up to 32 MByte storage. ; ; ; ; To access > 32 MByte disks, use the device driver calls. ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; al drive (0= A, ... ) ; ; cx sectors ; ; dx physical disk sector address ; ; ds:bx buffer address ; ; ; ;...............................................................; _Interrupt_25 proc far saveSegments di, si, bp, dx, cx, bx push ds push bx pop di pop es ; buffer to es: di mov bx, cx ; sectors xor cx, cx ; extended sector address cmp bx, -1 ; points to DISKIO struct ? jnz _Int25_06 ; no --> mov bx, word ptr [ diskioSectors ][ di ] mov cx, word ptr [ diskioStartSector. _high ][ di ] mov dx, word ptr [ diskioStartSector. _low ][ di ] mov es, word ptr [ diskioBuffer. _segment ][ di ] mov di, word ptr [ diskioBuffer. _pointer ][ di ] _Int25_06: or bx, bx ; nothing to read ? jz _Int25_08 ; if none --> call DevRead _Int25_08: restoreSegments bx, cx, dx, bp, si, di retf _Interrupt_25 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 26 - Write To Disk ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Like MSDOS, the Int 25 and 26 definitions do not allow for ; ; 32 bit sector addressing. These functions support only disk ; ; drives up to 32 MByte storage. ; ; ; ; To access > 32 MByte disks, use the device driver calls. ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; al drive (0= A, ... ) ; ; cx sectors ; ; dx physical disk sector address ; ; ds:bx buffer address ; ; ; ;...............................................................; _Interrupt_26 proc far saveSegments di, si, bp, dx, cx, bx push ds push bx pop di pop es ; buffer to es: di mov bx, cx ; sectors xor cx, cx ; extended sector address cmp bx, -1 ; points to DISKIO struct ? jnz _Int26_06 ; no --> mov bx, word ptr [ diskioSectors ][ di ] mov cx, word ptr [ diskioStartSector. _high ][ di ] mov dx, word ptr [ diskioStartSector. _low ][ di ] mov es, word ptr [ diskioBuffer. _segment ][ di ] mov di, word ptr [ diskioBuffer. _pointer ][ di ] _Int26_06: or bx, bx ; nothing to write ? jz _Int26_08 ; if none --> call DevWrite _Int26_08: restoreSegments bx, cx, dx, bp, si, di retf _Interrupt_26 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 27 ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Terminate Stay Resident ; ;...............................................................; _Interrupt_27 proc far Int21 TerminateStayResident, 00 ; no return code _Interrupt_27 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 28 ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Idle Loop ; ;...............................................................; _Interrupt_28 proc far iret _Interrupt_28 endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 2f ; ;...............................................................; _Interrupt_2a proc far xor ax, ax iret _Interrupt_2a endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Interrupt 2f ; ;...............................................................; _Interrupt_2f proc far xor bx, bx iret _Interrupt_2f endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; All other interrupts ; ;...............................................................; _IRet proc far iret _IRet endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; System Functions ; ;...............................................................; ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Default USA Upper Case Routine ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; al Contains character. Converted to Upper Case. ; ;...............................................................; RxDOS_USA_DefaultUpperCaseFunction proc far cmp al, 128 jc _USA_Default08 push ds push bx xor bx, bx mov bl, al ; pointer to mov al, byte ptr cs:[ _RxDOS_USA_UpperCaseTable ][ bx ] pop bx pop ds _USA_Default08: ret RxDOS_USA_DefaultUpperCaseFunction endp ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Default USA Upper Case Table ; ;...............................................................; _RxDOS_USA_UpperCaseTable: ; 128, 129, 130, 131, 132, 133, 134, 135 db 128, 154, "E", "A", 143, "A", 143, 128 ; 136, 137, 138, 139, 140, 141, 142, 143 db "E", "E", "E", "I", "I", "I", 142, 143 ; 144, 145, 146, 147, 148, 149, 150, 151 db 144, 146, 146, "O", 153, "O", "U", "U" ; 152, 153, 154, 155, 156, 157, 158, 159 db "Y", 153, 154, 155, 156, 157, 158, 159 ; 160, 161, 162, 163, 164, 165, 166, 167 db "A", "I", "O", "U", 164, 165, 166, 167 ; 168, 169, 170, 171, 172, 173, 174, 175 db 168, 169, 170, 171, 172, 173, 174, 175 ; 176, 177, 178, 179, 180, 181, 182, 183 db 176, 177, 178, 179, 180, 181, 182, 183 ; 184, 185, 186, 187, 188, 189, 190, 191 db 184, 185, 186, 187, 188, 189, 190, 191 ; 192, 193, 194, 195, 196, 197, 198, 199 db 192, 193, 194, 195, 196, 197, 198, 199 ; 200, 201, 202, 203, 204, 205, 206, 207 db 200, 201, 202, 203, 204, 205, 206, 207 ; 208, 209, 210, 211, 212, 213, 214, 215 db 208, 209, 210, 211, 212, 213, 214, 215 ; 216, 217, 218, 219, 220, 221, 222, 223 db 216, 217, 218, 219, 220, 221, 222, 223 ; 224, 225, 226, 227, 228, 229, 230, 231 db 224, 225, 226, 227, 228, 229, 230, 231 ; 232, 233, 234, 235, 236, 237, 238, 239 db 232, 233, 234, 235, 236, 237, 238, 239 ; 240, 241, 242, 243, 244, 245, 246, 247 db 240, 241, 242, 243, 244, 245, 246, 247 ; 248, 249, 250, 251, 252, 253, 254, 255 db 248, 249, 250, 251, 252, 253, 254, 255 ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Get Current PSP ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Output: ; ; es PSP address ; ;...............................................................; getPSP: push ax mov ax, word ptr ss:[ _RxDOS_CurrentPSP ] or ax, ax jz getPSP_08 mov es, ax getPSP_08: pop ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Get Current Handle Table ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Output: ; ; es:bx Handle Table ; ;...............................................................; getHandleTable: call getPSP jz getHandleTable_08 les bx, dword ptr es:[ pspFileHandlePtr ] getHandleTable_08: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; For Directory Functions, Change Error to 'Path Not Found' ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; ax contains error reference ; ; cy error flag retained ; ;...............................................................; _chgErrorToPathNotFound: jnc _chgtoPathError_14 ; if no error --> pushf ; save carry, status cmp ax, offset pexterrFileNotFound ; file not found ? jnz _chgtoPathError_12 ; no, ignore change --> mov ax, offset pexterrPathNotFound ; else change error _chgtoPathError_12: popf _chgtoPathError_14: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Return Pointer to Caller's Stack Frame ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Output: ; ; returns on stack segment and offset ; ; ; ; Usage: ; ; call RetCallersStackFrame ; ; pop reg ; ; pop seg ; ;...............................................................; _RetCallersStackFrame: push bp mov bp, sp push word ptr [ bp + 2 ] ; create return stack space push word ptr [ bp ] push bx pushf ; save interrupts cli mov bx, word ptr ss:[ _RxDOS_CurrentInstance ] ; base address of current stack popf ; restore interrupts push word ptr ss:[ _segment ][ bx ] pop word ptr [ bp + 2 ] push word ptr ss:[ _pointer ][ bx ] pop word ptr [ bp ] pop bx ; restore registers pop bp ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Set FCB Error if Carry ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; if carry, set AL to -1, else set AL to 0. ; ;...............................................................; setFCBErrorIfCarry: pushf jnc setFCBErrorIfCarry_08 ; if no error --> mov word ptr ss:[ _RxDOS_pExtErrorCode ], ax ; save ptr to error code setFCBErrorIfCarry_08: mov ax, 0000 sbb ax, ax ; nc -> 00; cy -> FF push ds push di RetCallersStackFrame ds, di mov byte ptr [ _AX. _AL ][ di ], al pop di pop ds popf ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 32 Bit Multiply ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; dx:ax numerator ; ; cx multiplier ; ; ; ;...............................................................; _mul32: or dx, dx ; simple multiply ? jnz _mul32_12 ; not really --> mul cx ret _mul32_12: push bx mov bx, ax mov ax, dx mul cx xchg ax, bx mul cx add dx, bx pop bx ; restore bx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 32 Bit Divide ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; dx:ax numerator ; ; cx divisor ; ; ; ;...............................................................; _div32: or cx, cx ; protect from zero divisor stc ; in case of error jz _div32_return ; if so, just return with carry push bx mov bx, dx xchg ax, bx xor dx, dx div cx ; divide high order first xchg ax, bx div cx ; REMAINDER WILL BE IN DX mov word ptr ss:[ _RxDOS_Remainder ], dx ; save remainder mov dx, bx ; full 32-bit answer or bx, ax ; set zr flag if result is zero pop bx _div32_return: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Check if Keyboard Chars Available ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; zr none available ; ; nz available ; ; ; ; AL 00 if none, -1 if available ; ;...............................................................; CheckKeyboardCharsAvailable: Entry defbytes reqBlock, sizeMaxReqHeader mov al, -1 ; character device mov ah, NONDESTRREAD lea di, offset reqBlock [ bp ] call initReqBlock mov ax, word ptr [ _RxDOS_pCONdriver. _segment ] or ax, word ptr [ _RxDOS_pCONdriver. _pointer ] jz checkKeybd_None ; if no CON driver --> push word ptr [ _RxDOS_pCONdriver. _segment ] push word ptr [ _RxDOS_pCONdriver. _pointer ] call CharDevRequest ; test for character mov al, 00 ; set character available test word ptr [ reqBlock. ndrStatus ][ bp ], OP_DONE jz checkKeybd_None ; if no character --> test word ptr [ reqBlock. ndrStatus ][ bp ], OP_BUSY jnz checkKeybd_None ; if no character --> mov al, -1 ; set character available checkKeybd_None: or al, al Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Redirected Input ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; ax device handle ; ; ; ; Returns: ; ; al character from device ; ;...............................................................; _RedirectedInput: Entry def _handle, ax defbytes _tempbuffer, 8 ; just need 2, but give a little. call CtrlC_CheckAlways ; control C ? mov word ptr _tempbuffer [ bp ], 0000 ; just place a null in case of error call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _redirectedInput_22 ; if sft NOT located --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; read from redirected file (SFT pointer at es:di) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call updateAllChangedCCBBuffers mov cx, 0001 ; bytes to read getarg ax, _handle ; 00 if stdin lea bx, offset _tempbuffer [ bp ] push ss ; buffer pointer. _segment push bx ; buffer pointer. _pointer call _SFTReadFile ; read using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _redirectedInput_22: xor ax, ax RetCallersStackFrame es, bx mov al, byte ptr _tempbuffer [ bp ] mov word ptr es:[ _AX ][ bx ], ax Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Redirected Output ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; ax device handle ; ; dl character to display to standard output ; ;...............................................................; _RedirectedOutput: Entry defbytes _tempbuffer, 8 ; just need 2, but give a little. mov byte ptr _tempbuffer [ bp ], dl ; save character to display call CtrlC_CheckAlways ; control C ? call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _redirectedOutput_22 ; if sft NOT located --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; display to redirected file (SFT pointer at es:di) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov cx, 0001 ; bytes to write lea bx, offset _tempbuffer [ bp ] push ss ; buffer pointer. _segment push bx ; buffer pointer. _pointer call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _redirectedOutput_22: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Control C Check ; ;...............................................................; CtrlC_Check: cmp byte ptr ss:[ _RxDOS_bCtrlBreakCheck ], 00 ; check for control C ? jnz CtrlC_CheckAlways ; if perform check --> clc ; not terminate ! ret ; return CtrlC_CheckAlways: Entry defbytes reqBlock, sizeMaxReqHeader defbytes _tempBuffer, 8 SaveAllRegisters mov al, -1 ; character device mov ah, NONDESTRREAD lea di, offset reqBlock [ bp ] call initReqBlock mov dx, word ptr [ _RxDOS_pCONdriver. _segment ] or dx, word ptr [ _RxDOS_pCONdriver. _pointer ] jz CtrlC_Check18 ; if no CON driver --> push word ptr [ _RxDOS_pCONdriver. _segment ] push word ptr [ _RxDOS_pCONdriver. _pointer ] call CharDevRequest ; test for character clc ; clear carry test word ptr [ reqBlock. ndrStatus ][ bp ], OP_DONE jz CtrlC_Check18 ; if no character --> test word ptr [ reqBlock. ndrStatus ][ bp ], OP_BUSY jnz CtrlC_Check18 ; if no character --> mov al, byte ptr [ reqBlock. ndrCharRead ][ bp ] cmp al, 03 ; control C ? jz CtrlC_CheckCallBack ; if control Break --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit without terminate ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CtrlC_Check18: clc ; clear carry RestoreAllRegisters ; restore all Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; process control-c ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CtrlC_CheckCallBack: setDS ss lea dx, offset _tempBuffer [ bp ] mov word ptr [ reqBlock.rwrBuffer. _segment ][ bp ], ss mov word ptr [ reqBlock.rwrBuffer. _pointer ][ bp ], dx mov word ptr [ reqBlock.rwrBytesReq ][ bp ], 1 mov byte ptr [ reqBlock.rwrFunction ][ bp ], DEVICEREAD push word ptr [ _RxDOS_pCONdriver. _segment ] push word ptr [ _RxDOS_pCONdriver. _pointer ] call CharDevRequest ; read ^C character ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; echo control-c ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - setES cs mov cx, 4 mov bx, offset _RxDOS_ContrlC_Message call writeConsoleOut cli mov bx, word ptr [ _RxDOS_CurrentInstance ] ; base address of current user stack mov ax, word ptr [ bx - 4 ] ; stack top mov word ptr [ _RxDOS_CurrentStackTop ], ax mov ax, word ptr [ bx - 6 ] ; current instance mov word ptr [ _RxDOS_CurrentInstance ], ax mov ax, word ptr [ bx - 8 ] ; INDOS flag mov word ptr [ _RxDOS_INDOSFlag ], ax mov dx, word ptr [ _segment ][ bx ] ; get seg address of user's stack mov ax, word ptr [ _pointer ][ bx ] ; get ptr address of user's stack sub ax, sizeStackFrame ; adjusted stack pointer mov sp, ax mov ss, dx ; switch stacks sti ; restore interrupts nop ; convenience for debugging pop ax ; restore registers pop bx pop cx pop dx pop si pop di pop bp pop ds pop es int intCONTROLC ; cause int 23 if Control C jnc CtrlC_CheckCallBack_08 ; if not terminate --> mov ah, TerminateProcess ; terminate process CtrlC_CheckCallBack_08: Int 21h ; should never return stc ; exit with carry retf 2 ; if it does, we left a return address ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; DOS Functions ; ;...............................................................; ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 01h Keyboard Input (from redirected STDIN) ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al character from standard input ; ;...............................................................; _KeyboardInput: mov ax, STDIN ; handle is stdin call _RedirectedInput ; byte saved in AL on return mov dl, al ; set to echo character mov ax, STDOUT ; handle jmp _RedirectedOutput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 02h Display Output ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; dl character to display to standard output ; ;...............................................................; _DisplayOutput: mov ax, STDOUT ; handle jmp _RedirectedOutput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 03h Aux (Comm Port) Input ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al character from standard aux ; ;...............................................................; _AuxInput: mov ax, STDAUX jmp _RedirectedInput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 04h Aux (Comm Port) Output ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; dl character from standard aux ; ;...............................................................; _AuxOutput: mov ax, STDAUX jmp _RedirectedOutput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 05h Prn (Printer) Output ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; dl character from standard aux ; ;...............................................................; _PrinterOutput: mov ax, STDPRN jmp _RedirectedOutput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 06h Direct Console I/O ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; dl = ff, read ; ; = anything else, writes dl character ; ; ; ; Returns: ; ; dl character from standard aux ; ;...............................................................; _DirectConsole: cmp dl, -1 ; read ? jz _DirectConsoleInput ; yes --> mov ax, STDOUT ; else output char in dl jmp _RedirectedOutput ; to stdout --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; input ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _DirectConsoleInput: mov ax, STDIN jmp _RedirectedInput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 07h Unfiltered Console Input No Echo ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al character from keyboard ; ;...............................................................; _DirectConsoleInputNoEcho: mov ax, STDIN jmp _RedirectedInput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 08h Direct Console Input No Echo ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al character from keyboard ; ;...............................................................; _ConsoleInputNoEcho: mov ax, STDIN jmp _RedirectedInput ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 09h Display String ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; ds:dx pointer to display string ; ;...............................................................; _DisplayString: Entry ddef _sftPointer ddef _buffer, es, dx call CtrlC_CheckAlways ; look-ahead CtrlC Check mov ax, STDOUT ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _displayOutput_22 ; if sft NOT located --> stordarg _sftPointer, es, di ; save sft buffer pointer ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; display to redirected file ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov al, '$' mov cx, -1 les di, dword ptr [ _buffer ][ bp ] repnz scasb ; compute length of string jnz _displayOutput_22 ; strange, but exit if none --> neg cx sub cx, 2 ; remove $ from output push word ptr [ _buffer. _segment ][ bp ] push word ptr [ _buffer. _pointer ][ bp ] getdarg es, di, _sftPointer ; get sft buffer pointer call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _displayOutput_22: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Ah Get Buffered Keyboard Input ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; es:dx pointer to a buffer ; ; (lead byte contains max length) ; ;...............................................................; _BufferedKeyboardInput: Entry ddef _buffer, es, dx def _needsEcho, FALSE mov bx, dx mov byte ptr es:[ bufActualLength ][ bx ], 00 ; actual bytes read (none so far ) call CtrlC_CheckAlways ; look-ahead CtrlC Check mov ax, STDIN ; handle is stdin call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _buffkbdInput_Exit ; if sft NOT located --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; read from redirected file (SFT pointer at es:di) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call updateAllChangedCCBBuffers ; if stdin input, must flsuh buffers getdarg ds, bx, _buffer mov ch, 0 mov cl, byte ptr [ bufMaxLength ][ bx ] ; max bytes mov byte ptr [ bufActualLength ][ bx ], 00 ; actual bytes read lea bx, offset [ bufData ][ bx ] ; pointer to actual data test word ptr es:[ sftDevInfo ][ di ], sftIsDevice jz _buffkbdInput_14 ; if file --> push word ptr es:[ sftDCB. _segment ][ di ] push word ptr es:[ sftDCB. _pointer ][ di ] mov es, word ptr [ _buffer. _segment ][ bp ] ; return buffer segment mov di, bx ; buffer address call devCharReadLine ; read till cr or eof. mov ax, cx jmp short _buffkbdInput_16 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if read from file ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _buffkbdInput_14: push ds ; buffer pointer. _segment push bx ; buffer pointer. _pointer call _SFTReadLine ; read using sft (at es:di ) mov word ptr [ _needsEcho ][ bp ], TRUE _buffkbdInput_16: getdarg es, bx, _buffer mov byte ptr es:[ bufActualLength ][ bx ], al ; actual bytes read cmp ax, word ptr es:[ bufMaxLength ][ bx ] ; at maximum buffer ? jge _buffkbdInput_22 ; yes --> add bx, ax mov byte ptr es:[ bufData ][ bx ], ControlM ; add cr to end inc ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; echo line to stdout ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _buffkbdInput_22: cmp word ptr [ _needsEcho ][ bp ], FALSE jz _buffkbdInput_Exit ; if no echo --> push ax ; count mov ax, STDOUT ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) pop cx jc _buffkbdInput_Exit ; if sft NOT located --> push word ptr [ _buffer. _segment ][ bp ] mov bx, word ptr [ _buffer. _pointer ][ bp ] lea bx, offset [ bufData ][ bx ] ; pointer to actual data push bx call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _buffkbdInput_Exit: getdarg es, bx, _buffer mov al, byte ptr es:[ bufActualLength ][ bx ] ; actual bytes read mov ah, 0 Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Bh Check Keyboard Input ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; AL = -1 if data available in STDIN ; ;...............................................................; _CheckKeyboardInput: call CtrlC_CheckAlways ; look-ahead CtrlC Check mov ax, STDIN ; handle is stdin call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) mov al, 00 jc _checkkbdInput_22 ; if sft not located --> test word ptr es:[ sftDevInfo ][ di ], sftIsDevice jz _checkkbdInput_22 ; if not a keyboard device --> call CheckKeyboardCharsAvailable ; set if character is available _checkkbdInput_22: RetCallersStackFrame es, bx mov byte ptr es:[ _AX. _AL ][ bx ], al ; set chars available or ax, ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Ch Clear buffered keyboard input ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; AL function number ; ; ; ;...............................................................; _ClearBufferedKeyboardInput: push es push dx push ax ; save service mov ax, STDIN ; handle is stdin call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _ClrBuf_16 ; if sft not located --> test word ptr es:[ sftDevInfo ][ di ], sftIsDevice jz _ClrBuf_16 ; if not a keyboard device --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; see if characters are available ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ClrBuf_14: call CheckKeyboardCharsAvailable jz _ClrBuf_16 mov ax, STDIN ; handle is stdin call _RedirectedInput ; read keyboard jmp _ClrBuf_14 ; loop until cleared buffer --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; dispatch to follow-up service ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ClrBuf_16: pop ax pop dx pop es ; restore registers cmp al, KeyboardInput ifz _KeyboardInput ; if function 01 --> cmp al, DirectConsole ifz _DirectConsole ; if function 06 --> cmp al, DirectConsoleInputNoEcho ifz _DirectConsoleInputNoEcho ; if function 07 --> cmp al, ConsoleInputNoEcho ifz _ConsoleInputNoEcho ; if function 08 --> cmp al, BufferedKeyboardInput ifz _BufferedKeyboardInput ; if function 0A --> RetCallersStackFrame es, bx mov byte ptr es:[ _AX. _AL ][ bx ], 00 ; else clear character or ax, ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Dh Reset Disk ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Update disk buffers. ; ; ; ;...............................................................; _DiskReset: call updateAllChangedCCBBuffers ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Eh Select Disk ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; dl select drive (0 = A:, 1 = B:, ... ) ; ;...............................................................; _SelectDisk: RetCallersStackFrame es, bx mov al, byte ptr [ _RxDOS_bLastDrive ] ; max logical drives mov byte ptr es:[ _AX. _AL ][ bx ], al ; return max. cmp dl, al ; greater than max drives ? jge _selectDisk_08 ; yes, ignore change --> push dx xor ah, ah mov al, dl ; drive letter call getDPB ; see if valid drive pop dx ; restore disk select jc _selectDisk_08 ; if invalid drive --> cmp word ptr es:[ _dpbptrDeviceDriver. _segment ][ bx ], 0000 stc jz _selectDisk_08 ; if invalid drive --> mov byte ptr [ _RxDOS_CurrentDrive ], dl ; else change drives. _selectDisk_08: or ax, ax ; no carry ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 0Fh Open File with FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _OpenFileFCB: Entry def _openMode ddef _fcbPointer, es, dx defbytes _expandedName, 128 ; expanded file name (128 bytes ) call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; convert FCB name to name usable by SFT Open ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov si, dx ; source FCB address lea di, offset _expandedName [ bp ] ; expand name saveRegisters es, si, ss, di ; arguments call convFCBNametoASCIZ ; build asciz name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; try SFT Open ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - setES ss ; es: lea dx, offset _expandedName [ bp ] ; es: dx filename mov al, DEFAULT_FCBOPENMODE ; mode is default open mode call _SFTOpenFile ; build an SFT jc _OpenFileFCB_26 ; if error --> getdarg ds, si, _fcbPointer ; fcb address call initFCBfromSFT ; [ax] handle, [es:di] ptr to sft or ax, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _OpenFileFCB_26: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 10h Close FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _CloseFileFCB: call findmatchingFCBSFT ; find matching SFT jc _CloseFileFCB_Error ; if can't locate, can't close --> call _SFTCloseFile or bx, bx ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CloseFileFCB_Error: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 11h Search First File FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; or, pointer to an extended FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _SearchFirstFileFCB: Entry ddef _fcb, es, dx defbytes _findEntry, sizeFINDENTRY call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build find entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lea di, offset _findEntry [ bp ] push es push dx push ss push di xor dx, dx ; begin at start of dir call buildFindFromFCB call LocateFileByAttribute ; locate item jc _SearchFirstFileFCB_20 ; if not found --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build a return entry in DTA ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - push word ptr [ _fcb. _segment ][ bp ] ; fcb address push word ptr [ _fcb. _pointer ][ bp ] push es ; find block push di call buildDTAfcbFind ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; all set, return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SearchFirstFileFCB_20: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 12h Search Next File FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _SearchNextFileFCB: Entry ddef _fcb, es, dx defbytes _findEntry, sizeFINDENTRY call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build find entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lea di, offset _findEntry [ bp ] push es push dx push ss push di mov bx, dx mov dx, word ptr es:[ fcbCurrRecNo ][ bx ] inc dx ; point to next entry call buildFindFromFCB call LocateFileByAttribute ; locate item jc _SearchNextFileFCB_08 ; if none found --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build a return entry in DTA ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - push word ptr [ _fcb. _segment ][ bp ] ; fcb address push word ptr [ _fcb. _pointer ][ bp ] push es ; find block push di call buildDTAfcbFind ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SearchNextFileFCB_08: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 13h Delete File FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB, wild cards allowed ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _DeleteFileFCB: Entry ddef _fcb, es, dx def _deleted, 0000 defbytes _findEntry, sizeFINDENTRY call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build find entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lea di, offset _findEntry [ bp ] push es push dx push ss push di xor dx, dx ; begin at start of dir call buildFindFromFCB ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; keep looping until all matching are deleted ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _deleteFileFCB_08: setES ss lea di, offset _findEntry [ bp ] call LocateFileByAttribute ; locate item jc _deleteFileFCB_20 mov si, word ptr [ _findEntry. findCCBPointer ][ bp ] call locateCCBPHeader ; get buffers segment test byte ptr es:[ deAttributes ][ si ], ATTR_READONLY jnz _deleteFileFCB_08 mov al, byte ptr [ _findEntry. findSrchDrive ][ bp ] mov dx, word ptr es:[ deStartCluster ][ si ] mov byte ptr es:[ si ], DIRENTRY_DELETED call ReleaseClusterChain ; release cluster chain call CCBChanged ; release buffer at [es:di] inc word ptr [ _deleted ][ bp ] ; say some items deleted jmp _deleteFileFCB_08 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _deleteFileFCB_20: cmp word ptr [ _deleted ][ bp ], 0000 ; any deleted ? jg _deleteFileFCB_24 ; yes --> stc ; if none found. _deleteFileFCB_24: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 14h Read Sequential/ FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _SeqReadFileFCB: Entry def _readCount ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to read if valid fcb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov cx, word ptr es:[ fcbRecordSize ][ di ] mov word ptr [ _readCount ][ bp ], cx ; bytes to read to dta or cx, cx stc jz _SeqReadFileFCB_Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, 128 mul word ptr es:[ fcbCurrBlockNo ][ di ] ; block # times 128 add al, byte ptr es:[ fcbCurrRecNo ][ di ] ; full 23 bit address mul cx ; actual byte offset stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _SeqReadFileFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restor position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx mov ax, -1 ; ! stdin mov cx, word ptr [ _readCount ][ bp ] ; bytes to read to dta push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTReadFile ; read using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute return logical position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, di, _fcbPointer getdarg dx, ax, _position add ax, word ptr es:[ fcbRecordSize ][ di ] adc dx, 0000 div word ptr es:[ fcbRecordSize ][ di ] ; actual byte offset xor dx, dx mov cx, 128 div cx mov byte ptr es:[ fcbCurrRecNo ][ di ], dl mov word ptr es:[ fcbCurrBlockNo ][ di ], ax or ax, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SeqReadFileFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 15h Write Sequential/ FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _SeqWriteFileFCB: Entry def _writeCount ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to write if valid fcb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov cx, word ptr es:[ fcbRecordSize ][ di ] mov word ptr [ _writeCount ][ bp ], cx ; bytes to write from dta or cx, cx ; if bytes are zero stc jz _SeqWriteFileFCB_Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, 128 mul word ptr es:[ fcbCurrBlockNo ][ di ] ; block # times 128 add al, byte ptr es:[ fcbCurrRecNo ][ di ] ; full 23 bit address mul cx ; actual byte offset stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _SeqWriteFileFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restore position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx getarg cx, _writeCount ; bytes to write to dta push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute return logical position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, di, _fcbPointer inc byte ptr es:[ fcbCurrRecNo ][ di ] test byte ptr es:[ fcbCurrRecNo ][ di ], 128 jz _SeqWriteFileFCB_22 inc word ptr es:[ fcbCurrBlockNo ][ di ] _SeqWriteFileFCB_22: and byte ptr es:[ fcbCurrRecNo ][ di ], 127 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SeqWriteFileFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 16h Create File with FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _CreateFileFCB: Entry ddef _fcbPointer, es, dx defbytes _expandedName, 128 ; expanded file name (128 bytes ) call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; convert FCB name to name usable by SFT Open ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov si, dx ; source FCB address lea di, offset _expandedName [ bp ] ; expand name saveRegisters es, si, ss, di ; arguments call convFCBNametoASCIZ ; build asciz name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; try SFT Open ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - setES ss ; es: lea dx, offset _expandedName [ bp ] ; es: dx filename mov al, DEFAULT_FCBOPENMODE ; mode is default open mode xor cx, cx ; expected attributes call _SFTCreateFile ; build an SFT jc _CreateFileFCB_26 ; if error --> getdarg ds, si, _fcbPointer ; fcb address call initFCBfromSFT ; [ax] handle, [es:di] ptr to sft or ax, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateFileFCB_26: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 17h Rename File FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB, wild cards allowed ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _RenameFileFCB: Entry ddef _fcb, es, dx defbytes _expandedName, 128 ; expanded file name (128 bytes ) call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build first name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov si, dx ; source FCB address lea di, offset _expandedName [ bp ] ; expand name saveRegisters es, si, ss, di ; arguments call convFCBNametoASCIZ ; build asciz name push es push di ; unexpanded filename push ds mov di, offset SDAFirstName push di ; where to expand name mov ax, FILECANNOT_BEDIRECTORY call ExpandFileName ; expand first name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; build second name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, si, _fcb ; source FCB address add si, 16 ; point to second part of fcb lea di, offset _expandedName [ bp ] ; expand name saveRegisters es, si, ss, di ; arguments call convFCBNametoASCIZ ; build asciz name push es push di ; unexpanded filename push ds mov di, offset SDASecondName push di ; where to expand name mov ax, FILECANNOT_BEDIRECTORY call ExpandFileName ; expand second name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Use IFS to rename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IFS IFSRenameFile ; rename file call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 19h Current Disk ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al current disk returned. ; ;...............................................................; _CurrentDisk: RetCallersStackFrame es, bx mov al, byte ptr [ _RxDOS_CurrentDrive ] mov byte ptr es:[ _AX._AL ][ bx ], al ; set max for return ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 1Ah Set Disk Transfer Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx Disk Transfer Address ; ; ; ; (see related function 2F - Get Disk Transfer Address) ; ;...............................................................; _SetDiskTransferAddress: mov word ptr [ _RxDOS_pDTA. _pointer ], dx mov word ptr [ _RxDOS_pDTA. _segment ], es ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 1Bh Get Default Drive Data ; ;...............................................................; _GetDefaultDriveData: xor dx, dx ; set current drive ; jmp short _GetDriveData ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 1Ch Get Drive Data ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; dl drive ; ;...............................................................; _GetDriveData: push ds push dx ; (argument expected on stack) call GetActualDrive ; actual drive (in dx) jc _getDriveData_20 ; if invalid drive --> call getDPB ; get pointer to DPB jc _getDriveData_20 ; if invalid drive --> RetCallersStackFrame ds, si mov cx, word ptr es:[ _dpbBytesPerSector ][ bx ] mov dx, word ptr es:[ _dpbMaxClusterNumber ][ bx ] mov al, byte ptr es:[ _dpbClusterSizeMask ][ bx ] inc al mov byte ptr [ _AX._AL ][ si ], al ; sectors/cluster mov word ptr [ _CX ][ si ], cx ; bytes per sector mov word ptr [ _DX ][ si ], dx ; clusters/drive lea di, offset _dpbMediaDescriptor [ bx ] mov word ptr [ _BX ][ si ], di mov word ptr [ _DataSegment ][ si ], es ; where to find media byte or ax, ax ; clear carry _getDriveData_20: jnc _getDriveData_22 mov al, -1 _getDriveData_22: pop ds ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 1Fh Get Dos Default Drive Device Parameter Block ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; no parameters ; ; ; ; Returns: ; ; al 0ffh if invalid drive ; ; ds:bx returns pointer to dos device parameter block ; ; ; ; (see related function 32 - Get Dos Device Parameter Block) ; ;...............................................................; _GetDefaultDriveParameterBlock: xor dx, dx ; select default drive jmp _GetDriveParameterBlock ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 21h Read Sequential/ FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _ReadFileFCB: Entry def _readCount ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to read if valid fcb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov cx, word ptr es:[ fcbRecordSize ][ di ] mov word ptr [ _readCount ][ bp ], cx ; bytes to read to dta or cx, cx stc jz _ReadFileFCB_Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, word ptr es:[ fcbRecordSize ][ di ] call _mul32 stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _ReadFileFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restore position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx mov ax, -1 ; ! stdin mov cx, word ptr [ _readCount ][ bp ] ; bytes to read to dta push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTReadFile ; read using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute return logical position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, di, _fcbPointer mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, 128 call _div32 mov word ptr es:[ fcbCurrBlockNo ][ di ], ax mov dl, byte ptr es:[ fcbRandomRecNo. _low ][ di ] and dl, 127 mov byte ptr es:[ fcbCurrRecNo ][ di ], dl ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ReadFileFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 22h Write Sequential/ FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _WriteFileFCB: Entry def _writeCount ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to Write if valid fcb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov cx, word ptr es:[ fcbRecordSize ][ di ] mov word ptr [ _writeCount ][ bp ], cx ; bytes to write to dta or cx, cx stc jz _WriteFileFCB_Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, word ptr es:[ fcbRecordSize ][ di ] call _mul32 stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute block/ sector ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, 128 call _div32 mov word ptr es:[ fcbCurrBlockNo ][ di ], ax mov dl, byte ptr es:[ fcbRandomRecNo. _low ][ di ] and dl, 127 mov byte ptr es:[ fcbCurrRecNo ][ di ], dl ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _WriteFileFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restore position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx mov cx, word ptr [ _writeCount ][ bp ] ; bytes to write to dta push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _WriteFileFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 23h Get File Size FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ;...............................................................; _FileSizeFCB: mov di, dx cmp word ptr es:[ fcbRecordSize ][ di ], 0000 stc jz _FileSizeFCB_12 mov ax, word ptr es:[ fcbFileSize. _low ][ di ] mov dx, word ptr es:[ fcbFileSize. _high ][ di ] mov cx, word ptr es:[ fcbRecordSize ][ di ] call _div32 ; [ax:dx] / [cx] mov word ptr es:[ fcbRandomRecNo. _low ][ di ], ax mov word ptr es:[ fcbRandomRecNo. _high ][ di ], dx or ax, ax _FileSizeFCB_12: call setFCBErrorIfCarry ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 24h Set Random Record Number FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to FCB ; ;...............................................................; _SetRelativeRecordFCB: mov di, dx mov ax, 128 ; records/block mul word ptr es:[ fcbCurrBlockNo ][ di ] ; block # times record address add al, byte ptr es:[ fcbCurrRecNo ][ di ] ; full 23 bit address mov word ptr es:[ fcbRandomRecNo. _low ][ di ], ax mov word ptr es:[ fcbRandomRecNo. _high ][ di ], dx RetCallersStackFrame es, bx mov byte ptr es:[ _AX. _AL ][ bx ], 00 ; al always set to 00. clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 25h Set Interrupt Vector ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al interrupt number ; ; ds:dx interrupt routine address ; ;...............................................................; _SetInterruptVector: pushf ; save interrupts push ds push ax push bx push dx ; address to set push es ; user's [ds] at [es] inside code mov ah, 0 mov bx, ax ; int vector to [bx] add bx, bx add bx, bx cli xor ax, ax mov ds, ax pop word ptr [ bx. _segment ] ; segment pop word ptr [ bx. _pointer ] ; address pop bx pop ax pop ds popf ; restore interrupts ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 26h Create New Program Segment Prefix ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; dx segment address ; ; ; ; (see related function 55 - Duplicate PSP ) ; ;...............................................................; _CreateNewProgramSeg: mov es, dx ; new PSP segment address call copyCurrentPSP ; create a new PSP here ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 27h Random Read / FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx number of blocks to read ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _RandomBlockReadFCB: Entry def _error, 0000 def _readCount def _numBlocks, cx ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to read if valid fcb ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov cx, word ptr es:[ fcbRecordSize ][ di ] mov word ptr [ _readCount ][ bp ], cx ; bytes to read to dta or cx, cx stc jz _ReadBlockFCB_Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, word ptr es:[ fcbRecordSize ][ di ] call _mul32 stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _ReadBlockFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restor position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx mov ax, word ptr [ _numBlocks ][ bp ] ; number of blocks mul word ptr [ _readCount ][ bp ] ; bytes to read to dta mov cx, ax ; total bytes to read or dx, dx ; over 64k ? jz _ReadBlockFCB_12 ; if ok --> mov word ptr [ _error ][ bp ], errFCBSizeTooLarge ; too large mov cx, 0FFFFh ; read as much as possible _ReadBlockFCB_12: mov ax, -1 ; ! stdin push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTReadFile ; read using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute return logical position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, di, _fcbPointer getdarg dx, ax, _position add ax, word ptr es:[ fcbRecordSize ][ di ] adc dx, 0000 div word ptr es:[ fcbRecordSize ][ di ] ; actual byte offset xor dx, dx mov cx, 128 div cx mov byte ptr es:[ fcbCurrRecNo ][ di ], dl mov word ptr es:[ fcbCurrBlockNo ][ di ], ax mov ax, word ptr [ _numBlocks ][ bp ] ; number of blocks add word ptr es:[ fcbRandomRecNo. _low ][ di ], ax adc word ptr es:[ fcbRandomRecNo. _high ][ di ], 0000 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ReadBlockFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 28h Random Write / FCB ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx number of blocks to write ; ; ds:dx pointer to FCB ; ; ; ; Return: ; ; al = ff, if cannot locate any matching entry ; ; 00, if match located ; ;...............................................................; _RandomBlockWriteFCB: Entry def _error, 0000 def _writeCount def _numBlocks, cx ddef _position ddef _fcbPointer, es, dx call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute byte offset from block/rec nos ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx mov ax, word ptr es:[ fcbRandomRecNo. _low ][ di ] mov dx, word ptr es:[ fcbRandomRecNo. _high ][ di ] mov cx, word ptr es:[ fcbRecordSize ][ di ] call _mul32 stordarg _position, dx, ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find corresponding sft ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call findmatchingFCBSFT ; find matching SFT jc _WriteBlockFCB_Return ; if no space --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init disk access block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg cx, dx, _position ; restor position mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx mov ax, word ptr [ _numBlocks ][ bp ] ; number of blocks mul word ptr [ _writeCount ][ bp ] ; bytes to write to dta mov cx, ax ; total bytes to Write or dx, dx ; over 64k ? jz _WriteBlockFCB_12 ; if ok --> mov word ptr [ _error ][ bp ], errFCBSizeTooLarge ; too large mov cx, 0FFFFh ; read as much as possible _WriteBlockFCB_12: push word ptr [ _RxDOS_pDTA. _segment ] ; disk transfer address push word ptr [ _RxDOS_pDTA. _pointer ] call _SFTWriteFile ; write using sft (at es:di ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; compute return logical position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getdarg es, di, _fcbPointer getdarg dx, ax, _position add ax, word ptr es:[ fcbRecordSize ][ di ] adc dx, 0000 mov cx, word ptr es:[ fcbRecordSize ][ di ] ; record size call _div32 mov word ptr es:[ fcbRandomRecNo. _low ][ di ], ax mov word ptr es:[ fcbRandomRecNo. _high ][ di ], dx mov cx, 128 call _div32 ; divide by 128 mov word ptr es:[ fcbCurrBlockNo ][ di ], ax mov dx, word ptr es:[ fcbRandomRecNo. _low ][ di ] and dl, 127 mov byte ptr es:[ fcbCurrRecNo ][ di ], dl ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _WriteBlockFCB_Return: call setFCBErrorIfCarry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 29h Parse Filename ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Usage: ; ; ds:si points to name to parse ; ; es:di points to uninitialized FCB ; ; al parse control ; ;...............................................................; _ParseFilenameFCB: Entry def _parseControl, ax def _wildChars, 0000 ddef _FCBPointer RetCallersStackFrame ds, bx mov di, word ptr [ _DI ][ bx ] mov es, word ptr [ _ExtraSegment ][ bx ] mov si, word ptr [ _SI ][ bx ] mov ds, word ptr [ _DataSegment ][ bx ] stordarg _FCBPointer, es, di ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; initialize FCB ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - test word ptr [ _parseControl ][ bp ], FCBPARSE_LEAVEDRIVEUNCHANGED jnz _ParseFilenameFCB_08 ; leave drive alone --> mov byte ptr es:[ fcbDrive ][ di ], 00h ; clear drive info _ParseFilenameFCB_08: test word ptr [ _parseControl ][ bp ], FCBPARSE_LEAVEFILENAMEUNCHANGED jnz _ParseFilenameFCB_12 ; leave filename alone --> getdarg es, di, _FCBPointer lea di, [ fcbName ][ di ] mov cx, sizefnName mov al, ' ' rep stosb ; clear filename to blanks _ParseFilenameFCB_12: test word ptr [ _parseControl ][ bp ], FCBPARSE_LEAVEEXTENSIONUNCHANGED jnz _ParseFilenameFCB_14 ; leave alone --> getdarg es, di, _FCBPointer lea di, [ fcbExtension ][ di ] mov cx, sizefnExtension mov al, ' ' rep stosb ; clear filename to blanks ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; skip through any leading garb characters ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_14: lodsb ; get char cmp al, ' ' ; space ? jz _ParseFilenameFCB_14 ; skip leading white space --> ifc _ParseFilenameFCB_86 ; if control char, exit --> call _ParseFilenameSeparator jnz _ParseFilenameFCB_36 ; yes, see if skip allowed --> test word ptr [ _parseControl ][ bp ], FCBPARSE_IGNORELEADSEPARATOR jnz _ParseFilenameFCB_14 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; test for valid drive ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_36: cmp byte ptr [ si ], ':' ; drive follows ? jnz _ParseFilenameFCB_54 ; no --> call lowerCase ; convert to lower case sub al, 'a' ; range jge _ParseFilenameFCB_40 ; if ok --> mov byte ptr [ _wildChars ][ bp ], -1 _ParseFilenameFCB_40: mov byte ptr es:[ fcbDrive ][ di ], al ; store drive info inc si ; skip over ':' lodsb ; get lead character of filename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; filename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_44: dec si ; position back at start of filename cmp byte ptr [ si ], '.' ; extension follows ? jnz _ParseFilenameFCB_48 ; no --> test word ptr [ _parseControl ][ bp ], FCBPARSE_LEAVEFILENAMEUNCHANGED jnz _ParseFilenameFCB_64 ; leave alone --> _ParseFilenameFCB_48: mov al, ' ' getdarg es, di, _FCBPointer lea di, [ fcbName ][ di ] mov cx, sizefnName push di push cx rep stosb ; clear filename to blanks pop cx pop di _ParseFilenameFCB_50: cmp byte ptr [ si ], '.' jz _ParseFilenameFCB_64 ; extension follows lodsb call _ParseFilenameSeparator jz _ParseFilenameFCB_64 cmp al, '*' jz _ParseFilenameFCB_58 cmp al, '?' jnz _ParseFilenameFCB_52 or byte ptr [ _wildChars ][ bp ], 01h _ParseFilenameFCB_52: call upperCase stosb ; save updated character loop _ParseFilenameFCB_50 ; continue --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; continue to skip until '.' or end of field ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_54: cmp byte ptr [ si ], '.' jz _ParseFilenameFCB_64 ; extension follows lodsb ; skip rest until '.' call _ParseFilenameSeparator ; if end of field jz _ParseFilenameFCB_64 jmp _ParseFilenameFCB_54 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; '*' fill filename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_58: or cx, cx jz _ParseFilenameFCB_64 mov al, '?' rep stosb or byte ptr [ _wildChars ][ bp ], 01h jmp _ParseFilenameFCB_54 ; make sure we loop for '.' ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; extension ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_64: cmp byte ptr [ si ], '.' ; extension follows ? jz _ParseFilenameFCB_66 ; yes --> test word ptr [ _parseControl ][ bp ], FCBPARSE_LEAVEEXTENSIONUNCHANGED jnz _ParseFilenameFCB_86 ; leave alone --> _ParseFilenameFCB_66: mov al, ' ' getdarg es, di, _FCBPointer lea di, [ fcbExtension ][ di ] mov cx, sizefnExtension push di push cx rep stosb ; clear filename to blanks pop cx pop di cmp byte ptr [ si ], '.' jnz _ParseFilenameFCB_86 ; if no extension follows --> _ParseFilenameFCB_70: lodsb call _ParseFilenameSeparator jz _ParseFilenameFCB_86 cmp al, '*' jz _ParseFilenameFCB_78 cmp al, '?' jnz _ParseFilenameFCB_72 or byte ptr [ _wildChars ][ bp ], 01h _ParseFilenameFCB_72: call upperCase stosb ; save updated character loop _ParseFilenameFCB_70 ; continue --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; continue to skip until end of field ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_74: lodsb ; skip rest until '.' call _ParseFilenameSeparator ; if end of field jz _ParseFilenameFCB_86 jmp _ParseFilenameFCB_74 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; '*' fill filename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_78: or cx, cx jz _ParseFilenameFCB_86 mov al, '?' rep stosb or byte ptr [ _wildChars ][ bp ], 01h jmp _ParseFilenameFCB_74 ; make sure we loop for '.' ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; end of parse ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameFCB_86: RetCallersStackFrame ds, bx mov word ptr [ _SI ][ bx ], si mov al, byte ptr [ _wildChars ][ bp ] mov byte ptr [ _AX._AL ][ bx ], al ; set wild character flag Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; filename separator test ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ParseFilenameSeparator: cmp al, '+' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '=' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, ',' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, ';' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '/' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '[' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, ']' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '<' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '>' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '"' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, '|' ; file name separator ? jz _ParseFnSeparator_08 ; yes --> cmp al, ' ' ; file name separator ? jge _ParseFnSeparator_08 ; yes --> xor ax, ax ; space or control is treated as space _ParseFnSeparator_08: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2Ah Get Date ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al day of week ( 0 = Sun, 1 = Mon, ... ) ; ; cx year (1980 - 2099) ; ; dh month (1 - 12) ; ; dl day (1 - 31) ; ;...............................................................; _GetDate: call getExpandedDate push cx push dx call getSystemDateValue pop dx pop cx RetCallersStackFrame ds, si mov word ptr [ _AX ][ si ], ax mov word ptr [ _CX ][ si ], cx mov word ptr [ _DX ][ si ], dx ; return parameters clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2Bh Set Date ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx year (1980 - 2099) ; ; dh month (1 - 12) ; ; dl day (1 - 31) ; ; ; ; Returns: ; ; al 00, date was valid ; ; ff, date was not valid ; ;...............................................................; _SetDate: Entry defbytes _datedef, sizeCLOCKDATA or dh, dh jz _setdate_error or dl, dl jz _setdate_error cmp dh, 12 + 1 jnc _setdate_error cmp dl, 31 + 1 jnc _setdate_error cmp cx, 1980 jl _setdate_error cmp cx, 2100 jnc _setdate_error push dx push cx setES ss lea di, offset _datedef [ bp ] call getSysDate ; get system date pop cx pop dx ; restore values mov byte ptr [ _datedef. cl_day ][ bp ], dl mov byte ptr [ _datedef. cl_month ][ bp ], dh mov word ptr [ _datedef. cl_year ][ bp ], cx call getDaysSince1980 mov word ptr [ _datedef. cl_daysSince1980 ][ bp ], ax setES ss lea di, offset _datedef [ bp ] call setSysDate ; set system date xor ax, ax call setFCBErrorIfCarry ; no error, no carry Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; problem with date ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _setdate_error: stc call setFCBErrorIfCarry ; set carry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2Ch Get Time ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; ch hour ( 0 - 23) ; ; cl minutes ( 0 - 59) ; ; dh seconds ( 0 - 59) ; ; dl hundredths ( 0 - 99) ; ;...............................................................; _GetTime: call getExpandedDateTime ; get system date RetCallersStackFrame ds, si mov word ptr [ _DX ][ si ], dx mov word ptr [ _CX ][ si ], cx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2Dh Set Time ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ch hour ( 0 - 23) ; ; cl minutes ( 0 - 59) ; ; dh seconds ( 0 - 59) ; ; dl hundredths ( 0 - 99) ; ; ; ; Returns: ; ; al 00, date was valid ; ; ff, date was not valid ; ;...............................................................; _SetTime: Entry defbytes _datedef, sizeCLOCKDATA cmp ch, 24 jnc _settime_error cmp cl, 60 jnc _settime_error cmp dh, 60 jnc _settime_error cmp dl, 100 jnc _settime_error push dx ; save time passed push cx setES ss lea di, offset _datedef [ bp ] call getSysDate ; get system date pop word ptr [ _datedef. cl_minutes ][ bp ] pop word ptr [ _datedef. cl_hseconds ][ bp ] call setSysDate ; set system date clc call setFCBErrorIfCarry ; no carry Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; problem with time ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _settime_error: stc call setFCBErrorIfCarry ; set carry Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2E00h Reset DOS Write Verify Switch ; ; 2E01h Set DOS Write Verify Switch ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al 00, set verify off ; ; 01, set verify on ; ; ; ; (see related function 54 - Get DOS Verify Switch ) ; ;...............................................................; _SetVerifySwitch: or al,al jz _setverifySwitch_20 cmp al,1 jz _setverifySwitch_20 stc ret _setverifySwitch_20: mov byte ptr [ _RxDOS_Verify ], al or ax, ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 2Fh Get Disk Transfer Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; es:bx Disk Transfer Address ; ; ; ; (see related function 1A - Set Disk Transfer Address) ; ;...............................................................; _GetDiskTransferAddress: les bx, dword ptr [ _RxDOS_pDTA. _pointer ] RetCallersStackFrame ds, si mov word ptr [ _ExtraSegment ][ si ], es mov word ptr [ _BX ][ si ], bx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 30h Get DOS Version ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; al 00h return OEM version number in bh ; ; 01h return version flag in bh ; ; ; ; Returns: ; ; al major version ; ; ah minor version ; ; bl:cx user's serial number ; ; bh OEM identification number ; ; or version flag ; ;...............................................................; _GetDOSVersion: mov bh, byte ptr ss:[ _RxDOS_DOSOEMVersion ] ; always 94 for RxDOS cmp al, 1 ; ROM version status ? jnz _GetDOSVersion_08 ; no --> mov bh, byte ptr ss:[ _RxDOS_DOSROMStatusFlag ] ; always 94 for RxDOS _GetDOSVersion_08: mov cx, word ptr ss:[ _RxDOS_UserSerialNumber ] mov bl, byte ptr ss:[ _RxDOS_UserSerialNumber + 2 ] mov ax, word ptr ss:[ _RxDOS_DOSVersion ] ; pre DOS 5 (see 3306h) mov dx, word ptr ss:[ _RxDOS_CurrentPSP ] ; get PSP or dx, dx ; during device laod ? jz _GetDOSVersion_12 ; yes --> mov es, dx ; Seg Pointer of current PSP mov ax, word ptr es:[ pspVersion ] ; Major, Minor version (VERS) _GetDOSVersion_12: RetCallersStackFrame ds, si mov word ptr [ _AX ][ si ], ax mov word ptr [ _BX ][ si ], bx mov word ptr [ _CX ][ si ], cx clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 31h Terminate But Stay Resident ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al return value ; ; dx keep memory size ; ;...............................................................; _TerminateStayResident: Entry def _parentPSP, 0000 ddef _returnVector mov ah, TERMINATE_TSR mov word ptr [ _RxDOS_ChildReturnCode ], ax ; save return status code ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; fix size of current PSP block ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov es, word ptr [ _RxDOS_CurrentPSP ] mov bx, dx ; keep size call _modifyMemBlock ; fix size ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; see if there is a parent process ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov es, word ptr ss:[ _RxDOS_CurrentPSP ] mov dx, word ptr es:[ pspParentId ] ; get parent PSP storarg _parentPSP, dx ; save for later mov word ptr es:[ pspParentId ], 0000 ; kill parent for next time. or dx, dx ; no parent ? jz _TerminateStayResident_20 ; can't terminate --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; restore interrupts/ return to parent PSP ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cli push ds xor ax, ax mov ds, ax mov es, word ptr ss:[ _RxDOS_CurrentPSP ] mov ax, word ptr es:[ pspTerminateVect. _pointer ] mov dx, word ptr es:[ pspTerminateVect. _segment ] stordarg _returnVector, dx, ax mov bx, offset ( intCONTROLC * 4 ) ; Int23 control-C vector mov ax, word ptr es:[ pspControlCVect. _pointer ] mov dx, word ptr es:[ pspControlCVect. _segment ] mov word ptr [ _pointer ][ bx ], ax mov word ptr [ _segment ][ bx ], dx mov bx, offset ( intCRITICALERROR * 4 ) ; Int24 criterror vector mov ax, word ptr es:[ pspCritErrorVect. _pointer ] mov dx, word ptr es:[ pspCritErrorVect. _segment ] mov word ptr [ _pointer ][ bx ], ax mov word ptr [ _segment ][ bx ], dx pop ds sti ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return to parent process ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getarg es, _parentPSP ; get PSP mov word ptr ss:[ _RxDOS_CurrentPSP ], es ; restore mov dx, word ptr es:[ pspUserStack. _segment ] mov ax, word ptr es:[ pspUserStack. _pointer ] ; parent user's stack mov bx, word ptr ss:[ _RxDOS_CurrentInstance ] ; base address of current stack mov word ptr ss:[ _segment ][ bx ], dx mov word ptr ss:[ _pointer ][ bx ], ax RetCallersStackFrame es, bx getdarg dx, ax, _returnVector mov word ptr es:[ _CS ][ bx ], dx mov word ptr es:[ _IP ][ bx ], ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _TerminateStayResident_20: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 32h Get Dos Device Parameter Block ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; dl 0= default, ; ; 1= a:, 2 = b:, ... ; ; ; ; Returns: ; ; al 0ffh if invalid drive ; ; ds:bx returns pointer to dos device parameter block ; ; ; ; (see related function 1F - Get Default Drive DPB ) ; ;...............................................................; _GetDriveParameterBlock: push dx call GetActualDrive ; actual drive (in ax) jnc _GetDriveParameterBlock_08 ; if valid drive --> call setFCBErrorIfCarry ; else set error ret _GetDriveParameterBlock_08: mov cx, sizeDPB mul cx ; create DPB offset les bx, dword ptr ss:[ _RxDOS_pDPB ] add bx, ax RetCallersStackFrame ds, si mov word ptr [ _DataSegment ][ si ], es mov word ptr [ _BX ][ si ], bx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3300h Get ControlC Check Flag ; ; 3301h Set ControlC Check Flag ; ; 3305h Get Startup Drive ; ; 3306h Get DOS Version ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; dx returns values ; ;...............................................................; _CtrlBreakCheck: RetCallersStackFrame es, si Goto GetControlC, __getControlC Goto SetControlC, __setControlC Goto GetStartupDrive, __getStartupDrive Goto GetExtDosVersion, __getExtDosVersion stc call setFCBErrorIfCarry ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get control c flag ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __getControlC: mov dl, byte ptr ss:[ _RxDOS_bCtrlBreakCheck ] mov byte ptr es:[ _DX._DL ][ si ], dl ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; set control c flag ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __setControlC: mov dl, byte ptr es:[ _DX._DL ][ si ] and dl, 0001h mov byte ptr ss:[ _RxDOS_bCtrlBreakCheck ], dl ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get startup drive ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __getStartupDrive: mov dl, byte ptr ss:[ _RxDOS_BootDrive ] mov byte ptr es:[ _DX._DL ][ si ], dl ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get extended DOS version ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __getExtDosVersion: mov bx, word ptr ss:[ _RxDOS_DOSVersion ] mov word ptr es:[ _BX ][ si ], bx mov word ptr es:[ _DX ][ si ], 0000 ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 34h Get INDOS Flag Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; es:bx returns pointer INDOS flag ; ;...............................................................; _GetInDOSFlagAddress: RetCallersStackFrame es, si mov word ptr es:[ _BX ][ si ], offset _RxDOS_INDOSFlag mov word ptr es:[ _ExtraSegment ][ si ], ds ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 35h Get Interrupt Vector ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al interrupt number ; ; es:bx interrupt routine address ; ;...............................................................; _GetInterruptVector: pushf ; save interrupts push ds ; save current segment mov ah, 0 mov si, ax add si, si add si, si cli xor ax, ax mov ds, ax mov es, word ptr [ si ][ _segment ] ; segment mov bx, word ptr [ si ][ _pointer ] ; address RetCallersStackFrame ds, si mov word ptr [ _BX ][ si ], bx mov word ptr [ _ExtraSegment ][ si ], es pop ds popf ; restore interrupts ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 36h Get Free Disk Space ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; dl drive (A=1, B=2, ... ) ; ;...............................................................; _GetFreeDiskSpace: call CtrlC_Check ; look-ahead CtrlC Check RetCallersStackFrame es, bx mov word ptr es:[ _AX ][ bx ], -1 ; in case of error, -1 push dx call GetActualDrive ; actual drive (in dx) jc _getFreeDiskSpace_20 ; arg returend in ax call AmountFreeSpace ; get amount free space RetCallersStackFrame ds, si mov cx, word ptr es:[ _dpbFreeCount ][ bx ] mov word ptr [ _BX ][ si ], cx ; # free clusters mov cx, word ptr es:[ _dpbBytesPerSector ][ bx ] mov dx, word ptr es:[ _dpbMaxClusterNumber ][ bx ] mov al, byte ptr es:[ _dpbClusterSizeMask ][ bx ] cbw inc ax mov word ptr [ _AX ][ si ], ax ; sectors/cluster mov word ptr [ _CX ][ si ], cx ; bytes per sector mov word ptr [ _DX ][ si ], dx ; clusters/drive or ax, ax ; clear carry _getFreeDiskSpace_20: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3700h Get Switch Char ; ; 3701h Set Switch Char ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; dl switch character ; ; ; ; ; ; -- Obsoleted. This fct no longer supported in v.5 MSDOS ---- ; ;...............................................................; _GetSetSwitchChar: or al, al jnz _GetSetSwitchChar_Set mov dl, byte ptr [ _RxDOS_bSwitchChar ] RetCallersStackFrame es, bx mov byte ptr es:[ _DX._DL ][ bx ], dl ; return value. ret _GetSetSwitchChar_Set: mov byte ptr [ _RxDOS_bSwitchChar ], dl ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 38h Country Dependent Info ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx points to get country info buffer ; ; dx = FFFFh, Set country code ; ; ; ; al country code if less than 254, else FFh ; ; ; ; bx country code if greater than 254 ; ; al = FFh ; ; ; ; If dx is NOT FFFFh, returns COUNTRYINFO structure, else ; ; sets country code. ; ;...............................................................; _CountryDependentInfo: RetCallersStackFrame es, bx cmp dx, -1 ; set or return country code ? jz _SetCountryInfo ; if set country info --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get country info ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, dx ; destination address mov si, offset _RxDOS_CurrCountryInfo ; current country info mov cx, sizeCOUNTRYINFO ; size rep movsb ; copy mov ax, word ptr [ _RxDOS_UserCountryCode ] mov word ptr es:[ _BX ][ bx ], ax ; CC returned in BX mov byte ptr es:[ _AX. _AL ][ bx ], al ; ... and AL clc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; set country info ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetCountryInfo: cmp al, -1 ; country < 254 ? jz _SetCountryInfo_08 ; no --> mov bx, ax xor bh, bh ; country code to bx _SetCountryInfo_08: mov word ptr [ _RxDOS_UserCountryCode ], bx ; should check values clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 39h Create Subdirectory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to subdirectory ; ;...............................................................; _CreateSubdirectory: Entry ddef _pathname, es, dx ; arg passed internally as es:dx ddef _dirAddress ; dir reference def _alloccluster ; allocated cluster ddef _datetime defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; does entry already exist ? ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME + FILEHAS_NOFILENAME + FILECANNOT_BEDEFINED) getdarg es, si, _pathname ; arg passed internally as es:dx lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _MakeSubDir_12 ; if path is valid --> call _chgErrorToPathNotFound ; if name referenced path jmp _MakeSubDir_40 ; if path invalid --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; find next empty directory entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _MakeSubDir_12: and word ptr [ _dirAccess. fileAcDrive ][ bp ], 7FFFh mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] mov dx, word ptr [ _dirAccess. fileAcDirCluster ][ bp ] call LocateFreeDirSlot ; valid empty entry ? ifc _MakeSubDir_40 ; if can't find free slot --> push si call locateCCBPHeader ; get ccb header into es:di or byte ptr es:[ ccbStatus ][ di ], ccb_isONHOLD pop di ; convert name to dir style stordarg _dirAddress, es, di ; address of empty loc found clearMemory sizeDIRENTRY ; init to zeroes lea si, word ptr [ _dirAccess ][ bp ] mov si, word ptr [ fileAcNameOffset ][ si ] call convFilenametoFCBString ; dir style name call getSysDateinDirFormat stordarg _datetime, dx, ax ; make sure we get these ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Allocate cluster for sub-directory ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] call AllocateInitCluster ; init/ allocate storarg _alloccluster, dx ; save cluster ifc _MakeSubDir_40 ; if error --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init (.) entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lea si, offset ccbData [ di ] ; point to data call blankinitDirName ; initialize file name mov byte ptr es:[ deName ][ si ], '.' ; set dot entry getarg dx, _alloccluster ; get cluster mov word ptr es:[ deStartCluster ][ si ], dx getdarg dx, ax, _datetime ; get date/ time mov word ptr es:[ deTime ][ si ], ax ; time created mov word ptr es:[ deDate ][ si ], dx ; date created mov byte ptr es:[ deAttributes ][ si ], ATTR_DIRECTORY ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; init (..) entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lea si, offset ccbData.sizeDIRENTRY [ di ] call blankinitDirName ; initialize file name mov word ptr es:[ deName ][ si ], '..' ; set double dot entry mov dx, word ptr [ _dirAccess. fileAcDirCluster ][ bp ] mov word ptr es:[ deStartCluster ][ si ], dx getdarg dx, ax, _datetime ; get date time mov word ptr es:[ deTime ][ si ], ax ; time created mov word ptr es:[ deDate ][ si ], dx ; date created mov byte ptr es:[ deAttributes ][ si ], ATTR_DIRECTORY call CCBChanged ; mark changes made mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] ; call updateDriveBuffers ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; in parent directory, build entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getarg dx, _alloccluster getdarg es, si, _dirAddress ; restore si pointer mov word ptr es:[ deStartCluster ][ si ], dx mov byte ptr es:[ deAttributes ][ si ], ATTR_DIRECTORY getdarg dx, ax, _datetime ; get date time mov word ptr es:[ deTime ][ si ], ax ; time created mov word ptr es:[ deDate ][ si ], dx ; date created call locateCCBPHeader ; get ccb header into es:di call CCBChanged ; mark changes made mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] ; call updateDriveBuffers xor ax, ax ; clear carry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; normal exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _MakeSubDir_40: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3Ah Remove Subdirectory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to subdirectory ; ;...............................................................; _RemoveSubdirectory: Entry ddef _pathname, es, dx ; arg passed internally as es:dx defbytes _dirAccess, sizeDIRACCESS defbytes _diskAccess, sizeDISKACCESS defbytes _tempfilename, sizeTempFILENAME call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; parse file name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME + FILEHAS_NOFILENAME) getdarg es, si, _pathname ; arg passed internally as es:dx lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _RemoveSubDir_12 ; if path valid --> call _chgErrorToPathNotFound ; if name referenced path jmp _RemoveSubDir_40 ; if path invalid --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; trying to remove current directory ? ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _RemoveSubDir_12: mov cx, dx ; save returned dir cluster call getCurrDirCluster ; get cluster of curr directory cmp cx, dx ; same directory as current ? jnz _RemoveSubDir_16 ; dir is ok --> SetError pexterrCurrentDirectory, _RemoveSubDir_40 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; see if directory is empty (contains other than . and .. ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _RemoveSubDir_16: setES ds mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] mov dx, word ptr [ _dirAccess. fileAcCluster ][ bp ] lea bx, offset _diskAccess [ bp ] ; pointer to access block call initdiskAccess ; [ax] is drive, [dx] is cluster ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; scan directory sectors ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov word ptr [ _diskAccess. diskAcOptions ][ bp ], (ccb_isDIR) mov word ptr [ _diskAccess. diskAcPosition. _low ][ bp ], sizeDIRENTRY _RemoveSubDir_22: add word ptr [ _diskAccess. diskAcPosition. _low ][ bp ], sizeDIRENTRY adc word ptr [ _diskAccess. diskAcPosition. _high ][ bp ], 0000 lea bx, offset _diskAccess [ bp ] ; pointer to access block call _FATReadRandom ; read into buffer jz _RemoveSubDir_32 ; if no more data, ok to delete --> cmp byte ptr es:[ bx ], DIRENTRY_NEVERUSED jz _RemoveSubDir_32 ; if no more data, ok to delete --> cmp byte ptr es:[ bx ], DIRENTRY_DELETED ; entry deleted ? jz _RemoveSubDir_22 ; yes, keep searching --> SetError pexterrIllegalName, _RemoveSubDir_40 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to remove this entry. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _RemoveSubDir_32: mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] mov dx, word ptr [ _dirAccess. fileAcCluster ][ bp ] call ReleaseClusterChain les di, dword ptr [ _dirAccess. fileAcBufferPtr ][ bp ] mov bx, word ptr [ _dirAccess. fileAcDirOffset ][ bp ] mov byte ptr es:[ di + bx ], DIRENTRY_DELETED call CCBChanged mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] call updateDriveBuffers clc ; return no error ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; normal exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _RemoveSubDir_40: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3Bh Change Subdirectory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to subdirectory ; ;...............................................................; _ChangeSubdirectory: Entry ddef _pathname, es, dx ; arg passed internally as es:dx defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; parse file name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME + FILEHAS_NOFILENAME) getdarg es, si, _pathname ; arg passed internally as es:dx lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _ChgSubDir_12 ; if path valid --> call _chgErrorToPathNotFound ; if name referenced path jmp _ChgSubDir_40 ; if path invalid --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; copy path to CDS table. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ChgSubDir_12: push ds ; save current segment push dx ; cluster address getdarg es, si, _pathname ; arg passed internally as es:dx call getDrive les di, dword ptr [ _RxDOS_pCDS ] ; actual address in CDS mov cl, sizeCDS mul cl ; ax contains current drive add di, ax ; from push di setDS ss ; copy from stack lea si, offset _dirAccess. fileAcExpandedName [ bp ] lea di, offset _cdsActualDirectory [ di ] _ChgSubDir_22: lodsb ; copy buffer stosb or al, al jnz _ChgSubDir_22 pop di ; restore CDS pointer pop word ptr es:[ _cdsStartClusterDir ][ di ] pop ds ; restore ds clc ; no error ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; normal exit ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ChgSubDir_40: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3Ch Create File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx attributes ; ; ds:dx pointer to filename( path included ) ; ;...............................................................; _CreateFile: call CtrlC_Check ; look-ahead CtrlC Check call VerifyAvailableHandle ; see if handle available jc _CreateFile_42 ; exit if none --> RetCallersStackFrame es, si mov cx, word ptr es:[ _CX ][ si ] ; attributes mov dx, word ptr es:[ _DX ][ si ] mov es, word ptr es:[ _DataSegment ][ si ] call _SFTCreateFile jc _CreateFile_42 ; exit if error --> call MapSFTtoAppHandle ; if no space, create error _CreateFile_42: RetCallersStackFrame ds, si mov word ptr [ _AX ][ si ], ax ; return handle or error code ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3dh Open File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al open mode ; ; ds:dx pointer to filename( path included ) ; ;...............................................................; _OpenFile: Entry def _mode, ax call CtrlC_Check ; look-ahead CtrlC Check call VerifyAvailableHandle ; see if handle available jc _OpenFile_42 ; exit if none --> RetCallersStackFrame es, si mov dx, word ptr es:[ _DX ][ si ] mov es, word ptr es:[ _DataSegment ][ si ] mov ax, word ptr [ _mode ][ bp ] call _SFTOpenFile ; build an SFT jc _OpenFile_42 ; exit if error --> call MapSFTtoAppHandle ; record SFT handle into JHT _OpenFile_42: RetCallersStackFrame ds, si mov word ptr [ _AX ][ si ], ax ; return handle or error code Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3Eh Close File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx handle to open file ; ;...............................................................; _CloseFile: Entry def _handle, bx ddef _sftPointer defbytes _diskAccess, sizeDISKACCESS mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _CloseFile_error ; if could not find --> call _SFTCloseFile ; close SFT Entry jc _CloseFile_error ; if error --> call getHandleTable ; get handle table add bx, word ptr [ _handle ][ bp ] mov byte ptr es:[ bx ], -1 ; cancel handle reference in PSP's handle table or bx, bx ; no carry _CloseFile_error: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 3fh Read File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx handle ; ; cx max bytes to read ; ; ds:dx buffer address ; ;...............................................................; _ReadFile: Entry def _handle, bx def _readCount, cx ddef _sftPointer ddef _bufPtr, es, dx ; save buffer pointer call CtrlC_Check ; look-ahead CtrlC Check getarg ax, _handle ; get file handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) stordarg _sftPointer, es, di ; save sft address jc _ReadFile_Return ; if could not find --> push word ptr [ _bufPtr. _segment ][ bp ] push word ptr [ _bufPtr. _pointer ][ bp ] getarg cx, _readCount ; bytes to read getarg ax, _handle ; call _SFTReadFile ; read using sft (at es:di ) _ReadFile_Return: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 40h Write File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx handle ; ; cx bytes to write ; ; ds:dx buffer address ; ;...............................................................; _WriteFile: Entry def _handle, bx def _writeCount, cx ddef _sftPointer ddef _bufPtr, es, dx ; save buffer pointer call CtrlC_Check ; look-ahead CtrlC Check mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) stordarg _sftPointer, es, di ; save sft buffer pointer jc _WriteFile_error ; if could not find --> push word ptr [ _bufPtr. _segment ][ bp ] push word ptr [ _bufPtr. _pointer ][ bp ] getarg cx, _writeCount ; bytes to write call _SFTWriteFile ; write using sft (at es:di ) _WriteFile_error: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 41h Delete File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx Asciz name of file to delete (no wild chars) ; ;...............................................................; _DeleteFile: Entry ddef _filename, es, dx ; arg passed internally as es:dx ddef _dirEntry ; directory entry defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; parse file name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDIRECTORY) mov si, dx ; name from caller lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile jc _DeleteFile_18 ; if file/path valid --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; mark found entry in directory as deleted ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - les di, dword ptr [ _dirAccess. fileAcBufferPtr ][ bp ] mov bx, word ptr [ _dirAccess. fileAcDirOffset ][ bp ] mov byte ptr es:[ di + bx ], DIRENTRY_DELETED call CCBChanged mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] mov dx, word ptr [ _dirAccess. fileAcCluster ][ bp ] call ReleaseClusterChain mov ax, word ptr [ _dirAccess. fileAcDrive ][ bp ] call updateDriveBuffers or ax, ax ; return no error _DeleteFile_18: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 42h Lseek (Move) File Pointer ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al move method ; ; bx handle ; ; cx:dx distance to move pointer ; ;...............................................................; _MoveFilePointer: Entry def _method, ax def _handle, bx ddef _moveDistance, cx, dx ddef _newPosition call CtrlC_Check ; look-ahead CtrlC Check mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _moveFilePointer_36 ; if could not find --> getdarg cx, dx, _moveDistance mov ax, word ptr [ _method ][ bp ] Goto SEEK_BEG, _moveFilePointer_beg Goto SEEK_CUR, _moveFilePointer_cur Goto SEEK_END, _moveFilePointer_end SetError -1, _moveFilePointer_36 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; seek from end ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _moveFilePointer_end: add dx, word ptr es:[ sftFileSize. _low ][ di ] adc cx, word ptr es:[ sftFileSize. _high ][ di ] jmp short _moveFilePointer_beg ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; seek from current position ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _moveFilePointer_cur: add dx, word ptr es:[ sftFilePosition. _low ][ di ] adc cx, word ptr es:[ sftFilePosition. _high ][ di ] ; jmp short _moveFilePointer_beg ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; seek from beginning ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _moveFilePointer_beg: mov word ptr es:[ sftFilePosition. _low ][ di ], dx mov word ptr es:[ sftFilePosition. _high ][ di ], cx clc ; no error ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _moveFilePointer_36: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], dx mov word ptr [ _DX ][ bx ], cx Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 43h Get/Set File Attributes ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx file name ; ; al get/set flag ; ; cx attributes ; ;...............................................................; _ChangeFileMode: Entry def _mode, ax ; get/set flag. def _attributes, cx ; attributes, if change. ddef _filename, es, dx ; arg passed internally as es:dx ddef _dirEntry ; directory entry defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; parse file name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME) mov si, dx ; name from caller lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; locate file jc _ChangeFileMode_18 ; if file/path valid --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if found, either get or set the attribute ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - les di, dword ptr [ _dirAccess. fileAcBufferPtr ][ bp ] mov bx, word ptr [ _dirAccess. fileAcDirOffset ][ bp ] mov al, byte ptr [ _mode ][ bp ] Goto 00, _ChangeFileMode_GetAttrib ; get Goto 01, _ChangeFileMode_SetAttrib ; set SetError pexterrInvalidFunction, _ChangeFileMode_18 ; else --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if get file attributes ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ChangeFileMode_GetAttrib: RetCallersStackFrame ds, si mov cx, ATTR_DIRECTORY mov ax, es or ax, ax ; if no dir entry, jz _ChangeFileMode_GetAttrib_08 ; then it must be root dir -> mov cl, byte ptr es:[ deAttributes ][ di + bx ] _ChangeFileMode_GetAttrib_08: mov word ptr [ _CX ][ si ], cx Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if set file attributes ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ChangeFileMode_SetAttrib: mov ax, es or ax, ax ; root dir ? jnz _ChangeFileMode_SetAttrib_08 ; anything but root --> SetError pexterrPathNotFound, _ChangeFileMode_18 _ChangeFileMode_SetAttrib_08: mov cx, word ptr [ _attributes ][ bp ] test cx, not ATTR_SETTABLE jz _ChangeFileMode_12 SetError pexterrAccessDenied, _ChangeFileMode_18 _ChangeFileMode_12: mov al, byte ptr es:[ deAttributes ][ di + bx ] and al, ATTR_SETTABLE cmp al, cl jz _ChangeFileMode_16 ; if no change --> and byte ptr es:[ deAttributes ][ di + bx ], not ATTR_SETTABLE or byte ptr es:[ deAttributes ][ di + bx ], cl call CCBChanged ; update changed buffer _ChangeFileMode_16: clc _ChangeFileMode_18: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 44h IoControl ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; al subfunction ; ; bx file handle ; ; ; ; Output: ; ; dx depends on function ; ; ; ;...............................................................; _IoControl: Entry def _handle, bx def _count, cx ddef _bufPtr, es, dx call CtrlC_Check ; look-ahead CtrlC Check Goto 00h, _IoControl_GetDeviceData Goto 01h, _IoControl_SetDeviceData Goto 02h, _IoControl_CharDev_ReadControlData Goto 03h, _IoControl_CharDev_WriteControlData Goto 04h, _IoControl_BlockDev_ReadControlData Goto 05h, _IoControl_BlockDev_WriteControlData Goto 06h, _IoControl_CheckDevInputStatus Goto 07h, _IoControl_CheckDevOutputStatus Goto 08h, _IoControl_CheckDeviceRemovableMedia Goto 09h, _IoControl_IsDriveRemote Goto 0Ah, _IoControl_IsFileOrDeviceRemote Goto 0Bh, _IoControl_SetSharingRetryCount _IoControl_BlockDev_ReadControlData: _IoControl_BlockDev_WriteControlData: _IoControl_CheckDevInputStatus: _IoControl_CheckDevOutputStatus: _IoControl_CheckDeviceRemovableMedia: _IoControl_IsFileOrDeviceRemote: _IoControl_SetSharingRetryCount: mov ax, offset pexterrInvalidFunction stc Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; 4400 - Get Device Data ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _IoControl_GetDeviceData: mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _IoControl_GetDevData_12 ; if error --> mov dx, word ptr es:[ sftDevInfo ][ di ] RetCallersStackFrame ds, bx mov word ptr [ _DX ][ bx ], dx clc _IoControl_GetDevData_12: Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; 4401 - Set Device Data ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _IoControl_SetDeviceData: mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _IoControl_SetDevData_12 ; if error --> RetCallersStackFrame ds, bx mov dx, word ptr [ _DX ][ bx ] ; get device data bits mov word ptr es:[ sftDevInfo ][ di ], dx ; set data bits clc _IoControl_SetDevData_12: Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; 4402 - Read Control Data ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _IoControl_CharDev_ReadControlData: mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _IoControl_ReadCharData_22 ; if error --> test word ptr es:[ sftDevInfo ][ di ], sftIsDevice jnz _IoControl_ReadCharData_14 ; if device --> SetError pexterrAccessDenied, _IoControl_ReadCharData_22 _IoControl_ReadCharData_14: push word ptr es:[ sftDCB. _segment ][ di ] ; device driver address push word ptr es:[ sftDCB. _pointer ][ di ] getarg cx, _count ; count getdarg es, di, _bufPtr ; buffer pointer call devCharRead ; read data mov ax, cx ; characters actually read clc ; remove carry _IoControl_ReadCharData_22: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; 4403 - Write Control Data ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _IoControl_CharDev_WriteControlData: mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _IoControl_WriteCharData_12 ; if error --> push word ptr [ _bufPtr. _segment ][ bp ] push word ptr [ _bufPtr. _pointer ][ bp ] getarg cx, _count ; bytes to write call _SFTWriteFile ; Write using sft (at es:di ) _IoControl_WriteCharData_12: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; 4409 - Is Drive Remote ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _IoControl_IsDriveRemote: RetCallersStackFrame ds, bx mov word ptr [ _DX ][ bx ], 0000 ; we don't support anything clc Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 45h Duplicate File Handle ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; bx existing (old) handle ; ; ; ; Output: ; ; ax new handle ; ;...............................................................; _DuplicateFileHandle: mov es, word ptr [ _RxDOS_CurrentPSP ] mov cx, word ptr es:[ pspFileHandleCount ] mov dx, cx ; save original count cmp bx, word ptr es:[ pspFileHandleCount ] ; illegal reference ? jc _duplFileHandle_12 ; if valid -> _duplFileHandle_InvHandleError: seterror pexterrInvalidHandle, _duplFileHandle_Return ; if illegal --> _duplFileHandle_12: les di, dword ptr es:[ pspFileHandlePtr ] mov bl, byte ptr es:[ di + bx ] ; get SFT handle from current cmp bl, -1 ; invalid entry ? jz _duplFileHandle_InvHandleError ; if error --> ; is there an available entry ? mov al, -1 repnz scasb ; scan for empty slot jnz _duplFileHandle_InvHandleError ; if error --> sub dx, cx ; get count dec dx push dx mov byte ptr es:[ di - 1 ], bl ; duplicate handle xor ax, ax mov al, bl ; old handle call FindSFTbyHandle ; get corresponding SFT (es: di ) inc word ptr es:[ sftRefCount ][ di ] ; bump in use count pop ax ; new handle or ax, ax ; no carry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if error, exit with error code. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _duplFileHandle_Return: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 46h Force File Handle Duplicate ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; bx existing open handle ; ; cx duplicate handle ; ; ; ; Output: ; ; ax new handle ; ;...............................................................; _ForceFileHandle: ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Close duplicate handle if it is open ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - push bx ; save regs push cx mov ax, cx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _ForceFileHandle_10 ; if could not find --> call _SFTCloseFile ; close SFT Entry ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Duplicate Handle ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ForceFileHandle_10: pop cx ; restore regs pop bx mov es, word ptr [ _RxDOS_CurrentPSP ] les di, dword ptr es:[ pspFileHandlePtr ] cmp bx, word ptr es:[ pspFileHandleCount ] jnc _ForceFileHandle_InvHandleError ; if error value --> cmp cx, word ptr es:[ pspFileHandleCount ] jnc _ForceFileHandle_InvHandleError ; if error value --> xor ah, ah mov al, byte ptr es:[ di + bx ] ; SFT handle for duplicate xchg cx, bx mov byte ptr es:[ di + bx ], al ; duplicate handle call FindSFTbyHandle ; get corresponding SFT (es: di ) inc word ptr es:[ sftRefCount ][ di ] ; bump in -use count or ax, ax ; no carry ret _ForceFileHandle_InvHandleError: mov ax, offset pexterrInvalidHandle ; invalid handle stc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 47h Get Current Directory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:si pointer to max 64 byte user memory area ; ; dl drive number ; ;...............................................................; _GetCurrentDirectory: push dx call GetActualDrive ; actual drive (in ax) jnc getCurrDir_14 ; if no error --> RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax ; else save error code ret ; return getCurrDir_14: mov cl, sizeCDS mul cl ; ax contains offset to current drive lds si, dword ptr [ _RxDOS_pCDS ] ; actual address in CDS add si, ax ; from mov ax, _cdsActualDirectory ; proper offset add al, byte ptr [ _cdsNonSubstOffset ][ si ] add si, ax push ds RetCallersStackFrame ds, bx mov es, word ptr [ _DataSegment ][ bx ] mov di, word ptr [ _SI ][ bx ] pop ds getCurrDir_22: lodsb ; copy buffer stosb or al, al jnz getCurrDir_22 clc ret ; ds:si will be returned. ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 48h Allocate Memory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx # paragraphs of memory requested ; ; ; ; Returns: ; ; ax segment address of allocated memory block ; ; bx size of largest block of memory available in ; ; paragraphs, if allocation fails. ; ;...............................................................; _AllocateMemory: Entry def _allocation, bx call _allocateUpperMB ; allocate upper mem blocks jnc _AllocateMemory_12 ; if allocation made --> getarg bx, _allocation call _allocateConvMB ; allocate lower mem blocks _AllocateMemory_12: RetCallersStackFrame ds, si mov word ptr [ _AX ][ si ], ax ; error or segment allocation jnc _AllocateMemory_16 ; if not error --> mov word ptr [ _BX ][ si ], dx ; largest block _AllocateMemory_16: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 49h Free Allocated Memory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; es paragraph to free ; ;...............................................................; _FreeAllocatedMemory: RetCallersStackFrame es, bx mov bx, word ptr es:[ _ExtraSegment ][ bx ] dec bx ; preceding seg contains block mov es, bx ; is this a valid memory block ? cmp byte ptr es:[ _memSignature ], _RxDOS_MEMSIGNATURE jz _freeallocateMemory_12 cmp byte ptr es:[ _memSignature ], _RxDOS_ENDSIGNATURE jz _freeallocateMemory_12 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; invalid block. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RetCallersStackFrame es, bx mov word ptr es:[ _AX ][ bx ], offset pexterrInvalidBlock stc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; block is valid. free it. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _freeallocateMemory_12: xor ax, ax mov word ptr es:[ _memParent ], ax ; free memory block ; call _collectMemoryBlocks ; save space ; or ax, ax ; no carry ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4ah Modify Allocate Memory ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; es paragraph to free ; ; bx new paragraph size ; ;...............................................................; _ModifyAllocatedMemory: RetCallersStackFrame es, si mov es, word ptr es:[ _ExtraSegment ][ si ] call _modifyMemBlock ; fix size ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4Bxxh Load and Execute Program ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx program name ; ; es:bx program arguments ; ;...............................................................; _ExecuteProgram: call loadProgram ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4Ch Terminate Process ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al return value ; ;...............................................................; _TerminateProcess_00: xor ax, ax ; int 21/ ah = 0 _TerminateProcess: Entry def _parentPSP, 0000 ddef _returnVector setDS ss setES ss mov ah, TERMINATE_NORMAL mov word ptr [ _RxDOS_ChildReturnCode ], ax ; save return status code inc word ptr [ _RxDOS_AbortInProgress ] ; skip critical error if already in here ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; see if there is a parent process ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xor ax, ax mov es, ax mov bx, offset ( intTERMINATEAPP * 4 ) ; Int22 terminate app mov ax, word ptr es:[ _pointer ][ bx ] mov dx, word ptr es:[ _segment ][ bx ] stordarg _returnVector, dx, ax ; default terminate address mov es, word ptr ss:[ _RxDOS_CurrentPSP ] mov bx, word ptr es:[ pspParentId ] ; get parent PSP storarg _parentPSP, bx ; save for later or bx, bx ; no parent ? jz _TerminateProcess_20 ; can't terminate --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; restore interrupts/ return to parent PSP ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - push ds xor ax, ax mov ds, ax mov bx, offset ( intTERMINATEAPP * 4 ) ; Int22 terminate app mov ax, word ptr es:[ pspTerminateVect. _pointer ] mov dx, word ptr es:[ pspTerminateVect. _segment ] mov word ptr [ _pointer ][ bx ], ax mov word ptr [ _segment ][ bx ], dx stordarg _returnVector, dx, ax ; actual terminate address mov bx, offset ( intCONTROLC * 4 ) ; Int23 control-C vector mov ax, word ptr es:[ pspControlCVect. _pointer ] mov dx, word ptr es:[ pspControlCVect. _segment ] mov word ptr [ _pointer ][ bx ], ax mov word ptr [ _segment ][ bx ], dx mov bx, offset ( intCRITICALERROR * 4 ) ; Int24 criterror vector mov ax, word ptr es:[ pspCritErrorVect. _pointer ] mov dx, word ptr es:[ pspCritErrorVect. _segment ] mov word ptr [ _pointer ][ bx ], ax mov word ptr [ _segment ][ bx ], dx pop ds ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; free all allocated memory ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call _SFTCloseAllFiles ; close/ commit all files mov bx, word ptr ss:[ _RxDOS_CurrentPSP ] call _releaseOwnerMemoryBlocks ; release memory call _collectMemoryBlocks ; collect free blocks ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return to parent process ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - getarg es, _parentPSP ; get PSP mov word ptr ss:[ _RxDOS_CurrentPSP ], es ; restore mov ax, word ptr es:[ pspUserStack. _pointer ] ; parent user's stack mov dx, word ptr es:[ pspUserStack. _segment ] mov bx, word ptr ss:[ _RxDOS_CurrentInstance ] ; base address of current stack mov word ptr ss:[ _segment ][ bx ], dx mov word ptr ss:[ _pointer ][ bx ], ax ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _TerminateProcess_20: RetCallersStackFrame es, bx getdarg dx, ax, _returnVector mov word ptr es:[ _CS ][ bx ], dx mov word ptr es:[ _IP ][ bx ], ax dec word ptr [ _RxDOS_AbortInProgress ] ; restore critical error Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4Dh Get Return Code ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ;...............................................................; _GetReturnCode: mov ax, word ptr [ _RxDOS_ChildReturnCode ] mov word ptr [ _RxDOS_ChildReturnCode ], 0000 RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4Eh Find First Matching Name ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx file name ; ; cx attributes ; ;...............................................................; _FindFirstFile: Entry def _findType, 0000 def _attributes, cx ddef _filename, es, dx ; arg passed internally as es:dx defbytes _dirAccess, sizeDIRACCESS ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; make sure path is ok, try to match file ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILEHAS_WILDCHARS) mov si, dx ; name from caller (es: si ) lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; don't worry about finding a file storarg _findType, ax ; find type/ drive ; mov ax, offset pexterrNoMoreFiles jc _FindFirstFile_50 ; error code already set --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; setup find search template ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xor ax, ax mov cx, sizeFINDENTRY les di, dword ptr [ _RxDOS_pDTA ] rep stosb ; clear area ( 0 handle ) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; start at begining of directory, locate by attribute and name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov si, word ptr [ _dirAccess. fileAcNameOffset ][ bp ] mov di, word ptr [ _RxDOS_pDTA. _pointer ] lea di, offset findSrchName [ di ] call convFilenametoFCBString ; convert to a match template les di, dword ptr [ _RxDOS_pDTA ] lea si, offset findSrchDrive [ di ] lea di, offset findFileName [ di ] saveRegisters es, si, es, di ; arguments call convFCBNametoASCIZ ; build asciz name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; start at begining of directory, locate by attribute and name ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di, word ptr [ _RxDOS_pDTA. _pointer ] mov al, byte ptr [ _dirAccess. fileAcDrive ][ bp ] mov byte ptr es:[ findSrchDrive ][ di ], al mov cl, byte ptr [ _attributes ][ bp ] mov byte ptr es:[ findSrchAttributes ][ di ], cl mov ax, word ptr [ _dirAccess. fileAcDirCluster ][ bp ] mov word ptr es:[ findDirBegCluster ][ di ], ax mov word ptr es:[ findDirCurrCluster ][ di ], ax mov word ptr es:[ findDirEntry ][ di ], -1 mov ax, word ptr [ _dirAccess. fileAcDevicePtr._segment ][ bp ] or ax, word ptr [ _dirAccess. fileAcDevicePtr._pointer ][ bp ] jnz _FindFirstFile_50 ; if device, item found --> mov ax, offset pexterrNoMoreFiles test word ptr [ _findType ][ bp ], 8000h stc ; if error jnz _FindFirstFile_50 ; no need to search if device --> call LocateFileByAttribute ; lookup by attribute ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _FindFirstFile_50: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax ; return possible error code Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 4Fh Find Next Matching Name ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; no parameters. uses find record in DTA. ; ;...............................................................; _FindNextFile: les di, dword ptr [ _RxDOS_pDTA ] mov ax, offset pexterrNoMoreFiles cmp word ptr es:[ findDirEntry ][ di ], -1 ; stc ; assume not found in previous jz _FindNextFile_08 ; if not found in find first --> inc word ptr es:[ findDirEntry ][ di ] call LocateFileByAttribute ; lookup by attribute _FindNextFile_08: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax ; return possible error code ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 50h Set PSP Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx contains PSP address to use ; ;...............................................................; _SetPSPAddress: mov word ptr [ _RxDOS_CurrentPSP ], bx ; Seg Pointer to current PSP ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 51h Get PSP Address ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx PSP value returned ; ;...............................................................; _GetPSPAddress: mov bx, word ptr [ _RxDOS_CurrentPSP ] ; Seg Pointer of current PSP RetCallersStackFrame es, si mov word ptr es:[ _BX ][ si ], bx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 52h Get Dos Data Table Pointer ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; es:bx returns pointer to dos device parameter block ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _GetDosDataTablePtr: RetCallersStackFrame es, si mov word ptr es:[ _ExtraSegment ][ si ], ds mov word ptr es:[ _BX ][ si ], offset _RxDOS_pDPB clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 53h Translate a BIOS Parameter Block ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; ds:si pointer to BIOS Paramater Block ; ; es:bp pointer to DOS Drive Parameter Block ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _TranslateBIOSParameterBlock: RetCallersStackFrame es, bx push word ptr es:[ _DataSegment ][ bx ] push word ptr es:[ _SI ][ bx ] ; BIOS Parameter Block push word ptr es:[ _ExtraSegment ][ bx ] push word ptr es:[ _BP ][ bx ] ; DOS Drive Parameter Block call DefineDPB ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 54h Get DOS Verify Setting ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Returns: ; ; al 00, if verify is off ; ; 01, if verify is on ; ; ; ; (see related function 2E - Set/Reset Verify Switch ) ; ;...............................................................; _GetVerify: mov al, byte ptr [ _RxDOS_Verify ] RetCallersStackFrame ds, bx mov byte ptr [ _AX._AL ][ bx ], al or al, al ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 55h Duplicate PSP ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; dx segment where to setup new PSP ; ; si value to place in memory size field ; ; ; ; (see related function 26 - Create PSP ) ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _DuplicatePSP: push dx ; new seg push si ; new size mov es, dx ; new PSP segment address call copyCurrentPSP ; create a new PSP here pop si pop es ; new PSP address mov word ptr es:[ pspNextParagraph ], si ; set size mov word ptr [ _RxDOS_CurrentPSP ], es ; change running PSP ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 56h Rename File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ds:dx pointer to ASCIZ existing file/path ; ; es:di pointer to ASCIZ rename file/path ; ;...............................................................; _RenameFile: Entry ddef _wherePointer defbytes _existfileAccess, sizeDIRACCESS defbytes _renfileAccess, sizeDIRACCESS ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; does existing file exist ? ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDIRECTORY) mov si, dx ; name from caller lea di, offset _existfileAccess [ bp ] ; work dir access block call LocateFile ; check file path ifc _renameFile_40 ; if file does not exist --> push ds RetCallersStackFrame ds, bx mov es, word ptr [ _ExtraSegment ][ bx ] mov si, word ptr [ _DI ][ bx ] ; get user's parameter pop ds mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDEFINED + FILECANNOT_BEDIRECTORY) lea di, offset _renfileAccess [ bp ] ; renamed file dir access block call LocateFile ; check file path ifc _renameFile_40 ; if file does not exist --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; both files seem ok, so we'll move them ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov al, byte ptr [ _existfileAccess. fileAcDrive ][ bp ] cmp al, byte ptr [ _renfileAccess. fileAcDrive ][ bp ] mov ax, offset pexterrPathNotFound stc ifnz _renameFile_40 ; cannot move across drives --> mov ax, word ptr [ _existfileAccess. fileAcDirCluster ][ bp ] cmp ax, word ptr [ _renfileAccess. fileAcDirCluster ][ bp ] jnz _renameFile_22 ; if must move files across dirs --> setDS ss mov si, word ptr [ _renfileAccess. fileAcNameOffset ][ bp ] les di, dword ptr [ _existfileAccess. fileAcBufferPtr ][ bp ] add di, word ptr [ _existfileAccess. fileAcDirOffset ][ bp ] call convFilenametoFCBString ; convert name les si, dword ptr [ _existfileAccess. fileAcBufferPtr ][ bp ] call locateCCBPHeader call CCBChanged ; update buffer jmp short _renameFile_38 ; exit --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; move entry between directories ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _renameFile_22: and word ptr [ _renfileAccess. fileAcDrive ][ bp ], 7FFFh mov ax, word ptr [ _renfileAccess. fileAcDrive ][ bp ] mov dx, word ptr [ _renfileAccess. fileAcDirCluster ][ bp ] call LocateFreeDirSlot ; can we find a valid empty entry ? ifc _renameFile_40 ; if can't find free slot --> stordarg _wherePointer, es, si mov di, si ; where entry must be copied to lds si, dword ptr [ _existfileAccess. fileAcBufferPtr ][ bp ] add si, word ptr [ _existfileAccess. fileAcDirOffset ][ bp ] mov cx, ( sizeDIRENTRY / 2 ) rep movsw ; copy entry from source dir setDS ss getdarg es, di, _wherePointer mov si, word ptr [ _renfileAccess. fileAcNameOffset ][ bp ] call convFilenametoFCBString ; rename file getdarg es, si, _wherePointer call locateCCBPHeader call CCBChanged ; update buffer les di, dword ptr [ _existfileAccess. fileAcBufferPtr ][ bp ] mov bx, word ptr [ _existfileAccess. fileAcDirOffset ][ bp ] mov byte ptr es:[ di + bx ], DIRENTRY_DELETED call CCBChanged ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _renameFile_38: mov ax, word ptr [ _renfileAccess. fileAcDrive ][ bp ] call updateDriveBuffers mov ax, word ptr [ _existfileAccess. fileAcDrive ][ bp ] call updateDriveBuffers or ax, ax ; no carry _renameFile_40: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 5700h Get File Date Time ; ; 5701h Set File Date Time ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al = 00, get date/time ; ; 01, set date/time ; ; ; ; bx file handle ; ; cx time ; ; dx date ; ; ; ;...............................................................; _SetFileDateTime: call CtrlC_Check ; look-ahead CtrlC Check push ax ; save mode mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) pop ax ; restore mode jc _SetFileDateTime_20 ; if could not find --> Goto 00h, _GetFileDateTime ; get date/ time Goto 01h, _SetFileDateTime_06 ; set date/ time SetError pexterrInvalidHandle, _SetFileDateTime_20 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; set date/ time ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetFileDateTime_06: RetCallersStackFrame ds, bx mov cx, word ptr [ _CX ][ bx ] ; restore arguments mov dx, word ptr [ _DX ][ bx ] mov word ptr es:[ sftTime ][ di ], cx ; time mov word ptr es:[ sftDate ][ di ], dx ; date cmp word ptr es:[ sftDevInfo ][ di ], sftIsDevice jnz _SetFileDateTime_12 ; if device --> or word ptr es:[ sftDevInfo ][ di ], sftDateset + sftWritten _SetFileDateTime_12: clc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get date/ time ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetFileDateTime: RetCallersStackFrame ds, bx mov cx, word ptr es:[ sftTime ][ di ] ; time mov dx, word ptr es:[ sftDate ][ di ] ; date mov word ptr [ _CX ][ bx ], cx mov word ptr [ _DX ][ bx ], dx or ax, ax ; no carry _SetFileDateTime_20: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 5800h Get Allocation Strategy ; ; 5801h Set Allocation Strategy ; ; 5802h Get Upper Memory Link ; ; 5803h Set Upper Memory Link ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; al = mode, as shown above ; ; ; ; bx allocation strategy on set ; ; ax allocation strategy on get ; ; ; ;...............................................................; _GetAllocationStrategy: Goto 00, _GetAllocStrategy Goto 01, _SetAllocStrategy Goto 02, _GetUpperMemLink Goto 03, _SetUpperMemLink SetError pexterrInvalidFunction, _ChangeFileMode_18 ; else --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get allocation strategy ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetAllocStrategy: RetCallersStackFrame es, bx mov ax, word ptr [ _RxDOS_AllocStrategy ] mov word ptr es:[ _AX ][ bx ], ax ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; set allocation strategy ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetAllocStrategy: cmp bx, _MEM_FIRSTFIT_LOW ; must be greater than this jl _SetAllocStrategy_22 ; if error --> cmp bx, _MEM_LASTFIT_LOW ; low memory range values jle _SetAllocStrategy_08 ; if ok --> cmp bx, _MEM_FIRSTFIT_HIGHONLY ; must be greater than this jl _SetAllocStrategy_22 ; if error --> cmp bx, _MEM_LASTFIT_HIGHONLY ; high only memory range values jle _SetAllocStrategy_08 ; if ok --> cmp bx, _MEM_FIRSTFIT_HIGH ; must be greater than this jl _SetAllocStrategy_22 ; if error --> cmp bx, _MEM_LASTFIT_HIGH ; high memory range values jle _SetAllocStrategy_08 ; if ok --> _SetAllocStrategy_08: clc mov word ptr [ _RxDOS_AllocStrategy ], bx ; if valid. ret _SetAllocStrategy_22: mov ax, offset pexterrInvalidFunction ; if invalid. stc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get allocation strategy ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetUpperMemLink: RetCallersStackFrame es, bx mov ax, word ptr [ _RxDOS_UMBAllowed ] ; set allow/disallow flag mov word ptr es:[ _AX ][ bx ], ax ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get allocation strategy ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetUpperMemLink: cmp word ptr [ _RxDOS_UMBEnabled ], 0000 ; UMB enabled ? jz _SetUpperMemLink_08 ; no --> cmp bx, 0000h jz _SetUpperMemLink_04 cmp bx, 0001h jnz _SetUpperMemLink_08 _SetUpperMemLink_04: clc ; mov word ptr [ _RxDOS_UMBAllowed ], bx ; set allow/disallow flag ; ret ; always return error until UMB support can be provided _SetUpperMemLink_08: mov ax, offset pexterrInvalidFunction stc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 59h Get Extended Error ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; ax extended error code ; ; bh error class ; ; bl suggested action ; ; ch locus ; ;...............................................................; _GetExtendedError: RetCallersStackFrame es, si cmp word ptr [ _RxDOS_ExtErrorFlag ], TRUE jnz _GetExtendedError_08 ; lookup error --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; error set by app ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov word ptr [ _RxDOS_ExtErrorFlag ], FALSE mov ax, word ptr [ _RxDOS_ExtErrorInfo. errSI ] mov cx, word ptr [ _RxDOS_ExtErrorInfo. errDS ] mov dx, word ptr [ _RxDOS_ExtErrorInfo. errES ] mov word ptr es:[ _SI ][ si ], ax mov word ptr es:[ _DataSegment ][ si ], cx mov word ptr es:[ _ExtraSegment ][ si ], dx mov ax, word ptr [ _RxDOS_ExtErrorInfo. errAX ] mov bx, word ptr [ _RxDOS_ExtErrorInfo. errBX ] mov cx, word ptr [ _RxDOS_ExtErrorInfo. errCX ] mov dx, word ptr [ _RxDOS_ExtErrorInfo. errDX ] mov di, word ptr [ _RxDOS_ExtErrorInfo. errDI ] mov word ptr es:[ _AX ][ si ], ax mov word ptr es:[ _BX ][ si ], bx mov word ptr es:[ _CX ][ si ], cx mov word ptr es:[ _DX ][ si ], dx mov word ptr es:[ _DI ][ si ], di clc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; error set by RxDOS ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetExtendedError_08: xor ax, ax xor bx, bx xor cx, cx xor dx, dx ; if no error xchg bx, word ptr [ _RxDOS_pExtErrorcode ] ; no longer need to save error ptr or bx, bx ; no actual error saved ? jz _GetExtendedError_12 ; skip around --> mov ax, word ptr cs:[ ExtErrorCodeValue ][ bx ] ; else get error values mov ch, byte ptr cs:[ Locus ][ bx ] mov dl, byte ptr cs:[ SuggestedAction ][ bx ] mov dh, byte ptr cs:[ ErrorClass ][ bx ] _GetExtendedError_12: mov word ptr [ _RxDOS_ExtErrorcode ], ax mov byte ptr [ _RxDOS_LocusLasterror ], ch mov byte ptr [ _RxDOS_SuggestedAction ], dl mov byte ptr [ _RxDOS_ClassOfError ], dh mov word ptr es:[ _AX ][ si ], ax ; return extended error code mov byte ptr es:[ _CX. _CH ][ si ], ch mov word ptr es:[ _BX ][ si ], dx clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 5Ah Create Unique File Name ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx attributes ; ; ds:dx pointer to asciz containing path ; ;...............................................................; _CreateUniqueFile: Entry def _handle, -1 def _tempnamePointer def _bytecount def _attributes, cx ; attributes ddef _returnnamePointer, es, dx defbytes _dirAccess, sizeDIRACCESS defbytes _tempname, 128 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; file handle available ? ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call CtrlC_Check ; look-ahead CtrlC Check call VerifyAvailableHandle ; see if handle available ifc _CreateUniqueFile_40 ; exit if none --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; copy buffer ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - push word ptr [ _returnnamePointer. _segment ][ bp ] push word ptr [ _returnnamePointer. _pointer ][ bp ] mov cx, 128 ; maximum string length call condStringLength jz _CreateUniqueFile_08 SetError pexterrIllegalName, _CreateUniqueFile_40 _CreateUniqueFile_08: storarg _bytecount, cx ; save byte count push ax ; character just before null push word ptr [ _returnnamePointer. _segment ][ bp ] push word ptr [ _returnnamePointer. _pointer ][ bp ] push ss lea di, offset _tempname [ bp ] push di call CopyString pop ax cmp al, '\' ; ended with \ ? jz _CreateUniqueFile_12 ; yes --> cmp al, '/' ; ended with / ? jz _CreateUniqueFile_12 ; yes --> mov al, '\' stosb ; we'll make one. _CreateUniqueFile_12: storarg _tempnamePointer, di ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; create a unique filename ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call getExpandedDateTime ; expand time ch:cl dh:dl getarg di, _tempnamePointer mov al, ch ; hours call __ascii_stosb mov al, cl ; minutes call __ascii_stosb mov al, dh ; seconds call __ascii_stosb mov al, dl ; hundreths of second call __ascii_stosb xor al, al stosb ; null term ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; make sure file does not exist ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateUniqueFile_16: mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDEFINED + FILECANNOT_BEDIRECTORY) lea si, offset _tempname [ bp ] lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _CreateUniqueFile_36 ; if path invalid --> getarg di, _tempnamePointer mov cx, (sizefnName - 1) add di, cx _CreateUniqueFile_18: cmp byte ptr ss:[ di ], 'Z' ; already at end of alphabet ? jnz _CreateUniqueFile_32 ; no --> mov byte ptr ss:[ di ], 'A' ; cycle to prev column dec di ; adj address loop _CreateUniqueFile_18 ; and loop --> stc ; just in case jmp short _CreateUniqueFile_40 ; we'll have an error exit --> _CreateUniqueFile_32: inc byte ptr ss:[ di ] jmp _CreateUniqueFile_16 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; it doesn't, so we'll make one. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateUniqueFile_36: lea di, offset _dirAccess [ bp ] ; work dir access block mov cx, word ptr [ _attributes ][ bp ] ; get attributes and cx, not ( ATTR_VOLUME + ATTR_DIRECTORY ) call createSFTEntry ; create SFT entry jc _CreateUniqueFile_40 ; if error --> call MapSFTtoAppHandle ; if no space, create error push ax push ss push word ptr [ _tempnamePointer ][ bp ] getdarg es, di, _returnnamePointer add di, word ptr [ _bytecount ][ bp ] ; point to null terminator push es push di call CopyString ; copy name back to user pop ax clc ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateUniqueFile_40: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 5Bh Create New File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; cx attributes ; ; ds:dx pointer to filename( path included ) ; ;...............................................................; _CreateNewFile: Entry def _attributes, cx ; attributes defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check call VerifyAvailableHandle ; see if handle available jc _CreateNewFile_40 ; exit if none --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; make sure file does not exist ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RetCallersStackFrame es, bx mov si, word ptr es:[ _DX ][ bx ] mov es, word ptr es:[ _DataSegment ][ bx ] mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDEFINED + FILECANNOT_BEDIRECTORY) lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _CreateNewFile_16 ; if valid --> test word ptr [ _dirAccess. fileAcDrive ][ bp ], 8000h ; not found ? jnz _CreateNewFile_14 ; ok, error code is fine -> mov ax, offset pexterrFileExists ; upgrade error code _CreateNewFile_14: stc jmp short _CreateNewFile_40 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ok to create new. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateNewFile_16: RetCallersStackFrame es, bx mov cx, word ptr es:[ _CX ][ bx ] mov dx, word ptr es:[ _DX ][ bx ] mov es, word ptr es:[ _DataSegment ][ bx ] lea di, offset _dirAccess [ bp ] ; work dir access block mov cx, word ptr [ _attributes ][ bp ] ; get attributes call createSFTEntry ; create SFT entry jc _CreateNewFile_40 ; exit if none or error --> call MapSFTtoAppHandle ; if no space, create error ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CreateNewFile_40: RetCallersStackFrame ds, bx mov word ptr [ _AX ][ bx ], ax Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 5Dxxh Server, Share and Swap ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; ; ; Output: ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _ServerShareAndSwap: RetCallersStackFrame es, bx Goto 00h, _ShareUnimplemented Goto 06h, _GetSwappableDataArea Goto 0Ah, _SetExtendedError _ShareUnimplemented: mov ax, offset pexterrInvalidFunction stc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; get swappable data area ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetSwappableDataArea: mov word ptr es:[ _DataSegment ][ bx ], ss mov word ptr es:[ _SI ][ bx ], offset SDABeginArea mov word ptr es:[ _CX ][ bx ], SDAExtendedSwapArea - SDABeginArea mov word ptr es:[ _DX ][ bx ], SDAEndArea - SDABeginArea ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; set extended error ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetExtendedError: mov word ptr [ _RxDOS_ExtErrorFlag ], TRUE ; extended error is true mov ds, word ptr es:[ _DataSegment ][ bx ] mov si, word ptr es:[ _DataSegment ][ bx ] ; where extended info available mov di, offset _RxDOS_ExtErrorInfo mov cx, sizeERROR / 2 rep movsw ; copy words clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 60h Get Actual (Expanded) File Name ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; ds:si pointer to filename( path included ) ; ; es:di pointer to expanded filename ; ; ; ; Output: ; ; ax 0000 if name is local. ; ; ax 005c if name is networked. ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _GetActualFileName: RetCallersStackFrame es, bx push word ptr es:[ _DataSegment ][ bx ] ; non-canonical name push word ptr es:[ _SI ][ bx ] push word ptr es:[ _ExtraSegment ][ bx ] ; expanded filename push word ptr es:[ _DI ][ bx ] mov ax, FILECANNOT_BEDIRECTORY call ExpandFileName ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 63h Get DBCS String Pointer ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Output: ; ; ds:si points to DBCS string. ; ; cy if error ; ; ; ; ; ; This function is not supported in RxDOS. ; ; Always returns ptr to NULL double bytes. ; ; ; ; ; ; --- DOS Undocumented Feature -------------------------------- ; ;...............................................................; _GetDBCSString: RetCallersStackFrame ds, bx mov word ptr [ _SI ][ bx ], offset _RxDOS_DBCS_Table mov word ptr [ _DataSegment ][ bx ], cs clc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 65h Country Dependent Functions ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Input: ; ; al function ; ; 01h get extended country info ; ; ; ; 02h get uppercase table ; ; ; ; 04h get filename uppercase table ; ; ; ; 05h get filename character table ; ; ; ; 06h get collate sequence table ; ; ; ; 07h get double byte character set ; ; ; ; 20h character capitalization ; ; dl contains character ; ; dh 2nd byte in double byte languages ; ; ; ; 21h length defined string capitalization ; ; ds:dx string pointer ; ; cx length ; ; ; ; 22h ASCIZ capitalization ; ; ds:dx string pointer ; ; ; ; 23h does character represent Yes/No response ; ; dl contains character ; ; dh 2nd byte in double byte languages ; ; ; ; returns: ax = 00 if yes ; ; 01 if no ; ; 02 if other ; ; ; ; A0h filename character capitalization ; ; dl contains character ; ; ; ; A1h filename length defined string capitalization ; ; ds:dx string pointer ; ; cx length ; ; ; ; A2h filename ASCIZ capitalization ; ; ds:dx string pointer ; ; ; ; ; ; Output: ; ; cy if error ; ; ; ;...............................................................; _ExtCountryDependentFunctions: mov ah, al ; copy function to ah also ;;;; Goto 01h, _GetExtendedCountryInfo Goto 02h, _GetUpperCaseTable Goto 04h, _GetFilenameUpperCaseTable Goto 05h, _GetFilenameCharacterTable Goto 06h, _GetCollateSequenceTable Goto 07h, _GetDoubleByteCharacterSet Goto _CapCharacter, _Capitalize_08 Goto _CapLengthDefString, _Capitalize_12 Goto _CapString, _Capitalize_22 Goto _CountryDepYesNo, _Capitalize_30 Goto _CapFnCharacter, _Capitalize_08 Goto _CapFnLengthDefString, _Capitalize_12 Goto _CapFnString, _Capitalize_22 _GetUpperCaseTable: _GetFilenameUpperCaseTable: _GetFilenameCharacterTable: _GetCollateSequenceTable: _GetDoubleByteCharacterSet: mov ax, offset pexterrInvalidFunction stc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get Extended Country Info ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetExtendedCountryInfo: cmp bx, -1 ; if get info jz _GetExtendedCountryInfo_08 ; go do get --> mov word ptr [ _RxDOS_UserCodePage ], bx ; should check values mov word ptr [ _RxDOS_UserCountryCode ], dx ; should check values or bx, bx ret _GetExtendedCountryInfo_08: mov ax, word ptr [ _RxDOS_UserCodePage ] ; should check values mov dx, word ptr [ _RxDOS_UserCountryCode ] ; should check values RetCallersStackFrame es, bx mov word ptr es:[ _BX ][ bx ], ax ; code page mov word ptr es:[ _DX ][ bx ], dx ; country code or bx, bx ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; capitalize character ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Capitalize_08: mov al, dl call upperCase RetCallersStackFrame ds, bx mov byte ptr [ _DX._DL ][ bx ], al ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; capitalize length defined string (was ds:dx, now es:di) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Capitalize_12: or cx, cx jz _Capitalize_18 _Capitalize_14: mov al, byte ptr es:[ di ] call upperCase mov byte ptr es:[ di ], al inc di loop _Capitalize_14 _Capitalize_18: clc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; capitalize ASCIZ string (was ds:dx, now es:di) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Capitalize_22: mov al, byte ptr es:[ di ] or al, al jz _Capitalize_28 call upperCase mov byte ptr es:[ di ], al inc di jmp _Capitalize_22 _Capitalize_28: clc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return country dependent yes/no answer ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _Capitalize_30: mov al, dl call upperCase ;** this is of course wrong for now !! mov dl, 00h ; if yes cmp al, 'Y' jz _Capitalize_34 mov dl, 01h ; if no cmp al, 'N' jz _Capitalize_34 mov dl, 02h ; if neither _Capitalize_34: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 86h Global Code Page Settings ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; Get Global Code Page: ; ; al 01 ; ; bx user code page ; ; dx system code page ; ; ; ; Set Global Code Page: ; ; al 02 ; ; bx user code page ; ; dx system code page ; ; ; ;...............................................................; _GlobalCodePage: RetCallersStackFrame es, bx Goto 01, _GetCodePage Goto 02, _SetCodePage mov ax, offset pexterrInvalidFunction stc ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get Code Page Value ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _GetCodePage: mov ax, word ptr [ _RxDOS_UserCodePage ] mov dx, word ptr [ _RxDOS_SystemCodePage ] mov word ptr es:[ _BX ][ bx ], ax mov word ptr es:[ _DX ][ bx ], dx ret ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Set Code Page Value ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _SetCodePage: mov ax, word ptr es:[ _BX ][ bx ] mov dx, word ptr es:[ _DX ][ bx ] mov word ptr [ _RxDOS_UserCodePage ], ax mov word ptr [ _RxDOS_SystemCodePage ], dx ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 67h Set Handles Count ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx number of file handles to allocate to an application ; ;...............................................................; _SetHandlesCount: Entry def _handles, bx def _allocatedseg mov es, word ptr [ _RxDOS_CurrentPSP ] cmp bx, word ptr es:[ pspFileHandleCount ] ; more than current ? jnc _SetHandlesCount_08 ; yes, relocate --> call TestIfMoveHandleTable ; else, see if can relocate back to PSP jmp _SetHandlesCount_26 _SetHandlesCount_08: add bx, ( sizeParagraph - 1 ) shr bx, 1 shr bx, 1 shr bx, 1 shr bx, 1 ; compute segments required call _allocateUpperMB ; allocate upper mem blocks jnc _SetHandlesCount_12 ; if allocation made --> call _allocateConvMB ; allocate lower mem blocks jc _SetHandlesCount_30 ; if allocation not made --> _SetHandlesCount_12: mov es, ax ; new segment storarg _allocatedseg, ax ; save getarg cx, _handles ; allocated request add cx, ( sizeParagraph - 1 ) and cx, not ( sizeParagraph - 1 ) ; allocated size shr cx, 1 ; optimize for words xor di, di mov ax, -1 rep stosw ; clear words push ds push es mov es, word ptr [ _RxDOS_CurrentPSP ] ; get PSP mov cx, word ptr es:[ pspFileHandleCount ] ; source count lds si, dword ptr es:[ pspFileHandlePtr ] ; source pointer pop es xor di, di ; where to copy to rep movsb ; copy table pop ds ; restore current segment getarg ax, _allocatedseg ; allocated segment mov es, word ptr [ _RxDOS_CurrentPSP ] mov word ptr es:[ pspFileHandlePtr. _segment ], ax mov word ptr es:[ pspFileHandlePtr. _pointer ], 0000 getarg bx, _handles mov word ptr es:[ pspFileHandleCount ], bx _SetHandlesCount_26: clc _SetHandlesCount_30: Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 68h Commit File ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx handle to open file ; ;...............................................................; _CommitFile: call CtrlC_Check ; look-ahead CtrlC Check mov ax, bx ; handle call MapAppToSFTHandle ; map to internal handle info call FindSFTbyHandle ; get corresponding SFT (es: di ) jc _CommitFile_error ; if could not find --> call _SFTCommitFile ; commit SFT Entry or bx, bx ; no carry _CommitFile_error: ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; 6Ch Extended Open/Create ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; bx mode ; ; cx attributes ; ; dx action to take ; ; ds:si pointer to filename ; ;...............................................................; _ExtendedOpenCreate: Entry def _mode, bx def _attributes, cx def _action, dx def _actionTaken, 0000 def _found, FALSE ddef _filename, es, si defbytes _dirAccess, sizeDIRACCESS call CtrlC_Check ; look-ahead CtrlC Check call VerifyAvailableHandle ; see if handle available ifc _ExtendedOpenCreate_42 ; if error --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; determine if file exists ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RetCallersStackFrame es, bx mov si, word ptr es:[ _SI ][ bx ] mov es, word ptr es:[ _DataSegment ][ bx ] mov ax, (FILE_NODEVICENAME + FILECANNOT_BEDIRECTORY) lea di, offset _dirAccess [ bp ] ; work dir access block call LocateFile ; check file path jnc _ExtendedOpenCreate_FileFound ; if file found, see if replace --> storarg _found, FALSE test word ptr [ _action ][ bp ], EXTENDEDACTION_CREATE jnz _ExtendedOpenCreate_Create ; ok to create --> ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; open file ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ExtendedOpenCreate_Open: RetCallersStackFrame es, si mov dx, word ptr es:[ _SI ][ si ] mov es, word ptr es:[ _DataSegment ][ si ] mov ax, word ptr [ _mode ][ bp ] call _SFTOpenFile ; build an SFT jc _ExtendedOpenCreate_42 ; if error --> call MapSFTtoAppHandle ; record SFT handle into JHT mov word ptr [ _actionTaken ][ bp ], ACTION_OPENED jmp short _ExtendedOpenCreate_42 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; create file ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ExtendedOpenCreate_Create: RetCallersStackFrame es, si mov cx, word ptr es:[ _CX ][ si ] ; attributes mov dx, word ptr es:[ _SI ][ si ] ; filename in ds:si mov es, word ptr es:[ _DataSegment ][ si ] call _SFTCreateFile jc _ExtendedOpenCreate_42 ; if error --> call MapSFTtoAppHandle ; record SFT handle into JHT mov cx, ACTION_REPLACED_OPENED cmp word ptr [ _found ][ bp ], TRUE jz _ExtendedOpenCreate_32 ; if found, then was truncated -> mov cx, ACTION_CREATED_OPENED _ExtendedOpenCreate_32: clc ; no carry mov word ptr [ _actionTaken ][ bp ], cx jmp short _ExtendedOpenCreate_42 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if file found, determine if truncate ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ExtendedOpenCreate_FileFound: storarg _found, TRUE test word ptr [ _action ][ bp ], EXTENDEDACTION_TRUNCATE jnz _ExtendedOpenCreate_Create ; ok to create/ truncate --> test word ptr [ _action ][ bp ], EXTENDEDACTION_OPEN jnz _ExtendedOpenCreate_Open ; ok to open --> stc mov ax, offset pexterrAccessDenied ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ExtendedOpenCreate_42: RetCallersStackFrame es, bx mov word ptr es:[ _AX ][ bx ], AX getarg cx, _actionTaken mov word ptr es:[ _CX ][ bx ], CX Return ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Unused / Unimplemented Functions ; ;...............................................................; _UnusedReturnInst: RetCallersStackFrame es, bx mov word ptr es:[ _AX. _AL ][ bx ], 01h stc ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Unused / Unimplemented Functions ; ;...............................................................; _GetDiskSerialNumber: _LockFileAccess: _GetMachineName: _GetRedirectionList: _Unused: call _UnusedReturnInst ret ;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''; ; Debug Interrupt Trap ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; ; ; This code is called whenever one of the debug routines ; ; ; ; ; ; ; ;...............................................................; _DebugInterruptTrap: ret RxDOS ENDS END RxDOS_start