-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathDOSidle_251.asm
4077 lines (3440 loc) · 115 KB
/
DOSidle_251.asm
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
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
PAGE 59,132
; ÜÚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¿Ü ;
; ÄÍ͹³ CPUidle for DOS ³ÌÍÍÄ ;
; ßÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙß ;
;[KERNEL CHARACTERISTICS]
; Kernel name: CPUidle for DOS.
; Programming stage: Working version, Under development.
; Kernel version: V2.10 [Build 0077], Marton Balog, May 07, 1998 - [See: http://img.prohardver.hu/ad/prohardver/plusabit_1/english.htm]
; V2.50 [Build 0101], I. Tsenov, May, 2015 [See: http://www.vogons.org/viewtopic.php?f=24&t=43384]
; V2.51 [Build 0102], M. Kennedy (MJK), July, 2015 [See above vogons thread].
;[NOTES]
; Ralphs intlist -> more idle possibilities.
;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»;
;º ²²²²²²²²²²²²²²²²²²²²²²² RESIDENT PART OF PROGRAM ²²²²²²²²²²²²²²²²²²²²²²² º;
;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;°°°°°°°°°°±±±±±±±±±± GLOBAL CODE & DATA FOR ALL HANDLERS ±±±±±±±±±±°°°°°°°°°;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
.586p
ideal ; Yep, this prog is TASM 4.0 coded!
SAMESIZE = 1
SEGMENT CODE16 PARA PUBLIC USE16 'CODE'
ASSUME CS: CODE16, DS:NOTHING, SS:STACK16
RESIDENT_START:
PROC mem_lallocate
push bx
mov bx,cx
mov ah,48h
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
pop bx
retn
ENDP
PROC mem_lrelease
push ax es
mov es,ax
mov ah,49h
int 21h ; DOS Services ah=function 49h
; release memory block, es=seg
pop es ax
retn
ENDP
PROC mem_lresize
push ax bx es
mov es,ax
mov bx,cx
mov ah,4Ah
int 21h ; DOS Services ah=function 4Ah
; change memory allocation
; bx=bytes/16, es=mem segment
pop es bx ax
retn
ENDP
PROC mem_lallocate_all
push bx
mov bx,0FFFFh
mov ah,48h
int 21h ; DOS Services ah=function 48h
; allocate memory, bx=bytes/16
mov ax,bx
mov cx,bx
pop bx
retn
ENDP
IFDEF SAMESIZE
db 15 dup(0)
ELSE
ALIGN 16
ENDIF
struc rmdw
ofss dw 0
segm dw 0
ends
struc intr_vec_struc
number db 0
old_isr dd 0
new_isr dd 0
ends
struc intr_suspend_struc
byte1 db 0
bytes25 dd 0
ends
INT2DH_BIOS = 2dh * 4
tsr_kernel_id dw 0 ;data_11 stores KERNEL_ID
tsr_psp_seg dw 0 ;data_12 stores psp_seg
tsr_env_seg dw 0 ;data_13 stores env seg
new_int_2dh dd isr_2dh ;data_14
old_int_2dh rmdw <0, 0> ;data_15
intr_vectors intr_vec_struc 30 dup (<>) ;data_16
vectors_hooked dw 0 ;data_17
suspend_vectors intr_suspend_struc 30 dup (<>) ;data_18
vectors_suspend dw 0 ;data_19
TSR_ID = 0FEADh
ACTION_TEST = 0
ACTION_UNINSTALL = 1
ACTION_SUSPEND = 2
ACTION_REACTIVATE = 3
PROC isr_2dh
cmp dx, [cs:tsr_kernel_id]
jz short loc_1
loc_2:
jmp [dword cs:old_int_2dh]
loc_1: ;* No entry point to code
cmp bx, ACTION_TEST
jne short loc_3 ; Jump if not equal
mov ax, TSR_ID
sti ; Enable interrupts
iret ; Interrupt return
loc_3:
ASSUME DS: CODE16
cmp bx, ACTION_UNINSTALL
jne short loc_10 ; Jump if not equal
cli ; Disable interrupts
push cx si di ds es
mov ax,cs
mov ds,ax
xor ax,ax ; Zero register
mov es,ax
mov eax, [new_int_2dh]
cmp [es:INT2DH_BIOS],eax
jne short loc_8 ; Jump if not equal
mov si,offset intr_vectors
mov cx, [vectors_hooked]
test cx,cx
jz short loc_7 ; Jump if zero
locloop_4:
movzx di, [(intr_vec_struc si).number] ; Mov w/zero extend
shl di,2 ; Shift w/zeros fill
mov eax,[(intr_vec_struc si).old_isr]
cmp [es:di],eax
je short loc_5 ; Jump if equal
mov eax,[(intr_vec_struc si).new_isr]
cmp [es:di],eax
jne short loc_8 ; Jump if not equal
loc_5:
add si,size intr_vec_struc
loop locloop_4 ; Loop if cx > 0
mov si,offset intr_vectors
mov cx,[vectors_hooked]
locloop_6:
mov eax,[(intr_vec_struc si).old_isr]
movzx di,[(intr_vec_struc si).number] ; Mov w/zero extend
shl di,2 ; Shift w/zeros fill
mov [es:di],eax
add si,size intr_vec_struc
loop locloop_6 ; Loop if cx > 0
loc_7:
mov eax, [dword ptr old_int_2dh]
mov [es:INT2DH_BIOS],eax
mov ax, [tsr_psp_seg] ;xxx perhaps error, should be mov bx, [tsr_bx]
call mem_lrelease
mov ax,1
jmp short loc_9
loc_8:
xor ax,ax ; Zero register
loc_9:
pop es ds di si cx
sti ; Enable interrupts
iret ; Interrupt return
loc_10:
cmp bx, ACTION_SUSPEND
jne short loc_15 ; Jump if not equal
cli ; Disable interrupts
push ebx cx si di ds es
mov ax,cs
mov ds,ax
cmp [vectors_suspend],0
jne short loc_13 ; Jump if not equal
mov si,offset intr_vectors
mov di,offset suspend_vectors
mov cx,[vectors_hooked]
mov [vectors_suspend],cx
test cx,cx
jz short loc_12 ; Jump if zero
locloop_11:
mov ebx,[(intr_vec_struc si).new_isr]
ror ebx,10h ; Rotate
mov es,bx ;save isr seg
rol ebx,10h ; Rotate
mov al,[es:bx] ;copy first byte of new isr
mov [(intr_suspend_struc di).byte1],al
mov eax,[es:bx+1] ;copy bytes 2-5 of new isr
mov [(intr_suspend_struc di).bytes25],eax
mov eax,[(intr_vec_struc si).old_isr]
mov [byte ptr es:bx],0EAh ;patch isr with JMP FAR
mov [es:bx+1],eax ;patch isr with jmp far old_intr_XX
add si,size intr_vec_struc
add di,size intr_suspend_struc
loop locloop_11 ; Loop if cx > 0
loc_12:
mov ax,1
jmp short loc_14
loc_13:
xor ax,ax ; Zero register
loc_14:
pop es ds di si cx ebx
sti ; Enable interrupts
iret ; Interrupt return
loc_15:
cmp bx, ACTION_REACTIVATE
jne loc_2 ; Jump if not equal
cli ; Disable interrupts
push ebx cx si di ds es
mov ax,cs
mov ds,ax
cmp [vectors_suspend],0
je short loc_18 ; Jump if equal
mov si,offset intr_vectors
mov di,offset suspend_vectors
mov cx,[vectors_hooked]
mov [vectors_suspend],0
test cx,cx
jz short loc_17 ; Jump if zero
locloop_16:
mov ebx,[(intr_vec_struc si).new_isr]
ror ebx,10h ; Rotate
mov es,bx
rol ebx,10h ; Rotate
mov al,[(intr_suspend_struc di).byte1]
mov [es:bx],al ;restore first byte of isr
mov eax,[(intr_suspend_struc di).bytes25]
mov [es:bx+1],eax ;restore bytes 2-5 of isr
add si,size intr_vec_struc
add di,size intr_suspend_struc
loop locloop_16 ; Loop if cx > 0
loc_17:
mov ax,1
jmp short loc_19
loc_18:
xor ax,ax ; Zero register
loc_19:
pop es ds di si cx ebx
sti ; Enable interrupts
iret ; Interrupt return
ENDP
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
IFDEF SAMESIZE
DB 7 DUP (0)
ELSE
ALIGN 16
ENDIF
Struc qk_item
prog db 12 dup (0), 0 ; Name of the child process.
hooknum db 0 ; Number of FN hooks.
execnum dw 0 ; "PID number" of child.
Ends
Struc qk_hook
fnaddr dw 0 ; Address of FN to hook.
newaddr dw 0 ; New address of the FN.
oldaddr dw 0 ; Old address of the FN.
Ends
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
MODE_OPTIMIZE = 01h ; Set if CPU optimization selected.
MODE_HLT = 02h ; Set if normal HLT method selected.
MODE_APM = 04h ; Set if APM cooling method selected.
MODE_NOFORCE = 08h ; Set if any FORCE MODE is disabled.
MODE_WFORCE = 10h ; Set if WEAK FORCE strategy selected.
MODE_SFORCE = 20h ; Set if STRONG FORCE strategy selected.
MODE_MOUSE = 80h ; Set if there is a mouse driver
IRQ_00 = 01h ;
IRQ_01 = 02h ;
IRQ_02 = 04h ;
IRQ_03 = 08h ;
IRQ_04 = 10h ;
IRQ_05 = 20h ; Flag set if that specific IRQ was
IRQ_06 = 40h ; invoked. Should later be cleared by
IRQ_07 = 80h ; kernel...
INT_XXH_FORCE = 300 ; # of calls to FN before forced HLT.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
int_xxh_fcount dd 0 ; # int xxh FN(x) called repeatedly.
mode_flags db MODE_SFORCE ; Config flags for program startup.
irq_flags db 0 ; IRQ flags for kernel.
quirk_table qk_item <"NC.EXE", 1, 0>
qk_hook <int_21h_fntable + 2ch * 2, int_xxh_forcehlt, int_xxh_zerocount>
qk_item <"SCANDISK.EXE", 1, 0>
qk_hook <int_21h_fntable + 0bh * 2, int_xxh_zerocount, int_xxh_forcehlt>
QK_ITEMS = 2
exec_calls dw 200 ; Count of DOS FN 4bh calls.
child_name db 13 dup (0) ; Name of the child to be executed.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
ASSUME DS: CODE16
Proc _str_cmp ; NOTE: Copied from _string.h!!
push ax cx si di
mov cx,0FFh ; CX = maximum string length.
@@cmp: mov al,[ds:si] ; Read char from string #1.
cmp al,[es:di] ; Char (#1) == char (#2)?
jne short @@done ; Nope, strings can't be equal.
test al,al ; Done (char (#1) = char (#2) = 0)?
jz short @@done ; Yes, string are equal.
inc si ;
inc di ;
loop @@cmp ; Continue.
@@done: pop di si cx ax
ret
Endp
;----------------------------------------------------------------------------;
Proc int_xxh_forcehlt
inc [int_xxh_fcount] ; Increase force counter.
cmp [int_xxh_fcount],INT_XXH_FORCE ; Over the minimum?
jb short @@done ; Nah, don't HLT yet.
mov [irq_flags],0 ; Clear IRQ flags.
sti ; Enable IRQs for following HLT.
test [mode_flags],MODE_APM ; APM usage requested?
jnz short @@apm ; Yes.
;- - - - - - - - - - -;
@@std: test [mode_flags],MODE_SFORCE ; Running under STRONG FORCE mode?
jnz short @@stds ; Yes.
@@stdw: hlt ; Enter power saving mode.
ret ; Fast exit.
@@stds: and [irq_flags],not IRQ_00 ; Clear IRQ0 occurred flag.
hlt ; Enter power saving mode.
cmp [irq_flags],IRQ_00 ; Was it IRQ0 (timer) ONLY?!
je @@stds ; Yes, go back HLTing.
ret ; Fast exit.
;- - - - - - - - - - -;
;- - - - - - - - - - -;
@@apm: test [mode_flags],MODE_SFORCE ; Running under STRONG FORCE mode?
jnz short @@apms ; Yes.
@@apmw:
push ax ; Safety only - AX already saved in the
; int 14h, 16h, 21h and 2Fh handlers.
mov ax,5305h ;
pushf ;
call [dword old_int_15h] ; Call APM FN to put the CPU idle.
pop ax
ret
@@apms:
push ax ; Save AX (see comments above)
@@apm2: and [irq_flags],not IRQ_00 ; Clear IRQ0 occurred flag.
mov ax,5305h ;
pushf ;
call [dword old_int_15h] ; Call APM FN to put the CPU idle.
cmp [irq_flags],IRQ_00 ; Was it IRQ0 (timer) ONLY?!
je @@apm2 ; Yes, go back HLTing.
pop ax
@@done: ret
Endp
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Proc int_xxh_zerocount ; Zero ALL FORCE counters.
mov [int_xxh_fcount],0 ; Zero int xxh force counter.
ret
Endp
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Proc int_xxh_skip ; Skip ALL FORCE counter updates.
ret
Endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;°°°°°°°°°°°°°°°±±±±±±±±±±±±±± INT 21H HANDLER ±±±±±±±±±±±±±±°°°°°°°°°°°°°°°°;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
INT_21H_TOPFN = 4ch ; Highest FN that is handled.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
old_int_21h rmdw <0, 0>
int_21h_fntable dw offset int_xxh_zerocount ; FN 00h: Terminate.
dw offset int_21h_normalhlt ; FN 01h: Keyboard input.
dw offset int_xxh_zerocount ; FN 02h: Display char.
dw offset int_xxh_skip ; FN 03h: Auxiliary input.
dw offset int_xxh_zerocount ; FN 04h: Auxiliary output.
dw offset int_xxh_zerocount ; FN 05h: Printer output.
dw offset int_21h_fn06h ; FN 06h: Console I/O.
dw offset int_21h_normalhlt ; FN 07h: No echo unfiltered input.
dw offset int_21h_normalhlt ; FN 08h: No echo input.
dw offset int_xxh_zerocount ; FN 09h: Display string.
dw offset int_xxh_skip ; FN 0ah: Buffered input.
dw offset int_xxh_forcehlt ; FN 0bh: "Keypressed?"
dw offset int_xxh_skip ; FN 0ch: Clear buffer and input.
dw 24h dup (int_xxh_zerocount) ; FNs 0dh - 30h.
dw offset int_21h_fn31h ; FN 31h: Terminate and Stay Resident.
dw 19h dup (int_xxh_zerocount) ; FNs 32h - 4ah.
dw offset int_21h_fn4bh ; FN 4bh: Execute child process.
dw offset int_21h_fn4ch ; FN 4ch: Terminate child process.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Proc int_21h_fn06h ; DOS FN: Console I/O.
cmp dl,0ffh ; "Keypressed?" function requested?
jne short @@done ; No.
jmp [int_21h_fntable + 0bh * 2] ; Force HLT (as FN 0bh does it).
@@done: ret
Endp
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Proc int_21h_fn31h ; DOS FN: Terminate and Stay Resident.
jmp short int_21h_fn4ch ; Same as standard exit...
Endp
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Proc int_21h_fn4bh ; DOS FN: Execute child process.
pusha
push es ;
mov bp,sp ; BP = ptr to entry DS on stack.
inc [exec_calls] ; Increase count of exec calls.
test al,al ; Load and execute child?
jnz short @@done ; No, no work for us.
mov ax,[ss:bp + 2 + 16 + 2] ; Get DS from stack.
mov es,ax ;
mov di,dx ; ES:DI = caller's DS:DX = child name.
;- - - - - - - - - - -;
lea si,[child_name] ; DS:SI = target buffer for child name.
xor bx,bx ; BX = index of char at [DS:SI].
@@read: mov al,[es:di] ; Get char of child name in int 21h.
mov [ds:si + bx],al ; Save it to our buffer.
cmp al,':' ; Was it a DRIVE specifier?
je short @@kill ; Yes.
cmp al,'\' ; Was it a PATH separator?
jne short @@next ; No.
@@kill: mov bx,-1 ; Restart saving to buffer...
@@next: inc di ;
inc bx ; Advance index pointers.
test al,al ; At end of ASCIIZ filename?
jnz @@read ; No.
;- - - - - - - - - - -;
;- - - - - - - - - - -;
lea bx,[quirk_table] ; BX = ptr to table of quirky programs.
mov cx,QK_ITEMS ; CX = number of entries in table.
lea di,[child_name] ;
mov ax,ds ;
mov es,ax ; ES:DI = ptr to ASCIIZ name of child.
@@find: lea si,[(qk_item bx).prog] ; SI = ptr to quirky child name.
call _str_cmp ; Is this child being executed?
je short @@set ; Yes, handle it.
mov al,[(qk_item bx).hooknum] ; AL = number of FN hooks.
mov ah,size qk_hook ; AH = size of one FN hook.
mul ah ; AX = value to increment BX with.
add bx,ax ;
add bx,size qk_item ;
loop @@find ; Continue.
jmp short @@done ; Child is NOT a quirky program, done.
;- - - - - - - - - - -;
;- - - - - - - - - - -;
@@set: mov ax,[exec_calls] ;
mov [(qk_item bx).execnum],ax ; Save "PID" of this quirky program.
xor ch,ch ;
mov cl,[(qk_item bx).hooknum] ; CX = number of hooks to install.
add bx,size qk_item ; BX = ptr to first hook data.
test cl,cl ; No hooks needed?
jz short @@done ; Yes, crazy but quit...
@@hook: mov si,[(qk_hook bx).fnaddr] ; SI = address of FN to hook.
mov ax,[ds:si] ; Get old FN handler.
mov [(qk_hook bx).oldaddr],ax ; Save it.
mov ax,[(qk_hook bx).newaddr] ; Get new address for FN handler.
mov [ds:si],ax ; Hook FN.
add bx,size qk_hook ;
loop @@hook ; Continue.
;- - - - - - - - - - -;
@@done: pop es
popa
ret
Endp
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
Proc int_21h_fn4ch ; DOS FN: Terminate child process.
pusha
lea bx,[quirk_table] ; BX = ptr to table of quirky programs.
mov cx,QK_ITEMS ; CX = number of entries in table.
;- - - - - - - - - - -;
@@find: mov ax,[(qk_item bx).execnum] ; Get "PID" of saved program.
cmp ax,[exec_calls] ; Is it this program?
je short @@set ; Yes, handle it.
mov al,[(qk_item bx).hooknum] ; AL = number of FN hooks.
mov ah,size qk_hook ; AH = size of one FN hook.
mul ah ; AX = value to increment BX with.
add bx,ax ;
add bx,size qk_item ;
loop @@find ; Continue.
jmp short @@done ; Finish, program wasn't found.
;- - - - - - - - - - -;
;- - - - - - - - - - -;
@@set: xor ch,ch ;
mov cl,[(qk_item bx).hooknum] ; CX = number of hooks to deinstall.
add bx,size qk_item ; BX = ptr to first hook data.
test cl,cl ; No hooks needed?
jz short @@done ; Yes, crazy but quit...
@@unhk: mov si,[(qk_hook bx).fnaddr] ; SI = address of FN to unhook.
mov ax,[(qk_hook bx).oldaddr] ; Get old FN handler.
mov [ds:si],ax ; Restore original handler.
add bx,size qk_hook ;
loop @@unhk ; Continue.
;- - - - - - - - - - -;
@@done: dec [exec_calls]
popa
ret
Endp
;----------------------------------------------------------------------------;
Proc int_21h_normalhlt
sti ; Enable IRQs for following HLT.
mov ah,0bh ; Int 21h FN: "Keypressed?".
test [mode_flags],MODE_APM ; APM usage requested?
jnz short @@apml ; Yes.
@@stdl: hlt ; Enter power saving mode.
pushf ;
call [dword old_int_21h] ; Simulate int 21h without reentrancy.
cmp al,0ffh ; Keystroke ready?
jne @@stdl ; No, continue HLTing.
jmp short @@done ; Finish.
@@apml: mov ax,5305h ;
pushf ;
call [dword old_int_15h] ; Call APM FN to put the CPU idle.
mov ah,0bh ; Int 21h FN: "Keypressed?"
pushf ;
call [dword old_int_21h] ; Simulate int 21h without reentrancy.
cmp al,0ffh ; Keystroke ready?
jne @@apml ; No, continue HLTing.
@@done: ret
Endp
;----------------------------------------------------------------------------;
Align 16
Proc int_21h_handler ; DOS functions handler.
push ax bx ds
mov bx,cs ;
mov ds,bx ; CODE = DATA.
cmp ah,INT_21H_TOPFN ; FN irrelevant for our handler?
ja short @@old ; Yes, zero force counter and chain.
xor bh,bh ;
mov bl,ah ;
add bx,bx ; BX = index to int_21h_fntable.
add bx,offset int_21h_fntable ; BX = offset of handler.
call [word bx] ; Call the appropriate FN handler.
jmp short @@oldn ; Chain without zeroing force count.
@@old: mov [int_xxh_fcount],0 ; Zero int xxh force counter.
@@oldn: pop ds bx ax
jmp [dword cs:old_int_21h] ; Chain to old interrupt handler.
Endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;°°°°°°°°°°°°°°°±±±±±±±±±±±±±± INT 16H HANDLER ±±±±±±±±±±±±±±°°°°°°°°°°°°°°°°;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
INT_16H_TOPFN = 12h ; Highest FN that is handled.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
old_int_16h rmdw <0, 0>
int_16h_fntable dw offset int_16h_normalhlt ; FN 00h: Keyboard input.
dw offset int_xxh_forcehlt ; FN 01h: "Keypressed?".
dw offset int_xxh_forcehlt ; FN 02h: "SHIFT Keypressed?".
dw 0dh dup (int_xxh_zerocount) ; FNs 03h - 09h.
dw offset int_16h_normalhlt ; FN 10h: Keyboard input (101-keys).
dw offset int_xxh_forcehlt ; FN 11h: "Keypressed?" (101-keys).
dw offset int_xxh_forcehlt ; FN 12h: "SHIFT Keypressed?" (101).
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Proc int_16h_normalhlt
push bx ; Safety only - BX already saved in the main Int-16 handler
inc ah ; Int 16h FN: Is keystroke ready?
mov bh,ah ; Save AH (FN number).
sti ; Enable IRQs for following HLT.
test [mode_flags],MODE_APM ; APM usage requested?
jnz short @@apml ; Yes.
@@stdl: pushf ;
call [dword old_int_16h] ; Simulate int 16h without reentrancy.
jnz short @@done ; If ZF == 0 then key is ready.
hlt ; Enter power saving mode.
mov ah,bh ; Restore saved AH (FN number).
jmp @@stdl
@@apml: pushf ;
call [dword old_int_16h] ; Simulate int 16h without reentrancy.
jnz short @@done ; If ZF == 0 then key is ready.
mov ax,5305h ;
pushf ;
call [dword old_int_15h] ; Call APM FN to put the CPU idle.
mov ah,bh ; Restore saved AH (FN number).
jmp @@apml ; No, continue HLTing.
@@done:
pop bx
ret
Endp
;----------------------------------------------------------------------------;
Align 16
Proc int_16h_handler ; BIOS keyboard functions handler.
push ax bx ds
mov bx,cs ;
mov ds,bx ; CODE = DATA.
cmp ah,INT_16H_TOPFN ; FN irrelevant for our handler?
ja short @@old ; Yes, zero force counter and chain.
xor bh,bh ;
mov bl,ah ;
add bx,bx ; BX = index to int_16h_fntable.
add bx,offset int_16h_fntable ; BX = offset of handler.
call [word bx] ; Call the appropriate FN handler.
jmp short @@oldn ; Chain without zeroing force count.
@@old: mov [int_xxh_fcount],0 ; Zero int xxh force counter.
@@oldn: pop ds bx ax
jmp [dword cs:old_int_16h] ; Chain to old interrupt handler.
Endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;°°°°°°°°°°°°°°°±±±±±±±±±±±±±± INT 2FH HANDLER ±±±±±±±±±±±±±±°°°°°°°°°°°°°°°°;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
INT_2FH_TOPFN = 0ffffh ; Highest FN that is handled.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
old_int_2fh rmdw <0, 0>
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 16
Proc int_2fh_handler
push ax dx ds ; (AX might be clobbered in int_xxh_forcehlt)
mov dx,cs ;
mov ds,dx ; CODE = DATA.
cmp ax,1680h ; DPMI release time slice?
je short @@dpmi ; Yes.
cmp ax,1607 ; Windows VMPoll Idle callout?
jne short @@old ; No, exit.
@@vmpl: cmp bx,0018h ; Is it the VMPoll VxD ID number?
jne short @@old ; No, exit.
test cx,cx ; Is it the VMPoll driver?
jnz short @@old ; No, exit.
@@dpmi: call int_xxh_forcehlt ; Enter power saving mode.
jmp short @@oldn ; Chain without zeroing force count.
@@old: mov [int_xxh_fcount],0 ; Zero int xxh force counter.
@@oldn: pop ds dx ax
jmp [dword cs:old_int_2fh] ; Chain to old interrupt handler.
Endp
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
old_int_33h rmdw <0, 0>
user_mouse_handler rmdw <OFFSET dummy_mouse_handler, SEG dummy_mouse_handler>
user_mouse_mask dw 0
dummy_handler_ptr rmdw <OFFSET dummy_mouse_handler, SEG dummy_mouse_handler>
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 16
Proc int_33h_handler
sti ; (let 'em run!)
mov [cs:int_xxh_fcount],0 ; Zero int xxh force counter.
cmp ax,000Ch
je short @@set_handler
cmp ax,0014h
je short @@xchg_handler
cmp ax,0018h
je short @@set_alt_handler
jmp [dword cs:old_int_33h] ; Chain to old interrupt handler.
@@set_handler:
push es dx cx
call install_mouse_handler
pop cx dx es
iret
@@xchg_handler:
call install_mouse_handler
iret
@@set_alt_handler:
mov ax,0FFFFh ; Return error
iret
Endp
Proc mouse_handler
mov [cs:int_xxh_fcount],0 ; Zero int xxh force counter.
and ax,[word ptr cs:user_mouse_mask]
jz short @@done
;call debug_char
jmp [dword ptr cs:user_mouse_handler]
@@done:
retf
Endp
;----------------------------------------------------------------------------;
; Installs a new mouse handler and returns the current one
; ES:DX - the new mouse handler to install (can be 0:0)
; CX - the new mouse event mask (can be 0)
;
; NB: re saving/clobbering CX, DX, ES. This proc used in two cases:
; - Service int 33H fn 0Ch (set new mouse handler). CX, DX and ES are already
; saved before this proc is called, and restored later.
; - Service int 33h fn 14h (to set a new mouse handler and to return the old one).
; These regs must NOT be saved and restored, as int 33h fn 14h returns the old
; mouse handler in ES:DX and the old event mask in CX.
Proc install_mouse_handler
push ds ; (Do NOT save/restore CX, DX, ES - see note above)
push eax
mov ax,cs ; Set the DS to point to our segment
mov ds,ax
; Save the new mouse handler
mov ax,es
rol eax,16
mov ax,dx ; EAX now contains the new handler
test eax,eax ; Is the new handler null?
jnz short @@valid_handler
mov eax,[dword dummy_handler_ptr] ; YES, replace with dummy_mouse_handler and zero the mask
xor cx,cx
@@valid_handler:
xchg [dword ptr user_mouse_handler],eax
xchg [word ptr user_mouse_mask],cx
mov dx,ax ; Save the previous handler in ES:DX
ror eax,16
mov es,ax
push es
push dx
push cx
; Install our real mouse handler
mov dx,SEG mouse_handler
mov es,dx
mov dx,offset mouse_handler
mov cx,7Fh ; Catch all mouse events
mov ax,000Ch
pushf
call [dword old_int_33h] ; "INT-Call" to old interrupt handler.
pop cx
pop dx
pop es
pop eax
pop ds
ret
Endp
Proc dummy_mouse_handler
retf
Endp
;----------------------------------------------------------------------------;
; Debugging - show "changing" char at top-left of screen
; proc debug_char
; push es
; push ax
; mov ax,0B800h
; mov es,ax
; inc [byte ptr es:0]
; pop ax
; pop es
; ret
; endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
;°°°°°°°°°°°°°°°±±±±±±±±±±±±±± INT 14H HANDLER ±±±±±±±±±±±±±±°°°°°°°°°°°°°°°°;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ;
INT_14H_TOPFN = 03h ; Highest FN that is handled.
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Align 4
old_int_14h rmdw <0, 0>
int_14h_fntable dw offset int_xxh_zerocount ; FN 00h: Init COM port.
dw offset int_xxh_zerocount ; FN 01h: Send char to COM port.
dw offset int_14h_normalhlt ; FN 02h: Read char from COM port.
dw offset int_xxh_forcehlt ; FN 03h: "Char ready?"
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
Proc int_14h_normalhlt
sti ; Enable IRQs for following HLT.
test [mode_flags],MODE_APM ; APM usage requested?
jnz short @@apml ; Yes.
@@stdl: hlt ; Enter power saving mode.
mov ah,03h ; Int 14h FN: Get serial port status.
pushf ;
call [dword old_int_14h] ; Simulate int 14h without reentrancy.
test ah,1 ; Is data ready?
jz @@stdl ; No, continue loop.
jmp short @@done ; Finish.
@@apml: mov ax,5305h ;
pushf ;
call [dword old_int_15h] ; Call APM FN to put the CPU idle.
mov ah,03h ; Int 14h FN: Get serial port status.
pushf ;
call [dword old_int_14h] ; Simulate int 14h without reentrancy.
test ah,1 ; Is data ready?
jz @@apml ; No, continue loop.
@@done: ret
Endp
;----------------------------------------------------------------------------;
Align 16
Proc int_14h_handler ; BIOS serial I/O handler.
push ax bx ds
mov bx,cs ;
mov ds,bx ; CODE = DATA.
cmp ah,INT_14H_TOPFN ; FN irrelevant for our handler?
ja short @@old ; Yes, zero force counter and chain.
xor bh,bh ;
mov bl,ah ;
add bx,bx ; BX = index to int_14h_fntable.
add bx,offset int_14h_fntable ; BX = offset of handler.
call [word bx] ; Call the appropriate FN handler.
jmp short @@oldn ; Chain without zeroing force count.
@@old: mov [int_xxh_fcount],0 ; Zero int xxh force counter.
@@oldn: pop ds bx ax
jmp [dword cs:old_int_14h] ; Chain to old interrupt handler.
Endp