summaryrefslogtreecommitdiff
path: root/v2.0/source/MISC.ASM
blob: e0a5cee23c7b6332d83f7d4531b27be5bead7d15 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
TITLE MISC - Miscellanious routines for MS-DOS
NAME  MISC
;
; Miscellaneous system calls most of which are CAVEAT
;
; $SLEAZEFUNC
; $SLEAZEFUNCDL
; $GET_INDOS_FLAG
; $GET_IN_VARS
; $GET_DEFAULT_DPB
; $GET_DPB
; $DISK_RESET
; $SETDPB
; $Dup_PDB
; $CREATE_PROCESS_DATA_BLOCK
; SETMEM
;
.xlist
;
; get the appropriate segment definitions
;
INCLUDE DOSSEG.ASM

CODE    SEGMENT BYTE PUBLIC  'CODE'
        ASSUME  SS:DOSGROUP,CS:DOSGROUP

.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list


ifndef  Kanji
Kanji   equ 0
endif

ENTRYPOINTSEG   EQU     0CH
MAXDIF          EQU     0FFFH
SAVEXIT         EQU     10

        i_need  LASTBUFFER,DWORD
        i_need  INDOS,BYTE
        i_need  SYSINITVAR,BYTE
        i_need  CurrentPDB,WORD
        i_need  CreatePDB,BYTE
        i_need  EXIT_TYPE,BYTE
        i_need  EXIT_CODE,WORD
        i_need  LASTENT,WORD
        i_need  THISDPB,DWORD
        i_need  ATTRIB,BYTE
        i_need  EXTFCB,BYTE
        i_need  DMAADD,DWORD
        i_need  DIRSTART,WORD
        i_need  CURBUF,DWORD
        i_need  USER_SP,WORD
        i_need  ENTLAST,WORD
        i_need  THISDRV,BYTE

ASSUME  SS:DOSGROUP

BREAK <SleazeFunc -- get a pointer to media byte>

;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
        procedure   $SLEAZEFUNC,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       None
; Function:
;       Return Stuff sort of like old get fat call
; Outputs:
;       DS:BX = Points to FAT ID byte (IBM only)
;               GOD help anyone who tries to do ANYTHING except
;               READ this ONE byte.
;       DX = Total Number of allocation units on disk
;       CX = Sector size
;       AL = Sectors per allocation unit
;          = -1 if bad drive specified

        MOV     DL,0
    entry   $SLEAZEFUNCDL
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        MOV     AL,DL
        invoke  GETTHISDRV
        MOV     AL,-1
        JC      BADSLDRIVE
        invoke  FATREAD
        MOV     DX,ES:[BP.dpb_max_cluster]
        DEC     DX
        MOV     AL,ES:[BP.dpb_cluster_mask]
        INC     AL
        MOV     CX,ES:[BP.dpb_sector_size]
        ADD     BP,dpb_media
BADSLDRIVE:
        invoke  get_user_stack
ASSUME  DS:NOTHING
        MOV     [SI.user_CX],CX
        MOV     [SI.user_DX],DX
        MOV     [SI.user_BX],BP
        MOV     [SI.user_DS],ES
        return
$SLEAZEFUNC    ENDP
;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;



BREAK <$ABORT -- Terminate a process>
        procedure   $ABORT,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       CS:00 must point to valid program header block
; Function:
;       Restore terminate and Cntrl-C addresses, flush buffers
;       and transfer to the terminate address
; Returns:
;       TO THE TERMINATE ADDRESS

        XOR     AL,AL
        MOV     [exit_type],exit_abort

;
; abort_inner must have AL set as the exit code!
;
        entry   abort_inner
        MOV     AH,[exit_type]
        MOV     [exit_code],AX
        invoke  Get_user_stack
        MOV     DS,[SI.user_CS]         ; set up old interrupts
        XOR     AX,AX
        MOV     ES,AX
        MOV     SI,SAVEXIT
        MOV     DI,addr_int_terminate
        MOVSW
        MOVSW
        MOVSW
        MOVSW
        MOVSW
        MOVSW
        transfer    reset_environment
$ABORT   ENDP

BREAK <$Dir_Search_First -- Start a directory search>
        procedure   $DIR_SEARCH_FIRST,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:DX Points to unopenned FCB
; Function:
;       Directory is searched for first matching entry and the directory
;       entry is loaded at the disk transfer address
; Returns:
;       AL = -1 if no entries matched, otherwise 0

        invoke  GETFILE
ASSUME  DS:DOSGROUP
SAVPLCE:
; Search-for-next enters here to save place and report
; findings.
        MOV     DL,0            ; Do not XOR!!!
        JC      KILLSRCH
        OR      AH,AH           ; Is it I/O device?
        JS      KILLIT          ; If so, sign bit will end search
        MOV     AX,[LASTENT]
        INC     DL
KILLIT:
        MOV     ES:[DI.FILDIRENT],AX
        MOV     AX,WORD PTR [THISDPB]
        MOV     ES:[DI.fcb_DRVBP],AX
        MOV     AX,WORD PTR [THISDPB+2]
        MOV     ES:[DI.fcb_DRVBP+2],AX
        MOV     AX,[DIRSTART]
        MOV     ES:[DI.fcb_DRVBP+4],AX
; Information in directory entry must be copied into the first
; 33 bytes starting at the disk transfer address.
        MOV     SI,BX
        LES     DI,[DMAADD]
        MOV     AX,00FFH
        CMP     AL,[EXTFCB]
        JNZ     NORMFCB
        STOSW
        INC     AL
        STOSW
        STOSW
        MOV     AL,[ATTRIB]
        STOSB
NORMFCB:
        MOV     AL,[THISDRV]
        INC     AL
        STOSB   ; Set drive number
        OR      DL,DL
        JZ      DOSRELATIVE
        MOV     DS,WORD PTR [CURBUF+2]
ASSUME  DS:NOTHING
DOSRELATIVE:

        IF      KANJI
        MOVSW
        CMP     BYTE PTR ES:[DI-2],5
        JNZ     NOTKTRAN
        MOV     BYTE PTR ES:[DI-2],0E5H
NOTKTRAN:
        MOV     CX,15
        ELSE
        MOV     CX,16
        ENDIF

        REP     MOVSW   ; Copy 32 bytes of directory entry
        XOR     AL,AL
        return

ASSUME  DS:NOTHING
KILLSRCH1:
        PUSH    DS
        POP     ES      ; Make ES:DI point to the FCB
KILLSRCH:
        MOV     AX,-1
        MOV     WORD PTR ES:[DI.FILDIRENT],AX
        return
$DIR_SEARCH_FIRST ENDP

BREAK <$Dir_Search_Next -- Find next matching directory entry>
        procedure   $DIR_SEARCH_NEXT,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
; Function:
;       Directory is searched for the next matching entry and the directory
;       entry is loaded at the disk transfer address
; Returns:
;       AL = -1 if no entries matched, otherwise 0

        invoke  MOVNAMENOSET
ASSUME  ES:DOSGROUP
        MOV     DI,DX
        JC      NEAR PTR KILLSRCH1
        MOV     AX,[DI.FILDIRENT]
        LES     BP,DWORD PTR [DI.fcb_DRVBP]
        OR      AX,AX
        JS      NEAR PTR KILLSRCH1
        MOV     BX,[DI.fcb_DRVBP+4]
        PUSH    DX
        PUSH    DS
        PUSH    AX
        MOV     WORD PTR [THISDPB],BP
        MOV     WORD PTR [THISDPB+2],ES
        invoke  SetDirSrch
        ASSUME  DS:DOSGROUP
        POP     AX
        MOV     [ENTLAST],-1
        invoke  GetEnt
        invoke  NextEnt
        POP     ES
        ASSUME  ES:NOTHING
        POP     DI
        JMP     SAVPLCE
$DIR_SEARCH_NEXT ENDP

BREAK <$Get_FCB_File_Length -- Return size of file in current records>
        procedure   $GET_FCB_FILE_LENGTH,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:DX points to unopenned FCB
; Function:
;       Set random record field to size of file
; Returns:
;       AL = -1 if no entries matched, otherwise 0

        invoke  GETFILE
ASSUME  DS:DOSGROUP
        MOV     AL,-1
        retc
        ADD     DI,fcb_RR       ; Write size in RR field
        MOV     CX,WORD PTR ES:[DI.fcb_RECSIZ-fcb_RR]
        OR      CX,CX
        JNZ     RECOK
        MOV     CX,128
RECOK:
        XOR     DX,DX           ; Intialize size to zero
        INC     SI
        INC     SI              ; Point to length field
        MOV     DS,WORD PTR [CURBUF+2]
ASSUME  DS:NOTHING
        MOV     AX,[SI+2]       ; Get high word of size
        DIV     CX
        PUSH    AX              ; Save high part of result
        LODSW           ; Get low word of size
        DIV     CX
        OR      DX,DX           ; Check for zero remainder
        POP     DX
        JZ      DEVSIZ
        INC     AX              ; Round up for partial record
        JNZ     DEVSIZ          ; Propagate carry?
        INC     DX
DEVSIZ:
        STOSW
        MOV     AX,DX
        STOSB
        MOV     AL,0
        CMP     CX,64
        JAE     RET14           ; Only 3-byte field if fcb_RECSIZ >= 64
        MOV     ES:[DI],AH
RET14:  return
$GET_FCB_FILE_LENGTH ENDP

BREAK <$Get_Fcb_Position -- Set random record field to current position>
        procedure   $GET_FCB_POSITION,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:DX points to openned FCB
; Function:
;       Sets random record field to be same as current record fields
; Returns:
;       None

        invoke  GETREC
        MOV     WORD PTR [DI+fcb_RR],AX
        MOV     [DI+fcb_RR+2],DL
        CMP     [DI.fcb_RECSIZ],64
        JAE     RET16
        MOV     [DI+fcb_RR+2+1],DH      ; Set 4th byte only if record size < 64
RET16:  return
$GET_FCB_POSITION ENDP

BREAK <$Disk_Reset -- Flush out all dirty buffers>
        procedure   $DISK_RESET,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       None
; Function:
;       Flush and invalidate all buffers
; Returns:
;       Nothing

        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        MOV     AL,-1
        invoke  FLUSHBUF
        MOV     WORD PTR [LASTBUFFER+2],-1
        MOV     WORD PTR [LASTBUFFER],-1
        invoke  SETVISIT
ASSUME  DS:NOTHING
NBFFR:                                  ; Free ALL buffers
        MOV     [DI.VISIT],1            ; Mark as visited
        CMP     BYTE PTR [DI.BUFDRV],-1
        JZ      SKPBF                   ; Save a call to PLACEBUF
        MOV     WORD PTR [DI.BUFDRV],00FFH
        invoke  SCANPLACE
SKPBF:
        invoke  SKIPVISIT
        JNZ     NBFFR
        return
$DISK_RESET ENDP

        procedure   $RAW_CON_IO,NEAR   ; System call 6
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DL = -1 if input
;       else DL is output character
; Function:
;       Input or output raw character from console, no echo
; Returns:
;       AL = character

        MOV     AL,DL
        CMP     AL,-1
        JNZ     RAWOUT
        LES     DI,DWORD PTR [user_SP]                ; Get pointer to register save area
        XOR     BX,BX
        invoke  GET_IO_FCB
        retc
        MOV     AH,1
        invoke  IOFUNC
        JNZ     RESFLG
        invoke  SPOOLINT
        OR      BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag
        XOR     AL,AL
        return

RESFLG:
        AND     BYTE PTR ES:[DI.user_F],0FFH-40H    ; Reset user's zero flag

RILP:
        invoke  SPOOLINT
    entry   $RAW_CON_INPUT        ; System call 7

; Inputs:
;       None
; Function:
;       Input raw character from console, no echo
; Returns:
;       AL = character

        XOR     BX,BX
        invoke  GET_IO_FCB
        retc
        MOV     AH,1
        invoke  IOFUNC
        JZ      RILP
        XOR     AH,AH
        invoke  IOFUNC
        return
;
;       Output the character in AL to stdout
;
entry   RAWOUT

        PUSH    BX
        MOV     BX,1

        invoke  GET_IO_FCB
        JC      RAWRET1

        TEST    [SI.fcb_DEVID],080H             ; output to file?
        JZ      RAWNORM                         ; if so, do normally
        PUSH    DS
        PUSH    SI
        LDS     SI,DWORD PTR [SI.fcb_FIRCLUS]   ; output to special?
        TEST    BYTE PTR [SI+SDEVATT],ISSPEC
        POP     SI
        POP     DS
        JZ      RAWNORM                         ; if not, do normally
        INT     int_fastcon                     ; quickly output the char
        JMP     SHORT RAWRET
RAWNORM:

        CALL    RAWOUT3
RAWRET: CLC
RAWRET1:
        POP     BX
        return

;
;       Output the character in AL to handle in BX
;
entry   RAWOUT2

        invoke  GET_IO_FCB
        retc
RAWOUT3:
        PUSH    AX
        JMP     SHORT RAWOSTRT
ROLP:
        invoke  SPOOLINT
RAWOSTRT:
        MOV     AH,3
        CALL    IOFUNC
        JZ      ROLP
        POP     AX
        MOV     AH,2
        CALL    IOFUNC
        CLC                     ; Clear carry indicating successful
        return
$RAW_CON_IO   ENDP

ASSUME  DS:NOTHING,ES:NOTHING
; This routine is called at DOS init

        procedure   OUTMES,NEAR ; String output for internal messages
        LODS    CS:BYTE PTR [SI]
        CMP     AL,"$"
        retz
        invoke  OUT
        JMP     SHORT OUTMES
        return
OutMes  ENDP
        ASSUME  SS:DOSGROUP

BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>
        procedure   $PARSE_FILE_DESCRIPTOR,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:SI Points to a command line
;       ES:DI Points to an empty FCB
;       Bit 0 of AL = 1 At most one leading separator scanned off
;                   = 0 Parse stops if separator encountered
;       Bit 1 of AL = 1 If drive field blank in command line - leave FCB
;                   = 0  "    "    "     "         "      "  - put 0 in FCB
;       Bit 2 of AL = 1 If filename field blank - leave FCB
;                   = 0  "       "      "       - put blanks in FCB
;       Bit 3 of AL = 1 If extension field blank - leave FCB
;                   = 0  "       "      "        - put blanks in FCB
; Function:
;       Parse command line into FCB
; Returns:
;       AL = 1 if '*' or '?' in filename or extension, 0 otherwise
;       DS:SI points to first character after filename

        invoke  MAKEFCB
        PUSH    SI
        invoke  get_user_stack
        POP     [SI.user_SI]
        return
$PARSE_FILE_DESCRIPTOR ENDP

BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
        procedure   $Dup_PDB,NEAR
ASSUME  DS:NOTHING,ES:NOTHING
        MOV     BYTE PTR [CreatePDB], 0FFH  ; indicate a new process
$Dup_PDB    ENDP


        procedure   $CREATE_PROCESS_DATA_BLOCK,NEAR
ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

; Inputs:
;       DX = Segment number of new base
; Function:
;       Set up program base and copy term and ^C from int area
; Returns:
;       None
; Called at DOS init

        MOV     ES,DX
        TEST    BYTE PTR [CreatePDB],0FFh
        JZ      create_PDB_old
        MOV     DS,[CurrentPDB]
        JMP     SHORT Create_copy

Create_PDB_old:
        invoke  get_user_stack
        MOV     DS,[SI.user_CS]

Create_copy:
        XOR     SI,SI                   ; copy all 80h bytes
        MOV     DI,SI
        MOV     CX,80H
        REP     MOVSW

        TEST    BYTE PTR [CreatePDB],0FFh   ; Shall we create a process?
        JZ      Create_PDB_cont         ; nope, old style call
;
; Here we set up for a new process...
;

        PUSH    CS
        POP     DS
        ASSUME  DS:DOSGROUP
        XOR     BX,BX                   ; dup all jfns
        MOV     CX,FilPerProc

Create_dup_jfn:
        PUSH    ES                      ; save new PDB
        invoke  get_jfn_pointer         ; ES:DI is jfn
        JC      create_skip             ; not a valid jfn
        PUSH    ES                      ; save him
        PUSH    DI
        invoke  get_sf_from_jfn         ; get sf pointer
        JC      create_no_inc
        INC     ES:[DI].sf_ref_count    ; new fh

create_no_inc:
        POP     DI
        POP     ES                      ; get old jfn
        MOV     AL,ES:[DI]              ; get sfn
        POP     ES
        PUSH    ES
        MOV     AL,ES:[BX]              ; copy into new place!

create_skip:
        POP     ES
        INC     BX                      ; next jfn...
        LOOP    create_dup_jfn

        PUSH    [CurrentPDB]            ; get current process
        POP     BX
        PUSH    BX
        POP     ES:[PDB_Parent_PID]     ; stash in child
        MOV     [CurrentPDB],ES
        ASSUME  DS:NOTHING
        MOV     DS,BX
;
; end of new process create
;
Create_PDB_cont:
        MOV     BYTE PTR [CreatePDB],0h ; reset flag
        MOV     AX,DS:[2]               ; set up size for fall through

entry SETMEM
ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

; Inputs:
;       AX = Size of memory in paragraphs
;       DX = Segment
; Function:
;       Completely prepares a program base at the
;       specified segment.
; Called at DOS init
; Outputs:
;       DS = DX
;       ES = DX
;       [0] has INT int_abort
;       [2] = First unavailable segment ([ENDMEM])
;       [5] to [9] form a long call to the entry point
;       [10] to [13] have exit address (from int_terminate)
;       [14] to [17] have ctrl-C exit address (from int_ctrl_c)
;       [18] to [21] have fatal error address (from int_fatal_abort)
; DX,BP unchanged. All other registers destroyed.

        XOR     CX,CX
        MOV     DS,CX
        MOV     ES,DX
        MOV     SI,addr_int_terminate
        MOV     DI,SAVEXIT
        MOV     CX,6
        REP     MOVSW
        MOV     ES:[2],AX
        SUB     AX,DX
        CMP     AX,MAXDIF
        JBE     HAVDIF
        MOV     AX,MAXDIF
HAVDIF:
        MOV     BX,ENTRYPOINTSEG
        SUB     BX,AX
        MOV     CL,4
        SHL     AX,CL
        MOV     DS,DX
        MOV     WORD PTR DS:[PDB_CPM_Call+1],AX
        MOV     WORD PTR DS:[PDB_CPM_Call+3],BX
        MOV     DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT
        MOV     BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL
        MOV     WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT
        MOV     BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET
        return

$CREATE_PROCESS_DATA_BLOCK ENDP
        do_ext

 CODE   ENDS
        END