]> wirehaze git hosting - MS-DOS.git/blob - v2.0/source/MISC.ASM

wirehaze git hosting

README in Portuguese is now README.pt-PT
[MS-DOS.git] / v2.0 / source / MISC.ASM
1 TITLE MISC - Miscellanious routines for MS-DOS
2 NAME MISC
3 ;
4 ; Miscellaneous system calls most of which are CAVEAT
5 ;
6 ; $SLEAZEFUNC
7 ; $SLEAZEFUNCDL
8 ; $GET_INDOS_FLAG
9 ; $GET_IN_VARS
10 ; $GET_DEFAULT_DPB
11 ; $GET_DPB
12 ; $DISK_RESET
13 ; $SETDPB
14 ; $Dup_PDB
15 ; $CREATE_PROCESS_DATA_BLOCK
16 ; SETMEM
17 ;
18 .xlist
19 ;
20 ; get the appropriate segment definitions
21 ;
22 INCLUDE DOSSEG.ASM
23
24 CODE SEGMENT BYTE PUBLIC 'CODE'
25 ASSUME SS:DOSGROUP,CS:DOSGROUP
26
27 .xcref
28 INCLUDE DOSSYM.ASM
29 INCLUDE DEVSYM.ASM
30 .cref
31 .list
32
33
34 ifndef Kanji
35 Kanji equ 0
36 endif
37
38 ENTRYPOINTSEG EQU 0CH
39 MAXDIF EQU 0FFFH
40 SAVEXIT EQU 10
41
42 i_need LASTBUFFER,DWORD
43 i_need INDOS,BYTE
44 i_need SYSINITVAR,BYTE
45 i_need CurrentPDB,WORD
46 i_need CreatePDB,BYTE
47 i_need EXIT_TYPE,BYTE
48 i_need EXIT_CODE,WORD
49 i_need LASTENT,WORD
50 i_need THISDPB,DWORD
51 i_need ATTRIB,BYTE
52 i_need EXTFCB,BYTE
53 i_need DMAADD,DWORD
54 i_need DIRSTART,WORD
55 i_need CURBUF,DWORD
56 i_need USER_SP,WORD
57 i_need ENTLAST,WORD
58 i_need THISDRV,BYTE
59
60 ASSUME SS:DOSGROUP
61
62 BREAK <SleazeFunc -- get a pointer to media byte>
63
64 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
65 ; C A V E A T P R O G R A M M E R ;
66 ; ;
67 procedure $SLEAZEFUNC,NEAR
68 ASSUME DS:NOTHING,ES:NOTHING
69
70 ; Inputs:
71 ; None
72 ; Function:
73 ; Return Stuff sort of like old get fat call
74 ; Outputs:
75 ; DS:BX = Points to FAT ID byte (IBM only)
76 ; GOD help anyone who tries to do ANYTHING except
77 ; READ this ONE byte.
78 ; DX = Total Number of allocation units on disk
79 ; CX = Sector size
80 ; AL = Sectors per allocation unit
81 ; = -1 if bad drive specified
82
83 MOV DL,0
84 entry $SLEAZEFUNCDL
85 PUSH SS
86 POP DS
87 ASSUME DS:DOSGROUP
88 MOV AL,DL
89 invoke GETTHISDRV
90 MOV AL,-1
91 JC BADSLDRIVE
92 invoke FATREAD
93 MOV DX,ES:[BP.dpb_max_cluster]
94 DEC DX
95 MOV AL,ES:[BP.dpb_cluster_mask]
96 INC AL
97 MOV CX,ES:[BP.dpb_sector_size]
98 ADD BP,dpb_media
99 BADSLDRIVE:
100 invoke get_user_stack
101 ASSUME DS:NOTHING
102 MOV [SI.user_CX],CX
103 MOV [SI.user_DX],DX
104 MOV [SI.user_BX],BP
105 MOV [SI.user_DS],ES
106 return
107 $SLEAZEFUNC ENDP
108 ; ;
109 ; C A V E A T P R O G R A M M E R ;
110 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
111
112
113
114 BREAK <$ABORT -- Terminate a process>
115 procedure $ABORT,NEAR
116 ASSUME DS:NOTHING,ES:NOTHING
117
118 ; Inputs:
119 ; CS:00 must point to valid program header block
120 ; Function:
121 ; Restore terminate and Cntrl-C addresses, flush buffers
122 ; and transfer to the terminate address
123 ; Returns:
124 ; TO THE TERMINATE ADDRESS
125
126 XOR AL,AL
127 MOV [exit_type],exit_abort
128
129 ;
130 ; abort_inner must have AL set as the exit code!
131 ;
132 entry abort_inner
133 MOV AH,[exit_type]
134 MOV [exit_code],AX
135 invoke Get_user_stack
136 MOV DS,[SI.user_CS] ; set up old interrupts
137 XOR AX,AX
138 MOV ES,AX
139 MOV SI,SAVEXIT
140 MOV DI,addr_int_terminate
141 MOVSW
142 MOVSW
143 MOVSW
144 MOVSW
145 MOVSW
146 MOVSW
147 transfer reset_environment
148 $ABORT ENDP
149
150 BREAK <$Dir_Search_First -- Start a directory search>
151 procedure $DIR_SEARCH_FIRST,NEAR
152 ASSUME DS:NOTHING,ES:NOTHING
153
154 ; Inputs:
155 ; DS:DX Points to unopenned FCB
156 ; Function:
157 ; Directory is searched for first matching entry and the directory
158 ; entry is loaded at the disk transfer address
159 ; Returns:
160 ; AL = -1 if no entries matched, otherwise 0
161
162 invoke GETFILE
163 ASSUME DS:DOSGROUP
164 SAVPLCE:
165 ; Search-for-next enters here to save place and report
166 ; findings.
167 MOV DL,0 ; Do not XOR!!!
168 JC KILLSRCH
169 OR AH,AH ; Is it I/O device?
170 JS KILLIT ; If so, sign bit will end search
171 MOV AX,[LASTENT]
172 INC DL
173 KILLIT:
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
179 MOV AX,[DIRSTART]
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.
183 MOV SI,BX
184 LES DI,[DMAADD]
185 MOV AX,00FFH
186 CMP AL,[EXTFCB]
187 JNZ NORMFCB
188 STOSW
189 INC AL
190 STOSW
191 STOSW
192 MOV AL,[ATTRIB]
193 STOSB
194 NORMFCB:
195 MOV AL,[THISDRV]
196 INC AL
197 STOSB ; Set drive number
198 OR DL,DL
199 JZ DOSRELATIVE
200 MOV DS,WORD PTR [CURBUF+2]
201 ASSUME DS:NOTHING
202 DOSRELATIVE:
203
204 IF KANJI
205 MOVSW
206 CMP BYTE PTR ES:[DI-2],5
207 JNZ NOTKTRAN
208 MOV BYTE PTR ES:[DI-2],0E5H
209 NOTKTRAN:
210 MOV CX,15
211 ELSE
212 MOV CX,16
213 ENDIF
214
215 REP MOVSW ; Copy 32 bytes of directory entry
216 XOR AL,AL
217 return
218
219 ASSUME DS:NOTHING
220 KILLSRCH1:
221 PUSH DS
222 POP ES ; Make ES:DI point to the FCB
223 KILLSRCH:
224 MOV AX,-1
225 MOV WORD PTR ES:[DI.FILDIRENT],AX
226 return
227 $DIR_SEARCH_FIRST ENDP
228
229 BREAK <$Dir_Search_Next -- Find next matching directory entry>
230 procedure $DIR_SEARCH_NEXT,NEAR
231 ASSUME DS:NOTHING,ES:NOTHING
232
233 ; Inputs:
234 ; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
235 ; Function:
236 ; Directory is searched for the next matching entry and the directory
237 ; entry is loaded at the disk transfer address
238 ; Returns:
239 ; AL = -1 if no entries matched, otherwise 0
240
241 invoke MOVNAMENOSET
242 ASSUME ES:DOSGROUP
243 MOV DI,DX
244 JC NEAR PTR KILLSRCH1
245 MOV AX,[DI.FILDIRENT]
246 LES BP,DWORD PTR [DI.fcb_DRVBP]
247 OR AX,AX
248 JS NEAR PTR KILLSRCH1
249 MOV BX,[DI.fcb_DRVBP+4]
250 PUSH DX
251 PUSH DS
252 PUSH AX
253 MOV WORD PTR [THISDPB],BP
254 MOV WORD PTR [THISDPB+2],ES
255 invoke SetDirSrch
256 ASSUME DS:DOSGROUP
257 POP AX
258 MOV [ENTLAST],-1
259 invoke GetEnt
260 invoke NextEnt
261 POP ES
262 ASSUME ES:NOTHING
263 POP DI
264 JMP SAVPLCE
265 $DIR_SEARCH_NEXT ENDP
266
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
270
271 ; Inputs:
272 ; DS:DX points to unopenned FCB
273 ; Function:
274 ; Set random record field to size of file
275 ; Returns:
276 ; AL = -1 if no entries matched, otherwise 0
277
278 invoke GETFILE
279 ASSUME DS:DOSGROUP
280 MOV AL,-1
281 retc
282 ADD DI,fcb_RR ; Write size in RR field
283 MOV CX,WORD PTR ES:[DI.fcb_RECSIZ-fcb_RR]
284 OR CX,CX
285 JNZ RECOK
286 MOV CX,128
287 RECOK:
288 XOR DX,DX ; Intialize size to zero
289 INC SI
290 INC SI ; Point to length field
291 MOV DS,WORD PTR [CURBUF+2]
292 ASSUME DS:NOTHING
293 MOV AX,[SI+2] ; Get high word of size
294 DIV CX
295 PUSH AX ; Save high part of result
296 LODSW ; Get low word of size
297 DIV CX
298 OR DX,DX ; Check for zero remainder
299 POP DX
300 JZ DEVSIZ
301 INC AX ; Round up for partial record
302 JNZ DEVSIZ ; Propagate carry?
303 INC DX
304 DEVSIZ:
305 STOSW
306 MOV AX,DX
307 STOSB
308 MOV AL,0
309 CMP CX,64
310 JAE RET14 ; Only 3-byte field if fcb_RECSIZ >= 64
311 MOV ES:[DI],AH
312 RET14: return
313 $GET_FCB_FILE_LENGTH ENDP
314
315 BREAK <$Get_Fcb_Position -- Set random record field to current position>
316 procedure $GET_FCB_POSITION,NEAR
317 ASSUME DS:NOTHING,ES:NOTHING
318
319 ; Inputs:
320 ; DS:DX points to openned FCB
321 ; Function:
322 ; Sets random record field to be same as current record fields
323 ; Returns:
324 ; None
325
326 invoke GETREC
327 MOV WORD PTR [DI+fcb_RR],AX
328 MOV [DI+fcb_RR+2],DL
329 CMP [DI.fcb_RECSIZ],64
330 JAE RET16
331 MOV [DI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64
332 RET16: return
333 $GET_FCB_POSITION ENDP
334
335 BREAK <$Disk_Reset -- Flush out all dirty buffers>
336 procedure $DISK_RESET,NEAR
337 ASSUME DS:NOTHING,ES:NOTHING
338
339 ; Inputs:
340 ; None
341 ; Function:
342 ; Flush and invalidate all buffers
343 ; Returns:
344 ; Nothing
345
346 PUSH SS
347 POP DS
348 ASSUME DS:DOSGROUP
349 MOV AL,-1
350 invoke FLUSHBUF
351 MOV WORD PTR [LASTBUFFER+2],-1
352 MOV WORD PTR [LASTBUFFER],-1
353 invoke SETVISIT
354 ASSUME DS:NOTHING
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
360 invoke SCANPLACE
361 SKPBF:
362 invoke SKIPVISIT
363 JNZ NBFFR
364 return
365 $DISK_RESET ENDP
366
367 procedure $RAW_CON_IO,NEAR ; System call 6
368 ASSUME DS:NOTHING,ES:NOTHING
369
370 ; Inputs:
371 ; DL = -1 if input
372 ; else DL is output character
373 ; Function:
374 ; Input or output raw character from console, no echo
375 ; Returns:
376 ; AL = character
377
378 MOV AL,DL
379 CMP AL,-1
380 JNZ RAWOUT
381 LES DI,DWORD PTR [user_SP] ; Get pointer to register save area
382 XOR BX,BX
383 invoke GET_IO_FCB
384 retc
385 MOV AH,1
386 invoke IOFUNC
387 JNZ RESFLG
388 invoke SPOOLINT
389 OR BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag
390 XOR AL,AL
391 return
392
393 RESFLG:
394 AND BYTE PTR ES:[DI.user_F],0FFH-40H ; Reset user's zero flag
395
396 RILP:
397 invoke SPOOLINT
398 entry $RAW_CON_INPUT ; System call 7
399
400 ; Inputs:
401 ; None
402 ; Function:
403 ; Input raw character from console, no echo
404 ; Returns:
405 ; AL = character
406
407 XOR BX,BX
408 invoke GET_IO_FCB
409 retc
410 MOV AH,1
411 invoke IOFUNC
412 JZ RILP
413 XOR AH,AH
414 invoke IOFUNC
415 return
416 ;
417 ; Output the character in AL to stdout
418 ;
419 entry RAWOUT
420
421 PUSH BX
422 MOV BX,1
423
424 invoke GET_IO_FCB
425 JC RAWRET1
426
427 TEST [SI.fcb_DEVID],080H ; output to file?
428 JZ RAWNORM ; if so, do normally
429 PUSH DS
430 PUSH SI
431 LDS SI,DWORD PTR [SI.fcb_FIRCLUS] ; output to special?
432 TEST BYTE PTR [SI+SDEVATT],ISSPEC
433 POP SI
434 POP DS
435 JZ RAWNORM ; if not, do normally
436 INT int_fastcon ; quickly output the char
437 JMP SHORT RAWRET
438 RAWNORM:
439
440 CALL RAWOUT3
441 RAWRET: CLC
442 RAWRET1:
443 POP BX
444 return
445
446 ;
447 ; Output the character in AL to handle in BX
448 ;
449 entry RAWOUT2
450
451 invoke GET_IO_FCB
452 retc
453 RAWOUT3:
454 PUSH AX
455 JMP SHORT RAWOSTRT
456 ROLP:
457 invoke SPOOLINT
458 RAWOSTRT:
459 MOV AH,3
460 CALL IOFUNC
461 JZ ROLP
462 POP AX
463 MOV AH,2
464 CALL IOFUNC
465 CLC ; Clear carry indicating successful
466 return
467 $RAW_CON_IO ENDP
468
469 ASSUME DS:NOTHING,ES:NOTHING
470 ; This routine is called at DOS init
471
472 procedure OUTMES,NEAR ; String output for internal messages
473 LODS CS:BYTE PTR [SI]
474 CMP AL,"$"
475 retz
476 invoke OUT
477 JMP SHORT OUTMES
478 return
479 OutMes ENDP
480 ASSUME SS:DOSGROUP
481
482 BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>
483 procedure $PARSE_FILE_DESCRIPTOR,NEAR
484 ASSUME DS:NOTHING,ES:NOTHING
485
486 ; Inputs:
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
497 ; Function:
498 ; Parse command line into FCB
499 ; Returns:
500 ; AL = 1 if '*' or '?' in filename or extension, 0 otherwise
501 ; DS:SI points to first character after filename
502
503 invoke MAKEFCB
504 PUSH SI
505 invoke get_user_stack
506 POP [SI.user_SI]
507 return
508 $PARSE_FILE_DESCRIPTOR ENDP
509
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 ;
513 ; ;
514 procedure $Dup_PDB,NEAR
515 ASSUME DS:NOTHING,ES:NOTHING
516 MOV BYTE PTR [CreatePDB], 0FFH ; indicate a new process
517 $Dup_PDB ENDP
518
519
520 procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
521 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
522
523 ; Inputs:
524 ; DX = Segment number of new base
525 ; Function:
526 ; Set up program base and copy term and ^C from int area
527 ; Returns:
528 ; None
529 ; Called at DOS init
530
531 MOV ES,DX
532 TEST BYTE PTR [CreatePDB],0FFh
533 JZ create_PDB_old
534 MOV DS,[CurrentPDB]
535 JMP SHORT Create_copy
536
537 Create_PDB_old:
538 invoke get_user_stack
539 MOV DS,[SI.user_CS]
540
541 Create_copy:
542 XOR SI,SI ; copy all 80h bytes
543 MOV DI,SI
544 MOV CX,80H
545 REP MOVSW
546
547 TEST BYTE PTR [CreatePDB],0FFh ; Shall we create a process?
548 JZ Create_PDB_cont ; nope, old style call
549 ;
550 ; Here we set up for a new process...
551 ;
552
553 PUSH CS
554 POP DS
555 ASSUME DS:DOSGROUP
556 XOR BX,BX ; dup all jfns
557 MOV CX,FilPerProc
558
559 Create_dup_jfn:
560 PUSH ES ; save new PDB
561 invoke get_jfn_pointer ; ES:DI is jfn
562 JC create_skip ; not a valid jfn
563 PUSH ES ; save him
564 PUSH DI
565 invoke get_sf_from_jfn ; get sf pointer
566 JC create_no_inc
567 INC ES:[DI].sf_ref_count ; new fh
568
569 create_no_inc:
570 POP DI
571 POP ES ; get old jfn
572 MOV AL,ES:[DI] ; get sfn
573 POP ES
574 PUSH ES
575 MOV AL,ES:[BX] ; copy into new place!
576
577 create_skip:
578 POP ES
579 INC BX ; next jfn...
580 LOOP create_dup_jfn
581
582 PUSH [CurrentPDB] ; get current process
583 POP BX
584 PUSH BX
585 POP ES:[PDB_Parent_PID] ; stash in child
586 MOV [CurrentPDB],ES
587 ASSUME DS:NOTHING
588 MOV DS,BX
589 ;
590 ; end of new process create
591 ;
592 Create_PDB_cont:
593 MOV BYTE PTR [CreatePDB],0h ; reset flag
594 MOV AX,DS:[2] ; set up size for fall through
595
596 entry SETMEM
597 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
598
599 ; Inputs:
600 ; AX = Size of memory in paragraphs
601 ; DX = Segment
602 ; Function:
603 ; Completely prepares a program base at the
604 ; specified segment.
605 ; Called at DOS init
606 ; Outputs:
607 ; DS = DX
608 ; ES = DX
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.
616
617 XOR CX,CX
618 MOV DS,CX
619 MOV ES,DX
620 MOV SI,addr_int_terminate
621 MOV DI,SAVEXIT
622 MOV CX,6
623 REP MOVSW
624 MOV ES:[2],AX
625 SUB AX,DX
626 CMP AX,MAXDIF
627 JBE HAVDIF
628 MOV AX,MAXDIF
629 HAVDIF:
630 MOV BX,ENTRYPOINTSEG
631 SUB BX,AX
632 MOV CL,4
633 SHL AX,CL
634 MOV DS,DX
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
641 return
642
643 $CREATE_PROCESS_DATA_BLOCK ENDP
644 do_ext
645
646 CODE ENDS
647 END
648