-
Notifications
You must be signed in to change notification settings - Fork 134
/
Copy pathinterrupts.js
3409 lines (3398 loc) · 132 KB
/
interrupts.js
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
/**
* @fileoverview PCx86-specific BIOS/DOS interrupt definitions
* @author Jeff Parsons <[email protected]>
* @copyright © 2012-2024 Jeff Parsons
* @license MIT <https://www.pcjs.org/LICENSE.txt>
*
* This file is part of PCjs, a computer emulation software project at <https://www.pcjs.org>.
*/
const Interrupts = {
/**
* The original ROM BIOS defined vectors 0x08-0x1F with a table at F000:FEF3 (VECTOR_TABLE).
*/
VIDEO: 0x10,
EQUIPMENT: 0x11,
MEM_SIZE: 0x12,
DISK: 0x13,
SERIAL: 0x14,
CASSETTE: 0x15,
KEYBOARD: 0x16,
PARALLEL: 0x17,
BASIC: 0x18, // normally F600:0000
BOOTSTRAP: 0x19,
TIMER: 0x1A,
KBD_BREAK: 0x1B,
TMR_BREAK: 0x1C, // invoked by the BIOS timer interrupt handler (normally vector 0x08)
VID_PARMS: 0x1D,
DSK_PARMS: 0x1E, // vector for Diskette Parameter Table (DPT)
/**
* For characters 0x00-0x7F, the original ROM BIOS used a built-in table at F000:FA6E (CRT_CHAR_GEN),
* since the MDA/CGA font ROM was not CPU-addressable, but presumably there wasn't enough room in the
* ROM BIOS for all 256 characters, so if software wanted to draw any characters 0x80-0xFF in graphics
* mode, it was up to software to provide the font data and set the VID_EXT vector to point to it.
*/
VID_EXT: 0x1F, // graphics characters 0x80-0xFF (aka EXT_PTR)
DOS_EXIT: 0x20,
DOS: 0x21,
DOS_IDLE: 0x28,
DOS_NETBIOS:0x2A,
MOUSE: 0x33,
ALT_DISK: 0x40, // HDC ROM saves original FDC vector here
HD0_PARMS: 0x41, // vector for Fixed Disk Parameter Table (FDPT) for hard drive 0
VID_PLANAR: 0x42, // EGA ROM saves original VIDEO ("planar ROM") vector here
EGA_GRX: 0x43, // EGA ROM provides a complete set of mode-appropriate font data here (0000:010C)
HD1_PARMS: 0x46, // vector for Fixed Disk Parameter Table (FDPT) for hard drive 1
HD_PARMS: {
MAX_CYL: 0x00, // maximum cylinders (2 bytes)
MAX_HEADS: 0x02, // maximum heads (1 byte)
WP_CYL: 0x05, // write precompensation cylinder (2 bytes)
MAX_ECC: 0x07, // max ECC burst (1 byte)
DRIVE_CTRL: 0x08, // drive control (1 byte)
PARK_CYL: 0x0C, // landing zone cylinder (2 bytes)
SEC_TRACK: 0x0E // sectors per track (1 byte)
},
WINCB: {
VECTOR: 0x30 // Windows PM call-back interface (aka Transfer Space Fault)
},
WINDBG: { // Windows Debugger protected-mode interface
VECTOR: 0x41, // (AX is one of the following DS commands)
OUTCHAR: 0x0000, // DS_Out_Char (display the char in DL)
INCHAR: 0x0001, // DS_In_Char (read a char into AL)
OUTSTR: 0x0002, // DS_Out_Str (display a NUL terminated string pointed to by DS:ESI)
ISCHAR: 0x0003, // DS_Is_Char (non-blocking In_Chr)
OUTSTR16: 0x0012, // DS_Out_Str16 (display a NUL terminated string pointed to by DS:SI; same as DS_Out_Str but for 16-bit callers)
FORCEDGO16: 0x0040, // DS_ForcedGO16 (enter the debugger and perform the equivalent of a GO command to force a stop at the specified CS:IP; CX is the desired CS and BX is the desired IP)
LINKMAP: 0x0045, // DS_LinkMap (DX:(E)DI = ptr to paragraph in front of map)
UNLINKMAP: 0x0046, // DS_UnlinkMap (DX:(E)DI = ptr to paragraph in front of map)
CHECKMAP: 0x0047, // DS_CheckMap (DX:(E)DI = pointer to module name; returns AX != 0 if map found or AX == 0 if map not found)
AUTOLOAD: 0x0048, // DS_IsAutoLoadSym (returns AX != 0, auto load symbols; AX == 0, don't auto load symbols)
IS_LOADED: 0x004F, // DS_DebLoaded
LOADED: 0xF386, // DS_DebPresent (returned in AX in response to DS_DebLoaded if Windows Debugger loaded)
LOADSEG: 0x0050, // DS_LoadSeg (SI is 0 if code sel, 1 if data sel, 0x80 if code seg, 0x81 if data seg; BX is segnum-1; CX is sel or seg; DX is data instance; ES:[E]DI -> module name)
LOADSEG32: 0x0150, // DS_LoadSeg_32 (SI is 0 0 if code, 1 if data; DX:EBX -> D386_Device_Params)
FREESEG: 0x0052, // DS_FreeSeg (BX == segment)
KRNLVARS: 0x005A, // DS_Kernel_Vars
RELSEG: 0x005C, // DS_ReleaseSeg (same as DS_FreeSeg but "restores any breakpoints first")
LOADHIGH: 0x005D, // D386_LoadCodeDataHigh
EXITCALL: 0x0062, // DS_EXITCALL
LOADDLL: 0x0064, // DS_LOADDLL
DELMODULE: 0x0065, // DS_DELMODULE
UNKNOWN66: 0x0066, // Unknown (but I suspect it isn't good)
UNKNOWN67: 0x0067, // Unknown (but I suspect it isn't good)
REGDOTCMD: 0x0070, // DS_RegisterDotCommand
CHECKFAULT: 0x007F, // DS_CheckFault (BX == fault #, CX == FAULTTYPE bits; return AX=0 to handle fault normally, 1 to issue TRAPFAULT)
FAULTTYPE: {
V86: 0x0001,
PM: 0x0002,
RING0: 0x0004,
FIRST: 0x0008,
LAST: 0x0010
},
TRAPFAULT: 0x0083, // DS_TrapFault (BX == fault #, CX == faulting CS, EDX == faulting EIP, ESI == fault error, EDI == fault flags)
GETSYMBOL: 0x008D, // DS_GetSymbol (DS:ESI -> symbol; return AX == 0 if success, 1 if not found, 2 if memory not loaded yet)
FREESEG32: 0x0152, // DS_FreeSeg_32 (BX == segment, DX:EDI -> module name)
CONDBP: 0xF001, // DS_CondBP (break here if WDEB386 was run with /B; ESI -> string to display)
FORCEDBP: 0xF002, // DS_ForcedBP
FORCEDGO: 0xF003, // DS_ForcedGO (enter the debugger and perform the equivalent of a GO command to force a stop at the specified CS:EIP; CX is the desired CS, EBX is the desired EIP)
HARDINT1: 0xF004, // DS_HardINT1 (check to see if INT 1 hooked for all rings; ENTER: nothing, EXIT: AX = 0, if no, 1, if yes)
ENABLED: true // support for WINDBG interrupts can be disabled (but NOT if WINDBGRM is enabled)
},
WINDBGRM: { // Windows Debugger real-mode interface
VECTOR: 0x68, // (AH is one of the following D386 commands)
IS_LOADED: 0x43, // D386_Identify
LOADED: 0xF386, // D386_Id (returned in AX if Windows Debugger loaded)
PREP_PMODE: 0x44, // D386_Prepare_PMode (must return a 16:32 address in ES:EDI to a "PMinit" handler)
FREESEG: 0x48, // D386_Free_Segment (BX == real-mode segment)
REMOVESEGS: 0x4F, // D386_Remove_Segs (remove any undefined segments from the named module at ES:DI)
LOADSEG: 0x50, // D386_Load_Segment (AL=segment type, ES:DI -> D386_Device_Params)
ENABLED: true // support for WINDBGRM interrupts can be disabled
},
VIDEO_VGA: 0x6D, // VGA ROM entry point (the default VGA INT 10h handler invokes this interrupt and IRETs)
FUNCS: {} // filled in only if DEBUGGER is true
};
Interrupts.BIOS_DATA = {
0x400: ["RS232_BASE",8], // BASE ADDRESSES OF RS232 ADAPTERS
0x408: ["PRINTER_BASE",8], // BASE ADDRESSES OF PRINTER ADAPTERS
0x410: ["EQUIP_FLAG",2], // INSTALLED HARDWARE FLAGS
0x412: ["MFG_TST",1], // INITIALIZATION FLAGS
0x413: ["MEMORY_SIZE",2], // BASE MEMORY SIZE IN K BYTES (X 1024)
0x415: ["MFG_ERR_FLAG",2], // SCRATCHPAD FOR MANUFACTURING ERROR CODES
0x417: ["KB_FLAG",1], // KEYBOARD SHIFT STATE AND STATUS FLAGS
0x418: ["KB_FLAG_1",1], // SECOND BYTE OF KEYBOARD STATUS
0x419: ["ALT_INPUT",1], // STORAGE FOR ALTERNATE KEY PAD ENTRY
0x41A: ["BUFFER_HEAD",2], // POINTER TO HEAD OF KEYBOARD BUFFER
0x41C: ["BUFFER_TAIL",2], // POINTER TO TAIL OF KEYBOARD BUFFER
0x41E: ["KB_BUFFER",32], // ROOM FOR 15 SCAN CODE ENTRIES
0x43E: ["SEEK_STATUS",1], // DRIVE RECALIBRATION STATUS (BIT 3-0 = DRIVE 3-0 RECALIBRATION BEFORE NEXT SEEK IF BIT IS = 0)
0x43F: ["MOTOR_STATUS",1], // MOTOR STATUS (BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING, BIT 7 = CURRENT OPERATION IS A WRITE)
0x440: ["MOTOR_COUNT",1], // TIME OUT COUNTER FOR MOTOR(S) TURN OFF
0x441: ["DISKETTE_STATUS",1], // RETURN CODE STATUS BYTE
0x442: ["NEC_STATUS",7], // STATUS BYTES FROM DISKETTE OPERATION
0x449: ["CRT_MODE",1], // CURRENT DISPLAY MODE (TYPE)
0x44A: ["CRT_COLS",2], // NUMBER OF COLUMNS ON SCREEN
0x44C: ["CRT_LEN",2], // LENGTH OF REGEN BUFFER IN BYTES
0x44E: ["CRT_START",2], // STARTING ADDRESS IN REGEN BUFFER
0x450: ["CURSOR_POSN",16], // CURSOR FOR EACH OF UP TO 8 PAGES
0x460: ["CURSOR_MODE",2], // CURRENT CURSOR MODE SETTING
0x462: ["ACTIVE_PAGE",1], // CURRENT PAGE BEING DISPLAYED
0x463: ["ADDR_6845",2], // BASE ADDRESS FOR ACTIVE DISPLAY CARD
0x465: ["CRT_MODE_SET",1], // CURRENT SETTING OF THE 3X8 REGISTER
0x466: ["CRT_PALETTE",1], // CURRENT PALETTE SETTING - COLOR CARD
0x467: ["IO_ROM_INIT",2], // POINTER TO ROM INITIALIZATION ROUTINE
0x469: ["IO_ROM_SEG",2], // POINTER TO I/O ROM SEGMENT
0x46B: ["INTR_FLAG",1], // FLAG INDICATING AN INTERRUPT HAPPENED
0x46C: ["TIMER_LOW",2], // LOW WORD OF TIMER COUNT
0x46E: ["TIMER_HIGH",2], // HIGH WORD OF TIMER COUNT
0x470: ["TIMER_OFL",1], // TIMER HAS ROLLED OVER SINCE LAST READ
0x471: ["BIOS_BREAK",1], // BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
0x472: ["RESET_FLAG",2], // WORD=1234H IF KEYBOARD RESET UNDERWAY
0x474: ["DISK_STATUS1",1], // FIXED DISK STATUS
0x475: ["HF_NUM",1], // COUNT OF FIXED DISK DRIVES
0x476: ["CONTROL_BYTE",1], // HEAD CONTROL BYTE
0x477: ["PORT_OFF",1], // RESERVED (PORT OFFSET)
0x478: ["PRINT_TIM_OUT",4], // TIME OUT COUNTERS FOR PRINTER RESPONSE
0x47C: ["RS232_TIM_OUT",4], // TIME OUT COUNTERS FOR RS232 RESPONSE
0x480: ["BUFFER_START",2], // OFFSET OF KEYBOARD BUFFER START
0x482: ["BUFFER_END",2], // OFFSET OF END OF BUFFER
0x484: ["ROWS",1], // ROWS ON THE ACTIVE SCREEN (LESS 1)
0x485: ["POINTS",2], // BYTES PER CHARACTER
0x487: ["INFO",1], // MODE OPTIONS
0x488: ["INFO_3",3], // FEATURE BIT SWITCHES
0x48B: ["LASTRATE",1], // LAST DISKETTE DATA RATE SELECTED
0x48C: ["HF_STATUS",1], // STATUS REGISTER
0x48D: ["HF_ERROR",1], // ERROR REGISTER
0x48E: ["HF_INT_FLAG",1], // FIXED DISK INTERRUPT FLAG
0x48F: ["HF_CNTRL",1], // COMBO FIXED DISK/DISKETTE CARD BIT 0=1
0x490: ["DSK_STATE",4], // DRIVE 0 MEDIA STATE, DRIVE 1 MEDIA STATE, DRIVE 0 OPERATION START STATE, DRIVE 1 OPERATION START STATE
0x494: ["DSK_TRK",2], // DRIVE 0 PRESENT CYLINDER, DRIVE 1 PRESENT CYLINDER
0x496: ["KB_FLAG_3",1], // KEYBOARD MODE STATE AND TYPE FLAGS
0x497: ["KB_FLAG_2",1], // KEYBOARD LED FLAGS
0x498: ["USER_FLAG",2], // OFFSET ADDRESS OF USERS WAIT FLAG
0x49A: ["USER_FLAG_SEG",2], // SEGMENT ADDRESS OF USER WAIT FLAG
0x49C: ["RTC_LOW",2], // LOW WORD OF USER WAIT FLAG
0x49E: ["RTC_HIGH",2], // HIGH WORD OF USER WAIT FLAG
0x4A0: ["RTC_WAIT_FLAG",1], // WAIT ACTIVE FLAG (01=BUSY, 80=POSTED) (00=POST ACKNOWLEDGED)
0x4A1: ["NET",7], // RESERVED FOR NETWORK ADAPTERS
0x4A8: ["SAVE_PTR",4] // POINTER TO EGA PARAMETER CONTROL BLOCK
};
/**
* See Debuggerx86.prototype.replaceRegs() for the rules governing how register contents are replaced in the strings below.
*
* Replacements occur in the following order:
*
* Replace every @XX (or @XXX), where XX (or XXX) is a register, with the register's value.
* Replace every #XX, where XX is a hex byte value, with the corresponding ASCII character (if printable).
* Replace every $XXXX:XXXX, where XXXX:XXXX is a segmented address, with the zero-terminated string at that address.
* Replace every ^XXXX:XXXX, where XXXX:XXXX is a segmented address, with the FCB filename stored at that address.
*
* The last replacement is obviously DOS-specific, since FCBs are DOS constructs.
*/
Interrupts.FUNCS[Interrupts.VIDEO] = {
0x00: "set mode (@AL)",
0x01: "set cursor type (start=@CH,end=@CL)",
0x02: "set cursor pos (row=@DH,col=@DL,page=@BH)",
0x03: "read cursor pos (page=@BH)",
0x04: "read light pen",
0x05: "set display page (@AL)",
0x06: "scroll up (lines=@AL)",
0x07: "scroll down (lines=@AL)",
0x08: "read character (page=@BH)",
0x09: "write char/attr (@AL,attr=@BL,count=@CX)",
0x0A: "write char (@AL,count=@CX)",
0x0B: "set palette (id=@BH,color=@BL)",
0x0C: "write dot (row=@DX,col=@CX)",
0x0D: "read dot (row=@DX,col=@CX)",
0x0E: "write tty (@AL)"
};
Interrupts.FUNCS[Interrupts.DISK] = {
0x00: "disk reset",
0x01: "get status",
0x02: "read drive @DL (@CH:@DH:@CL,@AL) into @ES:@BX",
0x03: "write drive @DL (@CH:@DH:@CL,@AL) from @ES:@BX",
0x04: "verify drive @DL (@CH:@DH:@CL,@AL)",
0x05: "format drive @DL using @ES:@BX",
0x08: "read drive @DL parameters",
0x15: "get drive @DL DASD type",
0x16: "get drive @DL change line status",
0x17: "set drive @DL DASD type",
0x18: "set drive @DL media type"
/**
* Here's an additional function reference, previously in the HDC component, but moved here
* because our components are hardware emulations, not BIOS emulations, so this information is
* really only of interest to the Debugger (or the casual observer).
*
* RESET: 0x00,
* GET_STATUS: 0x01,
* READ_SECTORS: 0x02,
* WRITE_SECTORS: 0x03,
* VERIFY_SECTORS: 0x04,
* FORMAT_TRK: 0x05,
* FORMAT_BAD: 0x06,
* FORMAT_DRIVE: 0x07,
* GET_DRIVEPARMS: 0x08,
* SET_DRIVEPARMS: 0x09,
* READ_LONG: 0x0A,
* WRITE_LONG: 0x0B,
* SEEK: 0x0C,
* ALT_RESET: 0x0D,
* READ_BUFFER: 0x0E,
* WRITE_BUFFER: 0x0F,
* TEST_READY: 0x10,
* RECALIBRATE: 0x11,
* RAM_DIAGNOSTIC: 0x12,
* DRV_DIAGNOSTIC: 0x13,
* CTL_DIAGNOSTIC: 0x14
*/
};
Interrupts.FUNCS[Interrupts.CASSETTE] = {
0x80: "open device",
0x81: "close device",
0x82: "program termination",
0x83: "wait @CX:@DXus for event",
0x84: "joystick support",
0x85: "SYSREQ pressed",
0x86: "wait @CX:@DXus",
0x87: "move block (@CX words)",
0x88: "get extended memory size",
0x89: "processor to virtual mode",
0x90: "device busy loop",
0x91: "interrupt complete flag set"
};
Interrupts.FUNCS[Interrupts.DOS] = {
0x00: "terminate program",
0x01: "read character (AL) from stdin with echo",
0x02: "write character #@DL to stdout",
0x03: "read character (AL) from stdaux", // eg, COM1
0x04: "write character #@DL to stdaux", // eg, COM1
0x05: "write character #@DL to stdprn", // eg, LPT1
0x06: "direct console output (input if @DL=FF)",
0x07: "direct console input without echo",
0x08: "read character (AL) from stdin without echo",
0x09: "write string $@DS:@DX to stdout",
0x0A: "buffered input (DS:DX)", // byte 0 is maximum chars, byte 1 is number of previous characters, byte 2 is number of characters read
0x0B: "get stdin status",
0x0C: "flush buffer and read stdin", // AL is a function # (0x01, 0x06, 0x07, 0x08, or 0x0A)
0x0D: "disk reset",
0x0E: "select default drive @DL", // returns # of available drives in AL
0x0F: "open file using FCB ^@DS:@DX", // DS:DX -> unopened File Control Block
0x10: "close file using FCB ^@DS:@DX",
0x11: "find first matching file using FCB ^@DS:@DX",
0x12: "find next matching file using FCB ^@DS:@DX",
0x13: "delete file using FCB ^@DS:@DX",
0x14: "sequential read from file using FCB ^@DS:@DX",
0x15: "sequential write to file using FCB ^@DS:@DX",
0x16: "create or truncate file using FCB ^@DS:@DX",
0x17: "rename file using FCB ^@DS:@DX",
0x19: "get current default drive (AL)",
0x1A: "set disk transfer area (DTA=@DS:@DX)",
0x1B: "get allocation information for default drive",
0x1C: "get allocation information for specific drive @DL",
0x1F: "get drive parameter block for default drive",
0x21: "read random record from file using FCB ^@DS:@DX",
0x22: "write random record to file using FCB ^@DS:@DX",
0x23: "get file size using FCB ^@DS:@DX",
0x24: "set random record number for FCB ^@DS:@DX",
0x25: "set address @DS:@DX of interrupt vector @AL",
0x26: "create new PSP at segment @DX",
0x27: "random block read from file using FCB ^@DS:@DX",
0x28: "random block write to file using FCB ^@DS:@DX",
0x29: "parse filename $@DS:@SI into FCB @ES:@DI using @AL",
0x2A: "get system date (year=CX, mon=DH, day=DL)",
0x2B: "set system date (year=@CX, mon=@DH, day=@DL)",
0x2C: "get system time (hour=CH, min=CL, sec=DH, 100ths=DL)",
0x2D: "set system time (hour=@CH, min=@CL, sec=@DH, 100ths=@DL)",
0x2E: "set verify flag @AL",
0x2F: "get disk transfer area (DTA=ES:BX)", // DOS 2.00+
0x30: "get DOS version (AL=major, AH=minor)",
0x31: "terminate and stay resident",
0x32: "get drive parameter block (DPB=DS:BX) for drive @DL",
0x33: "extended break check",
0x34: "get address (ES:BX) of InDOS flag",
0x35: "get address (ES:BX) of interrupt vector @AL",
0x36: "get free disk space of drive @DL",
0x37: "get(0)/set(1) switch character @DL (@AL)",
0x38: "get country-specific information",
0x39: "create subdirectory $@DS:@DX",
0x3A: "remove subdirectory $@DS:@DX",
0x3B: "set current directory $@DS:@DX",
0x3C: "create or truncate file $@DS:@DX with attributes @CX",
0x3D: "open file $@DS:@DX with mode @AL",
0x3E: "close file @BX",
0x3F: "read @CX bytes from file @BX into buffer @DS:@DX",
0x40: "write @CX bytes to file @BX from buffer @DS:@DX",
0x41: "delete file $@DS:@DX",
0x42: "set position @CX:@DX of file @BX relative to @AL",
0x43: "get(0)/set(1) attributes @CX of file $@DS:@DX (@AL)",
0x44: "get device information (IOCTL)",
0x45: "duplicate file handle @BX",
0x46: "force file handle @CX to duplicate file handle @BX",
0x47: "get current directory (DS:SI) for drive @DL",
0x48: "allocate memory segment with @BX paragraphs",
0x49: "free memory segment @ES",
0x4A: "resize memory segment @ES to @BX paragraphs",
0x4B: "load program $@DS:@DX using parameter block @ES:@BX",
0x4C: "terminate with return code @AL",
0x4D: "get return code (AL)",
0x4E: "find first matching file $@DS:@DX with attributes @CX",
0x4F: "find next matching file",
0x50: "set current PSP @BX",
0x51: "get current PSP (bx)",
0x52: "get system variables (ES:BX)",
0x53: "translate BPB @DS:@SI to DPB (ES:BP)",
0x54: "get verify flag (AL)",
0x55: "create child PSP at segment @DX",
0x56: "rename file $@DS:@DX to $@ES:@DI",
0x57: "get(0)/set(1) file @BX date @DX and time @CX (@AL)",
0x58: "get(0)/set(1) memory allocation strategy (@AL)", // DOS 2.11+
0x59: "get extended error information", // DOS 3.00+
0x5A: "create temporary file $@DS:@DX with attributes @CX", // DOS 3.00+
0x5B: "create file $@DS:@DX with attributes @CX", // DOS 3.00+ (doesn't truncate existing files like 0x3C)
0x5C: "lock(0)/unlock(1) file @BX region @CX:@DX length @SI:@DI (@AL)", // DOS 3.00+
0x5D: "critical error information (@AL)", // DOS 3.00+ (undocumented)
0x60: "get fully-qualified filename from $@DS:@SI", // DOS 3.00+ (undocumented)
0x63: "get lead byte table (@AL)", // DOS 2.25 and 3.20+
0x6C: "extended open file $@DS:@SI" // DOS 4.00+
};
Interrupts.FUNCS[Interrupts.WINDBG.VECTOR] = {
0x004F: "check debugger loaded" // WINDBG.IS_LOADED returns WINDBG.LOADED (0xF386) if debugger loaded
};
/**
* DOS function reference (from https://pcdosretro.github.io/dosfunc.txt)
*
* INT 20 Program terminate (1.0+)
* Entry: CS=PSP
* Exit: Does not return to caller
*
* INT 21 Execute DOS function
* 00 Program terminate (1.0+)
* Entry: CS=PSP
* Exit: Does not return to caller
* 01 Character input (1.0+)
* Entry: None
* Exit: AL=character
* 02 Character output (1.0+)
* Entry: DL=character
* Exit: None
* 03 Auxiliary input (1.0+)
* Entry: None
* Exit: AL=character
* 04 Auxiliary output (1.0+)
* Entry: DL=character
* Exit: None
* 05 Printer output (1.0+)
* Entry: DL=character
* Exit: None
* 06 Direct console I/O (1.0+)
* Entry: DL=FF for console input
* DL=character for console output
* Exit: ZF=0 if a character is ready, AL=character
* ZF=1 if no character is ready
* 07 Direct console input without echo (1.0+)
* Entry: None
* Exit: AL=character
* 08 Console input without echo (1.0+)
* Entry: None
* Exit: AL=character
* 09 Display string (1.0+)
* Entry: DS:DX->string ending with $
* Exit: None
* 0A Buffered keyboard input (1.0+)
* Entry: DS:DX->input buffer (first byte of buffer=maximum input length)
* Exit: second byte of buffer=actual input length
* 0B Get input status (1.0+)
* Entry: None
* Exit: AL=00 no character available
* AL=FF character available
* 0C Flush input buffer and input (1.0+)
* Entry: AL=function number (01,06,07,08,or 0A otherwise flush only)
* DS:DX->input buffer if function 0A
* Exit: AL=character unless function 0A
* 0D Disk reset (1.0+)
* Entry: None
* Exit: None
* 0E Set default drive (1.0+)
* Entry: DL=drive code (0=A)
* Exit: AL=number of logical drives
* 0F Open file (1.0+)
* Entry: DS:DX->unopened FCB
* Exit: AL=00 file opened
* AL=FF file not found
* 10 Close file (1.0+)
* Entry: DS:DX->opened FCB
* Exit: AL=00 file closed
* AL=FF file not found
* 11 Find first file (1.0+)
* Entry: DS:DX->unopened FCB
* Exit: AL=00 matching filename found
* buffer at DTA receives an unopened FCB and directory entry
* original FCB contents:
* FCB search drive code (1=A)
* FCB+1 specified filespec
* FCB+12 search attribute byte
* FCB+13 directory entry offset
* FCB+15 directory cluster (0=root)
* FCB+17 unused
* FCB+21 actual drive code (1=A)
* AL=FF matching filename not found
* Note: The file's directory entry is returned after the FCB drive code.
* If a character device is found then the directory attribute byte
* is set to 40h.
* 12 Find next file (1.0+)
* Entry: DS:DX->unopened FCB from previous 11 or 12 call
* Exit: AL=00 matching filename found
* buffer at DTA receives an unopened FCB and directory entry
* AL=FF matching filename not found
* Note: The file's directory entry is returned after the FCB drive code.
* 13 Delete file (1.0+)
* Entry: DS:DX->unopened FCB
* Exit: AL=00 file deleted
* AL=FF matching filename not found or files are read-only
* 14 Sequential read (1.0+)
* Entry: DS:DX->opened FCB
* Exit: AL=00 file was read
* AL=01 EOF (no data read)
* AL=02 segment wrap
* AL=03 EOF (partial read)
* 15 Sequential write (1.0+)
* Entry: DS:DX->opened FCB
* Exit: AL=00 file was written
* AL=01 disk full
* AL=02 segment wrap
* 16 Create or truncate file (1.0+)
* Entry: DS:DX->unopened FCB
* Exit: AL=00 file created
* AL=FF directory full
* 17 Rename file (1.0+)
* Entry: DS:DX->rename FCB (FCB+11h->new filename)
* Exit: AL=00 file renamed
* AL=FF no matching files found or new filename already exists
* 18 Reserved
* 19 Get default drive (1.0+)
* Entry: None
* Exit: AL=drive code (0=A)
* 1A Set disk transfer address (1.0+)
* Entry: DS:DX=new DTA
* Exit: None
* 1B Get allocation info for default drive (1.0+)
* Entry: None
* Exit: AL=sectors per cluster
* CX=bytes per sector
* DX=clusters per drive
* DS:BX->media descriptor byte
* AL=FF invalid drive
* 1C Get allocation info for specified drive (1.1+)
* Entry: DL=drive code (0=default)
* Exit: Same as function 1B
* 1D Reserved
* 1E Reserved
* 1F Get disk parameter block for default drive (1.1+)
* Entry: None
* Exit: AL=00 drive valid
* DS:BX->disk parameter block
* 0 drive code (0=A) 13 maximum cluster number
* 1 unit code 15 sectors per FAT
* 2 bytes per sector 17 first directory sector
* 4 sectors per cluster-1 19 pointer to device driver
* 5 cluster shift factor 23 media descriptor byte
* 6 first FAT sector 24 access flag (0=accessed)
* 8 number of FATs 25 pointer to next DPB
* 9 number of directory entries 29 last cluster allocated
* 11 first data sector 31 free clusters (-1=unknown)
* AL=FF drive invalid
* Note: (3.x) The sectors per FAT field is one byte and all following
* fields are moved back one byte.
* 20 Reserved
* 21 Random read (1.0+)
* Entry: DS:DX->opened FCB
* Exit: AL=00 file was read
* AL=01 EOF (no data read)
* AL=02 segment wrap
* AL=03 EOF (partial read)
* 22 Random write (1.0+)
* Entry: DS:DX->opened FCB
* Exit: AL=00 file was written
* AL=01 disk full
* AL=02 segment wrap
* 23 Get file size in records (1.0+)
* Entry: DS:DX->unopened FCB
* Exit: AL=00 random record field is set by dividing the file size by the
* specified record size
* AL=FF file not found
* 24 Set random record number (1.0+)
* Entry: DS:DX->opened FCB
* Exit: random record field is set based on record size, current record,
* and current block
* 25 Set interrupt vector (1.0+)
* Entry: DS:DX=new address
* AL=interrupt number
* Exit: None
* 26 Create PSP (1.0+)
* Entry: CS=PSP
* DX=segment for new PSP
* Exit: None
* 27 Random block read (1.0+)
* Entry: DS:DX->opened FCB
* CX=number of records to read
* Exit: AL=00 file was read
* AL=01 EOF (no data read)
* AL=02 segment wrap
* AL=03 EOF (partial read)
* CX=actual number of records read
* 28 Random block write (1.0+)
* Entry: DS:DX->opened FCB
* CX=number of records to write
* Exit: AL=00 file was written
* AL=01 disk full
* AL=02 segment wrap
* CX=actual number of records written
* 29 Parse filename (1.0+)
* Entry: DS:SI->string to parse
* ES:DI->buffer for unopened FCB
* AL=flags
* Bit 0 1=ignore leading separators
* 1 1=modify FCB drive code byte only if a drive is specified
* 2 1=modify FCB filename only if a filename is specified
* 3 1=modify FCB extension only if an extension is specified
* Exit: DS:SI->first character after parsed filename
* AL=00 no wildcard characters in string
* AL=01 wildcard characters in string
* AL=FF invalid drive
* 2A Get date (1.0+)
* Entry: None
* Exit: AL=weekday (0=Sunday)
* CX=year
* DH=month
* DL=day
* 2B Set date (1.0+)
* Entry: CX=year
* DH=month
* DL=day
* Exit: AL=00 date set
* AL=FF invalid date
* 2C Get time (1.0+)
* Entry: None
* Exit: CH=hours
* CL=minutes
* DH=seconds
* DL=hundredths
* 2D Set time (1.0+)
* Entry: CH=hours
* CL=minutes
* DH=seconds
* DL=hundredths
* Exit: AL=00 time set
* AL=FF invalid time
* 2E Set verify flag (1.1+)
* Entry: AL=verify flag (0=off,1=on)
* Exit: None
* 2F Get disk transfer address (2.0+)
* Entry: None
* Exit: ES:BX=DTA
* 30 Get DOS version (2.0+)
* Entry: AL=0 return OEM number (5.0+)
* AL=1 return version flag (5.0+)
* Exit: AL=major version number
* AH=minor version number
* BH=OEM number or version flag (00=RAM,08=ROM)
* BL:CX=24-bit serial number or 0
* 31 Terminate and stay resident (2.0+)
* Entry: AL=return code
* DX=memory size in paragraphs (minimum 6)
* Exit: Does not return to caller
* 32 Get disk parameter block for specified drive (2.0+)
* Entry: DL=drive code (0=default)
* Exit: Same as function 1F
* 33 Get or set Ctrl-Break (2.0+)
* Entry: AL=0 get break
* AL=1 set break
* AL=2 swap break (*) (3.1+)
* AL=5 get boot drive (4.0+)
* AL=6 get DOS version (5.0+)
* DL=break flag if set or swap (0=off,1=on)
* Exit: if function 00 or 02:
* DL=break flag
* if function 05:
* DL=boot drive code (1=A)
* if function 06:
* BL=major version
* BH=minor version
* DL=revision (0=A)
* DH=version flag (00=low,08=ROM,10=HMA)
* 34 Get InDOS flag pointer (2.0+)
* Entry: None
* Exit: ES:BX->InDOS flag
* Note: The DOS critical error flag immediately precedes this byte.
* 35 Get interrupt vector (2.0+)
* Entry: AL=interrupt number
* Exit: ES:BX=interrupt address
* 36 Get free disk space (2.0+)
* Entry: DL=drive code (0=default)
* Exit: AX=sectors per cluster
* BX=free clusters
* CX=bytes per sector
* DX=clusters per drive
* AX=FFFF if drive invalid
* 37 Get or set switch character (*) (2.0+)
* Entry: AL=0 get switch character
* AL=1 set switch character
* DL=switch character if set
* Exit: DL=switch character if get
* Note: (5.0+) Function 3701 has been disabled.
* 38 Get or set country info (2.0+)
* Entry: AL=country code (0=default)
* BX=country code if AL=FF (3.0+)
* DX=FFFF if set request (2.11+)
* DS:DX->buffer if get request
* Exit: CF=0 BX=country code if get request (3.0+)
* buffer format:
* 0 date format (0=USA,1=Europe,2=Japan)
* 2 currency symbol string
* 7 thousands separator
* 9 decimal separator
* 11 date separator
* 13 time separator
* 15 currency format
* 0 symbol before amount, no space between
* 1 symbol after amount, no space between
* 2 symbol before amount, 1 space between
* 3 symbol after amount, 1 space between
* 4 symbol replaces decimal separator
* 16 digits after decimal in currency
* 17 time format (0=12-hour,1=24-hour)
* 18 case map call address
* 22 data list separator
* 24 reserved (10 bytes)
* CF=1 AX=error code
* 39 Create directory (2.0+)
* Entry: DS:DX->directory name
* Exit: CF=0 None
* CF=1 AX=error code
* 3A Remove directory (2.0+)
* Entry: DS:DX->directory name
* Exit: CF=0 None
* CF=1 AX=error code
* 3B Change current directory (2.0+)
* Entry: DS:DX->directory name
* Exit: CF=0 None
* CF=1 AX=error code
* 3C Create or truncate file (2.0+)
* Entry: DS:DX->filename
* CX=file attributes
* Exit: CF=0 AX=file handle
* CF=1 AX=error code
* 3D Open file (2.0+)
* Entry: DS:DX->filename
* AL=open mode
* Bit 0-2 access mode
* 000=read
* 001=write
* 010=read/write
* 4-6 sharing mode (3.0+)
* 000=compatibility
* 001=deny read/write access
* 010=deny write access
* 011=deny read access
* 100=deny none access
* 7 inheritance flag
* 0=file inherited by EXECed programs
* 1=file not inherited by EXECed programs
* Exit: CF=0 AX=file handle
* CF=1 AX=error code
* 3E Close file (2.0+)
* Entry: BX=file handle
* Exit: CF=0 None
* CF=1 AX=error code
* 3F Read file or device (2.0+)
* Entry: BX=file handle
* CX=bytes to read
* DS:DX->input buffer
* Exit: CF=0 AX=number of bytes read (0=EOF)
* CF=1 AX=error code
* 40 Write file or device (2.0+)
* Entry: BX=file handle
* CX=bytes to write (0=truncate file)
* DS:DX->output buffer
* Exit: CF=0 AX=number of bytes written (0=disk full)
* CF=1 AX=error code
* 41 Delete file (2.0+)
* Entry: DS:DX->filename
* Exit: CF=0 None
* CF=1 AX=error code
* 42 Move file pointer (2.0+)
* Entry: AL=code (0=absolute,1=relative,2=relative to EOF)
* BX=file handle
* CX:DX=offset
* Exit: CF=0 DX:AX=new pointer
* CF=1 AX=error code
* 43 Get or set file attributes (2.0+)
* Entry: AL=0 get attributes
* AL=1 set attributes
* CX=file attributes if set
* Bit 0 1=read-only
* 1 1=hidden
* 2 1=system
* 4 1=directory (get only)
* 5 1=archive
* DS:DX->filename
* Exit: CF=0 CX=file attributes if get
* CF=1 AX=error code
* 44 I/O control for devices (2.0+)
* Notes: 1) Functions 02-05 work only if bit 14 of the device driver
* attribute word is set.
* 2) Function 08 works only if bit 11 of the device driver
* attribute word is set.
* 3) Functions 0C-0F work only if bit 6 of the device driver
* attribute word is set.
* 4) Functions 10-11 work only if bit 7 of the device driver
* attribute word is set.
* 00 Get device attributes (2.0+)
* Entry: BX=file handle
* Exit: CF=0 DX=device attributes
* Character devices:
* Bit 0 1=console input
* 1 1=console output
* 2 1=NUL device
* 3 1=CLOCK device
* 4 1=INT 29 output (CON)
* 5 0=ASCII,1=binary
* 6 0=EOF on input
* 7 1=character device
* 11 1=open/close supported
* 13 1=output until busy supported
* 14 1=IOCTL supported
* Block devices:
* Bit 0-5 drive code (0=A)
* 6 0=file has been written
* 7 0=block device
* CF=1 AX=error code
* 01 Set device attributes (2.0+)
* Entry: BX=file handle (character devices only)
* DX=device attributes (DH must be 0)
* Exit: CF=0 None
* CF=1 AX=error code
* 02 Read from character device (2.0+)
* 03 Write to character device (2.0+)
* Entry: BX=file handle
* CX=number of bytes
* DS:DX->buffer
* Exit: CF=0 AX=number of bytes transferred
* CF=1 AX=error code
* 04 Read from block device (2.0+)
* 05 Write to block device (2.0+)
* Entry: BL=drive code (0=default)
* CX=number of bytes
* DS:DX->buffer
* Exit: CF=0 AX=number of bytes transferred
* CF=1 AX=error code
* 06 Get input status (2.0+)
* 07 Get output status (2.0+)
* Entry: BX=file handle
* Exit: CF=0 AL=status (00=not ready,FF=ready)
* CF=1 AX=error code
* 08 Removable media check (3.0+)
* Entry: BL=drive code (0=default)
* Exit: CF=0 AX=value (0=removable,1=fixed)
* CF=1 AX=error code
* 09 Local/remote drive check (3.0+)
* Entry: BL=drive code (0=default)
* Exit: CF=0 DX=device attributes
* Bit 1 1=32-bit sectors supported
* 6 1=generic IOCTL calls supported
* 7 1=query IOCTL call supported
* 9 1=shared drive; direct I/O not allowed
* 11 1=removable media call supported
* 12 1=remote drive
* 13 1=media descriptor in FAT required
* 14 1=IOCTL calls supported
* 15 1=SUBSTed
* CF=1 AX=error code
* 0A Local/remote handle check (3.0+)
* Entry: BX=file handle
* Exit: CF=0 DX=device attributes from SFT
* Character devices:
* Bit 0 1=console input
* 1 1=console output
* 2 1=NUL device
* 3 1=CLOCK device
* 4 1=INT 29 output (CON)
* 5 0=ASCII,1=binary
* 6 0=EOF on input
* 7 1=character device
* 11 1=network spooler
* 12 1=no inherit
* 13 1=named pipe
* 15 1=remote
* Block devices:
* Bit 0-5 drive code (0=A)
* 6 0=file has been written
* 7 0=block device
* 12 1=no inherit
* 14 1=date/time set
* 15 1=remote
* CF=1 AX=error code
* 0B Change sharing retry count (3.0+)
* Entry: CX=delay loop count
* DX=retry count
* Exit: None
* 0C Generic IOCTL for handles (3.2+)
* Entry: BX=file handle
* CH=category code (01=AUX,03=CON,05=PRN)
* CL=function code
* 45 set printer retry count
* 4A set code page (3.3+)
* 4C prepare start (3.3+)
* 4D prepare end (3.3+)
* 5F set display info (4.0+)
* 65 get printer retry count
* 6A get code page (3.3+)
* 6B get prepare list (3.3+)
* 7F get display info (4.0+)
* DS:DX->parameter block or retry count word
* Exit: CF=0 None
* CF=1 AX=error code
* Get/set code page and prepare end parameter block format:
* 0 length (2)
* 2 code page
* Prepare start parameter block format:
* 0 flags (device specific)
* 2 data length
* 4 number of code pages
* 6 code pages (-1=perform a refresh operation)
* Get prepare list parameter block format:
* 0 data length
* 2 number of hardware code pages
* 4 hardware code pages
* n number of prepared code pages
* n+2 prepared code pages
* Display info parameter block format:
* 0 info level (must be 0)
* 1 reserved
* 2 data length (14)
* 4 flags
* Bit 0 (0=blink,1=intensity)
* 6 mode (1=text,2=graphics)
* 7 reserved
* 8 colors
* 10 pixel columns
* 12 pixel rows
* 14 character columns
* 16 character rows
* 0D Generic IOCTL for drives (3.2+)
* Entry: BL=drive code (0=default)
* CH=category code (08=disk)
* CL=function code
* 40 set device parameters
* 41 write track
* 42 format track
* 46 set media info (4.0+)
* 47 set access flag (4.0+)
* 60 get device parameters
* 61 read track
* 62 verify track
* 66 get media info (4.0+)
* 67 get access flag (4.0+)
* 68 sense media type (5.0+)
* DS:DX->parameter block
* Exit: CF=0 None
* CF=1 AX=error code
* Get/set device parameter block format:
* 0 flags (only bit 0 is used by get)
* Bit 0 0=return default BPB/build new BPB
* 1=return build BPB/use device BPB
* 1 0=read all fields
* 1=read track layout only
* 2 0=sector sizes vary
* 1=sector sizes equal
* 1 drive type
* 0=360K 5=fixed
* 1=1.2M 6=tape
* 2=720K 7=1.44M
* 3=8" single sided 8=read/write optical
* 4=8" double sided 9=2.88M
* 2 attributes
* Bit 0 1=non-removable
* 1 1=changeline supported
* 4 cylinders
* 6 density (0=high,1=double)
* 7 BIOS parameter block
* 32 reserved
* 38 track layout count
* 40 track layout words (sector number,sector size)
* Note: Track layout fields are used by set only.
* Read/write parameter block format:
* 0 reserved
* 1 head
* 3 cylinder
* 5 sector
* 7 number of sectors
* 9 buffer address
* Format/verify parameter block format:
* 0 reserved
* 1 head
* 3 cylinder
* Get/set media info parameter block format:
* 0 info level (must be 0)
* 2 volume serial number
* 6 volume label
* 17 8-byte file system type
* Get/set access flag parameter block format:
* 0 reserved
* 1 access flag (0=disallow disk access,1=allow disk access)
* Sense media type parameter block format:
* 0 media type flag (0=other,1=default)
* 1 media type (2=720K,7=1.44M,9=2.88M)
* 0E Get logical drive map (3.2+)
* 0F Set logical drive map (3.2+)
* Entry: BL=logical drive code (0=default)
* Exit: CF=0 AL=physical drive code (0=only 1 logical drive mapped)
* CF=1 AX=error code
* 10 Query IOCTL for handles (5.0+)
* Entry: BX=file handle
* CH=category code (01=AUX,03=CON,05=PRN)
* CL=function code
* Exit: CF=0 None
* CF=1 AX=error code
* 11 Query IOCTL for drives (5.0+)
* Entry: BL=drive code (0=default)
* CH=category code (08=disk)
* CL=function code
* Exit: CF=0 None
* CF=1 AX=error code
* 45 Duplicate handle (2.0+)
* Entry: BX=file handle
* Exit: CF=0 AX=new file handle
* CF=1 AX=error code
* 46 Redirect handle (2.0+)
* Entry: BX=file handle
* CX=file handle to redirect
* Exit: CF=0 None
* CF=1 AX=error code
* Note: If the handle to redirect is opened then it is closed before
* being redirected.
* 47 Get current directory (2.0+)
* Entry: DS:SI->64-byte buffer for pathname
* DL=drive code (0=default)
* Exit: CF=0 None
* CF=1 AX=error code
* 48 Allocate memory (2.0+)
* Entry: BX=number of paragraphs to allocate
* Exit: CF=0 AX=segment of allocated block
* CF=1 AX=error code
* BX=size of largest available block
* 49 Release memory (2.0+)
* Entry: ES=segment of block to release
* Exit: CF=0 None
* CF=1 AX=error code
* 4A Reallocate memory (2.0+)
* Entry: BX=number of paragraphs to allocate
* ES=segment of block to reallocate
* Exit: CF=0 None
* CF=1 AX=error code
* BX=size of largest available block
* 4B Execute program (2.0+)