summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/PRINT/PRINT_R.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/PRINT/PRINT_R.ASM')
-rw-r--r--v4.0/src/CMD/PRINT/PRINT_R.ASM3432
1 files changed, 3432 insertions, 0 deletions
diff --git a/v4.0/src/CMD/PRINT/PRINT_R.ASM b/v4.0/src/CMD/PRINT/PRINT_R.ASM
new file mode 100644
index 0000000..539339e
--- /dev/null
+++ b/v4.0/src/CMD/PRINT/PRINT_R.ASM
@@ -0,0 +1,3432 @@
1 page 80,132
2 TITLE DOS - PRINT - RESIDENT
3; $SALUT (4,25,30,41)
4 INCLUDE pridefs.inc
5
6; include Extended Atribute support
7
8 include EA.INC
9
10 BREAK <Resident Portion>
11;
12; DOS PRINT
13;
14; Resident Portion
15;
16
17Code Segment public para
18 extrn TransRet:WORD,TransSize:WORD,NameBuf:WORD
19 extrn GoDispMsg:FAR
20Code EndS
21
22 BREAK <Resident Data>
23
24CodeR Segment public para
25
26 public SliceCnt, BusyTick, MaxTick, TimeSlice
27 public EndRes, BlkSiz, QueueLen, PChar
28 public ListName, FileQueue, EndQueue, Buffer
29 public EndPtr, NxtChr, MoveTrans
30 public TO_DOS
31
32 public MESBAS
33
34
35 ASSUME CS:CodeR
36
37 db " - PRINT utility - "
38
39 include copyrigh.inc
40
41 db 01Ah ; fake end of file for 'TYPE'
42 DB (361 - 80h) + 310 DUP (?) ; (362 - 80h) is IBM's New
43 ; recommended Stack Size -
44 ; Old recommended Stack Size
45 ; == New stack growth
46ISTACK LABEL WORD ;Stack starts here and grows down the
47
48;Resident data
49
50;
51; Due to flagrant bogosity by file servers, BUSY is *ALWAYS* relevant.
52;
53BUSY DB 0 ;Internal ME flag
54
55;
56; WARNING!!! The *&^%(*&^ 286 chip hangs if you access a word that will wrap
57; at the segment boundary. Make the initial INDOS point somewhere reasonable.
58;
59INDOS DD TimeSlice ;DOS buisy flag
60NEXTINT DD ? ;Chain for int
61NEXT_REBOOT DD ? ;Chain for ROM bootstrap
62
63fFake db 0 ; TRUE => do not diddle I/O ports
64SOFINT DB 0 ;Internal ME flag
65TICKCNT DB 0 ;Tick counter
66TICKSUB DB 0 ;Tick miss counter
67SLICECNT DB DefTimeSlice ;Time slice counter, init to same val
68 ; as TIMESLICE
69
70TIMESLICE DB DefTimeSlice ;The PRINT scheduling time slice. PRINT
71 ; lets this many "ticks" go by before
72 ; using a time slice to pump out characters.
73 ; Setting this to 3 for instance means PRINT
74 ; Will skip 3 slices, then take the fourth.
75 ; Thus using up 1/4 of the CPU. Setting it
76 ; to one gives PRINT 1/2 of the CPU.
77 ; The above examples assume MAXTICK is
78 ; 1. The actual PRINT CPU percentage is
79 ; (MAXTICK/(1+TIMESLICE))*100
80
81MAXTICK DB DefMaxTick ;The PRINT in timeslice. PRINT will pump
82 ; out characters for this many clock ticks
83 ; and then exit. The selection of a value
84 ; for this is dependent on the timer rate.
85
86BUSYTICK DB DefBusyTick ;If PRINT sits in a wait loop waiting for
87 ; output device to come ready for this
88 ; many ticks, it gives up its time slice.
89 ; Setting it greater than or equal to
90 ; MAXTICK causes it to be ignored.
91
92;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK
93; ticks go by without getting a character out.
94
95QueueLen db DefQueueLen ; Actual length of print queue
96 even
97EndQueue dw ? ; pointer to end of print queue
98QueueTail dw offset CodeR:FileQueue ; pointer to next free entry
99 ; in the print queue
100buffer dw ? ; pointer to data buffer
101
102I24_ERR DW ? ;Save location for INT 24H error code
103Ctrlc DB ? ; saved ^C trapping state
104SPNEXT DD ? ;Chain location for INT 28
105COMNEXT DD ? ;Chain location for INT 2F
106SSsave DW ? ;Stack save area for INT 24
107SPsave DW ?
108HERRINT DD ? ;Place to save Hard error interrupt
109LISTDEV DD ? ;Pointer to Device
110COLPOS DB 0 ;Column position for TAB processing
111CURRFIL DB 0
112CURRCP DW -1 ; Current file's CP in binary ;AN000;
113NXTCHR DW ?
114CURRHAND DW -1
115PrinterNum DW no_lptx ; index for printer
116no_lptx equ -1 ; no valid LPTx
117QueueLock db 0 ; queue lock, 0=unlocked
118
119
120PChar db ? ; path character
121AmbCan db ? ; = 1 ambigous cancel
122CanFlg db ? ; = 1 Current was already canceled
123ACanOcrd db ? ; = 1 a file was found during an
124 ; ambigous cancel
125
126;--- Warnning: this is a FCB!!
127
128ACBuf db ?
129ACName db 8 dup(?)
130ACExt db 3 dup(?)
131 db 4 dup(?) ; how big is an unopened fcb???
132
133
134CONTXTFLAG DB 0 ;0 means his context, NZ means me
135HISPDB DW ?
136PABORT DB 0 ;Abort flag
137BLKSIZ DW DefBufferLen ;Size of the PRINT I/O block in bytes
138ENDPTR DW ?
139
140COMDISP LABEL WORD ; Communications dispatch table
141
142 DW OFFSET CodeR:INST_REQ
143 DW OFFSET CodeR:ADDFIL
144 DW OFFSET CodeR:CANFIL
145 DW OFFSET CodeR:CanAll
146 DW OFFSET CodeR:QSTAT
147 DW OFFSET CodeR:EndStat
148 DW OFFSET CodeR:QSTATDEV
149
150query_list label word
151
152 dw 1
153 qea <EAISBINARY,EASYSTEM,2,"C">
154 db "P" ; specify name as CP
155
156list label word
157 dw 1 ; only one EA of interest
158 ea <EAISBINARY,EASYSTEM,?,2,2,"C">
159 db "P"
160code_page dw 0 ; CP initialized to 0
161
162list_size equ $ - list
163 ;--------------------------------------
164 ; Resident Message Buffer - Data area
165 ;--------------------------------------
166
167ERRMES DB 13,10,13,10
168 DB "**********"
169 DB 13,10,"$"
170
171BELMES DB 13,0CH,7,"$"
172
173CRLF DB 13,10,0
174
175 ;--------------------------------------
176 ; Resident Message Pointer Control Block
177 ;--------------------------------------
178
179MESBAS DW ? ; OFFSET CodeR:ERR0 This list is order sensitive
180 DW ? ; OFFSET CodeR:ERR1 and must not be changed without
181 DW ? ; OFFSET CodeR:ERR2 considering the logic in
182 DW ? ; OFFSET CodeR:ERR3 Load_R_Msg
183 DW ? ; OFFSET CodeR:ERR4
184 DW ? ; OFFSET CodeR:ERR5
185 DW ? ; OFFSET CodeR:ERR6
186 DW ? ; OFFSET CodeR:ERR7
187 DW ? ; OFFSET CodeR:ERR8
188 DW ? ; OFFSET CodeR:ERR9
189 DW ? ; OFFSET CodeR:ERR10
190 DW ? ; OFFSET CodeR:ERR11
191 DW ? ; OFFSET CodeR:ERR12
192ERRMEST_PTR DW ? ; OFFSET CodeR:ERRMEST
193ErrMesT2_PTR DW ? ; OFFSET CodeR:ErrMesT2
194CANMES_PTR DW ? ; OFFSET CodeR:CANMES
195CanFilNam_PTR DW ? ; OFFSET CodeR:CanFilNam
196AllCan_PTR DW ? ; OFFSET CodeR:AllCan
197FATMES_PTR DW ? ; OFFSET CodeR:FATMES
198BADDRVM_PTR DW ? ; OFFSET CodeR:BADDRVM
199
200ENDRES DW ? ; filled in at initialization time
201
202PRTDPL DPL <>
203
204CodeR EndS
205
206BREAK <Resident Code>
207
208CodeR Segment public para
209
210Break <Server critical section routines>
211
212; $SALUT (4,4,9,41)
213
214TestSetServer:
215
216 clc
217 push ax
218 mov ax,8700h ; Can I run?
219 int 2Ah
220 pop ax
221
222 ret
223
224LeaveServer:
225
226 push ax
227 mov ax,8701h
228 int 2Ah
229 pop ax
230
231 ret
232 ;---------------------------------------
233 ; Interrupt routines
234 ;---------------------------------------
235
236ASSUME CS:CodeR,DS:nothing,ES:nothing,SS:nothing
237
238 ;---------------------------------------
239 ;
240 ; PRINT is stimulated by a hardware
241 ; interrupt.
242 ;
243 ;
244 ; The Server may also stimulate us
245 ; during timer ticks (if we handled
246 ; the ticks ourselves, it would be
247 ; disasterous). Therefore, we have a
248 ; substitute entry here that simulates
249 ; the timer stuff but does NOT muck
250 ; with the ports.
251 ;
252 ;---------------------------------------
253FakeINT1C:
254
255 mov fFake,-1
256 jmp SHORT InnerHardInt
257
258HDSPINT: ;Hardware interrupt entry point
259
260 mov fFake,0
261
262InnerHardInt:
263
264 call TestSetServer
265
266; $if nc ; ;AC000;
267 JC $$IF1
268
269 inc [TICKCNT] ;Tick
270 inc [TICKSUB] ;Tick
271 cmp [SLICECNT],0
272
273; $if nz ; ;AC000;
274 JZ $$IF2
275
276 dec [SLICECNT] ;Count down
277
278; $else ; ;AC000;
279 JMP SHORT $$EN2
280$$IF2:
281
282 cmp BUSY,0 ; interrupting ourself ?
283
284; $if z,and ; if NOT interupting ourselves and ... ;AC000;
285 JNZ $$IF4
286
287 push ax ; check for nested interrupts
288 mov al,00001011b ; select ISR in 8259
289 out 20h,al
290 jmp x
291
292x:
293
294 in al,20H ; get ISR register
295 and al,0FEH ; mask timer int
296 pop ax
297
298; $if z,and ; if there are no other ints to service;AC000;
299 JNZ $$IF4
300
301 push ds
302 push si
303 lds si,[INDOS] ;Check for making DOS calls
304
305 ;---------------------------------------
306 ;
307 ; WARNING!!! Due to INT 24 clearing the
308 ; INDOS flag, we must test both INDOS
309 ; and ERRORMODE at once!
310 ;
311 ; These must be contiguous in MSDATA.
312 ;
313 ;---------------------------------------
314 cmp WORD PTR [SI-1],0
315 pop SI
316 pop DS
317
318; $if z ; if no errors ;AC000;
319 JNZ $$IF4
320
321 inc [BUSY] ;Exclude furthur interrupts
322 mov [TICKCNT],0 ;Reset tick counter
323 mov [TICKSUB],0 ;Reset tick counter
324 sti ;Keep things rolling
325 test fFake,-1
326
327; $if z ;if needed ;AC000;
328 JNZ $$IF5
329
330 push ax
331 mov al,EOI ;Acknowledge interrupt
332 out AKPORT,al
333 pop ax
334
335; $endif ; endif ;AC000;
336$$IF5:
337
338 call DOINT
339 cli
340 push ax
341 mov al,[TIMESLICE]
342 mov [SLICECNT],al ;Either soft or hard int resets time slice
343 pop ax
344 dec Busy ;Done, let others in
345
346; $endif ; ;AC000;
347$$IF4:
348
349; $endif ; ;AC000;
350$$EN2:
351
352 Call LeaveServer
353
354; $endif ; ;AC000;
355$$IF1:
356
357 test fFake,-1
358
359; $if z ; ;AC000;
360 JNZ $$IF10
361
362 jmp [NEXTINT] ; chain to next clock routine
363
364; $endif ; ;AC000;
365$$IF10:
366
367 iret
368
369 ;---------------------------------------
370 ; PRINT is stimulated by a
371 ; spooler idle interrupt
372 ;---------------------------------------
373
374SPINT: ; INT 28H entry point
375
376 call TestSetServer
377
378; $if nc ; if no server ;AC000;
379 JC $$IF12
380
381 cmp [BUSY],0
382
383; $if z ; if not busy ;AC000;
384 JNZ $$IF13
385
386 inc [BUSY] ; exclude hardware interrupt
387 inc [SOFINT] ; indicate a software int in progress
388 sti ; hardware interrupts ok on INT 28H entry
389 call DOINT
390 cli
391 mov [SOFINT],0 ;Indicate INT done
392 push ax
393 mov al,[TIMESLICE]
394 mov [SLICECNT],al ;Either soft or hard int resets time slice
395 pop ax
396 dec Busy
397
398; $endif ; ;AC000;
399$$IF13:
400
401 call LeaveServer
402
403; $endif ; ;AC000;
404$$IF12:
405
406 jmp [SPNEXT] ;Chain to next INT 28
407
408 ;---------------------------------------
409 ; Since we may be entering at arbitrary
410 ; times, we need to get/set the extended
411 ; error as we may end up blowing it away.
412 ; We do not do this on spooler ints.
413 ;---------------------------------------
414
415SaveState DPL <> ; empty DPL
416
417 public enterprint
418
419EnterPRINT:
420
421 test SofInt,-1
422
423; $if z ;if not soft int ;AC000;
424 JNZ $$IF16
425
426 mov ah,GetExtendedError
427 call DO_21
428 mov SaveState.DPL_AX,AX
429 mov SaveState.DPL_BX,BX
430 mov SaveState.DPL_CX,CX
431 mov SaveState.DPL_DX,DX
432 mov SaveState.DPL_SI,SI
433 mov SaveState.DPL_DI,DI
434 mov SaveState.DPL_DS,DS
435 mov SaveState.DPL_ES,ES
436
437; $endif ; ;AC000;
438$$IF16:
439
440 ret
441
442 public leaveprint
443
444LeavePRINT:
445
446 test SofInt,-1
447
448; $if z ; if soft int ;AC000;
449 JNZ $$IF18
450
451 mov ax,(ServerCall SHL 8) + 10
452 push cs
453 pop ds
454 mov dx,OFFSET CodeR:SaveState
455 call Do_21
456
457; $endif ; ;AC000;
458$$IF18:
459
460 ret
461
462 public doint
463
464DOINT:
465
466 ASSUME CS:CodeR,DS:nothing,ES:nothing,SS:nothing
467
468 cmp [CURRFIL],0
469 jnz GOAHEAD
470
471SPRET:
472
473 ret ;Nothing to do
474
475GOAHEAD:
476
477 cmp [QueueLock],1
478 je spret ; queue locked, do nothing...
479 push ax ;Need a working register
480 mov [SSsave],ss
481 mov [SPsave],sp
482 mov ax,cs
483 cli
484 ;---------------------------------------
485 ; Go to internal stack to prevent
486 ; INT 24 overflowing system stack
487 ;---------------------------------------
488 mov ss,ax
489 mov sp,OFFSET CodeR:ISTACK
490 sti
491 push es
492 push ds
493 push bp
494 push bx
495 push cx
496 push dx
497 push si
498 push di
499 push cs
500 pop ds
501
502 ASSUME DS:CodeR
503
504 call EnterPRINT
505 mov bx,[NXTCHR]
506 cmp bx,[ENDPTR]
507 jb PLOOP
508 jmp READBUFF ;Buffer empty
509
510DONEJMPJP:
511
512 popf ; ;AC000;
513
514DONEJMPJ:
515
516 jmp DONEJMP
517
518FILEOFJ:
519
520 ASSUME DS:CodeR
521
522 jmp FILEOF
523
524PLOOP:
525
526 mov bx,[NXTCHR]
527 cmp bx,[ENDPTR]
528 jae DONEJMPJ ;Buffer has become empty
529 cmp [SOFINT],0
530 jnz STATCHK
531 push ax
532 mov al,[MAXTICK]
533 cmp [TICKCNT],al ;Check our time slice
534 pop ax
535 jae DONEJMPJ
536
537STATCHK:
538
539 call PSTAT
540 pushf
541 cmp [CURRFIL],0
542 jz DONEJMPJP ;File got cancelled by error
543 popf ; ;AC000;
544 jz DOCHAR ;Printer ready
545 cmp [SOFINT],0
546 jnz DONEJMP ;If soft int give up
547 push ax
548 mov al,[BUSYTICK]
549 cmp [TICKSUB],al ;Check our busy timeout
550 pop ax
551 jae DONEJMP
552 jmp PLOOP
553
554DOCHAR:
555
556 mov al,BYTE PTR [BX]
557 cmp al,1Ah ;^Z?
558 jz FILEOFJ ;CPM EOF
559 cmp al,0Dh ;CR?
560
561; $if z ; if CR ;AC000;
562 JNZ $$IF20
563
564 mov [COLPOS],0
565
566; $endif ; ;AC000;
567$$IF20:
568
569 cmp al,9 ;TAB?
570 jnz NOTABDO
571 mov cl,[COLPOS] ;expand tab to # spaces
572 or cl,0F8h
573 neg cl
574 xor ch,ch
575 jcxz TABDONE ;CX contains # spaces to print
576
577;G TABLP:
578
579 mov al," "
580 inc [COLPOS]
581 push cx
582 call POUT
583 pop cx
584 dec cx ;G
585 jz TABDONE ;G We're done - get next char
586 jmp PLOOP ;G Keep processing tab
587
588;G LOOP TABLP
589;G JMP TABDONE
590
591NOTABDO:
592
593 cmp al,8 ;Back space?
594 jnz NOTBACK
595 dec [COLPOS]
596
597NOTBACK:
598
599 cmp al,20h ;Non Printing char?
600
601; $if ae ; if not printable
602 JNAE $$IF22
603
604 inc [COLPOS] ;Printing char
605
606; $endif ;
607$$IF22:
608
609 call POUT ;Print it
610
611TABDONE:
612
613 inc [NXTCHR] ;Next char
614 mov [TICKSUB],0 ;Got a character out, Reset counter
615 cmp [SOFINT],0 ;Soft int does one char at a time
616 jnz DONEJMP
617 jmp PLOOP
618
619DONEJMP:
620
621 call CONTEXT_BACK
622 call LeavePRINT
623 pop di
624 pop si
625 pop dx
626 pop cx
627 pop bx
628 pop bp
629 pop ds
630 pop es
631
632 ASSUME DS:nothing,ES:nothing
633
634 cli
635 mov ss,[SSsave] ;Restore Entry Stack
636 mov sp,[SPsave]
637 sti
638 pop ax
639
640 ret
641
642CONTEXT_BACK:
643
644 ASSUME DS:nothing,ES:nothing,SS:nothing
645
646 cmp [CONTXTFLAG],0
647
648; $if nz ; if not in context ;AC000;
649 JZ $$IF24
650
651 SaveReg <AX,BX>
652 mov bx,[HISPDB]
653 mov ah,SET_CURRENT_PDB
654 call do_21
655 RestoreReg <BX,AX>
656 mov [CONTXTFLAG],0
657
658; $endif ; ;AC000;
659$$IF24:
660
661 ret
662
663CONTEXT_SWITCH:
664
665 ASSUME DS:nothing,ES:nothing,SS:nothing
666
667 cmp [CONTXTFLAG],0
668
669; $if z ; if context off ;AC000;
670 JNZ $$IF26
671
672 SaveReg <BX,AX>
673 mov ah,GET_CURRENT_PDB
674 call do_21
675 mov [HISPDB],bx
676 mov bx,cs
677 sub bx,10h ; The 2.5 print is an exe program
678 mov ah,SET_CURRENT_PDB
679 call do_21
680 RestoreReg <AX,BX>
681 mov [CONTXTFLAG],1
682
683; $endif ; ;AC000;
684$$IF26:
685
686 ret
687 ;---------------------------------------
688 ;--- Refill the print buffer ---
689 ;---------------------------------------
690READBUFF:
691
692 ASSUME DS:CodeR,ES:NOTHING,SS:NOTHING
693
694 call Set24 ; switch Int24 vector
695 mov [PABORT],0 ;No abort
696 mov BX,[CURRHAND]
697 mov CX,[BLKSIZ]
698 mov DX,[BUFFER]
699 mov AH,READ
700 call My21
701 pushf
702 call Res24 ; reset Int 24 vector
703 cmp [PABORT],0
704 jz NOHERR
705 pop ax ;Flags from read
706 jmp FilClose ;Barf on this file, got INT 24
707
708NOHERR:
709
710 popf ; ;AC000;
711 jc FILEOF
712 cmp ax,0
713 jz FILEOF ;Read EOF?
714 mov bx,[BUFFER] ;Buffer full
715 mov di,bx
716 add di,ax
717 mov [NXTCHR],bx
718 mov cx,[BLKSIZ]
719 sub cx,ax
720
721; $if ncxz ; if buffer is not completely full ;AC000;
722 JCXZ $$IF28
723
724 push cs
725 pop es
726 mov al,1Ah
727 cld
728 rep stosb ; pad the buffer
729
730; $endif ; endif ;AC000;
731$$IF28:
732
733 jmp DONEJMP
734
735FILEOF:
736
737 mov al,0Ch ;Form feed
738 call POUT
739 ;---------------------------------------
740 ;--- Close file
741 ;
742 ; note: we came here from an i24
743 ; then PAbort is already = 1
744 ;---------------------------------------
745FilClose:
746
747 call Set24
748 mov pAbort,-1
749 mov bx,[CURRHAND]
750 call CloseFile ; ;AC000;
751 call Res24
752 mov [CURRFIL],0 ; No file
753 mov [CURRHAND],-1 ; Invalid handle
754 mov ax,[ENDPTR]
755 mov [NXTCHR],ax ; Buffer empty
756
757 ;---------------------------------------
758 ;--- Send close on output device
759 ;---------------------------------------
760 call Close_Dev
761
762 ;---------------------------------------
763 ;--- compact the print queue
764 ;---------------------------------------
765
766CompQAgn:
767
768 call CompQ
769
770 ;---------------------------------------
771 ;--- Check if there are any more
772 ; files to print
773 ;---------------------------------------
774 mov si,OFFSET CodeR:FileQueue
775 cmp byte ptr [si],0 ; no more left if name starts with nul
776 je NoFilesLeft
777 call Set24
778 mov [PABORT],0 ;No abort
779 mov dx,si ; DS:DX points to file name
780 call OpenFile ; try opening new file ;AC000;
781 pushf
782 call Res24
783 cmp [PAbort],0
784 je NoI24a
785 popf ; ;AC000;
786 jmp short CompQAgn ; try next file
787
788NoI24a:
789
790 popf ; ;AC000;
791 jnc GotNewFile
792 call PrtOpErr
793 jmp short CompQAgn
794
795GotNewFile: ; buffer was already marked as empty
796
797 mov [CurrHand],ax
798 mov [CurrFil],1
799
800 ;---------------------------------------
801 ;--- Send Open on output device
802 ;---------------------------------------
803 call Open_Dev
804
805NoFilesLeft:
806
807 jmp DONEJMP
808
809 ;---------------------------------------
810 ;--- Print open error ---
811 ; - preserves DS
812 ;---------------------------------------
813
814PrtOpErr:
815
816 ASSUME DS:CodeR,ES:nothing
817
818 ;---------------------------------------
819 ; This stuff constitutes a "file" so it
820 ; is bracketed by an open/close
821 ; on the output device.
822 ;---------------------------------------
823
824 ;---------------------------------------
825 ;--- Send Open on output device
826 ;---------------------------------------
827 call Open_Dev
828
829 push cs
830 pop es
831
832 ASSUME ES:CodeR
833
834 mov si,OFFSET CodeR:ErrMes
835 call ListMes
836 mov si,ErrMesT2_ptr ; ;AC000;
837 call ListMes
838 mov si,OFFSET CodeR:FileQueue
839 call ListMes2
840 mov si,OFFSET CodeR:BelMes
841 call ListMes
842
843 ;---------------------------------------
844 ;--- Send close on output device
845 ;---------------------------------------
846
847 call Close_Dev
848
849 ret
850
851
852 ;---------------------------------------
853 ;--- Compact File Queue ---
854 ; - modifies: AX,CX,SI,DI,ES
855 ;---------------------------------------
856
857CompQ:
858
859 ASSUME DS:CodeR,ES:nothing,SS:nothing
860
861 push cs
862 pop es
863
864 ASSUME ES:CodeR
865
866 mov di,OFFSET CodeR:FileQueue ; ES:DI points to top of queue
867 mov si,(OFFSET CodeR:FileQueue + MaxFileLen) ; DS:SI points to next entry
868 mov cx,[EndQueue]
869 sub cx,si ; length in bytes of the queue
870 cld
871 rep movsb ; compact the queue
872 mov ax,[QueueTail] ; normalize tail pointer as we
873 sub ax,MaxFileLen ; know have a new "next empty slot"
874 mov [QueueTail],ax
875 mov si,ax
876 mov byte ptr [si],0 ; nul first byte of last entry
877
878 ret
879
880
881 BREAK <Resident Code: DSKERR>
882
883 ;---------------------------------------
884 ;--- Set Local Int 24 vector ---
885 ; - modifies: AX,DX
886 ;---------------------------------------
887
888Set24:
889
890 ASSUME DS:nothing,ES:nothing,SS:nothing
891
892 push es
893 push bx
894 push dx
895 mov al,24h
896 mov ah,GET_INTERRUPT_VECTOR
897 call do_21
898 mov WORD PTR [HERRINT+2],es ; Save current vector
899 mov WORD PTR [HERRINT],bx
900 mov dx,OFFSET CodeR:DSKERR
901 mov al,24h
902 mov ah,SET_INTERRUPT_VECTOR ; Install our own
903 call do_21 ; Spooler must catch its errors
904 pop dx
905 pop bx
906 pop es
907
908 ret
909 ;---------------------------------------
910 ;--- Reset Old Int 24 vector ---
911 ; - modifies: none
912 ;---------------------------------------
913Res24:
914
915 ASSUME DS:nothing,ES:nothing,SS:nothing
916
917 push ds
918 push ax
919 push dx
920 lds dx,[HERRINT]
921
922 ASSUME DS:nothing
923
924 mov al,24h
925 mov ah,SET_INTERRUPT_VECTOR
926 call do_21 ;Restore Error INT
927 pop dx
928 pop ax
929 pop ds
930
931 ret
932 ;---------------------------------------
933 ;--- INT 24 handler ---
934 ;---------------------------------------
935DSKERR:
936
937 ASSUME DS:nothing,ES:nothing,SS:nothing
938
939 cmp [PABORT],0
940
941; $if z ; if not to ignore ;AC000;
942 JNZ $$IF30
943
944 sti
945 push bx
946 push cx
947 push dx
948 push di
949 push si
950 push bp
951 push es
952 push ds
953 push cs
954 pop ds
955 push cs
956 pop es
957
958 ASSUME DS:CodeR,ES:CodeR
959
960 mov si,BADDRVM_PTR ; Fix up Drive ID for FATMES ;AC000;
961 add ds:[si],al ; ;AC000;
962 mov si,OFFSET CodeR:ERRMES
963 call LISTMES
964 test AH,080H
965
966; $if z ; if not fat error ;AC000;
967 JNZ $$IF31
968
969 and di,0FFh
970 cmp di,12
971
972; $if a ; if greater - force it to 12 ;AC000;
973 JNA $$IF32
974
975 mov di,12
976
977; $endif ; ;AC000;
978$$IF32:
979
980 mov [I24_ERR],di
981 shl di,1
982 mov di,WORD PTR [di+MESBAS] ; Get pointer to error message
983 mov si,di
984 call LISTMES ; Print error type
985 mov si,ERRMEST_PTR ; ;AC000;
986 call LISTMES
987 mov si,OFFSET CodeR:FileQueue ; print filename
988 call ListMes2 ; print name
989 mov si,OFFSET CodeR:BelMes
990 call ListMes
991
992; $else ; ;AC000;
993 JMP SHORT $$EN31
994$$IF31:
995
996 mov [I24_ERR],0FFh
997 mov si,FATMES_PTR ; ;AC000;
998 call LISTMES
999
1000; $endif ; ;AC000;
1001$$EN31:
1002
1003 inc [PABORT] ;Indicate abort
1004 pop ds
1005 pop es
1006 pop bp
1007 pop si
1008 pop di
1009 pop dx
1010 pop cx
1011 pop bx
1012
1013; $endif ; ;AC000;
1014$$IF30:
1015
1016 xor al,al ;Ignore
1017
1018 iret
1019
1020 BREAK <Resident Code: SPCOMINT>
1021
1022 ;---------------------------------------
1023 ;--- Communications interrupt ---
1024 ;---------------------------------------
1025
1026 SPCOMINT proc far
1027
1028 ASSUME DS:nothing,ES:nothing,SS:nothing
1029
1030 cmp ah,1
1031 jbe mine
1032 jmp [COMNEXT]
1033
1034MINE:
1035
1036 cmp al,0F8h
1037 jae RESERVED_RET
1038 cmp ax,0080h
1039 jnz CheckPSP
1040 jmp FakeINT1C
1041
1042CheckPSP:
1043
1044 or ah,ah
1045 jne PSPDO
1046 mov al,1 ; Tell PSPRINT to go away (AH = 1)
1047
1048RESERVED_RET:
1049
1050 iret
1051
1052PSPDO:
1053
1054 or al,al
1055 jne PSPDISP
1056
1057INST_REQ:
1058
1059 mov al,0FFh
1060
1061 iret
1062
1063PSPDISP:
1064
1065 cmp [BUSY],0
1066 jz SETCBUSY
1067
1068ErrBusy:
1069
1070 mov ax,error_busy
1071
1072setcret:
1073
1074 push bp
1075 mov bp,sp
1076 or word ptr [bp+6],f_Carry
1077 pop bp
1078
1079 iret
1080
1081SETCBUSY:
1082
1083 XOR AH,AH
1084 CMP AX,6 ; check function within valid range
1085 Jbe GoForIt
1086 mov ax,error_invalid_function
1087 jmp setcret
1088
1089GoForIt:
1090
1091 inc [BUSY] ;Exclude
1092 sti ;Turn ints back on
1093 push di ;G
1094 push es
1095 push ds
1096 push cs
1097 pop ds
1098
1099 ASSUME DS:CodeR
1100
1101 mov [QueueLock],0 ; unlock the print queue
1102 shl ax,1 ;Turn into word index
1103 mov di,ax
1104 call ComDisp[DI]
1105
1106 ASSUME DS:nothing
1107
1108; $if nc ; if no error ;AC000;
1109 JC $$IF37
1110
1111 ASSUME DS:CodeR,ES:nothing
1112
1113 push ds
1114 push cs
1115 pop ds
1116
1117 ASSUME DS:CodeR,ES:nothing
1118
1119 call PSTAT ; Tweek error counter
1120 pop ds
1121
1122 ASSUME DS:nothing
1123
1124; $endif ; ;AC000;
1125$$IF37:
1126
1127 pushf
1128 call Context_Back
1129 popf ; ;AC000;
1130 cli
1131 dec BUSY ; leaves carry alone!
1132 pop ds
1133
1134 ASSUME DS:nothing
1135
1136 pop es
1137 pop di ;G
1138 jc setcret
1139 push bp
1140 mov bp,sp
1141 and word ptr [bp+6],NOT f_Carry
1142 pop bp
1143
1144 iret
1145
1146SpComInt Endp
1147
1148 BREAK <Get queue status>
1149
1150 ;---------------------------------------
1151 ;--- Return pointer to file queue ---
1152 ;---------------------------------------
1153
1154QSTAT:
1155
1156 ASSUME DS:CodeR,ES:nothing
1157
1158 mov [QueueLock],1 ; lock the print queue
1159 call PSTAT ; Tweek error counter
1160 push bp
1161 mov bp,sp ; 0 2 4
1162 mov [bp+ 2 + 2],cs ; <BP> <RET> <DS>
1163 pop bp
1164 mov si,OFFSET CodeR:FileQueue
1165 mov dx,[ErrCnt] ; return error count
1166 clc
1167
1168 ret
1169 ;---------------------------------------
1170 ;--- Return pointer to device ---
1171 ; --- driver if active ---
1172 ;---------------------------------------
1173QSTATDEV:
1174
1175 ASSUME DS:CodeR,ES:nothing
1176
1177 xor ax,ax ;g assume not busy
1178 mov [QueueLock],1 ;g lock the print queue
1179 call PSTAT ;g Tweek error counter
1180 cmp byte ptr FileQueue,0 ;g is there anything in the queue?
1181 clc ;g
1182 jz qstatdev_end ;g no - just exit
1183 mov ax,error_queue_full ;g yes - set error queue full
1184 mov si,word ptr [listdev+2] ;g get segment of list device
1185 push bp ;g
1186 mov bp,sp ;g 0 2 4
1187 mov [bp+2+2],si ;g <BP><RET><DS> seg of device to DS
1188 pop bp ;g
1189 mov si,word ptr [listdev] ;g offset of device to SI
1190 stc ;g
1191
1192qstatdev_end: ;g
1193
1194 mov [QueueLock],0 ;g unlock the print queue
1195 ret ;g
1196
1197 BREAK <Resident Code: EndStat>
1198
1199 ;---------------------------------------
1200 ;--- Unlock the print queue ---
1201 ;---------------------------------------
1202
1203EndStat:
1204
1205 ASSUME DS:CodeR,ES:nothing
1206
1207 mov [QueueLock],0
1208 clc
1209
1210 ret
1211
1212 BREAK <Cancel all available files in the queue>
1213
1214 ;---------------------------------------
1215 ; Note: Loop until the background is free
1216 ;---------------------------------------
1217
1218CanAll:
1219
1220 ASSUME DS:CodeR,ES:nothing
1221
1222 cmp [CurrFil],0 ; are we currently printing?
1223
1224; $if nz ;
1225 JZ $$IF39
1226
1227 ;---------------------------------------
1228 ;--- Cancel active file
1229 ;---------------------------------------
1230
1231 mov bx,[CurrHand] ; close the current file
1232 call Set24
1233 mov [PAbort],1 ; no Int24's
1234 call CloseFile ; close the file ;AC000;
1235 call Res24
1236 mov [CurrFil],0 ; no files to print
1237 mov [CurrHand],-1 ; invalidate handle
1238 mov ax,[EndPtr] ; buffer empty
1239 mov [NxtChr],ax
1240
1241 ;---------------------------------------
1242 ;--- Cancel rest of files
1243 ;---------------------------------------
1244
1245 mov si,OFFSET CodeR:FileQueue
1246 mov [QueueTail],si ; next free entry is the first
1247 mov byte ptr [si],0 ; nul first byte of firts entry
1248 mov si,AllCan_PTR ; ;AC000;
1249 call ListMes ; print cancelation message
1250 mov si,OFFSET CodeR:BelMes
1251 call ListMes ; ring!!
1252
1253 ;---------------------------------------
1254 ;--- Send close on output device
1255 ;---------------------------------------
1256
1257 call Close_Dev
1258 clc
1259
1260; $endif ; ;AC000;
1261$$IF39:
1262
1263 ret
1264
1265 BREAK <Cancel a file in progress>
1266
1267CANFIL:
1268
1269 ASSUME DS:CodeR,ES:nothing
1270
1271 cmp [CURRFIL],0
1272 jnz DOCAN
1273
1274 ret ; carry is clear
1275
1276DOCAN:
1277 ;---------------------------------------
1278 ;--- find which file to cancel
1279 ;---------------------------------------
1280 push bp
1281 mov bp,sp ; 0 2 4
1282 mov ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
1283 pop bp
1284
1285 ASSUME DS:nothing
1286
1287 push cs
1288 pop es
1289
1290 ASSUME ES:CodeR
1291
1292 mov [CanFlg],0 ; reset message flag
1293 mov [ACanOcrd],0 ; no cancelation has ocured yet
1294 mov bx,OFFSET CodeR:FileQueue ; ES:BX points to 1st entry in queue
1295 call AmbChk
1296
1297AnotherTry:
1298
1299 mov di,bx ; ES:DI points to 1st entry in queue
1300 mov si,dx ; DS:SI points to filename to cancel
1301
1302MatchLoop:
1303
1304 lodsb
1305 cmp al,byte ptr es:[di] ; names in queue are all in upper case
1306 je CharMatch
1307 jmp AnotherName ; a mismatch, try another name
1308
1309CharMatch:
1310
1311 cmp es:byte ptr es:[di],0 ; was this the terminating nul?
1312 je NameFound ; yes we got our file...
1313 inc di
1314 jmp MatchLoop
1315
1316AnotherName:
1317
1318 cmp [AmbCan],1 ; ambigous file name specified?
1319 jne AnName ; if not then no more work to do
1320 cmp al,"?"
1321 jne AnName
1322 cmp byte ptr es:[di],"."
1323 je FindPeriod
1324 cmp byte ptr es:[di],0 ; if nul then file names match
1325 jne CharMatch ; only if only ?'s are left...
1326
1327FindNul:
1328
1329 lodsb
1330 cmp al,"?"
1331 je FindNul
1332 cmp al,"."
1333 je FindNul
1334 or al,al
1335 jne AnName ; found something else, no match
1336 jmp short NameFound
1337
1338FindPeriod: ; ambigous files always have 8 chars
1339
1340 lodsb ; in name so we can not look for the
1341 or al,al ; period twice (smart uh?)
1342 je AnName ; no period found, files do not match
1343 cmp al,"."
1344 jne FindPeriod
1345 jmp short CharMatch
1346
1347AnName:
1348
1349 add bx,MaxFileLen
1350 cmp byte ptr es:[bx],0 ; end of queue?
1351 jne AnotherTry ; no, continue...
1352 cmp [ACanOcrd],1 ; yes, was there a file found?
1353 jne sk2
1354 push cs
1355 pop ds
1356
1357 ASSUME DS:CodeR ; StartAnFil likes it this way...
1358
1359 jmp StartAnFil ; restart printing
1360
1361sk2:
1362
1363 ASSUME DS:nothing
1364
1365 mov ax,error_file_not_found
1366 stc
1367
1368 ret
1369 ;---------------------------------------
1370 ;--- Name found, check if current file
1371 ;---------------------------------------
1372NameFound:
1373
1374 push cs
1375 pop ds
1376
1377 ASSUME DS:CodeR
1378
1379 mov [ACanOcrd],1 ; remember we found a file
1380 cmp bx,OFFSET CodeR:FileQueue ; is the file being printed?
1381
1382; $if e,and ; if it is and .................. ;AC000;
1383 JNE $$IF41
1384
1385 cmp [CanFlg],0 ; :
1386
1387; $if e ; if not in cancel mode ........: ;AC000;
1388 JNE $$IF41
1389
1390 ;---------------------------------------
1391 ;--- Cancel current file
1392 ;---------------------------------------
1393
1394 mov [CanFlg],1 ; remeber we already canceled current
1395 push bx
1396 mov bx,[CurrHand] ; close the current file
1397 call Set24
1398 mov [PAbort],1 ; no Int24's
1399 call CloseFile ; close the file ;AC000;
1400 call Res24
1401 mov [CurrFil],0 ; no files to print
1402 mov [CurrHand],-1 ; invalidate handle
1403 mov ax,[EndPtr] ; buffer empty
1404 mov [NxtChr],ax
1405 pop bx
1406 ;---------------------------------------
1407 ;--- print cancelation message
1408 ;---------------------------------------
1409 push bx
1410 mov si,CanMes_PTR ; ;AC000;
1411 call ListMes ; print cancelation message
1412 mov si,bx ; points to filename
1413 call ListMes2 ; print filename
1414 mov si,CanFilNam_PTR ; ;AC000;
1415 call ListMes
1416 mov si,OFFSET CodeR:BelMes
1417 call ListMes ; ring!!
1418 pop bx
1419 ;---------------------------------------
1420 ;--- Send close on output device
1421 ;---------------------------------------
1422 call Close_Dev
1423
1424; $endif ; ;AC000;
1425$$IF41:
1426
1427 mov di,bx ; DI points to entry to cancel
1428 mov si,bx
1429 add si,MaxFileLen ; SI points to next entry
1430 cmp si,[QueueTail] ; is the entry being canceled the last?
1431
1432; $if e ; if it is ;AC000;
1433 JNE $$IF43
1434
1435 mov byte ptr [di],0 ; yes, just nul the first byte
1436
1437; $else ; ;AC000;
1438 JMP SHORT $$EN43
1439$$IF43:
1440
1441 mov cx,[EndQueue] ; CX points to the end of the queue
1442 sub cx,si ; length of the remainning of the queue
1443 cld
1444 rep movsb ; compact the queue
1445
1446; $endif ; ;AC000;
1447$$EN43:
1448
1449 mov ax,[QueueTail] ; remember new end of queue
1450 sub ax,MaxFileLen
1451 mov [QueueTail],ax
1452 mov si,ax
1453 mov byte ptr [si],0 ; nul first byte of last entry
1454
1455 cmp byte ptr [bx],0 ; is there another file to consider?
1456 je StartAnFil
1457 push bp
1458 mov bp,sp ; 0 2 4
1459 mov ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
1460 pop bp
1461
1462 ASSUME DS:nothing
1463
1464 jmp AnotherTry ; yes do it again...
1465
1466 ;---------------------------------------
1467 ;--- Start new file...
1468 ;---------------------------------------
1469StartAnFil:
1470
1471 ASSUME DS:CodeR
1472
1473 cmp [CurrHand],-1 ; was the canceled name the current?
1474 jne NoneLeft ; no, just quit
1475
1476StartAnFil2:
1477
1478 mov si,OFFSET CodeR:FileQueue ; points to new current file
1479 cmp byte ptr[si],0 ; is there one there?
1480 je NoneLeft ; no, we canceled current and are none left
1481 call Set24
1482 mov [PAbort],0
1483 mov dx,si
1484 call OpenFile ; try to open the file ;AC000;
1485 pushf
1486 call Res24
1487 cmp [PAbort],0
1488 je NoI24b
1489 popf ; ;AC000;
1490 call CompQ ; compact file queue
1491 jmp short StartAnFil2
1492
1493NoI24b:
1494
1495 popf ; ;AC000;
1496 jnc GoodNewCurr
1497 call PrtOpErr ; print open error
1498 call CompQ ; compact file queue
1499 jmp short StartAnFil2
1500
1501GoodNewCurr:
1502
1503 mov [CurrHand],ax ; save handle
1504 mov [CurrFil],1 ; signal active (buffer is already empty)
1505
1506 ;---------------------------------------
1507 ;--- Send Open on output device
1508 ;---------------------------------------
1509 call Open_Dev
1510
1511NoneLeft:
1512
1513 clc
1514
1515 ret
1516 ;---------------------------------------
1517 ;--- Ambigous file name check ---
1518 ; entry: ds:dx points to filename
1519 ; preserves ds:dx and es
1520 ;---------------------------------------
1521 ASSUME DS:nothing,ES:CodeR
1522
1523AmbChk:
1524
1525 mov [AmbCan],0 ; assume not ambigous
1526 mov si,dx
1527 cld
1528
1529; $do ; ;AC000;
1530$$DO46:
1531
1532 lodsb
1533 or al,al ; the nul?
1534
1535; $enddo e ; ;AC000;
1536 JNE $$DO46
1537
1538 dec si ; points to nul
1539 std ; scan backwards
1540
1541; $do ; ;AC000;
1542$$DO48:
1543
1544 lodsb
1545 cmp al,"*"
1546
1547; $if e ; if a * ;AC000;
1548 JNE $$IF49
1549
1550 mov [AmbCan],1
1551
1552; $endif ; ;AC000;
1553$$IF49:
1554
1555 cmp al,"?"
1556
1557; $if e ; if a ? ;AC000;
1558 JNE $$IF51
1559
1560 mov [AmbCan],1
1561
1562; $endif ; ;AC000;
1563$$IF51:
1564
1565 cmp al,[PChar]
1566
1567; $enddo e ; ;AC000;
1568 JNE $$DO48
1569
1570 cld ; be safe
1571 cmp [AmbCan],1 ; an ambigous cancel?
1572
1573; $if e ; if its an ambiguous cancel ;AC000;
1574 JNE $$IF54
1575
1576 ;---------------------------------------
1577 ;--- transform * to ?'s
1578 ;---------------------------------------
1579 inc si
1580 inc si ; points to actual name (past path char)
1581 mov di,OFFSET CodeR:ACBuf
1582 push di
1583 mov cx,12
1584 mov al,20h
1585 cld
1586 rep stosb ; fill fcb with blanks
1587 pop di
1588 push si
1589 mov ax,(Parse_file_descriptor shl 8) and 0FF00h
1590 call My21
1591 pop si
1592
1593 ;---------------------------------------
1594 ;--- Copy name to expanded name
1595 ;---------------------------------------
1596
1597 push ds
1598 pop es
1599
1600 ASSUME DS:nothing
1601
1602 push cs
1603 pop ds
1604
1605 ASSUME DS:CodeR
1606
1607 push es
1608 mov di,si
1609 mov si,OFFSET CodeR:ACName
1610 mov cx,8
1611
1612; $do ; ;AC000;
1613$$DO55:
1614
1615 lodsb ; move name
1616 cmp al,20h
1617
1618; $leave e ; ;AC000;
1619 JE $$EN55
1620
1621 stosb
1622
1623; $enddo loop ; ;AC000;
1624 LOOP $$DO55
1625$$EN55:
1626
1627 mov si,OFFSET CodeR:ACExt
1628 cmp byte ptr [si],20h ; extension starts with blank ?
1629
1630; $if ne ; if it does not ;AC000;
1631 JE $$IF58
1632
1633 mov al,"."
1634 stosb
1635 mov cx,3
1636
1637; $do ; ;AC000;
1638$$DO59:
1639
1640 lodsb ; move name
1641 cmp al,20h
1642
1643; $leave e ; ;AC000;
1644 JE $$EN59
1645
1646 stosb
1647
1648; $enddo loop ; ;AC000;
1649 LOOP $$DO59
1650$$EN59:
1651
1652; $endif ; ;AC000;
1653$$IF58:
1654
1655 mov byte ptr es:[di],0 ; nul terminate
1656 pop ds
1657
1658 ASSUME DS:nothing
1659
1660 push cs
1661 pop es
1662
1663; $endif ; ;AC000;
1664$$IF54:
1665
1666 ASSUME ES:CodeR
1667
1668 ret
1669
1670 BREAK <Add a file to the queue>
1671
1672ADDFIL:
1673
1674 ASSUME DS:CodeR,ES:nothing
1675
1676 ;---------------------------------------
1677 ;--- Check that queue is not full
1678 ;---------------------------------------
1679
1680 mov di,[QueueTail] ; load pointer to next empty entry
1681 cmp di,[EndQueue] ; queue full?
1682 jb OkToQueue ; no, place in queue...
1683 mov ax,error_queue_full
1684 stc
1685
1686 ret
1687 ;---------------------------------------
1688 ;--- Copy name to empty slot in queue
1689 ;---------------------------------------
1690OkToQueue:
1691
1692 ;
1693 ; Retrieve old DS
1694 ;
1695 push bp
1696 mov bp,sp ; 0 2 4
1697 mov ds,[bp+ 2 + 2] ; <BP> <RET> <DS>
1698 pop bp
1699
1700 ASSUME DS:nothing
1701
1702 push cs
1703 pop es ; ES:DI points to empty slot
1704
1705 ASSUME ES:CodeR
1706
1707 mov si,dx ; DS:SI points to submit packet
1708 cmp byte ptr ds:[si],0
1709 jnz IncorrectLevel
1710 lds si,dword ptr ds:[si+1] ; DS:SI points to filename
1711 mov cx,MaxFileLen ; maximum length of file name
1712
1713CopyLop:
1714
1715 lodsb
1716 stosb
1717 or al,al ; nul?
1718 je CopyDone ; yes, done with move...
1719 loop CopyLop
1720 push cs
1721 pop ds
1722
1723 ASSUME DS:CodeR
1724
1725 mov ax,error_name_too_long ; if normal exit from the loop then
1726 stc
1727
1728 ret
1729
1730IncorrectLevel:
1731
1732 mov ax,error_invalid_function
1733 stc
1734
1735 ret
1736
1737 ASSUME DS:nothing,ES:nothing ; es:nothing = not true but lets
1738
1739CopyDone: ; avoid possible problems...
1740
1741 push cs
1742 pop ds
1743
1744 ASSUME DS:CodeR
1745
1746 ;---------------------------------------
1747 ;--- advance queue pointer
1748 ;---------------------------------------
1749
1750 mov si,[QueueTail] ; pointer to slot just used
1751 push si ; save for test open later
1752 add si,MaxFileLen
1753 mov [QueueTail],si ; store for next round
1754 mov byte ptr [si],0 ; nul next entry (maybe the EndQueue)
1755
1756 ;---------------------------------------
1757 ;--- Check that file exists
1758 ;---------------------------------------
1759
1760 call Set24
1761 mov [PAbort],0
1762 pop dx ; get pointer to filename
1763 call OpenFile ; ;AC000;
1764 pushf
1765 push dx
1766 call Res24
1767 pop dx
1768;;;popff ;; dcl removed for p1020 ;AC000;
1769 popf ;; dcl to fix p1020
1770 jnc GOTFIL
1771 ;---------------------------------------
1772 ; See if brain damaged user entered
1773 ; an invalid drive
1774 ;---------------------------------------
1775 push ax
1776 mov si,dx
1777 cmp BYTE PTR CS:[SI+1],':'
1778 jz GotDrive
1779 pop ax
1780 jmp SHORT i24bf
1781
1782GotDrive:
1783
1784 mov ah,Get_default_drive ; get current
1785 call My21
1786 push ax
1787 mov dl,CS:[SI] ; get drive letter to test
1788 or dl,20h
1789 sub dl,'a'
1790 mov ah,Set_Default_Drive ; set it
1791 call My21
1792 mov ah,Get_default_drive ; get it back
1793 call My21
1794 cmp al,dl ; same? ;; dcl change al,al to al,dl
1795 jnz BadDrive ; no, bad drive
1796 pop dx ; get original back
1797 mov ah,Set_Default_Drive ; set original
1798 call My21
1799 pop ax
1800 mov dx,si
1801 jmp SHORT i24bf
1802
1803BadDrive:
1804
1805 pop dx ; get original back
1806 mov ah,Set_Default_Drive ; set original
1807 call My21
1808 pop ax
1809 mov ax,error_invalid_drive
1810 mov dx,si
1811
1812I24BF:
1813
1814 mov si,[QueueTail] ; take bad name out of queue
1815 sub si,MaxFileLen ; SI points to the slot with bad name
1816 mov [QueueTail],si
1817 mov byte ptr [si],0 ; nul the first byte
1818 stc
1819
1820 ret
1821
1822
1823 ;---------------------------------------
1824 ;--- Check if print currently busy
1825 ;---------------------------------------
1826
1827GotFil:
1828
1829 cmp [CURRFIL],0 ; currently printing?
1830
1831; $if nz ; if currently printing ;AC000;
1832 JZ $$IF64
1833
1834 mov bx,ax ; busy, close handle
1835 call Set24
1836 mov [PAbort],1 ; no Int24's
1837 call CloseFile ; close the file ;AC000;
1838 call Res24
1839
1840; $else ; ;AC000;
1841 JMP SHORT $$EN64
1842$$IF64:
1843 ;---------------------------------------
1844 ;--- Save file data
1845 ;---------------------------------------
1846
1847 mov [CURRHAND],ax ; Valid handle
1848 mov ax,[ENDPTR]
1849 mov [NXTCHR],ax ; Buffer empty
1850 mov [CURRFIL],1
1851 ;---------------------------------------
1852 ;--- Send Open on output device
1853 ;---------------------------------------
1854 call Open_Dev
1855
1856; $endif ; ;AC000;
1857$$EN64:
1858
1859 clc
1860
1861 ret
1862
1863 BREAK <Fake int 21H>
1864
1865 ;---------------------------------------
1866 ; perform a system call as myself
1867 ;---------------------------------------
1868
1869My21:
1870
1871 call Context_switch
1872 call Do_21
1873
1874 ret
1875
1876 Public do_21
1877
1878DO_21:
1879
1880 ASSUME DS:nothing,ES:nothing
1881
1882 CMP BYTE PTR CS:[INT15FLAG],0
1883
1884; $if nz ; if for PRINT ;AC000;
1885 JZ $$IF67
1886
1887 push ds
1888 push bx
1889 lds bx,cs:[INT15PTR]
1890 inc BYTE PTR [bx]
1891 pop bx
1892 pop ds
1893 call OffSave
1894 int 21h
1895 call OnSave
1896 push ds
1897 push bx
1898 pushf ; Flags from system call
1899 lds bx,CS:[INT15PTR]
1900 dec BYTE PTR [BX]
1901 popf ;
1902 pop bx ;AC000;
1903 pop ds
1904
1905; $else ; ;AC000;
1906 JMP SHORT $$EN67
1907$$IF67:
1908
1909 call OffSave
1910 int 21h
1911 call OnSave
1912
1913; $endif ; ;AC000;
1914$$EN67:
1915
1916 ret
1917
1918OffSave:
1919
1920 ASSUME DS:nothing,ES:nothing,SS:nothing
1921
1922 push ax
1923 push dx
1924 mov ax,Set_CTRL_C_Trapping SHL 8 + 2
1925 xor dl,dl
1926 int 21h
1927 mov CtrlC,dl
1928 pop dx
1929 pop ax
1930
1931 ret
1932
1933OnSave:
1934
1935 ASSUME DS:nothing,ES:nothing,SS:nothing
1936
1937 push ax
1938 push dx
1939 mov ax,Set_CTRL_C_Trapping SHL 8 + 2
1940 mov dl,CtrlC
1941 int 21h
1942 pop dx
1943 pop ax
1944
1945 ret
1946
1947 BREAK <Priter Support>
1948
1949ListMes2:
1950
1951 ASSUME DS:CodeR,ES:nothing
1952
1953 lodsb
1954 cmp al,0
1955 jz LMesDone
1956 call LOUT
1957 jmp SHORT LISTMES2
1958
1959
1960LISTMES:
1961
1962 ASSUME DS:CodeR,ES:nothing
1963
1964 lodsb
1965 cmp al,"$"
1966 jz LMESDONE
1967 call LOUT
1968 jmp SHORT LISTMES
1969
1970LMESDONE:
1971
1972 ret
1973
1974LOUT:
1975
1976 push bx
1977
1978LWAIT:
1979
1980 call PSTAT
1981 jz PREADY
1982 cmp [ERRCNT],ERRCNT2
1983 ja POPRET ;Don't get stuck
1984 jmp SHORT LWAIT
1985
1986PREADY:
1987
1988 call POUT
1989
1990POPRET:
1991
1992 pop bx
1993
1994 ret
1995
1996
1997 BREAK <TO_DOS>
1998;******************* START OF SPECIFICATIONS ***********************************
1999;
2000; NAME: TO_DOS
2001;
2002; FUNCTION: Make a SERVER DOS call
2003;
2004; INPUT:
2005;
2006; OUTPUT:
2007;
2008; NOTE:
2009;
2010; REGISTERS USED: T.B.D.
2011; (NOT RESTORED)
2012;
2013; LINKAGE:
2014;
2015; NORMAL
2016; EXIT:
2017;
2018; ERROR
2019; EXIT:
2020;
2021; CHANGE 12/16/87 - Add SERVER DOS call - F. G
2022; LOG:
2023;
2024;******************* END OF SPECIFICATIONS *************************************
2025;******************** START - PSEUDOCODE ***************************************
2026;
2027; START TO_DOS
2028;
2029; ret
2030;
2031; END TO_DOS
2032;
2033;******************** END - PSEUDOCODE ***************************************
2034
2035 TO_DOS PROC FAR
2036
2037 ASSUME DS:NOTHING,ES:NOTHING
2038
2039; Call the dos via server dos call using a DPL. The currentPDB *must* be
2040; properly set before this call!
2041; INPUT: Regs set for INT 21
2042; OUTPUT: Of INT 21
2043
2044
2045
2046 MOV [PRTDPL.DPL_DS],DS ; ;AN010;
2047 PUSH CS ; ;AN010;
2048 POP DS ; ;AN010;
2049
2050 MOV [PRTDPL.DPL_BX],BX ; ;AN010;
2051 MOV BL,AL ; set up DRIVE ID ;AN010;
2052 SUB BL,40h ; convert to number ;AN010;
2053 XOR AL,AL ; remove file ID ;AN010;
2054 MOV [PRTDPL.DPL_AX],AX ; ;AN010;
2055 MOV [PRTDPL.DPL_CX],CX ; ;AN010;
2056 MOV [PRTDPL.DPL_DX],DX ; ;AN010;
2057 MOV [PRTDPL.DPL_SI],SI ; ;AN010;
2058 MOV [PRTDPL.DPL_DI],DI ; ;AN010;
2059 MOV [PRTDPL.DPL_ES],ES ; ;AN010;
2060 XOR AX,AX ; ;AN010;
2061 MOV [PRTDPL.DPL_reserved],AX ; ;AN010;
2062 MOV [PRTDPL.DPL_UID],AX ; ;AN010;
2063 MOV AX,CS ; ;AN010;
2064 SUB AX,10h ; ;AN010;
2065 MOV [PRTDPL.DPL_PID],AX ; ;AN010; ; ;AN010;
2066 ; IOCtl call to see if target drive is local
2067 ; x = IOCTL (getdrive, Drive+1) ;AN010;
2068 mov ax,(IOCTL SHL 8) + 9 ; ;AN010;
2069 INT 21h ; IOCtl + dev_local <4409> ;AN010;
2070
2071 MOV BX,[PRTDPL.DPL_BX] ; restore register ;AN010;
2072
2073; $if nc,and ; target drive local and ;AN010;
2074 JC $$IF70
2075
2076 test dx,1200H ; check if (x & 0x1000) ;AN010;
2077 ; (redirected or shared)
2078; $if z ; if RC indicates NOT a network drive ;AN010;
2079 JNZ $$IF70
2080
2081 MOV DX,OFFSET CODER:PRTDPL ; ;AN010;
2082 MOV AX,(ServerCall SHL 8) ; make a SERVER DOS call ;AN010;
2083
2084; $else ; ;AN010;
2085 JMP SHORT $$EN70
2086$$IF70:
2087
2088 MOV DX,[PRTDPL.DPL_DX] ; fix up reg ;AN010;
2089 MOV AX,[PRTDPL.DPL_AX] ; make a normal DOS call ;AN010;
2090 PUSH [PRTDPL.DPL_DS] ; fix up segment reg ;AN010;
2091 POP DS ; ;AN010;
2092
2093; $endif ; ;AN010;
2094$$EN70:
2095
2096 CALL My21 ; ;AN010;
2097
2098 RET ; ;AN010;
2099
2100 TO_DOS ENDP
2101
2102 BREAK <Open_Device>
2103 ;---------------------------------------
2104 ; Stuff for BIOS interface
2105 ;---------------------------------------
2106
2107; $SALUT (4,25,30,41)
2108
2109IOBUSY EQU 0200H
2110IOERROR EQU 8000H
2111
2112BYTEBUF DB ?
2113
2114CALLAD DD ?
2115
2116IOCALL DB 22
2117 DB 0
2118IOREQ DB ?
2119IOSTAT DW 0
2120 DB 8 DUP(?)
2121 DB 0
2122 DW OFFSET CodeR:BYTEBUF
2123INTSEG DW ?
2124IOCNT DW 1
2125 DW 0
2126
2127; $SALUT (4,4,9,41)
2128
2129 ;---------------------------------------
2130 ; Following two routines perform device
2131 ; open and close on output device.
2132 ; NO REGISTERS (including flags) are
2133 ; Revised. No errors generated.
2134 ;---------------------------------------
2135
2136 public open_dev
2137
2138Open_Dev:
2139
2140 ASSUME DS:nothing,ES:nothing
2141
2142 ;---------------------------------------
2143 ; We are now going to use the printer...
2144 ; We must lock down the printer so that
2145 ; the network does not intersperse output
2146 ; on us...
2147 ; We must also signal the REDIRector for
2148 ; stream open. We must ask DOS to set
2149 ; the Printer Flag to busy
2150 ;---------------------------------------
2151
2152 push bx
2153 pushf
2154 push ax
2155 push dx
2156 mov dx,PrinterNum
2157 cmp dx,-1
2158
2159; $if nz ; ;AC000;
2160 JZ $$IF73
2161
2162 mov ax,0203h ; redirector lock
2163 int 2Fh
2164 mov ax,0201H ; Redirector OPEN
2165 int 2Fh
2166
2167; $endif ;
2168$$IF73:
2169
2170 mov ax,(SET_PRINTER_FLAG SHL 8) + 01
2171 int 21h
2172 pop dx
2173 pop ax
2174 mov bl,DEVOPN ; Device OPEN
2175 call OP_CL_OP
2176 popf ; ;AC000;
2177 pop bx
2178
2179 ret
2180
2181OP_CL_OP:
2182
2183 push ds
2184 push si
2185 lds si,[LISTDEV]
2186
2187 ASSUME DS:nothing
2188
2189 test [SI.SDEVATT],DEVOPCL
2190
2191; $if nz ; ;AC000;
2192 JZ $$IF75
2193
2194 push cs
2195 pop ds
2196
2197 ASSUME DS:CodeR
2198
2199 mov [IOCALL],DOPCLHL
2200 call DOCALL
2201
2202; $endif ; ;AC000;
2203$$IF75:
2204
2205 pop si
2206 pop ds
2207
2208 ASSUME DS:nothing
2209
2210 ret
2211
2212 public close_dev
2213
2214Close_Dev:
2215
2216 ASSUME DS:nothing,ES:nothing
2217
2218 ;---------------------------------------
2219 ; At this point, we release the ownership
2220 ; of the printer... and do a redirector
2221 ; CLOSE.
2222 ; Also tell DOS to reset the Printer Flag
2223 ;---------------------------------------
2224
2225 push bx
2226 pushf
2227 mov bl,DEVCLS
2228 call OP_CL_OP ; Device CLOSE
2229 push ax
2230 push dx
2231 mov dx,PrinterNum
2232 cmp dx,-1
2233
2234; $if nz ; ;AC000;
2235 JZ $$IF77
2236
2237 mov ax,0202h ; redirector CLOSE
2238 int 2Fh
2239 mov ax,0204h ; redirector clear
2240 int 2Fh
2241
2242; $endif ; ;AC000;
2243$$IF77:
2244
2245 mov ax,(SET_PRINTER_FLAG SHL 8) +00
2246 int 21h
2247 pop dx
2248 pop ax
2249 popf ; ;AC000;
2250 pop bx
2251
2252 ret
2253
2254PSTAT:
2255
2256 ASSUME DS:CodeR
2257
2258 push bx
2259 inc [ERRCNT]
2260 mov BL,DEVOST
2261 mov [IOCALL],DSTATHL
2262 call DOCALL
2263 test [IOSTAT],IOERROR
2264
2265; $if nz ; ;AC000;
2266 JZ $$IF79
2267
2268 or [IOSTAT],IOBUSY ;If error, show buisy
2269
2270; $endif ; ;AC000;
2271$$IF79:
2272
2273 test [IOSTAT],IOBUSY
2274
2275; $if z ; if ;AC000;
2276 JNZ $$IF81
2277
2278 mov [ERRCNT],0
2279
2280; $endif ; ;AC000;
2281$$IF81:
2282
2283 pop bx
2284
2285 ret
2286
2287POUT:
2288
2289 ASSUME DS:CodeR
2290
2291 mov [BYTEBUF],al
2292 mov bx,DEVWRT
2293 mov [IOCALL],DRDWRHL
2294
2295DOCALL:
2296
2297 push es
2298 mov [IOREQ],bl
2299 mov bx,cs
2300 mov es,bx
2301 mov [IOSTAT],0
2302 mov [IOCNT],1
2303 push ds
2304 push si
2305 push ax
2306 call Context_Switch
2307 mov bx,OFFSET CodeR:IOCALL
2308 lds si,[LISTDEV]
2309
2310 ASSUME DS:nothing
2311
2312 mov ax,[SI+SDEVSTRAT]
2313 mov WORD PTR [CALLAD],ax
2314 call [CALLAD]
2315 mov AX,[SI+SDEVINT]
2316 mov WORD PTR [CALLAD],ax
2317 call [CALLAD]
2318 pop ax
2319 pop si
2320 pop ds
2321
2322 ASSUME DS:CodeR
2323
2324 pop es
2325
2326 ret
2327
2328; $SALUT (4,25,30,41)
2329
2330REAL_INT_13 DD ?
2331
2332INT_13_RETADDR DW OFFSET CodeR:INT_13_BACK
2333
2334; $SALUT (4,4,9,41)
2335
2336 INT_13 PROC FAR
2337
2338 ASSUME DS:nothing,ES:nothing,SS:nothing
2339
2340 pushf
2341 inc [BUSY] ;Exclude if dumb program call ROM
2342 push cs
2343 push [INT_13_RETADDR]
2344 push WORD PTR [REAL_INT_13+2]
2345 push WORD PTR [REAL_INT_13]
2346
2347 ret
2348
2349 INT_13 ENDP
2350
2351 INT_13_BACK PROC FAR
2352
2353 pushf
2354 dec [BUSY]
2355 popf ; ;AC000;
2356
2357 ret 2 ;Chuck saved flags
2358
2359 INT_13_BACK ENDP
2360
2361; $SALUT (4,25,30,41)
2362
2363REAL_INT_15 DD ?
2364INT15FLAG DB 0 ; Init to off
2365INT15PTR DD ?
2366
2367; $SALUT (4,4,9,41)
2368
2369 INT_15 PROC FAR
2370
2371 ASSUME DS:nothing,ES:nothing,SS:nothing
2372
2373 cmp ah,20h
2374 jnz REAL_15 ; Not my function
2375 cmp AL,1
2376 ja REAL_15 ; I only know 0 and 1
2377 je FUNC1
2378 inc [INT15FLAG] ; Turn ON
2379 mov WORD PTR [INT15PTR],bx ; Save counter loc
2380 mov WORD PTR [INT15PTR+2],es
2381
2382 iret
2383
2384FUNC1:
2385
2386 mov [INT15FLAG],0 ; Turn OFF
2387
2388 iret
2389
2390REAL_15:
2391
2392 jmp [REAL_INT_15]
2393
2394 INT_15 ENDP
2395
2396; $SALUT (4,25,30,41)
2397
2398FLAG17_14 DB 0 ; Flags state of AUX/PRN redir
2399REAL_INT_5 DD ?
2400REAL_INT_17 DD ?
2401INT_17_NUM DW 0
2402
2403; $SALUT (4,4,9,41)
2404
2405INT_17:
2406
2407 ASSUME DS:nothing,ES:nothing,SS:nothing
2408
2409 cmp [FLAG17_14],1
2410 jnz DO_INT_17 ;The PRN device is not used
2411 cmp [CURRFIL],0
2412 jz DO_INT_17 ;Nothing pending, so OK
2413 cmp dx,[INT_17_NUM]
2414 jnz DO_INT_17 ;Not my unit
2415 cmp [BUSY],0
2416 jnz DO_INT_17 ;You are me
2417 sti
2418 mov ah,0A1h ;You are bad, get time out
2419
2420 iret
2421
2422DO_INT_17:
2423
2424 jmp [REAL_INT_17] ;Do a 17
2425
2426; $SALUT (4,25,30,41)
2427
2428REAL_INT_14 DD ?
2429INT_14_NUM DW 0
2430
2431; $SALUT (4,4,9,41)
2432
2433INT_14:
2434
2435 ASSUME DS:nothing,ES:nothing,SS:nothing
2436
2437 cmp [FLAG17_14],2
2438 jnz DO_INT_14 ;The AUX device is not used
2439 cmp [CURRFIL],0
2440 jz DO_INT_14 ;Nothing pending, so OK
2441 cmp DX,[INT_14_NUM]
2442 jnz DO_INT_14 ;Not my unit
2443 cmp [BUSY],0
2444 jnz DO_INT_14 ;You are me
2445 sti
2446 or ah,ah
2447 jz SET14_AX
2448 cmp ah,2
2449 jbe SET14_AH
2450
2451SET14_AX:
2452
2453 mov al,0
2454
2455SET14_AH:
2456
2457 mov ah,80h ;Time out
2458
2459 iret
2460
2461DO_INT_14:
2462
2463 jmp [REAL_INT_14] ;Do a 14
2464
2465INT_5:
2466
2467 ASSUME DS:nothing,ES:nothing,SS:nothing
2468
2469 cmp [FLAG17_14],1
2470 jnz DO_INT_5 ;The PRN device is not used
2471 cmp [CURRFIL],0
2472 jz DO_INT_5 ;Nothing pending, so OK
2473 cmp [INT_17_NUM],0
2474 jnz DO_INT_5 ;Only care about unit 0
2475
2476 iret ;Pretend it worked
2477
2478DO_INT_5:
2479
2480 jmp [REAL_INT_5] ;Do a 5
2481
2482; $SALUT (4,25,30,41)
2483
2484ERRCNT DW 0
2485
2486; $SALUT (4,4,9,41)
2487
2488 BREAK <Bootstrap Cleanup Code>
2489
2490ReBtINT:
2491
2492 ASSUME CS:CodeR,DS:nothing,ES:nothing,SS:nothing
2493
2494 cli
2495 push cs
2496 pop ds
2497
2498IntWhileBusy:
2499
2500 int ComInt
2501 jnc NotBusy
2502 jmp IntWhileBusy
2503
2504NotBusy:
2505
2506 inc [BUSY] ; Exclude hardware interrupts
2507 inc [SOFINT] ; Exclude software interrupts
2508
2509 call CanAll ; Purge the Queue
2510
2511 lds dx,CodeR:COMNEXT
2512 mov ax,(set_interrupt_vector shl 8) or comint
2513 int 21h ;Set int 2f vector
2514
2515 lds dx,CodeR:NEXTINT
2516 mov ax,(set_interrupt_vector shl 8) or intloc
2517 int 21h ;Set hardware interrupt
2518
2519 mov ax,(set_interrupt_vector shl 8) or 15h
2520 lds dx,CodeR:Real_Int_15 ; Reset the wait on event on ATs
2521 int 21h
2522
2523 mov ax,(set_interrupt_vector shl 8) or 17h
2524 lds dx,CodeR:Real_Int_17
2525 int 21h ;Set printer interrupt
2526
2527 mov ax,(set_interrupt_vector shl 8) or 5h
2528 lds dx,CodeR:Real_Int_5
2529 int 21h ;Set print screen interrupt
2530
2531 mov ax,(set_interrupt_vector shl 8) or 14h
2532 lds dx,CodeR:Real_Int_14
2533 int 21h ;Set printer interrupt
2534
2535 mov ax,(set_interrupt_vector shl 8) or 24h
2536 lds dx,CodeR:HERRINT
2537 int 21h ;Set printer interrupt
2538
2539 mov ax,(set_interrupt_vector shl 8) or reboot
2540 lds dx,CodeR:NEXT_REBOOT
2541 int 21h ;Set bootstrap interrupt
2542
2543 sti
2544 int 19h
2545
2546 BREAK <OpenFile>
2547;******************* START OF SPECIFICATIONS ***********************************
2548;
2549; NAME: OpenFile - PRINT Open a File for printing
2550;
2551; FUNCTION: This subroutine will mannage all environment changes required
2552; for Code Page switching support. This is accomplished as set
2553; out in the pseudocode below.
2554;
2555; INPUT: (DS:DX) = ASCIIZ of file to print
2556;
2557; OUTPUT: (AX) = handle of file
2558; No CPSW - File opened using INT 21 - 3D
2559; CPSW active - no CP on print file
2560; - Print file opened using INT 21 - 3D
2561; - valid CP on print file
2562; - PRINTER.SYS locked from CP change
2563; - Print file opened using INT 21 - 6C
2564; - Print file CP in CURRCP
2565; - Printer set to CURRCP
2566;
2567; NOTE: PRINT - PRINTER.SYS 2F Interface
2568;
2569; (AX) = AD40h - ADh is the function id
2570; - 40h is the sub-function id
2571; (BX) = n - change to this code page (binary value)
2572; and save current CP or any further
2573; change requested
2574; -1 - restore saved CP and unlock
2575; (DX) m - LPTm #
2576;
2577;
2578; REGISTERS USED: T.B.D.
2579; (NOT RESTORED)
2580;
2581; LINKAGE: Called by FILEOF, CANFIL and ADDFIL
2582;
2583; EXTERNAL Calls to: My21
2584; ROUTINES:
2585;
2586; NORMAL CF = 0
2587; EXIT:
2588;
2589; ERROR CF = 1
2590; EXIT:
2591;
2592; CHANGE 03/11/87 - First release - F. Gnuechtel
2593; LOG:
2594;
2595;******************* END OF SPECIFICATIONS *************************************
2596;******************** START - PSEUDOCODE ***************************************
2597;
2598; START OpenFile
2599;
2600; set up for INT 21 - 33 to see if CPSW is active
2601; call MY_21
2602; if CPSW is active and
2603; set up for INT 21 - 6C Extended Open
2604; call MY_21 to open file
2605; if no error and
2606; if valid CP
2607; if valid LPTx
2608; update CURRCP
2609; call INT 2F to lock and set PRINTER.SYS to CURRCP
2610; endif
2611; else
2612; set up for INT 21 - 3D Open
2613; call MY_21 to open file
2614; endif
2615; return
2616;
2617; END OpenFile
2618;
2619;******************** END - PSEUDOCODE ***************************************
2620
2621 OpenFile PROC NEAR
2622
2623nop
2624;int 3
2625nop
2626
2627 mov bx,dx ; save pointer for later ;AN000;
2628 mov ax,(Set_CTRL_C_Trapping shl 8) + get_CPSW ; set up for INT 21 - 33 ;AN000;
2629 ; to see if CPSW is active
2630 call My21 ; call MY_21 ;AN000;
2631 xchg dx,bx ; recover pointer ;AN000;
2632 cmp bl,CPSW_on ; is CPSW active ? ;AN000; ;AN000;
2633
2634; $if e ; if CPSW is active ;AC006;
2635 JNE $$IF83
2636
2637 mov ax,(ExtOpen shl 8) + 0 ; set for INT 21-6C ;AN000;
2638 xor cx,cx ; Extended Open ;AN000;
2639 mov bx,open_mode ; ;AN000;
2640 mov si,dx ; set DS:SI to name ;AC006;
2641 mov dx,(ignore_cp shl 8) + (failopen shl 4) + openit ; open if exists ;AC001;
2642 mov di,cx ; ;AC001;
2643 dec di ; ;AC001;
2644 mov al,ds:[si] ; recover drive - TO_DOS needs it
2645 call TO_DOS ; call TO_DOS to open file (SERVER DOS);AC010;
2646
2647; $if nc,and ; if no error and ;AN000;
2648 JC $$IF84
2649
2650 mov bx,ax ; ;AN001;
2651 mov ax,(File_Times SHL 8) + get_ea_by_handle ; now find out what CP ;AN001;
2652 mov cx,list_size ; ;AN001;
2653 lea si,query_list ; ;AN001;
2654 lea di,list ; ;AN001;
2655 call My21 ; to get the CP ;AN001;
2656
2657; $if nc,and ; if no error and ;AN000;
2658 JC $$IF84
2659
2660 mov ax,bx ; move HANDLE back to where its needed ;AN001;
2661
2662 mov bx,[code_page] ; is there a valid CP ? ;AC006;
2663
2664 cmp bx,0 ; is there a valid CP ? ;AC006;
2665
2666; $if g ; if valid CP ie: 0 < CP < -1 ;AN000;
2667 JNG $$IF84
2668
2669 cmp [PrinterNum],no_lptx ; is there a valid LPTx ? ;AN000; ;AN000;
2670
2671; $if ne ; if valid LPTx available ;AN000;
2672 JE $$IF85
2673
2674 mov cx,ax ; save file handle ;AN008;
2675 mov [CURRCP],bx ; update CURRCP ;AN000;
2676 mov dx,[PrinterNum] ; ;AN000;
2677 mov ax,(major_code shl 8) + minor_code ; semophore PRINTER.SYS ;AN000;
2678 int 2Fh ; call INT 2F to lock and set ;AN000;
2679 ; PRINTER.SYS to CURRCP
2680 mov ax,cx ; restore file handle ;AN008;
2681; $endif ; endif ;AN000;
2682$$IF85:
2683; $endif ; endif ;AN006;
2684$$IF84:
2685
2686; $else ; else ;AN000;
2687 JMP SHORT $$EN83
2688$$IF83:
2689
2690 mov si,dx
2691 mov al,ds:[si] ; recover drive - TO_DOS needs it
2692 mov ah,(open) ; set up for INT 21 - 3D Open ;AN000;
2693 mov cx,016h ; set up search attribute for Server ;AN011;
2694 ; DOS Open
2695 call TO_DOS ; call TO_DOS to open file (SERVER DOS);AC010;
2696
2697; $endif ; endif ;AN000;
2698$$EN83:
2699
2700 ret ; return ;AN000;
2701
2702 OpenFile ENDP
2703
2704 BREAK <CloseFile>
2705;******************* START OF SPECIFICATIONS ***********************************
2706;
2707; NAME: CloseFile - PRINT Close a File for printing
2708;
2709; FUNCTION: This subroutine will mannage all environment changes required
2710; for Code Page switching support. This is accomplished by:
2711;
2712; (see pseudocode)
2713;
2714; INPUT: (BX) = handle of file to close
2715; (DS) = CodeR
2716;
2717; OUTPUT: File closed
2718; CPSW active - PRINTER.SYS unlocked
2719; - CHECKCP is reset
2720;
2721; REGISTERS USED: T.B.D.
2722; (NOT RESTORED)
2723;
2724; LINKAGE: Called by FILEOF, CANALL, CANFIL and ADDFIL
2725;
2726; EXTERNAL Calls to: My21
2727; ROUTINES:
2728;
2729; NORMAL CF = 0
2730; EXIT:
2731;
2732; ERROR CF = 1
2733; EXIT:
2734;
2735; CHANGE 03/11/87 - First release - F. G
2736; LOG:
2737;
2738;******************* END OF SPECIFICATIONS *************************************
2739;******************** START - PSEUDOCODE ***************************************
2740;
2741; START CloseFile
2742;
2743; if CHECKCP != 0 then
2744; call INT 2F to unlock PRINTER.SYS
2745; reset CHECKCP
2746; endif
2747; set up for My21
2748; call My21 to close file
2749;
2750; return
2751;
2752; END CloseFile
2753;
2754;******************** END - PSEUDOCODE ***************************************
2755
2756 CloseFile PROC NEAR
2757
2758 cmp [CURRCP],0 ; is 0 < CHECKCP < -1 ? ;AN000;
2759
2760; $if g ; if CHECKCP is valid ;AN000;
2761 JNG $$IF90
2762
2763 push bx ; save file handle ;AN000;
2764 xor bx,bx ; set CP to unlock ;AN000;
2765 dec bx ; ;AN000;
2766 mov dx,[PrinterNum] ; set which LPTx ;AN000;
2767 mov ax,(major_code shl 8) + minor_code ; semophore to PRINTER.SYS ;AN000;
2768 int 2Fh ; call INT 2F to unlock PRINTER.SYS ;AN000;
2769 mov [CURRCP],0 ; reset CHECKCP ;AN000;
2770 pop bx ; recover file handle ;AN000;
2771
2772; $endif ; endif ;AN000;
2773$$IF90:
2774
2775 mov ax,(close shl 8) ; set up for INT 21 - close ;AN000;
2776 call My21 ; call My21 to close file ;AC010;
2777
2778 ret ; return ;AN000;
2779
2780 CloseFile ENDP
2781
2782 BREAK <QUeue & Buffer Space>
2783
2784; $SALUT (4,25,30,41)
2785
2786 ;---------------------------------------
2787 ;
2788 ; NOTE: FileQueue is the actuall end of
2789 ; the RESIDENT PRINT code. The
2790 ; code that follows this is still
2791 ; initialization code - and is NOT
2792 ; left resident.
2793 ;
2794 ; --- File name Queue and data buffer
2795 ; follows here
2796 ;
2797 ;---------------------------------------
2798
2799FileQueue Label byte
2800
2801 db 0 ; the file queue starts empty
2802
2803
2804 BREAK <SETDEV>
2805;******************* START OF SPECIFICATIONS ***********************************
2806;
2807; NAME: SETDEV
2808;
2809; FUNCTION:
2810;
2811; INPUT: LISTNAME has the 8 char device name IN UPPER CASE
2812;
2813; OUTPUT:
2814;
2815; NOTE:
2816;
2817; REGISTERS USED: Only DS preserved
2818; (NOT RESTORED)
2819;
2820; LINKAGE: Called by: MoveTrans
2821;
2822; NORMAL CF = 0
2823; EXIT:
2824;
2825; ERROR CF = 1 - Bad Device name
2826; EXIT:
2827;
2828; CHANGE 05/20/87 - Header added - F. G
2829; LOG:
2830;
2831;******************* END OF SPECIFICATIONS *************************************
2832;******************** START - PSEUDOCODE ***************************************
2833;
2834; START SETDEV
2835;
2836; ret
2837;
2838; END SETDEV
2839;
2840;******************** END - PSEUDOCODE ***************************************
2841
2842 ;---------------------------------------
2843 ; Reserved names for parallel card
2844 ;---------------------------------------
2845INT_17_HITLIST LABEL BYTE
2846
2847 DB 8,"PRN ",0
2848 DB 8,"LPT1 ",0
2849 DB 8,"LPT2 ",1
2850 DB 8,"LPT3 ",2
2851 DB 0
2852
2853 ;---------------------------------------
2854 ; Reserved names for Async adaptor
2855 ;---------------------------------------
2856INT_14_HITLIST LABEL BYTE
2857
2858 DB 8,"AUX ",0
2859 DB 8,"COM1 ",0
2860 DB 8,"COM2 ",1
2861 DB 0
2862 ;---------------------------------------
2863 ; Default Device Name
2864 ;---------------------------------------
2865
2866LISTNAME DB "PRN " ;Device name
2867
2868; $SALUT (4,4,9,41)
2869
2870 SETDEV PROC NEAR
2871
2872 ASSUME CS:CodeR,DS:CodeR,ES:nothing,SS:nothing
2873
2874
2875 mov ah,GET_IN_VARS
2876 call My21
2877 push es
2878 pop ds
2879 lea si,es:[bx.SYSI_DEV]
2880
2881 ASSUME DS:nothing
2882
2883 push cs
2884 pop es
2885
2886 ASSUME ES:CodeR
2887
2888 mov di,OFFSET CodeR:LISTNAME
2889
2890; $search ; ;AN000;
2891$$DO92:
2892
2893 test [si.SDEVATT],DEVTYP ;
2894
2895; $if nz,and ; if type is character ;AN000;
2896 JZ $$IF93
2897
2898 push si ;
2899 push di ;
2900 add si,SDEVNAME ; Point at name
2901 mov cx,8 ;
2902 repe cmpsb ;
2903 pop di ;
2904 pop si ;
2905
2906; $if z ; if the end was reached with a match ;AN000;
2907 JNZ $$IF93
2908
2909 stc ; signal end ;AN000;
2910
2911; $else
2912 JMP SHORT $$EN93
2913$$IF93:
2914
2915 clc ; keep looking
2916
2917; $endif ; ;AN000;
2918$$EN93:
2919
2920; $exitif c ; ;AN000;
2921 JNC $$IF92
2922
2923 mov WORD PTR [CALLAD+2],ds ;Get I/O routines
2924 mov WORD PTR [LISTDEV+2],ds ;Get I/O routines
2925 mov WORD PTR [LISTDEV],si
2926 push cs
2927 pop ds
2928
2929 ASSUME DS:CodeR
2930
2931 mov PrinterNum,-1 ; Assume not an INT 17 device
2932 push cs
2933 pop es
2934
2935 ASSUME ES:CodeR
2936
2937 mov bp,OFFSET CodeR:LISTNAME
2938 mov si,bp
2939 mov di,OFFSET CodeR:INT_17_HITLIST
2940
2941 call chk_int17_dev
2942
2943; $orelse ; ;AN000;
2944 JMP SHORT $$SR92
2945$$IF92:
2946
2947 lds si,[si.SDEVNEXT] ;
2948 cmp si,-1 ;
2949
2950; $endloop z ; ;AN000;
2951 JNZ $$DO92
2952
2953 push cs
2954 pop ds
2955 stc
2956
2957; $endsrch ; ;AN000;
2958$$SR92:
2959
2960 ret
2961
2962 SETDEV ENDP
2963
2964 BREAK <chk_int17_dev>
2965;******************* START OF SPECIFICATIONS ***********************************
2966;
2967; NAME: chk_int17_dev
2968;
2969; FUNCTION:
2970;
2971; INPUT: (DS) = CodeR
2972; (ES) = CodeR
2973;
2974; OUTPUT:
2975;
2976; NOTE:
2977;
2978; REGISTERS USED: T.B.D.
2979; (NOT RESTORED)
2980;
2981; LINKAGE:
2982;
2983; NORMAL
2984; EXIT:
2985;
2986; ERROR
2987; EXIT:
2988;
2989; CHANGE 05/20/87 - Header added - F. G
2990; LOG:
2991;
2992;******************* END OF SPECIFICATIONS *************************************
2993;******************** START - PSEUDOCODE ***************************************
2994;
2995; START chk_int17_dev
2996;
2997; ret
2998;
2999; END chk_int17_dev
3000;
3001;******************** END - PSEUDOCODE ***************************************
3002
3003 chk_int17_dev PROC NEAR
3004
3005; $search ; ;AC000;
3006$$DO100:
3007 mov si,bp
3008 mov cl,[di]
3009 inc di
3010
3011; $if ncxz ; ;AC000;
3012 JCXZ $$IF101
3013
3014 clc ; ;AC000;
3015
3016; $else ; ;AC000;
3017 JMP SHORT $$EN101
3018$$IF101:
3019
3020 stc ; ;AC000;
3021
3022; $endif ; ;AC000;
3023$$EN101:
3024
3025; $exitif c ; ;AC000;
3026 JNC $$IF100
3027
3028 mov di,OFFSET CodeR:INT_14_HITLIST
3029
3030 call chk_int14_dev ; ;AC000;
3031
3032; $orelse ; ;AC000;
3033 JMP SHORT $$SR100
3034$$IF100:
3035
3036 repe cmpsb
3037 lahf
3038 add di,cx ;Bump to next position without affecting flags
3039 mov bl,[di] ;Get device number
3040 inc di
3041 sahf
3042
3043; $endloop z ; ;AC000;
3044 JNZ $$DO100
3045
3046 xor bh,bh
3047 mov [INT_17_NUM],bx
3048 mov PrinterNum,bx ; Set this as well to the INT 17 device
3049 mov [FLAG17_14],1
3050 clc
3051 ;
3052; $endsrch ; ;AC000;
3053$$SR100:
3054
3055 ret
3056
3057 chk_int17_dev ENDP
3058
3059 BREAK <chk_int14_dev>
3060;******************* START OF SPECIFICATIONS ***********************************
3061;
3062; NAME: chk_int14_dev
3063;
3064; FUNCTION:
3065;
3066; INPUT: (DS) = CodeR
3067; (ES) = CodeR
3068;
3069; OUTPUT:
3070;
3071; NOTE:
3072;
3073; REGISTERS USED: T.B.D.
3074; (NOT RESTORED)
3075;
3076; LINKAGE:
3077;
3078; NORMAL
3079; EXIT:
3080;
3081; ERROR
3082; EXIT:
3083;
3084; CHANGE 05/20/87 - Header added - F. G
3085; LOG:
3086;
3087;******************* END OF SPECIFICATIONS *************************************
3088;******************** START - PSEUDOCODE ***************************************
3089;
3090; START chk_int14_dev
3091;
3092; ret
3093;
3094; END chk_int14_dev
3095;
3096;******************** END - PSEUDOCODE ***************************************
3097
3098 chk_int14_dev PROC NEAR
3099
3100; $search ; ;AC000;
3101$$DO108:
3102
3103 mov si,bp
3104 mov cl,[di]
3105 inc di
3106
3107; $if ncxz ; ;AC000;
3108 JCXZ $$IF109
3109
3110 clc ; ;AC000;
3111
3112; $else ; ;AC000;
3113 JMP SHORT $$EN109
3114$$IF109:
3115
3116 stc ; ;AC000;
3117
3118; $endif ; ;AC000;
3119$$EN109:
3120
3121; $exitif c ; ;AC000;
3122 JNC $$IF108
3123
3124 mov [FLAG17_14],0
3125
3126; $orelse ; ;AC000;
3127 JMP SHORT $$SR108
3128$$IF108:
3129
3130 repe cmpsb
3131 lahf
3132 add di,cx ;Bump to next position without affecting flags
3133 mov bl,[di] ;Get device number
3134 inc di
3135 sahf
3136
3137; $endloop z ; ;AC000;
3138 JNZ $$DO108
3139
3140 xor bh,bh
3141 mov [INT_14_NUM],bx
3142 mov [FLAG17_14],2
3143
3144; $endsrch ; ;AC000;
3145$$SR108:
3146
3147 clc ; ;AC015;
3148
3149 ret
3150
3151 chk_int14_dev ENDP
3152
3153 BREAK <BADSPOOL>
3154;******************* START OF SPECIFICATIONS ***********************************
3155;
3156; NAME: BADSPOOL
3157;
3158; FUNCTION:
3159;
3160; INPUT:
3161;
3162; OUTPUT:
3163;
3164; NOTE:
3165;
3166; REGISTERS USED: T.B.D.
3167; (NOT RESTORED)
3168;
3169; LINKAGE:
3170;
3171; NORMAL
3172; EXIT:
3173;
3174; ERROR
3175; EXIT:
3176;
3177; CHANGE 05/20/87 - Header added - F. G
3178; LOG:
3179;
3180;******************* END OF SPECIFICATIONS *************************************
3181;******************** START - PSEUDOCODE ***************************************
3182;
3183; START BADSPOOL
3184;
3185; ret
3186;
3187; END BADSPOOL
3188;
3189;******************** END - PSEUDOCODE ***************************************
3190
3191 BADSPOOL PROC NEAR
3192
3193 ASSUME CS:CodeR,DS:CodeR,ES:nothing,SS:nothing
3194
3195 mov ax,(CLASS_B shl 8) + BADMES ; ;AC000;
3196 call GoDispMsg ; ;AC002;
3197;*********************************************************************
3198 mov ax,(SET_PRINTER_FLAG SHL 8) ; Set flag to Idle
3199 int 21h
3200;*********************************************************************
3201 mov ax,(EXIT SHL 8) OR 0FFH
3202 int 21h
3203
3204 BADSPOOL ENDP
3205
3206 BREAK <MoveTrans>
3207;******************* START OF SPECIFICATIONS ***********************************
3208;
3209; NAME: MoveTrans
3210;
3211; FUNCTION: Move the transient out of the way of the Buffer space
3212;
3213; INPUT:
3214;
3215; OUTPUT:
3216;
3217; NOTE:
3218;
3219; REGISTERS USED: T.B.D.
3220; (NOT RESTORED)
3221;
3222; LINKAGE:
3223;
3224; NORMAL
3225; EXIT:
3226;
3227; ERROR
3228; EXIT:
3229;
3230; CHANGE 05/20/87 - Header added - F. G
3231; LOG:
3232;
3233;******************* END OF SPECIFICATIONS *************************************
3234;******************** START - PSEUDOCODE ***************************************
3235;
3236; START MoveTrans
3237;
3238; ret
3239;
3240; END MoveTrans
3241;
3242;******************** END - PSEUDOCODE ***************************************
3243
3244ContTrans dd ? ; transient continuation address after move
3245
3246MoveTrans label far
3247
3248 ASSUME CS:CodeR,DS:CodeR,ES:CodeR,SS:nothing
3249
3250 cli
3251 cld
3252 mov [INTSEG],cs
3253 call SETDEV ;
3254
3255 ASSUME ES:nothing
3256
3257 jc BADSPOOL
3258 mov dx,OFFSET CodeR:SPINT
3259 mov al,SOFTINT
3260 mov ah,GET_INTERRUPT_VECTOR
3261 int 21h ;Get soft vector
3262 mov WORD PTR [SPNEXT+2],es
3263 mov WORD PTR [SPNEXT],bx
3264 mov al,SOFTINT
3265 mov ah,SET_INTERRUPT_VECTOR
3266 int 21h ;Set soft vector
3267 mov dx,OFFSET CodeR:SPCOMINT
3268 mov al,ComInt
3269 mov ah,GET_INTERRUPT_VECTOR
3270 int 21h ;Get communication vector
3271 mov WORD PTR [COMNEXT+2],es
3272 mov WORD PTR [COMNEXT],bx
3273 mov al,ComInt
3274 mov ah,SET_INTERRUPT_VECTOR ;Set communication vector
3275 int 21h
3276 mov al,13h
3277 mov AH,GET_INTERRUPT_VECTOR
3278 int 21h
3279 mov WORD PTR [REAL_INT_13+2],es
3280 mov WORD PTR [REAL_INT_13],bx
3281 mov DX,OFFSET CodeR:INT_13
3282 mov al,13h
3283 mov ah,SET_INTERRUPT_VECTOR
3284 int 21h ;Set diskI/O interrupt
3285
3286 mov al,15h
3287 mov ah,GET_INTERRUPT_VECTOR
3288 int 21h
3289 mov WORD PTR [REAL_INT_15+2],es
3290 mov WORD PTR [REAL_INT_15],bx
3291 mov dx,OFFSET CodeR:INT_15
3292 mov al,15h
3293 mov ah,SET_INTERRUPT_VECTOR
3294 int 21h ;Set INT 15 vector
3295 mov al,17h
3296 mov ah,GET_INTERRUPT_VECTOR
3297 int 21h
3298 mov WORD PTR [REAL_INT_17+2],es
3299 mov WORD PTR [REAL_INT_17],bx
3300 mov dx,OFFSET CodeR:INT_17
3301 mov al,17H
3302 mov ah,SET_INTERRUPT_VECTOR
3303 int 21h ;Set printer interrupt
3304 mov al,14h
3305 mov ah,GET_INTERRUPT_VECTOR
3306 int 21h
3307 mov WORD PTR [REAL_INT_14+2],es
3308 mov WORD PTR [REAL_INT_14],bx
3309 mov dx,OFFSET CodeR:INT_14
3310 mov al,14h
3311 mov ah,SET_INTERRUPT_VECTOR
3312 int 21h ;Set RS232 port interrupt
3313 mov al,5
3314 mov ah,GET_INTERRUPT_VECTOR
3315 int 21h
3316 mov WORD PTR [REAL_INT_5+2],es
3317 mov WORD PTR [REAL_INT_5],bx
3318 mov DX,OFFSET CodeR:INT_5
3319 mov al,5
3320 mov ah,SET_INTERRUPT_VECTOR
3321 int 21h ;Set print screen interrupt
3322 mov ah,GET_INDOS_FLAG
3323 int 21h
3324
3325 ASSUME ES:nothing
3326
3327 mov WORD PTR [INDOS+2],es ;Get indos flag location
3328 mov WORD PTR [INDOS],bx
3329 mov al,INTLOC
3330 mov ah,GET_INTERRUPT_VECTOR
3331 int 21h
3332 mov WORD PTR [NEXTINT+2],es
3333 mov WORD PTR [NEXTINT],bx
3334
3335 mov al,REBOOT ; We also need to chain
3336 mov ah,GET_INTERRUPT_VECTOR ; Into the INT 19 sequence
3337 int 21h ; To properly "unhook"
3338 mov WORD PTR [NEXT_REBOOT+2],es ; ourselves from the TimerTick
3339 mov WORD PTR [NEXT_REBOOT],bx ; sequence
3340 mov ax,0B800h
3341 int 2Fh
3342 cmp al,0
3343 je SET_HDSPINT ; No NETWORK, set hardware int
3344 test bx,0000000011000100B
3345 jnz NO_HDSPINT ; DO NOT set HDSPINT if RCV|MSG|SRV
3346
3347SET_HDSPINT:
3348
3349 mov dx,OFFSET CodeR:HDSPINT
3350 mov al,INTLOC
3351 mov ah,SET_INTERRUPT_VECTOR
3352 int 21h ;Set hardware interrupt
3353
3354 mov dx,OFFSET CodeR:ReBtINT
3355 mov al,REBOOT
3356 mov ah,SET_INTERRUPT_VECTOR
3357 int 21h ;Set bootstrap interrupt
3358
3359NO_HDSPINT:
3360
3361 mov ax,(CLASS_B shl 8) + GOODMES ; ;AC000;
3362 call GoDispMsg ; ;AC002;
3363
3364 ;---------------------------------------
3365 ;--- Move transient
3366 ; Note: do not use stack, it may
3367 ; get trashed in move!
3368 ;---------------------------------------
3369
3370 public RealMove
3371
3372RealMove:
3373
3374 mov ax,OFFSET dg:TransRet
3375 mov WORD PTR [ContTrans],ax ; store return offset
3376 mov cx,DG
3377 mov WORD PTR [ContTrans+2],cx ; return segment
3378 mov ax,CodeR
3379 add ax,[endres] ; get start of moved transient, actually
3380 ; this is 100 bytes more than need be
3381 ; because of lack of pdb, but who cares?
3382
3383 ; NOTE: The following $IF was added for
3384 ; DOS 4.0. For earlier versions,
3385 ; the transient would even be moved
3386 ; IN if required < available
3387 ; - this would now clobber the
3388 ; message code.
3389
3390 cmp ax,cx ; is required size > available size ?
3391
3392; $if a ; if it is - move transient out
3393 JNA $$IF116
3394
3395 mov WORD PTR [ContTrans+2],ax ; return segment
3396 mov es,ax ; new location for dg group
3397
3398 ASSUME ES:nothing
3399
3400 mov ax,dg
3401 mov ds,ax
3402
3403 ASSUME DS:nothing
3404
3405 mov cx,OFFSET dg:TransSize
3406 mov si,cx ; start from the bottom and move up
3407 mov di,cx
3408 std
3409 rep movsb ; move all code, data and stack
3410 cld ; restore to expected setting...
3411
3412 ;---------------------------------------
3413 ;--- normalize transient segment regs
3414 ;---------------------------------------
3415 mov ax,es
3416 mov ds,ax
3417 sub ax,dg ; displacement
3418 mov dx,ss
3419 add dx,ax ; displace stack segemnt
3420 mov ss,dx
3421
3422; $endif
3423$$IF116:
3424
3425 ASSUME DS:nothing,ES:nothing,SS:nothing
3426
3427 jmp ContTrans ; back to the transient...
3428
3429 CodeR EndS
3430
3431 End
3432 \ No newline at end of file