1 TITLE MISC
- Miscellanious routines for
MS-DOS
4 ; Miscellaneous system calls most of which are CAVEAT
15 ; $CREATE_PROCESS_DATA_BLOCK
20 ; get the appropriate segment definitions
24 CODE SEGMENT BYTE PUBLIC 'CODE'
25 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
42 i_need LASTBUFFER
,DWORD
44 i_need SYSINITVAR
,BYTE
45 i_need CurrentPDB
,WORD
62 BREAK <SleazeFunc
-- get a pointer to media
byte>
64 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
65 ; C A V E A T P R O G R A M M E R ;
67 procedure $SLEAZEFUNC
,NEAR
68 ASSUME
DS:NOTHING
,ES:NOTHING
73 ; Return Stuff sort of like old get fat call
75 ; DS:BX = Points to FAT ID byte (IBM only)
76 ; GOD help anyone who tries to do ANYTHING except
78 ; DX = Total Number of allocation units on disk
80 ; AL = Sectors per allocation unit
81 ; = -1 if bad drive specified
93 MOV DX,ES:[BP.dpb_max_cluster
]
95 MOV AL,ES:[BP.dpb_cluster_mask
]
97 MOV CX,ES:[BP.dpb_sector_size
]
100 invoke get_user_stack
109 ; C A V E A T P R O G R A M M E R ;
110 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
114 BREAK <$ABORT
-- Terminate a process
>
115 procedure $ABORT
,NEAR
116 ASSUME
DS:NOTHING
,ES:NOTHING
119 ; CS:00 must point to valid program header block
121 ; Restore terminate and Cntrl-C addresses, flush buffers
122 ; and transfer to the terminate address
124 ; TO THE TERMINATE ADDRESS
127 MOV [exit_type
],exit_abort
130 ; abort_inner must have AL set as the exit code!
135 invoke Get_user_stack
136 MOV DS,[SI.user_CS
] ; set up old interrupts
140 MOV DI,addr_int_terminate
147 transfer reset_environment
150 BREAK <$Dir_Search_First
-- Start a directory search
>
151 procedure $DIR_SEARCH_FIRST
,NEAR
152 ASSUME
DS:NOTHING
,ES:NOTHING
155 ; DS:DX Points to unopenned FCB
157 ; Directory is searched for first matching entry and the directory
158 ; entry is loaded at the disk transfer address
160 ; AL = -1 if no entries matched, otherwise 0
165 ; Search-for-next enters here to save place and report
167 MOV DL,0 ; Do not XOR!!!
169 OR AH,AH ; Is it I/O device?
170 JS KILLIT
; If so, sign bit will end search
174 MOV ES:[DI.FILDIRENT
],AX
175 MOV AX,WORD PTR [THISDPB
]
176 MOV ES:[DI.fcb_DRVBP
],AX
177 MOV AX,WORD PTR [THISDPB
+2]
178 MOV ES:[DI.fcb_DRVBP
+2],AX
180 MOV ES:[DI.fcb_DRVBP
+4],AX
181 ; Information in directory entry must be copied into the first
182 ; 33 bytes starting at the disk transfer address.
197 STOSB ; Set drive number
200 MOV DS,WORD PTR [CURBUF
+2]
206 CMP BYTE PTR ES:[DI-2],5
208 MOV BYTE PTR ES:[DI-2],0E5H
215 REP MOVSW ; Copy 32 bytes of directory entry
222 POP ES ; Make ES:DI point to the FCB
225 MOV WORD PTR ES:[DI.FILDIRENT
],AX
227 $DIR_SEARCH_FIRST ENDP
229 BREAK <$Dir_Search_Next
-- Find next matching directory
entry>
230 procedure $DIR_SEARCH_NEXT
,NEAR
231 ASSUME
DS:NOTHING
,ES:NOTHING
234 ; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
236 ; Directory is searched for the next matching entry and the directory
237 ; entry is loaded at the disk transfer address
239 ; AL = -1 if no entries matched, otherwise 0
244 JC NEAR PTR KILLSRCH1
245 MOV AX,[DI.FILDIRENT
]
246 LES BP,DWORD PTR [DI.fcb_DRVBP
]
248 JS NEAR PTR KILLSRCH1
249 MOV BX,[DI.fcb_DRVBP
+4]
253 MOV WORD PTR [THISDPB
],BP
254 MOV WORD PTR [THISDPB
+2],ES
265 $DIR_SEARCH_NEXT ENDP
267 BREAK <$Get_FCB_File_Length
-- Return size of
file in current records
>
268 procedure $GET_FCB_FILE_LENGTH
,NEAR
269 ASSUME
DS:NOTHING
,ES:NOTHING
272 ; DS:DX points to unopenned FCB
274 ; Set random record field to size of file
276 ; AL = -1 if no entries matched, otherwise 0
282 ADD DI,fcb_RR
; Write size in RR field
283 MOV CX,WORD PTR ES:[DI.fcb_RECSIZ
-fcb_RR
]
288 XOR DX,DX ; Intialize size to zero
290 INC SI ; Point to length field
291 MOV DS,WORD PTR [CURBUF
+2]
293 MOV AX,[SI+2] ; Get high word of size
295 PUSH AX ; Save high part of result
296 LODSW ; Get low word of size
298 OR DX,DX ; Check for zero remainder
301 INC AX ; Round up for partial record
302 JNZ DEVSIZ
; Propagate carry?
310 JAE RET14
; Only 3-byte field if fcb_RECSIZ >= 64
313 $GET_FCB_FILE_LENGTH ENDP
315 BREAK <$Get_Fcb_Position
-- Set random record field to current position
>
316 procedure $GET_FCB_POSITION
,NEAR
317 ASSUME
DS:NOTHING
,ES:NOTHING
320 ; DS:DX points to openned FCB
322 ; Sets random record field to be same as current record fields
327 MOV WORD PTR [DI+fcb_RR
],AX
329 CMP [DI.fcb_RECSIZ
],64
331 MOV [DI+fcb_RR
+2+1],DH ; Set 4th byte only if record size < 64
333 $GET_FCB_POSITION ENDP
335 BREAK <$Disk_Reset
-- Flush
out all dirty buffers
>
336 procedure $DISK_RESET
,NEAR
337 ASSUME
DS:NOTHING
,ES:NOTHING
342 ; Flush and invalidate all buffers
351 MOV WORD PTR [LASTBUFFER
+2],-1
352 MOV WORD PTR [LASTBUFFER
],-1
355 NBFFR: ; Free ALL buffers
356 MOV [DI.VISIT
],1 ; Mark as visited
357 CMP BYTE PTR [DI.BUFDRV
],-1
358 JZ SKPBF
; Save a call to PLACEBUF
359 MOV WORD PTR [DI.BUFDRV
],00FFH
367 procedure $RAW_CON_IO
,NEAR ; System call 6
368 ASSUME
DS:NOTHING
,ES:NOTHING
372 ; else DL is output character
374 ; Input or output raw character from console, no echo
381 LES DI,DWORD PTR [user_SP
] ; Get pointer to register save area
389 OR BYTE PTR ES:[DI.user_F
],40H
; Set user's zero flag
394 AND BYTE PTR ES:[DI.user_F
],0FFH-40H
; Reset user's zero flag
398 entry $RAW_CON_INPUT
; System call 7
403 ; Input raw character from console, no echo
417 ; Output the character in AL to stdout
427 TEST [SI.fcb_DEVID
],080H ; output to file?
428 JZ RAWNORM
; if so, do normally
431 LDS SI,DWORD PTR [SI.fcb_FIRCLUS
] ; output to special?
432 TEST BYTE PTR [SI+SDEVATT
],ISSPEC
435 JZ RAWNORM
; if not, do normally
436 INT int_fastcon
; quickly output the char
447 ; Output the character in AL to handle in BX
465 CLC ; Clear carry indicating successful
469 ASSUME
DS:NOTHING
,ES:NOTHING
470 ; This routine is called at DOS init
472 procedure OUTMES
,NEAR ; String output for internal messages
473 LODS CS:BYTE PTR [SI]
482 BREAK <$Parse_File_Descriptor
-- Parse an arbitrary string
into an FCB
>
483 procedure $PARSE_FILE_DESCRIPTOR
,NEAR
484 ASSUME
DS:NOTHING
,ES:NOTHING
487 ; DS:SI Points to a command line
488 ; ES:DI Points to an empty FCB
489 ; Bit 0 of AL = 1 At most one leading separator scanned off
490 ; = 0 Parse stops if separator encountered
491 ; Bit 1 of AL = 1 If drive field blank in command line - leave FCB
492 ; = 0 " " " " " " - put 0 in FCB
493 ; Bit 2 of AL = 1 If filename field blank - leave FCB
494 ; = 0 " " " - put blanks in FCB
495 ; Bit 3 of AL = 1 If extension field blank - leave FCB
496 ; = 0 " " " - put blanks in FCB
498 ; Parse command line into FCB
500 ; AL = 1 if '*' or '?' in filename or extension, 0 otherwise
501 ; DS:SI points to first character after filename
505 invoke get_user_stack
508 $PARSE_FILE_DESCRIPTOR ENDP
510 BREAK <$Create_Process_Data_Block
,SetMem
-- Set up process
data block
>
511 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
512 ; C A V E A T P R O G R A M M E R ;
514 procedure $Dup_PDB
,NEAR
515 ASSUME
DS:NOTHING
,ES:NOTHING
516 MOV BYTE PTR [CreatePDB
], 0FFH ; indicate a new process
520 procedure $CREATE_PROCESS_DATA_BLOCK
,NEAR
521 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
524 ; DX = Segment number of new base
526 ; Set up program base and copy term and ^C from int area
532 TEST BYTE PTR [CreatePDB
],0FFh
535 JMP SHORT Create_copy
538 invoke get_user_stack
542 XOR SI,SI ; copy all 80h bytes
547 TEST BYTE PTR [CreatePDB
],0FFh ; Shall we create a process?
548 JZ Create_PDB_cont
; nope, old style call
550 ; Here we set up for a new process...
556 XOR BX,BX ; dup all jfns
560 PUSH ES ; save new PDB
561 invoke get_jfn_pointer
; ES:DI is jfn
562 JC create_skip
; not a valid jfn
565 invoke get_sf_from_jfn
; get sf pointer
567 INC ES:[DI].sf_ref_count
; new fh
572 MOV AL,ES:[DI] ; get sfn
575 MOV AL,ES:[BX] ; copy into new place!
582 PUSH [CurrentPDB
] ; get current process
585 POP ES:[PDB_Parent_PID
] ; stash in child
590 ; end of new process create
593 MOV BYTE PTR [CreatePDB
],0h
; reset flag
594 MOV AX,DS:[2] ; set up size for fall through
597 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
600 ; AX = Size of memory in paragraphs
603 ; Completely prepares a program base at the
609 ; [0] has INT int_abort
610 ; [2] = First unavailable segment ([ENDMEM])
611 ; [5] to [9] form a long call to the entry point
612 ; [10] to [13] have exit address (from int_terminate)
613 ; [14] to [17] have ctrl-C exit address (from int_ctrl_c)
614 ; [18] to [21] have fatal error address (from int_fatal_abort)
615 ; DX,BP unchanged. All other registers destroyed.
620 MOV SI,addr_int_terminate
635 MOV WORD PTR DS:[PDB_CPM_Call
+1],AX
636 MOV WORD PTR DS:[PDB_CPM_Call
+3],BX
637 MOV DS:[PDB_Exit_Call
],(int_abort
SHL 8) + mi_INT
638 MOV BYTE PTR DS:[PDB_CPM_Call
],mi_Long_CALL
639 MOV WORD PTR DS:[PDB_Call_System
],(int_command
SHL 8) + mi_INT
640 MOV BYTE PTR DS:[PDB_Call_System
+2],mi_Long_RET
643 $CREATE_PROCESS_DATA_BLOCK ENDP